This commit is contained in:
overtake 2017-06-06 13:00:05 +03:00
commit d294e15e16
15 changed files with 263 additions and 79 deletions

View File

@ -174,6 +174,10 @@
D0BEAF701E54BC1E00BD963D /* AccountRecordsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF6F1E54BC1E00BD963D /* AccountRecordsView.swift */; };
D0BEAF711E54BC1E00BD963D /* AccountRecordsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEAF6F1E54BC1E00BD963D /* AccountRecordsView.swift */; };
D0C07F6A1B67DB4800966E43 /* SwiftSignalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0C07F691B67DB4800966E43 /* SwiftSignalKit.framework */; };
D0C0B5AB1EE1AB08000F4D2C /* ReverseAssociatedPeerTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C0B5AA1EE1AB08000F4D2C /* ReverseAssociatedPeerTable.swift */; };
D0C0B5AC1EE1AB08000F4D2C /* ReverseAssociatedPeerTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C0B5AA1EE1AB08000F4D2C /* ReverseAssociatedPeerTable.swift */; };
D0C0B5AE1EE1B3F4000F4D2C /* PostboxUpgrade_13to14.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C0B5AD1EE1B3F4000F4D2C /* PostboxUpgrade_13to14.swift */; };
D0C0B5AF1EE1B3F4000F4D2C /* PostboxUpgrade_13to14.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C0B5AD1EE1B3F4000F4D2C /* PostboxUpgrade_13to14.swift */; };
D0C674C81CBB11C600183765 /* MessageHistoryReadStateTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C674C71CBB11C600183765 /* MessageHistoryReadStateTable.swift */; };
D0C674CC1CBB14A700183765 /* PeerReadState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C674CB1CBB14A700183765 /* PeerReadState.swift */; };
D0C735281C864DF300BB3149 /* PeerChatStateTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C735271C864DF300BB3149 /* PeerChatStateTable.swift */; };
@ -376,6 +380,8 @@
D0BEAF6C1E54B77900BD963D /* AccountManagerRecordTable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountManagerRecordTable.swift; sourceTree = "<group>"; };
D0BEAF6F1E54BC1E00BD963D /* AccountRecordsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountRecordsView.swift; sourceTree = "<group>"; };
D0C07F691B67DB4800966E43 /* SwiftSignalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = SwiftSignalKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D0C0B5AA1EE1AB08000F4D2C /* ReverseAssociatedPeerTable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReverseAssociatedPeerTable.swift; sourceTree = "<group>"; };
D0C0B5AD1EE1B3F4000F4D2C /* PostboxUpgrade_13to14.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostboxUpgrade_13to14.swift; sourceTree = "<group>"; };
D0C674C71CBB11C600183765 /* MessageHistoryReadStateTable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageHistoryReadStateTable.swift; sourceTree = "<group>"; };
D0C674CB1CBB14A700183765 /* PeerReadState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerReadState.swift; sourceTree = "<group>"; };
D0C735271C864DF300BB3149 /* PeerChatStateTable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerChatStateTable.swift; sourceTree = "<group>"; };
@ -536,6 +542,7 @@
children = (
D0F02CDE1E99223D0065DEE2 /* Upgrades.swift */,
D0F02CE11E9922F50065DEE2 /* PostboxUpgrade_12to13.swift */,
D0C0B5AD1EE1B3F4000F4D2C /* PostboxUpgrade_13to14.swift */,
);
name = Upgrade;
sourceTree = "<group>";
@ -577,6 +584,7 @@
D0F3CC711DDE1CDC008148FA /* ItemCacheTable.swift */,
D07827C21E008F7300071108 /* ReverseIndexReferenceTable.swift */,
D07827C41E00B23F00071108 /* PeerNameIndexTable.swift */,
D0C0B5AA1EE1AB08000F4D2C /* ReverseAssociatedPeerTable.swift */,
D0AD23261E194D1C00A7089A /* PeerOperationLogTable.swift */,
D010B6191E1E463900C3E282 /* PeerMergedOperationLogIndexTable.swift */,
D0AD23281E196B6400A7089A /* PeerOperationLogMetadataTable.swift */,
@ -978,6 +986,7 @@
D0BEAF641E54B2FA00BD963D /* AccountManager.swift in Sources */,
D073CE7F1DCBF3B4007511FD /* ItemCollection.swift in Sources */,
D0F7B1D91E045C6A007EB8A5 /* OrderStatisticTable.swift in Sources */,
D0C0B5AF1EE1B3F4000F4D2C /* PostboxUpgrade_13to14.swift in Sources */,
D073CEA01DCBF3C1007511FD /* ItemCollectionsView.swift in Sources */,
D0BE383A1E7C1FD4000079AF /* ItemCollectionInfoView.swift in Sources */,
D0B418491D7DFE20004562A4 /* ChatListView.swift in Sources */,
@ -1027,6 +1036,7 @@
D0B418311D7DFE16004562A4 /* ValueBox.swift in Sources */,
D08775041E3E3E7400A97350 /* PreferencesEntry.swift in Sources */,
D0B4184E1D7DFE20004562A4 /* MessageHistoryHolesView.swift in Sources */,
D0C0B5AC1EE1AB08000F4D2C /* ReverseAssociatedPeerTable.swift in Sources */,
D0B844051DAB91B5005F29E1 /* MediaBox.swift in Sources */,
D0B418321D7DFE16004562A4 /* SqliteValueBox.swift in Sources */,
D073CE741DCBF3B4007511FD /* Peer.swift in Sources */,
@ -1105,6 +1115,7 @@
D0BEAF631E54B2FA00BD963D /* AccountManager.swift in Sources */,
D0AD23271E194D1C00A7089A /* PeerOperationLogTable.swift in Sources */,
D021E0D41DB4FAE100C6B04F /* ItemCollection.swift in Sources */,
D0C0B5AE1EE1B3F4000F4D2C /* PostboxUpgrade_13to14.swift in Sources */,
D0D510F91D63BCC200A97B8A /* IntermediateMessage.swift in Sources */,
D0BE38391E7C1FD4000079AF /* ItemCollectionInfoView.swift in Sources */,
D0F9E86B1C59719800037222 /* ChatListView.swift in Sources */,
@ -1154,6 +1165,7 @@
D03120FC1DA55427006A2A60 /* PeerNotificationSettings.swift in Sources */,
D0F7AB321DCFAB18009AD9A1 /* PeerChatTopIndexableMessageIds.swift in Sources */,
D03BCCF81C73561C0097A291 /* Table.swift in Sources */,
D0C0B5AB1EE1AB08000F4D2C /* ReverseAssociatedPeerTable.swift in Sources */,
D021E0DC1DB5237C00C6B04F /* ItemCollectionsView.swift in Sources */,
D0C735281C864DF300BB3149 /* PeerChatStateTable.swift in Sources */,
D0AAD1B31E3266B100D5B9DE /* TimestampBasedMessageAttributesTable.swift in Sources */,

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -444,11 +444,9 @@ final class MutableChatListView {
var peers = SimpleDictionary<PeerId, Peer>()
if let peer = getPeer(index.messageIndex.id.peerId) {
peers[peer.id] = peer
if let associatedPeerIds = peer.associatedPeerIds {
for associatedPeerId in associatedPeerIds {
if let associatedPeer = getPeer(associatedPeerId) {
peers[associatedPeer.id] = associatedPeer
}
if let associatedPeerId = peer.associatedPeerId {
if let associatedPeer = getPeer(associatedPeerId) {
peers[associatedPeer.id] = associatedPeer
}
}
}

View File

@ -1625,11 +1625,9 @@ final class MessageHistoryTable: Table {
if let chatPeer = peerTable.get(message.id.peerId) {
peers[chatPeer.id] = chatPeer
if let associatedPeerIds = chatPeer.associatedPeerIds {
for peerId in associatedPeerIds {
if let peer = peerTable.get(peerId) {
peers[peer.id] = peer
}
if let associatedPeerId = chatPeer.associatedPeerId {
if let peer = peerTable.get(associatedPeerId) {
peers[peer.id] = peer
}
}
}

View File

@ -95,7 +95,7 @@ public func <(lhs: PeerId, rhs: PeerId) -> Bool {
public protocol Peer: class, Coding {
var id: PeerId { get }
var indexName: PeerIndexNameRepresentation { get }
var associatedPeerIds: [PeerId]? { get }
var associatedPeerId: PeerId? { get }
var notificationSettingsPeerId: PeerId? { get }
func isEqual(_ other: Peer) -> Bool

View File

@ -257,7 +257,7 @@ final class PeerNameIndexTable: Table {
}
}
func matchingPeerIds(tokens: (regular: [ValueBoxKey], transliterated: [ValueBoxKey]?), categories: PeerNameIndexCategories, chatListIndexTable: ChatListIndexTable, contactTable: ContactTable) -> (chats: [PeerId], contacts: [PeerId]) {
func matchingPeerIds(tokens: (regular: [ValueBoxKey], transliterated: [ValueBoxKey]?), categories: PeerNameIndexCategories, chatListIndexTable: ChatListIndexTable, contactTable: ContactTable, reverseAssociatedPeerTable: ReverseAssociatedPeerTable) -> (chats: [PeerId], contacts: [PeerId]) {
if categories.isEmpty {
return ([], [])
} else {

View File

@ -5,11 +5,19 @@ final class PeerTable: Table {
return ValueBoxTable(id: id, keyType: .int64)
}
private let reverseAssociatedTable: ReverseAssociatedPeerTable
private let sharedEncoder = Encoder()
private let sharedKey = ValueBoxKey(length: 8)
private var cachedPeers: [PeerId: Peer] = [:]
private var updatedPeerIds = Set<PeerId>()
private var updatedInitialPeers: [PeerId: Peer?] = [:]
init(valueBox: ValueBox, table: ValueBoxTable, reverseAssociatedTable: ReverseAssociatedPeerTable) {
self.reverseAssociatedTable = reverseAssociatedTable
super.init(valueBox: valueBox, table: table)
}
private func key(_ id: PeerId) -> ValueBoxKey {
self.sharedKey.setInt64(0, value: id.toInt64())
@ -17,8 +25,11 @@ final class PeerTable: Table {
}
func set(_ peer: Peer) {
let previous = self.get(peer.id)
self.cachedPeers[peer.id] = peer
self.updatedPeerIds.insert(peer.id)
if self.updatedInitialPeers[peer.id] == nil {
self.updatedInitialPeers[peer.id] = previous
}
}
func get(_ id: PeerId) -> Peer? {
@ -36,19 +47,31 @@ final class PeerTable: Table {
override func clearMemoryCache() {
self.cachedPeers.removeAll()
self.updatedPeerIds.removeAll()
assert(self.updatedInitialPeers.isEmpty)
}
override func beforeCommit() {
for peerId in self.updatedPeerIds {
for (peerId, previousPeer) in self.updatedInitialPeers {
if let peer = self.cachedPeers[peerId] {
self.sharedEncoder.reset()
self.sharedEncoder.encodeRootObject(peer)
self.valueBox.set(self.table, key: self.key(peerId), value: self.sharedEncoder.readBufferNoCopy())
let previousAssociation = previousPeer?.associatedPeerId
if previousAssociation != peer.associatedPeerId {
if let previousAssociation = previousAssociation {
self.reverseAssociatedTable.removeReverseAssociation(target: previousAssociation, from: peerId)
}
if let associatedPeerId = peer.associatedPeerId {
self.reverseAssociatedTable.addReverseAssociation(target: associatedPeerId, from: peerId)
}
}
} else {
assertionFailure()
}
}
self.updatedPeerIds.removeAll()
self.updatedInitialPeers.removeAll()
}
}

View File

@ -1,6 +1,6 @@
import Foundation
final class MutablePeerView {
final class MutablePeerView: MutablePostboxView {
let peerId: PeerId
var notificationSettings: PeerNotificationSettings?
var cachedData: CachedPeerData?
@ -8,17 +8,27 @@ final class MutablePeerView {
var peerPresences: [PeerId: PeerPresence] = [:]
var peerIsContact: Bool
init(peerId: PeerId, notificationSettings: PeerNotificationSettings?, cachedData: CachedPeerData?, peerIsContact: Bool, getPeer: (PeerId) -> Peer?, getPeerPresence: (PeerId) -> PeerPresence?) {
init(postbox: Postbox, peerId: PeerId) {
let notificationSettings = postbox.peerNotificationSettingsTable.get(peerId)
let cachedData = postbox.cachedPeerDataTable.get(peerId)
let peerIsContact = postbox.contactsTable.isContact(peerId: peerId)
let getPeer: (PeerId) -> Peer? = { peerId in
return postbox.peerTable.get(peerId)
}
let getPeerPresence: (PeerId) -> PeerPresence? = { peerId in
return postbox.peerPresenceTable.get(peerId)
}
self.peerId = peerId
self.notificationSettings = notificationSettings
self.cachedData = cachedData
self.peerIsContact = peerIsContact
var peerIds = Set<PeerId>()
peerIds.insert(peerId)
if let peer = getPeer(peerId), let associatedPeerIds = peer.associatedPeerIds {
for peerId in associatedPeerIds {
peerIds.insert(peerId)
}
if let peer = getPeer(peerId), let associatedPeerId = peer.associatedPeerId {
peerIds.insert(associatedPeerId)
}
if let cachedData = cachedData {
peerIds.formUnion(cachedData.peerIds)
@ -31,19 +41,35 @@ final class MutablePeerView {
self.peerPresences[id] = presence
}
}
if let peer = self.peers[peerId], let associatedPeerIds = peer.associatedPeerIds {
for id in associatedPeerIds {
if let peer = getPeer(id) {
self.peers[id] = peer
}
if let presence = getPeerPresence(id) {
self.peerPresences[id] = presence
}
if let peer = self.peers[peerId], let associatedPeerId = peer.associatedPeerId {
if let peer = getPeer(associatedPeerId) {
self.peers[associatedPeerId] = peer
}
if let presence = getPeerPresence(associatedPeerId) {
self.peerPresences[associatedPeerId] = presence
}
}
}
func replay(updatedPeers: [PeerId: Peer], updatedNotificationSettings: [PeerId: PeerNotificationSettings], updatedCachedPeerData: [PeerId: CachedPeerData], updatedPeerPresences: [PeerId: PeerPresence], replaceContactPeerIds: Set<PeerId>?, getPeer: (PeerId) -> Peer?, getPeerPresence: (PeerId) -> PeerPresence?) -> Bool {
func reset(postbox: Postbox) -> Bool {
return false
}
func replay(postbox: Postbox, transaction: PostboxTransaction) -> Bool {
let updatedPeers = transaction.currentUpdatedPeers
let updatedNotificationSettings = transaction.currentUpdatedPeerNotificationSettings
let updatedCachedPeerData = transaction.currentUpdatedCachedPeerData
let updatedPeerPresences = transaction.currentUpdatedPeerPresences
let replaceContactPeerIds = transaction.replaceContactPeerIds
let getPeer: (PeerId) -> Peer? = { peerId in
return postbox.peerTable.get(peerId)
}
let getPeerPresence: (PeerId) -> PeerPresence? = { peerId in
return postbox.peerPresenceTable.get(peerId)
}
var updated = false
if let cachedData = updatedCachedPeerData[self.peerId], self.cachedData == nil || !self.cachedData!.isEqual(to: cachedData) {
@ -52,10 +78,8 @@ final class MutablePeerView {
var peerIds = Set<PeerId>()
peerIds.insert(self.peerId)
if let peer = getPeer(self.peerId), let associatedPeerIds = peer.associatedPeerIds {
for peerId in associatedPeerIds {
peerIds.insert(peerId)
}
if let peer = getPeer(self.peerId), let associatedPeerId = peer.associatedPeerId {
peerIds.insert(associatedPeerId)
}
peerIds.formUnion(cachedData.peerIds)
@ -97,10 +121,8 @@ final class MutablePeerView {
} else {
var peerIds = Set<PeerId>()
peerIds.insert(self.peerId)
if let peer = getPeer(self.peerId), let associatedPeerIds = peer.associatedPeerIds {
for peerId in associatedPeerIds {
peerIds.insert(peerId)
}
if let peer = getPeer(self.peerId), let associatedPeerId = peer.associatedPeerId {
peerIds.insert(associatedPeerId)
}
if let cachedData = self.cachedData {
peerIds.formUnion(cachedData.peerIds)
@ -139,9 +161,13 @@ final class MutablePeerView {
return updated
}
func immutableView() -> PostboxView {
return PeerView(self)
}
}
public final class PeerView {
public final class PeerView: PostboxView {
public let peerId: PeerId
public let cachedData: CachedPeerData?
public let notificationSettings: PeerNotificationSettings?

View File

@ -739,6 +739,7 @@ public final class Postbox {
let itemCacheTable: ItemCacheTable
let peerNameTokenIndexTable: ReverseIndexReferenceTable<PeerIdReverseIndexReference>
let peerNameIndexTable: PeerNameIndexTable
let reverseAssociatedPeerTable: ReverseAssociatedPeerTable
let peerChatTopTaggedMessageIdsTable: PeerChatTopTaggedMessageIdsTable
let peerOperationLogMetadataTable: PeerOperationLogMetadataTable
let peerMergedOperationLogIndexTable: PeerMergedOperationLogIndexTable
@ -782,7 +783,8 @@ public final class Postbox {
self.metadataTable = MetadataTable(valueBox: self.valueBox, table: MetadataTable.tableSpec(0))
self.keychainTable = KeychainTable(valueBox: self.valueBox, table: KeychainTable.tableSpec(1))
self.peerTable = PeerTable(valueBox: self.valueBox, table: PeerTable.tableSpec(2))
self.reverseAssociatedPeerTable = ReverseAssociatedPeerTable(valueBox: self.valueBox, table:ReverseAssociatedPeerTable.tableSpec(40))
self.peerTable = PeerTable(valueBox: self.valueBox, table: PeerTable.tableSpec(2), reverseAssociatedTable: self.reverseAssociatedPeerTable)
self.globalMessageIdsTable = GlobalMessageIdsTable(valueBox: self.valueBox, table: GlobalMessageIdsTable.tableSpec(3), namespace: self.globalMessageIdsNamespace)
self.globallyUniqueMessageIdsTable = MessageGloballyUniqueIdTable(valueBox: self.valueBox, table: MessageGloballyUniqueIdTable.tableSpec(32))
self.messageHistoryMetadataTable = MessageHistoryMetadataTable(valueBox: self.valueBox, table: MessageHistoryMetadataTable.tableSpec(10))
@ -850,6 +852,7 @@ public final class Postbox {
tables.append(self.itemCacheMetaTable)
tables.append(self.itemCacheTable)
tables.append(self.peerNameIndexTable)
tables.append(self.reverseAssociatedPeerTable)
tables.append(self.peerNameTokenIndexTable)
tables.append(self.peerChatTopTaggedMessageIdsTable)
tables.append(self.peerOperationLogMetadataTable)
@ -1257,7 +1260,7 @@ public final class Postbox {
for table in self.tables {
table.clearMemoryCache()
}
self.viewTracker.refreshViewsDueToExternalTransaction(fetchAroundChatEntries: self.fetchAroundChatEntries, fetchAroundHistoryEntries: self.fetchAroundHistoryEntries, fetchUnsentMessageIds: {
self.viewTracker.refreshViewsDueToExternalTransaction(postbox: self, fetchAroundChatEntries: self.fetchAroundChatEntries, fetchAroundHistoryEntries: self.fetchAroundHistoryEntries, fetchUnsentMessageIds: {
return self.messageHistoryUnsentTable.get()
}, fetchSynchronizePeerReadStateOperations: {
return self.synchronizeReadStateTable.get(getCombinedPeerReadState: { peerId in
@ -1781,7 +1784,7 @@ public final class Postbox {
public func searchContacts(query: String) -> Signal<[Peer], NoError> {
return self.modify { modifier -> Signal<[Peer], NoError> in
let (_, contactPeerIds) = self.peerNameIndexTable.matchingPeerIds(tokens: (regular: stringIndexTokens(query, transliteration: .none), transliterated: stringIndexTokens(query, transliteration: .transliterated)), categories: [.contacts], chatListIndexTable: self.chatListIndexTable, contactTable: self.contactsTable)
let (_, contactPeerIds) = self.peerNameIndexTable.matchingPeerIds(tokens: (regular: stringIndexTokens(query, transliteration: .none), transliterated: stringIndexTokens(query, transliteration: .transliterated)), categories: [.contacts], chatListIndexTable: self.chatListIndexTable, contactTable: self.contactsTable, reverseAssociatedPeerTable: self.reverseAssociatedPeerTable)
var contactPeers: [Peer] = []
for peerId in contactPeerIds {
@ -1800,7 +1803,7 @@ public final class Postbox {
var peerIds = Set<PeerId>()
var chatPeers: [Peer] = []
let (chatPeerIds, contactPeerIds) = self.peerNameIndexTable.matchingPeerIds(tokens: (regular: stringIndexTokens(query, transliteration: .none), transliterated: stringIndexTokens(query, transliteration: .transliterated)), categories: [.chats, .contacts], chatListIndexTable: self.chatListIndexTable, contactTable: self.contactsTable)
let (chatPeerIds, contactPeerIds) = self.peerNameIndexTable.matchingPeerIds(tokens: (regular: stringIndexTokens(query, transliteration: .none), transliterated: stringIndexTokens(query, transliteration: .transliterated)), categories: [.chats, .contacts], chatListIndexTable: self.chatListIndexTable, contactTable: self.contactsTable, reverseAssociatedPeerTable: self.reverseAssociatedPeerTable)
for peerId in chatPeerIds {
if let peer = self.peerTable.get(peerId) {
@ -1825,7 +1828,7 @@ public final class Postbox {
public func peerView(id: PeerId) -> Signal<PeerView, NoError> {
return self.modify { modifier -> Signal<PeerView, NoError> in
let view = MutablePeerView(peerId: id, notificationSettings: self.peerNotificationSettingsTable.get(id), cachedData: self.cachedPeerDataTable.get(id), peerIsContact: self.contactsTable.isContact(peerId: id), getPeer: { self.peerTable.get($0) }, getPeerPresence: { self.peerPresenceTable.get($0) })
let view = MutablePeerView(postbox: self, peerId: id)
let (index, signal) = self.viewTracker.addPeerView(view)
return (.single(PeerView(view))

View File

@ -0,0 +1,41 @@
import Foundation
private func writePeerIds(_ buffer: WriteBuffer, _ peerIds: Set<PeerId>) {
for id in peerIds {
var value: Int64 = id.toInt64()
buffer.write(&value, offset: 0, length: 8)
}
}
func postboxUpgrade_13to14(metadataTable: MetadataTable, valueBox: ValueBox) {
var reverseAssociations: [PeerId: Set<PeerId>] = [:]
let peerTable = ValueBoxTable(id: 2, keyType: .int64)
valueBox.scan(peerTable, values: { _, value in
if let peer = Decoder(buffer: value).decodeRootObject() as? Peer {
if let association = peer.associatedPeerId {
if reverseAssociations[association] == nil {
reverseAssociations[association] = Set()
}
reverseAssociations[association]!.insert(peer.id)
}
} else {
assertionFailure()
}
return true
})
let reverseAssociatedPeerTable = ValueBoxTable(id: 40, keyType: .int64)
let sharedKey = ValueBoxKey(length: 8)
let sharedBuffer = WriteBuffer()
for (peerId, associations) in reverseAssociations {
sharedBuffer.reset()
writePeerIds(sharedBuffer, associations)
sharedKey.setInt64(0, value: peerId.toInt64())
valueBox.set(reverseAssociatedPeerTable, key: sharedKey, value: sharedBuffer)
}
metadataTable.setUserVersion(14)
}

View File

@ -0,0 +1,99 @@
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)
}
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))
} else {
buffer.reset()
writePeerIds(buffer, peerIds)
self.valueBox.set(self.table, key: self.key(peerId), value: buffer)
}
} else {
assertionFailure()
}
}
self.updatedAssociations.removeAll()
}
}
}

View File

@ -7,5 +7,6 @@ enum PostboxUpgradeOperation {
func registeredUpgrades() -> [Int32: PostboxUpgradeOperation] {
var dict: [Int32: PostboxUpgradeOperation] = [:]
dict[12] = .inplace(postboxUpgrade_12to13)
dict[13] = .inplace(postboxUpgrade_13to14)
return dict
}

View File

@ -289,7 +289,7 @@ final class ViewTracker {
self.combinedViews.remove(index)
}
func refreshViewsDueToExternalTransaction(fetchAroundChatEntries: (_ index: ChatListIndex, _ count: Int) -> (entries: [MutableChatListEntry], earlier: MutableChatListEntry?, later: MutableChatListEntry?), fetchAroundHistoryEntries: (_ index: MessageIndex, _ count: Int, _ tagMask: MessageTags?) -> (entries: [MutableMessageHistoryEntry], lower: MutableMessageHistoryEntry?, upper: MutableMessageHistoryEntry?), fetchUnsentMessageIds: () -> [MessageId], fetchSynchronizePeerReadStateOperations: () -> [PeerId: PeerReadStateSynchronizationOperation]) {
func refreshViewsDueToExternalTransaction(postbox: Postbox, fetchAroundChatEntries: (_ index: ChatListIndex, _ count: Int) -> (entries: [MutableChatListEntry], earlier: MutableChatListEntry?, later: MutableChatListEntry?), fetchAroundHistoryEntries: (_ index: MessageIndex, _ count: Int, _ tagMask: MessageTags?) -> (entries: [MutableMessageHistoryEntry], lower: MutableMessageHistoryEntry?, upper: MutableMessageHistoryEntry?), fetchUnsentMessageIds: () -> [MessageId], fetchSynchronizePeerReadStateOperations: () -> [PeerId: PeerReadStateSynchronizationOperation]) {
var updateTrackedHolesPeerIds: [PeerId] = []
for (peerId, bag) in self.messageHistoryViews {
@ -327,35 +327,7 @@ final class ViewTracker {
}
for (mutableView, pipe) in self.peerViews.copyItems() {
var updatedPeers: [PeerId: Peer] = [:]
var updatedPeerPresences: [PeerId: PeerPresence] = [:]
var updatedNotificationSettings: [PeerId: PeerNotificationSettings] = [:]
var updatedCachedPeerData: [PeerId: CachedPeerData] = [:]
let peerId = mutableView.peerId
if let peer = self.getPeer(peerId) {
updatedPeers[peerId] = peer
}
if let presence = self.getPeerPresence(peerId) {
updatedPeerPresences[peerId] = presence
}
if let notificationSettings = self.getPeerNotificationSettings(peerId) {
updatedNotificationSettings[peerId] = notificationSettings
}
if let cachedPeerData = self.getCachedPeerData(peerId) {
updatedCachedPeerData[peerId] = cachedPeerData
for cachedPeerId in cachedPeerData.peerIds {
if let peer = self.getPeer(cachedPeerId) {
updatedPeers[cachedPeerId] = peer
}
if let presence = self.getPeerPresence(cachedPeerId) {
updatedPeerPresences[cachedPeerId] = presence
}
}
}
if mutableView.replay(updatedPeers: updatedPeers, updatedNotificationSettings: updatedNotificationSettings, updatedCachedPeerData: updatedCachedPeerData, updatedPeerPresences: updatedPeerPresences, replaceContactPeerIds: nil, getPeer: self.getPeer, getPeerPresence: self.getPeerPresence) {
if mutableView.reset(postbox: postbox) {
pipe.putNext(PeerView(mutableView))
}
}
@ -483,7 +455,7 @@ final class ViewTracker {
}
for (mutableView, pipe) in self.peerViews.copyItems() {
if mutableView.replay(updatedPeers: transaction.currentUpdatedPeers, updatedNotificationSettings: transaction.currentUpdatedPeerNotificationSettings, updatedCachedPeerData: transaction.currentUpdatedCachedPeerData, updatedPeerPresences: transaction.currentUpdatedPeerPresences, replaceContactPeerIds: transaction.replaceContactPeerIds, getPeer: self.getPeer, getPeerPresence: self.getPeerPresence) {
if mutableView.replay(postbox: postbox, transaction: transaction) {
pipe.putNext(PeerView(mutableView))
}
}

View File

@ -9,6 +9,7 @@ public enum PostboxViewKey: Hashable {
case accessChallengeData
case preferences(keys: Set<ValueBoxKey>)
case globalMessageTags(globalTag: GlobalMessageTags, position: MessageIndex, count: Int, groupingPredicate: ((Message, Message) -> Bool)?)
case peer(peerId: PeerId)
public var hashValue: Int {
switch self {
@ -28,6 +29,8 @@ public enum PostboxViewKey: Hashable {
return 3
case .globalMessageTags:
return 4
case let .peer(peerId):
return peerId.hashValue
}
}
@ -81,6 +84,12 @@ public enum PostboxViewKey: Hashable {
} else {
return false
}
case let .peer(peerId):
if case .peer(peerId) = rhs {
return true
} else {
return false
}
}
}
}
@ -103,5 +112,7 @@ func postboxViewForKey(postbox: Postbox, key: PostboxViewKey) -> MutablePostboxV
return MutablePreferencesView(postbox: postbox, keys: keys)
case let .globalMessageTags(globalTag, position, count, groupingPredicate):
return MutableGlobalMessageTagsView(postbox: postbox, globalTag: globalTag, position: position, count: count, groupingPredicate: groupingPredicate)
case let .peer(peerId):
return MutablePeerView(postbox: postbox, peerId: peerId)
}
}