From 403c9577ea2a447c2660715af6540e66da8fc4c8 Mon Sep 17 00:00:00 2001 From: "A. Jesse Jiryu Davis" Date: Wed, 25 Nov 2020 08:16:58 -0500 Subject: SERVER-52544 Update IDL for listDatabases --- jstests/sharding/features1.js | 3 +- src/mongo/db/commands/list_databases.cpp | 44 ++++++++-------- src/mongo/db/commands/list_databases.idl | 30 ++++++++++- .../s/commands/cluster_list_databases_cmd.cpp | 58 +++++++++++----------- 4 files changed, 80 insertions(+), 55 deletions(-) diff --git a/jstests/sharding/features1.js b/jstests/sharding/features1.js index 25308f47788..f5e215a0346 100644 --- a/jstests/sharding/features1.js +++ b/jstests/sharding/features1.js @@ -118,7 +118,8 @@ assert.commandWorked(s.s0.adminCommand({shardcollection: "test.foo9", key: {a: 1 // --- listDatabases --- var r = db.getMongo().getDBs(); assert.eq(3, r.databases.length, tojson(r)); -assert.eq("number", typeof (r.totalSize), "listDatabases 3 : " + tojson(r)); +assert(r.totalSize > 0, "listDatabases 3 : " + tojson(r)); +assert(r.totalSizeMb >= 0, "listDatabases 3 : " + tojson(r)); // --- flushRouterconfig --- assert.commandWorked(s.s0.adminCommand({flushRouterConfig: 1})); diff --git a/src/mongo/db/commands/list_databases.cpp b/src/mongo/db/commands/list_databases.cpp index 354801cdd7d..fa70ed6ac96 100644 --- a/src/mongo/db/commands/list_databases.cpp +++ b/src/mongo/db/commands/list_databases.cpp @@ -102,7 +102,7 @@ public: BSONObjBuilder& result) final { CommandHelpers::handleMarkKillOnClientDisconnect(opCtx); IDLParserErrorContext ctx("listDatabases"); - auto cmd = ListDatabasesCommand::parse(ctx, cmdObj); + auto cmd = ListDatabases::parse(ctx, cmdObj); auto* as = AuthorizationSession::get(opCtx->getClient()); // {nameOnly: bool} - default false. @@ -146,53 +146,51 @@ public: dbNames = storageEngine->listDatabases(); } - vector dbInfos; + vector items; const bool filterNameOnly = filter && filter->getCategory() == MatchExpression::MatchCategory::kLeaf && filter->path() == kNameField; - intmax_t totalSize = 0; - for (const auto& dbname : dbNames) { - if (authorizedDatabases && !as->isAuthorizedForAnyActionOnAnyResourceInDB(dbname)) { + long long totalSize = 0; + for (const auto& itemName : dbNames) { + if (authorizedDatabases && !as->isAuthorizedForAnyActionOnAnyResourceInDB(itemName)) { // We don't have listDatabases on the cluser or find on this database. continue; } - BSONObjBuilder b; - b.append("name", dbname); + ListDatabasesReplyItem item(itemName); - int64_t size = 0; + long long size = 0; if (!nameOnly) { // Filtering on name only should not require taking locks on filtered-out names. - if (filterNameOnly && !filter->matchesBSON(b.asTempObj())) + if (filterNameOnly && !filter->matchesBSON(item.toBSON())) continue; - AutoGetDb autoDb(opCtx, dbname, MODE_IS); + AutoGetDb autoDb(opCtx, itemName, MODE_IS); Database* const db = autoDb.getDb(); if (!db) continue; - writeConflictRetry(opCtx, "sizeOnDisk", dbname, [&] { - size = storageEngine->sizeOnDiskForDb(opCtx, dbname); + writeConflictRetry(opCtx, "sizeOnDisk", itemName, [&] { + size = storageEngine->sizeOnDiskForDb(opCtx, itemName); }); - b.append("sizeOnDisk", static_cast(size)); - - b.appendBool( - "empty", - CollectionCatalog::get(opCtx)->getAllCollectionUUIDsFromDb(dbname).empty()); + item.setSizeOnDisk(size); + item.setEmpty( + CollectionCatalog::get(opCtx)->getAllCollectionUUIDsFromDb(itemName).empty()); } - BSONObj curDbObj = b.obj(); - - if (!filter || filter->matchesBSON(curDbObj)) { + if (!filter || filter->matchesBSON(item.toBSON())) { totalSize += size; - dbInfos.push_back(curDbObj); + items.push_back(std::move(item)); } } - result.append("databases", dbInfos); + ListDatabasesReply reply(items); if (!nameOnly) { - result.append("totalSize", double(totalSize)); + reply.setTotalSize(totalSize); + reply.setTotalSizeMb(totalSize / (1024 * 1024)); } + + reply.serialize(&result); return true; } } cmdListDatabases; diff --git a/src/mongo/db/commands/list_databases.idl b/src/mongo/db/commands/list_databases.idl index 83e3e8f5351..8342078de30 100644 --- a/src/mongo/db/commands/list_databases.idl +++ b/src/mongo/db/commands/list_databases.idl @@ -32,12 +32,39 @@ global: imports: - "mongo/idl/basic_types.idl" +structs: + ListDatabasesReplyItem: + description: "Individual result" + fields: + name: string + sizeOnDisk: + type: long + optional: true + empty: + type: bool + optional: true + shards: + type: object_owned + optional: true + + ListDatabasesReply: + description: "The listDatabases command's reply." + fields: + databases: array + totalSize: + type: long + optional: true + totalSizeMb: + type: long + optional: true commands: - listDatabasesCommand: + listDatabases: description: "listDatabases Command" command_name: "listDatabases" namespace: ignored + api_version: "1" + strict: true fields: nameOnly: description: "Return just the database name without metadata" @@ -51,3 +78,4 @@ commands: description: "Filter description to limit results" type: object optional: true + reply_type: ListDatabasesReply diff --git a/src/mongo/s/commands/cluster_list_databases_cmd.cpp b/src/mongo/s/commands/cluster_list_databases_cmd.cpp index 5dea5e17120..a95dc29c972 100644 --- a/src/mongo/s/commands/cluster_list_databases_cmd.cpp +++ b/src/mongo/s/commands/cluster_list_databases_cmd.cpp @@ -95,7 +95,7 @@ public: CommandHelpers::handleMarkKillOnClientDisconnect(opCtx); IDLParserErrorContext ctx("listDatabases"); - auto cmd = ListDatabasesCommand::parse(ctx, cmdObj); + auto cmd = ListDatabases::parse(ctx, cmdObj); auto* as = AuthorizationSession::get(opCtx->getClient()); // { nameOnly: bool } - Default false. @@ -178,52 +178,50 @@ public: bb.reset(new BSONObjBuilder()); } - bb->appendNumber(s->getId().toString(), size); + bb->append(s->getId().toString(), size); } } // Now that we have aggregated results for all the shards, convert to a response, // and compute total sizes. long long totalSize = 0; + std::vector items; + for (const auto& sizeEntry : sizes) { + const auto& name = sizeEntry.first; + const long long size = sizeEntry.second; - { - BSONArrayBuilder dbListBuilder(result.subarrayStart("databases")); - for (const auto& sizeEntry : sizes) { - const auto& name = sizeEntry.first; - const long long size = sizeEntry.second; - - // Skip the local database, since all shards have their own independent local - if (name == NamespaceString::kLocalDb) - continue; - - if (authorizedDatabases && !as->isAuthorizedForAnyActionOnAnyResourceInDB(name)) { - // We don't have listDatabases on the cluser or find on this database. - continue; - } + // Skip the local database, since all shards have their own independent local + if (name == NamespaceString::kLocalDb) + continue; - BSONObjBuilder temp; - temp.append("name", name); - if (!nameOnly) { - temp.appendNumber("sizeOnDisk", size); - temp.appendBool("empty", size == 1); - temp.append("shards", dbShardInfo[name]->obj()); + if (authorizedDatabases && !as->isAuthorizedForAnyActionOnAnyResourceInDB(name)) { + // We don't have listDatabases on the cluser or find on this database. + continue; + } - uassert(ErrorCodes::BadValue, - str::stream() << "Found negative 'sizeOnDisk' in: " << name, - size >= 0); + ListDatabasesReplyItem item(name); + if (!nameOnly) { + item.setSizeOnDisk(size); + item.setEmpty(size == 1); + item.setShards(dbShardInfo[name]->obj()); - totalSize += size; - } + uassert(ErrorCodes::BadValue, + str::stream() << "Found negative 'sizeOnDisk' in: " << name, + size >= 0); - dbListBuilder.append(temp.obj()); + totalSize += size; } + + items.push_back(std::move(item)); } + ListDatabasesReply reply(items); if (!nameOnly) { - result.appendNumber("totalSize", totalSize); - result.appendNumber("totalSizeMb", totalSize / (1024 * 1024)); + reply.setTotalSize(totalSize); + reply.setTotalSizeMb(totalSize / (1024 * 1024)); } + reply.serialize(&result); return true; } -- cgit v1.2.1