summaryrefslogtreecommitdiff
path: root/jstests/replsets/drop_collections_two_phase_long_index_names.js
blob: 46745a27427bf309e730c0ee78f19f64e2e55d2d (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
/**
 * Test to ensure that indexes with long names are handled gracefully during a two phase collection
 * drop rename. If a rename would violate length constraints on MMAPv1, the offending indexes should
 * be physically dropped immediately.
 */

(function() {
    'use strict';

    load("jstests/replsets/libs/two_phase_drops.js");  // For TwoPhaseDropCollectionTest.

    // Return a list of all indexes for a given collection. Use 'args' as the
    // 'listIndexes' command arguments.
    function listIndexes(database, coll, args) {
        args = args || {};
        let failMsg = "'listIndexes' command failed";
        let listIndexesCmd = {listIndexes: coll};
        let res = assert.commandWorked(database.runCommand(listIndexesCmd, args), failMsg);
        return res.cursor.firstBatch;
    }

    // Set up a two phase drop test.
    let testName = "drop_collection_two_phase_long_index_names";
    let dbName = testName;
    let collName = "collToDrop";
    let twoPhaseDropTest = new TwoPhaseDropCollectionTest(testName, dbName);

    // Initialize replica set.
    let replTest = twoPhaseDropTest.initReplSet();

    // Create the collection that will be dropped.
    twoPhaseDropTest.createCollection(collName);

    // Two phase collection drops should handle long index names gracefully. MMAPv1 imposes a hard
    // limit on index namespaces so we have to drop indexes that are too long to store on disk after
    // renaming the collection (see SERVER-29747). Other storage engines should allow the implicit
    // index renames to proceed because these renamed indexes are internal and will not be visible
    // to users (no risk of being exported to another storage engine).
    let coll = replTest.getPrimary().getDB(dbName).getCollection(collName);
    let maxNsLength = 127;
    let longIndexName = ''.pad(maxNsLength - (coll.getFullName() + '.$').length, true, 'a');
    let shortIndexName = "short_name";

    // Create one index with a "too long" name, and one with a name of acceptable size.
    assert.commandWorked(coll.ensureIndex({a: 1}, {name: longIndexName}));
    assert.commandWorked(coll.ensureIndex({b: 1}, {name: shortIndexName}));

    let droppedCollName = twoPhaseDropTest.prepareDropCollection(collName);

    // Check that indexes that would violate the namespace length constraints after rename were
    // dropped.
    const primary = replTest.getPrimary();
    let primaryDB = primary.getDB(dbName);
    let indexes = listIndexes(primaryDB, droppedCollName);
    assert(indexes.find(idx => idx.name === shortIndexName));
    assert.eq(undefined, indexes.find(idx => idx.name === longIndexName));

    // Check that index drop appears before collection drop in the oplog.
    const oplogColl = primary.getCollection('local.oplog.rs');
    const cmdNs = primaryDB.getCollection('$cmd').getFullName();
    const dropOplogEntry = oplogColl.findOne({ns: cmdNs, o: {drop: collName}});
    const dropIndexOplogEntry =
        oplogColl.findOne({ns: cmdNs, o: {dropIndexes: collName, index: longIndexName}});
    const dropTimestamp = dropOplogEntry.ts;
    const dropIndexTimestamp = dropIndexOplogEntry.ts;
    assert.lt(dropIndexTimestamp,
              dropTimestamp,
              'index was not dropped before collection. index drop: ' +
                  tojson(dropIndexOplogEntry) + ' . collection drop: ' + tojson(dropOplogEntry));

    twoPhaseDropTest.commitDropCollection(collName);

    replTest.stopSet();

})();