store_api/logstore/
entry.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 std::mem::size_of;
16
17use crate::logstore::provider::Provider;
18use crate::storage::RegionId;
19
20/// An entry's id.
21/// Different log store implementations may interpret the id to different meanings.
22pub type Id = u64;
23
24/// The [Entry::Naive] is used in RaftEngineLogStore and KafkaLogStore.
25///
26/// The [Entry::MultiplePart] contains multiple parts of data that split from a large entry, is used in KafkaLogStore,
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub enum Entry {
29    Naive(NaiveEntry),
30    MultiplePart(MultiplePartEntry),
31}
32
33impl Entry {
34    /// Into [NaiveEntry] if it's type of [Entry::Naive].
35    pub fn into_naive_entry(self) -> Option<NaiveEntry> {
36        match self {
37            Entry::Naive(entry) => Some(entry),
38            Entry::MultiplePart(_) => None,
39        }
40    }
41
42    /// Into [MultiplePartEntry] if it's type of [Entry::MultiplePart].
43    pub fn into_multiple_part_entry(self) -> Option<MultiplePartEntry> {
44        match self {
45            Entry::Naive(_) => None,
46            Entry::MultiplePart(entry) => Some(entry),
47        }
48    }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct NaiveEntry {
53    pub provider: Provider,
54    pub region_id: RegionId,
55    pub entry_id: Id,
56    pub data: Vec<u8>,
57}
58
59impl NaiveEntry {
60    /// Estimates the persisted size of the entry.
61    fn estimated_size(&self) -> usize {
62        size_of::<Self>() + self.data.len() * size_of::<u8>()
63    }
64}
65
66#[derive(Debug, Clone, PartialEq, Eq)]
67pub enum MultiplePartHeader {
68    First,
69    Middle(usize),
70    Last,
71}
72
73#[derive(Debug, Clone, PartialEq, Eq)]
74pub struct MultiplePartEntry {
75    pub provider: Provider,
76    pub region_id: RegionId,
77    pub entry_id: Id,
78    pub headers: Vec<MultiplePartHeader>,
79    pub parts: Vec<Vec<u8>>,
80}
81
82impl MultiplePartEntry {
83    fn is_complete(&self) -> bool {
84        self.headers.contains(&MultiplePartHeader::First)
85            && self.headers.contains(&MultiplePartHeader::Last)
86    }
87
88    /// Estimates the persisted size of the entry.
89    fn estimated_size(&self) -> usize {
90        size_of::<Self>()
91            + self
92                .parts
93                .iter()
94                .map(|data| data.len() * size_of::<u8>())
95                .sum::<usize>()
96            + self.headers.len() * size_of::<MultiplePartHeader>()
97    }
98}
99
100impl Entry {
101    /// Returns the [Provider]
102    pub fn provider(&self) -> &Provider {
103        match self {
104            Entry::Naive(entry) => &entry.provider,
105            Entry::MultiplePart(entry) => &entry.provider,
106        }
107    }
108
109    /// Returns the [RegionId]
110    pub fn region_id(&self) -> RegionId {
111        match self {
112            Entry::Naive(entry) => entry.region_id,
113            Entry::MultiplePart(entry) => entry.region_id,
114        }
115    }
116
117    /// Returns the [Id]
118    pub fn entry_id(&self) -> Id {
119        match self {
120            Entry::Naive(entry) => entry.entry_id,
121            Entry::MultiplePart(entry) => entry.entry_id,
122        }
123    }
124
125    /// Returns the [Id]
126    pub fn set_entry_id(&mut self, id: Id) {
127        match self {
128            Entry::Naive(entry) => entry.entry_id = id,
129            Entry::MultiplePart(entry) => entry.entry_id = id,
130        }
131    }
132
133    /// Returns true if it's a complete entry.
134    pub fn is_complete(&self) -> bool {
135        match self {
136            Entry::Naive(_) => true,
137            Entry::MultiplePart(entry) => entry.is_complete(),
138        }
139    }
140
141    pub fn into_bytes(self) -> Vec<u8> {
142        match self {
143            Entry::Naive(entry) => entry.data,
144            Entry::MultiplePart(entry) => entry.parts.concat(),
145        }
146    }
147
148    pub fn estimated_size(&self) -> usize {
149        match self {
150            Entry::Naive(entry) => entry.estimated_size(),
151            Entry::MultiplePart(entry) => entry.estimated_size(),
152        }
153    }
154}