|
1 | 1 | extern mod extra; |
2 | 2 |
|
3 | 3 | use extra::arc::MutexArc; |
4 | | -use std::cell::Cell; |
5 | 4 |
|
6 | | -use super::{PostgresConnection, PostgresConnectError}; |
| 5 | +use super::{PostgresConnection, |
| 6 | + NormalPostgresStatement, |
| 7 | + PostgresDbError, |
| 8 | + PostgresConnectError, |
| 9 | + PostgresTransaction}; |
| 10 | +use super::types::ToSql; |
7 | 11 |
|
8 | 12 | pub struct PostgresConnectionPoolConfig { |
9 | 13 | initial_size: uint, |
@@ -75,37 +79,69 @@ impl PostgresConnectionPool { |
75 | 79 | }) |
76 | 80 | } |
77 | 81 |
|
78 | | - pub fn try_with_connection<T>(&mut self, |
79 | | - blk: &fn(&PostgresConnection) -> T) |
80 | | - -> Result<T, PostgresConnectError> { |
81 | | - // Can't use access_cond here since PostgresConnection uses Cell |
| 82 | + pub fn try_get_connection(&self) -> Result<PooledPostgresConnection, |
| 83 | + PostgresConnectError> { |
82 | 84 | let conn = unsafe { |
83 | | - do self.pool.unsafe_access_cond |pool, cond| { |
| 85 | + do self.pool.unsafe_access_cond |pool, cvar| { |
84 | 86 | while pool.pool.is_empty() { |
85 | | - cond.wait(); |
| 87 | + cvar.wait(); |
86 | 88 | } |
87 | 89 |
|
88 | 90 | pool.pool.pop() |
89 | 91 | } |
90 | 92 | }; |
91 | 93 |
|
92 | | - let ret = blk(&conn); |
| 94 | + Ok(PooledPostgresConnection { |
| 95 | + pool: self.clone(), |
| 96 | + conn: Some(conn) |
| 97 | + }) |
| 98 | + } |
93 | 99 |
|
94 | | - let conn = Cell::new(conn); |
| 100 | + pub fn get_connection(&self) -> PooledPostgresConnection { |
| 101 | + match self.try_get_connection() { |
| 102 | + Ok(conn) => conn, |
| 103 | + Err(err) => fail!("Unable to get connection: %s", err.to_str()) |
| 104 | + } |
| 105 | + } |
| 106 | +} |
| 107 | + |
| 108 | +// Should be a newtype |
| 109 | +pub struct PooledPostgresConnection { |
| 110 | + priv pool: PostgresConnectionPool, |
| 111 | + // Todo remove the Option wrapper when drop takes self by value |
| 112 | + priv conn: Option<PostgresConnection> |
| 113 | +} |
| 114 | + |
| 115 | +impl Drop for PooledPostgresConnection { |
| 116 | + fn drop(&mut self) { |
95 | 117 | unsafe { |
96 | | - do self.pool.unsafe_access |pool| { |
97 | | - pool.pool.push(conn.take()); |
| 118 | + do self.pool.pool.unsafe_access |pool| { |
| 119 | + pool.pool.push(self.conn.take_unwrap()); |
98 | 120 | } |
99 | 121 | } |
| 122 | + } |
| 123 | +} |
100 | 124 |
|
101 | | - Ok(ret) |
| 125 | +impl PooledPostgresConnection { |
| 126 | + pub fn try_prepare<'a>(&'a self, query: &str) |
| 127 | + -> Result<NormalPostgresStatement<'a>, PostgresDbError> { |
| 128 | + self.conn.get_ref().try_prepare(query) |
102 | 129 | } |
103 | 130 |
|
104 | | - pub fn with_connection<T>(&mut self, blk: &fn(&PostgresConnection) -> T) |
105 | | - -> T { |
106 | | - match self.try_with_connection(blk) { |
107 | | - Ok(ret) => ret, |
108 | | - Err(err) => fail!("Error getting connection: %s", err.to_str()) |
109 | | - } |
| 131 | + pub fn prepare<'a>(&'a self, query: &str) -> NormalPostgresStatement<'a> { |
| 132 | + self.conn.get_ref().prepare(query) |
| 133 | + } |
| 134 | + |
| 135 | + pub fn try_update(&self, query: &str, params: &[&ToSql]) |
| 136 | + -> Result<uint, PostgresDbError> { |
| 137 | + self.conn.get_ref().try_update(query, params) |
| 138 | + } |
| 139 | + |
| 140 | + pub fn update(&self, query: &str, params: &[&ToSql]) -> uint { |
| 141 | + self.conn.get_ref().update(query, params) |
| 142 | + } |
| 143 | + |
| 144 | + pub fn in_transaction<T>(&self, blk: &fn(&PostgresTransaction) -> T) -> T { |
| 145 | + self.conn.get_ref().in_transaction(blk) |
110 | 146 | } |
111 | 147 | } |
0 commit comments