rustfs_erasure_codec/core/
mod.rs1extern crate alloc;
2
3#[cfg(feature = "std")]
4pub(crate) mod cache_detect;
5mod codec;
6mod encode;
7mod leopard;
8pub(crate) mod leopard_gf16;
9pub(crate) mod leopard_gf8;
10mod metrics;
11mod options;
12#[cfg(feature = "std")]
13mod parallel;
14mod reconstruct;
15mod shard_by_shard;
16#[cfg(feature = "std")]
17pub mod stream;
18mod verify;
19mod workspace;
20
21use alloc::sync::Arc;
22use alloc::vec::Vec;
23
24use hashlink::LruCache;
25#[cfg(feature = "std")]
26use parking_lot::Mutex;
27#[cfg(not(feature = "std"))]
28use spin::Mutex;
29
30use crate::Field;
31use crate::matrix::Matrix;
32
33use leopard::FamilyState;
34
35#[cfg(feature = "std")]
36pub use leopard_gf8::LeopardGf8ProfileStats;
37#[cfg(feature = "std")]
38pub(crate) use leopard_gf8::{leopard_gf8_profile_stats, reset_leopard_gf8_profile_stats};
39#[cfg(feature = "std")]
40pub use metrics::{ReconstructionCacheAnalysis, ReconstructionCacheStats, RuntimeProfileStats};
41pub use options::{CodecFamily, CodecOptions, MatrixMode};
42#[cfg(feature = "std")]
43pub(crate) use parallel::RuntimeParallelPolicyCache;
44#[cfg(feature = "std")]
45pub use parallel::{PARALLEL_POLICY_VERSION, ParallelDecision, ParallelPolicy};
46pub use shard_by_shard::ShardByShard;
47pub use workspace::VerifyWorkspace;
48
49#[cfg(feature = "std")]
50use metrics::{ReconstructionCacheMetrics, RuntimeProfileMetrics};
51
52pub(crate) const DATA_DECODE_MATRIX_CACHE_MIN_CAPACITY: usize = 128;
53pub(crate) const DATA_DECODE_MATRIX_CACHE_MAX_CAPACITY: usize = 4096;
54pub(crate) const CODE_SLICE_MIN_CHUNK_BYTES: usize = 16 * 1024;
55pub(crate) const CODE_SLICE_DEFAULT_CHUNK_BYTES: usize = 64 * 1024;
56pub(crate) const CODE_SLICE_LARGE_CHUNK_BYTES: usize = 256 * 1024;
57pub(crate) const VERIFY_INLINE_SCRATCH_ELEMS: usize = 4 * 1024;
58#[cfg(feature = "std")]
59pub(crate) const PARALLEL_MIN_SHARD_BYTES: usize = 256 * 1024;
60
61#[derive(Debug)]
62pub struct ReedSolomon<F: Field> {
63 data_shard_count: usize,
64 parity_shard_count: usize,
65 total_shard_count: usize,
66 codec_family: CodecFamily,
67 pub(crate) family_state: FamilyState<F>,
68 matrix: Matrix<F>,
69 options: CodecOptions,
70 #[cfg(feature = "std")]
71 pub(crate) policy_cache: RuntimeParallelPolicyCache,
72 data_decode_matrix_cache: Mutex<LruCache<Vec<usize>, Arc<Matrix<F>>>>,
73 #[cfg(feature = "std")]
74 reconstruction_cache_metrics: ReconstructionCacheMetrics,
75 #[cfg(feature = "std")]
76 runtime_profile_metrics: RuntimeProfileMetrics,
77}
78
79impl<F: Field> Clone for ReedSolomon<F> {
80 fn clone(&self) -> ReedSolomon<F> {
81 match ReedSolomon::with_options(
82 self.data_shard_count,
83 self.parity_shard_count,
84 self.options,
85 ) {
86 Ok(codec) => codec,
87 Err(err) => {
88 debug_assert!(
89 false,
90 "existing codec invariants must produce a valid clone, but got error: {err:?}"
91 );
92 let mut matrix = Matrix::new(self.matrix.row_count(), self.matrix.col_count());
93 for row in 0..self.matrix.row_count() {
94 for col in 0..self.matrix.col_count() {
95 matrix.set(row, col, self.matrix.get(row, col));
96 }
97 }
98
99 let family_state = crate::core::leopard::build_family_state(
100 self.codec_family,
101 self.data_shard_count,
102 self.parity_shard_count,
103 &matrix,
104 )
105 .unwrap_or_else(|_| {
106 debug_assert!(
107 false,
108 "fallback clone path could not rebuild family state from stored matrix"
109 );
110 match self.codec_family {
111 super::CodecFamily::Classic => FamilyState::Classic,
112 super::CodecFamily::LeopardGF16 => FamilyState::LeopardGF16,
113 super::CodecFamily::LeopardGF8 => {
114 debug_assert!(
115 false,
116 "LeopardGF8 should have a recoverable family state"
117 );
118 FamilyState::Classic
119 }
120 }
121 });
122
123 let options = self.options;
124 #[cfg(feature = "std")]
125 let policy_cache = self.policy_cache;
126
127 ReedSolomon {
128 data_shard_count: self.data_shard_count,
129 parity_shard_count: self.parity_shard_count,
130 total_shard_count: self.total_shard_count,
131 codec_family: self.codec_family,
132 family_state,
133 matrix,
134 options,
135 #[cfg(feature = "std")]
136 policy_cache,
137 data_decode_matrix_cache: Mutex::new(LruCache::new(
138 options.inversion_cache_capacity,
139 )),
140 #[cfg(feature = "std")]
141 reconstruction_cache_metrics: ReconstructionCacheMetrics::default(),
142 #[cfg(feature = "std")]
143 runtime_profile_metrics: RuntimeProfileMetrics::default(),
144 }
145 }
146 }
147 }
148}
149
150impl<F: Field> PartialEq for ReedSolomon<F> {
151 fn eq(&self, rhs: &ReedSolomon<F>) -> bool {
152 self.data_shard_count == rhs.data_shard_count
153 && self.parity_shard_count == rhs.parity_shard_count
154 && self.codec_family == rhs.codec_family
155 }
156}
157
158impl<F: Field> ReedSolomon<F> {
159 pub(crate) fn ensure_classic_family_execution(&self) -> Result<(), crate::Error> {
165 match self.family_state {
166 FamilyState::Classic | FamilyState::LeopardGF8(_) | FamilyState::LeopardGF16 => Ok(()),
167 }
168 }
169
170 pub(crate) fn is_leopard_gf8_family(&self) -> bool {
171 matches!(self.family_state, FamilyState::LeopardGF8(_))
172 }
173
174 pub(crate) fn is_leopard_gf16_family(&self) -> bool {
175 matches!(self.family_state, FamilyState::LeopardGF16)
176 }
177}