Home telegram - chatListIndexTable
Post
Cancel

telegram - chatListIndexTable

ChatListIndexTable

enum PeerChatListInclusion

1
2
case notIncluded
case ifHasMessagesOrOneOf(groupId: PeerGroupId, pinningIndex: UInt16?, minTimestamp: Int32?)

struct ChatListPeerInclusionIndex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let topMessageIndex: MessageIndex?
let inclusion: PeerChatListInclusion

func includedIndex(peerId: PeerId) -> (PeerGroupId, ChatListIndex)? {
    switch inclusion {
        case .notIncluded:
            return nil
        case let .ifHasMessagesOrOneOf(groupId, pinningIndex, minTimestamp):
            if let minTimestamp = minTimestamp {
                if let topMessageIndex = self.topMessageIndex, topMessageIndex.timestamp >= minTimestamp {
                    return (groupId, ChatListIndex(pinningIndex: pinningIndex, messageIndex: topMessageIndex))
                } else {
                    return (groupId, ChatListIndex(pinningIndex: pinningIndex, messageIndex: MessageIndex(id: MessageId(peerId: peerId, namespace: 0, id: 0), timestamp: minTimestamp)))
                }
            } else if let topMessageIndex = self.topMessageIndex {
                return (groupId, ChatListIndex(pinningIndex: pinningIndex, messageIndex: topMessageIndex))
            } else if let pinningIndex = pinningIndex {
                return (groupId, ChatListIndex(pinningIndex: pinningIndex, messageIndex: MessageIndex(id: MessageId(peerId: peerId, namespace: 0, id: 0), timestamp: 0)))
            } else {
                return nil
            }
    }
}

struct ChatListIndexFlags

1
2
var rawValue: Int8
static let hasIndex = ChatListIndexFlags(rawValue: 1 << 0)

class ChatListIndexTable

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
static func tableSpec(_ id: Int32) -> ValueBoxTable {
    return ValueBoxTable(id: id, keyType: .int64, compactValuesOnCreation: true)
}

private let peerNameIndexTable: PeerNameIndexTable
private let metadataTable: MessageHistoryMetadataTable
private let readStateTable: MessageHistoryReadStateTable
private let notificationSettingsTable: PeerNotificationSettingsTable

private var cachedPeerIndices: [PeerId: ChatListPeerInclusionIndex] = [:]
private var updatedPreviousPeerCachedIndices: [PeerId: ChatListPeerInclusionIndex] = [:]


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

private func key(_ groupId: PeerGroupId) -> ValueBoxKey {
  // 0xFFFFFF groupId
    self.sharedKey.setInt32(0, value: Int32.max)
    self.sharedKey.setInt32(4, value: groupId.rawValue)
    return self.sharedKey
}

// update topMessageIndex 
func setTopMessageIndex(peerId: PeerId, index: MessageIndex?) -> ChatListPeerInclusionIndex {
    let current = self.get(peerId: peerId)
    if self.updatedPreviousPeerCachedIndices[peerId] == nil {
        self.updatedPreviousPeerCachedIndices[peerId] = current
    }
    let updated = ChatListPeerInclusionIndex(topMessageIndex: index, inclusion: current.inclusion)
    self.cachedPeerIndices[peerId] = updated
    return updated
}

// update inclusion
func setInclusion(peerId: PeerId, inclusion: PeerChatListInclusion) -> ChatListPeerInclusionIndex {
    let current = self.get(peerId: peerId)
    if self.updatedPreviousPeerCachedIndices[peerId] == nil {
        self.updatedPreviousPeerCachedIndices[peerId] = current
    }
    let updated = ChatListPeerInclusionIndex(topMessageIndex: current.topMessageIndex, inclusion: inclusion)
    self.cachedPeerIndices[peerId] = updated
    return updated
}

// get 
func get(peerId: PeerId) -> ChatListPeerInclusionIndex {
    if let cached = self.cachedPeerIndices[peerId] {// read from cache
        return cached
    } else {
      // read from disk
        if let value = self.valueBox.get(self.table, key: self.key(peerId)) {
            let topMessageIndex: MessageIndex?

          // read indexFlags
            var flagsValue: Int8 = 0
            value.read(&flagsValue, offset: 0, length: 1)
            let flags = ChatListIndexFlags(rawValue: flagsValue)

            if flags.contains(.hasIndex) {
                var idNamespace: Int32 = 0
                var idId: Int32 = 0
                var idTimestamp: Int32 = 0
                value.read(&idNamespace, offset: 0, length: 4)
                value.read(&idId, offset: 0, length: 4)
                value.read(&idTimestamp, offset: 0, length: 4)
                topMessageIndex = MessageIndex(id: MessageId(peerId: peerId, namespace: idNamespace, id: idId), timestamp: idTimestamp)
            } else {
                topMessageIndex = nil
            }

          // read inclusion
            let inclusion: PeerChatListInclusion

            var inclusionId: Int8 = 0
            value.read(&inclusionId, offset: 0, length: 1)
            if inclusionId == 0 {
                inclusion = .notIncluded
            } else if inclusionId == 1 {
              // read pinning index
                var pinningIndexValue: UInt16 = 0
                value.read(&pinningIndexValue, offset: 0, length: 2)

              // read hasMinTimestamp
                var hasMinTimestamp: Int8 = 0
                value.read(&hasMinTimestamp, offset: 0, length: 1)
                let minTimestamp: Int32?
                if hasMinTimestamp != 0 {
                    var minTimestampValue: Int32 = 0
                  // read minTimestampValue
                    value.read(&minTimestampValue, offset: 0, length: 4)
                    minTimestamp = minTimestampValue
                } else {
                    minTimestamp = nil
                }

              // read groupId
                var groupIdValue: Int32 = 0
                value.read(&groupIdValue, offset: 0, length: 4)

                inclusion = .ifHasMessagesOrOneOf(groupId: PeerGroupId(rawValue: groupIdValue), pinningIndex: chatListPinningIndexFromKeyValue(pinningIndexValue), minTimestamp: minTimestamp)
            } else {
                preconditionFailure()
            }

            let inclusionIndex = ChatListPeerInclusionIndex(topMessageIndex: topMessageIndex, inclusion: inclusion)
            self.cachedPeerIndices[peerId] = inclusionIndex
            return inclusionIndex
        } else {
          
          // (nil, included)
            let inclusionIndex = ChatListPeerInclusionIndex(topMessageIndex: nil, inclusion: .notIncluded)
            self.cachedPeerIndices[peerId] = inclusionIndex
            return inclusionIndex
        }
    }
}
This post is licensed under CC BY 4.0 by the author.