1
0
Fork 0

fixed compactor locks

This commit is contained in:
jsteemann 2016-07-26 10:22:44 +02:00
parent b54f0a15d8
commit 9af8a30a36
9 changed files with 172 additions and 321 deletions

View File

@ -179,7 +179,6 @@ void BootstrapFeature::unprepare() {
}
}
} else {
std::vector<std::string> names = databaseFeature->getDatabaseNames();
for (auto& name : databaseFeature->getDatabaseNames()) {
TRI_vocbase_t* vocbase = databaseFeature->useDatabase(name);

View File

@ -1073,7 +1073,6 @@ int DatabaseFeature::createApplicationDirectory(std::string const& name, std::st
int DatabaseFeature::iterateDatabases(VPackSlice const& databases) {
V8DealerFeature* dealer = ApplicationServer::getFeature<V8DealerFeature>("V8Dealer");
std::string const appPath = dealer->appPath();
std::string const databasePath = ApplicationServer::getFeature<DatabasePathFeature>("DatabasePath")->subdirectoryName("databases");
StorageEngine* engine = ApplicationServer::getFeature<EngineSelectorFeature>("EngineSelector")->ENGINE;

View File

@ -22,6 +22,7 @@
////////////////////////////////////////////////////////////////////////////////
#include "CollectionExport.h"
#include "Basics/WriteLocker.h"
#include "Indexes/PrimaryIndex.h"
#include "Utils/CollectionGuard.h"
#include "Utils/SingleCollectionTransaction.h"
@ -63,17 +64,13 @@ CollectionExport::~CollectionExport() {
}
void CollectionExport::run(uint64_t maxWaitTime, size_t limit) {
{
// try to acquire the exclusive lock on the compaction
while (!TRI_CheckAndLockCompactorVocBase(_document->_vocbase)) {
// didn't get it. try again...
usleep(5000);
}
WRITE_LOCKER_EVENTUAL(locker, _document->_vocbase->_compactionBlockers._lock, 5000);
// create a ditch under the compaction lock
_ditch = _document->ditches()->createDocumentDitch(false, __FILE__, __LINE__);
// release the lock
TRI_UnlockCompactorVocBase(_document->_vocbase);
}
// now we either have a ditch or not
if (_ditch == nullptr) {

View File

@ -23,6 +23,7 @@
#include "CollectionKeys.h"
#include "Basics/StaticStrings.h"
#include "Basics/WriteLocker.h"
#include "Utils/CollectionGuard.h"
#include "Utils/SingleCollectionTransaction.h"
#include "Utils/StandaloneTransactionContext.h"
@ -88,17 +89,13 @@ void CollectionKeys::create(TRI_voc_tick_t maxTick) {
arangodb::wal::LogfileManager::instance()->waitForCollectorQueue(
_document->_info.id(), 30.0);
{
// try to acquire the exclusive lock on the compaction
while (!TRI_CheckAndLockCompactorVocBase(_document->_vocbase)) {
// didn't get it. try again...
usleep(5000);
}
WRITE_LOCKER_EVENTUAL(locker, _document->_vocbase->_compactionBlockers._lock, 5000);
// create a ditch under the compaction lock
_ditch = _document->ditches()->createDocumentDitch(false, __FILE__, __LINE__);
// release the lock
TRI_UnlockCompactorVocBase(_document->_vocbase);
}
// now we either have a ditch or not
if (_ditch == nullptr) {

View File

@ -25,8 +25,9 @@
#include "ApplicationFeatures/ApplicationServer.h"
#include "Basics/ReadLocker.h"
#include "Basics/WriteLocker.h"
#include "Basics/files.h"
#include "Basics/tri-strings.h"
//#include "Basics/tri-strings.h"
#include "Logger/Logger.h"
#include "Utils/CursorRepository.h"
#include "VocBase/Ditch.h"
@ -259,7 +260,11 @@ void TRI_CleanupVocBase(void* data) {
}
// check if we can get the compactor lock exclusively
if (TRI_CheckAndLockCompactorVocBase(vocbase)) {
// check if compaction is currently disallowed
{
TRY_WRITE_LOCKER(locker, vocbase->_compactionBlockers._lock);
if (locker.isLocked()) {
try {
READ_LOCKER(readLocker, vocbase->_collectionsLock);
// copy all collections
@ -295,8 +300,7 @@ void TRI_CleanupVocBase(void* data) {
CleanupDocumentCollection(collection, document);
}
TRI_UnlockCompactorVocBase(vocbase);
}
}
if (vocbase->_state >= 1) {

View File

@ -165,10 +165,7 @@ struct compaction_info_t {
bool _keepDeletions;
};
////////////////////////////////////////////////////////////////////////////////
/// @brief determine the number of documents in the collection
///////////////////////////////////////////////////////////////////////////////
static uint64_t GetNumberOfDocuments(TRI_document_collection_t* document) {
TRI_vocbase_t* vocbase = document->_vocbase;
@ -962,88 +959,15 @@ static bool CompactifyDocumentCollection(TRI_document_collection_t* document) {
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief try to write-lock the compaction
/// returns true if lock acquisition was successful. the caller is responsible
/// to free the write lock eventually
////////////////////////////////////////////////////////////////////////////////
static bool TryLockCompaction(TRI_vocbase_t* vocbase) {
return TRI_TryWriteLockReadWriteLock(&vocbase->_compactionBlockers._lock);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief write-lock the compaction
////////////////////////////////////////////////////////////////////////////////
static void LockCompaction(TRI_vocbase_t* vocbase) {
while (!TryLockCompaction(vocbase)) {
// cycle until we have acquired the write-lock
usleep(1000);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief write-unlock the compaction
////////////////////////////////////////////////////////////////////////////////
static void UnlockCompaction(TRI_vocbase_t* vocbase) {
TRI_WriteUnlockReadWriteLock(&vocbase->_compactionBlockers._lock);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief atomic check and lock for running the compaction
/// if this function returns true, it has acquired a write-lock on the
/// compactionBlockers structure, which the caller must free eventually
////////////////////////////////////////////////////////////////////////////////
static bool CheckAndLockCompaction(TRI_vocbase_t* vocbase) {
// check if we can acquire the write lock instantly
if (!TryLockCompaction(vocbase)) {
// couldn't acquire the write lock
return false;
}
// we are now holding the write lock
double now = TRI_microtime();
// check if we have a still-valid compaction blocker
for (auto const& blocker : vocbase->_compactionBlockers._data) {
if (blocker._expires > now) {
// found a compaction blocker. unlock and return
UnlockCompaction(vocbase);
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief initialize the compaction blockers structure
////////////////////////////////////////////////////////////////////////////////
int TRI_InitCompactorVocBase(TRI_vocbase_t* vocbase) {
TRI_InitReadWriteLock(&vocbase->_compactionBlockers._lock);
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destroy the compaction blockers structure
////////////////////////////////////////////////////////////////////////////////
void TRI_DestroyCompactorVocBase(TRI_vocbase_t* vocbase) {
TRI_DestroyReadWriteLock(&vocbase->_compactionBlockers._lock);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief remove data of expired compaction blockers
////////////////////////////////////////////////////////////////////////////////
bool TRI_CleanupCompactorVocBase(TRI_vocbase_t* vocbase) {
// check if we can instantly acquire the lock
if (!TryLockCompaction(vocbase)) {
TRY_WRITE_LOCKER(locker, vocbase->_compactionBlockers._lock);
if (!locker.isLocked()) {
// couldn't acquire lock
return false;
}
@ -1064,8 +988,6 @@ bool TRI_CleanupCompactorVocBase(TRI_vocbase_t* vocbase) {
}
}
UnlockCompaction(vocbase);
return true;
}
@ -1084,15 +1006,16 @@ int TRI_InsertBlockerCompactorVocBase(TRI_vocbase_t* vocbase, double lifetime,
blocker._expires = TRI_microtime() + lifetime;
int res = TRI_ERROR_NO_ERROR;
LockCompaction(vocbase);
{
WRITE_LOCKER_EVENTUAL(locker, vocbase->_compactionBlockers._lock, 1000);
try {
vocbase->_compactionBlockers._data.push_back(blocker);
} catch (...) {
res = TRI_ERROR_OUT_OF_MEMORY;
}
UnlockCompaction(vocbase);
}
if (res != TRI_ERROR_NO_ERROR) {
return res;
@ -1109,47 +1032,20 @@ int TRI_InsertBlockerCompactorVocBase(TRI_vocbase_t* vocbase, double lifetime,
int TRI_TouchBlockerCompactorVocBase(TRI_vocbase_t* vocbase, TRI_voc_tick_t id,
double lifetime) {
bool found = false;
if (lifetime <= 0.0) {
return TRI_ERROR_BAD_PARAMETER;
}
LockCompaction(vocbase);
WRITE_LOCKER_EVENTUAL(locker, vocbase->_compactionBlockers._lock, 1000);
for (auto& blocker : vocbase->_compactionBlockers._data) {
if (blocker._id == id) {
blocker._expires = TRI_microtime() + lifetime;
found = true;
break;
}
}
UnlockCompaction(vocbase);
if (!found) {
return TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND;
}
return TRI_ERROR_NO_ERROR;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief atomically check-and-lock the compactor
/// if the function returns true, then a write-lock on the compactor was
/// acquired, which must eventually be freed by the caller
////////////////////////////////////////////////////////////////////////////////
bool TRI_CheckAndLockCompactorVocBase(TRI_vocbase_t* vocbase) {
return TryLockCompaction(vocbase);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief unlock the compactor
////////////////////////////////////////////////////////////////////////////////
void TRI_UnlockCompactorVocBase(TRI_vocbase_t* vocbase) {
UnlockCompaction(vocbase);
return TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND;
}
////////////////////////////////////////////////////////////////////////////////
@ -1158,9 +1054,7 @@ void TRI_UnlockCompactorVocBase(TRI_vocbase_t* vocbase) {
int TRI_RemoveBlockerCompactorVocBase(TRI_vocbase_t* vocbase,
TRI_voc_tick_t id) {
bool found = false;
LockCompaction(vocbase);
WRITE_LOCKER_EVENTUAL(locker, vocbase->_compactionBlockers._lock, 1000);
size_t const n = vocbase->_compactionBlockers._data.size();
@ -1168,18 +1062,26 @@ int TRI_RemoveBlockerCompactorVocBase(TRI_vocbase_t* vocbase,
auto& blocker = vocbase->_compactionBlockers._data[i];
if (blocker._id == id) {
vocbase->_compactionBlockers._data.erase(vocbase->_compactionBlockers._data.begin() + i);
found = true;
break;
return TRI_ERROR_NO_ERROR;
}
}
UnlockCompaction(vocbase);
if (!found) {
return TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND;
}
return TRI_ERROR_NO_ERROR;
/// @brief check whether there is an active compaction blocker
/// note that this must be called while holding the compactionBlockers lock
static bool HasActiveBlockers(TRI_vocbase_t* vocbase) {
double const now = TRI_microtime();
// check if we have a still-valid compaction blocker
for (auto const& blocker : vocbase->_compactionBlockers._data) {
if (blocker._expires > now) {
// found a compaction blocker
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
@ -1199,8 +1101,11 @@ void TRI_CompactorVocBase(void* data) {
// compaction loop
int state = vocbase->_state;
{
// check if compaction is currently disallowed
if (CheckAndLockCompaction(vocbase)) {
TRY_WRITE_LOCKER(compactionLocker, vocbase->_compactionBlockers._lock);
if (compactionLocker.isLocked() && !HasActiveBlockers(vocbase)) {
// compaction is currently allowed
double now = TRI_microtime();
numCompacted = 0;
@ -1292,8 +1197,7 @@ void TRI_CompactorVocBase(void* data) {
TRI_UnlockCondition(&vocbase->_cleanupCondition);
}
}
UnlockCompaction(vocbase);
}
}
if (numCompacted > 0) {

View File

@ -25,65 +25,23 @@
#define ARANGOD_VOC_BASE_COMPACTOR_H 1
#include "Basics/Common.h"
#include "VocBase/voc-types.h"
struct TRI_vocbase_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief initialize the compaction blockers structure
////////////////////////////////////////////////////////////////////////////////
int TRI_InitCompactorVocBase(TRI_vocbase_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief destroy the compaction blockers structure
////////////////////////////////////////////////////////////////////////////////
void TRI_DestroyCompactorVocBase(TRI_vocbase_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief remove data of expired compaction blockers
////////////////////////////////////////////////////////////////////////////////
bool TRI_CleanupCompactorVocBase(TRI_vocbase_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief insert a compaction blocker
////////////////////////////////////////////////////////////////////////////////
int TRI_InsertBlockerCompactorVocBase(TRI_vocbase_t*, double, TRI_voc_tick_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief touch an existing compaction blocker
////////////////////////////////////////////////////////////////////////////////
int TRI_TouchBlockerCompactorVocBase(TRI_vocbase_t*, TRI_voc_tick_t, double);
////////////////////////////////////////////////////////////////////////////////
/// @brief remove an existing compaction blocker
////////////////////////////////////////////////////////////////////////////////
int TRI_RemoveBlockerCompactorVocBase(TRI_vocbase_t*, TRI_voc_tick_t);
////////////////////////////////////////////////////////////////////////////////
/// @brief atomically check-and-lock the compactor
/// if the function returns true, then a write-lock on the compactor was
/// acquired, which must eventually be freed by the caller
////////////////////////////////////////////////////////////////////////////////
bool TRI_CheckAndLockCompactorVocBase(TRI_vocbase_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief unlock the compactor
////////////////////////////////////////////////////////////////////////////////
void TRI_UnlockCompactorVocBase(TRI_vocbase_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief compactor event loop
////////////////////////////////////////////////////////////////////////////////
void TRI_CompactorVocBase(void*);
#endif

View File

@ -1264,8 +1264,6 @@ TRI_vocbase_t* TRI_OpenVocBase(char const* path,
return nullptr;
}
TRI_InitCompactorVocBase(vocbase);
// .............................................................................
// scan directory for collections
// .............................................................................
@ -1277,7 +1275,6 @@ TRI_vocbase_t* TRI_OpenVocBase(char const* path,
int res = ScanPath(vocbase, vocbase->_path, isUpgrade, iterateMarkers);
if (res != TRI_ERROR_NO_ERROR) {
TRI_DestroyCompactorVocBase(vocbase);
delete vocbase;
TRI_set_errno(res);
@ -1384,8 +1381,6 @@ void TRI_DestroyVocBase(TRI_vocbase_t* vocbase) {
for (auto& collection : vocbase->_collections) {
delete collection;
}
TRI_DestroyCompactorVocBase(vocbase);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -64,12 +64,10 @@ struct compaction_blocker_t {
};
struct compaction_blockers_t {
TRI_read_write_lock_t _lock;
arangodb::basics::ReadWriteLock _lock;
std::vector<compaction_blocker_t> _data;
};
extern bool IGNORE_DATAFILE_ERRORS;
////////////////////////////////////////////////////////////////////////////////
/// @brief tries to read lock the vocbase collection status
////////////////////////////////////////////////////////////////////////////////