LCOV - code coverage report
Current view: top level - src/leveldb/table - format.cc (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 83.3 % 78 65
Test Date: 2026-02-04 05:05:50 Functions: 100.0 % 5 5
Branches: 44.0 % 75 33

             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 "table/format.h"
       6                 :             : 
       7                 :             : #include "leveldb/env.h"
       8                 :             : #include "port/port.h"
       9                 :             : #include "table/block.h"
      10                 :             : #include "util/coding.h"
      11                 :             : #include "util/crc32c.h"
      12                 :             : 
      13                 :             : namespace leveldb {
      14                 :             : 
      15                 :       16431 : void BlockHandle::EncodeTo(std::string* dst) const {
      16                 :             :   // Sanity check that all fields have been set
      17         [ -  + ]:       16431 :   assert(offset_ != ~static_cast<uint64_t>(0));
      18         [ -  + ]:       16431 :   assert(size_ != ~static_cast<uint64_t>(0));
      19                 :       16431 :   PutVarint64(dst, offset_);
      20                 :       16431 :   PutVarint64(dst, size_);
      21                 :       16431 : }
      22                 :             : 
      23                 :     2337328 : Status BlockHandle::DecodeFrom(Slice* input) {
      24   [ +  -  +  - ]:     2337328 :   if (GetVarint64(input, &offset_) && GetVarint64(input, &size_)) {
      25                 :     2337328 :     return Status::OK();
      26                 :             :   } else {
      27                 :           0 :     return Status::Corruption("bad block handle");
      28                 :             :   }
      29                 :             : }
      30                 :             : 
      31                 :        2028 : void Footer::EncodeTo(std::string* dst) const {
      32         [ -  + ]:        2028 :   const size_t original_size = dst->size();
      33                 :        2028 :   metaindex_handle_.EncodeTo(dst);
      34                 :        2028 :   index_handle_.EncodeTo(dst);
      35                 :        2028 :   dst->resize(2 * BlockHandle::kMaxEncodedLength);  // Padding
      36                 :        2028 :   PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber & 0xffffffffu));
      37                 :        2028 :   PutFixed32(dst, static_cast<uint32_t>(kTableMagicNumber >> 32));
      38   [ -  +  -  + ]:        2028 :   assert(dst->size() == original_size + kEncodedLength);
      39                 :        2028 :   (void)original_size;  // Disable unused variable warning.
      40                 :        2028 : }
      41                 :             : 
      42                 :        4145 : Status Footer::DecodeFrom(Slice* input) {
      43         [ +  + ]:        4145 :   const char* magic_ptr = input->data() + kEncodedLength - 8;
      44         [ +  + ]:        4145 :   const uint32_t magic_lo = DecodeFixed32(magic_ptr);
      45                 :        4145 :   const uint32_t magic_hi = DecodeFixed32(magic_ptr + 4);
      46                 :        4145 :   const uint64_t magic = ((static_cast<uint64_t>(magic_hi) << 32) |
      47                 :        4145 :                           (static_cast<uint64_t>(magic_lo)));
      48         [ +  + ]:        4145 :   if (magic != kTableMagicNumber) {
      49                 :           1 :     return Status::Corruption("not an sstable (bad magic number)");
      50                 :             :   }
      51                 :             : 
      52                 :        4144 :   Status result = metaindex_handle_.DecodeFrom(input);
      53         [ +  - ]:        4144 :   if (result.ok()) {
      54   [ +  -  -  + ]:        4144 :     result = index_handle_.DecodeFrom(input);
      55                 :             :   }
      56         [ +  - ]:        4144 :   if (result.ok()) {
      57                 :             :     // We skip over any leftover data (just padding for now) in "input"
      58                 :        4144 :     const char* end = magic_ptr + 8;
      59                 :        4144 :     *input = Slice(end, input->data() + input->size() - end);
      60                 :             :   }
      61                 :        4144 :   return result;
      62                 :        4144 : }
      63                 :             : 
      64                 :       56898 : Status ReadBlock(RandomAccessFile* file, const ReadOptions& options,
      65                 :             :                  const BlockHandle& handle, BlockContents* result) {
      66                 :       56898 :   result->data = Slice();
      67                 :       56898 :   result->cachable = false;
      68                 :       56898 :   result->heap_allocated = false;
      69                 :             : 
      70                 :             :   // Read the block contents as well as the type/crc footer.
      71                 :             :   // See table_builder.cc for the code that built this structure.
      72                 :       56898 :   size_t n = static_cast<size_t>(handle.size());
      73                 :       56898 :   char* buf = new char[n + kBlockTrailerSize];
      74                 :       56898 :   Slice contents;
      75                 :       56898 :   Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf);
      76         [ -  + ]:       56898 :   if (!s.ok()) {
      77                 :           0 :     delete[] buf;
      78                 :           0 :     return s;
      79                 :             :   }
      80         [ -  + ]:       56898 :   if (contents.size() != n + kBlockTrailerSize) {
      81         [ #  # ]:           0 :     delete[] buf;
      82   [ #  #  #  # ]:           0 :     return Status::Corruption("truncated block read", file->GetName());
      83                 :             :   }
      84                 :             : 
      85                 :             :   // Check the crc of the type and the block contents
      86         [ +  - ]:       56898 :   const char* data = contents.data();  // Pointer to where Read put the data
      87         [ +  - ]:       56898 :   if (options.verify_checksums) {
      88         [ +  - ]:       56898 :     const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1));
      89         [ +  - ]:       56898 :     const uint32_t actual = crc32c::Value(data, n + 1);
      90         [ +  + ]:       56898 :     if (actual != crc) {
      91         [ +  - ]:           2 :       delete[] buf;
      92   [ +  -  +  -  :           4 :       s = Status::Corruption("block checksum mismatch", file->GetName());
                   -  + ]
      93                 :           2 :       return s;
      94                 :             :     }
      95                 :             :   }
      96                 :             : 
      97      [ +  -  - ]:       56896 :   switch (data[n]) {
      98                 :       56896 :     case kNoCompression:
      99         [ +  + ]:       56896 :       if (data != buf) {
     100                 :             :         // File implementation gave us pointer to some other data.
     101                 :             :         // Use it directly under the assumption that it will be live
     102                 :             :         // while the file is open.
     103         [ +  - ]:       56638 :         delete[] buf;
     104                 :       56638 :         result->data = Slice(data, n);
     105                 :       56638 :         result->heap_allocated = false;
     106                 :       56638 :         result->cachable = false;  // Do not double-cache
     107                 :             :       } else {
     108                 :         258 :         result->data = Slice(buf, n);
     109                 :         258 :         result->heap_allocated = true;
     110                 :         258 :         result->cachable = true;
     111                 :             :       }
     112                 :             : 
     113                 :             :       // Ok
     114                 :             :       break;
     115                 :           0 :     case kSnappyCompression: {
     116                 :           0 :       size_t ulength = 0;
     117                 :           0 :       if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) {
     118         [ #  # ]:           0 :         delete[] buf;
     119   [ #  #  #  # ]:           0 :         return Status::Corruption("corrupted compressed block contents", file->GetName());
     120                 :             :       }
     121                 :             :       char* ubuf = new char[ulength];
     122                 :             :       if (!port::Snappy_Uncompress(data, n, ubuf)) {
     123                 :             :         delete[] buf;
     124                 :             :         delete[] ubuf;
     125                 :             :         return Status::Corruption("corrupted compressed block contents", file->GetName());
     126                 :             :       }
     127                 :             :       delete[] buf;
     128                 :             :       result->data = Slice(ubuf, ulength);
     129                 :             :       result->heap_allocated = true;
     130                 :             :       result->cachable = true;
     131                 :             :       break;
     132                 :             :     }
     133                 :           0 :     default:
     134         [ #  # ]:           0 :       delete[] buf;
     135   [ #  #  #  # ]:           0 :       return Status::Corruption("bad block type", file->GetName());
     136                 :             :   }
     137                 :             : 
     138                 :       56896 :   return Status::OK();
     139                 :       56898 : }
     140                 :             : 
     141                 :             : }  // namespace leveldb
        

Generated by: LCOV version 2.0-1