1 //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 #pragma once
7 #ifndef ROCKSDB_LITE
8 
9 #include "db/arena_wrapped_db_iter.h"
10 #include "monitoring/statistics.h"
11 #include "rocksdb/iterator.h"
12 #include "util/stop_watch.h"
13 #include "utilities/blob_db/blob_db_impl.h"
14 
15 namespace ROCKSDB_NAMESPACE {
16 namespace blob_db {
17 
18 using ROCKSDB_NAMESPACE::ManagedSnapshot;
19 
20 class BlobDBIterator : public Iterator {
21  public:
22   BlobDBIterator(ManagedSnapshot* snapshot, ArenaWrappedDBIter* iter,
23                  BlobDBImpl* blob_db, Env* env, Statistics* statistics)
24       : snapshot_(snapshot),
25         iter_(iter),
26         blob_db_(blob_db),
27         env_(env),
28         statistics_(statistics) {}
29 
30   virtual ~BlobDBIterator() = default;
31 
32   bool Valid() const override {
33     if (!iter_->Valid()) {
34       return false;
35     }
36     return status_.ok();
37   }
38 
39   Status status() const override {
40     if (!iter_->status().ok()) {
41       return iter_->status();
42     }
43     return status_;
44   }
45 
46   void SeekToFirst() override {
47     StopWatch seek_sw(env_, statistics_, BLOB_DB_SEEK_MICROS);
48     RecordTick(statistics_, BLOB_DB_NUM_SEEK);
49     iter_->SeekToFirst();
50     while (UpdateBlobValue()) {
51       iter_->Next();
52     }
53   }
54 
55   void SeekToLast() override {
56     StopWatch seek_sw(env_, statistics_, BLOB_DB_SEEK_MICROS);
57     RecordTick(statistics_, BLOB_DB_NUM_SEEK);
58     iter_->SeekToLast();
59     while (UpdateBlobValue()) {
60       iter_->Prev();
61     }
62   }
63 
64   void Seek(const Slice& target) override {
65     StopWatch seek_sw(env_, statistics_, BLOB_DB_SEEK_MICROS);
66     RecordTick(statistics_, BLOB_DB_NUM_SEEK);
67     iter_->Seek(target);
68     while (UpdateBlobValue()) {
69       iter_->Next();
70     }
71   }
72 
73   void SeekForPrev(const Slice& target) override {
74     StopWatch seek_sw(env_, statistics_, BLOB_DB_SEEK_MICROS);
75     RecordTick(statistics_, BLOB_DB_NUM_SEEK);
76     iter_->SeekForPrev(target);
77     while (UpdateBlobValue()) {
78       iter_->Prev();
79     }
80   }
81 
82   void Next() override {
83     assert(Valid());
84     StopWatch next_sw(env_, statistics_, BLOB_DB_NEXT_MICROS);
85     RecordTick(statistics_, BLOB_DB_NUM_NEXT);
86     iter_->Next();
87     while (UpdateBlobValue()) {
88       iter_->Next();
89     }
90   }
91 
92   void Prev() override {
93     assert(Valid());
94     StopWatch prev_sw(env_, statistics_, BLOB_DB_PREV_MICROS);
95     RecordTick(statistics_, BLOB_DB_NUM_PREV);
96     iter_->Prev();
97     while (UpdateBlobValue()) {
98       iter_->Prev();
99     }
100   }
101 
102   Slice key() const override {
103     assert(Valid());
104     return iter_->key();
105   }
106 
107   Slice value() const override {
108     assert(Valid());
109     if (!iter_->IsBlob()) {
110       return iter_->value();
111     }
112     return value_;
113   }
114 
NewIterators(const ReadOptions &,const std::vector<ColumnFamilyHandle * > &,std::vector<Iterator * > *)115   // Iterator::Refresh() not supported.
116 
117  private:
118   // Return true if caller should continue to next value.
119   bool UpdateBlobValue() {
120     value_.Reset();
121     status_ = Status::OK();
122     if (iter_->Valid() && iter_->status().ok() && iter_->IsBlob()) {
123       Status s = blob_db_->GetBlobValue(iter_->key(), iter_->value(), &value_);
124       if (s.IsNotFound()) {
125         return true;
126       } else {
127         if (!s.ok()) {
128           status_ = s;
129         }
130         return false;
131       }
132     } else {
133       return false;
134     }
135   }
136 
137   std::unique_ptr<ManagedSnapshot> snapshot_;
138   std::unique_ptr<ArenaWrappedDBIter> iter_;
139   BlobDBImpl* blob_db_;
140   Env* env_;
141   Statistics* statistics_;
142   Status status_;
143   PinnableSlice value_;
144 };
145 }  // namespace blob_db
146 }  // namespace ROCKSDB_NAMESPACE
147 #endif  // !ROCKSDB_LITE
148