LCOV - code coverage report
Current view: top level - src/leveldb/db - log_writer.cc (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 86.7 % 60 52
Test Date: 2026-02-04 04:43:42 Functions: 83.3 % 6 5
Branches: 65.2 % 46 30

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
       2                 :             : // Use of this source code is governed by a BSD-style license that can be
       3                 :             : // found in the LICENSE file. See the AUTHORS file for names of contributors.
       4                 :             : 
       5                 :             : #include "db/log_writer.h"
       6                 :             : 
       7                 :             : #include <stdint.h>
       8                 :             : 
       9                 :             : #include "leveldb/env.h"
      10                 :             : #include "util/coding.h"
      11                 :             : #include "util/crc32c.h"
      12                 :             : 
      13                 :             : namespace leveldb {
      14                 :             : namespace log {
      15                 :             : 
      16                 :        1400 : static void InitTypeCrc(uint32_t* type_crc) {
      17         [ +  + ]:        8400 :   for (int i = 0; i <= kMaxRecordType; i++) {
      18                 :        7000 :     char t = static_cast<char>(i);
      19                 :        7000 :     type_crc[i] = crc32c::Value(&t, 1);
      20                 :             :   }
      21                 :        1400 : }
      22                 :             : 
      23                 :        1400 : Writer::Writer(WritableFile* dest) : dest_(dest), block_offset_(0) {
      24                 :        1400 :   InitTypeCrc(type_crc_);
      25                 :        1400 : }
      26                 :             : 
      27                 :           0 : Writer::Writer(WritableFile* dest, uint64_t dest_length)
      28                 :           0 :     : dest_(dest), block_offset_(dest_length % kBlockSize) {
      29                 :           0 :   InitTypeCrc(type_crc_);
      30                 :           0 : }
      31                 :             : 
      32                 :        1400 : Writer::~Writer() = default;
      33                 :             : 
      34                 :        2802 : Status Writer::AddRecord(const Slice& slice) {
      35                 :        2802 :   const char* ptr = slice.data();
      36                 :        2802 :   size_t left = slice.size();
      37                 :             : 
      38                 :             :   // Fragment the record if necessary and emit it.  Note that if slice
      39                 :             :   // is empty, we still want to iterate once to emit a single
      40                 :             :   // zero-length record
      41                 :        2802 :   Status s;
      42                 :        2802 :   bool begin = true;
      43                 :        3051 :   do {
      44                 :        3051 :     const int leftover = kBlockSize - block_offset_;
      45         [ -  + ]:        3051 :     assert(leftover >= 0);
      46         [ +  + ]:        3051 :     if (leftover < kHeaderSize) {
      47                 :             :       // Switch to a new block
      48         [ -  + ]:         249 :       if (leftover > 0) {
      49                 :             :         // Fill the trailer (literal below relies on kHeaderSize being 7)
      50                 :           0 :         static_assert(kHeaderSize == 7, "");
      51         [ #  # ]:           0 :         dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover));
      52                 :             :       }
      53                 :         249 :       block_offset_ = 0;
      54                 :             :     }
      55                 :             : 
      56                 :             :     // Invariant: we never leave < kHeaderSize bytes in a block.
      57         [ -  + ]:        3051 :     assert(kBlockSize - block_offset_ - kHeaderSize >= 0);
      58                 :             : 
      59                 :        3051 :     const size_t avail = kBlockSize - block_offset_ - kHeaderSize;
      60         [ +  + ]:        3051 :     const size_t fragment_length = (left < avail) ? left : avail;
      61                 :             : 
      62                 :        3051 :     RecordType type;
      63                 :        3051 :     const bool end = (left == fragment_length);
      64         [ +  + ]:        3051 :     if (begin && end) {
      65                 :             :       type = kFullType;
      66         [ +  + ]:         293 :     } else if (begin) {
      67                 :             :       type = kFirstType;
      68         [ +  + ]:         249 :     } else if (end) {
      69                 :             :       type = kLastType;
      70                 :             :     } else {
      71                 :         205 :       type = kMiddleType;
      72                 :             :     }
      73                 :             : 
      74   [ +  -  -  + ]:        3051 :     s = EmitPhysicalRecord(type, ptr, fragment_length);
      75                 :        3051 :     ptr += fragment_length;
      76                 :        3051 :     left -= fragment_length;
      77                 :        3051 :     begin = false;
      78   [ +  -  +  +  :        5853 :   } while (s.ok() && left > 0);
                   +  + ]
      79                 :        2802 :   return s;
      80                 :           0 : }
      81                 :             : 
      82                 :        3051 : Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr,
      83                 :             :                                   size_t length) {
      84         [ -  + ]:        3051 :   assert(length <= 0xffff);  // Must fit in two bytes
      85         [ -  + ]:        3051 :   assert(block_offset_ + kHeaderSize + length <= kBlockSize);
      86                 :             : 
      87                 :             :   // Format the header
      88                 :        3051 :   char buf[kHeaderSize];
      89                 :        3051 :   buf[4] = static_cast<char>(length & 0xff);
      90                 :        3051 :   buf[5] = static_cast<char>(length >> 8);
      91                 :        3051 :   buf[6] = static_cast<char>(t);
      92                 :             : 
      93                 :             :   // Compute the crc of the record type and the payload.
      94                 :        3051 :   uint32_t crc = crc32c::Extend(type_crc_[t], ptr, length);
      95                 :        3051 :   crc = crc32c::Mask(crc);  // Adjust for storage
      96                 :        3051 :   EncodeFixed32(buf, crc);
      97                 :             : 
      98                 :             :   // Write the header and the payload
      99                 :        3051 :   Status s = dest_->Append(Slice(buf, kHeaderSize));
     100         [ +  - ]:        3051 :   if (s.ok()) {
     101   [ +  -  -  + ]:        3051 :     s = dest_->Append(Slice(ptr, length));
     102         [ +  - ]:        3051 :     if (s.ok()) {
     103   [ +  -  -  + ]:        3051 :       s = dest_->Flush();
     104                 :             :     }
     105                 :             :   }
     106                 :        3051 :   block_offset_ += kHeaderSize + length;
     107                 :        3051 :   return s;
     108                 :           0 : }
     109                 :             : 
     110                 :             : }  // namespace log
     111                 :             : }  // namespace leveldb
        

Generated by: LCOV version 2.0-1