diff options
author | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2016-01-20 16:10:10 -0500 |
---|---|---|
committer | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2016-01-21 11:57:37 -0500 |
commit | cdbcef1a5f509a0677b0bdc6a74be1c82d39b9e2 (patch) | |
tree | 63eba7663d57079a24dde87124213bedf2f79eb0 | |
parent | 35d64612e0e5398611e967c6003c29dee67c1ff6 (diff) | |
download | mongo-cdbcef1a5f509a0677b0bdc6a74be1c82d39b9e2.tar.gz |
SERVER-22247 Do not fail when parsing pre-2.2 sharding collection metadata
-rw-r--r-- | src/mongo/s/catalog/type_chunk.cpp | 1 | ||||
-rw-r--r-- | src/mongo/s/catalog/type_chunk.h | 1 | ||||
-rw-r--r-- | src/mongo/s/catalog/type_chunk_test.cpp | 20 | ||||
-rw-r--r-- | src/mongo/s/catalog/type_collection.cpp | 19 | ||||
-rw-r--r-- | src/mongo/s/catalog/type_collection.h | 3 | ||||
-rw-r--r-- | src/mongo/s/catalog/type_collection_test.cpp | 40 |
6 files changed, 71 insertions, 13 deletions
diff --git a/src/mongo/s/catalog/type_chunk.cpp b/src/mongo/s/catalog/type_chunk.cpp index f59bf0ea7a0..aea8197acb5 100644 --- a/src/mongo/s/catalog/type_chunk.cpp +++ b/src/mongo/s/catalog/type_chunk.cpp @@ -52,7 +52,6 @@ const BSONField<bool> ChunkType::jumbo("jumbo"); const BSONField<Date_t> ChunkType::DEPRECATED_lastmod("lastmod"); const BSONField<OID> ChunkType::DEPRECATED_epoch("lastmodEpoch"); - StatusWith<ChunkType> ChunkType::fromBSON(const BSONObj& source) { ChunkType chunk; diff --git a/src/mongo/s/catalog/type_chunk.h b/src/mongo/s/catalog/type_chunk.h index 739d652ce98..7690d141917 100644 --- a/src/mongo/s/catalog/type_chunk.h +++ b/src/mongo/s/catalog/type_chunk.h @@ -61,7 +61,6 @@ public: static const BSONField<Date_t> DEPRECATED_lastmod; static const BSONField<OID> DEPRECATED_epoch; - /** * Constructs a new ChunkType object from BSON. * Also does validation of the contents. diff --git a/src/mongo/s/catalog/type_chunk_test.cpp b/src/mongo/s/catalog/type_chunk_test.cpp index 8806bafefac..a971de3bf22 100644 --- a/src/mongo/s/catalog/type_chunk_test.cpp +++ b/src/mongo/s/catalog/type_chunk_test.cpp @@ -40,6 +40,7 @@ namespace { using namespace mongo; using std::string; +using unittest::assertGet; TEST(ChunkType, MissingRequiredFields) { ChunkVersion chunkVersion(1, 2, OID::gen()); @@ -133,6 +134,25 @@ TEST(ChunkType, CorrectContents) { ASSERT_OK(chunk.validate()); } +TEST(ChunkType, Pre22Format) { + ChunkType chunk = assertGet( + ChunkType::fromBSON(BSON("_id" + << "test.mycol-a_MinKey" + << "lastmod" << Date_t::fromMillisSinceEpoch(1) << "ns" + << "test.mycol" + << "min" << BSON("a" << 10) << "max" << BSON("a" << 20) << "shard" + << "shard0001"))); + + ASSERT_OK(chunk.validate()); + ASSERT_EQUALS(chunk.getName(), "test.mycol-a_MinKey"); + ASSERT_EQUALS(chunk.getNS(), "test.mycol"); + ASSERT_EQUALS(chunk.getMin(), BSON("a" << 10)); + ASSERT_EQUALS(chunk.getMax(), BSON("a" << 20)); + ASSERT_EQUALS(chunk.getVersion().toLong(), 1); + ASSERT(!chunk.getVersion().epoch().isSet()); + ASSERT_EQUALS(chunk.getShard(), "shard0001"); +} + TEST(ChunkType, BadType) { BSONObj obj = BSON(ChunkType::name() << 0); StatusWith<ChunkType> chunkRes = ChunkType::fromBSON(obj); diff --git a/src/mongo/s/catalog/type_collection.cpp b/src/mongo/s/catalog/type_collection.cpp index 1d466314edb..87454e182a0 100644 --- a/src/mongo/s/catalog/type_collection.cpp +++ b/src/mongo/s/catalog/type_collection.cpp @@ -37,6 +37,12 @@ #include "mongo/util/assert_util.h" namespace mongo { +namespace { + +const BSONField<bool> kNoBalance("noBalance"); +const BSONField<bool> kDropped("dropped"); + +} // namespace const std::string CollectionType::ConfigNS = "config.collections"; @@ -45,9 +51,6 @@ const BSONField<OID> CollectionType::epoch("lastmodEpoch"); const BSONField<Date_t> CollectionType::updatedAt("lastmod"); const BSONField<BSONObj> CollectionType::keyPattern("key"); const BSONField<bool> CollectionType::unique("unique"); -const BSONField<bool> CollectionType::noBalance("noBalance"); -const BSONField<bool> CollectionType::dropped("dropped"); - StatusWith<CollectionType> CollectionType::fromBSON(const BSONObj& source) { CollectionType coll; @@ -63,7 +66,7 @@ StatusWith<CollectionType> CollectionType::fromBSON(const BSONObj& source) { { OID collEpoch; - Status status = bsonExtractOIDField(source, epoch.name(), &collEpoch); + Status status = bsonExtractOIDFieldWithDefault(source, epoch.name(), OID(), &collEpoch); if (!status.isOK()) return status; @@ -81,7 +84,7 @@ StatusWith<CollectionType> CollectionType::fromBSON(const BSONObj& source) { { bool collDropped; - Status status = bsonExtractBooleanField(source, dropped.name(), &collDropped); + Status status = bsonExtractBooleanField(source, kDropped.name(), &collDropped); if (status.isOK()) { coll._dropped = collDropped; } else if (status == ErrorCodes::NoSuchKey) { @@ -122,7 +125,7 @@ StatusWith<CollectionType> CollectionType::fromBSON(const BSONObj& source) { { bool collNoBalance; - Status status = bsonExtractBooleanField(source, noBalance.name(), &collNoBalance); + Status status = bsonExtractBooleanField(source, kNoBalance.name(), &collNoBalance); if (status.isOK()) { coll._allowBalance = !collNoBalance; } else if (status == ErrorCodes::NoSuchKey) { @@ -180,7 +183,7 @@ BSONObj CollectionType::toBSON() const { } builder.append(epoch.name(), _epoch.get_value_or(OID())); builder.append(updatedAt.name(), _updatedAt.get_value_or(Date_t())); - builder.append(dropped.name(), _dropped.get_value_or(false)); + builder.append(kDropped.name(), _dropped.get_value_or(false)); // These fields are optional, so do not include them in the metadata for the purposes of // consuming less space on the config servers. @@ -194,7 +197,7 @@ BSONObj CollectionType::toBSON() const { } if (_allowBalance.is_initialized()) { - builder.append(noBalance.name(), !_allowBalance.get()); + builder.append(kNoBalance.name(), !_allowBalance.get()); } return builder.obj(); diff --git a/src/mongo/s/catalog/type_collection.h b/src/mongo/s/catalog/type_collection.h index 545c949e81e..062b65a7717 100644 --- a/src/mongo/s/catalog/type_collection.h +++ b/src/mongo/s/catalog/type_collection.h @@ -57,9 +57,6 @@ public: static const BSONField<Date_t> updatedAt; static const BSONField<BSONObj> keyPattern; static const BSONField<bool> unique; - static const BSONField<bool> noBalance; - static const BSONField<bool> dropped; - /** * Constructs a new DatabaseType object from BSON. Also does validation of the contents. diff --git a/src/mongo/s/catalog/type_collection_test.cpp b/src/mongo/s/catalog/type_collection_test.cpp index 9d3d3553ef7..893f3e6cb56 100644 --- a/src/mongo/s/catalog/type_collection_test.cpp +++ b/src/mongo/s/catalog/type_collection_test.cpp @@ -38,6 +38,7 @@ namespace { using namespace mongo; +using unittest::assertGet; TEST(CollectionType, Empty) { StatusWith<CollectionType> status = CollectionType::fromBSON(BSONObj()); @@ -63,6 +64,45 @@ TEST(CollectionType, Basic) { ASSERT_EQUALS(coll.getDropped(), false); } +TEST(CollectionType, EpochCorrectness) { + CollectionType coll; + coll.setNs(NamespaceString{"db.coll"}); + coll.setUpdatedAt(Date_t::fromMillisSinceEpoch(1)); + coll.setKeyPattern(KeyPattern{BSON("a" << 1)}); + coll.setUnique(false); + coll.setDropped(false); + + // Validation will fail because we don't have epoch set. This ensures that if we read a + // collection with no epoch, we will write back one with epoch. + ASSERT_NOT_OK(coll.validate()); + + // We should be allowed to set empty epoch for dropped collections + coll.setDropped(true); + coll.setEpoch(OID()); + ASSERT_OK(coll.validate()); + + // We should be allowed to set normal epoch for non-dropped collections + coll.setDropped(false); + coll.setEpoch(OID::gen()); + ASSERT_OK(coll.validate()); +} + +TEST(CollectionType, Pre22Format) { + CollectionType coll = assertGet( + CollectionType::fromBSON(BSON("_id" + << "db.coll" + << "lastmod" << Date_t::fromMillisSinceEpoch(1) << "dropped" + << false << "key" << BSON("a" << 1) << "unique" << false))); + + ASSERT(coll.getNs() == NamespaceString{"db.coll"}); + ASSERT(!coll.getEpoch().isSet()); + ASSERT_EQUALS(coll.getUpdatedAt(), Date_t::fromMillisSinceEpoch(1)); + ASSERT_EQUALS(coll.getKeyPattern().toBSON(), BSON("a" << 1)); + ASSERT_EQUALS(coll.getUnique(), false); + ASSERT_EQUALS(coll.getAllowBalance(), true); + ASSERT_EQUALS(coll.getDropped(), false); +} + TEST(CollectionType, InvalidCollectionNamespace) { const OID oid = OID::gen(); StatusWith<CollectionType> result = CollectionType::fromBSON(BSON( |