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 8 #include <cinttypes> 9 10 #include "util/set_comparator.h" 11 12 namespace ROCKSDB_NAMESPACE { 13 // During recovery if the memtable is flushed we cannot rely on its help on 14 // duplicate key detection and as key insert will not be attempted. This class 15 // will be used as a emulator of memtable to tell if insertion of a key/seq 16 // would have resulted in duplication. 17 class DuplicateDetector { 18 public: DuplicateDetector(DBImpl * db)19 explicit DuplicateDetector(DBImpl* db) : db_(db) {} IsDuplicateKeySeq(uint32_t cf,const Slice & key,SequenceNumber seq)20 bool IsDuplicateKeySeq(uint32_t cf, const Slice& key, SequenceNumber seq) { 21 assert(seq >= batch_seq_); 22 if (batch_seq_ != seq) { // it is a new batch 23 keys_.clear(); 24 } 25 batch_seq_ = seq; 26 CFKeys& cf_keys = keys_[cf]; 27 if (cf_keys.size() == 0) { // just inserted 28 InitWithComp(cf); 29 } 30 auto it = cf_keys.insert(key); 31 if (it.second == false) { // second is false if a element already existed. 32 keys_.clear(); 33 InitWithComp(cf); 34 keys_[cf].insert(key); 35 return true; 36 } 37 return false; 38 } 39 40 private: 41 SequenceNumber batch_seq_ = 0; 42 DBImpl* db_; 43 using CFKeys = std::set<Slice, SetComparator>; 44 std::map<uint32_t, CFKeys> keys_; InitWithComp(const uint32_t cf)45 void InitWithComp(const uint32_t cf) { 46 auto h = db_->GetColumnFamilyHandle(cf); 47 if (!h) { 48 // TODO(myabandeh): This is not a concern in MyRocks as drop cf is not 49 // implemented yet. When it does, we should return proper error instead 50 // of throwing exception. 51 ROCKS_LOG_FATAL( 52 db_->immutable_db_options().info_log, 53 "Recovering an entry from the dropped column family %" PRIu32 54 ". WAL must must have been emptied before dropping the column " 55 "family", cf); 56 #ifndef ROCKSDB_LITE 57 throw std::runtime_error( 58 "Recovering an entry from a dropped column family. " 59 "WAL must must have been flushed before dropping the column " 60 "family"); 61 #endif 62 return; 63 } 64 auto cmp = h->GetComparator(); 65 keys_[cf] = CFKeys(SetComparator(cmp)); 66 } 67 }; 68 } // namespace ROCKSDB_NAMESPACE 69