Skip to content

Commit 960309e

Browse files
committed
Implement connection limit.
1 parent 6df0272 commit 960309e

File tree

2 files changed

+37
-39
lines changed

2 files changed

+37
-39
lines changed

SQLite/Core/ConnectionPool.swift

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public final class ConnectionPool {
3939
private var unavailableReadConnections = [DirectConnection]()
4040
private let lockQueue : dispatch_queue_t
4141
private var writeConnection : DirectConnection!
42+
private let connectionSemaphore = dispatch_semaphore_create(5)
4243

4344
public var foreignKeys : Bool {
4445
get {
@@ -91,6 +92,7 @@ public final class ConnectionPool {
9192
self.pool.unavailableReadConnections.removeAtIndex(index)
9293
}
9394
self.pool.availableReadConnections.append(self.connection)
95+
dispatch_semaphore_signal(self.pool.connectionSemaphore)
9496
}
9597
}
9698

@@ -151,44 +153,41 @@ public final class ConnectionPool {
151153

152154
var borrowed : BorrowedConnection!
153155

154-
repeat {
156+
dispatch_semaphore_wait(connectionSemaphore, DISPATCH_TIME_FOREVER)
157+
dispatch_sync(lockQueue) {
155158

156-
dispatch_sync(lockQueue) {
157-
158-
// Ensure database is open
159-
self.writable
159+
// Ensure database is open
160+
self.writable
161+
162+
let connection : DirectConnection
163+
164+
if let availableConnection = self.availableReadConnections.popLast() {
165+
connection = availableConnection
166+
}
167+
else {
160168

161-
let connection : DirectConnection
169+
let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX
162170

163-
if let availableConnection = self.availableReadConnections.popLast() {
164-
connection = availableConnection
165-
}
166-
else {
167-
168-
let flags = SQLITE_OPEN_READONLY | SQLITE_OPEN_WAL | SQLITE_OPEN_NOMUTEX
169-
170-
connection = try! DirectConnection(self.location, flags: flags, dispatcher: ImmediateDispatcher(), vfsName: vfsName)
171-
connection.busyTimeout = 2
171+
connection = try! DirectConnection(self.location, flags: flags, dispatcher: ImmediateDispatcher(), vfsName: vfsName)
172+
connection.busyTimeout = 2
172173

173-
for (type, setupProcessor) in self.internalSetup {
174-
if type == .WriteAheadLogging {
175-
continue
176-
}
177-
try! setupProcessor(connection)
178-
}
179-
180-
for setupProcessor in self.setup {
181-
try! setupProcessor(connection)
174+
for (type, setupProcessor) in self.internalSetup {
175+
if type == .WriteAheadLogging {
176+
continue
182177
}
183-
178+
try! setupProcessor(connection)
184179
}
185180

186-
self.unavailableReadConnections.append(connection)
181+
for setupProcessor in self.setup {
182+
try! setupProcessor(connection)
183+
}
187184

188-
borrowed = BorrowedConnection(pool: self, connection: connection)
189185
}
190186

191-
} while borrowed == nil
187+
self.unavailableReadConnections.append(connection)
188+
189+
borrowed = BorrowedConnection(pool: self, connection: connection)
190+
}
192191

193192
return borrowed
194193
}

SQLiteTests/ConnectionPoolTests.swift

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,33 +22,32 @@ class ConnectionPoolTests : SQLiteTestCase {
2222

2323
func testConcurrentAccess2() {
2424

25+
let threadCount = 20
2526
let conn = pool.writable
2627
try! conn.execute("DROP TABLE IF EXISTS test; CREATE TABLE test(id INTEGER PRIMARY KEY, name TEXT);")
2728
try! conn.execute("DELETE FROM test")
28-
try! conn.execute("INSERT INTO test(id,name) VALUES(0, 'test0')")
29-
try! conn.execute("INSERT INTO test(id,name) VALUES(1, 'test1')")
30-
try! conn.execute("INSERT INTO test(id,name) VALUES(2, 'test2')")
31-
try! conn.execute("INSERT INTO test(id,name) VALUES(3, 'test3')")
32-
try! conn.execute("INSERT INTO test(id,name) VALUES(4, 'test4')")
29+
for threadNumber in 0..<threadCount {
30+
try! conn.execute("INSERT INTO test(id,name) VALUES(\(threadNumber), 'test\(threadNumber)')")
31+
}
3332

3433
var quit = false
3534
let queue = dispatch_queue_create("Readers", DISPATCH_QUEUE_CONCURRENT)
36-
for x in 0..<5 {
35+
for threadNumber in 0..<threadCount {
3736
var reads = 0
3837

39-
let ex = expectationWithDescription("thread" + String(x))
38+
let ex = expectationWithDescription("thread" + String(threadNumber))
4039

4140
dispatch_async(queue) {
4241

43-
print("started", x)
42+
print("started", threadNumber)
4443

4544
let conn = self.pool.readable
4645

4746
let stmt = try! conn.prepare("SELECT name FROM test WHERE id = ?")
48-
var curr = stmt.scalar(x) as! String
47+
var curr = stmt.scalar(threadNumber) as! String
4948
while !quit {
5049

51-
let now = stmt.scalar(x) as! String
50+
let now = stmt.scalar(threadNumber) as! String
5251
if now != curr {
5352
//print(now)
5453
curr = now
@@ -90,7 +89,7 @@ class ConnectionPoolTests : SQLiteTestCase {
9089
let q = dispatch_queue_create("Readers/Writers", DISPATCH_QUEUE_CONCURRENT);
9190
var finished = false
9291

93-
for _ in 0..<5 {
92+
for _ in 0..<20 {
9493

9594
dispatch_async(q) {
9695

0 commit comments

Comments
 (0)