checkpoint
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
mod table_db;
|
||||
use super::*;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
@@ -10,15 +9,5 @@ mod native;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub use native::*;
|
||||
|
||||
pub static KNOWN_TABLE_NAMES: [&'static str; 7] = [
|
||||
"crypto_caches",
|
||||
"RouteSpecStore",
|
||||
"routing_table",
|
||||
"local_records",
|
||||
"local_subkeys",
|
||||
"remote_records",
|
||||
"remote_subkeys",
|
||||
];
|
||||
|
||||
pub static KNOWN_PROTECTED_STORE_KEYS: [&'static str; 4] =
|
||||
["node_id", "node_id_secret", "_test_key", "RouteSpecStore"];
|
||||
|
@@ -1,12 +1,10 @@
|
||||
mod block_store;
|
||||
mod protected_store;
|
||||
mod system;
|
||||
mod table_store;
|
||||
|
||||
pub use block_store::*;
|
||||
pub use protected_store::*;
|
||||
pub use system::*;
|
||||
pub use table_store::*;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub mod android;
|
||||
|
@@ -1,148 +0,0 @@
|
||||
use super::*;
|
||||
use crate::intf::table_db::TableDBUnlockedInner;
|
||||
pub use crate::intf::table_db::{TableDB, TableDBTransaction};
|
||||
use keyvaluedb_sqlite::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
struct TableStoreInner {
|
||||
opened: BTreeMap<String, Weak<TableDBUnlockedInner>>,
|
||||
}
|
||||
|
||||
/// Veilid Table Storage
|
||||
/// Database for storing key value pairs persistently across runs
|
||||
#[derive(Clone)]
|
||||
pub struct TableStore {
|
||||
config: VeilidConfig,
|
||||
inner: Arc<Mutex<TableStoreInner>>,
|
||||
}
|
||||
|
||||
impl TableStore {
|
||||
fn new_inner() -> TableStoreInner {
|
||||
TableStoreInner {
|
||||
opened: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
pub(crate) fn new(config: VeilidConfig) -> Self {
|
||||
Self {
|
||||
config,
|
||||
inner: Arc::new(Mutex::new(Self::new_inner())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete all known tables
|
||||
pub async fn delete_all(&self) {
|
||||
for ktn in &KNOWN_TABLE_NAMES {
|
||||
if let Err(e) = self.delete(ktn).await {
|
||||
error!("failed to delete '{}': {}", ktn, e);
|
||||
} else {
|
||||
debug!("deleted table '{}'", ktn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn init(&self) -> EyreResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn terminate(&self) {
|
||||
let inner = self.inner.lock();
|
||||
if !inner.opened.is_empty() {
|
||||
panic!(
|
||||
"all open databases should have been closed: {:?}",
|
||||
inner.opened
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn on_table_db_drop(&self, table: String) {
|
||||
let mut inner = self.inner.lock();
|
||||
if inner.opened.remove(&table).is_none() {
|
||||
unreachable!("should have removed an item");
|
||||
}
|
||||
}
|
||||
|
||||
fn get_dbpath(&self, table: &str) -> EyreResult<PathBuf> {
|
||||
if !table
|
||||
.chars()
|
||||
.all(|c| char::is_alphanumeric(c) || c == '_' || c == '-')
|
||||
{
|
||||
bail!("table name '{}' is invalid", table);
|
||||
}
|
||||
let c = self.config.get();
|
||||
let tablestoredir = c.table_store.directory.clone();
|
||||
std::fs::create_dir_all(&tablestoredir).wrap_err("failed to create tablestore path")?;
|
||||
|
||||
let dbpath: PathBuf = [tablestoredir, String::from(table)].iter().collect();
|
||||
Ok(dbpath)
|
||||
}
|
||||
|
||||
fn get_table_name(&self, table: &str) -> EyreResult<String> {
|
||||
if !table
|
||||
.chars()
|
||||
.all(|c| char::is_alphanumeric(c) || c == '_' || c == '-')
|
||||
{
|
||||
bail!("table name '{}' is invalid", table);
|
||||
}
|
||||
let c = self.config.get();
|
||||
let namespace = c.namespace.clone();
|
||||
Ok(if namespace.is_empty() {
|
||||
table.to_string()
|
||||
} else {
|
||||
format!("_ns_{}_{}", namespace, table)
|
||||
})
|
||||
}
|
||||
|
||||
/// Get or create a TableDB database table. If the column count is greater than an
|
||||
/// existing TableDB's column count, the database will be upgraded to add the missing columns
|
||||
pub async fn open(&self, name: &str, column_count: u32) -> EyreResult<TableDB> {
|
||||
let table_name = self.get_table_name(name)?;
|
||||
|
||||
let mut inner = self.inner.lock();
|
||||
if let Some(table_db_weak_inner) = inner.opened.get(&table_name) {
|
||||
match TableDB::try_new_from_weak_inner(table_db_weak_inner.clone()) {
|
||||
Some(tdb) => {
|
||||
return Ok(tdb);
|
||||
}
|
||||
None => {
|
||||
inner.opened.remove(&table_name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let dbpath = self.get_dbpath(&table_name)?;
|
||||
|
||||
// Ensure permissions are correct
|
||||
ensure_file_private_owner(&dbpath)?;
|
||||
|
||||
let cfg = DatabaseConfig::with_columns(column_count);
|
||||
let db = Database::open(&dbpath, cfg).wrap_err("failed to open tabledb")?;
|
||||
|
||||
// Ensure permissions are correct
|
||||
ensure_file_private_owner(&dbpath)?;
|
||||
|
||||
trace!(
|
||||
"opened table store '{}' at path '{:?}' with {} columns",
|
||||
name,
|
||||
dbpath,
|
||||
column_count
|
||||
);
|
||||
let table_db = TableDB::new(table_name.clone(), self.clone(), db);
|
||||
|
||||
inner.opened.insert(table_name, table_db.weak_inner());
|
||||
|
||||
Ok(table_db)
|
||||
}
|
||||
|
||||
/// Delete a TableDB table by name
|
||||
pub async fn delete(&self, name: &str) -> EyreResult<bool> {
|
||||
let table_name = self.get_table_name(name)?;
|
||||
|
||||
let inner = self.inner.lock();
|
||||
if inner.opened.contains_key(&table_name) {
|
||||
bail!("Not deleting table that is still opened");
|
||||
}
|
||||
let dbpath = self.get_dbpath(&table_name)?;
|
||||
let ret = std::fs::remove_file(dbpath).is_ok();
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
@@ -1,283 +0,0 @@
|
||||
use crate::*;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(target_arch = "wasm32")] {
|
||||
use keyvaluedb_web::*;
|
||||
use keyvaluedb::*;
|
||||
} else {
|
||||
use keyvaluedb_sqlite::*;
|
||||
use keyvaluedb::*;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TableDBUnlockedInner {
|
||||
table: String,
|
||||
table_store: TableStore,
|
||||
database: Database,
|
||||
}
|
||||
|
||||
impl fmt::Debug for TableDBUnlockedInner {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "TableDBInner(table={})", self.table)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TableDBUnlockedInner {
|
||||
fn drop(&mut self) {
|
||||
self.table_store.on_table_db_drop(self.table.clone());
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TableDB {
|
||||
unlocked_inner: Arc<TableDBUnlockedInner>,
|
||||
}
|
||||
|
||||
impl TableDB {
|
||||
pub(super) fn new(table: String, table_store: TableStore, database: Database) -> Self {
|
||||
Self {
|
||||
unlocked_inner: Arc::new(TableDBUnlockedInner {
|
||||
table,
|
||||
table_store,
|
||||
database,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn try_new_from_weak_inner(weak_inner: Weak<TableDBUnlockedInner>) -> Option<Self> {
|
||||
weak_inner.upgrade().map(|table_db_unlocked_inner| Self {
|
||||
unlocked_inner: table_db_unlocked_inner,
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn weak_inner(&self) -> Weak<TableDBUnlockedInner> {
|
||||
Arc::downgrade(&self.unlocked_inner)
|
||||
}
|
||||
|
||||
/// Get the total number of columns in the TableDB
|
||||
pub fn get_column_count(&self) -> VeilidAPIResult<u32> {
|
||||
let db = &self.unlocked_inner.database;
|
||||
db.num_columns().map_err(VeilidAPIError::from)
|
||||
}
|
||||
|
||||
/// Get the list of keys in a column of the TableDB
|
||||
pub async fn get_keys(&self, col: u32) -> VeilidAPIResult<Vec<Box<[u8]>>> {
|
||||
let db = self.unlocked_inner.database.clone();
|
||||
let mut out: Vec<Box<[u8]>> = Vec::new();
|
||||
db.iter(col, None, |kv| {
|
||||
out.push(kv.0.clone().into_boxed_slice());
|
||||
Ok(Option::<()>::None)
|
||||
})
|
||||
.await
|
||||
.map_err(VeilidAPIError::from)?;
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Start a TableDB write transaction. The transaction object must be committed or rolled back before dropping.
|
||||
pub fn transact(&self) -> TableDBTransaction {
|
||||
let dbt = self.unlocked_inner.database.transaction();
|
||||
TableDBTransaction::new(self.clone(), dbt)
|
||||
}
|
||||
|
||||
/// Store a key with a value in a column in the TableDB. Performs a single transaction immediately.
|
||||
pub async fn store(&self, col: u32, key: &[u8], value: &[u8]) -> VeilidAPIResult<()> {
|
||||
let db = self.unlocked_inner.database.clone();
|
||||
let mut dbt = db.transaction();
|
||||
dbt.put(col, key, value);
|
||||
db.write(dbt).await.map_err(VeilidAPIError::generic)
|
||||
}
|
||||
|
||||
/// Store a key in rkyv format with a value in a column in the TableDB. Performs a single transaction immediately.
|
||||
pub async fn store_rkyv<T>(&self, col: u32, key: &[u8], value: &T) -> VeilidAPIResult<()>
|
||||
where
|
||||
T: RkyvSerialize<DefaultVeilidRkyvSerializer>,
|
||||
{
|
||||
let v = to_rkyv(value)?;
|
||||
|
||||
let db = self.unlocked_inner.database.clone();
|
||||
let mut dbt = db.transaction();
|
||||
dbt.put(col, key, v.as_slice());
|
||||
db.write(dbt).await.map_err(VeilidAPIError::generic)
|
||||
}
|
||||
|
||||
/// Store a key in json format with a value in a column in the TableDB. Performs a single transaction immediately.
|
||||
pub async fn store_json<T>(&self, col: u32, key: &[u8], value: &T) -> VeilidAPIResult<()>
|
||||
where
|
||||
T: serde::Serialize,
|
||||
{
|
||||
let v = serde_json::to_vec(value).map_err(VeilidAPIError::internal)?;
|
||||
|
||||
let db = self.unlocked_inner.database.clone();
|
||||
let mut dbt = db.transaction();
|
||||
dbt.put(col, key, v.as_slice());
|
||||
db.write(dbt).await.map_err(VeilidAPIError::generic)
|
||||
}
|
||||
|
||||
/// Read a key from a column in the TableDB immediately.
|
||||
pub async fn load(&self, col: u32, key: &[u8]) -> VeilidAPIResult<Option<Vec<u8>>> {
|
||||
let db = self.unlocked_inner.database.clone();
|
||||
db.get(col, key).await.map_err(VeilidAPIError::from)
|
||||
}
|
||||
|
||||
/// Read an rkyv key from a column in the TableDB immediately
|
||||
pub async fn load_rkyv<T>(&self, col: u32, key: &[u8]) -> VeilidAPIResult<Option<T>>
|
||||
where
|
||||
T: RkyvArchive,
|
||||
<T as RkyvArchive>::Archived:
|
||||
for<'t> CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
|
||||
<T as RkyvArchive>::Archived: RkyvDeserialize<T, VeilidSharedDeserializeMap>,
|
||||
{
|
||||
let out = match self.load(col, key).await? {
|
||||
Some(v) => Some(from_rkyv(v)?),
|
||||
None => None,
|
||||
};
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Read an serde-json key from a column in the TableDB immediately
|
||||
pub async fn load_json<T>(&self, col: u32, key: &[u8]) -> VeilidAPIResult<Option<T>>
|
||||
where
|
||||
T: for<'de> serde::Deserialize<'de>,
|
||||
{
|
||||
let out = match self.load(col, key).await? {
|
||||
Some(v) => Some(serde_json::from_slice(&v).map_err(VeilidAPIError::internal)?),
|
||||
None => None,
|
||||
};
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Delete key with from a column in the TableDB
|
||||
pub async fn delete(&self, col: u32, key: &[u8]) -> VeilidAPIResult<Option<Vec<u8>>> {
|
||||
let db = self.unlocked_inner.database.clone();
|
||||
let old_value = db.delete(col, key).await.map_err(VeilidAPIError::from)?;
|
||||
Ok(old_value)
|
||||
}
|
||||
|
||||
/// Delete rkyv key with from a column in the TableDB
|
||||
pub async fn delete_rkyv<T>(&self, col: u32, key: &[u8]) -> VeilidAPIResult<Option<T>>
|
||||
where
|
||||
T: RkyvArchive,
|
||||
<T as RkyvArchive>::Archived:
|
||||
for<'t> CheckBytes<rkyv::validation::validators::DefaultValidator<'t>>,
|
||||
<T as RkyvArchive>::Archived: RkyvDeserialize<T, VeilidSharedDeserializeMap>,
|
||||
{
|
||||
let db = self.unlocked_inner.database.clone();
|
||||
let old_value = match db.delete(col, key).await.map_err(VeilidAPIError::from)? {
|
||||
Some(v) => Some(from_rkyv(v)?),
|
||||
None => None,
|
||||
};
|
||||
Ok(old_value)
|
||||
}
|
||||
|
||||
/// Delete serde-json key with from a column in the TableDB
|
||||
pub async fn delete_json<T>(&self, col: u32, key: &[u8]) -> VeilidAPIResult<Option<T>>
|
||||
where
|
||||
T: for<'de> serde::Deserialize<'de>,
|
||||
{
|
||||
let db = self.unlocked_inner.database.clone();
|
||||
let old_value = match db.delete(col, key).await.map_err(VeilidAPIError::from)? {
|
||||
Some(v) => Some(serde_json::from_slice(&v).map_err(VeilidAPIError::internal)?),
|
||||
None => None,
|
||||
};
|
||||
Ok(old_value)
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TableDBTransactionInner {
|
||||
dbt: Option<DBTransaction>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for TableDBTransactionInner {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"TableDBTransactionInner({})",
|
||||
match &self.dbt {
|
||||
Some(dbt) => format!("len={}", dbt.ops.len()),
|
||||
None => "".to_owned(),
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// A TableDB transaction
|
||||
/// Atomically commits a group of writes or deletes to the TableDB
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TableDBTransaction {
|
||||
db: TableDB,
|
||||
inner: Arc<Mutex<TableDBTransactionInner>>,
|
||||
}
|
||||
|
||||
impl TableDBTransaction {
|
||||
fn new(db: TableDB, dbt: DBTransaction) -> Self {
|
||||
Self {
|
||||
db,
|
||||
inner: Arc::new(Mutex::new(TableDBTransactionInner { dbt: Some(dbt) })),
|
||||
}
|
||||
}
|
||||
|
||||
/// Commit the transaction. Performs all actions atomically.
|
||||
pub async fn commit(self) -> VeilidAPIResult<()> {
|
||||
let dbt = {
|
||||
let mut inner = self.inner.lock();
|
||||
inner
|
||||
.dbt
|
||||
.take()
|
||||
.ok_or_else(|| VeilidAPIError::generic("transaction already completed"))?
|
||||
};
|
||||
let db = self.db.unlocked_inner.database.clone();
|
||||
db.write(dbt)
|
||||
.await
|
||||
.map_err(|e| VeilidAPIError::generic(format!("commit failed, transaction lost: {}", e)))
|
||||
}
|
||||
|
||||
/// Rollback the transaction. Does nothing to the TableDB.
|
||||
pub fn rollback(self) {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.dbt = None;
|
||||
}
|
||||
|
||||
/// Store a key with a value in a column in the TableDB
|
||||
pub fn store(&self, col: u32, key: &[u8], value: &[u8]) {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.dbt.as_mut().unwrap().put(col, key, value);
|
||||
}
|
||||
|
||||
/// Store a key in rkyv format with a value in a column in the TableDB
|
||||
pub fn store_rkyv<T>(&self, col: u32, key: &[u8], value: &T) -> VeilidAPIResult<()>
|
||||
where
|
||||
T: RkyvSerialize<DefaultVeilidRkyvSerializer>,
|
||||
{
|
||||
let v = to_rkyv(value)?;
|
||||
let mut inner = self.inner.lock();
|
||||
inner.dbt.as_mut().unwrap().put(col, key, v.as_slice());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Store a key in rkyv format with a value in a column in the TableDB
|
||||
pub fn store_json<T>(&self, col: u32, key: &[u8], value: &T) -> VeilidAPIResult<()>
|
||||
where
|
||||
T: serde::Serialize,
|
||||
{
|
||||
let v = serde_json::to_vec(value).map_err(VeilidAPIError::internal)?;
|
||||
let mut inner = self.inner.lock();
|
||||
inner.dbt.as_mut().unwrap().put(col, key, v.as_slice());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Delete key with from a column in the TableDB
|
||||
pub fn delete(&self, col: u32, key: &[u8]) {
|
||||
let mut inner = self.inner.lock();
|
||||
inner.dbt.as_mut().unwrap().delete(col, key);
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TableDBTransactionInner {
|
||||
fn drop(&mut self) {
|
||||
if self.dbt.is_some() {
|
||||
warn!("Dropped transaction without commit or rollback");
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +1,9 @@
|
||||
mod block_store;
|
||||
mod protected_store;
|
||||
mod system;
|
||||
mod table_store;
|
||||
|
||||
pub use block_store::*;
|
||||
pub use protected_store::*;
|
||||
pub use system::*;
|
||||
pub use table_store::*;
|
||||
|
||||
use super::*;
|
||||
|
@@ -1,147 +0,0 @@
|
||||
use super::*;
|
||||
use crate::intf::table_db::TableDBUnlockedInner;
|
||||
pub use crate::intf::table_db::{TableDB, TableDBTransaction};
|
||||
use keyvaluedb_web::*;
|
||||
|
||||
struct TableStoreInner {
|
||||
opened: BTreeMap<String, Weak<TableDBUnlockedInner>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TableStore {
|
||||
config: VeilidConfig,
|
||||
inner: Arc<Mutex<TableStoreInner>>,
|
||||
async_lock: Arc<AsyncMutex<()>>,
|
||||
}
|
||||
|
||||
impl TableStore {
|
||||
fn new_inner() -> TableStoreInner {
|
||||
TableStoreInner {
|
||||
opened: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
pub(crate) fn new(config: VeilidConfig) -> Self {
|
||||
Self {
|
||||
config,
|
||||
inner: Arc::new(Mutex::new(Self::new_inner())),
|
||||
async_lock: Arc::new(AsyncMutex::new(())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete all known tables
|
||||
pub async fn delete_all(&self) {
|
||||
for ktn in &KNOWN_TABLE_NAMES {
|
||||
if let Err(e) = self.delete(ktn).await {
|
||||
error!("failed to delete '{}': {}", ktn, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn init(&self) -> EyreResult<()> {
|
||||
let _async_guard = self.async_lock.lock().await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn terminate(&self) {
|
||||
let _async_guard = self.async_lock.lock().await;
|
||||
assert!(
|
||||
self.inner.lock().opened.len() == 0,
|
||||
"all open databases should have been closed"
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn on_table_db_drop(&self, table: String) {
|
||||
let mut inner = self.inner.lock();
|
||||
match inner.opened.remove(&table) {
|
||||
Some(_) => (),
|
||||
None => {
|
||||
assert!(false, "should have removed an item");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_table_name(&self, table: &str) -> EyreResult<String> {
|
||||
if !table
|
||||
.chars()
|
||||
.all(|c| char::is_alphanumeric(c) || c == '_' || c == '-')
|
||||
{
|
||||
bail!("table name '{}' is invalid", table);
|
||||
}
|
||||
let c = self.config.get();
|
||||
let namespace = c.namespace.clone();
|
||||
Ok(if namespace.len() == 0 {
|
||||
format!("{}", table)
|
||||
} else {
|
||||
format!("_ns_{}_{}", namespace, table)
|
||||
})
|
||||
}
|
||||
|
||||
/// Get or create a TableDB database table. If the column count is greater than an
|
||||
/// existing TableDB's column count, the database will be upgraded to add the missing columns
|
||||
pub async fn open(&self, name: &str, column_count: u32) -> EyreResult<TableDB> {
|
||||
let _async_guard = self.async_lock.lock().await;
|
||||
let table_name = self.get_table_name(name)?;
|
||||
|
||||
{
|
||||
let mut inner = self.inner.lock();
|
||||
if let Some(table_db_weak_inner) = inner.opened.get(&table_name) {
|
||||
match TableDB::try_new_from_weak_inner(table_db_weak_inner.clone()) {
|
||||
Some(tdb) => {
|
||||
return Ok(tdb);
|
||||
}
|
||||
None => {
|
||||
inner.opened.remove(&table_name);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
let db = Database::open(table_name.clone(), column_count, false)
|
||||
.await
|
||||
.wrap_err("failed to open tabledb")?;
|
||||
trace!(
|
||||
"opened table store '{}' with table name '{:?}' with {} columns",
|
||||
name,
|
||||
table_name,
|
||||
column_count
|
||||
);
|
||||
|
||||
let table_db = TableDB::new(table_name.clone(), self.clone(), db);
|
||||
|
||||
{
|
||||
let mut inner = self.inner.lock();
|
||||
inner.opened.insert(table_name, table_db.weak_inner());
|
||||
}
|
||||
|
||||
Ok(table_db)
|
||||
}
|
||||
|
||||
/// Delete a TableDB table by name
|
||||
pub async fn delete(&self, name: &str) -> EyreResult<bool> {
|
||||
let _async_guard = self.async_lock.lock().await;
|
||||
trace!("TableStore::delete {}", name);
|
||||
let table_name = self.get_table_name(name)?;
|
||||
|
||||
{
|
||||
let inner = self.inner.lock();
|
||||
if inner.opened.contains_key(&table_name) {
|
||||
trace!(
|
||||
"TableStore::delete {}: Not deleting, still open.",
|
||||
table_name
|
||||
);
|
||||
bail!("Not deleting table that is still opened");
|
||||
}
|
||||
}
|
||||
|
||||
if is_browser() {
|
||||
let out = match Database::delete(table_name.clone()).await {
|
||||
Ok(_) => true,
|
||||
Err(_) => false,
|
||||
};
|
||||
//.map_err(|e| format!("failed to delete tabledb at: {} ({})", table_name, e))?;
|
||||
trace!("TableStore::deleted {}", table_name);
|
||||
Ok(out)
|
||||
} else {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user