summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/indexbg1.js
blob: ae26b4a0494ab3c2eefffb59174c455e0f875554 (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
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
126
127
128
129
130
131
132
133
// Test background index creation

(function() {
    "use strict";

    load("jstests/noPassthrough/libs/index_build.js");

    const conn = MongoRunner.runMongod({smallfiles: "", nojournal: ""});
    assert.neq(null, conn, "mongod failed to start.");
    var db = conn.getDB("test");
    var baseName = "jstests_indexbg1";

    var parallel = function() {
        return db[baseName + "_parallelStatus"];
    };

    var resetParallel = function() {
        parallel().drop();
    };

    // Return the PID to call `waitpid` on for clean shutdown.
    var doParallel = function(work) {
        resetParallel();
        print("doParallel: " + work);
        return startMongoProgramNoConnect(
            "mongo",
            "--eval",
            work + "; db." + baseName + "_parallelStatus.save( {done:1} );",
            db.getMongo().host);
    };

    var doneParallel = function() {
        return !!parallel().findOne();
    };

    var waitParallel = function() {
        assert.soon(function() {
            return doneParallel();
        }, "parallel did not finish in time", 300000, 1000);
    };

    var size = 400 * 1000;
    var bgIndexBuildPid;
    while (1) {  // if indexing finishes before we can run checks, try indexing w/ more data
        print("size: " + size);

        var fullName = "db." + baseName;
        var t = db[baseName];
        t.drop();

        var bulk = db.jstests_indexbg1.initializeUnorderedBulkOp();
        for (var i = 0; i < size; ++i) {
            bulk.insert({i: i});
        }
        assert.writeOK(bulk.execute());
        assert.eq(size, t.count());

        bgIndexBuildPid = doParallel(fullName + ".ensureIndex( {i:1}, {background:true} )");
        try {
            // wait for indexing to start
            print("wait for indexing to start");
            assert.soon(function() {
                return getIndexBuildOpId(db) != -1;
            }, "no index created", 30000, 50);
            print("started.");
            sleep(1000);  // there is a race between when the index build shows up in curop and
            // when it first attempts to grab a write lock.
            assert.eq(size, t.count());
            assert.eq(100, t.findOne({i: 100}).i);
            var q = t.find();
            for (i = 0; i < 120; ++i) {  // getmore
                q.next();
                assert(q.hasNext(), "no next");
            }
            var ex = t.find({i: 100}).limit(-1).explain("executionStats");
            printjson(ex);
            assert(ex.executionStats.totalKeysExamined < 1000,
                   "took too long to find 100: " + tojson(ex));

            assert.writeOK(t.remove({i: 40}, true));      // table scan
            assert.writeOK(t.update({i: 10}, {i: -10}));  // should scan 10

            var id = t.find().hint({$natural: -1}).next()._id;

            assert.writeOK(t.update({_id: id}, {i: -2}));
            assert.writeOK(t.save({i: -50}));
            assert.writeOK(t.save({i: size + 2}));

            assert.eq(size + 1, t.count());

            print("finished with checks");
        } catch (e) {
            // only a failure if we're still indexing
            // wait for parallel status to update to reflect indexing status
            print("caught exception: " + e);
            sleep(1000);
            if (!doneParallel()) {
                throw e;
            }
            print("but that's OK");
        }

        print("going to check if index is done");
        if (!doneParallel()) {
            break;
        }
        print("indexing finished too soon, retrying...");
        // Although the index build finished, ensure the shell has exited.
        waitProgram(bgIndexBuildPid);
        size *= 2;
        assert(size < 200000000, "unable to run checks in parallel with index creation");
    }

    print("our tests done, waiting for parallel to finish");
    waitParallel();
    // Ensure the shell has exited cleanly. Otherwise the test harness may send a SIGTERM which can
    // lead to a false test failure.
    waitProgram(bgIndexBuildPid);
    print("finished");

    assert.eq(1, t.count({i: -10}));
    assert.eq(1, t.count({i: -2}));
    assert.eq(1, t.count({i: -50}));
    assert.eq(1, t.count({i: size + 2}));
    assert.eq(0, t.count({i: 40}));
    print("about to drop index");
    t.dropIndex({i: 1});
    var gle = db.getLastError();
    printjson(gle);
    assert(!gle);

    MongoRunner.stopMongod(conn);
})();