common_meta/snapshot/
file.rs

1// Copyright 2023 Greptime Team
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
15use common_time::util::current_time_millis;
16use flexbuffers::{FlexbufferSerializer, Reader};
17use serde::{Deserialize, Serialize};
18use snafu::ResultExt;
19
20use crate::error::{
21    DeserializeFlexbuffersSnafu, ReadFlexbuffersSnafu, Result, SerializeFlexbuffersSnafu,
22};
23use crate::rpc::KeyValue;
24use crate::snapshot::FileFormat;
25
26/// The layout of the backup file.
27#[derive(Debug, PartialEq, Serialize, Deserialize)]
28pub(crate) struct Document {
29    metadata: Metadata,
30    content: Content,
31}
32
33impl Document {
34    /// Creates a new document.
35    pub fn new(metadata: Metadata, content: Content) -> Self {
36        Self { metadata, content }
37    }
38
39    fn serialize_to_flexbuffer(&self) -> Result<Vec<u8>> {
40        let mut builder = FlexbufferSerializer::new();
41        self.serialize(&mut builder)
42            .context(SerializeFlexbuffersSnafu)?;
43        Ok(builder.take_buffer())
44    }
45
46    /// Converts the [`Document`] to a bytes.
47    pub(crate) fn to_bytes(&self, format: &FileFormat) -> Result<Vec<u8>> {
48        match format {
49            FileFormat::FlexBuffers => self.serialize_to_flexbuffer(),
50        }
51    }
52
53    fn deserialize_from_flexbuffer(data: &[u8]) -> Result<Self> {
54        let reader = Reader::get_root(data).context(ReadFlexbuffersSnafu)?;
55        Document::deserialize(reader).context(DeserializeFlexbuffersSnafu)
56    }
57
58    /// Deserializes the [`Document`] from a bytes.
59    pub(crate) fn from_slice(format: &FileFormat, data: &[u8]) -> Result<Self> {
60        match format {
61            FileFormat::FlexBuffers => Self::deserialize_from_flexbuffer(data),
62        }
63    }
64
65    /// Converts the [`Document`] to a [`MetadataContent`].
66    pub(crate) fn into_metadata_content(self) -> Result<MetadataContent> {
67        match self.content {
68            Content::Metadata(metadata) => Ok(metadata),
69        }
70    }
71}
72
73/// The metadata of the backup file.
74#[derive(Debug, PartialEq, Serialize, Deserialize)]
75pub(crate) struct Metadata {
76    // UNIX_EPOCH in milliseconds.
77    created_timestamp_mills: i64,
78}
79
80impl Metadata {
81    /// Create a new metadata.
82    ///
83    /// The `created_timestamp_mills` will be the current time in milliseconds.
84    pub fn new() -> Self {
85        Self {
86            created_timestamp_mills: current_time_millis(),
87        }
88    }
89}
90
91/// The content of the backup file.
92#[derive(Debug, PartialEq, Serialize, Deserialize)]
93pub(crate) enum Content {
94    Metadata(MetadataContent),
95}
96
97/// The content of the backup file.
98#[derive(Debug, PartialEq, Serialize, Deserialize)]
99pub(crate) struct MetadataContent {
100    values: Vec<KeyValue>,
101}
102
103impl MetadataContent {
104    /// Create a new metadata content.
105    pub fn new(values: impl IntoIterator<Item = KeyValue>) -> Self {
106        Self {
107            values: values.into_iter().collect(),
108        }
109    }
110
111    /// Returns an iterator over the key-value pairs.
112    pub fn into_iter(self) -> impl Iterator<Item = KeyValue> {
113        self.values.into_iter()
114    }
115
116    /// Returns the key-value pairs as a vector.
117    pub fn values(self) -> Vec<KeyValue> {
118        self.values
119    }
120}
121
122#[cfg(test)]
123mod tests {
124    use super::*;
125
126    #[test]
127    fn test_document() {
128        let document = Document::new(
129            Metadata::new(),
130            Content::Metadata(MetadataContent::new(vec![KeyValue {
131                key: b"key".to_vec(),
132                value: b"value".to_vec(),
133            }])),
134        );
135
136        let bytes = document.to_bytes(&FileFormat::FlexBuffers).unwrap();
137        let document_deserialized = Document::from_slice(&FileFormat::FlexBuffers, &bytes).unwrap();
138        assert_eq!(
139            document.metadata.created_timestamp_mills,
140            document_deserialized.metadata.created_timestamp_mills
141        );
142        assert_eq!(document.content, document_deserialized.content);
143    }
144}