summaryrefslogtreecommitdiff
path: root/src/mongo/s/chunk_version.cpp
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2022-01-20 09:13:17 +0100
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-01-24 16:51:41 +0000
commit3bc48c6fd422822c849ad3c82b780122c64ec423 (patch)
tree79590a2d52fd8e01d8152dbbec3669bb1561d066 /src/mongo/s/chunk_version.cpp
parenta94feb562cd9ffb42c10770fbf5b5d489875cc2f (diff)
downloadmongo-3bc48c6fd422822c849ad3c82b780122c64ec423.tar.gz
SERVER-62783 Make parsing of new and legacy formats more explicit
Diffstat (limited to 'src/mongo/s/chunk_version.cpp')
-rw-r--r--src/mongo/s/chunk_version.cpp95
1 files changed, 57 insertions, 38 deletions
diff --git a/src/mongo/s/chunk_version.cpp b/src/mongo/s/chunk_version.cpp
index fd71e7270f8..0de0352f3b9 100644
--- a/src/mongo/s/chunk_version.cpp
+++ b/src/mongo/s/chunk_version.cpp
@@ -56,28 +56,26 @@ StatusWith<ChunkVersion> ChunkVersion::fromBSON(const BSONObj& obj) {
if (!it.more())
return {ErrorCodes::BadValue, "Unexpected empty version array"};
- ChunkVersion version;
-
- // Expect the major and minor versions
+ // Expect the major and minor versions (must be present)
+ uint64_t combined;
{
BSONElement tsPart = it.next();
if (tsPart.type() != bsonTimestamp)
return {ErrorCodes::TypeMismatch,
str::stream() << "Invalid type " << tsPart.type()
<< " for version major and minor part."};
-
- version._combined = tsPart.timestamp().asULL();
+ combined = tsPart.timestamp().asULL();
}
- // Expect the epoch OID
+ // Expect the epoch OID (must be present)
+ boost::optional<OID> epoch;
{
BSONElement epochPart = it.next();
if (epochPart.type() != jstOID)
return {ErrorCodes::TypeMismatch,
str::stream() << "Invalid type " << epochPart.type()
<< " for version epoch part."};
-
- version._epoch = epochPart.OID();
+ epoch = epochPart.OID();
}
BSONElement nextElem = it.next();
@@ -90,33 +88,37 @@ StatusWith<ChunkVersion> ChunkVersion::fromBSON(const BSONObj& obj) {
}
// Check for timestamp
+ boost::optional<Timestamp> timestamp;
if (nextElem.type() == bsonTimestamp) {
- version._timestamp = nextElem.timestamp();
- } else if (nextElem.eoo() && version.is50IgnoredOrUnsharded()) {
+ timestamp = nextElem.timestamp();
+ } else if (nextElem.eoo() && (epoch == UNSHARDED().epoch() || epoch == IGNORED().epoch())) {
// In 5.0 binaries, the timestamp is not present in UNSHARDED and IGNORED versions
- version._timestamp =
- (version.epoch() == UNSHARDED().epoch()) ? Timestamp() : Timestamp::max();
+ timestamp =
+ (epoch == UNSHARDED().epoch() ? UNSHARDED().getTimestamp() : IGNORED().getTimestamp());
} else {
return {ErrorCodes::TypeMismatch,
str::stream() << "Invalid type " << nextElem.type()
<< " for version timestamp part."};
}
+ ChunkVersion version;
+ version._combined = combined;
+ version._epoch = *epoch;
+ version._timestamp = *timestamp;
return version;
}
StatusWith<ChunkVersion> ChunkVersion::parseLegacyWithField(const BSONObj& obj, StringData field) {
- auto versionElem = obj[field];
- if (versionElem.eoo())
- return {ErrorCodes::NoSuchKey,
- str::stream() << "Expected field " << field << " not found."};
-
- ChunkVersion version;
-
- // Expect the major and minor
+ // Expect the major and minor (must always exist)
+ uint64_t combined;
{
+ auto versionElem = obj[field];
+ if (versionElem.eoo())
+ return {ErrorCodes::NoSuchKey,
+ str::stream() << "Expected field " << field << " not found."};
+
if (versionElem.type() == bsonTimestamp || versionElem.type() == Date) {
- version._combined = versionElem._numberLong();
+ combined = versionElem._numberLong();
} else {
return {ErrorCodes::TypeMismatch,
str::stream() << "Invalid type " << versionElem.type()
@@ -124,14 +126,16 @@ StatusWith<ChunkVersion> ChunkVersion::parseLegacyWithField(const BSONObj& obj,
}
}
- bool fullVersion = false;
// Expect the epoch OID
+ //
+ // TODO: Confirm whether the epoch can still be missing in upgrade chains that started from
+ // pre-2.4 versions anymore (after FCV 4.4 -> 5.0 upgrade) ?
+ boost::optional<OID> epoch;
{
const auto epochField = field + "Epoch";
auto epochElem = obj[epochField];
if (epochElem.type() == jstOID) {
- version._epoch = epochElem.OID();
- fullVersion = true;
+ epoch = epochElem.OID();
} else if (!epochElem.eoo()) {
return {ErrorCodes::TypeMismatch,
str::stream() << "Invalid type " << epochElem.type()
@@ -139,27 +143,42 @@ StatusWith<ChunkVersion> ChunkVersion::parseLegacyWithField(const BSONObj& obj,
}
}
- // Expect the timestamp
+ // Expect the timestamp (can be missing only in the case of pre-5.0 UNSHARDED and IGNORED
+ // versions)
+ boost::optional<Timestamp> timestamp;
{
const auto timestampField = field + "Timestamp";
auto timestampElem = obj[timestampField];
- if (fullVersion) {
- if (timestampElem.type() == bsonTimestamp) {
- version._timestamp = timestampElem.timestamp();
- } else if (timestampElem.eoo() && version.is50IgnoredOrUnsharded()) {
- // In 5.0 binaries, the timestamp is not present in UNSHARDED and IGNORED versions
- version._timestamp =
- (version.epoch() == UNSHARDED().epoch()) ? Timestamp() : Timestamp::max();
- } else {
- return {ErrorCodes::TypeMismatch,
- str::stream() << "Invalid type " << timestampElem.type()
- << " for version timestamp part."};
- }
+ if (timestampElem.type() == bsonTimestamp) {
+ timestamp = timestampElem.timestamp();
+ } else if (!timestampElem.eoo()) {
+ return {ErrorCodes::TypeMismatch,
+ str::stream() << "Invalid type " << timestampElem.type()
+ << " for version timestamp part."};
+ }
+ }
+
+ if (epoch && timestamp) {
+ // Expected situation
+ } else if (epoch && !timestamp) {
+ if (epoch == UNSHARDED().epoch() || epoch == IGNORED().epoch()) {
+ // In 5.0 binaries, the timestamp is not present in UNSHARDED and IGNORED versions
+ timestamp = (epoch == UNSHARDED().epoch() ? UNSHARDED().getTimestamp()
+ : IGNORED().getTimestamp());
} else {
- invariant(timestampElem.eoo());
+ uasserted(6278300, "Timestamp must be present if epoch exists.");
}
+ } else if (!epoch && timestamp) {
+ uasserted(6278301, "Epoch must be present if timestamp exists.");
+ } else {
+ // Can happen in upgrade chains that started from pre-2.4 versions or in the case of
+ // persistence for ShardCollectionType
}
+ ChunkVersion version;
+ version._combined = combined;
+ version._epoch = epoch.value_or(OID());
+ version._timestamp = timestamp.value_or(Timestamp());
return version;
}