1
0
Fork 0

make ownership a bit more transparent, API-wise (#8653)

This commit is contained in:
Jan 2019-04-03 18:47:04 +02:00 committed by GitHub
parent d1d1fe555b
commit f16b75440c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 57 additions and 59 deletions

View File

@ -36,15 +36,15 @@
namespace arangodb { namespace arangodb {
MMFilesExportCursor::MMFilesExportCursor(TRI_vocbase_t& vocbase, CursorId id, MMFilesExportCursor::MMFilesExportCursor(TRI_vocbase_t& vocbase, CursorId id,
arangodb::MMFilesCollectionExport* ex, std::unique_ptr<arangodb::MMFilesCollectionExport> ex,
size_t batchSize, double ttl, bool hasCount) size_t batchSize, double ttl, bool hasCount)
: Cursor(id, batchSize, ttl, hasCount), : Cursor(id, batchSize, ttl, hasCount),
_guard(vocbase), _guard(vocbase),
_ex(ex), _ex(std::move(ex)),
_position(0), _position(0),
_size(ex->_vpack.size()) {} _size(_ex->_vpack.size()) {}
MMFilesExportCursor::~MMFilesExportCursor() { delete _ex; } MMFilesExportCursor::~MMFilesExportCursor() {}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief check whether the cursor contains more data /// @brief check whether the cursor contains more data
@ -79,6 +79,10 @@ std::pair<aql::ExecutionState, Result> MMFilesExportCursor::dump(VPackBuilder& b
} }
Result MMFilesExportCursor::dumpSync(VPackBuilder& builder) { Result MMFilesExportCursor::dumpSync(VPackBuilder& builder) {
if (_ex == nullptr) {
return Result(TRI_ERROR_CURSOR_NOT_FOUND);
}
auto ctx = transaction::StandaloneContext::Create(_guard.database()); auto ctx = transaction::StandaloneContext::Create(_guard.database());
VPackOptions const* oldOptions = builder.options; VPackOptions const* oldOptions = builder.options;
@ -135,8 +139,7 @@ Result MMFilesExportCursor::dumpSync(VPackBuilder& builder) {
if (!hasNext()) { if (!hasNext()) {
// mark the cursor as deleted // mark the cursor as deleted
delete _ex; _ex.reset();
_ex = nullptr;
this->setDeleted(); this->setDeleted();
} }
} catch (arangodb::basics::Exception const& ex) { } catch (arangodb::basics::Exception const& ex) {
@ -148,7 +151,7 @@ Result MMFilesExportCursor::dumpSync(VPackBuilder& builder) {
"internal error during MMFilesExportCursor::dump"); "internal error during MMFilesExportCursor::dump");
} }
builder.options = oldOptions; builder.options = oldOptions;
return TRI_ERROR_NO_ERROR; return Result();
} }
std::shared_ptr<transaction::Context> MMFilesExportCursor::context() const { std::shared_ptr<transaction::Context> MMFilesExportCursor::context() const {

View File

@ -36,8 +36,8 @@ class MMFilesCollectionExport;
class MMFilesExportCursor final : public Cursor { class MMFilesExportCursor final : public Cursor {
public: public:
MMFilesExportCursor(TRI_vocbase_t& vocbase, CursorId id, MMFilesExportCursor(TRI_vocbase_t& vocbase, CursorId id,
arangodb::MMFilesCollectionExport* ex, size_t batchSize, std::unique_ptr<arangodb::MMFilesCollectionExport> ex,
double ttl, bool hasCount); size_t batchSize, double ttl, bool hasCount);
~MMFilesExportCursor(); ~MMFilesExportCursor();
@ -58,7 +58,7 @@ class MMFilesExportCursor final : public Cursor {
private: private:
DatabaseGuard _guard; DatabaseGuard _guard;
arangodb::MMFilesCollectionExport* _ex; std::unique_ptr<arangodb::MMFilesCollectionExport> _ex;
size_t _position; size_t _position;
size_t const _size; size_t const _size;
}; };

View File

@ -257,17 +257,12 @@ void MMFilesRestExportHandler::createCursor() {
auto cursors = _vocbase.cursorRepository(); auto cursors = _vocbase.cursorRepository();
TRI_ASSERT(cursors != nullptr); TRI_ASSERT(cursors != nullptr);
Cursor* c = nullptr; auto cursor = std::make_unique<MMFilesExportCursor>(_vocbase, TRI_NewTickServer(),
std::move(collectionExport),
batchSize, ttl, count);
{ cursor->use();
auto cursor = std::make_unique<MMFilesExportCursor>(_vocbase, TRI_NewTickServer(), Cursor* c = cursors->addCursor(std::move(cursor));
collectionExport.get(),
batchSize, ttl, count);
collectionExport.release();
cursor->use();
c = cursors->addCursor(std::move(cursor));
}
TRI_ASSERT(c != nullptr); TRI_ASSERT(c != nullptr);
TRI_DEFER(cursors->release(c)); TRI_DEFER(cursors->release(c));

View File

@ -669,8 +669,7 @@ void MMFilesRestReplicationHandler::handleCommandCreateKeys() {
size_t const count = keys->count(); size_t const count = keys->count();
auto keysRepository = _vocbase.collectionKeys(); auto keysRepository = _vocbase.collectionKeys();
keysRepository->store(keys.get()); keysRepository->store(std::move(keys));
keys.release();
VPackBuilder result; VPackBuilder result;
result.add(VPackValue(VPackValueType::Object)); result.add(VPackValue(VPackValueType::Object));

View File

@ -70,11 +70,6 @@ CollectionKeysRepository::~CollectionKeysRepository() {
{ {
MUTEX_LOCKER(mutexLocker, _lock); MUTEX_LOCKER(mutexLocker, _lock);
for (auto it : _keys) {
delete it.second;
}
_keys.clear(); _keys.clear();
} }
} }
@ -83,9 +78,9 @@ CollectionKeysRepository::~CollectionKeysRepository() {
/// @brief stores collection keys in the repository /// @brief stores collection keys in the repository
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void CollectionKeysRepository::store(arangodb::CollectionKeys* keys) { void CollectionKeysRepository::store(std::unique_ptr<arangodb::CollectionKeys> keys) {
MUTEX_LOCKER(mutexLocker, _lock); MUTEX_LOCKER(mutexLocker, _lock);
_keys.emplace(keys->id(), keys); _keys.emplace(keys->id(), std::move(keys));
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -93,7 +88,7 @@ void CollectionKeysRepository::store(arangodb::CollectionKeys* keys) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool CollectionKeysRepository::remove(CollectionKeysId id) { bool CollectionKeysRepository::remove(CollectionKeysId id) {
arangodb::CollectionKeys* collectionKeys = nullptr; std::unique_ptr<arangodb::CollectionKeys> owner;
{ {
MUTEX_LOCKER(mutexLocker, _lock); MUTEX_LOCKER(mutexLocker, _lock);
@ -105,26 +100,28 @@ bool CollectionKeysRepository::remove(CollectionKeysId id) {
return false; return false;
} }
collectionKeys = (*it).second; if ((*it).second->isDeleted()) {
if (collectionKeys->isDeleted()) {
// already deleted // already deleted
return false; return false;
} }
if (collectionKeys->isUsed()) { if ((*it).second->isUsed()) {
// keys are in use by someone else. now mark as deleted // keys are in use by someone else. now mark as deleted
collectionKeys->deleted(); (*it).second->deleted();
return true; return true;
} }
// keys are not in use by someone else // keys are not in use by someone else
// move ownership for item to our local variable
owner = std::move((*it).second);
// clear entry from map
_keys.erase(it); _keys.erase(it);
} }
TRI_ASSERT(collectionKeys != nullptr); // when we leave this scope, this will fire the dtor of the
// entry, outside the lock
TRI_ASSERT(owner != nullptr);
delete collectionKeys;
return true; return true;
} }
@ -147,14 +144,13 @@ CollectionKeys* CollectionKeysRepository::find(CollectionKeysId id) {
return nullptr; return nullptr;
} }
collectionKeys = (*it).second; if ((*it).second->isDeleted()) {
if (collectionKeys->isDeleted()) {
// already deleted // already deleted
return nullptr; return nullptr;
} }
collectionKeys->use(); (*it).second->use();
collectionKeys = (*it).second.get();
} }
return collectionKeys; return collectionKeys;
@ -165,6 +161,8 @@ CollectionKeys* CollectionKeysRepository::find(CollectionKeysId id) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void CollectionKeysRepository::release(CollectionKeys* collectionKeys) { void CollectionKeysRepository::release(CollectionKeys* collectionKeys) {
std::unique_ptr<CollectionKeys> owner;
{ {
MUTEX_LOCKER(mutexLocker, _lock); MUTEX_LOCKER(mutexLocker, _lock);
@ -175,12 +173,17 @@ void CollectionKeysRepository::release(CollectionKeys* collectionKeys) {
return; return;
} }
// remove from the list // remove from the list and take ownership
_keys.erase(collectionKeys->id()); auto it = _keys.find(collectionKeys->id());
if (it != _keys.end()) {
owner = std::move((*it).second);
_keys.erase(it);
}
} }
// and free the keys // when we get here, the dtor of the entry will be called,
delete collectionKeys; // outside the lock
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -190,7 +193,7 @@ void CollectionKeysRepository::release(CollectionKeys* collectionKeys) {
bool CollectionKeysRepository::containsUsed() { bool CollectionKeysRepository::containsUsed() {
MUTEX_LOCKER(mutexLocker, _lock); MUTEX_LOCKER(mutexLocker, _lock);
for (auto it : _keys) { for (auto const& it : _keys) {
if (it.second->isUsed()) { if (it.second->isUsed()) {
return true; return true;
} }
@ -204,7 +207,7 @@ bool CollectionKeysRepository::containsUsed() {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool CollectionKeysRepository::garbageCollect(bool force) { bool CollectionKeysRepository::garbageCollect(bool force) {
std::vector<arangodb::CollectionKeys*> found; std::vector<std::unique_ptr<arangodb::CollectionKeys>> found;
found.reserve(MaxCollectCount); found.reserve(MaxCollectCount);
auto const now = TRI_microtime(); auto const now = TRI_microtime();
@ -213,7 +216,7 @@ bool CollectionKeysRepository::garbageCollect(bool force) {
MUTEX_LOCKER(mutexLocker, _lock); MUTEX_LOCKER(mutexLocker, _lock);
for (auto it = _keys.begin(); it != _keys.end(); /* no hoisting */) { for (auto it = _keys.begin(); it != _keys.end(); /* no hoisting */) {
auto collectionKeys = (*it).second; auto& collectionKeys = (*it).second;
if (collectionKeys->isUsed()) { if (collectionKeys->isUsed()) {
// must not destroy anything currently in use // must not destroy anything currently in use
@ -227,12 +230,13 @@ bool CollectionKeysRepository::garbageCollect(bool force) {
if (collectionKeys->isDeleted()) { if (collectionKeys->isDeleted()) {
try { try {
found.emplace_back(collectionKeys); found.emplace_back(std::move(collectionKeys));
it = _keys.erase(it);
} catch (...) { } catch (...) {
// stop iteration // stop iteration
break; break;
} }
it = _keys.erase(it);
if (!force && found.size() >= MaxCollectCount) { if (!force && found.size() >= MaxCollectCount) {
break; break;
@ -243,10 +247,7 @@ bool CollectionKeysRepository::garbageCollect(bool force) {
} }
} }
// remove keys outside the lock // when we get here, all instances in found will be destroyed
for (auto it : found) { // outside the lock
delete it;
}
return (!found.empty()); return (!found.empty());
} }

View File

@ -52,13 +52,13 @@ class CollectionKeysRepository {
/// @brief stores collection keys in the repository /// @brief stores collection keys in the repository
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void store(CollectionKeys*); void store(std::unique_ptr<CollectionKeys>);
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief remove a keys by id /// @brief remove a keys entry by id
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
bool remove(CollectionKeysId); bool remove(CollectionKeysId id);
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief find an existing collection keys list by id /// @brief find an existing collection keys list by id
@ -97,7 +97,7 @@ class CollectionKeysRepository {
/// @brief list of current keys /// @brief list of current keys
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
std::unordered_map<CollectionKeysId, CollectionKeys*> _keys; std::unordered_map<CollectionKeysId, std::unique_ptr<CollectionKeys>> _keys;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief maximum number of keys to garbage-collect in one go /// @brief maximum number of keys to garbage-collect in one go