Revision 1f32dc7d2b6721a1fe13eb515d52e5cd6f110f59 authored by Andrew Kryczka on 14 June 2018, 00:28:31 UTC, committed by Facebook Github Bot on 14 June 2018, 00:32:04 UTC
Summary:
Rebased and resubmitting #1831 on behalf of stevelittle.

The problem is when a single process attempts to open the same DB twice, the second attempt fails due to LOCK file held. If the second attempt had opened the LOCK file, it'll now need to close it, and closing causes the file to be unlocked. Then, any subsequent attempt to open the DB will succeed, which is the wrong behavior.

The solution was to track which files a process has locked in PosixEnv, and check those before opening a LOCK file.

Fixes #1780.
Closes https://github.com/facebook/rocksdb/pull/3993

Differential Revision: D8398984

Pulled By: ajkr

fbshipit-source-id: 2755fe66950a0c9de63075f932f9e15768041918
1 parent 7497f99
Raw File
managed_iterator.h
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
//  This source code is licensed under both the GPLv2 (found in the
//  COPYING file in the root directory) and Apache 2.0 License
//  (found in the LICENSE.Apache file in the root directory).
#pragma once

#ifndef ROCKSDB_LITE

#include <mutex>
#include <queue>
#include <string>
#include <vector>

#include "db/column_family.h"
#include "rocksdb/db.h"
#include "rocksdb/iterator.h"
#include "rocksdb/options.h"
#include "util/arena.h"

namespace rocksdb {

class DBImpl;
struct SuperVersion;
class ColumnFamilyData;

/**
 * ManagedIterator is a special type of iterator that supports freeing the
 * underlying iterator and still being able to access the current key/value
 * pair.  This is done by copying the key/value pair so that clients can
 * continue to access the data without getting a SIGSEGV.
 * The underlying iterator can be freed manually through the  call to
 * ReleaseIter or automatically (as needed on space pressure or age.)
 * The iterator is recreated using the saved original arguments.
 */
class ManagedIterator : public Iterator {
 public:
  ManagedIterator(DBImpl* db, const ReadOptions& read_options,
                  ColumnFamilyData* cfd);
  virtual ~ManagedIterator();

  virtual void SeekToLast() override;
  virtual void Prev() override;
  virtual bool Valid() const override;
  void SeekToFirst() override;
  virtual void Seek(const Slice& target) override;
  virtual void SeekForPrev(const Slice& target) override;
  virtual void Next() override;
  virtual Slice key() const override;
  virtual Slice value() const override;
  virtual Status status() const override;
  void ReleaseIter(bool only_old);
  void SetDropOld(bool only_old) {
    only_drop_old_ = read_options_.tailing || only_old;
  }

 private:
  void RebuildIterator(bool reseek = false);
  void UpdateCurrent();
  void SeekInternal(const Slice& user_key, bool seek_to_first);
  bool NeedToRebuild();
  void Lock();
  bool TryLock();
  void UnLock();
  DBImpl* const db_;
  ReadOptions read_options_;
  ColumnFamilyData* const cfd_;
  ColumnFamilyHandleInternal cfh_;

  uint64_t svnum_;
  std::unique_ptr<Iterator> mutable_iter_;
  // internal iterator status
  Status status_;
  bool valid_;

  IterKey cached_key_;
  IterKey cached_value_;

  bool only_drop_old_ = true;
  bool snapshot_created_;
  bool release_supported_;
  std::mutex in_use_;  // is managed iterator in use
};

}  // namespace rocksdb
#endif  // !ROCKSDB_LITE
back to top