LCOV - code coverage report
Current view: top level - pageserver/src - repository.rs (source / functions) Coverage Total Hit
Test: 36bb8dd7c7efcb53483d1a7d9f7cb33e8406dcf0.info Lines: 84.1 % 69 58
Test Date: 2024-04-08 10:22:05 Functions: 43.8 % 16 7

            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     13707986 : #[derive(Debug, Clone, Serialize, Deserialize)]
      12              : #[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      6351464 :     pub fn will_init(&self) -> bool {
      29      6351464 :         match self {
      30      6351464 :             Value::Image(_) => true,
      31            0 :             Value::WalRecord(rec) => rec.will_init(),
      32              :         }
      33      6351464 :     }
      34              : }
      35              : 
      36              : #[cfg(test)]
      37              : mod test {
      38              :     use super::*;
      39              : 
      40              :     use utils::bin_ser::BeSer;
      41              : 
      42              :     macro_rules! roundtrip {
      43              :         ($orig:expr, $expected:expr) => {{
      44              :             let orig: Value = $orig;
      45              : 
      46              :             let actual = Value::ser(&orig).unwrap();
      47              :             let expected: &[u8] = &$expected;
      48              : 
      49              :             assert_eq!(utils::Hex(&actual), utils::Hex(expected));
      50              : 
      51              :             let deser = Value::des(&actual).unwrap();
      52              : 
      53              :             assert_eq!(orig, deser);
      54              :         }};
      55              :     }
      56              : 
      57              :     #[test]
      58            2 :     fn image_roundtrip() {
      59            2 :         let image = Bytes::from_static(b"foobar");
      60            2 :         let image = Value::Image(image);
      61            2 : 
      62            2 :         #[rustfmt::skip]
      63            2 :         let expected = [
      64            2 :             // top level discriminator of 4 bytes
      65            2 :             0x00, 0x00, 0x00, 0x00,
      66            2 :             // 8 byte length
      67            2 :             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
      68            2 :             // foobar
      69            2 :             0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72
      70            2 :         ];
      71            2 : 
      72            2 :         roundtrip!(image, expected);
      73            2 :     }
      74              : 
      75              :     #[test]
      76            2 :     fn walrecord_postgres_roundtrip() {
      77            2 :         let rec = NeonWalRecord::Postgres {
      78            2 :             will_init: true,
      79            2 :             rec: Bytes::from_static(b"foobar"),
      80            2 :         };
      81            2 :         let rec = Value::WalRecord(rec);
      82            2 : 
      83            2 :         #[rustfmt::skip]
      84            2 :         let expected = [
      85            2 :             // flattened discriminator of total 8 bytes
      86            2 :             0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
      87            2 :             // will_init
      88            2 :             0x01,
      89            2 :             // 8 byte length
      90            2 :             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
      91            2 :             // foobar
      92            2 :             0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72
      93            2 :         ];
      94            2 : 
      95            2 :         roundtrip!(rec, expected);
      96            2 :     }
      97              : }
      98              : 
      99              : ///
     100              : /// Result of performing GC
     101              : ///
     102            0 : #[derive(Default, Serialize, Debug)]
     103              : pub struct GcResult {
     104              :     pub layers_total: u64,
     105              :     pub layers_needed_by_cutoff: u64,
     106              :     pub layers_needed_by_pitr: u64,
     107              :     pub layers_needed_by_branches: u64,
     108              :     pub layers_not_updated: u64,
     109              :     pub layers_removed: u64, // # of layer files removed because they have been made obsolete by newer ondisk files.
     110              : 
     111              :     #[serde(serialize_with = "serialize_duration_as_millis")]
     112              :     pub elapsed: Duration,
     113              : 
     114              :     /// The layers which were garbage collected.
     115              :     ///
     116              :     /// Used in `/v1/tenant/:tenant_id/timeline/:timeline_id/do_gc` to wait for the layers to be
     117              :     /// dropped in tests.
     118              :     #[cfg(feature = "testing")]
     119              :     #[serde(skip)]
     120              :     pub(crate) doomed_layers: Vec<crate::tenant::storage_layer::Layer>,
     121              : }
     122              : 
     123              : // helper function for `GcResult`, serializing a `Duration` as an integer number of milliseconds
     124            0 : fn serialize_duration_as_millis<S>(d: &Duration, serializer: S) -> Result<S::Ok, S::Error>
     125            0 : where
     126            0 :     S: serde::Serializer,
     127            0 : {
     128            0 :     d.as_millis().serialize(serializer)
     129            0 : }
     130              : 
     131              : impl AddAssign for GcResult {
     132            8 :     fn add_assign(&mut self, other: Self) {
     133            8 :         self.layers_total += other.layers_total;
     134            8 :         self.layers_needed_by_pitr += other.layers_needed_by_pitr;
     135            8 :         self.layers_needed_by_cutoff += other.layers_needed_by_cutoff;
     136            8 :         self.layers_needed_by_branches += other.layers_needed_by_branches;
     137            8 :         self.layers_not_updated += other.layers_not_updated;
     138            8 :         self.layers_removed += other.layers_removed;
     139            8 : 
     140            8 :         self.elapsed += other.elapsed;
     141            8 : 
     142            8 :         #[cfg(feature = "testing")]
     143            8 :         {
     144            8 :             let mut other = other;
     145            8 :             self.doomed_layers.append(&mut other.doomed_layers);
     146            8 :         }
     147            8 :     }
     148              : }
        

Generated by: LCOV version 2.1-beta