This commit is contained in:
overtake 2017-06-16 12:18:45 +03:00
commit c09f88d732
7 changed files with 158 additions and 39 deletions

View File

@ -1267,10 +1267,11 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
OTHER_CFLAGS = (
"-DSQLITE_TEMP_STORE=2",
"-DSQLITE_HAS_CODEC=1",
"-DSQLCIPHER_CRYPTO_CC=1",
"-DSQLITE_ENABLE_FTS3",
"-DSQLITE_OMIT_DEPRECATED",
"-DSQLITE_ENABLE_FTS5",
"-DSQLITE_DEFAULT_MEMSTATUS=0",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.telegram.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1394,10 +1395,11 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
OTHER_CFLAGS = (
"-DSQLITE_TEMP_STORE=2",
"-DSQLITE_HAS_CODEC=1",
"-DSQLCIPHER_CRYPTO_CC=1",
"-DSQLITE_ENABLE_FTS3",
"-DSQLITE_OMIT_DEPRECATED",
"-DSQLITE_ENABLE_FTS5",
"-DSQLITE_DEFAULT_MEMSTATUS=0",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.telegram.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1642,10 +1644,11 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
OTHER_CFLAGS = (
"-DSQLITE_TEMP_STORE=2",
"-DSQLITE_HAS_CODEC=1",
"-DSQLCIPHER_CRYPTO_CC=1",
"-DSQLITE_ENABLE_FTS3",
"-DSQLITE_OMIT_DEPRECATED",
"-DSQLITE_ENABLE_FTS5",
"-DSQLITE_DEFAULT_MEMSTATUS=0",
);
OTHER_SWIFT_FLAGS = "-DDEBUG";
PRODUCT_BUNDLE_IDENTIFIER = "org.telegram.$(PRODUCT_NAME:rfc1034identifier)";
@ -1675,10 +1678,11 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
OTHER_CFLAGS = (
"-DSQLITE_TEMP_STORE=2",
"-DSQLITE_HAS_CODEC=1",
"-DSQLCIPHER_CRYPTO_CC=1",
"-DSQLITE_ENABLE_FTS3",
"-DSQLITE_OMIT_DEPRECATED",
"-DSQLITE_ENABLE_FTS5",
"-DSQLITE_DEFAULT_MEMSTATUS=0",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.telegram.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@ -3,6 +3,7 @@ import Foundation
struct ChatListInclusionIndex {
let topMessageIndex: MessageIndex?
let inclusion: PeerChatListInclusion
var tags: [UInt16]?
func includedIndex(peerId: PeerId) -> ChatListIndex? {
switch inclusion {
@ -32,6 +33,17 @@ struct ChatListInclusionIndex {
}
}
private struct ChatListIndexFlags: OptionSet {
var rawValue: Int8
init(rawValue: Int8) {
self.rawValue = rawValue
}
static let hasIndex = ChatListIndexFlags(rawValue: 1 << 0)
static let hasTags = ChatListIndexFlags(rawValue: 1 << 1)
}
final class ChatListIndexTable: Table {
static func tableSpec(_ id: Int32) -> ValueBoxTable {
return ValueBoxTable(id: id, keyType: .int64)
@ -66,7 +78,7 @@ final class ChatListIndexTable: Table {
if self.updatedPreviousCachedIndices[peerId] == nil {
self.updatedPreviousCachedIndices[peerId] = current
}
let updated = ChatListInclusionIndex(topMessageIndex: index, inclusion: current.inclusion)
let updated = ChatListInclusionIndex(topMessageIndex: index, inclusion: current.inclusion, tags: current.tags)
self.cachedIndices[peerId] = updated
return updated
}
@ -76,7 +88,7 @@ final class ChatListIndexTable: Table {
if self.updatedPreviousCachedIndices[peerId] == nil {
self.updatedPreviousCachedIndices[peerId] = current
}
let updated = ChatListInclusionIndex(topMessageIndex: current.topMessageIndex, inclusion: inclusion)
let updated = ChatListInclusionIndex(topMessageIndex: current.topMessageIndex, inclusion: inclusion, tags: current.tags)
self.cachedIndices[peerId] = updated
return updated
}
@ -88,9 +100,11 @@ final class ChatListIndexTable: Table {
if let value = self.valueBox.get(self.table, key: self.key(peerId)) {
let topMessageIndex: MessageIndex?
var hasIndex: Int8 = 0
value.read(&hasIndex, offset: 0, length: 1)
if hasIndex != 0 {
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
@ -131,11 +145,24 @@ final class ChatListIndexTable: Table {
preconditionFailure()
}
let inclusionIndex = ChatListInclusionIndex(topMessageIndex: topMessageIndex, inclusion: inclusion)
var tags: [UInt16]?
if flags.contains(.hasTags) {
var count: UInt16 = 0
value.read(&count, offset: 0, length: 2)
var resultTags: [UInt16] = []
for _ in 0 ..< Int(count) {
var tag: UInt16 = 0
value.read(&tag, offset: 0, length: 2)
resultTags.append(tag)
}
tags = resultTags
}
let inclusionIndex = ChatListInclusionIndex(topMessageIndex: topMessageIndex, inclusion: inclusion, tags: tags)
self.cachedIndices[peerId] = inclusionIndex
return inclusionIndex
} else {
return ChatListInclusionIndex(topMessageIndex: nil, inclusion: .notSpecified)
return ChatListInclusionIndex(topMessageIndex: nil, inclusion: .notSpecified, tags: nil)
}
}
}
@ -162,18 +189,26 @@ final class ChatListIndexTable: Table {
let writeBuffer = WriteBuffer()
var flags: ChatListIndexFlags = []
if index.topMessageIndex != nil {
flags.insert(.hasIndex)
}
if index.tags != nil {
flags.insert(.hasTags)
}
var flagsValue = flags.rawValue
writeBuffer.write(&flagsValue, offset: 0, length: 1)
if let topMessageIndex = index.topMessageIndex {
var hasIndex: Int8 = 1
writeBuffer.write(&hasIndex, offset: 0, length: 1)
var idNamespace: Int32 = topMessageIndex.id.namespace
var idId: Int32 = topMessageIndex.id.id
var idTimestamp: Int32 = topMessageIndex.timestamp
writeBuffer.write(&idNamespace, offset: 0, length: 4)
writeBuffer.write(&idId, offset: 0, length: 4)
writeBuffer.write(&idTimestamp, offset: 0, length: 4)
} else {
var hasIndex: Int8 = 0
writeBuffer.write(&hasIndex, offset: 0, length: 1)
}
switch index.inclusion {
@ -205,6 +240,16 @@ final class ChatListIndexTable: Table {
}
}
if let tags = index.tags {
var count = UInt16(tags.count)
writeBuffer.write(&count, offset: 0, length: 2)
for tag in tags {
var tagValue: UInt16 = tag
writeBuffer.write(&tagValue, offset: 0, length: 2)
}
}
withExtendedLifetime(writeBuffer, {
self.valueBox.set(self.table, key: self.key(peerId), value: writeBuffer.readBufferNoCopy())
})

View File

@ -106,7 +106,13 @@ public final class Database {
///
/// - parameter SQL: A batch of zero or more semicolon-separated SQL statements.
public func execute(_ SQL: String) -> Bool {
return sqlite3_exec(self.handle, SQL, nil, nil, nil) == SQLITE_OK
let res = sqlite3_exec(self.handle, SQL, nil, nil, nil)
if res == SQLITE_OK {
return true
} else {
print("SQL error \(res) on SQL")
return false
}
}
}

View File

@ -2,7 +2,7 @@ import Foundation
public enum PeerIndexNameRepresentation: Equatable {
case title(title: String, addressName: String?)
case personName(first: String, last: String, addressName: String?)
case personName(first: String, last: String, addressName: String?, phoneNumber: String?)
public static func ==(lhs: PeerIndexNameRepresentation, rhs: PeerIndexNameRepresentation) -> Bool {
switch lhs {
@ -12,14 +12,41 @@ public enum PeerIndexNameRepresentation: Equatable {
} else {
return false
}
case let .personName(lhsFirst, lhsLast, lhsAddressName):
if case let .personName(rhsFirst, rhsLast, rhsAddressName) = rhs, lhsFirst == rhsFirst, lhsLast == rhsLast, lhsAddressName == rhsAddressName {
case let .personName(lhsFirst, lhsLast, lhsAddressName, lhsPhoneNumber):
if case let .personName(rhsFirst, rhsLast, rhsAddressName, rhsPhoneNumber) = rhs, lhsFirst == rhsFirst, lhsLast == rhsLast, lhsAddressName == rhsAddressName, lhsPhoneNumber == rhsPhoneNumber {
return true
} else {
return false
}
}
}
public var isEmpty: Bool {
switch self {
case let .title(title, addressName):
if !title.isEmpty {
return false
}
if let addressName = addressName, !addressName.isEmpty {
return false
}
return true
case let .personName(first, last, addressName, phoneNumber):
if !first.isEmpty {
return false
}
if !last.isEmpty {
return false
}
if let addressName = addressName, !addressName.isEmpty {
return false
}
if let phoneNumber = phoneNumber, !phoneNumber.isEmpty {
return false
}
return true
}
}
}
public enum PeerNameIndex {
@ -32,7 +59,7 @@ extension PeerIndexNameRepresentation {
switch self {
case let .title(title, _):
return title
case let .personName(first, last, _):
case let .personName(first, last, _, _):
switch index {
case .firstNameFirst:
return first + last
@ -68,12 +95,15 @@ extension PeerIndexNameRepresentation {
tokens.append(contentsOf: stringIndexTokens(addressName, transliteration: .none))
}
return tokens
case let .personName(first, last, addressName):
case let .personName(first, last, addressName, phoneNumber):
var tokens: [ValueBoxKey] = stringIndexTokens(first, transliteration: .combined)
tokens.append(contentsOf: stringIndexTokens(last, transliteration: .combined))
if let addressName = addressName {
tokens.append(contentsOf: stringIndexTokens(addressName, transliteration: .none))
}
if let phoneNumber = phoneNumber {
tokens.append(contentsOf: stringIndexTokens(phoneNumber, transliteration: .none))
}
return tokens
}
}

View File

@ -213,7 +213,15 @@ final class PeerNameIndexTable: Table {
updatedTokens = updatedName.indexTokens
} else {
if let peer = self.peerTable.get(peerId) {
if let associatedPeerId = peer.associatedPeerId {
if let associatedPeer = self.peerTable.get(associatedPeerId) {
updatedTokens = associatedPeer.indexName.indexTokens
} else {
updatedTokens = []
}
} else {
updatedTokens = peer.indexName.indexTokens
}
} else {
//assertionFailure()
updatedTokens = []

View File

@ -1356,8 +1356,23 @@ public final class Postbox {
if let updatedPeer = update(currentPeer, peer) {
self.peerTable.set(updatedPeer)
self.currentUpdatedPeers[updatedPeer.id] = updatedPeer
var previousIndexNameWasEmpty = true
if let currentPeer = currentPeer {
if !currentPeer.indexName.isEmpty {
previousIndexNameWasEmpty = false
}
}
let indexNameIsEmpty = updatedPeer.indexName.isEmpty
if !previousIndexNameWasEmpty || !indexNameIsEmpty {
if currentPeer?.indexName != updatedPeer.indexName {
self.peerNameIndexTable.markPeerNameUpdated(peerId: peer.id, name: updatedPeer.indexName)
for reverseAssociatedPeerId in self.reverseAssociatedPeerTable.get(peerId: peer.id) {
self.peerNameIndexTable.markPeerNameUpdated(peerId: reverseAssociatedPeerId, name: updatedPeer.indexName)
}
}
}
}
}
@ -1800,30 +1815,41 @@ public final class Postbox {
} |> switchToLatest
}
public func searchPeers(query: String) -> Signal<[Peer], NoError> {
return self.modify { modifier -> Signal<[Peer], NoError> in
public func searchPeers(query: String) -> Signal<[RenderedPeer], NoError> {
return self.modify { modifier -> Signal<[RenderedPeer], NoError> in
var peerIds = Set<PeerId>()
var chatPeers: [Peer] = []
var chatPeers: [RenderedPeer] = []
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) {
chatPeers.append(peer)
var peers = SimpleDictionary<PeerId, Peer>()
peers[peer.id] = peer
if let associatedPeerId = peer.associatedPeerId {
if let associatedPeer = self.peerTable.get(associatedPeerId) {
peers[associatedPeer.id] = associatedPeer
}
}
chatPeers.append(RenderedPeer(peerId: peer.id, peers: peers))
peerIds.insert(peerId)
}
}
var contactPeers: [Peer] = []
var contactPeers: [RenderedPeer] = []
for peerId in contactPeerIds {
if !peerIds.contains(peerId) {
if let peer = self.peerTable.get(peerId) {
contactPeers.append(peer)
var peers = SimpleDictionary<PeerId, Peer>()
peers[peer.id] = peer
contactPeers.append(RenderedPeer(peerId: peer.id, peers: peers))
}
}
}
contactPeers.sort(by: { $0.indexName.indexName(.lastNameFirst) < $1.indexName.indexName(.lastNameFirst) })
contactPeers.sort(by: { lhs, rhs in
lhs.peers[lhs.peerId]!.indexName.indexName(.lastNameFirst) < rhs.peers[rhs.peerId]!.indexName.indexName(.lastNameFirst)
})
return .single(chatPeers + contactPeers)
} |> switchToLatest
}

View File

@ -149,7 +149,7 @@ final class SqliteValueBox: ValueBox {
//database = Database(path)!
}
sqlite3_busy_timeout(database.handle, 10000000)
sqlite3_busy_timeout(database.handle, 1000 * 10000)
var resultCode: Bool
@ -158,9 +158,9 @@ final class SqliteValueBox: ValueBox {
assert(resultCode)
resultCode = database.execute("PRAGMA synchronous=NORMAL")
assert(resultCode)
//database.execute("PRAGMA temp_store=MEMORY")
resultCode = database.execute("PRAGMA wal_autocheckpoint=500")
resultCode = database.execute("PRAGMA temp_store=MEMORY")
assert(resultCode)
//resultCode = database.execute("PRAGMA wal_autocheckpoint=500")
//database.execute("PRAGMA journal_size_limit=1536")
/*var statement: OpaquePointer? = nil