use std::path::Path;
use anyhow::{Context, Result};
use redb::Database;
use super::tables::redb_cache_size_bytes;
use super::tables::{
CHUNKS_TABLE, ENTITIES_TABLE, FILE_HASHES_TABLE, KG_COMMUNITIES_TABLE, KG_EDGES_REV_TABLE,
KG_EDGES_TABLE, KG_NODES_TABLE, KG_SYMBOL_COMMUNITY_TABLE,
};
use crate::core::corpus_recovery::open_corpus_db_or_recreate;
pub struct CorpusStore {
pub(super) db: Database,
path: std::path::PathBuf,
}
impl CorpusStore {
pub fn open(path: &Path) -> Result<Self> {
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)
.with_context(|| format!("create parent of {}", path.display()))?;
}
let cache_bytes = redb_cache_size_bytes();
tracing::info!(
"corpus: opening {} with redb page cache = {} MB \
(set TRUSTY_REDB_CACHE_MB to override)",
path.display(),
cache_bytes / (1024 * 1024),
);
let db = open_corpus_db_or_recreate(path, cache_bytes)?;
{
let txn = db.begin_write().context("begin corpus init txn")?;
{
txn.open_table(CHUNKS_TABLE).context("init chunks table")?;
txn.open_table(ENTITIES_TABLE)
.context("init entities table")?;
txn.open_table(KG_NODES_TABLE)
.context("init kg_nodes table")?;
txn.open_table(KG_EDGES_TABLE)
.context("init kg_edges table")?;
txn.open_table(KG_EDGES_REV_TABLE)
.context("init kg_edges_rev table")?;
txn.open_table(KG_COMMUNITIES_TABLE)
.context("init kg_communities table")?;
txn.open_table(KG_SYMBOL_COMMUNITY_TABLE)
.context("init kg_symbol_community table")?;
txn.open_table(FILE_HASHES_TABLE)
.context("init file_hashes table")?;
txn.open_table(crate::core::migration::META_TABLE)
.context("init _meta table")?;
}
txn.commit().context("commit corpus init txn")?;
}
Ok(Self {
db,
path: path.to_path_buf(),
})
}
pub fn open_fresh(path: &Path) -> Result<Self> {
match std::fs::remove_file(path) {
Ok(()) => {}
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
Err(e) => {
return Err(e)
.with_context(|| format!("clear stale staging corpus at {}", path.display()))
}
}
Self::open(path)
}
pub fn path(&self) -> &Path {
&self.path
}
}