use super::*;
impl StorageManager {
#[cfg_attr(
feature = "instrument",
instrument(level = "trace", target = "stor", skip_all, fields(__VEILID_LOG_KEY = self.log_key()))
)]
pub async fn close_record(&self, record_key: RecordKey) -> VeilidAPIResult<()> {
let Ok(_guard) = self.startup_lock.enter() else {
apibail_not_initialized!();
};
let opaque_record_key = record_key.opaque();
let record_lock = self
.record_lock_table
.lock_record(
opaque_record_key.clone(),
StorageManagerRecordLockPurpose::Close,
)
.await;
let opt_cleanup = self.close_record_locked(&record_lock)?;
if let Some(cleanup) = opt_cleanup {
cleanup.await;
}
Ok(())
}
#[cfg_attr(
feature = "instrument",
instrument(level = "trace", target = "stor", skip_all, fields(__VEILID_LOG_KEY = self.log_key()))
)]
pub async fn close_all_records(&self) -> VeilidAPIResult<()> {
let Ok(_guard) = self.startup_lock.enter() else {
apibail_not_initialized!();
};
let record_locks = {
let keys = {
let inner = self.inner.lock();
inner.opened_records.keys().cloned().collect::<Vec<_>>()
};
self.record_lock_table
.lock_records(keys, StorageManagerRecordLockPurpose::Close)
.await
};
let mut all_cleanup: Option<TransactionCleanup> = None;
let mut opt_error = None;
for record_lock_guard in record_locks.record_lock_guards() {
let res = self.close_record_locked(record_lock_guard);
match res {
Ok(Some(cleanup)) => match &mut all_cleanup {
Some(existing) => existing.merge(cleanup),
None => all_cleanup = Some(cleanup),
},
Ok(None) => {}
Err(e) => {
opt_error = Some(e);
}
}
}
if let Some(cleanup) = all_cleanup {
cleanup.await;
}
if let Some(e) = opt_error {
return Err(e);
}
Ok(())
}
pub(super) fn close_record_locked(
&self,
record_lock: &StorageManagerRecordLockGuard,
) -> VeilidAPIResult<Option<TransactionCleanup>> {
let opaque_record_key = record_lock.record();
let local_record_store = self.get_local_record_store()?;
if !local_record_store.contains_record(&opaque_record_key) {
apibail_key_not_found!(opaque_record_key.clone());
}
let mut opt_cleanup = None;
{
let mut inner = self.inner.lock();
if let Some(opened_record) = inner.opened_records.remove(&opaque_record_key) {
let record_key = RecordKey::from_opaque(
opaque_record_key.clone(),
opened_record.encryption_key(),
);
inner
.outbound_watch_manager
.set_desired_watch(record_key, None);
if let Some(transaction_handle) = inner
.outbound_transaction_manager
.get_transaction_by_record(&opaque_record_key)
{
if let Some(state) = inner
.outbound_transaction_manager
.drop_transaction(transaction_handle.clone())
{
opt_cleanup = Some(state.into_transaction_cleanup(transaction_handle));
}
}
}
}
Ok(opt_cleanup)
}
}