summaryrefslogtreecommitdiff
path: root/src/mongo/s
diff options
context:
space:
mode:
authorGreg Studer <greg@10gen.com>2012-11-26 14:14:35 -0500
committerGreg Studer <greg@10gen.com>2012-12-03 17:01:20 -0500
commit64408b78c89a65a4a727b57d552b64bf5f7eb803 (patch)
tree1e82a375b2ddcacb79eb1d3e2035cc6b647c4f6f /src/mongo/s
parentd26f22eb2e4280f3dc5713ab99da810208c783da (diff)
downloadmongo-64408b78c89a65a4a727b57d552b64bf5f7eb803.tar.gz
SERVER-939 modify config types for config version changes
Diffstat (limited to 'src/mongo/s')
-rw-r--r--src/mongo/s/SConscript3
-rw-r--r--src/mongo/s/cluster_constants.cpp1
-rw-r--r--src/mongo/s/cluster_constants.h1
-rw-r--r--src/mongo/s/field_parser.cpp116
-rw-r--r--src/mongo/s/field_parser.h44
-rw-r--r--src/mongo/s/type_chunk.cpp80
-rw-r--r--src/mongo/s/type_chunk.h88
-rw-r--r--src/mongo/s/type_collection.cpp90
-rw-r--r--src/mongo/s/type_collection.h26
-rw-r--r--src/mongo/s/type_config_version.cpp156
-rw-r--r--src/mongo/s/type_config_version.h128
-rw-r--r--src/mongo/s/type_database.cpp2
-rw-r--r--src/mongo/s/type_database.h2
-rw-r--r--src/mongo/s/type_shard.cpp30
-rw-r--r--src/mongo/s/type_shard.h4
15 files changed, 603 insertions, 168 deletions
diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript
index e88793dba2a..8520525295d 100644
--- a/src/mongo/s/SConscript
+++ b/src/mongo/s/SConscript
@@ -11,7 +11,8 @@ env.StaticLibrary('base', ['cluster_constants.cpp',
'type_chunk.cpp',
'type_collection.cpp',
'type_database.cpp',
- 'type_shard.cpp'],
+ 'type_shard.cpp',
+ 'type_config_version.cpp'],
LIBDEPS=['$BUILD_DIR/mongo/base/base',
'$BUILD_DIR/mongo/bson'])
diff --git a/src/mongo/s/cluster_constants.cpp b/src/mongo/s/cluster_constants.cpp
index f75fd97ff26..5412d61fd9a 100644
--- a/src/mongo/s/cluster_constants.cpp
+++ b/src/mongo/s/cluster_constants.cpp
@@ -43,6 +43,7 @@ namespace mongo {
BSONField<Date_t> CollectionFields::lastmod("lastmod");
BSONField<bool> CollectionFields::dropped("dropped");
BSONField<bool> CollectionFields::noBalance("noBalance");
+ BSONField<OID> CollectionFields::epoch("lastmodEpoch");
const string ConfigNS::chunk = "config.chunks";
BSONField<string> ChunkFields::name("_id");
diff --git a/src/mongo/s/cluster_constants.h b/src/mongo/s/cluster_constants.h
index f6bc723c752..32612a82553 100644
--- a/src/mongo/s/cluster_constants.h
+++ b/src/mongo/s/cluster_constants.h
@@ -82,6 +82,7 @@ namespace mongo {
static BSONField<Date_t> lastmod; // when collecation was created
static BSONField<bool> dropped; // logical deletion
static BSONField<bool> noBalance; // true if balancing is disabled
+ static BSONField<OID> epoch; // Epoch of collection
};
/**
diff --git a/src/mongo/s/field_parser.cpp b/src/mongo/s/field_parser.cpp
index b9be26e1e72..0602eae6157 100644
--- a/src/mongo/s/field_parser.cpp
+++ b/src/mongo/s/field_parser.cpp
@@ -15,13 +15,29 @@
*/
#include "mongo/s/field_parser.h"
+#include "mongo/util/mongoutils/str.h"
namespace mongo {
+ using mongoutils::str::stream;
+
+ template<class T>
+ void _genFieldErrMsg(const BSONObj& doc,
+ const BSONField<T>& field,
+ const string expected,
+ string* errMsg)
+ {
+ if (!errMsg) return;
+ *errMsg = stream() << "wrong type for '" << field() << "' field, expected " << expected
+ << ", found " << doc[field.name()].toString();
+ }
+
bool FieldParser::extract(BSONObj doc,
const BSONField<bool>& field,
bool def,
- bool* out) {
+ bool* out,
+ string* errMsg)
+ {
BSONElement elem = doc[field.name()];
if (elem.eoo()) {
*out = def;
@@ -33,13 +49,16 @@ namespace mongo {
return true;
}
+ _genFieldErrMsg(doc, field, "boolean", errMsg);
return false;
}
bool FieldParser::extract(BSONObj doc,
const BSONField<BSONArray>& field,
const BSONArray& def,
- BSONArray* out) {
+ BSONArray* out,
+ string* errMsg)
+ {
BSONElement elem = doc[field.name()];
if (elem.eoo()) {
*out = def;
@@ -47,17 +66,20 @@ namespace mongo {
}
if (elem.type() == Array) {
- *out = BSONArray(elem.embeddedObject());
+ *out = BSONArray(elem.embeddedObject().getOwned());
return true;
}
+ _genFieldErrMsg(doc, field, "array", errMsg);
return false;
}
bool FieldParser::extract(BSONObj doc,
const BSONField<BSONObj>& field,
const BSONObj& def,
- BSONObj* out) {
+ BSONObj* out,
+ string* errMsg)
+ {
BSONElement elem = doc[field.name()];
if (elem.eoo()) {
*out = def;
@@ -65,17 +87,20 @@ namespace mongo {
}
if (elem.type() == Object) {
- *out = elem.embeddedObject();
+ *out = elem.embeddedObject().getOwned();
return true;
}
+ _genFieldErrMsg(doc, field, "object", errMsg);
return false;
}
bool FieldParser::extract(BSONObj doc,
const BSONField<Date_t>& field,
const Date_t def,
- Date_t* out) {
+ Date_t* out,
+ string* errMsg)
+ {
BSONElement elem = doc[field.name()];
if (elem.eoo()) {
*out = def;
@@ -87,13 +112,16 @@ namespace mongo {
return true;
}
+ _genFieldErrMsg(doc, field, "date or timestamp", errMsg);
return false;
}
bool FieldParser::extract(BSONObj doc,
const BSONField<string>& field,
const string& def,
- string* out) {
+ string* out,
+ string* errMsg)
+ {
BSONElement elem = doc[field.name()];
if (elem.eoo()) {
*out = def;
@@ -105,13 +133,16 @@ namespace mongo {
return true;
}
+ _genFieldErrMsg(doc, field, "string", errMsg);
return false;
}
bool FieldParser::extract(BSONObj doc,
const BSONField<OID>& field,
const OID& def,
- OID* out) {
+ OID* out,
+ string* errMsg)
+ {
BSONElement elem = doc[field.name()];
if (elem.eoo()) {
*out = def;
@@ -123,13 +154,58 @@ namespace mongo {
return true;
}
+ _genFieldErrMsg(doc, field, "OID", errMsg);
+ return false;
+ }
+
+ bool FieldParser::extract(BSONObj doc,
+ const BSONField<int>& field,
+ const int& def,
+ int* out,
+ string* errMsg)
+ {
+ BSONElement elem = doc[field.name()];
+ if (elem.eoo()) {
+ *out = def;
+ return true;
+ }
+
+ if (elem.type() == NumberInt) {
+ *out = elem.numberInt();
+ return true;
+ }
+
+ _genFieldErrMsg(doc, field, "integer", errMsg);
+ return false;
+ }
+
+ bool FieldParser::extractNumber(BSONObj doc,
+ const BSONField<int>& field,
+ const int& def,
+ int* out,
+ string* errMsg)
+ {
+ BSONElement elem = doc[field.name()];
+ if (elem.eoo()) {
+ *out = def;
+ return true;
+ }
+
+ if (elem.isNumber()) {
+ *out = elem.numberInt();
+ return true;
+ }
+
+ _genFieldErrMsg(doc, field, "number", errMsg);
return false;
}
bool FieldParser::extract(BSONObj doc,
const BSONField<long long>& field,
const long long& def,
- long long* out) {
+ long long* out,
+ string* errMsg)
+ {
BSONElement elem = doc[field.name()];
if (elem.eoo()) {
*out = def;
@@ -141,6 +217,28 @@ namespace mongo {
return true;
}
+ _genFieldErrMsg(doc, field, "long", errMsg);
+ return false;
+ }
+
+ bool FieldParser::extractNumber(BSONObj doc,
+ const BSONField<long long>& field,
+ const long long& def,
+ long long* out,
+ string* errMsg)
+ {
+ BSONElement elem = doc[field.name()];
+ if (elem.eoo()) {
+ *out = def;
+ return true;
+ }
+
+ if (elem.isNumber()) {
+ *out = elem.numberLong();
+ return true;
+ }
+
+ _genFieldErrMsg(doc, field, "number", errMsg);
return false;
}
diff --git a/src/mongo/s/field_parser.h b/src/mongo/s/field_parser.h
index bddae660562..c02fd438f52 100644
--- a/src/mongo/s/field_parser.h
+++ b/src/mongo/s/field_parser.h
@@ -41,37 +41,67 @@ namespace mongo {
static bool extract(BSONObj doc,
const BSONField<bool>& field,
bool def,
- bool* out);
+ bool* out,
+ string* errMsg = NULL);
static bool extract(BSONObj doc,
const BSONField<BSONArray>& field,
const BSONArray& def,
- BSONArray* out);
+ BSONArray* out,
+ string* errMsg = NULL);
static bool extract(BSONObj doc,
const BSONField<BSONObj>& field,
const BSONObj& def,
- BSONObj* out);
+ BSONObj* out,
+ string* errMsg = NULL);
static bool extract(BSONObj doc,
const BSONField<Date_t>& field,
const Date_t def,
- Date_t* out);
+ Date_t* out,
+ string* errMsg = NULL);
static bool extract(BSONObj doc,
const BSONField<string>& field,
const string& def,
- string* out);
+ string* out,
+ string* errMsg = NULL);
static bool extract(BSONObj doc,
const BSONField<OID>& field,
const OID& def,
- OID* out);
+ OID* out,
+ string* errMsg = NULL);
+
+ static bool extract(BSONObj doc,
+ const BSONField<int>& field,
+ const int& def,
+ int* out,
+ string* errMsg = NULL);
static bool extract(BSONObj doc,
const BSONField<long long>& field,
const long long& def,
- long long* out);
+ long long* out,
+ string* errMsg = NULL);
+
+ /**
+ * The following extractNumber methods do implicit conversion between any numeric type and
+ * the BSONField type. This can be useful when an exact numeric type is not needed, for
+ * example if the field is sometimes modified from the shell which can change the type.
+ */
+ static bool extractNumber(BSONObj doc,
+ const BSONField<int>& field,
+ const int& def,
+ int* out,
+ string* errMsg = NULL);
+
+ static bool extractNumber(BSONObj doc,
+ const BSONField<long long>& field,
+ const long long& def,
+ long long* out,
+ string* errMsg = NULL);
};
} // namespace mongo
diff --git a/src/mongo/s/type_chunk.cpp b/src/mongo/s/type_chunk.cpp
index 306f722a74a..ce513a62a8e 100644
--- a/src/mongo/s/type_chunk.cpp
+++ b/src/mongo/s/type_chunk.cpp
@@ -15,7 +15,6 @@
*/
#include <cstring> // for strcmp
-
#include "mongo/s/type_chunk.h"
#include "mongo/s/field_parser.h"
@@ -47,9 +46,8 @@ namespace mongo {
bool ChunkType::isValid(std::string* errMsg) const {
std::string dummy;
- if (errMsg == NULL) {
- errMsg = &dummy;
- }
+
+ if (errMsg == NULL) errMsg = &dummy;
// All the mandatory fields must be present.
if (_name.empty()) {
@@ -60,11 +58,11 @@ namespace mongo {
*errMsg = stream() << "missing " << ns.name() << " field";
return false;
}
- if (! _min.nFields()) {
+ if (!_min.nFields()) {
*errMsg = stream() << "missing " << min.name() << " field";
return false;
}
- if (! _max.nFields()) {
+ if (!_max.nFields()) {
*errMsg = stream() << "missing " << max.name() << " field";
return false;
}
@@ -110,12 +108,10 @@ namespace mongo {
if (_min.nFields()) builder.append(min(), _min);
if (_max.nFields()) builder.append(max(), _max);
- if (_version._combined != 0ULL) {
- BSONArrayBuilder arrBuilder(builder.subarrayStart(version()));
- arrBuilder.appendTimestamp(_version._major, _version._minor);
- arrBuilder.append(_version._epoch);
- arrBuilder.done();
- }
+ // For now, write both the deprecated *and* the new fields
+
+ _version.addToBSON(builder, version());
+ _version.addToBSON(builder, DEPRECATED_lastmod());
if (!_shard.empty()) builder.append(shard(), _shard);
if (_jumbo) builder.append(jumbo(), _jumbo);
@@ -123,53 +119,37 @@ namespace mongo {
return builder.obj();
}
- void ChunkType::parseBSON(BSONObj source) {
+ string ChunkType::toString() const {
+ return toBSON().toString();
+ }
+
+ bool ChunkType::parseBSON(BSONObj source, string* errMsg) {
clear();
- bool ok = true;
- ok &= FieldParser::extract(source, name, "", &_name);
- ok &= FieldParser::extract(source, ns, "", &_ns);
- ok &= FieldParser::extract(source, min, BSONObj(), &_min);
- ok &= FieldParser::extract(source, max, BSONObj(), &_max);
- ok &= FieldParser::extract(source, shard, "", &_shard);
- ok &= FieldParser::extract(source, jumbo, false, &_jumbo);
- if (! ok) {
- clear();
- return;
- }
+ string dummy;
+ if (!errMsg) errMsg = &dummy;
+
+ if (!FieldParser::extract(source, name, "", &_name, errMsg)) return false;
+ if (!FieldParser::extract(source, ns, "", &_ns, errMsg)) return false;
+ if (!FieldParser::extract(source, min, BSONObj(), &_min, errMsg)) return false;
+ if (!FieldParser::extract(source, max, BSONObj(), &_max, errMsg)) return false;
+ if (!FieldParser::extract(source, shard, "", &_shard, errMsg)) return false;
+ if (!FieldParser::extract(source, jumbo, false, &_jumbo, errMsg)) return false;
//
- // ShardChunkVersion backward compatibility logic
+ // ShardChunkVersion backward compatibility logic contained in ShardChunkVersion
//
// ShardChunkVersion is currently encoded as { 'version': [<TS>,<OID>] }
- BSONArray arrVersion;
- ok = FieldParser::extract(source, version, BSONArray(), &arrVersion);
- if (! ok) {
- clear();
- return;
- }
- else if (arrVersion.nFields()) {
- bool okVersion;
- _version = ShardChunkVersion::fromBSON(arrVersion, &okVersion);
- if (! okVersion) {
- clear();
- }
- return;
- }
- // If we haven't found the current format try parsing the deprecated format
- // { lastmod: <TS>, lastmodEpoch: <OID> }.
- Date_t lastmod;
- OID epoch;
- ok = FieldParser::extract(source, DEPRECATED_lastmod, time(0), &lastmod);
- ok &= FieldParser::extract(source, DEPRECATED_epoch, OID(), &epoch);
- if (! ok) {
- clear();
+ if (ShardChunkVersion::canParseBSON(source, version())) {
+ _version = ShardChunkVersion::fromBSON(source, version());
}
- else {
- _version = ShardChunkVersion(lastmod.millis, epoch);
+ else if (ShardChunkVersion::canParseBSON(source, DEPRECATED_lastmod())) {
+ _version = ShardChunkVersion::fromBSON(source, DEPRECATED_lastmod());
}
+
+ return true;
}
void ChunkType::clear() {
@@ -182,7 +162,7 @@ namespace mongo {
_jumbo = false;
}
- void ChunkType::cloneTo(ChunkType* other) {
+ void ChunkType::cloneTo(ChunkType* other) const {
other->clear();
other->_name = _name;
other->_ns = _ns;
diff --git a/src/mongo/s/type_chunk.h b/src/mongo/s/type_chunk.h
index a10fdfa206e..23f12db3280 100644
--- a/src/mongo/s/type_chunk.h
+++ b/src/mongo/s/type_chunk.h
@@ -22,7 +22,6 @@
#include "mongo/base/string_data.h"
#include "mongo/db/jsobj.h"
#include "mongo/s/util.h" // for ShardChunkVersion
-
namespace mongo {
/**
@@ -71,8 +70,8 @@ namespace mongo {
// Transition to new format, 2.2 -> 2.4
// 2.2 can read both lastmod + lastmodEpoch format and 2.4 [ lastmod, OID ] formats.
- static BSONField<Date_t> DEPRECATED_lastmod; // major | minor versions
- static BSONField<OID> DEPRECATED_epoch; // disambiguates collection incarnations
+ static BSONField<Date_t> DEPRECATED_lastmod; // major | minor versions
+ static BSONField<OID> DEPRECATED_epoch; // disambiguates collection incarnations
//
// chunk type methods
@@ -96,7 +95,7 @@ namespace mongo {
* 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);
+ bool parseBSON(BSONObj source, std::string* errMsg);
/**
* Clears the internal state.
@@ -106,7 +105,7 @@ namespace mongo {
/**
* Copies all the fields present in 'this' to 'other'.
*/
- void cloneTo(ChunkType* other);
+ void cloneTo(ChunkType* other) const;
/**
* Returns a string representation of the current internal state.
@@ -117,36 +116,71 @@ namespace mongo {
// individual field accessors
//
- void setName(const StringData& name) { _name = std::string(name.data(), name.size()); }
- const std::string& getName() const { return _name; }
+ void setName(const StringData& name) {
+ _name = std::string(name.data(), name.size());
+ }
+
+ const std::string& getName() const {
+ return _name;
+ }
+
+ void setNS(const StringData& ns) {
+ _ns = std::string(ns.data(), ns.size());
+ }
+
+ const std::string& getNS() const {
+ return _ns;
+ }
+
+ void setMin(const BSONObj& min) {
+ _min = min.getOwned();
+ }
+
+ BSONObj getMin() const {
+ return _min;
+ }
+
+ void setMax(const BSONObj& max) {
+ _max = max.getOwned();
+ }
+
+ BSONObj getMax() const {
+ return _max;
+ }
- void setNS(const StringData& ns) { _ns = std::string(ns.data(), ns.size()); }
- const std::string& getNS() const { return _ns; }
+ void setVersion(const ShardChunkVersion& version) {
+ _version = version;
+ }
- void setMin(const BSONObj& min) { _min = min.getOwned(); }
- BSONObj getMin() const { return _min; }
+ const ShardChunkVersion& getVersion() const {
+ return _version;
+ }
- void setMax(const BSONObj& max) { _max = max.getOwned(); }
- BSONObj getMax() const { return _max; }
+ void setShard(const StringData& shard) {
+ _shard = std::string(shard.data(), shard.size());
+ }
- void setVersion(const ShardChunkVersion& version) { _version = version; }
- const ShardChunkVersion& getVersion() const { return _version; }
+ const std::string& getShard() const {
+ return _shard;
+ }
- void setShard(const StringData& shard) { _shard=std::string(shard.data(), shard.size()); }
- const std::string& getShard() const { return _shard; }
+ void setJumbo(bool jumbo) {
+ _jumbo = jumbo;
+ }
- void setJumbo(bool jumbo) { _jumbo = jumbo; }
- bool getJumbo() const { return _jumbo; }
+ bool getJumbo() const {
+ return _jumbo;
+ }
private:
// Convention: (M)andatory, (O)ptional, (S)pecial rule.
- string _name; // (M) chunk's id
- string _ns; // (M) collection this chunk is in
- BSONObj _min; // (M) first key of the range, inclusive
- BSONObj _max; // (M) last key of the range, non-inclusive
- ShardChunkVersion _version; // (M) version of this chunk
- string _shard; // (M) shard this chunk lives in
- bool _jumbo; // (O) too big to move?
+ string _name; // (M) chunk's id
+ string _ns; // (M) collection this chunk is in
+ BSONObj _min; // (M) first key of the range, inclusive
+ BSONObj _max; // (M) last key of the range, non-inclusive
+ ShardChunkVersion _version; // (M) version of this chunk
+ string _shard; // (M) shard this chunk lives in
+ bool _jumbo; // (O) too big to move?
};
-} // namespace mongo
+} // namespace mongo
diff --git a/src/mongo/s/type_collection.cpp b/src/mongo/s/type_collection.cpp
index c3643fc2398..a1f5246c375 100644
--- a/src/mongo/s/type_collection.cpp
+++ b/src/mongo/s/type_collection.cpp
@@ -27,13 +27,14 @@ namespace mongo {
BSONField<std::string> CollectionType::primary("primary");
BSONField<BSONObj> CollectionType::keyPattern("key");
BSONField<bool> CollectionType::unique("unique");
- BSONField<Date_t> CollectionType::createdAt("createdAt");
+ BSONField<Date_t> CollectionType::updatedAt("updatedAt");
BSONField<bool> CollectionType::noBalance("noBalance");
BSONField<OID> CollectionType::epoch("epoch");
+ // To-be-deprecated, not yet
+ BSONField<bool> CollectionType::dropped("dropped");
BSONField<OID> CollectionType::DEPRECATED_lastmodEpoch("lastmodEpoch");
BSONField<Date_t> CollectionType::DEPRECATED_lastmod("lastmod");
- BSONField<bool> CollectionType::DEPRECATED_dropped("dropped");
CollectionType::CollectionType() {
clear();
@@ -44,28 +45,26 @@ namespace mongo {
bool CollectionType::isValid(std::string* errMsg) const {
std::string dummy;
- if (errMsg == NULL) {
- errMsg = &dummy;
- }
+
+ if (errMsg == NULL) errMsg = &dummy;
// All the mandatory fields must be present.
if (_ns.empty()) {
*errMsg = stream() << "missing " << ns.name() << " field";
return false;
}
- if (_createdAt.millis == 0) {
- *errMsg = stream() << "missing " << createdAt.name() << " field";
+ if (_updatedAt.millis == 0) {
+ *errMsg = stream() << "missing " << updatedAt.name() << " field";
return false;
}
- if (! _epoch.isSet()) {
+ if (!_epoch.isSet()) {
*errMsg = stream() << "missing " << epoch.name() << " field";
return false;
}
// Either sharding or primary information should be filled.
if (_primary.empty() == (_keyPattern.nFields() == 0)) {
- *errMsg = stream() << "either " << primary.name()
- << " or " << keyPattern.name()
+ *errMsg = stream() << "either " << primary.name() << " or " << keyPattern.name()
<< " should be filled";
return false;
}
@@ -81,62 +80,59 @@ namespace mongo {
BSONObj CollectionType::toBSON() const {
BSONObjBuilder builder;
- if (!_ns.empty()) builder.append(ns(), _ns);
+ builder.append(ns(), _ns);
if (!_primary.empty()) builder.append(primary(), _primary);
if (_keyPattern.nFields()) builder.append(keyPattern(), _keyPattern);
if (_unique) builder.append(unique(), _unique);
- if (_createdAt.millis > 0ULL) builder.append(createdAt(), _createdAt);
+ builder.append(updatedAt(), _updatedAt);
+ builder.append(DEPRECATED_lastmod(), _updatedAt);
if (_noBalance) builder.append(noBalance(), _noBalance);
- if (_epoch.isSet()) builder.append(epoch(), _epoch);
+ if (_epoch.isSet()) {
+ builder.append(epoch(), _epoch);
+ builder.append(DEPRECATED_lastmodEpoch(), _epoch);
+ }
+ // Always need to write dropped for compatibility w/ 2.0/2.2
+ builder.append(dropped(), _dropped);
return builder.obj();
}
- void CollectionType::parseBSON(BSONObj source) {
+ bool CollectionType::parseBSON(BSONObj source, string* errMsg) {
clear();
- bool ok = true;
- ok &= FieldParser::extract(source, ns, "", &_ns);
- ok &= FieldParser::extract(source, primary, "", &_primary);
- ok &= FieldParser::extract(source, keyPattern, BSONObj(), &_keyPattern);
- ok &= FieldParser::extract(source, unique, false, &_unique);
- ok &= FieldParser::extract(source, createdAt, 0ULL, &_createdAt);
- ok &= FieldParser::extract(source, noBalance, false, &_noBalance);
- ok &= FieldParser::extract(source, epoch, OID(), &_epoch);
- if (! ok) {
- clear();
- return;
- }
+ string dummy;
+ if (!errMsg) errMsg = &dummy;
+
+ if (!FieldParser::extract(source, ns, "", &_ns, errMsg)) return false;
+ if (!FieldParser::extract(source, primary, "", &_primary, errMsg)) return false;
+ if (!FieldParser::extract(source, keyPattern, BSONObj(), &_keyPattern, errMsg)) return false;
+ if (!FieldParser::extract(source, unique, false, &_unique, errMsg)) return false;
+ if (!FieldParser::extract(source, updatedAt, 0ULL, &_updatedAt, errMsg)) return false;
+ if (!FieldParser::extract(source, noBalance, false, &_noBalance, errMsg)) return false;
+ if (!FieldParser::extract(source, epoch, OID(), &_epoch, errMsg)) return false;
+ if (!FieldParser::extract(source, dropped, false, &_dropped, errMsg)) return false;
//
// backward compatibility
//
// 'createAt' used to be called 'lastmod' up to 2.2.
+
Date_t lastmod;
- if (! FieldParser::extract(source, DEPRECATED_lastmod, 0ULL, &lastmod)) {
- clear();
- return;
- }
- else if (lastmod != 0ULL) {
- _createdAt = lastmod;
- }
+ if (!FieldParser::extract(source, DEPRECATED_lastmod, 0ULL, &lastmod, errMsg)) return false;
- // There was a flag to mark a collection as loggically dropped, up to 2.2.
- bool dropped;
- if (! FieldParser::extract(source, DEPRECATED_dropped, false, &dropped) || dropped) {
- clear();
- return;
+ if (lastmod != 0ULL) {
+ _updatedAt = lastmod;
}
// 'lastmodEpoch' was a transition format to 'epoch', up to 2.2
OID lastmodEpoch;
- if (! FieldParser::extract(source, DEPRECATED_lastmodEpoch, OID(), &lastmodEpoch)) {
- clear();
- return;
- }
- else if (lastmodEpoch.isSet()) {
+ if (!FieldParser::extract(source, DEPRECATED_lastmodEpoch, OID(), &lastmodEpoch, errMsg)) return false;
+
+ if (lastmodEpoch.isSet()) {
_epoch = lastmodEpoch;
}
+
+ return true;
}
void CollectionType::clear() {
@@ -144,20 +140,22 @@ namespace mongo {
_primary.clear();
_keyPattern = BSONObj();
_unique = false;
- _createdAt = 0ULL;
+ _updatedAt = 0ULL;
_noBalance = false;
_epoch = OID();
+ _dropped = false;
}
- void CollectionType::cloneTo(CollectionType* other) {
+ void CollectionType::cloneTo(CollectionType* other) const {
other->clear();
other->_ns = _ns;
other->_primary = _primary;
other->_keyPattern = _keyPattern;
other->_unique = _unique;
- other->_createdAt = _createdAt;
+ other->_updatedAt = _updatedAt;
other->_noBalance = _noBalance;
other->_epoch = _epoch;
+ other->_dropped = _dropped;
}
std::string CollectionType::toString() const {
diff --git a/src/mongo/s/type_collection.h b/src/mongo/s/type_collection.h
index 3302d6c0d66..aac83375c5b 100644
--- a/src/mongo/s/type_collection.h
+++ b/src/mongo/s/type_collection.h
@@ -43,6 +43,10 @@ namespace mongo {
* if (! coll.isValid()) {
* // Can't use 'coll'. Take action.
* }
+ * if (coll.isDropped()) {
+ * // Coll doesn't exist, Take action.
+ * }
+ *
* // use 'coll'
*
*/
@@ -62,14 +66,15 @@ namespace mongo {
static BSONField<std::string> primary; // primary db when not sharded
static BSONField<BSONObj> keyPattern; // sharding key, if sharded
static BSONField<bool> unique; // sharding key unique?
- static BSONField<Date_t> createdAt; // when collection was created
+ static BSONField<Date_t> updatedAt; // when collection was created
static BSONField<bool> noBalance; // true if balancing is disabled
static BSONField<OID> epoch; // disambiguate ns (drop/recreate)
+ // To-be-deprecated, not yet
+ static BSONField<bool> dropped; // true if we should ignore this collection entry
// Deprecated fields should only be used in parseBSON calls. Exposed here for testing only.
static BSONField<OID> DEPRECATED_lastmodEpoch;
static BSONField<Date_t> DEPRECATED_lastmod;
- static BSONField<bool> DEPRECATED_dropped;
//
// collection type methods
@@ -93,7 +98,7 @@ namespace mongo {
* 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);
+ bool parseBSON(BSONObj source, std::string* errMsg);
/**
* Clears the internal state.
@@ -103,7 +108,7 @@ namespace mongo {
/**
* Copies all the fields present in 'this' to 'other'.
*/
- void cloneTo(CollectionType* other);
+ void cloneTo(CollectionType* other) const;
/**
* Returns a string representation of the current internal state.
@@ -124,10 +129,10 @@ namespace mongo {
BSONObj getKeyPattern() const { return _keyPattern; }
void setUnique(bool unique) { _unique = unique; }
- bool getUnique() const { return _unique; }
+ bool isUnique() const { return _unique; }
- void setCreatedAt(const Date_t& time) { _createdAt = time; }
- Date_t getCreatedAt() const { return _createdAt; }
+ void setUpdatedAt(const Date_t& time) { _updatedAt = time; }
+ Date_t getUpdatedAt() const { return _updatedAt; }
void setNoBalance(bool noBalance) { _noBalance = noBalance; }
bool getNoBalance() const { return _noBalance; }
@@ -135,16 +140,19 @@ namespace mongo {
void setEpoch(OID oid) { _epoch = oid; }
OID getEpoch() const { return _epoch; }
+ void setDropped(bool dropped) { _dropped = dropped; }
+ bool isDropped() const { return _dropped; }
+
private:
// Convention: (M)andatory, (O)ptional, (S)pecial rule.
std::string _ns; // (M) namespace
std::string _primary; // (S) either/or with _keyPattern
BSONObj _keyPattern; // (S) sharding pattern if sharded
bool _unique; // (S) mandatory if sharded, index is unique
- Date_t _createdAt; // (M) creation time
+ Date_t _updatedAt; // (M) last updated time
bool _noBalance; // (S) optional if sharded, disable balancing
OID _epoch; // (M) disambiguates collection incarnations
-
+ bool _dropped; // (O) if true, ignore this entry
};
} // namespace mongo
diff --git a/src/mongo/s/type_config_version.cpp b/src/mongo/s/type_config_version.cpp
new file mode 100644
index 00000000000..8fc69c45cf8
--- /dev/null
+++ b/src/mongo/s/type_config_version.cpp
@@ -0,0 +1,156 @@
+/**
+ * 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_config_version.h"
+
+#include "mongo/s/field_parser.h"
+#include "mongo/util/mongoutils/str.h"
+
+namespace mongo {
+
+ using mongoutils::str::stream;
+
+ const string VersionType::ConfigNS("config.version");
+
+ const BSONField<int> VersionType::minVersion("minVersion");
+ const BSONField<int> VersionType::maxVersion("maxVersion");
+ const BSONField<OID> VersionType::clusterId("clusterId");
+ const BSONField<int> VersionType::version_DEPRECATED("version");
+
+ VersionType::VersionType() {
+ clear();
+ }
+
+ VersionType::~VersionType() {
+ }
+
+ bool VersionType::isValid(string* errMsg) const {
+
+ std::string dummy;
+
+ if (errMsg == NULL) {
+ errMsg = &dummy;
+ }
+
+ if (_minVersion == -1) {
+ if (errMsg) {
+ *errMsg = stream() << "no version found";
+ }
+ return false;
+ }
+
+ // Hardcoded 3 here because it's the last version without a cluster id
+ if (_maxVersion > 3 && !_clusterId.isSet()) {
+ if (errMsg) {
+ *errMsg = stream() << "no clusterId found";
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ void VersionType::clear() {
+ _minVersion = -1;
+ _maxVersion = -1;
+ _clusterId = OID();
+ }
+
+ bool VersionType::parseBSON(const BSONObj& source, string* errMsg) {
+ clear();
+
+ string dummy;
+ if (!errMsg) errMsg = &dummy;
+
+ if (!FieldParser::extractNumber(source, minVersion, -1, &_minVersion, errMsg)) return false;
+
+ if (_minVersion == -1) {
+ if (!FieldParser::extractNumber(source, version_DEPRECATED, -1, &_minVersion, errMsg)) return false;
+ }
+
+ if (!FieldParser::extractNumber(source, maxVersion, -1, &_maxVersion, errMsg)) return false;
+
+ if (!FieldParser::extract(source, clusterId, OID(), &_clusterId, errMsg)) return false;
+
+ if (_maxVersion == -1) {
+ _maxVersion = _minVersion;
+ }
+
+ return true;
+ }
+
+ BSONObj VersionType::toBSON() const {
+ return BSON("_id" << 1
+ << version_DEPRECATED(_minVersion)
+ << minVersion(_minVersion)
+ << maxVersion(_maxVersion)
+ << clusterId(_clusterId));
+ }
+
+ string VersionType::toString() const {
+ return toBSON().toString();
+ }
+
+ OID VersionType::getClusterId() const {
+ return _clusterId;
+ }
+
+ void VersionType::setClusterId(const OID& clusterId) {
+ _clusterId = clusterId;
+ }
+
+ int VersionType::getMinCompatibleVersion() const {
+ return _minVersion;
+ }
+
+ void VersionType::setMinCompatibleVersion(int version) {
+ _minVersion = version;
+ }
+
+ int VersionType::getMaxCompatibleVersion() const {
+ return _maxVersion;
+ }
+
+ void VersionType::setMaxCompatibleVersion(int version) {
+ _maxVersion = version;
+ }
+
+ bool VersionType::isCompatibleVersion(int version) const {
+ return version >= _minVersion && version <= _maxVersion;
+ }
+
+ void VersionType::setDefaultVersion() {
+ _minVersion = 1;
+ _maxVersion = 1;
+ _clusterId = OID();
+ }
+
+ void VersionType::setEmptyVersion() {
+ _minVersion = 0;
+ _maxVersion = 0;
+ _clusterId = OID();
+ }
+
+ bool VersionType::isEmptyVersion() const {
+ return _minVersion == 0 && _maxVersion == 0 && _clusterId == OID();
+ }
+
+ bool VersionType::isEquivalentTo(const VersionType& other) const {
+ return _minVersion == other._minVersion && _maxVersion == other._maxVersion
+ && _clusterId == other._clusterId;
+ }
+
+} // namespace mongo
diff --git a/src/mongo/s/type_config_version.h b/src/mongo/s/type_config_version.h
new file mode 100644
index 00000000000..5fc5f40b642
--- /dev/null
+++ b/src/mongo/s/type_config_version.h
@@ -0,0 +1,128 @@
+/**
+ * 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 the single document contained in the
+ * config.version collection. All manipulation of this document should be done using this class.
+ *
+ * Usage Example:
+ *
+ * DBClientBase* conn;
+ * BSONObj query = QUERY();
+ * versionDoc = conn->findOne(VersionType::ConfigNS, query);
+ *
+ * // Process the response.
+ * VersionType versionInfo;
+ * if (!versionInfo.parseBSON(versionDoc)) {
+ * // Can't parse document, take action
+ * }
+ * if (!versionInfo.isValid()) {
+ * // Can't use version, take action.
+ * }
+ * // use 'versionInfo'
+ *
+ */
+ class VersionType {
+ MONGO_DISALLOW_COPYING(VersionType);
+ public:
+
+ // Name of the versions collection in the config schema
+ static const string ConfigNS;
+
+ // Field names and types of the version document
+ static const BSONField<int> minVersion;
+ static const BSONField<int> maxVersion;
+ static const BSONField<OID> clusterId;
+
+ // Transition to new format v2.2->v2.4
+ // We eventually will not use version, minVersion and maxVersion instead
+ static const BSONField<int> version_DEPRECATED;
+
+ VersionType();
+ ~VersionType();
+
+ /**
+ * 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.
+ */
+ bool parseBSON(const BSONObj& source, std::string* errMsg);
+
+ /**
+ * Clears the internal state.
+ */
+ void clear();
+
+ /**
+ * Returns a string representation of the current internal state.
+ */
+ std::string toString() const;
+
+ //
+ // individual field accessors and helpers
+ //
+
+ OID getClusterId() const;
+ void setClusterId(const OID& clusterId);
+
+ int getMinCompatibleVersion() const;
+ void setMinCompatibleVersion(int version);
+
+ int getMaxCompatibleVersion() const;
+ void setMaxCompatibleVersion(int version);
+
+ bool isCompatibleVersion(int version) const;
+
+ // If there is no version document but other config collections exist,
+ // this is the default version we use
+ void setDefaultVersion();
+
+ // If there is no data in the config server, this is the default version we use
+ void setEmptyVersion();
+
+ bool isEmptyVersion() const;
+
+ // Checks whether two versions are equivalent
+ bool isEquivalentTo(const VersionType& other) const;
+
+ private:
+
+ int _minVersion;
+ int _maxVersion;
+ OID _clusterId;
+ };
+
+} // namespace mongo
diff --git a/src/mongo/s/type_database.cpp b/src/mongo/s/type_database.cpp
index 8ed2a9762c1..060a40b3db1 100644
--- a/src/mongo/s/type_database.cpp
+++ b/src/mongo/s/type_database.cpp
@@ -102,7 +102,7 @@ namespace mongo {
_draining = false;
}
- void DatabaseType::cloneTo(DatabaseType* other) {
+ void DatabaseType::cloneTo(DatabaseType* other) const {
other->clear();
other->_name = _name;
other->_primary = _primary;
diff --git a/src/mongo/s/type_database.h b/src/mongo/s/type_database.h
index 37c98d05c01..6993fa1d42e 100644
--- a/src/mongo/s/type_database.h
+++ b/src/mongo/s/type_database.h
@@ -101,7 +101,7 @@ namespace mongo {
/**
* Copies all the fields present in 'this' to 'other'.
*/
- void cloneTo(DatabaseType* other);
+ void cloneTo(DatabaseType* other) const;
/**
* Returns a string representation of the current internal state.
diff --git a/src/mongo/s/type_shard.cpp b/src/mongo/s/type_shard.cpp
index 7313f44036c..66440f33dc2 100644
--- a/src/mongo/s/type_shard.cpp
+++ b/src/mongo/s/type_shard.cpp
@@ -39,10 +39,9 @@ namespace mongo {
}
bool ShardType::isValid(std::string* errMsg) const {
- std::string dummy;
- if (errMsg == NULL) {
- errMsg = &dummy;
- }
+
+ string dummy;
+ if (!errMsg) errMsg = &dummy;
// All the mandatory fields must be present.
if (_name.empty()) {
@@ -67,18 +66,19 @@ namespace mongo {
return builder.obj();
}
- void ShardType::parseBSON(BSONObj source) {
+ bool ShardType::parseBSON(BSONObj source, string* errMsg) {
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);
- ok &= FieldParser::extract(source, tags, BSONArray(), &_tags);
- if (! ok) {
- clear();
- }
+ string dummy;
+ if (!errMsg) errMsg = &dummy;
+
+ if (!FieldParser::extract(source, name, "", &_name, errMsg)) return false;
+ if (!FieldParser::extract(source, host, "", &_host, errMsg)) return false;
+ if (!FieldParser::extract(source, draining, false, &_draining, errMsg)) return false;
+ if (!FieldParser::extract(source, maxSize, 0LL, &_maxSize, errMsg)) return false;
+ if (!FieldParser::extract(source, tags, BSONArray(), &_tags, errMsg)) return false;
+
+ return true;
}
void ShardType::clear() {
@@ -89,7 +89,7 @@ namespace mongo {
_tags = BSONArray();
}
- void ShardType::cloneTo(ShardType* other) {
+ void ShardType::cloneTo(ShardType* other) const {
other->clear();
other->_name = _name;
other->_host = _host;
diff --git a/src/mongo/s/type_shard.h b/src/mongo/s/type_shard.h
index e705f1d3d42..60745f4553c 100644
--- a/src/mongo/s/type_shard.h
+++ b/src/mongo/s/type_shard.h
@@ -84,7 +84,7 @@ namespace mongo {
* 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);
+ bool parseBSON(BSONObj source, std::string* errMsg);
/**
* Clears the internal state.
@@ -94,7 +94,7 @@ namespace mongo {
/**
* Copies all the fields present in 'this' to 'other'.
*/
- void cloneTo(ShardType* other);
+ void cloneTo(ShardType* other) const;
/**
* Returns a string representation of the current internal state.