diff --git a/CHANGELOG b/CHANGELOG index 668ffb9e5a..4d3f1037ec 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,9 @@ v1.4.0-XXXXX (2013-XX-XX) ------------------------- +* improved server shutdown time by signalling shutdown to applicationserver, + logging, cleanup and compactor threads + * added foxx-manager `replace` command * added foxx-manager `installed` command (a more intuitive alias for `list`) diff --git a/arangod/VocBase/cleanup.c b/arangod/VocBase/cleanup.c index 07da10b0c9..f91613adab 100644 --- a/arangod/VocBase/cleanup.c +++ b/arangod/VocBase/cleanup.c @@ -305,9 +305,11 @@ void TRI_CleanupVocBase (void* data) { // clean up expired compactor locks TRI_CleanupCompactorVocBase(vocbase); - TRI_LockCondition(&vocbase->_cleanupCondition); - TRI_TimedWaitCondition(&vocbase->_cleanupCondition, (uint64_t) CLEANUP_INTERVAL); - TRI_UnlockCondition(&vocbase->_cleanupCondition); + if (state == 1) { + TRI_LockCondition(&vocbase->_cleanupCondition); + TRI_TimedWaitCondition(&vocbase->_cleanupCondition, (uint64_t) CLEANUP_INTERVAL); + TRI_UnlockCondition(&vocbase->_cleanupCondition); + } } if (state == 3) { diff --git a/arangod/VocBase/compactor.c b/arangod/VocBase/compactor.c index 86e42c7e5d..24085e2cf0 100644 --- a/arangod/VocBase/compactor.c +++ b/arangod/VocBase/compactor.c @@ -1476,9 +1476,11 @@ void TRI_CompactorVocBase (void* data) { } - if (vocbase->_state == 1) { + if (state != 2 && vocbase->_state == 1) { // only sleep while server is still running - usleep(COMPACTOR_INTERVAL); + TRI_LockCondition(&vocbase->_compactorCondition); + TRI_TimedWaitCondition(&vocbase->_compactorCondition, (uint64_t) COMPACTOR_INTERVAL); + TRI_UnlockCondition(&vocbase->_compactorCondition); } if (state == 2) { diff --git a/arangod/VocBase/server.c b/arangod/VocBase/server.c index 8dab2c15b5..c95438e1f8 100644 --- a/arangod/VocBase/server.c +++ b/arangod/VocBase/server.c @@ -592,6 +592,11 @@ static int OpenDatabases (TRI_server_t* server) { res = TRI_ERROR_NO_ERROR; files = TRI_FilesDirectory(server->_databasePath); n = files._length; + + // open databases in defined order + if (n > 1) { + qsort(files._buffer, n, sizeof(char**), &NameComparator); + } for (i = 0; i < n; ++i) { TRI_vocbase_t* vocbase; @@ -825,7 +830,7 @@ static int OpenDatabases (TRI_server_t* server) { static int CloseDatabases (TRI_server_t* server) { size_t i, n; - + TRI_WriteLockReadWriteLock(&server->_databasesLock); n = server->_databases._nrAlloc; diff --git a/arangod/VocBase/vocbase.c b/arangod/VocBase/vocbase.c index cfba63e11c..313dbc49a0 100644 --- a/arangod/VocBase/vocbase.c +++ b/arangod/VocBase/vocbase.c @@ -1340,6 +1340,7 @@ TRI_vocbase_t* TRI_OpenVocBase (TRI_server_t* server, vocbase->_syncWaiters = 0; TRI_InitCondition(&vocbase->_syncWaitersCondition); + TRI_InitCondition(&vocbase->_compactorCondition); TRI_InitCondition(&vocbase->_cleanupCondition); // ............................................................................. @@ -1489,10 +1490,18 @@ void TRI_DestroyVocBase (TRI_vocbase_t* vocbase) { // wait until synchroniser and compactor are finished TRI_JoinThread(&vocbase->_synchroniser); + + TRI_LockCondition(&vocbase->_compactorCondition); + TRI_SignalCondition(&vocbase->_compactorCondition); + TRI_UnlockCondition(&vocbase->_compactorCondition); TRI_JoinThread(&vocbase->_compactor); // this will signal the cleanup thread to do one last iteration vocbase->_state = 3; + + TRI_LockCondition(&vocbase->_cleanupCondition); + TRI_SignalCondition(&vocbase->_cleanupCondition); + TRI_UnlockCondition(&vocbase->_cleanupCondition); TRI_JoinThread(&vocbase->_cleanup); // free replication @@ -1513,9 +1522,7 @@ void TRI_DestroyVocBase (TRI_vocbase_t* vocbase) { // free collections for (i = 0; i < vocbase->_collections._length; ++i) { - TRI_vocbase_col_t* collection; - - collection = (TRI_vocbase_col_t*) vocbase->_collections._buffer[i]; + TRI_vocbase_col_t* collection = (TRI_vocbase_col_t*) vocbase->_collections._buffer[i]; TRI_FreeCollectionVocBase(collection); } @@ -1544,6 +1551,7 @@ void TRI_DestroyVocBase (TRI_vocbase_t* vocbase) { TRI_DestroyReadWriteLock(&vocbase->_lock); TRI_DestroyCondition(&vocbase->_syncWaitersCondition); TRI_DestroyCondition(&vocbase->_cleanupCondition); + TRI_DestroyCondition(&vocbase->_compactorCondition); // free name and path TRI_Free(TRI_CORE_MEM_ZONE, vocbase->_path); diff --git a/arangod/VocBase/vocbase.h b/arangod/VocBase/vocbase.h index 5435936d17..9e405f548d 100644 --- a/arangod/VocBase/vocbase.h +++ b/arangod/VocBase/vocbase.h @@ -367,6 +367,7 @@ typedef struct TRI_vocbase_s { } _compactionBlockers; + TRI_condition_t _compactorCondition; TRI_condition_t _cleanupCondition; TRI_condition_t _syncWaitersCondition; int64_t _syncWaiters; diff --git a/lib/ApplicationServer/ApplicationServer.cpp b/lib/ApplicationServer/ApplicationServer.cpp index 50eb50696b..99073593b4 100644 --- a/lib/ApplicationServer/ApplicationServer.cpp +++ b/lib/ApplicationServer/ApplicationServer.cpp @@ -39,6 +39,7 @@ #endif #include "ApplicationServer/ApplicationFeature.h" +#include "Basics/ConditionLocker.h" #include "Basics/FileUtils.h" #include "Basics/RandomGenerator.h" #include "Basics/StringUtils.h" @@ -144,7 +145,8 @@ ApplicationServer::ApplicationServer (std::string const& name, std::string const _logLineNumber(false), _logSourceFilter(), _logContentFilter(), - _randomGenerator(5) { + _randomGenerator(5), + _finishedCondition() { } #else @@ -185,7 +187,8 @@ ApplicationServer::ApplicationServer (std::string const& name, std::string const _logLineNumber(false), _logSourceFilter(), _logContentFilter(), - _randomGenerator(3) { + _randomGenerator(3), + _finishedCondition() { storeRealPrivileges(); } @@ -623,7 +626,9 @@ void ApplicationServer::wait () { running = false; break; } - sleep(1); + + CONDITION_LOCKER(locker, _finishedCondition); + locker.wait((uint64_t) (1000 * 1000)); } } @@ -645,6 +650,8 @@ void ApplicationServer::beginShutdown () { void ApplicationServer::stop () { beginShutdown(); + CONDITION_LOCKER(locker, _finishedCondition); + locker.signal(); // close all features for (vector::iterator i = _features.begin(); i != _features.end(); ++i) { @@ -664,8 +671,6 @@ void ApplicationServer::stop () { feature->stop(); LOGGER_TRACE("shut down server feature '" << feature->getName() << "'"); } - - } //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/ApplicationServer/ApplicationServer.h b/lib/ApplicationServer/ApplicationServer.h index f8fb3086b8..840b679378 100644 --- a/lib/ApplicationServer/ApplicationServer.h +++ b/lib/ApplicationServer/ApplicationServer.h @@ -31,6 +31,7 @@ #include "Basics/Common.h" #include "Basics/ProgramOptions.h" +#include "Basics/ConditionVariable.h" // ----------------------------------------------------------------------------- // --SECTION-- forward declarations @@ -840,6 +841,12 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// uint32_t _randomGenerator; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief condition variable for done +//////////////////////////////////////////////////////////////////////////////// + + triagens::basics::ConditionVariable _finishedCondition; }; } } diff --git a/lib/Basics/ConditionLocker.cpp b/lib/Basics/ConditionLocker.cpp index 77dce91e75..8d60af7a51 100644 --- a/lib/Basics/ConditionLocker.cpp +++ b/lib/Basics/ConditionLocker.cpp @@ -111,6 +111,14 @@ void ConditionLocker::broadcast () { _conditionVariable->broadcast(); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief signals an event +//////////////////////////////////////////////////////////////////////////////// + +void ConditionLocker::signal () { + _conditionVariable->signal(); +} + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/Basics/ConditionLocker.h b/lib/Basics/ConditionLocker.h index 1c601de11a..2111b0f88c 100644 --- a/lib/Basics/ConditionLocker.h +++ b/lib/Basics/ConditionLocker.h @@ -150,6 +150,12 @@ namespace triagens { void broadcast (); +//////////////////////////////////////////////////////////////////////////////// +/// @brief signals an event +//////////////////////////////////////////////////////////////////////////////// + + void signal (); + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/Basics/ConditionVariable.cpp b/lib/Basics/ConditionVariable.cpp index fc2c4efe49..77cb2220f2 100644 --- a/lib/Basics/ConditionVariable.cpp +++ b/lib/Basics/ConditionVariable.cpp @@ -109,6 +109,14 @@ void ConditionVariable::broadcast () { TRI_BroadcastCondition(&_condition); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief signals a waiting thread +//////////////////////////////////////////////////////////////////////////////// + +void ConditionVariable::signal () { + TRI_SignalCondition(&_condition); +} + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/Basics/ConditionVariable.h b/lib/Basics/ConditionVariable.h index 84f433a90d..dfcafda97d 100644 --- a/lib/Basics/ConditionVariable.h +++ b/lib/Basics/ConditionVariable.h @@ -151,6 +151,12 @@ namespace triagens { void broadcast (); +//////////////////////////////////////////////////////////////////////////////// +/// @brief signals a waiting thread +//////////////////////////////////////////////////////////////////////////////// + + void signal (); + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/BasicsC/logging.c b/lib/BasicsC/logging.c index 4be0c8715b..be9f269e2f 100644 --- a/lib/BasicsC/logging.c +++ b/lib/BasicsC/logging.c @@ -151,6 +151,12 @@ static TRI_log_buffer_t BufferOutput[OUTPUT_LOG_LEVELS][OUTPUT_BUFFER_SIZE]; static TRI_mutex_t BufferLock; +//////////////////////////////////////////////////////////////////////////////// +/// @brief condition variable for the logger +//////////////////////////////////////////////////////////////////////////////// + +static TRI_condition_t LogCondition; + //////////////////////////////////////////////////////////////////////////////// /// @brief message queue lock //////////////////////////////////////////////////////////////////////////////// @@ -790,7 +796,9 @@ static void MessageQueueWorker (void* data) { } if (LoggingActive) { - usleep(sl); + TRI_LockCondition(&LogCondition); + TRI_TimedWaitCondition(&LogCondition, (uint64_t) sl); + TRI_UnlockCondition(&LogCondition); } else { TRI_LockMutex(&LogMessageQueueLock); @@ -1905,6 +1913,7 @@ void TRI_InitialiseLogging (bool threaded) { ThreadedLogging = threaded; if (threaded) { + TRI_InitCondition(&LogCondition); TRI_InitMutex(&LogMessageQueueLock); TRI_InitVector(&LogMessageQueue, TRI_CORE_MEM_ZONE, sizeof(log_message_t)); @@ -1943,9 +1952,14 @@ bool TRI_ShutdownLogging (bool clearBuffers) { // join with the logging thread if (ThreadedLogging) { + TRI_LockCondition(&LogCondition); + TRI_SignalCondition(&LogCondition); + TRI_UnlockCondition(&LogCondition); + TRI_JoinThread(&LoggingThread); TRI_DestroyMutex(&LogMessageQueueLock); TRI_DestroyVector(&LogMessageQueue); + TRI_DestroyCondition(&LogCondition); } // cleanup appenders diff --git a/lib/Scheduler/ApplicationScheduler.cpp b/lib/Scheduler/ApplicationScheduler.cpp index 21632b46ce..bc5c1d8716 100644 --- a/lib/Scheduler/ApplicationScheduler.cpp +++ b/lib/Scheduler/ApplicationScheduler.cpp @@ -574,7 +574,7 @@ void ApplicationScheduler::stop () { for (size_t count = 0; count < MAX_TRIES && _scheduler->isRunning(); ++count) { LOGGER_TRACE("waiting for scheduler to stop"); - usleep(1000000); + usleep(100000); } _scheduler->shutdown();