1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! Segment error types.
use thiserror::Error;
/// Errors that can occur during segment operations.
#[derive(Debug, Error)]
pub enum SegmentError {
/// The segment file is corrupt or has an invalid format.
#[error("corrupt segment file: {detail}")]
CorruptFile {
/// Human-readable description of the corruption.
detail: String,
},
/// Invalid magic bytes in header or footer.
#[error("invalid magic bytes: expected CXSG")]
InvalidMagic,
/// `CRC32c` checksum mismatch.
#[error("checksum mismatch: expected {expected:#010x}, got {actual:#010x}")]
ChecksumMismatch {
/// Expected checksum value.
expected: u32,
/// Actual computed checksum.
actual: u32,
},
/// Unsupported segment version.
#[error("unsupported segment version: {version}")]
UnsupportedVersion {
/// The version number found in the file.
version: u16,
},
/// An I/O error occurred.
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
/// An encoding error occurred.
#[error("encoding error: {0}")]
Encoding(#[from] chronix_encoding::EncodingError),
/// The segment writer has already been finalized.
#[error("segment writer already finalized")]
AlreadyFinalized,
/// No data has been written to the segment.
#[error("no data written to segment")]
EmptySegment,
/// Row group index is out of range.
#[error("row group index {index} out of range (max: {max})")]
RowGroupOutOfRange {
/// Requested row group index.
index: usize,
/// Maximum valid row group index.
max: usize,
},
/// Column not found.
/// An encrypted column cannot be read because its key is not available.
///
/// **Not** [`CorruptFile`](Self::CorruptFile), which is what this used to
/// be: nothing is wrong with the bytes. The deployment is missing a key,
/// and the two have completely different next steps — one is "restore
/// from a backup", the other is "set the environment variable". The
/// commonest way to arrive here is restoring an encrypted backup onto a
/// machine the key was never given to.
#[error(
"column '{column}' is encrypted with key '{key_id}', which this database has no \
key for — set it under [database.field_encryption] and restart"
)]
MissingEncryptionKey {
/// The column that cannot be read.
column: String,
/// The key id its blocks were written under.
key_id: String,
},
/// The writer was asked for something the format cannot honestly do.
///
/// Distinct from [`CorruptFile`](Self::CorruptFile): nothing is wrong
/// with the data, the *configuration* is wrong — declaring a tag column
/// encrypted, for instance, which the format would accept and which
/// would publish the value in the sidecar beside it.
#[error("invalid segment writer configuration: {detail}")]
InvalidConfiguration {
/// What was asked for, and why it cannot be done.
detail: String,
},
/// A requested column is not in the segment.
#[error("column not found: {name}")]
ColumnNotFound {
/// The requested column name.
name: String,
},
}
/// A specialized `Result` type for segment operations.
pub type Result<T> = std::result::Result<T, SegmentError>;