diff options
31 files changed, 137 insertions, 269 deletions
diff --git a/jstests/aggregation/bugs/server12015.js b/jstests/aggregation/bugs/server12015.js index 150ff30e708..1b59a59545c 100644 --- a/jstests/aggregation/bugs/server12015.js +++ b/jstests/aggregation/bugs/server12015.js @@ -63,19 +63,23 @@ load("jstests/aggregation/extras/utils.js"); // For orderedArrayEq. assertResultsMatch([{$sort: {a: -1, b: -1}}, {$project: {_id: 1, a: 1, b: 1}}]); assertResultsMatch([{$sort: {a: 1, b: 1}}, {$project: {_id: 1, a: 1, b: 1}}]); assertResultsMatch( - [{$sort: {a: 1, b: 1}}, {$group: {_id: "$_id", arr: {$push: "$a"}, sum: {$sum: "$b"}}}]); + [{$sort: {a: 1, b: 1}}, {$group: {_id: "$_id", arr: {$push: "$a"}, sum: {$sum: "$b"}}}], + ignoreSortOrder); // Non-blocking $sort, covered $project. assertResultsMatch([{$sort: {a: -1, b: -1}}, {$project: {_id: 0, a: 1, b: 1}}]); assertResultsMatch([{$sort: {a: 1, b: 1}}, {$project: {_id: 0, a: 1, b: 1}}]); - assertResultsMatch([{$sort: {a: 1, b: 1}}, {$group: {_id: "$b", arr: {$push: "$a"}}}]); + assertResultsMatch([{$sort: {a: 1, b: 1}}, {$group: {_id: "$b", arr: {$push: "$a"}}}], + ignoreSortOrder); // Blocking $sort, uncovered $project. assertResultsMatch([{$sort: {b: 1, a: -1}}, {$project: {_id: 1, a: 1, b: 1}}]); assertResultsMatch( - [{$sort: {b: 1, a: -1}}, {$group: {_id: "$_id", arr: {$push: "$a"}, sum: {$sum: "$b"}}}]); + [{$sort: {b: 1, a: -1}}, {$group: {_id: "$_id", arr: {$push: "$a"}, sum: {$sum: "$b"}}}], + ignoreSortOrder); // Blocking $sort, covered $project. assertResultsMatch([{$sort: {b: 1, a: -1}}, {$project: {_id: 0, a: 1, b: 1}}]); - assertResultsMatch([{$sort: {b: 1, a: -1}}, {$group: {_id: "$b", arr: {$push: "$a"}}}]); + assertResultsMatch([{$sort: {b: 1, a: -1}}, {$group: {_id: "$b", arr: {$push: "$a"}}}], + ignoreSortOrder); }()); diff --git a/jstests/aggregation/sources/facet/inner_graphlookup.js b/jstests/aggregation/sources/facet/inner_graphlookup.js index 870bb975a8a..340853f7721 100644 --- a/jstests/aggregation/sources/facet/inner_graphlookup.js +++ b/jstests/aggregation/sources/facet/inner_graphlookup.js @@ -30,14 +30,21 @@ as: "connected" } }; - const normalResults = graphColl.aggregate([graphLookupStage]).toArray(); - const facetedResults = graphColl.aggregate([{$facet: {nested: [graphLookupStage]}}]).toArray(); + + const projectStage = {$project: {_id: 1, edges: 1, connected_length: {$size: "$connected"}}}; + + const normalResults = graphColl.aggregate([graphLookupStage, projectStage]).toArray(); + const facetedResults = + graphColl.aggregate([{$facet: {nested: [graphLookupStage, projectStage]}}]).toArray(); assert.eq(facetedResults, [{nested: normalResults}]); + const sortStage = {$sort: {_id: 1, "connected._id": 1}}; + const normalResultsUnwound = - graphColl.aggregate([graphLookupStage, {$unwind: "$connected"}]).toArray(); + graphColl.aggregate([graphLookupStage, {$unwind: "$connected"}, sortStage]).toArray(); const facetedResultsUnwound = - graphColl.aggregate([{$facet: {nested: [graphLookupStage, {$unwind: "$connected"}]}}]) + graphColl + .aggregate([{$facet: {nested: [graphLookupStage, {$unwind: "$connected"}, sortStage]}}]) .toArray(); assert.eq(facetedResultsUnwound, [{nested: normalResultsUnwound}]); }()); diff --git a/jstests/core/index_stats.js b/jstests/core/index_stats.js index 6bed899e16e..1834e7bb05f 100644 --- a/jstests/core/index_stats.js +++ b/jstests/core/index_stats.js @@ -111,26 +111,21 @@ // Confirm $and operation ticks indexes for winning plan, but not rejected plans. // - // Run explain to determine which indexes would be used for this query. Note that index - // access counters are not incremented for explain execution. - var explain = col.find({a: 2, b: 2}).explain("queryPlanner"); - var indexNameList = getIndexNamesForWinningPlan(explain); - assert.gte(indexNameList.length, 1); - - for (var i = 0; i < indexNameList.length; ++i) { - // Increment the expected $indexStats count for each index used. - var name = indexNameList[i]; - if (name === "a_1") { - countA++; - } else { - assert(name === "b_1_c_1"); - countB++; - } + // We cannot use explain() to determine which indexes would be used for this query, since + // 1) explain() will not bump the access counters + // 2) explain() always runs the multi planner, and the multi planner may choose a different + // index each run. We therefore run the query, and check that only one of the indexes has its + // counter bumped (assuming we never choose an index intersection plan). + const results = col.find({a: 2, b: 2}).itcount(); + if (countA + 1 == getUsageCount("a_1")) { + // Plan using index A was chosen. Index B should not have been used (assuming no index + // intersection plans are used). + countA++; + } else { + // Plan using index B was chosen. Index A should not have been used (assuming no index + // intersection plans are used). + assert.eq(++countB, getUsageCount("b_1_c_1")); } - - // Run the query again without explain to increment index access counters. - col.findOne({a: 2, b: 2}); - // Check all indexes for proper count. assert.eq(countA, getUsageCount("a_1")); assert.eq(countB, getUsageCount("b_1_c_1")); assert.eq(0, getUsageCount("_id_")); diff --git a/src/mongo/bson/simple_bsonobj_comparator.h b/src/mongo/bson/simple_bsonobj_comparator.h index 90183beadf5..24ef6ecfbdf 100644 --- a/src/mongo/bson/simple_bsonobj_comparator.h +++ b/src/mongo/bson/simple_bsonobj_comparator.h @@ -113,13 +113,6 @@ using SimpleBSONObjUnorderedSet = stdx::unordered_set<BSONObj, SimpleBSONObjComparator::Hasher, SimpleBSONObjComparator::EqualTo>; /** - * An unordered_multiset of BSONObjs that performs equality checks using simple binary semantics. - */ -using SimpleBSONObjUnorderedMultiset = stdx::unordered_multiset<BSONObj, - SimpleBSONObjComparator::Hasher, - SimpleBSONObjComparator::EqualTo>; - -/** * A map keyed on BSONObj that performs comparisons with simple binary semantics. */ template <typename T> @@ -138,13 +131,4 @@ template <typename T> using SimpleBSONObjUnorderedMap = stdx:: unordered_map<BSONObj, T, SimpleBSONObjComparator::Hasher, SimpleBSONObjComparator::EqualTo>; -/** - * An unordered_multimap keyed on BSONObj that performs equality checks using simple binary - * semantics. - */ -template <typename T> -using SimpleBSONObjUnorderedMultiMap = stdx::unordered_multimap<BSONObj, - T, - SimpleBSONObjComparator::Hasher, - SimpleBSONObjComparator::EqualTo>; } // namespace mongo diff --git a/src/mongo/bson/simple_bsonobj_comparator_test.cpp b/src/mongo/bson/simple_bsonobj_comparator_test.cpp index ca94968a483..a6d9ab85631 100644 --- a/src/mongo/bson/simple_bsonobj_comparator_test.cpp +++ b/src/mongo/bson/simple_bsonobj_comparator_test.cpp @@ -86,14 +86,6 @@ TEST(SimpleBSONObjContainerTest, UnorderedSetIsDefaultConstructible) { ASSERT_EQ(uset.size(), 2UL); } -TEST(SimpleBSONObjContainerTest, UnorderedMultiSetIsDefaultConstructible) { - SimpleBSONObjUnorderedMultiset umultiset; - umultiset.insert(BSON("x" << 1)); - umultiset.insert(BSON("x" << 1)); - umultiset.insert(BSON("y" << 1)); - ASSERT_EQ(umultiset.size(), 3UL); -} - /** * Asserts that the key-value pair 'pair' can be successfully inserted into 'map'. */ @@ -141,12 +133,5 @@ TEST(SimpleBSONObjContainerTest, UnorderedMapIsDefaultConstructible) { ASSERT_EQ(umap.size(), 2UL); } -TEST(SimpleBSONObjContainerTest, UnorderedMultiMapIsDefaultConstructible) { - SimpleBSONObjUnorderedMultiMap<std::string> umultimap; - umultimap.insert(std::make_pair(BSON("_id" << 0), "anica")); - umultimap.insert(std::make_pair(BSON("_id" << 0), "raj")); - umultimap.insert(std::make_pair(BSON("_id" << 1), "ian")); - ASSERT_EQ(umultimap.size(), 3UL); -} } // namespace } // namespace mongo diff --git a/src/mongo/db/auth/authorization_manager.cpp b/src/mongo/db/auth/authorization_manager.cpp index af7d9d18f61..7795040d86e 100644 --- a/src/mongo/db/auth/authorization_manager.cpp +++ b/src/mongo/db/auth/authorization_manager.cpp @@ -55,7 +55,6 @@ #include "mongo/db/auth/user.h" #include "mongo/db/auth/user_document_parser.h" #include "mongo/db/auth/user_name.h" -#include "mongo/db/auth/user_name_hash.h" #include "mongo/db/global_settings.h" #include "mongo/db/jsobj.h" #include "mongo/platform/compiler.h" diff --git a/src/mongo/db/auth/authorization_manager.h b/src/mongo/db/auth/authorization_manager.h index 1e1c29dc1b7..e186dbde970 100644 --- a/src/mongo/db/auth/authorization_manager.h +++ b/src/mongo/db/auth/authorization_manager.h @@ -47,7 +47,6 @@ #include "mongo/db/auth/role_graph.h" #include "mongo/db/auth/user.h" #include "mongo/db/auth/user_name.h" -#include "mongo/db/auth/user_name_hash.h" #include "mongo/db/jsobj.h" #include "mongo/db/namespace_string.h" #include "mongo/db/server_options.h" diff --git a/src/mongo/db/auth/authorization_manager_impl.cpp b/src/mongo/db/auth/authorization_manager_impl.cpp index 88368a9fd17..43124722d28 100644 --- a/src/mongo/db/auth/authorization_manager_impl.cpp +++ b/src/mongo/db/auth/authorization_manager_impl.cpp @@ -58,7 +58,7 @@ #include "mongo/db/auth/user_document_parser.h" #include "mongo/db/auth/user_management_commands_parser.h" #include "mongo/db/auth/user_name.h" -#include "mongo/db/auth/user_name_hash.h" + #include "mongo/db/global_settings.h" #include "mongo/db/jsobj.h" #include "mongo/db/mongod_options.h" diff --git a/src/mongo/db/auth/authorization_manager_impl.h b/src/mongo/db/auth/authorization_manager_impl.h index 7d8794a5b35..a734a1301b8 100644 --- a/src/mongo/db/auth/authorization_manager_impl.h +++ b/src/mongo/db/auth/authorization_manager_impl.h @@ -46,7 +46,6 @@ #include "mongo/db/auth/role_graph.h" #include "mongo/db/auth/user.h" #include "mongo/db/auth/user_name.h" -#include "mongo/db/auth/user_name_hash.h" #include "mongo/db/jsobj.h" #include "mongo/db/namespace_string.h" #include "mongo/db/server_options.h" diff --git a/src/mongo/db/auth/resource_pattern.h b/src/mongo/db/auth/resource_pattern.h index 584db465274..9fd1a8111dc 100644 --- a/src/mongo/db/auth/resource_pattern.h +++ b/src/mongo/db/auth/resource_pattern.h @@ -35,7 +35,6 @@ #include "mongo/base/string_data.h" #include "mongo/db/namespace_string.h" -#include "mongo/platform/hash_namespace.h" namespace mongo { @@ -174,11 +173,6 @@ public: std::string toString() const; - inline size_t hash() const { - // TODO: Choose a better hash function. - return MONGO_HASH_NAMESPACE::hash<std::string>()(_ns.ns()) ^ _matchType; - } - bool operator==(const ResourcePattern& other) const { if (_matchType != other._matchType) return false; @@ -187,6 +181,11 @@ public: return true; } + template <typename H> + friend H AbslHashValue(H h, const ResourcePattern& rp) { + return H::combine(std::move(h), rp._ns, rp._matchType); + } + private: enum MatchType { matchNever = 0, /// Matches no resource. @@ -208,12 +207,3 @@ private: std::ostream& operator<<(std::ostream& os, const ResourcePattern& pattern); } // namespace mongo - -MONGO_HASH_NAMESPACE_START -template <> -struct hash<mongo::ResourcePattern> { - size_t operator()(const mongo::ResourcePattern& resource) const { - return resource.hash(); - } -}; -MONGO_HASH_NAMESPACE_END diff --git a/src/mongo/db/auth/role_name.h b/src/mongo/db/auth/role_name.h index c9e77c03c58..24bdd4ffb18 100644 --- a/src/mongo/db/auth/role_name.h +++ b/src/mongo/db/auth/role_name.h @@ -40,7 +40,6 @@ #include "mongo/base/string_data.h" #include "mongo/bson/bsonelement.h" #include "mongo/bson/bsonobjbuilder.h" -#include "mongo/platform/hash_namespace.h" #include "mongo/util/assert_util.h" namespace mongo { @@ -94,6 +93,11 @@ public: return getFullName(); } + template <typename H> + friend H AbslHashValue(H h, const RoleName& rname) { + return H::combine(std::move(h), rname.getFullName()); + } + private: std::string _fullName; // The full name, stored as a string. "role@db". size_t _splitPoint; // The index of the "@" separating the role and db name parts. @@ -175,16 +179,6 @@ private: } // namespace mongo -// Define hash function for RoleNames so they can be keys in stdx::unordered_map -MONGO_HASH_NAMESPACE_START -template <> -struct hash<mongo::RoleName> { - size_t operator()(const mongo::RoleName& rname) const { - return hash<std::string>()(rname.getFullName()); - } -}; -MONGO_HASH_NAMESPACE_END - namespace mongo { template <typename ContainerIterator> diff --git a/src/mongo/db/auth/user_name.h b/src/mongo/db/auth/user_name.h index 54c653a98ee..6a3ebdfa885 100644 --- a/src/mongo/db/auth/user_name.h +++ b/src/mongo/db/auth/user_name.h @@ -113,6 +113,11 @@ public: return getUser() < rhs.getUser() || (getUser() == rhs.getUser() && getDB() < rhs.getDB()); } + template <typename H> + friend H AbslHashValue(H h, const UserName& userName) { + return H::combine(std::move(h), userName.getFullName()); + } + private: void _serializeToSubObj(BSONObjBuilder* sub) const; diff --git a/src/mongo/db/concurrency/lock_manager_defs.h b/src/mongo/db/concurrency/lock_manager_defs.h index 3e161da066a..5722d3eff69 100644 --- a/src/mongo/db/concurrency/lock_manager_defs.h +++ b/src/mongo/db/concurrency/lock_manager_defs.h @@ -36,7 +36,6 @@ #include "mongo/base/static_assert.h" #include "mongo/base/string_data.h" #include "mongo/config.h" -#include "mongo/platform/hash_namespace.h" namespace mongo { @@ -220,6 +219,11 @@ public: std::string toString() const; + template <typename H> + friend H AbslHashValue(H h, const ResourceId& resource) { + return H::combine(std::move(h), resource._fullHash); + } + private: /** * The top 'resourceTypeBits' bits of '_fullHash' represent the resource type, @@ -459,13 +463,3 @@ struct LockRequest { const char* lockRequestStatusName(LockRequest::Status status); } // namespace mongo - - -MONGO_HASH_NAMESPACE_START -template <> -struct hash<mongo::ResourceId> { - size_t operator()(const mongo::ResourceId& resource) const { - return resource; - } -}; -MONGO_HASH_NAMESPACE_END diff --git a/src/mongo/db/cursor_manager.cpp b/src/mongo/db/cursor_manager.cpp index 05a5aa0b329..395555af2b7 100644 --- a/src/mongo/db/cursor_manager.cpp +++ b/src/mongo/db/cursor_manager.cpp @@ -444,7 +444,7 @@ void CursorManager::invalidateAll(OperationContext* opCtx, // If there's an operation actively using the cursor, then that operation is now // responsible for cleaning it up. Otherwise we can immediately dispose of it. if (cursor->_operationUsingCursor) { - it = partition.erase(it); + partition.erase(it++); continue; } @@ -454,7 +454,7 @@ void CursorManager::invalidateAll(OperationContext* opCtx, ++it; } else { toDisposeWithoutMutex.emplace_back(cursor); - it = partition.erase(it); + partition.erase(it++); } } } @@ -483,7 +483,7 @@ std::size_t CursorManager::timeoutCursors(OperationContext* opCtx, Date_t now) { auto* cursor = it->second; if (cursorShouldTimeout_inlock(cursor, now)) { toDisposeWithoutMutex.emplace_back(cursor); - it = lockedPartition->erase(it); + lockedPartition->erase(it++); } else { ++it; } diff --git a/src/mongo/db/namespace_string.h b/src/mongo/db/namespace_string.h index 651d769544b..3db2576fcc4 100644 --- a/src/mongo/db/namespace_string.h +++ b/src/mongo/db/namespace_string.h @@ -38,7 +38,6 @@ #include "mongo/base/status_with.h" #include "mongo/base/string_data.h" #include "mongo/db/repl/optime.h" -#include "mongo/platform/hash_namespace.h" #include "mongo/util/assert_util.h" #include "mongo/util/uuid.h" @@ -211,12 +210,6 @@ public: return _ns.empty(); } - struct Hasher { - size_t operator()(const NamespaceString& nss) const { - return std::hash<std::string>()(nss._ns); - } - }; - // // The following methods assume isValid() is true for this NamespaceString. // @@ -452,6 +445,11 @@ public: return a.ns() >= b.ns(); } + template <typename H> + friend H AbslHashValue(H h, const NamespaceString& nss) { + return H::combine(std::move(h), nss._ns); + } + private: std::string _ns; size_t _dotIndex; @@ -615,13 +613,3 @@ inline bool NamespaceString::validCollectionName(StringData coll) { } } // namespace mongo - -MONGO_HASH_NAMESPACE_START -template <> -struct hash<mongo::NamespaceString> { - size_t operator()(const mongo::NamespaceString& nss) const { - mongo::NamespaceString::Hasher hasher; - return hasher(nss); - } -}; -MONGO_HASH_NAMESPACE_END diff --git a/src/mongo/db/pipeline/document_source_graph_lookup.cpp b/src/mongo/db/pipeline/document_source_graph_lookup.cpp index 1b6583bb655..926e056f9a2 100644 --- a/src/mongo/db/pipeline/document_source_graph_lookup.cpp +++ b/src/mongo/db/pipeline/document_source_graph_lookup.cpp @@ -289,7 +289,7 @@ boost::optional<BSONObj> DocumentSourceGraphLookUp::makeMatchStageFromFrontier( if (auto entry = _cache[*it]) { cached->insert(entry->begin(), entry->end()); size_t valueSize = it->getApproximateSize(); - it = _frontier.erase(it); + _frontier.erase(it++); // If the cached value increased in size while in the cache, we don't want to underflow // '_frontierUsageBytes'. diff --git a/src/mongo/db/query/plan_enumerator.cpp b/src/mongo/db/query/plan_enumerator.cpp index c8a12ee6335..c365b46ab44 100644 --- a/src/mongo/db/query/plan_enumerator.cpp +++ b/src/mongo/db/query/plan_enumerator.cpp @@ -411,7 +411,7 @@ bool PlanEnumerator::prepMemo(MatchExpression* node, PrepMemoContext context) { // either of the predicates on 'c', since this would change the predicate's meaning // from a==1 to "b.a"==1. if (it->second.traversedThroughElemMatchObj) { - it = childContextCopy.outsidePreds.erase(it); + childContextCopy.outsidePreds.erase(it++); } else { it->second.route.push_back(i); ++it; @@ -1331,7 +1331,7 @@ void PlanEnumerator::getMultikeyCompoundablePreds(const vector<MatchExpression*> RelevantTag* usedRt = static_cast<RelevantTag*>(assignedPred->getTag()); set<string> usedPrefixes; usedPrefixes.insert(getPathPrefix(usedRt->path)); - used[NULL] = usedPrefixes; + used[nullptr] = usedPrefixes; // If 'assigned' is a predicate inside an $elemMatch, we have to // add the prefix not only to the top-level context, but also to the @@ -1356,8 +1356,8 @@ void PlanEnumerator::getMultikeyCompoundablePreds(const vector<MatchExpression*> if (used.end() == used.find(rt->elemMatchExpr)) { // This is a new $elemMatch that we haven't seen before. - invariant(used.end() != used.find(NULL)); - set<string>& topLevelUsed = used.find(NULL)->second; + invariant(used.end() != used.find(nullptr)); + set<string>& topLevelUsed = used.find(nullptr)->second; // If the top-level path prefix of the $elemMatch hasn't been // used yet, couldCompound[i] is safe to compound. diff --git a/src/mongo/db/transaction_coordinator_catalog.cpp b/src/mongo/db/transaction_coordinator_catalog.cpp index 24a23035597..96520986a2e 100644 --- a/src/mongo/db/transaction_coordinator_catalog.cpp +++ b/src/mongo/db/transaction_coordinator_catalog.cpp @@ -94,10 +94,10 @@ std::shared_ptr<TransactionCoordinator> TransactionCoordinatorCatalog::get(Opera std::shared_ptr<TransactionCoordinator> coordinatorToReturn; - const auto& coordinatorsForSessionIter = _coordinatorsBySession.find(lsid); + auto coordinatorsForSessionIter = _coordinatorsBySession.find(lsid); if (coordinatorsForSessionIter != _coordinatorsBySession.end()) { const auto& coordinatorsForSession = coordinatorsForSessionIter->second; - const auto& coordinatorForTxnIter = coordinatorsForSession.find(txnNumber); + auto coordinatorForTxnIter = coordinatorsForSession.find(txnNumber); if (coordinatorForTxnIter != coordinatorsForSession.end()) { coordinatorToReturn = coordinatorForTxnIter->second; } @@ -107,10 +107,10 @@ std::shared_ptr<TransactionCoordinator> TransactionCoordinatorCatalog::get(Opera // If the failpoint is on and we couldn't find the coordinator in the main catalog, fall // back to the "defunct" catalog, which stores coordinators that have completed and would // normally be forgotten. - const auto& coordinatorsForSessionIter = _coordinatorsBySessionDefunct.find(lsid); - if (coordinatorsForSessionIter != _coordinatorsBySession.end()) { + auto coordinatorsForSessionIter = _coordinatorsBySessionDefunct.find(lsid); + if (coordinatorsForSessionIter != _coordinatorsBySessionDefunct.end()) { const auto& coordinatorsForSession = coordinatorsForSessionIter->second; - const auto& coordinatorForTxnIter = coordinatorsForSession.find(txnNumber); + auto coordinatorForTxnIter = coordinatorsForSession.find(txnNumber); if (coordinatorForTxnIter != coordinatorsForSession.end()) { coordinatorToReturn = coordinatorForTxnIter->second; } diff --git a/src/mongo/dbtests/commandtests.cpp b/src/mongo/dbtests/commandtests.cpp index f7212764304..08c24bc60d2 100644 --- a/src/mongo/dbtests/commandtests.cpp +++ b/src/mongo/dbtests/commandtests.cpp @@ -349,9 +349,9 @@ public: bool ok = db.runCommand(nsDb(), BSON("rolesInfo" << 1), result); ASSERT(ok); - stdx::unordered_set<std::string> observedFields; + StringSet observedFields; for (const auto& field : result) { - ASSERT(observedFields.find(field) == observedFields.end()); + ASSERT(observedFields.find(field.fieldNameStringData()) == observedFields.end()); observedFields.insert(field); } } diff --git a/src/mongo/executor/task_executor.h b/src/mongo/executor/task_executor.h index e8cff8ee0f6..1e3051e17b4 100644 --- a/src/mongo/executor/task_executor.h +++ b/src/mongo/executor/task_executor.h @@ -40,7 +40,6 @@ #include "mongo/base/string_data.h" #include "mongo/executor/remote_command_request.h" #include "mongo/executor/remote_command_response.h" -#include "mongo/platform/hash_namespace.h" #include "mongo/stdx/condition_variable.h" #include "mongo/stdx/functional.h" #include "mongo/transport/baton.h" @@ -335,14 +334,15 @@ public: return isValid(); } - std::size_t hash() const { - return std::hash<decltype(_callback)>()(_callback); - } - bool isCanceled() const { return getCallback()->isCanceled(); } + template <typename H> + friend H AbslHashValue(H h, const CallbackHandle& handle) { + return H::combine(std::move(h), handle._callback); + } + private: void setCallback(std::shared_ptr<CallbackState> callback) { _callback = callback; @@ -445,13 +445,3 @@ struct TaskExecutor::RemoteCommandCallbackArgs { } // namespace executor } // namespace mongo - -// Provide a specialization for hash<CallbackHandle> so it can easily be stored in unordered_set. -MONGO_HASH_NAMESPACE_START -template <> -struct hash<::mongo::executor::TaskExecutor::CallbackHandle> { - size_t operator()(const ::mongo::executor::TaskExecutor::CallbackHandle& x) const { - return x.hash(); - } -}; -MONGO_HASH_NAMESPACE_END diff --git a/src/mongo/platform/hash_namespace.h b/src/mongo/platform/hash_namespace.h deleted file mode 100644 index d38ceadc1df..00000000000 --- a/src/mongo/platform/hash_namespace.h +++ /dev/null @@ -1,50 +0,0 @@ - -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * 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 - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * <http://www.mongodb.com/licensing/server-side-public-license>. - * - * 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 Server Side 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. - */ - -#pragma once - -#include <functional> -#if defined(_WIN32) -#include <boost/functional/hash.hpp> -#endif - -#if defined(_WIN32) -#define MONGO_HASH_NAMESPACE_START namespace boost { -#else -#define MONGO_HASH_NAMESPACE_START namespace std { -#endif - -#define MONGO_HASH_NAMESPACE_END } - -#if defined(_WIN32) -#define MONGO_HASH_NAMESPACE boost -#else -#define MONGO_HASH_NAMESPACE std -#endif diff --git a/src/mongo/platform/process_id.h b/src/mongo/platform/process_id.h index 2e5d34f5146..f0cc3b62e73 100644 --- a/src/mongo/platform/process_id.h +++ b/src/mongo/platform/process_id.h @@ -38,8 +38,6 @@ #include <unistd.h> #endif -#include "mongo/platform/hash_namespace.h" - namespace mongo { #ifdef _WIN32 @@ -126,6 +124,11 @@ public: return _npid >= other._npid; } + template <typename H> + friend H AbslHashValue(H h, const ProcessId pid) { + return H::combine(std::move(h), pid.asUInt32()); + } + private: explicit ProcessId(NativeProcessId npid) : _npid(npid) {} @@ -135,12 +138,3 @@ private: std::ostream& operator<<(std::ostream& os, ProcessId pid); } // namespace mongo - -MONGO_HASH_NAMESPACE_START -template <> -struct hash<::mongo::ProcessId> { - size_t operator()(const ::mongo::ProcessId pid) const { - return hash<::std::uint32_t>()(pid.asUInt32()); - } -}; -MONGO_HASH_NAMESPACE_END diff --git a/src/mongo/s/query/cluster_cursor_manager.cpp b/src/mongo/s/query/cluster_cursor_manager.cpp index 6d4ad57a806..7ba8c456276 100644 --- a/src/mongo/s/query/cluster_cursor_manager.cpp +++ b/src/mongo/s/query/cluster_cursor_manager.cpp @@ -538,7 +538,7 @@ std::size_t ClusterCursorManager::killCursorsSatisfying( cursorsToDestroy.push_back(entry.releaseCursor(nullptr)); // Destroy the entry and set the iterator to the next element. - cursorIdEntryIt = entryMap.erase(cursorIdEntryIt); + entryMap.erase(cursorIdEntryIt++); } if (entryMap.empty()) { @@ -735,7 +735,7 @@ auto ClusterCursorManager::eraseContainer(NssToCursorContainerMap::iterator it) // with this namespace. size_t numDeleted = _cursorIdPrefixToNamespaceMap.erase(container.containerPrefix); invariant(numDeleted == 1); - it = _namespaceToContainerMap.erase(it); + _namespaceToContainerMap.erase(it++); invariant(_namespaceToContainerMap.size() == _cursorIdPrefixToNamespaceMap.size()); return it; } diff --git a/src/mongo/s/query/cluster_cursor_manager.h b/src/mongo/s/query/cluster_cursor_manager.h index 3b3d94c37c0..1a86765cd90 100644 --- a/src/mongo/s/query/cluster_cursor_manager.h +++ b/src/mongo/s/query/cluster_cursor_manager.h @@ -474,8 +474,7 @@ private: class CursorEntry; struct CursorEntryContainer; using CursorEntryMap = stdx::unordered_map<CursorId, CursorEntry>; - using NssToCursorContainerMap = - stdx::unordered_map<NamespaceString, CursorEntryContainer, NamespaceString::Hasher>; + using NssToCursorContainerMap = stdx::unordered_map<NamespaceString, CursorEntryContainer>; /** * Transfers ownership of the given pinned cursor back to the manager, and moves the cursor to diff --git a/src/mongo/db/auth/user_name_hash.h b/src/mongo/stdx/trusted_hasher.h index 480479214b6..8e3df6f07e0 100644 --- a/src/mongo/db/auth/user_name_hash.h +++ b/src/mongo/stdx/trusted_hasher.h @@ -1,4 +1,3 @@ - /** * Copyright (C) 2018-present MongoDB, Inc. * @@ -30,18 +29,38 @@ #pragma once -#include <string> +// This file depends on internal implementation details in abseil. In a library upgrade you may have +// to re-write this file significantly. +#include <absl/container/internal/hash_function_defaults.h> -#include "mongo/db/auth/user_name.h" -#include "mongo/platform/hash_namespace.h" +/** + * To be safe we let abseil hash the produced hash one more time to protect ourselves against bad + * hash functions. If you know your hash function is good and can be trusted you get mark it as + * trusted by specializing a template like this: + * + * namespace mongo { + * template <> + * struct IsTrustedHasher<YourHash, YourKey> : std::true_type {}; + * } + */ +namespace mongo { +template <typename Key> +using DefaultHasher = absl::container_internal::hash_default_hash<Key>; -// Define hash function for UserNames so they can be keys in stdx::unordered_map -MONGO_HASH_NAMESPACE_START -template <> -struct hash<mongo::UserName> { - size_t operator()(const mongo::UserName& pname) const { - return hash<std::string>()(pname.getFullName()); +template <typename Hasher, typename Key> +struct IsTrustedHasher : std::is_same<Hasher, DefaultHasher<Key>> {}; + +template <typename Hasher, typename Key> +struct HashImprover : private Hasher { + HashImprover(const Hasher& hasher = Hasher()) : Hasher(hasher) {} + std::size_t operator()(const Key& k) const { + return absl::Hash<std::size_t>{}(Hasher::operator()(k)); } }; -MONGO_HASH_NAMESPACE_END + +template <typename Hasher, typename Key> +using EnsureTrustedHasher = + std::conditional_t<IsTrustedHasher<Hasher, Key>::value, Hasher, HashImprover<Hasher, Key>>; + +} // namespace mongo diff --git a/src/mongo/stdx/unordered_map.h b/src/mongo/stdx/unordered_map.h index 0a207741b18..6f4e7a8728a 100644 --- a/src/mongo/stdx/unordered_map.h +++ b/src/mongo/stdx/unordered_map.h @@ -30,22 +30,15 @@ #pragma once -#if defined(_WIN32) -#include <boost/unordered_map.hpp> -#else -#include <unordered_map> -#endif +#include "mongo/stdx/trusted_hasher.h" + +#include <absl/container/node_hash_map.h> namespace mongo { namespace stdx { -#if defined(_WIN32) -using ::boost::unordered_map; // NOLINT -using ::boost::unordered_multimap; // NOLINT -#else -using ::std::unordered_map; // NOLINT -using ::std::unordered_multimap; // NOLINT -#endif +template <class Key, class Value, class Hasher = DefaultHasher<Key>, typename... Args> +using unordered_map = absl::node_hash_map<Key, Value, EnsureTrustedHasher<Hasher, Key>, Args...>; } // namespace stdx } // namespace mongo diff --git a/src/mongo/stdx/unordered_set.h b/src/mongo/stdx/unordered_set.h index dc24c3e7235..d88450cce75 100644 --- a/src/mongo/stdx/unordered_set.h +++ b/src/mongo/stdx/unordered_set.h @@ -30,22 +30,15 @@ #pragma once -#if defined(_WIN32) -#include <boost/unordered_set.hpp> -#else -#include <unordered_set> -#endif +#include "mongo/stdx/trusted_hasher.h" + +#include <absl/container/node_hash_set.h> namespace mongo { namespace stdx { -#if defined(_WIN32) -using ::boost::unordered_set; // NOLINT -using ::boost::unordered_multiset; // NOLINT -#else -using ::std::unordered_set; // NOLINT -using ::std::unordered_multiset; // NOLINT -#endif +template <class Key, class Hasher = DefaultHasher<Key>, typename... Args> +using unordered_set = absl::node_hash_set<Key, EnsureTrustedHasher<Hasher, Key>, Args...>; } // namespace stdx } // namespace mongo diff --git a/src/mongo/util/invalidating_lru_cache.h b/src/mongo/util/invalidating_lru_cache.h index 48550b22ba5..37a7bcdfef0 100644 --- a/src/mongo/util/invalidating_lru_cache.h +++ b/src/mongo/util/invalidating_lru_cache.h @@ -285,7 +285,7 @@ private: * otherwise pass nullptr and this function will lock/check the weak_ptr itself. */ ActiveIterator _invalidateActiveIterator(UniqueLockWithPtrGuard& guard, - const ActiveIterator& it, + ActiveIterator it, std::shared_ptr<Value>&& value) { // If the iterator is past-the-end, then just return the iterator if (it == _active.end()) { @@ -311,7 +311,8 @@ private: // Erase the iterator from the _active map and return the next iterator (so this // can be called in a loop). - return _active.erase(it); + _active.erase(it++); + return it; } /* diff --git a/src/mongo/util/keyed_executor.h b/src/mongo/util/keyed_executor.h index 2f0938c907c..80862d81e8e 100644 --- a/src/mongo/util/keyed_executor.h +++ b/src/mongo/util/keyed_executor.h @@ -73,13 +73,13 @@ namespace mongo { * be effected by ceasing to queue new work, running tasks which can fail early and waiting on * onAllCurrentTasksDrained. */ -template <typename Key, typename... MapArgs> +template <typename Key, typename Hasher = DefaultHasher<Key>, typename... MapArgs> class KeyedExecutor { // We hold a deque per key. Each entry in the deque represents a task we'll eventually execute // and a list of callers who need to be notified after it completes. using Deque = std::deque<std::vector<Promise<void>>>; - using Map = stdx::unordered_map<Key, Deque, MapArgs...>; + using Map = stdx::unordered_map<Key, Deque, Hasher, MapArgs...>; public: explicit KeyedExecutor(OutOfLineExecutor* executor) : _executor(executor) {} diff --git a/src/mongo/util/net/hostandport.cpp b/src/mongo/util/net/hostandport.cpp index e9103fc8062..eb6b402a05c 100644 --- a/src/mongo/util/net/hostandport.cpp +++ b/src/mongo/util/net/hostandport.cpp @@ -217,12 +217,3 @@ template StringBuilderImpl<SharedBufferAllocator>& operator<<( StringBuilderImpl<SharedBufferAllocator>&, const HostAndPort&); } // namespace mongo - -MONGO_HASH_NAMESPACE_START -size_t hash<mongo::HostAndPort>::operator()(const mongo::HostAndPort& host) const { - hash<int> intHasher; - size_t hash = intHasher(host.port()); - boost::hash_combine(hash, host.host()); - return hash; -} -MONGO_HASH_NAMESPACE_END diff --git a/src/mongo/util/net/hostandport.h b/src/mongo/util/net/hostandport.h index e01c75ebe06..d7b069ef08e 100644 --- a/src/mongo/util/net/hostandport.h +++ b/src/mongo/util/net/hostandport.h @@ -36,7 +36,6 @@ #include <boost/optional.hpp> #include "mongo/bson/util/builder.h" -#include "mongo/platform/hash_namespace.h" #include "mongo/util/net/sockaddr.h" namespace mongo { @@ -154,6 +153,11 @@ struct HostAndPort { return _port >= 0; } + template <typename H> + friend H AbslHashValue(H h, const HostAndPort& hostAndPort) { + return H::combine(std::move(h), hostAndPort.host(), hostAndPort.port()); + } + private: boost::optional<SockAddr> _addr; std::string _host; @@ -166,12 +170,3 @@ template <typename Allocator> StringBuilderImpl<Allocator>& operator<<(StringBuilderImpl<Allocator>& os, const HostAndPort& hp); } // namespace mongo - -MONGO_HASH_NAMESPACE_START - -template <> -struct hash<mongo::HostAndPort> { - size_t operator()(const mongo::HostAndPort& host) const; -}; - -MONGO_HASH_NAMESPACE_END |