Home telegram - messageHistoryHoleIndexTable
Post
Cancel

telegram - messageHistoryHoleIndexTable

Remove hole

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
// (peerId, Message.Namespace, MessageHistoryHoleSpace, ClosedRange<MessageId.Id>)
private func removeInternal(peerId: PeerId, namespace: MessageId.Namespace, space: MessageHistoryHoleSpace, range: ClosedRange<MessageId.Id>, operations: inout [MessageHistoryIndexHoleOperationKey: [MessageHistoryIndexHoleOperation]]) {
    var removedIndices = IndexSet()
    var insertedIndices = IndexSet()
    var removeKeys: [Int32] = []
    var insertRanges = IndexSet()

    func processRange(_ key: ValueBoxKey, _ value: ReadBuffer) {
        let (upperId, keySpace) = decomposeKey(key)
        assert(keySpace == space)
        assert(upperId.peerId == peerId)
        assert(upperId.namespace == namespace)
        let lowerId = decodeValue(value: value, peerId: peerId, namespace: namespace)
        let holeRange: ClosedRange<MessageId.Id> = lowerId.id ... upperId.id
        if range.lowerBound <= holeRange.lowerBound && range.upperBound >= holeRange.upperBound {
      	// 完全包含在range内,可以直接移除
            removeKeys.append(upperId.id)
        } else if range.overlaps(holeRange) {
          // 与range有部分交集
          // 可以移除
          // 同时还需要重新添加不在range的部分
            removeKeys.append(upperId.id)
            var holeIndices = IndexSet(integersIn: Int(holeRange.lowerBound) ... Int(holeRange.upperBound))
            holeIndices.remove(integersIn: Int(range.lowerBound) ... Int(range.upperBound))
            insertRanges.formUnion(holeIndices)
        }
    }

    let lowerScanBound = max(0, range.lowerBound - 2)

    self.valueBox.range(self.table, start: self.key(id: MessageId(peerId: peerId, namespace: namespace, id: lowerScanBound), space: space), end: self.key(id: MessageId(peerId: peerId, namespace: namespace, id: range.upperBound), space: space).successor, values: { key, value in
        processRange(key, value)
        return true
    }, limit: 0)

    self.valueBox.range(self.table, start: self.key(id: MessageId(peerId: peerId, namespace: namespace, id: range.upperBound), space: space), end: self.upperBound(peerId: peerId, namespace: namespace, space: space), values: { key, value in
        processRange(key, value)
        return true
    }, limit: 1)

    for id in removeKeys {
        self.valueBox.remove(self.table, key: self.key(id: MessageId(peerId: peerId, namespace: namespace, id: id), space: space), secure: false)
    }

    for insertRange in insertRanges.rangeView {
      // 注意closeRange: insertRange.lowerBound ... insertRange.upperBound - 1
        let closedRange: ClosedRange<MessageId.Id> = Int32(insertRange.lowerBound) ... Int32(insertRange.upperBound - 1)
        var lowerBound: Int32 = closedRange.lowerBound
      // 注意insertRange的存储key: (id: MessageId(peerId: peerId, namespace: namespace, id: closedRange.upperBound), space: space)
      // value: lowerBound
        self.valueBox.set(self.table, key: self.key(id: MessageId(peerId: peerId, namespace: namespace, id: closedRange.upperBound), space: space), value: MemoryBuffer(memory: &lowerBound, capacity: 4, length: 4, freeWhenDone: false))
    }

    if !removeKeys.isEmpty {
        addOperation(.remove(range), peerId: peerId, namespace: namespace, space: space, to: &operations)
    }
}

addHole

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
    private func addInternal(peerId: PeerId, namespace: MessageId.Namespace, space: MessageHistoryHoleSpace, range: ClosedRange<MessageId.Id>, operations: inout [MessageHistoryIndexHoleOperationKey: [MessageHistoryIndexHoleOperation]]) {
        let clippedLowerBound = max(1, range.lowerBound)
        let clippedUpperBound = min(Int32.max - 1, range.upperBound)
        if clippedLowerBound > clippedUpperBound {
            return
        }
        let clippedRange = clippedLowerBound ... clippedUpperBound
        
        var removedIndices = IndexSet()
        var insertedIndices = IndexSet()
        var removeKeys: [Int32] = []
        var insertRanges = IndexSet()
        
        var alreadyMapped = false
        
        func processRange(_ key: ValueBoxKey, _ value: ReadBuffer) {
            let (upperId, keySpace) = decomposeKey(key)
            assert(keySpace == space)
            assert(upperId.peerId == peerId)
            assert(upperId.namespace == namespace)
            let lowerId = decodeValue(value: value, peerId: peerId, namespace: namespace)
            let holeRange: ClosedRange<Int32> = lowerId.id ... upperId.id
            if clippedRange.lowerBound >= holeRange.lowerBound && clippedRange.upperBound <= holeRange.upperBound {
              // holeRange 完全落在 clippedRange内
              // 不需要再添加
                alreadyMapped = true
                return
            } else if clippedRange.overlaps(holeRange) || (holeRange.upperBound != Int32.max && clippedRange.lowerBound == holeRange.upperBound + 1) || clippedRange.upperBound == holeRange.lowerBound - 1 {
              //与clippedRange有部分有交集,或与clippedRange完全没有交集
              // 需要移除
              // 并重新添加整个并集(holeRange, clippedRange)
                removeKeys.append(upperId.id)
                let unionRange: ClosedRange = min(clippedRange.lowerBound, holeRange.lowerBound) ... max(clippedRange.upperBound, holeRange.upperBound)
                insertRanges.insert(integersIn: Int(unionRange.lowerBound) ... Int(unionRange.upperBound))
            }
        }
        
        let lowerScanBound = max(0, clippedRange.lowerBound - 2)
        
        self.valueBox.range(self.table, start: self.key(id: MessageId(peerId: peerId, namespace: namespace, id: lowerScanBound), space: space), end: self.key(id: MessageId(peerId: peerId, namespace: namespace, id: clippedRange.upperBound), space: space).successor, values: { key, value in
            processRange(key, value)
            if alreadyMapped {
                return false
            }
            return true
        }, limit: 0)
        
        if !alreadyMapped {
            self.valueBox.range(self.table, start: self.key(id: MessageId(peerId: peerId, namespace: namespace, id: clippedRange.upperBound), space: space), end: self.upperBound(peerId: peerId, namespace: namespace, space: space), values: { key, value in
                processRange(key, value)
                if alreadyMapped {
                    return false
                }
                return true
            }, limit: 1)
        }
        
        if alreadyMapped {
            return
        }
        
        insertRanges.insert(integersIn: Int(clippedRange.lowerBound) ... Int(clippedRange.upperBound))
        insertedIndices.insert(integersIn: Int(clippedRange.lowerBound) ... Int(clippedRange.upperBound))
        
        for id in removeKeys {
            self.valueBox.remove(self.table, key: self.key(id: MessageId(peerId: peerId, namespace: namespace, id: id), space: space), secure: false)
        }
        
        for insertRange in insertRanges.rangeView {
            let closedRange: ClosedRange<MessageId.Id> = Int32(insertRange.lowerBound) ... Int32(insertRange.upperBound - 1)
            var lowerBound: Int32 = closedRange.lowerBound
            self.valueBox.set(self.table, key: self.key(id: MessageId(peerId: peerId, namespace: namespace, id: closedRange.upperBound), space: space), value: MemoryBuffer(memory: &lowerBound, capacity: 4, length: 4, freeWhenDone: false))
        }
        
        addOperation(.insert(clippedRange), peerId: peerId, namespace: namespace, space: space, to: &operations)
    }

add

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func add(peerId: PeerId, namespace: MessageId.Namespace, space: MessageHistoryHoleSpace, range: ClosedRange<MessageId.Id>, operations: inout [MessageHistoryIndexHoleOperationKey:
[MessageHistoryIndexHoleOperation]]) {
    self.ensureInitialized(peerId: peerId)
    
    self.addInternal(peerId: peerId, namespace: namespace, space: space, range: range, operations: &operations)
    
    switch space {
        case .everywhere:
            if let namespaceHoleTags = self.seedConfiguration.messageHoles[peerId.namespace]?[namespace] {
                for tag in namespaceHoleTags {
                    self.addInternal(peerId: peerId, namespace: namespace, space: .tag(tag), range: range, operations: &operations)
                }
            }
        case .tag:
            break
    }
}

search for policy

```regulation expression HoleIndexTable.remove(peerId HoleIndexTable.add(peerId

addHole(peerId

removeHole(peerId ```

This post is licensed under CC BY 4.0 by the author.