summaryrefslogtreecommitdiff
path: root/jstests/core/capped6.js
blob: c9d8867c3f07d92e3c939c8d23abeff1dc8b03f7 (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
// Test NamespaceDetails::cappedTruncateAfter via "captrunc" command
//
// @tags: [
//   # This test attempts to perform read operations on a capped collection after truncating
//   # documents using the captrunc command. The former operations may be routed to a secondary in
//   # the replica set, whereas the latter must be routed to the primary.
//   assumes_read_preference_unchanged,
//   requires_capped,
//   requires_fastcount,
//   requires_non_retryable_commands,
//   uses_testing_only_commands,
// ]
(function() {
var coll = db.capped6;

Random.setRandomSeed();
var maxDocuments = Random.randInt(400) + 100;

/**
 * Check that documents in the collection are in order according to the value
 * of a, which corresponds to the insert order.  This is a check that the oldest
 * document(s) is/are deleted when space is needed for the newest document.  The
 * check is performed in both forward and reverse directions.
 */
function checkOrder(i, valueArray) {
    res = coll.find().sort({$natural: -1});
    assert(res.hasNext(), "A");
    var j = i;
    while (res.hasNext()) {
        assert.eq(valueArray[j--].a, res.next().a, "B");
    }

    res = coll.find().sort({$natural: 1});
    assert(res.hasNext(), "C");
    while (res.hasNext()) {
        assert.eq(valueArray[++j].a, res.next().a, "D");
    }
    assert.eq(j, i, "E");
}

/*
 * Prepare the values to insert and create the capped collection.
 */
function prepareCollection(shouldReverse) {
    coll.drop();
    assert.commandWorked(db.createCollection("capped6", {capped: true, size: 1000}));
    var valueArray = new Array(maxDocuments);
    var c = "";
    for (i = 0; i < maxDocuments; ++i, c += "-") {
        // The a values are strings of increasing length.
        valueArray[i] = {a: c};
    }
    if (shouldReverse) {
        valueArray.reverse();
    }
    return valueArray;
}

/**
 * 1. When this function is called the first time, insert new documents until 'maxDocuments'
 *    number of documents have been inserted. Note that the collection may not have
 *    'maxDocuments' number of documents since it is a capped collection.
 * 2. Remove all but one documents via one or more "captrunc" requests.
 * 3. For each subsequent call to this function, keep track of the removed documents using
 *    'valueArrayIndexes' and re-insert the removed documents each time this function is
 *    called.
 */
function runCapTrunc(valueArray, valueArrayCurIndex, n, inc) {
    // If n <= 0, no documents are removed by captrunc.
    assert.gt(n, 0);
    assert.gte(valueArray.length, maxDocuments);
    for (var i = valueArrayCurIndex; i < maxDocuments; ++i) {
        assert.commandWorked(coll.insert(valueArray[i]));
    }
    count = coll.count();

    // The index corresponding to the last document in the collection.
    valueArrayCurIndex = maxDocuments - 1;

    // Number of times to call "captrunc" so that (count - 1) documents are removed
    // and at least 1 document is left in the array.
    var iterations = Math.floor((count - 1) / (n + inc));

    for (i = 0; i < iterations; ++i) {
        assert.commandWorked(db.runCommand({captrunc: "capped6", n: n, inc: inc}));
        count -= (n + inc);
        valueArrayCurIndex -= (n + inc);
        checkOrder(valueArrayCurIndex, valueArray);
    }
    // We return the index of the next document that should be inserted into the capped
    // collection, which would be the document after valueArrayCurIndex.
    return valueArrayCurIndex + 1;
}

function doTest(shouldReverse) {
    var valueArray = prepareCollection(shouldReverse);
    var valueArrayIndex = 0;
    valueArrayIndex = runCapTrunc(valueArray, valueArrayIndex, 1, false);
    valueArrayIndex = runCapTrunc(valueArray, valueArrayIndex, 1, true);
    valueArrayIndex = runCapTrunc(valueArray, valueArrayIndex, 16, true);
    valueArrayIndex = runCapTrunc(valueArray, valueArrayIndex, 16, false);
    valueArrayIndex = runCapTrunc(valueArray, valueArrayIndex, maxDocuments - 2, true);
    valueArrayIndex = runCapTrunc(valueArray, valueArrayIndex, maxDocuments - 2, false);
}

// Repeatedly add up to 'maxDocuments' documents and then truncate the newest
// documents.  Newer documents take up more space than older documents.
doTest(false);

// Same test as above, but now the newer documents take less space than the
// older documents instead of more.
doTest(true);
})();