1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
'use strict';
var CheckShardFilteringMetadataHelpers = (function() {
function run(mongosConn, nodeConn, shardId, skipCheckShardedCollections = false) {
function checkDatabase(configDatabasesEntry) {
const dbName = configDatabasesEntry._id;
print(`CheckShardFilteringMetadata: checking database '${dbName}' on node '${
nodeConn.host}' of shard '${shardId}'`);
const nodeMetadata =
assert.commandWorked(nodeConn.adminCommand({getDatabaseVersion: dbName}));
if (nodeMetadata.dbVersion.timestamp === undefined) {
// Shards are allowed to not know the dbVersion.
return;
}
assert.eq(nodeMetadata.dbVersion.uuid,
configDatabasesEntry.version.uuid,
`Unexpected dbVersion.uuid for db '${dbName}' on node '${nodeConn.host}'`);
assert.eq(timestampCmp(nodeMetadata.dbVersion.timestamp,
configDatabasesEntry.version.timestamp),
0,
`Unexpected dbVersion timestamp for db '${dbName}' on node '${
nodeConn.host}'. Found '${
tojson(nodeMetadata.dbVersion.timestamp)}'; expected '${
tojson(configDatabasesEntry.version.timestamp)}'`);
assert.eq(nodeMetadata.dbVersion.lastMod,
configDatabasesEntry.version.lastMod,
`Unexpected dbVersion lastMod for db '${dbName}' on node '${nodeConn.host}'`);
print(`CheckShardFilteringMetadata: Database '${dbName}' on '${nodeConn.host}' OK`);
}
function checkShardedCollection(coll, nodeShardingState) {
const ns = coll._id;
print(`CheckShardFilteringMetadata: checking collection '${ns} ' on node '${
nodeConn.host}' of shard '${shardId}'`);
const configDB = mongosConn.getDB('config');
const highestChunkOnShard = configDB.chunks.find({uuid: coll.uuid, shard: shardId})
.sort({lastmod: -1})
.limit(1)
.toArray()[0];
const expectedShardVersion =
highestChunkOnShard ? highestChunkOnShard.lastmod : Timestamp(0, 0);
const expectedTimestamp = coll.timestamp;
const collectionMetadataOnNode = nodeShardingState.versions[ns];
if (collectionMetadataOnNode === undefined) {
// Shards are not authoritative. It is okay that they don't know their filtering
// info.
return;
}
if (collectionMetadataOnNode.timestamp === undefined) {
// Versions earlier than v6.3 did not report the timestamp on shardingState command
// (SERVER-70790). This early exit can be removed after v6.0 is no longer tested in
// multiversion suites.
return;
}
if (timestampCmp(collectionMetadataOnNode.timestamp, Timestamp(0, 0)) === 0) {
// The metadata reflects an unsharded collection. It is okay for a node to have this
// stale metadata, as long as the node knows the correct dbVersion.
return;
}
// If the node knows its filtering info, then assert that it is correct.
assert.eq(timestampCmp(collectionMetadataOnNode.timestamp, expectedTimestamp),
0,
`Unexpected timestamp for ns '${ns}' on node '${nodeConn.host}'. Found '${
tojson(collectionMetadataOnNode.timestamp)}', expected '${
tojson(expectedTimestamp)}'`);
// Only check the major version because some operations (such as resharding or
// setAllowMigrations) bump the minor version without the shards knowing. This does not
// affect placement, so it is okay.
assert.eq(collectionMetadataOnNode.placementVersion.t,
expectedShardVersion.t,
`Unexpected shardVersion for ns '${ns}' on node '${nodeConn.host}'`);
print(`CheckShardFilteringMetadata: ns '${ns}' on '${nodeConn.host}' OK`);
}
const configDB = mongosConn.getDB('config');
// Check shards know correct database versions.
// Note: We can only check the dbVersion on the primary shards because non-primary shards
// can have stale dbVersions cached (for versions on which they were not primary.). TODO:
// Once shards became authoritative for their dbVersions, we can check all shards.
configDB.databases.find({primary: shardId}).forEach(configDatabasesEntry => {
checkDatabase(configDatabasesEntry);
});
// Check that shards have correct filtering metadata for sharded collections.
if (!skipCheckShardedCollections) {
const nodeShardingState = nodeConn.adminCommand({shardingState: 1});
configDB.collections.find().forEach(coll => {
checkShardedCollection(coll, nodeShardingState);
});
}
print("CheckShardFilteringMetadata: finished");
}
return {
run: run,
};
})();
|