diff --git a/src/db/fix.rs b/src/db/fix.rs index 329e90a..f3985de 100644 --- a/src/db/fix.rs +++ b/src/db/fix.rs @@ -4,6 +4,7 @@ use std::{ }; use crate::db::Transaction; +use std::fmt::{Debug, Formatter}; /// Memory Fixpoint for a value in the DB /// @@ -40,4 +41,18 @@ impl<'env, T, V> Deref for LMDBorrow // valid pointer so this is safe. unsafe { self.ptr.as_ref() } } +} + +impl<'env, T, V: Debug> Debug for LMDBorrow { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.deref()) + } +} + +impl<'env, T, V: serde::Serialize> serde::Serialize for LMDBorrow { + fn serialize(&self, serializer: S) -> Result + where S: serde::Serializer + { + self.deref().serialize(serializer) + } } \ No newline at end of file diff --git a/src/db/mod.rs b/src/db/mod.rs index 5e69c79..456bcec 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -14,7 +14,7 @@ pub use lmdb::{ RwTransaction, }; -use rkyv::{Fallible, Serialize, ser::serializers::AllocSerializer, AlignedVec}; +use rkyv::{Fallible, Serialize, ser::serializers::AllocSerializer, AlignedVec, Archived}; mod raw; use raw::RawDB; @@ -60,14 +60,17 @@ pub use user::{ }; use lmdb::Error; +use rkyv::Deserialize; use rkyv::ser::serializers::AlignedSerializer; use std::sync::Arc; use std::path::Path; use crate::db::user::User; -use crate::db::resources::Resource; use std::collections::HashMap; -use crate::state::State; +use crate::state::{State, OwnedEntry}; use std::iter::FromIterator; +use std::ops::Deref; +use crate::oid::{ArchivedObjectIdentifier, ObjectIdentifier}; +use crate::state::value::SerializeValue; #[derive(Debug)] pub enum DBError { @@ -169,21 +172,62 @@ impl Databases { } } -#[derive(Debug, serde::Serialize, serde::Deserialize)] +#[derive(Debug, serde::Serialize)] pub struct Dump { users: HashMap, passwds: HashMap, - resources: HashMap, states: HashMap, } impl Dump { pub fn new(dbs: &Databases) -> Result { let users = HashMap::from_iter(dbs.userdb.get_all()?.into_iter()); - let passwds = HashMap::new(); - let resources = HashMap::new(); - let states = HashMap::new(); + 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 = input.deref(); + let hash: u64 = input.hash; + let inner: Vec = input.inner.iter().map(|entry| { - Ok(Self { users, passwds, resources, states }) + 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 = 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 = output.deref(); + let hash: u64 = output.hash; + let inner: Vec = output.inner.iter().map(|entry| { + + 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 = 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 }) } } \ No newline at end of file diff --git a/src/db/pass.rs b/src/db/pass.rs index 6b25427..b410d33 100644 --- a/src/db/pass.rs +++ b/src/db/pass.rs @@ -55,4 +55,19 @@ impl PassDB { txn.commit()?; Ok(()) } + + pub fn get_all(&self) -> Result> { + let txn = self.env.begin_ro_txn()?; + let mut cursor = self.db.open_ro_cursor(&txn)?; + let iter = cursor.iter_start(); + let mut out = Vec::new(); + for pass in iter { + let (uid, pass) = pass?; + let uid = unsafe { std::str::from_utf8_unchecked(uid).to_string() }; + let pass = unsafe { pass.as_str().to_string() }; + out.push((uid, pass)); + } + + Ok(out) + } } \ No newline at end of file diff --git a/src/db/resources.rs b/src/db/resources.rs index 0fdc5de..ae9d13d 100644 --- a/src/db/resources.rs +++ b/src/db/resources.rs @@ -1,7 +1,6 @@ use rkyv::{Archive, Serialize, Deserialize}; use super::{ - AllocAdapter, DB, }; use crate::db::AlignedAdapter; @@ -23,16 +22,16 @@ pub struct Resource { #[derive(Clone)] pub struct ResourceDB { env: Arc, - db: DB>, + //db: DB>, id_index: DB>, } impl ResourceDB { pub unsafe fn new(env: Arc, db: RawDB, id_index: RawDB) -> Self { - let db = DB::new_unchecked(db); + //let db = DB::new_unchecked(db); let id_index = DB::new_unchecked(id_index); - Self { env, db, id_index } + Self { env, /*db,*/ id_index } } pub unsafe fn open(env: Arc) -> Result { @@ -55,4 +54,19 @@ impl ResourceDB { })?; Ok(id) } + + pub fn get_all(&self) -> Result> { + let txn = self.env.begin_ro_txn()?; + let mut cursor = self.id_index.open_ro_cursor(&txn)?; + let iter = cursor.iter_start(); + let mut out = Vec::new(); + + for id in iter { + let (name, id) = id?; + let name = unsafe { std::str::from_utf8_unchecked(name).to_string() }; + out.push((name, *id)); + } + + Ok(out) + } } \ No newline at end of file diff --git a/src/db/state.rs b/src/db/state.rs index 35574e3..ee67b8e 100644 --- a/src/db/state.rs +++ b/src/db/state.rs @@ -3,7 +3,7 @@ use std::{ path::Path, }; -use rkyv::Archived; +use rkyv::{Archived}; use super::{ DB, diff --git a/src/oid.rs b/src/oid.rs index 720fdc2..a5e3809 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -485,6 +485,23 @@ mod serde_support { } } } + impl ser::Serialize for ArchivedObjectIdentifier { + fn serialize( + &self, + serializer: S, + ) -> Result + where + S: ser::Serializer, + { + if serializer.is_human_readable() { + let encoded: String = convert_to_string(self.deref()) + .expect("Failed to convert valid OID to String"); + serializer.serialize_str(&encoded) + } else { + serializer.serialize_bytes(self.deref()) + } + } + } } #[cfg(test)] diff --git a/src/state/mod.rs b/src/state/mod.rs index 6a16b53..a4e163f 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -22,7 +22,7 @@ use rkyv::{ pub mod value; use value::{SerializeValue, RegisteredImpl}; -use crate::state::value::{TypeOid, DynVal, DynOwnedVal}; +use crate::state::value::{TypeOid, DynVal, DynOwnedVal, }; use crate::oid::ObjectIdentifier; use serde::ser::SerializeMap; use std::ops::Deref; @@ -41,7 +41,7 @@ use serde::de::Error as _; /// 2. it is serializable and storable in the database /// 3. it is sendable and forwarded to all Actors and Notifys pub struct State { - hash: u64, + pub hash: u64, pub inner: Vec, } @@ -79,7 +79,6 @@ impl fmt::Debug for State { } } - pub struct StateBuilder { hasher: DefaultHasher, inner: Vec diff --git a/src/state/value.rs b/src/state/value.rs index 18874ff..05f0640 100644 --- a/src/state/value.rs +++ b/src/state/value.rs @@ -8,9 +8,7 @@ use std::{ str::FromStr, }; -use rkyv::{Archive, Archived, Serialize, Deserialize, out_field, Fallible, DeserializeUnsized, - ArchivePointee, ArchiveUnsized, ArchivedMetadata, SerializeUnsized, - }; +use rkyv::{Archive, Archived, Serialize, Deserialize, out_field, Fallible, DeserializeUnsized, ArchivePointee, ArchiveUnsized, ArchivedMetadata, SerializeUnsized, }; use rkyv_dyn::{DynSerializer, DynError, DynDeserializer}; use rkyv_typename::TypeName; use ptr_meta::{DynMetadata, Pointee}; @@ -263,7 +261,7 @@ impl ArchiveUnsized for dyn SerializeValue { #[derive(Debug)] pub struct ArchivedValueMetadata { - type_oid: Archived, + pub type_oid: Archived, } impl ArchivedValueMetadata {