LCOV - differential code coverage report
Current view: top level - libs/utils/src - id.rs (source / functions) Coverage Total Hit UBC CBC
Current: f6946e90941b557c917ac98cd5a7e9506d180f3e.info Lines: 84.7 % 137 116 21 116
Current Date: 2023-10-19 02:04:12 Functions: 48.4 % 188 91 97 91
Baseline: c8637f37369098875162f194f92736355783b050.info
Baseline Date: 2023-10-18 20:25:20

           TLA  Line data    Source code
       1                 : use std::{fmt, str::FromStr};
       2                 : 
       3                 : use anyhow::Context;
       4                 : use hex::FromHex;
       5                 : use rand::Rng;
       6                 : use serde::{Deserialize, Serialize};
       7                 : use thiserror::Error;
       8                 : 
       9 UBC           0 : #[derive(Error, Debug)]
      10                 : pub enum IdError {
      11                 :     #[error("invalid id length {0}")]
      12                 :     SliceParseError(usize),
      13                 : }
      14                 : 
      15                 : /// Neon ID is a 128-bit random ID.
      16                 : /// Used to represent various identifiers. Provides handy utility methods and impls.
      17                 : ///
      18                 : /// NOTE: It (de)serializes as an array of hex bytes, so the string representation would look
      19                 : /// like `[173,80,132,115,129,226,72,254,170,201,135,108,199,26,228,24]`.
      20                 : ///
      21                 : /// Use `#[serde_as(as = "DisplayFromStr")]` to (de)serialize it as hex string instead: `ad50847381e248feaac9876cc71ae418`.
      22                 : /// Check the `serde_with::serde_as` documentation for options for more complex types.
      23 CBC    24185423 : #[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
      24                 : struct Id([u8; 16]);
      25                 : 
      26                 : impl Id {
      27 UBC           0 :     pub fn get_from_buf(buf: &mut impl bytes::Buf) -> Id {
      28               0 :         let mut arr = [0u8; 16];
      29               0 :         buf.copy_to_slice(&mut arr);
      30               0 :         Id::from(arr)
      31               0 :     }
      32                 : 
      33 CBC       35074 :     pub fn from_slice(src: &[u8]) -> Result<Id, IdError> {
      34           35074 :         if src.len() != 16 {
      35 UBC           0 :             return Err(IdError::SliceParseError(src.len()));
      36 CBC       35074 :         }
      37           35074 :         let mut id_array = [0u8; 16];
      38           35074 :         id_array.copy_from_slice(src);
      39           35074 :         Ok(id_array.into())
      40           35074 :     }
      41                 : 
      42 UBC           0 :     pub fn as_arr(&self) -> [u8; 16] {
      43               0 :         self.0
      44               0 :     }
      45                 : 
      46 CBC         982 :     pub fn generate() -> Self {
      47             982 :         let mut tli_buf = [0u8; 16];
      48             982 :         rand::thread_rng().fill(&mut tli_buf);
      49             982 :         Id::from(tli_buf)
      50             982 :     }
      51                 : 
      52         5854105 :     fn hex_encode(&self) -> String {
      53         5854105 :         static HEX: &[u8] = b"0123456789abcdef";
      54         5854105 : 
      55         5854105 :         let mut buf = vec![0u8; self.0.len() * 2];
      56        93665680 :         for (&b, chunk) in self.0.as_ref().iter().zip(buf.chunks_exact_mut(2)) {
      57        93665680 :             chunk[0] = HEX[((b >> 4) & 0xf) as usize];
      58        93665680 :             chunk[1] = HEX[(b & 0xf) as usize];
      59        93665680 :         }
      60         5854105 :         unsafe { String::from_utf8_unchecked(buf) }
      61         5854105 :     }
      62                 : }
      63                 : 
      64                 : impl FromStr for Id {
      65                 :     type Err = hex::FromHexError;
      66                 : 
      67           72008 :     fn from_str(s: &str) -> Result<Id, Self::Err> {
      68           72008 :         Self::from_hex(s)
      69           72008 :     }
      70                 : }
      71                 : 
      72                 : // this is needed for pretty serialization and deserialization of Id's using serde integration with hex crate
      73                 : impl FromHex for Id {
      74                 :     type Error = hex::FromHexError;
      75                 : 
      76           72200 :     fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
      77           72200 :         let mut buf: [u8; 16] = [0u8; 16];
      78           72200 :         hex::decode_to_slice(hex, &mut buf)?;
      79           70697 :         Ok(Id(buf))
      80           72200 :     }
      81                 : }
      82                 : 
      83                 : impl AsRef<[u8]> for Id {
      84 UBC           0 :     fn as_ref(&self) -> &[u8] {
      85               0 :         &self.0
      86               0 :     }
      87                 : }
      88                 : 
      89                 : impl From<[u8; 16]> for Id {
      90 CBC       44326 :     fn from(b: [u8; 16]) -> Self {
      91           44326 :         Id(b)
      92           44326 :     }
      93                 : }
      94                 : 
      95                 : impl From<Id> for u128 {
      96             223 :     fn from(id: Id) -> Self {
      97             223 :         u128::from_le_bytes(id.0)
      98             223 :     }
      99                 : }
     100                 : 
     101                 : impl fmt::Display for Id {
     102         5843381 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     103         5843381 :         f.write_str(&self.hex_encode())
     104         5843381 :     }
     105                 : }
     106                 : 
     107                 : impl fmt::Debug for Id {
     108           10724 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     109           10724 :         f.write_str(&self.hex_encode())
     110           10724 :     }
     111                 : }
     112                 : 
     113                 : macro_rules! id_newtype {
     114                 :     ($t:ident) => {
     115                 :         impl $t {
     116 UBC           0 :             pub fn get_from_buf(buf: &mut impl bytes::Buf) -> $t {
     117               0 :                 $t(Id::get_from_buf(buf))
     118               0 :             }
     119                 : 
     120 CBC       35074 :             pub fn from_slice(src: &[u8]) -> Result<$t, IdError> {
     121           35074 :                 Ok($t(Id::from_slice(src)?))
     122           35074 :             }
     123                 : 
     124 UBC           0 :             pub fn as_arr(&self) -> [u8; 16] {
     125               0 :                 self.0.as_arr()
     126               0 :             }
     127                 : 
     128 CBC         982 :             pub fn generate() -> Self {
     129             982 :                 $t(Id::generate())
     130             982 :             }
     131                 : 
     132              12 :             pub const fn from_array(b: [u8; 16]) -> Self {
     133              12 :                 $t(Id(b))
     134              12 :             }
     135                 :         }
     136                 : 
     137                 :         impl FromStr for $t {
     138                 :             type Err = hex::FromHexError;
     139                 : 
     140           72008 :             fn from_str(s: &str) -> Result<$t, Self::Err> {
     141           72008 :                 let value = Id::from_str(s)?;
     142           70505 :                 Ok($t(value))
     143           72008 :             }
     144                 :         }
     145                 : 
     146                 :         impl From<[u8; 16]> for $t {
     147            8270 :             fn from(b: [u8; 16]) -> Self {
     148            8270 :                 $t(Id::from(b))
     149            8270 :             }
     150                 :         }
     151                 : 
     152                 :         impl FromHex for $t {
     153                 :             type Error = hex::FromHexError;
     154                 : 
     155             192 :             fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
     156             192 :                 Ok($t(Id::from_hex(hex)?))
     157             192 :             }
     158                 :         }
     159                 : 
     160                 :         impl AsRef<[u8]> for $t {
     161           26428 :             fn as_ref(&self) -> &[u8] {
     162           26428 :                 &self.0 .0
     163           26428 :             }
     164                 :         }
     165                 : 
     166                 :         impl From<$t> for u128 {
     167             223 :             fn from(id: $t) -> Self {
     168             223 :                 u128::from(id.0)
     169             223 :             }
     170                 :         }
     171                 : 
     172                 :         impl fmt::Display for $t {
     173         5843381 :             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     174         5843381 :                 self.0.fmt(f)
     175         5843381 :             }
     176                 :         }
     177                 : 
     178                 :         impl fmt::Debug for $t {
     179           10724 :             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     180           10724 :                 self.0.fmt(f)
     181           10724 :             }
     182                 :         }
     183                 :     };
     184                 : }
     185                 : 
     186                 : /// Neon timeline IDs are different from PostgreSQL timeline
     187                 : /// IDs. They serve a similar purpose though: they differentiate
     188                 : /// between different "histories" of the same cluster.  However,
     189                 : /// PostgreSQL timeline IDs are a bit cumbersome, because they are only
     190                 : /// 32-bits wide, and they must be in ascending order in any given
     191                 : /// timeline history.  Those limitations mean that we cannot generate a
     192                 : /// new PostgreSQL timeline ID by just generating a random number. And
     193                 : /// that in turn is problematic for the "pull/push" workflow, where you
     194                 : /// have a local copy of a Neon repository, and you periodically sync
     195                 : /// the local changes with a remote server. When you work "detached"
     196                 : /// from the remote server, you cannot create a PostgreSQL timeline ID
     197                 : /// that's guaranteed to be different from all existing timelines in
     198                 : /// the remote server. For example, if two people are having a clone of
     199                 : /// the repository on their laptops, and they both create a new branch
     200                 : /// with different name. What timeline ID would they assign to their
     201                 : /// branches? If they pick the same one, and later try to push the
     202                 : /// branches to the same remote server, they will get mixed up.
     203                 : ///
     204                 : /// To avoid those issues, Neon has its own concept of timelines that
     205                 : /// is separate from PostgreSQL timelines, and doesn't have those
     206                 : /// limitations. A Neon timeline is identified by a 128-bit ID, which
     207                 : /// is usually printed out as a hex string.
     208                 : ///
     209                 : /// NOTE: It (de)serializes as an array of hex bytes, so the string representation would look
     210                 : /// like `[173,80,132,115,129,226,72,254,170,201,135,108,199,26,228,24]`.
     211                 : /// See [`Id`] for alternative ways to serialize it.
     212        13006886 : #[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
     213                 : pub struct TimelineId(Id);
     214                 : 
     215                 : id_newtype!(TimelineId);
     216                 : 
     217                 : impl TryFrom<Option<&str>> for TimelineId {
     218                 :     type Error = anyhow::Error;
     219                 : 
     220             311 :     fn try_from(value: Option<&str>) -> Result<Self, Self::Error> {
     221             311 :         value
     222             311 :             .unwrap_or_default()
     223             311 :             .parse::<TimelineId>()
     224             311 :             .with_context(|| format!("Could not parse timeline id from {:?}", value))
     225             311 :     }
     226                 : }
     227                 : 
     228                 : /// Neon Tenant Id represents identifiar of a particular tenant.
     229                 : /// Is used for distinguishing requests and data belonging to different users.
     230                 : ///
     231                 : /// NOTE: It (de)serializes as an array of hex bytes, so the string representation would look
     232                 : /// like `[173,80,132,115,129,226,72,254,170,201,135,108,199,26,228,24]`.
     233                 : /// See [`Id`] for alternative ways to serialize it.
     234        13025893 : #[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
     235                 : pub struct TenantId(Id);
     236                 : 
     237                 : id_newtype!(TenantId);
     238                 : 
     239                 : /// Neon Connection Id identifies long-lived connections (for example a pagestream
     240                 : /// connection with the page_service). Is used for better logging and tracing
     241                 : ///
     242                 : /// NOTE: It (de)serializes as an array of hex bytes, so the string representation would look
     243                 : /// like `[173,80,132,115,129,226,72,254,170,201,135,108,199,26,228,24]`.
     244                 : /// See [`Id`] for alternative ways to serialize it.
     245 UBC           0 : #[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
     246                 : pub struct ConnectionId(Id);
     247                 : 
     248                 : id_newtype!(ConnectionId);
     249                 : 
     250                 : // A pair uniquely identifying Neon instance.
     251 CBC       24217 : #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize)]
     252                 : pub struct TenantTimelineId {
     253                 :     pub tenant_id: TenantId,
     254                 :     pub timeline_id: TimelineId,
     255                 : }
     256                 : 
     257                 : impl TenantTimelineId {
     258            9301 :     pub fn new(tenant_id: TenantId, timeline_id: TimelineId) -> Self {
     259            9301 :         TenantTimelineId {
     260            9301 :             tenant_id,
     261            9301 :             timeline_id,
     262            9301 :         }
     263            9301 :     }
     264                 : 
     265               2 :     pub fn generate() -> Self {
     266               2 :         Self::new(TenantId::generate(), TimelineId::generate())
     267               2 :     }
     268                 : 
     269            3565 :     pub fn empty() -> Self {
     270            3565 :         Self::new(TenantId::from([0u8; 16]), TimelineId::from([0u8; 16]))
     271            3565 :     }
     272                 : }
     273                 : 
     274                 : impl fmt::Display for TenantTimelineId {
     275            7637 :     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     276            7637 :         write!(f, "{}/{}", self.tenant_id, self.timeline_id)
     277            7637 :     }
     278                 : }
     279                 : 
     280                 : impl FromStr for TenantTimelineId {
     281                 :     type Err = anyhow::Error;
     282                 : 
     283               1 :     fn from_str(s: &str) -> Result<Self, Self::Err> {
     284               1 :         let mut parts = s.split('/');
     285               1 :         let tenant_id = parts
     286               1 :             .next()
     287               1 :             .ok_or_else(|| anyhow::anyhow!("TenantTimelineId must contain tenant_id"))?
     288               1 :             .parse()?;
     289               1 :         let timeline_id = parts
     290               1 :             .next()
     291               1 :             .ok_or_else(|| anyhow::anyhow!("TenantTimelineId must contain timeline_id"))?
     292               1 :             .parse()?;
     293               1 :         if parts.next().is_some() {
     294 UBC           0 :             anyhow::bail!("TenantTimelineId must contain only tenant_id and timeline_id");
     295 CBC           1 :         }
     296               1 :         Ok(TenantTimelineId::new(tenant_id, timeline_id))
     297               1 :     }
     298                 : }
     299                 : 
     300                 : // Unique ID of a storage node (safekeeper or pageserver). Supposed to be issued
     301                 : // by the console.
     302         1884918 : #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Hash, Debug, Serialize, Deserialize)]
     303                 : #[serde(transparent)]
     304                 : pub struct NodeId(pub u64);
     305                 : 
     306                 : impl fmt::Display for NodeId {
     307           15091 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     308           15091 :         write!(f, "{}", self.0)
     309           15091 :     }
     310                 : }
        

Generated by: LCOV version 2.1-beta