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
use std::ffi::CString;
use std::path::Path;
use std::ptr::{self, NonNull};
use std::sync::Arc;
use crate::database::FdbDatabase;
use crate::error::{check, FdbError, FdbResult, DATABASE_OPEN};
/// Returns [`FdbDatabase`] handle to the FDB cluster identified by
/// the provided cluster file.
///
/// If no cluster file is passed, FDB automatically [determines a
/// cluster file] with which to connect to a cluster.
///
/// A single client can use this function multiple times to connect to
/// different clusters simultaneously, with each invocation requiring
/// its own cluster file.
///
/// # Note
///
/// The caller *must* ensure that [`FdbDatabase`] stays alive during
/// the lifetime of any transactions or futures that [`FdbDatabase`]
/// creates.
///
/// [determines a cluster file]: https://apple.github.io/foundationdb/administration.html#specifying-a-cluster-file
pub fn open_database<P>(cluster_file_path: P) -> FdbResult<FdbDatabase>
where
P: AsRef<Path>,
{
let path = CString::new(
cluster_file_path
.as_ref()
.to_str()
.ok_or_else(|| FdbError::new(DATABASE_OPEN))?,
)
.map_err(|_| FdbError::new(DATABASE_OPEN))?;
// `path_ptr` is valid till we do `drop(path)`.
let path_ptr = path.as_ptr();
let mut v = ptr::null_mut();
let err = unsafe { fdb_sys::fdb_create_database(path_ptr, &mut v) };
drop(path);
// At this stage, we either have an error or a valid v.
check(err)?;
Ok(FdbDatabase::new(Some(Arc::new(NonNull::new(v).expect(
"fdb_create_database returned null, but did not return an error",
)))))
}