Home telegram - reverseAssociatedPeerTable
Post
Cancel

telegram - reverseAssociatedPeerTable

ReverseAssociatedPeerTable

class ReverseAssociatedPeerTable

1
2
3
4
5
6
7
8
9
10
11
private func readPeerIds(_ buffer: ReadBuffer) -> Set<PeerId> {
    assert(buffer.length % 8 == 0)
    let count = buffer.length / 8
    var result = Set<PeerId>()
    for _ in 0 ..< count {
        var value: Int64 = 0
        buffer.read(&value, offset: 0, length: 8)
        result.insert(PeerId(value))
    }
    return result
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
static func tableSpec(_ id: Int32) -> ValueBoxTable {
    return ValueBoxTable(id: id, keyType: .int64, compactValuesOnCreation: false)
}

private var cachedAssociations: [PeerId: Set<PeerId>] = [:]
private var updatedAssociations = Set<PeerId>()

private func key(_ peerId: PeerId) -> ValueBoxKey {
    self.sharedKey.setInt64(0, value: peerId.toInt64())
    return self.sharedKey
}

// get peerId
func get(peerId: PeerId) -> Set<PeerId> {
    if let cached = self.cachedAssociations[peerId] {// from memory cache
        return cached
    } else {
      // from db
        if let value = self.valueBox.get(self.table, key: self.key(peerId)) {
            let peerIds = readPeerIds(value)
            self.cachedAssociations[peerId] = peerIds
            return peerIds
        } else {
            self.cachedAssociations[peerId] = Set()
            return Set()
        }
    }
}

// add reverse association
func addReverseAssociation(target targetPeerId: PeerId, from sourcePeerId: PeerId) {
    var value = self.get(peerId: targetPeerId)
    if value.contains(sourcePeerId) {
        assertionFailure()
    } else {
        value.insert(sourcePeerId)
        self.cachedAssociations[targetPeerId] = value
        self.updatedAssociations.insert(targetPeerId)
    }
}

// remove reverse association
func removeReverseAssociation(target targetPeerId: PeerId, from sourcePeerId: PeerId) {
    var value = self.get(peerId: targetPeerId)
    if !value.contains(sourcePeerId) {
        assertionFailure()
    } else {
        value.remove(sourcePeerId)
        self.cachedAssociations[targetPeerId] = value
        self.updatedAssociations.insert(targetPeerId)
    }
}

// clear memory cache
override func clearMemoryCache() {
    self.cachedAssociations.removeAll()
    assert(self.updatedAssociations.isEmpty)
}

// before commit
override func beforeCommit() {
    if !self.updatedAssociations.isEmpty {
        let buffer = WriteBuffer()
        for peerId in self.updatedAssociations {
            if let peerIds = self.cachedAssociations[peerId] {
                if peerIds.isEmpty {
                    self.valueBox.remove(self.table, key: self.key(peerId), secure: false)
                } else {
                    buffer.reset()
                    writePeerIds(buffer, peerIds)
                    self.valueBox.set(self.table, key: self.key(peerId), value: buffer)
                }
            } else {
                assertionFailure()
            }
        }
        
        self.updatedAssociations.removeAll()
    }
}
This post is licensed under CC BY 4.0 by the author.