From 8ec5ad2a1e7b20aeecb1b6ef183e763cd52a3371 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 24 Jun 2014 09:02:36 +0200 Subject: [PATCH 01/21] removed bogus warning --- arangod/VocBase/index.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arangod/VocBase/index.cpp b/arangod/VocBase/index.cpp index 0a1abf914b..a62fbe12c4 100644 --- a/arangod/VocBase/index.cpp +++ b/arangod/VocBase/index.cpp @@ -2476,10 +2476,9 @@ TRI_index_t* TRI_CreateBitarrayIndex (TRI_document_collection_t* document, for (i = j + 1; i < paths->_length; ++i) { TRI_shape_pid_t* rightShape = (TRI_shape_pid_t*)(TRI_AtVector(paths,i)); if (*leftShape == *rightShape) { - LOG_WARNING("bitarray index creation failed -- duplicate keys in index"); *errorNum = TRI_ERROR_ARANGO_INDEX_BITARRAY_CREATION_FAILURE_DUPLICATE_ATTRIBUTES; - *errorStr = TRI_DuplicateString("bitarray index creation failed -- duplicate keys in index"); - return NULL; + *errorStr = TRI_DuplicateString("bitarray index creation failed - duplicate keys in index"); + return nullptr; } } } From 9695b25673d32ddfdbbf16de4fa8a782a326e387 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 24 Jun 2014 09:19:26 +0200 Subject: [PATCH 02/21] added tests --- UnitTests/Makefile.unittests | 1 + arangod/Wal/CollectorThread.cpp | 4 ++ js/server/tests/shell-wal-noncluster.js | 61 ++++++++++++++++++++++++- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/UnitTests/Makefile.unittests b/UnitTests/Makefile.unittests index fc5093f803..5b0542a6b9 100755 --- a/UnitTests/Makefile.unittests +++ b/UnitTests/Makefile.unittests @@ -210,6 +210,7 @@ unittests-recovery: @echo "================================================================================" @echo + $(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="collector-oom" $(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="transaction-no-abort" $(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="transaction-no-commit" $(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="multi-database-durability" diff --git a/arangod/Wal/CollectorThread.cpp b/arangod/Wal/CollectorThread.cpp index d058168840..4b0153178b 100644 --- a/arangod/Wal/CollectorThread.cpp +++ b/arangod/Wal/CollectorThread.cpp @@ -1064,6 +1064,10 @@ int CollectorThread::executeTransferMarkers (TRI_document_collection_t* document int CollectorThread::queueOperations (triagens::wal::Logfile* logfile, CollectorCache*& cache) { TRI_voc_cid_t cid = cache->collectionId; + + TRI_IF_FAILURE("CollectorThreadQueueOperations") { + throw std::bad_alloc(); + } MUTEX_LOCKER(_operationsQueueLock); diff --git a/js/server/tests/shell-wal-noncluster.js b/js/server/tests/shell-wal-noncluster.js index 32f9f37960..372fb9a7f2 100644 --- a/js/server/tests/shell-wal-noncluster.js +++ b/js/server/tests/shell-wal-noncluster.js @@ -30,6 +30,60 @@ var arangodb = require("org/arangodb"); var testHelper = require("org/arangodb/test-helper").Helper; var db = arangodb.db; var internal = require("internal"); + +// ----------------------------------------------------------------------------- +// --SECTION-- wal failures +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test suite +//////////////////////////////////////////////////////////////////////////////// + +function walFailureSuite () { + var cn = "UnitTestsWal"; + var c; + + return { + + setUp: function () { + internal.debugClearFailAt(); + db._drop(cn); + c = db._create(cn); + }, + + tearDown: function () { + db._drop(cn); + c = null; + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test bad alloc in collector +//////////////////////////////////////////////////////////////////////////////// + + testCollectorBadAlloc : function () { + internal.flushWal(true, true); + internal.debugSetFailAt("CollectorThreadQueueOperations"); + + var i = 0; + for (i = 0; i < 1000; ++i) { + c.save({ _key: "test" + i }); + } + + assertEqual(1000, c.count()); + internal.flushWal(true, false); + + assertEqual(1000, c.count()); + internal.wait(6); + internal.debugClearFailAt(); + + internal.wait(6); + testHelper.waitUnload(c); + + assertEqual(1000, c.count()); + } + + }; +} // ----------------------------------------------------------------------------- // --SECTION-- wal functions @@ -39,7 +93,7 @@ var internal = require("internal"); /// @brief test suite //////////////////////////////////////////////////////////////////////////////// -function WalSuite () { +function walSuite () { var cn = "UnitTestsWal"; var c; @@ -123,7 +177,10 @@ function WalSuite () { /// @brief executes the test suites //////////////////////////////////////////////////////////////////////////////// -jsunity.run(WalSuite); +if (internal.debugCanUseFailAt()) { + jsunity.run(walFailureSuite); +} +jsunity.run(walSuite); return jsunity.done(); From eb887369e7666c941dffe45d370e4ab6d47714d9 Mon Sep 17 00:00:00 2001 From: gschwab Date: Tue, 24 Jun 2014 09:52:23 +0200 Subject: [PATCH 03/21] merge after make --- .../js/modules/org/arangodb/general-graph.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/js/apps/system/aardvark/frontend/js/modules/org/arangodb/general-graph.js b/js/apps/system/aardvark/frontend/js/modules/org/arangodb/general-graph.js index 81fc22d68f..dbd7eb6432 100644 --- a/js/apps/system/aardvark/frontend/js/modules/org/arangodb/general-graph.js +++ b/js/apps/system/aardvark/frontend/js/modules/org/arangodb/general-graph.js @@ -2999,7 +2999,7 @@ Graph.prototype._countCommonProperties = function(vertex1Example, vertex2Example /// ~ var db = require("internal").db; /// var examples = require("org/arangodb/graph-examples/example-graph.js"); /// var g = examples.loadGraph("routeplanner"); -/// | g._absoluteEccentricity({}, {startVertexCollectionRestriction : 'city', +/// | g._absoluteEccentricity({}, {startVertexCollectionRestriction : 'germanCity', /// direction : 'outbound', weight : 'distance'}); /// @END_EXAMPLE_ARANGOSH_OUTPUT /// @@ -3030,7 +3030,7 @@ Graph.prototype._absoluteEccentricity = function(vertexExample, options) { /// [eccentricity](http://en.wikipedia.org/wiki/Distance_%28graph_theory%29) /// *of the vertices defined by the examples.* /// -/// Similar to [_absoluteEccentricity](#_absoluteEccentricity) but returns a normalized result. +/// Similar to [_absoluteEccentricity](#_absoluteeccentricity) but returns a normalized result. /// /// @EXAMPLES /// @@ -3161,7 +3161,7 @@ Graph.prototype._absoluteCloseness = function(vertexExample, options) { /// [closeness](http://en.wikipedia.org/wiki/Centrality#Closeness_centrality) /// *of graphs vertices.* /// -/// Similar to [_absoluteCloseness](#_absoluteCloseness) but returns a normalized value. +/// Similar to [_absoluteCloseness](#_absolutecloseness) but returns a normalized value. /// /// @EXAMPLES /// @@ -3253,7 +3253,7 @@ Graph.prototype._closeness = function(options) { /// g._absoluteBetweenness({weight : 'distance'}); /// @END_EXAMPLE_ARANGOSH_OUTPUT /// -/// A route planner example, the absolute closeness of all cities regarding only +/// A route planner example, the absolute betweenness of all cities regarding only /// outbound paths. /// /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModuleAbsBetweenness3} @@ -3289,7 +3289,7 @@ Graph.prototype._absoluteBetweenness = function(options) { /// [betweenness](http://en.wikipedia.org/wiki/Betweenness_centrality) /// *of graphs vertices.* /// -/// Similar to [_absoluteBetweeness](#_absoluteBetweeness) but returns normalized values. +/// Similar to [_absoluteBetweeness](#_absolutebetweeness) but returns normalized values. /// /// @EXAMPLES /// @@ -3302,7 +3302,7 @@ Graph.prototype._absoluteBetweenness = function(options) { /// g._betweenness(); /// @END_EXAMPLE_ARANGOSH_OUTPUT /// -/// A route planner example, the closeness of all locations. +/// A route planner example, the betweenness of all locations. /// This considers the actual distances. /// /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModuleBetweenness2} @@ -3312,7 +3312,7 @@ Graph.prototype._absoluteBetweenness = function(options) { /// g._betweenness({weight : 'distance'}); /// @END_EXAMPLE_ARANGOSH_OUTPUT /// -/// A route planner example, the closeness of all cities regarding only +/// A route planner example, the betweenness of all cities regarding only /// outbound paths. /// /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModuleBetweenness3} From f9f73c4e515c66a697ee71c6604132f9a83ca5b0 Mon Sep 17 00:00:00 2001 From: gschwab Date: Tue, 24 Jun 2014 10:44:06 +0200 Subject: [PATCH 04/21] docu --- js/common/modules/org/arangodb/general-graph.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/common/modules/org/arangodb/general-graph.js b/js/common/modules/org/arangodb/general-graph.js index 600f8cebec..bb9e953fd7 100644 --- a/js/common/modules/org/arangodb/general-graph.js +++ b/js/common/modules/org/arangodb/general-graph.js @@ -1553,7 +1553,7 @@ var _extendEdgeDefinitions = function (edgeDefinition) { /// /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraphHowTo2} /// ~ var graph_module = require("org/arangodb/general-graph"); -/// ~ graph = graph_module._create("mygraph", +/// ~ graph = graph_module._create("mygraph"); /// graph._addVertexCollection("shop"); /// graph._addVertexCollection("customer"); /// graph._addVertexCollection("pet"); @@ -1564,7 +1564,7 @@ var _extendEdgeDefinitions = function (edgeDefinition) { /// /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraphHowTo3} /// ~ var graph_module = require("org/arangodb/general-graph"); -/// ~ graph = graph_module._create("mygraph", +/// ~ graph = graph_module._create("mygraph"); /// var rel = graph_module._undirectedRelation("isCustomer", ["shop"], ["customer]); /// graph._extendEdgeDefinitions(rel); /// ~ graph_module._drop("mygraph"); From 98f87b1f801961c416538c33f20cb0bfdb196c5d Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 24 Jun 2014 10:55:05 +0200 Subject: [PATCH 05/21] write-throttling --- arangod/V8Server/v8-vocbase.cpp | 2 +- arangod/VocBase/transaction.cpp | 20 ++++++- arangod/Wal/CollectorThread.cpp | 56 ++++++++++++++---- arangod/Wal/CollectorThread.h | 6 ++ arangod/Wal/LogfileManager.cpp | 29 +++++++++- arangod/Wal/LogfileManager.h | 67 ++++++++++++++++++++++ js/server/tests/recovery/collector-oom.js | 69 +++++++++++++++++++++++ 7 files changed, 232 insertions(+), 17 deletions(-) create mode 100644 js/server/tests/recovery/collector-oom.js diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index cb8d75da8d..c1d0326322 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -7776,7 +7776,7 @@ static v8::Handle MapGetVocBase (v8::Local const name, /// @startDocuBlock TODO /// `db._changeMode()` /// -/// Sets the sever to the given mode. +/// Sets the server to the given mode. /// Possible parameters for mode are: /// - Normal /// - ReadOnly diff --git a/arangod/VocBase/transaction.cpp b/arangod/VocBase/transaction.cpp index 4b4cdc7c63..9713f8f156 100644 --- a/arangod/VocBase/transaction.cpp +++ b/arangod/VocBase/transaction.cpp @@ -653,9 +653,7 @@ template static T* CreateMarker () { TRI_transaction_t* TRI_CreateTransaction (TRI_vocbase_t* vocbase, double timeout, bool waitForSync) { - TRI_transaction_t* trx; - - trx = (TRI_transaction_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_transaction_t), false); + TRI_transaction_t* trx = static_cast(TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_transaction_t), false)); if (trx == nullptr) { // out of memory @@ -1017,6 +1015,22 @@ int TRI_BeginTransaction (TRI_transaction_t* trx, if (nestingLevel == 0) { TRI_ASSERT(trx->_status == TRI_TRANSACTION_CREATED); + + if (trx->_type == TRI_TRANSACTION_WRITE && + triagens::wal::LogfileManager::instance()->canBeThrottled()) { + // write-throttling? + static uint64_t const WaitTime = 50000; + uint64_t const maxIterations = triagens::wal::LogfileManager::instance()->maxThrottleWait() / (WaitTime / 1000); + uint64_t iterations = 0; + + while (triagens::wal::LogfileManager::instance()->isThrottled()) { + if (++iterations == maxIterations) { + return TRI_ERROR_LOCK_TIMEOUT; + } + + usleep(WaitTime); + } + } // get a new id trx->_id = TRI_NewTickServer(); diff --git a/arangod/Wal/CollectorThread.cpp b/arangod/Wal/CollectorThread.cpp index 4b0153178b..b35ac2731b 100644 --- a/arangod/Wal/CollectorThread.cpp +++ b/arangod/Wal/CollectorThread.cpp @@ -274,6 +274,9 @@ CollectorThread::CollectorThread (LogfileManager* logfileManager, _logfileManager(logfileManager), _server(server), _condition(), + _operationsQueueLock(), + _operationsQueue(), + _numPendingOperations(0), _stop(0), _inRecovery(true) { @@ -458,6 +461,20 @@ bool CollectorThread::processQueuedOperations () { } if (res == TRI_ERROR_NO_ERROR) { + uint64_t numOperations = (*it2)->operations->size(); + uint64_t maxNumPendingOperations = _logfileManager->throttleWhenPending(); + + if (maxNumPendingOperations > 0 && + _numPendingOperations >= maxNumPendingOperations && + (_numPendingOperations - numOperations) < maxNumPendingOperations) { + // write-throttling was active, but can be turned off now + _logfileManager->deactivateWriteThrottling(); + LOG_INFO("deactivating write-throttling"); + } + + _numPendingOperations -= numOperations; + + // delete the object delete (*it2); @@ -467,6 +484,7 @@ bool CollectorThread::processQueuedOperations () { _logfileManager->decreaseCollectQueueSize(logfile); } else { + // do not delete the object but advance in the operations vector ++it2; } } @@ -1064,24 +1082,40 @@ int CollectorThread::executeTransferMarkers (TRI_document_collection_t* document int CollectorThread::queueOperations (triagens::wal::Logfile* logfile, CollectorCache*& cache) { TRI_voc_cid_t cid = cache->collectionId; - + uint64_t maxNumPendingOperations = _logfileManager->throttleWhenPending(); + TRI_IF_FAILURE("CollectorThreadQueueOperations") { throw std::bad_alloc(); } - MUTEX_LOCKER(_operationsQueueLock); + { + MUTEX_LOCKER(_operationsQueueLock); - auto it = _operationsQueue.find(cid); - if (it == _operationsQueue.end()) { - std::vector ops; - ops.push_back(cache); - _operationsQueue.insert(it, std::make_pair(cid, ops)); - _logfileManager->increaseCollectQueueSize(logfile); + auto it = _operationsQueue.find(cid); + if (it == _operationsQueue.end()) { + std::vector ops; + ops.push_back(cache); + _operationsQueue.insert(it, std::make_pair(cid, ops)); + _logfileManager->increaseCollectQueueSize(logfile); + } + else { + (*it).second.push_back(cache); + _logfileManager->increaseCollectQueueSize(logfile); + } } - else { - (*it).second.push_back(cache); - _logfileManager->increaseCollectQueueSize(logfile); + + uint64_t numOperations = cache->operations->size(); + + if (maxNumPendingOperations > 0 && + _numPendingOperations < maxNumPendingOperations && + (_numPendingOperations + numOperations) >= maxNumPendingOperations) { + // activate write-throttling! + _logfileManager->activateWriteThrottling(); + LOG_WARNING("queued more than %llu pending WAL collector operations. now activating write-throttling", + (unsigned long long) maxNumPendingOperations); } + + _numPendingOperations += numOperations; // we have put the object into the queue successfully // now set the original pointer to null so it isn't double-freed diff --git a/arangod/Wal/CollectorThread.h b/arangod/Wal/CollectorThread.h index 0115df0c56..65fffdccc3 100644 --- a/arangod/Wal/CollectorThread.h +++ b/arangod/Wal/CollectorThread.h @@ -415,6 +415,12 @@ namespace triagens { std::unordered_map> _operationsQueue; +//////////////////////////////////////////////////////////////////////////////// +/// @brief number of pending operations in collector queue +//////////////////////////////////////////////////////////////////////////////// + + uint64_t _numPendingOperations; + //////////////////////////////////////////////////////////////////////////////// /// @brief stop flag //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Wal/LogfileManager.cpp b/arangod/Wal/LogfileManager.cpp index 1cbe319eca..c37e4098c1 100644 --- a/arangod/Wal/LogfileManager.cpp +++ b/arangod/Wal/LogfileManager.cpp @@ -56,6 +56,22 @@ static LogfileManager* Instance = nullptr; // --SECTION-- helper functions // ----------------------------------------------------------------------------- +//////////////////////////////////////////////////////////////////////////////// +/// @brief minimum value for --wal.throttle-when-pending +//////////////////////////////////////////////////////////////////////////////// + +static inline uint64_t MinThrottleWhenPending () { + return 1024 * 1024; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief minimum value for --wal.sync-interval +//////////////////////////////////////////////////////////////////////////////// + +static inline uint64_t MinSyncInterval () { + return 5; +} + //////////////////////////////////////////////////////////////////////////////// /// @brief minimum value for --wal.open-logfiles //////////////////////////////////////////////////////////////////////////////// @@ -227,6 +243,8 @@ LogfileManager::LogfileManager (TRI_server_t* server, _maxOpenLogfiles(10), _numberOfSlots(1048576), _syncInterval(100), + _maxThrottleWait(15000), + _throttleWhenPending(0), _allowOversizeEntries(true), _ignoreLogfileErrors(false), _allowWrites(false), // start in read-only mode @@ -245,6 +263,7 @@ LogfileManager::LogfileManager (TRI_server_t* server, _failedTransactions(), _droppedCollections(), _droppedDatabases(), + _writeThrottled(0), _filenameRegex(), _shutdown(0) { @@ -317,6 +336,8 @@ void LogfileManager::setupOptions (std::map 0 && _throttleWhenPending < MinThrottleWhenPending()) { + LOG_FATAL_AND_EXIT("invalid value for --wal.throttle-when-pending. Please use a value of at least %llu", (unsigned long long) MinThrottleWhenPending()); + } - if (_syncInterval < 5) { - LOG_FATAL_AND_EXIT("invalid sync interval."); + if (_syncInterval < MinSyncInterval()) { + LOG_FATAL_AND_EXIT("invalid value for --wal.sync-interval. Please use a value of at least %llu", (unsigned long long) MinSyncInterval()); } // sync interval is specified in milliseconds by the user, but internally diff --git a/arangod/Wal/LogfileManager.h b/arangod/Wal/LogfileManager.h index 194670c66f..f08dafe1bc 100644 --- a/arangod/Wal/LogfileManager.h +++ b/arangod/Wal/LogfileManager.h @@ -228,6 +228,46 @@ namespace triagens { return _slots; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief whether or not write-throttling can be enabled +//////////////////////////////////////////////////////////////////////////////// + + inline bool canBeThrottled () const { + return (_throttleWhenPending > 0); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief maximum wait time when write-throttled (in milliseconds) +//////////////////////////////////////////////////////////////////////////////// + + inline uint64_t maxThrottleWait () const { + return _maxThrottleWait; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief whether or not write-throttling is currently enabled +//////////////////////////////////////////////////////////////////////////////// + + inline bool isThrottled () { + return (_writeThrottled != 0); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief activate write-throttling +//////////////////////////////////////////////////////////////////////////////// + + void activateWriteThrottling () { + _writeThrottled = 1; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief deactivate write-throttling +//////////////////////////////////////////////////////////////////////////////// + + void deactivateWriteThrottling () { + _writeThrottled = 0; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief allow or disallow writes to the WAL //////////////////////////////////////////////////////////////////////////////// @@ -236,6 +276,14 @@ namespace triagens { _allowWrites = value; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief get the value of --wal.throttle-when-pending +//////////////////////////////////////////////////////////////////////////////// + + inline uint64_t throttleWhenPending () const { + return _throttleWhenPending; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief whether or not we are in the recovery mode //////////////////////////////////////////////////////////////////////////////// @@ -687,6 +735,19 @@ namespace triagens { uint64_t _syncInterval; +//////////////////////////////////////////////////////////////////////////////// +/// @brief maximum wait time for write-throttling +//////////////////////////////////////////////////////////////////////////////// + + uint64_t _maxThrottleWait; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief throttle writes to WAL when at least such many operations are +/// waiting for garbage collection +//////////////////////////////////////////////////////////////////////////////// + + uint64_t _throttleWhenPending; + //////////////////////////////////////////////////////////////////////////////// /// @brief allow entries that are bigger than a single logfile //////////////////////////////////////////////////////////////////////////////// @@ -799,6 +860,12 @@ namespace triagens { std::unordered_set _droppedDatabases; +//////////////////////////////////////////////////////////////////////////////// +/// @brief whether or not write-throttling is currently enabled +//////////////////////////////////////////////////////////////////////////////// + + alignas(64) int _writeThrottled; + //////////////////////////////////////////////////////////////////////////////// /// @brief regex to match logfiles //////////////////////////////////////////////////////////////////////////////// diff --git a/js/server/tests/recovery/collector-oom.js b/js/server/tests/recovery/collector-oom.js new file mode 100644 index 0000000000..b4626bd9a7 --- /dev/null +++ b/js/server/tests/recovery/collector-oom.js @@ -0,0 +1,69 @@ + +var db = require("org/arangodb").db; +var internal = require("internal"); +var jsunity = require("jsunity"); + + +function runSetup () { + internal.debugClearFailAt(); + + db._drop("UnitTestsRecovery"); + var c = db._create("UnitTestsRecovery"), i; + for (i = 0; i < 10000; ++i) { + c.save({ _key: "test" + i, value1: "test" + i, value2: i }); + } + + internal.debugSetFailAt("CollectorThreadQueueOperations"); + internal.flushWal(true, false); + internal.wait(5); + + internal.debugSegfault("crashing server"); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test suite +//////////////////////////////////////////////////////////////////////////////// + +function recoverySuite () { + jsunity.jsUnity.attachAssertions(); + + return { + setUp: function () { + }, + tearDown: function () { + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test whether we can restore the data +//////////////////////////////////////////////////////////////////////////////// + + testCollectorOom : function () { + var i, c = db._collection("UnitTestsRecovery"); + + assertEqual(10000, c.count()); + for (i = 0; i < 10000; ++i) { + var doc = c.document("test" + i); + + assertEqual("test" + i, doc.value1); + assertEqual(i, doc.value2); + } + } + + }; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief executes the test suite +//////////////////////////////////////////////////////////////////////////////// + +function main (argv) { + if (argv[1] === "setup") { + runSetup(); + return 0; + } + else { + jsunity.run(recoverySuite); + return jsunity.done() ? 0 : 1; + } +} + From 5232983bb103f4fff55ebbc656e96d48e45c3543 Mon Sep 17 00:00:00 2001 From: Michael Hackstein Date: Tue, 24 Jun 2014 11:08:22 +0200 Subject: [PATCH 06/21] Moved Edge and Vertex description of gharial to newest version of rest documentation --- .../Books/Users/HttpGharial/Edges.mdpp | 134 +++++++++++------- .../Books/Users/HttpGharial/Vertices.mdpp | 122 ++++++++++------ 2 files changed, 163 insertions(+), 93 deletions(-) diff --git a/Documentation/Books/Users/HttpGharial/Edges.mdpp b/Documentation/Books/Users/HttpGharial/Edges.mdpp index 900bbd5e34..5b3efcfef8 100644 --- a/Documentation/Books/Users/HttpGharial/Edges.mdpp +++ b/Documentation/Books/Users/HttpGharial/Edges.mdpp @@ -1,115 +1,151 @@ !CHAPTER Handling Edges -!SECTION Create an edge - -`POST /system/gharial/graph-name/edge/collection-name`*(create an edge)* - -!SUBSECTION URL parameters - -`graph-name (string, required)` -The name of the graph. - -`collection-name (string, required)` -The name of the edge collection the edge belongs to. - -!SUBSECTION Description +@RESTHEADER{POST /system/gharial/graph-name/edge/collection-name, Create an edge} +@RESTDESCRIPTION Creates a new edge in the collection. Within the body the has to contain a *\_from* and *\_to* value referencing to valid vertices in the graph. Furthermore the edge has to be valid in the definition of this edge collection. +@RESTURLPARAMS + +@RESTPARAM{graph-name, string, required} +The name of the graph. + +@RESTPARAM{collection-name, string, required} +The name of the edge collection the edge belongs to. + +@RESTBODYPARAMS +@RESTPARAM{_from, string, required} +@RESTPARAM{_to, string, required} + +The body has to be the JSON object to be stored. + +@RESTRETURNCODES + +@RESTRETURNCODE{201} +Returned if the edge could be created. + +@RESTRETURNCODE{404} +Returned if no graph with this name, no edge collection or no edge with this id could be found. + @EXAMPLES @startDocuBlock JSF_general_graph_edge_create_http_examples -!SECTION Get an edge +@RESTHEADER{GET /system/gharial/graph-name/edge/collection-name/edge-key, Get an edge} -`GET /system/gharial/graph-name/edge/collection-name/edge-key`*(get an edge)* +@RESTDESCRIPTION +Gets an edge from the given collection. -!SUBSECTION URL parameters +@RESTURLPARAMS -`graph-name (string, required)` +@RESTPARAM{graph-name, string, required} The name of the graph. -`collection-name (string, required)` +@RESTPARAM{collection-name, string, required} The name of the edge collection the edge belongs to. -`edge-key (string, required)` -The `_key` attribute of the edge. +@RESTPARAM{edge-key, string, required} +The *_key* attribute of the vertex. -!SUBSECTION Description +@RESTRETURNCODES +@RESTRETURNCODE{200} +Returned if the edge could be found. -Gets an edge from the given collection. +@RESTRETURNCODE{404} +Returned if no graph with this name, no edge collection or no edge with this id could be found. @EXAMPLES @startDocuBlock JSF_general_graph_edge_get_http_examples -!SECTION Modify an edge +@RESTHEADER{PATCH /system/gharial/graph-name/edge/collection-name/edge-key, Modify an edge} -`PATCH /system/gharial/graph-name/edge/collection-name/edge-key`*(modify an edge)* +@RESTDESCRIPTION +Updates the data of the specific edge in the collection. -!SUBSECTION URL parameters +@RESTURLPARAMS -`graph-name (string, required)` +@RESTPARAM{graph-name, string, required} The name of the graph. -`collection-name (string, required)` +@RESTPARAM{collection-name, string, required} The name of the edge collection the edge belongs to. -`edge-key (string, required)` -The `_key` attribute of the edge. +@RESTPARAM{edge-key, string, required} +The *_key* attribute of the vertex. -!SUBSECTION Description +@RESTBODYPARAMS +The body has to be a JSON object containing the attributes to be updated. -Updates the data of the specific edge in the collection. +@RESTRETURNCODES + +@RESTRETURNCODE{200} +Returned if the edge could be updated. + +@RESTRETURNCODE{404} +Returned if no graph with this name, no edge collection or no edge with this id could be found. @EXAMPLES @startDocuBlock JSF_general_graph_edge_modify_http_examples -!SECTION Replace an edge +@RESTHEADER{PUT /system/gharial/graph-name/edge/collection-name/edge-key, Replace an edge} -`PATCH /system/gharial/graph-name/edge/collection-name/edge-key`*(replace an edge)* +@RESTDESCRIPTION +Replaces the data of an edge in the collection. -!SUBSECTION URL parameters +@RESTURLPARAMS -`graph-name (string, required)` +@RESTPARAM{graph-name, string, required} The name of the graph. -`collection-name (string, required)` +@RESTPARAM{collection-name, string, required} The name of the edge collection the edge belongs to. -`edge-key (string, required)` -The `_key` attribute of the edge. +@RESTPARAM{edge-key, string, required} +The *_key* attribute of the vertex. -!SUBSECTION Description +@RESTBODYPARAMS +The body has to be the JSON object to be stored. -Replaces the data of an edge in the collection. +@RESTRETURNCODES + +@RESTRETURNCODE{200} +Returned if the edge could be replaced. + +@RESTRETURNCODE{404} +Returned if no graph with this name, no edge collection or no edge with this id could be found. @EXAMPLES @startDocuBlock JSF_general_graph_edge_replace_http_examples -!SECTION Remove an edge +@RESTHEADER{DELETE /system/gharial/graph-name/edge/collection-name/edge-key, Remove an edge} -`DELETE /system/gharial/graph-name/edge/collection-name/edge-key`*(remove an edge)* +@RESTDESCRIPTION +Removes an edge from the collection. -!SUBSECTION URL parameters +@RESTURLPARAMS -`graph-name (string, required)` +@RESTPARAM{graph-name, string, required} The name of the graph. -`collection-name (string, required)` +@RESTPARAM{collection-name, string, required} The name of the edge collection the edge belongs to. -`edge-key (string, required)` -The `_key` attribute of the edge. +@RESTPARAM{edge-key, string, required} +The *_key* attribute of the vertex. -!SUBSECTION Description +@RESTRETURNCODES -Removes an edge from the collection. +@RESTRETURNCODE{200} +Returned if the edge could be removed. + +@RESTRETURNCODE{404} +Returned if no graph with this name, no edge collection or no edge with this id could be found. @EXAMPLES diff --git a/Documentation/Books/Users/HttpGharial/Vertices.mdpp b/Documentation/Books/Users/HttpGharial/Vertices.mdpp index 9c4b1da74b..a7f882a313 100644 --- a/Documentation/Books/Users/HttpGharial/Vertices.mdpp +++ b/Documentation/Books/Users/HttpGharial/Vertices.mdpp @@ -1,112 +1,146 @@ !CHAPTER Handling Vertices -!SECTION Create a vertex +@RESTHEADER{POST /system/gharial/graph-name/vertex/collection-name, Create a vertex} -`POST /system/gharial/graph-name/vertex/collection-name`*(create a vertex)* +@RESTDESCRIPTION +Adds a vertex to the given collection. -!SUBSECTION URL parameters +@RESTURLPARAMS -`graph-name (string, required)` +@RESTPARAM{graph-name, string, required} The name of the graph. -`collection-name (string, required)` -The name of the vertex collection the edge belongs to. +@RESTPARAM{collection-name, string, required} +The name of the vertex collection the vertex belongs to. -!SUBSECTION Description +@RESTBODYPARAMS +The body has to be the JSON object to be stored. -Adds a vertex to the given collection. +@RESTRETURNCODES + +@RESTRETURNCODE{201} +Returned if the vertex could be added. + +@RESTRETURNCODE{404} +Returned if no graph or no vertex collection with this name could be found. @EXAMPLES @startDocuBlock JSF_general_graph_vertex_create_http_examples -!SECTION Get a vertex +@RESTHEADER{GET /system/gharial/graph-name/vertex/collection-name/vertex-key, Get a vertex} -`GET /system/gharial/graph-name/vertex/collection-name/vertex-key`*(get a vertex)* +@RESTDESCRIPTION +Gets a vertex from the given collection. -!SUBSECTION URL parameters +@RESTURLPARAMS -`graph-name (string, required)` +@RESTPARAM{graph-name, string, required} The name of the graph. -`collection-name (string, required)` +@RESTPARAM{collection-name, string, required} The name of the vertex collection the vertex belongs to. -`vertex-key (string, required)` -The `_key` attribute of the vertex. +@RESTPARAM{vertex-key, string, required} +The *_key* attribute of the vertex. -!SUBSECTION Description +@RESTRETURNCODES -Gets a vertex from the given collection. +@RESTRETURNCODE{200} +Returned if the vertex could be found. + +@RESTRETURNCODE{404} +Returned if no graph with this name, no vertex collection or no vertex with this id could be found. @EXAMPLES @startDocuBlock JSF_general_graph_vertex_get_http_examples -!SECTION Modify an vertex +@RESTHEADER{PATCH /system/gharial/graph-name/vertex/collection-name/vertex-key, Modify a vertex} -`PATCH /system/gharial/graph-name/vertex/collection-name/vertex-key`*(modify a vertex)* +@RESTDESCRIPTION +Updates the data of the specific vertex in the collection. -!SUBSECTION URL parameters +@RESTURLPARAMS -`graph-name (string, required)` +@RESTPARAM{graph-name, string, required} The name of the graph. -`collection-name (string, required)` +@RESTPARAM{collection-name, string, required} The name of the vertex collection the vertex belongs to. -`vertex-key (string, required)` -The `_key` attribute of the vertex. +@RESTPARAM{vertex-key, string, required} +The *_key* attribute of the vertex. -!SUBSECTION Description +@RESTBODYPARAMS +The body has to contain a JSON object containing exactly the attributes that should be replaced. -Updates the data of the specific vertex in the collection. +@RESTRETURNCODES + +@RESTRETURNCODE{200} +Returned if the vertex could be updated. + +@RESTRETURNCODE{404} +Returned if no graph with this name, no vertex collection or no vertex with this id could be found. @EXAMPLES @startDocuBlock JSF_general_graph_vertex_modify_http_examples -!SECTION Replace an vertex +@RESTHEADER{PUT /system/gharial/graph-name/vertex/collection-name/vertex-key, Replace a vertex} -`PATCH /system/gharial/graph-name/vertex/collection-name/vertex-key`*(replace a vertex)* +@RESTDESCRIPTION +Replaces the data of a vertex in the collection. -!SUBSECTION URL parameters +@RESTURLPARAMS -`graph-name (string, required)` +@RESTPARAM{graph-name, string, required} The name of the graph. -`collection-name (string, required)` +@RESTPARAM{collection-name, string, required} The name of the vertex collection the vertex belongs to. -`vertex-key (string, required)` -The `_key` attribute of the vertex. +@RESTPARAM{vertex-key, string, required} +The *_key* attribute of the vertex. -!SUBSECTION Description +@RESTBODYPARAMS +The body has to be the JSON object to be stored. -Replaces the data of a vertex in the collection. +@RESTRETURNCODES + +@RESTRETURNCODE{200} +Returned if the vertex could be replaced. + +@RESTRETURNCODE{404} +Returned if no graph with this name, no vertex collection or no vertex with this id could be found. @EXAMPLES @startDocuBlock JSF_general_graph_vertex_replace_http_examples -!SECTION Remove a vertex +@RESTHEADER{DELETE /system/gharial/graph-name/vertex/collection-name/vertex-key, Remove a vertex} -`DELETE /system/gharial/graph-name/vertex/collection-name/vertex-key`*(remove a vertex)* +@RESTDESCRIPTION +Removes a vertex from the collection. -!SUBSECTION URL parameters +@RESTURLPARAMS -`graph-name (string, required)` +@RESTPARAM{graph-name, string, required} The name of the graph. -`collection-name (string, required)` +@RESTPARAM{collection-name, string, required} The name of the vertex collection the vertex belongs to. -`vertex-key (string, required)` -The `_key` attribute of the vertex. +@RESTPARAM{vertex-key, string, required} +The *_key* attribute of the vertex. -!SUBSECTION Description +@RESTRETURNCODES -Removes a vertex from the collection. +@RESTRETURNCODE{200} +Returned if the vertex could be removed. + +@RESTRETURNCODE{404} +Returned if no graph with this name, no vertex collection or no vertex with this id could be found. @EXAMPLES From 31e6823daab4c53482055a57ec61ed262b7234e9 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 24 Jun 2014 11:24:10 +0200 Subject: [PATCH 07/21] fixed invalid regex --- js/common/modules/org/arangodb/testrunner.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/common/modules/org/arangodb/testrunner.js b/js/common/modules/org/arangodb/testrunner.js index 5af0aa171a..47b8e6df05 100644 --- a/js/common/modules/org/arangodb/testrunner.js +++ b/js/common/modules/org/arangodb/testrunner.js @@ -63,7 +63,7 @@ runCommandLineTests = function (opts) { options = opts || {}, jasmineReportFormat = options.jasmineReportFormat || 'progress', unitTests = internal.unitTests(), - isSpecRegEx = /.+spec.js/, + isSpecRegEx = /.+spec\.js/, isSpec = function (unitTest) { return isSpecRegEx.test(unitTest); }, From 97e36a7eb072feaabd8892bd4a03556ad9f7092a Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 24 Jun 2014 11:26:51 +0200 Subject: [PATCH 08/21] fixed examples --- arangod/RestHandler/RestImportHandler.cpp | 17 +++++++++- .../RestHandler/RestReplicationHandler.cpp | 8 ++--- js/actions/api-transaction.js | 34 +++---------------- 3 files changed, 22 insertions(+), 37 deletions(-) diff --git a/arangod/RestHandler/RestImportHandler.cpp b/arangod/RestHandler/RestImportHandler.cpp index ceb70a84f4..49ce3498ac 100644 --- a/arangod/RestHandler/RestImportHandler.cpp +++ b/arangod/RestHandler/RestImportHandler.cpp @@ -326,9 +326,11 @@ int RestImportHandler::handleSingleDocument (RestImportTransaction& trx, /// Importing documents with heterogenous attributes from a JSON list: /// /// @EXAMPLE_ARANGOSH_RUN{RestImportJsonList} +/// db._flushCache(); /// var cn = "products"; /// db._drop(cn); -/// db._create(cn) +/// db._create(cn); +/// db._flushCache(); /// /// var body = [ /// { _key: "abc", value1: 25, value2: "test", allowed: true }, @@ -351,9 +353,11 @@ int RestImportHandler::handleSingleDocument (RestImportTransaction& trx, /// Importing documents from individual JSON lines: /// /// @EXAMPLE_ARANGOSH_RUN{RestImportJsonLines} +/// db._flushCache(); /// var cn = "products"; /// db._drop(cn); /// db._create(cn); +/// db._flushCache(); /// /// var body = '{ "_key": "abc", "value1": 25, "value2": "test", "allowed": true }\n{ "_key": "foo", "name": "baz" }\n\n{ "name": { "detailed": "detailed name", "short": "short name" } }\n'; /// var response = logCurlRequestRaw('POST', "/_api/import?collection=" + cn + "&type=documents", body); @@ -371,9 +375,11 @@ int RestImportHandler::handleSingleDocument (RestImportTransaction& trx, /// Using the auto type detection: /// /// @EXAMPLE_ARANGOSH_RUN{RestImportJsonType} +/// db._flushCache(); /// var cn = "products"; /// db._drop(cn); /// db._create(cn); +/// db._flushCache(); /// /// var body = [ /// { _key: "abc", value1: 25, value2: "test", allowed: true }, @@ -396,9 +402,11 @@ int RestImportHandler::handleSingleDocument (RestImportTransaction& trx, /// Importing documents into a new collection from a JSON list: /// /// @EXAMPLE_ARANGOSH_RUN{RestImportJsonCreate} +/// db._flushCache(); /// var cn = "products"; /// db._drop(cn); /// db._create(cn); +/// db._flushCache(); /// /// var body = [ /// { id: "12553", active: true }, @@ -421,11 +429,13 @@ int RestImportHandler::handleSingleDocument (RestImportTransaction& trx, /// Importing into an edge collection, with attributes `_from`, `_to` and `name`: /// /// @EXAMPLE_ARANGOSH_RUN{RestImportJsonEdge} +/// db._flushCache(); /// var cn = "links"; /// db._drop(cn); /// db._createEdgeCollection(cn); /// db._drop("products"); /// db._create("products"); +/// db._flushCache(); /// /// var body = '{ "_from": "products/123", "_to": "products/234" }\n{ "_from": "products/332", "_to": "products/abc", "name": "other name" }'; /// @@ -445,9 +455,11 @@ int RestImportHandler::handleSingleDocument (RestImportTransaction& trx, /// Importing into an edge collection, omitting `_from` or `_to`: /// /// @EXAMPLE_ARANGOSH_RUN{RestImportJsonEdgeInvalid} +/// db._flushCache(); /// var cn = "links"; /// db._drop(cn); /// db._createEdgeCollection(cn); +/// db._flushCache(); /// /// var body = [ { name: "some name" } ]; /// @@ -469,6 +481,7 @@ int RestImportHandler::handleSingleDocument (RestImportTransaction& trx, /// var cn = "products"; /// db._drop(cn); /// db._create(cn); +/// db._flushCache(); /// /// var body = '{ "_key": "abc", "value1": 25, "value2": "test" }\n{ "_key": "abc", "value1": "bar", "value2": "baz" }'; /// @@ -490,6 +503,7 @@ int RestImportHandler::handleSingleDocument (RestImportTransaction& trx, /// var cn = "products"; /// db._drop(cn); /// db._create(cn); +/// db._flushCache(); /// /// var body = '{ "_key": "abc", "value1": 25, "value2": "test" }\n{ "_key": "abc", "value1": "bar", "value2": "baz" }'; /// @@ -522,6 +536,7 @@ int RestImportHandler::handleSingleDocument (RestImportTransaction& trx, /// var cn = "products"; /// db._drop(cn); /// db._create(cn); +/// db._flushCache(); /// /// var body = '{ }'; /// diff --git a/arangod/RestHandler/RestReplicationHandler.cpp b/arangod/RestHandler/RestReplicationHandler.cpp index 6905c25f79..cba143d976 100644 --- a/arangod/RestHandler/RestReplicationHandler.cpp +++ b/arangod/RestHandler/RestReplicationHandler.cpp @@ -1247,13 +1247,11 @@ void RestReplicationHandler::handleTrampolineCoordinator () { /// /// @EXAMPLE_ARANGOSH_RUN{RestReplicationLoggerFollowEmpty} /// var re = require("org/arangodb/replication"); -/// re.logger.start(); /// var lastTick = re.logger.state().state.lastLogTick; /// /// var url = "/_api/replication/logger-follow?from=" + lastTick; /// var response = logCurlRequest('GET', url); /// -/// re.logger.stop(); /// assert(response.code === 204); /// /// logRawResponse(response); @@ -1265,7 +1263,6 @@ void RestReplicationHandler::handleTrampolineCoordinator () { /// var re = require("org/arangodb/replication"); /// db._drop("products"); /// -/// re.logger.start(); /// var lastTick = re.logger.state().state.lastLogTick; /// /// db._create("products"); @@ -1275,10 +1272,10 @@ void RestReplicationHandler::handleTrampolineCoordinator () { /// db.products.update("p2", { "name" : "broken hovercraft" }); /// db.products.drop(); /// +/// require("internal").wait(1); /// var url = "/_api/replication/logger-follow?from=" + lastTick; /// var response = logCurlRequest('GET', url); /// -/// re.logger.stop(); /// assert(response.code === 200); /// /// logRawResponse(response); @@ -1290,7 +1287,6 @@ void RestReplicationHandler::handleTrampolineCoordinator () { /// var re = require("org/arangodb/replication"); /// db._drop("products"); /// -/// re.logger.start(); /// var lastTick = re.logger.state().state.lastLogTick; /// /// db._create("products"); @@ -1300,10 +1296,10 @@ void RestReplicationHandler::handleTrampolineCoordinator () { /// db.products.update("p2", { "name" : "broken hovercraft" }); /// db.products.drop(); /// +/// require("internal").wait(1); /// var url = "/_api/replication/logger-follow?from=" + lastTick + "&chunkSize=400"; /// var response = logCurlRequest('GET', url); /// -/// re.logger.stop(); /// assert(response.code === 200); /// /// logRawResponse(response); diff --git a/js/actions/api-transaction.js b/js/actions/api-transaction.js index 6bc89525c7..bb49b166a7 100644 --- a/js/actions/api-transaction.js +++ b/js/actions/api-transaction.js @@ -1,4 +1,4 @@ -/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true */ +/*jslint indent: 2, nomen: true, maxlen: 180, sloppy: true, vars: true, white: true, plusplus: true */ /*global require, TRANSACTION */ //////////////////////////////////////////////////////////////////////////////// @@ -35,11 +35,6 @@ var actions = require("org/arangodb/actions"); // --SECTION-- private functions // ----------------------------------------------------------------------------- -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup ArangoAPI -/// @{ -//////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// /// @brief execute a server-side transaction /// @@ -78,9 +73,6 @@ var actions = require("org/arangodb/actions"); /// value will be used. Setting `lockTimeout` to `0` will make ArangoDB /// not time out waiting for a lock. /// -/// - `replicate`: whether or not to replicate the operations from this -/// transaction. If not specified, the default value is `true`. -/// /// - `params`: optional arguments passed to `action`. /// /// If the transaction is fully executed and committed on the server, @@ -148,10 +140,7 @@ var actions = require("org/arangodb/actions"); /// collections: { /// write : "products" /// }, -/// action: "function () { " + -/// "var db = require('internal').db; " + -/// "db.products.save({}); " + -/// "return db.products.count(); }" +/// action: "function () { var db = require('internal').db; db.products.save({}); return db.products.count(); }" /// }; /// /// var response = logCurlRequest('POST', url, body); @@ -177,11 +166,7 @@ var actions = require("org/arangodb/actions"); /// collections: { /// write : [ "products", "materials" ] /// }, -/// action: "function () { " + -/// "var db = require('internal').db; " + -/// "db.products.save({}); " + -/// "db.materials.save({}); " + -/// "return 'worked!'; }" +/// action: "function () { var db = require('internal').db; db.products.save({}); db.materials.save({}); return 'worked!'; }" /// }; /// /// var response = logCurlRequest('POST', url, body); @@ -203,10 +188,7 @@ var actions = require("org/arangodb/actions"); /// collections: { /// write : "products" /// }, -/// action : "function () { " + -/// "var db = require('internal').db; " + -/// "db.products.save({ _key: 'abc'}); " + -/// "db.products.save({ _key: 'abc'}); }" +/// action : "function () { var db = require('internal').db; db.products.save({ _key: 'abc'}); db.products.save({ _key: 'abc'}); }" /// }; /// /// var response = logCurlRequest('POST', url, body); @@ -271,10 +253,6 @@ function post_api_transaction(req, res) { actions.resultOk(req, res, actions.HTTP_OK, { result : result }); } -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - // ----------------------------------------------------------------------------- // --SECTION-- initialiser // ----------------------------------------------------------------------------- @@ -304,10 +282,6 @@ actions.defineHttp({ } }); -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - // Local Variables: // mode: outline-minor // outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)" From 5846e4a9fe6329726c9302d91a4ef1ad2fce1b6d Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 24 Jun 2014 11:44:28 +0200 Subject: [PATCH 09/21] removed startup option `--random.no-seed` --- CHANGELOG | 4 ++++ lib/ApplicationServer/ApplicationServer.cpp | 1 - lib/ApplicationServer/ApplicationServer.h | 7 ------- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 098e812b37..bc70ac6c33 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,10 @@ v2.2.0 (XXXX-XX-XX) ------------------- +* removed startup option `--random.no-seed` + + This option had no effect in previous versions of ArangoDB and was thus removed. + * introduced write-ahead log All write operations in an ArangoDB server instance are automatically logged diff --git a/lib/ApplicationServer/ApplicationServer.cpp b/lib/ApplicationServer/ApplicationServer.cpp index f72954ba11..ca355619f4 100644 --- a/lib/ApplicationServer/ApplicationServer.cpp +++ b/lib/ApplicationServer/ApplicationServer.cpp @@ -820,7 +820,6 @@ void ApplicationServer::setupOptions (map& op // ............................................................................. options[OPTIONS_SERVER + ":help-extended"] - ("random.no-seed", "do not seed the random generator") ("random.generator", &_randomGenerator, "1 = mersenne, 2 = random, 3 = urandom, 4 = combined") #ifdef TRI_HAVE_SETUID ("server.uid", &_uid, "switch to user-id after reading config files") diff --git a/lib/ApplicationServer/ApplicationServer.h b/lib/ApplicationServer/ApplicationServer.h index 104e351ec3..f3ad3c73f8 100644 --- a/lib/ApplicationServer/ApplicationServer.h +++ b/lib/ApplicationServer/ApplicationServer.h @@ -755,13 +755,6 @@ namespace triagens { /// number generator using an implication of the Mersenne Twister MT19937 /// algorithm. Algorithm 4 is a combination of the blocking random number /// generator and the Mersenne Twister. -/// -/// @CMDOPT{\--random.no-seed} -/// -/// By default, the random generator is seeded. Setting this option causes the -/// random number generator not to be seeded. (Seeding the random number -/// generator only occurs if the generator is set to Mersenne, refer to -/// random.generator for details.) //////////////////////////////////////////////////////////////////////////////// uint32_t _randomGenerator; From 4f282cbe02e9a79f2ecde66be32ef34e1fb47cd1 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 24 Jun 2014 11:54:32 +0200 Subject: [PATCH 10/21] removed startup option `--database.remove-on-drop` --- CHANGELOG | 2 + .../Books/Users/ConfigureArango/Arangod.mdpp | 7 --- .../Users/ConfigureArango/RandomNumbers.mdpp | 6 +- Documentation/UserManual/CommandLineTOC.md | 1 - arangod/RestServer/ArangoServer.cpp | 12 +--- arangod/RestServer/ArangoServer.h | 28 --------- arangod/V8Server/v8-vocbase.cpp | 5 -- arangod/VocBase/vocbase-defaults.cpp | 11 +--- arangod/VocBase/vocbase-defaults.h | 1 - arangod/VocBase/vocbase.cpp | 62 ++++--------------- 10 files changed, 17 insertions(+), 118 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index bc70ac6c33..23012d5b23 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,8 @@ v2.2.0 (XXXX-XX-XX) This option had no effect in previous versions of ArangoDB and was thus removed. +* removed startup option `--database.remove-on-drop` + * introduced write-ahead log All write operations in an ArangoDB server instance are automatically logged diff --git a/Documentation/Books/Users/ConfigureArango/Arangod.mdpp b/Documentation/Books/Users/ConfigureArango/Arangod.mdpp index 6b537def69..1bd8aea8c4 100644 --- a/Documentation/Books/Users/ConfigureArango/Arangod.mdpp +++ b/Documentation/Books/Users/ConfigureArango/Arangod.mdpp @@ -346,13 +346,6 @@ If turned off, syncing will still happen for collection that have a waitForSync The default is true. -`--database.remove-on-drop flag` - -If true and you drop a collection, then they directory and all associated datafiles will be removed from disk. If false, then they collection directory will be renamed to deleted-..., but remains on hard disk. To restore such a dropped collection, you can rename the directory back to collection-..., but you must also edit the file parameter.json inside the directory. - -The default is true. - - `--javascript.gc-frequency frequency` Specifies the frequency (in seconds) for the automatic garbage collection of JavaScript objects. This setting is useful to have the garbage collection still work in periods with no or little numbers of requests. diff --git a/Documentation/Books/Users/ConfigureArango/RandomNumbers.mdpp b/Documentation/Books/Users/ConfigureArango/RandomNumbers.mdpp index 75f2553ded..0e7a0dcd0f 100644 --- a/Documentation/Books/Users/ConfigureArango/RandomNumbers.mdpp +++ b/Documentation/Books/Users/ConfigureArango/RandomNumbers.mdpp @@ -6,11 +6,7 @@ The argument is an integer (1,2,3 or 4) which sets the manner in which random nu Specifying an argument of 2, uses a blocking random (or pseudorandom) number generator. Specifying an argument 1 sets a pseudorandom number generator using an implication of the Mersenne Twister MT19937 algorithm. Algorithm 4 is a combination of the blocking random number generator and the Mersenne Twister. -`--random.no-seed` - -By default, the random generator is seeded. Setting this option causes the random number generator not to be seeded. (Seeding the random number generator only occurs if the generator is set to Mersenne, refer to random.generator for details.) - \ No newline at end of file +--> diff --git a/Documentation/UserManual/CommandLineTOC.md b/Documentation/UserManual/CommandLineTOC.md index 0c18fbd2d5..230240c8ff 100644 --- a/Documentation/UserManual/CommandLineTOC.md +++ b/Documentation/UserManual/CommandLineTOC.md @@ -74,4 +74,3 @@ TOC {#CommandLineTOC} - @ref CommandLineSchedulerShowIoBackends "show-io-backends" - @ref CommandLineRandom - @ref CommandLineRandomGenerator "random.generator" - - @ref CommandLineRandomGenerator "random.no-seed" diff --git a/arangod/RestServer/ArangoServer.cpp b/arangod/RestServer/ArangoServer.cpp index 719c713bf7..66173bc78c 100644 --- a/arangod/RestServer/ArangoServer.cpp +++ b/arangod/RestServer/ArangoServer.cpp @@ -284,9 +284,7 @@ ArangoServer::ArangoServer (int argc, char** argv) _defaultMaximalSize(TRI_JOURNAL_DEFAULT_MAXIMAL_SIZE), _defaultWaitForSync(false), _forceSyncProperties(true), - _unusedForceSyncShapes(false), _disableReplicationApplier(false), - _removeOnDrop(true), _server(nullptr) { char* p = TRI_GetTempPath(); @@ -417,6 +415,8 @@ void ArangoServer::buildApplicationServer () { ("ruby.modules-path", &ignoreOpt, "one or more directories separated by (semi-) colons") ("ruby.startup-directory", &ignoreOpt, "path to the directory containing alternate Ruby startup scripts") ("server.disable-replication-logger", &ignoreOpt, "start with replication logger turned off") + ("database.force-sync-shapes", &ignoreOpt, "force syncing of shape data to disk, will use waitForSync value of collection when turned off (deprecated)") + ("database.remove-on-drop", &ignoreOpt, "wipe a collection from disk after dropping") ; // ............................................................................. @@ -501,18 +501,11 @@ void ArangoServer::buildApplicationServer () { ; additional["DATABASE Options:help-admin"] - ("database.remove-on-drop", &_removeOnDrop, "wipe a collection from disk after dropping") ("database.maximal-journal-size", &_defaultMaximalSize, "default maximal journal size, can be overwritten when creating a collection") ("database.wait-for-sync", &_defaultWaitForSync, "default wait-for-sync behavior, can be overwritten when creating a collection") ("database.force-sync-properties", &_forceSyncProperties, "force syncing of collection properties to disk, will use waitForSync value of collection when turned off") ; - // deprecated options - additional[ApplicationServer::OPTIONS_HIDDEN] - ("database.force-sync-shapes", &_unusedForceSyncShapes, "force syncing of shape data to disk, will use waitForSync value of collection when turned off (deprecated)") - ; - - // ............................................................................. // cluster options // ............................................................................. @@ -1098,7 +1091,6 @@ void ArangoServer::openDatabases (bool checkVersion, // override with command-line options defaults.defaultMaximalSize = _defaultMaximalSize; - defaults.removeOnDrop = _removeOnDrop; defaults.defaultWaitForSync = _defaultWaitForSync; defaults.forceSyncProperties = _forceSyncProperties; defaults.requireAuthentication = ! _disableAuthentication; diff --git a/arangod/RestServer/ArangoServer.h b/arangod/RestServer/ArangoServer.h index 16c82ca15b..2033d2ec32 100644 --- a/arangod/RestServer/ArangoServer.h +++ b/arangod/RestServer/ArangoServer.h @@ -393,17 +393,6 @@ namespace triagens { bool _forceSyncProperties; -//////////////////////////////////////////////////////////////////////////////// -/// @brief force syncing of shapes -/// -/// @CMDOPT{\--database.force-sync-shapes @CA{boolean}} -/// -/// This option is not used in this version of ArangoDB. It only remains here -/// for compatibility reasons. -//////////////////////////////////////////////////////////////////////////////// - - bool _unusedForceSyncShapes; - //////////////////////////////////////////////////////////////////////////////// /// @brief disable the replication applier on server startup /// @@ -424,23 +413,6 @@ namespace triagens { bool _disableReplicationApplier; -//////////////////////////////////////////////////////////////////////////////// -/// @brief remove on drop -/// -/// @CMDOPT{\--database.remove-on-drop @CA{flag}} -/// -/// If @LIT{true} and you drop a collection, then they directory and all -/// associated datafiles will be removed from disk. If @LIT{false}, then they -/// collection directory will be renamed to @LIT{deleted-...}, but remains on -/// hard disk. To restore such a dropped collection, you can rename the -/// directory back to @LIT{collection-...}, but you must also edit the file -/// @LIT{parameter.json} inside the directory. -/// -/// The default is @LIT{true}. -//////////////////////////////////////////////////////////////////////////////// - - bool _removeOnDrop; - //////////////////////////////////////////////////////////////////////////////// /// @brief unit tests /// diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index c1d0326322..5a96e0ae7f 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -8976,7 +8976,6 @@ static v8::Handle JS_CreateDatabase (v8::Arguments const& argv) { TRI_vocbase_defaults_t defaults; TRI_GetDatabaseDefaultsServer((TRI_server_t*) v8g->_server, &defaults); - v8::Local keyRemoveOnDrop = v8::String::New("removeOnDrop"); v8::Local keyDefaultMaximalSize = v8::String::New("defaultMaximalSize"); v8::Local keyDefaultWaitForSync = v8::String::New("defaultWaitForSync"); v8::Local keyForceSyncProperties = v8::String::New("forceSyncProperties"); @@ -8988,10 +8987,6 @@ static v8::Handle JS_CreateDatabase (v8::Arguments const& argv) { if (argv.Length() > 1 && argv[1]->IsObject()) { v8::Handle options = argv[1]->ToObject(); - if (options->Has(keyRemoveOnDrop)) { - defaults.removeOnDrop = options->Get(keyRemoveOnDrop)->BooleanValue(); - } - if (options->Has(keyDefaultMaximalSize)) { defaults.defaultMaximalSize = (TRI_voc_size_t) options->Get(keyDefaultMaximalSize)->IntegerValue(); } diff --git a/arangod/VocBase/vocbase-defaults.cpp b/arangod/VocBase/vocbase-defaults.cpp index 2f78ff6076..e8ac937ba8 100644 --- a/arangod/VocBase/vocbase-defaults.cpp +++ b/arangod/VocBase/vocbase-defaults.cpp @@ -42,7 +42,6 @@ void TRI_ApplyVocBaseDefaults (TRI_vocbase_t* vocbase, TRI_vocbase_defaults_t const* defaults) { vocbase->_settings.defaultMaximalSize = defaults->defaultMaximalSize; - vocbase->_settings.removeOnDrop = defaults->removeOnDrop; vocbase->_settings.defaultWaitForSync = defaults->defaultWaitForSync; vocbase->_settings.forceSyncProperties = defaults->forceSyncProperties; vocbase->_settings.requireAuthentication = defaults->requireAuthentication; @@ -64,7 +63,6 @@ TRI_json_t* TRI_JsonVocBaseDefaults (TRI_memory_zone_t* zone, return NULL; } - TRI_Insert3ArrayJson(zone, json, "removeOnDrop", TRI_CreateBooleanJson(zone, defaults->removeOnDrop)); TRI_Insert3ArrayJson(zone, json, "waitForSync", TRI_CreateBooleanJson(zone, defaults->defaultWaitForSync)); TRI_Insert3ArrayJson(zone, json, "forceSyncProperties", TRI_CreateBooleanJson(zone, defaults->forceSyncProperties)); TRI_Insert3ArrayJson(zone, json, "requireAuthentication", TRI_CreateBooleanJson(zone, defaults->requireAuthentication)); @@ -81,18 +79,11 @@ TRI_json_t* TRI_JsonVocBaseDefaults (TRI_memory_zone_t* zone, void TRI_FromJsonVocBaseDefaults (TRI_vocbase_defaults_t* defaults, TRI_json_t const* json) { - TRI_json_t* optionJson; - if (! TRI_IsArrayJson(json)) { return; } - optionJson = TRI_LookupArrayJson(json, "removeOnDrop"); - - if (TRI_IsBooleanJson(optionJson)) { - defaults->removeOnDrop = optionJson->_value._boolean; - } - + TRI_json_t* optionJson; optionJson = TRI_LookupArrayJson(json, "waitForSync"); if (TRI_IsBooleanJson(optionJson)) { diff --git a/arangod/VocBase/vocbase-defaults.h b/arangod/VocBase/vocbase-defaults.h index 25ae82e617..8b62ad94d2 100644 --- a/arangod/VocBase/vocbase-defaults.h +++ b/arangod/VocBase/vocbase-defaults.h @@ -46,7 +46,6 @@ struct TRI_vocbase_s; typedef struct TRI_vocbase_defaults_s { TRI_voc_size_t defaultMaximalSize; - bool removeOnDrop; bool defaultWaitForSync; bool forceSyncProperties; bool requireAuthentication; diff --git a/arangod/VocBase/vocbase.cpp b/arangod/VocBase/vocbase.cpp index 804331eae0..0990e36a78 100644 --- a/arangod/VocBase/vocbase.cpp +++ b/arangod/VocBase/vocbase.cpp @@ -409,23 +409,15 @@ static bool DropCollectionCallback (TRI_collection_t* col, newFilename); } else { - if (collection->_vocbase->_settings.removeOnDrop) { - LOG_DEBUG("wiping dropped collection '%s' from disk", - collection->_name); + LOG_DEBUG("wiping dropped collection '%s' from disk", + collection->_name); - res = TRI_RemoveDirectory(newFilename); + res = TRI_RemoveDirectory(newFilename); - if (res != TRI_ERROR_NO_ERROR) { - LOG_ERROR("cannot wipe dropped collecton '%s' from disk: %s", - collection->_name, - TRI_last_error()); - } - } - else { - LOG_DEBUG("renamed dropped collection '%s' from '%s' to '%s'", + if (res != TRI_ERROR_NO_ERROR) { + LOG_ERROR("cannot wipe dropped collection '%s' from disk: %s", collection->_name, - collection->_path, - newFilename); + TRI_last_error()); } } @@ -906,45 +898,13 @@ static int ScanPath (TRI_vocbase_t* vocbase, } else if (info._deleted) { // we found a collection that is marked as deleted. - // it depends on the configuration what will happen with these collections + // deleted collections should be removed on startup. this is the default + LOG_DEBUG("collection '%s' was deleted, wiping it", name); - if (vocbase->_settings.removeOnDrop) { - // deleted collections should be removed on startup. this is the default - LOG_DEBUG("collection '%s' was deleted, wiping it", name); + res = TRI_RemoveDirectory(file); - res = TRI_RemoveDirectory(file); - - if (res != TRI_ERROR_NO_ERROR) { - LOG_WARNING("cannot wipe deleted collection: %s", TRI_last_error()); - } - } - else { - // deleted collections shout not be removed on startup - char* newFile; - char* tmp1; - char* tmp2; - - char const* first = name + matches[1].rm_so; - size_t firstLen = matches[1].rm_eo - matches[1].rm_so; - - tmp1 = TRI_DuplicateString2(first, firstLen); - tmp2 = TRI_Concatenate2String("deleted-", tmp1); - - TRI_FreeString(TRI_CORE_MEM_ZONE, tmp1); - - newFile = TRI_Concatenate2File(path, tmp2); - - TRI_FreeString(TRI_CORE_MEM_ZONE, tmp2); - - LOG_WARNING("collection '%s' was deleted, renaming it to '%s'", name, newFile); - - res = TRI_RenameFile(file, newFile); - - if (res != TRI_ERROR_NO_ERROR) { - LOG_WARNING("cannot rename deleted collection: %s", TRI_last_error()); - } - - TRI_FreeString(TRI_CORE_MEM_ZONE, newFile); + if (res != TRI_ERROR_NO_ERROR) { + LOG_WARNING("cannot wipe deleted collection: %s", TRI_last_error()); } } else { From e049f85b4441f076a22af7a7d2795868430eaa4d Mon Sep 17 00:00:00 2001 From: gschwab Date: Tue, 24 Jun 2014 11:54:42 +0200 Subject: [PATCH 11/21] docu --- .../Books/Users/General-Graphs/README.mdpp | 2 +- .../js/modules/org/arangodb/general-graph.js | 40 +++++++++++++++++++ .../modules/org/arangodb/general-graph.js | 26 +++++++----- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/Documentation/Books/Users/General-Graphs/README.mdpp b/Documentation/Books/Users/General-Graphs/README.mdpp index c0bbf28435..0d4d9f821b 100644 --- a/Documentation/Books/Users/General-Graphs/README.mdpp +++ b/Documentation/Books/Users/General-Graphs/README.mdpp @@ -12,6 +12,6 @@ collections*. In general a vertex is stored in a document collection. Which coll a graph is defined via *edge definitions*. A graph can have an arbitrary number of edge definitions. -!Subsection Three Steps to create a graph +!SUBSUBSECTION Three Steps to create a graph @startDocuBlock JSF_general_graph_how_to_create \ No newline at end of file diff --git a/js/apps/system/aardvark/frontend/js/modules/org/arangodb/general-graph.js b/js/apps/system/aardvark/frontend/js/modules/org/arangodb/general-graph.js index e958b2959a..f6f5fda83f 100644 --- a/js/apps/system/aardvark/frontend/js/modules/org/arangodb/general-graph.js +++ b/js/apps/system/aardvark/frontend/js/modules/org/arangodb/general-graph.js @@ -1539,6 +1539,44 @@ var _extendEdgeDefinitions = function (edgeDefinition) { //////////////////////////////////////////////////////////////////////////////// /// @brief create a new graph //////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +/// @startDocuBlock JSF_general_graph_how_to_create +/// +/// * Create a graph +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraphHowTo1} +/// var graph_module = require("org/arangodb/general-graph"); +/// var graph = graph_module._create("myGraph"); +/// graph; +/// ~ graph_module._drop("myGraph"); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// +/// * Add some vertex collections +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraphHowTo2} +/// ~ var graph_module = require("org/arangodb/general-graph"); +/// ~ var graph = graph_module._create("myGraph"); +/// graph._addVertexCollection("shop"); +/// graph._addVertexCollection("customer"); +/// graph._addVertexCollection("pet"); +/// graph; +/// ~ graph_module._drop("myGraph"); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// +/// * Define relations on the +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraphHowTo3} +/// ~ var graph_module = require("org/arangodb/general-graph"); +/// ~ var graph = graph_module._create("myGraph"); +/// var rel = graph_module._directedRelation("isCustomer", ["shop"], ["customer"]); +/// graph._extendEdgeDefinitions(rel); +/// graph; +/// ~ graph_module._drop("myGraph"); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// +/// @endDocuBlock +/// +//////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// @startDocuBlock JSF_general_graph_create @@ -3930,6 +3968,8 @@ Graph.prototype._PRINT = function(context) { context.output += name; context.output += " EdgeDefinitions: "; internal.printRecursive(edgeDefs, context); + context.output += " VertexCollections: "; + internal.printRecursive(this.__orphanCollections, context); context.output += " ]"; }; diff --git a/js/common/modules/org/arangodb/general-graph.js b/js/common/modules/org/arangodb/general-graph.js index bb9e953fd7..fa7bf848f9 100644 --- a/js/common/modules/org/arangodb/general-graph.js +++ b/js/common/modules/org/arangodb/general-graph.js @@ -1541,34 +1541,38 @@ var _extendEdgeDefinitions = function (edgeDefinition) { //////////////////////////////////////////////////////////////////////////////// /// @startDocuBlock JSF_general_graph_how_to_create /// -/// 1. Create a graph +/// * Create a graph /// /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraphHowTo1} /// var graph_module = require("org/arangodb/general-graph"); -/// graph = graph_module._create("myGraph"); -/// ~ graph_module._drop("mygraph"); +/// var graph = graph_module._create("myGraph"); +/// graph; +/// ~ graph_module._drop("myGraph"); /// @END_EXAMPLE_ARANGOSH_OUTPUT /// -/// 2. Add some vertex collections +/// * Add some vertex collections /// /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraphHowTo2} /// ~ var graph_module = require("org/arangodb/general-graph"); -/// ~ graph = graph_module._create("mygraph"); +/// ~ var graph = graph_module._create("myGraph"); /// graph._addVertexCollection("shop"); /// graph._addVertexCollection("customer"); /// graph._addVertexCollection("pet"); -/// ~ graph_module._drop("mygraph"); +/// graph; +/// ~ graph_module._drop("myGraph"); /// @END_EXAMPLE_ARANGOSH_OUTPUT /// -/// 3. Define relations on the +/// * Define relations on the /// /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphCreateGraphHowTo3} /// ~ var graph_module = require("org/arangodb/general-graph"); -/// ~ graph = graph_module._create("mygraph"); -/// var rel = graph_module._undirectedRelation("isCustomer", ["shop"], ["customer]); +/// ~ var graph = graph_module._create("myGraph"); +/// var rel = graph_module._directedRelation("isCustomer", ["shop"], ["customer"]); /// graph._extendEdgeDefinitions(rel); -/// ~ graph_module._drop("mygraph"); +/// graph; +/// ~ graph_module._drop("myGraph"); /// @END_EXAMPLE_ARANGOSH_OUTPUT +/// /// @endDocuBlock /// //////////////////////////////////////////////////////////////////////////////// @@ -3963,6 +3967,8 @@ Graph.prototype._PRINT = function(context) { context.output += name; context.output += " EdgeDefinitions: "; internal.printRecursive(edgeDefs, context); + context.output += " VertexCollections: "; + internal.printRecursive(this.__orphanCollections, context); context.output += " ]"; }; From 303378d8e2f0880305b4ac885030df9e58013a32 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 24 Jun 2014 12:06:47 +0200 Subject: [PATCH 12/21] honor `--server.disable-statistics` --- CHANGELOG | 6 ++++++ arangod/V8Server/v8-vocbase.cpp | 5 +++++ js/server/server.js | 7 ++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 23012d5b23..a740b8bff3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,12 @@ v2.2.0 (XXXX-XX-XX) ------------------- +* honor startup option `--server.disable-statistics` when deciding whether or not + to start periodic statistics collection jobs + + Previously, the statistics collection jobs were started even if the server was + started with the `--server.disable-statistics` flag being set to `true` + * removed startup option `--random.no-seed` This option had no effect in previous versions of ArangoDB and was thus removed. diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index 5a96e0ae7f..68072b69f8 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -95,6 +95,8 @@ using namespace triagens::rest; static v8::Handle WrapGeneralCursor (void* cursor); +extern bool TRI_ENABLE_STATISTICS; + // ----------------------------------------------------------------------------- // --SECTION-- private defines // ----------------------------------------------------------------------------- @@ -10160,6 +10162,9 @@ void TRI_InitV8VocBridge (v8::Handle context, // current thread number context->Global()->Set(TRI_V8_SYMBOL("THREAD_NUMBER"), v8::Number::New((double) threadNumber), v8::ReadOnly); + + // whether or not statistics are enabled + context->Global()->Set(TRI_V8_SYMBOL("ENABLE_STATISTICS"), v8::Boolean::New(TRI_ENABLE_STATISTICS), v8::ReadOnly); } // ----------------------------------------------------------------------------- diff --git a/js/server/server.js b/js/server/server.js index bd8428956c..f956575f42 100644 --- a/js/server/server.js +++ b/js/server/server.js @@ -1,5 +1,5 @@ /*jslint indent: 2, nomen: true, maxlen: 120, sloppy: true, vars: true, white: true, plusplus: true */ -/*global require */ +/*global require, ENABLE_STATISTICS */ //////////////////////////////////////////////////////////////////////////////// /// @brief JavaScript server functions @@ -50,6 +50,11 @@ var Buffer = require("buffer").Buffer; //////////////////////////////////////////////////////////////////////////////// (function () { + if (! ENABLE_STATISTICS) { + // statistics are turned off + return; + } + var internal = require("internal"); var interval = require('org/arangodb/statistics').STATISTICS_INTERVAL; var interval15 = require('org/arangodb/statistics').STATISTICS_HISTORY_INTERVAL; From 7756deff01f65aae100d7ae404651273dec15553 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 24 Jun 2014 12:07:00 +0200 Subject: [PATCH 13/21] typo --- arangod/Wal/LogfileManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arangod/Wal/LogfileManager.cpp b/arangod/Wal/LogfileManager.cpp index c37e4098c1..33c97e4aef 100644 --- a/arangod/Wal/LogfileManager.cpp +++ b/arangod/Wal/LogfileManager.cpp @@ -336,7 +336,7 @@ void LogfileManager::setupOptions (std::map Date: Tue, 24 Jun 2014 12:48:42 +0200 Subject: [PATCH 14/21] Added HMAC-SHA224, exposed SHA1, SHA224. --- .../frontend/js/bootstrap/module-internal.js | 36 ++++++-- js/common/bootstrap/module-internal.js | 36 ++++++-- js/common/modules/org/arangodb/crypto.js | 16 ++++ js/common/tests/shell-crypto.js | 68 +++++++++++++++ lib/Rest/SslInterface.cpp | 3 + lib/Rest/SslInterface.h | 3 +- lib/V8/v8-utils.cpp | 85 +++++++++++++++++++ 7 files changed, 228 insertions(+), 19 deletions(-) diff --git a/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js b/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js index 96796f6367..ccc68f3507 100644 --- a/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js +++ b/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js @@ -1,15 +1,15 @@ /*jslint indent: 2, nomen: true, maxlen: 120, vars: true, white: true, plusplus: true, nonpropdel: true, proto: true */ /*jslint sloppy: true, regexp: true */ /*global require, module, Module, ArangoError, SleepAndRequeue, - REPLICATION_LOGGER_STATE, REPLICATION_LOGGER_CONFIGURE, REPLICATION_APPLIER_CONFIGURE, REPLICATION_APPLIER_START, + REPLICATION_LOGGER_STATE, REPLICATION_LOGGER_CONFIGURE, REPLICATION_APPLIER_CONFIGURE, REPLICATION_APPLIER_START, REPLICATION_APPLIER_STOP, REPLICATION_APPLIER_FORGET, REPLICATION_APPLIER_STATE, REPLICATION_SYNCHRONISE, REPLICATION_SERVER_ID, CONFIGURE_ENDPOINT, REMOVE_ENDPOINT, LIST_ENDPOINTS, SYS_BASE64DECODE, SYS_BASE64ENCODE, SYS_DEBUG_SEGFAULT, - SYS_DEBUG_CAN_USE_FAILAT, SYS_DEBUG_SET_FAILAT, SYS_DEBUG_REMOVE_FAILAT, SYS_DEBUG_CLEAR_FAILAT, - SYS_DOWNLOAD, SYS_EXECUTE, SYS_GET_CURRENT_REQUEST, SYS_GET_CURRENT_RESPONSE, + SYS_DEBUG_CAN_USE_FAILAT, SYS_DEBUG_SET_FAILAT, SYS_DEBUG_REMOVE_FAILAT, SYS_DEBUG_CLEAR_FAILAT, + SYS_DOWNLOAD, SYS_EXECUTE, SYS_GET_CURRENT_REQUEST, SYS_GET_CURRENT_RESPONSE, SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS, - SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER, - SYS_HMAC, SYS_SHA256, SYS_SLEEP, SYS_WAIT, SYS_PARSE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, SYS_LOG, + SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER, + SYS_HMAC, SYS_SHA256, SYS_SHA224, SYS_SHA1, SYS_SLEEP, SYS_WAIT, SYS_PARSE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, SYS_LOG, SYS_GEN_RANDOM_NUMBERS, SYS_GEN_RANDOM_ALPHA_NUMBERS, SYS_GEN_RANDOM_SALT, SYS_CREATE_NONCE, SYS_CHECK_AND_MARK_NONCE, SYS_CLIENT_STATISTICS, SYS_HTTP_STATISTICS, SYS_UNIT_TESTS, SYS_UNIT_TESTS_RESULT:true, SYS_PROCESS_CSV_FILE, SYS_PROCESS_JSON_FILE, ARANGO_QUIET, COLORS, COLOR_OUTPUT, @@ -81,10 +81,10 @@ this.message = this.toString(); }; - - exports.ArangoError.prototype = new Error(); - } - + + exports.ArangoError.prototype = new Error(); + } + exports.ArangoError.prototype._PRINT = function (context) { context.output += this.toString(); }; @@ -613,6 +613,24 @@ delete SYS_SHA256; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief sha224 +//////////////////////////////////////////////////////////////////////////////// + + if (typeof SYS_SHA224 !== "undefined") { + exports.sha224 = SYS_SHA224; + delete SYS_SHA224; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief sha1 +//////////////////////////////////////////////////////////////////////////////// + + if (typeof SYS_SHA1 !== "undefined") { + exports.sha1 = SYS_SHA1; + delete SYS_SHA1; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief serverStatistics //////////////////////////////////////////////////////////////////////////////// diff --git a/js/common/bootstrap/module-internal.js b/js/common/bootstrap/module-internal.js index 96796f6367..ccc68f3507 100644 --- a/js/common/bootstrap/module-internal.js +++ b/js/common/bootstrap/module-internal.js @@ -1,15 +1,15 @@ /*jslint indent: 2, nomen: true, maxlen: 120, vars: true, white: true, plusplus: true, nonpropdel: true, proto: true */ /*jslint sloppy: true, regexp: true */ /*global require, module, Module, ArangoError, SleepAndRequeue, - REPLICATION_LOGGER_STATE, REPLICATION_LOGGER_CONFIGURE, REPLICATION_APPLIER_CONFIGURE, REPLICATION_APPLIER_START, + REPLICATION_LOGGER_STATE, REPLICATION_LOGGER_CONFIGURE, REPLICATION_APPLIER_CONFIGURE, REPLICATION_APPLIER_START, REPLICATION_APPLIER_STOP, REPLICATION_APPLIER_FORGET, REPLICATION_APPLIER_STATE, REPLICATION_SYNCHRONISE, REPLICATION_SERVER_ID, CONFIGURE_ENDPOINT, REMOVE_ENDPOINT, LIST_ENDPOINTS, SYS_BASE64DECODE, SYS_BASE64ENCODE, SYS_DEBUG_SEGFAULT, - SYS_DEBUG_CAN_USE_FAILAT, SYS_DEBUG_SET_FAILAT, SYS_DEBUG_REMOVE_FAILAT, SYS_DEBUG_CLEAR_FAILAT, - SYS_DOWNLOAD, SYS_EXECUTE, SYS_GET_CURRENT_REQUEST, SYS_GET_CURRENT_RESPONSE, + SYS_DEBUG_CAN_USE_FAILAT, SYS_DEBUG_SET_FAILAT, SYS_DEBUG_REMOVE_FAILAT, SYS_DEBUG_CLEAR_FAILAT, + SYS_DOWNLOAD, SYS_EXECUTE, SYS_GET_CURRENT_REQUEST, SYS_GET_CURRENT_RESPONSE, SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS, - SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER, - SYS_HMAC, SYS_SHA256, SYS_SLEEP, SYS_WAIT, SYS_PARSE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, SYS_LOG, + SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER, + SYS_HMAC, SYS_SHA256, SYS_SHA224, SYS_SHA1, SYS_SLEEP, SYS_WAIT, SYS_PARSE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, SYS_LOG, SYS_GEN_RANDOM_NUMBERS, SYS_GEN_RANDOM_ALPHA_NUMBERS, SYS_GEN_RANDOM_SALT, SYS_CREATE_NONCE, SYS_CHECK_AND_MARK_NONCE, SYS_CLIENT_STATISTICS, SYS_HTTP_STATISTICS, SYS_UNIT_TESTS, SYS_UNIT_TESTS_RESULT:true, SYS_PROCESS_CSV_FILE, SYS_PROCESS_JSON_FILE, ARANGO_QUIET, COLORS, COLOR_OUTPUT, @@ -81,10 +81,10 @@ this.message = this.toString(); }; - - exports.ArangoError.prototype = new Error(); - } - + + exports.ArangoError.prototype = new Error(); + } + exports.ArangoError.prototype._PRINT = function (context) { context.output += this.toString(); }; @@ -613,6 +613,24 @@ delete SYS_SHA256; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief sha224 +//////////////////////////////////////////////////////////////////////////////// + + if (typeof SYS_SHA224 !== "undefined") { + exports.sha224 = SYS_SHA224; + delete SYS_SHA224; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief sha1 +//////////////////////////////////////////////////////////////////////////////// + + if (typeof SYS_SHA1 !== "undefined") { + exports.sha1 = SYS_SHA1; + delete SYS_SHA1; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief serverStatistics //////////////////////////////////////////////////////////////////////////////// diff --git a/js/common/modules/org/arangodb/crypto.js b/js/common/modules/org/arangodb/crypto.js index da3d1fac73..9cc79d13fd 100644 --- a/js/common/modules/org/arangodb/crypto.js +++ b/js/common/modules/org/arangodb/crypto.js @@ -81,6 +81,22 @@ exports.sha256 = function (value) { return internal.sha256(value); }; +//////////////////////////////////////////////////////////////////////////////// +/// @brief apply an SHA 224 hash +//////////////////////////////////////////////////////////////////////////////// + +exports.sha224 = function (value) { + return internal.sha224(value); +}; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief apply an SHA 1 hash +//////////////////////////////////////////////////////////////////////////////// + +exports.sha1 = function (value) { + return internal.sha1(value); +}; + //////////////////////////////////////////////////////////////////////////////// /// @brief Generates a string of a given length containing numbers. //////////////////////////////////////////////////////////////////////////////// diff --git a/js/common/tests/shell-crypto.js b/js/common/tests/shell-crypto.js index c417e35a21..9faf1e8907 100644 --- a/js/common/tests/shell-crypto.js +++ b/js/common/tests/shell-crypto.js @@ -105,6 +105,72 @@ function CryptoSuite () { }); }, +//////////////////////////////////////////////////////////////////////////////// +/// @brief test sha224, invalid values +//////////////////////////////////////////////////////////////////////////////// + + testSha224Invalid : function () { + [ undefined, null, true, false, 0, 1, -1, 32.5, [ ], { } ].forEach(function (value) { + try { + crypto.sha224(value); + fail(); + } + catch (err) { + } + }); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test sha224 +//////////////////////////////////////////////////////////////////////////////// + + testSha224 : function () { + var data = [ + [ "", "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f" ], + [ " ", "ca17734c016e36b898af29c1aeb142e774abf4b70bac55ec98a27ba8"], + [ "arangodb", "deeb6d8f9b6c316e7f5a601fb2549a2ebc857bee78df38b1977c9989" ], + [ "Arangodb", "6d7a8a7fb22537dab437c8c2915874a170b2b14eb1aa787df32d6999" ], + [ "ArangoDB is a database", "9a3e02d47eb686c67f6b9a51efe16e8b4f88b0ee14248636d6163f1d" ] + ]; + + data.forEach(function (value) { + assertEqual(value[1], crypto.sha224(value[0])); + }); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test sha1, invalid values +//////////////////////////////////////////////////////////////////////////////// + + testSha1Invalid : function () { + [ undefined, null, true, false, 0, 1, -1, 32.5, [ ], { } ].forEach(function (value) { + try { + crypto.sha1(value); + fail(); + } + catch (err) { + } + }); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test sha1 +//////////////////////////////////////////////////////////////////////////////// + + testSha1 : function () { + var data = [ + [ "", "da39a3ee5e6b4b0d3255bfef95601890afd80709" ], + [ " ", "b858cb282617fb0956d960215c8e84d1ccf909c6"], + [ "arangodb", "1f9aa6577198dd5fcab487d08d45258608dac9b5" ], + [ "Arangodb", "5fc1b451c5cd4770df14bd3ae362b5587a195311" ], + [ "ArangoDB is a database", "9e45475b50ea3e8438c55919238aa5b0736bda43" ] + ]; + + data.forEach(function (value) { + assertEqual(value[1], crypto.sha1(value[0])); + }); + }, + //////////////////////////////////////////////////////////////////////////////// /// @brief test hmac, invalid values //////////////////////////////////////////////////////////////////////////////// @@ -142,6 +208,8 @@ function CryptoSuite () { [ "secret", "Arangodb", "sha256", "95144e880bbc4a4bf10a2b683603c763a38817b544e1c2f6ff1bd3523bf60f9e" ], [ "secret", "ArangoDB is a database", "sha256", "4888d586d3208ca18ebaf78569949a13f3c03585edb007771cd820820a351b0f" ], [ "SECRET", "ArangoDB is a database", "sha256", "a04df5ce362f49439db5e30032b20e0fa64d01c60ceb32a9150e58d3c2c929af" ], + [ "secret", "ArangoDB is a database", "sha224", "b55c13e25227abf919b510cf2289f4501fa13584676e7e4d56108172" ], + [ "secret", "ArangoDB is a database", "SHA224", "b55c13e25227abf919b510cf2289f4501fa13584676e7e4d56108172" ], [ "secret", "ArangoDB is a database", "sha1", "f39d7a76e502ba3f79d663cfbc9ac43eb6fd323e" ], [ "secret", "ArangoDB is a database", "SHA1", "f39d7a76e502ba3f79d663cfbc9ac43eb6fd323e" ], [ "secret", "ArangoDB is a database", "md5", "6eecfc947725974efc24bbaaafe15a13" ], diff --git a/lib/Rest/SslInterface.cpp b/lib/Rest/SslInterface.cpp index e301baf2f0..4c63104ae5 100644 --- a/lib/Rest/SslInterface.cpp +++ b/lib/Rest/SslInterface.cpp @@ -190,6 +190,9 @@ namespace triagens { if (algorithm == Algorithm::ALGORITHM_SHA1) { evp_md = const_cast(EVP_sha1()); } + else if (algorithm == Algorithm::ALGORITHM_SHA224) { + evp_md = const_cast(EVP_sha224()); + } else if (algorithm == Algorithm::ALGORITHM_MD5) { evp_md = const_cast(EVP_md5()); } diff --git a/lib/Rest/SslInterface.h b/lib/Rest/SslInterface.h index 9db30df18b..0bedc036c1 100644 --- a/lib/Rest/SslInterface.h +++ b/lib/Rest/SslInterface.h @@ -39,7 +39,8 @@ namespace triagens { enum Algorithm { ALGORITHM_SHA256 = 0, ALGORITHM_SHA1 = 1, - ALGORITHM_MD5 = 2 + ALGORITHM_MD5 = 2, + ALGORITHM_SHA224 = 3 }; ////////////////////////////////////////////////////////////////////////// diff --git a/lib/V8/v8-utils.cpp b/lib/V8/v8-utils.cpp index ec109ba1d3..56f23ec462 100644 --- a/lib/V8/v8-utils.cpp +++ b/lib/V8/v8-utils.cpp @@ -2273,6 +2273,86 @@ static v8::Handle JS_Sha256 (v8::Arguments const& argv) { return scope.Close(hashStr); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief computes the sha224 sum +/// +/// @FUN{internal.sha224(@FA{text})} +/// +/// Computes an sha224 for the @FA{text}. +//////////////////////////////////////////////////////////////////////////////// + +static v8::Handle JS_Sha224 (v8::Arguments const& argv) { + v8::HandleScope scope; + + // extract arguments + if (argv.Length() != 1 || ! argv[0]->IsString()) { + TRI_V8_EXCEPTION_USAGE(scope, "sha224()"); + } + + string key = TRI_ObjectToString(argv[0]); + + // create sha224 + char* hash = 0; + size_t hashLen; + + SslInterface::sslSHA224(key.c_str(), key.size(), hash, hashLen); + + // as hex + char* hex = 0; + size_t hexLen; + + SslInterface::sslHEX(hash, hashLen, hex, hexLen); + + delete[] hash; + + // and return + v8::Handle hashStr = v8::String::New(hex, (int) hexLen); + + delete[] hex; + + return scope.Close(hashStr); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief computes the sha1 sum +/// +/// @FUN{internal.sha1(@FA{text})} +/// +/// Computes an sha1 for the @FA{text}. +//////////////////////////////////////////////////////////////////////////////// + +static v8::Handle JS_Sha1 (v8::Arguments const& argv) { + v8::HandleScope scope; + + // extract arguments + if (argv.Length() != 1 || ! argv[0]->IsString()) { + TRI_V8_EXCEPTION_USAGE(scope, "sha1()"); + } + + string key = TRI_ObjectToString(argv[0]); + + // create sha1 + char* hash = 0; + size_t hashLen; + + SslInterface::sslSHA1(key.c_str(), key.size(), hash, hashLen); + + // as hex + char* hex = 0; + size_t hexLen; + + SslInterface::sslHEX(hash, hashLen, hex, hexLen); + + delete[] hash; + + // and return + v8::Handle hashStr = v8::String::New(hex, (int) hexLen); + + delete[] hex; + + return scope.Close(hashStr); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief sleeps /// @@ -2565,6 +2645,9 @@ static v8::Handle JS_HMAC (v8::Arguments const& argv) { else if (algorithm == "sha256") { al = SslInterface::Algorithm::ALGORITHM_SHA256; } + else if (algorithm == "sha224") { + al = SslInterface::Algorithm::ALGORITHM_SHA224; + } else if (algorithm == "md5") { al = SslInterface::Algorithm::ALGORITHM_MD5; } @@ -3391,6 +3474,8 @@ void TRI_InitV8Utils (v8::Handle context, TRI_AddGlobalFunctionVocbase(context, "SYS_SAVE", JS_Save); TRI_AddGlobalFunctionVocbase(context, "SYS_SERVER_STATISTICS", JS_ServerStatistics); TRI_AddGlobalFunctionVocbase(context, "SYS_SHA256", JS_Sha256); + TRI_AddGlobalFunctionVocbase(context, "SYS_SHA224", JS_Sha224); + TRI_AddGlobalFunctionVocbase(context, "SYS_SHA1", JS_Sha1); TRI_AddGlobalFunctionVocbase(context, "SYS_SLEEP", JS_Sleep); TRI_AddGlobalFunctionVocbase(context, "SYS_SPRINTF", JS_SPrintF); TRI_AddGlobalFunctionVocbase(context, "SYS_STATUS_EXTERNAL", JS_StatusExternal); From 4f01409c4bf20790be5dbefc92bb3cf4ded49d48 Mon Sep 17 00:00:00 2001 From: scottashton Date: Tue, 24 Jun 2014 13:13:01 +0200 Subject: [PATCH 15/21] processed lucas feedback regarding aql docu --- .../Books/Users/Aql/GraphOperations.mdpp | 9 +- .../Books/Users/General-Graphs/Functions.mdpp | 11 + arangod/Ahuacatl/ahuacatl-functions.cpp | 2 +- .../modules/org/arangodb/general-graph.js | 221 +++++++++++++++++- js/common/tests/shell-general-graph.js | 28 ++- js/server/modules/org/arangodb/ahuacatl.js | 166 ++++++------- 6 files changed, 340 insertions(+), 97 deletions(-) diff --git a/Documentation/Books/Users/Aql/GraphOperations.mdpp b/Documentation/Books/Users/Aql/GraphOperations.mdpp index 81f0d0b682..55530fef13 100644 --- a/Documentation/Books/Users/Aql/GraphOperations.mdpp +++ b/Documentation/Books/Users/Aql/GraphOperations.mdpp @@ -10,7 +10,6 @@ A lot of the following functions accept a vertex (or edge) example as parameter. * *idString* : Returns the vertex/edge with the id *idString*. * {*key1* : *value1*, *key2* : *value2*} : Returns the vertices/edges that match this example, which means that both have *key1* and *key2* with the corresponding attributes. * [{*key1* : *value1*}, {*key2* : *value2*}] : Returns the vertices/edges that match one of the examples, which means that either *key1* or *key2* are set with the corresponding value. -the examples. !SUBSECTION Edges and Vertices related functions @@ -24,6 +23,10 @@ This section describes various AQL functions which can be used to receive inform @startDocuBlock JSF_ahuacatl_general_graph_vertices +!SUBSUBSECTION GRAPH_NEIGHBORS + +@startDocuBlock JSF_ahuacatl_general_graph_neighbors + !SUBSUBSECTION GRAPH_COMMON_NEIGHBORS @startDocuBlock JSF_ahuacatl_general_graph_common_neighbors @@ -32,10 +35,6 @@ This section describes various AQL functions which can be used to receive inform @startDocuBlock JSF_ahuacatl_general_graph_common_properties -!SUBSUBSECTION GRAPH_NEIGHBORS - -@startDocuBlock JSF_ahuacatl_general_graph_neighbors - !SUBSECTION Shortest Paths, distances and traversals. This section describes AQL functions, that calculate pathes from a subset of vertices in a graph to another subset of vertices. diff --git a/Documentation/Books/Users/General-Graphs/Functions.mdpp b/Documentation/Books/Users/General-Graphs/Functions.mdpp index 7977ea2fa0..f8ae4b9ba8 100644 --- a/Documentation/Books/Users/General-Graphs/Functions.mdpp +++ b/Documentation/Books/Users/General-Graphs/Functions.mdpp @@ -37,6 +37,17 @@ A lot of these accept a vertex (or edge) example as parameter as defined in the @startDocuBlock JSF_general_graph_count_common_properties +!SECTION _paths + +@startDocuBlock JSF_general_graph_paths + +!SECTION _shortestPath + +@startDocuBlock JSF_general_graph_shortest_path + +!SECTION _distanceTo + +@startDocuBlock JSF_general_graph_distance_to !SECTION _absoluteEccentricity diff --git a/arangod/Ahuacatl/ahuacatl-functions.cpp b/arangod/Ahuacatl/ahuacatl-functions.cpp index e880184730..98089e9cd6 100644 --- a/arangod/Ahuacatl/ahuacatl-functions.cpp +++ b/arangod/Ahuacatl/ahuacatl-functions.cpp @@ -668,7 +668,7 @@ TRI_associative_pointer_t* TRI_CreateFunctionsAql (void) { // graph functions REGISTER_FUNCTION("PATHS", "GRAPH_PATHS", false, false, "c,h|s,b", &OptimisePaths); - REGISTER_FUNCTION("GRAPH_PATHS", "GENERAL_GRAPH_PATHS", false, false, "s|s,b,n,n", &OptimisePaths); + REGISTER_FUNCTION("GRAPH_PATHS", "GENERAL_GRAPH_PATHS", false, false, "s|a", &OptimisePaths); REGISTER_FUNCTION("SHORTEST_PATH", "GRAPH_SHORTEST_PATH", false, false, "h,h,s,s,s|a", NULL); REGISTER_FUNCTION("GRAPH_SHORTEST_PATH", "GENERAL_GRAPH_SHORTEST_PATH", false, false, "s,als,als|a", NULL); REGISTER_FUNCTION("GRAPH_DISTANCE_TO", "GENERAL_GRAPH_DISTANCE_TO", false, false, "s,als,als|a", NULL); diff --git a/js/common/modules/org/arangodb/general-graph.js b/js/common/modules/org/arangodb/general-graph.js index 6d6136b2b5..c51a384f8d 100644 --- a/js/common/modules/org/arangodb/general-graph.js +++ b/js/common/modules/org/arangodb/general-graph.js @@ -2938,6 +2938,215 @@ Graph.prototype._countCommonProperties = function(vertex1Example, vertex2Example }; +//////////////////////////////////////////////////////////////////////////////// +/// @startDocuBlock JSF_general_graph_paths +/// +/// `graph._paths (options)` +/// *The _paths function returns all paths of a graph.* +/// +/// This function determines all available paths in a graph. +/// +/// *Parameters* +/// +/// * *options* (optional) : An object containing options, see below: +/// * *direction* : The direction of the edges. Possible values are *any*, +/// *inbound* and *outbound* (default). +/// * *followCycles* (optional) : If set to *true* the query follows cycles in the graph, +/// default is false. +/// * *minLength* (optional) : Defines the minimal length a path must +/// have to be returned (default is 0). +/// * *maxLength* (optional) : Defines the maximal length a path must +/// have to be returned (default is 10). +/// +/// *Examples* +/// +/// Return all paths of the graph "social": +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModulePaths} +/// ~ var db = require("internal").db; +/// var examples = require("org/arangodb/graph-examples/example-graph.js"); +/// var g = examples.loadGraph("social"); +/// g._paths(); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// +/// Return all inbound paths of the graph "social" with a maximal +/// length of 1 and a minimal length of 2: +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModulePaths2} +/// ~ var db = require("internal").db; +/// var examples = require("org/arangodb/graph-examples/example-graph.js"); +/// var g = examples.loadGraph("social"); +/// g._paths({direction : 'inbound', minLength : 1, maxLength : 2}); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// @endDocuBlock +// +//////////////////////////////////////////////////////////////////////////////// +Graph.prototype._paths = function(options) { + var query = "RETURN" + + " GRAPH_PATHS(@graphName" + + ',@options' + + ')'; + options = options || {}; + var bindVars = { + "graphName": this.__name, + "options": options + }; + var result = db._query(query, bindVars).toArray(); + return result; +}; + +//////////////////////////////////////////////////////////////////////////////// +/// @startDocuBlock JSF_general_graph_shortest_path +/// +/// `graph._shortestPath (startVertexExample, endVertexExample, options)` +/// *The _shortestPath function returns all shortest paths of a graph.* +/// +/// This function determines all shortest paths in a graph. +/// The function accepts an id, an example, a list of examples +/// or even an empty example as parameter for +/// start and end vertex. If one wants to call this function to receive nearly all +/// shortest paths for a graph the option *algorithm* should be set to +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) +/// to increase performance. +/// If no algorithm is provided in the options the function chooses the appropriate +/// one (either [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) +/// or [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm)) according to its parameters. +/// The length of a path is by default the amount of edges from one start vertex to +/// an end vertex. The option weight allows the user to define an edge attribute +/// representing the length. +/// +/// *Parameters* +/// +/// * *startVertexExample* (optional) : An example for the desired start Vertices +/// (see [Definition of examples](#definition_of_examples)). +/// * *endVertexExample* (optional) : An example for the desired +/// end Vertices (see [Definition of examples](#definition_of_examples)). +/// * *options* (optional) : An object containing options, see below: +/// * *direction* : The direction of the edges as a string. +/// Possible values are *outbound*, *inbound* and *any* (default). +/// * *edgeCollectionRestriction* : One or multiple edge +/// collection names. Only edges from these collections will be considered for the path. +/// * *startVertexCollectionRestriction* : One or multiple vertex +/// collection names. Only vertices from these collections will be considered as +/// start vertex of a path. +/// * *endVertexCollectionRestriction* : One or multiple vertex +/// collection names. Only vertices from these collections will be considered as +/// end vertex of a path. +/// * *edgeExamples* : A filter example for the +/// edges in the shortest paths +/// (see [example](#short_explaination_of_the_vertex_example_parameter)). +/// * *algorithm* : The algorithm to calculate +/// the shortest paths. If both start and end vertex examples are empty +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) is +/// used, otherwise the default is [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm) +/// * *weight* : The name of the attribute of +/// the edges containing the length as a string. +/// * *defaultWeight* : Only used with the option *weight*. +/// If an edge does not have the attribute named as defined in option *weight* this default +/// is used as length. +/// If no default is supplied the default would be positive Infinity so the path could +/// not be calculated. +/// +/// *Examples* +/// +/// A route planner example, shortest path from all german to all french cities: +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModuleShortestPaths1} +/// ~ var db = require("internal").db; +/// var examples = require("org/arangodb/graph-examples/example-graph.js"); +/// var g = examples.loadGraph("routeplanner"); +/// | g._shortestPath({}, {}, {weight : 'distance', endVertexCollectionRestriction : 'frenchCity', +/// startVertexCollectionRestriction : 'germanCity'}); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// +/// A route planner example, shortest path from Hamburg and Cologne to Lyon: +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModuleShortestPaths2} +/// ~ var db = require("internal").db; +/// var examples = require("org/arangodb/graph-examples/example-graph.js"); +/// var g = examples.loadGraph("routeplanner"); +/// | g._shortestPath([{_id: 'germanCity/Cologne'},{_id: 'germanCity/Munich'}], 'frenchCity/Lyon', +/// {weight : 'distance'}); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// +/// @endDocuBlock +// +//////////////////////////////////////////////////////////////////////////////// +Graph.prototype._shortestPath = function(startVertexExample, endVertexExample, options) { + var ex1 = transformExample(startVertexExample); + var ex2 = transformExample(endVertexExample); + var query = "RETURN" + + " GRAPH_SHORTEST_PATH(@graphName" + + ',@ex1' + + ',@ex2' + + ',@options' + + ')'; + options = options || {}; + var bindVars = { + "graphName": this.__name, + "options": options, + "ex1": ex1, + "ex2": ex2 + }; + var result = db._query(query, bindVars).toArray(); + return result; +}; + + +//////////////////////////////////////////////////////////////////////////////// +/// @startDocuBlock JSF_general_graph_distance_to +/// +/// `graph._distanceTo (startVertexExample, endVertexExample, options)` +/// *The _distanceTo function returns all paths and there distance within a graph.* +/// +/// This function is a wrapper of [graph._shortestPath](#_shortestpath). +/// It does not return the actual path but only the distance between two vertices. +/// +/// *Examples* +/// +/// A route planner example, shortest distance from all german to all french cities: +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModuleDistanceTo1} +/// ~ var db = require("internal").db; +/// var examples = require("org/arangodb/graph-examples/example-graph.js"); +/// var g = examples.loadGraph("routeplanner"); +/// | g._distanceTo({}, {}, {weight : 'distance', endVertexCollectionRestriction : 'frenchCity', +/// startVertexCollectionRestriction : 'germanCity'}); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// +/// A route planner example, shortest distance from Hamburg and Cologne to Lyon: +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModuleDistanceTo2} +/// ~ var db = require("internal").db; +/// var examples = require("org/arangodb/graph-examples/example-graph.js"); +/// var g = examples.loadGraph("routeplanner"); +/// | g._distanceTo([{_id: 'germanCity/Cologne'},{_id: 'germanCity/Munich'}], 'frenchCity/Lyon', +/// {weight : 'distance'}); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// +/// @endDocuBlock +// +//////////////////////////////////////////////////////////////////////////////// +Graph.prototype._distanceTo = function(startVertexExample, endVertexExample, options) { + var ex1 = transformExample(startVertexExample); + var ex2 = transformExample(endVertexExample); + var query = "RETURN" + + " GRAPH_DISTANCE_TO(@graphName" + + ',@ex1' + + ',@ex2' + + ',@options' + + ')'; + options = options || {}; + var bindVars = { + "graphName": this.__name, + "options": options, + "ex1": ex1, + "ex2": ex2 + }; + var result = db._query(query, bindVars).toArray(); + return result; +}; + //////////////////////////////////////////////////////////////////////////////// /// @startDocuBlock JSF_general_graph_absolute_eccentricity /// @@ -2962,7 +3171,8 @@ Graph.prototype._countCommonProperties = function(vertex1Example, vertex2Example /// considered for target vertices. /// * *edgeExamples*: Filter the edges to be followed, see [Definition of examples](#definition_of_examples) /// * *algorithm*: The algorithm to calculate the shortest paths, possible values are -/// *"Floyd-Warshall"* and *"Dijkstra"*. +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) and +/// [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight*: The name of the attribute of the edges containing the weight. /// * *defaultWeight*: Only used with the option *weight*. /// If an edge does not have the attribute named as defined in option *weight* this default @@ -3090,7 +3300,8 @@ Graph.prototype._eccentricity = function(options) { /// considered for target vertices. /// * *edgeExamples*: Filter the edges to be followed, see [Definition of examples](#definition_of_examples) /// * *algorithm*: The algorithm to calculate the shortest paths, possible values are -/// *"Floyd-Warshall"* and *"Dijkstra"*. +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) and +/// [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight*: The name of the attribute of the edges containing the weight. /// * *defaultWeight*: Only used with the option *weight*. /// If an edge does not have the attribute named as defined in option *weight* this default @@ -3338,7 +3549,8 @@ Graph.prototype._betweenness = function(options) { /// * *options* (optional): An object defining further options. Can have the following values: /// * *direction*: The direction of the edges. Possible values are *outbound*, *inbound* and *any* (default). /// * *algorithm*: The algorithm to calculate the shortest paths, possible values are -/// *"Floyd-Warshall"* and *"Dijkstra"*. +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) and +/// [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight*: The name of the attribute of the edges containing the weight. /// * *defaultWeight*: Only used with the option *weight*. /// If an edge does not have the attribute named as defined in option *weight* this default @@ -3406,7 +3618,8 @@ Graph.prototype._radius = function(options) { /// * *options* (optional): An object defining further options. Can have the following values: /// * *direction*: The direction of the edges. Possible values are *outbound*, *inbound* and *any* (default). /// * *algorithm*: The algorithm to calculate the shortest paths, possible values are -/// *"Floyd-Warshall"* and *"Dijkstra"*. +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) and +/// [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight*: The name of the attribute of the edges containing the weight. /// * *defaultWeight*: Only used with the option *weight*. /// If an edge does not have the attribute named as defined in option *weight* this default diff --git a/js/common/tests/shell-general-graph.js b/js/common/tests/shell-general-graph.js index a4ecb8e4eb..88919b5648 100644 --- a/js/common/tests/shell-general-graph.js +++ b/js/common/tests/shell-general-graph.js @@ -2623,7 +2623,7 @@ function MeasurementsSuite() { var ids = {}; var vertex = g[vc1].save({first_name: "Tam"}); ids.vId11 = vertex._id; - vertex = g[vc1].save({first_name: "Tem"}); + vertex = g[vc1].save({first_name: "Tem", age : 20}); ids.vId12 = vertex._id; vertex = g[vc1].save({first_name: "Tim"}); ids.vId13 = vertex._id; @@ -2635,7 +2635,7 @@ function MeasurementsSuite() { ids.vId31 = vertex._id; vertex = g[vc3].save({first_name: "Tem"}); ids.vId32 = vertex._id; - vertex = g[vc3].save({first_name: "Tim"}); + vertex = g[vc3].save({first_name: "Tim", age : 24}); ids.vId33 = vertex._id; vertex = g[vc3].save({first_name: "Tom"}); ids.vId34 = vertex._id; @@ -2726,6 +2726,18 @@ function MeasurementsSuite() { test_diameter : function () { var a = g._diameter({}); assertEqual(a[0] , 2); + }, + test_paths : function () { + var a = g._paths({maxLength : 2}); + assertEqual(a[0].length , 50); + }, + test_shortestPaths : function () { + var a = g._shortestPath([{first_name: 'Tim',age : 24}, {first_name: 'Tom'}], [{first_name: 'Tam'}, {first_name: 'Tem',age : 20}]); + assertEqual(a[0].length , 9); + }, + test_distanceTo : function () { + var a = g._distanceTo([{first_name: 'Tim',age : 24}, {first_name: 'Tom'}], [{first_name: 'Tam'}, {first_name: 'Tem' ,age : 20}]); + assertEqual(a[0].length , 9); } @@ -2743,12 +2755,12 @@ function MeasurementsSuite() { /// @brief executes the test suites //////////////////////////////////////////////////////////////////////////////// -jsunity.run(GeneralGraphCommonNeighborsSuite); -jsunity.run(GeneralGraphAQLQueriesSuite); -jsunity.run(EdgesAndVerticesSuite); -jsunity.run(GeneralGraphCreationSuite); -jsunity.run(ChainedFluentAQLResultsSuite); -jsunity.run(OrphanCollectionSuite); +//jsunity.run(GeneralGraphCommonNeighborsSuite); +//jsunity.run(GeneralGraphAQLQueriesSuite); +//jsunity.run(EdgesAndVerticesSuite); +//jsunity.run(GeneralGraphCreationSuite); +//jsunity.run(ChainedFluentAQLResultsSuite); +//jsunity.run(OrphanCollectionSuite); jsunity.run(MeasurementsSuite); return jsunity.done(); diff --git a/js/server/modules/org/arangodb/ahuacatl.js b/js/server/modules/org/arangodb/ahuacatl.js index c9f9ba33ac..c8f837189e 100644 --- a/js/server/modules/org/arangodb/ahuacatl.js +++ b/js/server/modules/org/arangodb/ahuacatl.js @@ -4342,22 +4342,20 @@ function GRAPH_PATHS (vertices, edgeCollection, direction, followCycles, minLeng //////////////////////////////////////////////////////////////////////////////// /// @startDocuBlock JSF_ahuacatl_general_graph_paths /// -/// `GRAPH_PATHS (graphName, direction, followCycles, minLength, maxLength)` +/// `GRAPH_PATHS (graphName, options)` /// *The GRAPH\_PATHS function returns all paths of a graph.* /// -/// This function determines all available paths in a graph identified by *graphName*. -/// Except for *graphName* every other parameter is optional. -/// /// *Parameters* /// /// * *graphName* : The name of the graph as a string. -/// * *direction* (optional) : The direction of the edges as a string. -/// Possible values are *any*, *inbound* and *outbound* (default). -/// * *followCycles* (optional) : If set to *true* the query follows cycles in the graph, +/// * *options* : An object containing options, see below: +/// * *direction* : The direction of the edges. Possible values are *any*, +/// *inbound* and *outbound* (default). +/// * *followCycles* (optional) : If set to *true* the query follows cycles in the graph, /// default is false. -/// * *minLength* (optional) : Defines the minimal length a path must +/// * *minLength* (optional) : Defines the minimal length a path must /// have to be returned (default is 0). -/// * *maxLength* (optional) : Defines the maximal length a path must +/// * *maxLength* (optional) : Defines the maximal length a path must /// have to be returned (default is 10). /// /// *Examples* @@ -4378,20 +4376,25 @@ function GRAPH_PATHS (vertices, edgeCollection, direction, followCycles, minLeng /// ~ var db = require("internal").db; /// var examples = require("org/arangodb/graph-examples/example-graph.js"); /// var g = examples.loadGraph("social"); -/// db._query("RETURN GRAPH_PATHS('social', 'inbound', false, 1, 2)").toArray(); +/// | db._query( +/// | "RETURN GRAPH_PATHS('social', {direction : 'inbound', minLength : 1, maxLength : 2})" +/// ).toArray(); /// @END_EXAMPLE_ARANGOSH_OUTPUT /// @endDocuBlock // //////////////////////////////////////////////////////////////////////////////// -function GENERAL_GRAPH_PATHS (graphName, direction, followCycles, minLength, maxLength) { +function GENERAL_GRAPH_PATHS (graphName, options) { "use strict"; var searchDirection; - direction = direction || "outbound"; - followCycles = followCycles || false; - minLength = minLength || 0; - maxLength = maxLength !== undefined ? maxLength : 10; + if (! options) { + options = {}; + } + var direction = options.direction || "outbound"; + var followCycles = options.followCycles || false; + var minLength = options.minLength || 0; + var maxLength = options.maxLength || 10; // check graph exists and load edgeDefintions var graph = DOCUMENT_HANDLE("_graphs/" + graphName); @@ -5236,13 +5239,13 @@ function IS_EXAMPLE_SET (example) { /// *The GRAPH\_SHORTEST\_PATH function returns all shortest paths of a graph.* /// /// This function determines all shortest paths in a graph identified by *graphName*. -/// The function accepts an id, an example, a list of examples -/// or even an empty example as parameter for -/// start and end vertex. If one wants to call this function to receive nearly all -/// shortest paths for a graph the -/// option *algorithm* should be set to *Floyd-Warshall* to increase performance. +/// If one wants to call this function to receive nearly all shortest paths for a +/// graph the option *algorithm* should be set to +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) to +/// increase performance. /// If no algorithm is provided in the options the function chooses the appropriate -/// one (either *Floyd-Warshall* or *Dijsktra*) according to its parameters. +/// one (either [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) +/// or [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm)) according to its parameters. /// The length of a path is by default the amount of edges from one start vertex to /// an end vertex. The option weight allows the user to define an edge attribute /// representing the length. @@ -5258,17 +5261,20 @@ function IS_EXAMPLE_SET (example) { /// * *direction* : The direction of the edges as a string. /// Possible values are *outbound*, *inbound* and *any* (default). /// * *edgeCollectionRestriction* : One or multiple edge -/// collections that should be considered. +/// collection names. Only edges from these collections will be considered for the path. /// * *startVertexCollectionRestriction* : One or multiple vertex -/// collections that should be considered. +/// collection names. Only vertices from these collections will be considered as +/// start vertex of a path. /// * *endVertexCollectionRestriction* : One or multiple vertex -/// collections that should be considered. +/// collection names. Only vertices from these collections will be considered as +/// end vertex of a path. /// * *edgeExamples* : A filter example for the /// edges in the shortest paths /// (see [example](#short_explaination_of_the_vertex_example_parameter)). /// * *algorithm* : The algorithm to calculate -/// the shortest paths. If both start and end vertex examples are empty *Floyd-Warshall* is -/// used, otherwise the default is *Dijkstra* +/// the shortest paths. If both start and end vertex examples are empty +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) is +/// used, otherwise the default is [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight* : The name of the attribute of /// the edges containing the length as a string. /// * *defaultWeight* : Only used with the option *weight*. @@ -5279,7 +5285,7 @@ function IS_EXAMPLE_SET (example) { /// /// *Examples* /// -/// A route planner example, shortest distance from all German to all french cities: +/// A route planner example, shortest distance from all german to all french cities: /// /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphShortestPaths1} /// ~ var db = require("internal").db; @@ -5489,7 +5495,7 @@ function GRAPH_TRAVERSAL_TREE (vertexCollection, /// /// *Examples* /// -/// A route planner example, distance from all french to all German cities: +/// A route planner example, distance from all french to all german cities: /// /// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphDistanceTo1} /// ~ var db = require("internal").db; @@ -5709,8 +5715,8 @@ function GRAPH_NEIGHBORS (vertexCollection, /// `GRAPH_NEIGHBORS (graphName, vertexExample, options)` /// *The GRAPH\_NEIGHBORS function returns all neighbors of vertices.* /// -/// The function accepts an id, an example, a list of examples or even an empty -/// example as parameter for vertex. +/// By default only the direct neighbors (path length equals 1) are returned, but one can define +/// the range of the path length to the neighbors with the options *minDepth* and *maxDepth*. /// /// *Parameters* /// @@ -5724,10 +5730,11 @@ function GRAPH_NEIGHBORS (vertexCollection, /// the neighbors (see [example](#short_explaination_of_the_vertex_example_parameter)). /// * *neighborExamples* : An example for the desired neighbors /// (see [example](#short_explaination_of_the_vertex_example_parameter)). -/// * *edgeCollectionRestriction* : One or multiple -/// edge collections that should be considered. -/// * *vertexCollectionRestriction* : One or multiple -/// vertex collections that should be considered. +/// * *edgeCollectionRestriction* : One or multiple edge +/// collection names. Only edges from these collections will be considered for the path. +/// * *vertexCollectionRestriction* : One or multiple vertex +/// collection names. Only vertices from these collections will be considered as +/// neighbor. /// * *minDepth* : Defines the minimal /// depth a path to a neighbor must have to be returned (default is 1). /// * *maxDepth* : Defines the maximal @@ -5821,10 +5828,8 @@ function GENERAL_GRAPH_NEIGHBORS (graphName, /// @startDocuBlock JSF_ahuacatl_general_graph_edges /// /// `GRAPH_EDGES (graphName, vertexExample, options)` -/// *The GRAPH\_EDGES function returns all edges of vertices.* -/// -/// The function accepts an id, an example, a list of examples or even an empty -/// example as parameter for vertex. +/// *The GRAPH\_EDGES function returns all edges of the graph connected to the vertices +/// defined by the example.* /// /// *Parameters* /// @@ -5834,20 +5839,24 @@ function GENERAL_GRAPH_NEIGHBORS (graphName, /// * *options* (optional) : An object containing options, see below: /// * *direction* : The direction /// of the edges as a string. Possible values are *outbound*, *inbound* and *any* (default). -/// * *edgeCollectionRestriction* : One or multiple -/// edge collections that should be considered. -/// * *startVertexCollectionRestriction* : One or multiple -/// vertex collections that should be considered. -/// * *endVertexCollectionRestriction* : One or multiple -/// vertex collections that should be considered. +/// * *edgeCollectionRestriction* : One or multiple edge +/// collection names. Only edges from these collections will be considered for the path. +/// * *startVertexCollectionRestriction* : One or multiple vertex +/// collection names. Only vertices from these collections will be considered as +/// start vertex of a path. +/// * *endVertexCollectionRestriction* : One or multiple vertex +/// collection names. Only vertices from these collections will be considered as +/// end vertex of a path. /// * *edgeExamples* : A filter example /// for the edges (see [example](#short_explaination_of_the_vertex_example_parameter)). /// * *neighborExamples* : An example for /// the desired neighbors (see [example](#short_explaination_of_the_vertex_example_parameter)). -/// * *minDepth* : Defines the minimal -/// depth a path to a neighbor must have to be returned (default is 1). -/// * *maxDepth* : Defines the maximal -/// depth a path to a neighbor must have to be returned (default is 1). +/// * *minDepth* : Defines the minimal length of a path from an edge +/// to a vertex (default is 1, which means only the edges directly connected to a vertex would +/// be returned). +/// * *maxDepth* : Defines the maximal length of a path from an edge +/// to a vertex (default is 1, which means only the edges directly connected to a vertex would +/// be returned). /// /// *Examples* /// @@ -5901,8 +5910,6 @@ function GENERAL_GRAPH_EDGES ( /// `GRAPH_VERTICES (graphName, vertexExample, options)` /// *The GRAPH\_VERTICES function returns all vertices.* /// -/// The function accepts an id, an example, a list of examples or even an empty -/// example as parameter for vertex. /// According to the optional filters it will only return vertices that have /// outbound, onbound or any (default) edges. /// @@ -5996,9 +6003,6 @@ function TRANSFER_GENERAL_GRAPH_NEIGHBORS_RESULT (result) { /// *The GRAPH\_COMMON\_NEIGHBORS function returns all common neighbors of the vertices /// defined by the examples.* /// -/// The function accepts an id, an example, a list of examples or even an empty -/// example as parameter for vertex1Example and vertex2Example. -/// /// This function returns the intersection of *GRAPH_NEIGHBORS(vertex1Example, optionsVertex1)* /// and *GRAPH_NEIGHBORS(vertex2Example, optionsVertex2)*. /// For parameter documentation read the documentation of @@ -6096,9 +6100,6 @@ function GENERAL_GRAPH_COMMON_NEIGHBORS ( /// *The GRAPH\_COMMON\_PROPERTIES function returns all vertices /// defined by the examples that share common properties /// -/// The function accepts an id, an example, a list of examples or even an empty -/// example as parameter for vertex1Example and vertex2Example. -/// /// *Parameters* /// /// * *graphName* : The name of the graph as a string. @@ -6107,10 +6108,10 @@ function GENERAL_GRAPH_COMMON_NEIGHBORS ( /// * *vertex2Example* : An example for the desired /// vertices (see [example](#short_explaination_of_the_vertex_example_parameter)). /// * *options* (optional) : An object containing options, see below: -/// * *vertex1CollectionRestriction* : One or multiple -/// vertex collections that should be considered. -/// * *vertex2CollectionRestriction* : One or multiple -/// vertex collections that should be considered. +/// * *vertex1CollectionRestriction* : One or multiple vertex +/// collection names. Only vertices from these collections will be considered. +/// * *vertex2CollectionRestriction* : One or multiple vertex +/// collection names. Only vertices from these collections will be considered. /// * *ignoreProperties* : One or multiple /// attributes of a document that should be ignored, either a string or an array.. /// @@ -6235,9 +6236,6 @@ function GENERAL_GRAPH_COMMON_PROPERTIES ( /// [eccentricity](http://en.wikipedia.org/wiki/Distance_%28graph_theory%29) /// of the vertices defined by the examples.* /// -/// The function accepts an id, an example, a list of examples or even an empty -/// example as parameter for vertexExample. -/// /// *Parameters* /// /// * *graphName* : The name of the graph as a string. @@ -6247,16 +6245,20 @@ function GENERAL_GRAPH_COMMON_PROPERTIES ( /// * *direction* : The direction of the edges as a string. /// Possible values are *outbound*, *inbound* and *any* (default). /// * *edgeCollectionRestriction* : One or multiple edge -/// collections that should be considered. +/// collection names. Only edges from these collections will be considered for the path. /// * *startVertexCollectionRestriction* : One or multiple vertex -/// collections that should be considered. +/// collection names. Only vertices from these collections will be considered as +/// start vertex of a path. /// * *endVertexCollectionRestriction* : One or multiple vertex -/// collections that should be considered. +/// collection names. Only vertices from these collections will be considered as +/// end vertex of a path. /// * *edgeExamples* : A filter example for the edges in the /// shortest paths (see [example](#short_explaination_of_the_vertex_example_parameter)). /// * *algorithm* : The algorithm to calculate -/// the shortest paths as a string. If vertex example is empty *Floyd-Warshall* is -/// used as default, otherwise the default is *Dijkstra* +/// the shortest paths as a string. If vertex example is empty +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) is +/// used as default, otherwise the default is +/// [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm) /// * *weight* : The name of the attribute of /// the edges containing the length as a string. /// * *defaultWeight* : Only used with the option *weight*. @@ -6342,7 +6344,8 @@ function GENERAL_GRAPH_ABSOLUTE_ECCENTRICITY (graphName, vertexExample, options) /// * *direction* : The direction of the edges as a string. /// Possible values are *outbound*, *inbound* and *any* (default). /// * *algorithm* : The algorithm to calculate the shortest paths as a string. Possible -/// values are *Floyd-Warshall* (default) and *Dijkstra*. +/// values are [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) +/// (default) and [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight* : The name of the attribute of the edges containing the length as a string. /// * *defaultWeight* : Only used with the option *weight*. /// If an edge does not have the attribute named as defined in option *weight* this default @@ -6409,9 +6412,6 @@ function GENERAL_GRAPH_ECCENTRICITY (graphName, options) { /// [closeness](http://en.wikipedia.org/wiki/Centrality#Closeness_centrality) /// of the vertices defined by the examples.* /// -/// The function accepts an id, an example, a list of examples or even an empty -/// example as parameter for vertexExample. -/// /// *Parameters* /// /// * *graphName* : The name of the graph as a string. @@ -6421,16 +6421,20 @@ function GENERAL_GRAPH_ECCENTRICITY (graphName, options) { /// * *direction* : The direction of the edges. /// Possible values are *outbound*, *inbound* and *any* (default). /// * *edgeCollectionRestriction* : One or multiple edge -/// collections that should be considered. +/// collection names. Only edges from these collections will be considered for the path. /// * *startVertexCollectionRestriction* : One or multiple vertex -/// collections that should be considered. +/// collection names. Only vertices from these collections will be considered as +/// start vertex of a path. /// * *endVertexCollectionRestriction* : One or multiple vertex -/// collections that should be considered. +/// collection names. Only vertices from these collections will be considered as +/// end vertex of a path. /// * *edgeExamples* : A filter example for the /// edges in the shortest paths ( /// see [example](#short_explaination_of_the_vertex_example_parameter)). /// * *algorithm* : The algorithm to calculate -/// the shortest paths. Possible values are *Floyd-Warshall* (default) and *Dijkstra*. +/// the shortest paths. Possible values are +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) (default) +/// and [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight* : The name of the attribute of /// the edges containing the length. /// * *defaultWeight* : Only used with the option *weight*. @@ -6516,7 +6520,9 @@ function GENERAL_GRAPH_ABSOLUTE_CLOSENESS (graphName, vertexExample, options) { /// * *direction* : The direction of the edges. /// Possible values are *outbound*, *inbound* and *any* (default). /// * *algorithm* : The algorithm to calculate -/// the shortest paths. Possible values are *Floyd-Warshall* (default) and *Dijkstra*. +/// the shortest paths. Possible values are +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) (default) +/// and [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight* : The name of the attribute of /// the edges containing the length. /// * *defaultWeight* : Only used with the option *weight*. @@ -6790,7 +6796,8 @@ function GENERAL_GRAPH_BETWEENNESS (graphName, options) { /// * *direction* : The direction of the edges. /// Possible values are *outbound*, *inbound* and *any* (default). /// * *algorithm* : The algorithm to calculate the shortest paths as a string. Possible -/// values are *Floyd-Warshall* (default) and *Dijkstra*. +/// values are [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) +/// (default) and [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight* : The name of the attribute of /// the edges containing the length. /// * *defaultWeight* : Only used with the option *weight*. @@ -6878,7 +6885,8 @@ function GENERAL_GRAPH_RADIUS (graphName, options) { /// * *direction* : The direction of the edges. /// Possible values are *outbound*, *inbound* and *any* (default). /// * *algorithm* : The algorithm to calculate the shortest paths as a string. Possible -/// values are *Floyd-Warshall* (default) and *Dijkstra*. +/// values are [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) +/// (default) and [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight* : The name of the attribute of /// the edges containing the length. /// * *defaultWeight* : Only used with the option *weight*. From d50bd571f7685554c3537947f3168f50c6e7fc17 Mon Sep 17 00:00:00 2001 From: Alan Plum Date: Tue, 24 Jun 2014 13:24:32 +0200 Subject: [PATCH 16/21] Trimmed line length. --- .../system/aardvark/frontend/js/bootstrap/module-internal.js | 3 ++- js/common/bootstrap/module-internal.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js b/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js index ccc68f3507..e5da9268b2 100644 --- a/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js +++ b/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js @@ -9,7 +9,8 @@ SYS_DOWNLOAD, SYS_EXECUTE, SYS_GET_CURRENT_REQUEST, SYS_GET_CURRENT_RESPONSE, SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS, SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER, - SYS_HMAC, SYS_SHA256, SYS_SHA224, SYS_SHA1, SYS_SLEEP, SYS_WAIT, SYS_PARSE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, SYS_LOG, + SYS_HMAC, SYS_SHA256, SYS_SHA224, SYS_SHA1, SYS_SLEEP, SYS_WAIT, + SYS_PARSE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, SYS_LOG, SYS_GEN_RANDOM_NUMBERS, SYS_GEN_RANDOM_ALPHA_NUMBERS, SYS_GEN_RANDOM_SALT, SYS_CREATE_NONCE, SYS_CHECK_AND_MARK_NONCE, SYS_CLIENT_STATISTICS, SYS_HTTP_STATISTICS, SYS_UNIT_TESTS, SYS_UNIT_TESTS_RESULT:true, SYS_PROCESS_CSV_FILE, SYS_PROCESS_JSON_FILE, ARANGO_QUIET, COLORS, COLOR_OUTPUT, diff --git a/js/common/bootstrap/module-internal.js b/js/common/bootstrap/module-internal.js index ccc68f3507..e5da9268b2 100644 --- a/js/common/bootstrap/module-internal.js +++ b/js/common/bootstrap/module-internal.js @@ -9,7 +9,8 @@ SYS_DOWNLOAD, SYS_EXECUTE, SYS_GET_CURRENT_REQUEST, SYS_GET_CURRENT_RESPONSE, SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS, SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER, - SYS_HMAC, SYS_SHA256, SYS_SHA224, SYS_SHA1, SYS_SLEEP, SYS_WAIT, SYS_PARSE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, SYS_LOG, + SYS_HMAC, SYS_SHA256, SYS_SHA224, SYS_SHA1, SYS_SLEEP, SYS_WAIT, + SYS_PARSE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, SYS_LOG, SYS_GEN_RANDOM_NUMBERS, SYS_GEN_RANDOM_ALPHA_NUMBERS, SYS_GEN_RANDOM_SALT, SYS_CREATE_NONCE, SYS_CHECK_AND_MARK_NONCE, SYS_CLIENT_STATISTICS, SYS_HTTP_STATISTICS, SYS_UNIT_TESTS, SYS_UNIT_TESTS_RESULT:true, SYS_PROCESS_CSV_FILE, SYS_PROCESS_JSON_FILE, ARANGO_QUIET, COLORS, COLOR_OUTPUT, From 50fba66900c5b9cee20e207a91bde984577556ae Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 24 Jun 2014 13:56:17 +0200 Subject: [PATCH 17/21] close failed transactions on start --- arangod/Wal/LogfileManager.cpp | 209 +++++++++++++++++++-------------- arangod/Wal/LogfileManager.h | 34 ++++-- 2 files changed, 144 insertions(+), 99 deletions(-) diff --git a/arangod/Wal/LogfileManager.cpp b/arangod/Wal/LogfileManager.cpp index 33c97e4aef..3159805bc7 100644 --- a/arangod/Wal/LogfileManager.cpp +++ b/arangod/Wal/LogfileManager.cpp @@ -38,6 +38,7 @@ #include "Basics/ReadLocker.h" #include "Basics/StringUtils.h" #include "Basics/WriteLocker.h" +#include "Utils/Exception.h" #include "VocBase/server.h" #include "Wal/AllocatorThread.h" #include "Wal/CollectorThread.h" @@ -112,22 +113,6 @@ static inline uint32_t MaxSlots () { return 1024 * 1024 * 16; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief callback to handle one marker during logfile inspection -//////////////////////////////////////////////////////////////////////////////// - -static bool ScanMarkerTick (TRI_df_marker_t const* marker, - void* data, - TRI_datafile_t* datafile) { - RecoverState* state = reinterpret_cast(data); - - TRI_ASSERT(marker != nullptr); - TRI_ASSERT(marker->_tick >= state->lastTick); - state->lastTick = marker->_tick; - - return true; -} - //////////////////////////////////////////////////////////////////////////////// /// @brief callback to handle one marker during recovery //////////////////////////////////////////////////////////////////////////////// @@ -186,7 +171,7 @@ static bool ScanMarker (TRI_df_marker_t const* marker, // insert this transaction into the list of failed transactions // we do this because if we don't find a commit marker for this transaction, // we'll have it in the failed list at the end of the scan and can ignore it - state->failedTransactions.insert(m->_transactionId); + state->failedTransactions.insert(std::make_pair(m->_transactionId, std::make_pair(m->_databaseId, false))); break; } case TRI_WAL_MARKER_COMMIT_TRANSACTION: { @@ -199,7 +184,15 @@ static bool ScanMarker (TRI_df_marker_t const* marker, case TRI_WAL_MARKER_ABORT_TRANSACTION: { // insert this transaction into the list of failed transactions transaction_abort_marker_t const* m = reinterpret_cast(marker); - state->failedTransactions.insert(m->_transactionId); + + auto it = state->failedTransactions.find(m->_transactionId); + if (it != state->failedTransactions.end()) { + // delete previous element if present + state->failedTransactions.erase(m->_transactionId); + } + + // and (re-)insert + state->failedTransactions.insert(std::make_pair(m->_transactionId, std::make_pair(m->_databaseId, true))); break; } @@ -237,6 +230,7 @@ LogfileManager::LogfileManager (TRI_server_t* server, _server(server), _databasePath(databasePath), _directory(), + _recoverState(new RecoverState()), _filesize(32 * 1024 * 1024), _reserveLogfiles(4), _historicLogfiles(10), @@ -268,6 +262,7 @@ LogfileManager::LogfileManager (TRI_server_t* server, _shutdown(0) { LOG_TRACE("creating WAL logfile manager"); + TRI_ASSERT(! _allowWrites); int res = regcomp(&_filenameRegex, "^logfile-([0-9][0-9]*)\\.db$", REG_EXTENDED); @@ -287,6 +282,11 @@ LogfileManager::~LogfileManager () { regfree(&_filenameRegex); + if (_recoverState != nullptr) { + delete _recoverState; + _recoverState = nullptr; + } + if (_slots != nullptr) { delete _slots; _slots = nullptr; @@ -424,6 +424,8 @@ bool LogfileManager::start () { return true; } + TRI_ASSERT(! _allowWrites); + int res = inventory(); if (res != TRI_ERROR_NO_ERROR) { @@ -435,6 +437,8 @@ bool LogfileManager::start () { bool const shutdownFileExists = basics::FileUtils::exists(shutdownFile); if (shutdownFileExists) { + LOG_TRACE("shutdown file found"); + res = readShutdownInfo(); if (res != TRI_ERROR_NO_ERROR) { @@ -444,6 +448,9 @@ bool LogfileManager::start () { return false; } } + else { + LOG_TRACE("no shutdown file found"); + } res = openLogfiles(); @@ -495,9 +502,11 @@ bool LogfileManager::open () { // we were already started return true; } + + TRI_ASSERT(! _allowWrites); opened = true; - + return runRecovery(); } @@ -560,11 +569,11 @@ void LogfileManager::stop () { /// @brief registers a transaction //////////////////////////////////////////////////////////////////////////////// -bool LogfileManager::registerTransaction (TRI_voc_tid_t id) { +bool LogfileManager::registerTransaction (TRI_voc_tid_t transactionId) { { WRITE_LOCKER(_logfilesLock); - _transactions.insert(make_pair(id, make_pair(_lastCollectedId, _lastSealedId))); + _transactions.insert(make_pair(transactionId, make_pair(_lastCollectedId, _lastSealedId))); TRI_ASSERT(_lastCollectedId <= _lastSealedId); } @@ -575,14 +584,14 @@ bool LogfileManager::registerTransaction (TRI_voc_tid_t id) { /// @brief unregisters a transaction //////////////////////////////////////////////////////////////////////////////// -void LogfileManager::unregisterTransaction (TRI_voc_tid_t id, +void LogfileManager::unregisterTransaction (TRI_voc_tid_t transactionId, bool markAsFailed) { { WRITE_LOCKER(_logfilesLock); - _transactions.erase(id); + _transactions.erase(transactionId); if (markAsFailed) { - _failedTransactions.insert(id); + _failedTransactions.insert(transactionId); } } } @@ -1371,30 +1380,50 @@ void LogfileManager::waitForCollector (Logfile::IdType logfileId) { } } -//////////////////////////////////////////////////////////////////////////////// -/// @brief scan a single logfile for the max tick -//////////////////////////////////////////////////////////////////////////////// - -bool LogfileManager::scanLogfileTick (Logfile const* logfile, - RecoverState& state) { - TRI_ASSERT(logfile != nullptr); - - LOG_TRACE("scanning logfile %llu (%s)", (unsigned long long) logfile->id(), logfile->statusText().c_str()); - - return TRI_IterateDatafile(logfile->df(), &ScanMarkerTick, static_cast(&state)); -} - //////////////////////////////////////////////////////////////////////////////// /// @brief scan a single logfile //////////////////////////////////////////////////////////////////////////////// -bool LogfileManager::scanLogfile (Logfile const* logfile, - RecoverState& state) { +bool LogfileManager::scanLogfile (Logfile const* logfile) { TRI_ASSERT(logfile != nullptr); LOG_TRACE("scanning logfile %llu (%s)", (unsigned long long) logfile->id(), logfile->statusText().c_str()); - return TRI_IterateDatafile(logfile->df(), &ScanMarker, static_cast(&state)); + return TRI_IterateDatafile(logfile->df(), &ScanMarker, static_cast(_recoverState)); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief write abort markers for all open transactions +//////////////////////////////////////////////////////////////////////////////// + +void LogfileManager::closeOpenTransactions () { + TRI_ASSERT(_recoverState != nullptr); + + if (! _recoverState->failedTransactions.empty()) { + LOG_TRACE("writing abort markers for previously failed transactions"); + + // write an abort marker for all transactions + for (auto it = _recoverState->failedTransactions.begin(); it != _recoverState->failedTransactions.end(); ++it) { + TRI_voc_tid_t transactionId = (*it).first; + + if ((*it).second.second) { + // already handled + continue; + } + + TRI_voc_tick_t databaseId = (*it).second.first; + + // only write abort markers for databases that haven't been deleted yet + if (_recoverState->droppedDatabases.find(databaseId) == _recoverState->droppedDatabases.end()) { + AbortTransactionMarker marker(databaseId, transactionId); + SlotInfoCopy slotInfo = allocateAndWrite(marker.mem(), marker.size(), false); + + if (slotInfo.errorCode != TRI_ERROR_NO_ERROR) { + THROW_ARANGO_EXCEPTION(slotInfo.errorCode); + } + } + } + } } //////////////////////////////////////////////////////////////////////////////// @@ -1404,51 +1433,9 @@ bool LogfileManager::scanLogfile (Logfile const* logfile, bool LogfileManager::runRecovery () { LOG_TRACE("running WAL recovery"); - RecoverState state; - state.lastTick = 0; - - int logfilesToCollect = 0; - - // we're the only ones that access the logfiles at this point - // nevertheless, get the read-lock - { - READ_LOCKER(_logfilesLock); - - // first iterate the logfiles in order and track which collections are in use - // this also populates a list of failed transactions - for (auto it = _logfiles.begin(); it != _logfiles.end(); ++it) { - Logfile* logfile = (*it).second; - - if (logfile != nullptr) { - if (logfile->status() == Logfile::StatusType::OPEN || - logfile->status() == Logfile::StatusType::SEALED) { - ++logfilesToCollect; - } - - if (! scanLogfile(logfile, state)) { - LOG_TRACE("WAL recovery failed when scanning logfile '%s'", logfile->filename().c_str()); - return false; - } - } - } - } - - // update the tick with the max tick we found in the WAL - TRI_UpdateTickServer(state.lastTick); - - // note all failed transactions that we found plus the list - // of collections and databases that we can ignore - { - WRITE_LOCKER(_logfilesLock); - _failedTransactions = state.failedTransactions; - _droppedDatabases = state.droppedDatabases; - _droppedCollections = state.droppedCollections; - } - // "seal" any open logfiles so the collector can copy over everything this->setAllSealed(); - int res = startCollectorThread(); if (res != TRI_ERROR_NO_ERROR) { @@ -1461,6 +1448,24 @@ bool LogfileManager::runRecovery () { LOG_TRACE("waiting for collector to catch up"); waitForCollector(_lastOpenedId); + // from now on, we allow writes to the logfile + allowWrites(true); + + try { + closeOpenTransactions(); + } + catch (triagens::arango::Exception const& ex) { + LOG_ERROR("could not abort previously open transactions: %s", TRI_errno_string(ex.code())); + return false; + } + catch (...) { + LOG_ERROR("could not abort previously open transactions"); + return false; + } + + // write the current state into the shutdown file + writeShutdownInfo(true); + { // reset the list of failed transactions WRITE_LOCKER(_logfilesLock); @@ -1469,10 +1474,9 @@ bool LogfileManager::runRecovery () { _droppedCollections.clear(); } + // finished recovery _inRecovery = false; - // from now on, we allow writes to the logfile - allowWrites(true); // tell the collector that the recovery is over now _collectorThread->recoveryDone(); @@ -1487,10 +1491,14 @@ bool LogfileManager::runRecovery () { return false; } - if (logfilesToCollect > 0) { + if (_recoverState->logfilesToCollect > 0) { LOG_INFO("WAL recovery finished successfully"); } + // recover state is not needed anymore + delete _recoverState; + _recoverState = nullptr; + return true; } @@ -1545,6 +1553,13 @@ int LogfileManager::readShutdownInfo () { lastSealedId = lastCollectedId; } + std::string const shutdownTime(basics::JsonHelper::getStringValue(json, "shutdownTime")); + if (shutdownTime.empty()) { + LOG_TRACE("no previous shutdown time found"); + } + else { + LOG_TRACE("previous shutdown was at '%s'", shutdownTime.c_str()); + } { WRITE_LOCKER(_logfilesLock); @@ -1759,8 +1774,7 @@ int LogfileManager::inventory () { int LogfileManager::inspectLogfiles () { LOG_TRACE("inspecting WAL logfiles"); - RecoverState state; - state.lastTick = 0; + TRI_ASSERT(_recoverState != nullptr); // we're the only ones that access the logfiles at this point // nevertheless, get the read-lock @@ -1773,7 +1787,12 @@ int LogfileManager::inspectLogfiles () { Logfile* logfile = (*it).second; if (logfile != nullptr) { - if (! scanLogfileTick(logfile, state)) { + if (logfile->status() == Logfile::StatusType::OPEN || + logfile->status() == Logfile::StatusType::SEALED) { + ++_recoverState->logfilesToCollect; + } + + if (! scanLogfile(logfile)) { LOG_TRACE("WAL inspection failed when scanning logfile '%s'", logfile->filename().c_str()); return TRI_ERROR_INTERNAL; } @@ -1784,7 +1803,19 @@ int LogfileManager::inspectLogfiles () { } // update the tick with the max tick we found in the WAL - TRI_UpdateTickServer(state.lastTick); + TRI_UpdateTickServer(_recoverState->lastTick); + + // note all failed transactions that we found plus the list + // of collections and databases that we can ignore + { + WRITE_LOCKER(_logfilesLock); + for (auto it = _recoverState->failedTransactions.begin(); it != _recoverState->failedTransactions.end(); ++it) { + _failedTransactions.insert((*it).first); + } + + _droppedDatabases = _recoverState->droppedDatabases; + _droppedCollections = _recoverState->droppedCollections; + } return TRI_ERROR_NO_ERROR; } diff --git a/arangod/Wal/LogfileManager.h b/arangod/Wal/LogfileManager.h index f08dafe1bc..97d7e45eda 100644 --- a/arangod/Wal/LogfileManager.h +++ b/arangod/Wal/LogfileManager.h @@ -60,11 +60,21 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// struct RecoverState { + RecoverState () + : collections(), + failedTransactions(), + droppedCollections(), + droppedDatabases(), + lastTick(0), + logfilesToCollect(0) { + } + std::unordered_map collections; - std::unordered_set failedTransactions; + std::unordered_map> failedTransactions; std::unordered_set droppedCollections; std::unordered_set droppedDatabases; TRI_voc_tick_t lastTick; + int logfilesToCollect; }; // ----------------------------------------------------------------------------- @@ -546,19 +556,17 @@ namespace triagens { void waitForCollector (Logfile::IdType); -//////////////////////////////////////////////////////////////////////////////// -/// @brief scan a single logfile for the max tick -//////////////////////////////////////////////////////////////////////////////// - - bool scanLogfileTick (Logfile const*, - RecoverState&); - //////////////////////////////////////////////////////////////////////////////// /// @brief scan a single logfile //////////////////////////////////////////////////////////////////////////////// - bool scanLogfile (Logfile const*, - RecoverState&); + bool scanLogfile (Logfile const*); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief write abort markers for all open transactions +//////////////////////////////////////////////////////////////////////////////// + + void closeOpenTransactions (); //////////////////////////////////////////////////////////////////////////////// /// @brief run the recovery procedure @@ -699,6 +707,12 @@ namespace triagens { std::string _directory; +//////////////////////////////////////////////////////////////////////////////// +/// @brief state during recovery +//////////////////////////////////////////////////////////////////////////////// + + RecoverState* _recoverState; + //////////////////////////////////////////////////////////////////////////////// /// @brief the size of each logfile //////////////////////////////////////////////////////////////////////////////// From bab8ff0bde8bca0b873e3b04ddf2eab8e1b1615d Mon Sep 17 00:00:00 2001 From: gschwab Date: Tue, 24 Jun 2014 14:06:27 +0200 Subject: [PATCH 18/21] changing graph management - initial checkin --- .../js/modules/org/arangodb/general-graph.js | 221 +++++++++++++++++- .../aardvark/frontend/js/routers/router.js | 2 +- .../frontend/js/views/graphManagementView.js | 77 ++++++ 3 files changed, 295 insertions(+), 5 deletions(-) diff --git a/js/apps/system/aardvark/frontend/js/modules/org/arangodb/general-graph.js b/js/apps/system/aardvark/frontend/js/modules/org/arangodb/general-graph.js index f6f5fda83f..44cf9276fc 100644 --- a/js/apps/system/aardvark/frontend/js/modules/org/arangodb/general-graph.js +++ b/js/apps/system/aardvark/frontend/js/modules/org/arangodb/general-graph.js @@ -2977,6 +2977,215 @@ Graph.prototype._countCommonProperties = function(vertex1Example, vertex2Example }; +//////////////////////////////////////////////////////////////////////////////// +/// @startDocuBlock JSF_general_graph_paths +/// +/// `graph._paths (options)` +/// *The _paths function returns all paths of a graph.* +/// +/// This function determines all available paths in a graph. +/// +/// *Parameters* +/// +/// * *options* (optional) : An object containing options, see below: +/// * *direction* : The direction of the edges. Possible values are *any*, +/// *inbound* and *outbound* (default). +/// * *followCycles* (optional) : If set to *true* the query follows cycles in the graph, +/// default is false. +/// * *minLength* (optional) : Defines the minimal length a path must +/// have to be returned (default is 0). +/// * *maxLength* (optional) : Defines the maximal length a path must +/// have to be returned (default is 10). +/// +/// *Examples* +/// +/// Return all paths of the graph "social": +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModulePaths} +/// ~ var db = require("internal").db; +/// var examples = require("org/arangodb/graph-examples/example-graph.js"); +/// var g = examples.loadGraph("social"); +/// g._paths(); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// +/// Return all inbound paths of the graph "social" with a maximal +/// length of 1 and a minimal length of 2: +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModulePaths2} +/// ~ var db = require("internal").db; +/// var examples = require("org/arangodb/graph-examples/example-graph.js"); +/// var g = examples.loadGraph("social"); +/// g._paths({direction : 'inbound', minLength : 1, maxLength : 2}); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// @endDocuBlock +// +//////////////////////////////////////////////////////////////////////////////// +Graph.prototype._paths = function(options) { + var query = "RETURN" + + " GRAPH_PATHS(@graphName" + + ',@options' + + ')'; + options = options || {}; + var bindVars = { + "graphName": this.__name, + "options": options + }; + var result = db._query(query, bindVars).toArray(); + return result; +}; + +//////////////////////////////////////////////////////////////////////////////// +/// @startDocuBlock JSF_general_graph_shortest_path +/// +/// `graph._shortestPath (startVertexExample, endVertexExample, options)` +/// *The _shortestPath function returns all shortest paths of a graph.* +/// +/// This function determines all shortest paths in a graph. +/// The function accepts an id, an example, a list of examples +/// or even an empty example as parameter for +/// start and end vertex. If one wants to call this function to receive nearly all +/// shortest paths for a graph the option *algorithm* should be set to +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) +/// to increase performance. +/// If no algorithm is provided in the options the function chooses the appropriate +/// one (either [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) +/// or [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm)) according to its parameters. +/// The length of a path is by default the amount of edges from one start vertex to +/// an end vertex. The option weight allows the user to define an edge attribute +/// representing the length. +/// +/// *Parameters* +/// +/// * *startVertexExample* (optional) : An example for the desired start Vertices +/// (see [Definition of examples](#definition_of_examples)). +/// * *endVertexExample* (optional) : An example for the desired +/// end Vertices (see [Definition of examples](#definition_of_examples)). +/// * *options* (optional) : An object containing options, see below: +/// * *direction* : The direction of the edges as a string. +/// Possible values are *outbound*, *inbound* and *any* (default). +/// * *edgeCollectionRestriction* : One or multiple edge +/// collection names. Only edges from these collections will be considered for the path. +/// * *startVertexCollectionRestriction* : One or multiple vertex +/// collection names. Only vertices from these collections will be considered as +/// start vertex of a path. +/// * *endVertexCollectionRestriction* : One or multiple vertex +/// collection names. Only vertices from these collections will be considered as +/// end vertex of a path. +/// * *edgeExamples* : A filter example for the +/// edges in the shortest paths +/// (see [example](#short_explaination_of_the_vertex_example_parameter)). +/// * *algorithm* : The algorithm to calculate +/// the shortest paths. If both start and end vertex examples are empty +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) is +/// used, otherwise the default is [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm) +/// * *weight* : The name of the attribute of +/// the edges containing the length as a string. +/// * *defaultWeight* : Only used with the option *weight*. +/// If an edge does not have the attribute named as defined in option *weight* this default +/// is used as length. +/// If no default is supplied the default would be positive Infinity so the path could +/// not be calculated. +/// +/// *Examples* +/// +/// A route planner example, shortest path from all german to all french cities: +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModuleShortestPaths1} +/// ~ var db = require("internal").db; +/// var examples = require("org/arangodb/graph-examples/example-graph.js"); +/// var g = examples.loadGraph("routeplanner"); +/// | g._shortestPath({}, {}, {weight : 'distance', endVertexCollectionRestriction : 'frenchCity', +/// startVertexCollectionRestriction : 'germanCity'}); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// +/// A route planner example, shortest path from Hamburg and Cologne to Lyon: +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModuleShortestPaths2} +/// ~ var db = require("internal").db; +/// var examples = require("org/arangodb/graph-examples/example-graph.js"); +/// var g = examples.loadGraph("routeplanner"); +/// | g._shortestPath([{_id: 'germanCity/Cologne'},{_id: 'germanCity/Munich'}], 'frenchCity/Lyon', +/// {weight : 'distance'}); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// +/// @endDocuBlock +// +//////////////////////////////////////////////////////////////////////////////// +Graph.prototype._shortestPath = function(startVertexExample, endVertexExample, options) { + var ex1 = transformExample(startVertexExample); + var ex2 = transformExample(endVertexExample); + var query = "RETURN" + + " GRAPH_SHORTEST_PATH(@graphName" + + ',@ex1' + + ',@ex2' + + ',@options' + + ')'; + options = options || {}; + var bindVars = { + "graphName": this.__name, + "options": options, + "ex1": ex1, + "ex2": ex2 + }; + var result = db._query(query, bindVars).toArray(); + return result; +}; + + +//////////////////////////////////////////////////////////////////////////////// +/// @startDocuBlock JSF_general_graph_distance_to +/// +/// `graph._distanceTo (startVertexExample, endVertexExample, options)` +/// *The _distanceTo function returns all paths and there distance within a graph.* +/// +/// This function is a wrapper of [graph._shortestPath](#_shortestpath). +/// It does not return the actual path but only the distance between two vertices. +/// +/// *Examples* +/// +/// A route planner example, shortest distance from all german to all french cities: +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModuleDistanceTo1} +/// ~ var db = require("internal").db; +/// var examples = require("org/arangodb/graph-examples/example-graph.js"); +/// var g = examples.loadGraph("routeplanner"); +/// | g._distanceTo({}, {}, {weight : 'distance', endVertexCollectionRestriction : 'frenchCity', +/// startVertexCollectionRestriction : 'germanCity'}); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// +/// A route planner example, shortest distance from Hamburg and Cologne to Lyon: +/// +/// @EXAMPLE_ARANGOSH_OUTPUT{generalGraphModuleDistanceTo2} +/// ~ var db = require("internal").db; +/// var examples = require("org/arangodb/graph-examples/example-graph.js"); +/// var g = examples.loadGraph("routeplanner"); +/// | g._distanceTo([{_id: 'germanCity/Cologne'},{_id: 'germanCity/Munich'}], 'frenchCity/Lyon', +/// {weight : 'distance'}); +/// @END_EXAMPLE_ARANGOSH_OUTPUT +/// +/// @endDocuBlock +// +//////////////////////////////////////////////////////////////////////////////// +Graph.prototype._distanceTo = function(startVertexExample, endVertexExample, options) { + var ex1 = transformExample(startVertexExample); + var ex2 = transformExample(endVertexExample); + var query = "RETURN" + + " GRAPH_DISTANCE_TO(@graphName" + + ',@ex1' + + ',@ex2' + + ',@options' + + ')'; + options = options || {}; + var bindVars = { + "graphName": this.__name, + "options": options, + "ex1": ex1, + "ex2": ex2 + }; + var result = db._query(query, bindVars).toArray(); + return result; +}; + //////////////////////////////////////////////////////////////////////////////// /// @startDocuBlock JSF_general_graph_absolute_eccentricity /// @@ -3001,7 +3210,8 @@ Graph.prototype._countCommonProperties = function(vertex1Example, vertex2Example /// considered for target vertices. /// * *edgeExamples*: Filter the edges to be followed, see [Definition of examples](#definition_of_examples) /// * *algorithm*: The algorithm to calculate the shortest paths, possible values are -/// *"Floyd-Warshall"* and *"Dijkstra"*. +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) and +/// [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight*: The name of the attribute of the edges containing the weight. /// * *defaultWeight*: Only used with the option *weight*. /// If an edge does not have the attribute named as defined in option *weight* this default @@ -3129,7 +3339,8 @@ Graph.prototype._eccentricity = function(options) { /// considered for target vertices. /// * *edgeExamples*: Filter the edges to be followed, see [Definition of examples](#definition_of_examples) /// * *algorithm*: The algorithm to calculate the shortest paths, possible values are -/// *"Floyd-Warshall"* and *"Dijkstra"*. +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) and +/// [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight*: The name of the attribute of the edges containing the weight. /// * *defaultWeight*: Only used with the option *weight*. /// If an edge does not have the attribute named as defined in option *weight* this default @@ -3377,7 +3588,8 @@ Graph.prototype._betweenness = function(options) { /// * *options* (optional): An object defining further options. Can have the following values: /// * *direction*: The direction of the edges. Possible values are *outbound*, *inbound* and *any* (default). /// * *algorithm*: The algorithm to calculate the shortest paths, possible values are -/// *"Floyd-Warshall"* and *"Dijkstra"*. +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) and +/// [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight*: The name of the attribute of the edges containing the weight. /// * *defaultWeight*: Only used with the option *weight*. /// If an edge does not have the attribute named as defined in option *weight* this default @@ -3445,7 +3657,8 @@ Graph.prototype._radius = function(options) { /// * *options* (optional): An object defining further options. Can have the following values: /// * *direction*: The direction of the edges. Possible values are *outbound*, *inbound* and *any* (default). /// * *algorithm*: The algorithm to calculate the shortest paths, possible values are -/// *"Floyd-Warshall"* and *"Dijkstra"*. +/// [Floyd-Warshall](http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm) and +/// [Dijkstra](http://en.wikipedia.org/wiki/Dijkstra's_algorithm). /// * *weight*: The name of the attribute of the edges containing the weight. /// * *defaultWeight*: Only used with the option *weight*. /// If an edge does not have the attribute named as defined in option *weight* this default diff --git a/js/apps/system/aardvark/frontend/js/routers/router.js b/js/apps/system/aardvark/frontend/js/routers/router.js index e3e78e2018..e3dd4b2535 100644 --- a/js/apps/system/aardvark/frontend/js/routers/router.js +++ b/js/apps/system/aardvark/frontend/js/routers/router.js @@ -20,7 +20,7 @@ "databases": "databases", "applications": "applications", "application/documentation/:key": "appDocumentation", - "graph": "graph", + "graph": "graphManagement", "graphManagement": "graphManagement", "userManagement": "userManagement", "userProfile": "userProfile", diff --git a/js/apps/system/aardvark/frontend/js/views/graphManagementView.js b/js/apps/system/aardvark/frontend/js/views/graphManagementView.js index edf7c4fa91..baafe79218 100644 --- a/js/apps/system/aardvark/frontend/js/views/graphManagementView.js +++ b/js/apps/system/aardvark/frontend/js/views/graphManagementView.js @@ -263,6 +263,83 @@ window.modalView.show("modalTable.ejs", "Graph Properties", buttons, tableContent); + }, + createNewGraphModal2: function() { + var buttons = [], + tableContent = []; + + tableContent.push( + window.modalView.createTextEntry( + "createNewGraphName", + "Name", + "", + "The name to identify the graph. Has to be unique.", + "graphName", + true + ) + ); + tableContent.push( + window.modalView.createTextEntry( + "newEdgeDefinitions", + "Edge definitions", + "", + "Some info for edge definitions", + "Edge definitions", + true + ) + ); + tableContent.push( + window.modalView.createSelect2Entry( + "newVertexCollections", + "Vertex collections", + "", + "Some info for vertex collections", + "Vertex Collections", + false + ) + ); + buttons.push( + window.modalView.createSuccessButton("Create", this.createNewGraph.bind(this)) + ); + + window.modalView.show("modalTable.ejs", "Add new Graph", buttons, tableContent); + }, + + createEditGraphModal2: function(name, vertices, edges) { + var buttons = [], + tableContent = []; + + tableContent.push( + window.modalView.createReadOnlyEntry( + "editGraphName", + "Name", + name, + false + ) + ); + tableContent.push( + window.modalView.createReadOnlyEntry( + "editVertices", + "Vertices", + vertices, + false + ) + ); + tableContent.push( + window.modalView.createReadOnlyEntry( + "editEdges", + "Edges", + edges, + false + ) + ); + + buttons.push( + window.modalView.createDeleteButton("Delete", this.deleteGraph.bind(this)) + ); + + window.modalView.show("modalTable.ejs", "Edit Graph", buttons, tableContent); + } }); From 44c11d3846e7867124772e0c57892afb38e2bcab Mon Sep 17 00:00:00 2001 From: gschwab Date: Tue, 24 Jun 2014 14:08:48 +0200 Subject: [PATCH 19/21] graph management: links changed --- .../system/aardvark/frontend/js/views/graphManagementView.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/apps/system/aardvark/frontend/js/views/graphManagementView.js b/js/apps/system/aardvark/frontend/js/views/graphManagementView.js index baafe79218..e54b136b07 100644 --- a/js/apps/system/aardvark/frontend/js/views/graphManagementView.js +++ b/js/apps/system/aardvark/frontend/js/views/graphManagementView.js @@ -19,7 +19,7 @@ addNewGraph: function(e) { e.preventDefault(); - this.createNewGraphModal(); + this.createNewGraphModal2(); }, deleteGraph: function(e) { @@ -54,7 +54,7 @@ this.collection.fetch(); this.graphToEdit = this.evaluateGraphName($(e.currentTarget).attr("id"), '_settings'); var graph = this.collection.findWhere({_key: this.graphToEdit}); - this.createEditGraphModal(this.graphToEdit, graph.get("vertices"), graph.get("edges")); + this.createEditGraphModal2(this.graphToEdit, graph.get("vertices"), graph.get("edges")); }, info : function(e) { From 3dc71881417eb5245db6a090499f6d3aa2e36fb2 Mon Sep 17 00:00:00 2001 From: scottashton Date: Tue, 24 Jun 2014 14:26:46 +0200 Subject: [PATCH 20/21] heal the build --- arangod/Ahuacatl/ahuacatl-functions.cpp | 2 +- js/common/tests/shell-general-graph.js | 12 ++++++------ js/server/tests/ahuacatl-general-graph.js | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arangod/Ahuacatl/ahuacatl-functions.cpp b/arangod/Ahuacatl/ahuacatl-functions.cpp index 98089e9cd6..0351164d5d 100644 --- a/arangod/Ahuacatl/ahuacatl-functions.cpp +++ b/arangod/Ahuacatl/ahuacatl-functions.cpp @@ -668,7 +668,7 @@ TRI_associative_pointer_t* TRI_CreateFunctionsAql (void) { // graph functions REGISTER_FUNCTION("PATHS", "GRAPH_PATHS", false, false, "c,h|s,b", &OptimisePaths); - REGISTER_FUNCTION("GRAPH_PATHS", "GENERAL_GRAPH_PATHS", false, false, "s|a", &OptimisePaths); + REGISTER_FUNCTION("GRAPH_PATHS", "GENERAL_GRAPH_PATHS", false, false, "s|a", NULL); REGISTER_FUNCTION("SHORTEST_PATH", "GRAPH_SHORTEST_PATH", false, false, "h,h,s,s,s|a", NULL); REGISTER_FUNCTION("GRAPH_SHORTEST_PATH", "GENERAL_GRAPH_SHORTEST_PATH", false, false, "s,als,als|a", NULL); REGISTER_FUNCTION("GRAPH_DISTANCE_TO", "GENERAL_GRAPH_DISTANCE_TO", false, false, "s,als,als|a", NULL); diff --git a/js/common/tests/shell-general-graph.js b/js/common/tests/shell-general-graph.js index 88919b5648..d3c28fa26e 100644 --- a/js/common/tests/shell-general-graph.js +++ b/js/common/tests/shell-general-graph.js @@ -2755,12 +2755,12 @@ function MeasurementsSuite() { /// @brief executes the test suites //////////////////////////////////////////////////////////////////////////////// -//jsunity.run(GeneralGraphCommonNeighborsSuite); -//jsunity.run(GeneralGraphAQLQueriesSuite); -//jsunity.run(EdgesAndVerticesSuite); -//jsunity.run(GeneralGraphCreationSuite); -//jsunity.run(ChainedFluentAQLResultsSuite); -//jsunity.run(OrphanCollectionSuite); +jsunity.run(GeneralGraphCommonNeighborsSuite); +jsunity.run(GeneralGraphAQLQueriesSuite); +jsunity.run(EdgesAndVerticesSuite); +jsunity.run(GeneralGraphCreationSuite); +jsunity.run(ChainedFluentAQLResultsSuite); +jsunity.run(OrphanCollectionSuite); jsunity.run(MeasurementsSuite); return jsunity.done(); diff --git a/js/server/tests/ahuacatl-general-graph.js b/js/server/tests/ahuacatl-general-graph.js index c8e0ef65b3..a1884c70eb 100644 --- a/js/server/tests/ahuacatl-general-graph.js +++ b/js/server/tests/ahuacatl-general-graph.js @@ -560,7 +560,7 @@ function ahuacatlQueryGeneralPathsTestSuite() { testPathsWithDirectionAnyAndMaxLength1: function () { var actual, result = {}, i = 0, ed; - actual = getQueryResults("FOR e IN GRAPH_PATHS('bla3', 'any', false , 1 , 1) SORT e.source._key,e.destination._key RETURN [e.source._key,e.destination._key,e.edges]"); + actual = getQueryResults("FOR e IN GRAPH_PATHS('bla3', {direction :'any', minLength : 1 , maxLength: 1}) SORT e.source._key,e.destination._key RETURN [e.source._key,e.destination._key,e.edges]"); actual.forEach(function (p) { i++; ed = ""; @@ -589,7 +589,7 @@ function ahuacatlQueryGeneralPathsTestSuite() { testInBoundPaths: function () { var actual, result = {}, i = 0, ed; - actual = getQueryResults("FOR e IN GRAPH_PATHS('bla3', 'inbound', false, 1) SORT e.source._key,e.destination._key RETURN [e.source._key,e.destination._key,e.edges]"); + actual = getQueryResults("FOR e IN GRAPH_PATHS('bla3', {direction : 'inbound', minLength : 1}) SORT e.source._key,e.destination._key RETURN [e.source._key,e.destination._key,e.edges]"); actual.forEach(function (p) { i++; From 9e818fb010853895e8134b191ebcd496f82731b7 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 24 Jun 2014 14:26:51 +0200 Subject: [PATCH 21/21] removed warnings --- arangod/Ahuacatl/ahuacatl-codegen.cpp | 8 ++----- arangod/Ahuacatl/ahuacatl-functions.cpp | 31 +++++++++---------------- arangod/VocBase/voc-shaper.cpp | 2 +- 3 files changed, 14 insertions(+), 27 deletions(-) diff --git a/arangod/Ahuacatl/ahuacatl-codegen.cpp b/arangod/Ahuacatl/ahuacatl-codegen.cpp index fd42889712..6927610306 100644 --- a/arangod/Ahuacatl/ahuacatl-codegen.cpp +++ b/arangod/Ahuacatl/ahuacatl-codegen.cpp @@ -1125,10 +1125,8 @@ static void GeneratePrimaryAccess (TRI_aql_codegen_js_t* const generator, const TRI_aql_collection_t* const collection, const char* const collectionName) { TRI_aql_field_access_t* fieldAccess; - size_t n; - n = idx->_fieldAccesses->_length; - TRI_ASSERT(n == 1); + TRI_ASSERT(idx->_fieldAccesses->_length == 1); fieldAccess = (TRI_aql_field_access_t*) TRI_AtVectorPointer(idx->_fieldAccesses, 0); @@ -1269,10 +1267,8 @@ static void GenerateEdgeAccess (TRI_aql_codegen_js_t* const generator, const TRI_aql_collection_t* const collection, const char* const collectionName) { TRI_aql_field_access_t* fieldAccess; - size_t n; - n = idx->_fieldAccesses->_length; - TRI_ASSERT(n > 0); + TRI_ASSERT(idx->_fieldAccesses->_length > 0); fieldAccess = (TRI_aql_field_access_t*) TRI_AtVectorPointer(idx->_fieldAccesses, 0); diff --git a/arangod/Ahuacatl/ahuacatl-functions.cpp b/arangod/Ahuacatl/ahuacatl-functions.cpp index 98089e9cd6..2549f75e17 100644 --- a/arangod/Ahuacatl/ahuacatl-functions.cpp +++ b/arangod/Ahuacatl/ahuacatl-functions.cpp @@ -389,33 +389,24 @@ static bool CheckPathRestriction (TRI_aql_field_access_t* fieldAccess, static void OptimisePaths (const TRI_aql_node_t* const fcallNode, TRI_aql_context_t* const context, TRI_aql_field_access_t* fieldAccess) { - TRI_aql_node_t* args; - TRI_aql_node_t* vertexCollection; - TRI_aql_node_t* edgeCollection; - TRI_aql_node_t* direction; - char* directionValue; - char* name; - size_t n; + TRI_aql_node_t* args = TRI_AQL_NODE_MEMBER(fcallNode, 0); - args = TRI_AQL_NODE_MEMBER(fcallNode, 0); - - if (args == NULL) { + if (args == nullptr) { return; } - vertexCollection = TRI_AQL_NODE_MEMBER(args, 0); - edgeCollection = TRI_AQL_NODE_MEMBER(args, 1); - direction = TRI_AQL_NODE_MEMBER(args, 2); + TRI_aql_node_t* vertexCollection = TRI_AQL_NODE_MEMBER(args, 0); + TRI_aql_node_t* direction = TRI_AQL_NODE_MEMBER(args, 2); - TRI_ASSERT(vertexCollection); - TRI_ASSERT(edgeCollection); - TRI_ASSERT(direction); - TRI_ASSERT(fieldAccess); + TRI_ASSERT(vertexCollection != nullptr); + TRI_ASSERT(TRI_AQL_NODE_MEMBER(args, 1) != nullptr); // edgeCollection + TRI_ASSERT(direction != nullptr); + TRI_ASSERT(fieldAccess != nullptr); - n = strlen(fieldAccess->_fullName); - name = fieldAccess->_fullName + fieldAccess->_variableNameLength; + size_t n = strlen(fieldAccess->_fullName); + char* name = fieldAccess->_fullName + fieldAccess->_variableNameLength; - directionValue = TRI_AQL_NODE_STRING(direction); + char* directionValue = TRI_AQL_NODE_STRING(direction); // try to optimise the vertex collection access if (TRI_EqualString(directionValue, "outbound")) { CheckPathRestriction(fieldAccess, context, vertexCollection, ".source.", name, n); diff --git a/arangod/VocBase/voc-shaper.cpp b/arangod/VocBase/voc-shaper.cpp index 73c6119071..609a44b8f0 100644 --- a/arangod/VocBase/voc-shaper.cpp +++ b/arangod/VocBase/voc-shaper.cpp @@ -209,7 +209,7 @@ static TRI_shape_aid_t FindOrCreateAttributeByName (TRI_shaper_t* shaper, THROW_ARANGO_EXCEPTION(slotInfo.errorCode); } - void* f = TRI_InsertKeyAssociativeSynced(&s->_attributeIds, &aid, const_cast(slotInfo.mem), false); + void* f TRI_UNUSED = TRI_InsertKeyAssociativeSynced(&s->_attributeIds, &aid, const_cast(slotInfo.mem), false); TRI_ASSERT(f == nullptr); // enter into the dictionaries