mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of https://github.com/arangodb/arangodb into engine-api
This commit is contained in:
commit
c652a313da
|
@ -512,14 +512,7 @@ else ()
|
||||||
-Dlinux_use_gold_flags=0
|
-Dlinux_use_gold_flags=0
|
||||||
-Dv8_no_strict_aliasing=1
|
-Dv8_no_strict_aliasing=1
|
||||||
-Dwerror=
|
-Dwerror=
|
||||||
)
|
-Dv8_use_snapshot=true )
|
||||||
|
|
||||||
if (CROSS_COMPILING)
|
|
||||||
list(APPEND V8_GYP_ARGS -Dv8_use_snapshot=false )
|
|
||||||
# dependenis 'v8_libbase' and 'v8_libplatform' need be added in v8.gyp (under 'v8_use_snapshot!="true"')
|
|
||||||
else ()
|
|
||||||
list(APPEND V8_GYP_ARGS -Dv8_use_snapshot=true )
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (APPLE AND CMAKE_COMPILER_IS_CLANG)
|
if (APPLE AND CMAKE_COMPILER_IS_CLANG)
|
||||||
set(V8_CXXFLAGS "${V8_CXXFLAGS} -stdlib=libc++")
|
set(V8_CXXFLAGS "${V8_CXXFLAGS} -stdlib=libc++")
|
||||||
|
|
12
CHANGELOG
12
CHANGELOG
|
@ -1,6 +1,13 @@
|
||||||
devel
|
devel
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
* ui: fixed issue #2065
|
||||||
|
|
||||||
|
* ui: fixed a dashboard related memory issue
|
||||||
|
|
||||||
|
* Internal javascript rest actions will now hide their stack traces to the client
|
||||||
|
unless maintainer mode is activated. Instead they will always log to the logfile
|
||||||
|
|
||||||
* Removed undocumented internal HTTP API:
|
* Removed undocumented internal HTTP API:
|
||||||
* PUT _api/edges
|
* PUT _api/edges
|
||||||
|
|
||||||
|
@ -51,9 +58,12 @@ v3.2.alpha1 (2017-02-05)
|
||||||
* more detailed stacktraces in Foxx apps
|
* more detailed stacktraces in Foxx apps
|
||||||
|
|
||||||
|
|
||||||
v3.1.11 (2017-02-13)
|
v3.1.11 (2017-02-14)
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
* fixed a race between connection closing and sending out last chunks of data to clients
|
||||||
|
when the "Connection: close" HTTP header was set in requests
|
||||||
|
|
||||||
* ui: optimized smart graph creation usability
|
* ui: optimized smart graph creation usability
|
||||||
|
|
||||||
* ui: fixed #2308
|
* ui: fixed #2308
|
||||||
|
|
|
@ -603,7 +603,7 @@ if test -n "${TARGET_DIR}"; then
|
||||||
if [ -n "$CPACK" -a -n "${TARGET_DIR}" ]; then
|
if [ -n "$CPACK" -a -n "${TARGET_DIR}" ]; then
|
||||||
${PACKAGE_MAKE} copy_packages || exit 1
|
${PACKAGE_MAKE} copy_packages || exit 1
|
||||||
${PACKAGE_MAKE} clean_packages || exit 1
|
${PACKAGE_MAKE} clean_packages || exit 1
|
||||||
if test "${SYMSRV}" -eq 1; then
|
if test "${SYMSRV}" = "1"; then
|
||||||
echo "Storing symbols:"
|
echo "Storing symbols:"
|
||||||
export LIST="`pwd`/pdbfiles_list.txt"
|
export LIST="`pwd`/pdbfiles_list.txt"
|
||||||
find `pwd`/bin/ -name *pdb |grep -v Release |grep -v Debug |grep -v 3rdParty |grep -v vc120.pdb |cygpath -f - --windows > ${LIST}
|
find `pwd`/bin/ -name *pdb |grep -v Release |grep -v Debug |grep -v 3rdParty |grep -v vc120.pdb |cygpath -f - --windows > ${LIST}
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
// Execution plan:
|
// Execution plan:
|
||||||
// Id NodeType Est. Comment
|
// Id NodeType Est. Comment
|
||||||
// 1 SingletonNode 1 * ROOT
|
// 1 SingletonNode 1 * ROOT
|
||||||
// 2 EnumerateCollectionNode 6400 - FOR d IN ulf /* full collection scan */
|
// 2 EnumerateCollectionNode 6400 - FOR d IN coll /* full collection scan */
|
||||||
// 3 CalculationNode 6400 - LET #1 = DISTANCE(d.`lat`, d.`lon`, 0, 0) /* simple expression */ /* collections used: d : ulf */
|
// 3 CalculationNode 6400 - LET #1 = DISTANCE(d.`lat`, d.`lon`, 0, 0) /* simple expression */ /* collections used: d : coll */
|
||||||
// 4 SortNode 6400 - SORT #1 ASC
|
// 4 SortNode 6400 - SORT #1 ASC
|
||||||
// 5 LimitNode 5 - LIMIT 0, 5
|
// 5 LimitNode 5 - LIMIT 0, 5
|
||||||
// 6 ReturnNode 5 - RETURN d
|
// 6 ReturnNode 5 - RETURN d
|
||||||
|
|
|
@ -1591,7 +1591,7 @@ int MMFilesEngine::insertCompactionBlocker(TRI_vocbase_t* vocbase, double ttl,
|
||||||
CompactionBlocker blocker(TRI_NewTickServer(), TRI_microtime() + ttl);
|
CompactionBlocker blocker(TRI_NewTickServer(), TRI_microtime() + ttl);
|
||||||
|
|
||||||
{
|
{
|
||||||
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock, 1000);
|
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock);
|
||||||
|
|
||||||
auto it = _compactionBlockers.find(vocbase);
|
auto it = _compactionBlockers.find(vocbase);
|
||||||
|
|
||||||
|
@ -1614,7 +1614,7 @@ int MMFilesEngine::extendCompactionBlocker(TRI_vocbase_t* vocbase, TRI_voc_tick_
|
||||||
return TRI_ERROR_BAD_PARAMETER;
|
return TRI_ERROR_BAD_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock, 1000);
|
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock);
|
||||||
|
|
||||||
auto it = _compactionBlockers.find(vocbase);
|
auto it = _compactionBlockers.find(vocbase);
|
||||||
|
|
||||||
|
@ -1635,7 +1635,7 @@ int MMFilesEngine::extendCompactionBlocker(TRI_vocbase_t* vocbase, TRI_voc_tick_
|
||||||
/// @brief remove an existing compaction blocker
|
/// @brief remove an existing compaction blocker
|
||||||
int MMFilesEngine::removeCompactionBlocker(TRI_vocbase_t* vocbase,
|
int MMFilesEngine::removeCompactionBlocker(TRI_vocbase_t* vocbase,
|
||||||
TRI_voc_tick_t id) {
|
TRI_voc_tick_t id) {
|
||||||
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock, 1000);
|
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock);
|
||||||
|
|
||||||
auto it = _compactionBlockers.find(vocbase);
|
auto it = _compactionBlockers.find(vocbase);
|
||||||
|
|
||||||
|
@ -1663,7 +1663,7 @@ int MMFilesEngine::removeCompactionBlocker(TRI_vocbase_t* vocbase,
|
||||||
|
|
||||||
void MMFilesEngine::preventCompaction(TRI_vocbase_t* vocbase,
|
void MMFilesEngine::preventCompaction(TRI_vocbase_t* vocbase,
|
||||||
std::function<void(TRI_vocbase_t*)> const& callback) {
|
std::function<void(TRI_vocbase_t*)> const& callback) {
|
||||||
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock, 5000);
|
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock);
|
||||||
callback(vocbase);
|
callback(vocbase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ retry:
|
||||||
|
|
||||||
// reset failed connects
|
// reset failed connects
|
||||||
{
|
{
|
||||||
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock);
|
||||||
_applier->_state._failedConnects = 0;
|
_applier->_state._failedConnects = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ retry:
|
||||||
connectRetries++;
|
connectRetries++;
|
||||||
|
|
||||||
{
|
{
|
||||||
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock);
|
||||||
_applier->_state._failedConnects = connectRetries;
|
_applier->_state._failedConnects = connectRetries;
|
||||||
_applier->_state._totalRequests++;
|
_applier->_state._totalRequests++;
|
||||||
_applier->_state._totalFailedConnects++;
|
_applier->_state._totalFailedConnects++;
|
||||||
|
@ -163,7 +163,7 @@ retry:
|
||||||
LOG_TOPIC(WARN, Logger::REPLICATION) << "requireFromPresent feature is not supported on master server < ArangoDB 2.7";
|
LOG_TOPIC(WARN, Logger::REPLICATION) << "requireFromPresent feature is not supported on master server < ArangoDB 2.7";
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock);
|
||||||
res = getLocalState(errorMsg);
|
res = getLocalState(errorMsg);
|
||||||
|
|
||||||
_applier->_state._failedConnects = 0;
|
_applier->_state._failedConnects = 0;
|
||||||
|
@ -199,7 +199,7 @@ retry:
|
||||||
TRI_RemoveStateReplicationApplier(_vocbase);
|
TRI_RemoveStateReplicationApplier(_vocbase);
|
||||||
|
|
||||||
{
|
{
|
||||||
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock);
|
||||||
|
|
||||||
LOG_TOPIC(DEBUG, Logger::REPLICATION) << "stopped replication applier for database '" << _vocbase->name() << "' with lastProcessedContinuousTick: " << _applier->_state._lastProcessedContinuousTick << ", lastAppliedContinuousTick: " << _applier->_state._lastAppliedContinuousTick << ", safeResumeTick: " << _applier->_state._safeResumeTick;
|
LOG_TOPIC(DEBUG, Logger::REPLICATION) << "stopped replication applier for database '" << _vocbase->name() << "' with lastProcessedContinuousTick: " << _applier->_state._lastProcessedContinuousTick << ", lastAppliedContinuousTick: " << _applier->_state._lastAppliedContinuousTick << ", safeResumeTick: " << _applier->_state._safeResumeTick;
|
||||||
|
|
||||||
|
@ -808,7 +808,7 @@ int ContinuousSyncer::applyLogMarker(VPackSlice const& slice,
|
||||||
TRI_voc_tick_t newTick = static_cast<TRI_voc_tick_t>(
|
TRI_voc_tick_t newTick = static_cast<TRI_voc_tick_t>(
|
||||||
StringUtils::uint64(tick.c_str(), tick.size()));
|
StringUtils::uint64(tick.c_str(), tick.size()));
|
||||||
|
|
||||||
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock);
|
||||||
|
|
||||||
if (newTick >= firstRegularTick &&
|
if (newTick >= firstRegularTick &&
|
||||||
newTick > _applier->_state._lastProcessedContinuousTick) {
|
newTick > _applier->_state._lastProcessedContinuousTick) {
|
||||||
|
@ -960,7 +960,7 @@ int ContinuousSyncer::applyLog(SimpleHttpResult* response,
|
||||||
}
|
}
|
||||||
|
|
||||||
// update tick value
|
// update tick value
|
||||||
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock);
|
||||||
|
|
||||||
if (_applier->_state._lastProcessedContinuousTick >
|
if (_applier->_state._lastProcessedContinuousTick >
|
||||||
_applier->_state._lastAppliedContinuousTick) {
|
_applier->_state._lastAppliedContinuousTick) {
|
||||||
|
@ -996,7 +996,7 @@ int ContinuousSyncer::runContinuousSync(std::string& errorMsg) {
|
||||||
TRI_voc_tick_t safeResumeTick = 0;
|
TRI_voc_tick_t safeResumeTick = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock);
|
||||||
|
|
||||||
if (_useTick) {
|
if (_useTick) {
|
||||||
// use user-defined tick
|
// use user-defined tick
|
||||||
|
@ -1079,7 +1079,7 @@ int ContinuousSyncer::runContinuousSync(std::string& errorMsg) {
|
||||||
connectRetries++;
|
connectRetries++;
|
||||||
|
|
||||||
{
|
{
|
||||||
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock);
|
||||||
|
|
||||||
_applier->_state._failedConnects = connectRetries;
|
_applier->_state._failedConnects = connectRetries;
|
||||||
_applier->_state._totalRequests++;
|
_applier->_state._totalRequests++;
|
||||||
|
@ -1094,7 +1094,7 @@ int ContinuousSyncer::runContinuousSync(std::string& errorMsg) {
|
||||||
connectRetries = 0;
|
connectRetries = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock);
|
||||||
|
|
||||||
_applier->_state._failedConnects = connectRetries;
|
_applier->_state._failedConnects = connectRetries;
|
||||||
_applier->_state._totalRequests++;
|
_applier->_state._totalRequests++;
|
||||||
|
@ -1397,7 +1397,7 @@ int ContinuousSyncer::followMasterLog(std::string& errorMsg,
|
||||||
if (found) {
|
if (found) {
|
||||||
tick = StringUtils::uint64(header);
|
tick = StringUtils::uint64(header);
|
||||||
|
|
||||||
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock);
|
||||||
_applier->_state._lastAvailableContinuousTick = tick;
|
_applier->_state._lastAvailableContinuousTick = tick;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1426,7 +1426,7 @@ int ContinuousSyncer::followMasterLog(std::string& errorMsg,
|
||||||
TRI_voc_tick_t lastAppliedTick;
|
TRI_voc_tick_t lastAppliedTick;
|
||||||
|
|
||||||
{
|
{
|
||||||
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock);
|
||||||
lastAppliedTick = _applier->_state._lastAppliedContinuousTick;
|
lastAppliedTick = _applier->_state._lastAppliedContinuousTick;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1438,7 +1438,7 @@ int ContinuousSyncer::followMasterLog(std::string& errorMsg,
|
||||||
if (processedMarkers > 0) {
|
if (processedMarkers > 0) {
|
||||||
worked = true;
|
worked = true;
|
||||||
|
|
||||||
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock);
|
||||||
_applier->_state._totalEvents += processedMarkers;
|
_applier->_state._totalEvents += processedMarkers;
|
||||||
|
|
||||||
if (_applier->_state._lastAppliedContinuousTick != lastAppliedTick) {
|
if (_applier->_state._lastAppliedContinuousTick != lastAppliedTick) {
|
||||||
|
@ -1451,7 +1451,7 @@ int ContinuousSyncer::followMasterLog(std::string& errorMsg,
|
||||||
// write state at least once so the start tick gets saved
|
// write state at least once so the start tick gets saved
|
||||||
_hasWrittenState = true;
|
_hasWrittenState = true;
|
||||||
|
|
||||||
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLocker, _applier->_statusLock);
|
||||||
|
|
||||||
_applier->_state._lastAppliedContinuousTick = firstRegularTick;
|
_applier->_state._lastAppliedContinuousTick = firstRegularTick;
|
||||||
_applier->_state._lastProcessedContinuousTick = firstRegularTick;
|
_applier->_state._lastProcessedContinuousTick = firstRegularTick;
|
||||||
|
|
|
@ -101,7 +101,7 @@ void AqlFeature::stop() {
|
||||||
if (n == 0 && m == 0 && o == 0) {
|
if (n == 0 && m == 0 && o == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
LOG_TOPIC(INFO, Logger::QUERIES) << "AQLFeature shutdown, waiting for "
|
LOG_TOPIC(DEBUG, Logger::QUERIES) << "AQLFeature shutdown, waiting for "
|
||||||
<< o << " registered traverser engines to terminate and for "
|
<< o << " registered traverser engines to terminate and for "
|
||||||
<< n << " registered queries to terminate and for "
|
<< n << " registered queries to terminate and for "
|
||||||
<< m << " feature leases to be released";
|
<< m << " feature leases to be released";
|
||||||
|
|
|
@ -409,10 +409,8 @@ bool SocketTask::processAll() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_closeRequested) {
|
if (_closeRequested) {
|
||||||
LOG_TOPIC(DEBUG, Logger::COMMUNICATION)
|
// it is too early to close the stream here, as there may
|
||||||
<< "close requested, closing receive stream ";
|
// be some writeBuffers which still need to be sent to the client
|
||||||
|
|
||||||
closeReceiveStream();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -325,7 +325,7 @@ int RocksDBEngine::insertCompactionBlocker(TRI_vocbase_t* vocbase, double ttl,
|
||||||
CompactionBlocker blocker(TRI_NewTickServer(), TRI_microtime() + ttl);
|
CompactionBlocker blocker(TRI_NewTickServer(), TRI_microtime() + ttl);
|
||||||
|
|
||||||
{
|
{
|
||||||
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock, 1000);
|
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock);
|
||||||
|
|
||||||
auto it = _compactionBlockers.find(vocbase);
|
auto it = _compactionBlockers.find(vocbase);
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ int RocksDBEngine::extendCompactionBlocker(TRI_vocbase_t* vocbase, TRI_voc_tick_
|
||||||
return TRI_ERROR_BAD_PARAMETER;
|
return TRI_ERROR_BAD_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock, 1000);
|
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock);
|
||||||
|
|
||||||
auto it = _compactionBlockers.find(vocbase);
|
auto it = _compactionBlockers.find(vocbase);
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ int RocksDBEngine::extendCompactionBlocker(TRI_vocbase_t* vocbase, TRI_voc_tick_
|
||||||
/// @brief remove an existing compaction blocker
|
/// @brief remove an existing compaction blocker
|
||||||
int RocksDBEngine::removeCompactionBlocker(TRI_vocbase_t* vocbase,
|
int RocksDBEngine::removeCompactionBlocker(TRI_vocbase_t* vocbase,
|
||||||
TRI_voc_tick_t id) {
|
TRI_voc_tick_t id) {
|
||||||
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock, 1000);
|
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock);
|
||||||
|
|
||||||
auto it = _compactionBlockers.find(vocbase);
|
auto it = _compactionBlockers.find(vocbase);
|
||||||
|
|
||||||
|
@ -397,7 +397,7 @@ int RocksDBEngine::removeCompactionBlocker(TRI_vocbase_t* vocbase,
|
||||||
|
|
||||||
void RocksDBEngine::preventCompaction(TRI_vocbase_t* vocbase,
|
void RocksDBEngine::preventCompaction(TRI_vocbase_t* vocbase,
|
||||||
std::function<void(TRI_vocbase_t*)> const& callback) {
|
std::function<void(TRI_vocbase_t*)> const& callback) {
|
||||||
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock, 5000);
|
WRITE_LOCKER_EVENTUAL(locker, _compactionBlockersLock);
|
||||||
callback(vocbase);
|
callback(vocbase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -833,7 +833,7 @@ int LogicalCollection::rename(std::string const& newName) {
|
||||||
// Otherwise caching is destroyed.
|
// Otherwise caching is destroyed.
|
||||||
TRI_ASSERT(!ServerState::instance()->isCoordinator()); // NOT YET IMPLEMENTED
|
TRI_ASSERT(!ServerState::instance()->isCoordinator()); // NOT YET IMPLEMENTED
|
||||||
|
|
||||||
WRITE_LOCKER_EVENTUAL(locker, _lock, 1000);
|
WRITE_LOCKER_EVENTUAL(locker, _lock);
|
||||||
|
|
||||||
// Check for illeagal states.
|
// Check for illeagal states.
|
||||||
switch (_status) {
|
switch (_status) {
|
||||||
|
|
|
@ -60,6 +60,8 @@
|
||||||
#include "VocBase/replication-applier.h"
|
#include "VocBase/replication-applier.h"
|
||||||
#include "VocBase/ticks.h"
|
#include "VocBase/ticks.h"
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
using namespace arangodb;
|
using namespace arangodb;
|
||||||
using namespace arangodb::basics;
|
using namespace arangodb::basics;
|
||||||
|
|
||||||
|
@ -191,7 +193,7 @@ bool TRI_vocbase_t::unregisterCollection(arangodb::LogicalCollection* collection
|
||||||
bool TRI_vocbase_t::UnloadCollectionCallback(LogicalCollection* collection) {
|
bool TRI_vocbase_t::UnloadCollectionCallback(LogicalCollection* collection) {
|
||||||
TRI_ASSERT(collection != nullptr);
|
TRI_ASSERT(collection != nullptr);
|
||||||
|
|
||||||
WRITE_LOCKER_EVENTUAL(locker, collection->_lock, 1000);
|
WRITE_LOCKER_EVENTUAL(locker, collection->_lock);
|
||||||
|
|
||||||
if (collection->status() != TRI_VOC_COL_STATUS_UNLOADING) {
|
if (collection->status() != TRI_VOC_COL_STATUS_UNLOADING) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -233,7 +235,7 @@ bool TRI_vocbase_t::DropCollectionCallback(arangodb::LogicalCollection* collecti
|
||||||
std::string const name(collection->name());
|
std::string const name(collection->name());
|
||||||
|
|
||||||
{
|
{
|
||||||
WRITE_LOCKER_EVENTUAL(statusLock, collection->_lock, 1000);
|
WRITE_LOCKER_EVENTUAL(statusLock, collection->_lock);
|
||||||
|
|
||||||
if (collection->status() != TRI_VOC_COL_STATUS_DELETED) {
|
if (collection->status() != TRI_VOC_COL_STATUS_DELETED) {
|
||||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "someone resurrected the collection '" << name << "'";
|
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "someone resurrected the collection '" << name << "'";
|
||||||
|
@ -286,7 +288,7 @@ arangodb::LogicalCollection* TRI_vocbase_t::createCollectionWorker(
|
||||||
}
|
}
|
||||||
|
|
||||||
arangodb::LogicalCollection* collection =
|
arangodb::LogicalCollection* collection =
|
||||||
registerCollection(ConditionalWriteLocker<ReadWriteLock>::DoNotLock(), parameters);
|
registerCollection(basics::ConditionalLocking::DoNotLock, parameters);
|
||||||
|
|
||||||
// Register collection cannot return a nullptr.
|
// Register collection cannot return a nullptr.
|
||||||
// If it would return a nullptr it should have thrown instead
|
// If it would return a nullptr it should have thrown instead
|
||||||
|
@ -349,7 +351,7 @@ int TRI_vocbase_t::loadCollection(arangodb::LogicalCollection* collection,
|
||||||
// write lock
|
// write lock
|
||||||
// .............................................................................
|
// .............................................................................
|
||||||
|
|
||||||
WRITE_LOCKER_EVENTUAL(locker, collection->_lock, 1000);
|
WRITE_LOCKER_EVENTUAL(locker, collection->_lock);
|
||||||
|
|
||||||
// someone else loaded the collection, release the WRITE lock and try again
|
// someone else loaded the collection, release the WRITE lock and try again
|
||||||
if (collection->status() == TRI_VOC_COL_STATUS_LOADED) {
|
if (collection->status() == TRI_VOC_COL_STATUS_LOADED) {
|
||||||
|
@ -449,7 +451,7 @@ int TRI_vocbase_t::loadCollection(arangodb::LogicalCollection* collection,
|
||||||
}
|
}
|
||||||
|
|
||||||
// lock again to adjust the status
|
// lock again to adjust the status
|
||||||
locker.lockEventual(1000);
|
locker.lockEventual();
|
||||||
|
|
||||||
// no one else must have changed the status
|
// no one else must have changed the status
|
||||||
TRI_ASSERT(collection->status() == TRI_VOC_COL_STATUS_LOADING);
|
TRI_ASSERT(collection->status() == TRI_VOC_COL_STATUS_LOADING);
|
||||||
|
@ -475,9 +477,37 @@ int TRI_vocbase_t::dropCollectionWorker(arangodb::LogicalCollection* collection,
|
||||||
state = DROP_EXIT;
|
state = DROP_EXIT;
|
||||||
std::string const colName(collection->name());
|
std::string const colName(collection->name());
|
||||||
|
|
||||||
WRITE_LOCKER(writeLocker, _collectionsLock);
|
// do not acquire these locks instantly
|
||||||
|
CONDITIONAL_WRITE_LOCKER(writeLocker, _collectionsLock, basics::ConditionalLocking::DoNotLock);
|
||||||
|
CONDITIONAL_WRITE_LOCKER(locker, collection->_lock, basics::ConditionalLocking::DoNotLock);
|
||||||
|
|
||||||
WRITE_LOCKER_EVENTUAL(locker, collection->_lock, 1000);
|
while (true) {
|
||||||
|
TRI_ASSERT(!writeLocker.isLocked());
|
||||||
|
TRI_ASSERT(!locker.isLocked());
|
||||||
|
|
||||||
|
// block until we have acquired this lock
|
||||||
|
writeLocker.lock();
|
||||||
|
// we now have the one lock
|
||||||
|
|
||||||
|
TRI_ASSERT(writeLocker.isLocked());
|
||||||
|
|
||||||
|
if (locker.tryLock()) {
|
||||||
|
// we now have both locks and can continue outside of this loop
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unlock the write locker so we don't block other operations
|
||||||
|
writeLocker.unlock();
|
||||||
|
|
||||||
|
TRI_ASSERT(!writeLocker.isLocked());
|
||||||
|
TRI_ASSERT(!locker.isLocked());
|
||||||
|
|
||||||
|
// sleep for a while
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
TRI_ASSERT(writeLocker.isLocked());
|
||||||
|
TRI_ASSERT(locker.isLocked());
|
||||||
|
|
||||||
arangodb::aql::QueryCache::instance()->invalidate(this);
|
arangodb::aql::QueryCache::instance()->invalidate(this);
|
||||||
|
|
||||||
|
@ -654,7 +684,7 @@ std::shared_ptr<VPackBuilder> TRI_vocbase_t::inventory(TRI_voc_tick_t maxTick,
|
||||||
std::vector<arangodb::LogicalCollection*> collections;
|
std::vector<arangodb::LogicalCollection*> collections;
|
||||||
|
|
||||||
// cycle on write-lock
|
// cycle on write-lock
|
||||||
WRITE_LOCKER_EVENTUAL(writeLock, _inventoryLock, 1000);
|
WRITE_LOCKER_EVENTUAL(writeLock, _inventoryLock);
|
||||||
|
|
||||||
// copy collection pointers into vector so we can work with the copy without
|
// copy collection pointers into vector so we can work with the copy without
|
||||||
// the global lock
|
// the global lock
|
||||||
|
@ -814,7 +844,7 @@ arangodb::LogicalCollection* TRI_vocbase_t::createCollection(
|
||||||
int TRI_vocbase_t::unloadCollection(arangodb::LogicalCollection* collection, bool force) {
|
int TRI_vocbase_t::unloadCollection(arangodb::LogicalCollection* collection, bool force) {
|
||||||
TRI_voc_cid_t cid = collection->cid();
|
TRI_voc_cid_t cid = collection->cid();
|
||||||
{
|
{
|
||||||
WRITE_LOCKER_EVENTUAL(locker, collection->_lock, 1000);
|
WRITE_LOCKER_EVENTUAL(locker, collection->_lock);
|
||||||
|
|
||||||
// cannot unload a corrupted collection
|
// cannot unload a corrupted collection
|
||||||
if (collection->status() == TRI_VOC_COL_STATUS_CORRUPTED) {
|
if (collection->status() == TRI_VOC_COL_STATUS_CORRUPTED) {
|
||||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1819,8 +1819,9 @@ if (list.length > 0) {
|
||||||
<div class="dashboard-legend-inner" id="detailLegend"></div>
|
<div class="dashboard-legend-inner" id="detailLegend"></div>
|
||||||
</div>
|
</div>
|
||||||
</div></script><script id="modalGraphTable.ejs" type="text/template"><ul id="graphTab" class="nav nav-tabs">
|
</div></script><script id="modalGraphTable.ejs" type="text/template"><ul id="graphTab" class="nav nav-tabs">
|
||||||
<li class="active"><a href="#createGraph" data-toggle="tab" id="tab-createGraph">Create Graph</a></li>
|
<li class="active"><a href="#createGraph" data-toggle="tab" id="tab-createGraph">Graph</a></li>
|
||||||
<li><a href="#exampleGraphs" data-toggle="tab" id="tab-exampleGraphs">Example Graphs</a></li>
|
<li><a href="#smartGraph" data-toggle="tab" id="tab-smartGraph">Smart Graph</a></li>
|
||||||
|
<li><a href="#exampleGraphs" data-toggle="tab" id="tab-exampleGraphs">Examples</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="tab-content" id="tab-content-create-graph">
|
<div class="tab-content" id="tab-content-create-graph">
|
||||||
|
@ -1852,7 +1853,11 @@ if (list.length > 0) {
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="active tab-pane" id="createGraph"> <%
|
<div class="active tab-pane" id="createGraph">
|
||||||
|
|
||||||
|
<div id="smartGraphInfo" class="infoMessage" style="display: none;">
|
||||||
|
<span>Smart Graph Info: Only use non-existent collection names (vertices/edges).</span>
|
||||||
|
</div> <%
|
||||||
var createTR = function(row, disableSubmitOnEnter) {
|
var createTR = function(row, disableSubmitOnEnter) {
|
||||||
var mandatory = '';
|
var mandatory = '';
|
||||||
if (row.mandatory) {
|
if (row.mandatory) {
|
||||||
|
@ -1934,6 +1939,7 @@ if (list.length > 0) {
|
||||||
</div> <%
|
</div> <%
|
||||||
}
|
}
|
||||||
%> </div>
|
%> </div>
|
||||||
|
|
||||||
</div></script><script id="modalHotkeys.ejs" type="text/template"><ul class="hotkeysList"> <% _.each(content, function(categories) { %> <li class="hotkeysLabel"><%=categories.name%></li> <% _.each(categories.content, function(values) { %> <li class="hotkeysContent"><div class="hotkeysContentLabel"><%=values.label%></div><div class="hotkeysicons"> <%=values.letter%> </div></li> <% }); %> <% }); %> <ul></script><script id="modalTable.ejs" type="text/template"> <%
|
</div></script><script id="modalHotkeys.ejs" type="text/template"><ul class="hotkeysList"> <% _.each(content, function(categories) { %> <li class="hotkeysLabel"><%=categories.name%></li> <% _.each(categories.content, function(values) { %> <li class="hotkeysContent"><div class="hotkeysContentLabel"><%=values.label%></div><div class="hotkeysicons"> <%=values.letter%> </div></li> <% }); %> <% }); %> <ul></script><script id="modalTable.ejs" type="text/template"> <%
|
||||||
var createTR = function(row) {
|
var createTR = function(row) {
|
||||||
var mandatory = '';
|
var mandatory = '';
|
||||||
|
@ -2741,4 +2747,4 @@ var cutByResolution = function (str) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="workMonitorContent" class="innerContent">
|
<div id="workMonitorContent" class="innerContent">
|
||||||
</div></script></head><body><nav class="navbar" style="display: none"><div class="primary"><div class="navlogo"><a class="logo big" href="#"><img id="ArangoDBLogo" class="arangodbLogo" src="img/arangodb-edition-optimized.svg"></a><a class="logo small" href="#"><img class="arangodbLogo" src="img/arangodb_logo_small.png"></a><a class="version"><span id="currentVersion"></span></a></div><div class="statmenu" id="statisticBar"></div><div class="navmenu" id="navigationBar"></div></div></nav><div id="modalPlaceholder"></div><div class="bodyWrapper" style="display: none"><div class="centralRow"><div id="navbar2" class="navbarWrapper secondary"><div class="subnavmenu" id="subNavigationBar"></div></div><div class="resizecontainer contentWrapper"><div id="loadingScreen" class="loadingScreen" style="display: none"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw margin-bottom"></i> <span class="sr-only">Loading...</span></div><div id="content" class="centralContent"></div><footer class="footer"><div id="footerBar"></div></footer></div></div></div><div id="progressPlaceholder" style="display:none"></div><div id="spotlightPlaceholder" style="display:none"></div><div id="graphSettingsContent" style="display: none"></div><div id="offlinePlaceholder" style="display:none"><div class="offline-div"><div class="pure-u"><div class="pure-u-1-4"></div><div class="pure-u-1-2 offline-window"><div class="offline-header"><h3>You have been disconnected from the server</h3></div><div class="offline-body"><p>The connection to the server has been lost. The server may be under heavy load.</p><p>Trying to reconnect in <span id="offlineSeconds">10</span> seconds.</p><p class="animation_state"><span><button class="button-success">Reconnect now</button></span></p></div></div><div class="pure-u-1-4"></div></div></div></div><div class="arangoFrame" style=""><div class="outerDiv"><div class="innerDiv"></div></div></div><script src="libs.js?version=1487069085040"></script><script src="app.js?version=1487069085040"></script></body></html>
|
</div></script></head><body><nav class="navbar" style="display: none"><div class="primary"><div class="navlogo"><a class="logo big" href="#"><img id="ArangoDBLogo" class="arangodbLogo" src="img/arangodb-edition-optimized.svg"></a><a class="logo small" href="#"><img class="arangodbLogo" src="img/arangodb_logo_small.png"></a><a class="version"><span id="currentVersion"></span></a></div><div class="statmenu" id="statisticBar"></div><div class="navmenu" id="navigationBar"></div></div></nav><div id="modalPlaceholder"></div><div class="bodyWrapper" style="display: none"><div class="centralRow"><div id="navbar2" class="navbarWrapper secondary"><div class="subnavmenu" id="subNavigationBar"></div></div><div class="resizecontainer contentWrapper"><div id="loadingScreen" class="loadingScreen" style="display: none"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw margin-bottom"></i> <span class="sr-only">Loading...</span></div><div id="content" class="centralContent"></div><footer class="footer"><div id="footerBar"></div></footer></div></div></div><div id="progressPlaceholder" style="display:none"></div><div id="spotlightPlaceholder" style="display:none"></div><div id="graphSettingsContent" style="display: none"></div><div id="offlinePlaceholder" style="display:none"><div class="offline-div"><div class="pure-u"><div class="pure-u-1-4"></div><div class="pure-u-1-2 offline-window"><div class="offline-header"><h3>You have been disconnected from the server</h3></div><div class="offline-body"><p>The connection to the server has been lost. The server may be under heavy load.</p><p>Trying to reconnect in <span id="offlineSeconds">10</span> seconds.</p><p class="animation_state"><span><button class="button-success">Reconnect now</button></span></p></div></div><div class="pure-u-1-4"></div></div></div></div><div class="arangoFrame" style=""><div class="outerDiv"><div class="innerDiv"></div></div></div><script src="libs.js?version=1487326471860"></script><script src="app.js?version=1487326471860"></script></body></html>
|
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
@ -1590,7 +1590,6 @@
|
||||||
|
|
||||||
readQueryData: function (selected, forExecute) {
|
readQueryData: function (selected, forExecute) {
|
||||||
// var selectedText = this.aqlEditor.session.getTextRange(this.aqlEditor.getSelectionRange())
|
// var selectedText = this.aqlEditor.session.getTextRange(this.aqlEditor.getSelectionRange())
|
||||||
var sizeBox = $('#querySize');
|
|
||||||
var data = {
|
var data = {
|
||||||
id: 'currentFrontendQuery'
|
id: 'currentFrontendQuery'
|
||||||
};
|
};
|
||||||
|
@ -1608,12 +1607,6 @@
|
||||||
}
|
}
|
||||||
data = false;
|
data = false;
|
||||||
} else {
|
} else {
|
||||||
if (sizeBox.val() === 'all') {
|
|
||||||
data.batchSize = 1000000;
|
|
||||||
} else {
|
|
||||||
data.batchSize = parseInt(sizeBox.val(), 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
var bindVars = {};
|
var bindVars = {};
|
||||||
if (Object.keys(this.bindParamTableObj).length > 0) {
|
if (Object.keys(this.bindParamTableObj).length > 0) {
|
||||||
_.each(this.bindParamTableObj, function (val, key) {
|
_.each(this.bindParamTableObj, function (val, key) {
|
||||||
|
@ -1737,7 +1730,7 @@
|
||||||
outputEditor.getSession().setScrollTop(0);
|
outputEditor.getSession().setScrollTop(0);
|
||||||
},
|
},
|
||||||
|
|
||||||
renderQueryResult: function (data, counter, cached) {
|
renderQueryResult: function (data, counter, cached, queryID) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (window.location.hash === '#queries') {
|
if (window.location.hash === '#queries') {
|
||||||
|
@ -1849,9 +1842,26 @@
|
||||||
self.deselect(outputEditor);
|
self.deselect(outputEditor);
|
||||||
|
|
||||||
// when finished send a delete req to api (free db space)
|
// when finished send a delete req to api (free db space)
|
||||||
if (data.id) {
|
// deletion only necessary if result was not fully fetched
|
||||||
|
var url;
|
||||||
|
if (queryID && data.hasMore) {
|
||||||
|
url = arangoHelper.databaseUrl('/_api/cursor/' + encodeURIComponent(queryID));
|
||||||
|
} else {
|
||||||
|
if (data.id && data.hasMore) {
|
||||||
|
url = arangoHelper.databaseUrl('/_api/cursor/' + encodeURIComponent(data.id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (!data.complete) {
|
||||||
|
// TODO notify user?
|
||||||
|
// console.log('result was cutted down - more result avail - change limit');
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (url) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: arangoHelper.databaseUrl('/_api/cursor/' + encodeURIComponent(data.id)),
|
url: url,
|
||||||
type: 'DELETE'
|
type: 'DELETE'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1926,21 +1936,67 @@
|
||||||
|
|
||||||
queryCallbackFunction: function (queryID, counter) {
|
queryCallbackFunction: function (queryID, counter) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
self.tmpQueryResult = null;
|
||||||
|
|
||||||
this.bindQueryResultButtons(queryID, counter);
|
this.bindQueryResultButtons(queryID, counter);
|
||||||
this.execPending = false;
|
this.execPending = false;
|
||||||
|
|
||||||
|
var userLimit;
|
||||||
|
try {
|
||||||
|
userLimit = parseInt($('#querySize').val());
|
||||||
|
} catch (e) {
|
||||||
|
arangoHelper.arangoError('Parse Error', 'Could not parse defined user limit.');
|
||||||
|
}
|
||||||
|
|
||||||
|
var pushQueryResults = function (data) {
|
||||||
|
if (self.tmpQueryResult === null) {
|
||||||
|
self.tmpQueryResult = {
|
||||||
|
result: [],
|
||||||
|
complete: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
_.each(data, function (val, key) {
|
||||||
|
if (key !== 'result') {
|
||||||
|
self.tmpQueryResult[key] = val;
|
||||||
|
} else {
|
||||||
|
_.each(data.result, function (d) {
|
||||||
|
if (self.tmpQueryResult.result.length < userLimit) {
|
||||||
|
self.tmpQueryResult.result.push(d);
|
||||||
|
} else {
|
||||||
|
self.tmpQueryResult.complete = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// check if async query is finished
|
// check if async query is finished
|
||||||
var checkQueryStatus = function () {
|
var checkQueryStatus = function (cursorID) {
|
||||||
|
var url = arangoHelper.databaseUrl('/_api/job/' + encodeURIComponent(queryID));
|
||||||
|
if (cursorID) {
|
||||||
|
url = arangoHelper.databaseUrl('/_api/cursor/' + encodeURIComponent(cursorID));
|
||||||
|
}
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'PUT',
|
type: 'PUT',
|
||||||
url: arangoHelper.databaseUrl('/_api/job/' + encodeURIComponent(queryID)),
|
url: url,
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
processData: false,
|
processData: false,
|
||||||
success: function (data, textStatus, xhr) {
|
success: function (data, textStatus, xhr) {
|
||||||
// query finished, now fetch results
|
// query finished, now fetch results using cursor
|
||||||
if (xhr.status === 201) {
|
|
||||||
self.renderQueryResult(data, counter);
|
if (xhr.status === 201 || xhr.status === 200) {
|
||||||
|
if (data.hasMore) {
|
||||||
|
pushQueryResults(data);
|
||||||
|
|
||||||
|
// continue to fetch result
|
||||||
|
checkQueryStatus(data.id);
|
||||||
|
} else {
|
||||||
|
pushQueryResults(data);
|
||||||
|
self.renderQueryResult(self.tmpQueryResult, counter, queryID);
|
||||||
|
self.tmpQueryResult = null;
|
||||||
|
}
|
||||||
// SCROLL TO RESULT BOX
|
// SCROLL TO RESULT BOX
|
||||||
$('.centralRow').animate({ scrollTop: $('#queryContent').height() }, 'fast');
|
$('.centralRow').animate({ scrollTop: $('#queryContent').height() }, 'fast');
|
||||||
} else if (xhr.status === 204) {
|
} else if (xhr.status === 204) {
|
||||||
|
|
|
@ -164,7 +164,8 @@ $c-collection-tab-border-bottom: #888;
|
||||||
|
|
||||||
$c-sh-number: #044;
|
$c-sh-number: #044;
|
||||||
$c-sh-symbol: #00f;
|
$c-sh-symbol: #00f;
|
||||||
$c-sh-cbracket: #c7a317;
|
// $c-sh-cbracket: #c7a317;
|
||||||
|
$c-sh-cbracket: rgb(64, 74, 83);
|
||||||
$c-sh-keyword: #c12dad;
|
$c-sh-keyword: #c12dad;
|
||||||
$c-sh-string: #ce2f30;
|
$c-sh-string: #ce2f30;
|
||||||
$c-sh-object: #00f;
|
$c-sh-object: #00f;
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// 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 Jan Steemann
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef ARANGODB_BASICS_LOCKING_H
|
||||||
|
#define ARANGODB_BASICS_LOCKING_H 1
|
||||||
|
|
||||||
|
#include "Basics/Common.h"
|
||||||
|
|
||||||
|
namespace arangodb {
|
||||||
|
namespace basics {
|
||||||
|
|
||||||
|
enum class LockerType {
|
||||||
|
BLOCKING, // always lock, blocking if the lock cannot be acquired instantly
|
||||||
|
EVENTUAL, // always lock, sleeping while the lock is not acquired
|
||||||
|
TRY // try to acquire the lock and give up instantly if it cannot be acquired
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace ConditionalLocking {
|
||||||
|
static constexpr bool DoLock = true;
|
||||||
|
static constexpr bool DoNotLock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -326,9 +326,6 @@ class ConditionalReadLocker {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr bool DoLock() { return true; }
|
|
||||||
static constexpr bool DoNotLock() { return false; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// @brief the read-write lock
|
/// @brief the read-write lock
|
||||||
LockType* _readWriteLock;
|
LockType* _readWriteLock;
|
||||||
|
|
|
@ -26,39 +26,30 @@
|
||||||
#define ARANGODB_BASICS_WRITE_LOCKER_H 1
|
#define ARANGODB_BASICS_WRITE_LOCKER_H 1
|
||||||
|
|
||||||
#include "Basics/Common.h"
|
#include "Basics/Common.h"
|
||||||
|
#include "Basics/Locking.h"
|
||||||
#include "Basics/ReadWriteLock.h"
|
#include "Basics/ReadWriteLock.h"
|
||||||
|
|
||||||
#ifdef TRI_SHOW_LOCK_TIME
|
#ifdef TRI_SHOW_LOCK_TIME
|
||||||
#include "Logger/Logger.h"
|
#include "Logger/Logger.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief construct locker with file and line information
|
/// @brief construct locker with file and line information
|
||||||
///
|
|
||||||
/// Ones needs to use macros twice to get a unique variable based on the line
|
|
||||||
/// number.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifdef TRI_SHOW_LOCK_TIME
|
|
||||||
|
|
||||||
#define WRITE_LOCKER(obj, lock) \
|
#define WRITE_LOCKER(obj, lock) \
|
||||||
arangodb::basics::WriteLocker<std::decay<decltype (lock)>::type> obj(&lock, __FILE__, __LINE__)
|
arangodb::basics::WriteLocker<std::decay<decltype (lock)>::type> obj(&lock, arangodb::basics::LockerType::BLOCKING, true, __FILE__, __LINE__)
|
||||||
|
|
||||||
#define WRITE_LOCKER_EVENTUAL(obj, lock, t) \
|
#define WRITE_LOCKER_EVENTUAL(obj, lock) \
|
||||||
arangodb::basics::WriteLocker<std::decay<decltype (lock)>::type> obj(&lock, t, __FILE__, __LINE__)
|
arangodb::basics::WriteLocker<std::decay<decltype (lock)>::type> obj(&lock, arangodb::basics::LockerType::EVENTUAL, true, __FILE__, __LINE__)
|
||||||
|
|
||||||
#else
|
#define TRY_WRITE_LOCKER(obj, lock) \
|
||||||
|
arangodb::basics::WriteLocker<std::decay<decltype (lock)>::type> obj(&lock, arangodb::basics::LockerType::TRY, true, __FILE__, __LINE__)
|
||||||
|
|
||||||
#define WRITE_LOCKER(obj, lock) arangodb::basics::WriteLocker<std::decay<decltype (lock)>::type> obj(&lock)
|
#define CONDITIONAL_WRITE_LOCKER(obj, lock, condition) \
|
||||||
|
arangodb::basics::WriteLocker<std::decay<decltype (lock)>::type> obj(&lock, arangodb::basics::LockerType::BLOCKING, (condition), __FILE__, __LINE__)
|
||||||
#define WRITE_LOCKER_EVENTUAL(obj, lock, t) \
|
|
||||||
arangodb::basics::WriteLocker<std::decay<decltype (lock)>::type> obj(&lock, t)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TRY_WRITE_LOCKER(obj, lock) arangodb::basics::TryWriteLocker<std::decay<decltype (lock)>::type> obj(&lock)
|
|
||||||
|
|
||||||
#define CONDITIONAL_WRITE_LOCKER(obj, lock, condition) arangodb::basics::ConditionalWriteLocker<std::decay<decltype (lock)>::type> obj(&lock, (condition))
|
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
namespace basics {
|
namespace basics {
|
||||||
|
@ -72,46 +63,40 @@ class WriteLocker {
|
||||||
WriteLocker& operator=(WriteLocker const&) = delete;
|
WriteLocker& operator=(WriteLocker const&) = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// @brief aquires a write-lock
|
||||||
|
/// The constructors acquire a write lock, the destructor unlocks the lock.
|
||||||
|
WriteLocker(LockType* readWriteLock, LockerType type, bool condition, char const* file, int line)
|
||||||
|
: _readWriteLock(readWriteLock), _file(file), _line(line),
|
||||||
#ifdef TRI_SHOW_LOCK_TIME
|
#ifdef TRI_SHOW_LOCK_TIME
|
||||||
|
_isLocked(false), _time(0.0) {
|
||||||
/// @brief aquires a write-lock
|
|
||||||
/// The constructors acquire a write lock, the destructor unlocks the lock.
|
|
||||||
WriteLocker(LockType* readWriteLock, char const* file, int line)
|
|
||||||
: _readWriteLock(readWriteLock), _file(file), _line(line), _isLocked(false) {
|
|
||||||
double t = TRI_microtime();
|
|
||||||
lock();
|
|
||||||
_time = TRI_microtime() - t;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief aquires a write-lock, with periodic sleeps while not acquired
|
|
||||||
/// sleep time is specified in nanoseconds
|
|
||||||
WriteLocker(LockType* readWriteLock, uint64_t sleepTime,
|
|
||||||
char const* file, int line)
|
|
||||||
: _readWriteLock(readWriteLock), _file(file), _line(line), _isLocked(false) {
|
|
||||||
double t = TRI_microtime();
|
|
||||||
lockEventual(sleepTime);
|
|
||||||
_time = TRI_microtime() - t;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
_isLocked(false) {
|
||||||
/// @brief aquires a write-lock
|
|
||||||
/// The constructors acquire a write lock, the destructor unlocks the lock.
|
|
||||||
explicit WriteLocker(LockType* readWriteLock)
|
|
||||||
: _readWriteLock(readWriteLock), _isLocked(false) {
|
|
||||||
lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief aquires a write-lock, with periodic sleeps while not acquired
|
|
||||||
/// sleep time is specified in nanoseconds
|
|
||||||
WriteLocker(LockType* readWriteLock, uint64_t sleepTime)
|
|
||||||
: _readWriteLock(readWriteLock), _isLocked(false) {
|
|
||||||
lockEventual(sleepTime);
|
|
||||||
_isLocked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TRI_SHOW_LOCK_TIME
|
||||||
|
// fetch current time
|
||||||
|
double t = TRI_microtime();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (condition) {
|
||||||
|
if (type == LockerType::BLOCKING) {
|
||||||
|
lock();
|
||||||
|
TRI_ASSERT(_isLocked);
|
||||||
|
} else if (type == LockerType::EVENTUAL) {
|
||||||
|
lockEventual();
|
||||||
|
TRI_ASSERT(_isLocked);
|
||||||
|
} else if (type == LockerType::TRY) {
|
||||||
|
_isLocked = tryLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TRI_SHOW_LOCK_TIME
|
||||||
|
// add elapsed time to time tracker
|
||||||
|
_time = TRI_microtime() - t;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief releases the write-lock
|
/// @brief releases the write-lock
|
||||||
~WriteLocker() {
|
~WriteLocker() {
|
||||||
if (_isLocked) {
|
if (_isLocked) {
|
||||||
|
@ -120,28 +105,33 @@ class WriteLocker {
|
||||||
|
|
||||||
#ifdef TRI_SHOW_LOCK_TIME
|
#ifdef TRI_SHOW_LOCK_TIME
|
||||||
if (_time > TRI_SHOW_LOCK_THRESHOLD) {
|
if (_time > TRI_SHOW_LOCK_THRESHOLD) {
|
||||||
LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "WriteLocker " << _file << ":" << _line << " took " << _time << " s";
|
LOG_TOPIC(WARN, arangodb::Logger::PERFORMANCE) << "WriteLocker " << _file << ":" << _line << " took " << _time << " s";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief whether or not we acquired the lock
|
/// @brief whether or not we acquired the lock
|
||||||
bool isLocked() const { return _isLocked; }
|
bool isLocked() const noexcept { return _isLocked; }
|
||||||
|
|
||||||
/// @brief eventually acquire the write lock
|
/// @brief eventually acquire the write lock
|
||||||
void lockEventual(uint64_t sleepTime) {
|
void lockEventual() {
|
||||||
while (!_readWriteLock->tryWriteLock()) {
|
while (!_readWriteLock->tryWriteLock()) {
|
||||||
#ifdef _WIN32
|
std::this_thread::yield();
|
||||||
usleep((unsigned long)sleepTime);
|
|
||||||
#else
|
|
||||||
usleep((useconds_t)sleepTime);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
_isLocked = true;
|
_isLocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tryLock() {
|
||||||
|
TRI_ASSERT(!_isLocked);
|
||||||
|
if (_readWriteLock->tryWriteLock()) {
|
||||||
|
_isLocked = true;
|
||||||
|
}
|
||||||
|
return _isLocked;
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief acquire the write lock, blocking
|
/// @brief acquire the write lock, blocking
|
||||||
void lock() {
|
void lock() {
|
||||||
|
TRI_ASSERT(!_isLocked);
|
||||||
_readWriteLock->writeLock();
|
_readWriteLock->writeLock();
|
||||||
_isLocked = true;
|
_isLocked = true;
|
||||||
}
|
}
|
||||||
|
@ -169,165 +159,19 @@ class WriteLocker {
|
||||||
/// @brief the read-write lock
|
/// @brief the read-write lock
|
||||||
LockType* _readWriteLock;
|
LockType* _readWriteLock;
|
||||||
|
|
||||||
#ifdef TRI_SHOW_LOCK_TIME
|
|
||||||
|
|
||||||
/// @brief file
|
/// @brief file
|
||||||
char const* _file;
|
char const* _file;
|
||||||
|
|
||||||
/// @brief line number
|
/// @brief line number
|
||||||
int _line;
|
int _line;
|
||||||
|
|
||||||
/// @brief lock time
|
|
||||||
double _time;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// @brief whether or not the lock was acquired
|
/// @brief whether or not the lock was acquired
|
||||||
bool _isLocked;
|
bool _isLocked;
|
||||||
};
|
|
||||||
|
|
||||||
template<class LockType>
|
#ifdef TRI_SHOW_LOCK_TIME
|
||||||
class TryWriteLocker {
|
/// @brief lock time
|
||||||
TryWriteLocker(TryWriteLocker const&) = delete;
|
double _time;
|
||||||
TryWriteLocker& operator=(TryWriteLocker const&) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// @brief tries to acquire a write-lock
|
|
||||||
/// The constructor tries to aquire a write lock, the destructors unlocks the
|
|
||||||
/// lock if we acquired it in the constructor
|
|
||||||
explicit TryWriteLocker(LockType* readWriteLock)
|
|
||||||
: _readWriteLock(readWriteLock), _isLocked(false) {
|
|
||||||
_isLocked = _readWriteLock->tryWriteLock();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief releases the write-lock
|
|
||||||
~TryWriteLocker() {
|
|
||||||
if (_isLocked) {
|
|
||||||
_readWriteLock->unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief whether or not we acquired the lock
|
|
||||||
bool isLocked() const { return _isLocked; }
|
|
||||||
|
|
||||||
/// @brief eventually acquire the write lock
|
|
||||||
void lockEventual(uint64_t sleepTime) {
|
|
||||||
while (!_readWriteLock->tryWriteLock()) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
usleep((unsigned long)sleepTime);
|
|
||||||
#else
|
|
||||||
usleep((useconds_t)sleepTime);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
_isLocked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief acquire the write lock, blocking
|
|
||||||
void lock() {
|
|
||||||
_readWriteLock->writeLock();
|
|
||||||
_isLocked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief unlocks the read-write lock
|
|
||||||
bool unlock() {
|
|
||||||
if (_isLocked) {
|
|
||||||
_readWriteLock->unlock();
|
|
||||||
_isLocked = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief steals the lock, but does not unlock it
|
|
||||||
bool steal() {
|
|
||||||
if (_isLocked) {
|
|
||||||
_isLocked = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// @brief the read-write lock
|
|
||||||
LockType* _readWriteLock;
|
|
||||||
|
|
||||||
/// @brief whether or not we acquired the lock
|
|
||||||
bool _isLocked;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class LockType>
|
|
||||||
class ConditionalWriteLocker {
|
|
||||||
ConditionalWriteLocker(ConditionalWriteLocker const&) = delete;
|
|
||||||
ConditionalWriteLocker& operator=(ConditionalWriteLocker const&) = delete;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// @brief acquire a write-lock
|
|
||||||
/// The constructor tries to write-lock the lock, the destructor unlocks the
|
|
||||||
/// lock if it was acquired in the constructor
|
|
||||||
ConditionalWriteLocker(LockType* readWriteLock, bool condition)
|
|
||||||
: _readWriteLock(readWriteLock), _isLocked(false) {
|
|
||||||
if (condition) {
|
|
||||||
_readWriteLock->writeLock();
|
|
||||||
_isLocked = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief releases the write-lock
|
|
||||||
~ConditionalWriteLocker() {
|
|
||||||
if (_isLocked) {
|
|
||||||
_readWriteLock->unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief whether or not we acquired the lock
|
|
||||||
bool isLocked() const { return _isLocked; }
|
|
||||||
|
|
||||||
/// @brief eventually acquire the write lock
|
|
||||||
void lockEventual(uint64_t sleepTime) {
|
|
||||||
while (!_readWriteLock->tryWriteLock()) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
usleep((unsigned long)sleepTime);
|
|
||||||
#else
|
|
||||||
usleep((useconds_t)sleepTime);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
_isLocked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief acquire the write lock, blocking
|
|
||||||
void lock() {
|
|
||||||
_readWriteLock->writeLock();
|
|
||||||
_isLocked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief unlocks the read-write lock
|
|
||||||
bool unlock() {
|
|
||||||
if (_isLocked) {
|
|
||||||
_readWriteLock->unlock();
|
|
||||||
_isLocked = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief steals the lock, but does not unlock it
|
|
||||||
bool steal() {
|
|
||||||
if (_isLocked) {
|
|
||||||
_isLocked = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr bool DoLock() { return true; }
|
|
||||||
static constexpr bool DoNotLock() { return false; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// @brief the read-write lock
|
|
||||||
LockType* _readWriteLock;
|
|
||||||
|
|
||||||
/// @brief whether or not we acquired the lock
|
|
||||||
bool _isLocked;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue