summaryrefslogtreecommitdiff
path: root/src/mongo/s/chunk_diff.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/s/chunk_diff.cpp')
-rw-r--r--src/mongo/s/chunk_diff.cpp354
1 files changed, 173 insertions, 181 deletions
diff --git a/src/mongo/s/chunk_diff.cpp b/src/mongo/s/chunk_diff.cpp
index 488ea85728b..b270a54d9d3 100644
--- a/src/mongo/s/chunk_diff.cpp
+++ b/src/mongo/s/chunk_diff.cpp
@@ -42,223 +42,215 @@
namespace mongo {
- template <class ValType, class ShardType>
- ConfigDiffTracker<ValType, ShardType>::ConfigDiffTracker() {
- _ns.clear();
- _currMap = NULL;
- _maxVersion = NULL;
- _maxShardVersions = NULL;
- _validDiffs = 0;
- }
+template <class ValType, class ShardType>
+ConfigDiffTracker<ValType, ShardType>::ConfigDiffTracker() {
+ _ns.clear();
+ _currMap = NULL;
+ _maxVersion = NULL;
+ _maxShardVersions = NULL;
+ _validDiffs = 0;
+}
+
+template <class ValType, class ShardType>
+ConfigDiffTracker<ValType, ShardType>::~ConfigDiffTracker() = default;
+
+template <class ValType, class ShardType>
+void ConfigDiffTracker<ValType, ShardType>::attach(const std::string& ns,
+ RangeMap& currMap,
+ ChunkVersion& maxVersion,
+ MaxChunkVersionMap& maxShardVersions) {
+ _ns = ns;
+ _currMap = &currMap;
+ _maxVersion = &maxVersion;
+ _maxShardVersions = &maxShardVersions;
+ _validDiffs = 0;
+}
+
+template <class ValType, class ShardType>
+bool ConfigDiffTracker<ValType, ShardType>::isOverlapping(const BSONObj& min, const BSONObj& max) {
+ RangeOverlap overlap = overlappingRange(min, max);
+
+ return overlap.first != overlap.second;
+}
+
+template <class ValType, class ShardType>
+void ConfigDiffTracker<ValType, ShardType>::removeOverlapping(const BSONObj& min,
+ const BSONObj& max) {
+ _assertAttached();
- template <class ValType, class ShardType>
- ConfigDiffTracker<ValType, ShardType>::~ConfigDiffTracker() = default;
-
- template <class ValType, class ShardType>
- void ConfigDiffTracker<ValType, ShardType>::attach(const std::string& ns,
- RangeMap& currMap,
- ChunkVersion& maxVersion,
- MaxChunkVersionMap& maxShardVersions) {
- _ns = ns;
- _currMap = &currMap;
- _maxVersion = &maxVersion;
- _maxShardVersions = &maxShardVersions;
- _validDiffs = 0;
- }
+ RangeOverlap overlap = overlappingRange(min, max);
- template <class ValType, class ShardType>
- bool ConfigDiffTracker<ValType, ShardType>::isOverlapping(const BSONObj& min,
- const BSONObj& max) {
- RangeOverlap overlap = overlappingRange(min, max);
+ _currMap->erase(overlap.first, overlap.second);
+}
- return overlap.first != overlap.second;
- }
+template <class ValType, class ShardType>
+typename ConfigDiffTracker<ValType, ShardType>::RangeOverlap
+ConfigDiffTracker<ValType, ShardType>::overlappingRange(const BSONObj& min, const BSONObj& max) {
+ _assertAttached();
+
+ typename RangeMap::iterator low;
+ typename RangeMap::iterator high;
- template <class ValType, class ShardType>
- void ConfigDiffTracker<ValType, ShardType>::removeOverlapping(const BSONObj& min,
- const BSONObj& max) {
- _assertAttached();
+ if (isMinKeyIndexed()) {
+ // Returns the first chunk with a min key that is >= min - implies the
+ // previous chunk cannot overlap min
+ low = _currMap->lower_bound(min);
- RangeOverlap overlap = overlappingRange(min, max);
+ // Returns the first chunk with a min key that is >= max - implies the
+ // chunk does not overlap max
+ high = _currMap->lower_bound(max);
+ } else {
+ // Returns the first chunk with a max key that is > min - implies that
+ // the chunk overlaps min
+ low = _currMap->upper_bound(min);
- _currMap->erase(overlap.first, overlap.second);
+ // Returns the first chunk with a max key that is > max - implies that
+ // the next chunk cannot not overlap max
+ high = _currMap->upper_bound(max);
}
- template <class ValType, class ShardType>
- typename ConfigDiffTracker<ValType, ShardType>::RangeOverlap
- ConfigDiffTracker<ValType, ShardType>::overlappingRange(const BSONObj& min,
- const BSONObj& max) {
- _assertAttached();
+ return RangeOverlap(low, high);
+}
- typename RangeMap::iterator low;
- typename RangeMap::iterator high;
+template <class ValType, class ShardType>
+int ConfigDiffTracker<ValType, ShardType>::calculateConfigDiff(CatalogManager* catalogManager) {
+ _assertAttached();
- if (isMinKeyIndexed()) {
- // Returns the first chunk with a min key that is >= min - implies the
- // previous chunk cannot overlap min
- low = _currMap->lower_bound(min);
+ // Get the diff query required
+ Query diffQuery = configDiffQuery();
- // Returns the first chunk with a min key that is >= max - implies the
- // chunk does not overlap max
- high = _currMap->lower_bound(max);
- }
- else {
- // Returns the first chunk with a max key that is > min - implies that
- // the chunk overlaps min
- low = _currMap->upper_bound(min);
-
- // Returns the first chunk with a max key that is > max - implies that
- // the next chunk cannot not overlap max
- high = _currMap->upper_bound(max);
- }
+ try {
+ std::vector<ChunkType> chunks;
+ uassertStatusOK(catalogManager->getChunks(diffQuery, 0, &chunks));
- return RangeOverlap(low, high);
+ return calculateConfigDiff(chunks);
+ } catch (DBException& e) {
+ // Should only happen on connection errors
+ e.addContext(str::stream() << "could not calculate config difference for ns " << _ns);
+ throw;
}
+}
+
+template <class ValType, class ShardType>
+int ConfigDiffTracker<ValType, ShardType>::calculateConfigDiff(
+ const std::vector<ChunkType>& chunks) {
+ _assertAttached();
+
+ // Apply the chunk changes to the ranges and versions
+ //
+ // Overall idea here is to work in two steps :
+ // 1. For all the new chunks we find, increment the maximum version per-shard and
+ // per-collection, and remove any conflicting chunks from the ranges.
+ // 2. For all the new chunks we're interested in (all of them for mongos, just chunks on
+ // the shard for mongod) add them to the ranges.
- template<class ValType, class ShardType>
- int ConfigDiffTracker<ValType, ShardType>::calculateConfigDiff(
- CatalogManager* catalogManager) {
- _assertAttached();
+ std::vector<ChunkType> newTracked;
- // Get the diff query required
- Query diffQuery = configDiffQuery();
+ // Store epoch now so it doesn't change when we change max
+ OID currEpoch = _maxVersion->epoch();
- try {
- std::vector<ChunkType> chunks;
- uassertStatusOK(catalogManager->getChunks(diffQuery, 0, &chunks));
+ _validDiffs = 0;
- return calculateConfigDiff(chunks);
+ for (const ChunkType& chunk : chunks) {
+ ChunkVersion chunkVersion =
+ ChunkVersion::fromBSON(chunk.toBSON(), ChunkType::DEPRECATED_lastmod());
+
+ if (!chunkVersion.isSet() || !chunkVersion.hasEqualEpoch(currEpoch)) {
+ warning() << "got invalid chunk version " << chunkVersion << " in document "
+ << chunk.toString() << " when trying to load differing chunks at version "
+ << ChunkVersion(
+ _maxVersion->majorVersion(), _maxVersion->minorVersion(), currEpoch);
+
+ // Don't keep loading, since we know we'll be broken here
+ return -1;
}
- catch (DBException& e) {
- // Should only happen on connection errors
- e.addContext(str::stream() << "could not calculate config difference for ns " << _ns);
- throw;
+
+ _validDiffs++;
+
+ // Get max changed version and chunk version
+ if (chunkVersion > *_maxVersion) {
+ *_maxVersion = chunkVersion;
}
- }
- template<class ValType, class ShardType>
- int ConfigDiffTracker<ValType, ShardType>::calculateConfigDiff(
- const std::vector<ChunkType>& chunks) {
- _assertAttached();
+ // Chunk version changes
+ ShardType shard = shardFor(chunk.getShard());
- // Apply the chunk changes to the ranges and versions
- //
- // Overall idea here is to work in two steps :
- // 1. For all the new chunks we find, increment the maximum version per-shard and
- // per-collection, and remove any conflicting chunks from the ranges.
- // 2. For all the new chunks we're interested in (all of them for mongos, just chunks on
- // the shard for mongod) add them to the ranges.
-
- std::vector<ChunkType> newTracked;
-
- // Store epoch now so it doesn't change when we change max
- OID currEpoch = _maxVersion->epoch();
-
- _validDiffs = 0;
-
- for (const ChunkType& chunk : chunks) {
- ChunkVersion chunkVersion = ChunkVersion::fromBSON(chunk.toBSON(),
- ChunkType::DEPRECATED_lastmod());
-
- if (!chunkVersion.isSet() || !chunkVersion.hasEqualEpoch(currEpoch)) {
- warning() << "got invalid chunk version " << chunkVersion
- << " in document " << chunk.toString()
- << " when trying to load differing chunks at version "
- << ChunkVersion(_maxVersion->majorVersion(),
- _maxVersion->minorVersion(),
- currEpoch);
-
- // Don't keep loading, since we know we'll be broken here
- return -1;
- }
-
- _validDiffs++;
-
- // Get max changed version and chunk version
- if (chunkVersion > *_maxVersion) {
- *_maxVersion = chunkVersion;
- }
-
- // Chunk version changes
- ShardType shard = shardFor(chunk.getShard());
-
- typename MaxChunkVersionMap::const_iterator shardVersionIt = _maxShardVersions->find(shard);
- if (shardVersionIt == _maxShardVersions->end() ||
- shardVersionIt->second < chunkVersion) {
- (*_maxShardVersions)[shard] = chunkVersion;
- }
-
- // See if we need to remove any chunks we are currently tracking because of this
- // chunk's changes
- removeOverlapping(chunk.getMin(), chunk.getMax());
-
- // Figure out which of the new chunks we need to track
- // Important - we need to actually own this doc, in case the cursor decides to getMore
- // or unbuffer.
- if (isTracked(chunk)) {
- newTracked.push_back(chunk);
- }
+ typename MaxChunkVersionMap::const_iterator shardVersionIt = _maxShardVersions->find(shard);
+ if (shardVersionIt == _maxShardVersions->end() || shardVersionIt->second < chunkVersion) {
+ (*_maxShardVersions)[shard] = chunkVersion;
}
- LOG(3) << "found " << _validDiffs << " new chunks for collection " << _ns
- << " (tracking " << newTracked.size() << "), new version is " << *_maxVersion;
+ // See if we need to remove any chunks we are currently tracking because of this
+ // chunk's changes
+ removeOverlapping(chunk.getMin(), chunk.getMax());
- for (const ChunkType& chunk : newTracked) {
- // Invariant enforced by sharding - it's possible to read inconsistent state due to
- // getMore and yielding, so we want to detect it as early as possible.
- //
- // TODO: This checks for overlap, we also should check for holes here iff we're
- // tracking all chunks.
- if (isOverlapping(chunk.getMin(), chunk.getMax())) {
- return -1;
- }
+ // Figure out which of the new chunks we need to track
+ // Important - we need to actually own this doc, in case the cursor decides to getMore
+ // or unbuffer.
+ if (isTracked(chunk)) {
+ newTracked.push_back(chunk);
+ }
+ }
+
+ LOG(3) << "found " << _validDiffs << " new chunks for collection " << _ns << " (tracking "
+ << newTracked.size() << "), new version is " << *_maxVersion;
- _currMap->insert(rangeFor(chunk));
+ for (const ChunkType& chunk : newTracked) {
+ // Invariant enforced by sharding - it's possible to read inconsistent state due to
+ // getMore and yielding, so we want to detect it as early as possible.
+ //
+ // TODO: This checks for overlap, we also should check for holes here iff we're
+ // tracking all chunks.
+ if (isOverlapping(chunk.getMin(), chunk.getMax())) {
+ return -1;
}
- return _validDiffs;
+ _currMap->insert(rangeFor(chunk));
}
- template<class ValType, class ShardType>
- Query ConfigDiffTracker<ValType, ShardType>::configDiffQuery() const {
- _assertAttached();
+ return _validDiffs;
+}
- // Basic idea behind the query is to find all the chunks $gte the current max version.
- // Currently, any splits and merges will increment the current max version.
- BSONObjBuilder queryB;
- queryB.append(ChunkType::ns(), _ns);
+template <class ValType, class ShardType>
+Query ConfigDiffTracker<ValType, ShardType>::configDiffQuery() const {
+ _assertAttached();
- {
- BSONObjBuilder tsBuilder(queryB.subobjStart(ChunkType::DEPRECATED_lastmod()));
- tsBuilder.appendTimestamp("$gte", _maxVersion->toLong());
- tsBuilder.done();
- }
+ // Basic idea behind the query is to find all the chunks $gte the current max version.
+ // Currently, any splits and merges will increment the current max version.
+ BSONObjBuilder queryB;
+ queryB.append(ChunkType::ns(), _ns);
- // NOTE: IT IS IMPORTANT FOR CONSISTENCY THAT WE SORT BY ASC VERSION, IN ORDER TO HANDLE
- // CURSOR YIELDING BETWEEN CHUNKS BEING MIGRATED.
- //
- // This ensures that changes to chunk version (which will always be higher) will always
- // come *after* our current position in the chunk cursor.
+ {
+ BSONObjBuilder tsBuilder(queryB.subobjStart(ChunkType::DEPRECATED_lastmod()));
+ tsBuilder.appendTimestamp("$gte", _maxVersion->toLong());
+ tsBuilder.done();
+ }
- Query queryObj(queryB.obj());
- queryObj.sort(BSON("lastmod" << 1));
+ // NOTE: IT IS IMPORTANT FOR CONSISTENCY THAT WE SORT BY ASC VERSION, IN ORDER TO HANDLE
+ // CURSOR YIELDING BETWEEN CHUNKS BEING MIGRATED.
+ //
+ // This ensures that changes to chunk version (which will always be higher) will always
+ // come *after* our current position in the chunk cursor.
- LOG(2) << "major version query from " << *_maxVersion
- << " and over " << _maxShardVersions->size() << " shards is " << queryObj;
+ Query queryObj(queryB.obj());
+ queryObj.sort(BSON("lastmod" << 1));
- return queryObj;
- }
+ LOG(2) << "major version query from " << *_maxVersion << " and over "
+ << _maxShardVersions->size() << " shards is " << queryObj;
- template <class ValType, class ShardType>
- void ConfigDiffTracker<ValType, ShardType>::_assertAttached() const {
- invariant(_currMap);
- invariant(_maxVersion);
- invariant(_maxShardVersions);
- }
+ return queryObj;
+}
+
+template <class ValType, class ShardType>
+void ConfigDiffTracker<ValType, ShardType>::_assertAttached() const {
+ invariant(_currMap);
+ invariant(_maxVersion);
+ invariant(_maxShardVersions);
+}
- // Ensures that these instances of the template are compiled
- template class ConfigDiffTracker<BSONObj, std::string>;
- template class ConfigDiffTracker<std::shared_ptr<Chunk>, std::string>;
+// Ensures that these instances of the template are compiled
+template class ConfigDiffTracker<BSONObj, std::string>;
+template class ConfigDiffTracker<std::shared_ptr<Chunk>, std::string>;
-} // namespace mongo
+} // namespace mongo