LCOV - code coverage report
Current view: top level - src/leveldb/table - merger.cc (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 58.8 % 97 57
Test Date: 2026-02-04 05:05:50 Functions: 80.0 % 15 12
Branches: 46.2 % 78 36

             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/merger.h"
       6                 :             : 
       7                 :             : #include "leveldb/comparator.h"
       8                 :             : #include "leveldb/iterator.h"
       9                 :             : #include "table/iterator_wrapper.h"
      10                 :             : 
      11                 :             : namespace leveldb {
      12                 :             : 
      13                 :             : namespace {
      14                 :             : class MergingIterator : public Iterator {
      15                 :             :  public:
      16                 :        2900 :   MergingIterator(const Comparator* comparator, Iterator** children, int n)
      17                 :        5800 :       : comparator_(comparator),
      18   [ +  -  +  + ]:       11138 :         children_(new IteratorWrapper[n]),
      19                 :        2900 :         n_(n),
      20                 :        2900 :         current_(nullptr),
      21         [ +  - ]:        2900 :         direction_(kForward) {
      22         [ +  + ]:       11138 :     for (int i = 0; i < n; i++) {
      23         [ +  - ]:        8238 :       children_[i].Set(children[i]);
      24                 :             :     }
      25                 :        2900 :   }
      26                 :             : 
      27   [ +  -  +  + ]:       14038 :   ~MergingIterator() override { delete[] children_; }
      28                 :             : 
      29                 :     3892829 :   bool Valid() const override { return (current_ != nullptr); }
      30                 :             : 
      31                 :         295 :   void SeekToFirst() override {
      32         [ +  + ]:        1394 :     for (int i = 0; i < n_; i++) {
      33                 :        1099 :       children_[i].SeekToFirst();
      34                 :             :     }
      35                 :         295 :     FindSmallest();
      36                 :         295 :     direction_ = kForward;
      37                 :         295 :   }
      38                 :             : 
      39                 :           0 :   void SeekToLast() override {
      40         [ #  # ]:           0 :     for (int i = 0; i < n_; i++) {
      41                 :           0 :       children_[i].SeekToLast();
      42                 :             :     }
      43                 :           0 :     FindLargest();
      44                 :           0 :     direction_ = kReverse;
      45                 :           0 :   }
      46                 :             : 
      47                 :        2605 :   void Seek(const Slice& target) override {
      48         [ +  + ]:        9744 :     for (int i = 0; i < n_; i++) {
      49                 :        7139 :       children_[i].Seek(target);
      50                 :             :     }
      51                 :        2605 :     FindSmallest();
      52                 :        2605 :     direction_ = kForward;
      53                 :        2605 :   }
      54                 :             : 
      55                 :      617363 :   void Next() override {
      56         [ -  + ]:      617363 :     assert(Valid());
      57                 :             : 
      58                 :             :     // Ensure that all children are positioned after key().
      59                 :             :     // If we are moving in the forward direction, it is already
      60                 :             :     // true for all of the non-current_ children since current_ is
      61                 :             :     // the smallest child and key() == current_->key().  Otherwise,
      62                 :             :     // we explicitly position the non-current_ children.
      63         [ -  + ]:      617363 :     if (direction_ != kForward) {
      64         [ #  # ]:           0 :       for (int i = 0; i < n_; i++) {
      65                 :           0 :         IteratorWrapper* child = &children_[i];
      66         [ #  # ]:           0 :         if (child != current_) {
      67                 :           0 :           child->Seek(key());
      68   [ #  #  #  # ]:           0 :           if (child->Valid() &&
      69                 :           0 :               comparator_->Compare(key(), child->key()) == 0) {
      70                 :           0 :             child->Next();
      71                 :             :           }
      72                 :             :         }
      73                 :             :       }
      74                 :           0 :       direction_ = kForward;
      75                 :             :     }
      76                 :             : 
      77                 :      617363 :     current_->Next();
      78                 :      617363 :     FindSmallest();
      79                 :      617363 :   }
      80                 :             : 
      81                 :           0 :   void Prev() override {
      82         [ #  # ]:           0 :     assert(Valid());
      83                 :             : 
      84                 :             :     // Ensure that all children are positioned before key().
      85                 :             :     // If we are moving in the reverse direction, it is already
      86                 :             :     // true for all of the non-current_ children since current_ is
      87                 :             :     // the largest child and key() == current_->key().  Otherwise,
      88                 :             :     // we explicitly position the non-current_ children.
      89         [ #  # ]:           0 :     if (direction_ != kReverse) {
      90         [ #  # ]:           0 :       for (int i = 0; i < n_; i++) {
      91                 :           0 :         IteratorWrapper* child = &children_[i];
      92         [ #  # ]:           0 :         if (child != current_) {
      93                 :           0 :           child->Seek(key());
      94         [ #  # ]:           0 :           if (child->Valid()) {
      95                 :             :             // Child is at first entry >= key().  Step back one to be < key()
      96                 :           0 :             child->Prev();
      97                 :             :           } else {
      98                 :             :             // Child has no entries >= key().  Position at last entry.
      99                 :           0 :             child->SeekToLast();
     100                 :             :           }
     101                 :             :         }
     102                 :             :       }
     103                 :           0 :       direction_ = kReverse;
     104                 :             :     }
     105                 :             : 
     106                 :           0 :     current_->Prev();
     107                 :           0 :     FindLargest();
     108                 :           0 :   }
     109                 :             : 
     110                 :     1335606 :   Slice key() const override {
     111         [ -  + ]:     1335606 :     assert(Valid());
     112                 :     1335606 :     return current_->key();
     113                 :             :   }
     114                 :             : 
     115                 :      959572 :   Slice value() const override {
     116         [ -  + ]:      959572 :     assert(Valid());
     117                 :      959572 :     return current_->value();
     118                 :             :   }
     119                 :             : 
     120                 :         584 :   Status status() const override {
     121                 :         584 :     Status status;
     122         [ +  + ]:        2766 :     for (int i = 0; i < n_; i++) {
     123   [ +  -  -  + ]:        2182 :       status = children_[i].status();
     124         [ +  - ]:        2182 :       if (!status.ok()) {
     125                 :             :         break;
     126                 :             :       }
     127                 :             :     }
     128                 :         584 :     return status;
     129                 :           0 :   }
     130                 :             : 
     131                 :             :  private:
     132                 :             :   // Which direction is the iterator moving?
     133                 :             :   enum Direction { kForward, kReverse };
     134                 :             : 
     135                 :             :   void FindSmallest();
     136                 :             :   void FindLargest();
     137                 :             : 
     138                 :             :   // We might want to use a heap in case there are lots of children.
     139                 :             :   // For now we use a simple array since we expect a very small number
     140                 :             :   // of children in leveldb.
     141                 :             :   const Comparator* comparator_;
     142                 :             :   IteratorWrapper* children_;
     143                 :             :   int n_;
     144                 :             :   IteratorWrapper* current_;
     145                 :             :   Direction direction_;
     146                 :             : };
     147                 :             : 
     148                 :      620263 : void MergingIterator::FindSmallest() {
     149                 :      620263 :   IteratorWrapper* smallest = nullptr;
     150         [ +  + ]:     2213977 :   for (int i = 0; i < n_; i++) {
     151                 :     1593714 :     IteratorWrapper* child = &children_[i];
     152         [ +  + ]:     1593714 :     if (child->Valid()) {
     153         [ +  + ]:     1253254 :       if (smallest == nullptr) {
     154                 :             :         smallest = child;
     155         [ +  + ]:      634949 :       } else if (comparator_->Compare(child->key(), smallest->key()) < 0) {
     156                 :      286918 :         smallest = child;
     157                 :             :       }
     158                 :             :     }
     159                 :             :   }
     160                 :      620263 :   current_ = smallest;
     161                 :      620263 : }
     162                 :             : 
     163                 :           0 : void MergingIterator::FindLargest() {
     164                 :           0 :   IteratorWrapper* largest = nullptr;
     165         [ #  # ]:           0 :   for (int i = n_ - 1; i >= 0; i--) {
     166                 :           0 :     IteratorWrapper* child = &children_[i];
     167         [ #  # ]:           0 :     if (child->Valid()) {
     168         [ #  # ]:           0 :       if (largest == nullptr) {
     169                 :             :         largest = child;
     170         [ #  # ]:           0 :       } else if (comparator_->Compare(child->key(), largest->key()) > 0) {
     171                 :           0 :         largest = child;
     172                 :             :       }
     173                 :             :     }
     174                 :             :   }
     175                 :           0 :   current_ = largest;
     176                 :           0 : }
     177                 :             : }  // namespace
     178                 :             : 
     179                 :        5326 : Iterator* NewMergingIterator(const Comparator* comparator, Iterator** children,
     180                 :             :                              int n) {
     181         [ -  + ]:        5326 :   assert(n >= 0);
     182         [ -  + ]:        5326 :   if (n == 0) {
     183                 :           0 :     return NewEmptyIterator();
     184         [ +  + ]:        5326 :   } else if (n == 1) {
     185                 :        2426 :     return children[0];
     186                 :             :   } else {
     187         [ +  - ]:        2900 :     return new MergingIterator(comparator, children, n);
     188                 :             :   }
     189                 :             : }
     190                 :             : 
     191                 :             : }  // namespace leveldb
        

Generated by: LCOV version 2.0-1