LCOV - code coverage report
Current view: top level - libs/utils/src - id.rs (source / functions) Coverage Total Hit
Test: d3dc80ba303d573d9d44a7f3290f1b1b48b7e1a0.info Lines: 85.1 % 269 229
Test Date: 2024-06-25 11:53:14 Functions: 49.4 % 178 88

            Line data    Source code
       1              : use std::num::ParseIntError;
       2              : use std::{fmt, str::FromStr};
       3              : 
       4              : use anyhow::Context;
       5              : use hex::FromHex;
       6              : use rand::Rng;
       7              : use serde::de::Visitor;
       8              : use serde::{Deserialize, Serialize};
       9              : use thiserror::Error;
      10              : 
      11            0 : #[derive(Error, Debug)]
      12              : pub enum IdError {
      13              :     #[error("invalid id length {0}")]
      14              :     SliceParseError(usize),
      15              : }
      16              : 
      17              : /// Neon ID is a 128-bit random ID.
      18              : /// Used to represent various identifiers. Provides handy utility methods and impls.
      19              : ///
      20              : /// NOTE: It (de)serializes as an array of hex bytes, so the string representation would look
      21              : /// like `[173,80,132,115,129,226,72,254,170,201,135,108,199,26,228,24]`.
      22              : #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
      23              : struct Id([u8; 16]);
      24              : 
      25              : impl Serialize for Id {
      26         4248 :     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
      27         4248 :     where
      28         4248 :         S: serde::Serializer,
      29         4248 :     {
      30         4248 :         if serializer.is_human_readable() {
      31         1080 :             serializer.collect_str(self)
      32              :         } else {
      33         3168 :             self.0.serialize(serializer)
      34              :         }
      35         4248 :     }
      36              : }
      37              : 
      38              : impl<'de> Deserialize<'de> for Id {
      39       312062 :     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
      40       312062 :     where
      41       312062 :         D: serde::Deserializer<'de>,
      42       312062 :     {
      43       312062 :         struct IdVisitor {
      44       312062 :             is_human_readable_deserializer: bool,
      45       312062 :         }
      46       312062 : 
      47       312062 :         impl<'de> Visitor<'de> for IdVisitor {
      48       312062 :             type Value = Id;
      49       312062 : 
      50       312062 :             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
      51            0 :                 if self.is_human_readable_deserializer {
      52       312062 :                     formatter.write_str("value in form of hex string")
      53       312062 :                 } else {
      54       312062 :                     formatter.write_str("value in form of integer array([u8; 16])")
      55       312062 :                 }
      56       312062 :             }
      57       312062 : 
      58       312062 :             fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
      59       311892 :             where
      60       311892 :                 A: serde::de::SeqAccess<'de>,
      61       311892 :             {
      62       311892 :                 let s = serde::de::value::SeqAccessDeserializer::new(seq);
      63       312062 :                 let id: [u8; 16] = Deserialize::deserialize(s)?;
      64       312062 :                 Ok(Id::from(id))
      65       312062 :             }
      66       312062 : 
      67       312062 :             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
      68          170 :             where
      69          170 :                 E: serde::de::Error,
      70          170 :             {
      71          170 :                 Id::from_str(v).map_err(E::custom)
      72          170 :             }
      73       312062 :         }
      74       312062 : 
      75       312062 :         if deserializer.is_human_readable() {
      76          170 :             deserializer.deserialize_str(IdVisitor {
      77          170 :                 is_human_readable_deserializer: true,
      78          170 :             })
      79              :         } else {
      80       311892 :             deserializer.deserialize_tuple(
      81       311892 :                 16,
      82       311892 :                 IdVisitor {
      83       311892 :                     is_human_readable_deserializer: false,
      84       311892 :                 },
      85       311892 :             )
      86              :         }
      87       312062 :     }
      88              : }
      89              : 
      90              : impl Id {
      91            0 :     pub fn get_from_buf(buf: &mut impl bytes::Buf) -> Id {
      92            0 :         let mut arr = [0u8; 16];
      93            0 :         buf.copy_to_slice(&mut arr);
      94            0 :         Id::from(arr)
      95            0 :     }
      96              : 
      97           28 :     pub fn from_slice(src: &[u8]) -> Result<Id, IdError> {
      98           28 :         if src.len() != 16 {
      99            0 :             return Err(IdError::SliceParseError(src.len()));
     100           28 :         }
     101           28 :         let mut id_array = [0u8; 16];
     102           28 :         id_array.copy_from_slice(src);
     103           28 :         Ok(id_array.into())
     104           28 :     }
     105              : 
     106           18 :     pub fn as_arr(&self) -> [u8; 16] {
     107           18 :         self.0
     108           18 :     }
     109              : 
     110         8526 :     pub fn generate() -> Self {
     111         8526 :         let mut tli_buf = [0u8; 16];
     112         8526 :         rand::thread_rng().fill(&mut tli_buf);
     113         8526 :         Id::from(tli_buf)
     114         8526 :     }
     115              : 
     116       191863 :     fn hex_encode(&self) -> String {
     117       191863 :         static HEX: &[u8] = b"0123456789abcdef";
     118       191863 : 
     119       191863 :         let mut buf = vec![0u8; self.0.len() * 2];
     120      3069808 :         for (&b, chunk) in self.0.as_ref().iter().zip(buf.chunks_exact_mut(2)) {
     121      3069808 :             chunk[0] = HEX[((b >> 4) & 0xf) as usize];
     122      3069808 :             chunk[1] = HEX[(b & 0xf) as usize];
     123      3069808 :         }
     124              : 
     125              :         // SAFETY: vec constructed out of `HEX`, it can only be ascii
     126       191863 :         unsafe { String::from_utf8_unchecked(buf) }
     127       191863 :     }
     128              : }
     129              : 
     130              : impl FromStr for Id {
     131              :     type Err = hex::FromHexError;
     132              : 
     133         7511 :     fn from_str(s: &str) -> Result<Id, Self::Err> {
     134         7511 :         Self::from_hex(s)
     135         7511 :     }
     136              : }
     137              : 
     138              : // this is needed for pretty serialization and deserialization of Id's using serde integration with hex crate
     139              : impl FromHex for Id {
     140              :     type Error = hex::FromHexError;
     141              : 
     142         7559 :     fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
     143         7559 :         let mut buf: [u8; 16] = [0u8; 16];
     144         7559 :         hex::decode_to_slice(hex, &mut buf)?;
     145         7541 :         Ok(Id(buf))
     146         7559 :     }
     147              : }
     148              : 
     149              : impl AsRef<[u8]> for Id {
     150            0 :     fn as_ref(&self) -> &[u8] {
     151            0 :         &self.0
     152            0 :     }
     153              : }
     154              : 
     155              : impl From<[u8; 16]> for Id {
     156       856098 :     fn from(b: [u8; 16]) -> Self {
     157       856098 :         Id(b)
     158       856098 :     }
     159              : }
     160              : 
     161              : impl From<Id> for u128 {
     162            0 :     fn from(id: Id) -> Self {
     163            0 :         u128::from_le_bytes(id.0)
     164            0 :     }
     165              : }
     166              : 
     167              : impl fmt::Display for Id {
     168       190655 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     169       190655 :         f.write_str(&self.hex_encode())
     170       190655 :     }
     171              : }
     172              : 
     173              : impl fmt::Debug for Id {
     174         1208 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     175         1208 :         f.write_str(&self.hex_encode())
     176         1208 :     }
     177              : }
     178              : 
     179              : macro_rules! id_newtype {
     180              :     ($t:ident) => {
     181              :         impl $t {
     182            0 :             pub fn get_from_buf(buf: &mut impl bytes::Buf) -> $t {
     183            0 :                 $t(Id::get_from_buf(buf))
     184            0 :             }
     185              : 
     186           28 :             pub fn from_slice(src: &[u8]) -> Result<$t, IdError> {
     187           28 :                 Ok($t(Id::from_slice(src)?))
     188           28 :             }
     189              : 
     190           18 :             pub fn as_arr(&self) -> [u8; 16] {
     191           18 :                 self.0.as_arr()
     192           18 :             }
     193              : 
     194         8526 :             pub fn generate() -> Self {
     195         8526 :                 $t(Id::generate())
     196         8526 :             }
     197              : 
     198            8 :             pub const fn from_array(b: [u8; 16]) -> Self {
     199            8 :                 $t(Id(b))
     200            8 :             }
     201              :         }
     202              : 
     203              :         impl FromStr for $t {
     204              :             type Err = hex::FromHexError;
     205              : 
     206         7341 :             fn from_str(s: &str) -> Result<$t, Self::Err> {
     207         7341 :                 let value = Id::from_str(s)?;
     208         7323 :                 Ok($t(value))
     209         7341 :             }
     210              :         }
     211              : 
     212              :         impl From<[u8; 16]> for $t {
     213       535650 :             fn from(b: [u8; 16]) -> Self {
     214       535650 :                 $t(Id::from(b))
     215       535650 :             }
     216              :         }
     217              : 
     218              :         impl FromHex for $t {
     219              :             type Error = hex::FromHexError;
     220              : 
     221           48 :             fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
     222           48 :                 Ok($t(Id::from_hex(hex)?))
     223           48 :             }
     224              :         }
     225              : 
     226              :         impl AsRef<[u8]> for $t {
     227           32 :             fn as_ref(&self) -> &[u8] {
     228           32 :                 &self.0 .0
     229           32 :             }
     230              :         }
     231              : 
     232              :         impl From<$t> for u128 {
     233            0 :             fn from(id: $t) -> Self {
     234            0 :                 u128::from(id.0)
     235            0 :             }
     236              :         }
     237              : 
     238              :         impl fmt::Display for $t {
     239       189575 :             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     240       189575 :                 self.0.fmt(f)
     241       189575 :             }
     242              :         }
     243              : 
     244              :         impl fmt::Debug for $t {
     245         1208 :             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     246         1208 :                 self.0.fmt(f)
     247         1208 :             }
     248              :         }
     249              :     };
     250              : }
     251              : 
     252              : /// Neon timeline IDs are different from PostgreSQL timeline
     253              : /// IDs. They serve a similar purpose though: they differentiate
     254              : /// between different "histories" of the same cluster.  However,
     255              : /// PostgreSQL timeline IDs are a bit cumbersome, because they are only
     256              : /// 32-bits wide, and they must be in ascending order in any given
     257              : /// timeline history.  Those limitations mean that we cannot generate a
     258              : /// new PostgreSQL timeline ID by just generating a random number. And
     259              : /// that in turn is problematic for the "pull/push" workflow, where you
     260              : /// have a local copy of a Neon repository, and you periodically sync
     261              : /// the local changes with a remote server. When you work "detached"
     262              : /// from the remote server, you cannot create a PostgreSQL timeline ID
     263              : /// that's guaranteed to be different from all existing timelines in
     264              : /// the remote server. For example, if two people are having a clone of
     265              : /// the repository on their laptops, and they both create a new branch
     266              : /// with different name. What timeline ID would they assign to their
     267              : /// branches? If they pick the same one, and later try to push the
     268              : /// branches to the same remote server, they will get mixed up.
     269              : ///
     270              : /// To avoid those issues, Neon has its own concept of timelines that
     271              : /// is separate from PostgreSQL timelines, and doesn't have those
     272              : /// limitations. A Neon timeline is identified by a 128-bit ID, which
     273              : /// is usually printed out as a hex string.
     274              : ///
     275              : /// NOTE: It (de)serializes as an array of hex bytes, so the string representation would look
     276              : /// like `[173,80,132,115,129,226,72,254,170,201,135,108,199,26,228,24]`.
     277              : /// See [`Id`] for alternative ways to serialize it.
     278       156039 : #[derive(Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
     279              : pub struct TimelineId(Id);
     280              : 
     281              : id_newtype!(TimelineId);
     282              : 
     283              : impl TryFrom<Option<&str>> for TimelineId {
     284              :     type Error = anyhow::Error;
     285              : 
     286            8 :     fn try_from(value: Option<&str>) -> Result<Self, Self::Error> {
     287            8 :         value
     288            8 :             .unwrap_or_default()
     289            8 :             .parse::<TimelineId>()
     290            8 :             .with_context(|| format!("Could not parse timeline id from {:?}", value))
     291            8 :     }
     292              : }
     293              : 
     294              : /// Neon Tenant Id represents identifiar of a particular tenant.
     295              : /// Is used for distinguishing requests and data belonging to different users.
     296              : ///
     297              : /// NOTE: It (de)serializes as an array of hex bytes, so the string representation would look
     298              : /// like `[173,80,132,115,129,226,72,254,170,201,135,108,199,26,228,24]`.
     299              : /// See [`Id`] for alternative ways to serialize it.
     300       156017 : #[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
     301              : pub struct TenantId(Id);
     302              : 
     303              : id_newtype!(TenantId);
     304              : 
     305              : /// Neon Connection Id identifies long-lived connections (for example a pagestream
     306              : /// connection with the page_service). Is used for better logging and tracing
     307              : ///
     308              : /// NOTE: It (de)serializes as an array of hex bytes, so the string representation would look
     309              : /// like `[173,80,132,115,129,226,72,254,170,201,135,108,199,26,228,24]`.
     310              : /// See [`Id`] for alternative ways to serialize it.
     311            0 : #[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
     312              : pub struct ConnectionId(Id);
     313              : 
     314              : id_newtype!(ConnectionId);
     315              : 
     316              : // A pair uniquely identifying Neon instance.
     317            0 : #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize)]
     318              : pub struct TenantTimelineId {
     319              :     pub tenant_id: TenantId,
     320              :     pub timeline_id: TimelineId,
     321              : }
     322              : 
     323              : impl TenantTimelineId {
     324       358612 :     pub fn new(tenant_id: TenantId, timeline_id: TimelineId) -> Self {
     325       358612 :         TenantTimelineId {
     326       358612 :             tenant_id,
     327       358612 :             timeline_id,
     328       358612 :         }
     329       358612 :     }
     330              : 
     331         4020 :     pub fn generate() -> Self {
     332         4020 :         Self::new(TenantId::generate(), TimelineId::generate())
     333         4020 :     }
     334              : 
     335       198065 :     pub fn empty() -> Self {
     336       198065 :         Self::new(TenantId::from([0u8; 16]), TimelineId::from([0u8; 16]))
     337       198065 :     }
     338              : }
     339              : 
     340              : impl fmt::Display for TenantTimelineId {
     341          102 :     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     342          102 :         write!(f, "{}/{}", self.tenant_id, self.timeline_id)
     343          102 :     }
     344              : }
     345              : 
     346              : impl FromStr for TenantTimelineId {
     347              :     type Err = anyhow::Error;
     348              : 
     349            0 :     fn from_str(s: &str) -> Result<Self, Self::Err> {
     350            0 :         let mut parts = s.split('/');
     351            0 :         let tenant_id = parts
     352            0 :             .next()
     353            0 :             .ok_or_else(|| anyhow::anyhow!("TenantTimelineId must contain tenant_id"))?
     354            0 :             .parse()?;
     355            0 :         let timeline_id = parts
     356            0 :             .next()
     357            0 :             .ok_or_else(|| anyhow::anyhow!("TenantTimelineId must contain timeline_id"))?
     358            0 :             .parse()?;
     359            0 :         if parts.next().is_some() {
     360            0 :             anyhow::bail!("TenantTimelineId must contain only tenant_id and timeline_id");
     361            0 :         }
     362            0 :         Ok(TenantTimelineId::new(tenant_id, timeline_id))
     363            0 :     }
     364              : }
     365              : 
     366              : // Unique ID of a storage node (safekeeper or pageserver). Supposed to be issued
     367              : // by the console.
     368            4 : #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd, Hash, Debug, Serialize, Deserialize)]
     369              : #[serde(transparent)]
     370              : pub struct NodeId(pub u64);
     371              : 
     372              : impl fmt::Display for NodeId {
     373            2 :     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     374            2 :         write!(f, "{}", self.0)
     375            2 :     }
     376              : }
     377              : 
     378              : impl FromStr for NodeId {
     379              :     type Err = ParseIntError;
     380            0 :     fn from_str(s: &str) -> Result<Self, Self::Err> {
     381            0 :         Ok(NodeId(u64::from_str(s)?))
     382            0 :     }
     383              : }
     384              : 
     385              : #[cfg(test)]
     386              : mod tests {
     387              :     use serde_assert::{Deserializer, Serializer, Token, Tokens};
     388              : 
     389              :     use crate::bin_ser::BeSer;
     390              : 
     391              :     use super::*;
     392              : 
     393              :     #[test]
     394            2 :     fn test_id_serde_non_human_readable() {
     395            2 :         let original_id = Id([
     396            2 :             173, 80, 132, 115, 129, 226, 72, 254, 170, 201, 135, 108, 199, 26, 228, 24,
     397            2 :         ]);
     398            2 :         let expected_tokens = Tokens(vec![
     399            2 :             Token::Tuple { len: 16 },
     400            2 :             Token::U8(173),
     401            2 :             Token::U8(80),
     402            2 :             Token::U8(132),
     403            2 :             Token::U8(115),
     404            2 :             Token::U8(129),
     405            2 :             Token::U8(226),
     406            2 :             Token::U8(72),
     407            2 :             Token::U8(254),
     408            2 :             Token::U8(170),
     409            2 :             Token::U8(201),
     410            2 :             Token::U8(135),
     411            2 :             Token::U8(108),
     412            2 :             Token::U8(199),
     413            2 :             Token::U8(26),
     414            2 :             Token::U8(228),
     415            2 :             Token::U8(24),
     416            2 :             Token::TupleEnd,
     417            2 :         ]);
     418            2 : 
     419            2 :         let serializer = Serializer::builder().is_human_readable(false).build();
     420            2 :         let serialized_tokens = original_id.serialize(&serializer).unwrap();
     421            2 :         assert_eq!(serialized_tokens, expected_tokens);
     422              : 
     423            2 :         let mut deserializer = Deserializer::builder()
     424            2 :             .is_human_readable(false)
     425            2 :             .tokens(serialized_tokens)
     426            2 :             .build();
     427            2 :         let deserialized_id = Id::deserialize(&mut deserializer).unwrap();
     428            2 :         assert_eq!(deserialized_id, original_id);
     429            2 :     }
     430              : 
     431              :     #[test]
     432            2 :     fn test_id_serde_human_readable() {
     433            2 :         let original_id = Id([
     434            2 :             173, 80, 132, 115, 129, 226, 72, 254, 170, 201, 135, 108, 199, 26, 228, 24,
     435            2 :         ]);
     436            2 :         let expected_tokens = Tokens(vec![Token::Str(String::from(
     437            2 :             "ad50847381e248feaac9876cc71ae418",
     438            2 :         ))]);
     439            2 : 
     440            2 :         let serializer = Serializer::builder().is_human_readable(true).build();
     441            2 :         let serialized_tokens = original_id.serialize(&serializer).unwrap();
     442            2 :         assert_eq!(serialized_tokens, expected_tokens);
     443              : 
     444            2 :         let mut deserializer = Deserializer::builder()
     445            2 :             .is_human_readable(true)
     446            2 :             .tokens(Tokens(vec![Token::Str(String::from(
     447            2 :                 "ad50847381e248feaac9876cc71ae418",
     448            2 :             ))]))
     449            2 :             .build();
     450            2 :         assert_eq!(Id::deserialize(&mut deserializer).unwrap(), original_id);
     451            2 :     }
     452              : 
     453              :     macro_rules! roundtrip_type {
     454              :         ($type:ty, $expected_bytes:expr) => {{
     455              :             let expected_bytes: [u8; 16] = $expected_bytes;
     456              :             let original_id = <$type>::from(expected_bytes);
     457              : 
     458              :             let ser_bytes = original_id.ser().unwrap();
     459              :             assert_eq!(ser_bytes, expected_bytes);
     460              : 
     461              :             let des_id = <$type>::des(&ser_bytes).unwrap();
     462              :             assert_eq!(des_id, original_id);
     463              :         }};
     464              :     }
     465              : 
     466              :     #[test]
     467            2 :     fn test_id_bincode_serde() {
     468            2 :         let expected_bytes = [
     469            2 :             173, 80, 132, 115, 129, 226, 72, 254, 170, 201, 135, 108, 199, 26, 228, 24,
     470            2 :         ];
     471            2 : 
     472            2 :         roundtrip_type!(Id, expected_bytes);
     473            2 :     }
     474              : 
     475              :     #[test]
     476            2 :     fn test_tenant_id_bincode_serde() {
     477            2 :         let expected_bytes = [
     478            2 :             173, 80, 132, 115, 129, 226, 72, 254, 170, 201, 135, 108, 199, 26, 228, 24,
     479            2 :         ];
     480            2 : 
     481            2 :         roundtrip_type!(TenantId, expected_bytes);
     482            2 :     }
     483              : 
     484              :     #[test]
     485            2 :     fn test_timeline_id_bincode_serde() {
     486            2 :         let expected_bytes = [
     487            2 :             173, 80, 132, 115, 129, 226, 72, 254, 170, 201, 135, 108, 199, 26, 228, 24,
     488            2 :         ];
     489            2 : 
     490            2 :         roundtrip_type!(TimelineId, expected_bytes);
     491            2 :     }
     492              : }
        

Generated by: LCOV version 2.1-beta