depends/rocksdb/utilities/transactions/pessimistic_transaction.cc
Status PessimisticTransaction::LockBatch(WriteBatch* batch,
                                         TransactionKeyMap* keys_to_unlock) {
  class Handler : public WriteBatch::Handler {
   public:
    // Sorted map of column_family_id to sorted set of keys.
    // Since LockBatch() always locks keys in sorted order, it cannot deadlock
    // with itself.  We're not using a comparator here since it doesn't matter
    // what the sorting is as long as it's consistent.
    std::map<uint32_t, std::set<std::string>> keys_;

    Handler() {}

    void RecordKey(uint32_t column_family_id, const Slice& key) {
      std::string key_str = key.ToString();

      auto iter = (keys_)[column_family_id].find(key_str);
      if (iter == (keys_)[column_family_id].end()) {
        // key not yet seen, store it.
        (keys_)[column_family_id].insert({std::move(key_str)});
      }
    }

    virtual Status PutCF(uint32_t column_family_id, const Slice& key,
                         const Slice& /* unused */) override {
      RecordKey(column_family_id, key);
      return Status::OK();
    }
    virtual Status MergeCF(uint32_t column_family_id, const Slice& key,
                           const Slice& /* unused */) override {
      RecordKey(column_family_id, key);
      return Status::OK();
    }
    virtual Status DeleteCF(uint32_t column_family_id,
                            const Slice& key) override {
      RecordKey(column_family_id, key);
      return Status::OK();
    }
  };

  // Iterating on this handler will add all keys in this batch into keys
  Handler handler;
  batch->Iterate(&handler);

  Status s;

  // Attempt to lock all keys
  for (const auto& cf_iter : handler.keys_) {
    uint32_t cfh_id = cf_iter.first;
    auto& cfh_keys = cf_iter.second;

    for (const auto& key_iter : cfh_keys) {
      const std::string& key = key_iter;

      s = txn_db_impl_->TryLock(this, cfh_id, key, true /* exclusive */);
      if (!s.ok()) {
        break;
      }
      TrackKey(keys_to_unlock, cfh_id, std::move(key), kMaxSequenceNumber,
               false, true /* exclusive */);
    }

    if (!s.ok()) {
      break;
    }
  }

  if (!s.ok()) {
    txn_db_impl_->UnLock(this, keys_to_unlock);
  }

  return s;
}
// Lock all keys in this batch.
// On success, caller should unlock keys_to_unlock
Lock all keys in this batch.
On success, caller should unlock keys_to_unlock
Lock all keys in this batch . On success caller should unlock keys_to_unlock
Status PessimisticTransaction::LockBatch(WriteBatch* batch,
                                         TransactionKeyMap* keys_to_unlock) {
  class Handler : public WriteBatch::Handler {
   public:
    std::map<uint32_t, std::set<std::string>> keys_;
    Handler() {}
    void RecordKey(uint32_t column_family_id, const Slice& key) {
      std::string key_str = key.ToString();
      auto iter = (keys_)[column_family_id].find(key_str);
      if (iter == (keys_)[column_family_id].end()) {
        (keys_)[column_family_id].insert({std::move(key_str)});
      }
    }
    virtual Status PutCF(uint32_t column_family_id, const Slice& key,
                         const Slice& ) override {
      RecordKey(column_family_id, key);
      return Status::OK();
    }
    virtual Status MergeCF(uint32_t column_family_id, const Slice& key,
                           const Slice& ) override {
      RecordKey(column_family_id, key);
      return Status::OK();
    }
    virtual Status DeleteCF(uint32_t column_family_id,
                            const Slice& key) override {
      RecordKey(column_family_id, key);
      return Status::OK();
    }
  };
  Handler handler;
  batch->Iterate(&handler);
  Status s;
  for (const auto& cf_iter : handler.keys_) {
    uint32_t cfh_id = cf_iter.first;
    auto& cfh_keys = cf_iter.second;
    for (const auto& key_iter : cfh_keys) {
      const std::string& key = key_iter;
      s = txn_db_impl_->TryLock(this, cfh_id, key, true );
      if (!s.ok()) {
        break;
      }
      TrackKey(keys_to_unlock, cfh_id, std::move(key), kMaxSequenceNumber,
               false, true );
    }
    if (!s.ok()) {
      break;
    }
  }
  if (!s.ok()) {
    txn_db_impl_->UnLock(this, keys_to_unlock);
  }
  return s;
}
Status PessimisticTransaction :: LockBatch ( WriteBatch * batch , TransactionKeyMap * keys_to_unlock ) { class Handler : public WriteBatch :: Handler { public : std :: map < uint32_t , std :: set < std :: string > > keys_ ; Handler ( ) { } void RecordKey ( uint32_t column_family_id , const Slice & key ) { std :: string key_str = key . ToString ( ) ; auto iter = ( keys_ ) [ column_family_id ] . find ( key_str ) ; if ( iter == ( keys_ ) [ column_family_id ] . end ( ) ) { ( keys_ ) [ column_family_id ] . insert ( { std :: move ( key_str ) } ) ; } } virtual Status PutCF ( uint32_t column_family_id , const Slice & key , const Slice & ) override { RecordKey ( column_family_id , key ) ; return Status :: OK ( ) ; } virtual Status MergeCF ( uint32_t column_family_id , const Slice & key , const Slice & ) override { RecordKey ( column_family_id , key ) ; return Status :: OK ( ) ; } virtual Status DeleteCF ( uint32_t column_family_id , const Slice & key ) override { RecordKey ( column_family_id , key ) ; return Status :: OK ( ) ; } } ; Handler handler ; batch -> Iterate ( & handler ) ; Status s ; for ( const auto & cf_iter : handler . keys_ ) { uint32_t cfh_id = cf_iter . first ; auto & cfh_keys = cf_iter . second ; for ( const auto & key_iter : cfh_keys ) { const std :: string & key = key_iter ; s = txn_db_impl_ -> TryLock ( this , cfh_id , key , true ) ; if ( ! s . ok ( ) ) { break ; } TrackKey ( keys_to_unlock , cfh_id , std :: move ( key ) , kMaxSequenceNumber , false , true ) ; } if ( ! s . ok ( ) ) { break ; } } if ( ! s . ok ( ) ) { txn_db_impl_ -> UnLock ( this , keys_to_unlock ) ; } return s ; }
Lock all keys in this batch.
Lock all keys in this batch .
// Sorted map of column_family_id to sorted set of keys. // Since LockBatch() always locks keys in sorted order, it cannot deadlock // with itself.  We're not using a comparator here since it doesn't matter // what the sorting is as long as it's consistent. // key not yet seen, store it. /* unused */ /* unused */ // Iterating on this handler will add all keys in this batch into keys // Attempt to lock all keys /* exclusive */ /* exclusive */