1
0
Fork 0

Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel

This commit is contained in:
Frank Celler 2013-11-20 09:20:51 +01:00
commit f35347098b
64 changed files with 1210 additions and 1722 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
{

View File

@ -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;

View File

@ -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);
}
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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 ||

View File

@ -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) {

View File

@ -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);

View File

@ -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;) {

View File

@ -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);

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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)

View File

@ -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]

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -222,6 +222,7 @@ div.headerDropdown {
display:none;
margin-left: 5px;
margin-right: 5px;
padding-bottom: 15px;
width: auto;
}

View File

@ -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; */
}

View File

@ -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();
}
});
}());

View File

@ -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;
}
});
});
}());

View File

@ -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>

View File

@ -265,7 +265,7 @@ function ArangoAdapter(nodes, edges, config) {
return;
}
callback(absAdapter.insertInitialNode(n));
}
};
},

View File

@ -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();
}
}

View File

@ -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")

View File

@ -31,7 +31,6 @@ function EventDispatcher(nodeShaper, edgeShaper, config) {
"use strict";
var eventlib,
expandConfig,
svgBase,
svgTemp,
svgObj,

View File

@ -132,7 +132,7 @@ function EventLibrary() {
}
adapter.createNode(d, function(newNode) {
nodeShaper.reshapeNodes();
callback(newNode);
cb(newNode);
});
};
};

View File

@ -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;

View File

@ -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() {};

View File

@ -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);
});
});
};
}());

View File

@ -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,

View File

@ -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();

View File

@ -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);
});

View File

@ -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({

View File

@ -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() {
});
});
});

View File

@ -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");
});
});

View File

@ -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.");
});

View File

@ -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 @@
});
});
}());
}());

View File

@ -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",

View File

@ -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);

View File

@ -211,7 +211,6 @@
return;
}
var self = this;
window.arangoLogsStore.fetch({
success: function () {
window.logsView.render();

View File

@ -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(", ");

View File

@ -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 () {

View File

@ -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();
}
});
}
});
});
}());

View File

@ -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;

View File

@ -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) {

View File

@ -43,7 +43,6 @@
render: function() {
$(this.el).html(this.template.text);
var self = this;
_.each(this._subViews, function (v) {
$("#foxxList").append(v.render());
});

View File

@ -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;
}
});
}());

View File

@ -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;

View File

@ -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,

View File

@ -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();

View File

@ -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)) {

View File

@ -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
///

View 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--\\|/// @\\}"

View File

@ -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

View File

@ -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;
}

View File

@ -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);
////////////////////////////////////////////////////////////////////////////////
/// @}

View File

@ -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());

View File

@ -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

View File

@ -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"