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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
// Runner for validateCollections that runs full validation on all collections when loaded into
// the mongo shell.
'use strict';
(function() {
assert.eq(typeof db, 'object', 'Invalid `db` object, is the shell connected to a mongod?');
load('jstests/libs/parallelTester.js');
function getDirectConnections(conn) {
// If conn does not point to a repl set, then this function returns [conn].
const res = conn.adminCommand({isMaster: 1});
const connections = [];
if (res.hasOwnProperty('setName')) {
for (let hostString of res.hosts) {
connections.push(new Mongo(hostString));
}
if (res.hasOwnProperty('passives')) {
for (let hostString of res.passives) {
connections.push(new Mongo(hostString));
}
}
} else {
connections.push(conn);
}
return connections;
}
function getConfigConnStr() {
const shardMap = db.adminCommand({getShardMap: 1});
if (!shardMap.hasOwnProperty('map')) {
throw new Error('Expected getShardMap() to return an object a "map" field: ' +
tojson(shardMap));
}
const map = shardMap.map;
if (!map.hasOwnProperty('config')) {
throw new Error('Expected getShardMap().map to have a "config" field: ' + tojson(map));
}
return map.config;
}
function isMongos() {
return db.isMaster().msg === 'isdbgrid';
}
function getServerList() {
const serverList = [];
if (isMongos()) {
// We're connected to a sharded cluster through a mongos.
// 1) Add all the config servers to the server list.
const configConnStr = getConfigConnStr();
const configServerReplSetConn = new Mongo(configConnStr);
serverList.push(...getDirectConnections(configServerReplSetConn));
// 2) Add shard members to the server list.
const configDB = db.getSiblingDB('config');
const cursor = configDB.shards.find();
while (cursor.hasNext()) {
const shard = cursor.next();
const shardReplSetConn = new Mongo(shard.host);
serverList.push(...getDirectConnections(shardReplSetConn));
}
} else {
// We're connected to a mongod.
serverList.push(...getDirectConnections(db.getMongo()));
}
return serverList;
}
// Run a separate thread to validate collections on each server in parallel.
var validateCollectionsThread = function(host, testData) {
load('jstests/hooks/validate_collections.js'); // For validateCollections.
TestData = testData; // Pass the TestData object from main thread.
try {
print('Running validate() on ' + host);
const conn = new Mongo(host);
conn.setSlaveOk();
jsTest.authenticate(conn);
const dbNames = conn.getDBNames();
for (let dbName of dbNames) {
if (!validateCollections(conn.getDB(dbName), {full: true})) {
return {ok: 0};
}
}
return {ok: 1};
} catch (e) {
print('Exception caught in scoped thread running validationCollections on server: ' +
host);
return {ok: 0, error: e.toString(), stack: e.stack};
}
};
// We run the scoped threads in a try/finally block in case any thread throws an exception, in
// which case we want to still join all the threads.
let threads = [];
const serverList = getServerList();
try {
serverList.forEach(server => {
const thread = new ScopedThread(validateCollectionsThread, server.host, TestData);
threads.push(thread);
thread.start();
});
} finally {
// Wait for each thread to finish. Throw an error if any thread fails.
const returnData = threads.map(thread => {
thread.join();
return thread.returnData();
});
returnData.forEach(res => {
assert.commandWorked(res, 'Collection validation failed');
});
}
})();
|