diff options
author | Steven Green <steven@greenius.co.uk> | 2017-08-22 13:08:48 -0400 |
---|---|---|
committer | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2017-10-16 11:30:43 -0400 |
commit | b70b91f98c479d8f2abb3eb1c2805cc72962e464 (patch) | |
tree | ef686c5c7dc33139703a82fcef81be6b51f25c51 | |
parent | 235a680d55839e9a6750de13bfe051e9c50d0240 (diff) | |
download | mongo-b70b91f98c479d8f2abb3eb1c2805cc72962e464.tar.gz |
SERVER-30166 Replace string with explicit std::string. Enables compulation when using --use-system-pcre which presusably used to do 'using std::string' in an earlier version of pcre
Closes #1167
Signed-off-by: Mark Benvenuto <mark.benvenuto@mongodb.com>
(cherry picked from commit b7cebf82bc5e5572308cc3a3fb958a825db91498)
-rw-r--r-- | src/mongo/db/dbwebserver.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/matcher/expression_leaf.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/repl/master_slave.cpp | 38 | ||||
-rw-r--r-- | src/mongo/s/catalog/sharding_catalog_create_database_test.cpp | 216 | ||||
-rw-r--r-- | src/mongo/s/config.cpp | 1 | ||||
-rw-r--r-- | src/mongo/s/grid.cpp | 3 | ||||
-rw-r--r-- | src/mongo/shell/bench.cpp | 22 | ||||
-rw-r--r-- | src/mongo/util/net/miniwebserver.cpp | 1 |
8 files changed, 253 insertions, 31 deletions
diff --git a/src/mongo/db/dbwebserver.cpp b/src/mongo/db/dbwebserver.cpp index 3b16457cdcb..9dbc6650031 100644 --- a/src/mongo/db/dbwebserver.cpp +++ b/src/mongo/db/dbwebserver.cpp @@ -62,6 +62,7 @@ namespace mongo { using std::map; +using std::string; using std::stringstream; using std::vector; diff --git a/src/mongo/db/matcher/expression_leaf.cpp b/src/mongo/db/matcher/expression_leaf.cpp index 05edbdd094b..922a8bec263 100644 --- a/src/mongo/db/matcher/expression_leaf.cpp +++ b/src/mongo/db/matcher/expression_leaf.cpp @@ -196,7 +196,7 @@ void ComparisonMatchExpression::debugString(StringBuilder& debug, int level) con } void ComparisonMatchExpression::toBSON(BSONObjBuilder* out) const { - string opString = ""; + std::string opString = ""; switch (matchType()) { case LT: opString = "$lt"; diff --git a/src/mongo/db/repl/master_slave.cpp b/src/mongo/db/repl/master_slave.cpp index 5e69e6d4a64..d51bce0b9ce 100644 --- a/src/mongo/db/repl/master_slave.cpp +++ b/src/mongo/db/repl/master_slave.cpp @@ -77,6 +77,7 @@ using std::endl; using std::max; using std::min; using std::set; +using std::string; using std::stringstream; using std::vector; @@ -159,7 +160,7 @@ BSONObj ReplSource::jsobj() { BSONObjBuilder dbsNextPassBuilder; int n = 0; - for (set<string>::iterator i = addDbNextPass.begin(); i != addDbNextPass.end(); i++) { + for (set<std::string>::iterator i = addDbNextPass.begin(); i != addDbNextPass.end(); i++) { n++; dbsNextPassBuilder.appendBool(*i, 1); } @@ -168,7 +169,8 @@ BSONObj ReplSource::jsobj() { BSONObjBuilder incompleteCloneDbsBuilder; n = 0; - for (set<string>::iterator i = incompleteCloneDbs.begin(); i != incompleteCloneDbs.end(); i++) { + for (set<std::string>::iterator i = incompleteCloneDbs.begin(); i != incompleteCloneDbs.end(); + i++) { n++; incompleteCloneDbsBuilder.appendBool(*i, 1); } @@ -179,7 +181,7 @@ BSONObj ReplSource::jsobj() { } void ReplSource::ensureMe(OperationContext* txn) { - string myname = getHostName(); + std::string myname = getHostName(); // local.me is an identifier for a server for getLastError w:2+ bool exists = Helpers::getSingleton(txn, "local.me", _me); @@ -348,7 +350,7 @@ void ReplSource::forceResyncDead(OperationContext* txn, const char* requester) { } bool replHandshake(DBClientConnection* conn, const OID& myRID) { - string myname = getHostName(); + std::string myname = getHostName(); BSONObjBuilder cmd; cmd.append("handshake", myRID); @@ -400,7 +402,7 @@ void ReplSource::forceResync(OperationContext* txn, const char* requester) { BSONElement e = i.next(); if (e.eoo()) break; - string name = e.embeddedObject().getField("name").valuestr(); + std::string name = e.embeddedObject().getField("name").valuestr(); if (!e.embeddedObject().getBoolField("empty")) { if (name != "local") { if (only.empty() || only == name) { @@ -414,7 +416,7 @@ void ReplSource::forceResync(OperationContext* txn, const char* requester) { save(txn); } -void ReplSource::resyncDrop(OperationContext* txn, const string& db) { +void ReplSource::resyncDrop(OperationContext* txn, const std::string& db) { log() << "resync: dropping database " << db; Client::Context ctx(txn, db); dropDatabase(txn, ctx.db()); @@ -469,13 +471,13 @@ void ReplSource::resync(OperationContext* txn, const std::string& dbName) { static DatabaseIgnorer ___databaseIgnorer; -void DatabaseIgnorer::doIgnoreUntilAfter(const string& db, const OpTime& futureOplogTime) { +void DatabaseIgnorer::doIgnoreUntilAfter(const std::string& db, const OpTime& futureOplogTime) { if (futureOplogTime > _ignores[db]) { _ignores[db] = futureOplogTime; } } -bool DatabaseIgnorer::ignoreAt(const string& db, const OpTime& currentOplogTime) { +bool DatabaseIgnorer::ignoreAt(const std::string& db, const OpTime& currentOplogTime) { if (_ignores[db].isNull()) { return false; } @@ -565,7 +567,7 @@ bool ReplSource::handleDuplicateDbName(OperationContext* txn, // The database is present on the master and no conflicting databases // are present on the master. Drop any local conflicts. - for (set<string>::const_iterator i = duplicates.begin(); i != duplicates.end(); ++i) { + for (set<std::string>::const_iterator i = duplicates.begin(); i != duplicates.end(); ++i) { ___databaseIgnorer.doIgnoreUntilAfter(*i, lastTime); incompleteCloneDbs.erase(*i); addDbNextPass.erase(*i); @@ -735,10 +737,10 @@ void ReplSource::_sync_pullOpLog_applyOperation(OperationContext* txn, } void ReplSource::syncToTailOfRemoteLog() { - string _ns = ns(); + std::string _ns = ns(); BSONObjBuilder b; if (!only.empty()) { - b.appendRegex("ns", string("^") + pcrecpp::RE::QuoteMeta(only)); + b.appendRegex("ns", std::string("^") + pcrecpp::RE::QuoteMeta(only)); } BSONObj last = oplogReader.findOne(_ns.c_str(), Query(b.done()).sort(BSON("$natural" << -1))); if (!last.isEmpty()) { @@ -801,7 +803,7 @@ public: */ int ReplSource::_sync_pullOpLog(OperationContext* txn, int& nApplied) { int okResultCode = 1; - string ns = string("local.oplog.$") + sourceName(); + std::string ns = string("local.oplog.$") + sourceName(); LOG(2) << "repl: sync_pullOpLog " << ns << " syncedTo:" << syncedTo.toStringLong() << '\n'; bool tailing = true; @@ -821,7 +823,7 @@ int ReplSource::_sync_pullOpLog(OperationContext* txn, int& nApplied) { BSONElement e = i.next(); if (e.eoo()) break; - string name = e.embeddedObject().getField("name").valuestr(); + std::string name = e.embeddedObject().getField("name").valuestr(); if (!e.embeddedObject().getBoolField("empty")) { if (name != "local") { if (only.empty() || only == name) { @@ -845,7 +847,7 @@ int ReplSource::_sync_pullOpLog(OperationContext* txn, int& nApplied) { if (!only.empty()) { // note we may here skip a LOT of data table scanning, a lot of work for the master. // maybe append "\\." here? - query.appendRegex("ns", string("^") + pcrecpp::RE::QuoteMeta(only)); + query.appendRegex("ns", std::string("^") + pcrecpp::RE::QuoteMeta(only)); } BSONObj queryObj = query.done(); // e.g. queryObj = { ts: { $gte: syncedTo } } @@ -864,7 +866,7 @@ int ReplSource::_sync_pullOpLog(OperationContext* txn, int& nApplied) { // show any deferred database creates from a previous pass { - set<string>::iterator i = addDbNextPass.begin(); + set<std::string>::iterator i = addDbNextPass.begin(); if (i != addDbNextPass.end()) { BSONObjBuilder b; b.append("ns", *i + '.'); @@ -895,7 +897,7 @@ int ReplSource::_sync_pullOpLog(OperationContext* txn, int& nApplied) { BSONObj op = oplogReader.next(); BSONElement ts = op.getField("ts"); if (ts.type() != Date && ts.type() != Timestamp) { - string err = op.getStringField("$err"); + std::string err = op.getStringField("$err"); if (!err.empty()) { // 13051 is "tailable cursor requested on non capped collection" if (op.getIntField("code") == 13051) { @@ -1061,7 +1063,7 @@ int ReplSource::sync(OperationContext* txn, int& nApplied) { // FIXME Handle cases where this db isn't on default port, or default port is spec'd in // hostName. - if ((string("localhost") == hostName || string("127.0.0.1") == hostName) && + if ((std::string("localhost") == hostName || std::string("127.0.0.1") == hostName) && serverGlobalParams.port == ServerGlobalParams::DefaultDBPort) { log() << "repl: can't sync from self (localhost). sources configuration may be wrong." << endl; @@ -1206,7 +1208,7 @@ static void replMain(OperationContext* txn) { if (s) { stringstream ss; ss << "repl: sleep " << s << " sec before next pass"; - string msg = ss.str(); + std::string msg = ss.str(); if (!serverGlobalParams.quiet) log() << msg << endl; ReplInfo r(msg.c_str()); diff --git a/src/mongo/s/catalog/sharding_catalog_create_database_test.cpp b/src/mongo/s/catalog/sharding_catalog_create_database_test.cpp new file mode 100644 index 00000000000..0aab1fea1c6 --- /dev/null +++ b/src/mongo/s/catalog/sharding_catalog_create_database_test.cpp @@ -0,0 +1,216 @@ +/** + * Copyright (C) 2017 MongoDB Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kSharding + +#include "mongo/platform/basic.h" + +#include <pcrecpp.h> + +#include "mongo/bson/json.h" +#include "mongo/client/remote_command_targeter_mock.h" +#include "mongo/db/commands.h" +#include "mongo/db/query/query_request.h" +#include "mongo/db/repl/read_concern_args.h" +#include "mongo/executor/task_executor.h" +#include "mongo/rpc/get_status_from_command_result.h" +#include "mongo/rpc/metadata/repl_set_metadata.h" +#include "mongo/rpc/metadata/tracking_metadata.h" +#include "mongo/s/catalog/dist_lock_catalog_impl.h" +#include "mongo/s/catalog/sharding_catalog_manager.h" +#include "mongo/s/catalog/type_database.h" +#include "mongo/s/catalog/type_locks.h" +#include "mongo/s/catalog/type_shard.h" +#include "mongo/s/catalog/type_tags.h" +#include "mongo/s/chunk_version.h" +#include "mongo/s/client/shard_registry.h" +#include "mongo/s/config_server_test_fixture.h" +#include "mongo/stdx/future.h" +#include "mongo/util/log.h" +#include "mongo/util/scopeguard.h" +#include "mongo/util/time_support.h" + +namespace mongo { +namespace { + +using executor::RemoteCommandRequest; +using std::vector; + +using CreateDatabaseTest = ConfigServerTestFixture; + +TEST_F(CreateDatabaseTest, createDatabaseSuccess) { + const std::string dbname = "db1"; + + ShardType s0; + s0.setName("shard0000"); + s0.setHost("ShardHost0:27017"); + ASSERT_OK(setupShards(vector<ShardType>{s0})); + + ShardType s1; + s1.setName("shard0001"); + s1.setHost("ShardHost1:27017"); + ASSERT_OK(setupShards(vector<ShardType>{s1})); + + ShardType s2; + s2.setName("shard0002"); + s2.setHost("ShardHost2:27017"); + ASSERT_OK(setupShards(vector<ShardType>{s2})); + + // Prime the shard registry with information about the existing shards + shardRegistry()->reload(operationContext()); + + // Set up all the target mocks return values. + RemoteCommandTargeterMock::get( + uassertStatusOK(shardRegistry()->getShard(operationContext(), s0.getName()))->getTargeter()) + ->setFindHostReturnValue(HostAndPort(s0.getHost())); + RemoteCommandTargeterMock::get( + uassertStatusOK(shardRegistry()->getShard(operationContext(), s1.getName()))->getTargeter()) + ->setFindHostReturnValue(HostAndPort(s1.getHost())); + RemoteCommandTargeterMock::get( + uassertStatusOK(shardRegistry()->getShard(operationContext(), s2.getName()))->getTargeter()) + ->setFindHostReturnValue(HostAndPort(s2.getHost())); + + // Now actually start the createDatabase work. + + auto future = launchAsync([this, dbname] { + ON_BLOCK_EXIT([&] { Client::destroy(); }); + Client::initThreadIfNotAlready("Test"); + auto opCtx = cc().makeOperationContext(); + Status status = + ShardingCatalogManager::get(opCtx.get())->createDatabase(opCtx.get(), dbname); + ASSERT_OK(status); + }); + + // Return size information about first shard + onCommand([&](const RemoteCommandRequest& request) { + ASSERT_EQUALS(s0.getHost(), request.target.toString()); + ASSERT_EQUALS("admin", request.dbname); + std::string cmdName = request.cmdObj.firstElement().fieldName(); + ASSERT_EQUALS("listDatabases", cmdName); + ASSERT_FALSE(request.cmdObj.hasField(repl::ReadConcernArgs::kReadConcernFieldName)); + + ASSERT_BSONOBJ_EQ( + ReadPreferenceSetting(ReadPreference::PrimaryPreferred).toContainingBSON(), + rpc::TrackingMetadata::removeTrackingData(request.metadata)); + + return BSON("ok" << 1 << "totalSize" << 10); + }); + + // Return size information about second shard + onCommand([&](const RemoteCommandRequest& request) { + ASSERT_EQUALS(s1.getHost(), request.target.toString()); + ASSERT_EQUALS("admin", request.dbname); + std::string cmdName = request.cmdObj.firstElement().fieldName(); + ASSERT_EQUALS("listDatabases", cmdName); + ASSERT_FALSE(request.cmdObj.hasField(repl::ReadConcernArgs::kReadConcernFieldName)); + + ASSERT_BSONOBJ_EQ( + ReadPreferenceSetting(ReadPreference::PrimaryPreferred).toContainingBSON(), + rpc::TrackingMetadata::removeTrackingData(request.metadata)); + + return BSON("ok" << 1 << "totalSize" << 1); + }); + + // Return size information about third shard + onCommand([&](const RemoteCommandRequest& request) { + ASSERT_EQUALS(s2.getHost(), request.target.toString()); + ASSERT_EQUALS("admin", request.dbname); + std::string cmdName = request.cmdObj.firstElement().fieldName(); + ASSERT_EQUALS("listDatabases", cmdName); + + ASSERT_BSONOBJ_EQ( + ReadPreferenceSetting(ReadPreference::PrimaryPreferred).toContainingBSON(), + rpc::TrackingMetadata::removeTrackingData(request.metadata)); + + return BSON("ok" << 1 << "totalSize" << 100); + }); + + future.timed_get(kFutureTimeout); +} + +TEST_F(CreateDatabaseTest, createDatabaseDistLockHeld) { + const std::string dbname = "db2"; + + ASSERT_OK(distLockCatalog() + ->grabLock(operationContext(), + dbname, + OID::gen(), + "dummyWho", + "dummyProcessId", + Date_t::now(), + "dummyReason") + .getStatus()); + + Status status = + ShardingCatalogManager::get(operationContext())->createDatabase(operationContext(), dbname); + ASSERT_EQUALS(ErrorCodes::LockBusy, status); +} + +TEST_F(CreateDatabaseTest, createDatabaseDBExists) { + const std::string dbname = "db3"; + + ShardType shard; + shard.setName("shard0"); + shard.setHost("shard0:12"); + + ASSERT_OK(setupShards(vector<ShardType>{shard})); + + setupDatabase(dbname, shard.getName(), false); + + Status status = + ShardingCatalogManager::get(operationContext())->createDatabase(operationContext(), dbname); + ASSERT_OK(status); +} + +TEST_F(CreateDatabaseTest, createDatabaseDBExistsDifferentCase) { + const std::string dbname = "db4"; + const std::string dbnameDiffCase = "Db4"; + + ShardType shard; + shard.setName("shard0"); + shard.setHost("shard0:12"); + + ASSERT_OK(setupShards(vector<ShardType>{shard})); + + setupDatabase(dbnameDiffCase, shard.getName(), false); + + Status status = + ShardingCatalogManager::get(operationContext())->createDatabase(operationContext(), dbname); + ASSERT_EQUALS(ErrorCodes::DatabaseDifferCase, status); +} + +TEST_F(CreateDatabaseTest, createDatabaseNoShards) { + const std::string dbname = "db5"; + + Status status = + ShardingCatalogManager::get(operationContext())->createDatabase(operationContext(), dbname); + ASSERT_EQUALS(ErrorCodes::ShardNotFound, status); +} + +} // namespace +} // namespace mongo diff --git a/src/mongo/s/config.cpp b/src/mongo/s/config.cpp index 3f7586e70bb..6fcc2b23f84 100644 --- a/src/mongo/s/config.cpp +++ b/src/mongo/s/config.cpp @@ -67,6 +67,7 @@ using std::auto_ptr; using std::endl; using std::pair; using std::set; +using std::string; using std::stringstream; using std::vector; diff --git a/src/mongo/s/grid.cpp b/src/mongo/s/grid.cpp index d8228ba4be4..d955f25ecf1 100644 --- a/src/mongo/s/grid.cpp +++ b/src/mongo/s/grid.cpp @@ -64,6 +64,7 @@ using std::ostringstream; using std::set; using std::setfill; using std::setw; +using std::string; using std::stringstream; using std::vector; @@ -205,7 +206,7 @@ void Grid::setAllowLocalHost(bool allow) { bool Grid::addShard(string* name, const ConnectionString& servers, long long maxSize, - string& errMsg) { + std::string& errMsg) { // name can be NULL, so provide a dummy one here to avoid testing it elsewhere string nameInternal; if (!name) { diff --git a/src/mongo/shell/bench.cpp b/src/mongo/shell/bench.cpp index 5e5a71c5d42..d05afa3fd16 100644 --- a/src/mongo/shell/bench.cpp +++ b/src/mongo/shell/bench.cpp @@ -370,7 +370,7 @@ void BenchRunWorker::generateLoadOnConnection(DBClientBase* conn) { invariant(bsonTemplateEvaluator.setId(_id) == BsonTemplateEvaluator::StatusSuccess); if (_config->username != "") { - string errmsg; + std::string errmsg; if (!conn->auth("admin", _config->username, _config->password, errmsg)) { uasserted(15931, "Authenticating to connection for _benchThread failed: " + errmsg); } @@ -384,8 +384,8 @@ void BenchRunWorker::generateLoadOnConnection(DBClientBase* conn) { auto& stats = shouldCollectStats() ? _stats : _statsBlackHole; BSONElement e = i.next(); - string ns = e["ns"].String(); - string op = e["op"].String(); + std::string ns = e["ns"].String(); + std::string op = e["op"].String(); int delay = e["delay"].eoo() ? 0 : e["delay"].Int(); @@ -574,7 +574,7 @@ void BenchRunWorker::generateLoadOnConnection(DBClientBase* conn) { if (!result["err"].eoo() && result["err"].type() == String && (_config->throwGLE || e["throwGLE"].trueValue())) - throw DBException((string) "From benchRun GLE" + + throw DBException((std::string) "From benchRun GLE" + causedBy(result["err"].String()), result["code"].eoo() ? 0 : result["code"].Int()); } @@ -643,7 +643,7 @@ void BenchRunWorker::generateLoadOnConnection(DBClientBase* conn) { if (!result["err"].eoo() && result["err"].type() == String && (_config->throwGLE || e["throwGLE"].trueValue())) - throw DBException((string) "From benchRun GLE" + + throw DBException((std::string) "From benchRun GLE" + causedBy(result["err"].String()), result["code"].eoo() ? 0 : result["code"].Int()); } @@ -666,7 +666,7 @@ void BenchRunWorker::generateLoadOnConnection(DBClientBase* conn) { auto wcElem = e["writeConcern"]; if (wcElem.ok()) { builder.append("writeConcern", wcElem.Obj()); - } + } conn->runCommand( nsToDatabaseSubstring(ns).toString(), builder.done(), result); } else { @@ -695,7 +695,7 @@ void BenchRunWorker::generateLoadOnConnection(DBClientBase* conn) { if (!result["err"].eoo() && result["err"].type() == String && (_config->throwGLE || e["throwGLE"].trueValue())) - throw DBException((string) "From benchRun GLE " + + throw DBException((std::string) "From benchRun GLE " + causedBy(result["err"].String()), result["code"].eoo() ? 0 : result["code"].Int()); } @@ -704,7 +704,7 @@ void BenchRunWorker::generateLoadOnConnection(DBClientBase* conn) { } else if (op == "dropIndex") { conn->dropIndex(ns, e["key"].Obj()); } else if (op == "let") { - string target = e["target"].eoo() ? string() : e["target"].String(); + std::string target = e["target"].eoo() ? std::string() : e["target"].String(); BSONElement value = e["value"].eoo() ? BSONElement() : e["value"]; BSONObjBuilder valBuilder; BSONObjBuilder templateBuilder; @@ -794,7 +794,7 @@ void BenchRunWorker::run() { try { boost::scoped_ptr<DBClientBase> conn(_config->createConnection()); if (!_config->username.empty()) { - string errmsg; + std::string errmsg; if (!conn->auth("admin", _config->username, _config->password, errmsg)) { uasserted(15932, "Authenticating to connection for benchThread failed: " + errmsg); } @@ -826,7 +826,7 @@ void BenchRunner::start() { boost::scoped_ptr<DBClientBase> conn(_config->createConnection()); // Must authenticate to admin db in order to run serverStatus command if (_config->username != "") { - string errmsg; + std::string errmsg; if (!conn->auth("admin", _config->username, _config->password, errmsg)) { uasserted(16704, str::stream() @@ -862,7 +862,7 @@ void BenchRunner::stop() { { boost::scoped_ptr<DBClientBase> conn(_config->createConnection()); if (_config->username != "") { - string errmsg; + std::string errmsg; // this can only fail if admin access was revoked since start of run if (!conn->auth("admin", _config->username, _config->password, errmsg)) { uasserted(16705, diff --git a/src/mongo/util/net/miniwebserver.cpp b/src/mongo/util/net/miniwebserver.cpp index e0c05c7988a..bdfdcefc01d 100644 --- a/src/mongo/util/net/miniwebserver.cpp +++ b/src/mongo/util/net/miniwebserver.cpp @@ -43,6 +43,7 @@ namespace mongo { using boost::shared_ptr; using std::endl; +using std::string; using std::stringstream; using std::vector; |