summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaszlo Boszormenyi (GCS) <gcs@debian.org>2013-10-18 10:31:13 +0200
committerLaszlo Boszormenyi (GCS) <gcs@debian.org>2013-10-18 10:31:13 +0200
commit65585c90b12d6523bea75a2aebaae2a2fdf9e641 (patch)
treeccb3081edfe67f988844af661a2bf93aa95ae09f
parente3904bf97e74cbbe5dde6b3abc3e797ad7d26b5d (diff)
Imported Upstream version 2.4.6upstream/2.4.6
-rw-r--r--SConstruct3
-rwxr-xr-xbuildscripts/smoke.py6
-rwxr-xr-xdistsrc/client/SConstruct7
-rw-r--r--doxygenConfig2
-rw-r--r--jstests/connection_string_validation.js99
-rw-r--r--jstests/null_field_name.js8
-rw-r--r--jstests/repl/repl4.js5
-rw-r--r--jstests/replsets/chaining.js52
-rw-r--r--jstests/replsets/replset9.js2
-rw-r--r--jstests/replsets/stepdown.js1
-rw-r--r--jstests/sharding/auto2.js3
-rw-r--r--jstests/sharding/count1.js6
-rw-r--r--jstests/sharding/index1.js1
-rw-r--r--jstests/sharding/key_many.js2
-rw-r--r--jstests/sharding/key_string.js4
-rw-r--r--jstests/sharding/read_pref_cmd.js5
-rw-r--r--jstests/sharding/remove2.js6
-rw-r--r--jstests/sharding/sort1.js6
-rw-r--r--jstests/sharding/split_with_force.js60
-rw-r--r--jstests/sharding/split_with_force_small.js68
-rw-r--r--jstests/slowNightly/ipv6_connection_string_validation.js139
-rw-r--r--jstests/slowNightly/sharding_migrate_large_docs.js63
-rwxr-xr-xrpm/mongo.spec2
-rw-r--r--src/SConscript.client27
-rw-r--r--src/mongo/SConscript1
-rw-r--r--src/mongo/client/dbclient_rs.cpp263
-rw-r--r--src/mongo/client/dbclient_rs.h17
-rw-r--r--src/mongo/db/clientcursor.cpp30
-rw-r--r--src/mongo/db/clientcursor.h5
-rw-r--r--src/mongo/db/dbcommands_admin.cpp37
-rw-r--r--src/mongo/db/dur.cpp10
-rw-r--r--src/mongo/db/extsort.cpp1
-rw-r--r--src/mongo/db/fts/fts_matcher.cpp13
-rw-r--r--src/mongo/db/mongod.vcxproj6
-rw-r--r--src/mongo/db/mongod.vcxproj.filters18
-rw-r--r--src/mongo/db/mongod_sm.vcxproj6
-rw-r--r--src/mongo/db/mongod_sm.vcxproj.filters18
-rw-r--r--src/mongo/db/oplog.cpp2
-rw-r--r--src/mongo/db/repl/bgsync.cpp123
-rw-r--r--src/mongo/db/repl/rs_rollback.cpp34
-rw-r--r--src/mongo/db/repl/rs_sync.cpp5
-rw-r--r--src/mongo/db/ttl.cpp8
-rw-r--r--src/mongo/dbtests/jsobjtests.cpp6
-rw-r--r--src/mongo/dbtests/sharding.cpp5
-rw-r--r--src/mongo/dbtests/test.vcxproj6
-rwxr-xr-xsrc/mongo/dbtests/test.vcxproj.filters18
-rw-r--r--src/mongo/dbtests/test_sm.vcxproj6
-rw-r--r--src/mongo/dbtests/test_sm.vcxproj.filters18
-rw-r--r--src/mongo/platform/SConscript7
-rw-r--r--src/mongo/platform/backtrace.cpp215
-rw-r--r--src/mongo/platform/backtrace.h43
-rw-r--r--src/mongo/platform/posix_fadvise.cpp56
-rw-r--r--src/mongo/platform/posix_fadvise.h41
-rw-r--r--src/mongo/platform/strcasestr.cpp105
-rw-r--r--src/mongo/platform/strcasestr.h35
-rw-r--r--src/mongo/s/balance.cpp10
-rw-r--r--src/mongo/s/balancer_policy.cpp14
-rw-r--r--src/mongo/s/chunk_diff.hpp15
-rw-r--r--src/mongo/s/config_server_checker_service.cpp62
-rw-r--r--src/mongo/s/config_server_checker_service.h31
-rw-r--r--src/mongo/s/d_migrate.cpp107
-rw-r--r--src/mongo/s/d_split.cpp17
-rw-r--r--src/mongo/s/d_state.cpp4
-rw-r--r--src/mongo/s/mongos.vcxproj8
-rwxr-xr-xsrc/mongo/s/mongos.vcxproj.filters24
-rw-r--r--src/mongo/s/mongos_sm.vcxproj8
-rw-r--r--src/mongo/s/mongos_sm.vcxproj.filters24
-rw-r--r--src/mongo/s/server.cpp10
-rw-r--r--src/mongo/scripting/engine_v8.cpp10
-rw-r--r--src/mongo/scripting/engine_v8.h2
-rw-r--r--src/mongo/shell/dbshell.cpp6
-rw-r--r--src/mongo/shell/mongo.js64
-rwxr-xr-xsrc/mongo/shell/mongo.vcxproj18
-rw-r--r--src/mongo/shell/mongo.vcxproj.filters30
-rw-r--r--src/mongo/shell/mongo_sm.vcxproj18
-rw-r--r--src/mongo/shell/mongo_sm.vcxproj.filters30
-rw-r--r--src/mongo/tools/tool.cpp10
-rw-r--r--src/mongo/util/file_allocator.cpp9
-rw-r--r--src/mongo/util/log.cpp1
-rw-r--r--src/mongo/util/logfile.cpp16
-rw-r--r--src/mongo/util/mmap_posix.cpp5
-rw-r--r--src/mongo/util/net/hostandport.h2
-rw-r--r--src/mongo/util/net/sock.cpp8
-rw-r--r--src/mongo/util/net/sock_test.cpp11
-rw-r--r--src/mongo/util/net/ssl_manager.cpp15
-rw-r--r--src/mongo/util/processinfo_sunos5.cpp154
-rw-r--r--src/mongo/util/signal_handlers.cpp17
-rw-r--r--src/mongo/util/stack_introspect.cpp18
-rw-r--r--src/mongo/util/stacktrace.cpp97
-rw-r--r--src/mongo/util/stacktrace.h15
-rw-r--r--src/mongo/util/version.cpp2
-rwxr-xr-xsrc/third_party/s2/util/math/SConscript4
92 files changed, 2141 insertions, 490 deletions
diff --git a/SConstruct b/SConstruct
index 5fb0e83f492..69a374693bc 100644
--- a/SConstruct
+++ b/SConstruct
@@ -839,7 +839,8 @@ def doConfigure(myenv):
if (conf.CheckCXXHeader( "execinfo.h" ) and
conf.CheckDeclaration('backtrace', includes='#include <execinfo.h>') and
- conf.CheckDeclaration('backtrace_symbols', includes='#include <execinfo.h>')):
+ conf.CheckDeclaration('backtrace_symbols', includes='#include <execinfo.h>') and
+ conf.CheckDeclaration('backtrace_symbols_fd', includes='#include <execinfo.h>')):
myenv.Append( CPPDEFINES=[ "MONGO_HAVE_EXECINFO_BACKTRACE" ] )
diff --git a/buildscripts/smoke.py b/buildscripts/smoke.py
index b70d5e109a9..ebc0641e538 100755
--- a/buildscripts/smoke.py
+++ b/buildscripts/smoke.py
@@ -359,9 +359,6 @@ def skipTest(path):
if small_oplog: # For tests running in parallel
if basename in ["cursor8.js", "indexh.js", "dropdb.js", "connections_opened.js", "opcounters.js"]:
return True
- if os.sys.platform == "sunos5":
- if basename == "geo_update_btree.js":
- return True
if auth or keyFile: # For tests running with auth
# Skip any tests that run with auth explicitly
if parentDir == "auth" or "auth" in basename:
@@ -386,7 +383,8 @@ def skipTest(path):
("jstests", "bench_test1.js"),
("jstests", "bench_test2.js"),
("jstests", "bench_test3.js"),
- ("jstests", "drop2.js") # SERVER-8589
+ ("jstests", "drop2.js"), # SERVER-8589
+ ("jstests", "killop.js") # SERVER-10128
]
if os.path.join(parentDir,basename) in [ os.path.join(*test) for test in authTestsToSkip ]:
diff --git a/distsrc/client/SConstruct b/distsrc/client/SConstruct
index 17fa954fc9d..c8d95630ea6 100755
--- a/distsrc/client/SConstruct
+++ b/distsrc/client/SConstruct
@@ -93,6 +93,13 @@ for lib in boostLibs:
env['MONGO_BUILD_SASL_CLIENT'] = conf.CheckLibWithHeader(
"sasl2", "sasl/sasl.h", "C", "sasl_version_info(0, 0, 0, 0, 0, 0);", autoadd=False)
+if (conf.CheckCXXHeader( "execinfo.h" ) and
+ conf.CheckDeclaration('backtrace', includes='#include <execinfo.h>') and
+ conf.CheckDeclaration('backtrace_symbols', includes='#include <execinfo.h>') and
+ conf.CheckDeclaration('backtrace_symbols_fd', includes='#include <execinfo.h>')):
+
+ env.Append( CPPDEFINES=[ "MONGO_HAVE_EXECINFO_BACKTRACE" ] )
+
conf.Finish()
class InstallSetup:
diff --git a/doxygenConfig b/doxygenConfig
index 118f4bed67e..1eebb6c10b9 100644
--- a/doxygenConfig
+++ b/doxygenConfig
@@ -3,7 +3,7 @@
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = MongoDB
-PROJECT_NUMBER = 2.4.5
+PROJECT_NUMBER = 2.4.6
OUTPUT_DIRECTORY = docs/doxygen
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
diff --git a/jstests/connection_string_validation.js b/jstests/connection_string_validation.js
new file mode 100644
index 00000000000..fe15ea6808c
--- /dev/null
+++ b/jstests/connection_string_validation.js
@@ -0,0 +1,99 @@
+// Test validation of connection strings passed to the JavaScript "connect()" function.
+// Related to SERVER-8030.
+
+var goodStrings = [
+ "localhost:27999/test",
+ "127.0.0.1:27999/test"
+ ];
+
+var badStrings = [
+ { s: undefined, r: /^Missing connection string$/ },
+ { s: 7, r: /^Incorrect type/ },
+ { s: null, r: /^Incorrect type/ },
+ { s: "", r: /^Empty connection string$/ },
+ { s: " ", r: /^Empty connection string$/ },
+ { s: ":", r: /^Missing host name/ },
+ { s: "/", r: /^Missing host name/ },
+ { s: ":/", r: /^Missing host name/ },
+ { s: ":/test", r: /^Missing host name/ },
+ { s: ":27999/", r: /^Missing host name/ },
+ { s: ":27999/test", r: /^Missing host name/ },
+ { s: "/test", r: /^Missing host name/ },
+ { s: "localhost:/test", r: /^Missing port number/ },
+ { s: "127.0.0.1:/test", r: /^Missing port number/ },
+ { s: "127.0.0.1:cat/test", r: /^Invalid port number/ },
+ { s: "127.0.0.1:1cat/test", r: /^Invalid port number/ },
+ { s: "127.0.0.1:123456/test", r: /^Invalid port number/ },
+ { s: "127.0.0.1:65536/test", r: /^Invalid port number/ },
+ { s: "::1:65536/test", r: /^Invalid port number/ },
+ { s: "127.0.0.1:27999/", r: /^Missing database name/ },
+ { s: "::1:27999/", r: /^Missing database name/ }
+ ];
+
+function testGood(i, connectionString) {
+ print("\nTesting good connection string " + i + " (\"" + connectionString + "\") ...");
+ var gotException = false;
+ var exception;
+ try {
+ var connectDB = connect(connectionString);
+ connectDB = null;
+ }
+ catch (e) {
+ gotException = true;
+ exception = e;
+ }
+ if (!gotException) {
+ print("Good connection string " + i +
+ " (\"" + connectionString + "\") correctly validated");
+ return;
+ }
+ var message = "FAILED to correctly validate goodString " + i +
+ " (\"" + connectionString + "\"): exception was \"" + tojson(exception) + "\"";
+ doassert(message);
+}
+
+function testBad(i, connectionString, errorRegex) {
+ print("\nTesting bad connection string " + i + " (\"" + connectionString + "\") ...");
+ var gotException = false;
+ var gotCorrectErrorText = false;
+ var exception;
+ try {
+ var connectDB = connect(connectionString);
+ connectDB = null;
+ }
+ catch (e) {
+ gotException = true;
+ exception = e;
+ if (errorRegex.test(e.message)) {
+ gotCorrectErrorText = true;
+ }
+ }
+ if (gotCorrectErrorText) {
+ print("Bad connection string " + i + " (\"" + connectionString +
+ "\") correctly rejected:\n" + tojson(exception));
+ return;
+ }
+ var message = "FAILED to generate correct exception for badString " + i +
+ " (\"" + connectionString + "\"): ";
+ if (gotException) {
+ message += "exception was \"" + tojson(exception) +
+ "\", it should have matched \"" + errorRegex.toString() + "\"";
+ }
+ else {
+ message += "no exception was thrown";
+ }
+ doassert(message);
+}
+
+var i;
+jsTest.log("TESTING " + goodStrings.length + " good connection strings");
+for (i = 0; i < goodStrings.length; ++i) {
+ testGood(i, goodStrings[i]);
+}
+
+jsTest.log("TESTING " + badStrings.length + " bad connection strings");
+for (i = 0; i < badStrings.length; ++i) {
+ testBad(i, badStrings[i].s, badStrings[i].r);
+}
+
+jsTest.log("SUCCESSFUL test completion");
diff --git a/jstests/null_field_name.js b/jstests/null_field_name.js
new file mode 100644
index 00000000000..7fa14b0a1bc
--- /dev/null
+++ b/jstests/null_field_name.js
@@ -0,0 +1,8 @@
+// SERVER-10313: Test that null char in field name causes an error when converting to bson
+assert.throws( function () { Object.bsonsize({"a\0":1}); },
+ null,
+ "null char in field name");
+
+assert.throws( function () { Object.bsonsize({"\0asdf":1}); },
+ null,
+ "null char in field name"); \ No newline at end of file
diff --git a/jstests/repl/repl4.js b/jstests/repl/repl4.js
index 56719b73a6c..78836061201 100644
--- a/jstests/repl/repl4.js
+++ b/jstests/repl/repl4.js
@@ -35,4 +35,7 @@ doTest = function() {
soonCount( "c", "c", 2 );
}
-doTest();
+// Disabled because of SERVER-10344
+if (false) {
+ doTest();
+}
diff --git a/jstests/replsets/chaining.js b/jstests/replsets/chaining.js
deleted file mode 100644
index d424de5e3fc..00000000000
--- a/jstests/replsets/chaining.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// Test that chaining position propegation (percolate) still works properly
-// in the face of socket exceptions
-
-function assertGLEOK(status) {
- assert(status.ok && status.err === null,
- "Expected OK status object; found " + tojson(status));
-}
-
-var replTest = new ReplSetTest({name: 'testSet', nodes: 3});
-var nodes = replTest.startSet();
-var hostnames = replTest.nodeList();
-replTest.initiate(
- {
- "_id" : "testSet",
- "members" : [
- {"_id" : 0, "host" : hostnames[0], "priority" : 2},
- {"_id" : 1, "host" : hostnames[1]},
- {"_id" : 2, "host" : hostnames[2]}
- ],
- }
-);
-
-replTest.awaitReplication();
-
-replTest.bridge();
-replTest.partition(0, 2);
-
-// Now 0 and 2 can't see each other, so 2 should chain through 1 to reach 0.
-
-var master = replTest.getMaster();
-var cdb = master.getDB("chaining");
-var admin = nodes[1].getDB("admin");
-cdb.foo.insert({a:1});
-assertGLEOK(cdb.getLastErrorObj());
-replTest.awaitReplication();
-
-var result = admin.runCommand( { configureFailPoint: 'rsChaining1', mode: { times : 1 } } );
-assert.eq(1, result.ok, 'rsChaining1');
-cdb.foo.insert({a:1});
-assertGLEOK(cdb.getLastErrorObj());
-replTest.awaitReplication();
-admin.runCommand( { configureFailPoint: 'rsChaining2', mode: { times : 1 } } );
-assert.eq(1, result.ok, 'rsChaining2');
-cdb.foo.insert({a:1});
-assertGLEOK(cdb.getLastErrorObj());
-replTest.awaitReplication();
-admin.runCommand( { configureFailPoint: 'rsChaining3', mode: { times : 1 } } );
-assert.eq(1, result.ok, 'rsChaining3');
-cdb.foo.insert({a:1});
-assertGLEOK(cdb.getLastErrorObj());
-replTest.awaitReplication();
-replTest.stopSet();
diff --git a/jstests/replsets/replset9.js b/jstests/replsets/replset9.js
index 4398633e972..7bf5254a384 100644
--- a/jstests/replsets/replset9.js
+++ b/jstests/replsets/replset9.js
@@ -1,6 +1,6 @@
-var rt = new ReplSetTest( { name : "replset9tests" , nodes: 1, oplogSize: 255 } );
+var rt = new ReplSetTest( { name : "replset9tests" , nodes: 1, oplogSize: 300 } );
var nodes = rt.startSet();
rt.initiate();
diff --git a/jstests/replsets/stepdown.js b/jstests/replsets/stepdown.js
index 4e19daa59aa..5a2b576bf88 100644
--- a/jstests/replsets/stepdown.js
+++ b/jstests/replsets/stepdown.js
@@ -73,6 +73,7 @@ catch (e) {
}
print("\nawait");
+replTest.awaitSecondaryNodes(90000);
replTest.awaitReplication();
// 31000 may have just voted for 31001, preventing it from becoming primary for the first 30 seconds
diff --git a/jstests/sharding/auto2.js b/jstests/sharding/auto2.js
index 497a0e549ef..41cb38a4309 100644
--- a/jstests/sharding/auto2.js
+++ b/jstests/sharding/auto2.js
@@ -27,7 +27,8 @@ for ( j=0; j<30; j++ ){
}
assert.eq( i , j * 100 , "setup" );
-s.adminCommand( "connpoolsync" );
+// Until SERVER-9715 is fixed, the sync command must be run on a diff connection
+new Mongo( s.s.host ).adminCommand( "connpoolsync" );
db.getLastError();
print( "done inserting data" );
diff --git a/jstests/sharding/count1.js b/jstests/sharding/count1.js
index 1b338883c31..8d36cd5f6f5 100644
--- a/jstests/sharding/count1.js
+++ b/jstests/sharding/count1.js
@@ -54,7 +54,9 @@ assert.eq( 6 , db.foo.find().count() , "basic count" );
// part 2
s.adminCommand( { split : "test.foo" , find : { name : "joe" } } ); // [Minkey -> allan) , * [allan -> ..)
s.adminCommand( { split : "test.foo" , find : { name : "joe" } } ); // * [allan -> sara) , [sara -> Maxkey)
-s.adminCommand( { split : "test.foo" , find : { name : "joe" } } ); // [alan -> joe) , [joe -> sara]
+s.adminCommand( { split : "test.foo" , find : { name : "joe" } } ); // [alan -> eliot) , [eliot -> sara]
+
+// MINKEY->allan,bob->eliot,joe,mark->sara,MAXKEY
s.printChunks()
@@ -63,7 +65,7 @@ assert.eq( 6 , db.foo.find().count() , "basic count after split " );
assert.eq( 6 , db.foo.find().sort( { name : 1 } ).count() , "basic count after split sorted " );
// part 4
-s.adminCommand( { movechunk : "test.foo" , find : { name : "allan" } , to : secondary.getMongo().name , _waitForDelete : true } );
+s.adminCommand( { movechunk : "test.foo" , find : { name : "eliot" } , to : secondary.getMongo().name , _waitForDelete : true } );
assert.eq( 3 , primary.foo.find().toArray().length , "primary count" );
assert.eq( 3 , secondary.foo.find().toArray().length , "secondary count" );
diff --git a/jstests/sharding/index1.js b/jstests/sharding/index1.js
index e647c27b276..b66d0c405c7 100644
--- a/jstests/sharding/index1.js
+++ b/jstests/sharding/index1.js
@@ -11,6 +11,7 @@ for ( var i = 0; i < 19; i++ ) {
for ( var j = 0; j < 300; j++ ) {
coll.insert( { num : j, x : 1 } )
}
+ assert.eq( null, coll.getDB().getLastError() );
if(i == 0) s.adminCommand( { enablesharding : "" + coll._db } );
diff --git a/jstests/sharding/key_many.js b/jstests/sharding/key_many.js
index 75a9784096f..2246f01b504 100644
--- a/jstests/sharding/key_many.js
+++ b/jstests/sharding/key_many.js
@@ -98,7 +98,7 @@ for ( var i=0; i<types.length; i++ ){
s.adminCommand( { split : longName , find : makeObjectDotted( curT.values[3] ) } );
s.adminCommand( { split : longName , find : makeObjectDotted( curT.values[3] ) } );
- s.adminCommand( { movechunk : longName , find : makeObjectDotted( curT.values[0] ) , to : secondary.getMongo().name, _waitForDelete : true } );
+ s.adminCommand( { movechunk : longName , find : makeObjectDotted( curT.values[2] ) , to : secondary.getMongo().name, _waitForDelete : true } );
s.printChunks();
diff --git a/jstests/sharding/key_string.js b/jstests/sharding/key_string.js
index 990b0456665..f2c0ca209b3 100644
--- a/jstests/sharding/key_string.js
+++ b/jstests/sharding/key_string.js
@@ -24,7 +24,7 @@ s.adminCommand( { split : "test.foo" , find : { name : "joe" } } ); // [Minkey -
s.adminCommand( { split : "test.foo" , find : { name : "joe" } } ); // * [allan -> sara) , [sara -> Maxkey)
s.adminCommand( { split : "test.foo" , find : { name : "joe" } } ); // [alan -> joe) , [joe -> sara]
-s.adminCommand( { movechunk : "test.foo" , find : { name : "allan" } , to : seconday.getMongo().name, _waitForDelete : true, _waitForDelete : true } );
+s.adminCommand( { movechunk : "test.foo" , find : { name : "eliot" } , to : seconday.getMongo().name, _waitForDelete : true, _waitForDelete : true } );
s.printChunks();
@@ -42,7 +42,7 @@ assert.eq( "sara,mark,joe,eliot,bob,allan" , db.foo.find().sort( { name : -1 }
// make sure we can't foce a split on an extreme key
// [allan->joe)
assert.throws( function(){ s.adminCommand( { split : "test.foo" , middle : { name : "allan" } } ) } );
-assert.throws( function(){ s.adminCommand( { split : "test.foo" , middle : { name : "joe" } } ) } );
+assert.throws( function(){ s.adminCommand( { split : "test.foo" , middle : { name : "eliot" } } ) } );
s.stop();
diff --git a/jstests/sharding/read_pref_cmd.js b/jstests/sharding/read_pref_cmd.js
index 320cd035031..d36dcca9abc 100644
--- a/jstests/sharding/read_pref_cmd.js
+++ b/jstests/sharding/read_pref_cmd.js
@@ -1,3 +1,4 @@
+if (0) { // SERVER-10429, SERVER-7533
load("jstests/replsets/rslib.js");
var NODE_COUNT = 2;
@@ -265,7 +266,8 @@ var testAllModes = function(conn, hostList, isMongos) {
});
};
-var st = new ShardingTest({ shards: { rs0: { nodes: NODE_COUNT }}});
+var st = new ShardingTest({shards : {rs0 : {nodes : NODE_COUNT, verbose : 1}},
+ other : {mongosOptions : {verbose : 3}}});
st.stopBalancer();
ReplSetTest.awaitRSClientHosts(st.s, st.rs0.nodes);
@@ -342,3 +344,4 @@ testAllModes(st.s, st.rs0.nodes, true);
st.stop();
+}
diff --git a/jstests/sharding/remove2.js b/jstests/sharding/remove2.js
index daa5077431c..faedbf2b8da 100644
--- a/jstests/sharding/remove2.js
+++ b/jstests/sharding/remove2.js
@@ -35,7 +35,7 @@ removeShard = function(st, replTest) {
var res = directdb.currentOp( { desc: /^clean/ } );
print( "eliot: " + replTest.getPrimary() + "\t" + tojson(res) );
return res.inprog.length == 0;
- }, "never clean", 60000, 1000 );
+ }, "never clean", 5 * 60 * 1000, 1000 );
replTest.getPrimary().getDB( coll.getDB().getName() ).dropDatabase();
print( "Shard removed successfully" );
@@ -59,7 +59,7 @@ addShard = function(st, replTest) {
var x = st.chunkDiff( coll.getName() , coll.getDB().getName() );
print( "chunk diff: " + x );
return x < 2;
- } , "no balance happened", 60000 );
+ } , "no balance happened", 5 * 60 * 1000 );
try {
assert.eq( 300, coll.find().itcount() );
@@ -114,7 +114,7 @@ assert.eq( 300, coll.find().itcount() );
assert.soon( function() {
var x = st.chunkDiff( 'remove2' , "test" ); print( "chunk diff: " + x ); return x < 2;
-} , "no balance happened" );
+} , "no balance happened", 5 * 60 * 1000 );
assert.eq( 300, coll.find().itcount() );
diff --git a/jstests/sharding/sort1.js b/jstests/sharding/sort1.js
index 235e5c0b027..130e71d9020 100644
--- a/jstests/sharding/sort1.js
+++ b/jstests/sharding/sort1.js
@@ -1,5 +1,6 @@
s = new ShardingTest( "sort1" , 2 , 0 , 2 )
+s.stopBalancer();
s.adminCommand( { enablesharding : "test" } );
s.adminCommand( { shardcollection : "test.data" , key : { 'sub.num' : 1 } } );
@@ -20,7 +21,10 @@ db.getLastError();
s.adminCommand( { split : "test.data" , middle : { 'sub.num' : 33 } } )
s.adminCommand( { split : "test.data" , middle : { 'sub.num' : 66 } } )
-s.adminCommand( { movechunk : "test.data" , find : { 'sub.num' : 50 } , to : s.getOther( s.getServer( "test" ) ).name } );
+s.adminCommand({ movechunk : "test.data",
+ find : { 'sub.num' : 50 },
+ to : s.getOther( s.getServer( "test" ) ).name,
+ waitForDelete : true });
assert.lte( 3 , s.config.chunks.find().itcount() , "A1" );
diff --git a/jstests/sharding/split_with_force.js b/jstests/sharding/split_with_force.js
new file mode 100644
index 00000000000..9033abc2402
--- /dev/null
+++ b/jstests/sharding/split_with_force.js
@@ -0,0 +1,60 @@
+//
+// Tests autosplit locations with force : true
+//
+
+var options = { separateConfig : true,
+ chunksize : 1, // MB
+ mongosOptions : { noAutoSplit : "" }
+ };
+
+var st = new ShardingTest({ shards : 1, mongos : 1, other : options });
+st.stopBalancer();
+
+var mongos = st.s0;
+var admin = mongos.getDB( "admin" );
+var config = mongos.getDB( "config" );
+var shardAdmin = st.shard0.getDB( "admin" );
+var coll = mongos.getCollection( "foo.bar" );
+
+assert( admin.runCommand({ enableSharding : coll.getDB() + "" }).ok );
+assert( admin.runCommand({ shardCollection : coll + "", key : { _id : 1 } }).ok );
+assert( admin.runCommand({ split : coll + "", middle : { _id : 0 } }).ok );
+
+jsTest.log( "Insert a bunch of data into a chunk of the collection..." );
+
+for ( var i = 0; i < (250 * 1000) + 10; i++ ) {
+ coll.insert({ _id : i });
+}
+assert.eq( null, coll.getDB().getLastError() );
+
+jsTest.log( "Insert a bunch of data into the rest of the collection..." );
+
+for ( var i = 1; i <= (250 * 1000); i++ ) {
+ coll.insert({ _id : -i });
+}
+assert.eq( null, coll.getDB().getLastError() );
+
+jsTest.log( "Get split points of the chunk using force : true..." );
+
+var maxChunkSizeBytes = 1024 * 1024;
+
+var splitKeys = shardAdmin.runCommand({ splitVector : coll + "",
+ keyPattern : { _id : 1 },
+ min : { _id : 0 },
+ max : { _id : MaxKey },
+ force : true
+ }).splitKeys;
+
+printjson( splitKeys );
+printjson( coll.stats() );
+st.printShardingStatus();
+
+jsTest.log( "Make sure our split is approximately in half..." );
+
+assert.eq( splitKeys.length, 1 );
+var splitKey = splitKeys[0]._id;
+
+assert.gt( splitKey, ((250 * 1000) / 2) - 50 );
+assert.lt( splitKey, ((250 * 1000) / 2) + 50 );
+
+st.stop();
diff --git a/jstests/sharding/split_with_force_small.js b/jstests/sharding/split_with_force_small.js
new file mode 100644
index 00000000000..02abfe6230e
--- /dev/null
+++ b/jstests/sharding/split_with_force_small.js
@@ -0,0 +1,68 @@
+//
+// Tests autosplit locations with force : true, for small collections
+//
+
+var options = { separateConfig : true,
+ chunksize : 1, // MB
+ mongosOptions : { noAutoSplit : "" }
+ };
+
+var st = new ShardingTest({ shards : 1, mongos : 1, other : options });
+st.stopBalancer();
+
+var mongos = st.s0;
+var admin = mongos.getDB( "admin" );
+var config = mongos.getDB( "config" );
+var shardAdmin = st.shard0.getDB( "admin" );
+var coll = mongos.getCollection( "foo.bar" );
+
+assert( admin.runCommand({ enableSharding : coll.getDB() + "" }).ok );
+assert( admin.runCommand({ shardCollection : coll + "", key : { _id : 1 } }).ok );
+assert( admin.runCommand({ split : coll + "", middle : { _id : 0 } }).ok );
+
+jsTest.log( "Insert a bunch of data into the low chunk of a collection," +
+ " to prevent relying on stats." );
+
+var data128k = "x";
+for ( var i = 0; i < 7; i++ ) data128k += data128k;
+
+for ( var i = 0; i < 1024; i++ ) {
+ coll.insert({ _id : -(i + 1) });
+}
+assert.eq( null, coll.getDB().getLastError() );
+
+jsTest.log( "Insert 32 docs into the high chunk of a collection" );
+
+for ( var i = 0; i < 32; i++ ) {
+ coll.insert({ _id : i });
+}
+assert.eq( null, coll.getDB().getLastError() );
+
+jsTest.log( "Split off MaxKey chunk..." );
+
+assert( admin.runCommand({ split : coll + "", middle : { _id : 32 } }).ok );
+
+jsTest.log( "Keep splitting chunk multiple times..." );
+
+st.printShardingStatus();
+
+for ( var i = 0; i < 5; i++ ) {
+ assert( admin.runCommand({ split : coll + "", find : { _id : 0 } }).ok );
+ st.printShardingStatus();
+}
+
+// Make sure we can't split further than 5 (2^5) times
+assert( !admin.runCommand({ split : coll + "", find : { _id : 0 } }).ok );
+
+var chunks = config.chunks.find({ 'min._id' : { $gte : 0, $lt : 32 } }).sort({ min : 1 }).toArray();
+printjson( chunks );
+
+// Make sure the chunks grow by 2x (except the first)
+var nextSize = 1;
+for ( var i = 0; i < chunks.size; i++ ) {
+ assert.eq( coll.count({ _id : { $gte : chunks[i].min._id, $lt : chunks[i].max._id } }),
+ nextSize );
+ if ( i != 0 ) nextSize += nextSize;
+}
+
+st.stop();
diff --git a/jstests/slowNightly/ipv6_connection_string_validation.js b/jstests/slowNightly/ipv6_connection_string_validation.js
new file mode 100644
index 00000000000..597bc1809dd
--- /dev/null
+++ b/jstests/slowNightly/ipv6_connection_string_validation.js
@@ -0,0 +1,139 @@
+// Test validation of IPv6 connection strings passed to the JavaScript "connect()" function.
+// Related to SERVER-8030.
+
+// This file runs in two modes: outer and inner. This is to enable testing with --ipv6.
+// The outer mode test starts a mongod with --ipv6 and then starts a mongo shell with --ipv6
+// and a command line to run the test in inner_mode. The inner mode test is the actual test.
+
+if ("undefined" == typeof inner_mode) {
+
+ // Start a mongod with --ipv6
+ port = allocatePorts( 1 )[ 0 ];
+ var baseName = "jstests_slowNightly_ipv6_connection_string_validation";
+ jsTest.log("Outer mode test starting mongod with --ipv6");
+ var mongod = startMongod( "--port", port, "--ipv6", "--dbpath", "/data/db/" + baseName );
+ var args = [ "mongo", "--nodb", "--ipv6",
+ "--eval", "inner_mode=true;port=" + port + ";",
+ "jstests/slowNightly/ipv6_connection_string_validation.js" ];
+
+ // Start another shell running this test in "inner" mode
+ jsTest.log("Outer mode test starting inner mode test");
+ var exitCode = _runMongoProgram.apply(null, args);
+ jsTest.log("Inner mode test finished, exit code was " + exitCode);
+
+ // Stop the server we started
+ jsTest.log("Outer mode test stopping server");
+ stopMongod(port, 15);
+
+ // Pass the inner test's exit code back as the outer test's exit code
+ quit(exitCode);
+}
+
+var goodStrings = [
+ "localhost:27999/test",
+ "::1:27999/test",
+ "0:0:0:0:0:0:0:1:27999/test",
+ "0000:0000:0000:0000:0000:0000:0000:0001:27999/test"
+];
+
+var badStrings = [
+ { s: undefined, r: /^Missing connection string$/ },
+ { s: 7, r: /^Incorrect type/ },
+ { s: null, r: /^Incorrect type/ },
+ { s: "", r: /^Empty connection string$/ },
+ { s: " ", r: /^Empty connection string$/ },
+ { s: ":", r: /^Missing host name/ },
+ { s: "/", r: /^Missing host name/ },
+ { s: ":/", r: /^Missing host name/ },
+ { s: ":/test", r: /^Missing host name/ },
+ { s: ":27999/", r: /^Missing host name/ },
+ { s: ":27999/test", r: /^Missing host name/ },
+ { s: "/test", r: /^Missing host name/ },
+ { s: "localhost:/test", r: /^Missing port number/ },
+ { s: "::1:/test", r: /^Missing port number/ },
+ { s: "::1:cat/test", r: /^Invalid port number/ },
+ { s: "::1:1cat/test", r: /^Invalid port number/ },
+ { s: "::1:123456/test", r: /^Invalid port number/ },
+ { s: "::1:65536/test", r: /^Invalid port number/ },
+ { s: "127.0.0.1:65536/test", r: /^Invalid port number/ },
+ { s: "::1:27999/", r: /^Missing database name/ },
+ { s: "127.0.0.1:27999/", r: /^Missing database name/ }
+];
+
+var substitutePort = function(connectionString) {
+ // This will be called with non-strings as well as strings, so we need to catch exceptions
+ try {
+ return connectionString.replace("27999", "" + port);
+ }
+ catch (e) {
+ return connectionString;
+ }
+};
+
+var testGood = function(i, connectionString) {
+ print("\n---\nTesting good connection string " + i + " (\"" + connectionString + "\") ...");
+ var gotException = false;
+ var exception;
+ try {
+ var connectDB = connect(connectionString);
+ connectDB = null;
+ }
+ catch (e) {
+ gotException = true;
+ exception = e;
+ }
+ if (!gotException) {
+ print("Good connection string " + i +
+ " (\"" + connectionString + "\") correctly validated");
+ return;
+ }
+ var message = "FAILED to correctly validate goodString " + i +
+ " (\"" + connectionString + "\"): exception was \"" + tojson(exception) + "\"";
+ doassert(message);
+};
+
+var testBad = function(i, connectionString, errorRegex) {
+ print("\n---\nTesting bad connection string " + i + " (\"" + connectionString + "\") ...");
+ var gotException = false;
+ var gotCorrectErrorText = false;
+ var exception;
+ try {
+ var connectDB = connect(connectionString);
+ connectDB = null;
+ }
+ catch (e) {
+ gotException = true;
+ exception = e;
+ if (errorRegex.test(e.message)) {
+ gotCorrectErrorText = true;
+ }
+ }
+ if (gotCorrectErrorText) {
+ print("Bad connection string " + i + " (\"" + connectionString +
+ "\") correctly rejected:\n" + tojson(exception));
+ return;
+ }
+ var message = "FAILED to generate correct exception for badString " + i +
+ " (\"" + connectionString + "\"): ";
+ if (gotException) {
+ message += "exception was \"" + tojson(exception) +
+ "\", it should have matched \"" + errorRegex.toString() + "\"";
+ }
+ else {
+ message += "no exception was thrown";
+ }
+ doassert(message);
+};
+
+var i;
+jsTest.log("TESTING " + goodStrings.length + " good connection strings");
+for (i = 0; i < goodStrings.length; ++i) {
+ testGood(i, substitutePort(goodStrings[i]));
+}
+
+jsTest.log("TESTING " + badStrings.length + " bad connection strings");
+for (i = 0; i < badStrings.length; ++i) {
+ testBad(i, substitutePort(badStrings[i].s), badStrings[i].r);
+}
+
+jsTest.log("SUCCESSFUL test completion");
diff --git a/jstests/slowNightly/sharding_migrate_large_docs.js b/jstests/slowNightly/sharding_migrate_large_docs.js
new file mode 100644
index 00000000000..6b2e7faa56b
--- /dev/null
+++ b/jstests/slowNightly/sharding_migrate_large_docs.js
@@ -0,0 +1,63 @@
+//
+// Tests migration behavior of large documents
+//
+
+var st = new ShardingTest({ shards : 2, mongos : 1,
+ other : { separateConfig : true,
+ mongosOptions : { noAutoSplit : "" },
+ shardOptions : { /* binVersion : "latest" */ } } });
+st.stopBalancer()
+
+var mongos = st.s0;
+var coll = mongos.getCollection( "foo.bar" );
+var admin = mongos.getDB( "admin" );
+var shards = mongos.getCollection( "config.shards" ).find().toArray();
+var shardAdmin = st.shard0.getDB( "admin" );
+
+assert( admin.runCommand({ enableSharding : coll.getDB() + "" }).ok );
+printjson( admin.runCommand({ movePrimary : coll.getDB() + "", to : shards[0]._id }) );
+assert( admin.runCommand({ shardCollection : coll + "", key : { _id : 1 } }).ok );
+assert( admin.runCommand({ split : coll + "", middle : { _id : 0 } }).ok );
+
+jsTest.log( "Preparing large insert..." );
+
+var data1MB = "x"
+while ( data1MB.length < 1024 * 1024 )
+ data1MB += data1MB;
+
+var data15MB = "";
+for ( var i = 0; i < 15; i++ ) data15MB += data1MB;
+
+var data15PlusMB = data15MB;
+for ( var i = 0; i < 1023 * 1024; i++ ) data15PlusMB += "x";
+
+print("~15MB object size is : " + Object.bsonsize({ _id : 0, d : data15PlusMB }));
+
+jsTest.log( "Inserting docs of large and small sizes..." );
+
+// Two large docs next to each other
+coll.insert({ _id : -2, d : data15PlusMB });
+coll.insert({ _id : -1, d : data15PlusMB });
+
+// Docs of assorted sizes
+coll.insert({ _id : 0, d : "x" });
+coll.insert({ _id : 1, d : data15PlusMB });
+coll.insert({ _id : 2, d : "x" });
+coll.insert({ _id : 3, d : data15MB });
+coll.insert({ _id : 4, d : "x" });
+coll.insert({ _id : 5, d : data1MB });
+coll.insert({ _id : 6, d : "x" });
+
+assert.eq( null, coll.getDB().getLastError() );
+assert.eq( 9, coll.find().itcount() );
+
+jsTest.log( "Starting migration..." );
+
+assert( admin.runCommand({ moveChunk : coll + "", find : { _id : 0 }, to : shards[1]._id }).ok );
+assert( admin.runCommand({ moveChunk : coll + "", find : { _id : -1 }, to : shards[1]._id }).ok );
+
+assert.eq( 9, coll.find().itcount() );
+
+jsTest.log( "DONE!" );
+
+st.stop();
diff --git a/rpm/mongo.spec b/rpm/mongo.spec
index 7610f421e96..4b8185a0055 100755
--- a/rpm/mongo.spec
+++ b/rpm/mongo.spec
@@ -1,7 +1,7 @@
Name: mongo-10gen
Conflicts: mongo, mongo-10gen-unstable
Obsoletes: mongo-stable
-Version: 2.4.0
+Version: 2.4.6
Release: mongodb_1%{?dist}
Summary: mongo client shell and tools
License: AGPL 3.0
diff --git a/src/SConscript.client b/src/SConscript.client
index e30c73fcbb4..ff959e95f27 100644
--- a/src/SConscript.client
+++ b/src/SConscript.client
@@ -2,6 +2,8 @@
# This SConscript describes build and install rules for the Mongo C++ driver and associated exmaple
# programs.
+import os
+
Import('env has_option installSetup use_system_version_of_library')
Import('nix linux darwin windows')
@@ -52,6 +54,8 @@ clientSourceBasic = [
'mongo/db/namespace.cpp',
'mongo/db/dbmessage.cpp',
'mongo/pch.cpp',
+ 'mongo/platform/backtrace.cpp',
+ 'mongo/platform/posix_fadvise.cpp',
'mongo/platform/random.cpp',
'mongo/util/assert_util.cpp',
'mongo/util/background.cpp',
@@ -82,7 +86,6 @@ clientSourceBasic = [
'mongo/util/net/ssl_manager.cpp',
'mongo/util/password.cpp',
'mongo/util/processinfo.cpp',
- env.File('mongo/util/processinfo_${PYSYSPLATFORM}.cpp'),
'mongo/util/ramlog.cpp',
'mongo/util/signal_handlers.cpp',
'mongo/util/stringutils.cpp',
@@ -98,14 +101,28 @@ clientSourceBasic = [
clientSourceSasl = ['mongo/client/sasl_client_authenticate_impl.cpp',
'mongo/client/sasl_client_session.cpp']
-clientSourceAll = clientSourceBasic + clientSourceSasl
+clientSourceProcessInfo = [
+ 'mongo/util/processinfo_darwin.cpp',
+ 'mongo/util/processinfo_freebsd.cpp',
+ 'mongo/util/processinfo_linux2.cpp',
+ 'mongo/util/processinfo_none.cpp',
+ 'mongo/util/processinfo_sunos5.cpp',
+ 'mongo/util/processinfo_win32.cpp'
+]
+
+clientSourceAll = clientSourceBasic + clientSourceSasl + clientSourceProcessInfo
usingSasl = env['MONGO_BUILD_SASL_CLIENT']
+clientSource = list(clientSourceBasic)
if usingSasl:
- clientSource = clientSourceAll
-else:
- clientSource = clientSourceBasic
+ clientSource += clientSourceSasl
+
+processInfoPlatformFile = env.File( "mongo/util/processinfo_${PYSYSPLATFORM}.cpp" )
+# NOTE: See comment about similar code in src/mongo/SConscript
+if not os.path.exists( str( processInfoPlatformFile ) ):
+ processInfoPlatformFile = env.File( "mongo/util/processinfo_none.cpp" )
+clientSource += [processInfoPlatformFile]
exampleSourceMap = [
('authTest', 'mongo/client/examples/authTest.cpp'),
diff --git a/src/mongo/SConscript b/src/mongo/SConscript
index 27067e32e9d..816a6bfacf8 100644
--- a/src/mongo/SConscript
+++ b/src/mongo/SConscript
@@ -479,6 +479,7 @@ mongosLibraryFiles = [
"s/commands_public.cpp",
"s/request.cpp",
"s/client_info.cpp",
+ "s/config_server_checker_service.cpp",
"s/cursors.cpp",
"s/s_only.cpp",
"s/balance.cpp",
diff --git a/src/mongo/client/dbclient_rs.cpp b/src/mongo/client/dbclient_rs.cpp
index 2bd395d0232..21a5b0810f4 100644
--- a/src/mongo/client/dbclient_rs.cpp
+++ b/src/mongo/client/dbclient_rs.cpp
@@ -31,10 +31,80 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
#include "mongo/util/background.h"
+#include "mongo/util/concurrency/mutex.h" // for StaticObserver
#include "mongo/util/scopeguard.h"
#include "mongo/util/timer.h"
namespace mongo {
+
+ /* Replica Set statics:
+ * If a program (such as one built with the C++ driver) exits (by either calling exit()
+ * or by returning from main()), static objects will be destroyed in the reverse order
+ * of their creation (within each translation unit (source code file)). This makes it
+ * vital that the order be explicitly controlled within the source file so that destroyed
+ * objects never reference objects that have been destroyed earlier.
+ *
+ * The order chosen below is intended to allow safe destruction in reverse order from
+ * construction order:
+ * _setsLock -- mutex protecting _seedServers and _sets, destroyed last
+ * _seedServers -- list (map) of servers
+ * _sets -- list (map) of ReplicaSetMonitors
+ * replicaSetMonitorWatcher -- background job to check Replica Set members
+ * staticObserver -- sentinel to detect process termination
+ *
+ * Related to:
+ * SERVER-8891 -- Simple client fail with segmentation fault in mongoclient library
+ */
+ mongo::mutex ReplicaSetMonitor::_setsLock( "ReplicaSetMonitor" );
+ map<string, vector<HostAndPort> > ReplicaSetMonitor::_seedServers;
+ map<string, ReplicaSetMonitorPtr> ReplicaSetMonitor::_sets;
+
+ // global background job responsible for checking every X amount of time
+ class ReplicaSetMonitorWatcher : public BackgroundJob {
+ public:
+ ReplicaSetMonitorWatcher() : _safego("ReplicaSetMonitorWatcher::_safego") , _started(false) {}
+
+ virtual string name() const { return "ReplicaSetMonitorWatcher"; }
+
+ void safeGo() {
+ // check outside of lock for speed
+ if ( _started )
+ return;
+
+ scoped_lock lk( _safego );
+ if ( _started )
+ return;
+ _started = true;
+
+ go();
+ }
+
+ protected:
+ void run() {
+ log() << "starting" << endl;
+ sleepsecs( 10 );
+ while ( !inShutdown() && !StaticObserver::_destroyingStatics ) {
+ try {
+ ReplicaSetMonitor::checkAll( true );
+ }
+ catch ( std::exception& e ) {
+ error() << "check failed: " << e.what() << endl;
+ }
+ catch ( ... ) {
+ error() << "unknown error" << endl;
+ }
+ sleepsecs( 10 );
+ }
+ }
+
+ mongo::mutex _safego;
+ bool _started;
+
+ } replicaSetMonitorWatcher;
+
+ static StaticObserver staticObserver;
+
+
/*
* Set of commands that can be used with $readPreference
*/
@@ -154,6 +224,10 @@ namespace mongo {
}
if (secOnly && !node.okForSecondaryQueries()) {
+ LOG(3) << "dbclient_rs not selecting " << node
+ << ", not ok for secondary queries ("
+ << ( !node.secondary ? "not secondary" : "hidden" ) << ")"
+ << endl;
continue;
}
@@ -164,8 +238,8 @@ namespace mongo {
if (node.isLocalSecondary(localThresholdMillis)) {
// found a local node. return early.
- LOG(2) << "dbclient_rs _selectNode found local secondary for queries: "
- << nextNodeIndex << ", ping time: " << node.pingTimeMillis << endl;
+ LOG(2) << "dbclient_rs selecting local secondary " << fallbackHost
+ << ", ping time: " << node.pingTimeMillis << endl;
*lastHost = fallbackHost;
return fallbackHost;
}
@@ -176,6 +250,14 @@ namespace mongo {
*lastHost = fallbackHost;
}
+ if ( fallbackHost.empty() ) {
+ LOG(3) << "dbclient_rs no node selected for tag " << readPreferenceTag << endl;
+ }
+ else {
+ LOG(3) << "dbclient_rs node " << fallbackHost << " selected for tag "
+ << readPreferenceTag << endl;
+ }
+
return fallbackHost;
}
@@ -283,47 +365,6 @@ namespace mongo {
// ----- ReplicaSetMonitor ---------
// --------------------------------
- // global background job responsible for checking every X amount of time
- class ReplicaSetMonitorWatcher : public BackgroundJob {
- public:
- ReplicaSetMonitorWatcher() : _safego("ReplicaSetMonitorWatcher::_safego") , _started(false) {}
-
- virtual string name() const { return "ReplicaSetMonitorWatcher"; }
-
- void safeGo() {
- // check outside of lock for speed
- if ( _started )
- return;
-
- scoped_lock lk( _safego );
- if ( _started )
- return;
- _started = true;
-
- go();
- }
- protected:
- void run() {
- log() << "starting" << endl;
- while ( ! inShutdown() ) {
- sleepsecs( 10 );
- try {
- ReplicaSetMonitor::checkAll( true );
- }
- catch ( std::exception& e ) {
- error() << "check failed: " << e.what() << endl;
- }
- catch ( ... ) {
- error() << "unkown error" << endl;
- }
- }
- }
-
- mongo::mutex _safego;
- bool _started;
-
- } replicaSetMonitorWatcher;
-
string seedString( const vector<HostAndPort>& servers ){
string seedStr;
for ( unsigned i = 0; i < servers.size(); i++ ){
@@ -1164,6 +1205,10 @@ namespace mongo {
}
if (candidate.empty()) {
+
+ LOG( 3 ) << "dbclient_rs no compatible nodes found, refreshing view of replica set "
+ << _name << endl;
+
// mimic checkMaster behavior, which refreshes the local view of the replica set
_check(false);
@@ -1420,9 +1465,6 @@ namespace mongo {
return builder.obj();
}
- mongo::mutex ReplicaSetMonitor::_setsLock( "ReplicaSetMonitor" );
- map<string,ReplicaSetMonitorPtr> ReplicaSetMonitor::_sets;
- map<string,vector<HostAndPort> > ReplicaSetMonitor::_seedServers;
ReplicaSetMonitor::ConfigChangeHook ReplicaSetMonitor::_hook;
int ReplicaSetMonitor::_maxFailedChecks = 30; // At 1 check every 10 seconds, 30 checks takes 5 minutes
@@ -1625,9 +1667,21 @@ namespace mongo {
const BSONObj *fieldsToReturn,
int queryOptions,
int batchSize) {
- if (_isQueryOkToSecondary(ns, queryOptions, query.obj)) {
+
+ if ( _isQueryOkToSecondary( ns, queryOptions, query.obj ) ) {
+
shared_ptr<ReadPreferenceSetting> readPref(_extractReadPref(query.obj));
+ LOG( 3 ) << "dbclient_rs query using secondary or tagged node selection in "
+ << _getMonitor()->getName() << ", read pref is "
+ << readPref->toBSON() << " (primary : "
+ << ( _master.get() != NULL ?
+ _master->getServerAddress() : "[not cached]" )
+ << ", lastTagged : "
+ << ( _lastSlaveOkConn.get() != NULL ?
+ _lastSlaveOkConn->getServerAddress() : "[not cached]" )
+ << ")" << endl;
+
for (size_t retry = 0; retry < MAX_RETRY; retry++) {
try {
DBClientConnection* conn = selectNodeUsingTags(readPref);
@@ -1643,16 +1697,19 @@ namespace mongo {
return checkSlaveQueryResult(cursor);
}
catch (const DBException &dbExcep) {
- LOG(1) << "can't query replica set slave " << _lastSlaveOkHost
+ LOG(1) << "can't query replica set node " << _lastSlaveOkHost
<< ": " << causedBy(dbExcep) << endl;
invalidateLastSlaveOkCache();
}
}
- uasserted(16370, str::stream() << "Failed to do query, no good nodes in "
- << _getMonitor()->getName());
+ uasserted( 16370,
+ str::stream() << "Failed to do query, no good nodes in "
+ << _getMonitor()->getName() );
}
+ LOG( 3 ) << "dbclient_rs query to primary node in " << _getMonitor()->getName() << endl;
+
return checkMaster()->query(ns, query, nToReturn, nToSkip, fieldsToReturn,
queryOptions, batchSize);
}
@@ -1662,8 +1719,19 @@ namespace mongo {
const BSONObj *fieldsToReturn,
int queryOptions) {
if (_isQueryOkToSecondary(ns, queryOptions, query.obj)) {
+
shared_ptr<ReadPreferenceSetting> readPref(_extractReadPref(query.obj));
+ LOG( 3 ) << "dbclient_rs findOne using secondary or tagged node selection in "
+ << _getMonitor()->getName() << ", read pref is "
+ << readPref->toBSON() << " (primary : "
+ << ( _master.get() != NULL ?
+ _master->getServerAddress() : "[not cached]" )
+ << ", lastTagged : "
+ << ( _lastSlaveOkConn.get() != NULL ?
+ _lastSlaveOkConn->getServerAddress() : "[not cached]" )
+ << ")" << endl;
+
for (size_t retry = 0; retry < MAX_RETRY; retry++) {
try {
DBClientConnection* conn = selectNodeUsingTags(readPref);
@@ -1674,9 +1742,9 @@ namespace mongo {
return conn->findOne(ns,query,fieldsToReturn,queryOptions);
}
- catch (const DBException &dbExcep) {
- LOG(1) << "can't findone replica set slave " << _lastSlaveOkHost
- << ": " << causedBy(dbExcep) << endl;
+ catch ( const DBException &dbExcep ) {
+ LOG(1) << "can't findone replica set node " << _lastSlaveOkHost << ": "
+ << causedBy( dbExcep ) << endl;
invalidateLastSlaveOkCache();
}
}
@@ -1685,6 +1753,9 @@ namespace mongo {
<< _getMonitor()->getName());
}
+ LOG( 3 ) << "dbclient_rs findOne to primary node in " << _getMonitor()->getName()
+ << endl;
+
return checkMaster()->findOne(ns,query,fieldsToReturn,queryOptions);
}
@@ -1737,6 +1808,10 @@ namespace mongo {
DBClientConnection* DBClientReplicaSet::selectNodeUsingTags(
shared_ptr<ReadPreferenceSetting> readPref) {
if (checkLastHost(readPref.get())) {
+
+ LOG( 3 ) << "dbclient_rs selecting compatible last used node " << _lastSlaveOkHost
+ << endl;
+
return _lastSlaveOkConn.get();
}
@@ -1746,6 +1821,9 @@ namespace mongo {
&isPrimarySelected);
if ( _lastSlaveOkHost.empty() ){
+
+ LOG( 3 ) << "dbclient_rs no compatible node found" << endl;
+
return NULL;
}
@@ -1759,6 +1837,9 @@ namespace mongo {
checkMaster();
_lastSlaveOkConn = _master;
_lastSlaveOkHost = _masterHost; // implied, but still assign just to be safe
+
+ LOG( 3 ) << "dbclient_rs selecting primary node " << _lastSlaveOkHost << endl;
+
return _master.get();
}
@@ -1772,14 +1853,16 @@ namespace mongo {
// Assert here instead of returning NULL since the contract of this method is such
// that returning NULL means none of the nodes were good, which is not the case here.
- uassert(16532, str::stream() << "Failed to connect to "
- << _lastSlaveOkHost.toString(true),
+ uassert(16532, str::stream() << "Failed to connect to " << _lastSlaveOkHost.toString(),
newConn != NULL);
_lastSlaveOkConn.reset(newConn);
_lastSlaveOkConn->setReplSetClientCallback(this);
_auth(_lastSlaveOkConn.get());
+
+ LOG( 3 ) << "dbclient_rs selecting node " << _lastSlaveOkHost << endl;
+
return _lastSlaveOkConn.get();
}
@@ -1798,8 +1881,19 @@ namespace mongo {
const bool slaveOk = qm.queryOptions & QueryOption_SlaveOk;
if (_isQueryOkToSecondary(qm.ns, qm.queryOptions, qm.query)) {
+
shared_ptr<ReadPreferenceSetting> readPref(_extractReadPref(qm.query));
+ LOG( 3 ) << "dbclient_rs say using secondary or tagged node selection in "
+ << _getMonitor()->getName() << ", read pref is "
+ << readPref->toBSON() << " (primary : "
+ << ( _master.get() != NULL ?
+ _master->getServerAddress() : "[not cached]" )
+ << ", lastTagged : "
+ << ( _lastSlaveOkConn.get() != NULL ?
+ _lastSlaveOkConn->getServerAddress() : "[not cached]" )
+ << ")" << endl;
+
for (size_t retry = 0; retry < MAX_RETRY; retry++) {
_lazyState._retries = retry;
try {
@@ -1819,9 +1913,9 @@ namespace mongo {
_lazyState._slaveOk = slaveOk;
_lazyState._lastClient = conn;
}
- catch (const DBException& DBExcep) {
- LOG(1) << "can't callLazy replica set slave " << _lastSlaveOkHost
- << ": " << causedBy(DBExcep) << endl;
+ catch ( const DBException& DBExcep ) {
+ LOG(1) << "can't callLazy replica set node " << _lastSlaveOkHost << ": "
+ << causedBy( DBExcep ) << endl;
invalidateLastSlaveOkCache();
continue;
}
@@ -1834,6 +1928,9 @@ namespace mongo {
}
}
+ LOG( 3 ) << "dbclient_rs say to primary node in " << _getMonitor()->getName()
+ << endl;
+
DBClientConnection* master = checkMaster();
if (actualServer)
*actualServer = master->getServerAddress();
@@ -1940,8 +2037,19 @@ namespace mongo {
ns = qm.ns;
if (_isQueryOkToSecondary(ns, qm.queryOptions, qm.query)) {
+
shared_ptr<ReadPreferenceSetting> readPref(_extractReadPref(qm.query));
+ LOG( 3 ) << "dbclient_rs call using secondary or tagged node selection in "
+ << _getMonitor()->getName() << ", read pref is "
+ << readPref->toBSON() << " (primary : "
+ << ( _master.get() != NULL ?
+ _master->getServerAddress() : "[not cached]" )
+ << ", lastTagged : "
+ << ( _lastSlaveOkConn.get() != NULL ?
+ _lastSlaveOkConn->getServerAddress() : "[not cached]" )
+ << ")" << endl;
+
for (size_t retry = 0; retry < MAX_RETRY; retry++) {
try {
DBClientConnection* conn = selectNodeUsingTags(readPref);
@@ -1956,12 +2064,11 @@ namespace mongo {
return conn->call(toSend, response, assertOk);
}
- catch (const DBException& dbExcep) {
- LOG(1) << "can't call replica set slave " << _lastSlaveOkHost
- << ": " << causedBy(dbExcep) << endl;
+ catch ( const DBException& dbExcep ) {
+ LOG(1) << "can't call replica set node " << _lastSlaveOkHost << ": "
+ << causedBy( dbExcep ) << endl;
- if (actualServer)
- *actualServer = "";
+ if ( actualServer ) *actualServer = "";
invalidateLastSlaveOkCache();
}
@@ -1972,6 +2079,8 @@ namespace mongo {
}
}
+ LOG( 3 ) << "dbclient_rs call to primary node in " << _getMonitor()->getName() << endl;
+
DBClientConnection* m = checkMaster();
if ( actualServer )
*actualServer = m->getServerAddress();
@@ -2051,4 +2160,32 @@ namespace mongo {
bool TagSet::equals(const TagSet& other) const {
return _tags.equal(other._tags);
}
+
+ const BSONArray& TagSet::getTagBSON() const {
+ return _tags;
+ }
+
+ string readPrefToString( ReadPreference pref ) {
+ switch ( pref ) {
+ case ReadPreference_PrimaryOnly:
+ return "primary only";
+ case ReadPreference_PrimaryPreferred:
+ return "primary pref";
+ case ReadPreference_SecondaryOnly:
+ return "secondary only";
+ case ReadPreference_SecondaryPreferred:
+ return "secondary pref";
+ case ReadPreference_Nearest:
+ return "nearest";
+ default:
+ return "Unknown";
+ }
+ }
+
+ BSONObj ReadPreferenceSetting::toBSON() const {
+ BSONObjBuilder bob;
+ bob.append( "pref", readPrefToString( pref ) );
+ bob.append( "tags", tags.getTagBSON() );
+ return bob.obj();
+ }
}
diff --git a/src/mongo/client/dbclient_rs.h b/src/mongo/client/dbclient_rs.h
index ffdf0e0ecee..05f7faa9b2b 100644
--- a/src/mongo/client/dbclient_rs.h
+++ b/src/mongo/client/dbclient_rs.h
@@ -206,7 +206,7 @@ namespace mongo {
/**
* Removes the ReplicaSetMonitor for the given set name from _sets, which will delete it.
* If clearSeedCache is true, then the cached seed string for this Replica Set will be removed
- * from _setServers.
+ * from _seedServers.
*/
static void remove( const string& name, bool clearSeedCache = false );
@@ -333,7 +333,7 @@ namespace mongo {
bool verbose, int nodesOffset );
/**
- * Save the seed list for the current set into the _setServers map
+ * Save the seed list for the current set into the _seedServers map
* Should only be called if you're already holding _setsLock and this
* monitor's _lock.
*/
@@ -397,9 +397,12 @@ namespace mongo {
// The number of consecutive times the set has been checked and every member in the set was down.
int _failedChecks;
- static mongo::mutex _setsLock; // protects _sets and _setServers
- static map<string,ReplicaSetMonitorPtr> _sets; // set name to Monitor
- static map<string,vector<HostAndPort> > _seedServers; // set name to seed list. Used to rebuild the monitor if it is cleaned up but then the set is accessed again.
+ static mongo::mutex _setsLock; // protects _seedServers and _sets
+
+ // set name to seed list.
+ // Used to rebuild the monitor if it is cleaned up but then the set is accessed again.
+ static map<string, vector<HostAndPort> > _seedServers;
+ static map<string, ReplicaSetMonitorPtr> _sets; // set name to Monitor
static ConfigChangeHook _hook;
int _localThresholdMillis; // local ping latency threshold (protected by _lock)
@@ -672,6 +675,8 @@ namespace mongo {
*/
bool equals(const TagSet& other) const;
+ const BSONArray& getTagBSON() const;
+
private:
/**
* This is purposely undefined as the semantics for assignment can be
@@ -703,6 +708,8 @@ namespace mongo {
return pref == other.pref && tags.equals(other.tags);
}
+ BSONObj toBSON() const;
+
const ReadPreference pref;
TagSet tags;
};
diff --git a/src/mongo/db/clientcursor.cpp b/src/mongo/db/clientcursor.cpp
index a0693dd8c7d..fa39170d73b 100644
--- a/src/mongo/db/clientcursor.cpp
+++ b/src/mongo/db/clientcursor.cpp
@@ -554,6 +554,16 @@ namespace mongo {
return true;
}
+ void yieldOrSleepFor1Microsecond() {
+#ifdef _WIN32
+ SwitchToThread();
+#elif defined(__linux__)
+ pthread_yield();
+#else
+ sleepmicros(1);
+#endif
+ }
+
void ClientCursor::staticYield( int micros , const StringData& ns , Record * rec ) {
bool haveReadLock = Lock::isReadLocked();
@@ -564,7 +574,7 @@ namespace mongo {
// need to lock this else rec->touch won't be safe file could disappear
lk.reset( new LockMongoFilesShared() );
}
-
+
dbtempreleasecond unlock;
if ( unlock.unlocked() ) {
if ( haveReadLock ) {
@@ -574,16 +584,26 @@ namespace mongo {
#ifdef _WIN32
SwitchToThread();
#else
- sleepmicros(1);
+ if ( micros == 0 ) {
+ yieldOrSleepFor1Microsecond();
+ }
+ else {
+ sleepmicros(1);
+ }
#endif
}
else {
- if ( micros == -1 )
+ if ( micros == -1 ) {
micros = Client::recommendedYieldMicros();
- if ( micros > 0 )
+ }
+ else if ( micros == 0 ) {
+ yieldOrSleepFor1Microsecond();
+ }
+ else if ( micros > 0 ) {
sleepmicros( micros );
+ }
}
-
+
}
else if ( Listener::getTimeTracker() == 0 ) {
// we aren't running a server, so likely a repair, so don't complain
diff --git a/src/mongo/db/clientcursor.h b/src/mongo/db/clientcursor.h
index 7de161d6dd5..f2077282c66 100644
--- a/src/mongo/db/clientcursor.h
+++ b/src/mongo/db/clientcursor.h
@@ -178,7 +178,8 @@ namespace mongo {
/**
* @param microsToSleep -1 : ask client
- * >=0 : sleep for that amount
+ * 0 : pthread_yield or equivilant
+ * >0 : sleep for that amount
* @param recordToLoad after yielding lock, load this record with only mmutex
* do a dbtemprelease
* note: caller should check matcher.docMatcher().atomic() first and not yield if atomic -
@@ -188,7 +189,7 @@ namespace mongo {
* if false is returned, then this ClientCursor should be considered deleted -
* in fact, the whole database could be gone.
*/
- bool yield( int microsToSleep = -1 , Record * recordToLoad = 0 );
+ bool yield( int microsToSleep = -1, Record * recordToLoad = 0 );
enum RecordNeeds {
DontNeed = -1 , MaybeCovered = 0 , WillNeed = 100
diff --git a/src/mongo/db/dbcommands_admin.cpp b/src/mongo/db/dbcommands_admin.cpp
index 7ab769a9988..623a397201c 100644
--- a/src/mongo/db/dbcommands_admin.cpp
+++ b/src/mongo/db/dbcommands_admin.cpp
@@ -52,43 +52,6 @@
namespace mongo {
- class CleanCmd : public Command {
- public:
- CleanCmd() : Command( "clean" ) {}
-
- virtual bool slaveOk() const { return true; }
- virtual LockType locktype() const { return WRITE; }
-
- virtual void help(stringstream& h) const { h << "internal"; }
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) {
- ActionSet actions;
- actions.addAction(ActionType::clean);
- out->push_back(Privilege(parseNs(dbname, cmdObj), actions));
- }
- bool run(const string& dbname, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl ) {
- string dropns = dbname + "." + cmdObj.firstElement().valuestrsafe();
-
- if ( !cmdLine.quiet )
- tlog() << "CMD: clean " << dropns << endl;
-
- NamespaceDetails *d = nsdetails(dropns);
-
- if ( ! d ) {
- errmsg = "ns not found";
- return 0;
- }
-
- for ( int i = 0; i < Buckets; i++ )
- d->deletedList[i].Null();
-
- result.append("ns", dropns.c_str());
- return 1;
- }
-
- } cleanCmd;
-
namespace dur {
boost::filesystem::path getJournalDir();
}
diff --git a/src/mongo/db/dur.cpp b/src/mongo/db/dur.cpp
index e49d8ef9da0..9c336751446 100644
--- a/src/mongo/db/dur.cpp
+++ b/src/mongo/db/dur.cpp
@@ -470,12 +470,14 @@ namespace mongo {
fraction = 1;
lastRemap = now;
-#if defined(_WIN32)
+#if defined(_WIN32) || defined(__sunos__)
// Note that this negatively affects performance.
- // We must grab the exclusive lock here because remapThePrivateView() on Windows needs
- // to grab it as well, due to the lack of a non-atomic way to remap a memory mapped file.
+ // We must grab the exclusive lock here because remapPrivateView() on Windows and
+ // Solaris need to grab it as well, due to the lack of an atomic way to remap a
+ // memory mapped file.
// See SERVER-5723 for performance improvement.
- // See SERVER-5680 to see why this code is necessary.
+ // See SERVER-5680 to see why this code is necessary on Windows.
+ // See SERVER-8795 to see why this code is necessary on Solaris.
LockMongoFilesExclusive lk;
#else
LockMongoFilesShared lk;
diff --git a/src/mongo/db/extsort.cpp b/src/mongo/db/extsort.cpp
index 195b01851a8..d955acb94cc 100644
--- a/src/mongo/db/extsort.cpp
+++ b/src/mongo/db/extsort.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/kill_current_op.h"
#include "mongo/db/namespace-inl.h"
+#include "mongo/platform/posix_fadvise.h"
#include "mongo/util/file.h"
namespace mongo {
diff --git a/src/mongo/db/fts/fts_matcher.cpp b/src/mongo/db/fts/fts_matcher.cpp
index 313fdd5be9e..ee462bbb009 100644
--- a/src/mongo/db/fts/fts_matcher.cpp
+++ b/src/mongo/db/fts/fts_matcher.cpp
@@ -19,6 +19,7 @@
#include "mongo/pch.h"
#include "mongo/db/fts/fts_matcher.h"
+#include "mongo/platform/strcasestr.h"
namespace mongo {
@@ -226,20 +227,10 @@ namespace mongo {
/*
* Looks for phrase in a raw string
* @param phrase, phrase to match
- * @param raw, raw string to be parsed
+ * @param haystack, raw string to be parsed
*/
bool FTSMatcher::_phraseMatches( const string& phrase, const string& haystack ) const {
-#ifdef _WIN32
- // windows doesn't have strcasestr
- // for now, doing something very slow, bu correct
- string p = phrase;
- string h = haystack;
- makeLower( &p );
- makeLower( &h );
- return strstr( h.c_str(), p.c_str() ) > 0;
-#else
return strcasestr( haystack.c_str(), phrase.c_str() ) > 0;
-#endif
}
diff --git a/src/mongo/db/mongod.vcxproj b/src/mongo/db/mongod.vcxproj
index 5b7dc27a53e..9b4811af659 100644
--- a/src/mongo/db/mongod.vcxproj
+++ b/src/mongo/db/mongod.vcxproj
@@ -1934,7 +1934,10 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClCompile Include="..\client\distlock_test.cpp" />
<ClCompile Include="..\client\model.cpp" />
<ClCompile Include="..\client\sasl_client_authenticate.cpp" />
+ <ClCompile Include="..\platform\backtrace.cpp" />
+ <ClCompile Include="..\platform\posix_fadvise.cpp" />
<ClCompile Include="..\platform\random.cpp" />
+ <ClCompile Include="..\platform\strcasestr.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@@ -3025,13 +3028,16 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClInclude Include="..\platform\atomic_intrinsics.h" />
<ClInclude Include="..\platform\atomic_intrinsics_win32.h" />
<ClInclude Include="..\platform\atomic_word.h" />
+ <ClInclude Include="..\platform\backtrace.h" />
<ClInclude Include="..\platform\basic.h" />
<ClInclude Include="..\platform\bits.h" />
<ClInclude Include="..\platform\compiler.h" />
<ClInclude Include="..\platform\compiler_msvc.h" />
<ClInclude Include="..\platform\cstdint.h" />
<ClInclude Include="..\platform\float_utils.h" />
+ <ClInclude Include="..\platform\posix_fadvise.h" />
<ClInclude Include="..\platform\random.h" />
+ <ClInclude Include="..\platform\strcasestr.h" />
<ClInclude Include="..\platform\strtoll.h" />
<ClInclude Include="..\platform\unordered_map.h" />
<ClInclude Include="..\platform\unordered_set.h" />
diff --git a/src/mongo/db/mongod.vcxproj.filters b/src/mongo/db/mongod.vcxproj.filters
index 1b5e8788358..8e27c34a716 100644
--- a/src/mongo/db/mongod.vcxproj.filters
+++ b/src/mongo/db/mongod.vcxproj.filters
@@ -1814,6 +1814,15 @@
<ClCompile Include="index_set.cpp">
<Filter>db\Source Files\e to n</Filter>
</ClCompile>
+ <ClCompile Include="..\platform\strcasestr.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\backtrace.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\posix_fadvise.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\targetver.h" />
@@ -3828,6 +3837,15 @@
<ClInclude Include="index_set.h">
<Filter>db\Header Files\e to n</Filter>
</ClInclude>
+ <ClInclude Include="..\platform\strcasestr.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\backtrace.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\posix_fadvise.h">
+ <Filter>platform</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="mongo.ico">
diff --git a/src/mongo/db/mongod_sm.vcxproj b/src/mongo/db/mongod_sm.vcxproj
index df066a1baf8..b7add373e92 100644
--- a/src/mongo/db/mongod_sm.vcxproj
+++ b/src/mongo/db/mongod_sm.vcxproj
@@ -1588,7 +1588,10 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClCompile Include="..\client\distlock_test.cpp" />
<ClCompile Include="..\client\model.cpp" />
<ClCompile Include="..\client\sasl_client_authenticate.cpp" />
+ <ClCompile Include="..\platform\backtrace.cpp" />
+ <ClCompile Include="..\platform\posix_fadvise.cpp" />
<ClCompile Include="..\platform\random.cpp" />
+ <ClCompile Include="..\platform\strcasestr.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@@ -2377,13 +2380,16 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClInclude Include="..\platform\atomic_intrinsics.h" />
<ClInclude Include="..\platform\atomic_intrinsics_win32.h" />
<ClInclude Include="..\platform\atomic_word.h" />
+ <ClInclude Include="..\platform\backtrace.h" />
<ClInclude Include="..\platform\basic.h" />
<ClInclude Include="..\platform\bits.h" />
<ClInclude Include="..\platform\compiler.h" />
<ClInclude Include="..\platform\compiler_msvc.h" />
<ClInclude Include="..\platform\cstdint.h" />
<ClInclude Include="..\platform\float_utils.h" />
+ <ClInclude Include="..\platform\posix_fadvise.h" />
<ClInclude Include="..\platform\random.h" />
+ <ClInclude Include="..\platform\strcasestr.h" />
<ClInclude Include="..\platform\strtoll.h" />
<ClInclude Include="..\platform\unordered_map.h" />
<ClInclude Include="..\platform\unordered_set.h" />
diff --git a/src/mongo/db/mongod_sm.vcxproj.filters b/src/mongo/db/mongod_sm.vcxproj.filters
index dbf6beb6b82..ee4a208c28b 100644
--- a/src/mongo/db/mongod_sm.vcxproj.filters
+++ b/src/mongo/db/mongod_sm.vcxproj.filters
@@ -1475,6 +1475,15 @@
<ClCompile Include="index_set.cpp">
<Filter>db\Source Files\e to n</Filter>
</ClCompile>
+ <ClCompile Include="..\platform\strcasestr.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\backtrace.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\posix_fadvise.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\targetver.h" />
@@ -3012,6 +3021,15 @@
<ClInclude Include="index_set.h">
<Filter>db\Header Files\e to n</Filter>
</ClInclude>
+ <ClInclude Include="..\platform\strcasestr.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\backtrace.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\posix_fadvise.h">
+ <Filter>platform</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="mongo.ico">
diff --git a/src/mongo/db/oplog.cpp b/src/mongo/db/oplog.cpp
index 870601c9b4b..12f4742c256 100644
--- a/src/mongo/db/oplog.cpp
+++ b/src/mongo/db/oplog.cpp
@@ -576,7 +576,7 @@ namespace mongo {
while( !finder->done() ) {
if ( yieldCondition.intervalHasElapsed() ) {
if ( finder->prepareToYield() ) {
- ClientCursor::staticYield( -1, ns, 0 );
+ ClientCursor::staticYield( 0, ns, 0 );
finder->recoverFromYield();
}
}
diff --git a/src/mongo/db/repl/bgsync.cpp b/src/mongo/db/repl/bgsync.cpp
index 67c1eca8555..f2c22151636 100644
--- a/src/mongo/db/repl/bgsync.cpp
+++ b/src/mongo/db/repl/bgsync.cpp
@@ -63,7 +63,8 @@ namespace replset {
BackgroundSyncInterface::~BackgroundSyncInterface() {}
size_t getSize(const BSONObj& o) {
- return o.objsize();
+ // SERVER-9808 Avoid Fortify complaint about implicit signed->unsigned conversion
+ return static_cast<size_t>(o.objsize());
}
BackgroundSync::BackgroundSync() : _buffer(bufferMaxSizeGauge, &getSize),
@@ -240,11 +241,10 @@ namespace replset {
try {
_producerThread();
}
- catch (DBException& e) {
- sethbmsg(str::stream() << "db exception in producer: " << e.toString());
- sleepsecs(10);
+ catch (const DBException& e) {
+ sethbmsg(str::stream() << "sync source problem: " << e.toString());
}
- catch (std::exception& e2) {
+ catch (const std::exception& e2) {
sethbmsg(str::stream() << "exception in producer: " << e2.what());
sleepsecs(60);
}
@@ -288,7 +288,7 @@ namespace replset {
// this oplog reader does not do a handshake because we don't want the server it's syncing
// from to track how far it has synced
OplogReader r(false /* doHandshake */);
-
+ OpTime lastOpTimeFetched;
// find a target to sync from the last op time written
getOplogReader(r);
@@ -302,10 +302,11 @@ namespace replset {
// if there is no one to sync from
return;
}
-
- r.tailingQueryGTE(rsoplog, _lastOpTimeFetched);
+ lastOpTimeFetched = _lastOpTimeFetched;
}
+ r.tailingQueryGTE(rsoplog, lastOpTimeFetched);
+
// if target cut connections between connecting and querying (for
// example, because it stepped down) we might not have a cursor
if (!r.haveCursor()) {
@@ -320,72 +321,82 @@ namespace replset {
}
while (!inShutdown()) {
- while (!inShutdown()) {
-
- if (!r.moreInCurrentBatch()) {
- if (theReplSet->gotForceSync()) {
- return;
- }
- if (isAssumingPrimary() || theReplSet->isPrimary()) {
- return;
- }
-
- // re-evaluate quality of sync target
- if (shouldChangeSyncTarget()) {
- return;
- }
- //record time for each getmore
- {
- TimerHolder batchTimer(&getmoreReplStats);
- r.more();
- }
- //increment
- networkByteStats.increment(r.currentBatchMessageSize());
+ if (!r.moreInCurrentBatch()) {
+ // Check some things periodically
+ // (whenever we run out of items in the
+ // current cursor batch)
+ if (theReplSet->gotForceSync()) {
+ return;
+ }
+ // If we are transitioning to primary state, we need to leave
+ // this loop in order to go into bgsync-pause mode.
+ if (isAssumingPrimary() || theReplSet->isPrimary()) {
+ return;
}
- if (!r.more())
- break;
+ // re-evaluate quality of sync target
+ if (shouldChangeSyncTarget()) {
+ return;
+ }
- BSONObj o = r.nextSafe().getOwned();
- opsReadStats.increment();
{
- boost::unique_lock<boost::mutex> lock(_mutex);
- _appliedBuffer = false;
+ //record time for each getmore
+ TimerHolder batchTimer(&getmoreReplStats);
+
+ // This calls receiveMore() on the oplogreader cursor.
+ // It can wait up to five seconds for more data.
+ r.more();
}
+ networkByteStats.increment(r.currentBatchMessageSize());
- OCCASIONALLY {
- LOG(2) << "bgsync buffer has " << _buffer.size() << " bytes" << rsLog;
- }
- // the blocking queue will wait (forever) until there's room for us to push
- _buffer.push(o);
- bufferCountGauge.increment();
- bufferSizeGauge.increment(getSize(o));
+ if (!r.moreInCurrentBatch()) {
+ // If there is still no data from upstream, check a few more things
+ // and then loop back for another pass at getting more data
+ {
+ boost::unique_lock<boost::mutex> lock(_mutex);
+ if (_pause ||
+ !_currentSyncTarget ||
+ !_currentSyncTarget->hbinfo().hbstate.readable()) {
+ return;
+ }
+ }
- {
- boost::unique_lock<boost::mutex> lock(_mutex);
- _lastH = o["h"].numberLong();
- _lastOpTimeFetched = o["ts"]._opTime();
+ r.tailCheck();
+ if( !r.haveCursor() ) {
+ LOG(1) << "replSet end syncTail pass" << rsLog;
+ return;
+ }
+
+ continue;
}
- } // end while
+ }
+
+ // At this point, we are guaranteed to have at least one thing to read out
+ // of the oplogreader cursor.
+ BSONObj o = r.nextSafe().getOwned();
+ opsReadStats.increment();
{
boost::unique_lock<boost::mutex> lock(_mutex);
- if (_pause || !_currentSyncTarget || !_currentSyncTarget->hbinfo().hbstate.readable()) {
- return;
- }
+ _appliedBuffer = false;
}
-
- r.tailCheck();
- if( !r.haveCursor() ) {
- LOG(1) << "replSet end syncTail pass" << rsLog;
- return;
+ OCCASIONALLY {
+ LOG(2) << "bgsync buffer has " << _buffer.size() << " bytes" << rsLog;
}
+ // the blocking queue will wait (forever) until there's room for us to push
+ _buffer.push(o);
+ bufferCountGauge.increment();
+ bufferSizeGauge.increment(getSize(o));
- // looping back is ok because this is a tailable cursor
+ {
+ boost::unique_lock<boost::mutex> lock(_mutex);
+ _lastH = o["h"].numberLong();
+ _lastOpTimeFetched = o["ts"]._opTime();
+ }
}
}
diff --git a/src/mongo/db/repl/rs_rollback.cpp b/src/mongo/db/repl/rs_rollback.cpp
index 8c8e89c20c6..68b7fc17529 100644
--- a/src/mongo/db/repl/rs_rollback.cpp
+++ b/src/mongo/db/repl/rs_rollback.cpp
@@ -68,7 +68,11 @@ namespace mongo {
class rsfatal : public std::exception {
public:
- virtual const char* what() const throw() { return "replica set fatal exception"; }
+ rsfatal(std::string m = "replica set fatal exception") : msg(m) {}
+ virtual ~rsfatal() throw() {};
+ virtual const char* what() const throw() { return msg.c_str(); }
+ private:
+ std::string msg;
};
struct DocID {
@@ -193,19 +197,13 @@ namespace mongo {
int getRBID(DBClientConnection*);
static void syncRollbackFindCommonPoint(DBClientConnection *them, HowToFixUp& h) {
- static time_t last;
- if( time(0)-last < 60 ) {
- throw "findcommonpoint waiting a while before trying again";
- }
- last = time(0);
-
verify( Lock::isLocked() );
Client::Context c(rsoplog);
NamespaceDetails *nsd = nsdetails(rsoplog);
verify(nsd);
ReverseCappedCursor u(nsd);
if( !u.ok() )
- throw "our oplog empty or unreadable";
+ throw rsfatal("our oplog empty or unreadable");
const Query q = Query().sort(reverseNaturalObj);
const bo fields = BSON( "ts" << 1 << "h" << 1 );
@@ -215,7 +213,7 @@ namespace mongo {
h.rbid = getRBID(them);
auto_ptr<DBClientCursor> t = them->query(rsoplog, q, 0, 0, &fields, 0, 0);
- if( t.get() == 0 || !t->more() ) throw "remote oplog empty or unreadable";
+ if( t.get() == 0 || !t->more() ) throw rsfatal("remote oplog empty or unreadable");
BSONObj ourObj = u.current();
OpTime ourTime = ourObj["ts"]._opTime();
@@ -230,7 +228,8 @@ namespace mongo {
log() << "replSet info rollback diff in end of log times: " << diff << " seconds" << rsLog;
if( diff > 1800 ) {
log() << "replSet rollback too long a time period for a rollback." << rsLog;
- throw "error not willing to roll back more than 30 minutes of data";
+ throw rsfatal(str::stream() << "rollback error: not willing to roll back "
+ << "more than 30 minutes of data");
}
}
@@ -256,7 +255,7 @@ namespace mongo {
log() << "replSet them: " << them->toString() << " scanned: " << scanned << rsLog;
log() << "replSet theirTime: " << theirTime.toStringLong() << rsLog;
log() << "replSet ourTime: " << ourTime.toStringLong() << rsLog;
- throw "RS100 reached beginning of remote oplog [2]";
+ throw rsfatal("RS100 reached beginning of remote oplog [2]");
}
theirObj = t->nextSafe();
theirTime = theirObj["ts"]._opTime();
@@ -267,7 +266,7 @@ namespace mongo {
log() << "replSet them: " << them->toString() << " scanned: " << scanned << rsLog;
log() << "replSet theirTime: " << theirTime.toStringLong() << rsLog;
log() << "replSet ourTime: " << ourTime.toStringLong() << rsLog;
- throw "RS101 reached beginning of local oplog [1]";
+ throw rsfatal("RS101 reached beginning of local oplog [1]");
}
ourObj = u.current();
ourTime = ourObj["ts"]._opTime();
@@ -278,7 +277,7 @@ namespace mongo {
log() << "replSet them: " << them->toString() << " scanned: " << scanned << rsLog;
log() << "replSet theirTime: " << theirTime.toStringLong() << rsLog;
log() << "replSet ourTime: " << ourTime.toStringLong() << rsLog;
- throw "RS100 reached beginning of remote oplog [1]";
+ throw rsfatal("RS100 reached beginning of remote oplog [1]");
}
theirObj = t->nextSafe();
theirTime = theirObj["ts"]._opTime();
@@ -292,7 +291,7 @@ namespace mongo {
log() << "replSet them: " << them->toString() << " scanned: " << scanned << rsLog;
log() << "replSet theirTime: " << theirTime.toStringLong() << rsLog;
log() << "replSet ourTime: " << ourTime.toStringLong() << rsLog;
- throw "RS101 reached beginning of local oplog [2]";
+ throw rsfatal("RS101 reached beginning of local oplog [2]");
}
ourObj = u.current();
ourTime = ourObj["ts"]._opTime();
@@ -637,11 +636,8 @@ namespace mongo {
try {
syncRollbackFindCommonPoint(r.conn(), how);
}
- catch( const char *p ) {
- sethbmsg(string("rollback 2 error ") + p);
- return 10;
- }
- catch( rsfatal& ) {
+ catch( rsfatal& e ) {
+ sethbmsg(string(e.what()));
_fatal();
return 2;
}
diff --git a/src/mongo/db/repl/rs_sync.cpp b/src/mongo/db/repl/rs_sync.cpp
index f1c531b1c7d..e6e31943a9f 100644
--- a/src/mongo/db/repl/rs_sync.cpp
+++ b/src/mongo/db/repl/rs_sync.cpp
@@ -587,8 +587,9 @@ namespace replset {
lock rsLock( this );
Lock::GlobalWrite writeLock;
- // make sure we're not primary, secondary, or fatal already
- if (box.getState().primary() || box.getState().secondary() || box.getState().fatal()) {
+ // make sure we're not primary, secondary, rollback, or fatal already
+ if (box.getState().primary() || box.getState().secondary() ||
+ box.getState().fatal()) {
return false;
}
diff --git a/src/mongo/db/ttl.cpp b/src/mongo/db/ttl.cpp
index 584bc20a3bc..66c0ee7ee7f 100644
--- a/src/mongo/db/ttl.cpp
+++ b/src/mongo/db/ttl.cpp
@@ -27,6 +27,7 @@
#include "mongo/db/instance.h"
#include "mongo/db/ops/delete.h"
#include "mongo/db/replutil.h"
+#include "mongo/db/server_parameters.h"
#include "mongo/util/background.h"
namespace mongo {
@@ -37,7 +38,7 @@ namespace mongo {
ServerStatusMetricField<Counter64> ttlPassesDisplay("ttl.passes", &ttlPasses);
ServerStatusMetricField<Counter64> ttlDeletedDocumentsDisplay("ttl.deletedDocuments", &ttlDeletedDocuments);
-
+ MONGO_EXPORT_SERVER_PARAMETER( ttlMonitorEnabled, bool, true );
class TTLMonitor : public BackgroundJob {
public:
@@ -124,6 +125,11 @@ namespace mongo {
sleepsecs( 60 );
LOG(3) << "TTLMonitor thread awake" << endl;
+
+ if ( !ttlMonitorEnabled ) {
+ LOG(1) << "TTLMonitor is disabled" << endl;
+ continue;
+ }
if ( lockedForWriting() ) {
// note: this is not perfect as you can go into fsync+lock between
diff --git a/src/mongo/dbtests/jsobjtests.cpp b/src/mongo/dbtests/jsobjtests.cpp
index 80b88831c47..bb2c58207c3 100644
--- a/src/mongo/dbtests/jsobjtests.cpp
+++ b/src/mongo/dbtests/jsobjtests.cpp
@@ -1504,9 +1504,9 @@ namespace JsobjTests {
public:
void run() {
Date_t before = jsTime();
- sleepmillis(1);
- time_t now = time(NULL);
- sleepmillis(1);
+ sleepmillis(2);
+ time_t now = jsTime().toTimeT();
+ sleepmillis(2);
Date_t after = jsTime();
BSONObjBuilder b;
diff --git a/src/mongo/dbtests/sharding.cpp b/src/mongo/dbtests/sharding.cpp
index f5e43be7687..e0f6218a0f4 100644
--- a/src/mongo/dbtests/sharding.cpp
+++ b/src/mongo/dbtests/sharding.cpp
@@ -98,6 +98,11 @@ namespace ShardingTests {
_shard = Shard( "shard0000", "$hostFooBar:27017" );
// Need to run this to ensure the shard is in the global lookup table
_shard.setAddress( _shard.getAddress() );
+
+ // Create an index so that diffing works correctly, otherwise no cursors from S&O
+ client().ensureIndex( "config.chunks", // br
+ BSON( "ns" << 1 << // br
+ "lastmod" << 1 ) );
}
virtual ~ChunkManagerTest() {
diff --git a/src/mongo/dbtests/test.vcxproj b/src/mongo/dbtests/test.vcxproj
index 77b70f4ce25..827a155651b 100644
--- a/src/mongo/dbtests/test.vcxproj
+++ b/src/mongo/dbtests/test.vcxproj
@@ -711,13 +711,16 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClInclude Include="..\platform\atomic_intrinsics.h" />
<ClInclude Include="..\platform\atomic_intrinsics_win32.h" />
<ClInclude Include="..\platform\atomic_word.h" />
+ <ClInclude Include="..\platform\backtrace.h" />
<ClInclude Include="..\platform\basic.h" />
<ClInclude Include="..\platform\bits.h" />
<ClInclude Include="..\platform\compiler.h" />
<ClInclude Include="..\platform\compiler_msvc.h" />
<ClInclude Include="..\platform\cstdint.h" />
<ClInclude Include="..\platform\float_utils.h" />
+ <ClInclude Include="..\platform\posix_fadvise.h" />
<ClInclude Include="..\platform\random.h" />
+ <ClInclude Include="..\platform\strcasestr.h" />
<ClInclude Include="..\platform\strtoll.h" />
<ClInclude Include="..\platform\unordered_map.h" />
<ClInclude Include="..\platform\unordered_set.h" />
@@ -2578,7 +2581,10 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClCompile Include="..\db\scanandorder.cpp" />
<ClCompile Include="..\db\server_parameters.cpp" />
<ClCompile Include="..\db\stats\timer_stats.cpp" />
+ <ClCompile Include="..\platform\backtrace.cpp" />
+ <ClCompile Include="..\platform\posix_fadvise.cpp" />
<ClCompile Include="..\platform\random.cpp" />
+ <ClCompile Include="..\platform\strcasestr.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
diff --git a/src/mongo/dbtests/test.vcxproj.filters b/src/mongo/dbtests/test.vcxproj.filters
index 49ff9f467b2..d3216639cc7 100755
--- a/src/mongo/dbtests/test.vcxproj.filters
+++ b/src/mongo/dbtests/test.vcxproj.filters
@@ -2205,6 +2205,15 @@
<ClInclude Include="..\db\index_set.h">
<Filter>db\Header Files\e to n</Filter>
</ClInclude>
+ <ClInclude Include="..\platform\strcasestr.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\backtrace.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\posix_fadvise.h">
+ <Filter>platform</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\client\connpool.cpp">
@@ -4201,6 +4210,15 @@
<ClCompile Include="..\db\hashindex.cpp">
<Filter>db\Source Files\e to n</Filter>
</ClCompile>
+ <ClCompile Include="..\platform\strcasestr.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\backtrace.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\posix_fadvise.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="btreetests.inl">
diff --git a/src/mongo/dbtests/test_sm.vcxproj b/src/mongo/dbtests/test_sm.vcxproj
index 646d513dbbe..806c70053f1 100644
--- a/src/mongo/dbtests/test_sm.vcxproj
+++ b/src/mongo/dbtests/test_sm.vcxproj
@@ -767,13 +767,16 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClInclude Include="..\platform\atomic_intrinsics.h" />
<ClInclude Include="..\platform\atomic_intrinsics_win32.h" />
<ClInclude Include="..\platform\atomic_word.h" />
+ <ClInclude Include="..\platform\backtrace.h" />
<ClInclude Include="..\platform\basic.h" />
<ClInclude Include="..\platform\bits.h" />
<ClInclude Include="..\platform\compiler.h" />
<ClInclude Include="..\platform\compiler_msvc.h" />
<ClInclude Include="..\platform\cstdint.h" />
<ClInclude Include="..\platform\float_utils.h" />
+ <ClInclude Include="..\platform\posix_fadvise.h" />
<ClInclude Include="..\platform\random.h" />
+ <ClInclude Include="..\platform\strcasestr.h" />
<ClInclude Include="..\platform\strtoll.h" />
<ClInclude Include="..\platform\unordered_map.h" />
<ClInclude Include="..\platform\unordered_set.h" />
@@ -2869,7 +2872,10 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClCompile Include="..\db\scanandorder.cpp" />
<ClCompile Include="..\db\server_parameters.cpp" />
<ClCompile Include="..\db\stats\timer_stats.cpp" />
+ <ClCompile Include="..\platform\backtrace.cpp" />
+ <ClCompile Include="..\platform\posix_fadvise.cpp" />
<ClCompile Include="..\platform\random.cpp" />
+ <ClCompile Include="..\platform\strcasestr.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
diff --git a/src/mongo/dbtests/test_sm.vcxproj.filters b/src/mongo/dbtests/test_sm.vcxproj.filters
index 9855716ca4e..cfead0b3f30 100644
--- a/src/mongo/dbtests/test_sm.vcxproj.filters
+++ b/src/mongo/dbtests/test_sm.vcxproj.filters
@@ -1716,6 +1716,15 @@
<ClInclude Include="..\db\index_set.h">
<Filter>db\Header Files\e to n</Filter>
</ClInclude>
+ <ClInclude Include="..\platform\strcasestr.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\backtrace.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\posix_fadvise.h">
+ <Filter>platform</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\client\connpool.cpp">
@@ -3373,6 +3382,15 @@
<ClCompile Include="..\db\hashindex.cpp">
<Filter>db\Source Files\e to n</Filter>
</ClCompile>
+ <ClCompile Include="..\platform\strcasestr.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\backtrace.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\posix_fadvise.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="btreetests.inl">
diff --git a/src/mongo/platform/SConscript b/src/mongo/platform/SConscript
index c18fbae3ce8..99738b6693a 100644
--- a/src/mongo/platform/SConscript
+++ b/src/mongo/platform/SConscript
@@ -2,7 +2,12 @@
Import("env")
-env.Library( "platform", "random.cpp" )
+env.Library('platform', [
+ 'backtrace.cpp',
+ 'posix_fadvise.cpp',
+ 'random.cpp',
+ 'strcasestr.cpp',
+ ])
env.CppUnitTest('atomic_word_test', 'atomic_word_test.cpp')
env.CppUnitTest('bits_test', 'bits_test.cpp')
diff --git a/src/mongo/platform/backtrace.cpp b/src/mongo/platform/backtrace.cpp
new file mode 100644
index 00000000000..89694425daf
--- /dev/null
+++ b/src/mongo/platform/backtrace.cpp
@@ -0,0 +1,215 @@
+/* Copyright 2013 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(_WIN32)
+#if defined(__sunos__) || !defined(MONGO_HAVE_EXECINFO_BACKTRACE)
+
+#include "mongo/platform/backtrace.h"
+
+#include <boost/smart_ptr/scoped_array.hpp>
+#include <cstdio>
+#include <dlfcn.h>
+#include <string>
+#include <ucontext.h>
+#include <vector>
+
+#include "mongo/base/init.h"
+#include "mongo/base/status.h"
+
+using std::string;
+using std::vector;
+
+namespace mongo {
+namespace pal {
+
+namespace {
+ class WalkcontextCallback {
+ public:
+ WalkcontextCallback(uintptr_t* array, int size)
+ : _position(0),
+ _count(size),
+ _addresses(array) {}
+
+ // This callback function is called from C code, and so must not throw exceptions
+ //
+ static int callbackFunction(uintptr_t address,
+ int signalNumber,
+ WalkcontextCallback* thisContext) {
+ if (thisContext->_position < thisContext->_count) {
+ thisContext->_addresses[thisContext->_position++] = address;
+ return 0;
+ }
+ return 1;
+ }
+ int getCount() const { return static_cast<int>(_position); }
+ private:
+ size_t _position;
+ size_t _count;
+ uintptr_t* _addresses;
+ };
+
+ // This function emulates a Solaris function that was added to Solaris 11 at the same time
+ // that the backtrace* functions were added. It is not important to match the function name
+ // or interface for this code, but this is a fine interface for our purposes and following
+ // an existing model seems potentially helpful ... hence the all-lowercase name with no
+ // underscores. The formatting of the output matches what Solaris 11 does; this is similar
+ // to Linux's display, but slightly different.
+ //
+ int addrtosymstr(void* address, char* outputBuffer, int outputBufferSize) {
+ Dl_info_t symbolInfo;
+ if (dladdr(address, &symbolInfo) == 0) { // no info: "[address]"
+ return snprintf(outputBuffer, outputBufferSize, "[0x%p]", address);
+ }
+ if (symbolInfo.dli_sname == NULL) {
+ return snprintf(outputBuffer, // no symbol: "filename'offset [address]"
+ outputBufferSize,
+ "%s'0x%p [0x%p]",
+ symbolInfo.dli_fname,
+ reinterpret_cast<char*>(reinterpret_cast<char*>(address) -
+ reinterpret_cast<char*>(symbolInfo.dli_fbase)),
+ address);
+ }
+ return snprintf(outputBuffer, // symbol: "filename'symbol+offset [address]"
+ outputBufferSize,
+ "%s'%s+0x%p [0x%p]",
+ symbolInfo.dli_fname,
+ symbolInfo.dli_sname,
+ reinterpret_cast<char*>(reinterpret_cast<char*>(address) -
+ reinterpret_cast<char*>(symbolInfo.dli_saddr)),
+ address);
+ }
+} // namespace
+
+ typedef int (*WalkcontextCallbackFunc)(uintptr_t address, int signalNumber, void* thisContext);
+
+ int backtrace_emulation(void** array, int size) {
+ WalkcontextCallback walkcontextCallback(reinterpret_cast<uintptr_t*>(array), size);
+ ucontext_t context;
+ if (getcontext(&context) != 0) {
+ return 0;
+ }
+ int wcReturn = walkcontext(
+ &context,
+ reinterpret_cast<WalkcontextCallbackFunc>(WalkcontextCallback::callbackFunction),
+ static_cast<void*>(&walkcontextCallback));
+ if (wcReturn == 0) {
+ return walkcontextCallback.getCount();
+ }
+ return 0;
+ }
+
+ // The API for backtrace_symbols() specifies that the caller must call free() on the char**
+ // returned by this function, and must *not* call free on the individual strings.
+ // In order to support this API, we allocate a single block of memory containing both the
+ // array of pointers to the strings and the strings themselves. Constructing this block
+ // requires two passes: one to collect the strings and calculate the required size of the
+ // combined single memory block; and a second pass to copy the strings into the block and
+ // set their pointers.
+ // The result is that we return a single memory block (allocated with malloc()) which begins
+ // with an array of pointers to strings (of count 'size'). This array is immediately
+ // followed by the strings themselves, each NUL terminated.
+ //
+ char** backtrace_symbols_emulation(void* const* array, int size) {
+ vector<string> stringVector;
+ vector<size_t> stringLengths;
+ size_t blockSize = size * sizeof(char*);
+ size_t blockPtr = blockSize;
+ const size_t kBufferSize = 8 * 1024;
+ boost::scoped_array<char> stringBuffer(new char[kBufferSize]);
+ for (int i = 0; i < size; ++i) {
+ size_t thisLength = 1 + addrtosymstr(array[i], stringBuffer.get(), kBufferSize);
+ stringVector.push_back(string(stringBuffer.get()));
+ stringLengths.push_back(thisLength);
+ blockSize += thisLength;
+ }
+ char** singleBlock = static_cast<char**>(malloc(blockSize));
+ if (singleBlock == NULL) {
+ return NULL;
+ }
+ for (int i = 0; i < size; ++i) {
+ singleBlock[i] = reinterpret_cast<char*>(singleBlock) + blockPtr;
+ strncpy(singleBlock[i], stringVector[i].c_str(), stringLengths[i]);
+ blockPtr += stringLengths[i];
+ }
+ return singleBlock;
+ }
+
+ void backtrace_symbols_fd_emulation(void* const* array, int size, int fd) {
+ const int kBufferSize = 4 * 1024;
+ char stringBuffer[kBufferSize];
+ for (int i = 0; i < size; ++i) {
+ int len = addrtosymstr(array[i], stringBuffer, kBufferSize);
+ if (len > kBufferSize - 1) {
+ len = kBufferSize - 1;
+ }
+ stringBuffer[len] = '\n';
+ write(fd, stringBuffer, len + 1);
+ }
+ }
+
+ typedef int (*BacktraceFunc)(void** array, int size);
+ static BacktraceFunc backtrace_switcher =
+ pal::backtrace_emulation;
+
+ typedef char** (*BacktraceSymbolsFunc)(void* const* array, int size);
+ static BacktraceSymbolsFunc backtrace_symbols_switcher =
+ pal::backtrace_symbols_emulation;
+
+ typedef void (*BacktraceSymbolsFdFunc)(void* const* array, int size, int fd);
+ static BacktraceSymbolsFdFunc backtrace_symbols_fd_switcher =
+ pal::backtrace_symbols_fd_emulation;
+
+ int backtrace(void** array, int size) {
+ return backtrace_switcher(array, size);
+ }
+
+ char** backtrace_symbols(void* const* array, int size) {
+ return backtrace_symbols_switcher(array, size);
+ }
+
+ void backtrace_symbols_fd(void* const* array, int size, int fd) {
+ backtrace_symbols_fd_switcher(array, size, fd);
+ }
+
+} // namespace pal
+
+ // 'backtrace()', 'backtrace_symbols()' and 'backtrace_symbols_fd()' on Solaris will call
+ // emulation functions if the symbols are not found
+ //
+ MONGO_INITIALIZER_GENERAL(SolarisBacktrace,
+ MONGO_NO_PREREQUISITES,
+ ("default"))(InitializerContext* context) {
+ void* functionAddress = dlsym(RTLD_DEFAULT, "backtrace");
+ if (functionAddress != NULL) {
+ pal::backtrace_switcher =
+ reinterpret_cast<pal::BacktraceFunc>(functionAddress);
+ }
+ functionAddress = dlsym(RTLD_DEFAULT, "backtrace_symbols");
+ if (functionAddress != NULL) {
+ pal::backtrace_symbols_switcher =
+ reinterpret_cast<pal::BacktraceSymbolsFunc>(functionAddress);
+ }
+ functionAddress = dlsym(RTLD_DEFAULT, "backtrace_symbols_fd");
+ if (functionAddress != NULL) {
+ pal::backtrace_symbols_fd_switcher =
+ reinterpret_cast<pal::BacktraceSymbolsFdFunc>(functionAddress);
+ }
+ return Status::OK();
+ }
+
+} // namespace mongo
+
+#endif // #if defined(__sunos__)
+#endif // #if !defined(_WIN32)
diff --git a/src/mongo/platform/backtrace.h b/src/mongo/platform/backtrace.h
new file mode 100644
index 00000000000..962cfa43119
--- /dev/null
+++ b/src/mongo/platform/backtrace.h
@@ -0,0 +1,43 @@
+/* Copyright 2013 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#if !defined(_WIN32)
+#if defined(__sunos__) || !defined(MONGO_HAVE_EXECINFO_BACKTRACE)
+
+namespace mongo {
+ namespace pal {
+ int backtrace(void** array, int size);
+ char** backtrace_symbols(void* const* array, int size);
+ void backtrace_symbols_fd(void* const* array, int size, int fd);
+ } // namespace pal
+ using pal::backtrace;
+ using pal::backtrace_symbols;
+ using pal::backtrace_symbols_fd;
+} // namespace mongo
+
+#else
+
+#include <execinfo.h>
+
+namespace mongo {
+ using ::backtrace;
+ using ::backtrace_symbols;
+ using ::backtrace_symbols_fd;
+} // namespace mongo
+
+#endif
+#endif
diff --git a/src/mongo/platform/posix_fadvise.cpp b/src/mongo/platform/posix_fadvise.cpp
new file mode 100644
index 00000000000..3053b02fbec
--- /dev/null
+++ b/src/mongo/platform/posix_fadvise.cpp
@@ -0,0 +1,56 @@
+/* Copyright 2013 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(__sunos__)
+
+#include "mongo/platform/posix_fadvise.h"
+
+#include <dlfcn.h>
+
+#include "mongo/base/init.h"
+#include "mongo/base/status.h"
+
+namespace mongo {
+namespace pal {
+
+ int posix_fadvise_emulation(int fd, off_t offset, off_t len, int advice) {
+ return 0;
+ }
+
+ typedef int (*PosixFadviseFunc)(int fd, off_t offset, off_t len, int advice);
+ static PosixFadviseFunc posix_fadvise_switcher = mongo::pal::posix_fadvise_emulation;
+
+ int posix_fadvise(int fd, off_t offset, off_t len, int advice) {
+ return posix_fadvise_switcher(fd, offset, len, advice);
+ }
+
+} // namespace pal
+
+ // 'posix_fadvise()' on Solaris will call the emulation if the symbol is not found
+ //
+ MONGO_INITIALIZER_GENERAL(SolarisPosixFadvise,
+ MONGO_NO_PREREQUISITES,
+ ("default"))(InitializerContext* context) {
+ void* functionAddress = dlsym(RTLD_DEFAULT, "posix_fadvise");
+ if (functionAddress != NULL) {
+ mongo::pal::posix_fadvise_switcher =
+ reinterpret_cast<mongo::pal::PosixFadviseFunc>(functionAddress);
+ }
+ return Status::OK();
+ }
+
+} // namespace mongo
+
+#endif // #if defined(__sunos__)
diff --git a/src/mongo/platform/posix_fadvise.h b/src/mongo/platform/posix_fadvise.h
new file mode 100644
index 00000000000..117b6b917f4
--- /dev/null
+++ b/src/mongo/platform/posix_fadvise.h
@@ -0,0 +1,41 @@
+/* Copyright 2013 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#if !defined(_WIN32)
+
+#include <fcntl.h>
+
+#if defined(__sunos__)
+
+#include <sys/types.h>
+
+namespace mongo {
+ namespace pal {
+ int posix_fadvise(int fd, off_t offset, off_t len, int advice);
+ } // namespace pal
+ using pal::posix_fadvise;
+} // namespace mongo
+
+#elif defined(POSIX_FADV_DONTNEED)
+
+namespace mongo {
+ using ::posix_fadvise;
+} // namespace mongo
+
+#endif
+
+#endif
diff --git a/src/mongo/platform/strcasestr.cpp b/src/mongo/platform/strcasestr.cpp
new file mode 100644
index 00000000000..1bcd0a37094
--- /dev/null
+++ b/src/mongo/platform/strcasestr.cpp
@@ -0,0 +1,105 @@
+/* Copyright 2013 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mongo/platform/strcasestr.h"
+
+#if defined(__sunos__)
+#include <dlfcn.h>
+
+#include "mongo/base/init.h"
+#include "mongo/base/status.h"
+#endif
+
+#if defined(_WIN32) || defined(__sunos__)
+
+#include <algorithm>
+#include <cctype>
+#include <cstring>
+#include <string>
+
+#if defined(__sunos__)
+#define STRCASESTR_EMULATION_NAME strcasestr_emulation
+#else
+#define STRCASESTR_EMULATION_NAME strcasestr
+#endif
+
+namespace mongo {
+namespace pal {
+
+ /**
+ * strcasestr -- case-insensitive search for a substring within another string.
+ *
+ * @param haystack ptr to C-string to search
+ * @param needle ptr to C-string to try to find within 'haystack'
+ * @return ptr to start of 'needle' within 'haystack' if found, NULL otherwise
+ */
+ const char* STRCASESTR_EMULATION_NAME(const char* haystack, const char* needle) {
+
+ std::string haystackLower(haystack);
+ std::transform(haystackLower.begin(),
+ haystackLower.end(),
+ haystackLower.begin(),
+ ::tolower);
+
+ std::string needleLower(needle);
+ std::transform(needleLower.begin(),
+ needleLower.end(),
+ needleLower.begin(),
+ ::tolower);
+
+ // Use strstr() to find 'lowercased needle' in 'lowercased haystack'
+ // If found, use the location to compute the matching location in the original string
+ // If not found, return NULL
+ const char* haystackLowerStart = haystackLower.c_str();
+ const char* location = strstr(haystackLowerStart, needleLower.c_str());
+ return location ? (haystack + (location - haystackLowerStart)) : NULL;
+ }
+
+#if defined(__sunos__)
+
+ typedef const char* (*StrCaseStrFunc)(const char* haystack, const char* needle);
+ static StrCaseStrFunc strcasestr_switcher = mongo::pal::strcasestr_emulation;
+
+ const char* strcasestr(const char* haystack, const char* needle) {
+ return strcasestr_switcher(haystack, needle);
+ }
+
+#endif // #if defined(__sunos__)
+
+} // namespace pal
+} // namespace mongo
+
+#endif // #if defined(_WIN32) || defined(__sunos__)
+
+#if defined(__sunos__)
+
+namespace mongo {
+
+ // 'strcasestr()' on Solaris will call the emulation if the symbol is not found
+ //
+ MONGO_INITIALIZER_GENERAL(SolarisStrCaseCmp,
+ MONGO_NO_PREREQUISITES,
+ ("default"))(InitializerContext* context) {
+ void* functionAddress = dlsym(RTLD_DEFAULT, "strcasestr");
+ if (functionAddress != NULL) {
+ mongo::pal::strcasestr_switcher =
+ reinterpret_cast<mongo::pal::StrCaseStrFunc>(functionAddress);
+ }
+ return Status::OK();
+ }
+
+} // namespace mongo
+
+#endif // __sunos__
diff --git a/src/mongo/platform/strcasestr.h b/src/mongo/platform/strcasestr.h
new file mode 100644
index 00000000000..844374f6915
--- /dev/null
+++ b/src/mongo/platform/strcasestr.h
@@ -0,0 +1,35 @@
+/* Copyright 2013 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#if defined(_WIN32) || defined(__sunos__)
+
+namespace mongo {
+namespace pal {
+ const char* strcasestr(const char* haystack, const char* needle);
+}
+ using mongo::pal::strcasestr;
+}
+
+#else
+
+#include <cstring>
+
+namespace mongo {
+ using ::strcasestr;
+}
+
+#endif
diff --git a/src/mongo/s/balance.cpp b/src/mongo/s/balance.cpp
index de72b25dada..2cf9d06d131 100644
--- a/src/mongo/s/balance.cpp
+++ b/src/mongo/s/balance.cpp
@@ -24,6 +24,7 @@
#include "mongo/db/jsobj.h"
#include "mongo/s/chunk.h"
#include "mongo/s/config.h"
+#include "mongo/s/config_server_checker_service.h"
#include "mongo/s/grid.h"
#include "mongo/s/server.h"
#include "mongo/s/shard.h"
@@ -461,7 +462,14 @@ namespace mongo {
sleepsecs( sleepTime ); // no need to wake up soon
continue;
}
-
+
+ if ( !isConfigServerConsistent() ) {
+ conn.done();
+ warning() << "Skipping balancing round because data inconsistency"
+ << " was detected amongst the config servers." << endl;
+ continue;
+ }
+
LOG(1) << "*** start balancing round" << endl;
bool waitForDelete = false;
diff --git a/src/mongo/s/balancer_policy.cpp b/src/mongo/s/balancer_policy.cpp
index 184451637ed..e5edf340c1c 100644
--- a/src/mongo/s/balancer_policy.cpp
+++ b/src/mongo/s/balancer_policy.cpp
@@ -77,8 +77,18 @@ namespace mongo {
unsigned minChunks = numeric_limits<unsigned>::max();
for ( ShardInfoMap::const_iterator i = _shardInfo.begin(); i != _shardInfo.end(); ++i ) {
- if ( i->second.isSizeMaxed() || i->second.isDraining() || i->second.hasOpsQueued() ) {
- LOG(1) << i->first << " is unavailable" << endl;
+ if ( i->second.isSizeMaxed() ) {
+ LOG(1) << i->first << " has already reached the maximum total chunk size." << endl;
+ continue;
+ }
+
+ if ( i->second.isDraining() ) {
+ LOG(1) << i->first << " is currently draining." << endl;
+ continue;
+ }
+
+ if ( i->second.hasOpsQueued() ) {
+ LOG(1) << i->first << " has writebacks queued." << endl;
continue;
}
diff --git a/src/mongo/s/chunk_diff.hpp b/src/mongo/s/chunk_diff.hpp
index 0206851d26e..b5b0bab410b 100644
--- a/src/mongo/s/chunk_diff.hpp
+++ b/src/mongo/s/chunk_diff.hpp
@@ -173,8 +173,11 @@ namespace mongo {
if( isTracked( diffChunkDoc ) ) newTracked.push_back( diffChunkDoc.getOwned() );
}
- LOG(3) << "found " << _validDiffs << " new chunks for collection " << _ns
- << " (tracking " << newTracked.size() << "), new version is " << _maxVersion << endl;
+ LOG(3) << "found " << _validDiffs
+ << " new chunks for collection " << _ns
+ << " (tracking " << newTracked.size()
+ << "), new version is " << *_maxVersion
+ << endl;
for( vector<BSONObj>::iterator it = newTracked.begin(); it != newTracked.end(); it++ ){
@@ -279,9 +282,6 @@ namespace mongo {
BSONObj query = queryB.obj();
- LOG(2) << "major version query from " << *_maxVersion << " and over "
- << _maxShardVersions->size() << " shards is " << query << endl;
-
//
// NOTE: IT IS IMPORTANT FOR CONSISTENCY THAT WE SORT BY ASC VERSION, TO HANDLE
// CURSOR YIELDING BETWEEN CHUNKS BEING MIGRATED.
@@ -293,7 +293,10 @@ namespace mongo {
Query queryObj(query);
queryObj.sort(BSON( "lastmod" << 1 ));
- return Query( query );
+ LOG(2) << "major version query from " << *_maxVersion << " and over "
+ << _maxShardVersions->size() << " shards is " << queryObj << endl;
+
+ return queryObj;
}
} // namespace mongo
diff --git a/src/mongo/s/config_server_checker_service.cpp b/src/mongo/s/config_server_checker_service.cpp
new file mode 100644
index 00000000000..4d30cdcf50f
--- /dev/null
+++ b/src/mongo/s/config_server_checker_service.cpp
@@ -0,0 +1,62 @@
+/**
+ * Copyright (C) 2013 10gen Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <boost/scoped_ptr.hpp>
+#include <boost/thread/thread.hpp>
+
+#include "mongo/s/config.h"
+#include "mongo/s/config_server_checker_service.h"
+#include "mongo/util/concurrency/mutex.h"
+
+namespace mongo {
+
+ namespace {
+
+ // Thread that runs dbHash on config servers for checking data consistency.
+ boost::scoped_ptr<boost::thread> _checkerThread;
+
+ // Protects _isConsistentFromLastCheck.
+ mutex _isConsistentMutex( "ConfigServerConsistent" );
+ bool _isConsistentFromLastCheck = true;
+
+ void checkConfigConsistency() {
+ while ( !inShutdown() ) {
+ bool isConsistent = configServer.ok( true );
+
+ {
+ scoped_lock sl( _isConsistentMutex );
+ _isConsistentFromLastCheck = isConsistent;
+ }
+
+ sleepsecs( 60 );
+ }
+ }
+ }
+
+ bool isConfigServerConsistent() {
+ scoped_lock sl( _isConsistentMutex );
+ return _isConsistentFromLastCheck;
+ }
+
+ bool startConfigServerChecker() {
+ if ( _checkerThread == NULL ) {
+ _checkerThread.reset( new boost::thread( checkConfigConsistency ));
+ }
+
+ return _checkerThread != NULL;
+ }
+}
+
diff --git a/src/mongo/s/config_server_checker_service.h b/src/mongo/s/config_server_checker_service.h
new file mode 100644
index 00000000000..4661d0fc756
--- /dev/null
+++ b/src/mongo/s/config_server_checker_service.h
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) 2013 10gen Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace mongo {
+
+ /**
+ * Returns true if the config servers have the same contents since the last check
+ * was performed. Currently checks only the config.chunks and config.databases.
+ */
+ bool isConfigServerConsistent();
+
+ /**
+ * Starts the thread that periodically checks data consistency amongst the config servers.
+ * Note: this is not thread safe.
+ */
+ bool startConfigServerChecker();
+}
+
diff --git a/src/mongo/s/d_migrate.cpp b/src/mongo/s/d_migrate.cpp
index 139a640f5ce..85eb18294dd 100644
--- a/src/mongo/s/d_migrate.cpp
+++ b/src/mongo/s/d_migrate.cpp
@@ -589,10 +589,11 @@ namespace mongo {
}
BSONObj o = dl.obj();
-
+
// use the builder size instead of accumulating 'o's size so that we take into consideration
- // the overhead of BSONArray indices
- if ( a.len() + o.objsize() + 1024 > BSONObjMaxUserSize ) {
+ // the overhead of BSONArray indices, and *always* append one doc
+ if ( a.arrSize() != 0 &&
+ a.len() + o.objsize() + 1024 > BSONObjMaxUserSize ) {
filledBuffer = true; // break out of outer while loop
break;
}
@@ -638,6 +639,11 @@ namespace mongo {
_cloneLocs.erase( dl );
}
+ std::size_t cloneLocsRemaining() {
+ scoped_spinlock lk( _trackerLocks );
+ return _cloneLocs.size();
+ }
+
long long mbUsed() const { return _memoryUsed / ( 1024 * 1024 ); }
bool getInCriticalSection() const {
@@ -1161,15 +1167,20 @@ namespace mongo {
timing.done( 3 );
// 4.
+
+ // Track last result from TO shard for sanity check
+ BSONObj res;
for ( int i=0; i<86400; i++ ) { // don't want a single chunk move to take more than a day
verify( !Lock::isLocked() );
// Exponential sleep backoff, up to 1024ms. Don't sleep much on the first few
// iterations, since we want empty chunk migrations to be fast.
sleepmillis( 1 << std::min( i , 10 ) );
+
scoped_ptr<ScopedDbConnection> conn(
ScopedDbConnection::getScopedDbConnection( toShard.getConnString() ) );
- BSONObj res;
+
bool ok;
+ res = BSONObj();
try {
ok = conn->get()->runCommand( "admin" , BSON( "_recvChunkStatus" << 1 ) , res );
res = res.getOwned();
@@ -1217,9 +1228,26 @@ namespace mongo {
// 5.
// Before we get into the critical section of the migration, let's double check
- // that the config servers are reachable and the lock is in place.
- log() << "About to check if it is safe to enter critical section";
+ // that the docs have been cloned, the config servers are reachable,
+ // and the lock is in place.
+ log() << "About to check if it is safe to enter critical section" << endl;
+
+ // Ensure all cloned docs have actually been transferred
+ std::size_t locsRemaining = migrateFromStatus.cloneLocsRemaining();
+ if ( locsRemaining != 0 ) {
+
+ errmsg =
+ str::stream() << "moveChunk cannot enter critical section before all data is"
+ << " cloned, " << locsRemaining << " locs were not transferred"
+ << " but to-shard reported " << res;
+
+ // Should never happen, but safe to abort before critical section
+ error() << errmsg << migrateLog;
+ dassert( false );
+ return false;
+ }
+ // Ensure distributed lock still held
string lockHeldMsg;
bool lockHeld = dlk.isLockHeld( 30.0 /* timeout */, &lockHeldMsg );
if ( !lockHeld ) {
@@ -1252,49 +1280,48 @@ namespace mongo {
// 5.b
// we're under the collection lock here, too, so we can undo the chunk donation because no other state change
// could be ongoing
- {
- BSONObj res;
+
+ BSONObj res;
+ bool ok;
+
+ try {
scoped_ptr<ScopedDbConnection> connTo(
ScopedDbConnection::getScopedDbConnection( toShard.getConnString(),
35.0 ) );
-
- bool ok;
-
- try{
- ok = connTo->get()->runCommand( "admin" ,
- BSON( "_recvChunkCommit" << 1 ) ,
- res );
- }
- catch( DBException& e ){
- errmsg = str::stream() << "moveChunk could not contact to: shard " << toShard.getConnString() << " to commit transfer" << causedBy( e );
- warning() << errmsg << endl;
- ok = false;
- }
-
+ ok = connTo->get()->runCommand( "admin", BSON( "_recvChunkCommit" << 1 ), res );
connTo->done();
+ }
+ catch ( DBException& e ) {
+ errmsg = str::stream() << "moveChunk could not contact to: shard "
+ << toShard.getConnString() << " to commit transfer"
+ << causedBy( e );
+ warning() << errmsg << endl;
+ ok = false;
+ }
- if ( ! ok ) {
- log() << "moveChunk migrate commit not accepted by TO-shard: " << res
- << " resetting shard version to: " << startingVersion << migrateLog;
- {
- Lock::GlobalWrite lk;
- log() << "moveChunk global lock acquired to reset shard version from "
- "failed migration" << endl;
-
- // revert the chunk manager back to the state before "forgetting" about the chunk
- shardingState.undoDonateChunk( ns , min , max , startingVersion );
- }
- log() << "Shard version successfully reset to clean up failed migration"
- << endl;
+ if ( !ok ) {
+ log() << "moveChunk migrate commit not accepted by TO-shard: " << res
+ << " resetting shard version to: " << startingVersion << migrateLog;
+ {
+ Lock::GlobalWrite lk;
+ log() << "moveChunk global lock acquired to reset shard version from "
+ "failed migration"
+ << endl;
- errmsg = "_recvChunkCommit failed!";
- result.append( "cause" , res );
- return false;
+ // revert the chunk manager back to the state before "forgetting" about the
+ // chunk
+ shardingState.undoDonateChunk( ns, min, max, startingVersion );
}
+ log() << "Shard version successfully reset to clean up failed migration"
+ << endl;
- log() << "moveChunk migrate commit accepted by TO-shard: " << res << migrateLog;
+ errmsg = "_recvChunkCommit failed!";
+ result.append( "cause", res );
+ return false;
}
+ log() << "moveChunk migrate commit accepted by TO-shard: " << res << migrateLog;
+
// 5.c
// version at which the next highest lastmod will be set
@@ -1404,7 +1431,7 @@ namespace mongo {
LOG(7) << "moveChunk update: " << cmd << migrateLog;
int exceptionCode = OkCode;
- bool ok = false;
+ ok = false;
BSONObj cmdResult;
try {
scoped_ptr<ScopedDbConnection> conn(
diff --git a/src/mongo/s/d_split.cpp b/src/mongo/s/d_split.cpp
index 5231e9e571b..86f9d5ef728 100644
--- a/src/mongo/s/d_split.cpp
+++ b/src/mongo/s/d_split.cpp
@@ -289,13 +289,14 @@ namespace mongo {
// 'force'-ing a split is equivalent to having maxChunkSize be the size of the current chunk, i.e., the
// logic below will split that chunk in half
long long maxChunkSize = 0;
- bool force = false;
+ bool forceMedianSplit = false;
{
BSONElement maxSizeElem = jsobj[ "maxChunkSize" ];
BSONElement forceElem = jsobj[ "force" ];
if ( forceElem.trueValue() ) {
- force = true;
+ forceMedianSplit = true;
+ // This chunk size is effectively ignored if force is true
maxChunkSize = dataSize;
}
@@ -365,7 +366,8 @@ namespace mongo {
while ( cc->ok() ) {
currCount++;
- if ( currCount > keyCount ) {
+ if ( currCount > keyCount && !forceMedianSplit ) {
+
BSONObj currKey = bc->prettyKey( c->currKey() ).extractFields(keyPattern);
// Do not use this split key if it is the same used in the previous split point.
if ( currKey.woCompare( splitKeys.back() ) == 0 ) {
@@ -403,10 +405,15 @@ namespace mongo {
}
}
- if ( splitKeys.size() > 1 || ! force )
+ if ( ! forceMedianSplit )
break;
- force = false;
+ //
+ // If we're forcing a split at the halfway point, then the first pass was just
+ // to count the keys, and we still need a second pass.
+ //
+
+ forceMedianSplit = false;
keyCount = currCount / 2;
currCount = 0;
log() << "splitVector doing another cycle because of force, keyCount now: " << keyCount << endl;
diff --git a/src/mongo/s/d_state.cpp b/src/mongo/s/d_state.cpp
index 95ba21ab8f9..bca04ff565a 100644
--- a/src/mongo/s/d_state.cpp
+++ b/src/mongo/s/d_state.cpp
@@ -275,6 +275,10 @@ namespace mongo {
}
{
+ // NOTE: This lock prevents the ns version from changing while a write operation occurs.
+ Lock::DBRead readLk(ns);
+
+ // This lock prevents simultaneous metadata changes using the same map
scoped_lock lk( _mutex );
// since we loaded the chunk manager unlocked, other thread may have done the same
diff --git a/src/mongo/s/mongos.vcxproj b/src/mongo/s/mongos.vcxproj
index fb597f75bce..97300042b3f 100644
--- a/src/mongo/s/mongos.vcxproj
+++ b/src/mongo/s/mongos.vcxproj
@@ -2442,7 +2442,10 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClCompile Include="..\db\server_parameters.cpp" />
<ClCompile Include="..\db\stats\timer_stats.cpp" />
<ClCompile Include="..\db\stats\top.cpp" />
+ <ClCompile Include="..\platform\backtrace.cpp" />
+ <ClCompile Include="..\platform\posix_fadvise.cpp" />
<ClCompile Include="..\platform\random.cpp" />
+ <ClCompile Include="..\platform\strcasestr.cpp" />
<ClCompile Include="..\scripting\bench.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator_test.cpp">
@@ -2538,6 +2541,7 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClCompile Include="commands_admin.cpp" />
<ClCompile Include="commands_public.cpp" />
<ClCompile Include="config.cpp" />
+ <ClCompile Include="config_server_checker_service.cpp" />
<ClCompile Include="config_upgrade.cpp" />
<ClCompile Include="config_upgrade_helpers.cpp" />
<ClCompile Include="config_upgrade_v0_to_v4.cpp" />
@@ -3136,13 +3140,16 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClInclude Include="..\platform\atomic_intrinsics.h" />
<ClInclude Include="..\platform\atomic_intrinsics_win32.h" />
<ClInclude Include="..\platform\atomic_word.h" />
+ <ClInclude Include="..\platform\backtrace.h" />
<ClInclude Include="..\platform\basic.h" />
<ClInclude Include="..\platform\bits.h" />
<ClInclude Include="..\platform\compiler.h" />
<ClInclude Include="..\platform\compiler_msvc.h" />
<ClInclude Include="..\platform\cstdint.h" />
<ClInclude Include="..\platform\float_utils.h" />
+ <ClInclude Include="..\platform\posix_fadvise.h" />
<ClInclude Include="..\platform\random.h" />
+ <ClInclude Include="..\platform\strcasestr.h" />
<ClInclude Include="..\platform\strtoll.h" />
<ClInclude Include="..\platform\unordered_map.h" />
<ClInclude Include="..\platform\unordered_set.h" />
@@ -3259,6 +3266,7 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClInclude Include="cluster_client_internal.h" />
<ClInclude Include="collection_manager.h" />
<ClInclude Include="config.h" />
+ <ClInclude Include="config_server_checker_service.h" />
<ClInclude Include="config_upgrade.h" />
<ClInclude Include="config_upgrade_helpers.h" />
<ClInclude Include="cursors.h" />
diff --git a/src/mongo/s/mongos.vcxproj.filters b/src/mongo/s/mongos.vcxproj.filters
index 691485ab06c..c55dc8ff667 100755
--- a/src/mongo/s/mongos.vcxproj.filters
+++ b/src/mongo/s/mongos.vcxproj.filters
@@ -1632,6 +1632,18 @@
<ClCompile Include="..\client\sasl_client_authenticate.cpp">
<Filter>client</Filter>
</ClCompile>
+ <ClCompile Include="..\platform\strcasestr.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\backtrace.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\posix_fadvise.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="config_server_checker_service.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\pch.h" />
@@ -3210,6 +3222,18 @@
<ClInclude Include="..\client\sasl_client_authenticate.h">
<Filter>client</Filter>
</ClInclude>
+ <ClInclude Include="..\platform\strcasestr.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\backtrace.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\posix_fadvise.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="config_server_checker_service.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\base\error_codes.err">
diff --git a/src/mongo/s/mongos_sm.vcxproj b/src/mongo/s/mongos_sm.vcxproj
index e02683838f5..bb4d032f8e3 100644
--- a/src/mongo/s/mongos_sm.vcxproj
+++ b/src/mongo/s/mongos_sm.vcxproj
@@ -2271,7 +2271,10 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClCompile Include="..\db\server_parameters.cpp" />
<ClCompile Include="..\db\stats\timer_stats.cpp" />
<ClCompile Include="..\db\stats\top.cpp" />
+ <ClCompile Include="..\platform\backtrace.cpp" />
+ <ClCompile Include="..\platform\posix_fadvise.cpp" />
<ClCompile Include="..\platform\random.cpp" />
+ <ClCompile Include="..\platform\strcasestr.cpp" />
<ClCompile Include="..\scripting\bench.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator_test.cpp">
@@ -2394,6 +2397,7 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClCompile Include="commands_admin.cpp" />
<ClCompile Include="commands_public.cpp" />
<ClCompile Include="config.cpp" />
+ <ClCompile Include="config_server_checker_service.cpp" />
<ClCompile Include="config_upgrade.cpp" />
<ClCompile Include="config_upgrade_helpers.cpp" />
<ClCompile Include="config_upgrade_v0_to_v4.cpp" />
@@ -2719,13 +2723,16 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClInclude Include="..\platform\atomic_intrinsics.h" />
<ClInclude Include="..\platform\atomic_intrinsics_win32.h" />
<ClInclude Include="..\platform\atomic_word.h" />
+ <ClInclude Include="..\platform\backtrace.h" />
<ClInclude Include="..\platform\basic.h" />
<ClInclude Include="..\platform\bits.h" />
<ClInclude Include="..\platform\compiler.h" />
<ClInclude Include="..\platform\compiler_msvc.h" />
<ClInclude Include="..\platform\cstdint.h" />
<ClInclude Include="..\platform\float_utils.h" />
+ <ClInclude Include="..\platform\posix_fadvise.h" />
<ClInclude Include="..\platform\random.h" />
+ <ClInclude Include="..\platform\strcasestr.h" />
<ClInclude Include="..\platform\strtoll.h" />
<ClInclude Include="..\platform\unordered_map.h" />
<ClInclude Include="..\platform\unordered_set.h" />
@@ -2869,6 +2876,7 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClInclude Include="cluster_client_internal.h" />
<ClInclude Include="collection_manager.h" />
<ClInclude Include="config.h" />
+ <ClInclude Include="config_server_checker_service.h" />
<ClInclude Include="config_upgrade.h" />
<ClInclude Include="config_upgrade_helpers.h" />
<ClInclude Include="cursors.h" />
diff --git a/src/mongo/s/mongos_sm.vcxproj.filters b/src/mongo/s/mongos_sm.vcxproj.filters
index 8b107b3dc2f..7660ede7014 100644
--- a/src/mongo/s/mongos_sm.vcxproj.filters
+++ b/src/mongo/s/mongos_sm.vcxproj.filters
@@ -1233,6 +1233,18 @@
<ClCompile Include="..\client\sasl_client_authenticate.cpp">
<Filter>client</Filter>
</ClCompile>
+ <ClCompile Include="..\platform\strcasestr.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\backtrace.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\posix_fadvise.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="config_server_checker_service.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\pch.h" />
@@ -2349,6 +2361,18 @@
<ClInclude Include="..\client\sasl_client_authenticate.h">
<Filter>client</Filter>
</ClInclude>
+ <ClInclude Include="..\platform\strcasestr.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\backtrace.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\posix_fadvise.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="config_server_checker_service.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\third_party\js-1.7\jskeyword.tbl">
diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp
index 6f5f4ed52f7..e6aa728d7a3 100644
--- a/src/mongo/s/server.cpp
+++ b/src/mongo/s/server.cpp
@@ -45,6 +45,7 @@
#include "cursors.h"
#include "../util/processinfo.h"
#include "mongo/db/lasterror.h"
+#include "mongo/s/config_server_checker_service.h"
#include "mongo/s/config_upgrade.h"
#include "mongo/util/stacktrace.h"
#include "mongo/util/exception_filter_win32.h"
@@ -292,14 +293,7 @@ static bool runMongosServer( bool doUpgrade ) {
return false;
}
- {
- class CheckConfigServers : public task::Task {
- virtual string name() const { return "CheckConfigServers"; }
- virtual void doWork() { configServer.ok(true); }
- };
-
- task::repeat(new CheckConfigServers, 60*1000);
- }
+ startConfigServerChecker();
VersionType initVersionInfo;
VersionType versionInfo;
diff --git a/src/mongo/scripting/engine_v8.cpp b/src/mongo/scripting/engine_v8.cpp
index 7ffebec383e..5aa40b1abf0 100644
--- a/src/mongo/scripting/engine_v8.cpp
+++ b/src/mongo/scripting/engine_v8.cpp
@@ -919,7 +919,7 @@ namespace mongo {
// script loaded from file
ss << " at " << *resourceName;
const int linenum = message->GetLineNumber();
- if (linenum != 1) ss << ":L" << linenum;
+ if (linenum != 1) ss << ":" << linenum;
}
return ss.str();
}
@@ -1572,6 +1572,14 @@ namespace mongo {
void V8Scope::v8ToMongoElement(BSONObjBuilder & b, const StringData& sname,
v8::Handle<v8::Value> value, int depth,
BSONObj* originalParent) {
+
+ // Null char should be at the end, not in the string
+ uassert(16985,
+ str::stream() << "JavaScript property (name) contains a null char "
+ << "which is not allowed in BSON. "
+ << originalParent->jsonString(),
+ (string::npos == sname.find('\0')) );
+
if (value->IsString()) {
b.append(sname, V8String(value));
return;
diff --git a/src/mongo/scripting/engine_v8.h b/src/mongo/scripting/engine_v8.h
index 448ab38af26..442441c55ce 100644
--- a/src/mongo/scripting/engine_v8.h
+++ b/src/mongo/scripting/engine_v8.h
@@ -530,7 +530,7 @@ namespace mongo {
if (try_catch.HasCaught() && try_catch.CanContinue()) {
// normal JS exception
- _error = string("JavaScript execution failed: ") + v8ExceptionToSTLString(&try_catch);
+ _error = v8ExceptionToSTLString(&try_catch);
haveError = true;
}
else if (hasOutOfMemoryException()) {
diff --git a/src/mongo/shell/dbshell.cpp b/src/mongo/shell/dbshell.cpp
index 4d71d2b8d19..5934e862076 100644
--- a/src/mongo/shell/dbshell.cpp
+++ b/src/mongo/shell/dbshell.cpp
@@ -1043,10 +1043,6 @@ int _main( int argc, char* argv[], char **envp ) {
#ifdef _WIN32
int wmain( int argc, wchar_t* argvW[] ) {
static mongo::StaticObserver staticObserver;
- UINT initialConsoleInputCodePage = GetConsoleCP();
- UINT initialConsoleOutputCodePage = GetConsoleOutputCP();
- SetConsoleCP( CP_UTF8 );
- SetConsoleOutputCP( CP_UTF8 );
int returnCode;
try {
WindowsCommandLine wcl( argc, argvW );
@@ -1056,8 +1052,6 @@ int wmain( int argc, wchar_t* argvW[] ) {
cerr << "exception: " << e.what() << endl;
returnCode = 1;
}
- SetConsoleCP( initialConsoleInputCodePage );
- SetConsoleOutputCP( initialConsoleOutputCodePage );
::_exit(returnCode);
}
#else // #ifdef _WIN32
diff --git a/src/mongo/shell/mongo.js b/src/mongo/shell/mongo.js
index e4786a7cc17..2f3667f53f3 100644
--- a/src/mongo/shell/mongo.js
+++ b/src/mongo/shell/mongo.js
@@ -98,26 +98,58 @@ Mongo.prototype.getReadPrefTagSet = function () {
return this._readPrefTagSet;
};
-connect = function( url , user , pass ){
- chatty( "connecting to: " + url )
-
- if ( user && ! pass )
- throw "you specified a user and not a password. either you need a password, or you're using the old connect api";
+connect = function(url, user, pass) {
+ if (user && !pass)
+ throw Error("you specified a user and not a password. " +
+ "either you need a password, or you're using the old connect api");
+
+ // Validate connection string "url" as "hostName:portNumber/databaseName"
+ // or "hostName/databaseName"
+ // or "databaseName"
+ // hostName may be an IPv6 address (with colons), in which case ":portNumber" is required
+ //
+ var urlType = typeof url;
+ if (urlType == "undefined") {
+ throw Error("Missing connection string");
+ }
+ if (urlType != "string") {
+ throw Error("Incorrect type \"" + urlType +
+ "\" for connection string \"" + tojson(url) + "\"");
+ }
+ url = url.trim();
+ if (0 == url.length) {
+ throw Error("Empty connection string");
+ }
+ var colon = url.lastIndexOf(":");
+ var slash = url.lastIndexOf("/");
+ if (0 == colon || 0 == slash) {
+ throw Error("Missing host name in connection string \"" + url + "\"");
+ }
+ if (colon == slash - 1 || colon == url.length - 1) {
+ throw Error("Missing port number in connection string \"" + url + "\"");
+ }
+ if (colon != -1 && colon < slash) {
+ var portNumber = url.substring(colon + 1, slash);
+ if (portNumber.length > 5 || !/^\d*$/.test(portNumber) || parseInt(portNumber) > 65535) {
+ throw Error("Invalid port number \"" + portNumber +
+ "\" in connection string \"" + url + "\"");
+ }
+ }
+ if (slash == url.length - 1) {
+ throw Error("Missing database name in connection string \"" + url + "\"");
+ }
- var idx = url.lastIndexOf( "/" );
-
+ chatty("connecting to: " + url)
var db;
-
- if ( idx < 0 )
- db = new Mongo().getDB( url );
+ if (slash == -1)
+ db = new Mongo().getDB(url);
else
- db = new Mongo( url.substring( 0 , idx ) ).getDB( url.substring( idx + 1 ) );
-
- if ( user && pass ){
- if ( ! db.auth( user , pass ) ){
- throw "couldn't login";
+ db = new Mongo(url.substring(0, slash)).getDB(url.substring(slash + 1));
+
+ if (user && pass) {
+ if (!db.auth(user, pass)) {
+ throw Error("couldn't login");
}
}
-
return db;
}
diff --git a/src/mongo/shell/mongo.vcxproj b/src/mongo/shell/mongo.vcxproj
index 48bc5625c62..219f43e2488 100755
--- a/src/mongo/shell/mongo.vcxproj
+++ b/src/mongo/shell/mongo.vcxproj
@@ -382,6 +382,16 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="..\..\third_party\murmurhash3\MurmurHash3.cpp">
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4355;4800;4267;4244;4351;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">4355;4800;4267;4244;4351;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Win2008PlusDebug|Win32'">4355;4800;4267;4244;4351;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Win2008PlusRelease|Win32'">4355;4800;4267;4244;4351;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4355;4800;4267;4244;4351;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4355;4800;4267;4244;4351;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Win2008PlusDebug|x64'">4355;4800;4267;4244;4351;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Win2008PlusRelease|x64'">4355;4800;4267;4244;4351;4141</DisableSpecificWarnings>
+ </ClCompile>
<ClCompile Include="..\..\third_party\v8\src\experimental-libraries.cc">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\third_party\v8\src</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\third_party\v8\src</AdditionalIncludeDirectories>
@@ -1074,7 +1084,10 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClCompile Include="..\client\connection_factory.cpp" />
<ClCompile Include="..\client\sasl_client_authenticate.cpp" />
<ClCompile Include="..\db\dbmessage.cpp" />
+ <ClCompile Include="..\platform\backtrace.cpp" />
+ <ClCompile Include="..\platform\posix_fadvise.cpp" />
<ClCompile Include="..\platform\random.cpp" />
+ <ClCompile Include="..\platform\strcasestr.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -1271,6 +1284,7 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClCompile Include="shell_utils_launcher.cpp" />
</ItemGroup>
<ItemGroup>
+ <None Include="..\..\third_party\murmurhash3\SConscript" />
<None Include="..\..\third_party\run_if_newer.js" />
<None Include="..\..\third_party\v8\ChangeLog" />
<None Include="..\..\third_party\v8\ChangeLog_10gen" />
@@ -1309,6 +1323,7 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<None Include="utils_sh.js" />
</ItemGroup>
<ItemGroup>
+ <ClInclude Include="..\..\third_party\murmurhash3\MurmurHash3.h" />
<ClInclude Include="..\..\third_party\v8\include\v8-debug.h" />
<ClInclude Include="..\..\third_party\v8\include\v8-preparser.h" />
<ClInclude Include="..\..\third_party\v8\include\v8-profiler.h" />
@@ -1639,13 +1654,16 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClInclude Include="..\platform\atomic_intrinsics.h" />
<ClInclude Include="..\platform\atomic_intrinsics_win32.h" />
<ClInclude Include="..\platform\atomic_word.h" />
+ <ClInclude Include="..\platform\backtrace.h" />
<ClInclude Include="..\platform\basic.h" />
<ClInclude Include="..\platform\bits.h" />
<ClInclude Include="..\platform\compiler.h" />
<ClInclude Include="..\platform\compiler_msvc.h" />
<ClInclude Include="..\platform\cstdint.h" />
<ClInclude Include="..\platform\float_utils.h" />
+ <ClInclude Include="..\platform\posix_fadvise.h" />
<ClInclude Include="..\platform\random.h" />
+ <ClInclude Include="..\platform\strcasestr.h" />
<ClInclude Include="..\platform\strtoll.h" />
<ClInclude Include="..\platform\unordered_map.h" />
<ClInclude Include="..\platform\unordered_set.h" />
diff --git a/src/mongo/shell/mongo.vcxproj.filters b/src/mongo/shell/mongo.vcxproj.filters
index 0af752a3e3b..4f0661b84e3 100644
--- a/src/mongo/shell/mongo.vcxproj.filters
+++ b/src/mongo/shell/mongo.vcxproj.filters
@@ -158,6 +158,9 @@
<Filter Include="JavaScript source files\Included in shell only">
<UniqueIdentifier>{0d7ccbd5-b4e4-4e57-ae0b-b4a80a6fa6bb}</UniqueIdentifier>
</Filter>
+ <Filter Include="third_party\MurmurHash3">
+ <UniqueIdentifier>{5ced80f0-4dce-421a-ba59-1b338973dd97}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\scripting\engine.cpp">
@@ -1016,6 +1019,18 @@
<ClCompile Include="..\client\sasl_client_authenticate.cpp">
<Filter>client</Filter>
</ClCompile>
+ <ClCompile Include="..\..\third_party\murmurhash3\MurmurHash3.cpp">
+ <Filter>third_party\MurmurHash3</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\strcasestr.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\backtrace.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\posix_fadvise.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\third_party\v8\src\apinatives.js">
@@ -1126,6 +1141,9 @@
<None Include="types.js">
<Filter>JavaScript source files\Included in all executables</Filter>
</None>
+ <None Include="..\..\third_party\murmurhash3\SConscript">
+ <Filter>third_party\MurmurHash3</Filter>
+ </None>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\pch.h" />
@@ -2387,6 +2405,18 @@
<ClInclude Include="..\client\sasl_client_authenticate.h">
<Filter>client</Filter>
</ClInclude>
+ <ClInclude Include="..\..\third_party\murmurhash3\MurmurHash3.h">
+ <Filter>third_party\MurmurHash3</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\strcasestr.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\backtrace.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\posix_fadvise.h">
+ <Filter>platform</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\db\db.rc">
diff --git a/src/mongo/shell/mongo_sm.vcxproj b/src/mongo/shell/mongo_sm.vcxproj
index 0f2bd65b5b8..82381afe47b 100644
--- a/src/mongo/shell/mongo_sm.vcxproj
+++ b/src/mongo/shell/mongo_sm.vcxproj
@@ -876,6 +876,16 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Win2008PlusDebug|x64'">4355;4800;4267;4244;4334</DisableSpecificWarnings>
<DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Win2008PlusRelease|x64'">4355;4800;4267;4244;4334</DisableSpecificWarnings>
</ClCompile>
+ <ClCompile Include="..\..\third_party\murmurhash3\MurmurHash3.cpp">
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4355;4800;4267;4244;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">4355;4800;4267;4244;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Win2008PlusDebug|Win32'">4355;4800;4267;4244;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Win2008PlusRelease|Win32'">4355;4800;4267;4244;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">4355;4800;4267;4244;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Release|x64'">4355;4800;4267;4244;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Win2008PlusDebug|x64'">4355;4800;4267;4244;4141</DisableSpecificWarnings>
+ <DisableSpecificWarnings Condition="'$(Configuration)|$(Platform)'=='Win2008PlusRelease|x64'">4355;4800;4267;4244;4141</DisableSpecificWarnings>
+ </ClCompile>
<ClCompile Include="..\base\configuration_variable_manager.cpp" />
<ClCompile Include="..\base\error_codes.cpp" />
<ClCompile Include="..\base\global_initializer.cpp" />
@@ -897,7 +907,10 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClCompile Include="..\client\connection_factory.cpp" />
<ClCompile Include="..\client\sasl_client_authenticate.cpp" />
<ClCompile Include="..\db\dbmessage.cpp" />
+ <ClCompile Include="..\platform\backtrace.cpp" />
+ <ClCompile Include="..\platform\posix_fadvise.cpp" />
<ClCompile Include="..\platform\random.cpp" />
+ <ClCompile Include="..\platform\strcasestr.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator.cpp" />
<ClCompile Include="..\scripting\bson_template_evaluator_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@@ -1114,6 +1127,7 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ItemGroup>
<None Include="..\..\third_party\js-1.7\jskeyword.tbl" />
<None Include="..\..\third_party\js-1.7\jsopcode.tbl" />
+ <None Include="..\..\third_party\murmurhash3\SConscript" />
<None Include="..\base\error_codes.err" />
<None Include="..\base\generate_error_codes.py" />
<None Include="assert.js" />
@@ -1180,6 +1194,7 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClInclude Include="..\..\third_party\js-1.7\jsxml.h" />
<ClInclude Include="..\..\third_party\js-1.7\prmjtime.h" />
<ClInclude Include="..\..\third_party\js-1.7\resource.h" />
+ <ClInclude Include="..\..\third_party\murmurhash3\MurmurHash3.h" />
<ClInclude Include="..\base\configuration_variable_manager.h" />
<ClInclude Include="..\base\counter.h" />
<ClInclude Include="..\base\disallow_copying.h" />
@@ -1211,13 +1226,16 @@ cscript //Nologo "$(ProjectDir)..\shell\createCPPfromJavaScriptFiles.js" "$(Proj
<ClInclude Include="..\platform\atomic_intrinsics.h" />
<ClInclude Include="..\platform\atomic_intrinsics_win32.h" />
<ClInclude Include="..\platform\atomic_word.h" />
+ <ClInclude Include="..\platform\backtrace.h" />
<ClInclude Include="..\platform\basic.h" />
<ClInclude Include="..\platform\bits.h" />
<ClInclude Include="..\platform\compiler.h" />
<ClInclude Include="..\platform\compiler_msvc.h" />
<ClInclude Include="..\platform\cstdint.h" />
<ClInclude Include="..\platform\float_utils.h" />
+ <ClInclude Include="..\platform\posix_fadvise.h" />
<ClInclude Include="..\platform\random.h" />
+ <ClInclude Include="..\platform\strcasestr.h" />
<ClInclude Include="..\platform\strtoll.h" />
<ClInclude Include="..\platform\unordered_map.h" />
<ClInclude Include="..\platform\unordered_set.h" />
diff --git a/src/mongo/shell/mongo_sm.vcxproj.filters b/src/mongo/shell/mongo_sm.vcxproj.filters
index 1c015105890..33678d8fb74 100644
--- a/src/mongo/shell/mongo_sm.vcxproj.filters
+++ b/src/mongo/shell/mongo_sm.vcxproj.filters
@@ -104,6 +104,9 @@
<Filter Include="JavaScript source files\Included in shell only">
<UniqueIdentifier>{283d932c-5594-47a6-9b1b-8f5af53c0337}</UniqueIdentifier>
</Filter>
+ <Filter Include="third_party\MurmurHash3">
+ <UniqueIdentifier>{a07219b6-a351-468a-a705-2b691500c617}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\scripting\engine.cpp">
@@ -623,6 +626,18 @@
<ClCompile Include="..\client\sasl_client_authenticate.cpp">
<Filter>client</Filter>
</ClCompile>
+ <ClCompile Include="..\platform\strcasestr.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\third_party\murmurhash3\MurmurHash3.cpp">
+ <Filter>third_party\MurmurHash3</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\backtrace.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
+ <ClCompile Include="..\platform\posix_fadvise.cpp">
+ <Filter>platform</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\third_party\js-1.7\jskeyword.tbl">
@@ -679,6 +694,9 @@
<None Include="utils.js">
<Filter>JavaScript source files\Included in all executables</Filter>
</None>
+ <None Include="..\..\third_party\murmurhash3\SConscript">
+ <Filter>third_party\MurmurHash3</Filter>
+ </None>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\pch.h" />
@@ -1454,6 +1472,18 @@
<ClInclude Include="..\client\sasl_client_authenticate.h">
<Filter>client</Filter>
</ClInclude>
+ <ClInclude Include="..\platform\strcasestr.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\third_party\murmurhash3\MurmurHash3.h">
+ <Filter>third_party\MurmurHash3</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\backtrace.h">
+ <Filter>platform</Filter>
+ </ClInclude>
+ <ClInclude Include="..\platform\posix_fadvise.h">
+ <Filter>platform</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\db\db.rc">
diff --git a/src/mongo/tools/tool.cpp b/src/mongo/tools/tool.cpp
index c2728b88af0..2539e5cacb4 100644
--- a/src/mongo/tools/tool.cpp
+++ b/src/mongo/tools/tool.cpp
@@ -18,20 +18,20 @@
#include "mongo/tools/tool.h"
+#include <boost/filesystem/operations.hpp>
#include <fstream>
#include <iostream>
#include "pcrecpp.h"
+#include "mongo/client/dbclient_rs.h"
#include "mongo/client/sasl_client_authenticate.h"
+#include "mongo/db/json.h"
#include "mongo/db/namespace_details.h"
+#include "mongo/platform/posix_fadvise.h"
#include "mongo/util/file_allocator.h"
#include "mongo/util/password.h"
#include "mongo/util/version.h"
-#include "mongo/client/dbclient_rs.h"
-#include "mongo/db/json.h"
-
-#include <boost/filesystem/operations.hpp>
using namespace std;
using namespace mongo;
@@ -480,7 +480,7 @@ namespace mongo {
return 0;
}
-#if !defined(__sunos__) && defined(POSIX_FADV_SEQUENTIAL)
+#ifdef POSIX_FADV_SEQUENTIAL
posix_fadvise(fileno(file), 0, fileLength, POSIX_FADV_SEQUENTIAL);
#endif
diff --git a/src/mongo/util/file_allocator.cpp b/src/mongo/util/file_allocator.cpp
index 07a962b42a2..e59bce6934b 100644
--- a/src/mongo/util/file_allocator.cpp
+++ b/src/mongo/util/file_allocator.cpp
@@ -16,11 +16,13 @@
*/
#include "mongo/pch.h"
+
#include "mongo/util/file_allocator.h"
+
#include <boost/thread.hpp>
#include <boost/filesystem/operations.hpp>
-#include <fcntl.h>
#include <errno.h>
+#include <fcntl.h>
#if defined(__freebsd__) || defined(__openbsd__)
# include <sys/stat.h>
@@ -34,10 +36,11 @@
# include <io.h>
#endif
-#include "mongo/util/time_support.h"
-#include "mongo/util/timer.h"
+#include "mongo/platform/posix_fadvise.h"
#include "mongo/util/mongoutils/str.h"
#include "mongo/util/paths.h"
+#include "mongo/util/time_support.h"
+#include "mongo/util/timer.h"
using namespace mongoutils;
diff --git a/src/mongo/util/log.cpp b/src/mongo/util/log.cpp
index 00845d07da1..9ed7c224f6e 100644
--- a/src/mongo/util/log.cpp
+++ b/src/mongo/util/log.cpp
@@ -18,6 +18,7 @@
#include "mongo/pch.h"
+#include "mongo/platform/posix_fadvise.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/concurrency/threadlocal.h"
#include "mongo/util/stacktrace.h"
diff --git a/src/mongo/util/logfile.cpp b/src/mongo/util/logfile.cpp
index 23b3b597e19..9ab57deac3a 100644
--- a/src/mongo/util/logfile.cpp
+++ b/src/mongo/util/logfile.cpp
@@ -16,12 +16,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "pch.h"
-#include "logfile.h"
-#include "text.h"
-#include "mongoutils/str.h"
-#include "mongo/util/startup_test.h"
+#include "mongo/pch.h"
+
+#include "mongo/util/logfile.h"
+
+#include "mongo/platform/posix_fadvise.h"
#include "mongo/util/mmap.h"
+#include "mongo/util/mongoutils/str.h"
+#include "mongo/util/startup_test.h"
+#include "mongo/util/text.h"
+
using namespace mongoutils;
@@ -64,7 +68,7 @@ namespace mongo {
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
- FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
+ FILE_FLAG_NO_BUFFERING,
NULL);
if( _fd == INVALID_HANDLE_VALUE ) {
DWORD e = GetLastError();
diff --git a/src/mongo/util/mmap_posix.cpp b/src/mongo/util/mmap_posix.cpp
index 7eb5f062045..46f8c481ae3 100644
--- a/src/mongo/util/mmap_posix.cpp
+++ b/src/mongo/util/mmap_posix.cpp
@@ -174,6 +174,11 @@ namespace mongo {
}
void* MemoryMappedFile::remapPrivateView(void *oldPrivateAddr) {
+#if defined(__sunos__) // SERVER-8795
+ verify( Lock::isW() );
+ LockMongoFilesExclusive lockMongoFiles;
+#endif
+
// don't unmap, just mmap over the old region
void * x = mmap( oldPrivateAddr, len , PROT_READ|PROT_WRITE , MAP_PRIVATE|MAP_NORESERVE|MAP_FIXED , fd , 0 );
if( x == MAP_FAILED ) {
diff --git a/src/mongo/util/net/hostandport.h b/src/mongo/util/net/hostandport.h
index 2d8e435293c..ff47d7f9ef4 100644
--- a/src/mongo/util/net/hostandport.h
+++ b/src/mongo/util/net/hostandport.h
@@ -170,7 +170,7 @@ namespace mongo {
const char *colon = strrchr(p, ':');
if( colon ) {
int port = atoi(colon+1);
- uassert(13095, "HostAndPort: bad port #", port > 0);
+ massert(13095, "HostAndPort: bad port #", port > 0);
_host = string(p,colon-p);
_port = port;
}
diff --git a/src/mongo/util/net/sock.cpp b/src/mongo/util/net/sock.cpp
index 2f155c5295c..f8eb34414d6 100644
--- a/src/mongo/util/net/sock.cpp
+++ b/src/mongo/util/net/sock.cpp
@@ -377,7 +377,7 @@ namespace mongo {
string SocketException::toString() const {
stringstream ss;
- ss << _ei.code << " socket exception [" << _type << "] ";
+ ss << _ei.code << " socket exception [" << _getStringType(_type) << "] ";
if ( _server.size() )
ss << "server [" << _server << "] ";
@@ -425,6 +425,12 @@ namespace mongo {
void Socket::close() {
if ( _fd >= 0 ) {
+ // Stop any blocking reads/writes, and prevent new reads/writes
+#if defined(_WIN32)
+ shutdown( _fd, SD_BOTH );
+#else
+ shutdown( _fd, SHUT_RDWR );
+#endif
closesocket( _fd );
_fd = -1;
}
diff --git a/src/mongo/util/net/sock_test.cpp b/src/mongo/util/net/sock_test.cpp
index c1e48c63d43..1bc9df617d6 100644
--- a/src/mongo/util/net/sock_test.cpp
+++ b/src/mongo/util/net/sock_test.cpp
@@ -48,9 +48,9 @@ namespace {
typedef boost::shared_ptr<Socket> SocketPtr;
typedef std::pair<SocketPtr, SocketPtr> SocketPair;
- // On UNIX, make a connected pair of PF_LOCAL sockets via the native 'socketpair' call. The
- // 'type' parameter should be one of SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET, etc. For
- // Win32, we don't have a native socketpair function, so we hack up a connected PF_INET
+ // On UNIX, make a connected pair of PF_LOCAL (aka PF_UNIX) sockets via the native 'socketpair'
+ // call. The 'type' parameter should be one of SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET, etc.
+ // For Win32, we don't have a native socketpair function, so we hack up a connected PF_INET
// pair on a random port.
SocketPair socketPair(const int type, const int protocol = 0);
@@ -184,7 +184,10 @@ namespace {
#else
// We can just use ::socketpair and wrap up the result in a Socket.
SocketPair socketPair(const int type, const int protocol) {
- const int domain = PF_LOCAL;
+ // PF_LOCAL is the POSIX name for Unix domain sockets, while PF_UNIX
+ // is the name that BSD used. We use the BSD name because it is more
+ // widely supported (e.g. Solaris 10).
+ const int domain = PF_UNIX;
int socks[2];
const int result = ::socketpair(domain, type, protocol, socks);
diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp
index dadc6b66f1b..83ecd5923da 100644
--- a/src/mongo/util/net/ssl_manager.cpp
+++ b/src/mongo/util/net/ssl_manager.cpp
@@ -298,17 +298,21 @@ namespace mongo {
}
SSL* SSLManager::connect(int fd) {
SSL* ssl = _secure(fd);
+ ScopeGuard guard = MakeGuard(::SSL_free, ssl);
int ret = _ssl_connect(ssl);
if (ret != 1)
_handleSSLError(SSL_get_error(ssl, ret));
+ guard.Dismiss();
return ssl;
}
SSL* SSLManager::accept(int fd) {
SSL* ssl = _secure(fd);
+ ScopeGuard guard = MakeGuard(::SSL_free, ssl);
int ret = SSL_accept(ssl);
if (ret != 1)
_handleSSLError(SSL_get_error(ssl, ret));
+ guard.Dismiss();
return ssl;
}
@@ -362,35 +366,32 @@ namespace mongo {
// accepts the socket connection but fails to do the SSL handshake in a timely
// manner.
error() << "SSL error: " << code << ", possibly timed out during connect" << endl;
- throw SocketException(SocketException::CONNECT_ERROR, "");
break;
case SSL_ERROR_SYSCALL:
if (code < 0) {
error() << "socket error: " << errnoWithDescription() << endl;
- throw SocketException(SocketException::CONNECT_ERROR, "");
}
- error() << "could not negotiate SSL connection: EOF detected" << endl;
- throw SocketException(SocketException::CONNECT_ERROR, "");
+ else {
+ error() << "could not negotiate SSL connection: EOF detected" << endl;
+ }
break;
case SSL_ERROR_SSL:
{
int ret = ERR_get_error();
error() << _getSSLErrorMessage(ret) << endl;
- throw SocketException(SocketException::CONNECT_ERROR, "");
break;
}
case SSL_ERROR_ZERO_RETURN:
error() << "could not negotiate SSL connection: EOF detected" << endl;
- throw SocketException(SocketException::CONNECT_ERROR, "");
break;
default:
error() << "unrecognized SSL error" << endl;
- throw SocketException(SocketException::CONNECT_ERROR, "");
break;
}
+ throw SocketException(SocketException::CONNECT_ERROR, "");
}
}
diff --git a/src/mongo/util/processinfo_sunos5.cpp b/src/mongo/util/processinfo_sunos5.cpp
index 089edc24eed..22a0b5e6d7d 100644
--- a/src/mongo/util/processinfo_sunos5.cpp
+++ b/src/mongo/util/processinfo_sunos5.cpp
@@ -1,6 +1,4 @@
-// processinfo_none.cpp
-
-/* Copyright 2009 10gen Inc.
+/* Copyright 2013 10gen Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,54 +13,162 @@
* limitations under the License.
*/
-#include "pch.h"
-#include "processinfo.h"
-
+#include <boost/filesystem.hpp>
+#include <fstream>
#include <iostream>
-using namespace std;
+#include <malloc.h>
+#include <procfs.h>
+#include <stdio.h>
+#include <string>
+#include <sys/mman.h>
+#include <sys/systeminfo.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+#include <vector>
+
+#include "mongo/util/file.h"
+#include "mongo/util/mongoutils/str.h"
+#include "mongo/util/processinfo.h"
namespace mongo {
- ProcessInfo::ProcessInfo( pid_t pid ) {
+ /**
+ * Read the first line from a file; return empty string on failure
+ */
+ static string readLineFromFile(const char* fname) {
+ std::string fstr;
+ std::ifstream f(fname);
+ if (f.is_open()) {
+ std::getline(f, fstr);
+ }
+ return fstr;
}
- ProcessInfo::~ProcessInfo() {
- }
+ struct ProcPsinfo {
+ ProcPsinfo() {
+ FILE* f = fopen("/proc/self/psinfo", "r");
+ massert(16846,
+ mongoutils::str::stream() << "couldn't open \"/proc/self/psinfo\": "
+ << errnoWithDescription(),
+ f);
+ size_t num = fread(&psinfo, sizeof(psinfo), 1, f);
+ int err = errno;
+ fclose(f);
+ massert(16847,
+ mongoutils::str::stream() << "couldn't read from \"/proc/self/psinfo\": "
+ << errnoWithDescription(err),
+ num == 1);
+ }
+ psinfo_t psinfo;
+ };
+
+ struct ProcUsage {
+ ProcUsage() {
+ FILE* f = fopen("/proc/self/usage", "r");
+ massert(16848,
+ mongoutils::str::stream() << "couldn't open \"/proc/self/usage\": "
+ << errnoWithDescription(),
+ f);
+ size_t num = fread(&prusage, sizeof(prusage), 1, f);
+ int err = errno;
+ fclose(f);
+ massert(16849,
+ mongoutils::str::stream() << "couldn't read from \"/proc/self/usage\": "
+ << errnoWithDescription(err),
+ num == 1);
+ }
+ prusage_t prusage;
+ };
+
+ ProcessInfo::ProcessInfo(pid_t pid) : _pid(pid) { }
+ ProcessInfo::~ProcessInfo() { }
bool ProcessInfo::supported() {
- return false;
+ return true;
}
int ProcessInfo::getVirtualMemorySize() {
- return -1;
+ ProcPsinfo p;
+ return static_cast<int>(p.psinfo.pr_size / 1024);
}
int ProcessInfo::getResidentSize() {
- return -1;
- }
-
- bool ProcessInfo::checkNumaEnabled() {
- return false;
+ ProcPsinfo p;
+ return static_cast<int>(p.psinfo.pr_rssize / 1024);
}
- bool ProcessInfo::blockCheckSupported() {
- return false;
+ void ProcessInfo::getExtraInfo(BSONObjBuilder& info) {
+ ProcUsage p;
+ info.appendNumber("page_faults", static_cast<long long>(p.prusage.pr_majf));
}
+ /**
+ * Save a BSON obj representing the host system's details
+ */
void ProcessInfo::SystemInfo::collectSystemInfo() {
+ struct utsname unameData;
+ if (uname(&unameData) == -1) {
+ log() << "Unable to collect detailed system information: " << strerror(errno) << endl;
+ }
+
+ char buf_64[32];
+ char buf_native[32];
+ if (sysinfo(SI_ARCHITECTURE_64, buf_64, sizeof(buf_64)) != -1 &&
+ sysinfo(SI_ARCHITECTURE_NATIVE, buf_native, sizeof(buf_native)) != -1) {
+ addrSize = mongoutils::str::equals(buf_64, buf_native) ? 64 : 32;
+ }
+ else {
+ log() << "Unable to determine system architecture: " << strerror(errno) << endl;
+ }
+
+ osType = unameData.sysname;
+ osName = mongoutils::str::ltrim(readLineFromFile("/etc/release"));
+ osVersion = unameData.version;
+ pageSize = static_cast<unsigned long long>(sysconf(_SC_PAGESIZE));
+ memSize = pageSize * static_cast<unsigned long long>(sysconf(_SC_PHYS_PAGES));
+ numCores = static_cast<unsigned>(sysconf(_SC_NPROCESSORS_CONF));
+ cpuArch = unameData.machine;
+ hasNuma = checkNumaEnabled();
+
+ BSONObjBuilder bExtra;
+ bExtra.append("kernelVersion", unameData.release);
+ bExtra.append("pageSize", static_cast<long long>(pageSize));
+ bExtra.append("numPages", static_cast<int>(sysconf(_SC_PHYS_PAGES)));
+ bExtra.append("maxOpenFiles", static_cast<int>(sysconf(_SC_OPEN_MAX)));
+ _extraStats = bExtra.obj();
+ }
+ bool ProcessInfo::checkNumaEnabled() {
+ return false;
}
- void ProcessInfo::getExtraInfo( BSONObjBuilder& info ) {
-
+ bool ProcessInfo::blockCheckSupported() {
+ return true;
}
bool ProcessInfo::blockInMemory(const void* start) {
- verify(0);
+ char x = 0;
+ if (mincore(static_cast<char*>(const_cast<void*>(alignToStartOfPage(start))),
+ getPageSize(),
+ &x)) {
+ log() << "mincore failed: " << errnoWithDescription() << endl;
+ return 1;
+ }
+ return x & 0x1;
}
- bool ProcessInfo::pagesInMemory(const void* start, size_t numPages, vector<char>* out) {
- verify(0);
+ bool ProcessInfo::pagesInMemory(const void* start, size_t numPages, std::vector<char>* out) {
+ out->resize(numPages);
+ if (mincore(static_cast<char*>(const_cast<void*>(alignToStartOfPage(start))),
+ numPages * getPageSize(),
+ &out->front())) {
+ log() << "mincore failed: " << errnoWithDescription() << endl;
+ return false;
+ }
+ for (size_t i = 0; i < numPages; ++i) {
+ (*out)[i] &= 0x1;
+ }
+ return true;
}
}
diff --git a/src/mongo/util/signal_handlers.cpp b/src/mongo/util/signal_handlers.cpp
index 52694900448..241d824b1a0 100644
--- a/src/mongo/util/signal_handlers.cpp
+++ b/src/mongo/util/signal_handlers.cpp
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "pch.h"
+#include "mongo/pch.h"
#include <cstdarg>
#include <cstdio>
@@ -26,20 +26,17 @@
#include <unistd.h>
#endif
-#ifdef MONGO_HAVE_EXECINFO_BACKTRACE
-#include <execinfo.h>
-#endif
-
-#include "log.h"
-#include "signal_handlers.h"
+#include "mongo/platform/backtrace.h"
+#include "mongo/util/log.h"
+#include "mongo/util/signal_handlers.h"
namespace mongo {
/*
* WARNING: PLEASE READ BEFORE CHANGING THIS MODULE
*
- * All code in this module should be singal-friendly. Before adding any system
- * call or other dependency, please make sure the latter still holds.
+ * All code in this module must be signal-friendly. Before adding any system
+ * call or other dependency, please make sure that this still holds.
*
*/
@@ -84,7 +81,7 @@ namespace mongo {
static void formattedBacktrace( int fd ) {
-#ifdef MONGO_HAVE_EXECINFO_BACKTRACE
+#if !defined(_WIN32)
int numFrames;
const int MAX_DEPTH = 20;
diff --git a/src/mongo/util/stack_introspect.cpp b/src/mongo/util/stack_introspect.cpp
index 27ebb0267cf..ce69b988bb7 100644
--- a/src/mongo/util/stack_introspect.cpp
+++ b/src/mongo/util/stack_introspect.cpp
@@ -18,22 +18,21 @@
#include "mongo/util/stack_introspect.h"
+#if !defined(_WIN32)
+
#include <cstdlib>
+#include <cxxabi.h>
#include <iostream>
-#include <string>
#include <map>
+#include <string>
#include <vector>
+#include "mongo/platform/backtrace.h"
#include "mongo/util/concurrency/mutex.h"
#include "mongo/util/text.h"
using namespace std;
-#ifdef MONGO_HAVE_EXECINFO_BACKTRACE
-
-#include <execinfo.h>
-#include <cxxabi.h>
-
namespace mongo {
namespace {
@@ -106,7 +105,7 @@ namespace mongo {
bool inConstructorChain( bool printOffending ){
void* b[maxBackTraceFrames];
- int size = ::backtrace( b, maxBackTraceFrames );
+ int size = backtrace( b, maxBackTraceFrames );
char** strings = 0;
@@ -122,7 +121,7 @@ namespace mongo {
}
if ( ! strings )
- strings = ::backtrace_symbols( b, size );
+ strings = backtrace_symbols( b, size );
string symbol = strings[i];
@@ -176,5 +175,4 @@ namespace mongo {
bool inConstructorChainSupported() { return false; }
}
-#endif // defined(MONGO_HAVE_EXECINFO_BACKTRACE)
-
+#endif // #if !defined(_WIN32)
diff --git a/src/mongo/util/stacktrace.cpp b/src/mongo/util/stacktrace.cpp
index ab405c9a717..c1348a00240 100644
--- a/src/mongo/util/stacktrace.cpp
+++ b/src/mongo/util/stacktrace.cpp
@@ -1,4 +1,17 @@
-// Copyright 2009. 10gen, Inc.
+/* Copyright 2009 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#include "mongo/util/stacktrace.h"
@@ -11,53 +24,18 @@
#include "mongo/util/log.h"
#ifdef _WIN32
-#include <sstream>
-#include <stdio.h>
#include <boost/filesystem/operations.hpp>
#include <boost/smart_ptr/scoped_array.hpp>
+#include <sstream>
+#include <stdio.h>
#include "mongo/platform/windows_basic.h"
#include <DbgHelp.h>
#include "mongo/util/assert_util.h"
+#else
+#include "mongo/platform/backtrace.h"
#endif
-#ifdef MONGO_HAVE_EXECINFO_BACKTRACE
-
-#include <execinfo.h>
-
-namespace mongo {
- static const int maxBackTraceFrames = 20;
-
- /**
- * Print a stack backtrace for the current thread to the specified ostream.
- *
- * @param os ostream& to receive printed stack backtrace
- */
- void printStackTrace( std::ostream& os ) {
-
- void *b[maxBackTraceFrames];
-
- int size = ::backtrace( b, maxBackTraceFrames );
- for ( int i = 0; i < size; i++ )
- os << std::hex << b[i] << std::dec << ' ';
- os << std::endl;
-
- char **strings;
-
- strings = ::backtrace_symbols( b, size );
- if (strings == NULL) {
- const int err = errno;
- os << "Unable to collect backtrace symbols (" << errnoWithDescription(err) << ")"
- << std::endl;
- return;
- }
- for ( int i = 0; i < size; i++ )
- os << ' ' << strings[i] << '\n';
- os.flush();
- ::free( strings );
- }
-}
-
-#elif defined(_WIN32)
+#if defined(_WIN32)
namespace mongo {
@@ -306,12 +284,43 @@ namespace mongo {
}
}
-
#else
namespace mongo {
- void printStackTrace( std::ostream &os ) {}
+ static const int maxBackTraceFrames = 20;
+
+ /**
+ * Print a stack backtrace for the current thread to the specified ostream.
+ *
+ * @param os ostream& to receive printed stack backtrace
+ */
+ void printStackTrace( std::ostream& os ) {
+
+ void* addresses[maxBackTraceFrames];
+
+ int addressCount = backtrace(addresses, maxBackTraceFrames);
+ if (addressCount == 0) {
+ const int err = errno;
+ os << "Unable to collect backtrace addresses (" << errnoWithDescription(err) << ")"
+ << std::endl;
+ return;
+ }
+ for (int i = 0; i < addressCount; i++)
+ os << std::hex << addresses[i] << std::dec << ' ';
+ os << std::endl;
+
+ char** backtraceStrings = backtrace_symbols(addresses, addressCount);
+ if (backtraceStrings == NULL) {
+ const int err = errno;
+ os << "Unable to collect backtrace symbols (" << errnoWithDescription(err) << ")"
+ << std::endl;
+ return;
+ }
+ for (int i = 0; i < addressCount; i++)
+ os << ' ' << backtraceStrings[i] << '\n';
+ os.flush();
+ free(backtraceStrings);
+ }
}
#endif
-
diff --git a/src/mongo/util/stacktrace.h b/src/mongo/util/stacktrace.h
index 1a5d62dcdf1..f1cd6279107 100644
--- a/src/mongo/util/stacktrace.h
+++ b/src/mongo/util/stacktrace.h
@@ -1,4 +1,17 @@
-// Copyright 2009. 10gen, Inc.
+/* Copyright 2009 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
/**
* Tools for working with in-process stack traces.
diff --git a/src/mongo/util/version.cpp b/src/mongo/util/version.cpp
index 0756bca0901..25fe64b5811 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.5";
+ const char versionString[] = "2.4.6";
// See unit test for example outputs
BSONArray toVersionArray(const char* version){
diff --git a/src/third_party/s2/util/math/SConscript b/src/third_party/s2/util/math/SConscript
index 8ad3ee125f1..af51445de1d 100755
--- a/src/third_party/s2/util/math/SConscript
+++ b/src/third_party/s2/util/math/SConscript
@@ -7,6 +7,10 @@ env = env.Clone()
env.Append(CCFLAGS=['-Isrc/third_party/s2'])
env.Append(CCFLAGS=['-Isrc/third_party/gflags-2.0/src'])
+if solaris:
+ # Enables declaration of isinf() on Solaris
+ env.Append(CPPDEFINES=['__C99FEATURES__'])
+
env.StaticLibrary("math",
[ "mathutil.cc",
# "mathlimits.cc",