summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/lock_free_read_unsharded_sharded_unsharded.js
blob: 02ac2b85ae20b8fd6db83f4bb0b514199042851e (plain)
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
/*
 * Tests a possible lock-free read scenario wherein the collection on a namespace goes from
 * unsharded (sent in the request to the shard) to sharded (which the lock-free state finds) to
 * dropped and recreated (which the subsequent shardVersion check finds) while the lock-free state
 * is being set up for a read. The lock-free state must ensure consistency with the sharding state.
 * In such a case, the lock-free read state setup should be retried internally until consistent.
 *
 * @tags: [
 *   requires_sharding,
 * ]
 */

(function() {
"use strict";

load("jstests/libs/fail_point_util.js");         // configureFailPoint
load("jstests/libs/parallel_shell_helpers.js");  // startParallelShell

const st = new ShardingTest({mongos: 1, config: 1, shards: 1, rs: {nodes: 1}});

// This logical session ID is used to identify the particular find command for the failpoints.
const lsid = ({id: UUID()});

const hangBeforeAutoGetCollectionLockFreeShardedStateAccessFp =
    configureFailPoint(st.shard0.rs.nodes[0],
                       "hangBeforeAutoGetCollectionLockFreeShardedStateAccess",
                       {lsid: lsid.id});

const reachedAutoGetLockFreeShardConsistencyRetryFp = configureFailPoint(
    st.shard0.rs.nodes[0], "reachedAutoGetLockFreeShardConsistencyRetry", {lsid: lsid.id});

const hangBeforeAutoGetShardVersionCheckFp = configureFailPoint(
    st.shard0.rs.nodes[0], "hangBeforeAutoGetShardVersionCheck", {lsid: lsid.id});

const dbName = "test";
const collName = "lock_free_read_unsharded_sharded_unsharded";
const collection = st.s.getCollection(`${dbName}.${collName}`);

assert.commandWorked(st.s.adminCommand({enableSharding: dbName}));
assert.commandWorked(collection.runCommand("create"));

// Establish state on the mongos for the new collection as unsharded.
collection.find().toArray();

// Start a new read routed through the mongos that will send an UNSHARDED version with the request
// to the mongod.
const awaitFind = startParallelShell(
    funWithArgs(function(lsid, ns) {
        const mongos = db.getMongo();
        assert.commandWorked(mongos.getCollection(ns).runCommand("find", {lsid}));
    }, lsid, collection.getFullName()), st.s.port);

// Pause the operation right before lock-free read setup checks whether or not the collection is
// sharded.
hangBeforeAutoGetCollectionLockFreeShardedStateAccessFp.wait();

// Shard the collection so the lock-free read setup will find the collection sharded.
assert.commandWorked(st.s.adminCommand({shardCollection: collection.getFullName(), key: {_id: 1}}));

// Unpause the lock-free state to find a sharded collection, then wait for it to pause before the SV
// check.
hangBeforeAutoGetCollectionLockFreeShardedStateAccessFp.off();
hangBeforeAutoGetShardVersionCheckFp.wait();

// Drop the sharded collection and recreate a collection on the same namespace that's unsharded.
assert.commandWorked(collection.runCommand("drop"));
assert.commandWorked(collection.runCommand("create"));

// Release the lock-free read.
hangBeforeAutoGetShardVersionCheckFp.off();

// Make sure we reach the point in the code where the inconsistency is detected, before proceeding
reachedAutoGetLockFreeShardConsistencyRetryFp.wait();
reachedAutoGetLockFreeShardConsistencyRetryFp.off();

awaitFind();

st.stop();
})();