bitcoinleveldb_log/writer.rs
1crate::ix!();
2
3//-------------------------------------------[.cpp/bitcoin/src/leveldb/db/log_writer.h]
4//-------------------------------------------[.cpp/bitcoin/src/leveldb/db/log_writer.cc]
5
6pub fn init_type_crc(type_crc: *mut u32) {
7
8 todo!();
9 /*
10 for (int i = 0; i <= kMaxRecordType; i++) {
11 char t = static_cast<char>(i);
12 type_crc[i] = crc32c::Value(&t, 1);
13 }
14 */
15}
16
17pub struct LogWriter {
18
19 dest: Rc<RefCell<dyn WritableFile>>,
20
21 /**
22 | Current offset in block
23 |
24 */
25 block_offset: i32,
26
27 /**
28 | crc32c values for all supported record
29 | types. These are pre-computed to reduce
30 | the overhead of computing the crc of
31 | the record type stored in the header.
32 |
33 */
34 type_crc: [u32; LOG_MAX_RECORD_TYPE as usize + 1],
35}
36
37
38impl LogWriter {
39
40 /**
41 | Create a writer that will append data to
42 | "*dest".
43 |
44 | "*dest" must have initial length
45 | "dest_length".
46 |
47 | "*dest" must remain live while this LogWriter is
48 | in use.
49 */
50 pub fn new(
51 dest: Rc<RefCell<dyn WritableFile>>,
52 dest_length: u64) -> Self {
53
54 todo!();
55 /*
56 : dest_(dest), block_offset_(dest_length % kBlockSize)
57 InitTypeCrc(type_crc_);
58 */
59 }
60
61 pub fn add_record(&mut self, slice: &Slice) -> crate::Status {
62
63 todo!();
64 /*
65 const char* ptr = slice.data();
66 size_t left = slice.size();
67
68 // Fragment the record if necessary and emit it. Note that if slice
69 // is empty, we still want to iterate once to emit a single
70 // zero-length record
71 Status s;
72 bool begin = true;
73 do {
74 const int leftover = kBlockSize - block_offset_;
75 assert(leftover >= 0);
76 if (leftover < kHeaderSize) {
77 // Switch to a new block
78 if (leftover > 0) {
79 // Fill the trailer (literal below relies on kHeaderSize being 7)
80 const_assert(kHeaderSize == 7, "");
81 dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover));
82 }
83 block_offset_ = 0;
84 }
85
86 // Invariant: we never leave < kHeaderSize bytes in a block.
87 assert(kBlockSize - block_offset_ - kHeaderSize >= 0);
88
89 const size_t avail = kBlockSize - block_offset_ - kHeaderSize;
90 const size_t fragment_length = (left < avail) ? left : avail;
91
92 RecordType type;
93 const bool end = (left == fragment_length);
94 if (begin && end) {
95 type = kFullType;
96 } else if (begin) {
97 type = kFirstType;
98 } else if (end) {
99 type = kLastType;
100 } else {
101 type = kMiddleType;
102 }
103
104 s = EmitPhysicalRecord(type, ptr, fragment_length);
105 ptr += fragment_length;
106 left -= fragment_length;
107 begin = false;
108 } while (s.ok() && left > 0);
109 return s;
110 */
111 }
112
113 pub fn emit_physical_record(&mut self,
114 t: LogRecordType,
115 ptr: *const u8,
116 length: usize) -> Status {
117
118 todo!();
119 /*
120 assert(length <= 0xffff); // Must fit in two bytes
121 assert(block_offset_ + kHeaderSize + length <= kBlockSize);
122
123 // Format the header
124 char buf[kHeaderSize];
125 buf[4] = static_cast<char>(length & 0xff);
126 buf[5] = static_cast<char>(length >> 8);
127 buf[6] = static_cast<char>(t);
128
129 // Compute the crc of the record type and the payload.
130 uint32_t crc = crc32c::Extend(type_crc_[t], ptr, length);
131 crc = crc32c::Mask(crc); // Adjust for storage
132 EncodeFixed32(buf, crc);
133
134 // Write the header and the payload
135 Status s = dest_->Append(Slice(buf, kHeaderSize));
136 if (s.ok()) {
137 s = dest_->Append(Slice(ptr, length));
138 if (s.ok()) {
139 s = dest_->Flush();
140 }
141 }
142 block_offset_ += kHeaderSize + length;
143 return s;
144 */
145 }
146}