Skip to content

Commit 65aabf5

Browse files
committed
Sketches of a connection pool
1 parent 2f282af commit 65aabf5

5 files changed

Lines changed: 133 additions & 5 deletions

File tree

Makefile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,21 @@ RUSTFLAGS += -L. --cfg debug -Z debug-info
44
.PHONY: all
55
all: postgres.dummy
66

7-
postgres.dummy: src/lib.rs src/message.rs src/types.rs src/error.rs
7+
postgres.dummy: src/lib.rs src/message.rs src/types.rs src/error.rs src/pool/mod.rs
88
$(RUSTC) $(RUSTFLAGS) --lib src/lib.rs --out-dir .
99
touch $@
1010

1111
.PHONY: check
12-
check: check-postgres
12+
check: check-postgres check-pool
1313

1414
check-postgres: postgres.dummy src/test.rs
1515
$(RUSTC) $(RUSTFLAGS) --test src/test.rs -o $@
1616
./$@
1717

18+
check-pool: postgres.dummy src/pool/test.rs
19+
$(RUSTC) $(RUSTFLAGS) --test src/pool/test.rs -o $@
20+
./$@
21+
1822
.PHONY: clean
1923
clean:
2024
git clean -dfx

src/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
macro_rules! make_errors(
22
($($code:pat => $error:ident),+) => (
33
// TODO: Get rid of this module when mozilla/rust#4375 is fixed
4-
mod hack {
4+
pub mod hack {
55
#[deriving(ToStr, Eq)]
66
pub enum PostgresSqlState {
77
$($error,)+

src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@ use message::{RowDescriptionEntry, WriteMessage, ReadMessage};
5757

5858
use types::{PostgresType, ToSql, FromSql};
5959

60-
mod error;
60+
pub mod error;
61+
pub mod pool;
6162
mod message;
62-
mod types;
63+
pub mod types;
6364

6465
pub trait PostgresNoticeHandler {
6566
fn handle(&mut self, notice: PostgresDbError);

src/pool/mod.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
extern mod extra;
2+
3+
use extra::arc::MutexArc;
4+
use std::cell::Cell;
5+
6+
use super::{PostgresConnection, PostgresConnectError};
7+
8+
pub struct PostgresConnectionPoolConfig {
9+
initial_size: uint,
10+
min_size: uint,
11+
max_size: uint
12+
}
13+
14+
impl PostgresConnectionPoolConfig {
15+
fn validate(&self) {
16+
assert!(self.initial_size >= self.min_size);
17+
assert!(self.initial_size <= self.max_size);
18+
}
19+
}
20+
21+
pub static DEFAULT_CONFIG: PostgresConnectionPoolConfig =
22+
PostgresConnectionPoolConfig {
23+
initial_size: 3,
24+
min_size: 3,
25+
max_size: 15
26+
};
27+
28+
struct InnerConnectionPool {
29+
url: ~str,
30+
config: PostgresConnectionPoolConfig,
31+
pool: ~[PostgresConnection],
32+
size: uint,
33+
}
34+
35+
impl InnerConnectionPool {
36+
fn new_connection(&mut self) -> Option<PostgresConnectError> {
37+
match PostgresConnection::try_connect(self.url) {
38+
Ok(conn) => {
39+
self.pool.push(conn);
40+
self.size += 1;
41+
None
42+
}
43+
Err(err) => Some(err)
44+
}
45+
}
46+
}
47+
48+
// Should be a newtype, but blocked by mozilla/rust#9155
49+
pub struct PostgresConnectionPool {
50+
pool: MutexArc<InnerConnectionPool>
51+
}
52+
53+
impl PostgresConnectionPool {
54+
pub fn new(url: &str, config: PostgresConnectionPoolConfig)
55+
-> Result<PostgresConnectionPool, PostgresConnectError> {
56+
config.validate();
57+
58+
let mut pool = InnerConnectionPool {
59+
url: url.to_owned(),
60+
config: config,
61+
pool: ~[],
62+
size: 0,
63+
};
64+
65+
while pool.size < pool.config.initial_size {
66+
match pool.new_connection() {
67+
None => (),
68+
Some(err) => return Err(err)
69+
}
70+
}
71+
72+
Ok(PostgresConnectionPool {
73+
pool: MutexArc::new(pool)
74+
})
75+
}
76+
77+
pub fn try_with_connection<T>(&mut self,
78+
blk: &fn(&PostgresConnection) -> T)
79+
-> Result<T, PostgresConnectError> {
80+
let conn = unsafe {
81+
do self.pool.unsafe_access_cond |pool, cond| {
82+
while pool.pool.is_empty() {
83+
cond.wait();
84+
}
85+
86+
pool.pool.pop()
87+
}
88+
};
89+
90+
let ret = blk(&conn);
91+
92+
let conn = Cell::new(conn);
93+
unsafe {
94+
do self.pool.unsafe_access |pool| {
95+
pool.pool.push(conn.take());
96+
}
97+
}
98+
99+
Ok(ret)
100+
}
101+
102+
pub fn with_connection<T>(&mut self, blk: &fn(&PostgresConnection) -> T)
103+
-> T {
104+
match self.try_with_connection(blk) {
105+
Ok(ret) => ret,
106+
Err(err) => fail!("Error getting connection: %s", err.to_str())
107+
}
108+
}
109+
}

src/pool/test.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
extern mod postgres;
2+
3+
use postgres::pool;
4+
use postgres::pool::{PostgresConnectionPool};
5+
6+
#[test]
7+
fn test_pool() {
8+
let mut pool = PostgresConnectionPool::new("postgres://postgres@localhost",
9+
pool::DEFAULT_CONFIG).unwrap();
10+
11+
do pool.with_connection |_conn| {
12+
13+
}
14+
}

0 commit comments

Comments
 (0)