risingwave_backup/
lib.rs

1// Copyright 2025 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#![allow(clippy::derive_partial_eq_without_eq)]
16#![feature(trait_alias)]
17#![feature(type_alias_impl_trait)]
18#![feature(custom_test_frameworks)]
19#![feature(map_try_insert)]
20#![feature(btree_extract_if)]
21#![feature(let_chains)]
22#![feature(error_generic_member_access)]
23#![cfg_attr(coverage, feature(coverage_attribute))]
24
25pub mod error;
26pub mod meta_snapshot;
27pub mod meta_snapshot_v1;
28pub mod meta_snapshot_v2;
29pub mod storage;
30
31use std::collections::{HashMap, HashSet};
32
33use itertools::Itertools;
34use risingwave_common::RW_VERSION;
35use risingwave_hummock_sdk::state_table_info::StateTableInfo;
36use risingwave_hummock_sdk::version::HummockVersion;
37use risingwave_hummock_sdk::{HummockSstableObjectId, HummockVersionId};
38use risingwave_pb::backup_service::{PbMetaSnapshotManifest, PbMetaSnapshotMetadata};
39use serde::{Deserialize, Serialize};
40
41use crate::error::{BackupError, BackupResult};
42
43pub type MetaSnapshotId = u64;
44pub type MetaBackupJobId = u64;
45
46/// `MetaSnapshotMetadata` is metadata of `MetaSnapshot`.
47#[derive(Serialize, Deserialize, Clone)]
48pub struct MetaSnapshotMetadata {
49    pub id: MetaSnapshotId,
50    pub hummock_version_id: HummockVersionId,
51    pub ssts: HashSet<HummockSstableObjectId>,
52    #[serde(default)]
53    pub format_version: u32,
54    pub remarks: Option<String>,
55    #[serde(default)]
56    pub state_table_info: HashMap<u32, StateTableInfo>,
57    pub rw_version: Option<String>,
58}
59
60impl MetaSnapshotMetadata {
61    pub fn new(
62        id: MetaSnapshotId,
63        v: &HummockVersion,
64        format_version: u32,
65        remarks: Option<String>,
66    ) -> Self {
67        Self {
68            id,
69            hummock_version_id: v.id,
70            ssts: v.get_object_ids(false),
71            format_version,
72            remarks,
73            state_table_info: v
74                .state_table_info
75                .info()
76                .iter()
77                .map(|(id, info)| (id.table_id, info.into()))
78                .collect(),
79            rw_version: Some(RW_VERSION.to_owned()),
80        }
81    }
82}
83
84/// `MetaSnapshotManifest` is the source of truth for valid `MetaSnapshot`.
85#[derive(Serialize, Deserialize, Default, Clone)]
86pub struct MetaSnapshotManifest {
87    pub manifest_id: u64,
88    pub snapshot_metadata: Vec<MetaSnapshotMetadata>,
89}
90
91pub fn xxhash64_checksum(data: &[u8]) -> u64 {
92    twox_hash::XxHash64::oneshot(0, data)
93}
94
95pub fn xxhash64_verify(data: &[u8], checksum: u64) -> BackupResult<()> {
96    let data_checksum = xxhash64_checksum(data);
97    if data_checksum != checksum {
98        return Err(BackupError::ChecksumMismatch {
99            expected: checksum,
100            found: data_checksum,
101        });
102    }
103    Ok(())
104}
105
106impl From<&MetaSnapshotMetadata> for PbMetaSnapshotMetadata {
107    fn from(m: &MetaSnapshotMetadata) -> Self {
108        Self {
109            id: m.id,
110            hummock_version_id: m.hummock_version_id.to_u64(),
111            format_version: Some(m.format_version),
112            remarks: m.remarks.clone(),
113            state_table_info: m
114                .state_table_info
115                .iter()
116                .map(|(t, i)| (*t, i.into()))
117                .collect(),
118            rw_version: m.rw_version.clone(),
119        }
120    }
121}
122
123impl From<&MetaSnapshotManifest> for PbMetaSnapshotManifest {
124    fn from(m: &MetaSnapshotManifest) -> Self {
125        Self {
126            manifest_id: m.manifest_id,
127            snapshot_metadata: m.snapshot_metadata.iter().map_into().collect_vec(),
128        }
129    }
130}