diff --git a/src/sql.rs b/src/sql.rs index 718fa5cee..cf8e9d7c3 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -196,12 +196,12 @@ impl Sql { /// Creates a new connection pool. fn new_pool(dbfile: &Path, passphrase: String) -> Result { - let mut connections = Vec::new(); - for _ in 0..3 { - let connection = new_connection(dbfile, &passphrase)?; - connections.push(connection); - } + let mut connections = [None, None, None]; // array from iter is not stable yet + for c in &mut connections { + let connection = new_connection(dbfile, &passphrase)?; + *c = Some(connection); + } let pool = Pool::new(connections); Ok(pool) } diff --git a/src/sql/pool.rs b/src/sql/pool.rs index 477b7d57f..51577da5d 100644 --- a/src/sql/pool.rs +++ b/src/sql/pool.rs @@ -7,10 +7,13 @@ use std::sync::{Arc, Weak}; use parking_lot::{Condvar, Mutex}; use rusqlite::Connection; +/// Total size of the connection pool. +pub const POOL_SIZE: usize = 3; + /// Inner connection pool. struct InnerPool { /// Available connections. - connections: Mutex>, + connections: Mutex<[Option; POOL_SIZE]>, /// Conditional variable to notify about added connections. /// @@ -24,7 +27,19 @@ impl InnerPool { /// The connection could be new or returned back. fn put(&self, connection: Connection) { let mut connections = self.connections.lock(); - connections.push(connection); + let mut found_one = false; + for c in &mut *connections { + if c.is_none() { + *c = Some(connection); + found_one = true; + break; + } + } + assert!( + found_one, + "attempted to put more connections than available" + ); + drop(connections); self.cond.notify_one(); } @@ -79,7 +94,7 @@ impl fmt::Debug for Pool { impl Pool { /// Creates a new connection pool. - pub fn new(connections: Vec) -> Self { + pub fn new(connections: [Option; POOL_SIZE]) -> Self { let inner = Arc::new(InnerPool { connections: Mutex::new(connections), cond: Condvar::new(), @@ -92,7 +107,7 @@ impl Pool { let mut connections = self.inner.connections.lock(); loop { - if let Some(conn) = connections.pop() { + if let Some(conn) = get_next(&mut *connections) { return PooledConnection { pool: Arc::downgrade(&self.inner), conn: Some(conn), @@ -103,3 +118,16 @@ impl Pool { } } } + +/// Returns the first available connection. +/// +/// `None` if no connection is availble. +fn get_next(connections: &mut [Option; POOL_SIZE]) -> Option { + for c in &mut *connections { + if c.is_some() { + return c.take(); + } + } + + None +}