use common::encoding;
use connection::Connection;
use context::params::{CommonCreate, ConnCreate, PoolCreate};
use context::Context;
use error::{Error, ErrorKind, Result};
use odpi::opaque::{ODPIConn, ODPIPool};
use odpi::structs::ODPIEncodingInfo;
use odpi::{enums, externs, flags};
use std::convert::TryFrom;
use std::ptr::{self, Unique};
use util::ODPIStr;
pub struct Pool {
inner: Unique<ODPIPool>,
}
impl Pool {
#[doc(hidden)]
pub fn inner(&self) -> *mut ODPIPool {
self.inner.as_ptr()
}
pub fn acquire_connection(
&self,
username: Option<&str>,
password: Option<&str>,
conn_create_params: Option<ConnCreate>,
) -> Result<Connection> {
let username_s: ODPIStr = TryFrom::try_from(username)?;
let password_s: ODPIStr = TryFrom::try_from(password)?;
let conn_cp = if let Some(conn_create_params) = conn_create_params {
conn_create_params
} else {
Default::default()
};
let mut conn: *mut ODPIConn = ptr::null_mut();
try_dpi!(
externs::dpiPool_acquireConnection(
self.inner.as_ptr(),
username_s.ptr(),
username_s.len(),
password_s.ptr(),
password_s.len(),
&mut conn_cp.inner(),
&mut conn
),
Ok(conn.into()),
ErrorKind::Pool("dpiPool_acquireConnection".to_string())
)
}
pub fn close(&self, close_mode: flags::ODPIPoolCloseMode) -> Result<()> {
try_dpi!(
externs::dpiPool_close(self.inner.as_ptr(), close_mode),
Ok(()),
ErrorKind::Pool("dpiPool_close".to_string())
)
}
pub fn create(
context: &Context,
username: Option<&str>,
password: Option<&str>,
connect_string: Option<&str>,
common_create_params: Option<CommonCreate>,
pool_create_params: Option<PoolCreate>,
) -> Result<Self> {
let username_s: ODPIStr = TryFrom::try_from(username)?;
let password_s: ODPIStr = TryFrom::try_from(password)?;
let connect_string_s: ODPIStr = TryFrom::try_from(connect_string)?;
let mut inner: *mut ODPIPool = ptr::null_mut();
let comm_cp = if let Some(common_create_params) = common_create_params {
common_create_params
} else {
context.init_common_create_params()?
};
let pool_cp = if let Some(pool_create_params) = pool_create_params {
pool_create_params
} else {
context.init_pool_create_params()?
};
try_dpi!(
externs::dpiPool_create(
context.inner(),
username_s.ptr(),
username_s.len(),
password_s.ptr(),
password_s.len(),
connect_string_s.ptr(),
connect_string_s.len(),
&comm_cp.inner(),
&mut pool_cp.inner(),
&mut inner
),
Ok(TryFrom::try_from(inner)?),
ErrorKind::Pool("dpiPool_create".to_string())
)
}
pub fn get_busy_count(&self) -> Result<u32> {
let mut busy_count = 0;
try_dpi!(
externs::dpiPool_getBusyCount(self.inner.as_ptr(), &mut busy_count),
Ok(busy_count),
ErrorKind::Pool("dpiPool_getBusyCount".to_string())
)
}
pub fn get_encoding_info(&self) -> Result<encoding::Info> {
let mut enc_info: ODPIEncodingInfo = Default::default();
try_dpi!(
externs::dpiPool_getEncodingInfo(self.inner.as_ptr(), &mut enc_info),
Ok(enc_info.into()),
ErrorKind::Pool("dpiPool_getEncodingInfo".to_string())
)
}
pub fn get_get_mode(&self) -> Result<enums::ODPIPoolGetMode> {
let mut get_mode = enums::ODPIPoolGetMode::NoWait;
try_dpi!(
externs::dpiPool_getGetMode(self.inner.as_ptr(), &mut get_mode),
Ok(get_mode),
ErrorKind::Pool("dpiPool_getGetMode".to_string())
)
}
pub fn get_max_lifetime_session(&self) -> Result<u32> {
let mut max_lifetime_session = 0;
try_dpi!(
externs::dpiPool_getMaxLifetimeSession(self.inner.as_ptr(), &mut max_lifetime_session),
Ok(max_lifetime_session),
ErrorKind::Pool("dpiPool_getMaxLifetimeSession".to_string())
)
}
pub fn get_open_count(&self) -> Result<u32> {
let mut open_count = 0;
try_dpi!(
externs::dpiPool_getOpenCount(self.inner.as_ptr(), &mut open_count),
Ok(open_count),
ErrorKind::Pool("dpiPool_getOpenCount".to_string())
)
}
pub fn get_stmt_cache_size(&self) -> Result<u32> {
let mut stmt_cache_size = 0;
try_dpi!(
externs::dpiPool_getStmtCacheSize(self.inner.as_ptr(), &mut stmt_cache_size),
Ok(stmt_cache_size),
ErrorKind::Pool("dpiPool_getStmtCacheSize".to_string())
)
}
pub fn get_timeout(&self) -> Result<u32> {
let mut timeout = 0;
try_dpi!(
externs::dpiPool_getTimeout(self.inner.as_ptr(), &mut timeout),
Ok(timeout),
ErrorKind::Pool("dpiPool_getTimeout".to_string())
)
}
pub fn set_get_mode(&self, get_mode: enums::ODPIPoolGetMode) -> Result<()> {
try_dpi!(
externs::dpiPool_setGetMode(self.inner.as_ptr(), get_mode),
Ok(()),
ErrorKind::Pool("dpiPool_setGetMode".to_string())
)
}
pub fn set_max_lifetime_session(&self, max_lifetime: u32) -> Result<()> {
try_dpi!(
externs::dpiPool_setMaxLifetimeSession(self.inner.as_ptr(), max_lifetime),
Ok(()),
ErrorKind::Pool("dpiPool_setMaxLifetimeSession".to_string())
)
}
pub fn set_stmt_cache_size(&self, stmt_cache_size: u32) -> Result<()> {
try_dpi!(
externs::dpiPool_setStmtCacheSize(self.inner.as_ptr(), stmt_cache_size),
Ok(()),
ErrorKind::Pool("dpiPool_setStmtCacheSize".to_string())
)
}
pub fn set_timeout(&self, timeout: u32) -> Result<()> {
try_dpi!(
externs::dpiPool_setTimeout(self.inner.as_ptr(), timeout),
Ok(()),
ErrorKind::Pool("dpiPool_setTimeout".to_string())
)
}
}
impl TryFrom<*mut ODPIPool> for Pool {
type Error = Error;
fn try_from(inner: *mut ODPIPool) -> Result<Self> {
let pool = Unique::new(inner).ok_or_else(|| ErrorKind::Pool("try_from".to_string()))?;
Ok(Self { inner: pool })
}
}
impl Drop for Pool {
fn drop(&mut self) {
if !self.inner.as_ptr().is_null() {
unsafe {
externs::dpiPool_release(self.inner.as_ptr());
}
}
}
}