LCOV - code coverage report
Current view: top level - pageserver/compaction/src - interface.rs (source / functions) Coverage Total Hit
Test: 53437f7e869ac68c86c7d3e4c20964c0156f158c.info Lines: 0.0 % 9 0
Test Date: 2024-09-20 16:14:12 Functions: 0.0 % 3 0

            Line data    Source code
       1              : //! This is what the compaction implementation needs to know about
       2              : //! layers, keyspace etc.
       3              : //!
       4              : //! All the heavy lifting is done by the create_image and create_delta
       5              : //! functions that the implementor provides.
       6              : use futures::Future;
       7              : use pageserver_api::{key::Key, keyspace::ShardedRange, shard::ShardIdentity};
       8              : use std::ops::Range;
       9              : use utils::lsn::Lsn;
      10              : 
      11              : /// Public interface. This is the main thing that the implementor needs to provide
      12              : pub trait CompactionJobExecutor {
      13              :     // Type system.
      14              :     //
      15              :     // We assume that there are two kinds of layers, deltas and images. The
      16              :     // compaction doesn't distinguish whether they are stored locally or
      17              :     // remotely.
      18              :     //
      19              :     // The keyspace is defined by the CompactionKey trait.
      20              :     type Key: CompactionKey;
      21              : 
      22              :     type Layer: CompactionLayer<Self::Key> + Clone;
      23              :     type DeltaLayer: CompactionDeltaLayer<Self> + Clone;
      24              :     type ImageLayer: CompactionImageLayer<Self> + Clone;
      25              : 
      26              :     // This is passed through to all the interface functions. The compaction
      27              :     // implementation doesn't do anything with it, but it might be useful for
      28              :     // the interface implementation.
      29              :     type RequestContext: CompactionRequestContext;
      30              : 
      31              :     // ----
      32              :     // Functions that the planner uses to support its decisions
      33              :     // ----
      34              : 
      35              :     fn get_shard_identity(&self) -> &ShardIdentity;
      36              : 
      37              :     /// Return all layers that overlap the given bounding box.
      38              :     fn get_layers(
      39              :         &mut self,
      40              :         key_range: &Range<Self::Key>,
      41              :         lsn_range: &Range<Lsn>,
      42              :         ctx: &Self::RequestContext,
      43              :     ) -> impl Future<Output = anyhow::Result<Vec<Self::Layer>>> + Send;
      44              : 
      45              :     fn get_keyspace(
      46              :         &mut self,
      47              :         key_range: &Range<Self::Key>,
      48              :         lsn: Lsn,
      49              :         ctx: &Self::RequestContext,
      50              :     ) -> impl Future<Output = anyhow::Result<CompactionKeySpace<Self::Key>>> + Send;
      51              : 
      52              :     /// NB: This is a pretty expensive operation. In the real pageserver
      53              :     /// implementation, it downloads the layer, and keeps it resident
      54              :     /// until the DeltaLayer is dropped.
      55              :     fn downcast_delta_layer(
      56              :         &self,
      57              :         layer: &Self::Layer,
      58              :     ) -> impl Future<Output = anyhow::Result<Option<Self::DeltaLayer>>> + Send;
      59              : 
      60              :     // ----
      61              :     // Functions to execute the plan
      62              :     // ----
      63              : 
      64              :     /// Create a new image layer, materializing all the values in the key range,
      65              :     /// at given 'lsn'.
      66              :     fn create_image(
      67              :         &mut self,
      68              :         lsn: Lsn,
      69              :         key_range: &Range<Self::Key>,
      70              :         ctx: &Self::RequestContext,
      71              :     ) -> impl Future<Output = anyhow::Result<()>> + Send;
      72              : 
      73              :     /// Create a new delta layer, containing all the values from 'input_layers'
      74              :     /// in the given key and LSN range.
      75              :     fn create_delta(
      76              :         &mut self,
      77              :         lsn_range: &Range<Lsn>,
      78              :         key_range: &Range<Self::Key>,
      79              :         input_layers: &[Self::DeltaLayer],
      80              :         ctx: &Self::RequestContext,
      81              :     ) -> impl Future<Output = anyhow::Result<()>> + Send;
      82              : 
      83              :     /// Delete a layer. The compaction implementation will call this only after
      84              :     /// all the create_image() or create_delta() calls that deletion of this
      85              :     /// layer depends on have finished. But if the implementor has extra lazy
      86              :     /// background tasks, like uploading the index json file to remote storage.
      87              :     /// it is the implementation's responsibility to track those.
      88              :     fn delete_layer(
      89              :         &mut self,
      90              :         layer: &Self::Layer,
      91              :         ctx: &Self::RequestContext,
      92              :     ) -> impl Future<Output = anyhow::Result<()>> + Send;
      93              : }
      94              : 
      95              : pub trait CompactionKey: std::cmp::Ord + Clone + Copy + std::fmt::Display {
      96              :     const MIN: Self;
      97              :     const MAX: Self;
      98              : 
      99              :     /// Calculate distance between key_range.start and key_range.end.
     100              :     ///
     101              :     /// This returns u32, for compatibility with Repository::key. If the
     102              :     /// distance is larger, return u32::MAX.
     103              :     fn key_range_size(key_range: &Range<Self>, shard_identity: &ShardIdentity) -> u32;
     104              : 
     105              :     // return "self + 1"
     106              :     fn next(&self) -> Self;
     107              : 
     108              :     // return "self + <some decent amount to skip>". The amount to skip
     109              :     // is left to the implementation.
     110              :     // FIXME: why not just "add(u32)" ?  This is hard to use
     111              :     fn skip_some(&self) -> Self;
     112              : }
     113              : 
     114              : impl CompactionKey for Key {
     115              :     const MIN: Self = Self::MIN;
     116              :     const MAX: Self = Self::MAX;
     117              : 
     118            0 :     fn key_range_size(r: &std::ops::Range<Self>, shard_identity: &ShardIdentity) -> u32 {
     119            0 :         ShardedRange::new(r.clone(), shard_identity).page_count()
     120            0 :     }
     121            0 :     fn next(&self) -> Key {
     122            0 :         (self as &Key).next()
     123            0 :     }
     124            0 :     fn skip_some(&self) -> Key {
     125            0 :         self.add(128)
     126            0 :     }
     127              : }
     128              : 
     129              : /// Contiguous ranges of keys that belong to the key space. In key order, and
     130              : /// with no overlap.
     131              : pub type CompactionKeySpace<K> = Vec<Range<K>>;
     132              : 
     133              : /// Functions needed from all layers.
     134              : pub trait CompactionLayer<K: CompactionKey> {
     135              :     fn key_range(&self) -> &Range<K>;
     136              :     fn lsn_range(&self) -> &Range<Lsn>;
     137              : 
     138              :     fn file_size(&self) -> u64;
     139              : 
     140              :     /// For debugging, short human-readable representation of the layer. E.g. filename.
     141              :     fn short_id(&self) -> String;
     142              : 
     143              :     fn is_delta(&self) -> bool;
     144              : }
     145              : pub trait CompactionDeltaLayer<E: CompactionJobExecutor + ?Sized>: CompactionLayer<E::Key> {
     146              :     type DeltaEntry<'a>: CompactionDeltaEntry<'a, E::Key>
     147              :     where
     148              :         Self: 'a;
     149              : 
     150              :     /// Return all keys in this delta layer.
     151              :     fn load_keys<'a>(
     152              :         &self,
     153              :         ctx: &E::RequestContext,
     154              :     ) -> impl Future<Output = anyhow::Result<Vec<Self::DeltaEntry<'_>>>> + Send;
     155              : }
     156              : 
     157              : pub trait CompactionImageLayer<E: CompactionJobExecutor + ?Sized>: CompactionLayer<E::Key> {}
     158              : 
     159              : pub trait CompactionDeltaEntry<'a, K> {
     160              :     fn key(&self) -> K;
     161              :     fn lsn(&self) -> Lsn;
     162              :     fn size(&self) -> u64;
     163              : }
     164              : 
     165              : pub trait CompactionRequestContext {}
        

Generated by: LCOV version 2.1-beta