LCOV - differential code coverage report
Current view: top level - libs/utils/src - id.rs (source / functions) Coverage Total Hit UBC CBC
Current: cd44433dd675caa99df17a61b18949c8387e2242.info Lines: 89.0 % 272 242 30 242
Current Date: 2024-01-09 02:06:09 Functions: 66.4 % 304 202 102 202
Baseline: 66c52a629a0f4a503e193045e0df4c77139e344b.info
Baseline Date: 2024-01-08 15:34:46

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

Generated by: LCOV version 2.1-beta