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