diff --git a/arangod/RestHandler/RestReplicationHandler.cpp b/arangod/RestHandler/RestReplicationHandler.cpp index 2cc484cfc2..0483055d90 100644 --- a/arangod/RestHandler/RestReplicationHandler.cpp +++ b/arangod/RestHandler/RestReplicationHandler.cpp @@ -1911,12 +1911,18 @@ void RestReplicationHandler::handleCommandRestoreCollection() { if (found) { force = StringUtils::boolean(value); } + + uint64_t numberOfShards = 0; + value = _request->value("numberOfShards", found); + if (found) { + numberOfShards = StringUtils::uint64(value); + } string errorMsg; int res; if (ServerState::instance()->isCoordinator()) { res = processRestoreCollectionCoordinator(slice, overwrite, recycleIds, - force, errorMsg); + force, numberOfShards, errorMsg); } else { res = processRestoreCollection(slice, overwrite, recycleIds, force, errorMsg); @@ -2111,10 +2117,9 @@ int RestReplicationHandler::processRestoreCollection( /// @brief restores the structure of a collection, coordinator case //////////////////////////////////////////////////////////////////////////////// -#include int RestReplicationHandler::processRestoreCollectionCoordinator( VPackSlice const& collection, bool dropExisting, bool reuseId, bool force, - std::string& errorMsg) { + uint64_t numberOfShards, std::string& errorMsg) { if (!collection.isObject()) { errorMsg = "collection declaration is invalid"; @@ -2183,12 +2188,20 @@ int RestReplicationHandler::processRestoreCollectionCoordinator( // now re-create the collection // dig out number of shards: - uint64_t numberOfShards = 1; VPackSlice const shards = parameters.get("shards"); if (shards.isObject()) { numberOfShards = static_cast(shards.length()); } - // We take one shard if "shards" was not given + else { + // "shards" not specified + // now check if numberOfShards property was given + if (numberOfShards == 0) { + // We take one shard if no value was given + numberOfShards = 1; + } + } + + TRI_ASSERT(numberOfShards > 0); try { TRI_voc_tick_t newIdTick = ci->uniqid(1); @@ -2275,7 +2288,6 @@ int RestReplicationHandler::processRestoreCollectionCoordinator( VPackCollection::merge(parameters, sliceToMerge, false); VPackSlice const merged = mergedBuilder.slice(); - std::cout << "GOT MERGED VALUE: " << merged.toJson() << "\n"; int res = ci->createCollectionCoordinator(dbName, newId, numberOfShards, merged, errorMsg, 0.0); if (res != TRI_ERROR_NO_ERROR) { diff --git a/arangod/RestHandler/RestReplicationHandler.h b/arangod/RestHandler/RestReplicationHandler.h index f76f46046e..4b345966e3 100644 --- a/arangod/RestHandler/RestReplicationHandler.h +++ b/arangod/RestHandler/RestReplicationHandler.h @@ -201,7 +201,7 @@ class RestReplicationHandler : public RestVocbaseBaseHandler { /// @brief restores the structure of a collection, coordinator case //////////////////////////////////////////////////////////////////////////////// - int processRestoreCollectionCoordinator(VPackSlice const&, bool, bool, bool, + int processRestoreCollectionCoordinator(VPackSlice const&, bool, bool, bool, uint64_t, std::string&); //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/V8Server/v8-collection.cpp b/arangod/V8Server/v8-collection.cpp index 4600539db1..f9ee6d7551 100644 --- a/arangod/V8Server/v8-collection.cpp +++ b/arangod/V8Server/v8-collection.cpp @@ -2607,7 +2607,7 @@ static void JS_PropertiesVocbaseCol( result->Set(TRI_V8_ASCII_STRING("numberOfShards"), v8::Number::New(isolate, (*c).numberOfShards())); auto keyOpts = info.keyOptions(); - if (keyOpts->size() > 0) { + if (keyOpts != nullptr && keyOpts->size() > 0) { TRI_GET_GLOBAL_STRING(KeyOptionsKey); VPackSlice const slice(keyOpts->data()); result->Set(KeyOptionsKey, TRI_VPackToV8(isolate, slice)->ToObject()); diff --git a/arangosh/V8Client/arangorestore.cpp b/arangosh/V8Client/arangorestore.cpp index 1bf5ed3aab..92a6a9570c 100644 --- a/arangosh/V8Client/arangorestore.cpp +++ b/arangosh/V8Client/arangorestore.cpp @@ -45,6 +45,7 @@ #include #include + using namespace std; using namespace triagens::basics; using namespace triagens::httpclient; @@ -148,6 +149,12 @@ static bool ClusterMode = false; static int LastErrorCode = TRI_ERROR_NO_ERROR; +//////////////////////////////////////////////////////////////////////////////// +/// @brief default number of shards +//////////////////////////////////////////////////////////////////////////////// + +static int DefaultNumberOfShards = 1; + //////////////////////////////////////////////////////////////////////////////// /// @brief statistics //////////////////////////////////////////////////////////////////////////////// @@ -158,7 +165,6 @@ static struct { uint64_t _totalRead; } Stats; - //////////////////////////////////////////////////////////////////////////////// /// @brief parses the program options //////////////////////////////////////////////////////////////////////////////// @@ -175,6 +181,7 @@ static void ParseProgramOptions(int argc, char* argv[]) { "import-data", &ImportData, "import data into collection")( "recycle-ids", &RecycleIds, "recycle collection and revision ids from dump")( + "default-number-of-shards", &DefaultNumberOfShards, "default value for numberOfShards if not specified")( "force", &Force, "continue restore even in the face of some server-side errors")( "create-collection", &ImportStructure, "create collection structure")( @@ -419,13 +426,22 @@ static bool GetArangoIsCluster() { /// @brief send the request to re-create a collection //////////////////////////////////////////////////////////////////////////////// -static int SendRestoreCollection(VPackSlice const& slice, string& errorMsg) { - std::string const url = +static int SendRestoreCollection(VPackSlice const& slice, std::string const& name, std::string& errorMsg) { + std::string url = "/_api/replication/restore-collection" "?overwrite=" + string(Overwrite ? "true" : "false") + "&recycleIds=" + string(RecycleIds ? "true" : "false") + "&force=" + string(Force ? "true" : "false"); + + if (ClusterMode && + ! slice.hasKey(std::vector({ "parameters", "shards" })) && + ! slice.hasKey(std::vector({ "parameters", "numberOfShards" }))) { + // no "shards" and no "numberOfShards" attribute present. now assume + // default value from --default-number-of-shards + std::cerr << "# no sharding information specified for collection '" << name << "', using default number of shards " << DefaultNumberOfShards << std::endl; + url += "&numberOfShards=" + std::to_string(DefaultNumberOfShards); + } std::string const body = slice.toJson(); @@ -672,7 +688,8 @@ static int ProcessInputDirectory(std::string& errorMsg) { << "'..." << endl; } } - int res = SendRestoreCollection(collection, errorMsg); + + int res = SendRestoreCollection(collection, cname, errorMsg); if (res != TRI_ERROR_NO_ERROR) { if (Force) {