Skip to content

Commit

Permalink
Allow separate connections to share the same in-memory database
Browse files Browse the repository at this point in the history
  • Loading branch information
dpgao committed Jan 6, 2019
1 parent 55355ec commit 3c83b1d
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 17 deletions.
12 changes: 2 additions & 10 deletions Sources/SQLite/Database/SQLiteConnection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public final class SQLiteConnection: BasicWorker, DatabaseConnection, DatabaseQu

/// Reference to parent `SQLiteDatabase` that created this connection.
/// This reference will ensure the DB stays alive since this connection uses
/// it's dispatch queue.
/// it's thread pool.
private let database: SQLiteDatabase

/// Internal SQLite database handle.
Expand All @@ -45,15 +45,7 @@ public final class SQLiteConnection: BasicWorker, DatabaseConnection, DatabaseQu
/// Create a new SQLite conncetion.
internal init(database: SQLiteDatabase, on worker: Worker) throws {
self.database = database
// Make database connection
var handle: OpaquePointer?
let options = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX
guard sqlite3_open_v2(database.storage.path, &handle, options, nil) == SQLITE_OK,
let c = handle,
sqlite3_busy_handler(c, { _, _ in 1 }, nil) == SQLITE_OK else {
throw SQLiteError(problem: .error, reason: "Could not open database.", source: .capture())
}
self.handle = c
self.handle = try database.openConnection()
self.eventLoop = worker.eventLoop
}

Expand Down
37 changes: 37 additions & 0 deletions Sources/SQLite/Database/SQLiteDatabase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ public final class SQLiteDatabase: Database, LogSupporting {
/// Thread pool for performing blocking IO work. See `BlockingIOThreadPool`.
internal let blockingIO: BlockingIOThreadPool

/// If the database uses in-memory storage, this property will be set to
/// keep the database alive when there is no `SQLiteConnection` to it.
private var handle: OpaquePointer?

/// Create a new SQLite database.
///
/// let sqliteDB = SQLiteDatabase(storage: .memory)
Expand All @@ -31,6 +35,28 @@ public final class SQLiteDatabase: Database, LogSupporting {
public init(storage: SQLiteStorage = .memory, threadPool: BlockingIOThreadPool? = nil) throws {
self.storage = storage
self.blockingIO = threadPool ?? BlockingIOThreadPool(numberOfThreads: 2)
if case .memory = storage {
self.handle = try openConnection()
}
}

// Make database connection
internal func openConnection() throws -> OpaquePointer {
let path: String
switch storage {
case .memory:
path = "file:\(ObjectIdentifier(self))?mode=memory&cache=shared"
case .file(let file):
path = file
}
var handle: OpaquePointer?
let options = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX
guard sqlite3_open_v2(path, &handle, options, nil) == SQLITE_OK,
let c = handle,
sqlite3_busy_handler(c, { _, _ in 1 }, nil) == SQLITE_OK else {
throw SQLiteError(problem: .error, reason: "Could not open database.", source: .capture())
}
return c
}

/// See `Database`.
Expand All @@ -47,4 +73,15 @@ public final class SQLiteDatabase: Database, LogSupporting {
public static func enableLogging(_ logger: DatabaseLogger, on conn: SQLiteConnection) {
conn.logger = logger
}

deinit {
self.blockingIO.shutdownGracefully { [handle] error in
if let error = error {
print("[SQLite] [ERROR] Could not shutdown BlockingIOThreadPool: \(error)")
}
if let handle = handle, sqlite3_close(handle) != SQLITE_OK {
print("[SQLite] [ERROR] Could not close database.")
}
}
}
}
7 changes: 0 additions & 7 deletions Sources/SQLite/Database/SQLiteStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,4 @@ public enum SQLiteStorage {

/// File-based storage, persisted between application launches.
case file(path: String)

internal var path: String {
switch self {
case .memory: return ":memory:"
case .file(let path): return path
}
}
}

0 comments on commit 3c83b1d

Please sign in to comment.