github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/database/leveldb.chai2010/src/merger.cc (about)

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