LCOV - code coverage report
Current view: top level - pageserver/src - repository.rs (source / functions) Coverage Total Hit
Test: c639aa5f7ab62b43d647b10f40d15a15686ce8a9.info Lines: 95.8 % 72 69
Test Date: 2024-02-12 20:26:03 Functions: 65.5 % 29 19

            Line data    Source code
       1              : use crate::walrecord::NeonWalRecord;
       2              : use anyhow::Result;
       3              : use bytes::Bytes;
       4              : use serde::{Deserialize, Serialize};
       5              : use std::ops::AddAssign;
       6              : use std::time::Duration;
       7              : 
       8              : pub use pageserver_api::key::{Key, KEY_SIZE};
       9              : 
      10              : /// A 'value' stored for a one Key.
      11    273509500 : #[derive(Debug, Clone, Serialize, Deserialize)]
      12            4 : #[cfg_attr(test, derive(PartialEq))]
      13              : pub enum Value {
      14              :     /// An Image value contains a full copy of the value
      15              :     Image(Bytes),
      16              :     /// A WalRecord value contains a WAL record that needs to be
      17              :     /// replayed get the full value. Replaying the WAL record
      18              :     /// might need a previous version of the value (if will_init()
      19              :     /// returns false), or it may be replayed stand-alone (true).
      20              :     WalRecord(NeonWalRecord),
      21              : }
      22              : 
      23              : impl Value {
      24            0 :     pub fn is_image(&self) -> bool {
      25            0 :         matches!(self, Value::Image(_))
      26            0 :     }
      27              : 
      28     52098905 :     pub fn will_init(&self) -> bool {
      29     52098905 :         match self {
      30      7172359 :             Value::Image(_) => true,
      31     44926546 :             Value::WalRecord(rec) => rec.will_init(),
      32              :         }
      33     52098905 :     }
      34              : }
      35              : 
      36              : #[cfg(test)]
      37              : mod test {
      38              :     use super::*;
      39              : 
      40              :     use bytes::Bytes;
      41              :     use utils::bin_ser::BeSer;
      42              : 
      43              :     macro_rules! roundtrip {
      44              :         ($orig:expr, $expected:expr) => {{
      45              :             let orig: Value = $orig;
      46              : 
      47              :             let actual = Value::ser(&orig).unwrap();
      48              :             let expected: &[u8] = &$expected;
      49              : 
      50              :             assert_eq!(utils::Hex(&actual), utils::Hex(expected));
      51              : 
      52              :             let deser = Value::des(&actual).unwrap();
      53              : 
      54              :             assert_eq!(orig, deser);
      55              :         }};
      56              :     }
      57              : 
      58            2 :     #[test]
      59            2 :     fn image_roundtrip() {
      60            2 :         let image = Bytes::from_static(b"foobar");
      61            2 :         let image = Value::Image(image);
      62            2 : 
      63            2 :         #[rustfmt::skip]
      64            2 :         let expected = [
      65            2 :             // top level discriminator of 4 bytes
      66            2 :             0x00, 0x00, 0x00, 0x00,
      67            2 :             // 8 byte length
      68            2 :             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
      69            2 :             // foobar
      70            2 :             0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72
      71            2 :         ];
      72            2 : 
      73            2 :         roundtrip!(image, expected);
      74            2 :     }
      75              : 
      76            2 :     #[test]
      77            2 :     fn walrecord_postgres_roundtrip() {
      78            2 :         let rec = NeonWalRecord::Postgres {
      79            2 :             will_init: true,
      80            2 :             rec: Bytes::from_static(b"foobar"),
      81            2 :         };
      82            2 :         let rec = Value::WalRecord(rec);
      83            2 : 
      84            2 :         #[rustfmt::skip]
      85            2 :         let expected = [
      86            2 :             // flattened discriminator of total 8 bytes
      87            2 :             0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
      88            2 :             // will_init
      89            2 :             0x01,
      90            2 :             // 8 byte length
      91            2 :             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
      92            2 :             // foobar
      93            2 :             0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72
      94            2 :         ];
      95            2 : 
      96            2 :         roundtrip!(rec, expected);
      97            2 :     }
      98              : }
      99              : 
     100              : ///
     101              : /// Result of performing GC
     102              : ///
     103         1201 : #[derive(Default, Serialize, Debug)]
     104              : pub struct GcResult {
     105              :     pub layers_total: u64,
     106              :     pub layers_needed_by_cutoff: u64,
     107              :     pub layers_needed_by_pitr: u64,
     108              :     pub layers_needed_by_branches: u64,
     109              :     pub layers_not_updated: u64,
     110              :     pub layers_removed: u64, // # of layer files removed because they have been made obsolete by newer ondisk files.
     111              : 
     112              :     #[serde(serialize_with = "serialize_duration_as_millis")]
     113              :     pub elapsed: Duration,
     114              : 
     115              :     /// The layers which were garbage collected.
     116              :     ///
     117              :     /// Used in `/v1/tenant/:tenant_id/timeline/:timeline_id/do_gc` to wait for the layers to be
     118              :     /// dropped in tests.
     119              :     #[cfg(feature = "testing")]
     120              :     #[serde(skip)]
     121              :     pub(crate) doomed_layers: Vec<crate::tenant::storage_layer::Layer>,
     122              : }
     123              : 
     124              : // helper function for `GcResult`, serializing a `Duration` as an integer number of milliseconds
     125          372 : fn serialize_duration_as_millis<S>(d: &Duration, serializer: S) -> Result<S::Ok, S::Error>
     126          372 : where
     127          372 :     S: serde::Serializer,
     128          372 : {
     129          372 :     d.as_millis().serialize(serializer)
     130          372 : }
     131              : 
     132              : impl AddAssign for GcResult {
     133          496 :     fn add_assign(&mut self, other: Self) {
     134          496 :         self.layers_total += other.layers_total;
     135          496 :         self.layers_needed_by_pitr += other.layers_needed_by_pitr;
     136          496 :         self.layers_needed_by_cutoff += other.layers_needed_by_cutoff;
     137          496 :         self.layers_needed_by_branches += other.layers_needed_by_branches;
     138          496 :         self.layers_not_updated += other.layers_not_updated;
     139          496 :         self.layers_removed += other.layers_removed;
     140          496 : 
     141          496 :         self.elapsed += other.elapsed;
     142          496 : 
     143          496 :         #[cfg(feature = "testing")]
     144          496 :         {
     145          496 :             let mut other = other;
     146          496 :             self.doomed_layers.append(&mut other.doomed_layers);
     147          496 :         }
     148          496 :     }
     149              : }
        

Generated by: LCOV version 2.1-beta