diff --git a/UnitTests/Makefile.unittests b/UnitTests/Makefile.unittests index 6721c392be..8cdfad3feb 100755 --- a/UnitTests/Makefile.unittests +++ b/UnitTests/Makefile.unittests @@ -247,6 +247,7 @@ unittests-recovery: $(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="resume-recovery-multi-flush" $(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="resume-recovery-simple" $(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="resume-recovery-all" + $(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="resume-recovery-other" $(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="resume-recovery" $(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="foxx-directories" $(MAKE) execute-recovery-test PID=$(PID) RECOVERY_SCRIPT="collection-rename" diff --git a/arangod/Wal/CollectorThread.cpp b/arangod/Wal/CollectorThread.cpp index 050c93bb05..9a64113fea 100644 --- a/arangod/Wal/CollectorThread.cpp +++ b/arangod/Wal/CollectorThread.cpp @@ -495,10 +495,22 @@ int CollectorThread::collectLogfiles (bool& worked) { return res; } - catch (...) { - LOG_DEBUG("collecting logfile %llu failed", (unsigned long long) logfile->id()); - _logfileManager->setCollectionDone(logfile); + catch (triagens::basics::Exception const& ex) { + _logfileManager->forceStatus(logfile, Logfile::StatusType::SEALED); + int res = ex.code(); + + LOG_DEBUG("collecting logfile %llu failed: %s", + (unsigned long long) logfile->id(), + TRI_errno_string(res)); + + return res; + } + catch (...) { + _logfileManager->forceStatus(logfile, Logfile::StatusType::SEALED); + + LOG_DEBUG("collecting logfile %llu failed", (unsigned long long) logfile->id()); + return TRI_ERROR_INTERNAL; } } @@ -814,6 +826,10 @@ int CollectorThread::collect (Logfile* logfile) { TRI_datafile_t* df = logfile->df(); TRI_ASSERT(df != nullptr); + + TRI_IF_FAILURE("CollectorThreadCollectException") { + THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG); + } // We will sequentially scan the logfile for collection: TRI_MMFileAdvise(df->_data, df->_maximalSize, TRI_MADVISE_SEQUENTIAL); diff --git a/js/server/tests/recovery/resume-recovery-other.js b/js/server/tests/recovery/resume-recovery-other.js new file mode 100644 index 0000000000..c523700de8 --- /dev/null +++ b/js/server/tests/recovery/resume-recovery-other.js @@ -0,0 +1,129 @@ +/*jshint globalstrict:false, strict:false, unused : false */ +/*global assertEqual */ + +//////////////////////////////////////////////////////////////////////////////// +/// @brief tests for dump/reload +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2010-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 +//////////////////////////////////////////////////////////////////////////////// + +var db = require("org/arangodb").db; +var internal = require("internal"); +var jsunity = require("jsunity"); + + +function runSetup () { + 'use strict'; + internal.debugClearFailAt(); + + db._drop("UnitTestsRecovery"); + var c = db._create("UnitTestsRecovery"), i, j; + c.ensureSkiplist("value2"); + + for (i = 0; i < 10000; ++i) { + c.save({ _key: "test" + i, value1: "test" + i, value2: i }); + } + + internal.wal.flush(true, true); + + internal.debugSetFailAt("CollectorThreadCollectException"); + + for (j = 0; j < 4; ++j) { + for (i = 0; i < 10000; ++i) { + c.save({ _key: "foo-" + i + "-" + j, value1: "test" + i, value2: "abc" + i }); + } + + internal.wal.flush(true, false); + } + + for (i = 0; i < 10000; ++i) { + c.update("test" + i, { value2: i + 1 }); + } + + c.save({ _key: "crashme" }, true); + + internal.debugSegfault("crashing server"); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test suite +//////////////////////////////////////////////////////////////////////////////// + +function recoverySuite () { + 'use strict'; + jsunity.jsUnity.attachAssertions(); + + return { + setUp: function () { + }, + tearDown: function () { + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test whether we can restore the trx data +//////////////////////////////////////////////////////////////////////////////// + + testResumeRecoveryOther : function () { + var c = db._collection("UnitTestsRecovery"), i, j, doc; + var idx = c.getIndexes()[1]; + + assertEqual(50001, c.count()); + + for (i = 0; i < 10000; ++i) { + doc = c.document("test" + i); + assertEqual("test" + i, doc.value1); + assertEqual(i + 1, doc.value2); + assertEqual(1, c.byExampleSkiplist(idx.id, { value2: i + 1 }).toArray().length); + } + + for (j = 0; j < 4; ++j) { + for (i = 0; i < 10000; ++i) { + doc = c.document("foo-" + i + "-" + j); + assertEqual("test" + i, doc.value1); + assertEqual("abc" + i, doc.value2); + + assertEqual(4, c.byExampleSkiplist(idx.id, { value2: "abc" + i }).toArray().length); + } + } + } + + }; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief executes the test suite +//////////////////////////////////////////////////////////////////////////////// + +function main (argv) { + 'use strict'; + if (argv[1] === "setup") { + runSetup(); + return 0; + } + else { + jsunity.run(recoverySuite); + return jsunity.done().status ? 0 : 1; + } +} + diff --git a/js/server/tests/shell-wal-noncluster-memoryintense.js b/js/server/tests/shell-wal-noncluster-memoryintense.js index 95d100205a..f740009181 100644 --- a/js/server/tests/shell-wal-noncluster-memoryintense.js +++ b/js/server/tests/shell-wal-noncluster-memoryintense.js @@ -89,6 +89,31 @@ function walFailureSuite () { assertEqual(1000, c.count()); }, +//////////////////////////////////////////////////////////////////////////////// +/// @brief test disabled collector +//////////////////////////////////////////////////////////////////////////////// + + testCollectorThreadException : function () { + internal.wal.flush(true, true); + internal.debugSetFailAt("CollectorThreadCollectException"); + + var i = 0; + for (i = 0; i < 1000; ++i) { + c.save({ _key: "test" + i }); + } + + assertEqual(1000, c.count()); + internal.wal.flush(true, false); + + assertEqual(1000, c.count()); + internal.wait(6); + internal.debugClearFailAt(); + + testHelper.waitUnload(c); + + assertEqual(1000, c.count()); + }, + //////////////////////////////////////////////////////////////////////////////// /// @brief test no more available logfiles ////////////////////////////////////////////////////////////////////////////////