Improved shuffling

This commit is contained in:
Peter Iakovlev
2018-11-16 15:55:03 +04:00
parent 96916ca991
commit d4b7ea31fa
3 changed files with 52 additions and 16 deletions

View File

@@ -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<MessageId>)) -> 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)

View File

@@ -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<MessageId>), 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<Int>()
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
}
}

View File

@@ -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<MessageId>)) -> 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<MessageId>) -> Set<MessageId> {
@@ -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
}
}
}