no message

This commit is contained in:
Peter 2017-04-27 22:47:14 +03:00
parent b19a770951
commit a73bcc3180
6 changed files with 190 additions and 45 deletions

View File

@ -252,6 +252,15 @@ public final class Encoder {
self.buffer.write(key.utf8Start, offset: 0, length: Int(length))
}
public func encodeKey(_ key: String) {
let data = key.data(using: .utf8)!
data.withUnsafeBytes { (keyBytes: UnsafePointer<UInt8>) -> Void in
var length: Int8 = Int8(data.count)
self.buffer.write(&length, offset: 0, length: 1)
self.buffer.write(keyBytes, offset: 0, length: Int(length))
}
}
public func encodeNil(forKey key: StaticString) {
self.encodeKey(key)
var type: Int8 = ValueType.Nil.rawValue
@ -266,6 +275,14 @@ public final class Encoder {
self.buffer.write(&v, offset: 0, length: 4)
}
public func encodeInt32(_ value: Int32, forKey key: String) {
self.encodeKey(key)
var type: Int8 = ValueType.Int32.rawValue
self.buffer.write(&type, offset: 0, length: 1)
var v = value
self.buffer.write(&v, offset: 0, length: 4)
}
public func encodeInt64(_ value: Int64, forKey key: StaticString) {
self.encodeKey(key)
var type: Int8 = ValueType.Int64.rawValue
@ -325,6 +342,23 @@ public final class Encoder {
self.buffer.write(innerEncoder.buffer.memory, offset: 0, length: Int(length))
}
public func encodeObjectWithEncoder<T>(_ value: T, encoder: (Encoder) -> Void, forKey key: String) {
self.encodeKey(key)
var type: Int8 = ValueType.Object.rawValue
self.buffer.write(&type, offset: 0, length: 1)
let string = "\(type(of: value))"
var typeHash: Int32 = murMurHashString32(string)
self.buffer.write(&typeHash, offset: 0, length: 4)
let innerEncoder = Encoder()
encoder(innerEncoder)
var length: Int32 = Int32(innerEncoder.buffer.offset)
self.buffer.write(&length, offset: 0, length: 4)
self.buffer.write(innerEncoder.buffer.memory, offset: 0, length: Int(length))
}
public func encodeInt32Array(_ value: [Int32], forKey key: StaticString) {
self.encodeKey(key)
var type: Int8 = ValueType.Int32Array.rawValue
@ -591,6 +625,47 @@ public final class Decoder {
return false
}
private class func positionOnStringKey(_ rawBytes: UnsafeRawPointer, offset: inout Int, maxOffset: Int, length: Int, key: String, valueType: ValueType) -> Bool
{
let bytes = rawBytes.assumingMemoryBound(to: Int8.self)
let startOffset = offset
let keyData = key.data(using: .utf8)!
return keyData.withUnsafeBytes { (keyBytes: UnsafePointer<UInt8>) -> Bool in
let keyLength: Int = keyData.count
while (offset < maxOffset) {
let readKeyLength = bytes[offset]
assert(readKeyLength >= 0)
offset += 1
offset += Int(readKeyLength)
let readValueType = bytes[offset]
offset += 1
if keyLength == Int(readKeyLength) && memcmp(bytes + (offset - Int(readKeyLength) - 1), keyBytes, keyLength) == 0 {
if readValueType == valueType.rawValue {
return true
} else if readValueType == ValueType.Nil.rawValue {
return false
} else {
skipValue(bytes, offset: &offset, length: length, valueType: ValueType(rawValue: readValueType)!)
}
} else {
skipValue(bytes, offset: &offset, length: length, valueType: ValueType(rawValue: readValueType)!)
}
}
if (startOffset != 0) {
offset = 0
return positionOnStringKey(bytes, offset: &offset, maxOffset: startOffset, length: length, key: key, valueType: valueType)
}
return false
}
}
private class func positionOnKey(_ bytes: UnsafePointer<Int8>, offset: inout Int, maxOffset: Int, length: Int, key: Int16, valueType: ValueType) -> Bool
{
@ -634,6 +709,17 @@ public final class Decoder {
}
}
public func decodeInt32ForKey(_ key: String) -> Int32 {
if Decoder.positionOnStringKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int32) {
var value: Int32 = 0
memcpy(&value, self.buffer.memory + self.offset, 4)
self.offset += 4
return value
} else {
return 0
}
}
public func decodeInt32ForKey(_ key: StaticString) -> Int32? {
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int32) {
var value: Int32 = 0
@ -753,6 +839,24 @@ public final class Decoder {
}
}
public func decodeObjectForKeyThrowing(_ key: StaticString, decoder: (Decoder) throws -> Any) throws -> Any? {
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Object) {
var typeHash: Int32 = 0
memcpy(&typeHash, self.buffer.memory + self.offset, 4)
self.offset += 4
var length: Int32 = 0
memcpy(&length, self.buffer.memory + self.offset, 4)
let innerDecoder = Decoder(buffer: ReadBuffer(memory: self.buffer.memory + (self.offset + 4), length: Int(length), freeWhenDone: false))
self.offset += 4 + Int(length)
return try decoder(innerDecoder)
} else {
return nil
}
}
public func decodeInt32ArrayForKey(_ key: StaticString) -> [Int32] {
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int32Array) {
var length: Int32 = 0
@ -1023,7 +1127,7 @@ public final class Decoder {
}
}
public func decodeObjectDictionaryForKey<K, V: Coding where K: Hashable>(_ key: StaticString, keyDecoder: (Decoder) -> K) -> [K : V] where K: Hashable {
public func decodeObjectDictionaryForKey<K, V: Coding>(_ key: StaticString, keyDecoder: (Decoder) -> K) -> [K : V] where K: Hashable, K: Hashable {
if Decoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .ObjectDictionary) {
var length: Int32 = 0
memcpy(&length, self.buffer.memory + self.offset, 4)

View File

@ -68,8 +68,15 @@ public final class Database {
///
/// - returns: A new database connection.
public init?(_ location: Location = .InMemory, readonly: Bool = false) {
let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
let res = sqlite3_open_v2(location.description, &self.handle, flags | SQLITE_OPEN_FULLMUTEX, nil)
switch location {
case let .URI(uri):
let _ = open(uri + "-guard", O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR)
break
default:
break
}
//let flags = readonly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE
let res = sqlite3_open(location.description, &self.handle)
if res != SQLITE_OK {
preconditionFailure("sqlite3_open_v2: \(res)")
return nil

View File

@ -37,11 +37,11 @@ public final class MappedFile {
msync(self.memory, self.currentSize, MS_ASYNC)
}
public func write(at range: Range<Int>, from data: UnsafePointer<Void>) {
public func write(at range: Range<Int>, from data: UnsafeRawPointer) {
memcpy(self.memory.advanced(by: range.lowerBound), data, range.count)
}
public func read(at range: Range<Int>, to data: UnsafeMutablePointer<Void>) {
public func read(at range: Range<Int>, to data: UnsafeMutableRawPointer) {
memcpy(data, self.memory.advanced(by: range.lowerBound), range.count)
}

View File

@ -576,8 +576,9 @@ public final class MediaBox {
return fetch(resource, currentSize ..< Int.max, tag)
}) |> afterDisposed {
dataQueue.async {
if let fd = fd {
close(fd)
if let thisFd = fd {
close(thisFd)
fd = nil
}
}
}).start(next: { resultOption in
@ -750,8 +751,9 @@ public final class MediaBox {
}
}
case let .moveLocalFile(tempPath):
if let fd = fd {
close(fd)
if let thisFd = thisFd {
close(thisFd)
fd = nil
}
unlink(paths.partial)
do {

View File

@ -69,7 +69,7 @@ final class MutablePeerMergedOperationLogView {
}
for i in 0 ..< self.entries.count {
if i != 0 {
assert(self.entries[i].mergedIndex == self.entries[i - 1].mergedIndex + 1)
assert(self.entries[i].mergedIndex >= self.entries[i - 1].mergedIndex + 1)
}
}
if !self.entries.isEmpty {
@ -80,7 +80,7 @@ final class MutablePeerMergedOperationLogView {
} else {
assert(self.tailIndex != nil)
if let tailIndex = self.tailIndex {
assert(self.entries.last!.mergedIndex == tailIndex)
assert(self.entries.last!.mergedIndex <= tailIndex)
}
}
}

View File

@ -141,12 +141,19 @@ final class SqliteValueBox: ValueBox {
//database = Database(path)!
}
database.execute("PRAGMA cache_size=-2097152")
database.execute("PRAGMA synchronous=NORMAL")
database.execute("PRAGMA journal_mode=WAL")
database.execute("PRAGMA temp_store=MEMORY")
database.execute("PRAGMA wal_autocheckpoint=500")
database.execute("PRAGMA journal_size_limit=1536")
sqlite3_busy_timeout(database.handle, 10000000)
var resultCode: Bool
//database.execute("PRAGMA cache_size=-2097152")
resultCode = database.execute("PRAGMA journal_mode=WAL")
assert(resultCode)
resultCode = database.execute("PRAGMA synchronous=NORMAL")
assert(resultCode)
//database.execute("PRAGMA temp_store=MEMORY")
resultCode = database.execute("PRAGMA wal_autocheckpoint=500")
assert(resultCode)
//database.execute("PRAGMA journal_size_limit=1536")
/*var statement: OpaquePointer? = nil
sqlite3_prepare_v2(database.handle, "PRAGMA integrity_check", -1, &statement, nil)
@ -161,13 +168,14 @@ final class SqliteValueBox: ValueBox {
}
preparedStatement.destroy()*/
sqlite3_busy_timeout(database.handle, 10000000)
let result = self.getUserVersion(database)
if result != 2 {
database.execute("PRAGMA user_version=2")
database.execute("DROP TABLE IF EXISTS __meta_tables")
database.execute("CREATE TABLE __meta_tables (name INTEGER, keyType INTEGER)")
resultCode = database.execute("PRAGMA user_version=2")
assert(resultCode)
resultCode = database.execute("DROP TABLE IF EXISTS __meta_tables")
assert(resultCode)
resultCode = database.execute("CREATE TABLE __meta_tables (name INTEGER, keyType INTEGER)")
assert(resultCode)
}
for table in self.listTables(database) {
@ -202,20 +210,23 @@ final class SqliteValueBox: ValueBox {
public func begin() {
assert(self.queue.isCurrent())
self.database.execute("BEGIN IMMEDIATE")
let resultCode = self.database.execute("BEGIN IMMEDIATE")
assert(resultCode)
}
public func commit() {
assert(self.queue.isCurrent())
let startTime = CFAbsoluteTimeGetCurrent()
self.database.execute("COMMIT")
let resultCode = self.database.execute("COMMIT")
assert(resultCode)
self.commitTime += CFAbsoluteTimeGetCurrent() - startTime
}
private func getUserVersion(_ database: Database) -> Int64 {
assert(self.queue.isCurrent())
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(database.handle, "PRAGMA user_version", -1, &statement, nil)
let status = sqlite3_prepare_v2(database.handle, "PRAGMA user_version", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
let _ = preparedStatement.step()
let value = preparedStatement.int64At(0)
@ -226,7 +237,8 @@ final class SqliteValueBox: ValueBox {
private func listTables(_ database: Database) -> [ValueBoxTable] {
assert(self.queue.isCurrent())
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(database.handle, "SELECT name, keyType FROM __meta_tables", -1, &statement, nil)
let status = sqlite3_prepare_v2(database.handle, "SELECT name, keyType FROM __meta_tables", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
var tables: [ValueBoxTable] = []
while preparedStatement.step() {
@ -244,13 +256,18 @@ final class SqliteValueBox: ValueBox {
} else {
switch table.keyType {
case .binary:
self.database.execute("CREATE TABLE t\(table.id) (key BLOB, value BLOB)")
self.database.execute("CREATE INDEX t\(table.id)_key ON t\(table.id) (key)")
var resultCode: Bool
resultCode = self.database.execute("CREATE TABLE t\(table.id) (key BLOB, value BLOB)")
assert(resultCode)
resultCode = self.database.execute("CREATE INDEX t\(table.id)_key ON t\(table.id) (key)")
assert(resultCode)
case .int64:
self.database.execute("CREATE TABLE t\(table.id) (key INTEGER PRIMARY KEY, value BLOB)")
let resultCode = self.database.execute("CREATE TABLE t\(table.id) (key INTEGER PRIMARY KEY, value BLOB)")
assert(resultCode)
}
self.tables[table.id] = table
self.database.execute("INSERT INTO __meta_tables(name, keyType) VALUES (\(table.id), \(table.keyType.rawValue))")
let resultCode = self.database.execute("INSERT INTO __meta_tables(name, keyType) VALUES (\(table.id), \(table.keyType.rawValue))")
assert(resultCode)
}
}
@ -264,7 +281,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "SELECT value FROM t\(table.id) WHERE key=?", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "SELECT value FROM t\(table.id) WHERE key=?", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.getStatements[table.id] = preparedStatement
resultStatement = preparedStatement
@ -293,7 +311,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "SELECT key FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key ASC LIMIT ?", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "SELECT key FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key ASC LIMIT ?", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.rangeKeyAscStatementsLimit[table.id] = preparedStatement
resultStatement = preparedStatement
@ -325,7 +344,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "SELECT key FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key ASC", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "SELECT key FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key ASC", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.rangeKeyAscStatementsNoLimit[table.id] = preparedStatement
resultStatement = preparedStatement
@ -355,7 +375,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "SELECT key FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key DESC LIMIT ?", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "SELECT key FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key DESC LIMIT ?", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.rangeKeyDescStatementsLimit[table.id] = preparedStatement
resultStatement = preparedStatement
@ -386,7 +407,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "SELECT key FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key DESC", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "SELECT key FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key DESC", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.rangeKeyDescStatementsNoLimit[table.id] = preparedStatement
resultStatement = preparedStatement
@ -417,7 +439,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "SELECT key, value FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key ASC LIMIT ?", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "SELECT key, value FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key ASC LIMIT ?", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.rangeValueAscStatementsLimit[table.id] = preparedStatement
resultStatement = preparedStatement
@ -448,7 +471,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "SELECT key, value FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key ASC", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "SELECT key, value FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key ASC", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.rangeValueAscStatementsNoLimit[table.id] = preparedStatement
resultStatement = preparedStatement
@ -479,7 +503,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "SELECT key, value FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key DESC LIMIT ?", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "SELECT key, value FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key DESC LIMIT ?", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.rangeValueDescStatementsLimit[table.id] = preparedStatement
resultStatement = preparedStatement
@ -511,7 +536,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "SELECT key, value FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key DESC", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "SELECT key, value FROM t\(table.id) WHERE key > ? AND key < ? ORDER BY key DESC", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.rangeValueDescStatementsNoLimit[table.id] = preparedStatement
resultStatement = preparedStatement
@ -540,7 +566,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "SELECT key, value FROM t\(table.id) ORDER BY key ASC", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "SELECT key, value FROM t\(table.id) ORDER BY key ASC", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.scanStatements[table.id] = preparedStatement
resultStatement = preparedStatement
@ -561,7 +588,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "SELECT rowid FROM t\(table.id) WHERE key=?", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "SELECT rowid FROM t\(table.id) WHERE key=?", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.existsStatements[table.id] = preparedStatement
resultStatement = preparedStatement
@ -589,7 +617,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "UPDATE t\(table.id) SET value=? WHERE key=?", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "UPDATE t\(table.id) SET value=? WHERE key=?", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.updateStatements[table.id] = preparedStatement
resultStatement = preparedStatement
@ -618,7 +647,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "INSERT INTO t\(table.id) (key, value) VALUES(?, ?)", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "INSERT INTO t\(table.id) (key, value) VALUES(?, ?)", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.insertStatements[table.id] = preparedStatement
resultStatement = preparedStatement
@ -651,7 +681,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "INSERT OR REPLACE INTO t\(table.id) (key, value) VALUES(?, ?)", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "INSERT OR REPLACE INTO t\(table.id) (key, value) VALUES(?, ?)", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.insertOrReplaceStatements[table.id] = preparedStatement
resultStatement = preparedStatement
@ -684,7 +715,8 @@ final class SqliteValueBox: ValueBox {
resultStatement = statement
} else {
var statement: OpaquePointer? = nil
sqlite3_prepare_v2(self.database.handle, "DELETE FROM t\(table.id) WHERE key=?", -1, &statement, nil)
let status = sqlite3_prepare_v2(self.database.handle, "DELETE FROM t\(table.id) WHERE key=?", -1, &statement, nil)
assert(status == SQLITE_OK)
let preparedStatement = SqlitePreparedStatement(statement: statement)
self.deleteStatements[table.id] = preparedStatement
resultStatement = preparedStatement