1
0
Fork 0

Added a virtual base class for traverser engines.

This commit is contained in:
Michael Hackstein 2016-09-15 12:43:27 +02:00
parent 3c183cb24f
commit a7546b684c
5 changed files with 60 additions and 38 deletions

View File

@ -42,19 +42,9 @@ static const std::string EDGES = "edges";
static const std::string VARIABLES = "variables";
static const std::string VERTICES = "vertices";
TraverserEngine::TraverserEngine(TRI_vocbase_t* vocbase,
arangodb::velocypack::Slice info)
: _opts(nullptr),
_query(nullptr),
_trx(nullptr),
_collections(vocbase) {
VPackSlice optsSlice = info.get(OPTIONS);
if (optsSlice.isNone() || !optsSlice.isObject()) {
THROW_ARANGO_EXCEPTION_MESSAGE(
TRI_ERROR_BAD_PARAMETER,
"The body requires a " + OPTIONS + " attribute.");
}
BaseTraverserEngine::BaseTraverserEngine(TRI_vocbase_t* vocbase,
arangodb::velocypack::Slice info)
: _opts(nullptr), _query(nullptr), _trx(nullptr), _collections(vocbase) {
VPackSlice shardsSlice = info.get(SHARDS);
if (shardsSlice.isNone() || !shardsSlice.isObject()) {
THROW_ARANGO_EXCEPTION_MESSAGE(
@ -115,7 +105,6 @@ TraverserEngine::TraverserEngine(TRI_vocbase_t* vocbase,
"The optional " + VARIABLES + " has to be an array.");
}
for (auto v : VPackArrayIterator(variablesSlice)) {
// TODO do we have to keep the variable somewhere?
_query->ast()->variables()->createVariable(v);
}
}
@ -123,10 +112,9 @@ TraverserEngine::TraverserEngine(TRI_vocbase_t* vocbase,
_trx->begin(); // We begin the transaction before we lock.
// We also setup indexes before we lock.
_opts.reset(new TraverserOptions(_query, optsSlice, edgesSlice));
}
TraverserEngine::~TraverserEngine() {
BaseTraverserEngine::~BaseTraverserEngine() {
/*
auto resolver = _trx->resolver();
// TODO Do we need this or will delete trx do this already?
@ -151,7 +139,7 @@ TraverserEngine::~TraverserEngine() {
}
}
void TraverserEngine::getEdges(VPackSlice vertex, size_t depth, VPackBuilder& builder) {
void BaseTraverserEngine::getEdges(VPackSlice vertex, size_t depth, VPackBuilder& builder) {
// We just hope someone has locked the shards properly. We have no clue... Thanks locking
TRI_ASSERT(vertex.isString() || vertex.isArray());
@ -200,7 +188,7 @@ void TraverserEngine::getEdges(VPackSlice vertex, size_t depth, VPackBuilder& bu
builder.close();
}
void TraverserEngine::getVertexData(VPackSlice vertex, VPackBuilder& builder) {
void BaseTraverserEngine::getVertexData(VPackSlice vertex, VPackBuilder& builder) {
// We just hope someone has locked the shards properly. We have no clue...
// Thanks locking
TRI_ASSERT(vertex.isString() || vertex.isArray());
@ -248,7 +236,7 @@ void TraverserEngine::getVertexData(VPackSlice vertex, VPackBuilder& builder) {
builder.close(); // The outer object
}
void TraverserEngine::getVertexData(VPackSlice vertex, size_t depth,
void BaseTraverserEngine::getVertexData(VPackSlice vertex, size_t depth,
VPackBuilder& builder) {
// We just hope someone has locked the shards properly. We have no clue...
// Thanks locking
@ -305,12 +293,12 @@ void TraverserEngine::getVertexData(VPackSlice vertex, size_t depth,
builder.close();
}
void TraverserEngine::smartSearch(VPackSlice,
void BaseTraverserEngine::smartSearch(VPackSlice,
VPackBuilder&) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_ONLY_ENTERPRISE);
}
bool TraverserEngine::lockCollection(std::string const& shard) {
bool BaseTraverserEngine::lockCollection(std::string const& shard) {
if (_locked.find(shard) != _locked.end()) {
return false;
}
@ -329,6 +317,25 @@ bool TraverserEngine::lockCollection(std::string const& shard) {
return true;
}
std::shared_ptr<arangodb::TransactionContext> TraverserEngine::context() const {
std::shared_ptr<arangodb::TransactionContext> BaseTraverserEngine::context() const {
return _trx->transactionContext();
}
TraverserEngine::TraverserEngine(TRI_vocbase_t* vocbase,
arangodb::velocypack::Slice info)
: BaseTraverserEngine(vocbase, info) {
VPackSlice optsSlice = info.get(OPTIONS);
if (optsSlice.isNone() || !optsSlice.isObject()) {
THROW_ARANGO_EXCEPTION_MESSAGE(
TRI_ERROR_BAD_PARAMETER,
"The body requires a " + OPTIONS + " attribute.");
}
VPackSlice shardsSlice = info.get(SHARDS);
VPackSlice edgesSlice = shardsSlice.get(EDGES);
_opts.reset(new TraverserOptions(_query, optsSlice, edgesSlice));
}
TraverserEngine::~TraverserEngine() {
}

View File

@ -46,8 +46,7 @@ class Slice;
namespace traverser {
struct TraverserOptions;
class TraverserEngine {
class BaseTraverserEngine {
friend class TraverserEngineRegistry;
protected:
// These are private on purpose.
@ -56,13 +55,13 @@ class TraverserEngine {
// We can get into undefined state if sth.
// deletes an engine but the registry
// does not get informed properly
TraverserEngine(TRI_vocbase_t*, arangodb::velocypack::Slice);
BaseTraverserEngine(TRI_vocbase_t*, arangodb::velocypack::Slice);
public:
virtual ~TraverserEngine();
virtual ~BaseTraverserEngine();
// The engine is NOT copyable.
TraverserEngine(TraverserEngine const&) = delete;
BaseTraverserEngine(BaseTraverserEngine const&) = delete;
void getEdges(arangodb::velocypack::Slice, size_t,
arangodb::velocypack::Builder&);
@ -80,7 +79,7 @@ class TraverserEngine {
std::shared_ptr<TransactionContext> context() const;
private:
protected:
std::unique_ptr<TraverserOptions> _opts;
arangodb::aql::Query* _query;
arangodb::Transaction* _trx;
@ -88,6 +87,22 @@ class TraverserEngine {
std::unordered_set<std::string> _locked;
std::unordered_map<std::string, std::vector<std::string>> _vertexShards;
};
class TraverserEngine : public BaseTraverserEngine {
friend class TraverserEngineRegistry;
private:
// These are private on purpose.
// Only the Registry (friend) is allowed
// to create and destroy engines.
// We can get into undefined state if sth.
// deletes an engine but the registry
// does not get informed properly
TraverserEngine(TRI_vocbase_t*, arangodb::velocypack::Slice);
public:
~TraverserEngine();
};
} // namespace traverser
} // namespace arangodb

View File

@ -70,7 +70,7 @@ void TraverserEngineRegistry::destroy(TraverserEngineID id) {
}
/// @brief Get the engine with the given id
TraverserEngine* TraverserEngineRegistry::get(TraverserEngineID id) {
BaseTraverserEngine* TraverserEngineRegistry::get(TraverserEngineID id) {
WRITE_LOCKER(writeLocker, _lock);
auto e = _engines.find(id);
if (e == _engines.end()) {

View File

@ -32,13 +32,13 @@ struct TRI_vocbase_t;
namespace arangodb {
namespace traverser {
class TraverserEngine;
class BaseTraverserEngine;
/// @brief type of a Traverser Engine Id
typedef TRI_voc_tick_t TraverserEngineID;
class TraverserEngineRegistry {
friend class TraverserEngine;
friend class BaseTraverserEngine;
public:
TraverserEngineRegistry() {}
@ -53,7 +53,7 @@ class TraverserEngineRegistry {
/// @brief Get the engine with the given ID.
/// TODO Test what happens if this pointer
/// is requested twice in parallel?
TraverserEngine* get(TraverserEngineID);
BaseTraverserEngine* get(TraverserEngineID);
/// @brief Destroys the engine with the given id.
void destroy(TraverserEngineID);
@ -68,11 +68,11 @@ class TraverserEngineRegistry {
void destroy(TraverserEngineID, bool doLock);
struct EngineInfo {
bool _isInUse; // Flag if this engine is in use
std::unique_ptr<TraverserEngine> _engine; // The real engine
bool _isInUse; // Flag if this engine is in use
std::unique_ptr<BaseTraverserEngine> _engine; // The real engine
double _timeToLive; // in seconds
double _expires; // UNIX UTC timestamp for expiration
double _timeToLive; // in seconds
double _expires; // UNIX UTC timestamp for expiration
EngineInfo(TRI_vocbase_t*, arangodb::velocypack::Slice);
~EngineInfo();

View File

@ -63,7 +63,7 @@ struct Variable;
}
namespace traverser {
class TraverserEngine;
class BaseTraverserEngine;
}
//////////////////////////////////////////////////////////////////////////////
@ -76,7 +76,7 @@ struct OperationCursor;
class TransactionContext;
class Transaction {
friend class traverser::TraverserEngine;
friend class traverser::BaseTraverserEngine;
public: