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 370721 : #[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 7029 : pub fn none() -> Self {
40 7029 : Self::None
41 7029 : }
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 36 : pub fn new(v: u32) -> Self {
49 36 : Self::Valid(v)
50 36 : }
51 :
52 690380 : pub fn is_none(&self) -> bool {
53 690380 : matches!(self, Self::None)
54 690380 : }
55 :
56 30602 : pub fn get_suffix(&self) -> String {
57 30602 : match self {
58 657 : Self::Valid(v) => {
59 657 : format!("-{:08x}", v)
60 : }
61 29945 : Self::None => "".into(),
62 : Self::Broken => {
63 0 : panic!("Tried to use a broken generation");
64 : }
65 : }
66 30602 : }
67 : }
68 :
69 : impl Serialize for Generation {
70 : fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
71 : where
72 : S: serde::Serializer,
73 : {
74 1030 : if let Self::Valid(v) = self {
75 1030 : v.serialize(serializer)
76 : } else {
77 : // We should never be asked to serialize a None or Broken. Structures
78 : // that include an optional generation should convert None to an
79 : // Option<Generation>::None
80 0 : Err(serde::ser::Error::custom(
81 0 : "Tried to serialize invalid generation ({self})",
82 0 : ))
83 : }
84 1030 : }
85 : }
86 :
87 : impl<'de> Deserialize<'de> for Generation {
88 12 : fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
89 12 : where
90 12 : D: serde::Deserializer<'de>,
91 12 : {
92 12 : Ok(Self::Valid(u32::deserialize(deserializer)?))
93 12 : }
94 : }
95 :
96 : // We intentionally do not implement Display for Generation, to reduce the
97 : // risk of a bug where the generation is used in a format!() string directly
98 : // instead of using get_suffix().
99 : impl Debug for Generation {
100 7712 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101 7712 : match self {
102 0 : Self::Valid(v) => {
103 0 : write!(f, "{:08x}", v)
104 : }
105 : Self::None => {
106 7712 : write!(f, "<none>")
107 : }
108 : Self::Broken => {
109 0 : write!(f, "<broken>")
110 : }
111 : }
112 7712 : }
113 : }
|