mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
100 lines
3.3 KiB
Swift
100 lines
3.3 KiB
Swift
import Foundation
|
|
|
|
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
|
|
}
|
|
|
|
private func writePeerIds(_ buffer: WriteBuffer, _ peerIds: Set<PeerId>) {
|
|
for id in peerIds {
|
|
var value: Int64 = id.toInt64()
|
|
buffer.write(&value, offset: 0, length: 8)
|
|
}
|
|
}
|
|
|
|
final class ReverseAssociatedPeerTable: Table {
|
|
static func tableSpec(_ id: Int32) -> ValueBoxTable {
|
|
return ValueBoxTable(id: id, keyType: .int64, compactValuesOnCreation: false)
|
|
}
|
|
|
|
private let sharedKey = ValueBoxKey(length: 8)
|
|
|
|
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
|
|
}
|
|
|
|
func get(peerId: PeerId) -> Set<PeerId> {
|
|
if let cached = self.cachedAssociations[peerId] {
|
|
return cached
|
|
} else {
|
|
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()
|
|
}
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
override func clearMemoryCache() {
|
|
self.cachedAssociations.removeAll()
|
|
assert(self.updatedAssociations.isEmpty)
|
|
}
|
|
|
|
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()
|
|
}
|
|
}
|
|
}
|