summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorKyle Suarez <kyle.suarez@mongodb.com>2018-03-13 15:15:14 -0400
committerKyle Suarez <kyle.suarez@mongodb.com>2018-03-13 15:15:14 -0400
commitf176b8eefccdb1708c01f7a7ba508ccaae4709bc (patch)
tree3d26fb6ae7919933bc63d3e9653b375afb4ba769 /src/mongo
parent64e649a622b5ac4c1bfad0933132dc7d994b9458 (diff)
downloadmongo-f176b8eefccdb1708c01f7a7ba508ccaae4709bc.tar.gz
SERVER-33847 create type aliases for BSONObj containers with binary comparison semantics
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/bson/SConscript1
-rw-r--r--src/mongo/bson/simple_bsonobj_comparator.h97
-rw-r--r--src/mongo/bson/simple_bsonobj_comparator_test.cpp150
-rw-r--r--src/mongo/db/repl/dbcheck.cpp2
4 files changed, 248 insertions, 2 deletions
diff --git a/src/mongo/bson/SConscript b/src/mongo/bson/SConscript
index 941f7cdc2f0..783aad2f1ab 100644
--- a/src/mongo/bson/SConscript
+++ b/src/mongo/bson/SConscript
@@ -28,6 +28,7 @@ env.CppUnitTest(
target='bson_obj_test',
source=[
'bson_obj_test.cpp',
+ 'simple_bsonobj_comparator_test.cpp',
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
diff --git a/src/mongo/bson/simple_bsonobj_comparator.h b/src/mongo/bson/simple_bsonobj_comparator.h
index 2202e221696..59a61e27dd8 100644
--- a/src/mongo/bson/simple_bsonobj_comparator.h
+++ b/src/mongo/bson/simple_bsonobj_comparator.h
@@ -28,7 +28,12 @@
#pragma once
+#include <map>
+#include <set>
+
#include "mongo/bson/bsonobj_comparator_interface.h"
+#include "mongo/stdx/unordered_map.h"
+#include "mongo/stdx/unordered_set.h"
namespace mongo {
@@ -38,7 +43,7 @@ namespace mongo {
class SimpleBSONObjComparator final : public BSONObj::ComparatorInterface {
public:
// Global simple comparator for stateless BSONObj comparisons. BSONObj comparisons that require
- // database logic, such as collations, much instantiate their own comparator.
+ // database logic, such as collations, must instantiate their own comparator.
static const SimpleBSONObjComparator kInstance;
int compare(const BSONObj& lhs, const BSONObj& rhs) const final {
@@ -48,6 +53,96 @@ public:
void hash_combine(size_t& seed, const BSONObj& toHash) const final {
hashCombineBSONObj(seed, toHash, ComparisonRules::kConsiderFieldName, nullptr);
}
+
+ /**
+ * A functor with simple binary comparison semantics that's suitable for use with ordered STL
+ * containers.
+ */
+ class LessThan {
+ public:
+ explicit LessThan() = default;
+
+ bool operator()(const BSONObj& lhs, const BSONObj& rhs) const {
+ return kInstance.compare(lhs, rhs) < 0;
+ }
+ };
+
+ /**
+ * A functor with simple binary comparison semantics that's suitable for use with unordered STL
+ * containers.
+ */
+ class EqualTo {
+ public:
+ explicit EqualTo() = default;
+
+ bool operator()(const BSONObj& lhs, const BSONObj& rhs) const {
+ return kInstance.compare(lhs, rhs) == 0;
+ }
+ };
+
+ /**
+ * Functor for computing the hash of a BSONObj, compatible for use with unordered STL
+ * containers.
+ */
+ class Hasher {
+ public:
+ explicit Hasher() = default;
+
+ size_t operator()(const BSONObj& obj) const {
+ return kInstance.hash(obj);
+ }
+ };
};
+/**
+ * A set of BSONObjs that performs comparisons with simple binary semantics.
+ */
+using SimpleBSONObjSet = std::set<BSONObj, SimpleBSONObjComparator::LessThan>;
+
+/**
+ * A multiset of BSONObjs that performs comparisons with simple binary semantics.
+ */
+using SimpleBSONObjMultiSet = std::multiset<BSONObj, SimpleBSONObjComparator::LessThan>;
+
+/**
+ * An unordered_set of BSONObjs that performs equality checks using simple binary semantics.
+ */
+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>
+using SimpleBSONObjMap = std::map<BSONObj, T, SimpleBSONObjComparator::LessThan>;
+
+/**
+ * A multimap keyed on BSONObj that performs comparisons with simple binary semantics.
+ */
+template <typename T>
+using SimpleBSONObjMultiMap = std::multimap<BSONObj, T, SimpleBSONObjComparator::LessThan>;
+
+/**
+ * An unordered_map keyed on BSONObj that performs equality checks using simple binary semantics.
+ */
+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
new file mode 100644
index 00000000000..40d536f0bdf
--- /dev/null
+++ b/src/mongo/bson/simple_bsonobj_comparator_test.cpp
@@ -0,0 +1,150 @@
+/**
+ * Copyright (C) 2018 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.
+ */
+
+#include "mongo/platform/basic.h"
+
+#include <map>
+#include <set>
+#include <utility>
+
+#include "mongo/bson/bsonmisc.h"
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/bson/simple_bsonobj_comparator.h"
+#include "mongo/stdx/unordered_map.h"
+#include "mongo/stdx/unordered_set.h"
+#include "mongo/unittest/unittest.h"
+
+namespace mongo {
+namespace {
+/**
+ * Asserts that 'obj' can be successfully inserted into 'set'.
+ */
+template <typename Set>
+void assertInsertSucceeds(Set& set, BSONObj obj) {
+ ASSERT(set.insert(obj).second) << "failed to insert object: " << obj.jsonString();
+}
+
+/**
+ * Asserts that 'obj' fails to be inserted into 'set'.
+ */
+template <typename Set>
+void assertInsertFails(Set& set, BSONObj obj) {
+ ASSERT_FALSE(set.insert(obj).second)
+ << "object was inserted successfully, but should have failed: " << obj.jsonString();
+}
+
+TEST(SimpleBSONObjContainerTest, SetIsDefaultConstructible) {
+ SimpleBSONObjSet set;
+ assertInsertSucceeds(set, BSON("x" << 1));
+ ASSERT_EQ(set.size(), 1UL);
+ assertInsertSucceeds(set, BSON("y" << 1));
+ assertInsertFails(set, BSON("x" << 1));
+ ASSERT_EQ(set.size(), 2UL);
+}
+
+TEST(SimpleBSONObjContainerTest, MultiSetIsDefaultConstructible) {
+ SimpleBSONObjMultiSet multiset;
+ multiset.insert(BSON("x" << 1));
+ multiset.insert(BSON("x" << 1));
+ multiset.insert(BSON("y" << 1));
+ ASSERT_EQ(multiset.size(), 3UL);
+}
+
+TEST(SimpleBSONObjContainerTest, UnorderedSetIsDefaultConstructible) {
+ SimpleBSONObjUnorderedSet uset;
+ assertInsertSucceeds(uset, BSON("x" << 1));
+ ASSERT_EQ(uset.size(), 1UL);
+ assertInsertSucceeds(uset, BSON("y" << 1));
+ assertInsertFails(uset, BSON("x" << 1));
+ 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'.
+ */
+template <typename Map, typename T>
+void assertInsertSucceeds(Map& map, std::pair<BSONObj, T> pair) {
+ ASSERT(map.insert(pair).second) << "failed to insert {key: " << pair.first.jsonString()
+ << ", value: '" << pair.second << "'}";
+}
+
+/**
+ * Asserts that the key-value pair 'pair' fails to be inserted into 'map'.
+ */
+template <typename Map, typename T>
+void assertInsertFails(Map& map, std::pair<BSONObj, T> pair) {
+ ASSERT_FALSE(map.insert(pair).second)
+ << "key-value pair was inserted successfully, but should have failed: {key: "
+ << pair.first.jsonString() << ", value: '" << pair.second << "'}";
+}
+
+TEST(SimpleBSONObjContainerTest, MapIsDefaultConstructible) {
+ SimpleBSONObjMap<std::string> map;
+ assertInsertSucceeds(map, std::make_pair(BSON("_id" << 0), "kyle"));
+ ASSERT_EQ(map.size(), 1UL);
+ assertInsertSucceeds(map, std::make_pair(BSON("_id" << 1), "jungsoo"));
+ ASSERT_EQ(map.size(), 2UL);
+ assertInsertFails(map, std::make_pair(BSON("_id" << 1), "erjon"));
+ ASSERT_EQ(map.size(), 2UL);
+}
+
+TEST(SimpleBSONObjContainerTest, MultiMapIsDefaultConstructible) {
+ SimpleBSONObjMultiMap<std::string> multimap;
+ multimap.insert(std::make_pair(BSON("_id" << 0), "anica"));
+ multimap.insert(std::make_pair(BSON("_id" << 0), "raj"));
+ multimap.insert(std::make_pair(BSON("_id" << 1), "ian"));
+ ASSERT_EQ(multimap.size(), 3UL);
+}
+
+TEST(SimpleBSONObjContainerTest, UnorderedMapIsDefaultConstructible) {
+ SimpleBSONObjUnorderedMap<std::string> umap;
+ assertInsertSucceeds(umap, std::make_pair(BSON("_id" << 0), "kyle"));
+ ASSERT_EQ(umap.size(), 1UL);
+ assertInsertSucceeds(umap, std::make_pair(BSON("_id" << 1), "jungsoo"));
+ ASSERT_EQ(umap.size(), 2UL);
+ assertInsertFails(umap, std::make_pair(BSON("_id" << 1), "erjon"));
+ 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/repl/dbcheck.cpp b/src/mongo/db/repl/dbcheck.cpp
index 781d968f7f5..62e3f5da9f8 100644
--- a/src/mongo/db/repl/dbcheck.cpp
+++ b/src/mongo/db/repl/dbcheck.cpp
@@ -358,7 +358,7 @@ std::vector<BSONObj> collectionIndexInfo(OperationContext* opCtx, Collection* co
auto comp = stdx::make_unique<SimpleBSONObjComparator>();
- std::sort(result.begin(), result.end(), SimpleBSONObjComparator::LessThan(comp.get()));
+ std::sort(result.begin(), result.end(), SimpleBSONObjComparator::LessThan());
return result;
}