Skip to content

Commit 68357e5

Browse files
committed
Basic functionality
This doesn't acually work since generic destructors are still broken :( rust-lang/rust#15905
1 parent 75d0744 commit 68357e5

File tree

3 files changed

+147
-6
lines changed

3 files changed

+147
-6
lines changed

Cargo.toml

+9
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,12 @@
22
name = "r2d2"
33
version = "0.0.0"
44
authors = ["Steven Fackler <[email protected]>"]
5+
6+
[[lib]]
7+
name = "r2d2"
8+
path = "src/lib.rs"
9+
test = false
10+
11+
[[test]]
12+
name = "test"
13+
path = "tests/test.rs"

src/lib.rs

+71-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use std::default::Default;
44
use std::sync::Mutex;
5+
use std::fmt;
56

67
pub trait PoolManager<C, E> {
78
fn connect(&self) -> Result<C, E>;
@@ -19,6 +20,37 @@ impl Default for Config {
1920
}
2021
}
2122

23+
impl Config {
24+
pub fn validate(&self) -> Result<(), ConfigError> {
25+
Ok(())
26+
}
27+
}
28+
29+
#[deriving(PartialEq, Eq)]
30+
pub enum ConfigError {
31+
}
32+
33+
impl fmt::Show for ConfigError {
34+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35+
Ok(())
36+
}
37+
}
38+
39+
#[deriving(PartialEq, Eq)]
40+
pub enum NewPoolError<E> {
41+
InvalidConfig(ConfigError),
42+
ConnectionError(E),
43+
}
44+
45+
impl<E: fmt::Show> fmt::Show for NewPoolError<E> {
46+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
47+
match *self {
48+
InvalidConfig(ref error) => write!(f, "Invalid Config: {}", error),
49+
ConnectionError(ref error) => write!(f, "Unable to create connections: {}", error),
50+
}
51+
}
52+
}
53+
2254
struct PoolInternals<C> {
2355
conns: Vec<C>,
2456
}
@@ -30,23 +62,56 @@ pub struct Pool<C, M> {
3062
}
3163

3264
impl<C: Send, E, M: PoolManager<C, E>+Default> Pool<C, M> {
33-
pub fn new(config: Config) -> Pool<C, M> {
65+
pub fn new(config: Config) -> Result<Pool<C, M>, NewPoolError<E>> {
3466
Pool::with_manager(config, Default::default())
3567
}
3668
}
3769

3870
impl<C: Send, E, M: PoolManager<C, E>> Pool<C, M> {
39-
pub fn with_manager(config: Config, manager: M) -> Pool<C, M> {
40-
Pool {
71+
pub fn with_manager(config: Config, manager: M) -> Result<Pool<C, M>, NewPoolError<E>> {
72+
match config.validate() {
73+
Ok(()) => {}
74+
Err(err) => return Err(InvalidConfig(err))
75+
}
76+
77+
let mut internals = PoolInternals {
78+
conns: vec![],
79+
};
80+
81+
for _ in range(0, config.initial_size) {
82+
match manager.connect() {
83+
Ok(conn) => internals.conns.push(conn),
84+
Err(err) => return Err(ConnectionError(err)),
85+
}
86+
}
87+
88+
Ok(Pool {
4189
config: config,
4290
manager: manager,
43-
internals: Mutex::new(PoolInternals {
44-
conns: vec![]
45-
}),
91+
internals: Mutex::new(internals),
92+
})
93+
}
94+
95+
pub fn get<'a>(&'a self) -> Result<PooledConnection<'a, C, M>, E> {
96+
let mut internals = self.internals.lock();
97+
98+
loop {
99+
match internals.conns.pop() {
100+
Some(conn) => {
101+
return Ok(PooledConnection {
102+
pool: self,
103+
conn: Some(conn)
104+
})
105+
}
106+
None => internals.cond.wait(),
107+
}
46108
}
47109
}
48110

49111
fn put_back(&self, conn: C) {
112+
let mut internals = self.internals.lock();
113+
internals.conns.push(conn);
114+
internals.cond.signal();
50115
}
51116
}
52117

tests/test.rs

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
extern crate r2d2;
2+
3+
use std::cell::Cell;
4+
use std::default::Default;
5+
6+
#[deriving(Show, PartialEq)]
7+
struct FakeConnection;
8+
9+
#[deriving(Default)]
10+
struct OkManager;
11+
12+
impl r2d2::PoolManager<FakeConnection, ()> for OkManager {
13+
fn connect(&self) -> Result<FakeConnection, ()> {
14+
Ok(FakeConnection)
15+
}
16+
}
17+
18+
struct NthConnectFailManager {
19+
n: Cell<uint>
20+
}
21+
22+
impl r2d2::PoolManager<FakeConnection, ()> for NthConnectFailManager {
23+
fn connect(&self) -> Result<FakeConnection, ()> {
24+
let n = self.n.get();
25+
if n > 0 {
26+
self.n.set(n - 1);
27+
Ok(FakeConnection)
28+
} else {
29+
Err(())
30+
}
31+
}
32+
}
33+
34+
#[test]
35+
fn test_initial_size_ok() {
36+
let config = r2d2::Config {
37+
initial_size: 5,
38+
..Default::default()
39+
};
40+
let manager = NthConnectFailManager { n: Cell::new(5) };
41+
assert!(r2d2::Pool::with_manager(config, manager).is_ok());
42+
}
43+
44+
#[test]
45+
fn test_initial_size_err() {
46+
let config = r2d2::Config {
47+
initial_size: 5,
48+
..Default::default()
49+
};
50+
let manager = NthConnectFailManager { n: Cell::new(4) };
51+
assert_eq!(r2d2::Pool::with_manager(config, manager).err().unwrap(),
52+
r2d2::ConnectionError(()));
53+
}
54+
55+
#[test]
56+
fn test_acquire_release() {
57+
let config = r2d2::Config {
58+
initial_size: 2,
59+
..Default::default()
60+
};
61+
let pool = r2d2::Pool::with_manager(config, OkManager).unwrap();
62+
63+
let conn1 = pool.get().unwrap();
64+
let _conn2 = pool.get().unwrap();
65+
drop(conn1);
66+
let _conn3 = pool.get().unwrap();
67+
}

0 commit comments

Comments
 (0)