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}