forked from rust-postgres/rust-postgres
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmod.rs
More file actions
126 lines (106 loc) · 3.41 KB
/
Copy pathmod.rs
File metadata and controls
126 lines (106 loc) · 3.41 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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
extern mod extra;
use extra::arc::MutexArc;
use super::{PostgresConnection,
NormalPostgresStatement,
PostgresDbError,
PostgresConnectError,
PostgresTransaction};
use super::types::ToSql;
struct InnerConnectionPool {
url: ~str,
pool: ~[PostgresConnection],
}
impl InnerConnectionPool {
fn new_connection(&mut self) -> Option<PostgresConnectError> {
match PostgresConnection::try_connect(self.url) {
Ok(conn) => {
self.pool.push(conn);
None
}
Err(err) => Some(err)
}
}
}
// Should be a newtype, but blocked by mozilla/rust#9155
#[deriving(Clone)]
pub struct PostgresConnectionPool {
priv pool: MutexArc<InnerConnectionPool>
}
impl PostgresConnectionPool {
pub fn try_new(url: &str, pool_size: uint)
-> Result<PostgresConnectionPool, PostgresConnectError> {
let mut pool = InnerConnectionPool {
url: url.to_owned(),
pool: ~[],
};
while pool.pool.len() < pool_size {
match pool.new_connection() {
None => (),
Some(err) => return Err(err)
}
}
Ok(PostgresConnectionPool {
pool: MutexArc::new(pool)
})
}
pub fn new(url: &str, pool_size: uint) -> PostgresConnectionPool {
match PostgresConnectionPool::try_new(url, pool_size) {
Ok(pool) => pool,
Err(err) => fail!("Unable to initialize pool: %s", err.to_str())
}
}
pub fn try_get_connection(&self) -> Result<PooledPostgresConnection,
PostgresConnectError> {
let conn = unsafe {
do self.pool.unsafe_access_cond |pool, cvar| {
while pool.pool.is_empty() {
cvar.wait();
}
pool.pool.pop()
}
};
Ok(PooledPostgresConnection {
pool: self.clone(),
conn: Some(conn)
})
}
pub fn get_connection(&self) -> PooledPostgresConnection {
match self.try_get_connection() {
Ok(conn) => conn,
Err(err) => fail!("Unable to get connection: %s", err.to_str())
}
}
}
pub struct PooledPostgresConnection {
priv pool: PostgresConnectionPool,
// TODO remove the Option wrapper when drop takes self by value
priv conn: Option<PostgresConnection>
}
impl Drop for PooledPostgresConnection {
fn drop(&mut self) {
unsafe {
do self.pool.pool.unsafe_access |pool| {
pool.pool.push(self.conn.take_unwrap());
}
}
}
}
impl PooledPostgresConnection {
pub fn try_prepare<'a>(&'a self, query: &str)
-> Result<NormalPostgresStatement<'a>, PostgresDbError> {
self.conn.get_ref().try_prepare(query)
}
pub fn prepare<'a>(&'a self, query: &str) -> NormalPostgresStatement<'a> {
self.conn.get_ref().prepare(query)
}
pub fn try_update(&self, query: &str, params: &[&ToSql])
-> Result<uint, PostgresDbError> {
self.conn.get_ref().try_update(query, params)
}
pub fn update(&self, query: &str, params: &[&ToSql]) -> uint {
self.conn.get_ref().update(query, params)
}
pub fn in_transaction<T>(&self, blk: &fn(&PostgresTransaction) -> T) -> T {
self.conn.get_ref().in_transaction(blk)
}
}