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