From c55374a75c1aab7667ad21322014ff289f142f23 Mon Sep 17 00:00:00 2001 From: Jan Date: Thu, 25 Jan 2018 15:57:06 +0100 Subject: [PATCH] fix issue #4272 (#4418) --- CHANGELOG | 2 + arangod/MMFiles/MMFilesWalRecoverState.cpp | 18 ++++- arangod/VocBase/Methods/Databases.cpp | 9 ++- .../recovery/create-database-recovery.js | 81 +++++++++++++++++++ ...th-temp.js => create-with-temp-mmfiles.js} | 0 ...ld.js => create-with-temp-old-mmfiles.js:} | 0 ...atafiles.js => empty-datafiles-mmfiles.js} | 0 7 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 js/server/tests/recovery/create-database-recovery.js rename js/server/tests/recovery/{create-with-temp.js => create-with-temp-mmfiles.js} (100%) rename js/server/tests/recovery/{create-with-temp-old.js => create-with-temp-old-mmfiles.js:} (100%) rename js/server/tests/recovery/{empty-datafiles.js => empty-datafiles-mmfiles.js} (100%) diff --git a/CHANGELOG b/CHANGELOG index 8073ef1e7d..87b20742f5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ v3.3.3 (XXXX-XX-XX) ------------------- +* fix issue #4272: VERSION file keeps disappearing + * fix internal issue #81: quotation marks disappeared when switching table/json editor in the query editor ui diff --git a/arangod/MMFiles/MMFilesWalRecoverState.cpp b/arangod/MMFiles/MMFilesWalRecoverState.cpp index b14ef8f458..1430a63e84 100644 --- a/arangod/MMFiles/MMFilesWalRecoverState.cpp +++ b/arangod/MMFiles/MMFilesWalRecoverState.cpp @@ -33,10 +33,13 @@ #include "Basics/tri-strings.h" #include "MMFiles/MMFilesCollection.h" #include "MMFiles/MMFilesDatafileHelper.h" +#include "MMFiles/MMFilesEngine.h" #include "MMFiles/MMFilesLogfileManager.h" #include "MMFiles/MMFilesPersistentIndexFeature.h" #include "MMFiles/MMFilesWalSlots.h" +#include "Rest/Version.h" #include "RestServer/DatabaseFeature.h" +#include "StorageEngine/EngineSelectorFeature.h" #include "Transaction/Helpers.h" #include "Transaction/Hints.h" #include "Transaction/StandaloneContext.h" @@ -1176,12 +1179,16 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker, std::string nameString = nameSlice.copyString(); + MMFilesEngine* engine = static_cast(EngineSelectorFeature::ENGINE); + std::string const versionFile = engine->versionFilename(databaseId); + std::string const versionFileContent = std::string("{\"version\":") + std::to_string(rest::Version::getNumericServerVersion()) + ",\"tasks\":{}}"; + // remove already existing database with same name vocbase = state->databaseFeature->lookupDatabase(nameString); if (vocbase != nullptr) { TRI_voc_tick_t otherId = vocbase->id(); - + state->releaseDatabase(otherId); // TODO: how to signal a dropDatabase failure here? state->databaseFeature->dropDatabase(nameString, true, false); @@ -1201,6 +1208,15 @@ bool MMFilesWalRecoverState::ReplayMarker(MMFilesMarker const* marker, return state->canContinue(); } + try { + basics::FileUtils::spit(versionFile, versionFileContent); + } catch (...) { + LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "unable to store version file '" << versionFile << "' for database " + << databaseId; + ++state->errorCount; + return state->canContinue(); + } + break; } diff --git a/arangod/VocBase/Methods/Databases.cpp b/arangod/VocBase/Methods/Databases.cpp index aefdbcdf4d..41836930f7 100644 --- a/arangod/VocBase/Methods/Databases.cpp +++ b/arangod/VocBase/Methods/Databases.cpp @@ -25,6 +25,7 @@ #include "Agency/AgencyComm.h" #include "Basics/StringUtils.h" +#include "Basics/VelocyPackHelper.h" #include "Cluster/ClusterComm.h" #include "Cluster/ClusterInfo.h" #include "Cluster/ServerState.h" @@ -153,13 +154,13 @@ arangodb::Result Databases::create(std::string const& dbName, if (options.isNone() || options.isNull()) { options = VPackSlice::emptyObjectSlice(); } else if (!options.isObject()) { - return Result(TRI_ERROR_HTTP_BAD_PARAMETER); + return Result(TRI_ERROR_HTTP_BAD_PARAMETER, "invalid options slice"); } VPackSlice users = inUsers; if (users.isNone() || users.isNull()) { users = VPackSlice::emptyArraySlice(); } else if (!users.isArray()) { - return Result(TRI_ERROR_HTTP_BAD_PARAMETER); + return Result(TRI_ERROR_HTTP_BAD_PARAMETER, "invalid users slice"); } VPackBuilder sanitizedUsers; @@ -299,7 +300,7 @@ arangodb::Result Databases::create(std::string const& dbName, // purposes) TRI_voc_tick_t id = 0; if (options.hasKey("id")) { - id = options.get("id").getUInt(); + id = basics::VelocyPackHelper::stringUInt64(options, "id"); } TRI_vocbase_t* vocbase = nullptr; @@ -321,6 +322,8 @@ arangodb::Result Databases::create(std::string const& dbName, }); } + TRI_ASSERT(V8DealerFeature::DEALER != nullptr); + V8Context* ctx = V8DealerFeature::DEALER->enterContext(vocbase, true); if (ctx == nullptr) { return Result(TRI_ERROR_INTERNAL, "Could not get v8 context"); diff --git a/js/server/tests/recovery/create-database-recovery.js b/js/server/tests/recovery/create-database-recovery.js new file mode 100644 index 0000000000..6c04e8c688 --- /dev/null +++ b/js/server/tests/recovery/create-database-recovery.js @@ -0,0 +1,81 @@ +/* jshint globalstrict:false, strict:false, unused : false */ +/* global assertNotEqual */ +// ////////////////////////////////////////////////////////////////////////////// +// / @brief tests for transactions +// / +// / @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 2013, triAGENS GmbH, Cologne, Germany +// ////////////////////////////////////////////////////////////////////////////// + +var db = require('@arangodb').db; +var internal = require('internal'); +var jsunity = require('jsunity'); + +function runSetup () { + 'use strict'; + internal.debugClearFailAt(); + + db._createDatabase('UnitTestsRecovery'); + db._useDatabase('UnitTestsRecovery'); + require("fs").remove(db._versionFilename()); + internal.debugSegfault('crashing server'); +} + +// ////////////////////////////////////////////////////////////////////////////// +// / @brief test suite +// ////////////////////////////////////////////////////////////////////////////// + +function recoverySuite () { + 'use strict'; + jsunity.jsUnity.attachAssertions(); + + return { + setUp: function () {}, + tearDown: function () {}, + + // ////////////////////////////////////////////////////////////////////////////// + // / @brief test whether we the data are correct after restart + // ////////////////////////////////////////////////////////////////////////////// + + testCreateDatabaseRecovery: function () { + assertNotEqual(-1, db._databases().indexOf('UnitTestsRecovery')); + db._useDatabase('UnitTestsRecovery'); + } + + }; +} + +// ////////////////////////////////////////////////////////////////////////////// +// / @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/recovery/create-with-temp.js b/js/server/tests/recovery/create-with-temp-mmfiles.js similarity index 100% rename from js/server/tests/recovery/create-with-temp.js rename to js/server/tests/recovery/create-with-temp-mmfiles.js diff --git a/js/server/tests/recovery/create-with-temp-old.js b/js/server/tests/recovery/create-with-temp-old-mmfiles.js: similarity index 100% rename from js/server/tests/recovery/create-with-temp-old.js rename to js/server/tests/recovery/create-with-temp-old-mmfiles.js: diff --git a/js/server/tests/recovery/empty-datafiles.js b/js/server/tests/recovery/empty-datafiles-mmfiles.js similarity index 100% rename from js/server/tests/recovery/empty-datafiles.js rename to js/server/tests/recovery/empty-datafiles-mmfiles.js