From d4b7ea31faa2674f000ed9ceeaece4de4965b4e9 Mon Sep 17 00:00:00 2001 From: Peter Iakovlev Date: Fri, 16 Nov 2018 15:55:03 +0400 Subject: [PATCH] Improved shuffling --- Postbox/MessageHistoryTable.swift | 4 +-- Postbox/MessageHistoryTagsTable.swift | 21 ++++++++++--- Postbox/Postbox.swift | 43 ++++++++++++++++++++------- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/Postbox/MessageHistoryTable.swift b/Postbox/MessageHistoryTable.swift index 15efc25557..62a1ca40f5 100644 --- a/Postbox/MessageHistoryTable.swift +++ b/Postbox/MessageHistoryTable.swift @@ -3177,8 +3177,8 @@ final class MessageHistoryTable: Table { return result } - func findRandomMessage(peerId: PeerId, tagMask: MessageTags, ignoreId: MessageId) -> MessageIndex? { - if let index = self.tagsTable.findRandomIndex(peerId: peerId, tagMask: tagMask, ignoreId: ignoreId, isMessage: { index in + func findRandomMessage(peerId: PeerId, tagMask: MessageTags, ignoreIds: ([MessageId], Set)) -> MessageIndex? { + if let index = self.tagsTable.findRandomIndex(peerId: peerId, tagMask: tagMask, ignoreIds: ignoreIds, isMessage: { index in return self.getMessage(index) != nil }) { return self.getMessage(index).flatMap(MessageIndex.init) diff --git a/Postbox/MessageHistoryTagsTable.swift b/Postbox/MessageHistoryTagsTable.swift index c291d6f46a..5b163405ca 100644 --- a/Postbox/MessageHistoryTagsTable.swift +++ b/Postbox/MessageHistoryTagsTable.swift @@ -172,21 +172,34 @@ class MessageHistoryTagsTable: Table { return count } - func findRandomIndex(peerId: PeerId, tagMask: MessageTags, ignoreId: MessageId, isMessage: (MessageIndex) -> Bool) -> MessageIndex? { + func findRandomIndex(peerId: PeerId, tagMask: MessageTags, ignoreIds: ([MessageId], Set), isMessage: (MessageIndex) -> Bool) -> MessageIndex? { var indices: [MessageIndex] = [] self.valueBox.range(self.table, start: self.lowerBound(tagMask, peerId: peerId), end: self.upperBound(tagMask, peerId: peerId), keys: { key in indices.append(MessageIndex(id: MessageId(peerId: PeerId(key.getInt64(0)), namespace: key.getInt32(8 + 4 + 4), id: key.getInt32(8 + 4 + 4 + 4)), timestamp: key.getInt32(8 + 4))) return true }, limit: 0) var checkedIndices = Set() - loop: while checkedIndices.count < indices.count { + while checkedIndices.count < indices.count { let i = Int(arc4random_uniform(UInt32(indices.count))) if checkedIndices.contains(i) { - continue loop + continue } checkedIndices.insert(i) let index = indices[i] - if isMessage(index) && ignoreId != index.id { + if isMessage(index) && !ignoreIds.1.contains(index.id) { + return index + } + } + checkedIndices.removeAll() + let lastId = ignoreIds.0.last + while checkedIndices.count < indices.count { + let i = Int(arc4random_uniform(UInt32(indices.count))) + if checkedIndices.contains(i) { + continue + } + checkedIndices.insert(i) + let index = indices[i] + if isMessage(index) && lastId != index.id { return index } } diff --git a/Postbox/Postbox.swift b/Postbox/Postbox.swift index a36e3f6410..0971b64965 100644 --- a/Postbox/Postbox.swift +++ b/Postbox/Postbox.swift @@ -347,9 +347,14 @@ public final class Transaction { return self.postbox?.cachedPeerDataTable.get(peerId) } - public func updatePeerPresencesInternal(_ peerPresences: [PeerId: PeerPresence]) { + public func updatePeerPresencesInternal(presences: [PeerId: PeerPresence], merge: (PeerPresence, PeerPresence) -> PeerPresence) { assert(!self.disposed) - self.postbox?.updatePeerPresences(peerPresences) + self.postbox?.updatePeerPresences(presences: presences, merge: merge) + } + + public func updatePeerPresenceInternal(peerId: PeerId, update: (PeerPresence) -> PeerPresence) { + assert(!self.disposed) + self.postbox?.updatePeerPresence(peerId: peerId, update: update) } public func getPeerPresence(peerId: PeerId) -> PeerPresence? { @@ -607,9 +612,9 @@ public final class Transaction { return self.postbox?.messageHistoryTable.findClosestMessageId(peerId: peerId, timestamp: timestamp) } - public func findRandomMessage(peerId: PeerId, tagMask: MessageTags, ignoreId: MessageId) -> MessageIndex? { + public func findRandomMessage(peerId: PeerId, tagMask: MessageTags, ignoreIds: ([MessageId], Set)) -> MessageIndex? { assert(!self.disposed) - return self.postbox?.messageHistoryTable.findRandomMessage(peerId: peerId, tagMask: tagMask, ignoreId: ignoreId) + return self.postbox?.messageHistoryTable.findRandomMessage(peerId: peerId, tagMask: tagMask, ignoreIds: ignoreIds) } public func filterStoredMessageIds(_ messageIds: Set) -> Set { @@ -2067,12 +2072,30 @@ public final class Postbox { } } - fileprivate func updatePeerPresences(_ peerPresences: [PeerId: PeerPresence]) { - for (peerId, presence) in peerPresences { - let currentPresence = self.peerPresenceTable.get(peerId) - if currentPresence == nil || !(currentPresence!.isEqual(to: presence)) { - self.peerPresenceTable.set(id: peerId, presence: presence) - self.currentUpdatedPeerPresences[peerId] = presence + fileprivate func updatePeerPresences(presences: [PeerId: PeerPresence], merge: (PeerPresence, PeerPresence) -> PeerPresence) { + for (peerId, presence) in presences { + let updated: PeerPresence + let shouldUpdate: Bool + if let current = self.peerPresenceTable.get(peerId) { + updated = merge(current, presence) + shouldUpdate = !current.isEqual(to: updated) + } else { + updated = presence + shouldUpdate = true + } + if shouldUpdate { + self.peerPresenceTable.set(id: peerId, presence: updated) + self.currentUpdatedPeerPresences[peerId] = updated + } + } + } + + fileprivate func updatePeerPresence(peerId: PeerId, update: (PeerPresence) -> PeerPresence) { + if let current = self.peerPresenceTable.get(peerId) { + let updated = update(current) + if !current.isEqual(to: updated) { + self.peerPresenceTable.set(id: peerId, presence: updated) + self.currentUpdatedPeerPresences[peerId] = updated } } }