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