diff --git a/CHANGELOG b/CHANGELOG index 7339eb6fef..8dbb888344 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,12 @@ v2.2.0 (XXXX-XX-XX) ------------------- +* cleanup of version-check, added module org/arangodb/database-version, + added --check-version option + +* fixed issue #881: [2.1.0] Bombarded (every 10 sec or so) with + "WARNING format string is corrupt" when in non-system DB Dashboard + * specialized primary index implementation to allow faster hash table rebuilding and reduce lookups in datafiles for the actual value of `_key`. diff --git a/Documentation/UserManual/CommandLine.md b/Documentation/UserManual/CommandLine.md index 96f8ac79f3..38e9e193c5 100644 --- a/Documentation/UserManual/CommandLine.md +++ b/Documentation/UserManual/CommandLine.md @@ -23,7 +23,32 @@ General Options {#CommandLineGeneralOptions} @CLEARPAGE @anchor CommandLineUpgrade -@copydetails triagens::arango::ApplicationV8::_performUpgrade +@CMDOPT{\--upgrade} + +Specifying this option will make the server perform a database upgrade at +start. A database upgrade will first compare the version number stored in +the file VERSION in the database directory with the current server version. + +If the two version numbers match, the server will start normally. + +If the version number found in the database directory is higher than the +version number the server is running, the server expects this is an +unintentional downgrade and will warn about this. It will however start +normally. Using the server in these conditions is however not recommended +nor supported. + +If the version number found in the database directory is lower than the +version number the server is running, the server will check whether there +are any upgrade tasks to perform. It will then execute all required upgrade +tasks and print their statuses. If one of the upgrade tasks fails, the +server will exit and refuse to start. +Re-starting the server with the upgrade option will then again trigger the +upgrade check and execution until the problem is fixed. If all tasks are +finished, the server will start normally. + +Whether or not this option is specified, the server will always perform a +version check on startup. Running the server with a non-matching version +number in the VERSION file will make the server refuse to start. @CLEARPAGE @anchor CommandLineConfiguration diff --git a/UnitTests/Basics/mersenne-test.cpp b/UnitTests/Basics/mersenne-test.cpp deleted file mode 100644 index 4d77e6e91b..0000000000 --- a/UnitTests/Basics/mersenne-test.cpp +++ /dev/null @@ -1,160 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// @brief test suite for mersenne.c -/// -/// @file -/// -/// DISCLAIMER -/// -/// Copyright 2012 triagens GmbH, Cologne, Germany -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// -/// Copyright holder is triAGENS GmbH, Cologne, Germany -/// -/// @author Jan Steemann -/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany -//////////////////////////////////////////////////////////////////////////////// - -#include "BasicsC/mersenne.h" -#include - -// ----------------------------------------------------------------------------- -// --SECTION-- setup / tear-down -// ----------------------------------------------------------------------------- - -struct CMersenneSetup { - CMersenneSetup () { - BOOST_TEST_MESSAGE("setup mersenne"); - - TRI_InitialiseMersenneTwister(); - } - - ~CMersenneSetup () { - BOOST_TEST_MESSAGE("tear-down mersenne"); - } -}; - -// ----------------------------------------------------------------------------- -// --SECTION-- test suite -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @brief setup -//////////////////////////////////////////////////////////////////////////////// - -BOOST_FIXTURE_TEST_SUITE(CMersenneTest, CMersenneSetup) - -//////////////////////////////////////////////////////////////////////////////// -/// @brief test mersenne int32 -//////////////////////////////////////////////////////////////////////////////// - -BOOST_AUTO_TEST_CASE (tst_mersenne_int32) { - for (size_t i = 0; i < 100; ++i) { - int64_t value = (int64_t) TRI_Int32MersenneTwister(); - - BOOST_CHECK_EQUAL(true, value >= 0); - BOOST_CHECK_EQUAL(true, value <= UINT32_MAX); - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief test mersenne int31 -//////////////////////////////////////////////////////////////////////////////// - -BOOST_AUTO_TEST_CASE (tst_mersenne_int31) { - for (size_t i = 0; i < 100; ++i) { - int64_t value = (int64_t) TRI_Int31MersenneTwister(); - - BOOST_CHECK_EQUAL(true, value >= 0); - BOOST_CHECK_EQUAL(true, value <= INT32_MAX); - } -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief test after explicit seed -//////////////////////////////////////////////////////////////////////////////// - -BOOST_AUTO_TEST_CASE (tst_mersenne_seed) { - TRI_SeedMersenneTwister((uint32_t) 0UL); - BOOST_CHECK_EQUAL((uint32_t) 2357136044UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 2546248239UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 3071714933UL, TRI_Int32MersenneTwister()); - - TRI_SeedMersenneTwister((uint32_t) 1UL); - BOOST_CHECK_EQUAL((uint32_t) 1791095845UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 4282876139UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 3093770124UL, TRI_Int32MersenneTwister()); - - TRI_SeedMersenneTwister((uint32_t) 2UL); - BOOST_CHECK_EQUAL((uint32_t) 1872583848UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 794921487UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 111352301UL, TRI_Int32MersenneTwister()); - - TRI_SeedMersenneTwister((uint32_t) 23UL); - BOOST_CHECK_EQUAL((uint32_t) 2221777491UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 2873750246UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 4067173416UL, TRI_Int32MersenneTwister()); - - TRI_SeedMersenneTwister((uint32_t) 42UL); - BOOST_CHECK_EQUAL((uint32_t) 1608637542UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 3421126067UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 4083286876UL, TRI_Int32MersenneTwister()); - - TRI_SeedMersenneTwister((uint32_t) 458735UL); - BOOST_CHECK_EQUAL((uint32_t) 1537542272UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 4131475792UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 2280116031UL, TRI_Int32MersenneTwister()); - - TRI_SeedMersenneTwister((uint32_t) 395568682893UL); - BOOST_CHECK_EQUAL((uint32_t) 2297195664UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 2381406737UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 4184846092UL, TRI_Int32MersenneTwister()); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief test after explicit seed, repeated calls -//////////////////////////////////////////////////////////////////////////////// - -BOOST_AUTO_TEST_CASE (tst_mersenne_reseed) { - TRI_SeedMersenneTwister((uint32_t) 23UL); - BOOST_CHECK_EQUAL((uint32_t) 2221777491UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 2873750246UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 4067173416UL, TRI_Int32MersenneTwister()); - - // re-seed with same value and compare - TRI_SeedMersenneTwister((uint32_t) 23UL); - BOOST_CHECK_EQUAL((uint32_t) 2221777491UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 2873750246UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 4067173416UL, TRI_Int32MersenneTwister()); - - // seed with different value - TRI_SeedMersenneTwister((uint32_t) 458735UL); - BOOST_CHECK_EQUAL((uint32_t) 1537542272UL, TRI_Int32MersenneTwister()); - - // re-seed with original value and compare - TRI_SeedMersenneTwister((uint32_t) 23UL); - BOOST_CHECK_EQUAL((uint32_t) 2221777491UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 2873750246UL, TRI_Int32MersenneTwister()); - BOOST_CHECK_EQUAL((uint32_t) 4067173416UL, TRI_Int32MersenneTwister()); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief generate tests -//////////////////////////////////////////////////////////////////////////////// - -BOOST_AUTO_TEST_SUITE_END () - -// Local Variables: -// mode: outline-minor -// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" -// End: diff --git a/UnitTests/Makefile.unittests b/UnitTests/Makefile.unittests index 6e19844281..b92d1ad044 100755 --- a/UnitTests/Makefile.unittests +++ b/UnitTests/Makefile.unittests @@ -247,7 +247,6 @@ UnitTests_basics_suite_SOURCES = \ UnitTests/Basics/json-test.cpp \ UnitTests/Basics/json-utilities-test.cpp \ UnitTests/Basics/hashes-test.cpp \ - UnitTests/Basics/mersenne-test.cpp \ UnitTests/Basics/associative-pointer-test.cpp \ UnitTests/Basics/associative-multi-pointer-test.cpp \ UnitTests/Basics/associative-synced-test.cpp \ @@ -855,6 +854,7 @@ unittests-arangob: @builddir@/bin/arangob --configuration none --quiet --server.username "$(USERNAME)" --server.password "$(PASSWORD)" --server.endpoint unix://$(VOCDIR)/arango.sock --requests 500 --concurrency 3 --test aqltrx --complexity 1 || test "x$(FORCE)" == "x1" @builddir@/bin/arangob --configuration none --quiet --server.username "$(USERNAME)" --server.password "$(PASSWORD)" --server.endpoint unix://$(VOCDIR)/arango.sock --requests 100 --concurrency 3 --test counttrx || test "x$(FORCE)" == "x1" @builddir@/bin/arangob --configuration none --quiet --server.username "$(USERNAME)" --server.password "$(PASSWORD)" --server.endpoint unix://$(VOCDIR)/arango.sock --requests 500 --concurrency 3 --test multitrx || test "x$(FORCE)" == "x1" + @builddir@/bin/arangob --configuration none --quiet --server.username "$(USERNAME)" --server.password "$(PASSWORD)" --server.endpoint unix://$(VOCDIR)/arango.sock --requests 500 --concurrency 3 --test import-document --complexity 500 || test "x$(FORCE)" == "x1" kill `cat $(PIDFILE)` diff --git a/arangod/RestServer/ArangoServer.cpp b/arangod/RestServer/ArangoServer.cpp index f24f2d0075..a20933f50b 100644 --- a/arangod/RestServer/ArangoServer.cpp +++ b/arangod/RestServer/ArangoServer.cpp @@ -435,6 +435,7 @@ void ArangoServer::buildApplicationServer () { additional[ApplicationServer::OPTIONS_CMDLINE] ("console", "do not start as server, start a JavaScript emergency console instead") ("upgrade", "perform a database upgrade") + ("check-version", "checks the versions of the database and exit") ; // other options @@ -755,25 +756,46 @@ int ArangoServer::startupServer () { _applicationV8->setVocbase(vocbase); _applicationV8->setConcurrency(concurrency); + bool performUpgrade = false; + if (_applicationServer->programOptions().has("upgrade")) { - _applicationV8->performUpgrade(); + performUpgrade = true; } // skip an upgrade even if VERSION is missing + bool skipUpgrade = false; + if (_applicationServer->programOptions().has("no-upgrade")) { - _applicationV8->skipUpgrade(); + skipUpgrade = true; } + // ............................................................................. + // prepare everything + // ............................................................................. + + // prepare scheduler and dispatcher _applicationServer->prepare(); - // ............................................................................. - // create the dispatcher - // ............................................................................. - + // now we can create the queues _applicationDispatcher->buildStandardQueue(_dispatcherThreads, (int) _dispatcherQueueSize); + // and finish prepare _applicationServer->prepare2(); + // run version check + if (_applicationServer->programOptions().has("check-version")) { + _applicationV8->runUpgradeCheck(); + } + + _applicationV8->runVersionCheck(skipUpgrade, performUpgrade); + + // setup the V8 actions + _applicationV8->prepareActions(); + + // ............................................................................. + // create endpoints and handlers + // ............................................................................. + // we pass the options by reference, so keep them until shutdown RestActionHandler::action_options_t httpOptions; httpOptions._vocbase = vocbase; diff --git a/arangod/V8Server/ApplicationV8.cpp b/arangod/V8Server/ApplicationV8.cpp index f59a344ae3..b4894b772a 100644 --- a/arangod/V8Server/ApplicationV8.cpp +++ b/arangod/V8Server/ApplicationV8.cpp @@ -231,8 +231,6 @@ ApplicationV8::ApplicationV8 (TRI_server_t* server, _useActions(true), _developmentMode(false), _frontendDevelopmentMode(false), - _performUpgrade(false), - _skipUpgrade(false), _gcInterval(1000), _gcFrequency(10.0), _v8Options(""), @@ -280,22 +278,6 @@ void ApplicationV8::setVocbase (TRI_vocbase_t* vocbase) { _vocbase = vocbase; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief perform a database upgrade -//////////////////////////////////////////////////////////////////////////////// - -void ApplicationV8::performUpgrade () { - _performUpgrade = true; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief skip a database upgrade -//////////////////////////////////////////////////////////////////////////////// - -void ApplicationV8::skipUpgrade () { - _skipUpgrade = true; -} - //////////////////////////////////////////////////////////////////////////////// /// @brief enters a context //////////////////////////////////////////////////////////////////////////////// @@ -611,6 +593,194 @@ void ApplicationV8::enableDevelopmentMode () { _developmentMode = true; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief runs the version check +//////////////////////////////////////////////////////////////////////////////// + +void ApplicationV8::runVersionCheck (bool skip, bool perform) { + LOG_TRACE("starting version check"); + + // enter context and isolate + V8Context* context = _contexts[0]; + + context->_locker = new v8::Locker(context->_isolate); + context->_isolate->Enter(); + context->_context->Enter(); + + // run upgrade script + if (! skip) { + LOG_DEBUG("running database version check"); + + // can do this without a lock as this is the startup + for (size_t j = 0; j < _server->_databases._nrAlloc; ++j) { + TRI_vocbase_t* vocbase = (TRI_vocbase_t*) _server->_databases._table[j]; + + if (vocbase != 0) { + // special check script to be run just once in first thread (not in all) + // but for all databases + v8::HandleScope scope; + + v8::Handle args = v8::Object::New(); + args->Set(v8::String::New("upgrade"), v8::Boolean::New(perform)); + + context->_context->Global()->Set(v8::String::New("UPGRADE_ARGS"), args); + + bool ok = TRI_V8RunVersionCheck(vocbase, &_startupLoader, context->_context); + + if (! ok) { + if (context->_context->Global()->Has(v8::String::New("UPGRADE_STARTED"))) { + if (perform) { + LOG_FATAL_AND_EXIT( + "Database upgrade failed for '%s'. Please inspect the logs from the upgrade procedure", + vocbase->_name); + } + else { + LOG_FATAL_AND_EXIT( + "Database version check failed for '%s'. Please start the server with the --upgrade option", + vocbase->_name); + } + } + else { + LOG_FATAL_AND_EXIT("JavaScript error during server start"); + } + } + + LOG_DEBUG("database version check passed for '%s'", vocbase->_name); + } + } + } + + if (perform) { + + // issue #391: when invoked with --upgrade, the server will not always shut down + LOG_INFO("database upgrade passed"); + context->_context->Exit(); + context->_isolate->Exit(); + delete context->_locker; + + // regular shutdown... wait for all threads to finish + + // again, can do this without the lock + for (size_t j = 0; j < _server->_databases._nrAlloc; ++j) { + TRI_vocbase_t* vocbase = (TRI_vocbase_t*) _server->_databases._table[j]; + + if (vocbase != 0) { + vocbase->_state = 2; + + int res = TRI_ERROR_NO_ERROR; + + res |= TRI_JoinThread(&vocbase->_synchroniser); + res |= TRI_JoinThread(&vocbase->_compactor); + vocbase->_state = 3; + res |= TRI_JoinThread(&vocbase->_cleanup); + + if (res != TRI_ERROR_NO_ERROR) { + LOG_ERROR("unable to join database threads for database '%s'", vocbase->_name); + } + } + } + + LOG_INFO("finished"); + TRI_EXIT_FUNCTION(EXIT_SUCCESS, NULL); + } + + // and return from the context + context->_context->Exit(); + context->_isolate->Exit(); + delete context->_locker; + + LOG_TRACE("finished version check"); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief runs the upgrade check +//////////////////////////////////////////////////////////////////////////////// + +void ApplicationV8::runUpgradeCheck () { + LOG_TRACE("starting upgrade check"); + + // enter context and isolate + V8Context* context = _contexts[0]; + + context->_locker = new v8::Locker(context->_isolate); + context->_isolate->Enter(); + context->_context->Enter(); + + // run upgrade script + LOG_DEBUG("running database upgrade check"); + + // can do this without a lock as this is the startup + int result = 1; + + for (size_t j = 0; j < _server->_databases._nrAlloc; ++j) { + TRI_vocbase_t* vocbase = (TRI_vocbase_t*) _server->_databases._table[j]; + + if (vocbase != 0) { + // special check script to be run just once in first thread (not in all) + // but for all databases + v8::HandleScope scope; + + int status = TRI_V8RunUpgradeCheck(vocbase, &_startupLoader, context->_context); + + if (status < 0) { + LOG_FATAL_AND_EXIT( + "Database upgrade check failed for '%s'. Please inspect the logs from any errors", + vocbase->_name); + } + else if (status == 3) { + result = 3; + } + else if (status == 2 && result == 1) { + result = 2; + } + } + } + + // issue #391: when invoked with --upgrade, the server will not always shut down + context->_context->Exit(); + context->_isolate->Exit(); + delete context->_locker; + + // regular shutdown... wait for all threads to finish + + // again, can do this without the lock + for (size_t j = 0; j < _server->_databases._nrAlloc; ++j) { + TRI_vocbase_t* vocbase = (TRI_vocbase_t*) _server->_databases._table[j]; + + if (vocbase != 0) { + vocbase->_state = 2; + + int res = TRI_ERROR_NO_ERROR; + + res |= TRI_JoinThread(&vocbase->_synchroniser); + res |= TRI_JoinThread(&vocbase->_compactor); + vocbase->_state = 3; + res |= TRI_JoinThread(&vocbase->_cleanup); + + if (res != TRI_ERROR_NO_ERROR) { + LOG_ERROR("unable to join database threads for database '%s'", vocbase->_name); + } + } + } + + if (result == 1) { + TRI_EXIT_FUNCTION(EXIT_SUCCESS, NULL); + } + else { + TRI_EXIT_FUNCTION(result, NULL); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief prepares the actions +//////////////////////////////////////////////////////////////////////////////// + +void ApplicationV8::prepareActions () { + for (size_t i = 0; i < _nrInstances; ++i) { + prepareV8Actions(i); + } +} + // ----------------------------------------------------------------------------- // --SECTION-- ApplicationFeature methods // ----------------------------------------------------------------------------- @@ -643,7 +813,7 @@ void ApplicationV8::setupOptions (map /// {@inheritDoc} //////////////////////////////////////////////////////////////////////////////// -bool ApplicationV8::prepare2 () { +bool ApplicationV8::prepare () { // check the startup path if (_startupPath.empty()) { @@ -711,6 +881,15 @@ bool ApplicationV8::prepare2 () { _gcFrequency = 1; } + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + +bool ApplicationV8::prepare2 () { + // setup instances _contexts = new V8Context*[_nrInstances]; @@ -878,12 +1057,6 @@ bool ApplicationV8::prepareV8Instance (const size_t i) { } } - // set global flag before loading system files - if (i == 0 && ! _skipUpgrade) { - v8::HandleScope scope; - TRI_AddGlobalVariableVocbase(context->_context, "UPGRADE", v8::Boolean::New(_performUpgrade)); - } - // load all init files for (size_t j = 0; j < files.size(); ++j) { bool ok = _startupLoader.loadScript(context->_context, files[j]); @@ -893,78 +1066,40 @@ bool ApplicationV8::prepareV8Instance (const size_t i) { } } + // and return from the context + context->_context->Exit(); + context->_isolate->Exit(); + delete context->_locker; - // run upgrade script - if (i == 0 && ! _skipUpgrade) { - LOG_DEBUG("running database version check"); + // initialise garbage collection for context + context->_numExecutions = 0; + context->_hasDeadObjects = true; + context->_lastGcStamp = TRI_microtime(); - // can do this without a lock as this is the startup - for (size_t j = 0; j < _server->_databases._nrAlloc; ++j) { - TRI_vocbase_t* vocbase = (TRI_vocbase_t*) _server->_databases._table[j]; + LOG_TRACE("initialised V8 context #%d", (int) i); - if (vocbase != 0) { - // special check script to be run just once in first thread (not in all) - // but for all databases - v8::HandleScope scope; + _freeContexts.push_back(context); - context->_context->Global()->Set(v8::String::New("UPGRADE_ARGS"), v8::Object::New()); + return true; +} - bool ok = TRI_V8RunVersionCheck(vocbase, &_startupLoader, context->_context); +//////////////////////////////////////////////////////////////////////////////// +/// @brief prepares the V8 actions +//////////////////////////////////////////////////////////////////////////////// - if (! ok) { - if (context->_context->Global()->Has(v8::String::New("UPGRADE_STARTED"))) { - if (_performUpgrade) { - LOG_FATAL_AND_EXIT("Database upgrade failed for '%s'. Please inspect the logs from the upgrade procedure", vocbase->_name); - } - else { - LOG_FATAL_AND_EXIT("Database version check failed for '%s'. Please start the server with the --upgrade option", vocbase->_name); - } - } - else { - LOG_FATAL_AND_EXIT("JavaScript error during server start"); - } - } +void ApplicationV8::prepareV8Actions (const size_t i) { + LOG_TRACE("initialising V8 actions #%d", (int) i); - LOG_DEBUG("database version check passed for '%s'", vocbase->_name); - } - } - } + // enter context and isolate + V8Context* context = _contexts[i]; - if (_performUpgrade) { - // issue #391: when invoked with --upgrade, the server will not always shut down - LOG_INFO("database upgrade passed"); - context->_context->Exit(); - context->_isolate->Exit(); - delete context->_locker; - - // regular shutdown... wait for all threads to finish - - // again, can do this without the lock - for (size_t j = 0; j < _server->_databases._nrAlloc; ++j) { - TRI_vocbase_t* vocbase = (TRI_vocbase_t*) _server->_databases._table[j]; - - if (vocbase != 0) { - vocbase->_state = 2; - - int res = TRI_ERROR_NO_ERROR; - - res |= TRI_JoinThread(&vocbase->_synchroniser); - res |= TRI_JoinThread(&vocbase->_compactor); - vocbase->_state = 3; - res |= TRI_JoinThread(&vocbase->_cleanup); - - if (res != TRI_ERROR_NO_ERROR) { - LOG_ERROR("unable to join database threads for database '%s'", vocbase->_name); - } - } - } - - LOG_INFO("finished"); - TRI_EXIT_FUNCTION(EXIT_SUCCESS, NULL); - } + context->_locker = new v8::Locker(context->_isolate); + context->_isolate->Enter(); + context->_context->Enter(); // scan for foxx applications if (i == 0) { + // once again, we don't need the lock as this is the startup for (size_t j = 0; j < _server->_databases._nrAlloc; ++j) { TRI_vocbase_t* vocbase = (TRI_vocbase_t*) _server->_databases._table[j]; @@ -1001,15 +1136,7 @@ bool ApplicationV8::prepareV8Instance (const size_t i) { delete context->_locker; // initialise garbage collection for context - context->_numExecutions = 0; - context->_hasDeadObjects = true; - context->_lastGcStamp = TRI_microtime(); - - LOG_TRACE("initialised V8 context #%d", (int) i); - - _freeContexts.push_back(context); - - return true; + LOG_TRACE("initialised V8 actions #%d", (int) i); } //////////////////////////////////////////////////////////////////////////////// @@ -1048,6 +1175,10 @@ void ApplicationV8::shutdownV8Instance (size_t i) { LOG_TRACE("closed V8 context #%d", (int) i); } +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- + // Local Variables: // mode: outline-minor // outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}" diff --git a/arangod/V8Server/ApplicationV8.h b/arangod/V8Server/ApplicationV8.h index 0114706e67..c98b4b8b0f 100644 --- a/arangod/V8Server/ApplicationV8.h +++ b/arangod/V8Server/ApplicationV8.h @@ -269,18 +269,6 @@ namespace triagens { void setVocbase (struct TRI_vocbase_s*); -//////////////////////////////////////////////////////////////////////////////// -/// @brief enable the database version check -//////////////////////////////////////////////////////////////////////////////// - - void performUpgrade (); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief disable the database version check -//////////////////////////////////////////////////////////////////////////////// - - void skipUpgrade (); - //////////////////////////////////////////////////////////////////////////////// /// @brief enters an context //////////////////////////////////////////////////////////////////////////////// @@ -328,6 +316,24 @@ namespace triagens { _definedBooleans[name] = value; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief runs the version check +//////////////////////////////////////////////////////////////////////////////// + + void runVersionCheck (bool skip, bool perform); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief runs the upgrade check +//////////////////////////////////////////////////////////////////////////////// + + void runUpgradeCheck (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief prepares the actions +//////////////////////////////////////////////////////////////////////////////// + + void prepareActions (); + // ----------------------------------------------------------------------------- // --SECTION-- ApplicationFeature methods // ----------------------------------------------------------------------------- @@ -340,6 +346,12 @@ namespace triagens { void setupOptions (map&); +//////////////////////////////////////////////////////////////////////////////// +/// {@inheritDoc} +//////////////////////////////////////////////////////////////////////////////// + + bool prepare (); + //////////////////////////////////////////////////////////////////////////////// /// {@inheritDoc} //////////////////////////////////////////////////////////////////////////////// @@ -382,6 +394,12 @@ namespace triagens { bool prepareV8Instance (size_t); +//////////////////////////////////////////////////////////////////////////////// +/// @brief prepares the V8 actions +//////////////////////////////////////////////////////////////////////////////// + + void prepareV8Actions (size_t); + //////////////////////////////////////////////////////////////////////////////// /// @brief shut downs a V8 instances //////////////////////////////////////////////////////////////////////////////// @@ -468,45 +486,6 @@ namespace triagens { bool _frontendDevelopmentMode; -//////////////////////////////////////////////////////////////////////////////// -/// @brief perform a database upgrade -/// -/// @CMDOPT{\--upgrade} -/// -/// Specifying this option will make the server perform a database upgrade at -/// start. A database upgrade will first compare the version number stored in -/// the file VERSION in the database directory with the current server version. -/// -/// If the two version numbers match, the server will start normally. -/// -/// If the version number found in the database directory is higher than the -/// version number the server is running, the server expects this is an -/// unintentional downgrade and will warn about this. It will however start -/// normally. Using the server in these conditions is however not recommended -/// nor supported. -/// -/// If the version number found in the database directory is lower than the -/// version number the server is running, the server will check whether there -/// are any upgrade tasks to perform. It will then execute all required upgrade -/// tasks and print their statuses. If one of the upgrade tasks fails, the -/// server will exit and refuse to start. -/// Re-starting the server with the upgrade option will then again trigger the -/// upgrade check and execution until the problem is fixed. If all tasks are -/// finished, the server will start normally. -/// -/// Whether or not this option is specified, the server will always perform a -/// version check on startup. Running the server with a non-matching version -/// number in the VERSION file will make the server refuse to start. -//////////////////////////////////////////////////////////////////////////////// - - bool _performUpgrade; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief perform a database upgrade -//////////////////////////////////////////////////////////////////////////////// - - bool _skipUpgrade; - //////////////////////////////////////////////////////////////////////////////// /// @brief JavaScript garbage collection interval (each x requests) /// diff --git a/arangod/V8Server/V8PeriodicTask.cpp b/arangod/V8Server/V8PeriodicTask.cpp index 1fedec6b41..6023761d99 100644 --- a/arangod/V8Server/V8PeriodicTask.cpp +++ b/arangod/V8Server/V8PeriodicTask.cpp @@ -116,7 +116,10 @@ bool V8PeriodicTask::handlePeriod () { "(function (params) { " + _command + " } )(params);", _parameters); - _dispatcher->addJob(job); + if (! _dispatcher->addJob(job)) { + // just in case the dispatcher cannot accept the job (e.g. when shutting down) + delete job; + } return true; } diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index 3fb85bb90a..26db45b3b2 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -10218,6 +10218,28 @@ bool TRI_V8RunVersionCheck (void* vocbase, return ok; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief run upgrade check +//////////////////////////////////////////////////////////////////////////////// + +int TRI_V8RunUpgradeCheck (void* vocbase, + JSLoader* startupLoader, + v8::Handle context) { + assert(startupLoader != 0); + + v8::HandleScope scope; + TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData(); + void* orig = v8g->_vocbase; + v8g->_vocbase = vocbase; + + v8::Handle result = startupLoader->executeGlobalScript(context, "server/upgrade-check.js"); + int code = (int) TRI_ObjectToInt64(result); + + v8g->_vocbase = orig; + + return code; +} + //////////////////////////////////////////////////////////////////////////////// /// @brief initialize foxx //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/V8Server/v8-vocbase.h b/arangod/V8Server/v8-vocbase.h index fc84c1276e..b76c7107d8 100644 --- a/arangod/V8Server/v8-vocbase.h +++ b/arangod/V8Server/v8-vocbase.h @@ -103,6 +103,14 @@ bool TRI_V8RunVersionCheck (void*, triagens::arango::JSLoader*, v8::Handle); +//////////////////////////////////////////////////////////////////////////////// +/// @brief run upgrade check +//////////////////////////////////////////////////////////////////////////////// + +int TRI_V8RunUpgradeCheck (void* vocbase, + triagens::arango::JSLoader* startupLoader, + v8::Handle context); + //////////////////////////////////////////////////////////////////////////////// /// @brief initialize foxx //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/VocBase/datafile.cpp b/arangod/VocBase/datafile.cpp index 59bbc1c088..7732240db1 100644 --- a/arangod/VocBase/datafile.cpp +++ b/arangod/VocBase/datafile.cpp @@ -146,7 +146,7 @@ static int TruncateDatafile (TRI_datafile_t* const datafile, const off_t length) static int CreateSparseFile (char const* filename, const TRI_voc_size_t maximalSize) { - off_t offset; + TRI_lseek_t offset; char zero; ssize_t res; int fd; @@ -162,9 +162,9 @@ static int CreateSparseFile (char const* filename, } // create sparse file - offset = TRI_LSEEK(fd, maximalSize - 1, SEEK_SET); + offset = TRI_LSEEK(fd, (TRI_lseek_t) (maximalSize - 1), SEEK_SET); - if (offset == (off_t) -1) { + if (offset == (TRI_lseek_t) -1) { TRI_set_errno(TRI_ERROR_SYS_ERROR); TRI_CLOSE(fd); @@ -192,7 +192,6 @@ static int CreateSparseFile (char const* filename, return fd; } - //////////////////////////////////////////////////////////////////////////////// /// @brief initialises a datafile //////////////////////////////////////////////////////////////////////////////// @@ -266,7 +265,6 @@ static int TruncateAndSealDatafile (TRI_datafile_t* datafile, int fd; int res; size_t maximalSize; - off_t offset; void* data; void* mmHandle; @@ -295,9 +293,9 @@ static int TruncateAndSealDatafile (TRI_datafile_t* datafile, } // create sparse file - offset = TRI_LSEEK(fd, (TRI_lseek_t) maximalSize - 1, SEEK_SET); + TRI_lseek_t offset = TRI_LSEEK(fd, (TRI_lseek_t) (maximalSize - 1), SEEK_SET); - if (offset == (off_t) -1) { + if (offset == (TRI_lseek_t) -1) { TRI_set_errno(TRI_ERROR_SYS_ERROR); TRI_CLOSE(fd); diff --git a/js/apps/system/aardvark/cluster.js b/js/apps/system/aardvark/cluster.js index 6d65f50aeb..509b5f20be 100644 --- a/js/apps/system/aardvark/cluster.js +++ b/js/apps/system/aardvark/cluster.js @@ -187,7 +187,7 @@ var k = getStarter(); var shutdownInfo = k.shutdown(); if (shutdownInfo.error) { - require("console").log(JSON.stringify(shutdownInfo.results)); + require("console").log("%s", JSON.stringify(shutdownInfo.results)); } }); @@ -196,7 +196,7 @@ var shutdownInfo = k.shutdown(); cleanUp(); if (shutdownInfo.error) { - require("console").log(JSON.stringify(shutdownInfo.results)); + require("console").log("%s", JSON.stringify(shutdownInfo.results)); return; } }); diff --git a/js/apps/system/aardvark/frontend/js/bootstrap/errors.js b/js/apps/system/aardvark/frontend/js/bootstrap/errors.js index 4ff43c52b5..6341ead032 100644 --- a/js/apps/system/aardvark/frontend/js/bootstrap/errors.js +++ b/js/apps/system/aardvark/frontend/js/bootstrap/errors.js @@ -209,6 +209,8 @@ "ERROR_GRAPH_INVALID_FILTER_RESULT" : { "code" : 1910, "message" : "invalid filter result" }, "ERROR_GRAPH_COLLECTION_MULTI_USE" : { "code" : 1920, "message" : "an edge collection may only be used once in one edge definition of a graph." }, "ERROR_GRAPH_COLLECTION_USE_IN_MULTI_GRAPHS" : { "code" : 1921, "message" : " is already used by another graph in a different edge definition." }, + "ERROR_GRAPH_CREATE_MISSING_NAME" : { "code" : 1922, "message" : "a graph name is required to create a graph." }, + "ERROR_GRAPH_CREATE_MISSING_EDGE_DEFINITION" : { "code" : 1923, "message" : "at least one edge definition is required to create a graph." }, "ERROR_SESSION_UNKNOWN" : { "code" : 1950, "message" : "unknown session" }, "ERROR_SESSION_EXPIRED" : { "code" : 1951, "message" : "session expired" }, "SIMPLE_CLIENT_UNKNOWN_ERROR" : { "code" : 2000, "message" : "unknown client error" }, 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 4854df1db7..d26ef590bc 100644 --- a/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js +++ b/js/apps/system/aardvark/frontend/js/bootstrap/module-internal.js @@ -17,7 +17,7 @@ COLOR_OUTPUT_RESET, COLOR_BRIGHT, COLOR_BLACK, COLOR_BOLD_BLACK, COLOR_BLINK, COLOR_BLUE, COLOR_BOLD_BLUE, COLOR_BOLD_GREEN, COLOR_RED, COLOR_BOLD_RED, COLOR_GREEN, COLOR_WHITE, COLOR_BOLD_WHITE, COLOR_YELLOW, COLOR_BOLD_YELLOW, COLOR_CYAN, COLOR_BOLD_CYAN, COLOR_MAGENTA, - COLOR_BOLD_MAGENTA, PRETTY_PRINT, VALGRIND, VERSION, UPGRADE, + COLOR_BOLD_MAGENTA, PRETTY_PRINT, VALGRIND, VERSION, BYTES_SENT_DISTRIBUTION, BYTES_RECEIVED_DISTRIBUTION, CONNECTION_TIME_DISTRIBUTION, REQUEST_TIME_DISTRIBUTION, DEVELOPMENT_MODE, FE_DEVELOPMENT_MODE, THREAD_NUMBER, LOGFILE_PATH, SYS_PLATFORM, SYS_EXECUTE_EXTERNAL, SYS_STATUS_EXTERNAL, SYS_KILL_EXTERNAL, @@ -205,17 +205,6 @@ delete VERSION; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief upgrade -//////////////////////////////////////////////////////////////////////////////// - - exports.upgrade = "unknown"; - - if (typeof UPGRADE !== "undefined") { - exports.upgrade = UPGRADE; - delete UPGRADE; - } - //////////////////////////////////////////////////////////////////////////////// /// @brief platform //////////////////////////////////////////////////////////////////////////////// diff --git a/js/apps/system/aardvark/frontend/js/views/dashboardView.js b/js/apps/system/aardvark/frontend/js/views/dashboardView.js index 86d373b00e..c7a0860dd5 100644 --- a/js/apps/system/aardvark/frontend/js/views/dashboardView.js +++ b/js/apps/system/aardvark/frontend/js/views/dashboardView.js @@ -409,7 +409,7 @@ getStatistics: function () { var self = this; - var url = "statistics/short"; + var url = "/_db/_system/_admin/aardvark/statistics/short"; var urlParams = "?start="; if (self.nextStart) { @@ -551,7 +551,7 @@ }, prepareD3Charts: function (update) { - var v, self = this, f; + var self = this; var barCharts = { totalTimeDistribution: [ @@ -560,11 +560,6 @@ "bytesSentDistributionPercent", "bytesReceivedDistributionPercent"] }; - var dists = { - totalTimeDistribution: "Time Distribution", - dataTransferDistribution: "Size Distribution" - }; - if (this.d3NotInitialised) { update = false; this.d3NotInitialised = false; @@ -575,7 +570,6 @@ + 'Container .dashboard-interior-chart'); var selector = "#" + k + "Container svg"; - var dist = dists[k]; nv.addGraph(function () { var tickMarks = [0, 0.25, 0.5, 0.75, 1]; diff --git a/js/apps/system/aardvark/frontend/js/views/testView.js b/js/apps/system/aardvark/frontend/js/views/testView.js index 92058e499b..7656b93af5 100644 --- a/js/apps/system/aardvark/frontend/js/views/testView.js +++ b/js/apps/system/aardvark/frontend/js/views/testView.js @@ -15,7 +15,6 @@ readJSON: function() { var fileInput = document.getElementById('fileInput'); - var fileDisplayArea = document.getElementById('fileDisplayArea'); var file = fileInput.files[0]; var textType = 'application/json'; diff --git a/js/apps/system/aardvark/statistics.js b/js/apps/system/aardvark/statistics.js index ed56509f1f..59a137d280 100644 --- a/js/apps/system/aardvark/statistics.js +++ b/js/apps/system/aardvark/statistics.js @@ -31,7 +31,6 @@ var internal = require("internal"); var cluster = require("org/arangodb/cluster"); var actions = require("org/arangodb/actions"); -var console = require("console"); var FoxxController = require("org/arangodb/foxx").Controller; var controller = new FoxxController(applicationContext); diff --git a/js/apps/system/aardvark/test/specs/views/collectionsItemViewSpec.js b/js/apps/system/aardvark/test/specs/views/collectionsItemViewSpec.js index e75543fa96..7c70d3b213 100644 --- a/js/apps/system/aardvark/test/specs/views/collectionsItemViewSpec.js +++ b/js/apps/system/aardvark/test/specs/views/collectionsItemViewSpec.js @@ -133,7 +133,186 @@ expect(window.modalView.show).toHaveBeenCalled(); }); + it("should stop an events propagination", function() { + var e = { + stopPropagation: function(){} + }; + spyOn(e, "stopPropagation"); + tile1.noop(e); + expect(e.stopPropagation).toHaveBeenCalled(); + }); + + it("should load a collection", function() { + spyOn(tile1.model, "loadCollection"); + spyOn(tile1, "render"); + spyOn(window.modalView, "hide"); + tile1.loadCollection(); + expect(tile1.model.loadCollection).toHaveBeenCalled(); + expect(tile1.render).toHaveBeenCalled(); + expect(window.modalView.hide).toHaveBeenCalled(); + }); + + it("should unload a collection", function() { + spyOn(tile1.model, "unloadCollection"); + spyOn(tile1, "render"); + spyOn(window.modalView, "hide"); + tile1.unloadCollection(); + expect(tile1.model.unloadCollection).toHaveBeenCalled(); + expect(tile1.render).toHaveBeenCalled(); + expect(window.modalView.hide).toHaveBeenCalled(); + }); + + it("should delete a collection with success", function() { + spyOn(tile1.model, "destroy"); + spyOn(tile1.collectionsView, "render"); + spyOn(window.modalView, "hide"); + tile1.deleteCollection(); + expect(tile1.model.destroy).toHaveBeenCalled(); + expect(tile1.collectionsView.render).toHaveBeenCalled(); + expect(window.modalView.hide).toHaveBeenCalled(); + }); + + it("should save a modified collection (unloaded collection, save error)", function() { + window.App = { + notificationList: { + add: function() { + } + } + }; + + spyOn(arangoHelper, "arangoError"); + spyOn(tile1.model, "renameCollection"); + + tile1.saveModifiedCollection(); + + expect(tile1.model.renameCollection).toHaveBeenCalled(); + expect(arangoHelper.arangoError).toHaveBeenCalled(); + }); + + it("should save a modified collection (loaded collection, save error)", function() { + tile1.model.set('status', "loaded"); + window.App = { + notificationList: { + add: function() { + } + } + }; + + spyOn(arangoHelper, "arangoError"); + spyOn(tile1.model, "renameCollection"); + + tile1.saveModifiedCollection(); + + expect(tile1.model.renameCollection).toHaveBeenCalled(); + expect(arangoHelper.arangoError).toHaveBeenCalled(); + }); }); + it("should save a modified collection (unloaded collection, success)", function() { + window.App = { + notificationList: { + add: function() { + } + } + }; + + spyOn(tile1.model, "renameCollection").andReturn(true); + spyOn(tile1.collectionsView, "render"); + spyOn(window.modalView, "hide"); + tile1.saveModifiedCollection(); + + expect(window.modalView.hide).toHaveBeenCalled(); + expect(tile1.collectionsView.render).toHaveBeenCalled(); + expect(tile1.model.renameCollection).toHaveBeenCalled(); + }); + + it("should save a modified collection (loaded collection, success)", function() { + tile1.model.set('status', "loaded"); + window.App = { + notificationList: { + add: function() { + } + } + }; + + var tempdiv = document.createElement("div"); + tempdiv.id = "change-collection-size"; + document.body.appendChild(tempdiv); + $('#change-collection-size').val(123123123123); + + spyOn(tile1.model, "changeCollection").andReturn(true); + spyOn(tile1.model, "renameCollection").andReturn(true); + spyOn(tile1.collectionsView, "render"); + spyOn(window.modalView, "hide"); + tile1.saveModifiedCollection(); + + expect(window.modalView.hide).toHaveBeenCalled(); + expect(tile1.collectionsView.render).toHaveBeenCalled(); + expect(tile1.model.renameCollection).toHaveBeenCalled(); + + document.body.removeChild(tempdiv); + }); + + it("should not save a modified collection (invalid data, result)", function() { + tile1.model.set('status', "loaded"); + window.App = { + notificationList: { + add: function() { + } + } + }; + + var tempdiv = document.createElement("div"); + tempdiv.id = "change-collection-size"; + document.body.appendChild(tempdiv); + $('#change-collection-size').val(123123123123); + + spyOn(arangoHelper, "arangoError"); + spyOn(arangoHelper, "arangoNotification"); + spyOn(tile1.model, "changeCollection").andReturn(false); + spyOn(tile1.model, "renameCollection").andReturn(false); + spyOn(tile1.collectionsView, "render"); + spyOn(window.modalView, "hide"); + tile1.saveModifiedCollection(); + + expect(window.modalView.hide).not.toHaveBeenCalled(); + expect(tile1.collectionsView.render).not.toHaveBeenCalled(); + expect(tile1.model.renameCollection).toHaveBeenCalled(); + expect(arangoHelper.arangoError).toHaveBeenCalled(); + + document.body.removeChild(tempdiv); + }); + + it("should not save a modified collection (invalid data, result)", function() { + tile1.model.set('status', "loaded"); + window.App = { + notificationList: { + add: function() { + } + } + }; + + var tempdiv = document.createElement("div"); + tempdiv.id = "change-collection-size"; + document.body.appendChild(tempdiv); + $('#change-collection-size').val(123123123123); + + spyOn(arangoHelper, "arangoError"); + spyOn(arangoHelper, "arangoNotification"); + spyOn(tile1.model, "changeCollection").andReturn(false); + spyOn(tile1.model, "renameCollection").andReturn(true); + spyOn(tile1.collectionsView, "render"); + spyOn(window.modalView, "hide"); + tile1.saveModifiedCollection(); + + expect(window.modalView.hide).not.toHaveBeenCalled(); + expect(tile1.collectionsView.render).not.toHaveBeenCalled(); + expect(tile1.model.renameCollection).toHaveBeenCalled(); + expect(arangoHelper.arangoNotification).toHaveBeenCalled(); + + document.body.removeChild(tempdiv); + }); + + }); }()); diff --git a/js/common/bootstrap/errors.js b/js/common/bootstrap/errors.js index 4ff43c52b5..6341ead032 100644 --- a/js/common/bootstrap/errors.js +++ b/js/common/bootstrap/errors.js @@ -209,6 +209,8 @@ "ERROR_GRAPH_INVALID_FILTER_RESULT" : { "code" : 1910, "message" : "invalid filter result" }, "ERROR_GRAPH_COLLECTION_MULTI_USE" : { "code" : 1920, "message" : "an edge collection may only be used once in one edge definition of a graph." }, "ERROR_GRAPH_COLLECTION_USE_IN_MULTI_GRAPHS" : { "code" : 1921, "message" : " is already used by another graph in a different edge definition." }, + "ERROR_GRAPH_CREATE_MISSING_NAME" : { "code" : 1922, "message" : "a graph name is required to create a graph." }, + "ERROR_GRAPH_CREATE_MISSING_EDGE_DEFINITION" : { "code" : 1923, "message" : "at least one edge definition is required to create a graph." }, "ERROR_SESSION_UNKNOWN" : { "code" : 1950, "message" : "unknown session" }, "ERROR_SESSION_EXPIRED" : { "code" : 1951, "message" : "session expired" }, "SIMPLE_CLIENT_UNKNOWN_ERROR" : { "code" : 2000, "message" : "unknown client error" }, diff --git a/js/common/bootstrap/module-internal.js b/js/common/bootstrap/module-internal.js index 4854df1db7..d26ef590bc 100644 --- a/js/common/bootstrap/module-internal.js +++ b/js/common/bootstrap/module-internal.js @@ -17,7 +17,7 @@ COLOR_OUTPUT_RESET, COLOR_BRIGHT, COLOR_BLACK, COLOR_BOLD_BLACK, COLOR_BLINK, COLOR_BLUE, COLOR_BOLD_BLUE, COLOR_BOLD_GREEN, COLOR_RED, COLOR_BOLD_RED, COLOR_GREEN, COLOR_WHITE, COLOR_BOLD_WHITE, COLOR_YELLOW, COLOR_BOLD_YELLOW, COLOR_CYAN, COLOR_BOLD_CYAN, COLOR_MAGENTA, - COLOR_BOLD_MAGENTA, PRETTY_PRINT, VALGRIND, VERSION, UPGRADE, + COLOR_BOLD_MAGENTA, PRETTY_PRINT, VALGRIND, VERSION, BYTES_SENT_DISTRIBUTION, BYTES_RECEIVED_DISTRIBUTION, CONNECTION_TIME_DISTRIBUTION, REQUEST_TIME_DISTRIBUTION, DEVELOPMENT_MODE, FE_DEVELOPMENT_MODE, THREAD_NUMBER, LOGFILE_PATH, SYS_PLATFORM, SYS_EXECUTE_EXTERNAL, SYS_STATUS_EXTERNAL, SYS_KILL_EXTERNAL, @@ -205,17 +205,6 @@ delete VERSION; } -//////////////////////////////////////////////////////////////////////////////// -/// @brief upgrade -//////////////////////////////////////////////////////////////////////////////// - - exports.upgrade = "unknown"; - - if (typeof UPGRADE !== "undefined") { - exports.upgrade = UPGRADE; - delete UPGRADE; - } - //////////////////////////////////////////////////////////////////////////////// /// @brief platform //////////////////////////////////////////////////////////////////////////////// diff --git a/js/common/modules/org/arangodb/general-graph.js b/js/common/modules/org/arangodb/general-graph.js index 717805e786..789b31d67a 100644 --- a/js/common/modules/org/arangodb/general-graph.js +++ b/js/common/modules/org/arangodb/general-graph.js @@ -695,10 +695,16 @@ var _create = function (graphName, edgeDefinitions) { collections; if (!graphName) { - throw "a graph name is required to create a graph."; + var err = new ArangoError(); + err.errorNum = arangodb.errors.ERROR_GRAPH_CREATE_MISSING_NAME.code; + err.errorMessage = arangodb.errors.ERROR_GRAPH_CREATE_MISSING_NAME.message; + throw err; } if (!Array.isArray(edgeDefinitions) || edgeDefinitions.length === 0) { - throw "at least one edge definition is required to create a graph."; + var err = new ArangoError(); + err.errorNum = arangodb.errors.ERROR_GRAPH_CREATE_MISSING_EDGE_DEFINITION.code; + err.errorMessage = arangodb.errors.ERROR_GRAPH_CREATE_MISSING_EDGE_DEFINITION.message; + throw err; } //check, if a collection is already used in a different edgeDefinition var tmpCollections = []; @@ -874,7 +880,6 @@ var Graph = function(graphName, edgeDefinitions, vertexCollections, edgeCollecti }; // remove - var old_remove = wrap.remove; wrap.remove = function(edgeId, options) { //if _key make _id (only on 1st call) if (edgeId.indexOf("/") === -1) { @@ -1215,10 +1220,7 @@ Graph.prototype._getVertexCollectionByName = function(name) { //////////////////////////////////////////////////////////////////////////////// Graph.prototype._neighbors = function(vertexExample, options) { - var current_vertex, - target_array = [], - addNeighborToList, - AQLStmt; + var AQLStmt; if (! options) { options = { }; diff --git a/js/common/modules/org/arangodb/statistics.js b/js/common/modules/org/arangodb/statistics.js index 091da91ec9..38382fd4e0 100644 --- a/js/common/modules/org/arangodb/statistics.js +++ b/js/common/modules/org/arangodb/statistics.js @@ -87,8 +87,6 @@ function createStatisticsCollection (name) { /// TODO need to fix this //////////////////////////////////////////////////////////////////////////////// -var StatisticsNames = [ "_statisticsRaw", "_statistics", "_statistics15" ]; - function createStatisticsCollections () { 'use strict'; diff --git a/js/server/modules/org/arangodb/ahuacatl.js b/js/server/modules/org/arangodb/ahuacatl.js index d5dabd75a0..abce1f037c 100644 --- a/js/server/modules/org/arangodb/ahuacatl.js +++ b/js/server/modules/org/arangodb/ahuacatl.js @@ -4900,15 +4900,16 @@ function GENERAL_GRAPH_NEIGHBORS (graphName, options.direction = 'any'; } - var neighbors = [],match, - params = TRAVERSAL_PARAMS(), factory = TRAVERSAL.generalGraphDatasourceFactory(graphName); + var neighbors = [], + params = TRAVERSAL_PARAMS(), + factory = TRAVERSAL.generalGraphDatasourceFactory(graphName); + params.minDepth = options.minDepth === undefined ? 1 : options.minDepth; params.maxDepth = options.maxDepth === undefined ? 1 : options.maxDepth; params.paths = true; options.edgeExamples = options.edgeExamples || []; params.visitor = TRAVERSAL_NEIGHBOR_VISITOR; - var graph = RESOLVE_GRAPH_TO_DOCUMENTS(graphName, options); params.followEdges = MERGE_EXAMPLES_WITH_EDGES(options.edgeExamples, graph.edges); diff --git a/js/server/modules/org/arangodb/database-version.js b/js/server/modules/org/arangodb/database-version.js new file mode 100644 index 0000000000..d6b47b8030 --- /dev/null +++ b/js/server/modules/org/arangodb/database-version.js @@ -0,0 +1,200 @@ +/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true, stupid: true, continue: true, regexp: true nonpropdel: true*/ +/*global require, exports, module */ + +//////////////////////////////////////////////////////////////////////////////// +/// @brief database version check +/// +/// @file +/// +/// Checks if the database needs to be upgraded. +/// +/// DISCLAIMER +/// +/// Copyright 2014 triAGENS GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2014, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +var internal = require("internal"); +var cluster = require("org/arangodb/cluster"); +var fs = require("fs"); +var db = internal.db; +var console = require("console"); + +// ----------------------------------------------------------------------------- +// --SECTION-- private functions +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief logger +//////////////////////////////////////////////////////////////////////////////// + +var logger = { + info: function (msg) { + console.log("In database '%s': %s", db._name(), msg); + }, + + error: function (msg) { + console.error("In database '%s': %s", db._name(), msg); + }, + + log: function (msg) { + this.info(msg); + } +}; + +// ----------------------------------------------------------------------------- +// --SECTION-- public constants +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief VERSION_MATCH +//////////////////////////////////////////////////////////////////////////////// + +exports.VERSION_MATCH = 1; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief DOWNGRADE +//////////////////////////////////////////////////////////////////////////////// + +exports.DOWNGRADE_NEEDED = 2; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief UPGRADE +//////////////////////////////////////////////////////////////////////////////// + +exports.UPGRADE_NEEDED = 3; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief IS_CLUSTER +//////////////////////////////////////////////////////////////////////////////// + +exports.IS_CLUSTER = -1; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief CANNOT_PARSE_VERSION_FILE +//////////////////////////////////////////////////////////////////////////////// + +exports.CANNOT_PARSE_VERSION_FILE = -2; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief CANNOT_READ_VERSION_FILE +//////////////////////////////////////////////////////////////////////////////// + +exports.CANNOT_READ_VERSION_FILE = -3; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief NO_VERSION_FILE +//////////////////////////////////////////////////////////////////////////////// + +exports.NO_VERSION_FILE = -4; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief NO_SERVER_VERSION +//////////////////////////////////////////////////////////////////////////////// + +exports.NO_SERVER_VERSION = -5; + +// ----------------------------------------------------------------------------- +// --SECTION-- public functions +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks the version +//////////////////////////////////////////////////////////////////////////////// + +exports.databaseVersion = function () { + if (cluster.isCoordinator()) { + return { result: exports.IS_CLUSTER }; + } + + // path to the VERSION file + var versionFile = internal.db._path() + "/VERSION"; + var lastVersion = null; + + // VERSION file exists, read its contents + if (fs.exists(versionFile)) { + var versionInfo = fs.read(versionFile); + + if (versionInfo !== '') { + var versionValues = JSON.parse(versionInfo); + + if (versionValues && versionValues.version && ! isNaN(versionValues.version)) { + lastVersion = parseFloat(versionValues.version); + } + else { + logger.error("Cannot parse VERSION file '" + versionFile + "': '" + versionInfo + "'"); + return { result: exports.CANNOT_PARSE_VERSION_FILE }; + } + } + else { + logger.error("Cannot read VERSION file: '" + versionFile + "'"); + return { result: exports.CANNOT_READ_VERSION_FILE }; + } + } + else { + return { result: exports.NO_VERSION_FILE }; + } + + // extract server version + var currentServerVersion = internal.db._version().match(/^(\d+\.\d+).*$/); + + // server version is invalid for some reason + if (! currentServerVersion) { + logger.error("Unexpected ArangoDB server version: " + internal.db._version()); + return { result: exports.NO_SERVER_VERSION }; + } + + var currentVersion = parseFloat(currentServerVersion[1]); + + // version match! + if (lastVersion === currentVersion) { + return { + result: exports.VERSION_MATCH, + serverVersion: currentVersion, + databaseVersion: lastVersion + }; + } + + // downgrade?? + if (lastVersion > currentVersion) { + return { + result: exports.DOWNGRADE_NEEDED, + serverVersion: currentVersion, + databaseVersion: lastVersion + }; + } + + // upgrade + if (lastVersion < currentVersion) { + return { + result: exports.UPGRADE_NEEDED, + serverVersion: currentVersion, + databaseVersion: lastVersion + }; + } +}; + +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)" +// End: diff --git a/js/server/modules/org/arangodb/tasks.js b/js/server/modules/org/arangodb/tasks.js index dc4abbe858..c178afde0a 100644 --- a/js/server/modules/org/arangodb/tasks.js +++ b/js/server/modules/org/arangodb/tasks.js @@ -34,6 +34,10 @@ exports.register = internal.registerTask; exports.unregister = internal.unregisterTask; exports.get = internal.getTask; +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- + // Local Variables: // mode: outline-minor // outline-regexp: "/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @}\\|/\\*jslint" diff --git a/js/server/tests/ahuacatl-general-graph.js b/js/server/tests/ahuacatl-general-graph.js index 00d883167a..4cf6e6aef6 100644 --- a/js/server/tests/ahuacatl-general-graph.js +++ b/js/server/tests/ahuacatl-general-graph.js @@ -39,9 +39,6 @@ var assertQueryError = helper.assertQueryError; //////////////////////////////////////////////////////////////////////////////// function ahuacatlQueryGeneralEdgesTestSuite() { - var vertex = null; - var edge = null; - return { //////////////////////////////////////////////////////////////////////////////// @@ -262,9 +259,6 @@ function ahuacatlQueryGeneralEdgesTestSuite() { function ahuacatlQueryGeneralCommonTestSuite() { - var vertex = null; - var edge = null; - return { //////////////////////////////////////////////////////////////////////////////// @@ -450,9 +444,6 @@ function ahuacatlQueryGeneralCommonTestSuite() { //////////////////////////////////////////////////////////////////////////////// function ahuacatlQueryGeneralPathsTestSuite() { - var vertex = null; - var edge = null; - return { //////////////////////////////////////////////////////////////////////////////// @@ -620,9 +611,6 @@ function ahuacatlQueryGeneralPathsTestSuite() { //////////////////////////////////////////////////////////////////////////////// function ahuacatlQueryGeneralTraversalTestSuite() { - var vertex = null; - var edge = null; - return { //////////////////////////////////////////////////////////////////////////////// diff --git a/js/server/tests/shell-tasks.js b/js/server/tests/shell-tasks.js index 7f5f3c0889..a9d0df2b7c 100644 --- a/js/server/tests/shell-tasks.js +++ b/js/server/tests/shell-tasks.js @@ -555,6 +555,10 @@ jsunity.run(TaskSuite); return jsunity.done(); +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- + // Local Variables: // mode: outline-minor // outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)" diff --git a/js/server/upgrade-check.js b/js/server/upgrade-check.js new file mode 100644 index 0000000000..565bdc164f --- /dev/null +++ b/js/server/upgrade-check.js @@ -0,0 +1,49 @@ +/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true, stupid: true, continue: true, regexp: true nonpropdel: true*/ +/*global require, exports, module, UPGRADE_ARGS */ + +//////////////////////////////////////////////////////////////////////////////// +/// @brief upgrade check +/// +/// @file +/// +/// Version check at the start of the server, will optionally perform necessary +/// upgrades. +/// +/// DISCLAIMER +/// +/// Copyright 2014 triAGENS GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Dr. Frank Celler +/// @author Copyright 2014, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- upgrade check +// ----------------------------------------------------------------------------- + +(function() { + return require("org/arangodb/database-version").databaseVersion().result; +}()); + +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)" +// End: diff --git a/js/server/version-check.js b/js/server/version-check.js index c27c812e42..f55c398bc9 100755 --- a/js/server/version-check.js +++ b/js/server/version-check.js @@ -846,7 +846,7 @@ // version match! if (lastVersion === currentVersion) { - if (internal.upgrade) { + if (args.upgrade) { runUpgrade(currentVersion, true); } else { @@ -871,7 +871,7 @@ // upgrade if (lastVersion < currentVersion) { - if (internal.upgrade) { + if (args.upgrade) { return runUpgrade(currentVersion, true); } diff --git a/lib/ApplicationServer/ApplicationServer.cpp b/lib/ApplicationServer/ApplicationServer.cpp index aae26f34ae..b3c6507622 100644 --- a/lib/ApplicationServer/ApplicationServer.cpp +++ b/lib/ApplicationServer/ApplicationServer.cpp @@ -523,15 +523,15 @@ void ApplicationServer::prepare2 () { for (vector::reverse_iterator i = _features.rbegin(); i != _features.rend(); ++i) { ApplicationFeature* feature = *i; - LOG_DEBUG("preparing server feature '%s'", feature->getName().c_str()); + LOG_DEBUG("preparing(2) server feature '%s'", feature->getName().c_str()); bool ok = feature->prepare2(); if (! ok) { - LOG_FATAL_AND_EXIT("failed to prepare server feature '%s'", feature->getName().c_str()); + LOG_FATAL_AND_EXIT("failed to prepare(2) server feature '%s'", feature->getName().c_str()); } - LOG_TRACE("prepared server feature '%s'", feature->getName().c_str()); + LOG_TRACE("prepared(2) server feature '%s'", feature->getName().c_str()); } } diff --git a/lib/Basics/InitialiseBasics.cpp b/lib/Basics/InitialiseBasics.cpp index 7525d63a69..cf9be15fe5 100644 --- a/lib/Basics/InitialiseBasics.cpp +++ b/lib/Basics/InitialiseBasics.cpp @@ -47,7 +47,7 @@ namespace triagens { // use the rng so the linker does not remove it from the executable // we might need it later because .so files might refer to the symbols Random::random_e v = Random::selectVersion(Random::RAND_MERSENNE); - Random::UniformInteger random(0, 1); + Random::UniformInteger random(0, INT32_MAX); random.random(); Random::selectVersion(v); diff --git a/lib/Basics/RandomGenerator.cpp b/lib/Basics/RandomGenerator.cpp index 9202d646cc..fc1812f160 100644 --- a/lib/Basics/RandomGenerator.cpp +++ b/lib/Basics/RandomGenerator.cpp @@ -28,7 +28,6 @@ #include "RandomGenerator.h" -#include "BasicsC/mersenne.h" #include "BasicsC/logging.h" #include "BasicsC/socket-utils.h" #include "Basics/Exceptions.h" @@ -36,6 +35,9 @@ #include "Basics/MutexLocker.h" #include "Basics/Thread.h" +#include +#include + using namespace std; using namespace triagens::basics; @@ -92,8 +94,8 @@ namespace RandomHelper { template class RandomDeviceDirect : public RandomDevice { public: - RandomDeviceDirect (string path) - : fd(1), pos(0) { + RandomDeviceDirect (std::string const& path) + : fd(-1), pos(0) { fd = TRI_OPEN(path.c_str(), O_RDONLY); if (fd < 0) { @@ -106,7 +108,9 @@ namespace RandomHelper { ~RandomDeviceDirect () { - TRI_CLOSE(fd); + if (fd >= 0) { + TRI_CLOSE(fd); + } } @@ -121,6 +125,7 @@ namespace RandomHelper { private: void fillBuffer () { size_t n = sizeof(buffer); + char* ptr = reinterpret_cast(&buffer); while (0 < n) { @@ -151,7 +156,8 @@ namespace RandomHelper { template class RandomDeviceCombined : public RandomDevice { public: - RandomDeviceCombined (string path) : fd(0), pos(0), rseed(0) { + RandomDeviceCombined (std::string const& path) + : fd(-1), pos(0), rseed(0) { fd = TRI_OPEN(path.c_str(), O_RDONLY); @@ -183,7 +189,9 @@ namespace RandomHelper { ~RandomDeviceCombined () { - TRI_CLOSE(fd); + if (fd >= 0) { + TRI_CLOSE(fd); + } } @@ -224,11 +232,12 @@ namespace RandomHelper { } if (0 < n) { + std::mt19937 engine; unsigned long seed = RandomDevice::getSeed(); - TRI_SeedMersenneTwister((uint32_t) (rseed ^ (uint32_t) seed)); + engine.seed((uint32_t) (rseed ^ (uint32_t) seed)); while (0 < n) { - *ptr++ = TRI_Int32MersenneTwister(); + *ptr++ = engine(); --n; } } @@ -431,16 +440,21 @@ namespace triagens { // MERSENNE struct UniformIntegerMersenne : public UniformIntegerImpl { + UniformIntegerMersenne () + : engine(std::chrono::system_clock::now().time_since_epoch().count()) { + } + int32_t random (int32_t left, int32_t right) { const int64_t range = (int64_t) right - (int64_t) left + 1LL; - int32_t result = (int32_t) TRI_Int32MersenneTwister(); - assert(range > 0); + uint32_t result = engine(); result = (int32_t) (abs((int64_t) result % range) + (int64_t) left); return result; } + + std::mt19937 engine; }; diff --git a/lib/Basics/init.cpp b/lib/Basics/init.cpp index 96c5e757bb..e9bc8a0786 100644 --- a/lib/Basics/init.cpp +++ b/lib/Basics/init.cpp @@ -30,13 +30,11 @@ #include "BasicsC/files.h" #include "BasicsC/hashes.h" #include "BasicsC/logging.h" -#include "BasicsC/mersenne.h" #include "BasicsC/process-utils.h" #include "BasicsC/random.h" #include "BasicsC/socket-utils.h" #include "ShapedJson/json-shaper.h" - // ----------------------------------------------------------------------------- // --SECTION-- public functions // ----------------------------------------------------------------------------- @@ -53,7 +51,6 @@ void TRI_InitialiseC (int argc, char* argv[]) { TRI_InitialiseMemory(); TRI_InitialiseDebugging(); - TRI_InitialiseMersenneTwister(); TRI_InitialiseError(); TRI_InitialiseFiles(); TRI_InitialiseMimetypes(); diff --git a/lib/BasicsC/logging.c b/lib/BasicsC/logging.c index 7712f90eb6..df40c5110e 100644 --- a/lib/BasicsC/logging.c +++ b/lib/BasicsC/logging.c @@ -438,6 +438,8 @@ static int GenerateMessage (char* buffer, // ............................................................................. n = 0; + + // TODO: can this lock be removed? the prefix is only set at the server startup once TRI_LockSpin(&OutputPrefixLock); @@ -445,7 +447,6 @@ static int GenerateMessage (char* buffer, n = snprintf(buffer, size, "%s ", OutputPrefix); } - TRI_UnlockSpin(&OutputPrefixLock); if (n < 0) { diff --git a/lib/BasicsC/mersenne.c b/lib/BasicsC/mersenne.c deleted file mode 100644 index d0aa09c149..0000000000 --- a/lib/BasicsC/mersenne.c +++ /dev/null @@ -1,217 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// @brief mersenne twister implementation -/// -/// @file -/// -/// DISCLAIMER -/// -/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// -/// Copyright holder is triAGENS GmbH, Cologne, Germany -/// -/// @author Jan Steemann -/// @author see copyright notice of original authors below -/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany -//////////////////////////////////////////////////////////////////////////////// - -#include "mersenne.h" - -#include "BasicsC/threads.h" - -// ----------------------------------------------------------------------------- -// --SECTION-- MERSENNE TWISTER -// ----------------------------------------------------------------------------- - -// ----------------------------------------------------------------------------- -// --SECTION-- static functions -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup Random -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -/* - A C-program for MT19937, with initialization improved 2002/1/26. - Coded by Takuji Nishimura and Makoto Matsumoto. - - Before using, initialize the state by using init_genrand(seed) - or init_by_array(init_key, key_length). - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - Any feedback is very welcome. - http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html - email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) -*/ - -/* Period parameters */ -#define N 624 -#define M 397 -#define MATRIX_A 0x9908b0dfUL /* constant vector a */ -#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ -#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ - -static unsigned long mt[N]; /* the array for the state vector */ -static int mti = N+1; /* mti==N+1 means mt[N] is not initialized */ - -/* initializes mt[N] with a seed */ -static void init_genrand (unsigned long s) { - mt[0]= s & 0xffffffffUL; - for (mti=1; mti> 30)) + mti); - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array mt[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ - mt[mti] &= 0xffffffffUL; - /* for >32 bit machines */ - } -} - -/* generates a random number on [0,0xffffffff]-interval */ -static unsigned long genrand_int32 (void) { - unsigned long y; - static unsigned long mag01[2]={0x0UL, MATRIX_A}; - /* mag01[x] = x * MATRIX_A for x=0,1 */ - - if (mti >= N) { /* generate N words at one time */ - int kk; - - if (mti == N+1) /* if init_genrand() has not been called, */ - init_genrand(5489UL); /* a default initial seed is used */ - - for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; - } - for (;kk> 1) ^ mag01[y & 0x1UL]; - } - y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); - mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; - - mti = 0; - } - - y = mt[mti++]; - - /* Tempering */ - y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); - - return y; -} - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- public functions -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup Random -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @brief initialise the mersenne twister -/// this function needs to be called just once on startup -//////////////////////////////////////////////////////////////////////////////// - -void TRI_InitialiseMersenneTwister () { - unsigned long seed = (unsigned long) time(0); - -#ifdef TRI_HAVE_GETTIMEOFDAY - struct timeval tv; - int result = gettimeofday(&tv, 0); - - seed ^= (unsigned long) tv.tv_sec; - seed ^= (unsigned long) tv.tv_usec; - seed ^= (unsigned long) result; -#endif - - seed ^= (unsigned long) TRI_CurrentProcessId(); - - init_genrand((unsigned long) seed); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief explicitly seed the mersenne twister -//////////////////////////////////////////////////////////////////////////////// - -void TRI_SeedMersenneTwister (uint32_t seed) { - init_genrand((unsigned long) seed); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief generate a 31 bit random number -//////////////////////////////////////////////////////////////////////////////// - -uint32_t TRI_Int31MersenneTwister () { - return (uint32_t) (genrand_int32() >> 1); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @brief generate a 32 bit random number -//////////////////////////////////////////////////////////////////////////////// - -uint32_t TRI_Int32MersenneTwister () { - return (uint32_t) genrand_int32(); -} - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -// Local Variables: -// mode: outline-minor -// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}" -// End: diff --git a/lib/BasicsC/mersenne.h b/lib/BasicsC/mersenne.h deleted file mode 100644 index b25b9605fe..0000000000 --- a/lib/BasicsC/mersenne.h +++ /dev/null @@ -1,92 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -/// @brief mersenne twister implementation -/// -/// @file -/// -/// DISCLAIMER -/// -/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// -/// Copyright holder is triAGENS GmbH, Cologne, Germany -/// -/// @author Jan Steemann -/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany -//////////////////////////////////////////////////////////////////////////////// - -#ifndef TRIAGENS_BASICS_C_MERSENNE_H -#define TRIAGENS_BASICS_C_MERSENNE_H 1 - -#include "BasicsC/common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// ----------------------------------------------------------------------------- -// --SECTION-- MERSENNE TWISTER -// ----------------------------------------------------------------------------- - -// ----------------------------------------------------------------------------- -// --SECTION-- public functions -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup Random -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @brief initialise the mersenne twister -/// this function needs to be called just once on startup -//////////////////////////////////////////////////////////////////////////////// - -void TRI_InitialiseMersenneTwister (void); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief explicitly seed the mersenne twister -//////////////////////////////////////////////////////////////////////////////// - -void TRI_SeedMersenneTwister (uint32_t); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief generate a 31 bit random number -/// -/// generates a random number on [0,0x7fffffff]-interval -//////////////////////////////////////////////////////////////////////////////// - -uint32_t TRI_Int31MersenneTwister (void); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief generate a 32 bit random number -/// -/// generates a random number on [0,0xffffffff]-interval -//////////////////////////////////////////////////////////////////////////////// - -uint32_t TRI_Int32MersenneTwister (void); - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -} -#endif - -#endif - -// Local Variables: -// mode: outline-minor -// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}" -// End: diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 0b293d570a..f34225a635 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -84,7 +84,6 @@ add_library( BasicsC/linked-list.c BasicsC/logging.c BasicsC/memory.c - BasicsC/mersenne.c BasicsC/mimetypes.c BasicsC/prime-numbers.c BasicsC/process-utils.c diff --git a/lib/Makefile.files b/lib/Makefile.files index 29d61c2c7e..490691642e 100644 --- a/lib/Makefile.files +++ b/lib/Makefile.files @@ -54,7 +54,6 @@ lib_libarango_a_SOURCES = \ lib/BasicsC/logging.c \ lib/BasicsC/memory.c \ lib/BasicsC/memory-map-posix.c \ - lib/BasicsC/mersenne.c \ lib/BasicsC/mimetypes.c \ lib/BasicsC/prime-numbers.c \ lib/BasicsC/process-utils.c \