forked from rust-postgres/rust-postgres
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpool.rs
More file actions
112 lines (99 loc) · 3.19 KB
/
Copy pathpool.rs
File metadata and controls
112 lines (99 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//! A simple connection pool
#![deprecated="Use https://github.com/sfackler/r2d2-postgres instead"]
#![allow(deprecated)]
use std::sync::{Arc, Mutex};
use {PostgresConnectParams, IntoConnectParams, PostgresConnection, SslMode};
use error::PostgresConnectError;
struct InnerConnectionPool {
params: PostgresConnectParams,
ssl: SslMode,
pool: Vec<PostgresConnection>,
}
impl InnerConnectionPool {
fn add_connection(&mut self) -> Result<(), PostgresConnectError> {
PostgresConnection::connect(self.params.clone(), &self.ssl)
.map(|c| self.pool.push(c))
}
}
/// A simple fixed-size Postgres connection pool.
///
/// It can be shared across tasks.
///
/// ## Example
///
/// ```rust,no_run
/// # #![allow(deprecated)]
/// # use postgres::NoSsl;
/// # use postgres::pool::PostgresConnectionPool;
/// let pool = PostgresConnectionPool::new("postgres://postgres@localhost",
/// NoSsl, 5).unwrap();
/// for _ in range(0u, 10) {
/// let pool = pool.clone();
/// spawn(proc() {
/// let conn = pool.get_connection();
/// conn.execute("UPDATE foo SET bar = 1", []).unwrap();
/// });
/// }
/// ```
#[deriving(Clone)]
pub struct PostgresConnectionPool {
pool: Arc<Mutex<InnerConnectionPool>>
}
impl PostgresConnectionPool {
/// Creates a new pool with the specified number of connections.
///
/// Returns an error if the specified number of connections cannot be
/// created.
pub fn new<T: IntoConnectParams>(params: T, ssl: SslMode, pool_size: uint)
-> Result<PostgresConnectionPool, PostgresConnectError> {
let mut pool = InnerConnectionPool {
params: try!(params.into_connect_params()),
ssl: ssl,
pool: vec![],
};
for _ in range(0, pool_size) {
try!(pool.add_connection());
}
Ok(PostgresConnectionPool {
pool: Arc::new(Mutex::new(pool))
})
}
/// Retrieves a connection from the pool.
///
/// If all connections are in use, blocks until one becomes available.
pub fn get_connection(&self) -> PooledPostgresConnection {
let mut pool = self.pool.lock();
loop {
match pool.pool.pop() {
Some(conn) => {
return PooledPostgresConnection {
pool: self.clone(),
conn: Some(conn),
};
}
None => pool.cond.wait()
}
}
}
}
/// A Postgres connection pulled from a connection pool.
///
/// It will be returned to the pool when it falls out of scope, even due to
/// task failure.
pub struct PooledPostgresConnection {
pool: PostgresConnectionPool,
// TODO remove the Option wrapper when drop takes self by value
conn: Option<PostgresConnection>
}
impl Drop for PooledPostgresConnection {
fn drop(&mut self) {
let mut pool = self.pool.pool.lock();
pool.pool.push(self.conn.take().unwrap());
pool.cond.signal();
}
}
impl Deref<PostgresConnection> for PooledPostgresConnection {
fn deref<'a>(&'a self) -> &'a PostgresConnection {
self.conn.as_ref().unwrap()
}
}