TLA Line data Source code
1 : use std::fmt::Debug;
2 :
3 : use serde::{Deserialize, Serialize};
4 :
5 : /// Tenant generations are used to provide split-brain safety and allow
6 : /// multiple pageservers to attach the same tenant concurrently.
7 : ///
8 : /// See docs/rfcs/025-generation-numbers.md for detail on how generation
9 : /// numbers are used.
10 CBC 470495 : #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord)]
11 : pub enum Generation {
12 : // Generations with this magic value will not add a suffix to S3 keys, and will not
13 : // be included in persisted index_part.json. This value is only to be used
14 : // during migration from pre-generation metadata to generation-aware metadata,
15 : // and should eventually go away.
16 : //
17 : // A special Generation is used rather than always wrapping Generation in an Option,
18 : // so that code handling generations doesn't have to be aware of the legacy
19 : // case everywhere it touches a generation.
20 : None,
21 : // Generations with this magic value may never be used to construct S3 keys:
22 : // we will panic if someone tries to. This is for Tenants in the "Broken" state,
23 : // so that we can satisfy their constructor with a Generation without risking
24 : // a code bug using it in an S3 write (broken tenants should never write)
25 : Broken,
26 : Valid(u32),
27 : }
28 :
29 : /// The Generation type represents a number associated with a Tenant, which
30 : /// increments every time the tenant is attached to a new pageserver, or
31 : /// an attached pageserver restarts.
32 : ///
33 : /// It is included as a suffix in S3 keys, as a protection against split-brain
34 : /// scenarios where pageservers might otherwise issue conflicting writes to
35 : /// remote storage
36 : impl Generation {
37 : /// Create a new Generation that represents a legacy key format with
38 : /// no generation suffix
39 7879 : pub fn none() -> Self {
40 7879 : Self::None
41 7879 : }
42 :
43 : // Create a new generation that will panic if you try to use get_suffix
44 UBC 0 : pub fn broken() -> Self {
45 0 : Self::Broken
46 0 : }
47 :
48 CBC 102 : pub fn new(v: u32) -> Self {
49 102 : Self::Valid(v)
50 102 : }
51 :
52 852207 : pub fn is_none(&self) -> bool {
53 852207 : matches!(self, Self::None)
54 852207 : }
55 :
56 : #[track_caller]
57 46151 : pub fn get_suffix(&self) -> String {
58 46151 : match self {
59 8125 : Self::Valid(v) => {
60 8125 : format!("-{:08x}", v)
61 : }
62 38026 : Self::None => "".into(),
63 : Self::Broken => {
64 UBC 0 : panic!("Tried to use a broken generation");
65 : }
66 : }
67 CBC 46151 : }
68 :
69 : /// `suffix` is the part after "-" in a key
70 : ///
71 : /// Returns None if parsing was unsuccessful
72 11 : pub fn parse_suffix(suffix: &str) -> Option<Generation> {
73 11 : u32::from_str_radix(suffix, 16).map(Generation::new).ok()
74 11 : }
75 :
76 : #[track_caller]
77 24 : pub fn previous(&self) -> Generation {
78 24 : match self {
79 24 : Self::Valid(n) => {
80 24 : if *n == 0 {
81 : // Since a tenant may be upgraded from a pre-generations state, interpret the "previous" generation
82 : // to 0 as being "no generation".
83 UBC 0 : Self::None
84 : } else {
85 CBC 24 : Self::Valid(n - 1)
86 : }
87 : }
88 UBC 0 : Self::None => Self::None,
89 0 : Self::Broken => panic!("Attempted to use a broken generation"),
90 : }
91 CBC 24 : }
92 :
93 1 : pub fn next(&self) -> Generation {
94 1 : match self {
95 1 : Self::Valid(n) => Self::Valid(*n + 1),
96 UBC 0 : Self::None => Self::Valid(1),
97 0 : Self::Broken => panic!("Attempted to use a broken generation"),
98 : }
99 CBC 1 : }
100 :
101 : pub fn into(self) -> Option<u32> {
102 10 : if let Self::Valid(v) = self {
103 10 : Some(v)
104 : } else {
105 UBC 0 : None
106 : }
107 CBC 10 : }
108 : }
109 :
110 : impl Serialize for Generation {
111 : fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
112 : where
113 : S: serde::Serializer,
114 : {
115 28292 : if let Self::Valid(v) = self {
116 28292 : v.serialize(serializer)
117 : } else {
118 : // We should never be asked to serialize a None or Broken. Structures
119 : // that include an optional generation should convert None to an
120 : // Option<Generation>::None
121 UBC 0 : Err(serde::ser::Error::custom(
122 0 : "Tried to serialize invalid generation ({self})",
123 0 : ))
124 : }
125 CBC 28292 : }
126 : }
127 :
128 : impl<'de> Deserialize<'de> for Generation {
129 2060 : fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
130 2060 : where
131 2060 : D: serde::Deserializer<'de>,
132 2060 : {
133 2060 : Ok(Self::Valid(u32::deserialize(deserializer)?))
134 2060 : }
135 : }
136 :
137 : // We intentionally do not implement Display for Generation, to reduce the
138 : // risk of a bug where the generation is used in a format!() string directly
139 : // instead of using get_suffix().
140 : impl Debug for Generation {
141 4320 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142 4320 : match self {
143 48 : Self::Valid(v) => {
144 48 : write!(f, "{:08x}", v)
145 : }
146 : Self::None => {
147 4272 : write!(f, "<none>")
148 : }
149 : Self::Broken => {
150 UBC 0 : write!(f, "<broken>")
151 : }
152 : }
153 CBC 4320 : }
154 : }
|