mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel
This commit is contained in:
commit
f35347098b
51
CHANGELOG
51
CHANGELOG
|
@ -1,6 +1,35 @@
|
|||
v1.5.x (XXXX-XX-XX)
|
||||
-------------------
|
||||
|
||||
* simplified ArangoDB startup options
|
||||
|
||||
Some startup options are now superfluous or their usage is simplified. The
|
||||
following options have been changed:
|
||||
|
||||
* `--javascript.modules-path`: this option has been removed. The modules paths
|
||||
are determined by arangod and arangosh automatically based on the value of
|
||||
`--javascript.startup-directory`.
|
||||
|
||||
If the option is set on startup, it is ignored so startup will not abort with
|
||||
an error `unrecognized option`.
|
||||
|
||||
* `--javascript.action-directory`: this option has been removed. The actions
|
||||
directory is determined by arangod automatically based on the value of
|
||||
`--javascript.startup-directory`.
|
||||
|
||||
If the option is set on startup, it is ignored so startup will not abort with
|
||||
an error `unrecognized option`.
|
||||
|
||||
* `--javascript.package-path`: this option is still available but it is not
|
||||
required anymore to set the standard package paths (e.g. `js/npm`). arangod
|
||||
will automatically use this standard package path regardless of whether it
|
||||
was specified via the options.
|
||||
|
||||
It is possible to use this option to add additional package paths to the
|
||||
standard value.
|
||||
|
||||
Configuration files included with arangod are adjusted accordingly.
|
||||
|
||||
* layout of the graphs tab adapted to better fit with the other tabs
|
||||
|
||||
* database selection is moved to the bottom right corner of the web interface
|
||||
|
@ -67,6 +96,28 @@ v1.5.x (XXXX-XX-XX)
|
|||
v1.4.2 (XXXX-XX-XX)
|
||||
-------------------
|
||||
|
||||
* ported Windows version to use native Windows API SRWLocks (slim read-write locks)
|
||||
and condition variables instead of homemade versions
|
||||
|
||||
MSDN states the following about the compatibility of SRWLocks and Condition Variables:
|
||||
|
||||
Minimum supported client:
|
||||
Windows Server 2008 [desktop apps | Windows Store apps]
|
||||
|
||||
Minimum supported server:
|
||||
Windows Vista [desktop apps | Windows Store apps]
|
||||
|
||||
* fixed issue #662: ArangoDB on Windows hanging
|
||||
|
||||
This fixes a deadlock issue that occurred on Windows when documents were written to
|
||||
a collection at the same time when some other thread tried to drop the collection.
|
||||
|
||||
* fixed file-based logging in Windows
|
||||
|
||||
the logger complained on startup if the specified log file already existed
|
||||
|
||||
* fixed startup of server in daemon mode (`--daemon` startup option)
|
||||
|
||||
* fixed a segfault in the AQL optimiser
|
||||
|
||||
* issue #671: Method graph.measurement does not exist
|
||||
|
|
|
@ -225,8 +225,6 @@ you can skip this section.
|
|||
* `server.endpoint`: what IP address and port to bind to,
|
||||
* `log` parameters: if and where to log
|
||||
* `database.directory`: path the database files are stored in
|
||||
* `javascript.action-directory` and `javascript.modules-path`: where to
|
||||
look for Javascript files
|
||||
|
||||
If the configuration reveals something is not configured right, the config
|
||||
file should be adjusted and the server be restarted.
|
||||
|
@ -570,8 +568,6 @@ Use `--help` to get a list of command-line options:
|
|||
--javascript.check <string> syntax check code Javascript code from file
|
||||
--javascript.execute <string> execute Javascript code from file
|
||||
--javascript.execute-string <string> execute Javascript code from string
|
||||
--javascript.modules-path <string> one or more directories separated by semi-colons
|
||||
--javascript.package-path <string> one or more directories separated by semi-colons
|
||||
--javascript.startup-directory <string> startup paths containing the JavaScript files
|
||||
--javascript.unit-tests <string> do not start as shell, run unit tests instead
|
||||
--jslint <string> do not start as shell, run jslint instead
|
||||
|
|
|
@ -108,11 +108,9 @@ SERVER_OPT := \
|
|||
--configuration none \
|
||||
--database.maximal-journal-size 1048576 \
|
||||
--database.force-sync-properties false \
|
||||
--javascript.action-directory @top_srcdir@/js/actions \
|
||||
--javascript.app-path @top_srcdir@/js/apps \
|
||||
--javascript.gc-interval 1 \
|
||||
--javascript.modules-path @top_srcdir@/js/server/modules\;@top_srcdir@/js/common/modules\;@top_srcdir@/js/node \
|
||||
--javascript.package-path @top_srcdir@/js/npm\;@top_srcdir@/js/common/test-data/modules \
|
||||
--javascript.package-path @top_srcdir@/js/common/test-data/modules \
|
||||
--javascript.startup-directory @top_srcdir@/js \
|
||||
--log.file "" \
|
||||
--ruby.action-directory @top_srcdir@/mr/actions \
|
||||
|
@ -123,7 +121,6 @@ SERVER_OPT := \
|
|||
CLIENT_OPT := \
|
||||
--configuration none \
|
||||
--javascript.startup-directory @top_srcdir@/js \
|
||||
--javascript.modules-path @top_srcdir@/js/client/modules\;@top_srcdir@/js/common/modules\;@top_srcdir@/js/node \
|
||||
--javascript.package-path @top_srcdir@/js/common/test-data/modules \
|
||||
--no-colors \
|
||||
--quiet
|
||||
|
|
|
@ -8,10 +8,7 @@ threads = 4
|
|||
# maximal-journal-size 1048576
|
||||
|
||||
[javascript]
|
||||
action-directory = .\js\actions
|
||||
modules-path = .\js\server\modules;.\js\common\modules;.\js\node
|
||||
app-path = .\js\apps
|
||||
package-path = .\js\npm
|
||||
startup-directory = .\js
|
||||
|
||||
[scheduler]
|
||||
|
|
|
@ -6,5 +6,3 @@ disable-authentication = true
|
|||
|
||||
[javascript]
|
||||
startup-directory = .\js
|
||||
modules-path = .\js\client\modules;.\js\common\modules;.\js\node
|
||||
package-path = .\js\npm
|
||||
|
|
|
@ -45,6 +45,26 @@ using namespace triagens::rest;
|
|||
using namespace triagens::arango;
|
||||
using namespace triagens::httpclient;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private defines
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief write-lock the status
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define WRITE_LOCK_STATUS(applier) \
|
||||
while (! TRI_TryWriteLockReadWriteLock(&(applier->_statusLock))) { \
|
||||
usleep(1000); \
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief write-unlock the status
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define WRITE_UNLOCK_STATUS(applier) \
|
||||
TRI_WriteUnlockReadWriteLock(&(applier->_statusLock))
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -118,9 +138,9 @@ int ContinuousSyncer::run () {
|
|||
uint64_t connectRetries = 0;
|
||||
|
||||
// reset failed connects
|
||||
TRI_WriteLockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_LOCK_STATUS(_applier);
|
||||
_applier->_state._failedConnects = 0;
|
||||
TRI_WriteUnlockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_UNLOCK_STATUS(_applier);
|
||||
|
||||
while (_vocbase->_state < 2) {
|
||||
setProgress("fetching master state information");
|
||||
|
@ -131,11 +151,11 @@ int ContinuousSyncer::run () {
|
|||
// master error. try again after a sleep period
|
||||
connectRetries++;
|
||||
|
||||
TRI_WriteLockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_LOCK_STATUS(_applier);
|
||||
_applier->_state._failedConnects = connectRetries;
|
||||
_applier->_state._totalRequests++;
|
||||
_applier->_state._totalFailedConnects++;
|
||||
TRI_WriteUnlockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_UNLOCK_STATUS(_applier);
|
||||
|
||||
if (connectRetries <= _configuration._maxConnectRetries) {
|
||||
// check if we are aborted externally
|
||||
|
@ -153,12 +173,12 @@ int ContinuousSyncer::run () {
|
|||
}
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
TRI_WriteLockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_LOCK_STATUS(_applier);
|
||||
res = getLocalState(errorMsg);
|
||||
|
||||
_applier->_state._failedConnects = 0;
|
||||
_applier->_state._totalRequests++;
|
||||
TRI_WriteUnlockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_UNLOCK_STATUS(_applier);
|
||||
}
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -664,7 +684,7 @@ int ContinuousSyncer::applyLogMarker (TRI_json_t const* json,
|
|||
if (! tick.empty()) {
|
||||
TRI_voc_tick_t newTick = (TRI_voc_tick_t) StringUtils::uint64(tick.c_str(), tick.size());
|
||||
|
||||
TRI_WriteLockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_LOCK_STATUS(_applier);
|
||||
if (newTick > _applier->_state._lastProcessedContinuousTick) {
|
||||
_applier->_state._lastProcessedContinuousTick = newTick;
|
||||
}
|
||||
|
@ -673,7 +693,7 @@ int ContinuousSyncer::applyLogMarker (TRI_json_t const* json,
|
|||
(unsigned long long) newTick,
|
||||
(unsigned long long) _applier->_state._lastProcessedContinuousTick);
|
||||
}
|
||||
TRI_WriteUnlockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_UNLOCK_STATUS(_applier);
|
||||
}
|
||||
|
||||
// handle marker type
|
||||
|
@ -812,11 +832,11 @@ int ContinuousSyncer::applyLog (SimpleHttpResult* response,
|
|||
|
||||
if (updateTick) {
|
||||
// update tick value
|
||||
TRI_WriteLockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_LOCK_STATUS(_applier);
|
||||
if (_applier->_state._lastProcessedContinuousTick > _applier->_state._lastAppliedContinuousTick) {
|
||||
_applier->_state._lastAppliedContinuousTick = _applier->_state._lastProcessedContinuousTick;
|
||||
}
|
||||
TRI_WriteUnlockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_UNLOCK_STATUS(_applier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -834,7 +854,7 @@ int ContinuousSyncer::runContinuousSync (string& errorMsg) {
|
|||
// ---------------------------------------
|
||||
TRI_voc_tick_t fromTick = 0;
|
||||
|
||||
TRI_WriteLockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_LOCK_STATUS(_applier);
|
||||
|
||||
if (_useTick) {
|
||||
// use user-defined tick
|
||||
|
@ -850,7 +870,7 @@ int ContinuousSyncer::runContinuousSync (string& errorMsg) {
|
|||
}
|
||||
}
|
||||
|
||||
TRI_WriteUnlockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_UNLOCK_STATUS(_applier);
|
||||
|
||||
if (fromTick == 0) {
|
||||
return TRI_ERROR_REPLICATION_NO_START_TICK;
|
||||
|
@ -873,11 +893,11 @@ int ContinuousSyncer::runContinuousSync (string& errorMsg) {
|
|||
sleepTime = 30 * 1000 * 1000;
|
||||
connectRetries++;
|
||||
|
||||
TRI_WriteLockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_LOCK_STATUS(_applier);
|
||||
_applier->_state._failedConnects = connectRetries;
|
||||
_applier->_state._totalRequests++;
|
||||
_applier->_state._totalFailedConnects++;
|
||||
TRI_WriteUnlockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_UNLOCK_STATUS(_applier);
|
||||
|
||||
if (connectRetries > _configuration._maxConnectRetries) {
|
||||
// halt
|
||||
|
@ -887,10 +907,10 @@ int ContinuousSyncer::runContinuousSync (string& errorMsg) {
|
|||
else {
|
||||
connectRetries = 0;
|
||||
|
||||
TRI_WriteLockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_LOCK_STATUS(_applier);
|
||||
_applier->_state._failedConnects = connectRetries;
|
||||
_applier->_state._totalRequests++;
|
||||
TRI_WriteUnlockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_UNLOCK_STATUS(_applier);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
// some other error we will not ignore
|
||||
|
@ -1031,9 +1051,9 @@ int ContinuousSyncer::followMasterLog (string& errorMsg,
|
|||
if (found) {
|
||||
tick = StringUtils::uint64(header);
|
||||
|
||||
TRI_WriteLockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_LOCK_STATUS(_applier);
|
||||
_applier->_state._lastAvailableContinuousTick = tick;
|
||||
TRI_WriteUnlockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_UNLOCK_STATUS(_applier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1046,9 +1066,9 @@ int ContinuousSyncer::followMasterLog (string& errorMsg,
|
|||
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
TRI_ReadLockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_LOCK_STATUS(_applier);
|
||||
TRI_voc_tick_t lastAppliedTick = _applier->_state._lastAppliedContinuousTick;
|
||||
TRI_ReadUnlockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_UNLOCK_STATUS(_applier);
|
||||
|
||||
uint64_t processedMarkers = 0;
|
||||
res = applyLog(response, errorMsg, processedMarkers, ignoreCount);
|
||||
|
@ -1056,13 +1076,13 @@ int ContinuousSyncer::followMasterLog (string& errorMsg,
|
|||
if (processedMarkers > 0) {
|
||||
worked = true;
|
||||
|
||||
TRI_WriteLockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_LOCK_STATUS(_applier);
|
||||
_applier->_state._totalEvents += processedMarkers;
|
||||
|
||||
if (_applier->_state._lastAppliedContinuousTick != lastAppliedTick) {
|
||||
saveApplierState();
|
||||
}
|
||||
TRI_WriteUnlockReadWriteLock(&_applier->_statusLock);
|
||||
WRITE_UNLOCK_STATUS(_applier);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,12 @@ using namespace triagens::basics;
|
|||
using namespace triagens::arango;
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief we'll store deprecated config option values in here
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::string DeprecatedPath;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class V8GcThread
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -553,13 +559,14 @@ void ApplicationV8::setupOptions (map<string, basics::ProgramOptionsDescription>
|
|||
options["JAVASCRIPT Options:help-admin"]
|
||||
("javascript.gc-interval", &_gcInterval, "JavaScript request-based garbage collection interval (each x requests)")
|
||||
("javascript.gc-frequency", &_gcFrequency, "JavaScript time-based garbage collection frequency (each x seconds)")
|
||||
("javascript.action-directory", &_actionPath, "path to the JavaScript action directory")
|
||||
("javascript.app-path", &_appPath, "directory for Foxx applications (normal mode)")
|
||||
("javascript.dev-app-path", &_devAppPath, "directory for Foxx applications (development mode)")
|
||||
("javascript.modules-path", &_modulesPath, "one or more directories separated by semi-colons")
|
||||
("javascript.package-path", &_packagePath, "one or more directories separated by semi-colons")
|
||||
("javascript.startup-directory", &_startupPath, "path to the directory containing JavaScript startup scripts")
|
||||
("javascript.v8-options", &_v8Options, "options to pass to v8")
|
||||
// deprecated options
|
||||
("javascript.action-directory", &DeprecatedPath, "path to the JavaScript action directory (deprecated)")
|
||||
("javascript.modules-path", &DeprecatedPath, "one or more directories separated by semi-colons (deprecated)")
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -568,20 +575,20 @@ void ApplicationV8::setupOptions (map<string, basics::ProgramOptionsDescription>
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ApplicationV8::prepare () {
|
||||
// check the startup modules
|
||||
if (_modulesPath.empty()) {
|
||||
LOG_FATAL_AND_EXIT("no 'javascript.modules-path' has been supplied, giving up");
|
||||
}
|
||||
|
||||
// set up the startup loader
|
||||
// check the startup path
|
||||
if (_startupPath.empty()) {
|
||||
LOG_FATAL_AND_EXIT("no 'javascript.startup-directory' has been supplied, giving up");
|
||||
}
|
||||
|
||||
// set the actions path
|
||||
if (_useActions && _actionPath.empty()) {
|
||||
LOG_FATAL_AND_EXIT("no 'javascript.action-directory' has been supplied, giving up");
|
||||
}
|
||||
// remove trailing / from path
|
||||
_startupPath = StringUtils::trim(_startupPath, TRI_DIR_SEPARATOR_STR);
|
||||
|
||||
// derive all other options from --javascript.startup-directory
|
||||
_actionPath = _startupPath + TRI_DIR_SEPARATOR_STR + "actions";
|
||||
|
||||
_modulesPath = _startupPath + TRI_DIR_SEPARATOR_STR + "server" + TRI_DIR_SEPARATOR_STR + "modules;" +
|
||||
_startupPath + TRI_DIR_SEPARATOR_STR + "common" + TRI_DIR_SEPARATOR_STR + "modules;" +
|
||||
_startupPath + TRI_DIR_SEPARATOR_STR + "node";
|
||||
|
||||
// dump paths
|
||||
{
|
||||
|
@ -589,10 +596,7 @@ bool ApplicationV8::prepare () {
|
|||
|
||||
paths.push_back(string("startup '" + _startupPath + "'"));
|
||||
paths.push_back(string("modules '" + _modulesPath + "'"));
|
||||
|
||||
if (! _packagePath.empty()) {
|
||||
paths.push_back(string("packages '" + _packagePath + "'"));
|
||||
}
|
||||
paths.push_back(string("packages '" + _packagePath + "'"));
|
||||
|
||||
if (_useActions) {
|
||||
paths.push_back(string("actions '" + _actionPath + "'"));
|
||||
|
@ -614,12 +618,6 @@ bool ApplicationV8::prepare () {
|
|||
LOG_FATAL_AND_EXIT("no value has been specified for --javascript.app-path.");
|
||||
}
|
||||
|
||||
if (_packagePath.empty()) {
|
||||
LOG_ERROR("--javascript.package-path option was not specified. this may cause follow-up errors.");
|
||||
// TODO: decide if we want to abort server start here
|
||||
}
|
||||
|
||||
|
||||
_startupLoader.setDirectory(_startupPath);
|
||||
|
||||
|
||||
|
@ -760,7 +758,7 @@ bool ApplicationV8::prepareV8Instance (const size_t i) {
|
|||
|
||||
TRI_InitV8Buffer(context->_context);
|
||||
TRI_InitV8Conversions(context->_context);
|
||||
TRI_InitV8Utils(context->_context, _modulesPath, _packagePath, _startupPath);
|
||||
TRI_InitV8Utils(context->_context, _startupPath, _modulesPath, _packagePath);
|
||||
TRI_InitV8Shell(context->_context);
|
||||
|
||||
{
|
||||
|
|
|
@ -371,12 +371,12 @@ namespace triagens {
|
|||
struct TRI_server_s* _server;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief path to the directory containing alternate startup scripts
|
||||
/// @brief path to the directory containing the startup scripts
|
||||
///
|
||||
/// @CMDOPT{\--javascript.directory @CA{directory}}
|
||||
/// @CMDOPT{\--javascript.startup-directory @CA{directory}}
|
||||
///
|
||||
/// Specifies the @CA{directory} path to the JavaScript files used for
|
||||
/// bootstraping. Multiple paths can be specified separated with commas.
|
||||
/// bootstraping.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string _startupPath;
|
||||
|
@ -384,16 +384,14 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief semicolon separated list of module directories
|
||||
///
|
||||
/// @CMDOPT{\--javascript.modules-path @CA{directory}}
|
||||
///
|
||||
/// Specifies the @CA{directory} paths where the JavaScript modules are located.
|
||||
/// Multiple paths can be specified separated with commas.
|
||||
/// This variable is automatically set based on the value of
|
||||
/// `--javascript.startup-directory`.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string _modulesPath;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief semicolon separated list of module directories
|
||||
/// @brief semicolon separated list of package directories
|
||||
///
|
||||
/// @CMDOPT{\--javascript.package-path @CA{directory}}
|
||||
///
|
||||
|
@ -406,10 +404,8 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief path to the system action directory
|
||||
///
|
||||
/// @CMDOPT{\--javascript.action-directory @CA{directory}}
|
||||
///
|
||||
/// Specifies the @CA{directory} containg the JavaScript files describing the
|
||||
/// system actions. Multiple paths can be specified separated with commas.
|
||||
/// This variable is automatically set based on the value of
|
||||
/// `--javascript.startup-directory`.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string _actionPath;
|
||||
|
|
|
@ -1181,7 +1181,10 @@ static bool TryLockCompaction (TRI_vocbase_t* vocbase) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void LockCompaction (TRI_vocbase_t* vocbase) {
|
||||
TRI_WriteLockReadWriteLock(&vocbase->_compactionBlockers._lock);
|
||||
while (! TryLockCompaction(vocbase)) {
|
||||
// cycle until we have acquired the write-lock
|
||||
usleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1211,6 +1211,7 @@ int TRI_WriteElementDatafile (TRI_datafile_t* datafile,
|
|||
type != TRI_DF_MARKER_FOOTER &&
|
||||
type != TRI_COL_MARKER_HEADER) {
|
||||
|
||||
#ifdef TRI_ENABLE_MAINTAINER_MODE
|
||||
// check _tick value of marker and set min/max tick values for datafile
|
||||
if (tick <= datafile->_tickMin || tick <= (TRI_voc_tick_t) datafile->_fid) {
|
||||
LOG_WARNING("logic error. invalid tick value %llu encountered when writing marker of type %d into datafile '%s'. "
|
||||
|
@ -1229,6 +1230,7 @@ int TRI_WriteElementDatafile (TRI_datafile_t* datafile,
|
|||
datafile->getName(datafile),
|
||||
(unsigned long long) datafile->_tickMax);
|
||||
}
|
||||
#endif
|
||||
|
||||
// set data tick values (for documents and edge markers)
|
||||
if (type == TRI_DOC_MARKER_KEY_DOCUMENT ||
|
||||
|
|
|
@ -763,6 +763,13 @@ static int DumpCollection (TRI_replication_dump_t* dump,
|
|||
}
|
||||
|
||||
ptr += TRI_DF_ALIGN_BLOCK(marker->_size);
|
||||
|
||||
if (marker->_type == TRI_DF_MARKER_ATTRIBUTE ||
|
||||
marker->_type == TRI_DF_MARKER_SHAPE) {
|
||||
// fully ignore these marker types. they don't need to be replicated,
|
||||
// but we also cannot stop iteration if we find one of these
|
||||
continue;
|
||||
}
|
||||
|
||||
// get the marker's tick and check whether we should include it
|
||||
foundTick = marker->_tick;
|
||||
|
@ -777,7 +784,7 @@ static int DumpCollection (TRI_replication_dump_t* dump,
|
|||
hasMore = false;
|
||||
goto NEXT_DF;
|
||||
}
|
||||
|
||||
|
||||
if (marker->_type != TRI_DOC_MARKER_KEY_DOCUMENT &&
|
||||
marker->_type != TRI_DOC_MARKER_KEY_EDGE &&
|
||||
marker->_type != TRI_DOC_MARKER_KEY_DELETION) {
|
||||
|
|
|
@ -62,6 +62,36 @@
|
|||
|
||||
#define DATABASE_MANAGER_INTERVAL (500 * 1000)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief eventually acquire a write-lock on the databases
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define WRITE_LOCK_DATABASES(server) \
|
||||
while (! TRI_TryWriteLockReadWriteLock(&server->_databasesLock)) { \
|
||||
usleep(1000); \
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief write-unlock the databases
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define WRITE_UNLOCK_DATABASES(server) \
|
||||
TRI_WriteUnlockReadWriteLock(&server->_databasesLock)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief read-lock the databases
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define READ_LOCK_DATABASES(server) \
|
||||
TRI_ReadLockReadWriteLock(&server->_databasesLock)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief read-unlock the databases
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define READ_UNLOCK_DATABASES(server) \
|
||||
TRI_ReadUnlockReadWriteLock(&server->_databasesLock)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -823,7 +853,8 @@ static int OpenDatabases (TRI_server_t* server,
|
|||
static int CloseDatabases (TRI_server_t* server) {
|
||||
size_t i, n;
|
||||
|
||||
TRI_WriteLockReadWriteLock(&server->_databasesLock);
|
||||
WRITE_LOCK_DATABASES(server);
|
||||
|
||||
n = server->_databases._nrAlloc;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
|
@ -838,7 +869,7 @@ static int CloseDatabases (TRI_server_t* server) {
|
|||
}
|
||||
}
|
||||
|
||||
TRI_WriteUnlockReadWriteLock(&server->_databasesLock);
|
||||
WRITE_UNLOCK_DATABASES(server);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
@ -1405,7 +1436,7 @@ static void DatabaseManager (void* data) {
|
|||
// check if we have to drop some database
|
||||
database = NULL;
|
||||
|
||||
TRI_ReadLockReadWriteLock(&server->_databasesLock);
|
||||
READ_LOCK_DATABASES(server);
|
||||
|
||||
n = server->_droppedDatabases._length;
|
||||
|
||||
|
@ -1420,8 +1451,8 @@ static void DatabaseManager (void* data) {
|
|||
database = (TRI_vocbase_t*) TRI_RemoveVectorPointer(&server->_droppedDatabases, i);
|
||||
break;
|
||||
}
|
||||
|
||||
TRI_ReadUnlockReadWriteLock(&server->_databasesLock);
|
||||
|
||||
READ_UNLOCK_DATABASES(server);
|
||||
|
||||
if (database != NULL) {
|
||||
// remember the database path
|
||||
|
@ -1978,7 +2009,7 @@ int TRI_CreateDatabaseServer (TRI_server_t* server,
|
|||
|
||||
TRI_LockMutex(&server->_createLock);
|
||||
|
||||
TRI_ReadLockReadWriteLock(&server->_databasesLock);
|
||||
READ_LOCK_DATABASES(server);
|
||||
|
||||
n = server->_databases._nrAlloc;
|
||||
for (i = 0; i < n; ++i) {
|
||||
|
@ -1987,7 +2018,7 @@ int TRI_CreateDatabaseServer (TRI_server_t* server,
|
|||
if (vocbase != NULL) {
|
||||
if (TRI_EqualString(name, vocbase->_name)) {
|
||||
// name already in use
|
||||
TRI_ReadUnlockReadWriteLock(&server->_databasesLock);
|
||||
READ_UNLOCK_DATABASES(server);
|
||||
TRI_UnlockMutex(&server->_createLock);
|
||||
|
||||
return TRI_ERROR_ARANGO_DUPLICATE_NAME;
|
||||
|
@ -1996,7 +2027,7 @@ int TRI_CreateDatabaseServer (TRI_server_t* server,
|
|||
}
|
||||
|
||||
// name not yet in use, release the read lock
|
||||
TRI_ReadUnlockReadWriteLock(&server->_databasesLock);
|
||||
READ_UNLOCK_DATABASES(server);
|
||||
|
||||
// create the database directory
|
||||
tick = TRI_NewTickServer();
|
||||
|
@ -2045,10 +2076,10 @@ int TRI_CreateDatabaseServer (TRI_server_t* server,
|
|||
|
||||
// increase reference counter
|
||||
TRI_UseVocBase(vocbase);
|
||||
|
||||
TRI_WriteLockReadWriteLock(&server->_databasesLock);
|
||||
|
||||
WRITE_LOCK_DATABASES(server);
|
||||
TRI_InsertKeyAssociativePointer(&server->_databases, vocbase->_name, vocbase, false);
|
||||
TRI_WriteUnlockReadWriteLock(&server->_databasesLock);
|
||||
WRITE_UNLOCK_DATABASES(server);
|
||||
|
||||
TRI_UnlockMutex(&server->_createLock);
|
||||
|
||||
|
@ -2071,11 +2102,11 @@ int TRI_DropDatabaseServer (TRI_server_t* server,
|
|||
return TRI_ERROR_FORBIDDEN;
|
||||
}
|
||||
|
||||
TRI_WriteLockReadWriteLock(&server->_databasesLock);
|
||||
WRITE_LOCK_DATABASES(server);
|
||||
|
||||
if (TRI_ReserveVectorPointer(&server->_droppedDatabases, 1) != TRI_ERROR_NO_ERROR) {
|
||||
// we need space for one more element
|
||||
TRI_WriteUnlockReadWriteLock(&server->_databasesLock);
|
||||
WRITE_UNLOCK_DATABASES(server);
|
||||
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -2108,7 +2139,7 @@ int TRI_DropDatabaseServer (TRI_server_t* server,
|
|||
}
|
||||
}
|
||||
|
||||
TRI_WriteUnlockReadWriteLock(&server->_databasesLock);
|
||||
WRITE_UNLOCK_DATABASES(server);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -2122,7 +2153,7 @@ TRI_vocbase_t* TRI_UseDatabaseServer (TRI_server_t* server,
|
|||
char const* name) {
|
||||
TRI_vocbase_t* vocbase;
|
||||
|
||||
TRI_ReadLockReadWriteLock(&server->_databasesLock);
|
||||
READ_LOCK_DATABASES(server);
|
||||
|
||||
vocbase = TRI_LookupByKeyAssociativePointer(&server->_databases, name);
|
||||
|
||||
|
@ -2132,8 +2163,8 @@ TRI_vocbase_t* TRI_UseDatabaseServer (TRI_server_t* server,
|
|||
// if we got here, no one else can have deleted the database
|
||||
assert(result == true);
|
||||
}
|
||||
|
||||
TRI_ReadUnlockReadWriteLock(&server->_databasesLock);
|
||||
|
||||
READ_UNLOCK_DATABASES(server);
|
||||
|
||||
return vocbase;
|
||||
}
|
||||
|
@ -2163,7 +2194,7 @@ int TRI_GetUserDatabasesServer (TRI_server_t* server,
|
|||
|
||||
res = TRI_ERROR_NO_ERROR;
|
||||
|
||||
TRI_ReadLockReadWriteLock(&server->_databasesLock);
|
||||
READ_LOCK_DATABASES(server);
|
||||
n = server->_databases._nrAlloc;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
|
@ -2194,7 +2225,8 @@ int TRI_GetUserDatabasesServer (TRI_server_t* server,
|
|||
}
|
||||
}
|
||||
}
|
||||
TRI_ReadUnlockReadWriteLock(&server->_databasesLock);
|
||||
|
||||
READ_UNLOCK_DATABASES(server);
|
||||
|
||||
SortDatabaseNames(names);
|
||||
|
||||
|
@ -2213,7 +2245,7 @@ int TRI_GetDatabaseNamesServer (TRI_server_t* server,
|
|||
|
||||
res = TRI_ERROR_NO_ERROR;
|
||||
|
||||
TRI_ReadLockReadWriteLock(&server->_databasesLock);
|
||||
READ_LOCK_DATABASES(server);
|
||||
n = server->_databases._nrAlloc;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
|
@ -2239,7 +2271,8 @@ int TRI_GetDatabaseNamesServer (TRI_server_t* server,
|
|||
}
|
||||
}
|
||||
}
|
||||
TRI_ReadUnlockReadWriteLock(&server->_databasesLock);
|
||||
|
||||
READ_UNLOCK_DATABASES(server);
|
||||
|
||||
SortDatabaseNames(names);
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ static int const SYNCHRONISER_INTERVAL = (100 * 1000);
|
|||
/// @brief checks if a file needs to be synced
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool CheckSyncDocumentCollection (TRI_document_collection_t* doc) {
|
||||
static bool CheckSyncDocumentCollection (TRI_document_collection_t* document) {
|
||||
TRI_collection_t* base;
|
||||
TRI_datafile_t* journal;
|
||||
bool ok;
|
||||
|
@ -75,7 +75,7 @@ static bool CheckSyncDocumentCollection (TRI_document_collection_t* doc) {
|
|||
size_t n;
|
||||
|
||||
worked = false;
|
||||
base = &doc->base.base;
|
||||
base = &document->base.base;
|
||||
|
||||
// .............................................................................
|
||||
// the only thread MODIFYING the _journals variable is this thread,
|
||||
|
@ -93,18 +93,16 @@ static bool CheckSyncDocumentCollection (TRI_document_collection_t* doc) {
|
|||
continue;
|
||||
}
|
||||
|
||||
TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(doc);
|
||||
|
||||
synced = journal->_synced;
|
||||
TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(document);
|
||||
synced = journal->_synced;
|
||||
written = journal->_written;
|
||||
|
||||
TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(doc);
|
||||
TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(document);
|
||||
|
||||
if (synced < written) {
|
||||
worked = true;
|
||||
ok = journal->sync(journal, synced, written);
|
||||
|
||||
TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(doc);
|
||||
TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(document);
|
||||
|
||||
if (ok) {
|
||||
journal->_synced = written;
|
||||
|
@ -113,11 +111,11 @@ static bool CheckSyncDocumentCollection (TRI_document_collection_t* doc) {
|
|||
journal->_state = TRI_DF_STATE_WRITE_ERROR;
|
||||
}
|
||||
|
||||
TRI_BROADCAST_JOURNAL_ENTRIES_DOC_COLLECTION(doc);
|
||||
TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(doc);
|
||||
TRI_BROADCAST_JOURNAL_ENTRIES_DOC_COLLECTION(document);
|
||||
TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(document);
|
||||
|
||||
if (ok) {
|
||||
LOG_TRACE("msync succeeded %p, size %lu", synced, (unsigned long)(written - synced));
|
||||
LOG_TRACE("msync succeeded %p, size %lu", synced, (unsigned long) (written - synced));
|
||||
}
|
||||
else {
|
||||
LOG_ERROR("msync failed with: %s", TRI_last_error());
|
||||
|
@ -152,7 +150,6 @@ static bool CheckJournalDocumentCollection (TRI_document_collection_t* document)
|
|||
// .............................................................................
|
||||
|
||||
TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(document);
|
||||
|
||||
n = base->_journals._length;
|
||||
|
||||
for (i = 0; i < n;) {
|
||||
|
|
|
@ -212,10 +212,18 @@ static bool UnregisterCollection (TRI_vocbase_t* vocbase,
|
|||
assert(collection->_name != NULL);
|
||||
|
||||
TRI_WRITE_LOCK_COLLECTIONS_VOCBASE(vocbase);
|
||||
|
||||
// pre-condition
|
||||
TRI_ASSERT_MAINTAINER(vocbase->_collectionsByName._nrUsed == vocbase->_collectionsById._nrUsed);
|
||||
|
||||
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, collection->_name);
|
||||
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsById, &collection->_cid);
|
||||
// only if we find the collection by its id, we can delete it by name
|
||||
if (TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsById, &collection->_cid) != NULL) {
|
||||
// this is because someone else might have created a new collection with the same name,
|
||||
// but with a different id
|
||||
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, collection->_name);
|
||||
}
|
||||
|
||||
// post-condition
|
||||
TRI_ASSERT_MAINTAINER(vocbase->_collectionsByName._nrUsed == vocbase->_collectionsById._nrUsed);
|
||||
|
||||
TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
|
||||
|
@ -237,9 +245,9 @@ static bool UnloadCollectionCallback (TRI_collection_t* col, void* data) {
|
|||
TRI_document_collection_t* document;
|
||||
int res;
|
||||
|
||||
collection = data;
|
||||
collection = (TRI_vocbase_col_t*) data;
|
||||
|
||||
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
||||
if (collection->_status != TRI_VOC_COL_STATUS_UNLOADING) {
|
||||
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
@ -328,7 +336,7 @@ static bool DropCollectionCallback (TRI_collection_t* col,
|
|||
}
|
||||
|
||||
|
||||
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
||||
if (collection->_status != TRI_VOC_COL_STATUS_DELETED) {
|
||||
LOG_ERROR("someone resurrected the collection '%s'", collection->_name);
|
||||
|
@ -559,7 +567,7 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
|
|||
|
||||
// check name
|
||||
res = TRI_InsertKeyAssociativePointer2(&vocbase->_collectionsByName, name, collection, &found);
|
||||
|
||||
|
||||
if (found != NULL) {
|
||||
LOG_ERROR("duplicate entry for collection name '%s'", name);
|
||||
LOG_ERROR("collection id %llu has same name as already added collection %llu",
|
||||
|
@ -573,7 +581,7 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
|
|||
}
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
// OOM. this might have happend AFTER insertion
|
||||
// OOM. this might have happened AFTER insertion
|
||||
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, name);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection);
|
||||
TRI_set_errno(res);
|
||||
|
@ -582,8 +590,9 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
|
|||
}
|
||||
|
||||
// check collection identifier
|
||||
assert(collection->_cid == cid);
|
||||
res = TRI_InsertKeyAssociativePointer2(&vocbase->_collectionsById, &cid, collection, &found);
|
||||
|
||||
|
||||
if (found != NULL) {
|
||||
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, name);
|
||||
|
||||
|
@ -601,7 +610,6 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
|
|||
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsById, &cid);
|
||||
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, name);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection);
|
||||
|
||||
TRI_set_errno(res);
|
||||
|
||||
return NULL;
|
||||
|
@ -720,8 +728,7 @@ static int RenameCollection (TRI_vocbase_t* vocbase,
|
|||
void const* found;
|
||||
int res;
|
||||
|
||||
// lock collection because we are going to change the name
|
||||
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
||||
// this must be done after the collection lock
|
||||
TRI_WRITE_LOCK_COLLECTIONS_VOCBASE(vocbase);
|
||||
|
@ -815,10 +822,12 @@ static int RenameCollection (TRI_vocbase_t* vocbase,
|
|||
|
||||
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, oldName);
|
||||
TRI_CopyString(collection->_name, newName, sizeof(collection->_name) - 1);
|
||||
|
||||
|
||||
// this shouldn't fail, as we removed an element above so adding one should be ok
|
||||
found = TRI_InsertKeyAssociativePointer(&vocbase->_collectionsByName, newName, CONST_CAST(collection), false);
|
||||
assert(found == NULL);
|
||||
|
||||
TRI_ASSERT_MAINTAINER(vocbase->_collectionsByName._nrUsed == vocbase->_collectionsById._nrUsed);
|
||||
|
||||
TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
|
||||
|
||||
|
@ -1090,7 +1099,7 @@ static int LoadCollectionVocBase (TRI_vocbase_t* vocbase,
|
|||
// write lock
|
||||
// .............................................................................
|
||||
|
||||
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
||||
// someone else loaded the collection, release the WRITE lock and try again
|
||||
if (collection->_status == TRI_VOC_COL_STATUS_LOADED) {
|
||||
|
@ -1751,7 +1760,10 @@ TRI_json_t* TRI_InventoryCollectionsVocBase (TRI_vocbase_t* vocbase,
|
|||
|
||||
TRI_InitVectorPointer(&collections, TRI_CORE_MEM_ZONE);
|
||||
|
||||
TRI_WriteLockReadWriteLock(&vocbase->_inventoryLock);
|
||||
while (! TRI_TryWriteLockReadWriteLock(&vocbase->_inventoryLock)) {
|
||||
// cycle on write-lock
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
// copy collection pointers into vector so we can work with the copy without
|
||||
// the global lock
|
||||
|
@ -1980,7 +1992,7 @@ int TRI_UnloadCollectionVocBase (TRI_vocbase_t* vocbase,
|
|||
return TRI_set_errno(TRI_ERROR_FORBIDDEN);
|
||||
}
|
||||
|
||||
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
||||
// cannot unload a corrupted collection
|
||||
if (collection->_status == TRI_VOC_COL_STATUS_CORRUPTED) {
|
||||
|
@ -2065,14 +2077,14 @@ int TRI_DropCollectionVocBase (TRI_vocbase_t* vocbase,
|
|||
|
||||
TRI_ReadLockReadWriteLock(&vocbase->_inventoryLock);
|
||||
|
||||
// mark collection as deleted
|
||||
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
||||
// .............................................................................
|
||||
// collection already deleted
|
||||
// .............................................................................
|
||||
|
||||
if (collection->_status == TRI_VOC_COL_STATUS_DELETED) {
|
||||
// mark collection as deleted
|
||||
UnregisterCollection(vocbase, collection, generatingServer);
|
||||
|
||||
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
@ -2101,7 +2113,7 @@ int TRI_DropCollectionVocBase (TRI_vocbase_t* vocbase,
|
|||
|
||||
// remove dangling .json.tmp file if it exists
|
||||
tmpFile = TRI_Concatenate4String(collection->_path, TRI_DIR_SEPARATOR_STR, TRI_VOC_PARAMETER_FILE, ".tmp");
|
||||
|
||||
|
||||
if (tmpFile != NULL) {
|
||||
if (TRI_ExistsFile(tmpFile)) {
|
||||
TRI_UnlinkFile(tmpFile);
|
||||
|
@ -2125,7 +2137,6 @@ int TRI_DropCollectionVocBase (TRI_vocbase_t* vocbase,
|
|||
}
|
||||
|
||||
collection->_status = TRI_VOC_COL_STATUS_DELETED;
|
||||
|
||||
UnregisterCollection(vocbase, collection, generatingServer);
|
||||
|
||||
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
@ -2180,6 +2191,7 @@ int TRI_DropCollectionVocBase (TRI_vocbase_t* vocbase,
|
|||
}
|
||||
|
||||
collection->_status = TRI_VOC_COL_STATUS_DELETED;
|
||||
|
||||
UnregisterCollection(vocbase, collection, generatingServer);
|
||||
|
||||
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
|
|
@ -114,6 +114,13 @@ struct TRI_vocbase_defaults_s;
|
|||
#define TRI_READ_UNLOCK_STATUS_VOCBASE_COL(a) \
|
||||
TRI_ReadUnlockReadWriteLock(&(a)->_lock)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tries to write lock the vocbase collection status
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TRI_TRY_WRITE_LOCK_STATUS_VOCBASE_COL(a) \
|
||||
TRI_TryWriteLockReadWriteLock(&(a)->_lock)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief write locks the vocbase collection status
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -128,6 +135,15 @@ struct TRI_vocbase_defaults_s;
|
|||
#define TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(a) \
|
||||
TRI_WriteUnlockReadWriteLock(&(a)->_lock)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief write locks the vocbase collection status using spinning
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(a) \
|
||||
while (! TRI_TRY_WRITE_LOCK_STATUS_VOCBASE_COL(a)) { \
|
||||
usleep(1000); \
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief locks the synchroniser waiters
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -72,6 +72,12 @@ using namespace triagens::arango;
|
|||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief we'll store deprecated config option values in here
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::string DeprecatedPath;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief base class for clients
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -117,7 +123,7 @@ static JSLoader StartupLoader;
|
|||
static string StartupModules = "";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief path for Node modules files
|
||||
/// @brief path for JavaScript packages
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static string StartupPackages = "";
|
||||
|
@ -434,11 +440,12 @@ static vector<string> ParseProgramOptions (int argc, char* argv[]) {
|
|||
("javascript.execute-string", &ExecuteString, "execute Javascript code from string")
|
||||
("javascript.check", &CheckScripts, "syntax check code Javascript code from file")
|
||||
("javascript.gc-interval", &GcInterval, "JavaScript request-based garbage collection interval (each x commands)")
|
||||
("javascript.modules-path", &StartupModules, "one or more directories separated by semi-colons")
|
||||
("javascript.package-path", &StartupPackages, "one or more directories separated by semi-colons")
|
||||
("javascript.startup-directory", &StartupPath, "startup paths containing the JavaScript files")
|
||||
("javascript.unit-tests", &UnitTests, "do not start as shell, run unit tests instead")
|
||||
("jslint", &JsLint, "do not start as shell, run jslint instead")
|
||||
// deprecated options
|
||||
("javascript.modules-path", &DeprecatedPath, "one or more directories separated by semi-colons (deprecated)")
|
||||
;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -479,10 +486,10 @@ static vector<string> ParseProgramOptions (int argc, char* argv[]) {
|
|||
// set V8 options
|
||||
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
|
||||
|
||||
// check module path
|
||||
if (StartupModules.empty()) {
|
||||
LOG_FATAL_AND_EXIT("module path not known, please use '--javascript.modules-path'");
|
||||
}
|
||||
// derive other paths from `--javascript.directory`
|
||||
StartupModules = StartupPath + TRI_DIR_SEPARATOR_STR + "client" + TRI_DIR_SEPARATOR_STR + "modules;" +
|
||||
StartupPath + TRI_DIR_SEPARATOR_STR + "common" + TRI_DIR_SEPARATOR_STR + "modules;" +
|
||||
StartupPath + TRI_DIR_SEPARATOR_STR + "node";
|
||||
|
||||
// turn on paging automatically if "pager" option is set
|
||||
if (options.has("pager") && ! options.has("use-pager")) {
|
||||
|
@ -1814,7 +1821,7 @@ int main (int argc, char* argv[]) {
|
|||
|
||||
TRI_InitV8Buffer(context);
|
||||
|
||||
TRI_InitV8Utils(context, StartupModules, StartupPackages, StartupPath);
|
||||
TRI_InitV8Utils(context, StartupPath, StartupModules, StartupPackages);
|
||||
TRI_InitV8Shell(context);
|
||||
|
||||
// reset the prompt error flag (will determine prompt colors)
|
||||
|
|
|
@ -37,9 +37,6 @@ threads = 3
|
|||
|
||||
[javascript]
|
||||
startup-directory = @PKGDATADIR@/js
|
||||
action-directory = @PKGDATADIR@/js/actions
|
||||
modules-path = @PKGDATADIR@/js/server/modules;@PKGDATADIR@/js/common/modules;@PKGDATADIR@/js/node
|
||||
package-path = @PKGDATADIR@/js/npm
|
||||
app-path = @PKGDATADIR@/js/apps
|
||||
|
||||
[ruby]
|
||||
|
|
|
@ -6,5 +6,3 @@ disable-authentication = true
|
|||
|
||||
[javascript]
|
||||
startup-directory = @PKGDATADIR@/js
|
||||
modules-path = @PKGDATADIR@/js/client/modules;@PKGDATADIR@/js/common/modules;@PKGDATADIR@/js/node
|
||||
package-path = @PKGDATADIR@/js/npm
|
||||
|
|
|
@ -13,9 +13,6 @@ threads = 3
|
|||
|
||||
[javascript]
|
||||
startup-directory = ./js
|
||||
action-directory = ./js/actions
|
||||
modules-path = ./js/server/modules;./js/common/modules;./js/node
|
||||
package-path = ./js/npm
|
||||
app-path = ./js/apps
|
||||
|
||||
[ruby]
|
||||
|
|
|
@ -5,5 +5,3 @@ disable-authentication = true
|
|||
|
||||
[javascript]
|
||||
startup-directory = ./js
|
||||
modules-path = ./js/client/modules;./js/common/modules;./js/node
|
||||
package-path = ./js/npm
|
||||
|
|
|
@ -74,8 +74,6 @@ jslint:
|
|||
--log.level error \
|
||||
--server.password "" \
|
||||
--javascript.startup-directory @srcdir@/js \
|
||||
--javascript.modules-path "@srcdir@/js/client/modules;@srcdir@/js/common/modules;@srcdir@/js/node" \
|
||||
--javascript.package-path "@srcdir@/js/npm;@srcdir@/js/common/test-data/modules" \
|
||||
--jslint $$file; \
|
||||
done
|
||||
|
||||
|
|
|
@ -222,6 +222,7 @@ div.headerDropdown {
|
|||
display:none;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
padding-bottom: 15px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ img.searchSubmit {
|
|||
.searchByAttribute, .searchEqualsLabel {
|
||||
margin-top: 3px;
|
||||
margin-right: 6px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
svg.graphViewer text {
|
||||
|
@ -83,6 +84,21 @@ div.mousepointer {
|
|||
padding: 5px;
|
||||
}
|
||||
|
||||
.gv_searchInput {
|
||||
background-color: #FFFFFF;
|
||||
box-shadow: 0 !important;
|
||||
color: #555555;
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
height: 18px !important;
|
||||
line-height: 18px;
|
||||
margin-top: 5px;
|
||||
padding: 2px;
|
||||
vertical-align: middle;
|
||||
width:214px !important;
|
||||
border-radius: 0px 0px 0px 0px !important;
|
||||
}
|
||||
|
||||
button.graphViewer-icon-button {
|
||||
border: medium none;
|
||||
width: 20px;
|
||||
|
@ -278,7 +294,8 @@ input.gv_radio_button {
|
|||
}
|
||||
|
||||
label.gv_dropdown_label {
|
||||
color: white;
|
||||
color: white !important;
|
||||
padding-left: 0px !important;
|
||||
}
|
||||
|
||||
/*Overriding the slider UI*/
|
||||
|
@ -360,12 +377,16 @@ div.gv_colour_list li {
|
|||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
#transparentHeader div.searchByAttribute > ul.dropdown-menu {
|
||||
div.queryline div.searchByAttribute > ul.dropdown-menu {
|
||||
position: absolute;
|
||||
border-radius: 0px;
|
||||
margin-top: -4px;
|
||||
margin-left: 5px;
|
||||
top: 21px;
|
||||
left: 5px;
|
||||
width: 247px;
|
||||
background-color: #333231;
|
||||
color: white;
|
||||
margin-bottom: 100%;
|
||||
display: none;
|
||||
/* background-color: #8F8D8C; */
|
||||
}
|
||||
|
||||
|
|
|
@ -1,206 +1,211 @@
|
|||
/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true */
|
||||
/*jslint indent: 2, nomen: true, maxlen: 100, vars: true, white: true, plusplus: true */
|
||||
/*global require, exports, window, Backbone, arangoDocumentModel, _, $*/
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
window.arangoDocuments = Backbone.Collection.extend({
|
||||
currentPage: 1,
|
||||
collectionID: 1,
|
||||
totalPages: 1,
|
||||
documentsPerPage: 10,
|
||||
documentsCount: 1,
|
||||
offset: 0,
|
||||
window.arangoDocuments = Backbone.Collection.extend({
|
||||
currentPage: 1,
|
||||
collectionID: 1,
|
||||
totalPages: 1,
|
||||
documentsPerPage: 10,
|
||||
documentsCount: 1,
|
||||
offset: 0,
|
||||
|
||||
url: '/_api/documents',
|
||||
model: arangoDocumentModel,
|
||||
getFirstDocuments: function () {
|
||||
if (this.currentPage !== 1) {
|
||||
var link = window.location.hash.split("/");
|
||||
window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/1";
|
||||
}
|
||||
},
|
||||
getLastDocuments: function () {
|
||||
if (this.currentPage !== this.totalPages) {
|
||||
var link = window.location.hash.split("/");
|
||||
window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/" + this.totalPages;
|
||||
}
|
||||
},
|
||||
getPrevDocuments: function () {
|
||||
if (this.currentPage !== 1) {
|
||||
var link = window.location.hash.split("/");
|
||||
var page = parseInt(this.currentPage, null) - 1;
|
||||
window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/" + page;
|
||||
}
|
||||
},
|
||||
getNextDocuments: function () {
|
||||
if (this.currentPage !== this.totalPages) {
|
||||
var link = window.location.hash.split("/");
|
||||
var page = parseInt(this.currentPage, null) + 1;
|
||||
window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/" + page;
|
||||
}
|
||||
},
|
||||
getDocuments: function (colid, currpage) {
|
||||
var self = this;
|
||||
this.collectionID = colid;
|
||||
this.currentPage = currpage;
|
||||
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: "GET",
|
||||
url: "/_api/collection/" + this.collectionID + "/count",
|
||||
contentType: "application/json",
|
||||
processData: false,
|
||||
async: false,
|
||||
success: function(data) {
|
||||
self.totalPages = Math.ceil(data.count / self.documentsPerPage);
|
||||
self.documentsCount = data.count;
|
||||
},
|
||||
error: function(data) {
|
||||
url: '/_api/documents',
|
||||
model: arangoDocumentModel,
|
||||
getFirstDocuments: function () {
|
||||
if (this.currentPage !== 1) {
|
||||
var link = window.location.hash.split("/");
|
||||
window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/1";
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (isNaN(this.currentPage) || this.currentPage === undefined || this.currentPage < 1) {
|
||||
this.currentPage = 1;
|
||||
}
|
||||
if (this.totalPages === 0) {
|
||||
this.totalPages = 1;
|
||||
}
|
||||
|
||||
this.offset = (this.currentPage - 1) * this.documentsPerPage;
|
||||
|
||||
var myQueryVal;
|
||||
var sortParameter = '_key';
|
||||
var sortCount = 10000;
|
||||
|
||||
if (this.documentsCount <= sortCount) {
|
||||
//sorted
|
||||
myQueryVal = "FOR x in @@collection SORT TO_NUMBER(x._key) == 0 " +
|
||||
"? x._key : TO_NUMBER(x._key) LIMIT @offset, @count RETURN x";
|
||||
}
|
||||
else {
|
||||
//not sorted
|
||||
myQueryVal = "FOR x in @@collection LIMIT @offset, @count RETURN x";
|
||||
}
|
||||
|
||||
var myQuery = {
|
||||
query: myQueryVal,
|
||||
bindVars: {
|
||||
"@collection": this.collectionID,
|
||||
"offset": this.offset,
|
||||
"count": this.documentsPerPage
|
||||
},
|
||||
getLastDocuments: function () {
|
||||
if (this.currentPage !== this.totalPages) {
|
||||
var link = window.location.hash.split("/");
|
||||
window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/" + this.totalPages;
|
||||
}
|
||||
};
|
||||
},
|
||||
getPrevDocuments: function () {
|
||||
if (this.currentPage !== 1) {
|
||||
var link = window.location.hash.split("/");
|
||||
var page = parseInt(this.currentPage, null) - 1;
|
||||
window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/" + page;
|
||||
}
|
||||
},
|
||||
getNextDocuments: function () {
|
||||
if (this.currentPage !== this.totalPages) {
|
||||
var link = window.location.hash.split("/");
|
||||
var page = parseInt(this.currentPage, null) + 1;
|
||||
window.location.hash = link[0] + "/" + link[1] + "/" + link[2] + "/" + page;
|
||||
}
|
||||
},
|
||||
getDocuments: function (colid, currpage) {
|
||||
var self = this;
|
||||
this.collectionID = colid;
|
||||
this.currentPage = currpage;
|
||||
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: 'POST',
|
||||
async: false,
|
||||
url: '/_api/cursor',
|
||||
data: JSON.stringify(myQuery),
|
||||
contentType: "application/json",
|
||||
success: function(data) {
|
||||
self.clearDocuments();
|
||||
if (self.documentsCount !== 0) {
|
||||
$.each(data.result, function(k, v) {
|
||||
//ERROR HERE
|
||||
window.arangoDocumentsStore.add({
|
||||
"id": v._id,
|
||||
"rev": v._rev,
|
||||
"key": v._key,
|
||||
"content": v
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: "GET",
|
||||
url: "/_api/collection/" + this.collectionID + "/count",
|
||||
contentType: "application/json",
|
||||
processData: false,
|
||||
async: false,
|
||||
success: function(data) {
|
||||
self.totalPages = Math.ceil(data.count / self.documentsPerPage);
|
||||
self.documentsCount = data.count;
|
||||
},
|
||||
error: function(data) {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (isNaN(this.currentPage) || this.currentPage === undefined || this.currentPage < 1) {
|
||||
this.currentPage = 1;
|
||||
}
|
||||
if (this.totalPages === 0) {
|
||||
this.totalPages = 1;
|
||||
}
|
||||
|
||||
this.offset = (this.currentPage - 1) * this.documentsPerPage;
|
||||
|
||||
var myQueryVal;
|
||||
var sortCount = 10000;
|
||||
|
||||
if (this.documentsCount <= sortCount) {
|
||||
//sorted
|
||||
myQueryVal = "FOR x in @@collection SORT TO_NUMBER(x._key) == 0 " +
|
||||
"? x._key : TO_NUMBER(x._key) LIMIT @offset, @count RETURN x";
|
||||
}
|
||||
else {
|
||||
//not sorted
|
||||
myQueryVal = "FOR x in @@collection LIMIT @offset, @count RETURN x";
|
||||
}
|
||||
|
||||
var myQuery = {
|
||||
query: myQueryVal,
|
||||
bindVars: {
|
||||
"@collection": this.collectionID,
|
||||
"offset": this.offset,
|
||||
"count": this.documentsPerPage
|
||||
}
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: 'POST',
|
||||
async: false,
|
||||
url: '/_api/cursor',
|
||||
data: JSON.stringify(myQuery),
|
||||
contentType: "application/json",
|
||||
success: function(data) {
|
||||
self.clearDocuments();
|
||||
if (self.documentsCount !== 0) {
|
||||
$.each(data.result, function(k, v) {
|
||||
//ERROR HERE
|
||||
window.arangoDocumentsStore.add({
|
||||
"id": v._id,
|
||||
"rev": v._rev,
|
||||
"key": v._key,
|
||||
"content": v
|
||||
});
|
||||
});
|
||||
});
|
||||
window.documentsView.drawTable();
|
||||
window.documentsView.renderPagination(self.totalPages);
|
||||
window.documentsView.drawTable();
|
||||
window.documentsView.renderPagination(self.totalPages);
|
||||
}
|
||||
else {
|
||||
window.documentsView.initTable();
|
||||
window.documentsView.drawTable();
|
||||
}
|
||||
},
|
||||
error: function(data) {
|
||||
}
|
||||
else {
|
||||
window.documentsView.initTable();
|
||||
window.documentsView.drawTable();
|
||||
}
|
||||
},
|
||||
error: function(data) {
|
||||
});
|
||||
},
|
||||
|
||||
getFilteredDocuments: function (colid, currpage, filter, bindValues) {
|
||||
var self = this;
|
||||
this.collectionID = colid;
|
||||
this.currentPage = currpage;
|
||||
this.currentFilterPage = currpage;
|
||||
var filterString;
|
||||
if(filter.length === 0){
|
||||
filterString ="";
|
||||
} else {
|
||||
filterString = ' FILTER' + filter.join(' && ');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getFilteredDocuments: function (colid, currpage, filter, bindValues) {
|
||||
var self = this;
|
||||
this.collectionID = colid;
|
||||
this.currentPage = currpage;
|
||||
this.currentFilterPage = currpage;
|
||||
var filterString;
|
||||
if(filter.length === 0){
|
||||
filterString ="";
|
||||
} else {
|
||||
filterString = ' FILTER' + filter.join(' && ');
|
||||
}
|
||||
var sortCount = 10000;
|
||||
|
||||
var sortCount = 10000;
|
||||
|
||||
var sortString = '';
|
||||
if (this.documentsCount <= sortCount) {
|
||||
//sorted
|
||||
sortString = " SORT TO_NUMBER(u._key) == 0 ? u._key : TO_NUMBER(u._key)";
|
||||
}
|
||||
var myQueryVal = "FOR u in @@collection" + filterString + sortString +
|
||||
" LIMIT 0, @count RETURN u";
|
||||
|
||||
var myQuery = {
|
||||
query: myQueryVal,
|
||||
bindVars: {
|
||||
"@collection": this.collectionID,
|
||||
"count": this.documentsPerPage
|
||||
},
|
||||
options: {
|
||||
fullCount: true
|
||||
var sortString = '';
|
||||
if (this.documentsCount <= sortCount) {
|
||||
//sorted
|
||||
sortString = " SORT TO_NUMBER(u._key) == 0 ? u._key : TO_NUMBER(u._key)";
|
||||
}
|
||||
};
|
||||
var myQueryVal = "FOR u in @@collection" + filterString + sortString +
|
||||
" LIMIT 0, @count RETURN u";
|
||||
|
||||
$.each(bindValues, function(k,v) {
|
||||
myQuery.bindVars[k] = v;
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: 'POST',
|
||||
async: false,
|
||||
url: '/_api/cursor',
|
||||
data: JSON.stringify(myQuery),
|
||||
contentType: "application/json",
|
||||
success: function(data) {
|
||||
self.clearDocuments();
|
||||
self.documentsCount = data.extra.fullCount;
|
||||
self.totalPages = Math.ceil(self.documentsCount / self.documentsPerPage);
|
||||
if (isNaN(this.currentPage) || this.currentPage === undefined || this.currentPage < 1) {
|
||||
this.currentPage = 1;
|
||||
}
|
||||
if (this.totalPages === 0) {
|
||||
this.totalPages = 1;
|
||||
var myQuery = {
|
||||
query: myQueryVal,
|
||||
bindVars: {
|
||||
"@collection": this.collectionID,
|
||||
"count": this.documentsPerPage
|
||||
},
|
||||
options: {
|
||||
fullCount: true
|
||||
}
|
||||
};
|
||||
|
||||
this.offset = (this.currentPage - 1) * this.documentsPerPage;
|
||||
if (self.documentsCount !== 0) {
|
||||
$.each(data.result, function(k, v) {
|
||||
window.arangoDocumentsStore.add({
|
||||
"id": v._id,
|
||||
"rev": v._rev,
|
||||
"key": v._key,
|
||||
"content": v
|
||||
$.each(bindValues, function(k,v) {
|
||||
myQuery.bindVars[k] = v;
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: 'POST',
|
||||
async: false,
|
||||
url: '/_api/cursor',
|
||||
data: JSON.stringify(myQuery),
|
||||
contentType: "application/json",
|
||||
success: function(data) {
|
||||
self.clearDocuments();
|
||||
self.documentsCount = data.extra.fullCount;
|
||||
self.totalPages = Math.ceil(self.documentsCount / self.documentsPerPage);
|
||||
if (
|
||||
isNaN(this.currentPage)
|
||||
|| this.currentPage === undefined
|
||||
|| this.currentPage < 1
|
||||
) {
|
||||
this.currentPage = 1;
|
||||
}
|
||||
if (this.totalPages === 0) {
|
||||
this.totalPages = 1;
|
||||
}
|
||||
|
||||
this.offset = (this.currentPage - 1) * this.documentsPerPage;
|
||||
if (self.documentsCount !== 0) {
|
||||
$.each(data.result, function(k, v) {
|
||||
window.arangoDocumentsStore.add({
|
||||
"id": v._id,
|
||||
"rev": v._rev,
|
||||
"key": v._key,
|
||||
"content": v
|
||||
});
|
||||
});
|
||||
});
|
||||
window.documentsView.drawTable();
|
||||
window.documentsView.renderPagination(self.totalPages, true);
|
||||
window.documentsView.drawTable();
|
||||
window.documentsView.renderPagination(self.totalPages, true);
|
||||
}
|
||||
else {
|
||||
window.documentsView.initTable();
|
||||
window.documentsView.drawTable();
|
||||
}
|
||||
},
|
||||
error: function(data) {
|
||||
}
|
||||
else {
|
||||
window.documentsView.initTable();
|
||||
window.documentsView.drawTable();
|
||||
}
|
||||
},
|
||||
error: function(data) {
|
||||
"use strict";
|
||||
}
|
||||
});
|
||||
},
|
||||
clearDocuments: function () {
|
||||
window.arangoDocumentsStore.reset();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
clearDocuments: function () {
|
||||
window.arangoDocumentsStore.reset();
|
||||
}
|
||||
});
|
||||
}());
|
||||
|
|
|
@ -1,57 +1,16 @@
|
|||
/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true */
|
||||
/*jslint indent: 2, nomen: true, maxlen: 100, vars: true, white: true, plusplus: true */
|
||||
/*global require, exports, Backbone, window, $, arangoLog */
|
||||
(function () {
|
||||
|
||||
window.ArangoLogs = Backbone.Collection.extend({
|
||||
url: '/_admin/log?upto=4&size=10&offset=0',
|
||||
parse: function(response) {
|
||||
var myResponse = [];
|
||||
var i = 0;
|
||||
$.each(response.lid, function(key, val) {
|
||||
myResponse.push({
|
||||
"level": response.level[i],
|
||||
"lid": response.lid[i],
|
||||
"text": response.text[i],
|
||||
"timestamp": response.timestamp[i],
|
||||
"totalAmount": response.totalAmount
|
||||
});
|
||||
i++;
|
||||
});
|
||||
return myResponse;
|
||||
},
|
||||
tables: ["logTableID", "warnTableID", "infoTableID", "debugTableID", "critTableID"],
|
||||
model: arangoLog,
|
||||
clearLocalStorage: function () {
|
||||
window.arangoLogsStore.reset();
|
||||
},
|
||||
returnElements: function () {
|
||||
},
|
||||
fillLocalStorage: function (table, offset, size) {
|
||||
var self = this;
|
||||
this.clearLocalStorage();
|
||||
if (! table) {
|
||||
table = 'logTableID';
|
||||
}
|
||||
if (! size) {
|
||||
size = 10;
|
||||
}
|
||||
if (! offset) {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
var loglevel = this.showLogLevel(table);
|
||||
var url = "";
|
||||
if (loglevel === 5) {
|
||||
url = "/_admin/log?upto=4";
|
||||
}
|
||||
else {
|
||||
url = "/_admin/log?level=" + loglevel;
|
||||
}
|
||||
url = url + "&size=" + size + "&offset=" + offset;
|
||||
$.getJSON(url, function(response) {
|
||||
var totalAmount = response.totalAmount;
|
||||
"use strict";
|
||||
|
||||
window.ArangoLogs = Backbone.Collection.extend({
|
||||
url: '/_admin/log?upto=4&size=10&offset=0',
|
||||
parse: function(response) {
|
||||
var myResponse = [];
|
||||
var i = 0;
|
||||
$.each(response.lid, function () {
|
||||
window.arangoLogsStore.add({
|
||||
$.each(response.lid, function(key, val) {
|
||||
myResponse.push({
|
||||
"level": response.level[i],
|
||||
"lid": response.lid[i],
|
||||
"text": response.text[i],
|
||||
|
@ -60,27 +19,70 @@ window.ArangoLogs = Backbone.Collection.extend({
|
|||
});
|
||||
i++;
|
||||
});
|
||||
window.logsView.drawTable();
|
||||
});
|
||||
},
|
||||
showLogLevel: function (tableid) {
|
||||
tableid = '#'+tableid;
|
||||
var returnVal = 0;
|
||||
if (tableid === "#critTableID") {
|
||||
returnVal = 1;
|
||||
return myResponse;
|
||||
},
|
||||
tables: ["logTableID", "warnTableID", "infoTableID", "debugTableID", "critTableID"],
|
||||
model: arangoLog,
|
||||
clearLocalStorage: function () {
|
||||
window.arangoLogsStore.reset();
|
||||
},
|
||||
returnElements: function () {
|
||||
},
|
||||
fillLocalStorage: function (table, offset, size) {
|
||||
this.clearLocalStorage();
|
||||
if (! table) {
|
||||
table = 'logTableID';
|
||||
}
|
||||
if (! size) {
|
||||
size = 10;
|
||||
}
|
||||
if (! offset) {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
var loglevel = this.showLogLevel(table);
|
||||
var url = "";
|
||||
if (loglevel === 5) {
|
||||
url = "/_admin/log?upto=4";
|
||||
}
|
||||
else {
|
||||
url = "/_admin/log?level=" + loglevel;
|
||||
}
|
||||
url = url + "&size=" + size + "&offset=" + offset;
|
||||
$.getJSON(url, function(response) {
|
||||
var i = 0;
|
||||
$.each(response.lid, function () {
|
||||
window.arangoLogsStore.add({
|
||||
"level": response.level[i],
|
||||
"lid": response.lid[i],
|
||||
"text": response.text[i],
|
||||
"timestamp": response.timestamp[i],
|
||||
"totalAmount": response.totalAmount
|
||||
});
|
||||
i++;
|
||||
});
|
||||
window.logsView.drawTable();
|
||||
});
|
||||
},
|
||||
showLogLevel: function (tableid) {
|
||||
tableid = '#'+tableid;
|
||||
var returnVal = 0;
|
||||
if (tableid === "#critTableID") {
|
||||
returnVal = 1;
|
||||
}
|
||||
else if (tableid === "#warnTableID") {
|
||||
returnVal = 2;
|
||||
}
|
||||
else if (tableid === "#infoTableID") {
|
||||
returnVal = 3;
|
||||
}
|
||||
else if (tableid === "#debugTableID") {
|
||||
returnVal = 4;
|
||||
}
|
||||
else if (tableid === "#logTableID") {
|
||||
returnVal = 5;
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
else if (tableid === "#warnTableID") {
|
||||
returnVal = 2;
|
||||
}
|
||||
else if (tableid === "#infoTableID") {
|
||||
returnVal = 3;
|
||||
}
|
||||
else if (tableid === "#debugTableID") {
|
||||
returnVal = 4;
|
||||
}
|
||||
else if (tableid === "#logTableID") {
|
||||
returnVal = 5;
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
|
|
@ -1,237 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="style/bootstrap.min.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="style/graphlayout.css" type="text/css"/>
|
||||
<link rel="stylesheet" type="text/css" href="style/bootstrap.min.css">
|
||||
|
||||
<script src="../lib/d3.v3.min.js"></script>
|
||||
<script src="../lib/underscore.js"></script>
|
||||
<script src="../lib/jquery-1.8.3.js"></script>
|
||||
<script type="text/javascript" src="../lib/bootstrap.js"></script>
|
||||
<script src="../lib/jquery.livequery.js"></script>
|
||||
<script src="graph/colourMapper.js"></script>
|
||||
<script src="graph/forceLayouter.js"></script>
|
||||
<script src="graph/eventLibrary.js"></script>
|
||||
<script src="graph/eventDispatcher.js"></script>
|
||||
<script src="graph/nodeShaper.js"></script>
|
||||
<script src="graph/edgeShaper.js"></script>
|
||||
<script src="graph/arangoAdapter.js"></script>
|
||||
|
||||
<script type="text/javascript" src="ui/modalDialogHelper.js"></script>
|
||||
<script type="text/javascript" src="ui/nodeShaperControls.js"></script>
|
||||
<script type="text/javascript" src="ui/edgeShaperControls.js"></script>
|
||||
<script type="text/javascript" src="ui/uiComponentsHelper.js"></script>
|
||||
<script type="text/javascript" src="ui/eventDispatcherControls.js"></script>
|
||||
<script type="text/javascript" src="ui/graphViewerUI.js"></script>
|
||||
|
||||
<script src="graphViewer.js"></script>
|
||||
<script>
|
||||
|
||||
var arangodb = "http://localhost:8529";
|
||||
//var arangodb = "nirvana.org";
|
||||
|
||||
var createCollection = function(name, type, callback) {
|
||||
if (type !== "Document" && type !== "Edge") {
|
||||
throw "Unsupported type";
|
||||
}
|
||||
var data = {
|
||||
"name": name,
|
||||
"type": type,
|
||||
"journalSize": 1048576
|
||||
};
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: "POST",
|
||||
url: arangodb + "/_api/collection",
|
||||
data: JSON.stringify(data),
|
||||
contentType: "application/json",
|
||||
processData: false,
|
||||
async: false,
|
||||
success: function(data) {
|
||||
callback(data.id);
|
||||
},
|
||||
error: function(data) {
|
||||
throw data.statusText;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var insertEdge = function (collectionID, from, to) {
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: "POST",
|
||||
async: false,
|
||||
url: arangodb + "/_api/edge?collection=" + collectionID + "&from=" + from + "&to=" + to,
|
||||
data: JSON.stringify({}),
|
||||
contentType: "application/json",
|
||||
processData: false,
|
||||
success: function(data) {
|
||||
return data._id;
|
||||
},
|
||||
error: function(data) {
|
||||
throw data.statusText;
|
||||
}
|
||||
});
|
||||
};
|
||||
var insertNode = function (collectionID, node) {
|
||||
var id;
|
||||
$.ajax({
|
||||
cache: false,
|
||||
type: "POST",
|
||||
async: false,
|
||||
url: arangodb + "/_api/document?collection=" + collectionID,
|
||||
data: JSON.stringify(node),
|
||||
contentType: "application/json",
|
||||
processData: false,
|
||||
success: function(data) {
|
||||
id = data._id;
|
||||
},
|
||||
error: function(data) {
|
||||
throw data.statusText;
|
||||
}
|
||||
});
|
||||
return id;
|
||||
};
|
||||
|
||||
var setupArangoContent = function() {
|
||||
var nodesCollection = "Classes";
|
||||
var edgesCollection = "Connections";
|
||||
|
||||
//deleteArangoContent();
|
||||
|
||||
createCollection(nodesCollection, "Document", function(id) {nodesCollId = id;});
|
||||
createCollection(edgesCollection, "Edge", function(id) {edgesCollId = id;});
|
||||
|
||||
var c1 = insertNode(nodesCollection, {id: 1, name: "graphViewer", type: "Controller"}),
|
||||
c2 = insertNode(nodesCollection, {id: 2, name: "Shaper", type: "AbstractView"}),
|
||||
c3 = insertNode(nodesCollection, {id: 3, name: "NodeShaper", type: "View"}),
|
||||
c4 = insertNode(nodesCollection, {id: 4, name: "EdgeShaper", type: "View"}),
|
||||
c5 = insertNode(nodesCollection, {id: 5, name: "Adapter", type: "AbstractModel"}),
|
||||
c6 = insertNode(nodesCollection, {id: 6, name: "ArangoAdapter", type: "Model"}),
|
||||
c7 = insertNode(nodesCollection, {id: 7, name: "JSONAdapter", type: "Model"}),
|
||||
c8 = insertNode(nodesCollection, {id: 8, name: "Layouter", type: "AbstractView"}),
|
||||
c9 = insertNode(nodesCollection, {id: 9, name: "forceLayouter", type: "View"}),
|
||||
c10 = insertNode(nodesCollection, {id: 10, name: "eventLibrary", type: "Events"}),
|
||||
|
||||
|
||||
c11 = insertNode(nodesCollection, {id: 11, name: "Configuration", type: "JSON"}),
|
||||
c12 = insertNode(nodesCollection, {id: 12, name: "Configuration", type: "JSON"}),
|
||||
|
||||
c13 = insertNode(nodesCollection, {id: 13, name: "Configuration", type: "JSON"}),
|
||||
c14 = insertNode(nodesCollection, {id: 14, name: "Configuration", type: "JSON"}),
|
||||
c15 = insertNode(nodesCollection, {id: 15, name: "Configuration", type: "JSON"}),
|
||||
|
||||
|
||||
nsc1 = insertNode(nodesCollection, {id: 16, name: "shape", type: "NodeShaper.shapes"}),
|
||||
nsc2 = insertNode(nodesCollection, {id: 17, name: "label", type: "string||function(node)"}),
|
||||
nsc3 = insertNode(nodesCollection, {id: 18, name: "size", type: "double||function(node)"}),
|
||||
nsc4 = insertNode(nodesCollection, {id: 19, name: "ondrag", type: "function(node)"}),
|
||||
nsc5 = insertNode(nodesCollection, {id: 20, name: "onclick", type: "function(node)"}),
|
||||
nsc6 = insertNode(nodesCollection, {id: 21, name: "onupdate", type: "function(node)"});
|
||||
|
||||
insertEdge(edgesCollection, c1, c2);
|
||||
insertEdge(edgesCollection, c1, c5);
|
||||
insertEdge(edgesCollection, c1, c8);
|
||||
insertEdge(edgesCollection, c1, c10);
|
||||
|
||||
insertEdge(edgesCollection, c2, c3);
|
||||
insertEdge(edgesCollection, c2, c4);
|
||||
|
||||
insertEdge(edgesCollection, c5, c6);
|
||||
insertEdge(edgesCollection, c5, c7);
|
||||
|
||||
insertEdge(edgesCollection, c8, c9);
|
||||
|
||||
insertEdge(edgesCollection, c10, c8);
|
||||
insertEdge(edgesCollection, c10, c5);
|
||||
insertEdge(edgesCollection, c10, c2);
|
||||
|
||||
insertEdge(edgesCollection, c3, c11);
|
||||
insertEdge(edgesCollection, c4, c12);
|
||||
insertEdge(edgesCollection, c6, c13);
|
||||
insertEdge(edgesCollection, c7, c14);
|
||||
|
||||
insertEdge(edgesCollection, c9, c15);
|
||||
|
||||
insertEdge(edgesCollection, c11, nsc1);
|
||||
insertEdge(edgesCollection, c11, nsc2);
|
||||
insertEdge(edgesCollection, c11, nsc3);
|
||||
insertEdge(edgesCollection, c11, nsc4);
|
||||
insertEdge(edgesCollection, c11, nsc5);
|
||||
insertEdge(edgesCollection, c11, nsc6);
|
||||
};
|
||||
|
||||
function createViewer() {
|
||||
var host,
|
||||
ecol,
|
||||
ncol,
|
||||
aaconfig;
|
||||
|
||||
host = $("#host")[0].value;
|
||||
ecol = $("#edgeCollection")[0].value;
|
||||
ncol = $("#nodeCollection")[0].value;
|
||||
|
||||
aaconfig = {
|
||||
type: "arango",
|
||||
nodeCollection: ncol,
|
||||
edgeCollection: ecol,
|
||||
host: host
|
||||
};
|
||||
|
||||
/*
|
||||
layouterConfig = {
|
||||
"type": "force",
|
||||
"gravity": 0.01,
|
||||
"distance": 100,
|
||||
"charge": -300
|
||||
};
|
||||
*/
|
||||
|
||||
$("#creationDialog")[0].style.display = "none";
|
||||
ui = new GraphViewerUI(document.getElementById("content"), aaconfig);
|
||||
}
|
||||
|
||||
var ui;
|
||||
</script>
|
||||
<title>DEMO</title>
|
||||
</head>
|
||||
<!--<body onload="setupArangoContent()"> -->
|
||||
<body>
|
||||
<form action="javascript:void(0);" autocomplete="on" class="form-horizontal" id="creationDialog">
|
||||
<fieldset>
|
||||
<legend>Create the Viewer</legend>
|
||||
<fieldset>
|
||||
<legend>Setup Arango Connection</legend>
|
||||
<div class="control-group">
|
||||
<label for="host" class="control-label">Host</label>
|
||||
<div class="controls">
|
||||
<input id="host" type="text" name="host" placeholder="Host" maxlength="75" class="input-xlarge" value="http://localhost:8529">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="nodeCollection" class="control-label">Node Collection</label>
|
||||
<div class="controls">
|
||||
<input id="nodeCollection" type="text" name="nodeCollection" placeholder="Node Collection" maxlength="75" class="input-xlarge" value="Classes">
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label for="edgeCollection" class="control-label">Edge Collection</label>
|
||||
<div class="controls">
|
||||
<input id="edgeCollection" type="text" name="edgeCollection" placeholder="Edge Collection" maxlength="75" class="input-xlarge" value="Connections">
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<button type="submit" class="btn btn-primary" onclick="createViewer()">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
<div id="content" style="width:980px; height:640px" />
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -265,7 +265,7 @@ function ArangoAdapter(nodes, edges, config) {
|
|||
return;
|
||||
}
|
||||
callback(absAdapter.insertInitialNode(n));
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
|
|
|
@ -30,13 +30,12 @@
|
|||
function ColourMapper() {
|
||||
"use strict";
|
||||
|
||||
var mapCreated = false,
|
||||
mapping = {},
|
||||
reverseMapping = {},
|
||||
colours = [],
|
||||
listener,
|
||||
self = this,
|
||||
nextColour = 0;
|
||||
var mapping = {},
|
||||
reverseMapping = {},
|
||||
colours = [],
|
||||
listener,
|
||||
self = this,
|
||||
nextColour = 0;
|
||||
|
||||
colours.push({back: "navy", front: "white"});
|
||||
colours.push({back: "green", front: "white"});
|
||||
|
@ -129,4 +128,4 @@ function ColourMapper() {
|
|||
};
|
||||
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -368,7 +368,7 @@ function CommunityNode(parent, initial) {
|
|||
.attr("height", "20")
|
||||
.attr("fill", "#686766")
|
||||
.attr("stroke", "none");
|
||||
var dissolveBtn = bBox.append("image")
|
||||
bBox.append("image")
|
||||
.attr("id", self._id + "_dissolve")
|
||||
.attr("xlink:href", "img/icon_delete.png")
|
||||
.attr("width", "16")
|
||||
|
@ -379,8 +379,8 @@ function CommunityNode(parent, initial) {
|
|||
.on("click", function() {
|
||||
self.dissolve();
|
||||
start();
|
||||
}),
|
||||
collapseBtn = bBox.append("image")
|
||||
});
|
||||
bBox.append("image")
|
||||
.attr("id", self._id + "_collapse")
|
||||
.attr("xlink:href", "img/gv_collapse.png")
|
||||
.attr("width", "16")
|
||||
|
@ -391,8 +391,8 @@ function CommunityNode(parent, initial) {
|
|||
.on("click", function() {
|
||||
self.collapse();
|
||||
start();
|
||||
}),
|
||||
title = bBox.append("text")
|
||||
});
|
||||
var title = bBox.append("text")
|
||||
.attr("x", "45")
|
||||
.attr("y", "15")
|
||||
.attr("fill", "white")
|
||||
|
|
|
@ -31,7 +31,6 @@ function EventDispatcher(nodeShaper, edgeShaper, config) {
|
|||
"use strict";
|
||||
|
||||
var eventlib,
|
||||
expandConfig,
|
||||
svgBase,
|
||||
svgTemp,
|
||||
svgObj,
|
||||
|
|
|
@ -132,7 +132,7 @@ function EventLibrary() {
|
|||
}
|
||||
adapter.createNode(d, function(newNode) {
|
||||
nodeShaper.reshapeNodes();
|
||||
callback(newNode);
|
||||
cb(newNode);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
|
@ -112,7 +112,7 @@
|
|||
altEdgesCollection,
|
||||
mockCollection,
|
||||
callbackCheck,
|
||||
checkCallbackFunction = function() {
|
||||
checkCallbackFunction = function(test) {
|
||||
callbackCheck = true;
|
||||
},
|
||||
|
||||
|
@ -760,7 +760,12 @@
|
|||
if (vars !== undefined) {
|
||||
request.success({result: loadGraph(vars)});
|
||||
} else {
|
||||
request.success({result: {}});
|
||||
request.success({
|
||||
error: false,
|
||||
_id: "TestNodes654/myNewNode",
|
||||
_key: "myNewNode",
|
||||
_rev: "1234"
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -794,7 +799,7 @@
|
|||
|
||||
waitsFor(function() {
|
||||
return callbackCheck;
|
||||
}, 1000);
|
||||
}, 1500);
|
||||
|
||||
runs(function() {
|
||||
existNode(insertedId);
|
||||
|
@ -1060,9 +1065,6 @@
|
|||
}, 1000);
|
||||
|
||||
runs(function() {
|
||||
var callNodesIds = _.map(callNodes, function(n) {
|
||||
return n._id;
|
||||
});
|
||||
expect(this.fakeReducerBucketRequest).toHaveBeenCalledWith(
|
||||
jasmine.any(Array),
|
||||
5
|
||||
|
@ -1288,6 +1290,12 @@
|
|||
var insertedId;
|
||||
|
||||
runs(function() {
|
||||
fakeResult = {
|
||||
error: false,
|
||||
_id: "TestNodes123/MyNode",
|
||||
_rev: "1234",
|
||||
_key: "MyNode"
|
||||
};
|
||||
adapter.createNode({}, function(node) {
|
||||
insertedId = node._id;
|
||||
callbackCheck = true;
|
||||
|
@ -1355,7 +1363,6 @@
|
|||
});
|
||||
|
||||
it('should create a community node if limit is set too small', function() {
|
||||
var called;
|
||||
|
||||
runs(function() {
|
||||
callbackCheck = false;
|
||||
|
|
|
@ -151,15 +151,11 @@
|
|||
var edgeRoute,
|
||||
nodeRoute,
|
||||
queryRoute,
|
||||
loadGraph,
|
||||
requests;
|
||||
|
||||
beforeEach(function() {
|
||||
var self = this,
|
||||
route = "foxx/route",
|
||||
/*host = window.location.protocol + "//"
|
||||
+ window.location.host + "/"
|
||||
+ route;*/
|
||||
host = route;
|
||||
self.fakeReducerRequest = function() {};
|
||||
self.fakeReducerBucketRequest = function() {};
|
||||
|
|
|
@ -30,214 +30,215 @@
|
|||
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
var describeInterface = function (testee) {
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
describe('checking the interface', function() {
|
||||
it('should comply to the Adapter Interface', function() {
|
||||
this.addMatchers({
|
||||
toHaveFunction: function(func, argCounter) {
|
||||
var obj = this.actual;
|
||||
this.message = function(){
|
||||
return testee.constructor.name
|
||||
+ " should react to function "
|
||||
+ func
|
||||
+ " with at least "
|
||||
+ argCounter
|
||||
+ " arguments.";
|
||||
};
|
||||
if (typeof(obj[func]) !== "function") {
|
||||
return false;
|
||||
}
|
||||
if (obj[func].length < argCounter) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Add functions to load here:
|
||||
expect(testee).toHaveFunction("loadNode", 2);
|
||||
expect(testee).toHaveFunction("loadInitialNode", 2);
|
||||
expect(testee).toHaveFunction("explore", 2);
|
||||
// expect(testee).toHaveFunction("loadNodeFromTreeById", 2);
|
||||
expect(testee).toHaveFunction("requestCentralityChildren", 2);
|
||||
// expect(testee).toHaveFunction("loadNodeFromTreeByAttributeValue", 3);
|
||||
expect(testee).toHaveFunction("createEdge", 2);
|
||||
expect(testee).toHaveFunction("deleteEdge", 2);
|
||||
expect(testee).toHaveFunction("patchEdge", 3);
|
||||
expect(testee).toHaveFunction("createNode", 2);
|
||||
expect(testee).toHaveFunction("deleteNode", 2);
|
||||
expect(testee).toHaveFunction("patchNode", 3);
|
||||
expect(testee).toHaveFunction("setNodeLimit", 2);
|
||||
expect(testee).toHaveFunction("setChildLimit", 1);
|
||||
expect(testee).toHaveFunction("expandCommunity", 2);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Expectations on constructor:
|
||||
* Created with config: {prioList: ["foo", "bar", "baz"]}
|
||||
* loadNode -> Adds {_id: 1} -{_id:"1-2"}-> {_id: 2}
|
||||
* createEdge({source: {_id: 1}, target: {_id: 1}}) -> {_id: "1-2", _from:1, _to:2}
|
||||
* createNode({}) -> {_id: 1}
|
||||
*
|
||||
*/
|
||||
|
||||
var describeIntegeration = function(constructor) {
|
||||
"use strict";
|
||||
|
||||
describe('checking integeration of the abstract adapter', function() {
|
||||
window.describeInterface = function (testee) {
|
||||
|
||||
var mockedAbstract, testee;
|
||||
|
||||
beforeEach(function() {
|
||||
mockedAbstract = {
|
||||
edges: [],
|
||||
nodes: [],
|
||||
setWidth: function(){},
|
||||
setHeight: function(){},
|
||||
insertNode: function(data){
|
||||
var node = {
|
||||
_data: data,
|
||||
_id: data._id
|
||||
}, i;
|
||||
for (i = 0; i < this.nodes.length; i++) {
|
||||
if (this.nodes[i]._id === node._id) {
|
||||
return this.nodes[i];
|
||||
describe('checking the interface', function() {
|
||||
it('should comply to the Adapter Interface', function() {
|
||||
this.addMatchers({
|
||||
toHaveFunction: function(func, argCounter) {
|
||||
var obj = this.actual;
|
||||
this.message = function(){
|
||||
return testee.constructor.name
|
||||
+ " should react to function "
|
||||
+ func
|
||||
+ " with at least "
|
||||
+ argCounter
|
||||
+ " arguments.";
|
||||
};
|
||||
if (typeof(obj[func]) !== "function") {
|
||||
return false;
|
||||
}
|
||||
if (obj[func].length < argCounter) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
this.nodes.push(node);
|
||||
return node;
|
||||
},
|
||||
insertEdge: function(){},
|
||||
removeNode: function(){},
|
||||
removeEdge: function(){},
|
||||
removeEdgesForNode: function(){},
|
||||
expandCommunity: function(){},
|
||||
setNodeLimit: function(){},
|
||||
setChildLimit: function(){},
|
||||
checkSizeOfInserted: function(){},
|
||||
checkNodeLimit: function(){},
|
||||
explore: function(){},
|
||||
changeTo: function(){},
|
||||
getPrioList: function(){}
|
||||
};
|
||||
|
||||
|
||||
spyOn(window, "AbstractAdapter").andCallFake(function(nodes, edges, descendant, config) {
|
||||
mockedAbstract.nodes = nodes;
|
||||
mockedAbstract.edges = edges;
|
||||
return mockedAbstract;
|
||||
});
|
||||
|
||||
// Add functions to load here:
|
||||
expect(testee).toHaveFunction("loadNode", 2);
|
||||
expect(testee).toHaveFunction("loadInitialNode", 2);
|
||||
expect(testee).toHaveFunction("explore", 2);
|
||||
// expect(testee).toHaveFunction("loadNodeFromTreeById", 2);
|
||||
expect(testee).toHaveFunction("requestCentralityChildren", 2);
|
||||
// expect(testee).toHaveFunction("loadNodeFromTreeByAttributeValue", 3);
|
||||
expect(testee).toHaveFunction("createEdge", 2);
|
||||
expect(testee).toHaveFunction("deleteEdge", 2);
|
||||
expect(testee).toHaveFunction("patchEdge", 3);
|
||||
expect(testee).toHaveFunction("createNode", 2);
|
||||
expect(testee).toHaveFunction("deleteNode", 2);
|
||||
expect(testee).toHaveFunction("patchNode", 3);
|
||||
expect(testee).toHaveFunction("setNodeLimit", 2);
|
||||
expect(testee).toHaveFunction("setChildLimit", 1);
|
||||
expect(testee).toHaveFunction("expandCommunity", 2);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Expectations on constructor:
|
||||
* Created with config: {prioList: ["foo", "bar", "baz"]}
|
||||
* loadNode -> Adds {_id: 1} -{_id:"1-2"}-> {_id: 2}
|
||||
* createEdge({source: {_id: 1}, target: {_id: 1}}) -> {_id: "1-2", _from:1, _to:2}
|
||||
* createNode({}) -> {_id: 1}
|
||||
*
|
||||
*/
|
||||
|
||||
window.describeIntegeration = function(constructor) {
|
||||
|
||||
it('should create the AbstractAdapter with correct values', function() {
|
||||
testee = constructor();
|
||||
expect(window.AbstractAdapter).wasCalledWith(
|
||||
[],
|
||||
[],
|
||||
testee,
|
||||
{prioList: ["foo", "bar", "baz"]}
|
||||
);
|
||||
});
|
||||
|
||||
it('should call getPrioList on the abstract', function() {
|
||||
spyOn(mockedAbstract, "getPrioList");
|
||||
testee = constructor();
|
||||
testee.getPrioList();
|
||||
expect(mockedAbstract.getPrioList).wasCalled();
|
||||
});
|
||||
|
||||
it('should call setNodeLimit on the abstract', function() {
|
||||
spyOn(mockedAbstract, "setNodeLimit");
|
||||
testee = constructor();
|
||||
testee.setNodeLimit(5, function(){});
|
||||
expect(mockedAbstract.setNodeLimit).wasCalledWith(5, jasmine.any(Function));
|
||||
});
|
||||
|
||||
it('should propagate changeTo to the abstract', function() {
|
||||
spyOn(mockedAbstract, "changeTo");
|
||||
testee = constructor();
|
||||
testee.changeTo({prioList: ["foo", "bar", "baz"]});
|
||||
expect(mockedAbstract.changeTo).wasCalledWith({prioList: ["foo", "bar", "baz"]});
|
||||
});
|
||||
|
||||
it('should call explore on the abstract', function() {
|
||||
spyOn(mockedAbstract, "explore");
|
||||
testee = constructor();
|
||||
var node = {
|
||||
_id: "1"
|
||||
};
|
||||
testee.explore(node, function(){});
|
||||
expect(mockedAbstract.explore).wasCalledWith(node, jasmine.any(Function));
|
||||
});
|
||||
|
||||
it('should call setChildLimit on the abstract', function() {
|
||||
spyOn(mockedAbstract, "setChildLimit");
|
||||
testee = constructor();
|
||||
testee.setChildLimit(5);
|
||||
expect(mockedAbstract.setChildLimit).wasCalledWith(5);
|
||||
});
|
||||
|
||||
it('should call expandCommunity on the abstract', function() {
|
||||
spyOn(mockedAbstract, "expandCommunity");
|
||||
var comm = {};
|
||||
testee = constructor();
|
||||
testee.expandCommunity(comm);
|
||||
expect(mockedAbstract.expandCommunity).wasCalledWith(comm);
|
||||
});
|
||||
|
||||
it('should use the abstract to insert objects from loadNode', function() {
|
||||
spyOn(mockedAbstract, "insertNode").andCallThrough();
|
||||
spyOn(mockedAbstract, "insertEdge").andCallThrough();
|
||||
spyOn(mockedAbstract, "checkSizeOfInserted");
|
||||
spyOn(mockedAbstract, "checkNodeLimit");
|
||||
testee = constructor();
|
||||
testee.loadNode(1);
|
||||
expect(mockedAbstract.insertNode).wasCalledWith({_id: 1});
|
||||
expect(mockedAbstract.insertNode).wasCalledWith({_id: 2});
|
||||
expect(mockedAbstract.insertEdge).wasCalledWith({_id: "1-2", _from: 1, _to: 2});
|
||||
expect(mockedAbstract.checkSizeOfInserted).wasCalledWith({2: mockedAbstract.nodes[1]});
|
||||
expect(mockedAbstract.checkNodeLimit).wasCalledWith(mockedAbstract.nodes[0]);
|
||||
});
|
||||
|
||||
it('should insert an edge on createEdge', function() {
|
||||
spyOn(mockedAbstract, "insertEdge");
|
||||
testee = constructor();
|
||||
testee.createEdge({source: {_id: 1}, target: {_id: 2}}, function(){});
|
||||
expect(mockedAbstract.insertEdge).wasCalledWith({_id: "1-2", _from: 1, _to: 2});
|
||||
});
|
||||
|
||||
it('should remove an edge on deleteEdge', function() {
|
||||
spyOn(mockedAbstract, "removeEdge");
|
||||
testee = constructor();
|
||||
var edge = {_id: "1-2", _from: 1, _to: 2};
|
||||
testee.deleteEdge(edge);
|
||||
expect(mockedAbstract.removeEdge).wasCalledWith(edge);
|
||||
});
|
||||
|
||||
it('should insert a node on createNode', function() {
|
||||
spyOn(mockedAbstract, "insertNode");
|
||||
testee = constructor();
|
||||
testee.createNode({}, function(){});
|
||||
expect(mockedAbstract.insertNode).wasCalledWith({_id: 1});
|
||||
});
|
||||
|
||||
it('should remove a node on deleteNode', function() {
|
||||
spyOn(mockedAbstract, "removeNode");
|
||||
spyOn(mockedAbstract, "removeEdgesForNode");
|
||||
testee = constructor();
|
||||
var node = {_id: 1};
|
||||
testee.deleteNode(node);
|
||||
expect(mockedAbstract.removeEdgesForNode).wasCalledWith(node);
|
||||
expect(mockedAbstract.removeNode).wasCalledWith(node);
|
||||
});
|
||||
describe('checking integeration of the abstract adapter', function() {
|
||||
|
||||
var mockedAbstract, testee;
|
||||
|
||||
beforeEach(function() {
|
||||
mockedAbstract = {
|
||||
edges: [],
|
||||
nodes: [],
|
||||
setWidth: function(){},
|
||||
setHeight: function(){},
|
||||
insertNode: function(data){
|
||||
var node = {
|
||||
_data: data,
|
||||
_id: data._id
|
||||
}, i;
|
||||
for (i = 0; i < this.nodes.length; i++) {
|
||||
if (this.nodes[i]._id === node._id) {
|
||||
return this.nodes[i];
|
||||
}
|
||||
}
|
||||
this.nodes.push(node);
|
||||
return node;
|
||||
},
|
||||
insertEdge: function(){},
|
||||
removeNode: function(){},
|
||||
removeEdge: function(){},
|
||||
removeEdgesForNode: function(){},
|
||||
expandCommunity: function(){},
|
||||
setNodeLimit: function(){},
|
||||
setChildLimit: function(){},
|
||||
checkSizeOfInserted: function(){},
|
||||
checkNodeLimit: function(){},
|
||||
explore: function(){},
|
||||
changeTo: function(){},
|
||||
getPrioList: function(){}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
spyOn(window, "AbstractAdapter").andCallFake(function(nodes, edges, descendant, config) {
|
||||
mockedAbstract.nodes = nodes;
|
||||
mockedAbstract.edges = edges;
|
||||
return mockedAbstract;
|
||||
});
|
||||
});
|
||||
|
||||
it('should create the AbstractAdapter with correct values', function() {
|
||||
testee = constructor();
|
||||
expect(window.AbstractAdapter).wasCalledWith(
|
||||
[],
|
||||
[],
|
||||
testee,
|
||||
{prioList: ["foo", "bar", "baz"]}
|
||||
);
|
||||
});
|
||||
|
||||
it('should call getPrioList on the abstract', function() {
|
||||
spyOn(mockedAbstract, "getPrioList");
|
||||
testee = constructor();
|
||||
testee.getPrioList();
|
||||
expect(mockedAbstract.getPrioList).wasCalled();
|
||||
});
|
||||
|
||||
it('should call setNodeLimit on the abstract', function() {
|
||||
spyOn(mockedAbstract, "setNodeLimit");
|
||||
testee = constructor();
|
||||
testee.setNodeLimit(5, function(){});
|
||||
expect(mockedAbstract.setNodeLimit).wasCalledWith(5, jasmine.any(Function));
|
||||
});
|
||||
|
||||
it('should propagate changeTo to the abstract', function() {
|
||||
spyOn(mockedAbstract, "changeTo");
|
||||
testee = constructor();
|
||||
testee.changeTo({prioList: ["foo", "bar", "baz"]});
|
||||
expect(mockedAbstract.changeTo).wasCalledWith({prioList: ["foo", "bar", "baz"]});
|
||||
});
|
||||
|
||||
it('should call explore on the abstract', function() {
|
||||
spyOn(mockedAbstract, "explore");
|
||||
testee = constructor();
|
||||
var node = {
|
||||
_id: "1"
|
||||
};
|
||||
testee.explore(node, function(){});
|
||||
expect(mockedAbstract.explore).wasCalledWith(node, jasmine.any(Function));
|
||||
});
|
||||
|
||||
it('should call setChildLimit on the abstract', function() {
|
||||
spyOn(mockedAbstract, "setChildLimit");
|
||||
testee = constructor();
|
||||
testee.setChildLimit(5);
|
||||
expect(mockedAbstract.setChildLimit).wasCalledWith(5);
|
||||
});
|
||||
|
||||
it('should call expandCommunity on the abstract', function() {
|
||||
spyOn(mockedAbstract, "expandCommunity");
|
||||
var comm = {};
|
||||
testee = constructor();
|
||||
testee.expandCommunity(comm);
|
||||
expect(mockedAbstract.expandCommunity).wasCalledWith(comm);
|
||||
});
|
||||
|
||||
it('should use the abstract to insert objects from loadNode', function() {
|
||||
spyOn(mockedAbstract, "insertNode").andCallThrough();
|
||||
spyOn(mockedAbstract, "insertEdge").andCallThrough();
|
||||
spyOn(mockedAbstract, "checkSizeOfInserted");
|
||||
spyOn(mockedAbstract, "checkNodeLimit");
|
||||
testee = constructor();
|
||||
testee.loadNode(1);
|
||||
expect(mockedAbstract.insertNode).wasCalledWith({_id: 1});
|
||||
expect(mockedAbstract.insertNode).wasCalledWith({_id: 2});
|
||||
expect(mockedAbstract.insertEdge).wasCalledWith({_id: "1-2", _from: 1, _to: 2});
|
||||
expect(mockedAbstract.checkSizeOfInserted).wasCalledWith({2: mockedAbstract.nodes[1]});
|
||||
expect(mockedAbstract.checkNodeLimit).wasCalledWith(mockedAbstract.nodes[0]);
|
||||
});
|
||||
|
||||
it('should insert an edge on createEdge', function() {
|
||||
spyOn(mockedAbstract, "insertEdge");
|
||||
testee = constructor();
|
||||
testee.createEdge({source: {_id: 1}, target: {_id: 2}}, function(){});
|
||||
expect(mockedAbstract.insertEdge).wasCalledWith({_id: "1-2", _from: 1, _to: 2});
|
||||
});
|
||||
|
||||
it('should remove an edge on deleteEdge', function() {
|
||||
spyOn(mockedAbstract, "removeEdge");
|
||||
testee = constructor();
|
||||
var edge = {_id: "1-2", _from: 1, _to: 2};
|
||||
testee.deleteEdge(edge);
|
||||
expect(mockedAbstract.removeEdge).wasCalledWith(edge);
|
||||
});
|
||||
|
||||
it('should insert a node on createNode', function() {
|
||||
spyOn(mockedAbstract, "insertNode");
|
||||
testee = constructor();
|
||||
testee.createNode({}, function(){});
|
||||
expect(mockedAbstract.insertNode).wasCalledWith({_id: 1});
|
||||
});
|
||||
|
||||
it('should remove a node on deleteNode', function() {
|
||||
spyOn(mockedAbstract, "removeNode");
|
||||
spyOn(mockedAbstract, "removeEdgesForNode");
|
||||
testee = constructor();
|
||||
var node = {_id: 1};
|
||||
testee.deleteNode(node);
|
||||
expect(mockedAbstract.removeEdgesForNode).wasCalledWith(node);
|
||||
expect(mockedAbstract.removeNode).wasCalledWith(node);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
}());
|
||||
|
|
|
@ -326,8 +326,7 @@
|
|||
});
|
||||
|
||||
it('should be able to remove the cursor-following edge on demand', function() {
|
||||
var line,
|
||||
cursorX,
|
||||
var cursorX,
|
||||
cursorY,
|
||||
nodeX = 15,
|
||||
nodeY = 20,
|
||||
|
|
|
@ -207,18 +207,6 @@
|
|||
expect(function() {
|
||||
var e = new EventDispatcherControls();
|
||||
}).toThrow("A list element has to be given.");
|
||||
/* Archive
|
||||
expect(function() {
|
||||
var e = new EventDispatcherControls(list);
|
||||
}).toThrow("The cursor decoration box has to be given.");
|
||||
|
||||
expect(function() {
|
||||
var e = new EventDispatcherControls(list, mousePointerbox);
|
||||
}).toThrow("The NodeShaper has to be given.");
|
||||
expect(function() {
|
||||
var e = new EventDispatcherControls(list, mousePointerbox, nodeShaper);
|
||||
}).toThrow("The EdgeShaper has to be given.");
|
||||
*/
|
||||
|
||||
expect(function() {
|
||||
var e = new EventDispatcherControls(list);
|
||||
|
@ -377,7 +365,6 @@
|
|||
it('should be possible to add new attributes to nodes', function() {
|
||||
|
||||
runs(function() {
|
||||
var nested = JSON.stringify(edges[0]._data.nested);
|
||||
helper.simulateMouseEvent("click", id);
|
||||
helper.simulateMouseEvent("click", "1");
|
||||
|
||||
|
@ -691,10 +678,6 @@
|
|||
});
|
||||
|
||||
it('should draw a line from startNode following the cursor', function() {
|
||||
var line,
|
||||
cursorX,
|
||||
cursorY;
|
||||
|
||||
spyOn(edgeShaper, "addAnEdgeFollowingTheCursor");
|
||||
|
||||
dispatcherUI.addControlConnect();
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
describe('Expand', function() {
|
||||
|
||||
var
|
||||
dummy = {},
|
||||
config,
|
||||
testee;
|
||||
|
||||
|
@ -213,20 +212,21 @@
|
|||
callbackCheck = function() {
|
||||
called = true;
|
||||
},
|
||||
nodeEditorConfig = {
|
||||
nodes: nodes,
|
||||
adapter: adapterDummy,
|
||||
shaper: nodeShaperDummy
|
||||
},
|
||||
testee;
|
||||
|
||||
adapterDummy.createNode = function(nodeToCreate, callback) {
|
||||
created = nodeToCreate;
|
||||
nodes.push(created);
|
||||
callback(created);
|
||||
};
|
||||
|
||||
runs(function() {
|
||||
adapterDummy.createNode = function(nodeToCreate, callback) {
|
||||
created = nodeToCreate;
|
||||
nodes.push(created);
|
||||
callback(created);
|
||||
};
|
||||
|
||||
var nodeEditorConfig = {
|
||||
nodes: nodes,
|
||||
adapter: adapterDummy,
|
||||
shaper: nodeShaperDummy
|
||||
};
|
||||
|
||||
testee = eventLib.InsertNode(nodeEditorConfig);
|
||||
testee(callbackCheck);
|
||||
});
|
||||
|
|
|
@ -408,15 +408,9 @@
|
|||
|
||||
tmp = new ForceLayouter(config);
|
||||
|
||||
/*
|
||||
expect(mock.size).wasCalledWith([940, 640]);
|
||||
expect(mock.linkDistance).wasCalledWith(240);
|
||||
expect(mock.gravity).wasCalledWith(0.08);
|
||||
expect(mock.charge).wasCalledWith(-240);
|
||||
*/
|
||||
expect(mock.size).wasCalledWith([880, 680]);
|
||||
expect(mock.linkDistance).wasCalledWith(jasmine.any(Function));
|
||||
expect(mock.gravity).wasCalledWith(0.08);
|
||||
expect(mock.gravity).wasCalledWith(0.01);
|
||||
expect(mock.charge).wasCalledWith(jasmine.any(Function));
|
||||
|
||||
expect(fd({
|
||||
|
|
|
@ -37,10 +37,9 @@
|
|||
|
||||
describe("Graph Viewer", function() {
|
||||
"use strict";
|
||||
var viewer,
|
||||
waittime = 500,
|
||||
svg,
|
||||
docSVG;
|
||||
var waittime = 500,
|
||||
svg,
|
||||
docSVG;
|
||||
|
||||
beforeEach(function() {
|
||||
docSVG = document.createElement("svg");
|
||||
|
@ -305,4 +304,4 @@ describe("Graph Viewer", function() {
|
|||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
|
@ -124,7 +124,7 @@
|
|||
|
||||
it('should automatically start the ZoomManager', function() {
|
||||
expect(window.ZoomManager).toHaveBeenCalledWith(
|
||||
140,
|
||||
119,
|
||||
200,
|
||||
jasmine.any(Object),
|
||||
jasmine.any(Object),
|
||||
|
@ -310,21 +310,8 @@
|
|||
expect(map.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should be positioned in the top-right corner of the svg', function() {
|
||||
expect(map.css("position")).toEqual("absolute");
|
||||
var leftPos = $("#contentDiv svg").position().left,
|
||||
topPos = $("#contentDiv svg").position().top;
|
||||
leftPos += $("#contentDiv svg").width();
|
||||
if (leftPos === Math.round(leftPos)) {
|
||||
expect(map.css("left")).toEqual(leftPos + "px");
|
||||
} else {
|
||||
expect(map.css("left")).toEqual(leftPos.toFixed(1) + "px");
|
||||
}
|
||||
if (topPos === Math.round(topPos)) {
|
||||
expect(map.css("top")).toEqual(topPos + "px");
|
||||
} else {
|
||||
expect(map.css("top")).toEqual(topPos.toFixed(1) + "px");
|
||||
}
|
||||
it('should have the correct css class', function() {
|
||||
expect(map).toBeOfClass("gv_colour_list");
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -91,10 +91,10 @@
|
|||
|
||||
it('should throw errors if not setup correctly', function() {
|
||||
expect(function() {
|
||||
var e = new NodeShaperControls();
|
||||
var c = new NodeShaperControls();
|
||||
}).toThrow("A list element has to be given.");
|
||||
expect(function() {
|
||||
var e = new NodeShaperControls(list);
|
||||
var c = new NodeShaperControls(list);
|
||||
}).toThrow("The NodeShaper has to be given.");
|
||||
});
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@
|
|||
|
||||
it('should throw an error if no callback is given', function() {
|
||||
expect(function() {
|
||||
function Test(){}
|
||||
var s = new WebWorkerWrapper(Test);
|
||||
var Test = function() {},
|
||||
s = new WebWorkerWrapper(Test);
|
||||
}).toThrow("A callback has to be given.");
|
||||
});
|
||||
|
||||
|
@ -303,4 +303,4 @@
|
|||
});
|
||||
});
|
||||
|
||||
}());
|
||||
}());
|
||||
|
|
|
@ -37,8 +37,7 @@ function ArangoAdapterControls(list, adapter) {
|
|||
if (adapter === undefined) {
|
||||
throw "The ArangoAdapter has to be given.";
|
||||
}
|
||||
var self = this,
|
||||
baseClass = "adapter";
|
||||
var baseClass = "adapter";
|
||||
|
||||
this.addControlChangeCollections = function(callback) {
|
||||
var prefix = "control_adapter_collections",
|
||||
|
|
|
@ -43,8 +43,7 @@ function GraphViewerUI(container, adapterConfig, optWidth, optHeight, viewerConf
|
|||
throw "An adapter configuration has to be given";
|
||||
}
|
||||
|
||||
var self = this,
|
||||
graphViewer,
|
||||
var graphViewer,
|
||||
width = (optWidth || container.offsetWidth) - 81,
|
||||
height = optHeight || container.offsetHeight,
|
||||
menubar = document.createElement("ul"),
|
||||
|
@ -76,6 +75,110 @@ function GraphViewerUI(container, adapterConfig, optWidth, optHeight, viewerConf
|
|||
return list;
|
||||
},
|
||||
|
||||
makeFilterDiv = function() {
|
||||
var
|
||||
div = document.createElement("div"),
|
||||
innerDiv = document.createElement("div"),
|
||||
queryLine = document.createElement("div"),
|
||||
searchAttrDiv = document.createElement("div"),
|
||||
searchAttrExampleToggle = document.createElement("button"),
|
||||
searchAttrExampleCaret = document.createElement("span"),
|
||||
searchValueField = document.createElement("input"),
|
||||
searchStart = document.createElement("img"),
|
||||
equalsField = document.createElement("span"),
|
||||
|
||||
showSpinner = function() {
|
||||
$(background).css("cursor", "progress");
|
||||
},
|
||||
|
||||
hideSpinner = function() {
|
||||
$(background).css("cursor", "");
|
||||
},
|
||||
|
||||
alertError = function(msg) {
|
||||
window.alert(msg);
|
||||
},
|
||||
|
||||
resultCB = function(res) {
|
||||
hideSpinner();
|
||||
if (res && res.errorCode && res.errorCode === 404) {
|
||||
alertError("Sorry could not find a matching node.");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
searchFunction = function() {
|
||||
showSpinner();
|
||||
if (searchAttrField.value === ""
|
||||
|| searchAttrField.value === undefined) {
|
||||
graphViewer.loadGraph(
|
||||
searchValueField.value,
|
||||
resultCB
|
||||
);
|
||||
} else {
|
||||
graphViewer.loadGraphWithAttributeValue(
|
||||
searchAttrField.value,
|
||||
searchValueField.value,
|
||||
resultCB
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
div.id = "filterDropdown";
|
||||
div.className = "headerDropdown";
|
||||
innerDiv.className = "dropdownInner";
|
||||
queryLine.className = "queryline";
|
||||
|
||||
searchAttrField = document.createElement("input");
|
||||
searchAttrExampleList = document.createElement("ul");
|
||||
|
||||
searchAttrDiv.className = "pull-left input-append searchByAttribute";
|
||||
searchAttrField.id = "attribute";
|
||||
//searchAttrField.className = "input";
|
||||
searchAttrField.type = "text";
|
||||
searchAttrField.placeholder = "Attribute name";
|
||||
searchAttrExampleToggle.id = "attribute_example_toggle";
|
||||
searchAttrExampleToggle.className = "btn gv_example_toggle";
|
||||
searchAttrExampleCaret.className = "caret gv_caret";
|
||||
searchAttrExampleList.className = "dropdown-menu";
|
||||
searchValueField.id = "value";
|
||||
searchValueField.className = "gv_searchInput";
|
||||
//searchValueField.className = "filterValue";
|
||||
searchValueField.type = "text";
|
||||
searchValueField.placeholder = "Attribute value";
|
||||
searchStart.id = "loadnode";
|
||||
searchStart.className = "searchSubmit";
|
||||
equalsField.className = "searchEqualsLabel";
|
||||
equalsField.appendChild(document.createTextNode("=="));
|
||||
|
||||
innerDiv.appendChild(queryLine);
|
||||
queryLine.appendChild(searchAttrDiv);
|
||||
|
||||
searchAttrDiv.appendChild(searchAttrField);
|
||||
searchAttrDiv.appendChild(searchAttrExampleToggle);
|
||||
searchAttrDiv.appendChild(searchAttrExampleList);
|
||||
searchAttrExampleToggle.appendChild(searchAttrExampleCaret);
|
||||
queryLine.appendChild(equalsField);
|
||||
queryLine.appendChild(searchValueField);
|
||||
queryLine.appendChild(searchStart);
|
||||
|
||||
searchStart.onclick = searchFunction;
|
||||
$(searchValueField).keypress(function(e) {
|
||||
if (e.keyCode === 13 || e.which === 13) {
|
||||
searchFunction();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
searchAttrExampleToggle.onclick = function() {
|
||||
$(searchAttrExampleList).slideToggle(200);
|
||||
};
|
||||
|
||||
div.appendChild(innerDiv);
|
||||
return div;
|
||||
},
|
||||
|
||||
makeConfigureDiv = function () {
|
||||
var div, innerDiv, nodeList, nodeHeader, colList, colHeader;
|
||||
div = document.createElement("div");
|
||||
|
@ -97,39 +200,54 @@ function GraphViewerUI(container, adapterConfig, optWidth, optHeight, viewerConf
|
|||
innerDiv.appendChild(colList);
|
||||
div.appendChild(innerDiv);
|
||||
return {
|
||||
el: div,
|
||||
configure: div,
|
||||
nodes: nodeList,
|
||||
col: colList
|
||||
};
|
||||
},
|
||||
|
||||
makeConfigure = function (div, id) {
|
||||
var ul, li, a, span, lists;
|
||||
makeConfigure = function (div, idConf, idFilter) {
|
||||
var ul, liConf, aConf, spanConf, liFilter, aFilter, spanFilter, lists;
|
||||
div.className = "pagination pagination-small pagination-right btn-group";
|
||||
ul = document.createElement("ul");
|
||||
li = document.createElement("li");
|
||||
li.className = "enabled";
|
||||
a = document.createElement("a");
|
||||
a.id = id;
|
||||
a.className = "arangoHeaderA";
|
||||
span = document.createElement("span");
|
||||
span.className = "glyphicon glyphicon-cog";
|
||||
$(span).attr("data-original-title", "Configure");
|
||||
liConf = document.createElement("li");
|
||||
liConf.className = "enabled";
|
||||
aConf = document.createElement("a");
|
||||
aConf.id = idConf;
|
||||
aConf.className = "arangoHeaderA";
|
||||
spanConf = document.createElement("span");
|
||||
spanConf.className = "glyphicon glyphicon-cog";
|
||||
$(spanConf).attr("data-original-title", "Configure");
|
||||
|
||||
liFilter = document.createElement("li");
|
||||
liFilter.className = "enabled";
|
||||
aFilter = document.createElement("a");
|
||||
aFilter.id = idFilter;
|
||||
aFilter.className = "arangoHeaderA";
|
||||
spanFilter = document.createElement("span");
|
||||
spanFilter.className = "glyphicon glyphicon-filter";
|
||||
$(spanFilter).attr("data-original-title", "Filter");
|
||||
|
||||
div.appendChild(ul);
|
||||
ul.appendChild(li);
|
||||
li.appendChild(a);
|
||||
a.appendChild(span);
|
||||
|
||||
/*
|
||||
list = document.createElement("ul");
|
||||
list.className = "dropdown-menu gv_configure_menu";
|
||||
list.style.display = "none";
|
||||
div.appendChild(list);
|
||||
*/
|
||||
ul.appendChild(liConf);
|
||||
liConf.appendChild(aConf);
|
||||
aConf.appendChild(spanConf);
|
||||
|
||||
ul.appendChild(liFilter);
|
||||
liFilter.appendChild(aFilter);
|
||||
aFilter.appendChild(spanFilter);
|
||||
|
||||
lists = makeConfigureDiv();
|
||||
a.onclick = function () {
|
||||
$(lists.el).slideToggle(200);
|
||||
lists.filter = makeFilterDiv();
|
||||
aConf.onclick = function () {
|
||||
$(lists.configure).slideToggle(200);
|
||||
$(lists.filter).hide();
|
||||
};
|
||||
|
||||
aFilter.onclick = function () {
|
||||
$(lists.filter).slideToggle(200);
|
||||
$(lists.configure).hide();
|
||||
};
|
||||
|
||||
return lists;
|
||||
|
@ -235,6 +353,7 @@ function GraphViewerUI(container, adapterConfig, optWidth, optHeight, viewerConf
|
|||
searchAttrExampleList.appendChild(entry);
|
||||
entry.onclick = function() {
|
||||
searchAttrField.value = r;
|
||||
$(searchAttrExampleList).slideToggle(200);
|
||||
};
|
||||
});
|
||||
});
|
||||
|
@ -242,19 +361,13 @@ function GraphViewerUI(container, adapterConfig, optWidth, optHeight, viewerConf
|
|||
|
||||
createMenu = function() {
|
||||
var transparentHeader = document.createElement("div"),
|
||||
searchDiv = document.createElement("div"),
|
||||
searchAttrDiv = document.createElement("div"),
|
||||
searchAttrExampleToggle = document.createElement("button"),
|
||||
searchAttrExampleCaret = document.createElement("span"),
|
||||
searchValueField = document.createElement("input"),
|
||||
searchStart = document.createElement("img"),
|
||||
buttons = document.createElement("div"),
|
||||
equalsField = document.createElement("span"),
|
||||
configureDropDown = document.createElement("div"),
|
||||
configureLists = makeConfigure(
|
||||
configureDropDown,
|
||||
"configuredropdown"
|
||||
),
|
||||
"configuredropdown",
|
||||
"filterdropdown"
|
||||
);
|
||||
|
||||
/*
|
||||
nodeShaperDropDown = document.createElement("div"),
|
||||
|
@ -299,43 +412,7 @@ function GraphViewerUI(container, adapterConfig, optWidth, optHeight, viewerConf
|
|||
),
|
||||
*/
|
||||
|
||||
showSpinner = function() {
|
||||
$(background).css("cursor", "progress");
|
||||
},
|
||||
|
||||
hideSpinner = function() {
|
||||
$(background).css("cursor", "");
|
||||
},
|
||||
|
||||
alertError = function(msg) {
|
||||
window.alert(msg);
|
||||
},
|
||||
|
||||
resultCB = function(res) {
|
||||
hideSpinner();
|
||||
if (res && res.errorCode && res.errorCode === 404) {
|
||||
alertError("Sorry could not find a matching node.");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
searchFunction = function() {
|
||||
showSpinner();
|
||||
if (searchAttrField.value === ""
|
||||
|| searchAttrField.value === undefined) {
|
||||
graphViewer.loadGraph(
|
||||
searchValueField.value,
|
||||
resultCB
|
||||
);
|
||||
} else {
|
||||
graphViewer.loadGraphWithAttributeValue(
|
||||
searchAttrField.value,
|
||||
searchValueField.value,
|
||||
resultCB
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
nodeShaperUI = new NodeShaperControls(
|
||||
configureLists.nodes,
|
||||
|
@ -346,9 +423,6 @@ function GraphViewerUI(container, adapterConfig, optWidth, optHeight, viewerConf
|
|||
graphViewer.adapter
|
||||
);
|
||||
|
||||
searchAttrField = document.createElement("input");
|
||||
searchAttrExampleList = document.createElement("ul");
|
||||
|
||||
menubar.id = "menubar";
|
||||
menubar.className = "thumbnails2";
|
||||
|
||||
|
@ -357,27 +431,6 @@ function GraphViewerUI(container, adapterConfig, optWidth, optHeight, viewerConf
|
|||
buttons.id = "modifiers";
|
||||
buttons.className = "pull-right";
|
||||
|
||||
searchDiv.id = "transparentPlaceholder";
|
||||
searchDiv.className = "pull-left";
|
||||
|
||||
searchAttrDiv.className = "pull-left input-append searchByAttribute";
|
||||
searchAttrField.id = "attribute";
|
||||
searchAttrField.className = "input";
|
||||
searchAttrField.type = "text";
|
||||
searchAttrField.placeholder = "Attribute";
|
||||
searchAttrExampleToggle.id = "attribute_example_toggle";
|
||||
searchAttrExampleToggle.className = "btn gv_example_toggle";
|
||||
searchAttrExampleToggle.setAttribute("data-toggle", "dropdown");
|
||||
searchAttrExampleCaret.className = "caret gv_caret";
|
||||
searchAttrExampleList.className = "dropdown-menu";
|
||||
searchValueField.id = "value";
|
||||
searchValueField.className = "input-xlarge searchInput";
|
||||
searchValueField.type = "text";
|
||||
searchValueField.placeholder = "Value";
|
||||
searchStart.id = "loadnode";
|
||||
searchStart.className = "searchSubmit";
|
||||
equalsField.className = "searchEqualsLabel";
|
||||
equalsField.appendChild(document.createTextNode("=="));
|
||||
|
||||
/*
|
||||
nodeShaperDropDown.id = "nodeshapermenu";
|
||||
|
@ -388,26 +441,9 @@ function GraphViewerUI(container, adapterConfig, optWidth, optHeight, viewerConf
|
|||
configureDropDown.id = "configuremenu";
|
||||
|
||||
|
||||
searchStart.onclick = searchFunction;
|
||||
$(searchValueField).keypress(function(e) {
|
||||
if (e.keyCode === 13 || e.which === 13) {
|
||||
searchFunction();
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
menubar.appendChild(transparentHeader);
|
||||
menubar.appendChild(configureLists.el);
|
||||
transparentHeader.appendChild(searchDiv);
|
||||
searchDiv.appendChild(searchAttrDiv);
|
||||
searchAttrDiv.appendChild(searchAttrField);
|
||||
searchAttrDiv.appendChild(searchAttrExampleToggle);
|
||||
searchAttrDiv.appendChild(searchAttrExampleList);
|
||||
searchAttrExampleToggle.appendChild(searchAttrExampleCaret);
|
||||
searchDiv.appendChild(equalsField);
|
||||
searchDiv.appendChild(searchValueField);
|
||||
searchDiv.appendChild(searchStart);
|
||||
menubar.appendChild(configureLists.configure);
|
||||
menubar.appendChild(configureLists.filter);
|
||||
transparentHeader.appendChild(buttons);
|
||||
|
||||
buttons.appendChild(configureDropDown);
|
||||
|
@ -436,15 +472,6 @@ function GraphViewerUI(container, adapterConfig, optWidth, optHeight, viewerConf
|
|||
createColourList = function() {
|
||||
colourList = nodeShaperUI.createColourMappingList();
|
||||
colourList.className = "gv_colour_list";
|
||||
/*
|
||||
colourList.style.position = "absolute";
|
||||
var intSVG = $("#graphViewerSVG");
|
||||
colourList.style.top = intSVG.position().top.toFixed(1) + "px";
|
||||
colourList.style.left = (intSVG.position().left + intSVG.width()).toFixed(1) + "px";
|
||||
colourList.style.height = intSVG.height() + "px";
|
||||
colourList.style.overflow = "auto";
|
||||
container.appendChild(colourList);
|
||||
*/
|
||||
background.insertBefore(colourList, svg[0][0]);
|
||||
};
|
||||
container.appendChild(menubar);
|
||||
|
|
|
@ -211,7 +211,6 @@
|
|||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
window.arangoLogsStore.fetch({
|
||||
success: function () {
|
||||
window.logsView.render();
|
||||
|
|
|
@ -193,7 +193,6 @@
|
|||
var cssClass = 'collectionInfoTh modal-text';
|
||||
if (this.index) {
|
||||
var fieldString = '';
|
||||
var indexId = '';
|
||||
$.each(this.index.indexes, function(k,v) {
|
||||
if (v.fields !== undefined) {
|
||||
fieldString = v.fields.join(", ");
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
template: templateEngine.createTemplate("collectionView.ejs"),
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
$(this.el).html(this.template.text);
|
||||
$('#change-collection').modal('show');
|
||||
$('#change-collection').on('hidden', function () {
|
||||
|
|
|
@ -1,165 +1,168 @@
|
|||
/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true */
|
||||
/*jslint indent: 2, nomen: true, maxlen: 100, vars: true, white: true, plusplus: true */
|
||||
/*global window, document, Backbone, EJS, SwaggerUi, hljs, $, arangoHelper, templateEngine */
|
||||
(function() {
|
||||
|
||||
window.databaseView = Backbone.View.extend({
|
||||
el: '#content',
|
||||
"use strict";
|
||||
|
||||
template: templateEngine.createTemplate("databaseView.ejs"),
|
||||
window.databaseView = Backbone.View.extend({
|
||||
el: '#content',
|
||||
|
||||
currentDB: "",
|
||||
template: templateEngine.createTemplate("databaseView.ejs"),
|
||||
|
||||
events: {
|
||||
"click #createDatabase" : "createDatabase",
|
||||
"click #submitCreateDatabase" : "submitCreateDatabase",
|
||||
"click #selectDatabase" : "updateDatabase",
|
||||
"click #databaseTable .glyphicon-minus-sign" : "removeDatabase",
|
||||
"click #submitDeleteDatabase" : "submitRemoveDatabase",
|
||||
"click .databaseInactive a" : "changeDatabase"
|
||||
},
|
||||
currentDB: "",
|
||||
|
||||
initialize: function() {
|
||||
var self = this;
|
||||
this.collection.fetch({async:false});
|
||||
},
|
||||
events: {
|
||||
"click #createDatabase" : "createDatabase",
|
||||
"click #submitCreateDatabase" : "submitCreateDatabase",
|
||||
"click #selectDatabase" : "updateDatabase",
|
||||
"click #databaseTable .glyphicon-minus-sign" : "removeDatabase",
|
||||
"click #submitDeleteDatabase" : "submitRemoveDatabase",
|
||||
"click .databaseInactive a" : "changeDatabase"
|
||||
},
|
||||
|
||||
render: function(){
|
||||
this.currentDatabase();
|
||||
$(this.el).html(this.template.render({}));
|
||||
this.renderTable();
|
||||
this.selectCurrentDatabase();
|
||||
return this;
|
||||
},
|
||||
initialize: function() {
|
||||
this.collection.fetch({async:false});
|
||||
},
|
||||
|
||||
renderTable: function () {
|
||||
this.collection.map(function(dbs) {
|
||||
$("#databaseTable tbody").append(
|
||||
'<tr><td><a>' + dbs.get("name") + '</a></td>' +
|
||||
'<td><span class="glyphicon glyphicon-minus-sign"' +
|
||||
'data-original-title="Delete database"></span></td></tr>'
|
||||
);
|
||||
});
|
||||
},
|
||||
render: function(){
|
||||
this.currentDatabase();
|
||||
$(this.el).html(this.template.render({}));
|
||||
this.renderTable();
|
||||
this.selectCurrentDatabase();
|
||||
return this;
|
||||
},
|
||||
|
||||
selectedDatabase: function () {
|
||||
return $('#selectDatabases').val();
|
||||
},
|
||||
renderTable: function () {
|
||||
this.collection.map(function(dbs) {
|
||||
$("#databaseTable tbody").append(
|
||||
'<tr><td><a>' + dbs.get("name") + '</a></td>' +
|
||||
'<td><span class="glyphicon glyphicon-minus-sign"' +
|
||||
'data-original-title="Delete database"></span></td></tr>'
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
handleError: function(status, text, dbname) {
|
||||
if (status === 409) {
|
||||
arangoHelper.arangoError("Database " + dbname + " already exists.");
|
||||
return;
|
||||
}
|
||||
if (status === 400) {
|
||||
arangoHelper.arangoError("Invalid Parameters");
|
||||
return;
|
||||
}
|
||||
if (status === 403) {
|
||||
arangoHelper.arangoError("Insufficent rights. Execute this from _system database");
|
||||
return;
|
||||
}
|
||||
},
|
||||
selectedDatabase: function () {
|
||||
return $('#selectDatabases').val();
|
||||
},
|
||||
|
||||
validateDatabaseInfo: function (db, user, pw) {
|
||||
if (user === "") {
|
||||
arangoHelper.arangoError("You have to define an owner for the new database");
|
||||
return false;
|
||||
}
|
||||
if (db === "") {
|
||||
arangoHelper.arangoError("You have to define a name for the new database");
|
||||
return false;
|
||||
}
|
||||
if (db.indexOf("_") === 0) {
|
||||
arangoHelper.arangoError("Databasename should not start with _");
|
||||
return false;
|
||||
}
|
||||
if (!db.match(/^[a-zA-Z][a-zA-Z0-9_\-]*$/)) {
|
||||
arangoHelper.arangoError("Databasename may only contain numbers, letters, _ and -");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
handleError: function(status, text, dbname) {
|
||||
if (status === 409) {
|
||||
arangoHelper.arangoError("Database " + dbname + " already exists.");
|
||||
return;
|
||||
}
|
||||
if (status === 400) {
|
||||
arangoHelper.arangoError("Invalid Parameters");
|
||||
return;
|
||||
}
|
||||
if (status === 403) {
|
||||
arangoHelper.arangoError("Insufficent rights. Execute this from _system database");
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
submitCreateDatabase: function() {
|
||||
var self = this;
|
||||
var name = $('#newDatabaseName').val();
|
||||
var userName = $('#newUser').val();
|
||||
var userPassword = $('#newPassword').val();
|
||||
if (!this.validateDatabaseInfo(name, userName, userPassword)) {
|
||||
return;
|
||||
}
|
||||
var options = {
|
||||
name: name,
|
||||
users: [
|
||||
{
|
||||
username: userName,
|
||||
passwd: userPassword,
|
||||
active: true
|
||||
validateDatabaseInfo: function (db, user, pw) {
|
||||
if (user === "") {
|
||||
arangoHelper.arangoError("You have to define an owner for the new database");
|
||||
return false;
|
||||
}
|
||||
if (db === "") {
|
||||
arangoHelper.arangoError("You have to define a name for the new database");
|
||||
return false;
|
||||
}
|
||||
if (db.indexOf("_") === 0) {
|
||||
arangoHelper.arangoError("Databasename should not start with _");
|
||||
return false;
|
||||
}
|
||||
if (!db.match(/^[a-zA-Z][a-zA-Z0-9_\-]*$/)) {
|
||||
arangoHelper.arangoError("Databasename may only contain numbers, letters, _ and -");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
submitCreateDatabase: function() {
|
||||
var self = this;
|
||||
var name = $('#newDatabaseName').val();
|
||||
var userName = $('#newUser').val();
|
||||
var userPassword = $('#newPassword').val();
|
||||
if (!this.validateDatabaseInfo(name, userName, userPassword)) {
|
||||
return;
|
||||
}
|
||||
var options = {
|
||||
name: name,
|
||||
users: [
|
||||
{
|
||||
username: userName,
|
||||
passwd: userPassword,
|
||||
active: true
|
||||
}
|
||||
]
|
||||
};
|
||||
this.collection.create(options, {
|
||||
wait:true,
|
||||
error: function(data, err) {
|
||||
self.handleError(err.status, err.statusText, name);
|
||||
},
|
||||
success: function(data) {
|
||||
arangoHelper.arangoNotification("Database " + name + " created.");
|
||||
self.hideModal();
|
||||
self.updateDatabases();
|
||||
}
|
||||
]
|
||||
};
|
||||
this.collection.create(options, {
|
||||
wait:true,
|
||||
error: function(data, err) {
|
||||
self.handleError(err.status, err.statusText, name);
|
||||
},
|
||||
success: function(data) {
|
||||
arangoHelper.arangoNotification("Database " + name + " created.");
|
||||
self.hideModal();
|
||||
self.updateDatabases();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
hideModal: function() {
|
||||
$('#createDatabaseModal').modal('hide');
|
||||
},
|
||||
hideModal: function() {
|
||||
$('#createDatabaseModal').modal('hide');
|
||||
},
|
||||
|
||||
showModal: function() {
|
||||
$('#createDatabaseModal').modal('show');
|
||||
},
|
||||
showModal: function() {
|
||||
$('#createDatabaseModal').modal('show');
|
||||
},
|
||||
|
||||
createDatabase: function() {
|
||||
this.showModal();
|
||||
},
|
||||
createDatabase: function() {
|
||||
this.showModal();
|
||||
},
|
||||
|
||||
submitRemoveDatabase: function(e) {
|
||||
var toDelete = this.collection.where({name: this.dbToDelete});
|
||||
toDelete[0].destroy({wait: true, url:"/_api/database/"+this.dbToDelete});
|
||||
arangoHelper.arangoNotification("Database " + this.dbToDelete + " deleted.");
|
||||
this.dbToDelete = '';
|
||||
$('#deleteDatabaseModal').modal('hide');
|
||||
this.updateDatabases();
|
||||
},
|
||||
submitRemoveDatabase: function(e) {
|
||||
var toDelete = this.collection.where({name: this.dbToDelete});
|
||||
toDelete[0].destroy({wait: true, url:"/_api/database/"+this.dbToDelete});
|
||||
arangoHelper.arangoNotification("Database " + this.dbToDelete + " deleted.");
|
||||
this.dbToDelete = '';
|
||||
$('#deleteDatabaseModal').modal('hide');
|
||||
this.updateDatabases();
|
||||
},
|
||||
|
||||
removeDatabase: function(e) {
|
||||
this.dbToDelete = $(e.currentTarget).parent().parent().children().first().text();
|
||||
$('#deleteDatabaseModal').modal('show');
|
||||
},
|
||||
removeDatabase: function(e) {
|
||||
this.dbToDelete = $(e.currentTarget).parent().parent().children().first().text();
|
||||
$('#deleteDatabaseModal').modal('show');
|
||||
},
|
||||
|
||||
currentDatabase: function() {
|
||||
this.currentDB = this.collection.getCurrentDatabase();
|
||||
},
|
||||
currentDatabase: function() {
|
||||
this.currentDB = this.collection.getCurrentDatabase();
|
||||
},
|
||||
|
||||
selectCurrentDatabase: function() {
|
||||
$('#databaseTableBody tr').addClass('databaseInactive');
|
||||
var tr = $('#databaseTableBody td:contains('+this.currentDB+')').parent();
|
||||
$(tr).removeClass('databaseInactive').addClass('databaseActive');
|
||||
},
|
||||
selectCurrentDatabase: function() {
|
||||
$('#databaseTableBody tr').addClass('databaseInactive');
|
||||
var tr = $('#databaseTableBody td:contains('+this.currentDB+')').parent();
|
||||
$(tr).removeClass('databaseInactive').addClass('databaseActive');
|
||||
},
|
||||
|
||||
changeDatabase: function(e) {
|
||||
var changeTo = $("#dbSelectionList > option:selected").attr("id");
|
||||
var url = this.collection.createDatabaseURL(changeTo);
|
||||
window.location.replace(url);
|
||||
},
|
||||
changeDatabase: function(e) {
|
||||
var changeTo = $("#dbSelectionList > option:selected").attr("id");
|
||||
var url = this.collection.createDatabaseURL(changeTo);
|
||||
window.location.replace(url);
|
||||
},
|
||||
|
||||
updateDatabases: function() {
|
||||
var self = this;
|
||||
this.collection.fetch({
|
||||
success: function() {
|
||||
self.render();
|
||||
window.App.handleSelectDatabase();
|
||||
}
|
||||
});
|
||||
}
|
||||
updateDatabases: function() {
|
||||
var self = this;
|
||||
this.collection.fetch({
|
||||
success: function() {
|
||||
self.render();
|
||||
window.App.handleSelectDatabase();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
|
|
@ -264,7 +264,7 @@
|
|||
},
|
||||
|
||||
initTable: function () {
|
||||
var documentTable = $(this.table).dataTable({
|
||||
$(this.table).dataTable({
|
||||
"aaSorting": [[ 1, "asc" ]],
|
||||
"bAutoWidth": false,
|
||||
"bFilter": false,
|
||||
|
@ -332,7 +332,6 @@
|
|||
var self = this;
|
||||
var i = 0;
|
||||
$('.writeable', documentEditTable.fnGetNodes() ).each(function () {
|
||||
var aPos = documentEditTable.fnGetPosition(this);
|
||||
if (i === 1) {
|
||||
$(this).removeClass('writeable');
|
||||
i = 0;
|
||||
|
|
|
@ -486,7 +486,7 @@
|
|||
},
|
||||
|
||||
initTable: function (colid, pageid) {
|
||||
var documentsTable = $('#documentsTableID').dataTable({
|
||||
$('#documentsTableID').dataTable({
|
||||
"aaSorting": [[ 1, "asc" ]],
|
||||
"bFilter": false,
|
||||
"bPaginate":false,
|
||||
|
@ -811,7 +811,6 @@
|
|||
var cssClass = 'collectionInfoTh modal-text';
|
||||
if (this.index) {
|
||||
var fieldString = '';
|
||||
var indexId = '';
|
||||
var actionString = '';
|
||||
|
||||
$.each(this.index.indexes, function(k,v) {
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
|
||||
render: function() {
|
||||
$(this.el).html(this.template.text);
|
||||
var self = this;
|
||||
_.each(this._subViews, function (v) {
|
||||
$("#foxxList").append(v.render());
|
||||
});
|
||||
|
|
|
@ -1,50 +1,51 @@
|
|||
/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true */
|
||||
/*jslint indent: 2, nomen: true, maxlen: 100, vars: true, white: true, plusplus: true */
|
||||
/*global Backbone, EJS, $, window, _, templateEngine*/
|
||||
|
||||
var FoxxInstalledListView = Backbone.View.extend({
|
||||
el: '#content',
|
||||
template: templateEngine.createTemplate("applicationsView.ejs"),
|
||||
|
||||
events: {
|
||||
// 'click button#add': 'callback'
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
this._subViews = {};
|
||||
var self = this;
|
||||
this.collection.fetch({
|
||||
success: function() {
|
||||
_.each(self.collection.where({type: "app"}), function (foxx) {
|
||||
var subView = new window.FoxxInstalledView({model: foxx});
|
||||
self._subViews[foxx.get('_id')] = subView;
|
||||
});
|
||||
self.render();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
reload: function() {
|
||||
var self = this;
|
||||
this.collection.fetch({
|
||||
success: function() {
|
||||
self._subViews = {};
|
||||
_.each(self.collection.where({type: "app"}), function (foxx) {
|
||||
var subView = new window.FoxxInstalledView({model: foxx});
|
||||
self._subViews[foxx.get('_id')] = subView;
|
||||
});
|
||||
self.render();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
render: function() {
|
||||
$(this.el).html(this.template.text);
|
||||
var self = this;
|
||||
_.each(this._subViews, function (v) {
|
||||
$("#foxxList").append(v.render());
|
||||
});
|
||||
this.delegateEvents();
|
||||
return this;
|
||||
}
|
||||
});
|
||||
(function() {
|
||||
"use strict";
|
||||
window.FoxxInstalledListView = Backbone.View.extend({
|
||||
el: '#content',
|
||||
template: templateEngine.createTemplate("applicationsView.ejs"),
|
||||
|
||||
events: {
|
||||
// 'click button#add': 'callback'
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
this._subViews = {};
|
||||
var self = this;
|
||||
this.collection.fetch({
|
||||
success: function() {
|
||||
_.each(self.collection.where({type: "app"}), function (foxx) {
|
||||
var subView = new window.FoxxInstalledView({model: foxx});
|
||||
self._subViews[foxx.get('_id')] = subView;
|
||||
});
|
||||
self.render();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
reload: function() {
|
||||
var self = this;
|
||||
this.collection.fetch({
|
||||
success: function() {
|
||||
self._subViews = {};
|
||||
_.each(self.collection.where({type: "app"}), function (foxx) {
|
||||
var subView = new window.FoxxInstalledView({model: foxx});
|
||||
self._subViews[foxx.get('_id')] = subView;
|
||||
});
|
||||
self.render();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
render: function() {
|
||||
$(this.el).html(this.template.text);
|
||||
_.each(this._subViews, function (v) {
|
||||
$("#foxxList").append(v.render());
|
||||
});
|
||||
this.delegateEvents();
|
||||
return this;
|
||||
}
|
||||
});
|
||||
}());
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
template: templateEngine.createTemplate("graphView.ejs"),
|
||||
|
||||
initialize: function () {
|
||||
var self = this;
|
||||
this.newLineTmpl = templateEngine.createTemplate("graphViewGroupByEntry.ejs");
|
||||
this.graphs = [];
|
||||
this.i = 1;
|
||||
|
@ -66,12 +65,10 @@
|
|||
aaconfig,
|
||||
undirected,
|
||||
randomStart,
|
||||
groupByList,
|
||||
groupByAttribute,
|
||||
label,
|
||||
color,
|
||||
config,
|
||||
ui,
|
||||
sameColor,
|
||||
width,
|
||||
self = this;
|
||||
|
|
|
@ -109,7 +109,6 @@
|
|||
template: templateEngine.createTemplate("logsView.ejs"),
|
||||
|
||||
initLogTables: function () {
|
||||
var self = this;
|
||||
$.each(this.collection.tables, function(key, table) {
|
||||
table = $('#'+table).dataTable({
|
||||
"bFilter": false,
|
||||
|
|
|
@ -266,8 +266,6 @@
|
|||
this.renderSelectboxes();
|
||||
},
|
||||
saveAQL: function (e) {
|
||||
|
||||
var self = this;
|
||||
var inputEditor = ace.edit("aqlEditor");
|
||||
var queryName = $('#new-query-name').val();
|
||||
var content = inputEditor.getValue();
|
||||
|
|
|
@ -62,7 +62,6 @@
|
|||
replShell: function () {
|
||||
// Creating the console.
|
||||
var internal = require("internal");
|
||||
var arangodb = require("org/arangodb");
|
||||
var client = require("org/arangodb/arangosh");
|
||||
var header = 'Welcome to arangosh Copyright (c) triAGENS GmbH.\n';
|
||||
window.jqconsole = $('#replShell').jqconsole(header, 'JSH> ', "...>");
|
||||
|
@ -96,7 +95,7 @@
|
|||
jqconsole.Prompt(true, handler, function(command) {
|
||||
// Continue line if can't compile the command.
|
||||
try {
|
||||
var test = new Function(command);
|
||||
var f = new Function(command);
|
||||
}
|
||||
catch (e) {
|
||||
if (/[\[\{\(]$/.test(command)) {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*global exports, appCollection*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief A TODO-List Foxx-Application written for ArangoDB
|
||||
/// @brief functionality to expose API documentation for Foxx apps
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
|
|
|
@ -37,11 +37,6 @@
|
|||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Threading
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialises a new mutex
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -70,19 +65,10 @@ int TRI_DestroyMutex (TRI_mutex_t* mutex) {
|
|||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Threading
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief locks mutex
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -124,10 +110,6 @@ void TRI_UnlockMutex (TRI_mutex_t* mutex) {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- SPIN
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -136,11 +118,6 @@ void TRI_UnlockMutex (TRI_mutex_t* mutex) {
|
|||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Threading
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialises a new spin
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -157,19 +134,10 @@ void TRI_DestroySpin (TRI_spin_t* spin) {
|
|||
DeleteCriticalSection(spin);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Threading
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief locks spin
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -186,10 +154,6 @@ void TRI_UnlockSpin (TRI_spin_t* spin) {
|
|||
LeaveCriticalSection(spin);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- READ-WRITE LOCK
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -198,53 +162,12 @@ void TRI_UnlockSpin (TRI_spin_t* spin) {
|
|||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Threading
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialises a new read-write lock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_InitReadWriteLock (TRI_read_write_lock_t* lock) {
|
||||
|
||||
// ...........................................................................
|
||||
// set the number of readers reading on the read_write lock to 0
|
||||
// ...........................................................................
|
||||
|
||||
lock->_readers = 0;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Signaled: writer has no access
|
||||
// Non-Signaled: writer has access, block readers
|
||||
// Creates an event which allows a thread to wait on it (perhaps should use
|
||||
// a mutux rather than an event here). The writer event is set to signalled
|
||||
// when CreateEvent is called with these parameters.
|
||||
// ...........................................................................
|
||||
|
||||
lock->_writerEvent = CreateEvent(0, TRUE, TRUE, 0);
|
||||
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Signaled: no readers
|
||||
// Non-Signaled: some readers have access, block writer
|
||||
// Same as the writer event above except this is the reader event
|
||||
// ...........................................................................
|
||||
|
||||
lock->_readersEvent = CreateEvent(0, TRUE, TRUE, 0);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Creates critical sections for writer and readers.
|
||||
// Waits for ownership of the specified critical section object.
|
||||
// The function returns when the calling thread is granted ownership.
|
||||
// ...........................................................................
|
||||
|
||||
InitializeCriticalSection(&lock->_lockWriter);
|
||||
InitializeCriticalSection(&lock->_lockReaders);
|
||||
InitializeSRWLock(&lock->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -252,104 +175,18 @@ void TRI_InitReadWriteLock (TRI_read_write_lock_t* lock) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DestroyReadWriteLock (TRI_read_write_lock_t* lock) {
|
||||
DeleteCriticalSection(&lock->_lockWriter);
|
||||
DeleteCriticalSection(&lock->_lockReaders);
|
||||
|
||||
CloseHandle(lock->_writerEvent);
|
||||
CloseHandle(lock->_readersEvent);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Threading
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief increments readers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void IncrementReaders (TRI_read_write_lock_t* lock) {
|
||||
|
||||
// ...........................................................................
|
||||
// increment the number of readers we have on the read_write lock
|
||||
// ...........................................................................
|
||||
|
||||
lock->_readers++;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Since the number of readers must be positive, set the readers event to
|
||||
// non-signalled so that any write event will have to wait.
|
||||
// ...........................................................................
|
||||
ResetEvent(lock->_readersEvent);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief decrements readers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void DecrementReaders (TRI_read_write_lock_t* lock) {
|
||||
|
||||
// ...........................................................................
|
||||
// reduce the number of readers using the read_write lock by 1
|
||||
// ...........................................................................
|
||||
|
||||
lock->_readers--;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// When the number of readers is 0, set the event to signalled which allows
|
||||
// a writer to use the read_write lock.
|
||||
// ...........................................................................
|
||||
|
||||
if (lock->_readers == 0) {
|
||||
SetEvent(lock->_readersEvent);
|
||||
}
|
||||
else if (lock->_readers < 0) {
|
||||
LOG_FATAL_AND_EXIT("reader count is negative");
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Threading
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tries to read lock a read-write lock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_TryReadLockReadWriteLock (TRI_read_write_lock_t* lock) {
|
||||
WaitForSingleObject(lock->_writerEvent, 10); // 10 millis timeout
|
||||
|
||||
EnterCriticalSection(&lock->_lockReaders);
|
||||
IncrementReaders(lock);
|
||||
LeaveCriticalSection(&lock->_lockReaders);
|
||||
|
||||
if (WaitForSingleObject(lock->_writerEvent, 0) != WAIT_OBJECT_0) {
|
||||
EnterCriticalSection(&lock->_lockReaders);
|
||||
DecrementReaders(lock);
|
||||
LeaveCriticalSection(&lock->_lockReaders);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return (TryAcquireSRWLockShared(&lock->_lock) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -357,43 +194,7 @@ bool TRI_TryReadLockReadWriteLock (TRI_read_write_lock_t* lock) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_ReadLockReadWriteLock (TRI_read_write_lock_t* lock) {
|
||||
|
||||
while (true) {
|
||||
|
||||
// ........................................................................
|
||||
// Waits for a writer to finish if there is one. This function only
|
||||
// returns when the writer event is in a signalled state
|
||||
// ........................................................................
|
||||
|
||||
WaitForSingleObject(lock->_writerEvent, INFINITE);
|
||||
|
||||
|
||||
// .........................................................................
|
||||
// This thread will wait here until this resource becomes excusively available
|
||||
// .........................................................................
|
||||
|
||||
EnterCriticalSection(&lock->_lockReaders);
|
||||
IncrementReaders(lock);
|
||||
|
||||
// .........................................................................
|
||||
// allows some other thread to use this resource
|
||||
// .........................................................................
|
||||
|
||||
LeaveCriticalSection(&lock->_lockReaders);
|
||||
|
||||
|
||||
// it could have happened that the writer event is no longer in a signalled
|
||||
// state. Between leaving the crtical section and here a writer sneaked in.
|
||||
//
|
||||
if (WaitForSingleObject(lock->_writerEvent, 0) != WAIT_OBJECT_0) {
|
||||
EnterCriticalSection(&lock->_lockReaders);
|
||||
DecrementReaders(lock);
|
||||
LeaveCriticalSection(&lock->_lockReaders);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
AcquireSRWLockShared(&lock->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -401,98 +202,15 @@ void TRI_ReadLockReadWriteLock (TRI_read_write_lock_t* lock) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_ReadUnlockReadWriteLock (TRI_read_write_lock_t* lock) {
|
||||
EnterCriticalSection(&lock->_lockReaders);
|
||||
|
||||
/* this is wrong since it is possible for the write locker to block this event
|
||||
// a write lock eists
|
||||
if (WaitForSingleObject(lock->_writerEvent, 0) != WAIT_OBJECT_0) {
|
||||
LOG_FATAL_AND_EXIT("write lock, but trying to unlock read");
|
||||
}
|
||||
|
||||
// at least one reader exists
|
||||
else if (0 < lock->_readers) {
|
||||
DecrementReaders(lock);
|
||||
}
|
||||
|
||||
// ups, no writer and no reader
|
||||
else {
|
||||
LeaveCriticalSection(&lock->_lockReaders);
|
||||
LOG_FATAL_AND_EXIT("no reader and no writer, but trying to unlock");
|
||||
}
|
||||
*/
|
||||
|
||||
if (0 < lock->_readers) {
|
||||
DecrementReaders(lock);
|
||||
}
|
||||
|
||||
// oops no reader
|
||||
else {
|
||||
LeaveCriticalSection(&lock->_lockReaders);
|
||||
LOG_FATAL_AND_EXIT("no reader, but trying to unlock read lock");
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&lock->_lockReaders);
|
||||
ReleaseSRWLockShared(&lock->_lock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tries to write lock a read-write lock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_TryWriteLockReadWriteLock (TRI_read_write_lock_t* lock) {
|
||||
|
||||
BOOL result;
|
||||
// ...........................................................................
|
||||
// Here we use TryEnterCriticalSection instead of EnterCriticalSection
|
||||
// There could already be a write lock - which will actuall block from this
|
||||
// point on.
|
||||
// ...........................................................................
|
||||
|
||||
result = TryEnterCriticalSection(&lock->_lockWriter);
|
||||
|
||||
if (result == 0) {
|
||||
// appears some other writer is writing
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Wait until the lock->_writerEvent is in a 'signalled' state
|
||||
// This might fail because a reader is just about to read
|
||||
// ...........................................................................
|
||||
|
||||
if (WaitForSingleObject(lock->_writerEvent, 0) != WAIT_OBJECT_0) {
|
||||
LeaveCriticalSection(&lock->_lockWriter);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// Set _writeEvent as nonsignalled -- this will block other read/write
|
||||
// lockers
|
||||
// ...........................................................................
|
||||
|
||||
ResetEvent(lock->_writerEvent);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// If there are ANY read locks outstanding, leave
|
||||
// ...........................................................................
|
||||
|
||||
if (WaitForSingleObject(lock->_readersEvent, 0) != WAIT_OBJECT_0) {
|
||||
LeaveCriticalSection(&lock->_lockWriter);
|
||||
SetEvent(lock->_writerEvent);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Allow other threads to access this function
|
||||
// ...........................................................................
|
||||
|
||||
LeaveCriticalSection(&lock->_lockWriter);
|
||||
|
||||
return true;
|
||||
return (TryAcquireSRWLockExclusive(&lock->_lock) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -500,105 +218,17 @@ bool TRI_TryWriteLockReadWriteLock (TRI_read_write_lock_t* lock) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_WriteLockReadWriteLock (TRI_read_write_lock_t* lock) {
|
||||
|
||||
// ...........................................................................
|
||||
// Lock so no other thread can access this
|
||||
// EnterCriticalSection(&lock->_lockWriter) will block this thread until
|
||||
// it has been released by the other thread.
|
||||
// ...........................................................................
|
||||
|
||||
EnterCriticalSection(&lock->_lockWriter);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Wait until the lock->_writerEvent is in a 'signalled' state
|
||||
// ...........................................................................
|
||||
|
||||
WaitForSingleObject(lock->_writerEvent, INFINITE);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Set _writeEvent as nonsignalled -- this will block other read/write
|
||||
// lockers
|
||||
// ...........................................................................
|
||||
|
||||
ResetEvent(lock->_writerEvent);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// If there are ANY read locks outstanding, then wait until these are cleared
|
||||
// ...........................................................................
|
||||
|
||||
WaitForSingleObject(lock->_readersEvent, INFINITE);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Allow other threads to access this function
|
||||
// ...........................................................................
|
||||
|
||||
LeaveCriticalSection(&lock->_lockWriter);
|
||||
AcquireSRWLockExclusive(&lock->_lock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief write unlocks read-write lock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_WriteUnlockReadWriteLock (TRI_read_write_lock_t* lock) {
|
||||
|
||||
// ...........................................................................
|
||||
// Write lock this _lockReader so no other threads can access this
|
||||
// This will block this thread until it is released by the other thread
|
||||
// We do not need to lock the _lockWriter SINCE the TRI_WriteLockReadWriteLock
|
||||
// function above will lock (due to the ResetEvent(lock->_writerEvent); )
|
||||
// ...........................................................................
|
||||
|
||||
EnterCriticalSection(&lock->_lockReaders);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// In the function TRI_WriteLockReadWriteLock we set the _writerEvent to
|
||||
// 'nonsignalled'. So if a write lock exists clear it by setting it to
|
||||
// 'signalled'
|
||||
// ...........................................................................
|
||||
|
||||
if (WaitForSingleObject(lock->_writerEvent, 0) != WAIT_OBJECT_0) {
|
||||
SetEvent(lock->_writerEvent);
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// Oops at least one reader exists - something terrible happened.
|
||||
// ...........................................................................
|
||||
|
||||
else if (0 < lock->_readers) {
|
||||
LeaveCriticalSection(&lock->_lockReaders);
|
||||
LOG_FATAL_AND_EXIT("read lock, but trying to unlock write");
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Oops we are trying to unlock a write lock, but there isn't one! Something
|
||||
// terrible happend.
|
||||
// ...........................................................................
|
||||
|
||||
else {
|
||||
LeaveCriticalSection(&lock->_lockReaders);
|
||||
LOG_FATAL_AND_EXIT("no reader and no writer, but trying to unlock");
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Allow read locks to be applied now.
|
||||
// ...........................................................................
|
||||
|
||||
LeaveCriticalSection(&lock->_lockReaders);
|
||||
ReleaseSRWLockExclusive(&lock->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- CONDITION VARIABLE
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -607,11 +237,6 @@ void TRI_WriteUnlockReadWriteLock (TRI_read_write_lock_t* lock) {
|
|||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Threading
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialises a new condition variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -629,19 +254,10 @@ void TRI_DestroyCondition (TRI_condition_t* cond) {
|
|||
DeleteCriticalSection(&cond->_lockWaiters);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Threading
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief signals a condition variable
|
||||
///
|
||||
|
@ -715,7 +331,6 @@ void TRI_UnlockCondition (TRI_condition_t* cond) {
|
|||
LeaveCriticalSection(&cond->_lockWaiters);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// COMPARE & SWAP operations below for windows
|
||||
// Note that for the MAC OS we use the 'barrier' functions which ensure that
|
||||
|
@ -784,10 +399,6 @@ bool TRI_ComparePointer(void* volatile* theValue, void* oldValue) {
|
|||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
||||
|
|
|
@ -40,11 +40,6 @@ extern "C" {
|
|||
// --SECTION-- public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Threading
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief mutex type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -65,13 +60,7 @@ TRI_mutex_t;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_read_write_lock_s {
|
||||
HANDLE _writerEvent;
|
||||
HANDLE _readersEvent;
|
||||
|
||||
int _readers;
|
||||
|
||||
CRITICAL_SECTION _lockWriter;
|
||||
CRITICAL_SECTION _lockReaders;
|
||||
SRWLOCK _lock;
|
||||
}
|
||||
TRI_read_write_lock_t;
|
||||
|
||||
|
@ -85,10 +74,6 @@ typedef struct TRI_condition_s {
|
|||
}
|
||||
TRI_condition_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -57,16 +57,15 @@ _invalid_parameter_handler newInvalidHandleHandler;
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int ftruncate(int fd, long newSize) {
|
||||
int ftruncate (int fd, long newSize) {
|
||||
int result = _chsize(fd, newSize);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int getpagesize(void) {
|
||||
int getpagesize (void) {
|
||||
static int pageSize = 0; // only define it once
|
||||
|
||||
if (!pageSize) {
|
||||
if (! pageSize) {
|
||||
// first time, so call the system info function
|
||||
SYSTEM_INFO systemInfo;
|
||||
GetSystemInfo (&systemInfo);
|
||||
|
@ -76,22 +75,20 @@ int getpagesize(void) {
|
|||
return pageSize;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Calls the windows Sleep function which always sleeps for milliseconds
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_sleep(unsigned long waitTime) {
|
||||
void TRI_sleep (unsigned long waitTime) {
|
||||
Sleep(waitTime * 1000);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Calls a timer which waits for a signal after the elapsed time.
|
||||
// The timer is acurate to 100nanoseconds
|
||||
// The timer is accurate to 100nanoseconds
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_usleep(unsigned long waitTime) {
|
||||
void TRI_usleep (unsigned long waitTime) {
|
||||
int result;
|
||||
HANDLE hTimer = NULL; // stores the handle of the timer object
|
||||
LARGE_INTEGER wTime; // essentially a 64bit number
|
||||
|
@ -109,7 +106,7 @@ void TRI_usleep(unsigned long waitTime) {
|
|||
abort();
|
||||
}
|
||||
// Set timer to wait for indicated micro seconds.
|
||||
if (!SetWaitableTimer(hTimer, &wTime, 0, NULL, NULL, 0)) {
|
||||
if (! SetWaitableTimer(hTimer, &wTime, 0, NULL, NULL, 0)) {
|
||||
// not much we can do at this low level
|
||||
CloseHandle(hTimer);
|
||||
return;
|
||||
|
@ -135,14 +132,13 @@ void TRI_usleep(unsigned long waitTime) {
|
|||
// for now is to ignore error and hope it goes away!
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void InvalidParameterHandler(const wchar_t* expression, // expression sent to function - NULL
|
||||
const wchar_t* function, // name of function - NULL
|
||||
const wchar_t* file, // file where code resides - NULL
|
||||
unsigned int line, // line within file - NULL
|
||||
uintptr_t pReserved) { // in case microsoft forget something
|
||||
static void InvalidParameterHandler (const wchar_t* expression, // expression sent to function - NULL
|
||||
const wchar_t* function, // name of function - NULL
|
||||
const wchar_t* file, // file where code resides - NULL
|
||||
unsigned int line, // line within file - NULL
|
||||
uintptr_t pReserved) { // in case microsoft forget something
|
||||
LOG_ERROR("Invalid handle parameter passed");
|
||||
|
||||
/* start oreste -debug */
|
||||
/*
|
||||
if (expression != 0) {
|
||||
wprintf(L"win-utils.c:InvalidParameterHandler:EXPRESSION = %s\n",expression);
|
||||
}
|
||||
|
@ -161,14 +157,12 @@ static void InvalidParameterHandler(const wchar_t* expression, // expression sen
|
|||
else {
|
||||
wprintf(L"win-utils.c:InvalidParameterHandler:FILE = NULL\n");
|
||||
}
|
||||
printf("oreste:win-utils.c:InvalidParameterHandler:LINE = %ud\n",line);
|
||||
/* end oreste -debug */
|
||||
*/
|
||||
//abort();
|
||||
// TODO: use the wcstombs_s function to convert wchar to char - since all the above
|
||||
// wchar never will contain 2 byte chars
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Called from the 'main' and performs any initialisation requirements which
|
||||
// are specific to windows.
|
||||
|
@ -178,8 +172,8 @@ static void InvalidParameterHandler(const wchar_t* expression, // expression sen
|
|||
// calling function should decide what to do.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
int finaliseWindows(const TRI_win_finalise_e finaliseWhat, const char* data) {
|
||||
int finaliseWindows (const TRI_win_finalise_e finaliseWhat,
|
||||
const char* data) {
|
||||
int result = 0;
|
||||
|
||||
// ............................................................................
|
||||
|
@ -209,10 +203,8 @@ int finaliseWindows(const TRI_win_finalise_e finaliseWhat, const char* data) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int initialiseWindows(const TRI_win_initialise_e initialiseWhat, const char* data) {
|
||||
|
||||
int initialiseWindows (const TRI_win_initialise_e initialiseWhat,
|
||||
const char* data) {
|
||||
|
||||
// ............................................................................
|
||||
// The data is used to transport information from the calling function to here
|
||||
|
@ -273,7 +265,6 @@ int initialiseWindows(const TRI_win_initialise_e initialiseWhat, const char* dat
|
|||
|
||||
}
|
||||
|
||||
|
||||
int TRI_createFile (const char* filename, int openFlags, int modeFlags) {
|
||||
HANDLE fileHandle;
|
||||
int fileDescriptor;
|
||||
|
@ -282,11 +273,10 @@ int TRI_createFile (const char* filename, int openFlags, int modeFlags) {
|
|||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
CREATE_NEW,
|
||||
(openFlags & O_APPEND) ? OPEN_ALWAYS : CREATE_NEW,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
|
||||
if (fileHandle == INVALID_HANDLE_VALUE) {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -106,14 +106,14 @@ int TRI_openFile (const char* filename, int openFlags);
|
|||
// this provides a translation
|
||||
// .............................................................................
|
||||
|
||||
void TRI_sleep(unsigned long);
|
||||
void TRI_sleep (unsigned long);
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// there is no usleep (micro sleep) in windows, so we create one here
|
||||
// .............................................................................
|
||||
|
||||
void TRI_usleep(unsigned long);
|
||||
void TRI_usleep (unsigned long);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
|
@ -2724,10 +2724,25 @@ v8::Handle<v8::Array> TRI_V8PathList (string const& modules) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_InitV8Utils (v8::Handle<v8::Context> context,
|
||||
string const& startupPath,
|
||||
string const& modules,
|
||||
string const& packages,
|
||||
string const& startupPath) {
|
||||
string packages) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// merge package-paths
|
||||
|
||||
// built-in package-path is first
|
||||
string realPackages = startupPath + TRI_DIR_SEPARATOR_STR + "npm";
|
||||
if (! packages.empty()) {
|
||||
if (packages.substr(0, realPackages.size()) == realPackages) {
|
||||
packages = packages.substr(realPackages.size());
|
||||
}
|
||||
|
||||
packages = StringUtils::lTrim(packages, ";:");
|
||||
if (! packages.empty()) {
|
||||
realPackages += ";" + packages;
|
||||
}
|
||||
}
|
||||
|
||||
// check the isolate
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
|
@ -2817,7 +2832,7 @@ void TRI_InitV8Utils (v8::Handle<v8::Context> context,
|
|||
TRI_AddGlobalVariableVocbase(context, "HOME", v8::String::New(FileUtils::homeDirectory().c_str()));
|
||||
|
||||
TRI_AddGlobalVariableVocbase(context, "MODULES_PATH", TRI_V8PathList(modules));
|
||||
TRI_AddGlobalVariableVocbase(context, "PACKAGE_PATH", TRI_V8PathList(packages));
|
||||
TRI_AddGlobalVariableVocbase(context, "PACKAGE_PATH", TRI_V8PathList(realPackages));
|
||||
TRI_AddGlobalVariableVocbase(context, "STARTUP_PATH", v8::String::New(startupPath.c_str()));
|
||||
TRI_AddGlobalVariableVocbase(context, "PATH_SEPARATOR", v8::String::New(TRI_DIR_SEPARATOR_STR));
|
||||
TRI_AddGlobalVariableVocbase(context, "VALGRIND", RUNNING_ON_VALGRIND > 0 ? v8::True() : v8::False());
|
||||
|
|
|
@ -198,7 +198,7 @@ v8::Handle<v8::Array> TRI_V8PathList (std::string const&);
|
|||
void TRI_InitV8Utils (v8::Handle<v8::Context>,
|
||||
std::string const&,
|
||||
std::string const&,
|
||||
std::string const&);
|
||||
std::string);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
ARANGOD="${ARANGODB_ROOT}@SBINDIR@/arangod"
|
||||
DATABASE="${ARANGODB_ROOT}@DATABASEDIR@"
|
||||
MODULESPATH="${ARANGODB_ROOT}@PKGDATADIR@/js/server/modules;${ARANGODB_ROOT}@PKGDATADIR@/js/common/modules;${ARANGODB_ROOT}@PKGDATADIR@/js/node"
|
||||
PACKAGEPATH="${ARANGODB_ROOT}@PKGDATADIR@/js/npm"
|
||||
APPPATH="${ARANGODB_ROOT}@PKGDATADIR@/js/apps"
|
||||
STARTUPPATH="${ARANGODB_ROOT}@PKGDATADIR@/js"
|
||||
SCRIPT="${ARANGODB_ROOT}@PKGDATADIR@/js/server/arango-dfdb.js"
|
||||
|
@ -41,7 +39,5 @@ $ARANGOD \
|
|||
--no-upgrade \
|
||||
--database.directory "$DATABASE" \
|
||||
--javascript.startup-directory "$STARTUPPATH" \
|
||||
--javascript.modules-path "$MODULESPATH" \
|
||||
--javascript.package-path "$PACKAGEPATH" \
|
||||
--javascript.app-path "$APPPATH" \
|
||||
--javascript.script "$SCRIPT"
|
||||
|
|
Loading…
Reference in New Issue