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

297 lines
11 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 current sequence number
rocksdb::SequenceNumber sequenceNumber();
/// @brief read options for use with iterators
rocksdb::ReadOptions iteratorReadOptions();
/// @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 void EnableIndexing() {}
virtual bool Exists(rocksdb::ColumnFamilyHandle*, RocksDBKey const&) = 0;
virtual arangodb::Result Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const&,
std::string*) = 0;
virtual arangodb::Result Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const&,
rocksdb::PinnableSlice*) = 0;
virtual arangodb::Result Put(
rocksdb::ColumnFamilyHandle*, RocksDBKey const&, rocksdb::Slice const&,
rocksutils::StatusHint hint = rocksutils::StatusHint::none) = 0;
virtual arangodb::Result 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 arangodb::Result SingleDelete(rocksdb::ColumnFamilyHandle*,
RocksDBKey const&) = 0;
virtual std::unique_ptr<rocksdb::Iterator> NewIterator(
rocksdb::ReadOptions const&, rocksdb::ColumnFamilyHandle*) = 0;
virtual void SetSavePoint() = 0;
virtual arangodb::Result RollbackToSavePoint() = 0;
virtual void PopSavePoint() = 0;
// convenience and compatibility method
arangodb::Result Get(rocksdb::ColumnFamilyHandle*, RocksDBKey const&,
std::string*);
arangodb::Result Get(rocksdb::ColumnFamilyHandle*, RocksDBKey const&,
rocksdb::PinnableSlice*);
#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);
bool Exists(rocksdb::ColumnFamilyHandle*, RocksDBKey const&) override;
arangodb::Result Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const& key,
std::string* val) override;
arangodb::Result Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const& key,
rocksdb::PinnableSlice* val) override;
arangodb::Result Put(
rocksdb::ColumnFamilyHandle*, RocksDBKey const& key,
rocksdb::Slice const& val,
rocksutils::StatusHint hint = rocksutils::StatusHint::none) override;
arangodb::Result Delete(rocksdb::ColumnFamilyHandle*,
RocksDBKey const& key) override;
arangodb::Result SingleDelete(rocksdb::ColumnFamilyHandle*,
RocksDBKey const&) override;
std::unique_ptr<rocksdb::Iterator> NewIterator(
rocksdb::ReadOptions const&, rocksdb::ColumnFamilyHandle*) override;
void SetSavePoint() override {}
arangodb::Result RollbackToSavePoint() override { return arangodb::Result(); }
void PopSavePoint() override {}
private:
rocksdb::TransactionDB* _db;
};
/// transaction wrapper, uses the current rocksdb transaction
class RocksDBTrxMethods : public RocksDBMethods {
public:
explicit RocksDBTrxMethods(RocksDBTransactionState* state);
/// @brief returns true if indexing was disabled by this call
bool DisableIndexing() override;
void EnableIndexing() override;
bool Exists(rocksdb::ColumnFamilyHandle*, RocksDBKey const&) override;
arangodb::Result Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const& key,
std::string* val) override;
arangodb::Result Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const& key,
rocksdb::PinnableSlice* val) override;
arangodb::Result Put(
rocksdb::ColumnFamilyHandle*, RocksDBKey const& key,
rocksdb::Slice const& val,
rocksutils::StatusHint hint = rocksutils::StatusHint::none) override;
arangodb::Result Delete(rocksdb::ColumnFamilyHandle*,
RocksDBKey const& key) override;
arangodb::Result SingleDelete(rocksdb::ColumnFamilyHandle*,
RocksDBKey const&) override;
std::unique_ptr<rocksdb::Iterator> NewIterator(
rocksdb::ReadOptions const&, rocksdb::ColumnFamilyHandle*) override;
void SetSavePoint() override;
arangodb::Result RollbackToSavePoint() override;
void PopSavePoint() override;
bool _indexingDisabled;
};
/// transaction wrapper, uses the current rocksdb transaction and non-tracking methods
class RocksDBTrxUntrackedMethods final : public RocksDBTrxMethods {
public:
explicit RocksDBTrxUntrackedMethods(RocksDBTransactionState* state);
arangodb::Result Put(
rocksdb::ColumnFamilyHandle*, RocksDBKey const& key,
rocksdb::Slice const& val,
rocksutils::StatusHint hint = rocksutils::StatusHint::none) override;
arangodb::Result Delete(rocksdb::ColumnFamilyHandle*,
RocksDBKey const& key) override;
arangodb::Result SingleDelete(rocksdb::ColumnFamilyHandle*,
RocksDBKey const&) override;
};
/// wraps a writebatch - non transactional
class RocksDBBatchedMethods final : public RocksDBMethods {
public:
RocksDBBatchedMethods(RocksDBTransactionState*,
rocksdb::WriteBatch*);
bool Exists(rocksdb::ColumnFamilyHandle*, RocksDBKey const&) override;
arangodb::Result Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const& key,
std::string* val) override;
arangodb::Result Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const& key,
rocksdb::PinnableSlice* val) override;
arangodb::Result Put(
rocksdb::ColumnFamilyHandle*, RocksDBKey const& key,
rocksdb::Slice const& val,
rocksutils::StatusHint hint = rocksutils::StatusHint::none) override;
arangodb::Result Delete(rocksdb::ColumnFamilyHandle*,
RocksDBKey const& key) override;
arangodb::Result SingleDelete(rocksdb::ColumnFamilyHandle*,
RocksDBKey const&) override;
std::unique_ptr<rocksdb::Iterator> NewIterator(
rocksdb::ReadOptions const&, rocksdb::ColumnFamilyHandle*) override;
void SetSavePoint() override {}
arangodb::Result RollbackToSavePoint() override { return arangodb::Result(); }
void PopSavePoint() override {}
private:
rocksdb::TransactionDB* _db;
rocksdb::WriteBatch* _wb;
};
/// wraps a writebatch with index - non transactional
class RocksDBBatchedWithIndexMethods final : public RocksDBMethods {
public:
RocksDBBatchedWithIndexMethods(RocksDBTransactionState*,
rocksdb::WriteBatchWithIndex*);
bool Exists(rocksdb::ColumnFamilyHandle*, RocksDBKey const&) override;
arangodb::Result Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const& key,
std::string* val) override;
arangodb::Result Get(rocksdb::ColumnFamilyHandle*, rocksdb::Slice const& key,
rocksdb::PinnableSlice* val) override;
arangodb::Result Put(
rocksdb::ColumnFamilyHandle*, RocksDBKey const& key,
rocksdb::Slice const& val,
rocksutils::StatusHint hint = rocksutils::StatusHint::none) override;
arangodb::Result Delete(rocksdb::ColumnFamilyHandle*,
RocksDBKey const& key) override;
arangodb::Result SingleDelete(rocksdb::ColumnFamilyHandle*,
RocksDBKey const&) override;
std::unique_ptr<rocksdb::Iterator> NewIterator(
rocksdb::ReadOptions const&, rocksdb::ColumnFamilyHandle*) override;
void SetSavePoint() override {}
arangodb::Result RollbackToSavePoint() override { return arangodb::Result(); }
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;
};
} // namespace arangodb
#endif