LCOV - differential code coverage report
Current view: top level - libs/pageserver_api/src - key.rs (source / functions) Coverage Total Hit UBC CBC
Current: cd44433dd675caa99df17a61b18949c8387e2242.info Lines: 85.3 % 109 93 16 93
Current Date: 2024-01-09 02:06:09 Functions: 63.6 % 33 21 12 21
Baseline: 66c52a629a0f4a503e193045e0df4c77139e344b.info
Baseline Date: 2024-01-08 15:34:46

           TLA  Line data    Source code
       1                 : use anyhow::{bail, Result};
       2                 : use byteorder::{ByteOrder, BE};
       3                 : use serde::{Deserialize, Serialize};
       4                 : use std::fmt;
       5                 : 
       6                 : /// Key used in the Repository kv-store.
       7                 : ///
       8                 : /// The Repository treats this as an opaque struct, but see the code in pgdatadir_mapping.rs
       9                 : /// for what we actually store in these fields.
      10 CBC   201354926 : #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize)]
      11                 : pub struct Key {
      12                 :     pub field1: u8,
      13                 :     pub field2: u32,
      14                 :     pub field3: u32,
      15                 :     pub field4: u32,
      16                 :     pub field5: u8,
      17                 :     pub field6: u32,
      18                 : }
      19                 : 
      20                 : pub const KEY_SIZE: usize = 18;
      21                 : 
      22                 : impl Key {
      23                 :     /// 'field2' is used to store tablespaceid for relations and small enum numbers for other relish.
      24                 :     /// As long as Neon does not support tablespace (because of lack of access to local file system),
      25                 :     /// we can assume that only some predefined namespace OIDs are used which can fit in u16
      26        78069726 :     pub fn to_i128(&self) -> i128 {
      27        78069726 :         assert!(self.field2 < 0xFFFF || self.field2 == 0xFFFFFFFF || self.field2 == 0x22222222);
      28        78069726 :         (((self.field1 & 0xf) as i128) << 120)
      29        78069726 :             | (((self.field2 & 0xFFFF) as i128) << 104)
      30        78069726 :             | ((self.field3 as i128) << 72)
      31        78069726 :             | ((self.field4 as i128) << 40)
      32        78069726 :             | ((self.field5 as i128) << 32)
      33        78069726 :             | self.field6 as i128
      34        78069726 :     }
      35                 : 
      36        12150865 :     pub const fn from_i128(x: i128) -> Self {
      37        12150865 :         Key {
      38        12150865 :             field1: ((x >> 120) & 0xf) as u8,
      39        12150865 :             field2: ((x >> 104) & 0xFFFF) as u32,
      40        12150865 :             field3: (x >> 72) as u32,
      41        12150865 :             field4: (x >> 40) as u32,
      42        12150865 :             field5: (x >> 32) as u8,
      43        12150865 :             field6: x as u32,
      44        12150865 :         }
      45        12150865 :     }
      46                 : 
      47        18156039 :     pub fn next(&self) -> Key {
      48        18156039 :         self.add(1)
      49        18156039 :     }
      50                 : 
      51        18161850 :     pub fn add(&self, x: u32) -> Key {
      52        18161850 :         let mut key = *self;
      53        18161850 : 
      54        18161850 :         let r = key.field6.overflowing_add(x);
      55        18161850 :         key.field6 = r.0;
      56        18161850 :         if r.1 {
      57         1323329 :             let r = key.field5.overflowing_add(1);
      58         1323329 :             key.field5 = r.0;
      59         1323329 :             if r.1 {
      60 UBC           0 :                 let r = key.field4.overflowing_add(1);
      61               0 :                 key.field4 = r.0;
      62               0 :                 if r.1 {
      63               0 :                     let r = key.field3.overflowing_add(1);
      64               0 :                     key.field3 = r.0;
      65               0 :                     if r.1 {
      66               0 :                         let r = key.field2.overflowing_add(1);
      67               0 :                         key.field2 = r.0;
      68               0 :                         if r.1 {
      69               0 :                             let r = key.field1.overflowing_add(1);
      70               0 :                             key.field1 = r.0;
      71               0 :                             assert!(!r.1);
      72               0 :                         }
      73               0 :                     }
      74               0 :                 }
      75 CBC     1323329 :             }
      76        16838521 :         }
      77        18161850 :         key
      78        18161850 :     }
      79                 : 
      80        16792843 :     pub fn from_slice(b: &[u8]) -> Self {
      81        16792843 :         Key {
      82        16792843 :             field1: b[0],
      83        16792843 :             field2: u32::from_be_bytes(b[1..5].try_into().unwrap()),
      84        16792843 :             field3: u32::from_be_bytes(b[5..9].try_into().unwrap()),
      85        16792843 :             field4: u32::from_be_bytes(b[9..13].try_into().unwrap()),
      86        16792843 :             field5: b[13],
      87        16792843 :             field6: u32::from_be_bytes(b[14..18].try_into().unwrap()),
      88        16792843 :         }
      89        16792843 :     }
      90                 : 
      91        62181926 :     pub fn write_to_byte_slice(&self, buf: &mut [u8]) {
      92        62181926 :         buf[0] = self.field1;
      93        62181926 :         BE::write_u32(&mut buf[1..5], self.field2);
      94        62181926 :         BE::write_u32(&mut buf[5..9], self.field3);
      95        62181926 :         BE::write_u32(&mut buf[9..13], self.field4);
      96        62181926 :         buf[13] = self.field5;
      97        62181926 :         BE::write_u32(&mut buf[14..18], self.field6);
      98        62181926 :     }
      99                 : }
     100                 : 
     101                 : impl fmt::Display for Key {
     102         2937069 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     103         2937069 :         write!(
     104         2937069 :             f,
     105         2937069 :             "{:02X}{:08X}{:08X}{:08X}{:02X}{:08X}",
     106         2937069 :             self.field1, self.field2, self.field3, self.field4, self.field5, self.field6
     107         2937069 :         )
     108         2937069 :     }
     109                 : }
     110                 : 
     111                 : impl Key {
     112                 :     pub const MIN: Key = Key {
     113                 :         field1: u8::MIN,
     114                 :         field2: u32::MIN,
     115                 :         field3: u32::MIN,
     116                 :         field4: u32::MIN,
     117                 :         field5: u8::MIN,
     118                 :         field6: u32::MIN,
     119                 :     };
     120                 :     pub const MAX: Key = Key {
     121                 :         field1: u8::MAX,
     122                 :         field2: u32::MAX,
     123                 :         field3: u32::MAX,
     124                 :         field4: u32::MAX,
     125                 :         field5: u8::MAX,
     126                 :         field6: u32::MAX,
     127                 :     };
     128                 : 
     129          215201 :     pub fn from_hex(s: &str) -> Result<Self> {
     130          215201 :         if s.len() != 36 {
     131 UBC           0 :             bail!("parse error");
     132 CBC      215201 :         }
     133          215201 :         Ok(Key {
     134          215201 :             field1: u8::from_str_radix(&s[0..2], 16)?,
     135          215201 :             field2: u32::from_str_radix(&s[2..10], 16)?,
     136          215201 :             field3: u32::from_str_radix(&s[10..18], 16)?,
     137          215201 :             field4: u32::from_str_radix(&s[18..26], 16)?,
     138          215201 :             field5: u8::from_str_radix(&s[26..28], 16)?,
     139          215201 :             field6: u32::from_str_radix(&s[28..36], 16)?,
     140                 :         })
     141          215201 :     }
     142                 : }
     143                 : 
     144        22558333 : pub fn is_rel_block_key(key: &Key) -> bool {
     145        22558333 :     key.field1 == 0x00 && key.field4 != 0 && key.field6 != 0xffffffff
     146        22558333 : }
     147                 : 
     148                 : impl std::str::FromStr for Key {
     149                 :     type Err = anyhow::Error;
     150                 : 
     151               7 :     fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
     152               7 :         Self::from_hex(s)
     153               7 :     }
     154                 : }
     155                 : 
     156                 : #[cfg(test)]
     157                 : mod tests {
     158                 :     use std::str::FromStr;
     159                 : 
     160                 :     use crate::key::Key;
     161                 : 
     162                 :     use rand::Rng;
     163                 :     use rand::SeedableRng;
     164                 : 
     165               1 :     #[test]
     166               1 :     fn display_fromstr_bijection() {
     167               1 :         let mut rng = rand::rngs::StdRng::seed_from_u64(42);
     168               1 : 
     169               1 :         let key = Key {
     170               1 :             field1: rng.gen(),
     171               1 :             field2: rng.gen(),
     172               1 :             field3: rng.gen(),
     173               1 :             field4: rng.gen(),
     174               1 :             field5: rng.gen(),
     175               1 :             field6: rng.gen(),
     176               1 :         };
     177               1 : 
     178               1 :         assert_eq!(key, Key::from_str(&format!("{key}")).unwrap());
     179               1 :     }
     180                 : }
        

Generated by: LCOV version 2.1-beta