LCOV - code coverage report
Current view: top level - src/leveldb/table - two_level_iterator.cc (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 75.0 % 84 63
Test Date: 2026-02-04 05:05:50 Functions: 83.3 % 18 15
Branches: 54.3 % 70 38

             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/two_level_iterator.h"
       6                 :             : 
       7                 :             : #include "leveldb/table.h"
       8                 :             : #include "table/block.h"
       9                 :             : #include "table/format.h"
      10                 :             : #include "table/iterator_wrapper.h"
      11                 :             : 
      12                 :             : namespace leveldb {
      13                 :             : 
      14                 :             : namespace {
      15                 :             : 
      16                 :             : typedef Iterator* (*BlockFunction)(void*, const ReadOptions&, const Slice&);
      17                 :             : 
      18                 :             : class TwoLevelIterator : public Iterator {
      19                 :             :  public:
      20                 :             :   TwoLevelIterator(Iterator* index_iter, BlockFunction block_function,
      21                 :             :                    void* arg, const ReadOptions& options);
      22                 :             : 
      23                 :             :   ~TwoLevelIterator() override;
      24                 :             : 
      25                 :             :   void Seek(const Slice& target) override;
      26                 :             :   void SeekToFirst() override;
      27                 :             :   void SeekToLast() override;
      28                 :             :   void Next() override;
      29                 :             :   void Prev() override;
      30                 :             : 
      31                 :     2841842 :   bool Valid() const override { return data_iter_.Valid(); }
      32                 :      612628 :   Slice key() const override {
      33         [ -  + ]:      612628 :     assert(Valid());
      34                 :      612628 :     return data_iter_.key();
      35                 :             :   }
      36                 :      995066 :   Slice value() const override {
      37         [ -  + ]:      995066 :     assert(Valid());
      38                 :      995066 :     return data_iter_.value();
      39                 :             :   }
      40                 :        4576 :   Status status() const override {
      41                 :             :     // It'd be nice if status() returned a const Status& instead of a Status
      42   [ -  +  -  + ]:        4576 :     if (!index_iter_.status().ok()) {
      43                 :           0 :       return index_iter_.status();
      44   [ -  +  -  -  :        4576 :     } else if (data_iter_.iter() != nullptr && !data_iter_.status().ok()) {
                   -  + ]
      45                 :           0 :       return data_iter_.status();
      46                 :             :     } else {
      47         [ -  + ]:        4576 :       return status_;
      48                 :             :     }
      49                 :             :   }
      50                 :             : 
      51                 :             :  private:
      52                 :       12015 :   void SaveError(const Status& s) {
      53   [ +  +  +  + ]:       12015 :     if (status_.ok() && !s.ok()) status_ = s;
      54                 :       12015 :   }
      55                 :             :   void SkipEmptyDataBlocksForward();
      56                 :             :   void SkipEmptyDataBlocksBackward();
      57                 :             :   void SetDataIterator(Iterator* data_iter);
      58                 :             :   void InitDataBlock();
      59                 :             : 
      60                 :             :   BlockFunction block_function_;
      61                 :             :   void* arg_;
      62                 :             :   const ReadOptions options_;
      63                 :             :   Status status_;
      64                 :             :   IteratorWrapper index_iter_;
      65                 :             :   IteratorWrapper data_iter_;  // May be nullptr
      66                 :             :   // If data_iter_ is non-null, then "data_block_handle_" holds the
      67                 :             :   // "index_value" passed to block_function_ to create the data_iter_.
      68                 :             :   std::string data_block_handle_;
      69                 :             : };
      70                 :             : 
      71                 :        8517 : TwoLevelIterator::TwoLevelIterator(Iterator* index_iter,
      72                 :             :                                    BlockFunction block_function, void* arg,
      73                 :        8517 :                                    const ReadOptions& options)
      74                 :        8517 :     : block_function_(block_function),
      75                 :        8517 :       arg_(arg),
      76                 :        8517 :       options_(options),
      77         [ +  - ]:        8517 :       index_iter_(index_iter),
      78   [ +  -  +  -  :        8517 :       data_iter_(nullptr) {}
                   -  - ]
      79                 :             : 
      80         [ +  + ]:       17035 : TwoLevelIterator::~TwoLevelIterator() = default;
      81                 :             : 
      82                 :        5087 : void TwoLevelIterator::Seek(const Slice& target) {
      83                 :        5087 :   index_iter_.Seek(target);
      84                 :        5087 :   InitDataBlock();
      85         [ +  + ]:        5087 :   if (data_iter_.iter() != nullptr) data_iter_.Seek(target);
      86                 :        5087 :   SkipEmptyDataBlocksForward();
      87                 :        5087 : }
      88                 :             : 
      89                 :        1238 : void TwoLevelIterator::SeekToFirst() {
      90                 :        1238 :   index_iter_.SeekToFirst();
      91                 :        1238 :   InitDataBlock();
      92         [ +  - ]:        1238 :   if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst();
      93                 :        1238 :   SkipEmptyDataBlocksForward();
      94                 :        1238 : }
      95                 :             : 
      96                 :           0 : void TwoLevelIterator::SeekToLast() {
      97                 :           0 :   index_iter_.SeekToLast();
      98                 :           0 :   InitDataBlock();
      99         [ #  # ]:           0 :   if (data_iter_.iter() != nullptr) data_iter_.SeekToLast();
     100                 :           0 :   SkipEmptyDataBlocksBackward();
     101                 :           0 : }
     102                 :             : 
     103                 :      610749 : void TwoLevelIterator::Next() {
     104         [ -  + ]:      610749 :   assert(Valid());
     105                 :      610749 :   data_iter_.Next();
     106                 :      610749 :   SkipEmptyDataBlocksForward();
     107                 :      610749 : }
     108                 :             : 
     109                 :           0 : void TwoLevelIterator::Prev() {
     110         [ #  # ]:           0 :   assert(Valid());
     111                 :           0 :   data_iter_.Prev();
     112                 :           0 :   SkipEmptyDataBlocksBackward();
     113                 :           0 : }
     114                 :             : 
     115                 :      617074 : void TwoLevelIterator::SkipEmptyDataBlocksForward() {
     116   [ +  +  +  + ]:     1246163 :   while (data_iter_.iter() == nullptr || !data_iter_.Valid()) {
     117                 :             :     // Move to next block
     118         [ +  + ]:       16461 :     if (!index_iter_.Valid()) {
     119                 :        4446 :       SetDataIterator(nullptr);
     120                 :        4446 :       return;
     121                 :             :     }
     122                 :       12015 :     index_iter_.Next();
     123                 :       12015 :     InitDataBlock();
     124         [ +  + ]:       12015 :     if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst();
     125                 :             :   }
     126                 :             : }
     127                 :             : 
     128                 :           0 : void TwoLevelIterator::SkipEmptyDataBlocksBackward() {
     129   [ #  #  #  # ]:           0 :   while (data_iter_.iter() == nullptr || !data_iter_.Valid()) {
     130                 :             :     // Move to next block
     131         [ #  # ]:           0 :     if (!index_iter_.Valid()) {
     132                 :           0 :       SetDataIterator(nullptr);
     133                 :           0 :       return;
     134                 :             :     }
     135                 :           0 :     index_iter_.Prev();
     136                 :           0 :     InitDataBlock();
     137         [ #  # ]:           0 :     if (data_iter_.iter() != nullptr) data_iter_.SeekToLast();
     138                 :             :   }
     139                 :             : }
     140                 :             : 
     141                 :       22786 : void TwoLevelIterator::SetDataIterator(Iterator* data_iter) {
     142   [ +  +  +  - ]:       34801 :   if (data_iter_.iter() != nullptr) SaveError(data_iter_.status());
     143                 :       22786 :   data_iter_.Set(data_iter);
     144                 :       22786 : }
     145                 :             : 
     146                 :       18340 : void TwoLevelIterator::InitDataBlock() {
     147         [ +  + ]:       18340 :   if (!index_iter_.Valid()) {
     148                 :        4446 :     SetDataIterator(nullptr);
     149                 :             :   } else {
     150                 :       13894 :     Slice handle = index_iter_.value();
     151         [ +  + ]:       13894 :     if (data_iter_.iter() != nullptr &&
     152   [ -  +  +  - ]:        9794 :         handle.compare(data_block_handle_) == 0) {
     153                 :             :       // data_iter_ is already constructed with this iterator, so
     154                 :             :       // no need to change anything
     155                 :             :     } else {
     156                 :       13894 :       Iterator* iter = (*block_function_)(arg_, options_, handle);
     157                 :       13894 :       data_block_handle_.assign(handle.data(), handle.size());
     158                 :       13894 :       SetDataIterator(iter);
     159                 :             :     }
     160                 :             :   }
     161                 :       18340 : }
     162                 :             : 
     163                 :             : }  // namespace
     164                 :             : 
     165                 :        8517 : Iterator* NewTwoLevelIterator(Iterator* index_iter,
     166                 :             :                               BlockFunction block_function, void* arg,
     167                 :             :                               const ReadOptions& options) {
     168         [ +  - ]:        8517 :   return new TwoLevelIterator(index_iter, block_function, arg, options);
     169                 :             : }
     170                 :             : 
     171                 :             : }  // namespace leveldb
        

Generated by: LCOV version 2.0-1