1use crate::drop_event::DropEvent;
59use crate::errors::FxfsError;
60use crate::filesystem::MAX_BLOCK_SIZE;
61use crate::log::*;
62use crate::lsm_tree::bloom_filter::{BloomFilterReader, BloomFilterStats, BloomFilterWriter};
63use crate::lsm_tree::types::{
64 BoxedLayerIterator, Existence, FuzzyHash, Item, ItemRef, Key, Layer, LayerIterator, LayerValue,
65 LayerWriter, MaybeContainsKey,
66};
67use crate::object_handle::{LayerObject, ObjectHandle, ReadObjectHandle, WriteBytes};
68use crate::object_store::caching_object_handle::{CHUNK_SIZE, CachedChunk, CachingObjectHandle};
69use crate::object_store::extent::MIN_BLOCK_SIZE;
70use crate::object_store::{DataObjectHandle, HandleOptions, ObjectStore};
71use crate::serialized_types::serialized_key::{KeyDeserializer, compare_keys};
72use crate::serialized_types::{
73 LATEST_VERSION, OLD_KEY_SERIALIZATION_VERSION, Version, Versioned, VersionedLatest,
74};
75use anyhow::{Context, Error, anyhow, ensure};
76use async_trait::async_trait;
77use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
78use fprint::TypeFingerprint;
79use fuchsia_sync::Mutex;
80use futures::future::BoxFuture;
81use futures::stream::{FuturesUnordered, TryStreamExt};
82use fxfs_crypto::{Crypt, UnwrappedKey, WrappedKey};
83use serde::{Deserialize, Serialize};
84use static_assertions::const_assert;
85use std::cmp::Ordering;
86use std::io::{Read as _, Write as _};
87use std::marker::PhantomData;
88use std::ops::Bound;
89use std::sync::Arc;
90use storage_ptr_slice::PtrByteSlice;
91use storage_units::BlockSize;
92
93const PERSISTENT_LAYER_MAGIC: &[u8; 8] = b"FxfsLayr";
94
95pub type LayerHeader = LayerHeaderV39;
97
98#[derive(Debug, Serialize, Deserialize, TypeFingerprint, Versioned)]
99pub struct LayerHeaderV39 {
100 magic: [u8; 8],
102 block_size: u64,
108}
109
110pub type LayerInfo = LayerInfoV39;
112
113#[derive(Debug, Serialize, Deserialize, TypeFingerprint, Versioned)]
114pub struct LayerInfoV39 {
115 num_items: usize,
118 num_data_blocks: u64,
120 bloom_filter_size_bytes: usize,
122 bloom_filter_seed: u64,
124 bloom_filter_num_hashes: usize,
126}
127
128struct LayerData<K> {
129 object_id: u64,
130 version: Version,
131 block_size: BlockSize,
132 data_size: u64,
133 seek_table: Vec<u64>,
134 num_items: usize,
135 bloom_filter: Option<BloomFilterReader<K>>,
136 bloom_filter_stats: Option<BloomFilterStats>,
137 close_event: Mutex<Option<Arc<DropEvent>>>,
138}
139
140impl<K> LayerData<K> {
141 fn data_offset(&self) -> u64 {
142 NUM_HEADER_BLOCKS * self.block_size
143 }
144}
145
146pub struct PersistentLayer<K, V> {
148 object_handle: CachingObjectHandle<Arc<dyn LayerObject>>,
149 data: LayerData<K>,
150 _value_type: PhantomData<V>,
151}
152
153pub struct SyncPersistentLayer<K, V> {
155 object_handle: Arc<dyn LayerObject>,
156 data: LayerData<K>,
157 _value_type: PhantomData<V>,
158}
159
160struct BufferCursor<B> {
161 buffer: B,
162 pos: usize,
163}
164
165impl<B: LayerBuffer> BufferCursor<B> {
166 fn as_bytes(&self) -> &[u8] {
167 self.buffer.as_bytes_from(self.pos)
168 }
169}
170
171impl<B: LayerBuffer> std::io::Read for BufferCursor<B> {
172 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
173 let to_read = self.buffer.read_at(self.pos, buf);
174 self.pos += to_read;
175 Ok(to_read)
176 }
177}
178
179trait LayerBuffer {
180 fn read_at(&self, pos: usize, buf: &mut [u8]) -> usize;
181
182 fn as_bytes_from(&self, pos: usize) -> &[u8];
183
184 fn has_io_error(&self) -> bool {
185 false
186 }
187}
188
189struct ChunkBuffer<'iter> {
190 handle: &'iter CachingObjectHandle<Arc<dyn LayerObject>>,
191 chunk: Option<(usize, CachedChunk)>,
193}
194
195impl LayerBuffer for ChunkBuffer<'_> {
196 fn read_at(&self, pos: usize, buf: &mut [u8]) -> usize {
197 let Some((_, chunk)) = &self.chunk else {
198 return 0;
199 };
200 let to_read = std::cmp::min(buf.len(), chunk.len().saturating_sub(pos));
201 if to_read > 0 {
202 buf[..to_read].copy_from_slice(&chunk[pos..pos + to_read]);
203 }
204 to_read
205 }
206
207 fn as_bytes_from(&self, pos: usize) -> &[u8] {
208 self.chunk.as_ref().and_then(|(_, c)| c.get(pos..)).unwrap_or(&[])
209 }
210}
211
212#[derive(Clone, Copy)]
213struct SliceBuffer<'iter> {
214 handle: &'iter dyn LayerObject,
215 slice: &'iter [u8],
216}
217
218impl LayerBuffer for SliceBuffer<'_> {
219 fn read_at(&self, pos: usize, buf: &mut [u8]) -> usize {
220 let to_read = std::cmp::min(buf.len(), self.slice.len().saturating_sub(pos));
221 if to_read > 0 {
222 buf[..to_read].copy_from_slice(&self.slice[pos..pos + to_read]);
223 }
224 to_read
225 }
226
227 fn as_bytes_from(&self, pos: usize) -> &[u8] {
228 self.slice.get(pos..).unwrap_or(&[])
229 }
230
231 fn has_io_error(&self) -> bool {
232 self.handle.has_io_error()
233 }
234}
235
236const NUM_HEADER_BLOCKS: u64 = 1;
238
239const MINIMUM_LAYER_FILE_BLOCKS: u64 = 2;
242
243const MAX_BLOOM_FILTER_SIZE: usize = 64 * 1024 * 1024;
246const MAX_SEEK_TABLE_SIZE: usize = 64 * 1024 * 1024;
247
248const PER_DATA_BLOCK_HEADER_SIZE: usize = 2;
250const PER_DATA_BLOCK_SEEK_ENTRY_SIZE: usize = 2;
251
252enum KeyState<K> {
253 None,
254 Deserialized(K),
255 InPlace,
256}
257
258struct KeyOnlyIterator<'iter, K: Key, V: LayerValue, B> {
260 buffer: BufferCursor<B>,
262
263 layer: &'iter LayerData<K>,
264
265 pos: u64,
267
268 item_index: u16,
270
271 item_count: u16,
273
274 key: KeyState<K>,
276
277 current_block_base_u64: u64,
279
280 _value_type: PhantomData<V>,
281}
282
283impl<K: Key, V: LayerValue, B: LayerBuffer> KeyOnlyIterator<'_, K, V, B> {
284 fn corruption_error(&self, err: impl std::fmt::Display + Send + Sync + 'static) -> Error {
285 if self.buffer.buffer.has_io_error() {
286 anyhow!(zx_status::Status::IO).context(err)
287 } else {
288 anyhow!(FxfsError::Inconsistent).context(err)
289 }
290 }
291
292 fn seek_to_block_item(&mut self, index: u16) -> Result<(), Error> {
296 ensure!(index < self.item_count, FxfsError::OutOfRange);
297 if index == self.item_index && matches!(self.key, KeyState::None) {
298 return Ok(());
301 }
302 let block_start =
303 self.layer.block_size.align_down((self.buffer.pos as u64).saturating_sub(1)) as usize;
304 let offset_in_block = if index == 0 {
305 PER_DATA_BLOCK_HEADER_SIZE
308 } else {
309 let old_buffer_pos = self.buffer.pos;
310 let seek_entry_pos = (block_start + self.layer.block_size.get() as usize)
311 .checked_sub(PER_DATA_BLOCK_SEEK_ENTRY_SIZE * usize::from(self.item_count - index))
312 .ok_or_else(|| {
313 self.corruption_error(format!(
314 "Invalid item count {} for index {index}",
315 self.item_count
316 ))
317 })?;
318 if seek_entry_pos < block_start + PER_DATA_BLOCK_HEADER_SIZE {
319 return Err(self.corruption_error(format!(
320 "Invalid item count {} for index {index}",
321 self.item_count
322 )));
323 }
324 self.buffer.pos = seek_entry_pos;
325 let res = self.buffer.read_u16::<LittleEndian>();
326 self.buffer.pos = old_buffer_pos;
327 let offset_in_block = res
328 .map_err(|e| self.corruption_error(e))
329 .context("Failed to read offset")? as usize;
330 if offset_in_block >= self.layer.block_size.get() as usize
331 || offset_in_block <= PER_DATA_BLOCK_HEADER_SIZE
332 {
333 return Err(self
334 .corruption_error(format!("Offset {offset_in_block} is out of valid range.")));
335 }
336 offset_in_block
337 };
338 self.item_index = index;
339 self.key = KeyState::None;
340 self.buffer.pos = block_start + offset_in_block;
341 Ok(())
342 }
343
344 fn take_item(&mut self) -> Result<Option<Item<K, V>>, Error> {
345 let key = match std::mem::replace(&mut self.key, KeyState::None) {
346 KeyState::None => return Ok(None),
347 KeyState::InPlace => {
348 let (mut deserializer, key_len) =
349 KeyDeserializer::new(self.buffer.as_bytes(), Some(self.current_block_base_u64))
350 .map_err(|e| self.corruption_error(e))
351 .context("Corrupt layer (key format)")?;
352 let key = K::deserialize_key_from(&mut deserializer)
353 .map_err(|e| self.corruption_error(e))
354 .context("Corrupt layer (key)")?;
355 if !deserializer.is_empty() {
356 return Err(self.corruption_error("Trailing bytes in serialized key"));
357 }
358 self.buffer.pos += key_len;
359 key
360 }
361 KeyState::Deserialized(key) => key,
362 };
363 let value = V::deserialize_from_version(self.buffer.by_ref(), self.layer.version)
364 .map_err(|e| self.corruption_error(e))
365 .context("Corrupt layer (value)")?;
366 Ok(Some(Item { key, value }))
367 }
368
369 fn read_block_header(&mut self) -> Result<(), Error> {
370 self.item_count =
371 self.buffer.read_u16::<LittleEndian>().map_err(|e| self.corruption_error(e))?;
372 if self.item_count == 0 {
373 return Err(self.corruption_error(format!(
374 "Read block with zero item count (object: {}, offset: {})",
375 self.layer.object_id, self.pos
376 )));
377 }
378 if PER_DATA_BLOCK_HEADER_SIZE
379 + (usize::from(self.item_count) - 1) * PER_DATA_BLOCK_SEEK_ENTRY_SIZE
380 >= self.layer.block_size.get() as usize
381 {
382 return Err(self.corruption_error("Block seek table overlaps header"));
383 }
384 debug!(
385 pos = self.pos,
386 object_size = self.layer.data_offset() + self.layer.data_size,
387 oid = self.layer.object_id;
388 ""
389 );
390 if self.layer.version > OLD_KEY_SERIALIZATION_VERSION {
391 let block_index = (self.pos - self.layer.data_offset()) / self.layer.block_size;
392 self.current_block_base_u64 = *self
393 .layer
394 .seek_table
395 .get(block_index as usize)
396 .ok_or_else(|| self.corruption_error("Block index out of bounds"))?;
397 }
398 self.pos += self.layer.block_size;
399 self.item_index = 0;
400 self.key = KeyState::None;
401 Ok(())
402 }
403
404 fn deserialize_current_key(&mut self) -> Result<(), Error> {
405 self.seek_to_block_item(self.item_index)?;
406 self.key = if self.layer.version <= OLD_KEY_SERIALIZATION_VERSION {
407 KeyState::Deserialized(
408 K::deserialize_from_version(self.buffer.by_ref(), self.layer.version)
409 .map_err(|e| self.corruption_error(e))
410 .context("Corrupt layer (key)")?,
411 )
412 } else {
413 KeyState::InPlace
414 };
415 self.item_index += 1;
416 Ok(())
417 }
418
419 fn binary_search_block(
426 &mut self,
427 search_key: &mut SearchKey<'_, K>,
428 ) -> Result<Option<bool>, Error> {
429 if self.layer.version > OLD_KEY_SERIALIZATION_VERSION {
430 let target = search_key
431 .serialized_with_base(self.current_block_base_u64)
432 .ok_or_else(|| self.corruption_error("Search key precedes block"))?;
433 return self.binary_search_block_in_place(target);
434 }
435
436 let mut left_index = 0;
437 let mut right_index = self.item_count;
438 while left_index < (right_index - 1) {
439 let mid_index = left_index + ((right_index - left_index) / 2);
440 self.seek_to_block_item(mid_index).context("Read index offset for binary search")?;
441 self.deserialize_current_key()?;
442 match search_key.compare(self)?.context("Unexpected EOF")? {
443 Ordering::Greater => right_index = mid_index,
444 Ordering::Equal => return Ok(Some(true)),
445 Ordering::Less => left_index = mid_index,
446 }
447 }
448 if right_index < self.item_count {
449 self.seek_to_block_item(right_index)
450 .context("Read index for offset of right pointer")?;
451 self.deserialize_current_key()?;
452 return Ok(Some(false));
453 }
454 self.key = KeyState::None;
455 Ok(None)
456 }
457
458 fn binary_search_block_in_place(&mut self, target: &[u8]) -> Result<Option<bool>, Error> {
461 let mut left_index = 0;
462 let mut right_index = self.item_count;
463 if right_index > 1 {
464 let block_size = self.layer.block_size.get() as usize;
465 let block_start =
466 self.layer.block_size.align_down((self.buffer.pos as u64).saturating_sub(1))
467 as usize;
468 let block_bytes = self
469 .buffer
470 .buffer
471 .as_bytes_from(block_start)
472 .get(..block_size)
473 .ok_or_else(|| self.corruption_error("Short block"))?;
474 let seek_table_offset =
476 block_size - usize::from(right_index - 1) * PER_DATA_BLOCK_SEEK_ENTRY_SIZE;
477 let (data_bytes, seek_entries) = block_bytes.split_at(seek_table_offset);
478 let mut found = None;
479 while left_index < (right_index - 1) {
480 let mid_index = left_index + ((right_index - left_index) / 2);
481 let entry_pos = usize::from(mid_index - 1) * PER_DATA_BLOCK_SEEK_ENTRY_SIZE;
482 let offset = LittleEndian::read_u16(
483 &seek_entries[entry_pos..entry_pos + PER_DATA_BLOCK_SEEK_ENTRY_SIZE],
484 ) as usize;
485 if offset >= seek_table_offset || offset <= PER_DATA_BLOCK_HEADER_SIZE {
486 return Err(
487 self.corruption_error(format!("Offset {offset} is out of valid range."))
488 );
489 }
490 match compare_keys(&data_bytes[offset..], target)
491 .map_err(|e| self.corruption_error(e))?
492 {
493 Ordering::Greater => {
494 right_index = mid_index;
495 found = Some((mid_index, offset, false));
496 }
497 Ordering::Equal => {
498 found = Some((mid_index, offset, true));
499 break;
500 }
501 Ordering::Less => left_index = mid_index,
502 }
503 }
504 if let Some((index, offset, exact)) = found {
505 self.item_index = index + 1;
506 self.key = KeyState::InPlace;
507 self.buffer.pos = block_start + offset;
508 return Ok(Some(exact));
509 }
510 }
511 self.item_index = self.item_count;
512 self.key = KeyState::None;
513 Ok(None)
514 }
515}
516
517impl<'iter, K: Key, V: LayerValue, B> KeyOnlyIterator<'iter, K, V, B> {
518 fn new(layer: &'iter LayerData<K>, buffer: B, buffer_pos: usize, pos: u64) -> Self {
521 assert!(layer.block_size.is_aligned(pos));
522 Self {
523 layer,
524 buffer: BufferCursor { buffer, pos: buffer_pos },
525 pos,
526 item_index: 0,
527 item_count: 0,
528 key: KeyState::None,
529 current_block_base_u64: 0,
530 _value_type: PhantomData,
531 }
532 }
533}
534
535impl<'iter, K: Key, V: LayerValue> KeyOnlyIterator<'iter, K, V, ChunkBuffer<'iter>> {
536 fn new_async(layer: &'iter PersistentLayer<K, V>, pos: u64) -> Self {
537 Self::new(
538 &layer.data,
539 ChunkBuffer { handle: &layer.object_handle, chunk: None },
540 (pos % CHUNK_SIZE) as usize,
541 pos,
542 )
543 }
544
545 fn reposition(&self, pos: u64, other: Option<&Self>) -> Self {
548 let chunk_num = (pos / CHUNK_SIZE) as usize;
549 let chunk =
550 std::iter::once(self).chain(other).find_map(|iter| match &iter.buffer.buffer.chunk {
551 Some((n, chunk)) if *n == chunk_num => Some((chunk_num, chunk.clone())),
552 _ => None,
553 });
554 Self::new(
555 self.layer,
556 ChunkBuffer { handle: self.buffer.buffer.handle, chunk },
557 (pos % CHUNK_SIZE) as usize,
558 pos,
559 )
560 }
561
562 async fn advance(&mut self) -> Result<(), Error> {
563 if !self.try_advance()? {
564 let chunk_num = (self.pos / CHUNK_SIZE) as usize;
565 let chunk = self
566 .buffer
567 .buffer
568 .handle
569 .read(self.pos as usize)
570 .await
571 .context("Reading during advance")?;
572 self.buffer.buffer.chunk = Some((chunk_num, chunk));
573 self.buffer.pos = (self.pos % CHUNK_SIZE) as usize;
574 self.read_block_header()?;
575 self.deserialize_current_key()?;
576 }
577 Ok(())
578 }
579
580 fn try_advance(&mut self) -> Result<bool, Error> {
583 if self.item_index >= self.item_count {
584 if self.pos >= self.layer.data_offset() + self.layer.data_size {
585 self.key = KeyState::None;
586 return Ok(true);
587 }
588 let chunk_num = (self.pos / CHUNK_SIZE) as usize;
589 if !matches!(&self.buffer.buffer.chunk, Some((n, _)) if *n == chunk_num) {
590 let Some(chunk) = self.buffer.buffer.handle.try_read(self.pos as usize) else {
591 return Ok(false);
592 };
593 self.buffer.buffer.chunk = Some((chunk_num, chunk));
594 }
595 self.buffer.pos = (self.pos % CHUNK_SIZE) as usize;
596 self.read_block_header()?;
597 }
598 self.deserialize_current_key()?;
599 Ok(true)
600 }
601}
602
603impl<'iter, K: Key, V: LayerValue> KeyOnlyIterator<'iter, K, V, SliceBuffer<'iter>> {
604 fn new_sync(layer: &'iter SyncPersistentLayer<K, V>, pos: u64) -> Self {
605 let slice = layer.object_handle.as_slice().expect("slice must be present");
606 Self::new(
607 &layer.data,
608 SliceBuffer { handle: layer.object_handle.as_ref(), slice },
609 pos as usize,
610 pos,
611 )
612 }
613
614 fn reposition(&self, pos: u64, _other: Option<&Self>) -> Self {
617 Self::new(self.layer, self.buffer.buffer, pos as usize, pos)
618 }
619
620 fn advance(&mut self) -> Result<(), Error> {
621 if self.item_index >= self.item_count {
622 if self.pos >= self.layer.data_offset() + self.layer.data_size {
623 self.key = KeyState::None;
624 return Ok(());
625 }
626 self.buffer.pos = self.pos as usize;
627 self.read_block_header()?;
628 }
629 self.deserialize_current_key()
630 }
631}
632
633struct Iterator<'iter, K: Key, V: LayerValue, B> {
634 inner: KeyOnlyIterator<'iter, K, V, B>,
635 item: Option<Item<K, V>>,
637}
638
639impl<'iter, K: Key, V: LayerValue, B: LayerBuffer> Iterator<'iter, K, V, B> {
640 fn new(mut seek_iterator: KeyOnlyIterator<'iter, K, V, B>) -> Result<Self, Error> {
641 let item = seek_iterator.take_item()?;
642 Ok(Self { inner: seek_iterator, item })
643 }
644}
645
646impl<'iter, K: Key, V: LayerValue> LayerIterator<K, V>
647 for Iterator<'iter, K, V, ChunkBuffer<'iter>>
648{
649 async fn advance(&mut self) -> Result<(), Error> {
650 self.inner.advance().await?;
651 self.item = self.inner.take_item()?;
652 Ok(())
653 }
654
655 fn advance_dyn<'a>(&'a mut self) -> Result<Option<BoxFuture<'a, Result<(), Error>>>, Error> {
656 if self.inner.try_advance()? {
657 self.item = self.inner.take_item()?;
658 Ok(None)
659 } else {
660 Ok(Some(Box::pin(self.advance())))
661 }
662 }
663
664 fn get(&self) -> Option<ItemRef<'_, K, V>> {
665 self.item.as_ref().map(<&Item<K, V>>::into)
666 }
667}
668
669impl<'iter, K: Key, V: LayerValue> LayerIterator<K, V>
670 for Iterator<'iter, K, V, SliceBuffer<'iter>>
671{
672 async fn advance(&mut self) -> Result<(), Error> {
673 self.inner.advance()?;
674 self.item = self.inner.take_item()?;
675 Ok(())
676 }
677
678 fn advance_dyn<'a>(&'a mut self) -> Result<Option<BoxFuture<'a, Result<(), Error>>>, Error> {
679 self.inner.advance()?;
680 self.item = self.inner.take_item()?;
681 Ok(None)
682 }
683
684 fn get(&self) -> Option<ItemRef<'_, K, V>> {
685 self.item.as_ref().map(<&Item<K, V>>::into)
686 }
687}
688
689fn seek_table_size(version: Version, num_data_blocks: u64) -> Result<usize, Error> {
690 if num_data_blocks == 0 || version <= OLD_KEY_SERIALIZATION_VERSION {
691 return Ok(0);
694 }
695 let seek_table_size = (num_data_blocks as usize) * std::mem::size_of::<u64>();
696 if seek_table_size > MAX_SEEK_TABLE_SIZE {
697 return Err(anyhow!(FxfsError::NotSupported)).context("Seek table too large");
698 }
699 Ok(seek_table_size)
700}
701
702fn parse_seek_table(bytes: PtrByteSlice<'_>, num_data_blocks: u64) -> Result<Vec<u64>, Error> {
703 let mut seek_table = Vec::with_capacity(num_data_blocks as usize);
704 let mut prev = 0;
705 for chunk in bytes.iter_as::<[u8; 8]>() {
706 let next = u64::from_le_bytes(chunk);
707 if prev > next {
710 return Err(anyhow!(FxfsError::Inconsistent))
711 .context(format!("Seek table entry out of order, {prev:?} > {next:?}"));
712 }
713 prev = next;
714 seek_table.push(next);
715 }
716 Ok(seek_table)
717}
718
719async fn load_seek_table(
720 object_handle: &(impl ReadObjectHandle + 'static),
721 seek_table_offset: u64,
722 num_data_blocks: u64,
723 version: Version,
724) -> Result<Vec<u64>, Error> {
725 let seek_table_size = seek_table_size(version, num_data_blocks)?;
726 if seek_table_size == 0 {
727 return Ok(Vec::new());
728 }
729 let aligned_size =
730 object_handle.block_size().align_up(seek_table_size as u64).ok_or(FxfsError::TooBig)?
731 as usize;
732 let mut buffer = object_handle.allocate_buffer(aligned_size).await;
733 let bytes_read = object_handle
734 .read_aligned(seek_table_offset, buffer.as_mut())
735 .await
736 .context("Reading seek table blocks")?;
737 ensure!(bytes_read >= seek_table_size, "Short read");
738
739 parse_seek_table(buffer.subslice(0..seek_table_size).as_ptr_slice(), num_data_blocks)
740}
741
742const BLOOM_FILTER_READ_CHUNK_SIZE: usize = 1024 * 1024;
743
744fn bloom_filter_size(version: Version, layer_info: &LayerInfo) -> Result<usize, Error> {
745 if version != LATEST_VERSION || layer_info.bloom_filter_size_bytes == 0 {
746 return Ok(0);
750 }
751 if layer_info.bloom_filter_size_bytes > MAX_BLOOM_FILTER_SIZE {
752 return Err(anyhow!(FxfsError::NotSupported)).context("Bloom filter too large");
753 }
754 Ok(layer_info.bloom_filter_size_bytes)
755}
756
757async fn load_bloom_filter<K: FuzzyHash>(
758 handle: &(impl ReadObjectHandle + 'static),
759 bloom_filter_offset: u64,
760 version: Version,
761 layer_info: &LayerInfo,
762) -> Result<Option<BloomFilterReader<K>>, Error> {
763 let size = bloom_filter_size(version, layer_info)?;
764 if size == 0 {
765 return Ok(None);
766 }
767 let aligned_size = handle.block_size().align_up(size as u64).ok_or(FxfsError::TooBig)? as usize;
768 let mut buffer = handle.allocate_buffer(aligned_size).await;
769 let reads = FuturesUnordered::new();
770 let mut offset = bloom_filter_offset;
771 for chunk in buffer.as_mut().chunks_mut(BLOOM_FILTER_READ_CHUNK_SIZE) {
772 let chunk_len = chunk.len() as u64;
773 reads.push(async move {
774 handle.read_aligned(offset, chunk).await.context("Failed to read")?;
775 Ok::<(), Error>(())
776 });
777 offset += chunk_len;
778 }
779 reads.try_collect::<()>().await?;
780 Ok(Some(BloomFilterReader::read(
781 buffer.subslice(0..size).as_ptr_slice(),
782 layer_info.bloom_filter_seed,
783 layer_info.bloom_filter_num_hashes,
784 )?))
785}
786
787struct SearchKey<'a, K: Key> {
788 key: &'a K,
789 buf: Vec<u8>,
790 cached_base: Option<u64>,
791}
792
793impl<'a, K: Key> SearchKey<'a, K> {
794 fn new(key: &'a K) -> Self {
795 Self { key, buf: Vec::new(), cached_base: None }
796 }
797
798 fn serialized_with_base(&mut self, base: u64) -> Option<&[u8]> {
801 if self.key.get_leading_u64() < base {
802 return None;
803 }
804 if self.cached_base != Some(base) {
805 self.buf.clear();
806 self.key.serialize_key_with_base_into(&mut self.buf, base);
807 self.cached_base = Some(base);
808 }
809 Some(&self.buf)
810 }
811
812 fn compare<V: LayerValue, B: LayerBuffer>(
813 &mut self,
814 iter: &KeyOnlyIterator<'_, K, V, B>,
815 ) -> Result<Option<Ordering>, Error> {
816 match &iter.key {
817 KeyState::None => Ok(None),
818 KeyState::Deserialized(k) => Ok(Some(k.cmp_upper_bound(self.key))),
819 KeyState::InPlace => {
820 let Some(target) = self.serialized_with_base(iter.current_block_base_u64) else {
821 return Ok(Some(Ordering::Greater));
822 };
823 Ok(Some(
824 compare_keys(iter.buffer.as_bytes(), target)
825 .map_err(|e| iter.corruption_error(e))?,
826 ))
827 }
828 }
829 }
830}
831
832impl<K: FuzzyHash> LayerData<K> {
833 fn new(
834 object_id: u64,
835 version: Version,
836 block_size: BlockSize,
837 layer_info: &LayerInfo,
838 seek_table: Vec<u64>,
839 bloom_filter: Option<BloomFilterReader<K>>,
840 ) -> Self {
841 let bloom_filter_stats = bloom_filter.as_ref().map(|b| b.stats());
842 Self {
843 object_id,
844 version,
845 block_size,
846 data_size: block_size * layer_info.num_data_blocks,
847 seek_table,
848 num_items: layer_info.num_items,
849 bloom_filter,
850 bloom_filter_stats,
851 close_event: Mutex::new(Some(Arc::new(DropEvent::new()))),
852 }
853 }
854
855 fn parse_header(
856 mut reader: PtrByteSlice<'_>,
857 handle_block_size: BlockSize,
858 total_size: u64,
859 ) -> Result<(Version, BlockSize, u64), Error> {
860 let version = Version::deserialize_from(&mut reader)?;
861 ensure!(version <= LATEST_VERSION, FxfsError::InvalidVersion);
862 let header = LayerHeader::deserialize_from_version(&mut reader, version)
863 .context("Failed to deserialize header")?;
864 if &header.magic != PERSISTENT_LAYER_MAGIC {
865 return Err(anyhow!(FxfsError::Inconsistent).context("Invalid layer file magic"));
866 }
867 let block_size = BlockSize::from_u64(header.block_size).ok_or_else(|| {
868 anyhow!(FxfsError::Inconsistent)
869 .context(format!("Invalid block size {}", header.block_size))
870 })?;
871 ensure!(block_size <= MAX_BLOCK_SIZE, FxfsError::NotSupported);
872 ensure!(block_size >= MIN_BLOCK_SIZE, FxfsError::NotSupported);
873 if !handle_block_size.is_aligned(block_size.get()) {
874 return Err(anyhow!(FxfsError::Inconsistent)).context(format!(
875 "{block_size} not a multiple of handle block size {handle_block_size}"
876 ));
877 }
878 if total_size < MINIMUM_LAYER_FILE_BLOCKS * block_size {
879 return Err(anyhow!(FxfsError::Inconsistent).context("Layer file too short"));
880 }
881 let last_block_offset = total_size
882 .checked_sub(block_size.get())
883 .ok_or(FxfsError::Inconsistent)
884 .context("Layer file unexpectedly short")?;
885 Ok((version, block_size, last_block_offset))
886 }
887
888 fn parse_layer_info(
889 last_block: PtrByteSlice<'_>,
890 version: Version,
891 block_size: BlockSize,
892 total_size: u64,
893 ) -> Result<(LayerInfo, u64, u64), Error> {
894 let bs = block_size.get() as usize;
895 let layer_info_len = u64::from_le_bytes(last_block.subslice(bs - 8..bs).read().unwrap());
896 let layer_info_offset = std::mem::size_of::<u64>()
897 .checked_add(layer_info_len as usize)
898 .and_then(|n| bs.checked_sub(n))
899 .ok_or(FxfsError::Inconsistent)
900 .context("Invalid layer info length")?;
901 let mut reader = last_block.subslice(layer_info_offset..bs);
902 let layer_info = LayerInfo::deserialize_from_version(&mut reader, version)
903 .context("Failed to deserialize LayerInfo")?;
904 if layer_info.num_items == 0 && layer_info.num_data_blocks > 0 {
905 return Err(anyhow!(FxfsError::Inconsistent))
906 .context("Invalid num_items/num_data_blocks");
907 }
908 let total_blocks = total_size / block_size;
909 let bloom_filter_blocks =
910 block_size.align_up_to_blocks(layer_info.bloom_filter_size_bytes as u64);
911 if layer_info.num_data_blocks.saturating_add(bloom_filter_blocks)
912 > total_blocks - MINIMUM_LAYER_FILE_BLOCKS
913 {
914 return Err(anyhow!(FxfsError::Inconsistent)).context("Invalid number of blocks");
915 }
916 let bloom_filter_offset = block_size * (NUM_HEADER_BLOCKS + layer_info.num_data_blocks);
917 let seek_offset =
918 block_size * (NUM_HEADER_BLOCKS + layer_info.num_data_blocks + bloom_filter_blocks);
919 Ok((layer_info, bloom_filter_offset, seek_offset))
920 }
921
922 async fn open(handle: &Arc<dyn LayerObject>) -> Result<Self, Error> {
923 let handle_block_size = handle.block_size();
924 let mut buffer = handle.allocate_buffer(handle_block_size.get() as usize).await;
925 handle.read_aligned(0, buffer.as_mut()).await.context("Failed to read first block")?;
926 let (version, block_size, last_block_offset) =
927 Self::parse_header(buffer.as_ptr_slice(), handle_block_size, handle.get_size())?;
928
929 let bs = block_size.get() as usize;
930 handle
931 .read_aligned(last_block_offset, buffer.subslice_mut(0..bs))
932 .await
933 .context("Failed to read layer info")?;
934 let (layer_info, bloom_filter_offset, seek_offset) = Self::parse_layer_info(
935 buffer.subslice(0..bs).as_ptr_slice(),
936 version,
937 block_size,
938 handle.get_size(),
939 )?;
940 std::mem::drop(buffer);
941
942 let bloom_filter = load_bloom_filter(handle, bloom_filter_offset, version, &layer_info)
943 .await
944 .context("Failed to load bloom filter")?;
945 let seek_table = load_seek_table(handle, seek_offset, layer_info.num_data_blocks, version)
946 .await
947 .context("Failed to load seek table")?;
948
949 Ok(Self::new(
950 handle.object_id(),
951 version,
952 block_size,
953 &layer_info,
954 seek_table,
955 bloom_filter,
956 ))
957 }
958
959 fn open_from_slice(handle: &Arc<dyn LayerObject>) -> Result<Self, Error> {
960 let slice = handle.as_slice().ok_or(FxfsError::InvalidArgs)?;
961 let io_or_corruption = |err: Error| -> Error {
962 if handle.has_io_error() { anyhow!(zx_status::Status::IO).context(err) } else { err }
963 };
964 let handle_block_size = handle.block_size();
965 let total_size = slice.len() as u64;
966 if total_size < handle_block_size.get() {
967 return Err(io_or_corruption(
968 anyhow!(FxfsError::Inconsistent).context("Layer file too short"),
969 ));
970 }
971 let (version, block_size, last_block_offset) = Self::parse_header(
972 slice[..handle_block_size.get() as usize].into(),
973 handle_block_size,
974 total_size,
975 )
976 .map_err(&io_or_corruption)?;
977
978 let bs = block_size.get() as usize;
979 let last_block = &slice[last_block_offset as usize..last_block_offset as usize + bs];
980 let (layer_info, bloom_filter_offset, seek_offset) =
981 Self::parse_layer_info(last_block.into(), version, block_size, total_size)
982 .map_err(&io_or_corruption)?;
983
984 let bf_size = bloom_filter_size(version, &layer_info)
985 .map_err(&io_or_corruption)
986 .context("Failed to load bloom filter")?;
987 let st_size = seek_table_size(version, layer_info.num_data_blocks)
988 .map_err(&io_or_corruption)
989 .context("Failed to load seek table")?;
990 if bf_size > 0 {
991 handle.prefetch(bloom_filter_offset..total_size);
992 } else if st_size > 0 {
993 handle.prefetch(seek_offset..total_size);
994 }
995
996 let bloom_filter = if bf_size > 0 {
997 let start = bloom_filter_offset as usize;
998 let end = start
999 .checked_add(bf_size)
1000 .filter(|&end| end <= slice.len())
1001 .ok_or_else(|| io_or_corruption(anyhow!(FxfsError::Inconsistent)))
1002 .context("Bloom filter out of bounds")?;
1003 Some(BloomFilterReader::from_bytes(
1004 &slice[start..end],
1005 layer_info.bloom_filter_seed,
1006 layer_info.bloom_filter_num_hashes,
1007 ))
1008 } else {
1009 None
1010 };
1011
1012 let seek_table = if st_size > 0 {
1013 let start = seek_offset as usize;
1014 let end = start
1015 .checked_add(st_size)
1016 .filter(|&end| end <= slice.len())
1017 .ok_or_else(|| io_or_corruption(anyhow!(FxfsError::Inconsistent)))
1018 .context("Seek table out of bounds")?;
1019 parse_seek_table(slice[start..end].into(), layer_info.num_data_blocks)
1020 .map_err(&io_or_corruption)
1021 .context("Failed to load seek table")?
1022 } else {
1023 Vec::new()
1024 };
1025
1026 if handle.has_io_error() {
1027 return Err(anyhow!(zx_status::Status::IO).context("I/O error while opening layer"));
1028 }
1029
1030 Ok(Self::new(
1031 handle.object_id(),
1032 version,
1033 block_size,
1034 &layer_info,
1035 seek_table,
1036 bloom_filter,
1037 ))
1038 }
1039}
1040
1041macro_rules! seek_impl {
1042 ($self:ident, $bound:ident $(, $await:tt)?) => {{
1043 let (key, excluded) = match $bound {
1044 Bound::Unbounded => {
1045 let mut iterator = $self.key_only_iterator($self.data_offset());
1046 iterator.advance()$(.$await)? .context("Unbounded seek advance")?;
1047 return Ok(Iterator::new(iterator)?);
1048 }
1049 Bound::Included(k) => (k, false),
1050 Bound::Excluded(k) => (k, true),
1051 };
1052 let first_data_block_index = $self.data_offset() / $self.data.block_size;
1053
1054 let (mut left_offset, mut right_offset) = if $self.data.seek_table.is_empty() {
1055 ($self.data_offset(), $self.data_offset() + $self.data.data_size)
1056 } else {
1057 let target = key.get_leading_u64();
1063 let right_index =
1064 $self.data.seek_table.as_slice().partition_point(|&x| x <= target) as u64;
1065 if right_index == 0 {
1066 let mut iterator = $self.key_only_iterator($self.data_offset());
1067 iterator.advance()$(.$await)? .context("Initial seek advance")?;
1068 return Ok(Iterator::new(iterator)?);
1069 }
1070 let left_index = $self.data.seek_table.as_slice()[..right_index as usize]
1073 .partition_point(|&x| x < target)
1074 .saturating_sub(1) as u64;
1075
1076 (
1077 (left_index + first_data_block_index) * $self.data.block_size,
1078 (right_index + first_data_block_index) * $self.data.block_size,
1079 )
1080 };
1081 let mut left = $self.key_only_iterator(left_offset);
1082 left.advance()$(.$await)? .context("Initial seek advance")?;
1083 let mut search_key = SearchKey::new(key);
1084 match search_key.compare(&left)? {
1085 Some(Ordering::Less) => {}
1086 Some(Ordering::Equal) if excluded => {
1087 left.advance()$(.$await)??;
1088 return Ok(Iterator::new(left)?);
1089 }
1090 _ => return Ok(Iterator::new(left)?),
1091 }
1092 let mut right = None;
1093 while right_offset - left_offset > $self.data.block_size {
1094 let mid_offset =
1096 $self.data.block_size.align_down(left_offset + (right_offset - left_offset) / 2);
1097 let mut iterator = left.reposition(mid_offset, right.as_ref());
1098 iterator.advance()$(.$await)??;
1099 match search_key.compare(&iterator)?.context("Unexpected EOF")? {
1100 Ordering::Greater => {
1101 right_offset = mid_offset;
1102 right = Some(iterator);
1103 }
1104 Ordering::Equal => {
1105 if excluded {
1106 iterator.advance()$(.$await)??;
1107 }
1108 return Ok(Iterator::new(iterator)?);
1109 }
1110 Ordering::Less => {
1111 left_offset = mid_offset;
1112 left = iterator;
1113 }
1114 }
1115 }
1116
1117 match left.binary_search_block(&mut search_key)? {
1119 Some(true) if excluded => left.advance()$(.$await)??,
1120 Some(_) => {}
1121 None => match right {
1126 Some(right) => return Ok(Iterator::new(right)?),
1127 None => left.advance()$(.$await)??,
1128 },
1129 }
1130 Ok(Iterator::new(left)?)
1131 }};
1132}
1133
1134fn page_size() -> BlockSize {
1135 #[cfg(target_os = "fuchsia")]
1136 {
1137 storage_units::page_size().into()
1138 }
1139 #[cfg(not(target_os = "fuchsia"))]
1140 {
1141 BlockSize::SIZE_4KIB
1142 }
1143}
1144
1145impl<K: Key, V: LayerValue> PersistentLayer<K, V> {
1146 pub async fn open(handle: impl LayerObject + 'static) -> Result<Arc<dyn Layer<K, V>>, Error> {
1147 Self::open_layer(Arc::new(handle)).await
1148 }
1149
1150 pub async fn open_layer(handle: Arc<dyn LayerObject>) -> Result<Arc<dyn Layer<K, V>>, Error> {
1151 let data = LayerData::open(&handle).await?;
1152 if handle.as_slice().is_some() && data.block_size <= page_size() {
1153 Ok(Arc::new(SyncPersistentLayer {
1154 object_handle: handle,
1155 data,
1156 _value_type: PhantomData,
1157 }) as Arc<dyn Layer<K, V>>)
1158 } else {
1159 Ok(Arc::new(PersistentLayer {
1160 object_handle: CachingObjectHandle::new(handle),
1161 data,
1162 _value_type: PhantomData,
1163 }) as Arc<dyn Layer<K, V>>)
1164 }
1165 }
1166
1167 pub async fn open_async(handle: Arc<dyn LayerObject>) -> Result<Arc<Self>, Error> {
1168 let data = LayerData::open(&handle).await?;
1169 Ok(Arc::new(PersistentLayer {
1170 object_handle: CachingObjectHandle::new(handle),
1171 data,
1172 _value_type: PhantomData,
1173 }))
1174 }
1175
1176 pub async fn open_handle(
1179 handle: DataObjectHandle<ObjectStore>,
1180 unwrapped_key: Option<UnwrappedKey>,
1181 ) -> Result<Arc<dyn Layer<K, V>>, Error> {
1182 let layer_object: Arc<dyn LayerObject> =
1183 if let Some(layer_pager) = handle.store().filesystem().layer_pager() {
1184 layer_pager.open_layer(handle, unwrapped_key).await?
1185 } else {
1186 Arc::new(handle)
1187 };
1188 Self::open_layer(layer_object).await
1189 }
1190
1191 fn data_offset(&self) -> u64 {
1192 self.data.data_offset()
1193 }
1194
1195 fn key_only_iterator(&self, pos: u64) -> KeyOnlyIterator<'_, K, V, ChunkBuffer<'_>> {
1196 KeyOnlyIterator::new_async(self, pos)
1197 }
1198
1199 async fn seek<'a>(
1200 &'a self,
1201 bound: Bound<&K>,
1202 ) -> Result<Iterator<'a, K, V, ChunkBuffer<'a>>, Error> {
1203 seek_impl!(self, bound, await)
1204 }
1205}
1206
1207impl<K: Key, V: LayerValue> SyncPersistentLayer<K, V> {
1208 pub fn open(handle: Arc<dyn LayerObject>) -> Result<Arc<Self>, Error> {
1209 let data = LayerData::open_from_slice(&handle)?;
1210 ensure!(data.block_size <= page_size(), FxfsError::NotSupported);
1211 Ok(Arc::new(Self { object_handle: handle, data, _value_type: PhantomData }))
1212 }
1213
1214 fn data_offset(&self) -> u64 {
1215 self.data.data_offset()
1216 }
1217
1218 fn key_only_iterator(&self, pos: u64) -> KeyOnlyIterator<'_, K, V, SliceBuffer<'_>> {
1219 KeyOnlyIterator::new_sync(self, pos)
1220 }
1221
1222 fn seek<'a>(&'a self, bound: Bound<&K>) -> Result<Iterator<'a, K, V, SliceBuffer<'a>>, Error> {
1223 seek_impl!(self, bound)
1224 }
1225}
1226
1227async fn unwrap_layer_key(
1229 store: &ObjectStore,
1230 object_id: u64,
1231 crypt: &dyn Crypt,
1232) -> Result<Option<UnwrappedKey>, Error> {
1233 if store.filesystem().layer_pager().is_none() {
1234 return Ok(None);
1235 }
1236 let keys = store
1237 .get_keys(object_id)
1238 .await
1239 .with_context(|| format!("Failed to get keys for layer file {object_id}"))?;
1240 let (_, key) = keys
1241 .first()
1242 .ok_or_else(|| anyhow!(FxfsError::Inconsistent))
1243 .with_context(|| format!("Missing key for encrypted layer file {object_id}"))?;
1244 let wrapped_key = WrappedKey::from(key.clone());
1245 let unwrapped = crypt
1246 .unwrap_key(&wrapped_key, object_id)
1247 .await
1248 .with_context(|| format!("Failed to unwrap key for layer file {object_id}"))?;
1249 Ok(Some(unwrapped))
1250}
1251
1252pub async fn layer_from_handle<K: Key, V: LayerValue>(
1257 handle: DataObjectHandle<ObjectStore>,
1258 unwrapped_key: Option<UnwrappedKey>,
1259) -> Result<Arc<dyn Layer<K, V>>, Error> {
1260 PersistentLayer::open_handle(handle, unwrapped_key).await
1261}
1262
1263pub async fn open_layers<K: Key, V: LayerValue>(
1268 store: &Arc<ObjectStore>,
1269 object_ids: impl IntoIterator<Item = u64>,
1270 crypt: Option<Arc<dyn Crypt>>,
1271) -> Result<(Vec<Arc<dyn Layer<K, V>>>, u64), Error> {
1272 let mut layers = Vec::new();
1273 let mut total_size = 0;
1274 for object_id in object_ids {
1275 let handle =
1276 ObjectStore::open_object(store, object_id, HandleOptions::default(), crypt.clone())
1277 .await
1278 .with_context(|| format!("Failed to open layer file {object_id}"))?;
1279 total_size += handle.get_size();
1280 let unwrapped_key = if let Some(crypt) = &crypt {
1281 unwrap_layer_key(store, object_id, crypt.as_ref()).await?
1282 } else {
1283 None
1284 };
1285 layers.push(PersistentLayer::open_handle(handle, unwrapped_key).await?);
1286 }
1287 Ok((layers, total_size))
1288}
1289
1290#[async_trait]
1291impl<K: Key, V: LayerValue> Layer<K, V> for PersistentLayer<K, V> {
1292 fn handle(&self) -> Option<&dyn LayerObject> {
1293 Some(self.object_handle.source())
1294 }
1295
1296 fn purge_cached_data(&self) {
1297 self.object_handle.purge();
1298 }
1299
1300 fn clear_cached_data(&self) {
1301 self.object_handle.clear();
1302 }
1303
1304 async fn seek<'a>(&'a self, bound: Bound<&K>) -> Result<BoxedLayerIterator<'a, K, V>, Error> {
1305 Ok(Box::new(PersistentLayer::seek(self, bound).await?))
1306 }
1307
1308 fn len(&self) -> usize {
1309 self.data.num_items
1310 }
1311
1312 fn maybe_contains_key(&self, key: &K) -> MaybeContainsKey {
1313 self.data.bloom_filter.as_ref().map_or(MaybeContainsKey::Maybe, |f| f.maybe_contains(key))
1314 }
1315
1316 fn has_bloom_filter(&self) -> bool {
1317 self.data.bloom_filter.is_some()
1318 }
1319
1320 async fn key_exists(&self, key: &K) -> Result<Existence, Error> {
1321 match &self.data.bloom_filter {
1322 Some(filter) => Ok(match filter.maybe_contains(key) {
1323 MaybeContainsKey::False => Existence::Missing,
1324 MaybeContainsKey::Maybe | MaybeContainsKey::RangeKeyTooLarge => {
1325 Existence::MaybeExists
1326 }
1327 }),
1328 None => {
1329 let iter = self.seek(Bound::Included(key)).await?;
1330 Ok(iter.get().map_or(Existence::Missing, |i| {
1331 if i.key.cmp_upper_bound(key).is_eq() {
1332 Existence::Exists
1333 } else {
1334 Existence::Missing
1335 }
1336 }))
1337 }
1338 }
1339 }
1340
1341 fn lock(&self) -> Option<Arc<DropEvent>> {
1342 self.data.close_event.lock().clone()
1343 }
1344
1345 async fn close(&self) {
1346 let listener = self.data.close_event.lock().take().expect("close already called").listen();
1347 listener.await;
1348 self.object_handle.source().close().await;
1349 }
1350
1351 fn get_version(&self) -> Version {
1352 return self.data.version;
1353 }
1354
1355 fn record_inspect_data(self: Arc<Self>, node: &fuchsia_inspect::Node) {
1356 node.record_uint("num_items", self.data.num_items as u64);
1357 node.record_bool("persistent", true);
1358 node.record_uint("size", self.object_handle.source().get_size());
1359 if let Some(stats) = self.data.bloom_filter_stats.as_ref() {
1360 node.record_child("bloom_filter", move |node| {
1361 node.record_uint("size", stats.size as u64);
1362 node.record_uint("num_hashes", stats.num_hashes as u64);
1363 node.record_uint("fill_percentage", stats.fill_percentage as u64);
1364 });
1365 }
1366 }
1367}
1368
1369#[async_trait]
1370impl<K: Key, V: LayerValue> Layer<K, V> for SyncPersistentLayer<K, V> {
1371 fn handle(&self) -> Option<&dyn LayerObject> {
1372 Some(&self.object_handle)
1373 }
1374
1375 fn purge_cached_data(&self) {
1376 self.object_handle.purge_cached_data();
1377 }
1378
1379 fn clear_cached_data(&self) {
1380 self.object_handle.purge_cached_data();
1381 }
1382
1383 async fn seek<'a>(&'a self, bound: Bound<&K>) -> Result<BoxedLayerIterator<'a, K, V>, Error> {
1384 Ok(Box::new(SyncPersistentLayer::seek(self, bound)?))
1385 }
1386
1387 fn len(&self) -> usize {
1388 self.data.num_items
1389 }
1390
1391 fn maybe_contains_key(&self, key: &K) -> MaybeContainsKey {
1392 self.data.bloom_filter.as_ref().map_or(MaybeContainsKey::Maybe, |f| f.maybe_contains(key))
1393 }
1394
1395 fn has_bloom_filter(&self) -> bool {
1396 self.data.bloom_filter.is_some()
1397 }
1398
1399 async fn key_exists(&self, key: &K) -> Result<Existence, Error> {
1400 match &self.data.bloom_filter {
1401 Some(filter) => Ok(match filter.maybe_contains(key) {
1402 MaybeContainsKey::False => Existence::Missing,
1403 MaybeContainsKey::Maybe | MaybeContainsKey::RangeKeyTooLarge => {
1404 Existence::MaybeExists
1405 }
1406 }),
1407 None => {
1408 let iter = self.seek(Bound::Included(key))?;
1409 Ok(iter.get().map_or(Existence::Missing, |i| {
1410 if i.key.cmp_upper_bound(key).is_eq() {
1411 Existence::Exists
1412 } else {
1413 Existence::Missing
1414 }
1415 }))
1416 }
1417 }
1418 }
1419
1420 fn lock(&self) -> Option<Arc<DropEvent>> {
1421 self.data.close_event.lock().clone()
1422 }
1423
1424 async fn close(&self) {
1425 let listener = self.data.close_event.lock().take().expect("close already called").listen();
1426 listener.await;
1427 self.object_handle.close().await;
1428 }
1429
1430 fn get_version(&self) -> Version {
1431 return self.data.version;
1432 }
1433
1434 fn record_inspect_data(self: Arc<Self>, node: &fuchsia_inspect::Node) {
1435 node.record_uint("num_items", self.data.num_items as u64);
1436 node.record_bool("persistent", true);
1437 node.record_uint("size", self.object_handle.get_size());
1438 if let Some(stats) = self.data.bloom_filter_stats.as_ref() {
1439 node.record_child("bloom_filter", move |node| {
1440 node.record_uint("size", stats.size as u64);
1441 node.record_uint("num_hashes", stats.num_hashes as u64);
1442 node.record_uint("fill_percentage", stats.fill_percentage as u64);
1443 });
1444 }
1445 }
1446}
1447
1448const_assert!(MAX_BLOCK_SIZE.size() <= u16::MAX as u64 + 1);
1450
1451pub struct PersistentLayerWriter<W: WriteBytes, K: Key, V: LayerValue> {
1454 writer: W,
1455 version: Version,
1456 block_size: BlockSize,
1457 buf: Vec<u8>,
1458 buf_item_count: LayerWriterBufItemCount,
1459 item_count: usize,
1460 block_offsets: Vec<u16>,
1461 block_keys: Vec<u64>,
1462 bloom_filter: BloomFilterWriter<K>,
1463 _value: PhantomData<V>,
1464}
1465
1466impl<W: WriteBytes, K: Key, V: LayerValue> PersistentLayerWriter<W, K, V> {
1467 pub async fn new(writer: W, num_items: usize, block_size: BlockSize) -> Result<Self, Error> {
1469 Self::new_with_version(writer, num_items, block_size, LATEST_VERSION).await
1470 }
1471
1472 pub(crate) async fn new_with_version(
1473 mut writer: W,
1474 num_items: usize,
1475 block_size: BlockSize,
1476 version: Version,
1477 ) -> Result<Self, Error> {
1478 ensure!(block_size <= MAX_BLOCK_SIZE, FxfsError::NotSupported);
1479 ensure!(block_size >= MIN_BLOCK_SIZE, FxfsError::NotSupported);
1480
1481 let header =
1483 LayerHeader { magic: PERSISTENT_LAYER_MAGIC.clone(), block_size: block_size.get() };
1484 let mut buf = vec![0u8; block_size.get() as usize];
1485 {
1486 let mut cursor = std::io::Cursor::new(&mut buf[..]);
1487 version.serialize_into(&mut cursor)?;
1488 header.serialize_into(&mut cursor)?;
1489 }
1490 writer.write_bytes(&buf[..]).await?;
1491
1492 let seed: u64 = rand::random();
1493 Ok(Self {
1494 writer,
1495 version,
1496 block_size,
1497 buf: Vec::new(),
1498 buf_item_count: LayerWriterBufItemCount(0),
1499 item_count: 0,
1500 block_offsets: Vec::new(),
1501 block_keys: Vec::new(),
1502 bloom_filter: BloomFilterWriter::new(seed, num_items),
1503 _value: PhantomData,
1504 })
1505 }
1506
1507 async fn write_block(&mut self) -> Result<(), Error> {
1512 if *self.buf_item_count == 0 {
1513 return Ok(());
1514 }
1515 let seek_table_size = self.block_offsets.len() * PER_DATA_BLOCK_SEEK_ENTRY_SIZE;
1516 assert!(
1517 PER_DATA_BLOCK_HEADER_SIZE + seek_table_size + self.buf.len()
1518 <= self.block_size.get() as usize
1519 );
1520 let mut cursor = std::io::Cursor::new(vec![0u8; self.block_size.get() as usize]);
1521 cursor.write_u16::<LittleEndian>(*self.buf_item_count)?;
1522 cursor.write_all(&self.buf)?;
1523 cursor.set_position(self.block_size - seek_table_size as u64);
1524 for &offset in &self.block_offsets {
1526 cursor.write_u16::<LittleEndian>(offset)?;
1527 }
1528 self.writer.write_bytes(cursor.get_ref()).await?;
1529 debug!(item_count = *self.buf_item_count, byte_count = self.buf.len(); "wrote items");
1530 self.buf.clear();
1531 *self.buf_item_count = 0;
1532 self.block_offsets.clear();
1533 Ok(())
1534 }
1535
1536 async fn write_seek_table(&mut self) -> Result<usize, Error> {
1541 let keys = if self.version <= OLD_KEY_SERIALIZATION_VERSION {
1542 self.block_keys.get(1..).unwrap_or(&[])
1543 } else {
1544 &self.block_keys
1545 };
1546 if keys.len() == 0 {
1547 return Ok(0);
1548 }
1549 let size = keys.len() * std::mem::size_of::<u64>();
1550 self.buf.resize(size, 0);
1551 let mut len = 0;
1552 for key in keys {
1553 LittleEndian::write_u64(&mut self.buf[len..len + std::mem::size_of::<u64>()], *key);
1554 len += std::mem::size_of::<u64>();
1555 }
1556 self.writer.write_bytes(&self.buf).await?;
1557 Ok(size)
1558 }
1559
1560 async fn write_info(
1563 &mut self,
1564 num_data_blocks: u64,
1565 bloom_filter_size_bytes: usize,
1566 seek_table_len: usize,
1567 ) -> Result<(), Error> {
1568 let block_size = self.writer.block_size().get() as usize;
1569 let layer_info = LayerInfo {
1570 num_items: self.item_count,
1571 num_data_blocks,
1572 bloom_filter_size_bytes,
1573 bloom_filter_seed: self.bloom_filter.seed(),
1574 bloom_filter_num_hashes: self.bloom_filter.num_hashes(),
1575 };
1576 self.buf.clear();
1577 layer_info.serialize_into(&mut self.buf)?;
1578 let layer_info_len = self.buf.len() as u64;
1579 self.buf.write_u64::<LittleEndian>(layer_info_len)?;
1580 let actual_len = self.buf.len();
1581
1582 let avail_in_block =
1585 block_size - (seek_table_len as u64 % self.writer.block_size()) as usize;
1586 let to_skip = if avail_in_block < actual_len {
1587 block_size + avail_in_block - actual_len
1588 } else {
1589 avail_in_block - actual_len
1590 };
1591 self.buf.resize(to_skip + actual_len, 0);
1592 self.buf.copy_within(0..actual_len, to_skip);
1593 self.buf[..to_skip].fill(0);
1594 self.writer.write_bytes(&self.buf).await?;
1595 Ok(())
1596 }
1597
1598 async fn write_bloom_filter(&mut self) -> Result<usize, Error> {
1601 if self.data_blocks() == 0 || self.bloom_filter.serialized_size() == 0 {
1602 return Ok(0);
1603 }
1604 let size =
1606 self.block_size.align_up(self.bloom_filter.serialized_size() as u64).unwrap() as usize;
1607 self.buf.resize(size, 0);
1608 let mut cursor = std::io::Cursor::new(&mut self.buf);
1609 self.bloom_filter.write(&mut cursor)?;
1610 self.writer.write_bytes(&self.buf).await?;
1611 Ok(self.bloom_filter.serialized_size())
1612 }
1613
1614 #[cfg(test)]
1617 pub(crate) fn bloom_filter(&mut self) -> &mut BloomFilterWriter<K> {
1618 &mut self.bloom_filter
1619 }
1620
1621 fn serialize_item(&mut self, item: ItemRef<'_, K, V>) -> Result<(), Error> {
1622 if self.version <= OLD_KEY_SERIALIZATION_VERSION {
1623 item.key.serialize_into(&mut self.buf)?;
1624 } else {
1625 item.key.serialize_key_with_base_into(&mut self.buf, *self.block_keys.last().unwrap());
1626 }
1627 item.value.serialize_into(&mut self.buf)?;
1628 Ok(())
1629 }
1630
1631 fn data_blocks(&self) -> usize {
1632 self.block_keys.len()
1633 }
1634}
1635
1636impl<W: WriteBytes + Send, K: Key, V: LayerValue> LayerWriter<K, V>
1637 for PersistentLayerWriter<W, K, V>
1638{
1639 async fn write(&mut self, item: ItemRef<'_, K, V>) -> Result<(), Error> {
1640 let len = self.buf.len();
1642 if self.block_keys.is_empty() {
1646 self.block_keys.push(item.key.get_leading_u64());
1647 }
1648 self.serialize_item(item)?;
1649
1650 let mut added_offset = false;
1651 if *self.buf_item_count > 0 {
1653 self.block_offsets.push(u16::try_from(len + PER_DATA_BLOCK_HEADER_SIZE).unwrap());
1654 added_offset = true;
1655 }
1656
1657 if PER_DATA_BLOCK_HEADER_SIZE
1660 + self.buf.len()
1661 + (self.block_offsets.len() * PER_DATA_BLOCK_SEEK_ENTRY_SIZE)
1662 > self.block_size.get() as usize - 1
1663 {
1664 if added_offset {
1665 self.block_offsets.pop();
1668 }
1669 self.buf.truncate(len);
1670 self.write_block().await?;
1671
1672 self.block_keys.push(item.key.get_leading_u64());
1674 self.serialize_item(item)?;
1675 }
1676
1677 self.bloom_filter.insert(&item.key);
1678 *self.buf_item_count += 1;
1679 self.item_count += 1;
1680 Ok(())
1681 }
1682
1683 async fn complete(mut self) -> Result<u64, Error> {
1684 self.write_block().await?;
1685 let data_blocks = self.data_blocks() as u64;
1686 let bloom_filter_len = self.write_bloom_filter().await?;
1687 let seek_table_len = self.write_seek_table().await?;
1688 self.write_info(data_blocks, bloom_filter_len, seek_table_len).await?;
1689 self.writer.complete().await
1690 }
1691}
1692
1693#[repr(transparent)]
1695struct LayerWriterBufItemCount(u16);
1696
1697impl Drop for LayerWriterBufItemCount {
1698 fn drop(&mut self) {
1699 debug_assert!(self.0 == 0, "Dropping unwritten items; did you forget to call complete?");
1700 if self.0 > 0 {
1701 warn!("Dropping unwritten items; did you forget to call complete?");
1702 }
1703 }
1704}
1705
1706impl std::ops::Deref for LayerWriterBufItemCount {
1707 type Target = u16;
1708 fn deref(&self) -> &u16 {
1709 &self.0
1710 }
1711}
1712
1713impl std::ops::DerefMut for LayerWriterBufItemCount {
1714 fn deref_mut(&mut self) -> &mut u16 {
1715 &mut self.0
1716 }
1717}
1718
1719#[cfg(test)]
1720mod tests {
1721 use super::{
1722 BlockSize, FxfsError, LayerData, NUM_HEADER_BLOCKS, PersistentLayer, PersistentLayerWriter,
1723 SyncPersistentLayer,
1724 };
1725 use crate::filesystem::MAX_BLOCK_SIZE;
1726 use crate::lsm_tree::LayerIterator;
1727 use crate::lsm_tree::testing::TestKey;
1728 use crate::lsm_tree::types::{
1729 Existence, Item, ItemRef, Layer, LayerWriter, MaybeContainsKey, OrdUpperBound,
1730 };
1731 use crate::object_handle::{
1732 LayerObject, ObjectHandle, ReadObjectHandle, WriteBytes, WriteObjectHandle,
1733 };
1734 use crate::object_store::AttributeId;
1735 use crate::object_store::allocator::AllocatorKey;
1736 use crate::object_store::extent::{Extent, MIN_BLOCK_SIZE};
1737 use crate::object_store::object_record::ObjectKey;
1738 use crate::round::round_up;
1739 use crate::serialized_types::OLD_KEY_SERIALIZATION_VERSION;
1740 use crate::testing::fake_object::{FakeObject, FakeObjectHandle};
1741 use crate::testing::writer::Writer;
1742 use anyhow::Error;
1743 use async_trait::async_trait;
1744 use std::fmt::Debug;
1745 use std::ops::{Bound, Range};
1746 use std::sync::Arc;
1747 use std::sync::atomic::{AtomicBool, Ordering};
1748 use storage_device::buffer::{BufferFuture, MutableBufferRef};
1749
1750 impl<W: WriteBytes> Debug for PersistentLayerWriter<W, i32, i32> {
1751 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
1752 f.debug_struct("rPersistentLayerWriter")
1753 .field("block_size", &self.block_size)
1754 .field("item_count", &*self.buf_item_count)
1755 .finish()
1756 }
1757 }
1758
1759 #[fuchsia::test]
1760 async fn test_iterate_after_write() {
1761 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
1762 const ITEM_COUNT: i32 = 10000;
1763
1764 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
1765 {
1766 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
1767 Writer::new(&handle).await,
1768 ITEM_COUNT as usize * 4,
1769 BLOCK_SIZE,
1770 )
1771 .await
1772 .expect("writer new");
1773 for i in 0..ITEM_COUNT {
1774 writer.write(Item::new(i, i).as_item_ref()).await.expect("write failed");
1775 }
1776 writer.complete().await.expect("flush failed");
1777 }
1778 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1779 let mut iterator = layer.seek(Bound::Unbounded).await.expect("seek failed");
1780 for i in 0..ITEM_COUNT {
1781 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1782 assert_eq!((key, value), (&i, &i));
1783 iterator.advance().await.expect("failed to advance");
1784 }
1785 assert!(iterator.get().is_none());
1786 }
1787
1788 #[fuchsia::test]
1789 async fn test_seek_after_write() {
1790 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
1791 const ITEM_COUNT: i32 = 5000;
1792
1793 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
1794 {
1795 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
1796 Writer::new(&handle).await,
1797 ITEM_COUNT as usize * 18,
1798 BLOCK_SIZE,
1799 )
1800 .await
1801 .expect("writer new");
1802 for i in 0..ITEM_COUNT {
1803 writer.write(Item::new(i * 2, i * 2).as_item_ref()).await.expect("write failed");
1805 }
1806 writer.complete().await.expect("flush failed");
1807 }
1808 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1809 for i in 0..ITEM_COUNT * 2 {
1811 let expected = round_up(i, 2).unwrap();
1814 let mut iterator = layer.seek(Bound::Included(&i)).await.expect("failed to seek");
1815 if i >= (ITEM_COUNT * 2) - 1 {
1818 assert!(iterator.get().is_none());
1819 } else {
1820 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1821 assert_eq!((key, value), (&expected, &expected));
1822 }
1823
1824 iterator.advance().await.expect("failed to advance");
1826 if i >= (ITEM_COUNT * 2) - 3 {
1830 assert!(iterator.get().is_none());
1831 } else {
1832 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1833 let next = expected + 2;
1834 assert_eq!((key, value), (&next, &next));
1835 }
1836 }
1837 }
1838
1839 #[fuchsia::test]
1840 async fn test_seek_unbounded() {
1841 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
1842 const ITEM_COUNT: i32 = 1000;
1843
1844 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
1845 {
1846 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
1847 Writer::new(&handle).await,
1848 ITEM_COUNT as usize * 18,
1849 BLOCK_SIZE,
1850 )
1851 .await
1852 .expect("writer new");
1853 for i in 0..ITEM_COUNT {
1854 writer.write(Item::new(i, i).as_item_ref()).await.expect("write failed");
1855 }
1856 writer.complete().await.expect("flush failed");
1857 }
1858 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1859 let mut iterator = layer.seek(Bound::Unbounded).await.expect("failed to seek");
1860 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1861 assert_eq!((key, value), (&0, &0));
1862
1863 iterator.advance().await.expect("failed to advance");
1865 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1866 assert_eq!((key, value), (&1, &1));
1867 }
1868
1869 #[fuchsia::test]
1870 async fn test_zero_items() {
1871 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
1872
1873 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
1874 {
1875 let writer = PersistentLayerWriter::<_, i32, i32>::new(
1876 Writer::new(&handle).await,
1877 0,
1878 BLOCK_SIZE,
1879 )
1880 .await
1881 .expect("writer new");
1882 writer.complete().await.expect("flush failed");
1883 }
1884
1885 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1886 let iterator = (layer.as_ref() as &dyn Layer<i32, i32>)
1887 .seek(Bound::Unbounded)
1888 .await
1889 .expect("seek failed");
1890 assert!(iterator.get().is_none())
1891 }
1892
1893 #[fuchsia::test]
1894 async fn test_one_item() {
1895 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
1896
1897 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
1898 {
1899 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
1900 Writer::new(&handle).await,
1901 1,
1902 BLOCK_SIZE,
1903 )
1904 .await
1905 .expect("writer new");
1906 writer.write(Item::new(42, 42).as_item_ref()).await.expect("write failed");
1907 writer.complete().await.expect("flush failed");
1908 }
1909
1910 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1911 {
1912 let mut iterator = (layer.as_ref() as &dyn Layer<i32, i32>)
1913 .seek(Bound::Unbounded)
1914 .await
1915 .expect("seek failed");
1916 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1917 assert_eq!((key, value), (&42, &42));
1918 iterator.advance().await.expect("failed to advance");
1919 assert!(iterator.get().is_none())
1920 }
1921 {
1922 let mut iterator = (layer.as_ref() as &dyn Layer<i32, i32>)
1923 .seek(Bound::Included(&30))
1924 .await
1925 .expect("seek failed");
1926 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1927 assert_eq!((key, value), (&42, &42));
1928 iterator.advance().await.expect("failed to advance");
1929 assert!(iterator.get().is_none())
1930 }
1931 {
1932 let mut iterator = (layer.as_ref() as &dyn Layer<i32, i32>)
1933 .seek(Bound::Included(&42))
1934 .await
1935 .expect("seek failed");
1936 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1937 assert_eq!((key, value), (&42, &42));
1938 iterator.advance().await.expect("failed to advance");
1939 assert!(iterator.get().is_none())
1940 }
1941 {
1942 let iterator = (layer.as_ref() as &dyn Layer<i32, i32>)
1943 .seek(Bound::Included(&43))
1944 .await
1945 .expect("seek failed");
1946 assert!(iterator.get().is_none())
1947 }
1948 }
1949
1950 #[fuchsia::test]
1951 async fn test_large_block_size() {
1952 const BLOCK_SIZE: BlockSize = MAX_BLOCK_SIZE;
1954 let item_count: i32 = ((BLOCK_SIZE.get() as i32) / 18) * 3;
1956
1957 let handle = FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE);
1958 {
1959 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
1960 Writer::new(&handle).await,
1961 item_count as usize * 18,
1962 BLOCK_SIZE,
1963 )
1964 .await
1965 .expect("writer new");
1966 for i in 2000000000..(2000000000 + item_count) {
1968 writer.write(Item::new(i, i).as_item_ref()).await.expect("write failed");
1969 }
1970 writer.complete().await.expect("flush failed");
1971 }
1972
1973 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1974 let mut iterator = layer.seek(Bound::Unbounded).await.expect("seek failed");
1975 for i in 2000000000..(2000000000 + item_count) {
1976 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1977 assert_eq!((key, value), (&i, &i));
1978 iterator.advance().await.expect("failed to advance");
1979 }
1980 assert!(iterator.get().is_none());
1981 }
1982
1983 #[fuchsia::test]
1984 async fn test_overlarge_block_size() {
1985 const BLOCK_SIZE: BlockSize = BlockSize::from_u64(MAX_BLOCK_SIZE.size() * 2).unwrap();
1987
1988 let handle = FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE);
1989 PersistentLayerWriter::<_, i32, i32>::new(Writer::new(&handle).await, 0, BLOCK_SIZE)
1990 .await
1991 .expect_err("Creating writer with overlarge block size.");
1992 }
1993
1994 #[fuchsia::test]
1995 async fn test_seek_bound_excluded() {
1996 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
1997 const ITEM_COUNT: i32 = 10000;
1998
1999 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
2000 {
2001 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
2002 Writer::new(&handle).await,
2003 ITEM_COUNT as usize * 18,
2004 BLOCK_SIZE,
2005 )
2006 .await
2007 .expect("writer new");
2008 for i in 0..ITEM_COUNT {
2009 writer.write(Item::new(i, i).as_item_ref()).await.expect("write failed");
2010 }
2011 writer.complete().await.expect("flush failed");
2012 }
2013 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
2014
2015 for i in 9982..ITEM_COUNT {
2016 let mut iterator = layer.seek(Bound::Excluded(&i)).await.expect("failed to seek");
2017 let i_plus_one = i + 1;
2018 if i_plus_one < ITEM_COUNT {
2019 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
2020
2021 assert_eq!((key, value), (&i_plus_one, &i_plus_one));
2022
2023 iterator.advance().await.expect("failed to advance");
2025 let i_plus_two = i + 2;
2026 if i_plus_two < ITEM_COUNT {
2027 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
2028 assert_eq!((key, value), (&i_plus_two, &i_plus_two));
2029 } else {
2030 assert!(iterator.get().is_none());
2031 }
2032 } else {
2033 assert!(iterator.get().is_none());
2034 }
2035 }
2036 }
2037
2038 fn generate_extents(
2042 object_id: u64,
2043 base_offset: u64,
2044 count: u64,
2045 ) -> (Vec<Item<ObjectKey, u64>>, u64) {
2046 let mut items = Vec::new();
2047 for i in 0..count {
2048 items.push(Item::new(
2049 ObjectKey::extent(
2050 object_id,
2051 AttributeId::TEST_ID,
2052 (base_offset + i) * MIN_BLOCK_SIZE..(base_offset + i + 1) * MIN_BLOCK_SIZE,
2053 ),
2054 object_id,
2055 ));
2056 }
2057 (items, object_id + 1)
2058 }
2059
2060 fn generate_objects(object_id_range: Range<u64>) -> (Vec<Item<ObjectKey, u64>>, u64) {
2064 let mut items = Vec::new();
2065 let end = object_id_range.end;
2066 for object_id in object_id_range {
2067 items.push(Item::new(ObjectKey::object(object_id), object_id));
2068 }
2069 (items, end)
2070 }
2071
2072 #[fuchsia::test]
2075 async fn test_block_seek_duplicate_leading_u64() {
2076 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
2078 const ITEMS_PER_PHASE: u64 = 50;
2079
2080 let mut to_find = Vec::new();
2081
2082 let handle = FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE);
2083 {
2084 let mut items = Vec::new();
2085 let mut object_id = u32::MAX as u64 + 1;
2087
2088 {
2091 let base_extent_offset = 0;
2092 let (mut generated, next_object_id) =
2093 generate_extents(object_id, base_extent_offset, ITEMS_PER_PHASE * 3);
2094 items.append(&mut generated);
2095 let count = ITEMS_PER_PHASE * 3;
2096 to_find.push(ObjectKey::extent(
2097 object_id,
2098 AttributeId::TEST_ID,
2099 base_extent_offset * MIN_BLOCK_SIZE..(base_extent_offset + 1) * MIN_BLOCK_SIZE,
2100 ));
2101 to_find.push(ObjectKey::extent(
2102 object_id,
2103 AttributeId::TEST_ID,
2104 (base_extent_offset + count / 2) * MIN_BLOCK_SIZE
2105 ..(base_extent_offset + count / 2 + 1) * MIN_BLOCK_SIZE,
2106 ));
2107 to_find.push(ObjectKey::extent(
2108 object_id,
2109 AttributeId::TEST_ID,
2110 (base_extent_offset + count - 1) * MIN_BLOCK_SIZE
2111 ..(base_extent_offset + count) * MIN_BLOCK_SIZE,
2112 ));
2113 object_id = next_object_id;
2114 }
2115
2116 {
2118 let (mut generated, next_object_id) =
2119 generate_objects(object_id..object_id + ITEMS_PER_PHASE * 3);
2120 items.append(&mut generated);
2121 object_id = next_object_id;
2122 }
2123
2124 {
2127 let base_extent_offset = 1000;
2128 let (mut generated, next_object_id) =
2129 generate_extents(object_id, base_extent_offset, ITEMS_PER_PHASE * 3);
2130 items.append(&mut generated);
2131 let count = ITEMS_PER_PHASE * 3;
2132 to_find.push(ObjectKey::extent(
2133 object_id,
2134 AttributeId::TEST_ID,
2135 base_extent_offset * MIN_BLOCK_SIZE..(base_extent_offset + 1) * MIN_BLOCK_SIZE,
2136 ));
2137 to_find.push(ObjectKey::extent(
2138 object_id,
2139 AttributeId::TEST_ID,
2140 (base_extent_offset + count / 2) * MIN_BLOCK_SIZE
2141 ..(base_extent_offset + count / 2 + 1) * MIN_BLOCK_SIZE,
2142 ));
2143 to_find.push(ObjectKey::extent(
2144 object_id,
2145 AttributeId::TEST_ID,
2146 (base_extent_offset + count - 1) * MIN_BLOCK_SIZE
2147 ..(base_extent_offset + count) * MIN_BLOCK_SIZE,
2148 ));
2149 object_id = next_object_id;
2150 }
2151
2152 {
2154 let (mut generated, next_object_id) =
2155 generate_objects(object_id..object_id + ITEMS_PER_PHASE * 3);
2156 items.append(&mut generated);
2157 object_id = next_object_id;
2158 }
2159
2160 {
2163 let base_extent_offset = 2000;
2164 let (mut generated, _) =
2165 generate_extents(object_id, base_extent_offset, ITEMS_PER_PHASE * 3);
2166 items.append(&mut generated);
2167 let count = ITEMS_PER_PHASE * 3;
2168 to_find.push(ObjectKey::extent(
2169 object_id,
2170 AttributeId::TEST_ID,
2171 base_extent_offset * MIN_BLOCK_SIZE..(base_extent_offset + 1) * MIN_BLOCK_SIZE,
2172 ));
2173 to_find.push(ObjectKey::extent(
2174 object_id,
2175 AttributeId::TEST_ID,
2176 (base_extent_offset + count / 2) * MIN_BLOCK_SIZE
2177 ..(base_extent_offset + count / 2 + 1) * MIN_BLOCK_SIZE,
2178 ));
2179 to_find.push(ObjectKey::extent(
2180 object_id,
2181 AttributeId::TEST_ID,
2182 (base_extent_offset + count - 1) * MIN_BLOCK_SIZE
2183 ..(base_extent_offset + count) * MIN_BLOCK_SIZE,
2184 ));
2185 }
2186
2187 items.sort_by(|a, b| a.key.cmp_upper_bound(&b.key));
2189
2190 let mut writer = PersistentLayerWriter::<_, ObjectKey, u64>::new(
2191 Writer::new(&handle).await,
2192 (3 * BLOCK_SIZE) as usize,
2193 BLOCK_SIZE,
2194 )
2195 .await
2196 .expect("writer new");
2197
2198 for item in items {
2199 writer.write(item.as_item_ref()).await.expect("write failed");
2200 }
2201
2202 writer.complete().await.expect("flush failed");
2203 }
2204
2205 let layer = PersistentLayer::<ObjectKey, u64>::open(handle).await.expect("new failed");
2206 for target in to_find {
2207 let iterator = layer.seek(Bound::Included(&target)).await.expect("failed to seek");
2208 let ItemRef { key, .. } = iterator.get().expect("missing item");
2209 assert_eq!(&target, key);
2210 }
2211 }
2212
2213 #[fuchsia::test]
2214 async fn test_two_seek_blocks() {
2215 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
2217 const ITEMS_PER_PHASE: u64 = 50;
2218 const ITEM_COUNT: u64 = ITEMS_PER_PHASE * ((BLOCK_SIZE.size() / 8) + 2);
2219
2220 let mut to_find = Vec::new();
2221
2222 let handle = FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE);
2223 {
2224 let mut writer = PersistentLayerWriter::<_, TestKey, u64>::new(
2225 Writer::new(&handle).await,
2226 ITEM_COUNT as usize * 18,
2227 BLOCK_SIZE,
2228 )
2229 .await
2230 .expect("writer new");
2231
2232 let initial_value = u32::MAX as u64 + 1;
2234 for i in 0..ITEM_COUNT {
2235 writer
2236 .write(
2237 Item::new(TestKey(initial_value + i..initial_value + i), initial_value)
2238 .as_item_ref(),
2239 )
2240 .await
2241 .expect("write failed");
2242 }
2243 to_find.push(TestKey(initial_value..initial_value));
2245 let middle = initial_value + ITEM_COUNT / 2;
2246 to_find.push(TestKey(middle..middle));
2247 let end = initial_value + ITEM_COUNT - 1;
2248 to_find.push(TestKey(end..end));
2249
2250 writer.complete().await.expect("flush failed");
2251 }
2252
2253 let layer = PersistentLayer::<TestKey, u64>::open(handle).await.expect("new failed");
2254 for target in to_find {
2255 let iterator = layer.seek(Bound::Included(&target)).await.expect("failed to seek");
2256 let ItemRef { key, .. } = iterator.get().expect("missing item");
2257 assert_eq!(&target, key);
2258 }
2259 }
2260
2261 #[fuchsia::test]
2264 async fn test_full_seek_block() {
2265 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
2266 const ITEMS_PER_PHASE: u64 = 50;
2267
2268 const SEEK_TABLE_ENTRIES: u64 = BLOCK_SIZE.size() / 8;
2270
2271 const START_ENTRIES_COUNT: u64 = ITEMS_PER_PHASE * SEEK_TABLE_ENTRIES;
2275
2276 for entries in START_ENTRIES_COUNT..START_ENTRIES_COUNT + (ITEMS_PER_PHASE * 2) {
2277 let handle =
2278 FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE);
2279 {
2280 let mut writer = PersistentLayerWriter::<_, TestKey, u64>::new(
2281 Writer::new(&handle).await,
2282 entries as usize,
2283 BLOCK_SIZE,
2284 )
2285 .await
2286 .expect("writer new");
2287
2288 let initial_value = u32::MAX as u64 + 1;
2290 for i in 0..entries {
2291 writer
2292 .write(
2293 Item::new(TestKey(initial_value + i..initial_value + i), initial_value)
2294 .as_item_ref(),
2295 )
2296 .await
2297 .expect("write failed");
2298 }
2299
2300 writer.complete().await.expect("flush failed");
2301 }
2302 PersistentLayer::<TestKey, u64>::open(handle).await.expect("new failed");
2303 }
2304 }
2305
2306 #[fuchsia::test]
2307 async fn test_ignore_bloom_filter_on_older_versions() {
2308 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
2309 const ITEM_COUNT: u64 = 250;
2310
2311 let old_version_handle =
2312 FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE);
2313 let current_version_handle =
2314 FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE);
2315 let initial_value = u32::MAX as u64 + 1;
2317 {
2318 let mut old_version_writer =
2319 PersistentLayerWriter::<_, TestKey, u64>::new_with_version(
2320 Writer::new(&old_version_handle).await,
2321 ITEM_COUNT as usize,
2322 BLOCK_SIZE,
2323 OLD_KEY_SERIALIZATION_VERSION,
2324 )
2325 .await
2326 .expect("writer new");
2327 let mut current_version_writer = PersistentLayerWriter::<_, TestKey, u64>::new(
2328 Writer::new(¤t_version_handle).await,
2329 ITEM_COUNT as usize,
2330 BLOCK_SIZE,
2331 )
2332 .await
2333 .expect("writer new");
2334
2335 for i in 0..ITEM_COUNT {
2336 old_version_writer
2337 .write(
2338 Item::new(TestKey(initial_value + i..initial_value + i), initial_value)
2339 .as_item_ref(),
2340 )
2341 .await
2342 .expect("write failed");
2343 current_version_writer
2344 .write(
2345 Item::new(TestKey(initial_value + i..initial_value + i), initial_value)
2346 .as_item_ref(),
2347 )
2348 .await
2349 .expect("write failed");
2350 }
2351
2352 old_version_writer.complete().await.expect("flush failed");
2353 current_version_writer.complete().await.expect("flush failed");
2354 }
2355
2356 let old_layer =
2357 PersistentLayer::<TestKey, u64>::open(old_version_handle).await.expect("open failed");
2358 let current_layer = PersistentLayer::<TestKey, u64>::open(current_version_handle)
2359 .await
2360 .expect("open failed");
2361 assert!(!old_layer.has_bloom_filter());
2362 assert!(current_layer.has_bloom_filter());
2363
2364 let iter = old_layer.seek(Bound::Included(&TestKey(0..0))).await.expect("seek failed");
2366 let item = iter.get().expect("missing item");
2367 assert_eq!(item.key.0.start, initial_value);
2368
2369 let iter = current_layer.seek(Bound::Included(&TestKey(0..0))).await.expect("seek failed");
2370 let item = iter.get().expect("missing item");
2371 assert_eq!(item.key.0.start, initial_value);
2372
2373 let iter = old_layer.seek(Bound::Unbounded).await.expect("seek failed");
2374 let item = iter.get().expect("missing item");
2375 assert_eq!(item.key.0.start, initial_value);
2376
2377 let iter = current_layer.seek(Bound::Unbounded).await.expect("seek failed");
2378 let item = iter.get().expect("missing item");
2379 assert_eq!(item.key.0.start, initial_value);
2380
2381 let target_val = initial_value + ITEM_COUNT / 2;
2382 let iter = old_layer
2383 .seek(Bound::Included(&TestKey(target_val..target_val)))
2384 .await
2385 .expect("seek failed");
2386 let item = iter.get().expect("missing item");
2387 assert_eq!(item.key.0.start, target_val);
2388
2389 let iter = current_layer
2390 .seek(Bound::Included(&TestKey(target_val..target_val)))
2391 .await
2392 .expect("seek failed");
2393 let item = iter.get().expect("missing item");
2394 assert_eq!(item.key.0.start, target_val);
2395 }
2396
2397 #[fuchsia::test]
2398 async fn test_allocator_key_older_version_seek() {
2399 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
2400 const ITEM_COUNT: u64 = 100;
2401
2402 let old_version_handle =
2403 FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE);
2404 let current_version_handle =
2405 FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE);
2406 let step = MIN_BLOCK_SIZE.get();
2407 {
2408 let mut old_version_writer =
2409 PersistentLayerWriter::<_, AllocatorKey, i64>::new_with_version(
2410 Writer::new(&old_version_handle).await,
2411 ITEM_COUNT as usize,
2412 BLOCK_SIZE,
2413 OLD_KEY_SERIALIZATION_VERSION,
2414 )
2415 .await
2416 .expect("writer new");
2417 let mut current_version_writer = PersistentLayerWriter::<_, AllocatorKey, i64>::new(
2418 Writer::new(¤t_version_handle).await,
2419 ITEM_COUNT as usize,
2420 BLOCK_SIZE,
2421 )
2422 .await
2423 .expect("writer new");
2424
2425 for i in 0..ITEM_COUNT {
2426 let key = AllocatorKey { device_range: Extent(i * step..(i + 1) * step) };
2427 old_version_writer
2428 .write(Item::new(key.clone(), i as i64).as_item_ref())
2429 .await
2430 .expect("write failed");
2431 current_version_writer
2432 .write(Item::new(key, i as i64).as_item_ref())
2433 .await
2434 .expect("write failed");
2435 }
2436
2437 old_version_writer.complete().await.expect("flush failed");
2438 current_version_writer.complete().await.expect("flush failed");
2439 }
2440
2441 let old_layer = PersistentLayer::<AllocatorKey, i64>::open(old_version_handle)
2442 .await
2443 .expect("open failed");
2444 let current_layer = PersistentLayer::<AllocatorKey, i64>::open(current_version_handle)
2445 .await
2446 .expect("open failed");
2447
2448 let target_idx = ITEM_COUNT / 2;
2449 let target_key =
2450 AllocatorKey { device_range: Extent(target_idx * step..(target_idx + 1) * step) };
2451
2452 let iter = old_layer.seek(Bound::Included(&target_key)).await.expect("seek failed");
2453 let item = iter.get().expect("missing item");
2454 assert_eq!(item.key, &target_key);
2455
2456 let iter = current_layer.seek(Bound::Included(&target_key)).await.expect("seek failed");
2457 let item = iter.get().expect("missing item");
2458 assert_eq!(item.key, &target_key);
2459 }
2460
2461 #[fuchsia::test]
2462 async fn test_small_layer_has_bloom_filter() {
2463 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_8KIB;
2464 const ITEM_COUNT: i32 = 10;
2465
2466 let handle = FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE);
2467 {
2468 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
2469 Writer::new(&handle).await,
2470 ITEM_COUNT as usize,
2471 BLOCK_SIZE,
2472 )
2473 .await
2474 .expect("writer new");
2475 for i in 0..ITEM_COUNT {
2476 writer.write(Item::new(i * 2, i * 2).as_item_ref()).await.expect("write failed");
2477 }
2478 writer.complete().await.expect("flush failed");
2479 }
2480 let layer =
2481 PersistentLayer::<i32, i32>::open_async(Arc::new(handle)).await.expect("new failed");
2482 assert_eq!(layer.data.data_size, BLOCK_SIZE.get());
2483 assert!(layer.has_bloom_filter());
2484 let mut missing_count = 0;
2485 for i in 0..ITEM_COUNT {
2486 assert_eq!(
2487 layer.key_exists(&(i * 2)).await.expect("key_exists failed"),
2488 Existence::MaybeExists
2489 );
2490 if layer.key_exists(&(i * 2 + 1)).await.expect("key_exists failed")
2491 == Existence::Missing
2492 {
2493 missing_count += 1;
2494 }
2495 }
2496 assert!(missing_count > ITEM_COUNT / 2);
2497 }
2498
2499 #[fuchsia::test]
2500 async fn test_key_exists_with_bloom_filter() {
2501 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
2502 const ITEM_COUNT: i32 = 10000;
2503
2504 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
2505 {
2506 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
2507 Writer::new(&handle).await,
2508 ITEM_COUNT as usize,
2509 BLOCK_SIZE,
2510 )
2511 .await
2512 .expect("writer new");
2513 for i in 0..ITEM_COUNT {
2514 writer.write(Item::new(i * 2, i * 2).as_item_ref()).await.expect("write failed");
2515 }
2516 writer.complete().await.expect("flush failed");
2517 }
2518 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
2519 assert!(layer.has_bloom_filter());
2520
2521 for i in 0..ITEM_COUNT {
2522 assert_eq!(
2524 layer.key_exists(&(i * 2)).await.expect("key_exists failed"),
2525 Existence::MaybeExists
2526 );
2527 }
2528
2529 let mut missing_count = 0;
2532 for i in 0..ITEM_COUNT {
2533 let result = layer.key_exists(&(i * 2 + 1)).await.expect("key_exists failed");
2534 assert_ne!(result, Existence::Exists);
2535 if result == Existence::Missing {
2536 missing_count += 1;
2537 }
2538 }
2539 assert!(missing_count > ITEM_COUNT / 2);
2541 }
2542
2543 #[fuchsia::test]
2544 async fn test_load_large_bloom_filter_multi_chunk() {
2545 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
2546 const ESTIMATED_ITEMS: usize = 600_000;
2548 const WRITTEN_ITEMS: i32 = 2000;
2549
2550 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
2551 {
2552 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
2553 Writer::new(&handle).await,
2554 ESTIMATED_ITEMS,
2555 BLOCK_SIZE,
2556 )
2557 .await
2558 .expect("writer new");
2559 for i in 0..WRITTEN_ITEMS {
2560 writer.write(Item::new(i * 2, i * 2).as_item_ref()).await.expect("write failed");
2561 }
2562 writer.complete().await.expect("flush failed");
2563 }
2564 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("open failed");
2565 assert!(layer.has_bloom_filter());
2566
2567 for i in 0..WRITTEN_ITEMS {
2568 assert_eq!(layer.maybe_contains_key(&(i * 2)), MaybeContainsKey::Maybe);
2569 }
2570 let mut false_count = 0;
2571 for i in 0..WRITTEN_ITEMS {
2572 if layer.maybe_contains_key(&(i * 2 + 1)) == MaybeContainsKey::False {
2573 false_count += 1;
2574 }
2575 }
2576 assert!(false_count > WRITTEN_ITEMS / 2);
2577 }
2578
2579 #[fuchsia::test]
2580 async fn test_clear_cached_data() {
2581 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
2582 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
2583 {
2584 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
2585 Writer::new(&handle).await,
2586 100,
2587 BLOCK_SIZE,
2588 )
2589 .await
2590 .expect("writer new");
2591 writer.write(Item::new(1, 1).as_item_ref()).await.expect("write failed");
2592 writer.complete().await.expect("flush failed");
2593 }
2594 let layer =
2595 PersistentLayer::<i32, i32>::open_async(Arc::new(handle)).await.expect("open failed");
2596 let iter = layer.seek(Bound::Unbounded).await.expect("seek failed");
2597 assert_eq!(iter.get().map(|i| (*i.key, *i.value)), Some((1, 1)));
2598 drop(iter);
2599
2600 assert!(layer.object_handle.try_read(BLOCK_SIZE.get() as usize).is_some());
2601
2602 layer.clear_cached_data();
2603
2604 assert!(layer.object_handle.try_read(BLOCK_SIZE.get() as usize).is_none());
2605 }
2606
2607 struct SliceLayerObject {
2608 handle: FakeObjectHandle,
2609 slice: Vec<u8>,
2610 io_error: AtomicBool,
2611 purged: AtomicBool,
2612 closed: AtomicBool,
2613 }
2614
2615 impl ObjectHandle for SliceLayerObject {
2616 fn object_id(&self) -> u64 {
2617 self.handle.object_id()
2618 }
2619 fn block_size(&self) -> BlockSize {
2620 self.handle.block_size()
2621 }
2622 fn allocate_buffer(&self, size: usize) -> BufferFuture<'_> {
2623 self.handle.allocate_buffer(size)
2624 }
2625 }
2626
2627 #[async_trait]
2628 impl ReadObjectHandle for SliceLayerObject {
2629 async fn read_aligned(
2630 &self,
2631 offset: u64,
2632 buf: MutableBufferRef<'_>,
2633 ) -> Result<usize, Error> {
2634 self.handle.read_aligned(offset, buf).await
2635 }
2636 fn get_size(&self) -> u64 {
2637 self.handle.get_size()
2638 }
2639 }
2640
2641 #[async_trait]
2642 impl LayerObject for SliceLayerObject {
2643 fn as_slice(&self) -> Option<&[u8]> {
2644 Some(&self.slice)
2645 }
2646 fn has_io_error(&self) -> bool {
2647 self.io_error.load(Ordering::SeqCst)
2648 }
2649 fn purge_cached_data(&self) {
2650 self.purged.store(true, Ordering::SeqCst);
2651 }
2652 async fn close(&self) {
2653 self.closed.store(true, Ordering::SeqCst);
2654 }
2655 }
2656
2657 #[fuchsia::test]
2658 async fn test_sync_persistent_layer() {
2659 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
2660 const ITEM_COUNT: i32 = 1000;
2661
2662 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
2663 {
2664 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
2665 Writer::new(&handle).await,
2666 ITEM_COUNT as usize,
2667 BLOCK_SIZE,
2668 )
2669 .await
2670 .expect("writer new");
2671 for i in 0..ITEM_COUNT {
2672 writer.write(Item::new(i * 2, i * 2).as_item_ref()).await.expect("write failed");
2673 }
2674 writer.complete().await.expect("flush failed");
2675 }
2676
2677 let size = handle.get_size() as usize;
2678 let mut buf = handle.allocate_buffer(size).await;
2679 handle.read_aligned(0, buf.as_mut()).await.expect("read failed");
2680 let slice = buf.subslice(..).to_vec();
2681 drop(buf);
2682 let slice_obj = Arc::new(SliceLayerObject {
2683 handle,
2684 slice: slice.clone(),
2685 io_error: AtomicBool::new(false),
2686 purged: AtomicBool::new(false),
2687 closed: AtomicBool::new(false),
2688 });
2689
2690 let layer: Arc<dyn Layer<i32, i32>> =
2691 SyncPersistentLayer::<i32, i32>::open(slice_obj.clone()).expect("open failed");
2692 assert!(layer.has_bloom_filter());
2693 assert_eq!(layer.len(), ITEM_COUNT as usize);
2694
2695 let mut iter = layer.seek(Bound::Unbounded).await.expect("seek failed");
2697 for i in 0..ITEM_COUNT {
2698 let item = iter.get().expect("expected item");
2699 assert_eq!(*item.key, i * 2);
2700 assert_eq!(*item.value, i * 2);
2701 let fut = iter.advance_dyn().expect("advance_dyn failed");
2702 assert!(fut.is_none(), "SyncPersistentLayer iterator must advance synchronously");
2703 }
2704 assert!(iter.get().is_none());
2705
2706 let iter = layer.seek(Bound::Included(&500)).await.expect("seek included failed");
2708 assert_eq!(*iter.get().expect("expected item").key, 500);
2709
2710 let iter = layer.seek(Bound::Excluded(&500)).await.expect("seek excluded failed");
2711 assert_eq!(*iter.get().expect("expected item").key, 502);
2712
2713 let iter = layer.seek(Bound::Included(&501)).await.expect("seek non-existent failed");
2714 assert_eq!(*iter.get().expect("expected item").key, 502);
2715
2716 assert!(!slice_obj.purged.load(Ordering::SeqCst));
2718 layer.purge_cached_data();
2719 assert!(slice_obj.purged.load(Ordering::SeqCst));
2720
2721 assert!(!slice_obj.closed.load(Ordering::SeqCst));
2723 layer.close().await;
2724 assert!(slice_obj.closed.load(Ordering::SeqCst));
2725
2726 let mut zeroed_slice = slice;
2728 let bs = BLOCK_SIZE.get() as usize;
2729 zeroed_slice[bs..bs * 2].fill(0);
2730 let zeroed_obj = Arc::new(SliceLayerObject {
2731 handle: FakeObjectHandle::new(Arc::new(FakeObject::new())),
2732 slice: zeroed_slice,
2733 io_error: AtomicBool::new(false),
2734 purged: AtomicBool::new(false),
2735 closed: AtomicBool::new(false),
2736 });
2737 let mut wbuf = zeroed_obj.handle.allocate_buffer(zeroed_obj.slice.len()).await;
2740 wbuf.as_mut_ptr_slice().copy_from_slice(&zeroed_obj.slice);
2741 zeroed_obj.handle.write_or_append(Some(0), wbuf.as_ref()).await.unwrap();
2742 drop(wbuf);
2743 let zeroed_layer =
2744 PersistentLayer::<i32, i32>::open_layer(zeroed_obj.clone()).await.expect("open failed");
2745
2746 let err = zeroed_layer.seek(Bound::Unbounded).await.err().expect("seek should fail");
2749 assert!(FxfsError::Inconsistent.matches(&err), "expected Inconsistent, got {err:?}");
2750
2751 zeroed_obj.io_error.store(true, Ordering::SeqCst);
2754 let err = zeroed_layer.seek(Bound::Unbounded).await.err().expect("seek should fail");
2755 assert_eq!(
2756 err.root_cause().downcast_ref::<zx_status::Status>(),
2757 Some(&zx_status::Status::IO)
2758 );
2759 }
2760
2761 #[fuchsia::test]
2762 async fn test_open_from_slice() {
2763 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_512B;
2764 const ITEM_COUNT: i32 = 500;
2765
2766 let non_slice_handle: Arc<dyn LayerObject> =
2768 Arc::new(FakeObjectHandle::new(Arc::new(FakeObject::new())));
2769 let err = LayerData::<i32>::open_from_slice(&non_slice_handle)
2770 .err()
2771 .expect("open_from_slice should fail without slice");
2772 assert!(FxfsError::InvalidArgs.matches(&err));
2773
2774 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
2777 {
2778 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
2779 Writer::new(&handle).await,
2780 ITEM_COUNT as usize,
2781 BLOCK_SIZE,
2782 )
2783 .await
2784 .expect("writer new");
2785 for i in 0..ITEM_COUNT {
2786 writer.write(Item::new(i * 2, i * 2).as_item_ref()).await.expect("write failed");
2787 }
2788 writer.complete().await.expect("flush failed");
2789 }
2790 let size = handle.get_size() as usize;
2791 let mut buf = handle.allocate_buffer(size).await;
2792 handle.read_aligned(0, buf.as_mut()).await.expect("read failed");
2793 let valid_slice = buf.subslice(..).to_vec();
2794 drop(buf);
2795
2796 let make_slice_obj = |slice: Vec<u8>, io_error: bool| -> Arc<dyn LayerObject> {
2797 Arc::new(SliceLayerObject {
2798 handle: FakeObjectHandle::new(Arc::new(FakeObject::new())),
2799 slice,
2800 io_error: AtomicBool::new(io_error),
2801 purged: AtomicBool::new(false),
2802 closed: AtomicBool::new(false),
2803 })
2804 };
2805
2806 let async_handle: Arc<dyn LayerObject> = Arc::new(handle);
2807 let expected_data = LayerData::<i32>::open(&async_handle).await.expect("open failed");
2808 let slice_data =
2809 LayerData::<i32>::open_from_slice(&make_slice_obj(valid_slice.clone(), false))
2810 .expect("open_from_slice failed");
2811 assert_eq!(slice_data.version, expected_data.version);
2812 assert_eq!(slice_data.block_size, expected_data.block_size);
2813 assert_eq!(slice_data.data_size, expected_data.data_size);
2814 assert_eq!(slice_data.seek_table, expected_data.seek_table);
2815 assert_eq!(slice_data.num_items, expected_data.num_items);
2816 assert!(slice_data.bloom_filter.is_some());
2817 for k in [0, 1, 250, 251, 998, 999] {
2818 assert_eq!(
2819 slice_data.bloom_filter.as_ref().unwrap().maybe_contains(&k),
2820 expected_data.bloom_filter.as_ref().unwrap().maybe_contains(&k)
2821 );
2822 }
2823
2824 let err = LayerData::<i32>::open_from_slice(&make_slice_obj(valid_slice.clone(), true))
2826 .err()
2827 .expect("open_from_slice should fail on io_error");
2828 assert_eq!(
2829 err.root_cause().downcast_ref::<zx_status::Status>(),
2830 Some(&zx_status::Status::IO)
2831 );
2832
2833 let empty_handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
2835 {
2836 let writer = PersistentLayerWriter::<_, i32, i32>::new(
2837 Writer::new(&empty_handle).await,
2838 0,
2839 BLOCK_SIZE,
2840 )
2841 .await
2842 .expect("writer new");
2843 writer.complete().await.expect("flush failed");
2844 }
2845 let empty_size = empty_handle.get_size() as usize;
2846 let mut buf = empty_handle.allocate_buffer(empty_size).await;
2847 empty_handle.read_aligned(0, buf.as_mut()).await.expect("read failed");
2848 let empty_slice = buf.subslice(..).to_vec();
2849 drop(buf);
2850 let empty_data = LayerData::<i32>::open_from_slice(&make_slice_obj(empty_slice, false))
2851 .expect("open_from_slice on empty layer failed");
2852 assert_eq!(empty_data.num_items, 0);
2853 assert!(empty_data.seek_table.is_empty());
2854 assert!(empty_data.bloom_filter.is_none());
2855
2856 let bs = BLOCK_SIZE.get() as usize;
2859
2860 let truncated = vec![0u8; bs / 2];
2862
2863 let mut bad_magic = valid_slice.clone();
2865 bad_magic[4..12].fill(0);
2866
2867 let mut bad_layer_info = valid_slice.clone();
2869 let len = bad_layer_info.len();
2870 bad_layer_info[len - 8..len].copy_from_slice(&u64::MAX.to_le_bytes());
2871
2872 let mut bad_seek_table = valid_slice.clone();
2874 let num_data_blocks = (slice_data.data_size / BLOCK_SIZE) as usize;
2875 assert!(num_data_blocks >= 2);
2876 let bf_blocks = BLOCK_SIZE
2877 .align_up_to_blocks(slice_data.bloom_filter_stats.as_ref().unwrap().size as u64)
2878 as usize;
2879 let seek_offset = (NUM_HEADER_BLOCKS as usize + num_data_blocks + bf_blocks) * bs;
2880 bad_seek_table[seek_offset..seek_offset + 8].copy_from_slice(&100u64.to_le_bytes());
2881 bad_seek_table[seek_offset + 8..seek_offset + 16].copy_from_slice(&50u64.to_le_bytes());
2882
2883 for corrupted in [truncated, bad_magic, bad_layer_info, bad_seek_table] {
2884 let err = LayerData::<i32>::open_from_slice(&make_slice_obj(corrupted.clone(), false))
2885 .err()
2886 .expect("expected corruption error");
2887 assert!(FxfsError::Inconsistent.matches(&err), "expected Inconsistent, got {err:?}");
2888
2889 let err = LayerData::<i32>::open_from_slice(&make_slice_obj(corrupted, true))
2890 .err()
2891 .expect("expected I/O error");
2892 assert_eq!(
2893 err.root_cause().downcast_ref::<zx_status::Status>(),
2894 Some(&zx_status::Status::IO)
2895 );
2896 }
2897 }
2898
2899 #[fuchsia::test]
2900 async fn test_layer_block_size_gt_4k_falls_back_to_async_persistent_layer() {
2901 const BLOCK_SIZE: BlockSize = BlockSize::SIZE_8KIB;
2902 let handle = FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE);
2903 {
2904 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
2905 Writer::new(&handle).await,
2906 10,
2907 BLOCK_SIZE,
2908 )
2909 .await
2910 .expect("writer new");
2911 for i in 0..10 {
2912 writer.write(Item::new(i, i).as_item_ref()).await.expect("write failed");
2913 }
2914 writer.complete().await.expect("flush failed");
2915 }
2916
2917 let size = handle.get_size() as usize;
2918 let mut buf = handle.allocate_buffer(size).await;
2919 handle.read_aligned(0, buf.as_mut()).await.expect("read failed");
2920 let slice = buf.subslice(..).to_vec();
2921 drop(buf);
2922 let slice_obj = Arc::new(SliceLayerObject {
2923 handle,
2924 slice,
2925 io_error: AtomicBool::new(false),
2926 purged: AtomicBool::new(false),
2927 closed: AtomicBool::new(false),
2928 });
2929
2930 assert!(SyncPersistentLayer::<i32, i32>::open(slice_obj.clone()).is_err());
2932
2933 let layer = PersistentLayer::<i32, i32>::open_layer(slice_obj).await.expect("open_layer");
2935 let mut iter = layer.seek(Bound::Unbounded).await.expect("seek");
2936 for i in 0..10 {
2937 assert_eq!(*iter.get().expect("item").key, i);
2938 iter.advance().await.expect("advance");
2939 }
2940 assert!(iter.get().is_none());
2941 }
2942}