mz_storage_types/
instances.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! Types related to storage instances.
11
12use std::fmt;
13use std::str::FromStr;
14
15use anyhow::bail;
16use serde::{Deserialize, Serialize};
17use tracing::error;
18
19/// Identifier of a storage instance.
20#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
21pub enum StorageInstanceId {
22    /// A system storage instance.
23    System(u64),
24    /// A user storage instance.
25    User(u64),
26}
27
28impl StorageInstanceId {
29    /// Creates a new `StorageInstanceId` in the system namespace. The top 16 bits of `id` must be
30    /// 0, because this ID is packed into 48 bits of
31    /// [`mz_repr::GlobalId::IntrospectionSourceIndex`].
32    pub fn system(id: u64) -> Option<Self> {
33        Self::new(id, Self::System)
34    }
35
36    /// Creates a new `StorageInstanceId` in the user namespace. The top 16 bits of `id` must be
37    /// 0, because this ID is packed into 48 bits of
38    /// [`mz_repr::GlobalId::IntrospectionSourceIndex`].
39    pub fn user(id: u64) -> Option<Self> {
40        Self::new(id, Self::User)
41    }
42
43    fn new(id: u64, variant: fn(u64) -> Self) -> Option<Self> {
44        const MASK: u64 = 0xFFFF << 48;
45        const WARN_MASK: u64 = 1 << 47;
46        if MASK & id == 0 {
47            if WARN_MASK & id != 0 {
48                error!("{WARN_MASK} or more `StorageInstanceId`s allocated, we will run out soon");
49            }
50            Some(variant(id))
51        } else {
52            None
53        }
54    }
55
56    pub fn inner_id(&self) -> u64 {
57        match self {
58            StorageInstanceId::System(id) | StorageInstanceId::User(id) => *id,
59        }
60    }
61
62    pub fn is_user(&self) -> bool {
63        matches!(self, Self::User(_))
64    }
65
66    pub fn is_system(&self) -> bool {
67        matches!(self, Self::System(_))
68    }
69}
70
71impl FromStr for StorageInstanceId {
72    type Err = anyhow::Error;
73
74    fn from_str(s: &str) -> Result<Self, Self::Err> {
75        if s.len() < 2 {
76            bail!("couldn't parse compute instance id {}", s);
77        }
78        let val: u64 = s[1..].parse()?;
79        match s.chars().next().unwrap() {
80            's' => Ok(Self::System(val)),
81            'u' => Ok(Self::User(val)),
82            _ => bail!("couldn't parse compute instance id {}", s),
83        }
84    }
85}
86
87impl fmt::Display for StorageInstanceId {
88    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89        match self {
90            Self::System(id) => write!(f, "s{}", id),
91            Self::User(id) => write!(f, "u{}", id),
92        }
93    }
94}