1use crate::drop_event::DropEvent;
61use crate::errors::FxfsError;
62use crate::filesystem::MAX_BLOCK_SIZE;
63use crate::log::*;
64use crate::lsm_tree::bloom_filter::{BloomFilterReader, BloomFilterStats, BloomFilterWriter};
65use crate::lsm_tree::types::{
66 BoxedLayerIterator, Existence, FuzzyHash, Item, ItemRef, Key, Layer, LayerIterator, LayerValue,
67 LayerWriter,
68};
69use crate::object_handle::{ObjectHandle, ReadObjectHandle, WriteBytes};
70use crate::object_store::caching_object_handle::{CHUNK_SIZE, CachedChunk, CachingObjectHandle};
71use crate::round::{round_down, round_up};
72use crate::serialized_types::{
73 LATEST_VERSION, REMOVE_ITEM_SEQUENCE_VERSION, Version, Versioned, VersionedLatest,
74};
75use anyhow::{Context, Error, anyhow, bail, ensure};
76use async_trait::async_trait;
77use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
78use fprint::TypeFingerprint;
79use fuchsia_sync::Mutex;
80use serde::{Deserialize, Serialize};
81use static_assertions::const_assert;
82use std::cmp::Ordering;
83use std::io::{Read, Write as _};
84use std::marker::PhantomData;
85use std::ops::Bound;
86use std::sync::Arc;
87
88const PERSISTENT_LAYER_MAGIC: &[u8; 8] = b"FxfsLayr";
89
90pub type LayerHeader = LayerHeaderV39;
92
93#[derive(Debug, Serialize, Deserialize, TypeFingerprint, Versioned)]
94pub struct LayerHeaderV39 {
95 magic: [u8; 8],
97 block_size: u64,
103}
104
105pub type LayerInfo = LayerInfoV39;
107
108#[derive(Debug, Serialize, Deserialize, TypeFingerprint, Versioned)]
109pub struct LayerInfoV39 {
110 num_items: usize,
113 num_data_blocks: u64,
115 bloom_filter_size_bytes: usize,
117 bloom_filter_seed: u64,
119 bloom_filter_num_hashes: usize,
121}
122
123pub struct PersistentLayer<K, V> {
125 object_handle: Arc<dyn ReadObjectHandle>,
132 caching_object_handle: CachingObjectHandle<Arc<dyn ReadObjectHandle>>,
133 version: Version,
134 block_size: u64,
135 data_size: u64,
136 seek_table: Vec<u64>,
137 num_items: usize,
138 bloom_filter: Option<BloomFilterReader<K>>,
139 bloom_filter_stats: Option<BloomFilterStats>,
140 close_event: Mutex<Option<Arc<DropEvent>>>,
141 _value_type: PhantomData<V>,
142}
143
144#[derive(Debug)]
145struct BufferCursor {
146 chunk: Option<CachedChunk>,
147 pos: usize,
148}
149
150impl std::io::Read for BufferCursor {
151 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
152 let chunk = if let Some(chunk) = &self.chunk {
153 chunk
154 } else {
155 return Ok(0);
156 };
157 let to_read = std::cmp::min(buf.len(), chunk.len().saturating_sub(self.pos));
158 if to_read > 0 {
159 buf[..to_read].copy_from_slice(&chunk[self.pos..self.pos + to_read]);
160 self.pos += to_read;
161 }
162 Ok(to_read)
163 }
164}
165
166const MIN_BLOCK_SIZE: u64 = 512;
167
168const MINIMUM_DATA_BLOCKS_FOR_BLOOM_FILTER: usize = 4;
170
171const NUM_HEADER_BLOCKS: u64 = 1;
173
174const MINIMUM_LAYER_FILE_BLOCKS: u64 = 2;
177
178const MAX_BLOOM_FILTER_SIZE: usize = 64 * 1024 * 1024;
181const MAX_SEEK_TABLE_SIZE: usize = 64 * 1024 * 1024;
182
183const PER_DATA_BLOCK_HEADER_SIZE: usize = 2;
185const PER_DATA_BLOCK_SEEK_ENTRY_SIZE: usize = 2;
186
187struct KeyOnlyIterator<'iter, K: Key, V: LayerValue> {
189 buffer: BufferCursor,
191
192 layer: &'iter PersistentLayer<K, V>,
193
194 pos: u64,
196
197 item_index: u16,
199
200 item_count: u16,
202
203 key: Option<K>,
205
206 value_deserialized: bool,
209}
210
211impl<K: Key, V: LayerValue> KeyOnlyIterator<'_, K, V> {
212 fn new<'iter>(layer: &'iter PersistentLayer<K, V>, pos: u64) -> KeyOnlyIterator<'iter, K, V> {
213 assert!(pos % layer.block_size == 0);
214 KeyOnlyIterator {
215 layer,
216 buffer: BufferCursor { chunk: None, pos: pos as usize % CHUNK_SIZE },
217 pos,
218 item_index: 0,
219 item_count: 0,
220 key: None,
221 value_deserialized: false,
222 }
223 }
224
225 fn seek_to_block_item(&mut self, index: u16) -> Result<(), Error> {
229 ensure!(index < self.item_count, FxfsError::OutOfRange);
230 if index == self.item_index && self.value_deserialized {
231 return Ok(());
234 }
235 let offset_in_block = if index == 0 {
236 PER_DATA_BLOCK_HEADER_SIZE
239 } else {
240 let old_buffer_pos = self.buffer.pos;
241 self.buffer.pos = round_up(self.buffer.pos, self.layer.block_size as usize).unwrap()
242 - (PER_DATA_BLOCK_SEEK_ENTRY_SIZE * (usize::from(self.item_count - index)));
243 let res = self.buffer.read_u16::<LittleEndian>();
244 self.buffer.pos = old_buffer_pos;
245 let offset_in_block = res.context("Failed to read offset")? as usize;
246 if offset_in_block >= self.layer.block_size as usize
247 || offset_in_block <= PER_DATA_BLOCK_HEADER_SIZE
248 {
249 return Err(anyhow!(FxfsError::Inconsistent))
250 .context(format!("Offset {} is out of valid range.", offset_in_block));
251 }
252 offset_in_block
253 };
254 self.item_index = index;
255 self.buffer.pos =
256 round_down(self.buffer.pos, self.layer.block_size as usize) + offset_in_block;
257 Ok(())
258 }
259
260 async fn advance(&mut self) -> Result<(), Error> {
261 if self.item_index >= self.item_count {
262 if self.pos >= self.layer.data_offset() + self.layer.data_size {
263 self.key = None;
264 return Ok(());
265 }
266 if self.buffer.chunk.is_none() || self.pos as usize % CHUNK_SIZE == 0 {
267 self.buffer.chunk = Some(
268 self.layer
269 .caching_object_handle
270 .read(self.pos as usize)
271 .await
272 .context("Reading during advance")?,
273 );
274 }
275 self.buffer.pos = self.pos as usize % CHUNK_SIZE;
276 self.item_count = self.buffer.read_u16::<LittleEndian>()?;
277 if self.item_count == 0 {
278 bail!(
279 "Read block with zero item count (object: {}, offset: {})",
280 self.layer.object_handle.object_id(),
281 self.pos
282 );
283 }
284 debug!(
285 pos = self.pos,
286 buf:? = self.buffer,
287 object_size = self.layer.data_offset() + self.layer.data_size,
288 oid = self.layer.object_handle.object_id();
289 ""
290 );
291 self.pos += self.layer.block_size;
292 self.item_index = 0;
293 self.value_deserialized = true;
294 }
295 self.seek_to_block_item(self.item_index)?;
296 self.key = Some(
297 K::deserialize_from_version(self.buffer.by_ref(), self.layer.version)
298 .context("Corrupt layer (key)")?,
299 );
300 self.item_index += 1;
301 self.value_deserialized = false;
302 Ok(())
303 }
304
305 fn get(&self) -> Option<&K> {
306 self.key.as_ref()
307 }
308}
309
310struct Iterator<'iter, K: Key, V: LayerValue> {
311 inner: KeyOnlyIterator<'iter, K, V>,
312 item: Option<Item<K, V>>,
314}
315
316impl<'iter, K: Key, V: LayerValue> Iterator<'iter, K, V> {
317 fn new(mut seek_iterator: KeyOnlyIterator<'iter, K, V>) -> Result<Self, Error> {
318 let key = std::mem::take(&mut seek_iterator.key);
319 let item = if let Some(key) = key {
320 seek_iterator.value_deserialized = true;
321 let value = V::deserialize_from_version(
322 seek_iterator.buffer.by_ref(),
323 seek_iterator.layer.version,
324 )
325 .context("Corrupt layer (value)")?;
326 if seek_iterator.layer.version.major < REMOVE_ITEM_SEQUENCE_VERSION {
327 seek_iterator.buffer.read_u64::<LittleEndian>().context("Corrupt layer (seq)")?;
328 }
329 Some(Item { key, value })
330 } else {
331 None
332 };
333 Ok(Self { inner: seek_iterator, item })
334 }
335}
336
337#[async_trait]
338impl<'iter, K: Key, V: LayerValue> LayerIterator<K, V> for Iterator<'iter, K, V> {
339 async fn advance(&mut self) -> Result<(), Error> {
340 self.inner.advance().await?;
341 let key = std::mem::take(&mut self.inner.key);
342 self.item = if let Some(key) = key {
343 self.inner.value_deserialized = true;
344 let value =
345 V::deserialize_from_version(self.inner.buffer.by_ref(), self.inner.layer.version)
346 .context("Corrupt layer (value)")?;
347 if self.inner.layer.version.major < REMOVE_ITEM_SEQUENCE_VERSION {
348 self.inner.buffer.read_u64::<LittleEndian>().context("Corrupt layer (seq)")?;
349 }
350 Some(Item { key, value })
351 } else {
352 None
353 };
354 Ok(())
355 }
356
357 fn get(&self) -> Option<ItemRef<'_, K, V>> {
358 self.item.as_ref().map(<&Item<K, V>>::into)
359 }
360}
361
362fn seek_table_size(num_data_blocks: u64) -> usize {
364 let seek_table_entries = num_data_blocks.saturating_sub(1) as usize;
366 if seek_table_entries == 0 {
367 return 0;
368 }
369 let entry_size = std::mem::size_of::<u64>();
370 seek_table_entries * entry_size
371}
372
373async fn load_seek_table(
374 object_handle: &(impl ReadObjectHandle + 'static),
375 seek_table_offset: u64,
376 num_data_blocks: u64,
377) -> Result<Vec<u64>, Error> {
378 let seek_table_size = seek_table_size(num_data_blocks);
379 if seek_table_size == 0 {
380 return Ok(vec![]);
381 }
382 if seek_table_size > MAX_SEEK_TABLE_SIZE {
383 return Err(anyhow!(FxfsError::NotSupported)).context("Seek table too large");
384 }
385 let mut buffer = object_handle.allocate_buffer(seek_table_size).await;
386 let bytes_read = object_handle
387 .read(seek_table_offset, buffer.as_mut())
388 .await
389 .context("Reading seek table blocks")?;
390 ensure!(bytes_read == seek_table_size, "Short read");
391
392 let mut seek_table = Vec::with_capacity(num_data_blocks as usize);
393 seek_table.push(0);
395 let mut prev = 0;
396 for chunk in buffer.subslice(0..seek_table_size).as_ptr_slice().iter_as::<[u8; 8]>() {
397 let next = u64::from_le_bytes(chunk.read());
398 if prev > next {
401 return Err(anyhow!(FxfsError::Inconsistent))
402 .context(format!("Seek table entry out of order, {:?} > {:?}", prev, next));
403 }
404 prev = next;
405 seek_table.push(next);
406 }
407 Ok(seek_table)
408}
409
410async fn load_bloom_filter<K: FuzzyHash>(
411 handle: &(impl ReadObjectHandle + 'static),
412 bloom_filter_offset: u64,
413 layer_info: &LayerInfo,
414) -> Result<Option<BloomFilterReader<K>>, Error> {
415 if layer_info.bloom_filter_size_bytes == 0 {
416 return Ok(None);
417 }
418 if layer_info.bloom_filter_size_bytes > MAX_BLOOM_FILTER_SIZE {
419 return Err(anyhow!(FxfsError::NotSupported)).context("Bloom filter too large");
420 }
421 let mut buffer = handle.allocate_buffer(layer_info.bloom_filter_size_bytes).await;
422 handle.read(bloom_filter_offset, buffer.as_mut()).await.context("Failed to read")?;
423 Ok(Some(BloomFilterReader::read(
424 buffer.subslice(0..layer_info.bloom_filter_size_bytes).as_ptr_slice(),
425 layer_info.bloom_filter_seed,
426 layer_info.bloom_filter_num_hashes,
427 )?))
428}
429
430impl<K: Key, V: LayerValue> PersistentLayer<K, V> {
431 pub async fn open(handle: impl ReadObjectHandle + 'static) -> Result<Arc<Self>, Error> {
432 let bs = handle.block_size();
433 let mut buffer = handle.allocate_buffer(bs as usize).await;
434 handle.read(0, buffer.as_mut()).await.context("Failed to read first block")?;
435 let mut reader = buffer.as_ptr_slice();
436 let version = Version::deserialize_from(&mut reader)?;
437
438 ensure!(version <= LATEST_VERSION, FxfsError::InvalidVersion);
439 let header = LayerHeader::deserialize_from_version(&mut reader, version)
440 .context("Failed to deserialize header")?;
441 if &header.magic != PERSISTENT_LAYER_MAGIC {
442 return Err(anyhow!(FxfsError::Inconsistent).context("Invalid layer file magic"));
443 }
444 if header.block_size == 0 || !header.block_size.is_power_of_two() {
445 return Err(anyhow!(FxfsError::Inconsistent))
446 .context(format!("Invalid block size {}", header.block_size));
447 }
448 ensure!(header.block_size > 0, FxfsError::Inconsistent);
449 ensure!(header.block_size <= MAX_BLOCK_SIZE, FxfsError::NotSupported);
450 let physical_block_size = handle.block_size();
451 if header.block_size % physical_block_size != 0 {
452 return Err(anyhow!(FxfsError::Inconsistent)).context(format!(
453 "{} not a multiple of physical block size {}",
454 header.block_size, physical_block_size
455 ));
456 }
457
458 let bs = header.block_size as usize;
459 if handle.get_size() < MINIMUM_LAYER_FILE_BLOCKS * bs as u64 {
460 return Err(anyhow!(FxfsError::Inconsistent).context("Layer file too short"));
461 }
462
463 let layer_info = {
464 let last_block_offset = handle
465 .get_size()
466 .checked_sub(header.block_size)
467 .ok_or(FxfsError::Inconsistent)
468 .context("Layer file unexpectedly short")?;
469 handle
470 .read(last_block_offset, buffer.subslice_mut(0..header.block_size as usize))
471 .await
472 .context("Failed to read layer info")?;
473 let layer_info_len =
474 u64::from_le_bytes(buffer.subslice(bs - 8..bs).as_ptr_slice().read().unwrap());
475 let layer_info_offset = bs
476 .checked_sub(std::mem::size_of::<u64>() + layer_info_len as usize)
477 .ok_or(FxfsError::Inconsistent)
478 .context("Invalid layer info length")?;
479 let mut reader = buffer.subslice(layer_info_offset..).as_ptr_slice();
480 LayerInfo::deserialize_from_version(&mut reader, version)
481 .context("Failed to deserialize LayerInfo")?
482 };
483 std::mem::drop(buffer);
484 if layer_info.num_items == 0 && layer_info.num_data_blocks > 0 {
485 return Err(anyhow!(FxfsError::Inconsistent))
486 .context("Invalid num_items/num_data_blocks");
487 }
488 let total_blocks = handle.get_size() / header.block_size;
489 let bloom_filter_blocks =
490 round_up(layer_info.bloom_filter_size_bytes as u64, header.block_size)
491 .unwrap_or(layer_info.bloom_filter_size_bytes as u64)
492 / header.block_size;
493 if layer_info.num_data_blocks + bloom_filter_blocks
494 > total_blocks - MINIMUM_LAYER_FILE_BLOCKS
495 {
496 return Err(anyhow!(FxfsError::Inconsistent)).context("Invalid number of blocks");
497 }
498
499 let bloom_filter_offset =
500 header.block_size * (NUM_HEADER_BLOCKS + layer_info.num_data_blocks);
501 let bloom_filter = if version == LATEST_VERSION {
502 load_bloom_filter(&handle, bloom_filter_offset, &layer_info)
503 .await
504 .context("Failed to load bloom filter")?
505 } else {
506 None
510 };
511 let bloom_filter_stats = bloom_filter.as_ref().map(|b| b.stats());
512
513 let seek_offset = header.block_size
514 * (NUM_HEADER_BLOCKS + layer_info.num_data_blocks + bloom_filter_blocks);
515 let seek_table = load_seek_table(&handle, seek_offset, layer_info.num_data_blocks)
516 .await
517 .context("Failed to load seek table")?;
518
519 let object_handle = Arc::new(handle) as Arc<dyn ReadObjectHandle>;
520 let caching_object_handle = CachingObjectHandle::new(object_handle.clone());
521 Ok(Arc::new(PersistentLayer {
522 object_handle,
523 caching_object_handle,
524 version,
525 block_size: header.block_size,
526 data_size: layer_info.num_data_blocks * header.block_size,
527 seek_table,
528 num_items: layer_info.num_items,
529 bloom_filter,
530 bloom_filter_stats,
531 close_event: Mutex::new(Some(Arc::new(DropEvent::new()))),
532 _value_type: PhantomData::default(),
533 }))
534 }
535
536 pub fn has_bloom_filter(&self) -> bool {
541 self.bloom_filter.is_some()
542 }
543
544 fn data_offset(&self) -> u64 {
545 NUM_HEADER_BLOCKS * self.block_size
546 }
547}
548
549#[async_trait]
550impl<K: Key, V: LayerValue> Layer<K, V> for PersistentLayer<K, V> {
551 fn handle(&self) -> Option<&dyn ReadObjectHandle> {
552 Some(&self.object_handle)
553 }
554
555 fn purge_cached_data(&self) {
556 self.caching_object_handle.purge();
557 }
558
559 async fn seek<'a>(&'a self, bound: Bound<&K>) -> Result<BoxedLayerIterator<'a, K, V>, Error> {
560 let (key, excluded) = match bound {
561 Bound::Unbounded => {
562 let mut iterator = Iterator::new(KeyOnlyIterator::new(self, self.data_offset()))?;
563 iterator.advance().await.context("Unbounded seek advance")?;
564 return Ok(Box::new(iterator));
565 }
566 Bound::Included(k) => (k, false),
567 Bound::Excluded(k) => (k, true),
568 };
569 let first_data_block_index = self.data_offset() / self.block_size;
570
571 let (mut left_offset, mut right_offset) = {
572 let target = key.get_leading_u64();
577 let right_index = self.seek_table.as_slice().partition_point(|&x| x <= target) as u64;
579 let left_index = self.seek_table.as_slice()[..right_index as usize]
582 .partition_point(|&x| x < target)
583 .saturating_sub(1) as u64;
584
585 (
586 (left_index + first_data_block_index) * self.block_size,
587 (right_index + first_data_block_index) * self.block_size,
588 )
589 };
590 let mut left = KeyOnlyIterator::new(self, left_offset);
591 left.advance().await.context("Initial seek advance")?;
592 match left.get() {
593 None => return Ok(Box::new(Iterator::new(left)?)),
594 Some(left_key) => match left_key.cmp_upper_bound(key) {
595 Ordering::Greater => return Ok(Box::new(Iterator::new(left)?)),
596 Ordering::Equal => {
597 if excluded {
598 left.advance().await?;
599 }
600 return Ok(Box::new(Iterator::new(left)?));
601 }
602 Ordering::Less => {}
603 },
604 }
605 let mut right = None;
606 while right_offset - left_offset > self.block_size {
607 let mid_offset =
609 round_down(left_offset + (right_offset - left_offset) / 2, self.block_size);
610 let mut iterator = KeyOnlyIterator::new(self, mid_offset);
611 iterator.advance().await?;
612 let iter_key: &K = iterator.get().unwrap();
613 match iter_key.cmp_upper_bound(key) {
614 Ordering::Greater => {
615 right_offset = mid_offset;
616 right = Some(iterator);
617 }
618 Ordering::Equal => {
619 if excluded {
620 iterator.advance().await?;
621 }
622 return Ok(Box::new(Iterator::new(iterator)?));
623 }
624 Ordering::Less => {
625 left_offset = mid_offset;
626 left = iterator;
627 }
628 }
629 }
630
631 let mut left_index = 0;
633 let mut right_index = left.item_count;
634 while left_index < (right_index - 1) {
636 let mid_index = left_index + ((right_index - left_index) / 2);
637 left.seek_to_block_item(mid_index).context("Read index offset for binary search")?;
638 left.advance().await?;
639 match left.get().unwrap().cmp_upper_bound(key) {
640 Ordering::Greater => {
641 right_index = mid_index;
642 }
643 Ordering::Equal => {
644 if excluded {
645 left.advance().await?;
646 }
647 return Ok(Box::new(Iterator::new(left)?));
648 }
649 Ordering::Less => {
650 left_index = mid_index;
651 }
652 }
653 }
654 if right_index < left.item_count {
659 left.seek_to_block_item(right_index)
660 .context("Read index for offset of right pointer")?;
661 } else if let Some(right) = right {
662 return Ok(Box::new(Iterator::new(right)?));
663 } else {
664 }
670 left.advance().await?;
671 return Ok(Box::new(Iterator::new(left)?));
672 }
673
674 fn len(&self) -> usize {
675 self.num_items
676 }
677
678 fn maybe_contains_key(&self, key: &K) -> bool {
679 self.bloom_filter.as_ref().map_or(true, |f| f.maybe_contains(key))
680 }
681
682 async fn key_exists(&self, key: &K) -> Result<Existence, Error> {
683 match &self.bloom_filter {
684 Some(filter) => Ok(if filter.maybe_contains(key) {
685 Existence::MaybeExists
686 } else {
687 Existence::Missing
688 }),
689 None => {
690 let iter = self.seek(Bound::Included(key)).await?;
691 Ok(iter.get().map_or(Existence::Missing, |i| {
692 if i.key.cmp_upper_bound(key).is_eq() {
693 Existence::Exists
694 } else {
695 Existence::Missing
696 }
697 }))
698 }
699 }
700 }
701
702 fn lock(&self) -> Option<Arc<DropEvent>> {
703 self.close_event.lock().clone()
704 }
705
706 async fn close(&self) {
707 let listener = self.close_event.lock().take().expect("close already called").listen();
708 listener.await;
709 }
710
711 fn get_version(&self) -> Version {
712 return self.version;
713 }
714
715 fn record_inspect_data(self: Arc<Self>, node: &fuchsia_inspect::Node) {
716 node.record_uint("num_items", self.num_items as u64);
717 node.record_bool("persistent", true);
718 node.record_uint("size", self.object_handle.get_size());
719 if let Some(stats) = self.bloom_filter_stats.as_ref() {
720 node.record_child("bloom_filter", move |node| {
721 node.record_uint("size", stats.size as u64);
722 node.record_uint("num_hashes", stats.num_hashes as u64);
723 node.record_uint("fill_percentage", stats.fill_percentage as u64);
724 });
725 }
726 }
727}
728
729const_assert!(MAX_BLOCK_SIZE <= u16::MAX as u64 + 1);
731
732pub struct PersistentLayerWriter<W: WriteBytes, K: Key, V: LayerValue> {
735 writer: W,
736 block_size: u64,
737 buf: Vec<u8>,
738 buf_item_count: LayerWriterBufItemCount,
739 item_count: usize,
740 block_offsets: Vec<u16>,
741 block_keys: Vec<u64>,
742 bloom_filter: BloomFilterWriter<K>,
743 _value: PhantomData<V>,
744}
745
746impl<W: WriteBytes, K: Key, V: LayerValue> PersistentLayerWriter<W, K, V> {
747 pub async fn new(writer: W, num_items: usize, block_size: u64) -> Result<Self, Error> {
749 Self::new_with_version(writer, num_items, block_size, LATEST_VERSION).await
750 }
751
752 pub(crate) async fn new_with_version(
753 mut writer: W,
754 num_items: usize,
755 block_size: u64,
756 version: Version,
757 ) -> Result<Self, Error> {
758 ensure!(block_size <= MAX_BLOCK_SIZE, FxfsError::NotSupported);
759 ensure!(block_size >= MIN_BLOCK_SIZE, FxfsError::NotSupported);
760
761 let header = LayerHeader { magic: PERSISTENT_LAYER_MAGIC.clone(), block_size };
763 let mut buf = vec![0u8; block_size as usize];
764 {
765 let mut cursor = std::io::Cursor::new(&mut buf[..]);
766 version.serialize_into(&mut cursor)?;
767 header.serialize_into(&mut cursor)?;
768 }
769 writer.write_bytes(&buf[..]).await?;
770
771 let seed: u64 = rand::random();
772 Ok(Self {
773 writer,
774 block_size,
775 buf: Vec::new(),
776 buf_item_count: LayerWriterBufItemCount(0),
777 item_count: 0,
778 block_offsets: Vec::new(),
779 block_keys: Vec::new(),
780 bloom_filter: BloomFilterWriter::new(seed, num_items),
781 _value: PhantomData,
782 })
783 }
784
785 async fn write_block(&mut self, len: usize) -> Result<(), Error> {
790 if *self.buf_item_count == 0 {
791 return Ok(());
792 }
793 let seek_table_size = self.block_offsets.len() * PER_DATA_BLOCK_SEEK_ENTRY_SIZE;
794 assert!(PER_DATA_BLOCK_HEADER_SIZE + seek_table_size + len <= self.block_size as usize);
795 let mut cursor = std::io::Cursor::new(vec![0u8; self.block_size as usize]);
796 cursor.write_u16::<LittleEndian>(*self.buf_item_count)?;
797 cursor.write_all(self.buf.drain(..len).as_ref())?;
798 cursor.set_position(self.block_size - seek_table_size as u64);
799 for &offset in &self.block_offsets {
801 cursor.write_u16::<LittleEndian>(offset)?;
802 }
803 self.writer.write_bytes(cursor.get_ref()).await?;
804 debug!(item_count = *self.buf_item_count, byte_count = len; "wrote items");
805 *self.buf_item_count = 0;
806 self.block_offsets.clear();
807 Ok(())
808 }
809
810 async fn write_seek_table(&mut self) -> Result<usize, Error> {
815 if self.block_keys.len() == 0 {
816 return Ok(0);
817 }
818 let size = self.block_keys.len() * std::mem::size_of::<u64>();
819 self.buf.resize(size, 0);
820 let mut len = 0;
821 for key in &self.block_keys {
822 LittleEndian::write_u64(&mut self.buf[len..len + std::mem::size_of::<u64>()], *key);
823 len += std::mem::size_of::<u64>();
824 }
825 self.writer.write_bytes(&self.buf).await?;
826 Ok(size)
827 }
828
829 async fn write_info(
832 &mut self,
833 num_data_blocks: u64,
834 bloom_filter_size_bytes: usize,
835 seek_table_len: usize,
836 ) -> Result<(), Error> {
837 let block_size = self.writer.block_size() as usize;
838 let layer_info = LayerInfo {
839 num_items: self.item_count,
840 num_data_blocks,
841 bloom_filter_size_bytes,
842 bloom_filter_seed: self.bloom_filter.seed(),
843 bloom_filter_num_hashes: self.bloom_filter.num_hashes(),
844 };
845 let actual_len = {
846 let mut cursor = std::io::Cursor::new(&mut self.buf);
847 layer_info.serialize_into(&mut cursor)?;
848 let layer_info_len = cursor.position();
849 cursor.write_u64::<LittleEndian>(layer_info_len)?;
850 cursor.position() as usize
851 };
852
853 let avail_in_block = block_size - (seek_table_len % block_size);
856 let to_skip = if avail_in_block < actual_len {
857 block_size + avail_in_block - actual_len
858 } else {
859 avail_in_block - actual_len
860 } as u64;
861 self.writer.skip(to_skip).await?;
862 self.writer.write_bytes(&self.buf[..actual_len]).await?;
863 Ok(())
864 }
865
866 async fn write_bloom_filter(&mut self) -> Result<usize, Error> {
869 if self.data_blocks() < MINIMUM_DATA_BLOCKS_FOR_BLOOM_FILTER {
870 return Ok(0);
871 }
872 let size = round_up(self.bloom_filter.serialized_size(), self.block_size as usize).unwrap();
874 self.buf.resize(size, 0);
875 let mut cursor = std::io::Cursor::new(&mut self.buf);
876 self.bloom_filter.write(&mut cursor)?;
877 self.writer.write_bytes(&self.buf).await?;
878 Ok(self.bloom_filter.serialized_size())
879 }
880
881 #[cfg(test)]
884 pub(crate) fn bloom_filter(&mut self) -> &mut BloomFilterWriter<K> {
885 &mut self.bloom_filter
886 }
887
888 fn data_blocks(&self) -> usize {
889 if self.item_count == 0 { 0 } else { self.block_keys.len() + 1 }
890 }
891}
892
893impl<W: WriteBytes + Send, K: Key, V: LayerValue> LayerWriter<K, V>
894 for PersistentLayerWriter<W, K, V>
895{
896 async fn write(&mut self, item: ItemRef<'_, K, V>) -> Result<(), Error> {
897 let len = self.buf.len();
899 item.key.serialize_into(&mut self.buf)?;
900 item.value.serialize_into(&mut self.buf)?;
901
902 let mut added_offset = false;
903 if *self.buf_item_count > 0 {
905 self.block_offsets.push(u16::try_from(len + PER_DATA_BLOCK_HEADER_SIZE).unwrap());
906 added_offset = true;
907 }
908
909 if PER_DATA_BLOCK_HEADER_SIZE
912 + self.buf.len()
913 + (self.block_offsets.len() * PER_DATA_BLOCK_SEEK_ENTRY_SIZE)
914 > self.block_size as usize - 1
915 {
916 if added_offset {
917 self.block_offsets.pop();
920 }
921 self.write_block(len).await?;
922
923 self.block_keys.push(item.key.get_leading_u64());
925 }
926
927 self.bloom_filter.insert(&item.key);
928 *self.buf_item_count += 1;
929 self.item_count += 1;
930 Ok(())
931 }
932
933 async fn complete(mut self) -> Result<u64, Error> {
934 self.write_block(self.buf.len()).await?;
935 let data_blocks = self.data_blocks() as u64;
936 let bloom_filter_len = self.write_bloom_filter().await?;
937 let seek_table_len = self.write_seek_table().await?;
938 self.write_info(data_blocks, bloom_filter_len, seek_table_len).await?;
939 self.writer.complete().await
940 }
941}
942
943#[repr(transparent)]
945struct LayerWriterBufItemCount(u16);
946
947impl Drop for LayerWriterBufItemCount {
948 fn drop(&mut self) {
949 debug_assert!(self.0 == 0, "Dropping unwritten items; did you forget to call complete?");
950 if self.0 > 0 {
951 warn!("Dropping unwritten items; did you forget to call complete?");
952 }
953 }
954}
955
956impl std::ops::Deref for LayerWriterBufItemCount {
957 type Target = u16;
958 fn deref(&self) -> &u16 {
959 &self.0
960 }
961}
962
963impl std::ops::DerefMut for LayerWriterBufItemCount {
964 fn deref_mut(&mut self) -> &mut u16 {
965 &mut self.0
966 }
967}
968
969#[cfg(test)]
970mod tests {
971 use super::{PersistentLayer, PersistentLayerWriter};
972 use crate::filesystem::MAX_BLOCK_SIZE;
973 use crate::lsm_tree::LayerIterator;
974 use crate::lsm_tree::persistent_layer::MINIMUM_DATA_BLOCKS_FOR_BLOOM_FILTER;
975 use crate::lsm_tree::types::{Existence, Item, ItemRef, Layer, LayerWriter, OrdUpperBound};
976 use crate::object_handle::WriteBytes;
977 use crate::object_store::AttributeId;
978 use crate::object_store::object_record::ObjectKey;
979 use crate::round::round_up;
980 use crate::serialized_types::{LATEST_VERSION, Version};
981 use crate::testing::fake_object::{FakeObject, FakeObjectHandle};
982 use crate::testing::writer::Writer;
983
984 use std::fmt::Debug;
985
986 use std::ops::{Bound, Range};
987 use std::sync::Arc;
988
989 impl<W: WriteBytes> Debug for PersistentLayerWriter<W, i32, i32> {
990 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
991 f.debug_struct("rPersistentLayerWriter")
992 .field("block_size", &self.block_size)
993 .field("item_count", &*self.buf_item_count)
994 .finish()
995 }
996 }
997
998 #[fuchsia::test]
999 async fn test_iterate_after_write() {
1000 const BLOCK_SIZE: u64 = 512;
1001 const ITEM_COUNT: i32 = 10000;
1002
1003 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
1004 {
1005 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
1006 Writer::new(&handle).await,
1007 ITEM_COUNT as usize * 4,
1008 BLOCK_SIZE,
1009 )
1010 .await
1011 .expect("writer new");
1012 for i in 0..ITEM_COUNT {
1013 writer.write(Item::new(i, i).as_item_ref()).await.expect("write failed");
1014 }
1015 writer.complete().await.expect("flush failed");
1016 }
1017 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1018 let mut iterator = layer.seek(Bound::Unbounded).await.expect("seek failed");
1019 for i in 0..ITEM_COUNT {
1020 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1021 assert_eq!((key, value), (&i, &i));
1022 iterator.advance().await.expect("failed to advance");
1023 }
1024 assert!(iterator.get().is_none());
1025 }
1026
1027 #[fuchsia::test]
1028 async fn test_seek_after_write() {
1029 const BLOCK_SIZE: u64 = 512;
1030 const ITEM_COUNT: i32 = 5000;
1031
1032 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
1033 {
1034 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
1035 Writer::new(&handle).await,
1036 ITEM_COUNT as usize * 18,
1037 BLOCK_SIZE,
1038 )
1039 .await
1040 .expect("writer new");
1041 for i in 0..ITEM_COUNT {
1042 writer.write(Item::new(i * 2, i * 2).as_item_ref()).await.expect("write failed");
1044 }
1045 writer.complete().await.expect("flush failed");
1046 }
1047 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1048 for i in 0..ITEM_COUNT * 2 {
1050 let expected = round_up(i, 2).unwrap();
1053 let mut iterator = layer.seek(Bound::Included(&i)).await.expect("failed to seek");
1054 if i >= (ITEM_COUNT * 2) - 1 {
1057 assert!(iterator.get().is_none());
1058 } else {
1059 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1060 assert_eq!((key, value), (&expected, &expected));
1061 }
1062
1063 iterator.advance().await.expect("failed to advance");
1065 if i >= (ITEM_COUNT * 2) - 3 {
1069 assert!(iterator.get().is_none());
1070 } else {
1071 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1072 let next = expected + 2;
1073 assert_eq!((key, value), (&next, &next));
1074 }
1075 }
1076 }
1077
1078 #[fuchsia::test]
1079 async fn test_seek_unbounded() {
1080 const BLOCK_SIZE: u64 = 512;
1081 const ITEM_COUNT: i32 = 1000;
1082
1083 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
1084 {
1085 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
1086 Writer::new(&handle).await,
1087 ITEM_COUNT as usize * 18,
1088 BLOCK_SIZE,
1089 )
1090 .await
1091 .expect("writer new");
1092 for i in 0..ITEM_COUNT {
1093 writer.write(Item::new(i, i).as_item_ref()).await.expect("write failed");
1094 }
1095 writer.complete().await.expect("flush failed");
1096 }
1097 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1098 let mut iterator = layer.seek(Bound::Unbounded).await.expect("failed to seek");
1099 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1100 assert_eq!((key, value), (&0, &0));
1101
1102 iterator.advance().await.expect("failed to advance");
1104 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1105 assert_eq!((key, value), (&1, &1));
1106 }
1107
1108 #[fuchsia::test]
1109 async fn test_zero_items() {
1110 const BLOCK_SIZE: u64 = 512;
1111
1112 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
1113 {
1114 let writer = PersistentLayerWriter::<_, i32, i32>::new(
1115 Writer::new(&handle).await,
1116 0,
1117 BLOCK_SIZE,
1118 )
1119 .await
1120 .expect("writer new");
1121 writer.complete().await.expect("flush failed");
1122 }
1123
1124 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1125 let iterator = (layer.as_ref() as &dyn Layer<i32, i32>)
1126 .seek(Bound::Unbounded)
1127 .await
1128 .expect("seek failed");
1129 assert!(iterator.get().is_none())
1130 }
1131
1132 #[fuchsia::test]
1133 async fn test_one_item() {
1134 const BLOCK_SIZE: u64 = 512;
1135
1136 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
1137 {
1138 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
1139 Writer::new(&handle).await,
1140 1,
1141 BLOCK_SIZE,
1142 )
1143 .await
1144 .expect("writer new");
1145 writer.write(Item::new(42, 42).as_item_ref()).await.expect("write failed");
1146 writer.complete().await.expect("flush failed");
1147 }
1148
1149 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1150 {
1151 let mut iterator = (layer.as_ref() as &dyn Layer<i32, i32>)
1152 .seek(Bound::Unbounded)
1153 .await
1154 .expect("seek failed");
1155 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1156 assert_eq!((key, value), (&42, &42));
1157 iterator.advance().await.expect("failed to advance");
1158 assert!(iterator.get().is_none())
1159 }
1160 {
1161 let mut iterator = (layer.as_ref() as &dyn Layer<i32, i32>)
1162 .seek(Bound::Included(&30))
1163 .await
1164 .expect("seek failed");
1165 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1166 assert_eq!((key, value), (&42, &42));
1167 iterator.advance().await.expect("failed to advance");
1168 assert!(iterator.get().is_none())
1169 }
1170 {
1171 let mut iterator = (layer.as_ref() as &dyn Layer<i32, i32>)
1172 .seek(Bound::Included(&42))
1173 .await
1174 .expect("seek failed");
1175 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1176 assert_eq!((key, value), (&42, &42));
1177 iterator.advance().await.expect("failed to advance");
1178 assert!(iterator.get().is_none())
1179 }
1180 {
1181 let iterator = (layer.as_ref() as &dyn Layer<i32, i32>)
1182 .seek(Bound::Included(&43))
1183 .await
1184 .expect("seek failed");
1185 assert!(iterator.get().is_none())
1186 }
1187 }
1188
1189 #[fuchsia::test]
1190 async fn test_large_block_size() {
1191 const BLOCK_SIZE: u64 = MAX_BLOCK_SIZE;
1193 const ITEM_COUNT: i32 = ((BLOCK_SIZE as i32) / 18) * 3;
1195
1196 let handle =
1197 FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE as usize);
1198 {
1199 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
1200 Writer::new(&handle).await,
1201 ITEM_COUNT as usize * 18,
1202 BLOCK_SIZE,
1203 )
1204 .await
1205 .expect("writer new");
1206 for i in 2000000000..(2000000000 + ITEM_COUNT) {
1208 writer.write(Item::new(i, i).as_item_ref()).await.expect("write failed");
1209 }
1210 writer.complete().await.expect("flush failed");
1211 }
1212
1213 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1214 let mut iterator = layer.seek(Bound::Unbounded).await.expect("seek failed");
1215 for i in 2000000000..(2000000000 + ITEM_COUNT) {
1216 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1217 assert_eq!((key, value), (&i, &i));
1218 iterator.advance().await.expect("failed to advance");
1219 }
1220 assert!(iterator.get().is_none());
1221 }
1222
1223 #[fuchsia::test]
1224 async fn test_overlarge_block_size() {
1225 const BLOCK_SIZE: u64 = MAX_BLOCK_SIZE * 2;
1227
1228 let handle =
1229 FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE as usize);
1230 PersistentLayerWriter::<_, i32, i32>::new(Writer::new(&handle).await, 0, BLOCK_SIZE)
1231 .await
1232 .expect_err("Creating writer with overlarge block size.");
1233 }
1234
1235 #[fuchsia::test]
1236 async fn test_seek_bound_excluded() {
1237 const BLOCK_SIZE: u64 = 512;
1238 const ITEM_COUNT: i32 = 10000;
1239
1240 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
1241 {
1242 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
1243 Writer::new(&handle).await,
1244 ITEM_COUNT as usize * 18,
1245 BLOCK_SIZE,
1246 )
1247 .await
1248 .expect("writer new");
1249 for i in 0..ITEM_COUNT {
1250 writer.write(Item::new(i, i).as_item_ref()).await.expect("write failed");
1251 }
1252 writer.complete().await.expect("flush failed");
1253 }
1254 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1255
1256 for i in 9982..ITEM_COUNT {
1257 let mut iterator = layer.seek(Bound::Excluded(&i)).await.expect("failed to seek");
1258 let i_plus_one = i + 1;
1259 if i_plus_one < ITEM_COUNT {
1260 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1261
1262 assert_eq!((key, value), (&i_plus_one, &i_plus_one));
1263
1264 iterator.advance().await.expect("failed to advance");
1266 let i_plus_two = i + 2;
1267 if i_plus_two < ITEM_COUNT {
1268 let ItemRef { key, value, .. } = iterator.get().expect("missing item");
1269 assert_eq!((key, value), (&i_plus_two, &i_plus_two));
1270 } else {
1271 assert!(iterator.get().is_none());
1272 }
1273 } else {
1274 assert!(iterator.get().is_none());
1275 }
1276 }
1277 }
1278
1279 use crate::lsm_tree::testing::TestKey;
1280
1281 fn generate_extents(
1285 object_id: u64,
1286 base_offset: u64,
1287 count: u64,
1288 ) -> (Vec<Item<ObjectKey, u64>>, u64) {
1289 let mut items = Vec::new();
1290 for i in 0..count {
1291 items.push(Item::new(
1292 ObjectKey::extent(
1293 object_id,
1294 AttributeId::TEST_ID,
1295 base_offset + i..base_offset + i + 1,
1296 ),
1297 object_id,
1298 ));
1299 }
1300 (items, object_id + 1)
1301 }
1302
1303 fn generate_objects(object_id_range: Range<u64>) -> (Vec<Item<ObjectKey, u64>>, u64) {
1307 let mut items = Vec::new();
1308 let end = object_id_range.end;
1309 for object_id in object_id_range {
1310 items.push(Item::new(ObjectKey::object(object_id), object_id));
1311 }
1312 (items, end)
1313 }
1314
1315 #[fuchsia::test]
1318 async fn test_block_seek_duplicate_leading_u64() {
1319 const BLOCK_SIZE: u64 = 512;
1321 const ITEMS_PER_PHASE: u64 = 50;
1322
1323 let mut to_find = Vec::new();
1324
1325 let handle =
1326 FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE as usize);
1327 {
1328 let mut items = Vec::new();
1329 let mut object_id = u32::MAX as u64 + 1;
1331
1332 {
1335 let base_extent_offset = 0;
1336 let (mut generated, next_object_id) =
1337 generate_extents(object_id, base_extent_offset, ITEMS_PER_PHASE * 3);
1338 items.append(&mut generated);
1339 let count = ITEMS_PER_PHASE * 3;
1340 to_find.push(ObjectKey::extent(
1341 object_id,
1342 AttributeId::TEST_ID,
1343 base_extent_offset..base_extent_offset + 1,
1344 ));
1345 to_find.push(ObjectKey::extent(
1346 object_id,
1347 AttributeId::TEST_ID,
1348 base_extent_offset + (count / 2)..base_extent_offset + (count / 2) + 1,
1349 ));
1350 to_find.push(ObjectKey::extent(
1351 object_id,
1352 AttributeId::TEST_ID,
1353 base_extent_offset + (count - 1)..base_extent_offset + count,
1354 ));
1355 object_id = next_object_id;
1356 }
1357
1358 {
1360 let (mut generated, next_object_id) =
1361 generate_objects(object_id..object_id + ITEMS_PER_PHASE * 3);
1362 items.append(&mut generated);
1363 object_id = next_object_id;
1364 }
1365
1366 {
1369 let base_extent_offset = 1000;
1370 let (mut generated, next_object_id) =
1371 generate_extents(object_id, base_extent_offset, ITEMS_PER_PHASE * 3);
1372 items.append(&mut generated);
1373 let count = ITEMS_PER_PHASE * 3;
1374 to_find.push(ObjectKey::extent(
1375 object_id,
1376 AttributeId::TEST_ID,
1377 base_extent_offset..base_extent_offset + 1,
1378 ));
1379 to_find.push(ObjectKey::extent(
1380 object_id,
1381 AttributeId::TEST_ID,
1382 base_extent_offset + (count / 2)..base_extent_offset + (count / 2) + 1,
1383 ));
1384 to_find.push(ObjectKey::extent(
1385 object_id,
1386 AttributeId::TEST_ID,
1387 base_extent_offset + (count - 1)..base_extent_offset + count,
1388 ));
1389 object_id = next_object_id;
1390 }
1391
1392 {
1394 let (mut generated, next_object_id) =
1395 generate_objects(object_id..object_id + ITEMS_PER_PHASE * 3);
1396 items.append(&mut generated);
1397 object_id = next_object_id;
1398 }
1399
1400 {
1403 let base_extent_offset = 2000;
1404 let (mut generated, _) =
1405 generate_extents(object_id, base_extent_offset, ITEMS_PER_PHASE * 3);
1406 items.append(&mut generated);
1407 let count = ITEMS_PER_PHASE * 3;
1408 to_find.push(ObjectKey::extent(
1409 object_id,
1410 AttributeId::TEST_ID,
1411 base_extent_offset..base_extent_offset + 1,
1412 ));
1413 to_find.push(ObjectKey::extent(
1414 object_id,
1415 AttributeId::TEST_ID,
1416 base_extent_offset + (count / 2)..base_extent_offset + (count / 2) + 1,
1417 ));
1418 to_find.push(ObjectKey::extent(
1419 object_id,
1420 AttributeId::TEST_ID,
1421 base_extent_offset + (count - 1)..base_extent_offset + count,
1422 ));
1423 }
1424
1425 items.sort_by(|a, b| a.key.cmp_upper_bound(&b.key));
1427
1428 let mut writer = PersistentLayerWriter::<_, ObjectKey, u64>::new(
1429 Writer::new(&handle).await,
1430 3 * BLOCK_SIZE as usize,
1431 BLOCK_SIZE,
1432 )
1433 .await
1434 .expect("writer new");
1435
1436 for item in items {
1437 writer.write(item.as_item_ref()).await.expect("write failed");
1438 }
1439
1440 writer.complete().await.expect("flush failed");
1441 }
1442
1443 let layer = PersistentLayer::<ObjectKey, u64>::open(handle).await.expect("new failed");
1444 for target in to_find {
1445 let iterator: Box<dyn LayerIterator<ObjectKey, u64>> =
1446 layer.seek(Bound::Included(&target)).await.expect("failed to seek");
1447 let ItemRef { key, .. } = iterator.get().expect("missing item");
1448 assert_eq!(&target, key);
1449 }
1450 }
1451
1452 #[fuchsia::test]
1453 async fn test_two_seek_blocks() {
1454 const BLOCK_SIZE: u64 = 512;
1456 const ITEMS_PER_PHASE: u64 = 50;
1457 const ITEM_COUNT: u64 = ITEMS_PER_PHASE * ((BLOCK_SIZE / 8) + 2);
1458
1459 let mut to_find = Vec::new();
1460
1461 let handle =
1462 FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE as usize);
1463 {
1464 let mut writer = PersistentLayerWriter::<_, TestKey, u64>::new(
1465 Writer::new(&handle).await,
1466 ITEM_COUNT as usize * 18,
1467 BLOCK_SIZE,
1468 )
1469 .await
1470 .expect("writer new");
1471
1472 let initial_value = u32::MAX as u64 + 1;
1474 for i in 0..ITEM_COUNT {
1475 writer
1476 .write(
1477 Item::new(TestKey(initial_value + i..initial_value + i), initial_value)
1478 .as_item_ref(),
1479 )
1480 .await
1481 .expect("write failed");
1482 }
1483 to_find.push(TestKey(initial_value..initial_value));
1485 let middle = initial_value + ITEM_COUNT / 2;
1486 to_find.push(TestKey(middle..middle));
1487 let end = initial_value + ITEM_COUNT - 1;
1488 to_find.push(TestKey(end..end));
1489
1490 writer.complete().await.expect("flush failed");
1491 }
1492
1493 let layer = PersistentLayer::<TestKey, u64>::open(handle).await.expect("new failed");
1494 for target in to_find {
1495 let iterator: Box<dyn LayerIterator<TestKey, u64>> =
1496 layer.seek(Bound::Included(&target)).await.expect("failed to seek");
1497 let ItemRef { key, .. } = iterator.get().expect("missing item");
1498 assert_eq!(&target, key);
1499 }
1500 }
1501
1502 #[fuchsia::test]
1505 async fn test_full_seek_block() {
1506 const BLOCK_SIZE: u64 = 512;
1507 const ITEMS_PER_PHASE: u64 = 50;
1508
1509 const SEEK_TABLE_ENTRIES: u64 = BLOCK_SIZE / 8;
1511
1512 const START_ENTRIES_COUNT: u64 = ITEMS_PER_PHASE * SEEK_TABLE_ENTRIES;
1516
1517 for entries in START_ENTRIES_COUNT..START_ENTRIES_COUNT + (ITEMS_PER_PHASE * 2) {
1518 let handle = FakeObjectHandle::new_with_block_size(
1519 Arc::new(FakeObject::new()),
1520 BLOCK_SIZE as usize,
1521 );
1522 {
1523 let mut writer = PersistentLayerWriter::<_, TestKey, u64>::new(
1524 Writer::new(&handle).await,
1525 entries as usize,
1526 BLOCK_SIZE,
1527 )
1528 .await
1529 .expect("writer new");
1530
1531 let initial_value = u32::MAX as u64 + 1;
1533 for i in 0..entries {
1534 writer
1535 .write(
1536 Item::new(TestKey(initial_value + i..initial_value + i), initial_value)
1537 .as_item_ref(),
1538 )
1539 .await
1540 .expect("write failed");
1541 }
1542
1543 writer.complete().await.expect("flush failed");
1544 }
1545 PersistentLayer::<TestKey, u64>::open(handle).await.expect("new failed");
1546 }
1547 }
1548
1549 #[fuchsia::test]
1550 async fn test_ignore_bloom_filter_on_older_versions() {
1551 const BLOCK_SIZE: u64 = 512;
1552 const ITEMS_PER_PHASE: u64 = 50;
1553 const ITEM_COUNT: u64 = (1 + MINIMUM_DATA_BLOCKS_FOR_BLOOM_FILTER as u64) * ITEMS_PER_PHASE;
1555
1556 let old_version_handle =
1557 FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE as usize);
1558 let current_version_handle =
1559 FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE as usize);
1560 {
1561 let mut old_version_writer =
1562 PersistentLayerWriter::<_, TestKey, u64>::new_with_version(
1563 Writer::new(&old_version_handle).await,
1564 ITEM_COUNT as usize,
1565 BLOCK_SIZE,
1566 Version { major: LATEST_VERSION.major - 1, minor: 0 },
1567 )
1568 .await
1569 .expect("writer new");
1570 let mut current_version_writer = PersistentLayerWriter::<_, TestKey, u64>::new(
1571 Writer::new(¤t_version_handle).await,
1572 ITEM_COUNT as usize,
1573 BLOCK_SIZE,
1574 )
1575 .await
1576 .expect("writer new");
1577
1578 let initial_value = u32::MAX as u64 + 1;
1580 for i in 0..ITEM_COUNT {
1581 old_version_writer
1582 .write(
1583 Item::new(TestKey(initial_value + i..initial_value + i), initial_value)
1584 .as_item_ref(),
1585 )
1586 .await
1587 .expect("write failed");
1588 current_version_writer
1589 .write(
1590 Item::new(TestKey(initial_value + i..initial_value + i), initial_value)
1591 .as_item_ref(),
1592 )
1593 .await
1594 .expect("write failed");
1595 }
1596
1597 old_version_writer.complete().await.expect("flush failed");
1598 current_version_writer.complete().await.expect("flush failed");
1599 }
1600
1601 let old_layer =
1602 PersistentLayer::<TestKey, u64>::open(old_version_handle).await.expect("open failed");
1603 let current_layer = PersistentLayer::<TestKey, u64>::open(current_version_handle)
1604 .await
1605 .expect("open failed");
1606 assert!(!old_layer.has_bloom_filter());
1607 assert!(current_layer.has_bloom_filter());
1608 }
1609
1610 #[fuchsia::test]
1611 async fn test_key_exists_no_bloom_filter() {
1612 const BLOCK_SIZE: u64 = 8192;
1613 const ITEM_COUNT: i32 = 100;
1615
1616 let handle =
1617 FakeObjectHandle::new_with_block_size(Arc::new(FakeObject::new()), BLOCK_SIZE as usize);
1618 {
1619 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
1620 Writer::new(&handle).await,
1621 ITEM_COUNT as usize,
1622 BLOCK_SIZE,
1623 )
1624 .await
1625 .expect("writer new");
1626 for i in 0..ITEM_COUNT {
1627 writer.write(Item::new(i * 2, i * 2).as_item_ref()).await.expect("write failed");
1628 }
1629 writer.complete().await.expect("flush failed");
1630 }
1631 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1632 assert!(!layer.has_bloom_filter());
1633
1634 for i in 0..ITEM_COUNT {
1635 assert_eq!(
1636 layer.key_exists(&(i * 2)).await.expect("key_exists failed"),
1637 Existence::Exists
1638 );
1639 assert_eq!(
1640 layer.key_exists(&(i * 2 + 1)).await.expect("key_exists failed"),
1641 Existence::Missing
1642 );
1643 }
1644 }
1645
1646 #[fuchsia::test]
1647 async fn test_key_exists_with_bloom_filter() {
1648 const BLOCK_SIZE: u64 = 512;
1649 const ITEM_COUNT: i32 = 10000;
1651
1652 let handle = FakeObjectHandle::new(Arc::new(FakeObject::new()));
1653 {
1654 let mut writer = PersistentLayerWriter::<_, i32, i32>::new(
1655 Writer::new(&handle).await,
1656 ITEM_COUNT as usize,
1657 BLOCK_SIZE,
1658 )
1659 .await
1660 .expect("writer new");
1661 for i in 0..ITEM_COUNT {
1662 writer.write(Item::new(i * 2, i * 2).as_item_ref()).await.expect("write failed");
1663 }
1664 writer.complete().await.expect("flush failed");
1665 }
1666 let layer = PersistentLayer::<i32, i32>::open(handle).await.expect("new failed");
1667 assert!(layer.has_bloom_filter());
1668
1669 for i in 0..ITEM_COUNT {
1670 assert_eq!(
1672 layer.key_exists(&(i * 2)).await.expect("key_exists failed"),
1673 Existence::MaybeExists
1674 );
1675 }
1676
1677 let mut missing_count = 0;
1680 for i in 0..ITEM_COUNT {
1681 let result = layer.key_exists(&(i * 2 + 1)).await.expect("key_exists failed");
1682 assert_ne!(result, Existence::Exists);
1683 if result == Existence::Missing {
1684 missing_count += 1;
1685 }
1686 }
1687 assert!(missing_count > ITEM_COUNT / 2);
1689 }
1690}