mirror of https://gitee.com/bigwinds/arangodb
Implemented parts of the TraverserEngineRegistry. It can now lease, return and delete engines. It cannot yet create them, well they don't actually exist yet anyways...
This commit is contained in:
parent
1d6afd1c67
commit
9d0658c5ee
|
@ -170,10 +170,11 @@ add_executable(${BIN_ARANGOD}
|
|||
Cluster/ClusterInfo.cpp
|
||||
Cluster/ClusterMethods.cpp
|
||||
Cluster/ClusterTraverser.cpp
|
||||
Cluster/DBServerAgencySync.cpp
|
||||
Cluster/HeartbeatThread.cpp
|
||||
Cluster/RestAgencyCallbacksHandler.cpp
|
||||
Cluster/RestShardHandler.cpp
|
||||
Cluster/DBServerAgencySync.cpp
|
||||
Cluster/TraverserEngineRegistry.cpp
|
||||
Cluster/ServerState.cpp
|
||||
Cluster/v8-cluster.cpp
|
||||
Dispatcher/Dispatcher.cpp
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS 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 Michael Hackstein
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "TraverserEngineRegistry.h"
|
||||
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Basics/ReadLocker.h"
|
||||
#include "Basics/WriteLocker.h"
|
||||
|
||||
using namespace arangodb::traverser;
|
||||
|
||||
TraverserEngineRegistry::~TraverserEngineRegistry() {
|
||||
std::vector<TraverserEngineID> toDelete;
|
||||
{
|
||||
WRITE_LOCKER(writeLocker, _lock);
|
||||
try {
|
||||
for (auto const& it : _engines) {
|
||||
toDelete.emplace_back(it.first);
|
||||
}
|
||||
} catch (...) {
|
||||
// the emplace_back() above might fail
|
||||
// prevent throwing exceptions in the destructor
|
||||
}
|
||||
}
|
||||
|
||||
// note: destroy() will acquire _lock itself, so it must be called without
|
||||
// holding the lock
|
||||
for (auto& p : toDelete) {
|
||||
try { // just in case
|
||||
destroy(p);
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Create a new Engine and return it's id
|
||||
TraverserEngineID TraverserEngineRegistry::createNew() {
|
||||
WRITE_LOCKER(writeLocker, _lock);
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// @brief Destroy the engine with the given id
|
||||
void TraverserEngineRegistry::destroy(TraverserEngineID id) {
|
||||
WRITE_LOCKER(writeLocker, _lock);
|
||||
auto e = _engines.find(id);
|
||||
if (e == _engines.end()) {
|
||||
// Nothing to destroy
|
||||
// TODO: Should we throw an error instead?
|
||||
return;
|
||||
}
|
||||
// TODO what about shard locking?
|
||||
// TODO what about multiple dbs?
|
||||
if (e->second->_isInUse) {
|
||||
// Someone is still working with this engine.
|
||||
// TODO can we just delete it? Or throw an error?
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEADLOCK);
|
||||
}
|
||||
|
||||
delete e->second->_engine;
|
||||
e->second->_engine = nullptr;
|
||||
_engines.erase(id);
|
||||
}
|
||||
|
||||
/// @brief Get the engine with the given id
|
||||
TraverserEngine* TraverserEngineRegistry::get(TraverserEngineID id) {
|
||||
WRITE_LOCKER(writeLocker, _lock);
|
||||
auto e = _engines.find(id);
|
||||
if (e == _engines.end()) {
|
||||
// Nothing to hand out
|
||||
// TODO: Should we throw an error instead?
|
||||
return nullptr;
|
||||
}
|
||||
if (e->second->_isInUse) {
|
||||
// Someone is still working with this engine.
|
||||
// TODO can we just delete it? Or throw an error?
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEADLOCK);
|
||||
}
|
||||
e->second->_isInUse = true;
|
||||
return e->second->_engine;
|
||||
}
|
||||
|
||||
/// @brief Returns the engine to the registry. Someone else can now use it.
|
||||
void TraverserEngineRegistry::returnEngine(TraverserEngineID id) {
|
||||
WRITE_LOCKER(writeLocker, _lock);
|
||||
auto e = _engines.find(id);
|
||||
if (e == _engines.end()) {
|
||||
// Nothing to return
|
||||
// TODO: Should we throw an error instead?
|
||||
return;
|
||||
}
|
||||
if (e->second->_isInUse) {
|
||||
e->second->_isInUse = false;
|
||||
}
|
||||
// TODO Should we throw an error if we are not allowed to return this
|
||||
}
|
|
@ -24,14 +24,57 @@
|
|||
#ifndef ARANGOD_CLUSTER_TRAVERSER_ENGINE_REGISTRY_H
|
||||
#define ARANGOD_CLUSTER_TRAVERSER_ENGINE_REGISTRY_H 1
|
||||
|
||||
#include "Basics/ReadWriteLock.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
|
||||
namespace arangodb {
|
||||
namespace traverser {
|
||||
|
||||
class TraverserEngine;
|
||||
|
||||
/// @brief type of a Traverser Engine Id
|
||||
typedef TRI_voc_tick_t TraverserEngineID;
|
||||
|
||||
class TraverserEngineRegistry {
|
||||
public:
|
||||
TraverserEngineRegistry() {}
|
||||
|
||||
~TraverserEngineRegistry() {}
|
||||
~TraverserEngineRegistry();
|
||||
|
||||
/// @brief Create a new Engine in the registry.
|
||||
/// It can be referred to by the returned
|
||||
/// ID. If the returned ID is 0 something
|
||||
/// internally went wrong.
|
||||
TraverserEngineID createNew();
|
||||
|
||||
/// @brief Get the engine with the given ID.
|
||||
/// TODO Test what happens if this pointer
|
||||
/// is requested twice in parallel?
|
||||
TraverserEngine* get(TraverserEngineID);
|
||||
|
||||
/// @brief Destroys the engine with the given id.
|
||||
void destroy(TraverserEngineID);
|
||||
|
||||
/// @brief Returns the engine with the given id.
|
||||
/// NOTE: Caller is NOT allowed to use the
|
||||
/// engine after this return.
|
||||
void returnEngine(TraverserEngineID);
|
||||
|
||||
private:
|
||||
|
||||
struct EngineInfo {
|
||||
bool _isInUse; // Flag if this engine is in use
|
||||
TraverserEngine* _engine; // The real engine
|
||||
|
||||
double _timeToLive; // in seconds
|
||||
double _expires; // UNIX UTC timestamp for expiration
|
||||
};
|
||||
|
||||
/// @brief the actual map of engines
|
||||
std::unordered_map<TraverserEngineID, EngineInfo*> _engines;
|
||||
|
||||
/// @brief _lock, the read/write lock for access
|
||||
basics::ReadWriteLock _lock;
|
||||
};
|
||||
|
||||
} // namespace traverser
|
||||
|
|
Loading…
Reference in New Issue