diff options
-rw-r--r-- | src/mongo/s/SConscript | 5 | ||||
-rw-r--r-- | src/mongo/s/field_parser.cpp | 18 | ||||
-rw-r--r-- | src/mongo/s/field_parser.h | 5 | ||||
-rw-r--r-- | src/mongo/s/field_parser_test.cpp | 18 | ||||
-rw-r--r-- | src/mongo/s/type_shard.cpp | 100 | ||||
-rw-r--r-- | src/mongo/s/type_shard.h | 127 | ||||
-rw-r--r-- | src/mongo/s/type_shard_test.cpp | 52 |
7 files changed, 323 insertions, 2 deletions
diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript index 7a273dfeb33..e7a1bbdb739 100644 --- a/src/mongo/s/SConscript +++ b/src/mongo/s/SConscript @@ -6,7 +6,8 @@ env.StaticLibrary('config', ['cluster_constants.cpp', 'field_parser.cpp', 'type_chunk.cpp', 'type_collection.cpp', - 'type_database.cpp'], + 'type_database.cpp', + 'type_shard.cpp'], LIBDEPS=['$BUILD_DIR/mongo/base/base', '$BUILD_DIR/mongo/bson']) @@ -17,3 +18,5 @@ env.CppUnitTest('type_chunk_test', 'type_chunk_test.cpp', LIBDEPS=['config']) env.CppUnitTest('type_collection_test', 'type_collection_test.cpp', LIBDEPS=['config']) env.CppUnitTest('type_database_test', 'type_database_test.cpp', LIBDEPS=['config']) + +env.CppUnitTest('type_shard_test', 'type_shard_test.cpp', LIBDEPS=['config']) diff --git a/src/mongo/s/field_parser.cpp b/src/mongo/s/field_parser.cpp index 9d5080b16c5..b9be26e1e72 100644 --- a/src/mongo/s/field_parser.cpp +++ b/src/mongo/s/field_parser.cpp @@ -126,4 +126,22 @@ namespace mongo { return false; } + bool FieldParser::extract(BSONObj doc, + const BSONField<long long>& field, + const long long& def, + long long* out) { + BSONElement elem = doc[field.name()]; + if (elem.eoo()) { + *out = def; + return true; + } + + if (elem.type() == NumberLong) { + *out = elem.numberLong(); + return true; + } + + return false; + } + } // namespace mongo diff --git a/src/mongo/s/field_parser.h b/src/mongo/s/field_parser.h index 218ea0f89bf..bddae660562 100644 --- a/src/mongo/s/field_parser.h +++ b/src/mongo/s/field_parser.h @@ -67,6 +67,11 @@ namespace mongo { const BSONField<OID>& field, const OID& def, OID* out); + + static bool extract(BSONObj doc, + const BSONField<long long>& field, + const long long& def, + long long* out); }; } // namespace mongo diff --git a/src/mongo/s/field_parser_test.cpp b/src/mongo/s/field_parser_test.cpp index ffa43ad13c1..298d10e03a2 100644 --- a/src/mongo/s/field_parser_test.cpp +++ b/src/mongo/s/field_parser_test.cpp @@ -42,6 +42,7 @@ namespace { Date_t valDate; string valString; OID valOID; + long long valLong; static BSONField<bool> aBool; static BSONField<BSONArray> anArray; @@ -49,6 +50,7 @@ namespace { static BSONField<Date_t> aDate; static BSONField<string> aString; static BSONField<OID> anOID; + static BSONField<long long> aLong; void setUp() { valBool = true; @@ -57,13 +59,15 @@ namespace { valDate = 1ULL; valString = "a string"; valOID = OID::gen(); + valLong = 1LL; doc = BSON(aBool(valBool) << anArray(valArray) << anObj(valObj) << aDate(valDate) << aString(valString) << - anOID(valOID)); + anOID(valOID) << + aLong(valLong)); } void tearDown() { @@ -76,6 +80,7 @@ namespace { BSONField<Date_t> ExtractionFixture::aDate("aDate"); BSONField<string> ExtractionFixture::aString("aString"); BSONField<OID> ExtractionFixture::anOID("anOID"); + BSONField<long long> ExtractionFixture::aLong("aLong"); TEST_F(ExtractionFixture, GetBool) { BSONField<bool> notThere("otherBool"); @@ -144,4 +149,15 @@ namespace { ASSERT_FALSE(FieldParser::extract(doc, wrongType, defOID, &val)); } + TEST_F(ExtractionFixture, GetLong) { + BSONField<long long> notThere("otherLong"); + BSONField<long long> wrongType(aString.name()); + long long val; + ASSERT_TRUE(FieldParser::extract(doc, aLong, 0, &val)); + ASSERT_EQUALS(val, valLong); + ASSERT_TRUE(FieldParser::extract(doc, notThere, 0, &val)); + ASSERT_EQUALS(val, 0); + ASSERT_FALSE(FieldParser::extract(doc, wrongType, 0, &val)); + } + } // unnamed namespace diff --git a/src/mongo/s/type_shard.cpp b/src/mongo/s/type_shard.cpp new file mode 100644 index 00000000000..4269e88d7cc --- /dev/null +++ b/src/mongo/s/type_shard.cpp @@ -0,0 +1,100 @@ +/** + * Copyright (C) 2012 10gen 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/>. + */ + +#include "mongo/s/type_shard.h" + +#include "mongo/s/field_parser.h" +#include "mongo/util/mongoutils/str.h" + +namespace mongo { + + using mongoutils::str::stream; + + const std::string ShardType::ConfigNS = "config.shards"; + + BSONField<std::string> ShardType::name("_id"); + BSONField<std::string> ShardType::host("host"); + BSONField<bool> ShardType::draining("draining"); + BSONField<long long> ShardType::maxSize("maxSize"); + + ShardType::ShardType() { + clear(); + } + + ShardType::~ShardType() { + } + + bool ShardType::isValid(std::string* errMsg) const { + std::string dummy; + if (errMsg == NULL) { + errMsg = &dummy; + } + + // All the mandatory fields must be present. + if (_name.empty()) { + *errMsg = stream() << "missing " << name.name() << " field"; + return false; + } + if (_host.empty()) { + *errMsg = stream() << "missing " << host.name() << " field"; + return false; + } + + return true; + } + + BSONObj ShardType::toBSON() const { + BSONObjBuilder builder; + if (!_name.empty()) builder.append(name(), _name); + if (!_host.empty()) builder.append(host(), _host); + if (_draining) builder.append(draining(), _draining); + if (_maxSize > 0) builder.append(maxSize(), _maxSize); + return builder.obj(); + } + + void ShardType::parseBSON(BSONObj source) { + clear(); + + bool ok = true; + ok &= FieldParser::extract(source, name, "", &_name); + ok &= FieldParser::extract(source, host, "", &_host); + ok &= FieldParser::extract(source, draining, false, &_draining); + ok &= FieldParser::extract(source, maxSize, 0LL, &_maxSize); + if (! ok) { + clear(); + } + } + + void ShardType::clear() { + _name.clear(); + _host.clear(); + _draining = false; + _maxSize = 0; + } + + void ShardType::cloneTo(ShardType* other) { + other->clear(); + other->_name = _name; + other->_host = _host; + other->_draining = _draining; + other->_maxSize = _maxSize; + } + + std::string ShardType::toString() const { + return toBSON().toString(); + } + +} // namespace mongo diff --git a/src/mongo/s/type_shard.h b/src/mongo/s/type_shard.h new file mode 100644 index 00000000000..686fad638e8 --- /dev/null +++ b/src/mongo/s/type_shard.h @@ -0,0 +1,127 @@ +/** + * Copyright (C) 2012 10gen 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/>. + */ + +#pragma once + +#include <string> + +#include "mongo/base/disallow_copying.h" +#include "mongo/base/string_data.h" +#include "mongo/db/jsobj.h" + +namespace mongo { + + /** + * This class represents the layout and contents of documents contained in the + * config.shards collection. All manipulation of documents coming from that + * collection should be done with this class. + * + * Usage Example: + * + * DBClientBase* conn; + * BSONObj query = QUERY(ShardType::name("shard0000")); + * shardDoc = conn->findOne(ShardType::ConfigNS, query); + * + * // Process the response. + * ShardType shard; + * shard.fromBSON(shardDoc); + * if (! shard.isValid()) { + * // Can't use 'shard'. Take action. + * } + * // use 'shard' + * + */ + class ShardType { + MONGO_DISALLOW_COPYING(ShardType); + public: + + // + // schema declarations + // + + // Name of the shard collection in the config server. + static const std::string ConfigNS; + + // Field names and types in the shard collection type. + static BSONField<std::string> name; + static BSONField<std::string> host; + static BSONField<bool> draining; + static BSONField<long long> maxSize; + + // + // shard type methods + // + + ShardType(); + ~ShardType(); + + /** + * Returns true if all the mandatory fields are present and have valid + * representations. Otherwise returns false and fills in the optional 'errMsg' string. + */ + bool isValid(std::string* errMsg) const; + + /** + * Returns the BSON representation of the entry. + */ + BSONObj toBSON() const; + + /** + * Clears and populates the internal state using the 'source' BSON object if the + * latter contains valid values. Otherwise clear the internal state. + */ + void parseBSON(BSONObj source); + + /** + * Clears the internal state. + */ + void clear(); + + /** + * Copies all the fields present in 'this' to 'other'. + */ + void cloneTo(ShardType* other); + + /** + * Returns a string representation of the current internal state. + */ + std::string toString() const; + + // + // individual field accessors + // + + void setName(const StringData& name) { _name = std::string(name.data(), name.size()); } + const std::string& getName() const { return _name; } + + void setHost(const StringData& host) { _host = std::string(host.data(), host.size()); } + const std::string& getHost() const { return _host; } + + void setDraining(bool draining) { _draining = draining; } + bool getDraining() const { return _draining; } + + void setMaxSize(uint64_t maxSize) { _maxSize = maxSize; } + uint64_t getMaxSize() const { return _maxSize; } + + private: + // Convention: (M)andatory, (O)ptional, (S)pecial rule. + std::string _name; // (M) shard's id + std::string _host; // (M) connection string for the host(s) + bool _draining; // (O) is it draining chunks? + long long _maxSize; // (O) maximum allowed disk space in MB + }; + +} // namespace mongo diff --git a/src/mongo/s/type_shard_test.cpp b/src/mongo/s/type_shard_test.cpp new file mode 100644 index 00000000000..a316158175a --- /dev/null +++ b/src/mongo/s/type_shard_test.cpp @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2012 10gen 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/>. + */ + +#include "mongo/pch.h" + +#include "mongo/s/type_shard.h" +#include "mongo/unittest/unittest.h" + +namespace { + + using mongo::ShardType; + using mongo::BSONObj; + + TEST(Validity, Empty) { + ShardType shard; + BSONObj emptyObj = BSONObj(); + shard.parseBSON(emptyObj); + ASSERT_FALSE(shard.isValid(NULL)); + } + + TEST(Validity, OnlyMandatory) { + ShardType shard; + BSONObj obj = BSON(ShardType::name("shard0000") << + ShardType::host("localhost:27017")); + shard.parseBSON(obj); + ASSERT_TRUE(shard.isValid(NULL)); + } + + TEST(Validity, AllOptionalsPresent) { + ShardType shard; + BSONObj obj = BSON(ShardType::name("shard0000") << + ShardType::host("localhost:27017") << + ShardType::draining(true) << + ShardType::maxSize(100)); + shard.parseBSON(obj); + ASSERT_TRUE(shard.isValid(NULL)); + } + +} // unnamed namespace |