1
use crate::{
2
    address::Address,
3
    error::{PRes, PersyError},
4
    index::config::{format_segment_name_data, format_segment_name_meta, index_name_from_meta_segment},
5
    io::{InfallibleRead, InfallibleReadVarInt, InfallibleWrite, InfallibleWriteVarInt},
6
    persy::PersyImpl,
7
    snapshot::{SnapshotId, Snapshots},
8
    transaction::{Transaction, TxSegCheck},
9
};
10

11
use data_encoding::BASE32_DNSSEC;
12
pub use std::fs::OpenOptions;
13
use std::{fmt, str};
14
use unsigned_varint::{
15
    decode::{u32 as u32_vdec, u64 as u64_vdec},
16
    encode::{u32 as u32_venc, u32_buffer, u64 as u64_venc, u64_buffer},
17
};
18

19 1
fn write_id(f: &mut fmt::Formatter, id: u32) -> fmt::Result {
20 1
    let mut buffer = Vec::new();
21 1
    buffer.write_all(u32_venc(id, &mut u32_buffer()));
22 1
    buffer.push(0b0101_0101);
23 1
    write!(f, "{}", BASE32_DNSSEC.encode(&buffer))
24 1
}
25

26 1
fn read_id(s: &str) -> PRes<u32> {
27 1
    let bytes = BASE32_DNSSEC.decode(s.as_bytes())?;
28 1
    Ok(u32_vdec(&bytes).map_err(|_| PersyError::InvalidId(String::from(s)))?.0)
29 1
}
30

31 1
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug, Default)]
32
pub struct RecRef {
33 1
    pub page: u64,
34 1
    pub pos: u32,
35
}
36

37
impl RecRef {
38
    #[inline]
39 1
    pub(crate) fn new(page: u64, pos: u32) -> RecRef {
40 1
        RecRef { page, pos }
41 1
    }
42 1
    pub(crate) fn write(&self, write: &mut dyn InfallibleWrite) {
43 1
        write.write_varint_u64(self.page);
44 1
        write.write_varint_u32(self.pos);
45 1
    }
46 1
    pub(crate) fn read(read: &mut dyn InfallibleRead) -> RecRef {
47 1
        let page = read.read_varint_u64();
48 1
        let pos = read.read_varint_u32();
49 1
        Self::new(page, pos)
50 1
    }
51
}
52

53
impl fmt::Display for RecRef {
54 1
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55 1
        let mut buffer = Vec::new();
56 1
        buffer.write_all(u64_venc(self.page, &mut u64_buffer()));
57 1
        buffer.push(0b0101_0101);
58 1
        buffer.write_all(u32_venc(self.pos, &mut u32_buffer()));
59 1
        write!(f, "{}", BASE32_DNSSEC.encode(&buffer))
60 1
    }
61
}
62

63
impl std::str::FromStr for RecRef {
64
    type Err = PersyError;
65

66 1
    fn from_str(s: &str) -> Result<Self, Self::Err> {
67 1
        let bytes = BASE32_DNSSEC.decode(s.as_bytes())?;
68 1
        let (page, rest) = u64_vdec(&bytes).map_err(|_| PersyError::InvalidId(String::from(s)))?;
69 1
        let (pos, _) = u32_vdec(&rest[1..]).map_err(|_| PersyError::InvalidId(String::from(s)))?;
70 1
        Ok(RecRef::new(page, pos))
71 1
    }
72
}
73

74
/// Identifier of a persistent record, can be used for read, update or delete the record
75 1
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug)]
76 1
pub struct PersyId(pub(crate) RecRef);
77

78
impl fmt::Display for PersyId {
79 0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80 0
        write!(f, "{}", self.0)
81 0
    }
82
}
83

84
impl std::str::FromStr for PersyId {
85
    type Err = PersyError;
86

87
    fn from_str(s: &str) -> Result<Self, Self::Err> {
88
        Ok(PersyId(s.parse()?))
89
    }
90
}
91

92
/// Represents a looked-up segment
93
///
94
/// # Invalidation
95
/// When a segment is deleted, the corresponding SegmentId becomes invalid.
96
///
97
/// # Serialization
98
/// This type supports serialization,
99
/// It does NOT serialize to the segment name.
100 1
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
101
pub struct SegmentId {
102 1
    pub(crate) id: u32,
103
}
104

105
impl SegmentId {
106
    #[inline]
107 1
    pub(crate) fn new(id: u32) -> Self {
108 1
        SegmentId { id }
109 1
    }
110
}
111

112
pub trait ToSegmentId {
113
    fn to_segment_id(self, address: &Address) -> PRes<SegmentId>;
114
    fn to_segment_id_tx(self, persy: &PersyImpl, tx: &Transaction) -> PRes<(SegmentId, bool)>;
115
    fn to_segment_id_snapshot(self, snapshots: &Snapshots, snapshot: SnapshotId) -> PRes<SegmentId>;
116
}
117

118
impl ToSegmentId for &SegmentId {
119
    #[inline]
120 1
    fn to_segment_id(self, address: &Address) -> PRes<SegmentId> {
121 1
        self.clone().to_segment_id(address)
122 1
    }
123
    #[inline]
124 1
    fn to_segment_id_tx(self, persy: &PersyImpl, tx: &Transaction) -> PRes<(SegmentId, bool)> {
125 1
        self.clone().to_segment_id_tx(persy, tx)
126 1
    }
127
    #[inline]
128
    fn to_segment_id_snapshot(self, snapshots: &Snapshots, snapshot: SnapshotId) -> PRes<SegmentId> {
129
        self.clone().to_segment_id_snapshot(snapshots, snapshot)
130
    }
131
}
132

133
impl ToSegmentId for SegmentId {
134
    #[inline]
135 1
    fn to_segment_id(self, _address: &Address) -> PRes<SegmentId> {
136 1
        Ok(self)
137 1
    }
138
    #[inline]
139 1
    fn to_segment_id_tx(self, _persy: &PersyImpl, tx: &Transaction) -> PRes<(SegmentId, bool)> {
140
        // Is safe to check only if is created in tx, because a segment cannot be created and
141
        // dropped in the same tx
142 1
        let id = self.id;
143 1
        Ok((self, tx.segment_created_in_tx(id)))
144 1
    }
145
    #[inline]
146
    fn to_segment_id_snapshot(self, _snapshots: &Snapshots, _snapshot: SnapshotId) -> PRes<SegmentId> {
147
        Ok(self)
148
    }
149
}
150

151
impl<T: AsRef<str>> ToSegmentId for T {
152
    #[inline]
153 1
    fn to_segment_id(self, address: &Address) -> PRes<SegmentId> {
154 1
        address
155 1
            .segment_id(self.as_ref())?
156 1
            .map_or(Err(PersyError::SegmentNotFound), |id| Ok(SegmentId { id }))
157 1
    }
158
    #[inline]
159 1
    fn to_segment_id_tx(self, persy: &PersyImpl, tx: &Transaction) -> PRes<(SegmentId, bool)> {
160 1
        persy
161 1
            .check_segment_tx(tx, self.as_ref())
162 1
            .map(|(cr_in_tx, id)| (SegmentId::new(id), cr_in_tx))
163 1
    }
164 1
    fn to_segment_id_snapshot(self, snapshots: &Snapshots, snapshot: SnapshotId) -> PRes<SegmentId> {
165 1
        snapshots
166 1
            .solve_segment_id(snapshot, self.as_ref())?
167 1
            .ok_or(PersyError::SegmentNotFound)
168 1
    }
169
}
170

171
impl fmt::Display for SegmentId {
172 1
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
173 1
        write_id(f, self.id)
174 1
    }
175
}
176

177
impl std::str::FromStr for SegmentId {
178
    type Err = PersyError;
179

180 1
    fn from_str(s: &str) -> Result<Self, Self::Err> {
181 1
        Ok(SegmentId::new(read_id(s)?))
182 1
    }
183
}
184

185
/// Unique identifier of an index
186 1
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug)]
187
pub struct IndexId {
188 1
    meta: u32,
189 1
    data: u32,
190
}
191

192
pub trait ToIndexId {
193
    fn to_index_id(self, address: &Address) -> PRes<IndexId>;
194
    fn to_index_id_tx(self, persy: &PersyImpl, tx: &Transaction) -> PRes<(IndexId, bool)>;
195
    fn to_index_id_snapshot(self, snapshots: &Snapshots, snapshot: SnapshotId) -> PRes<IndexId>;
196
}
197

198
impl ToIndexId for &IndexId {
199
    #[inline]
200
    fn to_index_id(self, address: &Address) -> PRes<IndexId> {
201
        self.clone().to_index_id(address)
202
    }
203
    #[inline]
204
    fn to_index_id_tx(self, persy: &PersyImpl, tx: &Transaction) -> PRes<(IndexId, bool)> {
205
        self.clone().to_index_id_tx(persy, tx)
206
    }
207
    fn to_index_id_snapshot(self, snapshots: &Snapshots, snapshot: SnapshotId) -> PRes<IndexId> {
208
        self.clone().to_index_id_snapshot(snapshots, snapshot)
209
    }
210
}
211

212
impl ToIndexId for IndexId {
213
    #[inline]
214
    fn to_index_id(self, address: &Address) -> PRes<IndexId> {
215
        if self.data == 0 {
216
            // backward compatible serialization does not have data, find it by name convention
217
            let meta_name = address
218
                .segment_name_by_id(self.meta)?
219
                .ok_or(PersyError::IndexNotFound)?;
220
            let data_name = format_segment_name_data(&index_name_from_meta_segment(&meta_name));
221
            let data = address.segment_id(&data_name)?.ok_or(PersyError::IndexNotFound)?;
222
            Ok(IndexId::new(self.meta, data))
223
        } else {
224
            Ok(self)
225
        }
226
    }
227

228
    fn to_index_id_snapshot(self, snapshots: &Snapshots, snapshot: SnapshotId) -> PRes<IndexId> {
229
        if self.data == 0 {
230
            // backward compatible serialization does not have data, find it by name convention
231
            let meta_name = snapshots
232
                .solve_segment_name(snapshot, SegmentId::new(self.meta))?
233
                .ok_or(PersyError::IndexNotFound)?;
234
            let data_name = format_segment_name_data(&index_name_from_meta_segment(&meta_name));
235
            let data = snapshots
236
                .solve_segment_id(snapshot, &data_name)?
237
                .ok_or(PersyError::IndexNotFound)?;
238
            Ok(IndexId::new(self.meta, data.id))
239
        } else {
240
            Ok(self)
241
        }
242
    }
243

244
    #[inline]
245
    fn to_index_id_tx(self, persy: &PersyImpl, tx: &Transaction) -> PRes<(IndexId, bool)> {
246
        if self.data == 0 {
247
            // backward compatible serialization does not have data, find it by name convention
248
            let (meta_name, in_tx) = persy.segment_name_tx(tx, self.meta)?.ok_or(PersyError::IndexNotFound)?;
249
            let data_name = format_segment_name_data(&index_name_from_meta_segment(&meta_name));
250
            let data = if in_tx {
251
                if let TxSegCheck::CREATED(id) = tx.exists_segment(&data_name) {
252
                    id
253
                } else {
254
                    return Err(PersyError::IndexNotFound);
255
                }
256
            } else {
257
                persy
258
                    .address()
259
                    .segment_id(&data_name)?
260
                    .ok_or(PersyError::IndexNotFound)?
261
            };
262
            Ok((IndexId::new(self.meta, data), in_tx))
263
        } else {
264
            // Is safe to check only if is created in tx, because a segment cannot be created and
265
            // dropped in the same tx
266

267
            let id = self.meta;
268
            Ok((self, tx.segment_created_in_tx(id)))
269
        }
270
    }
271
}
272

273
impl<T: AsRef<str>> ToIndexId for T {
274
    #[inline]
275 1
    fn to_index_id(self, address: &Address) -> PRes<IndexId> {
276 1
        let meta_name = format_segment_name_meta(self.as_ref());
277 1
        let data_name = format_segment_name_data(self.as_ref());
278 1
        let meta = address.segment_id(&meta_name)?.ok_or(PersyError::IndexNotFound)?;
279 1
        let data = address.segment_id(&data_name)?.ok_or(PersyError::IndexNotFound)?;
280 1
        Ok(IndexId::new(meta, data))
281 1
    }
282 1
    fn to_index_id_snapshot(self, snapshots: &Snapshots, snapshot: SnapshotId) -> PRes<IndexId> {
283 1
        let meta_name = format_segment_name_meta(self.as_ref());
284 1
        let data_name = format_segment_name_data(self.as_ref());
285 1
        let meta = snapshots
286 1
            .solve_segment_id(snapshot, &meta_name)?
287 1
            .ok_or(PersyError::IndexNotFound)?;
288 1
        let data = snapshots
289 1
            .solve_segment_id(snapshot, &data_name)?
290 1
            .ok_or(PersyError::IndexNotFound)?;
291 1
        Ok(IndexId::new(meta.id, data.id))
292 1
    }
293
    #[inline]
294 1
    fn to_index_id_tx(self, persy: &PersyImpl, tx: &Transaction) -> PRes<(IndexId, bool)> {
295 1
        let meta_name = format_segment_name_meta(self.as_ref());
296 1
        let data_name = format_segment_name_data(self.as_ref());
297 1
        let (_, meta) = persy.check_segment_tx(tx, &meta_name)?;
298 1
        let (in_tx, data) = persy.check_segment_tx(tx, &data_name)?;
299 1
        Ok((IndexId::new(meta, data), in_tx))
300 1
    }
301
}
302
impl IndexId {
303 1
    pub(crate) fn new(meta: u32, data: u32) -> IndexId {
304 1
        IndexId { meta, data }
305 1
    }
306
}
307

308
impl fmt::Display for IndexId {
309 1
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
310 1
        let mut buffer = Vec::new();
311 1
        buffer.write_all(u32_venc(self.meta, &mut u32_buffer()));
312 1
        buffer.write_all(u32_venc(self.data, &mut u32_buffer()));
313 1
        buffer.push(0b0101_0101);
314 1
        write!(f, "{}", BASE32_DNSSEC.encode(&buffer))
315 1
    }
316
}
317

318
impl std::str::FromStr for IndexId {
319
    type Err = PersyError;
320

321 1
    fn from_str(s: &str) -> Result<Self, Self::Err> {
322 1
        let bytes = BASE32_DNSSEC.decode(s.as_bytes())?;
323 1
        let (meta, bytes) = u32_vdec(&bytes).map_err(|_| PersyError::InvalidId(String::from(s)))?;
324 1
        let data = if bytes.len() > 1 {
325 1
            let (d, _) = u32_vdec(&bytes).map_err(|_| PersyError::InvalidId(String::from(s)))?;
326 1
            d
327
        } else {
328 0
            0
329
        };
330 1
        Ok(IndexId::new(meta, data))
331 1
    }
332
}
333

334 1
pub fn index_id_to_segment_id_meta(id: &IndexId) -> SegmentId {
335 1
    SegmentId { id: id.meta }
336 1
}
337 1
pub fn index_id_to_segment_id_data(id: &IndexId) -> SegmentId {
338 1
    SegmentId { id: id.data }
339 1
}
340

341
#[cfg(test)]
342
mod tests {
343
    use super::{IndexId, RecRef, SegmentId};
344

345
    #[test]
346 1
    fn test_persy_id_string() {
347 1
        let id = RecRef::new(20, 30);
348 1
        let s = format!("{}", id);
349 1
        assert_eq!(s.parse::<RecRef>().ok(), Some(id));
350 1
    }
351

352
    #[test]
353 1
    fn test_persy_id_fixed_parse() {
354 1
        let id = RecRef::new(20, 30);
355 1
        assert_eq!("2hahs".parse::<RecRef>().ok(), Some(id));
356 1
    }
357

358
    #[test]
359 1
    fn test_persy_id_parse_failure() {
360 1
        let s = "ACCC";
361 1
        assert!(s.parse::<RecRef>().is_err());
362 1
    }
363

364
    #[test]
365 1
    fn test_segmend_id_string() {
366 1
        let id = SegmentId::new(20);
367 1
        let s = format!("{}", id);
368 1
        assert_eq!(s.parse::<SegmentId>().ok(), Some(id));
369 1
    }
370

371
    #[test]
372 1
    fn test_segment_id_parse_failure() {
373 1
        let s = "ACCC";
374 1
        assert!(s.parse::<SegmentId>().is_err());
375 1
    }
376

377
    #[test]
378 1
    fn test_index_id_string() {
379 1
        let id = IndexId::new(20, 30);
380 1
        let s = format!("{}", id);
381 1
        assert_eq!(s.parse::<IndexId>().ok(), Some(id));
382 1
    }
383

384
    #[test]
385 1
    fn test_index_id_parse_failure() {
386 1
        let s = "ACCC";
387 1
        assert!(s.parse::<IndexId>().is_err());
388 1
    }
389
}

Read our documentation on viewing source code .

Loading