refactor: migrate index metadata to on-disk JSON with fallible access
Migrate index state tracking from filesystem sentinel files to an on-disk JSON schema within `index.meta`. The `IndexMeta` struct is now wrapped in an `Arc` with internal locking, exposing only fallible methods for genome and state access. In-memory mutation capabilities have been removed, requiring callers to handle I/O errors explicitly and pass immutable references to downstream components like `PartitionRouter`. Public sentinel constants have been removed from exports.
This commit is contained in:
@@ -3,7 +3,7 @@ use std::sync::Arc;
|
||||
use obisys::progress_bar;
|
||||
|
||||
use obikindex::KmerIndex;
|
||||
use obikindex::OKIResult;
|
||||
use obikindex::{OKIError, OKIResult};
|
||||
|
||||
use super::cache::PartitionCache;
|
||||
use super::family_scan::{Selection, scan_layer_families};
|
||||
@@ -83,7 +83,7 @@ impl SnpAlignmentExt for KmerIndex {
|
||||
entropy_bias: Option<EntropyBias>,
|
||||
) -> OKIResult<SnpAlignment> {
|
||||
let n_parts = self.n_partitions();
|
||||
let n_genomes = self.meta().genomes.len();
|
||||
let n_genomes = self.meta().genomes().map_err(OKIError::Io)?.len();
|
||||
let with_counts = self.meta().config.with_counts;
|
||||
let k = self.kmer_size();
|
||||
let cache = Arc::new(PartitionCache::build(self, n_parts, with_counts)?);
|
||||
|
||||
@@ -5,7 +5,7 @@ use ndarray::Array2;
|
||||
use obisys::progress_bar;
|
||||
|
||||
use obikindex::KmerIndex;
|
||||
use obikindex::OKIResult;
|
||||
use obikindex::{OKIError, OKIResult};
|
||||
|
||||
use super::cache::PartitionCache;
|
||||
use super::distance::RawSnpDistanceOutput;
|
||||
@@ -65,7 +65,7 @@ impl CardinalityExt for KmerIndex {
|
||||
ratio_ceiling: f64,
|
||||
) -> OKIResult<CardinalityTally> {
|
||||
let n_parts = self.n_partitions();
|
||||
let n_genomes = self.meta().genomes.len();
|
||||
let n_genomes = self.meta().genomes().map_err(OKIError::Io)?.len();
|
||||
let with_counts = self.meta().config.with_counts;
|
||||
let k = self.kmer_size();
|
||||
let included = Array2::from_shape_fn((n_genomes, n_genomes), |(i, j)| {
|
||||
|
||||
@@ -5,7 +5,7 @@ use ndarray::Array2;
|
||||
use obisys::progress_bar;
|
||||
|
||||
use obikindex::KmerIndex;
|
||||
use obikindex::OKIResult;
|
||||
use obikindex::{OKIError, OKIResult};
|
||||
|
||||
use super::cache::PartitionCache;
|
||||
use super::family_scan::{Selection, scan_layer_families};
|
||||
@@ -66,7 +66,7 @@ where
|
||||
C: Fn(Acc, Acc) -> Acc,
|
||||
{
|
||||
let n_parts = index.n_partitions();
|
||||
let n_genomes = index.meta().genomes.len();
|
||||
let n_genomes = index.meta().genomes().map_err(OKIError::Io)?.len();
|
||||
let with_counts = index.meta().config.with_counts;
|
||||
let k = index.kmer_size();
|
||||
let cache = Arc::new(PartitionCache::build(index, n_parts, with_counts)?);
|
||||
@@ -149,7 +149,7 @@ pub trait DistanceExt {
|
||||
|
||||
impl DistanceExt for KmerIndex {
|
||||
fn raw_snp_distance(&self) -> OKIResult<RawSnpDistanceOutput> {
|
||||
let n_genomes = self.meta().genomes.len();
|
||||
let n_genomes = self.meta().genomes().map_err(OKIError::Io)?.len();
|
||||
let (snp, shared) = scan_family_pairs(
|
||||
self,
|
||||
"raw_snp_distance",
|
||||
@@ -182,7 +182,7 @@ impl DistanceExt for KmerIndex {
|
||||
raw: &RawSnpDistanceOutput,
|
||||
ratio_ceiling: f64,
|
||||
) -> OKIResult<BasePairTally> {
|
||||
let n_genomes = self.meta().genomes.len();
|
||||
let n_genomes = self.meta().genomes().map_err(OKIError::Io)?.len();
|
||||
let included = Array2::from_shape_fn((n_genomes, n_genomes), |(i, j)| {
|
||||
if i == j {
|
||||
return false;
|
||||
|
||||
@@ -135,7 +135,7 @@ impl ShannonEntropyExt for KmerIndex {
|
||||
entropy_bias: Option<EntropyBias>,
|
||||
) -> OKIResult<()> {
|
||||
let n_parts = self.n_partitions();
|
||||
let n_genomes = self.meta().genomes.len();
|
||||
let n_genomes = self.meta().genomes().map_err(OKIError::Io)?.len();
|
||||
let with_counts = self.meta().config.with_counts;
|
||||
let k = self.kmer_size();
|
||||
let cache = Arc::new(PartitionCache::build(self, n_parts, with_counts)?);
|
||||
@@ -227,7 +227,7 @@ pub(super) fn ensure_entropy_annexes(index: &KmerIndex, layer_dirs: &[PathBuf])
|
||||
}
|
||||
|
||||
let n_parts = index.n_partitions();
|
||||
let n_genomes = index.meta().genomes.len();
|
||||
let n_genomes = index.meta().genomes().map_err(OKIError::Io)?.len();
|
||||
let with_counts = index.meta().config.with_counts;
|
||||
let k = index.kmer_size();
|
||||
let cache = Arc::new(PartitionCache::build(index, n_parts, with_counts)?);
|
||||
|
||||
@@ -32,7 +32,7 @@ use ndarray::Array2;
|
||||
use obisys::progress_bar;
|
||||
|
||||
use obikindex::KmerIndex;
|
||||
use obikindex::OKIResult;
|
||||
use obikindex::{OKIError, OKIResult};
|
||||
|
||||
use super::alignment::{SnpAlignment, iupac_code};
|
||||
use super::cache::PartitionCache;
|
||||
@@ -79,7 +79,7 @@ impl SankoffBundleExt for KmerIndex {
|
||||
exclude_mask: &[bool],
|
||||
) -> OKIResult<SankoffBundle> {
|
||||
let n_parts = self.n_partitions();
|
||||
let n_genomes = self.meta().genomes.len();
|
||||
let n_genomes = self.meta().genomes().map_err(OKIError::Io)?.len();
|
||||
let with_counts = self.meta().config.with_counts;
|
||||
let k = self.kmer_size();
|
||||
let cache = Arc::new(PartitionCache::build(self, n_parts, with_counts)?);
|
||||
|
||||
@@ -5,7 +5,7 @@ use rayon::prelude::*;
|
||||
use obisys::progress_bar;
|
||||
|
||||
use obikindex::KmerIndex;
|
||||
use obikindex::OKIResult;
|
||||
use obikindex::{OKIError, OKIResult};
|
||||
|
||||
use super::ANNEX_FILE_NAME;
|
||||
use super::SiblingAnnex;
|
||||
@@ -105,7 +105,7 @@ impl SiblingStatsExt for KmerIndex {
|
||||
|
||||
fn sibling_annex_stats(&self) -> OKIResult<SiblingAnnexStats> {
|
||||
let n_parts = self.n_partitions();
|
||||
let n_genomes = self.meta().genomes.len();
|
||||
let n_genomes = self.meta().genomes().map_err(OKIError::Io)?.len();
|
||||
let with_counts = self.meta().config.with_counts;
|
||||
let k = self.kmer_size();
|
||||
// Same whole-run cache as `build_sibling_annex` — see its docs for
|
||||
|
||||
@@ -275,7 +275,7 @@ fn family_scan_consumers_agree_on_one_sibling_each() {
|
||||
|
||||
// Merge doesn't promise to preserve source order, so resolve each
|
||||
// genome's index by label rather than assuming g1 -> 0, g2 -> 1.
|
||||
let idx_of = |label: &str| merged.meta().genomes.iter().position(|g| g.label == label).unwrap();
|
||||
let idx_of = |label: &str| merged.meta().genomes().unwrap().iter().position(|g| g.label == label).unwrap();
|
||||
let (i1, i2) = (idx_of("g1"), idx_of("g2"));
|
||||
|
||||
// snp_pseudo_alignment: one variable family, one column — g1's row
|
||||
@@ -389,7 +389,7 @@ fn subsample_and_shannon_on_one_variable_family() {
|
||||
let merged = merge_two(dir.path(), &g1, &g2);
|
||||
merged.build_sibling_annex().expect("build_sibling_annex");
|
||||
|
||||
let idx_of = |label: &str| merged.meta().genomes.iter().position(|g| g.label == label).unwrap();
|
||||
let idx_of = |label: &str| merged.meta().genomes().unwrap().iter().position(|g| g.label == label).unwrap();
|
||||
let (i1, i2) = (idx_of("g1"), idx_of("g2"));
|
||||
|
||||
// This fixture has exactly one non-monomorphic family (see
|
||||
@@ -442,7 +442,7 @@ fn sankoff_bundle_matches_old_separate_calls() {
|
||||
let merged = merge_two(dir.path(), &g1, &g2);
|
||||
merged.build_sibling_annex().expect("build_sibling_annex");
|
||||
|
||||
let n_genomes = merged.meta().genomes.len();
|
||||
let n_genomes = merged.meta().genomes().unwrap().len();
|
||||
let exclude_mask = vec![false; n_genomes];
|
||||
let ratio_ceiling = 0.5;
|
||||
|
||||
@@ -487,7 +487,7 @@ fn base_pair_tally_accumulates_base_a_diagnostic() {
|
||||
).expect("merge");
|
||||
merged.build_sibling_annex().expect("build_sibling_annex");
|
||||
|
||||
let n_genomes = merged.meta().genomes.len();
|
||||
let n_genomes = merged.meta().genomes().unwrap().len();
|
||||
let exclude_mask = vec![false; n_genomes];
|
||||
let bundle = merged.sankoff_bundle(None, None, 0.5, &exclude_mask).expect("sankoff_bundle");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user