1use linera_base::ensure;
7use thiserror::Error;
8
9#[cfg(with_metrics)]
10mod metrics {
11 use std::sync::LazyLock;
12
13 use linera_base::prometheus_util::register_int_counter;
14 use prometheus::IntCounter;
15
16 pub static VALUE_SPLIT_COUNT: LazyLock<IntCounter> = LazyLock::new(|| {
18 register_int_counter(
19 "value_split_count",
20 "Number of values split across multiple keys due to size limits",
21 )
22 });
23}
24
25use crate::{
26 batch::{Batch, WriteOperation},
27 store::{
28 KeyValueDatabase, KeyValueStoreError, ReadableKeyValueStore, WithError,
29 WritableKeyValueStore,
30 },
31};
32#[cfg(with_testing)]
33use crate::{
34 memory::{MemoryStore, MemoryStoreError},
35 store::TestKeyValueDatabase,
36};
37
38#[derive(Clone)]
45pub struct ValueSplittingDatabase<D> {
46 database: D,
48}
49
50#[derive(Clone)]
52pub struct ValueSplittingStore<S> {
53 store: S,
55}
56
57#[derive(Error, Debug)]
59pub enum ValueSplittingError<E> {
60 #[error(transparent)]
62 InnerStoreError(#[from] E),
63
64 #[error("the key is of length less than 4, so we cannot extract the first byte")]
66 TooShortKey,
67
68 #[error("value segment is missing from the database")]
70 MissingSegment,
71
72 #[error("no count of size u32 is available in the value")]
74 NoCountAvailable,
75}
76
77impl<E: KeyValueStoreError> From<bcs::Error> for ValueSplittingError<E> {
78 fn from(error: bcs::Error) -> Self {
79 let error = E::from(error);
80 ValueSplittingError::InnerStoreError(error)
81 }
82}
83
84impl<E: KeyValueStoreError + 'static> KeyValueStoreError for ValueSplittingError<E> {
85 const BACKEND: &'static str = "value splitting";
86
87 fn must_reload_view(&self) -> bool {
88 match self {
89 ValueSplittingError::InnerStoreError(e) => e.must_reload_view(),
90 _ => false,
91 }
92 }
93}
94
95impl<S> WithError for ValueSplittingDatabase<S>
96where
97 S: WithError,
98 S::Error: 'static,
99{
100 type Error = ValueSplittingError<S::Error>;
101}
102
103impl<D> WithError for ValueSplittingStore<D>
104where
105 D: WithError,
106 D::Error: 'static,
107{
108 type Error = ValueSplittingError<D::Error>;
109}
110
111impl<S> ReadableKeyValueStore for ValueSplittingStore<S>
112where
113 S: ReadableKeyValueStore,
114 S::Error: 'static,
115{
116 const MAX_KEY_SIZE: usize = S::MAX_KEY_SIZE - 4;
117
118 fn max_stream_queries(&self) -> usize {
119 self.store.max_stream_queries()
120 }
121
122 fn root_key(&self) -> Result<Vec<u8>, Self::Error> {
123 Ok(self.store.root_key()?)
124 }
125
126 async fn read_value_bytes(&self, key: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
127 let mut big_key = key.to_vec();
128 big_key.extend(&[0, 0, 0, 0]);
129 let value = self.store.read_value_bytes(&big_key).await?;
130 let Some(value) = value else {
131 return Ok(None);
132 };
133 let count = Self::read_count_from_value(&value)?;
134 let mut big_value = value[4..].to_vec();
135 if count == 1 {
136 return Ok(Some(big_value));
137 }
138 let mut big_keys = Vec::new();
139 for i in 1..count {
140 let big_key_segment = Self::get_segment_key(key, i)?;
141 big_keys.push(big_key_segment);
142 }
143 let segments = self.store.read_multi_values_bytes(&big_keys).await?;
144 for segment in segments {
145 match segment {
146 None => {
147 return Err(ValueSplittingError::MissingSegment);
148 }
149 Some(segment) => {
150 big_value.extend(segment);
151 }
152 }
153 }
154 Ok(Some(big_value))
155 }
156
157 async fn contains_key(&self, key: &[u8]) -> Result<bool, Self::Error> {
158 let mut big_key = key.to_vec();
159 big_key.extend(&[0, 0, 0, 0]);
160 Ok(self.store.contains_key(&big_key).await?)
161 }
162
163 async fn contains_keys(&self, keys: &[Vec<u8>]) -> Result<Vec<bool>, Self::Error> {
164 let big_keys = keys
165 .iter()
166 .map(|key| {
167 let mut big_key = key.clone();
168 big_key.extend(&[0, 0, 0, 0]);
169 big_key
170 })
171 .collect::<Vec<_>>();
172 Ok(self.store.contains_keys(&big_keys).await?)
173 }
174
175 async fn read_multi_values_bytes(
176 &self,
177 keys: &[Vec<u8>],
178 ) -> Result<Vec<Option<Vec<u8>>>, Self::Error> {
179 let mut big_keys = Vec::new();
180 for key in keys {
181 let mut big_key = key.clone();
182 big_key.extend(&[0, 0, 0, 0]);
183 big_keys.push(big_key);
184 }
185 let values = self.store.read_multi_values_bytes(&big_keys).await?;
186 let mut big_values = Vec::<Option<Vec<u8>>>::new();
187 let mut keys_add = Vec::new();
188 let mut n_blocks = Vec::new();
189 for (key, value) in keys.iter().zip(values) {
190 match value {
191 None => {
192 n_blocks.push(0);
193 big_values.push(None);
194 }
195 Some(value) => {
196 let count = Self::read_count_from_value(&value)?;
197 let big_value = value[4..].to_vec();
198 for i in 1..count {
199 let big_key_segment = Self::get_segment_key(key, i)?;
200 keys_add.push(big_key_segment);
201 }
202 n_blocks.push(count);
203 big_values.push(Some(big_value));
204 }
205 }
206 }
207 if !keys_add.is_empty() {
208 let mut segments = self
209 .store
210 .read_multi_values_bytes(&keys_add)
211 .await?
212 .into_iter();
213 for (big_value, count) in big_values.iter_mut().zip(&n_blocks) {
214 if let Some(value) = big_value {
215 for _ in 1..*count {
216 let segment = segments.next().unwrap().unwrap();
217 value.extend(segment);
218 }
219 }
220 }
221 }
222 Ok(big_values)
223 }
224
225 async fn find_keys_by_prefix(&self, key_prefix: &[u8]) -> Result<Vec<Vec<u8>>, Self::Error> {
226 let mut keys = Vec::new();
227 for big_key in self.store.find_keys_by_prefix(key_prefix).await? {
228 let len = big_key.len();
229 if Self::read_index_from_key(&big_key)? == 0 {
230 let key = big_key[0..len - 4].to_vec();
231 keys.push(key);
232 }
233 }
234 Ok(keys)
235 }
236
237 async fn find_key_values_by_prefix(
238 &self,
239 key_prefix: &[u8],
240 ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, Self::Error> {
241 let small_key_values = self.store.find_key_values_by_prefix(key_prefix).await?;
242 let mut small_kv_iterator = small_key_values.into_iter();
243 let mut key_values = Vec::new();
244 while let Some((mut big_key, value)) = small_kv_iterator.next() {
245 if Self::read_index_from_key(&big_key)? != 0 {
246 continue; }
248 big_key.truncate(big_key.len() - 4);
249 let key = big_key;
250 let count = Self::read_count_from_value(&value)?;
251 let mut big_value = value[4..].to_vec();
252 for idx in 1..count {
253 let (big_key, value) = small_kv_iterator
254 .next()
255 .ok_or(ValueSplittingError::MissingSegment)?;
256 ensure!(
257 Self::read_index_from_key(&big_key)? == idx
258 && big_key.starts_with(&key)
259 && big_key.len() == key.len() + 4,
260 ValueSplittingError::MissingSegment
261 );
262 big_value.extend(value);
263 }
264 key_values.push((key, big_value));
265 }
266 Ok(key_values)
267 }
268}
269
270impl<K> WritableKeyValueStore for ValueSplittingStore<K>
271where
272 K: WritableKeyValueStore,
273 K::Error: 'static,
274{
275 const MAX_VALUE_SIZE: usize = usize::MAX;
276
277 async fn write_batch(&self, batch: Batch) -> Result<(), Self::Error> {
278 let mut batch_new = Batch::new();
279 for operation in batch.operations {
280 match operation {
281 WriteOperation::Delete { key } => {
282 let mut big_key = key.to_vec();
283 big_key.extend(&[0, 0, 0, 0]);
284 batch_new.delete_key(big_key);
285 }
286 WriteOperation::Put { key, mut value } => {
287 let big_key = Self::get_segment_key(&key, 0)?;
288 let mut count: u32 = 1;
289 let value_ext = if value.len() <= K::MAX_VALUE_SIZE - 4 {
290 Self::get_initial_count_first_chunk(count, &value)?
291 } else {
292 tracing::warn!(
293 value_len = value.len(),
294 max_value_size = K::MAX_VALUE_SIZE,
295 "Splitting large value across multiple keys"
296 );
297 #[cfg(with_metrics)]
298 metrics::VALUE_SPLIT_COUNT.inc();
299 let remainder = value.split_off(K::MAX_VALUE_SIZE - 4);
300 for value_chunk in remainder.chunks(K::MAX_VALUE_SIZE) {
301 let big_key_segment = Self::get_segment_key(&key, count)?;
302 batch_new.put_key_value_bytes(big_key_segment, value_chunk.to_vec());
303 count += 1;
304 }
305 Self::get_initial_count_first_chunk(count, &value)?
306 };
307 batch_new.put_key_value_bytes(big_key, value_ext);
308 }
309 WriteOperation::DeletePrefix { key_prefix } => {
310 batch_new.delete_key_prefix(key_prefix);
311 }
312 }
313 }
314 Ok(self.store.write_batch(batch_new).await?)
315 }
316
317 async fn clear_journal(&self) -> Result<(), Self::Error> {
318 Ok(self.store.clear_journal().await?)
319 }
320}
321
322impl<D> KeyValueDatabase for ValueSplittingDatabase<D>
323where
324 D: KeyValueDatabase,
325 D::Error: 'static,
326{
327 type Config = D::Config;
328
329 type Store = ValueSplittingStore<D::Store>;
330
331 fn get_name() -> String {
332 format!("value splitting {}", D::get_name())
333 }
334
335 async fn connect(config: &Self::Config, namespace: &str) -> Result<Self, Self::Error> {
336 let database = D::connect(config, namespace).await?;
337 Ok(Self { database })
338 }
339
340 fn open_shared(&self, root_key: &[u8]) -> Result<Self::Store, Self::Error> {
341 let store = self.database.open_shared(root_key)?;
342 Ok(ValueSplittingStore { store })
343 }
344
345 fn open_exclusive(&self, root_key: &[u8]) -> Result<Self::Store, Self::Error> {
346 let store = self.database.open_exclusive(root_key)?;
347 Ok(ValueSplittingStore { store })
348 }
349
350 async fn list_all(config: &Self::Config) -> Result<Vec<String>, Self::Error> {
351 Ok(D::list_all(config).await?)
352 }
353
354 async fn list_root_keys(&self) -> Result<Vec<Vec<u8>>, Self::Error> {
355 Ok(self.database.list_root_keys().await?)
356 }
357
358 async fn delete_all(config: &Self::Config) -> Result<(), Self::Error> {
359 Ok(D::delete_all(config).await?)
360 }
361
362 async fn exists(config: &Self::Config, namespace: &str) -> Result<bool, Self::Error> {
363 Ok(D::exists(config, namespace).await?)
364 }
365
366 async fn create(config: &Self::Config, namespace: &str) -> Result<(), Self::Error> {
367 Ok(D::create(config, namespace).await?)
368 }
369
370 async fn delete(config: &Self::Config, namespace: &str) -> Result<(), Self::Error> {
371 Ok(D::delete(config, namespace).await?)
372 }
373}
374
375#[cfg(with_testing)]
376impl<D> TestKeyValueDatabase for ValueSplittingDatabase<D>
377where
378 D: TestKeyValueDatabase,
379 D::Error: 'static,
380{
381 async fn new_test_config() -> Result<D::Config, Self::Error> {
382 Ok(D::new_test_config().await?)
383 }
384}
385
386impl<D> ValueSplittingStore<D>
387where
388 D: WithError,
389{
390 pub fn new(store: D) -> Self {
392 ValueSplittingStore { store }
393 }
394
395 fn get_segment_key(key: &[u8], index: u32) -> Result<Vec<u8>, ValueSplittingError<D::Error>> {
396 let mut big_key_segment = key.to_vec();
397 let mut bytes = bcs::to_bytes(&index)?;
398 bytes.reverse();
399 big_key_segment.extend(bytes);
400 Ok(big_key_segment)
401 }
402
403 fn get_initial_count_first_chunk(
404 count: u32,
405 first_chunk: &[u8],
406 ) -> Result<Vec<u8>, ValueSplittingError<D::Error>> {
407 let mut bytes = bcs::to_bytes(&count)?;
408 bytes.reverse();
409 let mut value_ext = Vec::new();
410 value_ext.extend(bytes);
411 value_ext.extend(first_chunk);
412 Ok(value_ext)
413 }
414
415 fn read_count_from_value(value: &[u8]) -> Result<u32, ValueSplittingError<D::Error>> {
416 if value.len() < 4 {
417 return Err(ValueSplittingError::NoCountAvailable);
418 }
419 let mut bytes = value[0..4].to_vec();
420 bytes.reverse();
421 Ok(bcs::from_bytes::<u32>(&bytes)?)
422 }
423
424 fn read_index_from_key(key: &[u8]) -> Result<u32, ValueSplittingError<D::Error>> {
425 let len = key.len();
426 if len < 4 {
427 return Err(ValueSplittingError::TooShortKey);
428 }
429 let mut bytes = key[len - 4..len].to_vec();
430 bytes.reverse();
431 Ok(bcs::from_bytes::<u32>(&bytes)?)
432 }
433}
434
435#[derive(Clone)]
437#[cfg(with_testing)]
438pub struct LimitedTestMemoryStore {
439 inner: MemoryStore,
440}
441
442#[cfg(with_testing)]
443impl Default for LimitedTestMemoryStore {
444 fn default() -> Self {
445 Self::new()
446 }
447}
448
449#[cfg(with_testing)]
450impl WithError for LimitedTestMemoryStore {
451 type Error = MemoryStoreError;
452}
453
454#[cfg(with_testing)]
455impl ReadableKeyValueStore for LimitedTestMemoryStore {
456 const MAX_KEY_SIZE: usize = usize::MAX;
457
458 fn max_stream_queries(&self) -> usize {
459 self.inner.max_stream_queries()
460 }
461
462 fn root_key(&self) -> Result<Vec<u8>, MemoryStoreError> {
463 self.inner.root_key()
464 }
465
466 async fn read_value_bytes(&self, key: &[u8]) -> Result<Option<Vec<u8>>, MemoryStoreError> {
467 self.inner.read_value_bytes(key).await
468 }
469
470 async fn contains_key(&self, key: &[u8]) -> Result<bool, MemoryStoreError> {
471 self.inner.contains_key(key).await
472 }
473
474 async fn contains_keys(&self, keys: &[Vec<u8>]) -> Result<Vec<bool>, MemoryStoreError> {
475 self.inner.contains_keys(keys).await
476 }
477
478 async fn read_multi_values_bytes(
479 &self,
480 keys: &[Vec<u8>],
481 ) -> Result<Vec<Option<Vec<u8>>>, MemoryStoreError> {
482 self.inner.read_multi_values_bytes(keys).await
483 }
484
485 async fn find_keys_by_prefix(
486 &self,
487 key_prefix: &[u8],
488 ) -> Result<Vec<Vec<u8>>, MemoryStoreError> {
489 self.inner.find_keys_by_prefix(key_prefix).await
490 }
491
492 async fn find_key_values_by_prefix(
493 &self,
494 key_prefix: &[u8],
495 ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, MemoryStoreError> {
496 self.inner.find_key_values_by_prefix(key_prefix).await
497 }
498}
499
500#[cfg(with_testing)]
501impl WritableKeyValueStore for LimitedTestMemoryStore {
502 const MAX_VALUE_SIZE: usize = 100;
505
506 async fn write_batch(&self, batch: Batch) -> Result<(), MemoryStoreError> {
507 assert!(
508 batch.check_value_size(Self::MAX_VALUE_SIZE),
509 "The batch size is not adequate for this test"
510 );
511 self.inner.write_batch(batch).await
512 }
513
514 async fn clear_journal(&self) -> Result<(), MemoryStoreError> {
515 self.inner.clear_journal().await
516 }
517}
518
519#[cfg(with_testing)]
520impl LimitedTestMemoryStore {
521 pub fn new() -> Self {
523 let inner = MemoryStore::new_for_testing();
524 LimitedTestMemoryStore { inner }
525 }
526}
527
528#[cfg(with_testing)]
530pub fn create_value_splitting_memory_store() -> ValueSplittingStore<LimitedTestMemoryStore> {
531 ValueSplittingStore::new(LimitedTestMemoryStore::new())
532}
533
534#[cfg(test)]
535mod tests {
536 use linera_views::{
537 batch::Batch,
538 store::{ReadableKeyValueStore, WritableKeyValueStore},
539 value_splitting::{LimitedTestMemoryStore, ValueSplittingStore},
540 };
541 use rand::Rng;
542
543 #[tokio::test]
546 async fn test_value_splitting1_testing_leftovers() {
547 let store = LimitedTestMemoryStore::new();
548 const MAX_LEN: usize = LimitedTestMemoryStore::MAX_VALUE_SIZE;
549 const _: () = assert!(MAX_LEN > 10);
550 let big_store = ValueSplittingStore::new(store.clone());
551 let key = vec![0, 0];
552 let mut batch = Batch::new();
554 let value = Vec::from([0; MAX_LEN + 1]);
555 batch.put_key_value_bytes(key.clone(), value.clone());
556 big_store.write_batch(batch).await.unwrap();
557 let value_read = big_store.read_value_bytes(&key).await.unwrap();
558 assert_eq!(value_read, Some(value));
559 let mut batch = Batch::new();
561 let value = Vec::from([0, 1]);
562 batch.put_key_value_bytes(key.clone(), value.clone());
563 big_store.write_batch(batch).await.unwrap();
564 let value_read = big_store.read_value_bytes(&key).await.unwrap();
565 assert_eq!(value_read, Some(value));
566 let keys = store.find_keys_by_prefix(&[0]).await.unwrap();
568 assert_eq!(keys, vec![vec![0, 0, 0, 0, 0], vec![0, 0, 0, 0, 1]]);
569 }
570
571 #[tokio::test]
572 async fn test_value_splitting2_testing_splitting() {
573 let store = LimitedTestMemoryStore::new();
574 const MAX_LEN: usize = LimitedTestMemoryStore::MAX_VALUE_SIZE;
575 let big_store = ValueSplittingStore::new(store.clone());
576 let key = vec![0, 0];
577 let mut batch = Batch::new();
579 let mut value = Vec::new();
580 let mut rng = crate::random::make_deterministic_rng();
581 for _ in 0..2 * MAX_LEN - 4 {
582 value.push(rng.gen::<u8>());
583 }
584 batch.put_key_value_bytes(key.clone(), value.clone());
585 big_store.write_batch(batch).await.unwrap();
586 let value_read = big_store.read_value_bytes(&key).await.unwrap();
587 assert_eq!(value_read, Some(value.clone()));
588 let mut value_concat = Vec::<u8>::new();
590 for index in 0..2 {
591 let mut segment_key = key.clone();
592 let mut bytes = bcs::to_bytes(&index).unwrap();
593 bytes.reverse();
594 segment_key.extend(bytes);
595 let value_read = store.read_value_bytes(&segment_key).await.unwrap();
596 let Some(value_read) = value_read else {
597 unreachable!()
598 };
599 if index == 0 {
600 value_concat.extend(&value_read[4..]);
601 } else {
602 value_concat.extend(&value_read);
603 }
604 }
605 assert_eq!(value, value_concat);
606 }
607
608 #[tokio::test]
609 async fn test_value_splitting3_write_and_delete() {
610 let store = LimitedTestMemoryStore::new();
611 const MAX_LEN: usize = LimitedTestMemoryStore::MAX_VALUE_SIZE;
612 let big_store = ValueSplittingStore::new(store.clone());
613 let key = vec![0, 0];
614 let mut batch = Batch::new();
616 let mut value = Vec::new();
617 let mut rng = crate::random::make_deterministic_rng();
618 for _ in 0..3 * MAX_LEN - 4 {
619 value.push(rng.gen::<u8>());
620 }
621 batch.put_key_value_bytes(key.clone(), value.clone());
622 big_store.write_batch(batch).await.unwrap();
623 let mut batch = Batch::new();
625 batch.delete_key(key.clone());
626 big_store.write_batch(batch).await.unwrap();
627 let key_values = big_store.find_key_values_by_prefix(&[0]).await.unwrap();
629 assert_eq!(key_values.len(), 0);
630 let keys = store.find_keys_by_prefix(&[0]).await.unwrap();
632 assert_eq!(keys, vec![vec![0, 0, 0, 0, 1], vec![0, 0, 0, 0, 2]]);
633 }
634}