1
0
Fork 0
arangodb/arangod/RocksDBEngine/RocksDBMethods.h

316 lines
12 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2017 ArangoDB GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Simon Grätzer
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGOD_ROCKSDB_ROCKSDB_METHODS_H
#define ARANGOD_ROCKSDB_ROCKSDB_METHODS_H 1
#include "Basics/Result.h"
#include "RocksDBColumnFamily.h"
#include "RocksDBCommon.h"
namespace rocksdb {
class Transaction;
class Slice;
class Iterator;
class TransactionDB;
class WriteBatch;
class WriteBatchWithIndex;
class Comparator;
struct ReadOptions;
} // namespace rocksdb
namespace arangodb {
namespace transaction {
class Methods;
}
class RocksDBKey;
class RocksDBMethods;
class RocksDBTransactionState;
class RocksDBSavePoint {
public:
RocksDBSavePoint(transaction::Methods* trx, TRI_voc_document_operation_e operationType);
~RocksDBSavePoint();
/// @brief acknowledges the current savepoint, so there
/// will be no rollback when the destructor is called
/// if an intermediate commit was performed, pass a value of
/// true, false otherwise
void finish(bool hasPerformedIntermediateCommit);
private:
void rollback();
private:
transaction::Methods* _trx;
TRI_voc_document_operation_e const _operationType;
bool _handled;
};
class RocksDBMethods {
public:
explicit RocksDBMethods(RocksDBTransactionState* state) : _state(state) {}
virtual ~RocksDBMethods() {}
/// @brief read options for use with iterators
rocksdb::ReadOptions iteratorReadOptions();
virtual bool isIndexingDisabled() const { return false; }
/// @brief returns true if indexing was disabled by this call
/// the default implementation is to do nothing
virtual bool DisableIndexing() { return false; }
// the default implementation is to do nothing
virtual bool EnableIndexing() { return false; }
virtual rocksdb::Status Get(rocksdb::ColumnFamilyHandle*,
rocksdb::Slice const&, rocksdb::PinnableSlice*) = 0;
virtual rocksdb::Status GetForUpdate(rocksdb::ColumnFamilyHandle*,
rocksdb::Slice const&,
rocksdb::PinnableSlice*) = 0;
/// assume_tracked=true will assume you used GetForUpdate on this key earlier.
/// it will still verify this, so it is slower than PutUntracked
virtual rocksdb::Status Put(rocksdb::ColumnFamilyHandle*, RocksDBKey const&,
rocksdb::Slice const&, bool assume_tracked) = 0;
/// Like Put, but will not perform any write-write conflict checks
virtual rocksdb::Status PutUntracked(rocksdb::ColumnFamilyHandle*, RocksDBKey const&,
rocksdb::Slice const&) = 0;
virtual rocksdb::Status Delete(rocksdb::ColumnFamilyHandle*, RocksDBKey const&) = 0;
/// contrary to Delete, a SingleDelete may only be used
/// when keys are inserted exactly once (and never overwritten)
virtual rocksdb::Status SingleDelete(rocksdb::ColumnFamilyHandle*, RocksDBKey const&) = 0;
virtual void PutLogData(rocksdb::Slice const&) = 0;
virtual std::unique_ptr<rocksdb::Iterator> NewIterator(rocksdb::ReadOptions const&,
rocksdb::ColumnFamilyHandle*) = 0;
virtual void SetSavePoint() = 0;
virtual rocksdb::Status RollbackToSavePoint() = 0;
virtual void PopSavePoint() = 0;
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE
std::size_t countInBounds(RocksDBKeyBounds const& bounds, bool isElementInRange = false);
#endif
protected:
RocksDBTransactionState* _state;
};
// only implements GET and NewIterator
class RocksDBReadOnlyMethods final : public RocksDBMethods {
public:
explicit RocksDBReadOnlyMethods(RocksDBTransactionState* state);
rocksdb::Status Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const& key,
rocksdb::PinnableSlice* val) override;
rocksdb::Status GetForUpdate(rocksdb::ColumnFamilyHandle*,
rocksdb::Slice const&,
rocksdb::PinnableSlice*) override;
rocksdb::Status Put(rocksdb::ColumnFamilyHandle*, RocksDBKey const& key,
rocksdb::Slice const& val, bool assume_tracked) override;
rocksdb::Status PutUntracked(rocksdb::ColumnFamilyHandle*, RocksDBKey const& key,
rocksdb::Slice const& val) override;
rocksdb::Status Delete(rocksdb::ColumnFamilyHandle*, RocksDBKey const& key) override;
rocksdb::Status SingleDelete(rocksdb::ColumnFamilyHandle*, RocksDBKey const&) override;
void PutLogData(rocksdb::Slice const&) override;
std::unique_ptr<rocksdb::Iterator> NewIterator(rocksdb::ReadOptions const&,
rocksdb::ColumnFamilyHandle*) override;
void SetSavePoint() override {}
rocksdb::Status RollbackToSavePoint() override {
return rocksdb::Status::OK();
}
void PopSavePoint() override {}
private:
rocksdb::TransactionDB* _db;
};
/// transaction wrapper, uses the current rocksdb transaction
class RocksDBTrxMethods : public RocksDBMethods {
public:
explicit RocksDBTrxMethods(RocksDBTransactionState* state);
virtual bool isIndexingDisabled() const override{ return _indexingDisabled; }
/// @brief returns true if indexing was disabled by this call
bool DisableIndexing() override;
bool EnableIndexing() override;
rocksdb::Status Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const& key,
rocksdb::PinnableSlice* val) override;
rocksdb::Status GetForUpdate(rocksdb::ColumnFamilyHandle*,
rocksdb::Slice const&,
rocksdb::PinnableSlice*) override;
rocksdb::Status Put(rocksdb::ColumnFamilyHandle*, RocksDBKey const& key,
rocksdb::Slice const& val, bool assume_tracked) override;
rocksdb::Status PutUntracked(rocksdb::ColumnFamilyHandle*, RocksDBKey const& key,
rocksdb::Slice const& val) override;
rocksdb::Status Delete(rocksdb::ColumnFamilyHandle*, RocksDBKey const& key) override;
rocksdb::Status SingleDelete(rocksdb::ColumnFamilyHandle*, RocksDBKey const&) override;
void PutLogData(rocksdb::Slice const&) override;
std::unique_ptr<rocksdb::Iterator> NewIterator(rocksdb::ReadOptions const&,
rocksdb::ColumnFamilyHandle*) override;
void SetSavePoint() override;
rocksdb::Status RollbackToSavePoint() override;
void PopSavePoint() override;
bool _indexingDisabled;
};
/// wraps a writebatch - non transactional
class RocksDBBatchedMethods final : public RocksDBMethods {
public:
RocksDBBatchedMethods(RocksDBTransactionState*, rocksdb::WriteBatch*);
rocksdb::Status Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const& key,
rocksdb::PinnableSlice* val) override;
rocksdb::Status GetForUpdate(rocksdb::ColumnFamilyHandle*,
rocksdb::Slice const&,
rocksdb::PinnableSlice*) override;
rocksdb::Status Put(rocksdb::ColumnFamilyHandle*, RocksDBKey const& key,
rocksdb::Slice const& val, bool assume_tracked) override;
rocksdb::Status PutUntracked(rocksdb::ColumnFamilyHandle*, RocksDBKey const& key,
rocksdb::Slice const& val) override;
rocksdb::Status Delete(rocksdb::ColumnFamilyHandle*, RocksDBKey const& key) override;
rocksdb::Status SingleDelete(rocksdb::ColumnFamilyHandle*, RocksDBKey const&) override;
void PutLogData(rocksdb::Slice const&) override;
std::unique_ptr<rocksdb::Iterator> NewIterator(rocksdb::ReadOptions const&,
rocksdb::ColumnFamilyHandle*) override;
void SetSavePoint() override {}
rocksdb::Status RollbackToSavePoint() override {
return rocksdb::Status::OK();
}
void PopSavePoint() override {}
private:
rocksdb::WriteBatch* _wb;
};
/// wraps a writebatch with index - non transactional
class RocksDBBatchedWithIndexMethods final : public RocksDBMethods {
public:
RocksDBBatchedWithIndexMethods(RocksDBTransactionState*, rocksdb::WriteBatchWithIndex*);
rocksdb::Status Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const& key,
rocksdb::PinnableSlice* val) override;
rocksdb::Status GetForUpdate(rocksdb::ColumnFamilyHandle*,
rocksdb::Slice const&,
rocksdb::PinnableSlice*) override;
rocksdb::Status Put(rocksdb::ColumnFamilyHandle*, RocksDBKey const& key,
rocksdb::Slice const& val, bool assume_tracked) override;
rocksdb::Status PutUntracked(rocksdb::ColumnFamilyHandle*, RocksDBKey const& key,
rocksdb::Slice const& val) override;
rocksdb::Status Delete(rocksdb::ColumnFamilyHandle*, RocksDBKey const& key) override;
rocksdb::Status SingleDelete(rocksdb::ColumnFamilyHandle*, RocksDBKey const&) override;
void PutLogData(rocksdb::Slice const&) override;
std::unique_ptr<rocksdb::Iterator> NewIterator(rocksdb::ReadOptions const&,
rocksdb::ColumnFamilyHandle*) override;
void SetSavePoint() override {}
rocksdb::Status RollbackToSavePoint() override {
return rocksdb::Status::OK();
}
void PopSavePoint() override {}
private:
rocksdb::TransactionDB* _db;
rocksdb::WriteBatchWithIndex* _wb;
};
// INDEXING MAY ONLY BE DISABLED IN TOPLEVEL AQL TRANSACTIONS
// THIS IS BECAUSE THESE TRANSACTIONS WILL EITHER READ FROM
// OR (XOR) WRITE TO A COLLECTION. IF THIS PRECONDITION IS
// VIOLATED THE DISABLED INDEXING WILL BREAK GET OPERATIONS.
struct IndexingDisabler {
// will only be active if condition is true
IndexingDisabler() = delete;
IndexingDisabler(IndexingDisabler&&) = delete;
IndexingDisabler(IndexingDisabler const&) = delete;
IndexingDisabler& operator=(IndexingDisabler const&) = delete;
IndexingDisabler& operator=(IndexingDisabler&&) = delete;
IndexingDisabler(RocksDBMethods* meth, bool condition) : _meth(nullptr) {
if (condition) {
bool disabledHere = meth->DisableIndexing();
if (disabledHere) {
_meth = meth;
}
}
}
~IndexingDisabler() {
if (_meth) {
_meth->EnableIndexing();
}
}
private:
RocksDBMethods* _meth;
};
// if only single indices should be enabled during operations
struct IndexingEnabler {
// will only be active if condition is true
IndexingEnabler() = delete;
IndexingEnabler(IndexingEnabler&&) = delete;
IndexingEnabler(IndexingEnabler const&) = delete;
IndexingEnabler& operator=(IndexingEnabler const&) = delete;
IndexingEnabler& operator=(IndexingEnabler&&) = delete;
IndexingEnabler(RocksDBMethods* meth, bool condition) : _meth(nullptr) {
if (condition) {
bool enableHere = meth->EnableIndexing();
if (enableHere) {
_meth = meth;
}
}
}
~IndexingEnabler() {
if (_meth) {
_meth->DisableIndexing();
}
}
private:
RocksDBMethods* _meth;
};
} // namespace arangodb
#endif