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(error_generic_member_access)]
21#![feature(coverage_attribute)]
22
23pub mod error;
24pub mod meta_snapshot;
25pub mod meta_snapshot_v1;
26pub mod meta_snapshot_v2;
27pub mod storage;
28
29use std::collections::{HashMap, HashSet};
30
31use itertools::Itertools;
32use risingwave_common::RW_VERSION;
33use risingwave_hummock_sdk::state_table_info::StateTableInfo;
34use risingwave_hummock_sdk::version::HummockVersion;
35use risingwave_hummock_sdk::{HummockRawObjectId, HummockVersionId};
36use risingwave_pb::backup_service::{PbMetaSnapshotManifest, PbMetaSnapshotMetadata};
37use risingwave_pb::id::TableId;
38use serde::{Deserialize, Serialize};
39
40use crate::error::{BackupError, BackupResult};
41
42pub type MetaSnapshotId = u64;
43pub type MetaBackupJobId = u64;
44
45/// `MetaSnapshotMetadata` is metadata of `MetaSnapshot`.
46#[derive(Serialize, Deserialize, Clone)]
47pub struct MetaSnapshotMetadata {
48    pub id: MetaSnapshotId,
49    pub hummock_version_id: HummockVersionId,
50    // rename to `ssts` for backward compatibility
51    #[serde(rename = "ssts")]
52    pub objects: HashSet<HummockRawObjectId>,
53    #[serde(default)]
54    pub format_version: u32,
55    pub remarks: Option<String>,
56    #[serde(default)]
57    pub state_table_info: HashMap<TableId, StateTableInfo>,
58    pub rw_version: Option<String>,
59}
60
61impl MetaSnapshotMetadata {
62    pub fn new(
63        id: MetaSnapshotId,
64        v: &HummockVersion,
65        format_version: u32,
66        remarks: Option<String>,
67    ) -> Self {
68        Self {
69            id,
70            hummock_version_id: v.id,
71            objects: v
72                .get_object_ids(false)
73                .map(|object_id| object_id.as_raw())
74                .collect(),
75            format_version,
76            remarks,
77            state_table_info: v
78                .state_table_info
79                .info()
80                .iter()
81                .map(|(id, info)| (*id, info.into()))
82                .collect(),
83            rw_version: Some(RW_VERSION.to_owned()),
84        }
85    }
86}
87
88/// `MetaSnapshotManifest` is the source of truth for valid `MetaSnapshot`.
89#[derive(Serialize, Deserialize, Default, Clone)]
90pub struct MetaSnapshotManifest {
91    pub manifest_id: u64,
92    pub snapshot_metadata: Vec<MetaSnapshotMetadata>,
93}
94
95pub fn xxhash64_checksum(data: &[u8]) -> u64 {
96    twox_hash::XxHash64::oneshot(0, data)
97}
98
99pub fn xxhash64_verify(data: &[u8], checksum: u64) -> BackupResult<()> {
100    let data_checksum = xxhash64_checksum(data);
101    if data_checksum != checksum {
102        return Err(BackupError::ChecksumMismatch {
103            expected: checksum,
104            found: data_checksum,
105        });
106    }
107    Ok(())
108}
109
110impl From<&MetaSnapshotMetadata> for PbMetaSnapshotMetadata {
111    fn from(m: &MetaSnapshotMetadata) -> Self {
112        Self {
113            id: m.id,
114            hummock_version_id: m.hummock_version_id.to_u64(),
115            format_version: Some(m.format_version),
116            remarks: m.remarks.clone(),
117            state_table_info: m
118                .state_table_info
119                .iter()
120                .map(|(t, i)| ((*t), i.into()))
121                .collect(),
122            rw_version: m.rw_version.clone(),
123        }
124    }
125}
126
127impl From<&MetaSnapshotManifest> for PbMetaSnapshotManifest {
128    fn from(m: &MetaSnapshotManifest) -> Self {
129        Self {
130            manifest_id: m.manifest_id,
131            snapshot_metadata: m.snapshot_metadata.iter().map_into().collect_vec(),
132        }
133    }
134}