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 703686 : #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
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 926 : pub fn none() -> Self {
40 926 : Self::None
41 926 : }
42 :
43 : // Create a new generation that will panic if you try to use get_suffix
44 0 : pub fn broken() -> Self {
45 0 : Self::Broken
46 0 : }
47 :
48 3691 : pub fn new(v: u32) -> Self {
49 3691 : Self::Valid(v)
50 3691 : }
51 :
52 1251691 : pub fn is_none(&self) -> bool {
53 1251691 : matches!(self, Self::None)
54 1251691 : }
55 :
56 : #[track_caller]
57 90516 : pub fn get_suffix(&self) -> String {
58 90516 : match self {
59 88814 : Self::Valid(v) => {
60 88814 : format!("-{:08x}", v)
61 : }
62 1702 : Self::None => "".into(),
63 : Self::Broken => {
64 0 : panic!("Tried to use a broken generation");
65 : }
66 : }
67 90516 : }
68 :
69 : /// `suffix` is the part after "-" in a key
70 : ///
71 : /// Returns None if parsing was unsuccessful
72 671 : pub fn parse_suffix(suffix: &str) -> Option<Generation> {
73 671 : u32::from_str_radix(suffix, 16).map(Generation::new).ok()
74 671 : }
75 :
76 : #[track_caller]
77 451 : pub fn previous(&self) -> Generation {
78 451 : match self {
79 451 : Self::Valid(n) => {
80 451 : 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 0 : Self::None
84 : } else {
85 451 : Self::Valid(n - 1)
86 : }
87 : }
88 0 : Self::None => Self::None,
89 0 : Self::Broken => panic!("Attempted to use a broken generation"),
90 : }
91 451 : }
92 :
93 2 : pub fn next(&self) -> Generation {
94 2 : match self {
95 2 : Self::Valid(n) => Self::Valid(*n + 1),
96 0 : Self::None => Self::Valid(1),
97 0 : Self::Broken => panic!("Attempted to use a broken generation"),
98 : }
99 2 : }
100 :
101 4449 : pub fn into(self) -> Option<u32> {
102 4449 : if let Self::Valid(v) = self {
103 4449 : Some(v)
104 : } else {
105 0 : None
106 : }
107 4449 : }
108 : }
109 :
110 : impl Serialize for Generation {
111 608828 : fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
112 608828 : where
113 608828 : S: serde::Serializer,
114 608828 : {
115 608828 : if let Self::Valid(v) = self {
116 608828 : 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 0 : Err(serde::ser::Error::custom(
122 0 : "Tried to serialize invalid generation ({self})",
123 0 : ))
124 : }
125 608828 : }
126 : }
127 :
128 : impl<'de> Deserialize<'de> for Generation {
129 59482 : fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
130 59482 : where
131 59482 : D: serde::Deserializer<'de>,
132 59482 : {
133 59482 : Ok(Self::Valid(u32::deserialize(deserializer)?))
134 59482 : }
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 29390 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142 29390 : match self {
143 28831 : Self::Valid(v) => {
144 28831 : write!(f, "{:08x}", v)
145 : }
146 : Self::None => {
147 559 : write!(f, "<none>")
148 : }
149 : Self::Broken => {
150 0 : write!(f, "<broken>")
151 : }
152 : }
153 29390 : }
154 : }
155 :
156 : #[cfg(test)]
157 : mod test {
158 : use super::*;
159 :
160 2 : #[test]
161 2 : fn generation_gt() {
162 : // Important that a None generation compares less than a valid one, during upgrades from
163 : // pre-generation systems.
164 2 : assert!(Generation::none() < Generation::new(0));
165 2 : assert!(Generation::none() < Generation::new(1));
166 2 : }
167 : }
|