fabaccess-bffh/bffhd/db.rs

234 lines
5.9 KiB
Rust
Raw Normal View History

use std::{
marker::PhantomData,
};
2021-10-07 16:44:01 +02:00
pub use lmdb::{
Environment,
DatabaseFlags,
WriteFlags,
EnvironmentFlags,
Transaction,
RoTransaction,
RwTransaction,
};
2021-10-20 20:56:47 +02:00
use rkyv::{Fallible, Serialize, ser::serializers::AllocSerializer, AlignedVec, Archived};
2021-10-07 16:44:01 +02:00
mod raw;
use raw::RawDB;
mod typed;
// re-exports
pub use typed::{
DB,
2021-10-20 18:37:50 +02:00
TypedCursor,
2021-10-07 16:44:01 +02:00
Adapter,
OutputBuffer,
OutputWriter,
};
mod hash;
pub use hash::{
HashDB,
Entry,
};
mod fix;
pub use fix::LMDBorrow;
pub mod state;
pub use state::{
StateDB,
};
mod resources;
pub use resources::{
ResourceDB,
};
2021-10-20 12:58:05 +02:00
2021-10-20 18:37:50 +02:00
mod pass;
pub use pass::{
PassDB,
};
mod user;
pub use user::{
UserDB,
};
2021-10-19 11:16:24 +02:00
use lmdb::Error;
2021-10-20 20:56:47 +02:00
use rkyv::Deserialize;
2021-10-19 11:16:24 +02:00
use rkyv::ser::serializers::AlignedSerializer;
2021-10-20 18:37:50 +02:00
use std::sync::Arc;
use std::path::Path;
use crate::db::user::User;
use std::collections::HashMap;
2021-10-27 21:32:50 +02:00
use crate::state::{OwnedEntry, State};
2021-10-20 18:37:50 +02:00
use std::iter::FromIterator;
2021-10-20 20:56:47 +02:00
use std::ops::Deref;
use crate::oid::{ArchivedObjectIdentifier, ObjectIdentifier};
use crate::state::value::SerializeValue;
2021-10-18 11:27:42 +02:00
#[derive(Debug)]
pub enum DBError {
LMDB(lmdb::Error),
RKYV(<AllocSerializer<1024> as Fallible>::Error),
}
2021-10-20 18:37:50 +02:00
pub(crate) type Result<T> = std::result::Result<T, DBError>;
impl From<lmdb::Error> for DBError {
fn from(e: lmdb::Error) -> Self {
Self::LMDB(e)
}
}
type Ser = AllocSerializer<1024>;
#[derive(Clone)]
struct AllocAdapter<V> {
phantom: PhantomData<V>,
}
impl<V> Fallible for AllocAdapter<V> {
type Error = DBError;
}
impl<V: Serialize<Ser>> Adapter for AllocAdapter<V> {
type Serializer = Ser;
type Value = V;
fn new_serializer() -> Self::Serializer {
Self::Serializer::default()
}
fn from_ser_err(e: <Self::Serializer as Fallible>::Error) -> Self::Error {
DBError::RKYV(e)
}
fn from_db_err(e: lmdb::Error) -> Self::Error {
e.into()
}
2021-10-19 11:16:24 +02:00
}
#[derive(Copy, Clone)]
pub struct AlignedAdapter<V> {
phantom: PhantomData<V>,
}
impl<V> Fallible for AlignedAdapter<V> {
type Error = lmdb::Error;
}
impl<V: Serialize<AlignedSerializer<AlignedVec>>> Adapter for AlignedAdapter<V> {
type Serializer = AlignedSerializer<AlignedVec>;
type Value = V;
fn new_serializer() -> Self::Serializer {
Self::Serializer::default()
}
fn from_ser_err(_: <Self::Serializer as Fallible>::Error) -> <Self as Fallible>::Error {
unreachable!()
}
fn from_db_err(e: Error) -> <Self as Fallible>::Error {
e
}
2021-10-20 18:37:50 +02:00
}
pub struct Databases {
pub userdb: UserDB,
pub passdb: PassDB,
pub resourcedb: ResourceDB,
pub statedb: StateDB,
}
impl Databases {
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
let env = Arc::new(Environment::new()
.open(&Path::join(path.as_ref(), "internal"))?
);
let userdb = unsafe { UserDB::open(env.clone())? };
let passdb = unsafe { PassDB::open(env.clone())? };
let resourcedb = unsafe { ResourceDB::open(env)? };
let statedb = StateDB::open(&Path::join(path.as_ref(), "state"))?;
Ok(Self { userdb, passdb, resourcedb, statedb })
}
pub fn create<P: AsRef<Path>>(path: P) -> Result<Self> {
let env = Arc::new(Environment::new()
.set_max_dbs(16)
.open(path.as_ref())?
);
let userdb = unsafe { UserDB::create(env.clone())? };
let passdb = unsafe { PassDB::create(env.clone())? };
let resourcedb = unsafe { ResourceDB::create(env)? };
let statedb = StateDB::create(&Path::join(path.as_ref(), "state"))?;
Ok(Self { userdb, passdb, resourcedb, statedb })
}
}
2021-10-20 20:56:47 +02:00
#[derive(Debug, serde::Serialize)]
2021-10-20 18:37:50 +02:00
pub struct Dump {
users: HashMap<String, User>,
passwds: HashMap<String, String>,
states: HashMap<String, (State, State)>,
}
impl Dump {
pub fn new(dbs: &Databases) -> Result<Self> {
let users = HashMap::from_iter(dbs.userdb.get_all()?.into_iter());
2021-10-20 20:56:47 +02:00
let passwds = HashMap::from_iter(dbs.passdb.get_all()?.into_iter());
let mut states = HashMap::new();
for (name, id) in dbs.resourcedb.get_all()?.into_iter() {
let input = dbs.statedb.get_input(id)?.map(|input| {
let input: &Archived<State> = input.deref();
let hash: u64 = input.hash;
2021-10-27 21:32:50 +02:00
let inner = input.inner.iter()
.map(|entry| {
2021-10-20 20:56:47 +02:00
let oid: &ArchivedObjectIdentifier = &entry.oid;
let bytes: &[u8] = oid.deref();
let mut vec = Vec::with_capacity(bytes.len());
vec.copy_from_slice(bytes);
let oid = ObjectIdentifier::new_unchecked(vec.into_boxed_slice());
let val: Box<dyn SerializeValue> = entry.val
.deserialize(&mut rkyv::Infallible).unwrap();
OwnedEntry { oid, val }
}).collect();
State { hash, inner }
}).unwrap_or(State::build().finish());
let output = dbs.statedb.get_output(id)?.map(|output| {
let output: &Archived<State> = output.deref();
let hash: u64 = output.hash;
2021-10-27 21:32:50 +02:00
let inner = output.inner.iter().map(|entry| {
2021-10-20 20:56:47 +02:00
let oid: &ArchivedObjectIdentifier = &entry.oid;
let bytes: &[u8] = oid.deref();
let mut vec = Vec::with_capacity(bytes.len());
vec.copy_from_slice(bytes);
let oid = ObjectIdentifier::new_unchecked(vec.into_boxed_slice());
let val: Box<dyn SerializeValue> = entry.val
.deserialize(&mut rkyv::Infallible).unwrap();
OwnedEntry { oid, val }
}).collect();
State { hash, inner }
}).unwrap_or(State::build().finish());
let old = states.insert(name, (input, output));
assert!(old.is_none());
}
Ok(Self { users, passwds, states })
2021-10-20 18:37:50 +02:00
}
2021-10-18 11:27:42 +02:00
}