diff options
-rw-r--r-- | src/mongo/base/SConscript | 2 | ||||
-rw-r--r-- | src/mongo/base/fast_string_key.h | 86 | ||||
-rw-r--r-- | src/mongo/base/fast_string_key_test.cpp | 202 | ||||
-rw-r--r-- | src/mongo/db/projection.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/projection.h | 5 |
5 files changed, 5 insertions, 296 deletions
diff --git a/src/mongo/base/SConscript b/src/mongo/base/SConscript index 9b0bdeacb53..104d1a555cb 100644 --- a/src/mongo/base/SConscript +++ b/src/mongo/base/SConscript @@ -31,5 +31,3 @@ env.CppUnitTest('parse_number_test', ['parse_number_test.cpp'], LIBDEPS=['base'] env.CppUnitTest('initializer_test', ['initializer_test.cpp'], LIBDEPS=['base']) -env.CppUnitTest('fast_string_key_test', ['fast_string_key_test.cpp'], LIBDEPS=[]) - diff --git a/src/mongo/base/fast_string_key.h b/src/mongo/base/fast_string_key.h deleted file mode 100644 index 6e6c724d8d5..00000000000 --- a/src/mongo/base/fast_string_key.h +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright 2012 10gen Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include <string> -#include <boost/functional/hash.hpp> - -#include "mongo/base/string_data.h" - -namespace mongo { - - /** This class should be a mostly drop-in replacement for std::string as keys in maps and sets. - * The main advantage over std::string is that you can do lookups using c-strings without - * constructing a std::string and copying the query to a heap-allocated buffer. - * - * NOTE: This is not a general purpose class. You should never create variables of this type. - * - * WARNING: this class does not support string with embedded NUL bytes. It is most useful for - * holding the equivalent of BSONObj fieldNames which do not support NUL either. - */ - class FastStringKey { - public: - /*implicit*/ FastStringKey(const char* s) : _str(s) {} - /*implicit*/ FastStringKey(const std::string& s) : _str(s.c_str()) {} - /*implicit*/ FastStringKey(const StringData& s) : _str(s.data()) {} - - /** This should only be called by containers when adding a new element - * - * This class assumes that lookups in containers don't copy the query object. This isn't - * guaranteed by the standard, but based on the required signatures no sane implementation - * would. If some STL implementation did copy the query object, we'd be no worse off than - * with just using std::string. - */ - FastStringKey(const FastStringKey& source) { - if (source._holder) - _holder = source._holder; - else - _holder = boost::shared_ptr<char>(strdup(source._str), free); - - _str = _holder.get(); - } - - - const char* c_str() const { return _str; } - - bool operator < (const FastStringKey& rhs) const { return strcmp(_str, rhs._str) < 0; } - bool operator == (const FastStringKey& rhs) const { return strcmp(_str, rhs._str) == 0; } - - /** This class is compliant with the TR1 std::hash interface. - * To use it, use unordered_set<FastStringKey, FastStringKey::hash>. - * We can't specialize std::hash easily because it may be called std::tr1::hash - */ - class hash { - public: - size_t operator() (const FastStringKey& str) const { - const char* begin = str.c_str(); - const char* end = begin + strlen(begin); - - // TODO maybe consider alternate hashing algorithms - return boost::hash_range(begin, end); - } - }; - - protected: // only subclass is in fast_string_key_test.cpp - bool isOwned() const { return _holder != NULL; } - - private: - const char* _str; - boost::shared_ptr<char> _holder; // NULL if not copied - - void operator= (const FastStringKey&); // not defined - }; -} diff --git a/src/mongo/base/fast_string_key_test.cpp b/src/mongo/base/fast_string_key_test.cpp deleted file mode 100644 index 741b9c30627..00000000000 --- a/src/mongo/base/fast_string_key_test.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* Copyright 2012 10gen Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Unit tests of the FastStringKey type. - */ - -#include <mongo/pch.h> // needed for mongoutils str.h - -#include "mongo/base/fast_string_key.h" - -#include <map> -#include <set> -#include <boost/unordered_map.hpp> -#include <boost/unordered_set.hpp> - -#include "mongo/platform/unordered_map.h" -#include "mongo/platform/unordered_set.h" -#include "mongo/util/mongoutils/str.h" -#include "mongo/unittest/unittest.h" - -namespace { - using namespace std; - using namespace mongo; - using namespace mongoutils; - - // This does extra checking that the map/set types use this class as expected - class FastStringKeyStrict : public FastStringKey { - public: - // can't use "using" on constructor - /*implicit*/ FastStringKeyStrict(const char* s) : FastStringKey(s) {} - /*implicit*/ FastStringKeyStrict(const std::string& s) : FastStringKey(s) {} - /*implicit*/ FastStringKeyStrict(const StringData& s) : FastStringKey(s) {} - - FastStringKeyStrict(const FastStringKeyStrict& s) : FastStringKey(s) { - ASSERT_TRUE(allow_FastStringKey_copies); - } - - bool operator < (const FastStringKeyStrict& rhs) const { - // at least one operand should be owned since it is in the map/set - ASSERT_TRUE(this->isOwned() || rhs.isOwned()); - - return FastStringKey::operator<(rhs); - } - bool operator == (const FastStringKeyStrict& rhs) const { - // at least one operand should be owned since it is in the map/set - ASSERT_TRUE(this->isOwned() || rhs.isOwned()); - - return FastStringKey::operator==(rhs); - } - - friend class DisallowCopies; - class DisallowCopies { - public: - DisallowCopies() { FastStringKeyStrict::allow_FastStringKey_copies = false; } - ~DisallowCopies() { FastStringKeyStrict::allow_FastStringKey_copies = true; } - }; - - private: - void assertOneOwned(const FastStringKeyStrict& rhs) const { - } - - static bool allow_FastStringKey_copies; - }; - bool FastStringKeyStrict::allow_FastStringKey_copies = true; - - template <typename Map> - void fillMap(Map& m) { - m[""] = 1; - m["a"] = 1; - m["aa"] = 1; - m["bb"] = 1; - m[string("b")] = 1; - m[StringData("abracadabra")] = 1; - } - - template <typename Map> - void fillMapPairs(Map& m) { - m.insert(make_pair("", 1)); - m.insert(make_pair("a", 1)); - m.insert(make_pair("aa", 1)); - m.insert(make_pair("bb", 1)); - m.insert(make_pair(string("b"), 1)); - m.insert(make_pair(StringData("abracadabra"), 1)); - } - - template <typename Set> - void fillSet(Set& s) { - s.insert(""); - s.insert("a"); - s.insert("aa"); - s.insert("bb"); - s.insert(string("b")); - s.insert(StringData("abracadabra")); - } - - template <typename StringType, typename MapOrSet> - void checkGeneric(const MapOrSet& ms, unsigned fills) { - FastStringKeyStrict::DisallowCopies no_copying_while_reading; - - ASSERT_EQUALS(ms.size(), 6u * fills); - - ASSERT_EQUALS(ms.count(StringType("")), fills); - ASSERT_EQUALS(ms.count(StringType("a")), fills); - ASSERT_EQUALS(ms.count(StringType("aa")), fills); - ASSERT_EQUALS(ms.count(StringType("bb")), fills); - ASSERT_EQUALS(ms.count(StringType("b")), fills); - ASSERT_EQUALS(ms.count(StringType("abracadabra")), fills); - - ASSERT_EQUALS(ms.count(StringType("no such key")), 0u); - } - - // Makes the TEMPLATE_TEST_INSTANCEs below easier to read - enum IsMulti{Single=false, Multi=true}; - - template<typename ContainerType, void(*fillFunc)(ContainerType&), IsMulti isMulti> - TEMPLATE_TEST(FastStringKeyTest, TestContainer) { - ContainerType cont; - - fillFunc(cont); - unsigned fills = 1; - - checkGeneric<const char*>(cont, fills); - checkGeneric<string>(cont, fills); - checkGeneric<StringData>(cont, fills); - - fillFunc(cont); - if (isMulti) fills++; - - checkGeneric<const char*>(cont, isMulti?2:1); - checkGeneric<string>(cont, isMulti?2:1); - checkGeneric<StringData>(cont, isMulti?2:1); - } - // Map tests - TEMPLATE_TEST_INSTANCE(FastStringKeyTest, TestContainer, - map<FastStringKeyStrict, int>, - fillMap, Single); - TEMPLATE_TEST_INSTANCE(FastStringKeyTest, TestContainer, - multimap<FastStringKeyStrict, int>, - fillMapPairs, Multi); - TEMPLATE_TEST_INSTANCE(FastStringKeyTest, TestContainer, - unordered_map<FastStringKeyStrict, int, FastStringKey::hash>, - fillMap, Single); - TEMPLATE_TEST_INSTANCE(FastStringKeyTest, TestContainer, - boost::unordered_map<FastStringKeyStrict, int, FastStringKey::hash>, - fillMap, Single); - TEMPLATE_TEST_INSTANCE(FastStringKeyTest, TestContainer, - boost::unordered_multimap<FastStringKeyStrict, int, FastStringKey::hash>, - fillMapPairs, Multi); - - // Set tests - TEMPLATE_TEST_INSTANCE(FastStringKeyTest, TestContainer, - set<FastStringKeyStrict>, - fillSet, Single); - TEMPLATE_TEST_INSTANCE(FastStringKeyTest, TestContainer, - multiset<FastStringKeyStrict>, - fillSet, Multi); - TEMPLATE_TEST_INSTANCE(FastStringKeyTest, TestContainer, - unordered_set<FastStringKeyStrict, FastStringKey::hash>, - fillSet, Single); - TEMPLATE_TEST_INSTANCE(FastStringKeyTest, TestContainer, - boost::unordered_set<FastStringKeyStrict, FastStringKey::hash>, - fillSet, Single); - TEMPLATE_TEST_INSTANCE(FastStringKeyTest, TestContainer, - boost::unordered_multiset<FastStringKeyStrict, FastStringKey::hash>, - fillSet, Multi); - - TEST(FastStringKeyTest, HashUniqueness) { - // Test all 0 and 1 char strings for hash uniqueness - // This test isn't strictly guaranteed to pass, but if it doesn't we would want to know. - // If it passes once, it will continue passing unless the hash function changes. - - unordered_map<size_t, string> hashes; - - for (char c='\0'; c < '\x7f'; c++) { - const char str[] = {c, '\0'}; - const size_t hash = FastStringKey::hash()(str); - - if (hashes.count(hash)) { - FAIL(str::stream() << "duplicate hash detected!" - << " hash: " << hash - << " str1: \"" << hashes[hash] << "\" " << int(hashes[hash][0]) - << " str2: \"" << str << "\" " << int(str[0]) - ); - } - - hashes[hash] = str; - } - } -} diff --git a/src/mongo/db/projection.cpp b/src/mongo/db/projection.cpp index 08960de6b1a..6c598f6daa7 100644 --- a/src/mongo/db/projection.cpp +++ b/src/mongo/db/projection.cpp @@ -176,8 +176,8 @@ namespace mongo { MatchDetails arrayDetails; arrayDetails.requestElemMatchKey(); if ( matcher->second->matches( in, &arrayDetails ) ) { - log(4) << "Matched array on field: " << matcher->first.c_str() << endl - << " from array: " << in.getField( matcher->first.c_str() ) << endl + log(4) << "Matched array on field: " << matcher->first << endl + << " from array: " << in.getField( matcher->first ) << endl << " in object: " << in << endl << " at position: " << arrayDetails.elemMatchKey() << endl; FieldMap::const_iterator field = _fields.find( e.fieldName() ); @@ -192,7 +192,7 @@ namespace mongo { arrayDetails.elemMatchKey() ).eoo() ); a.append( in.getField( e.fieldName() ).Obj() .getField( arrayDetails.elemMatchKey() ) ); - o.appendArray( matcher->first.c_str(), a.arr() ); + o.appendArray( matcher->first, a.arr() ); append( b, o.done().firstElement(), details, arrayOpType ); } } diff --git a/src/mongo/db/projection.h b/src/mongo/db/projection.h index 7f31601d7bb..c4844f7a146 100644 --- a/src/mongo/db/projection.h +++ b/src/mongo/db/projection.h @@ -18,7 +18,6 @@ #pragma once #include "mongo/pch.h" -#include "mongo/base/fast_string_key.h" #include "jsobj.h" namespace mongo { @@ -141,7 +140,7 @@ namespace mongo { bool _special; // true if this level can't be skipped or included without recursing //TODO: benchmark vector<pair> vs map - typedef map<FastStringKey, boost::shared_ptr<Projection> > FieldMap; + typedef map<string, boost::shared_ptr<Projection> > FieldMap; FieldMap _fields; BSONObj _source; bool _includeID; @@ -151,7 +150,7 @@ namespace mongo { int _limit; // used for $elemMatch and positional operator ($) - typedef map<FastStringKey, shared_ptr<Matcher> > Matchers; + typedef map<string, shared_ptr<Matcher> > Matchers; Matchers _matchers; ArrayOpType _arrayOpType; |