summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaszlo Boszormenyi (GCS) <gcs@debian.org>2014-04-27 22:12:11 +0200
committerLaszlo Boszormenyi (GCS) <gcs@debian.org>2014-04-27 22:12:11 +0200
commitf0716c5e9c213302422db87c1c36c1d177853e8e (patch)
tree44f26826e6dde7c32ad2f57f206d7da74e994625
parent547377230880c8e9def9ee9458ae69d298918467 (diff)
Imported Upstream version 2.4.10upstream/2.4.10
-rw-r--r--doxygenConfig2
-rw-r--r--jstests/bench_test3.js3
-rw-r--r--jstests/geo_s2indexversion1.js113
-rw-r--r--jstests/indexes_on_indexes.js19
-rw-r--r--jstests/replsets/compact.js59
-rw-r--r--jstests/replsets/initSyncV1Index.js4
-rw-r--r--jstests/replsets/replset_remove_node.js35
-rw-r--r--jstests/replsets/slavedelay1.js61
-rw-r--r--jstests/replsets/sync2.js16
-rwxr-xr-xjstests/replsets/two_initsync.js2
-rw-r--r--jstests/sharding/prefix_shard_key.js2
-rw-r--r--jstests/sharding/sync7.js4
-rw-r--r--src/mongo/client/distlock.cpp35
-rw-r--r--src/mongo/client/distlock.h25
-rw-r--r--src/mongo/client/gridfs.cpp2
-rw-r--r--src/mongo/db/db.cpp87
-rw-r--r--src/mongo/db/geo/s2index.cpp14
-rw-r--r--src/mongo/db/index.cpp27
-rw-r--r--src/mongo/db/instance.cpp23
-rw-r--r--src/mongo/db/namespace_details.cpp26
-rw-r--r--src/mongo/db/namespace_details.h1
-rw-r--r--src/mongo/db/namespacestring.h1
-rw-r--r--src/mongo/db/oplog.cpp21
-rw-r--r--src/mongo/db/pdfile.cpp30
-rw-r--r--src/mongo/db/pipeline/value.cpp13
-rw-r--r--src/mongo/db/repl/consensus.cpp1
-rw-r--r--src/mongo/db/repl/manager.cpp6
-rw-r--r--src/mongo/db/repl/rs_sync.cpp15
-rw-r--r--src/mongo/dbtests/d_chunk_manager_tests.cpp14
-rw-r--r--src/mongo/s/balance.cpp1
-rw-r--r--src/mongo/s/commands_admin.cpp2
-rw-r--r--src/mongo/s/config.cpp12
-rw-r--r--src/mongo/s/d_chunk_manager.cpp2
-rw-r--r--src/mongo/s/server.cpp3
-rw-r--r--src/mongo/shell/replsettest.js5
-rw-r--r--src/mongo/shell/shell_utils_extended.cpp2
-rw-r--r--src/mongo/util/file_allocator.cpp10
-rw-r--r--src/mongo/util/processinfo.h14
-rw-r--r--src/mongo/util/processinfo_win32.cpp11
-rw-r--r--src/mongo/util/version.cpp2
-rw-r--r--src/third_party/v8/src/spaces-inl.h2
41 files changed, 540 insertions, 187 deletions
diff --git a/doxygenConfig b/doxygenConfig
index 90b26608766..c301d1acf09 100644
--- a/doxygenConfig
+++ b/doxygenConfig
@@ -3,7 +3,7 @@
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = MongoDB
-PROJECT_NUMBER = 2.4.9
+PROJECT_NUMBER = 2.4.10
OUTPUT_DIRECTORY = docs/doxygen
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
diff --git a/jstests/bench_test3.js b/jstests/bench_test3.js
index 4bc21ed2505..34e033fe52a 100644
--- a/jstests/bench_test3.js
+++ b/jstests/bench_test3.js
@@ -8,7 +8,7 @@ benchArgs = { ops : [ { ns : t.getFullName() ,
query : { _id : { "#RAND_INT" : [ 0 , 5 , 4 ] } } ,
update : { $inc : { x : 1 } } } ] ,
parallel : 2 ,
- seconds : 1 ,
+ seconds : 5 ,
totals : true ,
host : db.getMongo().host }
@@ -24,4 +24,5 @@ printjson( res );
var keys = []
var totals = {}
db.bench_test3.find().sort( { _id : 1 } ).forEach( function(z){ keys.push( z._id ); totals[z._id] = z.x } );
+printjson(totals);
assert.eq( [ 0 , 4 , 8 , 12 , 16 ] , keys )
diff --git a/jstests/geo_s2indexversion1.js b/jstests/geo_s2indexversion1.js
new file mode 100644
index 00000000000..799ba775f02
--- /dev/null
+++ b/jstests/geo_s2indexversion1.js
@@ -0,0 +1,113 @@
+// Tests 2dsphere index option "2dsphereIndexVersion". Verifies that only index version 1 is
+// permitted.
+
+var coll = db.getCollection("geo_s2indexversion1");
+coll.drop();
+
+//
+// Index build should fail for invalid values of "2dsphereIndexVersion".
+//
+
+coll.ensureIndex({geo: "2dsphere"}, {"2dsphereIndexVersion": -1});
+assert.gleError(db);
+coll.drop();
+
+coll.ensureIndex({geo: "2dsphere"}, {"2dsphereIndexVersion": 0});
+assert.gleError(db);
+coll.drop();
+
+coll.ensureIndex({geo: "2dsphere"}, {"2dsphereIndexVersion": 2});
+assert.gleError(db);
+coll.drop();
+
+coll.ensureIndex({geo: "2dsphere"}, {"2dsphereIndexVersion": 3});
+assert.gleError(db);
+coll.drop();
+
+coll.ensureIndex({geo: "2dsphere"}, {"2dsphereIndexVersion": Infinity});
+assert.gleError(db);
+coll.drop();
+
+coll.ensureIndex({geo: "2dsphere"}, {"2dsphereIndexVersion": "foo"});
+assert.gleError(db);
+coll.drop();
+
+coll.ensureIndex({geo: "2dsphere"}, {"2dsphereIndexVersion": {a: 1}});
+assert.gleError(db);
+coll.drop();
+
+//
+// Index build should succeed for valid values of "2dsphereIndexVersion".
+//
+
+coll.ensureIndex({geo: "2dsphere"});
+assert.gleSuccess(db);
+coll.drop();
+
+coll.ensureIndex({geo: "2dsphere"}, {"2dsphereIndexVersion": 1});
+assert.gleSuccess(db);
+coll.drop();
+
+coll.ensureIndex({geo: "2dsphere"}, {"2dsphereIndexVersion": NumberInt(1)});
+assert.gleSuccess(db);
+coll.drop();
+
+coll.ensureIndex({geo: "2dsphere"}, {"2dsphereIndexVersion": NumberLong(1)});
+assert.gleSuccess(db);
+coll.drop();
+
+//
+// Test compatibility of various GeoJSON objects with 2dsphere.
+//
+
+var pointDoc = {geo: {type: "Point", coordinates: [40, 5]}};
+var lineStringDoc = {geo: {type: "LineString", coordinates: [[40, 5], [41, 6]]}};
+var polygonDoc = {geo: {type: "Polygon", coordinates: [[[0, 0], [3, 6], [6, 1], [0, 0]]]}};
+var multiPointDoc = {geo: {type: "MultiPoint",
+ coordinates: [[-73.9580, 40.8003], [-73.9498, 40.7968],
+ [-73.9737, 40.7648], [-73.9814, 40.7681]]}};
+var multiLineStringDoc = {geo: {type: "MultiLineString",
+ coordinates: [[[-73.96943, 40.78519], [-73.96082, 40.78095]],
+ [[-73.96415, 40.79229], [-73.95544, 40.78854]],
+ [[-73.97162, 40.78205], [-73.96374, 40.77715]],
+ [[-73.97880, 40.77247], [-73.97036, 40.76811]]]}};
+var multiPolygonDoc = {geo: {type: "MultiPolygon",
+ coordinates: [[[[-73.958, 40.8003], [-73.9498, 40.7968],
+ [-73.9737, 40.7648], [-73.9814, 40.7681],
+ [-73.958, 40.8003]]],
+ [[[-73.958, 40.8003], [-73.9498, 40.7968],
+ [-73.9737, 40.7648], [-73.958, 40.8003]]]]}};
+var geometryCollectionDoc = {geo: {type: "GeometryCollection",
+ geometries: [{type: "MultiPoint",
+ coordinates: [[-73.9580, 40.8003],
+ [-73.9498, 40.7968],
+ [-73.9737, 40.7648],
+ [-73.9814, 40.7681]]},
+ {type: "MultiLineString",
+ coordinates: [[[-73.96943, 40.78519],
+ [-73.96082, 40.78095]],
+ [[-73.96415, 40.79229],
+ [-73.95544, 40.78854]],
+ [[-73.97162, 40.78205],
+ [-73.96374, 40.77715]],
+ [[-73.97880, 40.77247],
+ [-73.97036, 40.76811]]]}]}};
+
+// {2dsphereIndexVersion: 1} indexes allow only Point, LineString, and Polygon.
+coll.ensureIndex({geo: "2dsphere"}, {"2dsphereIndexVersion": 1});
+assert.gleSuccess(db);
+coll.insert(pointDoc);
+assert.gleSuccess(db);
+coll.insert(lineStringDoc);
+assert.gleSuccess(db);
+coll.insert(polygonDoc);
+assert.gleSuccess(db);
+coll.insert(multiPointDoc);
+assert.gleError(db);
+coll.insert(multiLineStringDoc);
+assert.gleError(db);
+coll.insert(multiPolygonDoc);
+assert.gleError(db);
+coll.insert(geometryCollectionDoc);
+assert.gleError(db);
+coll.drop();
diff --git a/jstests/indexes_on_indexes.js b/jstests/indexes_on_indexes.js
new file mode 100644
index 00000000000..807c1e25bfd
--- /dev/null
+++ b/jstests/indexes_on_indexes.js
@@ -0,0 +1,19 @@
+// ensure an index cannot be created on system.indexes
+t = db.getSiblingDB("indexes_on_indexes");
+printjson(t.system.indexes.getIndexes());
+assert.eq(t.system.indexes.getIndexes().length, 0);
+print("trying via ensureIndex");
+assert.throws(t.system.indexes.ensureIndex({_id:1}));
+printjson(t.system.indexes.getIndexes());
+assert.eq(t.system.indexes.getIndexes().length, 0);
+print("trying via createIndex");
+assert.throws(t.system.indexes.createIndex({_id:1}));
+printjson(t.system.indexes.getIndexes());
+assert.eq(t.system.indexes.getIndexes().length, 0);
+print("trying via direct insertion");
+assert.throws(t.system.indexes.insert({ v:1,
+ key:{_id:1},
+ ns: "indexes_on_indexes.system.indexes",
+ name:"wontwork"}));
+printjson(t.system.indexes.getIndexes());
+assert.eq(t.system.indexes.getIndexes().length, 0);
diff --git a/jstests/replsets/compact.js b/jstests/replsets/compact.js
new file mode 100644
index 00000000000..d2a83a8c423
--- /dev/null
+++ b/jstests/replsets/compact.js
@@ -0,0 +1,59 @@
+if (0) { // this test also commented out in master (renamed to auth_compact.js) b/c of SERVER-12697
+
+// test that nodes still respond to heartbeats during compact() SERVER-12264
+var replTest = new ReplSetTest({ name: 'compact', nodes: 3 });
+
+replTest.startSet();
+replTest.initiate();
+
+var master = replTest.getMaster();
+var compactingSlave = replTest.liveNodes.slaves[0];
+
+// populate data
+for (i=0; i<1000; i++) {
+ var bulkInsertArr = [];
+ for (j=0; j<1000; j++) {
+ bulkInsertArr.push({x:i, y:j});
+ }
+ master.getDB("compact").foo.insert(bulkInsertArr);
+}
+
+// takes a while to replicate all this data...
+replTest.awaitReplication(1000*60*5);
+
+// run compact in parallel with this rest of the script
+var cmd = "tojson(db.getSiblingDB('compact').runCommand({'compact': 'foo', 'paddingFactor': 2}));";
+var compactor = startParallelShell(cmd, compactingSlave.port);;
+
+// wait for compact to show up in currentOp
+assert.soon(function() {
+ var curop = compactingSlave.getDB('compact').currentOp();
+ for (index in curop.inprog) {
+ entry = curop.inprog[index];
+ if (entry.query.hasOwnProperty("compact") && entry.query.compact === "foo"
+ && entry.hasOwnProperty("locks") && entry.locks.hasOwnProperty("^compact")
+ && entry.locks["^compact"] === "W") {
+ return true;
+ }
+ }
+ return false;
+}, "compact didn't start in 30 seconds", 30*1000, 100);
+
+// then check that it is still responding to heartbeats
+for (i=0; i<5; i++) {
+ var start = new Date();
+ var result = compactingSlave.getDB("admin").runCommand({"replSetHeartbeat": "compact",
+ "v": NumberInt(1),
+ "pv": NumberInt(1),
+ "checkEmpty": false,
+ "fromId": NumberInt(0)
+ });
+ var end = new Date();
+ assert.eq(result.ok, 1, "heartbeat didn't return properly");
+ // wait for 10 seconds because that's how long it takes for a node to be considered down
+ assert.lt(end - start, 10 * 1000, "heartbeat didn't return quickly enough");
+}
+
+replTest.stopSet();
+
+}
diff --git a/jstests/replsets/initSyncV1Index.js b/jstests/replsets/initSyncV1Index.js
index deec0177382..184eb76615f 100644
--- a/jstests/replsets/initSyncV1Index.js
+++ b/jstests/replsets/initSyncV1Index.js
@@ -12,8 +12,8 @@ for (var i = 0; i < 10000; i++) db1.foo.insert( {_id:i, x:i%1000, t:t} );
db1.foo.createIndex( {x:1}, {v: 0} );
var r2 = rs.add();
-rs.reInitiate();
-rs.awaitSecondaryNodes();
+rs.reInitiate(60000);
+
var db2 = r2.getDB('test');
r2.setSlaveOk();
diff --git a/jstests/replsets/replset_remove_node.js b/jstests/replsets/replset_remove_node.js
index bf99b1236fc..3294b226e27 100644
--- a/jstests/replsets/replset_remove_node.js
+++ b/jstests/replsets/replset_remove_node.js
@@ -1,9 +1,8 @@
-doTest = function( signal ) {
+(function() {
- // Make sure that we can manually shutdown a remove a
- // slave from the configuration.
+ // Make sure that we can manually shutdown and remove a
+ // secondary from the configuration.
- // Create a new replica set test. Specify set name and the number of nodes you want.
var replTest = new ReplSetTest( {name: 'testSet', nodes: 3} );
// call startSet() to start each mongod in the replica set
@@ -30,6 +29,10 @@ doTest = function( signal ) {
// Shut down the unwanted node
replTest.stop( slaveId );
+ // Note: this will cause the PRIMARY to step down, which causes it to close all
+ // connections, including the one we're using from the shell to drive this test.
+ // The shell will attempt to reconnect once.
+
// Remove that node from the configuration
replTest.remove( slaveId );
@@ -39,40 +42,44 @@ doTest = function( signal ) {
var config = replTest.getReplSetConfig();
config.version = c.version + 1;
config.members = [ { "_id" : 0, "host" : replTest.host + ":31000" },
- { "_id" : 2, "host" : replTest.host + ":31002" } ]
+ { "_id" : 2, "host" : replTest.host + ":31002" } ];
try {
+ // Note that this will cause the shell's connection to the primary to be disconnected again
replTest.initiate( config , 'replSetReconfig' );
}
catch(e) {
print(e);
}
-
// Make sure that a new master comes up
master = replTest.getMaster();
slaves = replTest.liveNodes.slaves;
+ // Trigger a reconnect from the shell again, to be sure we're reconnected.
+ try {
+ master.getDB("local").system.replset.findOne();
+ }
+ catch (e) {
+ print (e);
+ }
+
// Do a status check on each node
// Master should be set to 1 (primary)
assert.soon(function() {
- stat = master.getDB("admin").runCommand({replSetGetStatus: 1});
+ var stat = master.getDB("admin").runCommand({replSetGetStatus: 1});
printjson( stat );
return stat.myState == 1;
}, "Master failed to come up as master.", 60000);
// Slaves to be set to 2 (secondary)
assert.soon(function() {
- stat = slaves[0].getDB("admin").runCommand({replSetGetStatus: 1});
+ var stat = slaves[0].getDB("admin").runCommand({replSetGetStatus: 1});
return stat.myState == 2;
}, "Slave failed to come up as slave.", 60000);
assert.soon(function() {
- stat = slaves[0].getDB("admin").runCommand({replSetGetStatus: 1});
+ var stat = slaves[0].getDB("admin").runCommand({replSetGetStatus: 1});
return stat.members.length == 2;
}, "Wrong number of members", 60000);
-}
-
-print("replset_remove_node.js");
-doTest(15);
-print("replset_remove_node SUCCESS");
+}());
diff --git a/jstests/replsets/slavedelay1.js b/jstests/replsets/slavedelay1.js
index 13c6adfcdf3..623fa8a5ab4 100644
--- a/jstests/replsets/slavedelay1.js
+++ b/jstests/replsets/slavedelay1.js
@@ -12,17 +12,16 @@ doTest = function( signal ) {
/* set slaveDelay to 30 seconds */
var config = replTest.getReplSetConfig();
config.members[2].priority = 0;
- config.members[2].slaveDelay = 10;
+ config.members[2].slaveDelay = 30;
replTest.initiate(config);
var master = replTest.getMaster().getDB(name);
var slaveConns = replTest.liveNodes.slaves;
- var slave = [];
+ var slaves = [];
for (var i in slaveConns) {
var d = slaveConns[i].getDB(name);
- d.getMongo().setSlaveOk();
- slave.push(d);
+ slaves.push(d);
}
waitForAllMembers(master);
@@ -35,68 +34,44 @@ doTest = function( signal ) {
assert.eq(doc.x, 1);
// make sure slave has it
- var doc = slave[0].foo.findOne();
+ var doc = slaves[0].foo.findOne();
assert.eq(doc.x, 1);
// make sure delayed slave doesn't have it
- assert.eq(slave[1].foo.findOne(), null);
-
for (var i=0; i<8; i++) {
- assert.eq(slave[1].foo.findOne(), null);
+ assert.eq(slaves[1].foo.findOne(), null);
sleep(1000);
}
- // now delayed slave should have it
+ // within 30 seconds delayed slave should have it
assert.soon(function() {
- var z = slave[1].foo.findOne();
+ var z = slaves[1].foo.findOne();
return z && z.x == 1;
});
/************* Part 2 *******************/
- // how about non-initial sync?
-
- for (var i=0; i<100; i++) {
- master.foo.insert({_id : i, "foo" : "bar"});
- }
- master.runCommand({getlasterror:1,w:2});
-
- assert.eq(master.foo.findOne({_id : 99}).foo, "bar");
- assert.eq(slave[0].foo.findOne({_id : 99}).foo, "bar");
- assert.eq(slave[1].foo.findOne({_id : 99}), null);
-
- for (var i=0; i<8; i++) {
- assert.eq(slave[1].foo.findOne({_id:99}), null);
- sleep(1000);
- }
-
- assert.soon(function() {
- var z = slave[1].foo.findOne({_id : 99});
- return z && z.foo == "bar";
- });
-
- /************* Part 3 *******************/
-
// how about if we add a new server? will it sync correctly?
-
conn = replTest.add();
config = master.getSisterDB("local").system.replset.findOne();
printjson(config);
config.version++;
- config.members.push({_id : 3, host : host+":"+replTest.ports[replTest.ports.length-1],priority:0, slaveDelay:10});
+ config.members.push({_id: 3,
+ host: host+":"+replTest.ports[replTest.ports.length-1],
+ priority:0,
+ slaveDelay:30});
master = reconfig(replTest, config);
master = master.getSisterDB(name);
- // it should be all caught up now
+ // wait for the node to catch up
+ replTest.awaitReplication();
master.foo.insert({_id : 123, "x" : "foo"});
master.runCommand({getlasterror:1,w:2});
- conn.setSlaveOk();
-
for (var i=0; i<8; i++) {
assert.eq(conn.getDB(name).foo.findOne({_id:123}), null);
sleep(1000);
@@ -107,7 +82,7 @@ doTest = function( signal ) {
return z != null && z.x == "foo"
});
- /************* Part 4 ******************/
+ /************* Part 3 ******************/
print("reconfigure slavedelay");
@@ -120,6 +95,7 @@ doTest = function( signal ) {
return conn.getDB("local").system.replset.findOne().version == config.version;
});
+ // wait for node to become secondary
assert.soon(function() {
var result = conn.getDB("admin").isMaster();
printjson(result);
@@ -130,12 +106,15 @@ doTest = function( signal ) {
master.foo.insert({_id : 124, "x" : "foo"});
assert(master.foo.findOne({_id:124}) != null);
- for (var i=0; i<13; i++) {
+ for (var i=0; i<10; i++) {
assert.eq(conn.getDB(name).foo.findOne({_id:124}), null);
sleep(1000);
}
- replTest.awaitReplication();
+ // the node should have the document in 15 seconds (20 for some safety against races)
+ assert.soon(function() {
+ return conn.getDB(name).foo.findOne({_id:124}) != null;
+ }, 10*1000);
replTest.stopSet();
}
diff --git a/jstests/replsets/sync2.js b/jstests/replsets/sync2.js
index 258cfd3ee12..57577c6c46b 100644
--- a/jstests/replsets/sync2.js
+++ b/jstests/replsets/sync2.js
@@ -21,22 +21,6 @@ replTest.awaitSecondaryNodes();
master.getDB("foo").bar.insert({x:1});
replTest.awaitReplication();
-jsTestLog("Checking that currentOp for secondaries uses OpTime, not Date");
-assert.soon(
- function() {
- var count = 0;
- var currentOp = master.getDB("admin").currentOp({ns: 'local.oplog.rs'});
- printjson(currentOp);
- currentOp.inprog.forEach(
- function(op) {
- assert.eq(op.query.ts.$gte.constructor, Timestamp);
- count++;
- }
- );
- return count >= 4;
- }
-);
-
jsTestLog("Bridging replica set");
master = replTest.bridge();
diff --git a/jstests/replsets/two_initsync.js b/jstests/replsets/two_initsync.js
index 7d1442d344f..08e440406cb 100755
--- a/jstests/replsets/two_initsync.js
+++ b/jstests/replsets/two_initsync.js
@@ -63,7 +63,7 @@ doTest = function (signal) {
// Add the second node.
// This runs the equivalent of rs.add(newNode);
- replTest.reInitiate();
+ replTest.reInitiate(60000);
var b = second.getDB("admin");
diff --git a/jstests/sharding/prefix_shard_key.js b/jstests/sharding/prefix_shard_key.js
index 58091490b1c..0e55aae2d44 100644
--- a/jstests/sharding/prefix_shard_key.js
+++ b/jstests/sharding/prefix_shard_key.js
@@ -119,7 +119,7 @@ for( i=0; i < 3; i++ ){
var coll2 = db.foo2;
coll2.drop();
var moveRes = admin.runCommand( { movePrimary : coll2.getDB() + "", to : shards[0]._id } );
- assert.eq( moveRes.ok , 1 , "primary not moved correctly" );
+ assert.eq( moveRes.ok, 1, "primary not moved correctly: " + tojson( moveRes ));
// declare a longer index
if ( i == 0 ) {
diff --git a/jstests/sharding/sync7.js b/jstests/sharding/sync7.js
index 87eeaa0b36b..8c1430ea3c0 100644
--- a/jstests/sharding/sync7.js
+++ b/jstests/sharding/sync7.js
@@ -3,11 +3,11 @@
s = new ShardingTest( "moveDistLock", 3, 0, undefined, { sync : true } );
s._connections[0].getDB( "admin" ).runCommand( { _skewClockCommand : 1, skew : 15000 } )
-s._connections[1].getDB( "admin" ).runCommand( { _skewClockCommand : 1, skew : -16000 } )
+s._connections[1].getDB( "admin" ).runCommand( { _skewClockCommand : 1, skew : -32000 } )
// We need to start another mongos after skewing the clock, since the first mongos will have already
// tested the config servers (via the balancer) before we manually skewed them
-otherMongos = startMongos( { port : 30020, v : 0, configdb : s._configDB } );
+otherMongos = startMongos( { port : 30020, v : 2, configdb : s._configDB } );
// Initialize DB data
initDB = function(name) {
diff --git a/src/mongo/client/distlock.cpp b/src/mongo/client/distlock.cpp
index 0e38a64f953..a2f56e564bf 100644
--- a/src/mongo/client/distlock.cpp
+++ b/src/mongo/client/distlock.cpp
@@ -131,19 +131,32 @@ namespace mongo {
continue;
}
- // remove really old entries from the lockpings collection if they're not holding a lock
- // (this may happen if an instance of a process was taken down and no new instance came up to
- // replace it for a quite a while)
- // if the lock is taken, the take-over mechanism should handle the situation
- auto_ptr<DBClientCursor> c = conn->query( LocksType::ConfigNS , BSONObj() );
- // TODO: Would be good to make clear whether query throws or returns empty on errors
- uassert( 16060, str::stream() << "cannot query locks collection on config server " << conn.getHost(), c.get() );
+ // Remove really old entries from the lockpings collection if they're not
+ // holding a lock. This may happen if an instance of a process was taken down
+ // and no new instance came up to replace it for a quite a while.
+ // NOTE this is NOT the same as the standard take-over mechanism, which forces
+ // the lock entry.
+ BSONObj fieldsToReturn = BSON( LocksType::state() << 1 <<
+ LocksType::process() << 1 );
+ auto_ptr<DBClientCursor> activeLocks =
+ conn->query( LocksType::ConfigNS,
+ BSON( LocksType::state() << GT << 0 ) );
+
+ uassert( 16060,
+ str::stream() << "cannot query locks collection on config server "
+ << conn.getHost(),
+ activeLocks.get() );
set<string> pids;
- while ( c->more() ) {
- BSONObj lock = c->next();
- if ( ! lock[LocksType::process()].eoo() ) {
- pids.insert( lock[LocksType::process()].valuestrsafe() );
+ while ( activeLocks->more() ) {
+ BSONObj lock = activeLocks->nextSafe();
+
+ if ( !lock[LocksType::process()].eoo() ) {
+ pids.insert( lock[LocksType::process()].str() );
+ }
+ else {
+ warning() << "found incorrect lock document during lock ping cleanup: "
+ << lock.toString() << endl;
}
}
diff --git a/src/mongo/client/distlock.h b/src/mongo/client/distlock.h
index 183826afcce..774d94a0df8 100644
--- a/src/mongo/client/distlock.h
+++ b/src/mongo/client/distlock.h
@@ -57,12 +57,19 @@ namespace mongo {
};
/**
- * The distributed lock is a configdb backed way of synchronizing system-wide tasks. A task must be identified by a
- * unique name across the system (e.g., "balancer"). A lock is taken by writing a document in the configdb's locks
- * collection with that name.
+ * The distributed lock is a configdb backed way of synchronizing system-wide tasks. A task
+ * must be identified by a unique name across the system (e.g., "balancer"). A lock is taken
+ * by writing a document in the configdb's locks collection with that name.
*
- * To be maintained, each taken lock needs to be revalidated ("pinged") within a pre-established amount of time. This
- * class does this maintenance automatically once a DistributedLock object was constructed.
+ * To be maintained, each taken lock needs to be revalidated ("pinged") within a
+ * pre-established amount of time. This class does this maintenance automatically once a
+ * DistributedLock object was constructed. The ping procedure records the local time to
+ * the ping document, but that time is untrusted and is only used as a point of reference
+ * of whether the ping was refreshed or not. Ultimately, the clock a configdb is the source
+ * of truth when determining whether a ping is still fresh or not. This is achieved by
+ * (1) remembering the ping document time along with config server time when unable to
+ * take a lock, and (2) ensuring all config servers report similar times and have similar
+ * time rates (the difference in times must start and stay small).
*/
class DistributedLock {
public:
@@ -147,9 +154,13 @@ namespace mongo {
const ConnectionString& getRemoteConnection();
/**
- * Check the skew between a cluster of servers
+ * Checks the skew among a cluster of servers and returns true if the min and max clock
+ * times among the servers are within maxClockSkew.
*/
- static bool checkSkew( const ConnectionString& cluster, unsigned skewChecks = NUM_LOCK_SKEW_CHECKS, unsigned long long maxClockSkew = MAX_LOCK_CLOCK_SKEW, unsigned long long maxNetSkew = MAX_LOCK_NET_SKEW );
+ static bool checkSkew( const ConnectionString& cluster,
+ unsigned skewChecks = NUM_LOCK_SKEW_CHECKS,
+ unsigned long long maxClockSkew = MAX_LOCK_CLOCK_SKEW,
+ unsigned long long maxNetSkew = MAX_LOCK_NET_SKEW );
/**
* Get the remote time from a server or cluster
diff --git a/src/mongo/client/gridfs.cpp b/src/mongo/client/gridfs.cpp
index e2d1038d6ee..6d58ec690c2 100644
--- a/src/mongo/client/gridfs.cpp
+++ b/src/mongo/client/gridfs.cpp
@@ -37,7 +37,7 @@
namespace mongo {
- const unsigned DEFAULT_CHUNK_SIZE = 256 * 1024;
+ const unsigned DEFAULT_CHUNK_SIZE = 255 * 1024;
GridFSChunk::GridFSChunk( BSONObj o ) {
_data = o;
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index ec337c89885..046101a29bf 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -77,6 +77,7 @@ namespace mongo {
extern int diagLogging;
extern unsigned lenForNewNsFiles;
extern int lockFile;
+ extern bool checkNsFilesOnLoad;
extern string repairpath;
static void setupSignalHandlers();
@@ -321,6 +322,8 @@ namespace mongo {
Client::GodScope gs;
LOG(1) << "enter repairDatabases (to check pdfile version #)" << endl;
+ checkNsFilesOnLoad = false; // we are mainly just checking the header - don't scan the whole .ns file for every db here.
+
Lock::GlobalWrite lk;
vector< string > dbNames;
getDatabaseNames( dbNames );
@@ -361,12 +364,12 @@ namespace mongo {
}
}
else {
- if (h->versionMinor == PDFILE_VERSION_MINOR_22_AND_OLDER) {
- const string systemIndexes = cc().database()->name + ".system.indexes";
- shared_ptr<Cursor> cursor(theDataFileMgr.findAll(systemIndexes));
- for ( ; cursor && cursor->ok(); cursor->advance()) {
- const BSONObj index = cursor->current();
- const BSONObj key = index.getObjectField("key");
+ const string systemIndexes = cc().database()->name + ".system.indexes";
+ shared_ptr<Cursor> cursor(theDataFileMgr.findAll(systemIndexes));
+ for ( ; cursor && cursor->ok(); cursor->advance()) {
+ const BSONObj index = cursor->current();
+ const BSONObj key = index.getObjectField("key");
+ if (h->versionMinor == PDFILE_VERSION_MINOR_22_AND_OLDER) {
const string plugin = IndexPlugin::findPluginName(key);
if (IndexPlugin::existedBefore24(plugin))
continue;
@@ -377,6 +380,21 @@ namespace mongo {
<< "http://dochub.mongodb.org/core/upgrade-2.4"
<< startupWarningsLog;
}
+ else {
+ verify(h->versionMinor == PDFILE_VERSION_MINOR_24_AND_NEWER);
+ try {
+ IndexSpec(key, index, IndexSpec::RulesFor24);
+ }
+ catch (const DBException& e) {
+ error() << "Encountered an unrecognized index spec: " << index << endl;
+ error() << "Reason this index spec could not be loaded: \"" << e.what()
+ << "\"" << endl;
+ error() << "The index cannot be used with this version of MongoDB; "
+ << "exiting..." << endl;
+ cc().shutdown();
+ dbexit(EXIT_UNCAUGHT);
+ }
+ }
}
Database::closeDatabase( dbName.c_str(), dbpath );
}
@@ -389,6 +407,8 @@ namespace mongo {
cc().shutdown();
dbexit( EXIT_CLEAN );
}
+
+ checkNsFilesOnLoad = true;
}
void clearTmpFiles() {
@@ -528,39 +548,47 @@ namespace mongo {
/// warn if readahead > 256KB (gridfs chunk size)
static void checkReadAhead(const string& dir) {
#ifdef __linux__
- const dev_t dev = getPartition(dir);
-
- // This path handles the case where the filesystem uses the whole device (including LVM)
- string path = str::stream() <<
- "/sys/dev/block/" << major(dev) << ':' << minor(dev) << "/queue/read_ahead_kb";
-
- if (!boost::filesystem::exists(path)){
- // This path handles the case where the filesystem is on a partition.
- path = str::stream()
- << "/sys/dev/block/" << major(dev) << ':' << minor(dev) // this is a symlink
- << "/.." // parent directory of a partition is for the whole device
- << "/queue/read_ahead_kb";
- }
+ try {
+ const dev_t dev = getPartition(dir);
+
+ // This path handles the case where the filesystem uses the whole device (including LVM)
+ string path = str::stream() <<
+ "/sys/dev/block/" << major(dev) << ':' << minor(dev) << "/queue/read_ahead_kb";
+
+ if (!boost::filesystem::exists(path)){
+ // This path handles the case where the filesystem is on a partition.
+ path = str::stream()
+ << "/sys/dev/block/" << major(dev) << ':' << minor(dev) // this is a symlink
+ << "/.." // parent directory of a partition is for the whole device
+ << "/queue/read_ahead_kb";
+ }
- if (boost::filesystem::exists(path)) {
- ifstream file (path.c_str());
- if (file.is_open()) {
- int kb;
- file >> kb;
- if (kb > 256) {
- log() << startupWarningsLog;
+ if (boost::filesystem::exists(path)) {
+ ifstream file (path.c_str());
+ if (file.is_open()) {
+ int kb;
+ file >> kb;
+ if (kb > 256) {
+ log() << startupWarningsLog;
- log() << "** WARNING: Readahead for " << dir << " is set to " << kb << "KB"
+ log() << "** WARNING: Readahead for " << dir << " is set to " << kb << "KB"
<< startupWarningsLog;
- log() << "** We suggest setting it to 256KB (512 sectors) or less"
+ log() << "** We suggest setting it to 256KB (512 sectors) or less"
<< startupWarningsLog;
- log() << "** http://dochub.mongodb.org/core/readahead"
+ log() << "** http://dochub.mongodb.org/core/readahead"
<< startupWarningsLog;
+ }
}
}
}
+ catch (const std::exception& e) {
+ log() << "unable to validate readahead settings due to error: " << e.what()
+ << startupWarningsLog;
+ log() << "for more information, see http://dochub.mongodb.org/core/readahead"
+ << startupWarningsLog;
+ }
#endif // __linux__
}
@@ -1415,6 +1443,7 @@ namespace mongo {
sigaddset( &asyncSignals, SIGINT );
sigaddset( &asyncSignals, SIGTERM );
sigaddset( &asyncSignals, SIGUSR1 );
+ sigaddset( &asyncSignals, SIGXCPU );
set_terminate( myterminate );
set_new_handler( my_new_handler );
diff --git a/src/mongo/db/geo/s2index.cpp b/src/mongo/db/geo/s2index.cpp
index d52f0ad2991..412d425f2f8 100644
--- a/src/mongo/db/geo/s2index.cpp
+++ b/src/mongo/db/geo/s2index.cpp
@@ -365,6 +365,11 @@ namespace mongo {
uassert(16688, "finestIndexedLevel must be <= 30", params.finestIndexedLevel <= 30);
uassert(16689, "finestIndexedLevel must be >= coarsestIndexedLevel",
params.finestIndexedLevel >= params.coarsestIndexedLevel);
+ massert(17289,
+ str::stream() << "unsupported geo index version { "
+ << spec->info["2dsphereIndexVersion"]
+ << " }, only support versions: [1]",
+ configValueWithDefault(spec, "2dsphereIndexVersion", 1) == 1);
// Categorize the fields we're indexing and make sure we have a geo field.
int geoFields = 0;
@@ -388,6 +393,15 @@ namespace mongo {
return new S2IndexType(SPHERE_2D_NAME, this, spec, params);
}
+ virtual BSONObj adjustIndexSpec( const BSONObj& spec ) const {
+ BSONElement indexVersionElt = spec["2dsphereIndexVersion"];
+ uassert(17290,
+ str::stream() << "unsupported geo index version { " << indexVersionElt
+ << " }, only support versions: [1]",
+ indexVersionElt.eoo() || indexVersionElt.numberInt() == 1);
+ return spec;
+ }
+
int configValueWithDefault(const IndexSpec* spec, const string& name, int def) const {
BSONElement e = spec->info[name];
if (e.isNumber()) { return e.numberInt(); }
diff --git a/src/mongo/db/index.cpp b/src/mongo/db/index.cpp
index f7346978313..e4366977081 100644
--- a/src/mongo/db/index.cpp
+++ b/src/mongo/db/index.cpp
@@ -324,6 +324,8 @@ namespace mongo {
getDur().writingInt(dfh->versionMinor) = PDFILE_VERSION_MINOR_24_AND_NEWER;
}
+ extern BSONObj id_obj; // { _id : 1 }
+
bool prepareToBuildIndex(const BSONObj& io,
bool mayInterrupt,
bool god,
@@ -334,9 +336,11 @@ namespace mongo {
// the collection for which we are building an index
sourceNS = io.getStringField("ns");
+ NamespaceString nss(sourceNS);
uassert(10096, "invalid ns to index", sourceNS.find( '.' ) != string::npos);
- massert(10097, str::stream() << "bad table to index name on add index attempt current db: " << cc().database()->name << " source: " << sourceNS ,
- cc().database()->name == nsToDatabase(sourceNS));
+ uassert(17072, "cannot create indexes on the system.indexes collection",
+ !nss.isSystemDotIndexes());
+ massert(10097, str::stream() << "bad table to index name on add index attempt current db: " << cc().database()->name << " source: " << sourceNS , cc().database()->name == nsToDatabase(sourceNS));
// logical name of the index. todo: get rid of the name, we don't need it!
const char *name = io.getStringField("name");
@@ -393,10 +397,10 @@ namespace mongo {
all be treated as the same pattern.
*/
if ( IndexDetails::isIdIndexPattern(key) ) {
- if( !god ) {
- ensureHaveIdIndex( sourceNS.c_str(), mayInterrupt );
- return false;
- }
+ //if( !god ) {
+ //ensureHaveIdIndex( sourceNS.c_str(), mayInterrupt );
+ //return false;
+ //}
}
else {
/* is buildIndexes:false set for this replica set member?
@@ -435,7 +439,14 @@ namespace mongo {
}
// idea is to put things we use a lot earlier
b.append("v", v);
- b.append(o["key"]);
+ if ( IndexDetails::isIdIndexPattern(o["key"].Obj()) ) {
+ b.append("name", "_id_");
+ b.append("key", id_obj);
+ }
+ else {
+ b.append( o["name"] );
+ b.append(o["key"]);
+ }
if( o["unique"].trueValue() )
b.appendBool("unique", true); // normalize to bool true in case was int 1 or something...
b.append(o["ns"]);
@@ -446,7 +457,7 @@ namespace mongo {
while ( i.more() ) {
BSONElement e = i.next();
string s = e.fieldName();
- if( s != "_id" && s != "v" && s != "ns" && s != "unique" && s != "key" )
+ if( s != "_id" && s != "v" && s != "ns" && s != "unique" && s != "key" && s != "name" )
b.append(e);
}
}
diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp
index 926cdeecdb6..b95bcb1bfea 100644
--- a/src/mongo/db/instance.cpp
+++ b/src/mongo/db/instance.cpp
@@ -792,16 +792,19 @@ namespace mongo {
}
}
- theDataFileMgr.insertWithObjMod(ns,
- // May be modified in the call to add an _id field.
- js,
- // Only permit interrupting an (index build) insert if the
- // insert comes from a socket client request rather than a
- // parent operation using the client interface. The parent
- // operation might not support interrupts.
- cc().curop()->parent() == NULL,
- false);
- logOp("i", ns, js);
+ DiskLoc dl = theDataFileMgr.
+ insertWithObjMod(ns,
+ // May be modified in the call to add an _id field.
+ js,
+ // Only permit interrupting an (index build) insert if the
+ // insert comes from a socket client request rather than a
+ // parent operation using the client interface. The parent
+ // operation might not support interrupts.
+ cc().curop()->parent() == NULL,
+ false);
+ if (!dl.isNull()) {
+ logOp("i", ns, js);
+ }
}
NOINLINE_DECL void insertMulti(bool keepGoing, const char *ns, vector<BSONObj>& objs, CurOp& op) {
diff --git a/src/mongo/db/namespace_details.cpp b/src/mongo/db/namespace_details.cpp
index 0fc7bdf5eb5..382522bb50a 100644
--- a/src/mongo/db/namespace_details.cpp
+++ b/src/mongo/db/namespace_details.cpp
@@ -122,6 +122,29 @@ namespace mongo {
}
#endif
+ void NamespaceDetails::onLoad(const Namespace& k) {
+
+ if( k.isExtra() ) {
+ /* overflow storage for indexes - so don't treat as a NamespaceDetails object. */
+ return;
+ }
+
+ if( indexBuildsInProgress ) {
+ verify( Lock::isW() ); // TODO(erh) should this be per db?
+ if( indexBuildsInProgress ) {
+ log() << "indexBuildsInProgress was " << indexBuildsInProgress << " for " << k
+ << ", indicating an abnormal db shutdown" << endl;
+ getDur().writingInt( indexBuildsInProgress ) = 0;
+ }
+ }
+ }
+
+ static void namespaceOnLoadCallback(const Namespace& k, NamespaceDetails& v) {
+ v.onLoad(k);
+ }
+
+ bool checkNsFilesOnLoad = true;
+
NOINLINE_DECL void NamespaceIndex::_init() {
verify( !ht );
@@ -174,6 +197,9 @@ namespace mongo {
verify( len <= 0x7fffffff );
ht = new HashTable<Namespace,NamespaceDetails>(p, (int) len, "namespace index");
+ if( checkNsFilesOnLoad )
+ ht->iterAll(namespaceOnLoadCallback);
+
}
static void namespaceGetNamespacesCallback( const Namespace& k , NamespaceDetails& v , void * extra ) {
diff --git a/src/mongo/db/namespace_details.h b/src/mongo/db/namespace_details.h
index 0e7e324da67..3f381605250 100644
--- a/src/mongo/db/namespace_details.h
+++ b/src/mongo/db/namespace_details.h
@@ -405,6 +405,7 @@ namespace mongo {
/** Make all linked Extra objects writeable as well */
NamespaceDetails *writingWithExtra();
+ void onLoad( const Namespace& k );
private:
DiskLoc _alloc(const char *ns, int len);
void maybeComplain( const char *ns, int len ) const;
diff --git a/src/mongo/db/namespacestring.h b/src/mongo/db/namespacestring.h
index d108bbaac72..96d78230b39 100644
--- a/src/mongo/db/namespacestring.h
+++ b/src/mongo/db/namespacestring.h
@@ -46,6 +46,7 @@ namespace mongo {
bool isSystem() const { return strncmp(coll.c_str(), "system.", 7) == 0; }
bool isCommand() const { return coll == "$cmd"; }
+ bool isSystemDotIndexes() const { return strncmp(coll.c_str(), "system.indexes", 14) == 0; }
/**
* @return true if the namespace is valid. Special namespaces for internal use are considered as valid.
diff --git a/src/mongo/db/oplog.cpp b/src/mongo/db/oplog.cpp
index b88ad66ac03..33990367d92 100644
--- a/src/mongo/db/oplog.cpp
+++ b/src/mongo/db/oplog.cpp
@@ -95,7 +95,15 @@ namespace mongo {
*/
if( theReplSet ) {
if( !(theReplSet->lastOpTimeWritten<ts) ) {
- log() << "replSet error possible failover clock skew issue? " << theReplSet->lastOpTimeWritten.toString() << ' ' << endl;
+ log() << "replication oplog stream went back in time. previous timestamp: "
+ << theReplSet->lastOpTimeWritten << " newest timestamp: " << ts
+ << ". attempting to sync directly from primary." << endl;
+ std::string errmsg;
+ BSONObjBuilder result;
+ if (!theReplSet->forceSyncFrom(theReplSet->box.getPrimary()->fullName(),
+ errmsg, result)) {
+ log() << "Can't sync from primary: " << errmsg << endl;
+ }
}
theReplSet->lastOpTimeWritten = ts;
theReplSet->lastH = h;
@@ -222,8 +230,15 @@ namespace mongo {
*/
if( theReplSet ) {
if( !(theReplSet->lastOpTimeWritten<ts) ) {
- log() << "replSet ERROR possible failover clock skew issue? " << theReplSet->lastOpTimeWritten << ' ' << ts << rsLog;
- log() << "replSet " << theReplSet->isPrimary() << rsLog;
+ log() << "replication oplog stream went back in time. previous timestamp: "
+ << theReplSet->lastOpTimeWritten << " newest timestamp: " << ts
+ << ". attempting to sync directly from primary." << endl;
+ std::string errmsg;
+ BSONObjBuilder result;
+ if (!theReplSet->forceSyncFrom(theReplSet->box.getPrimary()->fullName(),
+ errmsg, result)) {
+ log() << "Can't sync from primary: " << errmsg << endl;
+ }
}
theReplSet->lastOpTimeWritten = ts;
theReplSet->lastH = hashNew;
diff --git a/src/mongo/db/pdfile.cpp b/src/mongo/db/pdfile.cpp
index 4085dfd2b3f..aa49b156a28 100644
--- a/src/mongo/db/pdfile.cpp
+++ b/src/mongo/db/pdfile.cpp
@@ -1316,8 +1316,10 @@ namespace mongo {
void DataFileMgr::insertAndLog( const char *ns, const BSONObj &o, bool god, bool fromMigrate ) {
BSONObj tmp = o;
- insertWithObjMod( ns, tmp, false, god );
- logOp( "i", ns, tmp, 0, 0, fromMigrate );
+ DiskLoc loc = insertWithObjMod( ns, tmp, false, god );
+ if (!loc.isNull()) {
+ logOp( "i", ns, tmp, 0, 0, fromMigrate );
+ }
}
/** @param o the object to insert. can be modified to add _id and thus be an in/out param
@@ -1475,16 +1477,20 @@ namespace mongo {
}
try {
- IndexDetails& idx = tableToIndex->getNextIndexDetails(tabletoidxns.c_str());
- // It's important that this is outside the inner try/catch so that we never try to call
- // kill_idx on a half-formed disk loc (if this asserts).
- getDur().writingDiskLoc(idx.info) = loc;
+ {
+ IndexDetails& idx = tableToIndex->getNextIndexDetails(tabletoidxns.c_str());
+ // It's important that this is outside the inner try/catch so that we never try to call
+ // kill_idx on a half-formed disk loc (if this asserts).
+ getDur().writingDiskLoc(idx.info) = loc;
+ }
try {
+ IndexDetails& idx = tableToIndex->getNextIndexDetails(tabletoidxns.c_str());
getDur().writingInt(tableToIndex->indexBuildsInProgress) += 1;
buildAnIndex(tabletoidxns, tableToIndex, idx, background, mayInterrupt);
}
catch (DBException& e) {
+ log() << "error building index: " << e << endl;
// save our error msg string as an exception or dropIndexes will overwrite our message
LastError *le = lastError.get();
int savecode = 0;
@@ -1499,7 +1505,10 @@ namespace mongo {
}
// Recalculate the index # so we can remove it from the list in the next catch
+
idxNo = IndexBuildsInProgress::get(tabletoidxns.c_str(), idxName);
+ IndexDetails& idx = tableToIndex->idx(idxNo);
+
// roll back this index
idx.kill_idx();
@@ -1519,6 +1528,7 @@ namespace mongo {
<< tableToIndex->nIndexes << endl;
// We cannot use idx here, as it may point to a different index entry if it was
// flipped during building
+
IndexDetails temp = tableToIndex->idx(idxNo);
*getDur().writing(&tableToIndex->idx(idxNo)) =
tableToIndex->idx(tableToIndex->nIndexes);
@@ -1531,6 +1541,7 @@ namespace mongo {
tableToIndex->setIndexIsMultikey(tabletoidxns.c_str(), tableToIndex->nIndexes,
tempMultikey);
+
idxNo = tableToIndex->nIndexes;
}
@@ -1542,10 +1553,10 @@ namespace mongo {
tableToIndex->addIndex(tabletoidxns.c_str());
getDur().writingInt(tableToIndex->indexBuildsInProgress) -= 1;
- IndexType* indexType = idx.getSpec().getType();
+ IndexType* indexType = tableToIndex->idx(idxNo).getSpec().getType();
const IndexPlugin *plugin = indexType ? indexType->getPlugin() : NULL;
if (plugin) {
- plugin->postBuildHook( idx.getSpec() );
+ plugin->postBuildHook( tableToIndex->idx(idxNo).getSpec() );
}
}
@@ -1589,7 +1600,8 @@ namespace mongo {
Lock::assertWriteLocked(ns);
NamespaceDetails* nsd = nsdetails(ns);
- for (int i=offset; i<nsd->getTotalIndexCount(); i++) {
+ // offset is 0-based, so we subtract one from the index count
+ for (int i = offset; i < (nsd->getTotalIndexCount() - 1); i++) {
if (i < NamespaceDetails::NIndexesMax-1) {
*getDur().writing(&nsd->idx(i)) = nsd->idx(i+1);
nsd->setIndexIsMultikey(ns, i, nsd->isMultikey(i+1));
diff --git a/src/mongo/db/pipeline/value.cpp b/src/mongo/db/pipeline/value.cpp
index 207dc4e37b8..6045207c764 100644
--- a/src/mongo/db/pipeline/value.cpp
+++ b/src/mongo/db/pipeline/value.cpp
@@ -513,19 +513,15 @@ namespace mongo {
}
string Value::coerceToString() const {
- stringstream ss;
switch(getType()) {
case NumberDouble:
- ss << _storage.doubleValue;
- return ss.str();
+ return str::stream() << _storage.doubleValue;
case NumberInt:
- ss << _storage.intValue;
- return ss.str();
+ return str::stream() << _storage.intValue;
case NumberLong:
- ss << _storage.longValue;
- return ss.str();
+ return str::stream() << _storage.longValue;
case Code:
case Symbol:
@@ -533,8 +529,7 @@ namespace mongo {
return getStringData().toString();
case Timestamp:
- ss << getTimestamp().toStringPretty();
- return ss.str();
+ return getTimestamp().toStringPretty();
case Date:
return tmToISODateString(coerceToTm());
diff --git a/src/mongo/db/repl/consensus.cpp b/src/mongo/db/repl/consensus.cpp
index dcb31408c11..a2459477432 100644
--- a/src/mongo/db/repl/consensus.cpp
+++ b/src/mongo/db/repl/consensus.cpp
@@ -253,7 +253,6 @@ namespace mongo {
try {
vote = yea(whoid);
dassert( hopeful->id() == whoid );
- rs.relinquish();
log() << "replSet info voting yea for " << hopeful->fullName() << " (" << whoid << ')' << rsLog;
}
catch(VoteException&) {
diff --git a/src/mongo/db/repl/manager.cpp b/src/mongo/db/repl/manager.cpp
index cbc3a3e7baa..4e9708a1d19 100644
--- a/src/mongo/db/repl/manager.cpp
+++ b/src/mongo/db/repl/manager.cpp
@@ -80,11 +80,7 @@ namespace mongo {
}
if (rs->box.getState().primary()) {
- // make sure exactly one primary steps down
- if (rs->selfId() < m->id()) {
- return;
- }
-
+ log() << "stepping down; another primary seen in replicaset";
rs->relinquish();
}
diff --git a/src/mongo/db/repl/rs_sync.cpp b/src/mongo/db/repl/rs_sync.cpp
index e6e31943a9f..f904d86c5ad 100644
--- a/src/mongo/db/repl/rs_sync.cpp
+++ b/src/mongo/db/repl/rs_sync.cpp
@@ -585,13 +585,6 @@ namespace replset {
bool golive = false;
lock rsLock( this );
- Lock::GlobalWrite writeLock;
-
- // make sure we're not primary, secondary, rollback, or fatal already
- if (box.getState().primary() || box.getState().secondary() ||
- box.getState().fatal()) {
- return false;
- }
if (_maintenanceMode > 0) {
// we're not actually going live
@@ -603,6 +596,14 @@ namespace replset {
return false;
}
+ Lock::GlobalWrite writeLock;
+
+ // make sure we're not primary, secondary, rollback, or fatal already
+ if (box.getState().primary() || box.getState().secondary() ||
+ box.getState().fatal()) {
+ return false;
+ }
+
minvalid = getMinValid();
if( minvalid <= lastOpTimeWritten ) {
golive=true;
diff --git a/src/mongo/dbtests/d_chunk_manager_tests.cpp b/src/mongo/dbtests/d_chunk_manager_tests.cpp
index e50961d3ee7..be7639f5794 100644
--- a/src/mongo/dbtests/d_chunk_manager_tests.cpp
+++ b/src/mongo/dbtests/d_chunk_manager_tests.cpp
@@ -362,6 +362,20 @@ namespace {
ASSERT( cloned->belongsToMe( split1 ) );
ASSERT( cloned->belongsToMe( split2 ) );
ASSERT( ! cloned->belongsToMe( max ) );
+
+ ASSERT_FALSE( cloned->getNextChunk( BSON( "a" << MinKey << "b" << 0 ), &min, &max ));
+ ASSERT_EQUALS( BSON( "a" << 10 << "b" << 0 ), min );
+ ASSERT_EQUALS( BSON( "a" << 15 << "b" << 0 ), max );
+
+ ASSERT_FALSE( cloned->getNextChunk( BSON( "a" << 10 << "b" << 0 ), &min, &max ));
+ ASSERT_EQUALS( BSON( "a" << 15 << "b" << 0 ), min );
+ ASSERT_EQUALS( BSON( "a" << 18 << "b" << 0 ), max );
+
+ ASSERT_FALSE( cloned->getNextChunk( BSON( "a" << 15 << "b" << 0 ), &min, &max ));
+ ASSERT_EQUALS( BSON( "a" << 18 << "b" << 0 ), min );
+ ASSERT_EQUALS( BSON( "a" << 20 << "b" << 0 ), max );
+
+ ASSERT( cloned->getNextChunk( BSON( "a" << 18 << "b" << 0 ), &min, &max ));
}
};
diff --git a/src/mongo/s/balance.cpp b/src/mongo/s/balance.cpp
index 2cf9d06d131..7e12e1c47b8 100644
--- a/src/mongo/s/balance.cpp
+++ b/src/mongo/s/balance.cpp
@@ -467,6 +467,7 @@ namespace mongo {
conn.done();
warning() << "Skipping balancing round because data inconsistency"
<< " was detected amongst the config servers." << endl;
+ sleepsecs( sleepTime );
continue;
}
diff --git a/src/mongo/s/commands_admin.cpp b/src/mongo/s/commands_admin.cpp
index 91577d33b97..d7061f6fa86 100644
--- a/src/mongo/s/commands_admin.cpp
+++ b/src/mongo/s/commands_admin.cpp
@@ -663,7 +663,7 @@ namespace mongo {
result << "collectionsharded" << ns;
// only initially move chunks when using a hashed shard key
- if (isHashedShardKey) {
+ if (isHashedShardKey && isEmpty) {
// Reload the new config info. If we created more than one initial chunk, then
// we need to move them around to balance.
diff --git a/src/mongo/s/config.cpp b/src/mongo/s/config.cpp
index b8698a10687..9e042938607 100644
--- a/src/mongo/s/config.cpp
+++ b/src/mongo/s/config.cpp
@@ -34,6 +34,8 @@
#include "mongo/s/type_chunk.h"
#include "mongo/s/type_collection.h"
#include "mongo/s/type_database.h"
+#include "mongo/s/type_locks.h"
+#include "mongo/s/type_lockpings.h"
#include "mongo/s/type_settings.h"
#include "mongo/s/type_shard.h"
#include "mongo/util/net/message.h"
@@ -985,6 +987,16 @@ namespace mongo {
conn->get()->ensureIndex(ShardType::ConfigNS, BSON(ShardType::host() << 1), true);
+ conn->get()->ensureIndex(LocksType::ConfigNS,
+ BSON( LocksType::lockID() << 1 ), true);
+
+ conn->get()->ensureIndex(LockpingsType::ConfigNS,
+ BSON( LockpingsType::ping() << 1 ), false);
+
+ conn->get()->ensureIndex(LocksType::ConfigNS,
+ BSON( LocksType::state() << 1 <<
+ LocksType::process() << 1 ), false);
+
conn->done();
}
catch ( DBException& e ) {
diff --git a/src/mongo/s/d_chunk_manager.cpp b/src/mongo/s/d_chunk_manager.cpp
index 4eb360702bc..98a6d90d341 100644
--- a/src/mongo/s/d_chunk_manager.cpp
+++ b/src/mongo/s/d_chunk_manager.cpp
@@ -426,7 +426,7 @@ namespace mongo {
BSONObj startKey = min;
for ( vector<BSONObj>::const_iterator it = splitKeys.begin() ; it != splitKeys.end() ; ++it ) {
BSONObj split = *it;
- p->_chunksMap[min] = split.getOwned();
+ p->_chunksMap[startKey] = split.getOwned();
p->_chunksMap.insert( make_pair( split.getOwned() , max.getOwned() ) );
p->_version.incMinor();
startKey = split;
diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp
index e6aa728d7a3..5bcfe291519 100644
--- a/src/mongo/s/server.cpp
+++ b/src/mongo/s/server.cpp
@@ -197,6 +197,9 @@ namespace mongo {
signal(SIGTERM, sighandler);
signal(SIGINT, sighandler);
+#if defined(SIGXCPU)
+ signal(SIGXCPU, sighandler);
+#endif
#if defined(SIGQUIT)
signal( SIGQUIT , printStackAndExit );
diff --git a/src/mongo/shell/replsettest.js b/src/mongo/shell/replsettest.js
index a9c8c36b050..6b84da39a06 100644
--- a/src/mongo/shell/replsettest.js
+++ b/src/mongo/shell/replsettest.js
@@ -489,12 +489,13 @@ ReplSetTest.prototype.initiate = function( cfg , initCmd , timeout ) {
}
}
-ReplSetTest.prototype.reInitiate = function() {
+ReplSetTest.prototype.reInitiate = function(timeout) {
var master = this.nodes[0];
var c = master.getDB("local")['system.replset'].findOne();
var config = this.getReplSetConfig();
+ var timeout = timeout || 60000;
config.version = c.version + 1;
- this.initiate( config , 'replSetReconfig' );
+ this.initiate( config , 'replSetReconfig', timeout );
}
ReplSetTest.prototype.getLastOpTimeWritten = function() {
diff --git a/src/mongo/shell/shell_utils_extended.cpp b/src/mongo/shell/shell_utils_extended.cpp
index 1e68882a3bc..2808bab7688 100644
--- a/src/mongo/shell/shell_utils_extended.cpp
+++ b/src/mongo/shell/shell_utils_extended.cpp
@@ -26,6 +26,7 @@
#include "mongo/util/file.h"
#include "mongo/util/md5.hpp"
#include "mongo/util/net/sock.h"
+#include "mongo/util/scopeguard.h"
#include "mongo/util/text.h"
namespace mongo {
@@ -144,6 +145,7 @@ namespace mongo {
stringstream ss;
FILE* f = fopen(e.valuestrsafe(), "rb");
uassert(CANT_OPEN_FILE, "couldn't open file", f );
+ ON_BLOCK_EXIT(fclose, f);
md5digest d;
md5_state_t st;
diff --git a/src/mongo/util/file_allocator.cpp b/src/mongo/util/file_allocator.cpp
index e59bce6934b..7876744f7d5 100644
--- a/src/mongo/util/file_allocator.cpp
+++ b/src/mongo/util/file_allocator.cpp
@@ -39,6 +39,7 @@
#include "mongo/platform/posix_fadvise.h"
#include "mongo/util/mongoutils/str.h"
#include "mongo/util/paths.h"
+#include "mongo/util/processinfo.h"
#include "mongo/util/time_support.h"
#include "mongo/util/timer.h"
@@ -186,6 +187,15 @@ namespace mongo {
size - 1 == lseek(fd, size - 1, SEEK_SET) );
uassert( 10442 , str::stream() << "Unable to allocate new file of size " << size << ' ' << errnoWithDescription(),
1 == write(fd, "", 1) );
+
+ // File expansion is completed here. Do not do the zeroing out on OS-es where there
+ // is no risk of triggering allocation-related bugs such as
+ // http://support.microsoft.com/kb/2731284.
+ //
+ if (!ProcessInfo::isDataFileZeroingNeeded()) {
+ return;
+ }
+
lseek(fd, 0, SEEK_SET);
const long z = 256 * 1024;
diff --git a/src/mongo/util/processinfo.h b/src/mongo/util/processinfo.h
index 8e9044d39e4..03fcdd85993 100644
--- a/src/mongo/util/processinfo.h
+++ b/src/mongo/util/processinfo.h
@@ -92,6 +92,11 @@ namespace mongo {
bool hasNumaEnabled() const { return sysInfo().hasNuma; }
/**
+ * Determine if file zeroing is necessary for newly allocated data files.
+ */
+ static bool isDataFileZeroingNeeded() { return systemInfo->fileZeroNeeded; }
+
+ /**
* Get extra system stats
*/
void appendSystemDetails( BSONObjBuilder& details ) const {
@@ -145,12 +150,19 @@ namespace mongo {
string cpuArch;
bool hasNuma;
BSONObj _extraStats;
+
+ // This is an OS specific value, which determines whether files should be zero-filled
+ // at allocation time in order to avoid Microsoft KB 2731284.
+ //
+ bool fileZeroNeeded;
+
SystemInfo() :
addrSize( 0 ),
memSize( 0 ),
numCores( 0 ),
pageSize( 0 ),
- hasNuma( false ) {
+ hasNuma( false ),
+ fileZeroNeeded (false) {
// populate SystemInfo during construction
collectSystemInfo();
}
diff --git a/src/mongo/util/processinfo_win32.cpp b/src/mongo/util/processinfo_win32.cpp
index 3f42eb12698..d6f88e88a59 100644
--- a/src/mongo/util/processinfo_win32.cpp
+++ b/src/mongo/util/processinfo_win32.cpp
@@ -100,7 +100,7 @@ namespace mongo {
void ProcessInfo::SystemInfo::collectSystemInfo() {
BSONObjBuilder bExtra;
stringstream verstr;
- OSVERSIONINFOEX osvi; // os version
+ OSVERSIONINFOEX osvi; // os version
MEMORYSTATUSEX mse; // memory stats
SYSTEM_INFO ntsysinfo; //system stats
@@ -142,6 +142,15 @@ namespace mongo {
osName += "Windows 7";
else
osName += "Windows Server 2008 R2";
+
+ // Windows 6.1 is either Windows 7 or Windows 2008 R2. There is no SP2 for
+ // either of these two operating systems, but the check will hold if one
+ // were released. This code assumes that SP2 will include fix for
+ // http://support.microsoft.com/kb/2731284.
+ //
+ if ((osvi.wServicePackMajor >= 0) && (osvi.wServicePackMajor < 2)) {
+ fileZeroNeeded = true;
+ }
break;
case 0:
if ( osvi.wProductType == VER_NT_WORKSTATION )
diff --git a/src/mongo/util/version.cpp b/src/mongo/util/version.cpp
index a5622e4dbbb..e27c3843a4a 100644
--- a/src/mongo/util/version.cpp
+++ b/src/mongo/util/version.cpp
@@ -47,7 +47,7 @@ namespace mongo {
* 1.2.3-rc4-pre-
* If you really need to do something else you'll need to fix _versionArray()
*/
- const char versionString[] = "2.4.9";
+ const char versionString[] = "2.4.10";
// See unit test for example outputs
BSONArray toVersionArray(const char* version){
diff --git a/src/third_party/v8/src/spaces-inl.h b/src/third_party/v8/src/spaces-inl.h
index ed78fc7a15f..d84019084cc 100644
--- a/src/third_party/v8/src/spaces-inl.h
+++ b/src/third_party/v8/src/spaces-inl.h
@@ -164,7 +164,7 @@ Page* Page::Initialize(Heap* heap,
Executability executable,
PagedSpace* owner) {
Page* page = reinterpret_cast<Page*>(chunk);
- ASSERT(chunk->size() <= static_cast<size_t>(kPageSize));
+ ASSERT(page->area_size() <= kNonCodeObjectAreaSize);
ASSERT(chunk->owner() == owner);
owner->IncreaseCapacity(page->area_size());
owner->Free(page->area_start(), page->area_size());