summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonin Kral <a.kral@bobek.cz>2013-04-17 21:51:49 +0200
committerAntonin Kral <a.kral@bobek.cz>2013-04-17 21:51:49 +0200
commit3c0811b838ca6b5e26855e6850b2f1d7fd8ea20a (patch)
treeb0c6fec4fa8578d9215c7fdcadd89b705aad2c64
parentf0db7048a1748ec5ee8a55eaf964b2b1ca886cef (diff)
Imported Upstream version 2.4.2upstream/2.4.2
-rw-r--r--buildscripts/packager.py6
-rw-r--r--doxygenConfig2
-rw-r--r--jstests/fts_partition1.js3
-rwxr-xr-xjstests/geo_s2edgecases.js8
-rw-r--r--jstests/geo_s2nearComplex.js18
-rw-r--r--jstests/nestedobj1.js2
-rw-r--r--jstests/sharding/cursor_cleanup.js62
-rw-r--r--jstests/sharding/gle_with_conf_servers.js8
-rw-r--r--jstests/sharding/migrateBig.js2
-rw-r--r--jstests/sharding/read_pref_rs_client.js220
-rw-r--r--jstests/slowNightly/sharding_migrateBigObject.js2
-rw-r--r--jstests/slowNightly/ttl_repl_secondary_disabled.js52
-rwxr-xr-xrpm/mongo.spec2
-rw-r--r--src/mongo/client/dbclient.cpp18
-rw-r--r--src/mongo/client/dbclient_rs.cpp30
-rw-r--r--src/mongo/client/dbclient_rs.h42
-rw-r--r--src/mongo/client/dbclient_rs_test.cpp405
-rw-r--r--src/mongo/client/distlock.cpp50
-rw-r--r--src/mongo/client/distlock.h37
-rw-r--r--src/mongo/client/syncclusterconnection.cpp28
-rw-r--r--src/mongo/db/auth/auth_external_state.cpp7
-rw-r--r--src/mongo/db/auth/auth_index_d.cpp20
-rw-r--r--src/mongo/db/commands/authentication_commands.cpp25
-rw-r--r--src/mongo/db/dbcommands.cpp4
-rw-r--r--src/mongo/db/fts/fts_command_mongod.cpp12
-rw-r--r--src/mongo/db/geo/geoparser.cpp5
-rw-r--r--src/mongo/db/geo/geoparser_test.cpp15
-rw-r--r--src/mongo/db/geo/s2cursor.cpp6
-rw-r--r--src/mongo/db/geo/s2cursor.h3
-rw-r--r--src/mongo/db/json.cpp69
-rw-r--r--src/mongo/db/repl/health.cpp5
-rw-r--r--src/mongo/db/repl/heartbeat.cpp9
-rw-r--r--src/mongo/db/repl/rs_member.h1
-rw-r--r--src/mongo/db/ttl.cpp5
-rw-r--r--src/mongo/dbtests/gle_test.cpp85
-rw-r--r--src/mongo/dbtests/jsontests.cpp45
-rw-r--r--src/mongo/dbtests/jstests.cpp309
-rw-r--r--src/mongo/dbtests/mock/mock_remote_db_server.cpp2
-rw-r--r--src/mongo/dbtests/mock/mock_remote_db_server.h10
-rw-r--r--src/mongo/dbtests/replica_set_monitor_test.cpp27
-rw-r--r--src/mongo/s/config_upgrade_helpers.cpp55
-rw-r--r--src/mongo/s/cursors.cpp7
-rw-r--r--src/mongo/s/cursors.h1
-rw-r--r--src/mongo/s/d_migrate.cpp50
-rw-r--r--src/mongo/s/server.cpp6
-rw-r--r--src/mongo/s/shard.h8
-rw-r--r--src/mongo/s/shardconnection.cpp196
-rw-r--r--src/mongo/s/shardkey.cpp27
-rw-r--r--src/mongo/s/strategy_shard.cpp8
-rw-r--r--src/mongo/scripting/engine_spidermonkey.cpp32
-rw-r--r--src/mongo/scripting/engine_spidermonkey_internal.h8
-rw-r--r--src/mongo/scripting/engine_v8.cpp326
-rw-r--r--src/mongo/scripting/engine_v8.h20
-rw-r--r--src/mongo/shell/db.js4
-rw-r--r--src/mongo/shell/types.js6
-rw-r--r--src/mongo/tools/restore.cpp1
-rw-r--r--src/mongo/tools/stat.cpp2
-rw-r--r--src/mongo/tools/tool.cpp26
-rw-r--r--src/mongo/tools/tool.h2
-rw-r--r--src/mongo/util/assert_util.h8
-rw-r--r--src/mongo/util/version.cpp21
-rwxr-xr-xsrc/third_party/pcre-8.30/config.status2365
62 files changed, 4047 insertions, 793 deletions
diff --git a/buildscripts/packager.py b/buildscripts/packager.py
index 3fc17954d96..dcddf0ab91b 100644
--- a/buildscripts/packager.py
+++ b/buildscripts/packager.py
@@ -924,9 +924,9 @@ fi
%{_mandir}/man1/mongostat.1*
# FIXME: uncomment when mongosniff is back in the package
#%{_mandir}/man1/mongosniff.1*
-#@@VERSION>2.4.0@@%{_mandir}/man1/mongotop.1*
-#@@VERSION>2.4.0@@%{_mandir}/man1/mongoperf.1*
-#@@VERSION>2.4.0@@%{_mandir}/man1/mongooplog.1*
+#@@VERSION>=2.4.0@@%{_mandir}/man1/mongotop.1*
+#@@VERSION>=2.4.0@@%{_mandir}/man1/mongoperf.1*
+#@@VERSION>=2.4.0@@%{_mandir}/man1/mongooplog.1*
%files server
%defattr(-,root,root,-)
diff --git a/doxygenConfig b/doxygenConfig
index 555ca59a38f..06f0529edba 100644
--- a/doxygenConfig
+++ b/doxygenConfig
@@ -3,7 +3,7 @@
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = MongoDB
-PROJECT_NUMBER = 2.4.1
+PROJECT_NUMBER = 2.4.2
OUTPUT_DIRECTORY = docs/doxygen
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
diff --git a/jstests/fts_partition1.js b/jstests/fts_partition1.js
index 7fa4aa40335..f1b4c437c3c 100644
--- a/jstests/fts_partition1.js
+++ b/jstests/fts_partition1.js
@@ -18,3 +18,6 @@ assert.eq( [ 1 ], queryIDS( t, "foo" , { x : 1 } ) );
res = t.runCommand( "text", { search : "foo" , filter : { x : 1 } } );
assert( res.results[0].score > 0, tojson( res ) )
+// repeat search with "language" specified, SERVER-8999
+res = t.runCommand( "text", { search : "foo" , filter : { x : 1 } , language : "english" } );
+assert( res.results[0].score > 0, tojson( res ) )
diff --git a/jstests/geo_s2edgecases.js b/jstests/geo_s2edgecases.js
index 02bd17d8b9f..bf46baba744 100755
--- a/jstests/geo_s2edgecases.js
+++ b/jstests/geo_s2edgecases.js
@@ -5,20 +5,20 @@ roundworldpoint = { "type" : "Point", "coordinates": [ 180, 0 ] }
// Opposite the equator
roundworld = { "type" : "Polygon",
- "coordinates" : [ [ [179,1], [181,1], [181,-1], [179,-1], [179,1]]]}
+ "coordinates" : [ [ [179,1], [-179,1], [-179,-1], [179,-1], [179,1]]]}
t.insert({geo : roundworld})
roundworld2 = { "type" : "Polygon",
- "coordinates" : [ [ [179,1], [179,-1], [181,-1], [181,1], [179,1]]]}
+ "coordinates" : [ [ [179,1], [179,-1], [-179,-1], [-179,1], [179,1]]]}
t.insert({geo : roundworld2})
// North pole
santapoint = { "type" : "Point", "coordinates": [ 180, 90 ] }
santa = { "type" : "Polygon",
- "coordinates" : [ [ [179,89], [179,90], [181,90], [181,89], [179,89]]]}
+ "coordinates" : [ [ [179,89], [179,90], [-179,90], [-179,89], [179,89]]]}
t.insert({geo : santa})
santa2 = { "type" : "Polygon",
- "coordinates" : [ [ [179,89], [181,89], [181,90], [179,90], [179,89]]]}
+ "coordinates" : [ [ [179,89], [-179,89], [-179,90], [179,90], [179,89]]]}
t.insert({geo : santa2})
// South pole
diff --git a/jstests/geo_s2nearComplex.js b/jstests/geo_s2nearComplex.js
index 78a055d719b..87dd034ca24 100644
--- a/jstests/geo_s2nearComplex.js
+++ b/jstests/geo_s2nearComplex.js
@@ -59,15 +59,25 @@ function uniformPoints(origin, count, minDist, maxDist){
var pointLat = asin((sin(lat) * cos(distance)) + (cos(lat) * sin(distance) * cos(angle)));
var pointDLng = atan2(sin(angle) * sin(distance) * cos(lat), cos(distance) - sin(lat) * sin(pointLat));
var pointLng = ((lng - pointDLng + PI) % 2*PI) - PI;
+
+ // Latitude must be [-90, 90]
+ var newLat = lat + pointLat;
+ if (newLat > 90) newLat -= 180;
+ if (newLat < -90) newLat += 180;
+
+ // Longitude must be [-180, 180]
+ var newLng = lng + pointLng;
+ if (newLng > 180) newLng -= 360;
+ if (newLng < -180) newLng += 360;
+
var newPoint = {
geo: {
type: "Point",
- coordinates: [lng + pointLng, lat + pointLat]
+ //coordinates: [lng + pointLng, lat + pointLat]
+ coordinates: [newLng, newLat]
}
};
- if(lat + pointLat > 90.0){
- continue;
- }
+
points.push(newPoint);
}
for(i=0; i < points.length; i++){
diff --git a/jstests/nestedobj1.js b/jstests/nestedobj1.js
index f1e733e8401..02dc5f085c4 100644
--- a/jstests/nestedobj1.js
+++ b/jstests/nestedobj1.js
@@ -14,7 +14,7 @@ t = db.objNestTest;
t.drop();
t.ensureIndex({a:1});
-nestedObj = makeNestObj(500);
+nestedObj = makeNestObj(300);
t.insert( { tst : "test1", a : nestedObj }, true );
t.insert( { tst : "test2", a : nestedObj }, true );
diff --git a/jstests/sharding/cursor_cleanup.js b/jstests/sharding/cursor_cleanup.js
new file mode 100644
index 00000000000..a28b5416e38
--- /dev/null
+++ b/jstests/sharding/cursor_cleanup.js
@@ -0,0 +1,62 @@
+//
+// Tests cleanup of sharded and unsharded cursors
+//
+
+var st = new ShardingTest({ shards : 2, mongos : 1, other : { separateConfig : true } });
+st.stopBalancer();
+
+var mongos = st.s0;
+var admin = mongos.getDB( "admin" );
+var config = mongos.getDB( "config" );
+var shards = config.shards.find().toArray();
+var coll = mongos.getCollection( "foo.bar" );
+var collUnsharded = mongos.getCollection( "foo.baz" );
+
+// Shard collection
+printjson(admin.runCommand({ enableSharding : coll.getDB() + "" }));
+printjson(admin.runCommand({ movePrimary : coll.getDB() + "", to : shards[0]._id }));
+printjson(admin.runCommand({ shardCollection : coll + "", key : { _id : 1 } }));
+printjson(admin.runCommand({ split : coll + "", middle : { _id : 0 } }));
+printjson(admin.runCommand({ moveChunk : coll + "", find : { _id : 0 }, to : shards[1]._id }));
+
+jsTest.log("Collection set up...");
+st.printShardingStatus(true);
+
+jsTest.log("Insert enough data to overwhelm a query batch.");
+
+for (var i = -150; i < 150; i++) {
+ coll.insert({ _id : i });
+ collUnsharded.insert({ _id : i });
+}
+assert.eq(null, coll.getDB().getLastError());
+
+jsTest.log("Open a cursor to a sharded and unsharded collection.");
+
+var shardedCursor = coll.find();
+assert.neq(null, shardedCursor.next());
+
+var unshardedCursor = collUnsharded.find();
+assert.neq(null, unshardedCursor.next());
+
+jsTest.log("Check whether the cursor is registered in the cursor info.");
+
+var cursorInfo = admin.runCommand({ cursorInfo : true });
+printjson(cursorInfo);
+
+assert.eq(cursorInfo.sharded, 1);
+assert.eq(cursorInfo.refs, 1);
+
+jsTest.log("End the cursors.");
+
+shardedCursor.itcount();
+unshardedCursor.itcount();
+
+var cursorInfo = admin.runCommand({ cursorInfo : true });
+printjson(cursorInfo);
+
+assert.eq(cursorInfo.sharded, 0);
+assert.eq(cursorInfo.refs, 0);
+
+jsTest.log("DONE!");
+
+st.stop();
diff --git a/jstests/sharding/gle_with_conf_servers.js b/jstests/sharding/gle_with_conf_servers.js
index 1fa7bde17bc..f4335a05d73 100644
--- a/jstests/sharding/gle_with_conf_servers.js
+++ b/jstests/sharding/gle_with_conf_servers.js
@@ -10,6 +10,14 @@ function writeToConfigTest(){
var gleObj = confDB.runCommand({ getLastError: 1, w: 'majority' });
assert( gleObj.ok );
+ assert.eq("norepl", gleObj.err);
+
+ // w:1 should still work
+ confDB.settings.update({ _id: 'balancer' }, { $set: { stopped: true }});
+ var gleObj = confDB.runCommand({ getLastError: 1, w: 1 });
+
+ assert(gleObj.ok);
+ assert.eq(null, gleObj.err);
st.stop();
}
diff --git a/jstests/sharding/migrateBig.js b/jstests/sharding/migrateBig.js
index d98459edd24..853a671915a 100644
--- a/jstests/sharding/migrateBig.js
+++ b/jstests/sharding/migrateBig.js
@@ -1,6 +1,6 @@
s = new ShardingTest( "migrateBig" , 2 , 0 , 1 , { chunksize : 1 } );
-s.config.settings.update( { _id: "balancer" }, { $set : { stopped: true } } , true );
+s.config.settings.update( { _id: "balancer" }, { $set : { stopped : true, _waitForDelete : true } } , true );
s.adminCommand( { enablesharding : "test" } );
s.adminCommand( { shardcollection : "test.foo" , key : { x : 1 } } );
diff --git a/jstests/sharding/read_pref_rs_client.js b/jstests/sharding/read_pref_rs_client.js
deleted file mode 100644
index 8a458101aa2..00000000000
--- a/jstests/sharding/read_pref_rs_client.js
+++ /dev/null
@@ -1,220 +0,0 @@
-/**
- * Testing read preference on DBClientReplicaSets, specifically on the auto-retry
- * and automatic failover selection
- */
-// NOTE: this test is skipped when running smoke.py with --auth because of SERVER-6972
-
-function basicTest() {
- var replTest = new ReplSetTest({ name: 'basic', nodes: 2, useHostName: true });
- replTest.startSet({ oplogSize: 1 });
- replTest.initiate();
- replTest.awaitSecondaryNodes();
-
- var PRI_HOST = replTest.getPrimary().host;
- var SEC_HOST = replTest.getSecondary().host;
-
- var replConn = new Mongo(replTest.getURL());
- var coll = replConn.getDB('test').user;
- var dest = coll.find().readPref('primary').explain().server;
- assert.eq(PRI_HOST, dest);
-
- // Create brand new connection to make sure that the last cached is not used
- replConn = new Mongo(replTest.getURL());
- coll = replConn.getDB('test').user;
- dest = coll.find().readPref('secondary').explain().server;
- assert.eq(SEC_HOST, dest);
-
- replConn = new Mongo(replTest.getURL());
- coll = replConn.getDB('test').user;
- dest = coll.find().readPref('primaryPreferred').explain().server;
- assert.eq(PRI_HOST, dest);
-
- replConn = new Mongo(replTest.getURL());
- coll = replConn.getDB('test').user;
- dest = coll.find().readPref('secondaryPreferred').explain().server;
- assert.eq(SEC_HOST, dest);
-
- replConn = new Mongo(replTest.getURL());
- coll = replConn.getDB('test').user;
- // just make sure that it doesn't throw
- coll.find().readPref('nearest').explain();
-
- replTest.stopSet();
-}
-
-function noPriNoSecTest() {
- var replTest = new ReplSetTest({ name: 'noPriNoSec', useHostName: true,
- nodes: [{}, { arbiter: true }, { arbiter: true }]});
- replTest.startSet({ oplogSize: 1 });
- replTest.initiate();
- replTest.awaitSecondaryNodes();
-
- var replConn = new Mongo(replTest.getURL());
- var coll = replConn.getDB('test').user;
-
- replTest.stop(0);
-
- assert.throws(function() {
- coll.find().readPref('primary').explain();
- });
-
- // Make sure that it still fails even when trying to refresh
- assert.throws(function() {
- coll.find().readPref('primary').explain();
- });
-
- // Don't need to create new connection because failed connections
- // would never be reused, and also becasue the js Mongo contructor
- // will throw when it can't connect to a primary
- assert.throws(function() {
- coll.find().readPref('secondary').explain();
- });
-
- assert.throws(function() {
- coll.find().readPref('secondary').explain();
- });
-
- assert.throws(function() {
- coll.find().readPref('primaryPreferred').explain();
- });
-
- assert.throws(function() {
- coll.find().readPref('primaryPreferred').explain();
- });
-
- assert.throws(function() {
- coll.find().readPref('secondaryPreferred').explain();
- });
-
- assert.throws(function() {
- coll.find().readPref('secondaryPreferred').explain();
- });
-
- assert.throws(function() {
- coll.find().readPref('neareset').explain();
- });
-
- assert.throws(function() {
- coll.find().readPref('nearest').explain();
- });
-
- replTest.stopSet();
-}
-
-function priOkNoSecTest() {
- var replTest = new ReplSetTest({ name: 'priOkNoSec', useHostName: true,
- nodes: [{}, { arbiter: true }, {}]});
- replTest.startSet({ oplogSize: 1 });
- replTest.initiate();
- replTest.awaitSecondaryNodes();
-
- var replConn = new Mongo(replTest.getURL());
- var coll = replConn.getDB('test').user;
-
- replTest.stop(2);
-
- var PRI_HOST = replTest.getPrimary().host;
-
- var dest = coll.find().readPref('primary').explain().server;
- assert.eq(PRI_HOST, dest);
-
- replConn = new Mongo(replTest.getURL());
- coll = replConn.getDB('test').user;
- dest = coll.find().readPref('primaryPreferred').explain().server;
- assert.eq(PRI_HOST, dest);
-
- replConn = new Mongo(replTest.getURL());
- coll = replConn.getDB('test').user;
- assert.throws(function() {
- coll.find().readPref('secondary').explain();
- });
-
- assert.throws(function() {
- coll.find().readPref('secondary').explain();
- });
-
- replConn = new Mongo(replTest.getURL());
- coll = replConn.getDB('test').user;
- dest = coll.find().readPref('secondaryPreferred').explain().server;
- assert.eq(PRI_HOST, dest);
-
- replConn = new Mongo(replTest.getURL());
- coll = replConn.getDB('test').user;
- dest = coll.find().readPref('nearest').explain().server;
- assert.eq(PRI_HOST, dest);
-
- replTest.stopSet();
-}
-
-function noPriSecOkTest() {
- var replTest = new ReplSetTest({ name: 'noPriSecOk', useHostName: true,
- nodes: [{ }, { arbiter: true }, { }]});
- replTest.startSet({ oplogSize: 1 });
- replTest.initiate();
- replTest.awaitSecondaryNodes();
-
- var priConn = replTest.getPrimary();
- var conf = priConn.getDB('local').system.replset.findOne();
- conf.version++;
- conf.members[0].priority = 99;
- conf.members[2].priority = 0;
-
- var SEC_HOST = replTest.nodes[2].host;
-
- try {
- priConn.getDB('admin').runCommand({ replSetReconfig: conf });
- } catch (x) {
- print('Exception from reconfig: ' + x);
- }
-
- var replConn = new Mongo(replTest.getURL());
- var coll = replConn.getDB('test').user;
-
- replTest.stop(0);
-
- assert.throws(function() {
- coll.find().readPref('primary').explain();
- });
-
- // Make sure that it still fails even when trying to refresh
- assert.throws(function() {
- coll.find().readPref('primary').explain();
- });
-
- replConn = new Mongo(replTest.getURL());
- coll = replConn.getDB('test').user;
- var dest = coll.find().readPref('primaryPreferred').explain().server;
- assert.eq(SEC_HOST, dest);
-
- replTest.start(0, {}, true);
- replTest.awaitSecondaryNodes();
- replConn = new Mongo(replTest.getURL());
- replTest.stop(0);
- coll = replConn.getDB('test').user;
- dest = coll.find().readPref('secondary').explain().server;
- assert.eq(SEC_HOST, dest);
-
- replTest.start(0, {}, true);
- replTest.awaitSecondaryNodes();
- replConn = new Mongo(replTest.getURL());
- replTest.stop(0);
- coll = replConn.getDB('test').user;
- dest = coll.find().readPref('secondaryPreferred').explain().server;
- assert.eq(SEC_HOST, dest);
-
- replTest.start(0, {}, true);
- replTest.awaitSecondaryNodes();
- replConn = new Mongo(replTest.getURL());
- replTest.stop(0);
- coll = replConn.getDB('test').user;
- dest = coll.find().readPref('nearest').explain().server;
- assert.eq(SEC_HOST, dest);
-
- replTest.stopSet();
-}
-
-basicTest();
-noPriNoSecTest();
-priOkNoSecTest();
-noPriSecOkTest();
-
diff --git a/jstests/slowNightly/sharding_migrateBigObject.js b/jstests/slowNightly/sharding_migrateBigObject.js
index 4e4f7dd9a04..9d45e35c253 100644
--- a/jstests/slowNightly/sharding_migrateBigObject.js
+++ b/jstests/slowNightly/sharding_migrateBigObject.js
@@ -65,7 +65,7 @@ assert.soon(
return res.length > 1 && Math.abs( res[0].nChunks - res[1].nChunks ) <= 3;
} ,
- "never migrated" , 180000 , 1000 );
+ "never migrated" , 10 * 60 * 1000 , 1000 );
stopMongod( 30000 );
stopMongod( 29999 );
diff --git a/jstests/slowNightly/ttl_repl_secondary_disabled.js b/jstests/slowNightly/ttl_repl_secondary_disabled.js
new file mode 100644
index 00000000000..47a447e048d
--- /dev/null
+++ b/jstests/slowNightly/ttl_repl_secondary_disabled.js
@@ -0,0 +1,52 @@
+/** Test TTL docs are not deleted from secondaries directly
+ */
+
+var rt = new ReplSetTest( { name : "ttl_repl" , nodes: 2 } );
+
+// setup set
+var nodes = rt.startSet();
+rt.initiate();
+var master = rt.getMaster();
+rt.awaitSecondaryNodes();
+var slave1 = rt.getSecondary();
+
+// shortcuts
+var masterdb = master.getDB( 'd' );
+var slave1db = slave1.getDB( 'd' );
+var mastercol = masterdb[ 'c' ];
+var slave1col = slave1db[ 'c' ];
+
+// create TTL index, wait for TTL monitor to kick in, then check things
+mastercol.ensureIndex( { x : 1 } , { expireAfterSeconds : 10 } );
+
+rt.awaitReplication();
+
+//increase logging
+slave1col.getDB().adminCommand({setParameter:1, logLevel:1});
+
+//insert old doc (10 minutes old) directly on secondary using godinsert
+slave1col.runCommand("godinsert",
+ {obj: {_id: new Date(), x: new Date( (new Date()).getTime() - 600000 ) } })
+assert.eq(1, slave1col.count(), "missing inserted doc" );
+
+sleep(70*1000) //wait for 70seconds
+assert.eq(1, slave1col.count(), "ttl deleted my doc!" );
+
+// looking for this error : "Assertion: 13312:replSet error : logOp() but not primary"
+// indicating that the secondary tried to delete the doc, but shouldn't be writing
+var errorString = "13312";
+var foundError = false;
+var globalLogLines = slave1col.getDB().adminCommand({getLog:"global"}).log
+for (i in globalLogLines) {
+ var line = globalLogLines[i];
+ if (line.match( errorString )) {
+ foundError = true;
+ errorString = line; // replace error string with what we found.
+ break;
+ }
+}
+
+assert.eq(false, foundError, "found error in this line: " + errorString);
+
+// finish up
+rt.stopSet(); \ No newline at end of file
diff --git a/rpm/mongo.spec b/rpm/mongo.spec
index 2946228d6d6..7610f421e96 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.1
+Version: 2.4.0
Release: mongodb_1%{?dist}
Summary: mongo client shell and tools
License: AGPL 3.0
diff --git a/src/mongo/client/dbclient.cpp b/src/mongo/client/dbclient.cpp
index 64161cb0708..88abdb77a83 100644
--- a/src/mongo/client/dbclient.cpp
+++ b/src/mongo/client/dbclient.cpp
@@ -500,11 +500,19 @@ namespace mongo {
return getLastErrorString( info );
}
- string DBClientWithCommands::getLastErrorString( const BSONObj& info ) {
- BSONElement e = info["err"];
- if( e.eoo() ) return "";
- if( e.type() == Object ) return e.toString();
- return e.str();
+ string DBClientWithCommands::getLastErrorString(const BSONObj& info) {
+ if (info["ok"].trueValue()) {
+ BSONElement e = info["err"];
+ if (e.eoo()) return "";
+ if (e.type() == Object) return e.toString();
+ return e.str();
+ } else {
+ // command failure
+ BSONElement e = info["errmsg"];
+ if (e.eoo()) return "";
+ if (e.type() == Object) return "getLastError command failed: " + e.toString();
+ return "getLastError command failed: " + e.str();
+ }
}
const BSONObj getpreverrorcmdobj = fromjson("{getpreverror:1}");
diff --git a/src/mongo/client/dbclient_rs.cpp b/src/mongo/client/dbclient_rs.cpp
index 90cbd5fcd58..2bd395d0232 100644
--- a/src/mongo/client/dbclient_rs.cpp
+++ b/src/mongo/client/dbclient_rs.cpp
@@ -244,19 +244,18 @@ namespace mongo {
uassert(16385, "tags for read preference should be an array",
tagsElem.type() == mongo::Array);
- std::auto_ptr<TagSet> tags(new TagSet(BSONArray(tagsElem.Obj())));
- if (pref == mongo::ReadPreference_PrimaryOnly && !tags->isExhausted()) {
+ TagSet tags(BSONArray(tagsElem.Obj().getOwned()));
+ if (pref == mongo::ReadPreference_PrimaryOnly && !tags.isExhausted()) {
uassert(16384, "Only empty tags are allowed with primary read preference",
- tags->getCurrentTag().isEmpty());
+ tags.getCurrentTag().isEmpty());
}
- return new ReadPreferenceSetting(pref, tags.release());
+ return new ReadPreferenceSetting(pref, tags);
}
}
- BSONArrayBuilder arrayBuilder;
- arrayBuilder.append(BSONObj());
- return new ReadPreferenceSetting(pref, new TagSet(arrayBuilder.arr()));
+ TagSet tags(BSON_ARRAY(BSONObj()));
+ return new ReadPreferenceSetting(pref, tags);
}
/**
@@ -1538,8 +1537,8 @@ namespace mongo {
DBClientConnection& DBClientReplicaSet::slaveConn() {
BSONArray emptyArray(BSON_ARRAY(BSONObj()));
TagSet tags(emptyArray);
- shared_ptr<ReadPreferenceSetting> readPref(new ReadPreferenceSetting(
- ReadPreference_SecondaryPreferred, new TagSet(emptyArray)));
+ shared_ptr<ReadPreferenceSetting> readPref(
+ new ReadPreferenceSetting(ReadPreference_SecondaryPreferred, tags));
DBClientConnection* conn = selectNodeUsingTags(readPref);
uassert( 16369, str::stream() << "No good nodes available for set: "
@@ -1743,7 +1742,7 @@ namespace mongo {
ReplicaSetMonitorPtr monitor = _getMonitor();
bool isPrimarySelected = false;
- _lastSlaveOkHost = monitor->selectAndCheckNode(readPref->pref, readPref->tags,
+ _lastSlaveOkHost = monitor->selectAndCheckNode(readPref->pref, &readPref->tags,
&isPrimarySelected);
if ( _lastSlaveOkHost.empty() ){
@@ -2011,6 +2010,13 @@ namespace mongo {
TagSet::TagSet() : _isExhausted(true), _tagIterator(_tags) {
}
+ TagSet::TagSet(const TagSet& other) :
+ _isExhausted(false),
+ _tags(other._tags.getOwned()),
+ _tagIterator(_tags) {
+ next();
+ }
+
TagSet::TagSet(const BSONArray& tags) :
_isExhausted(false),
_tags(tags.getOwned()),
@@ -2042,10 +2048,6 @@ namespace mongo {
return new BSONObjIterator(_tags);
}
- TagSet* TagSet::clone() const {
- return new TagSet(BSONArray(_tags.copy()));
- }
-
bool TagSet::equals(const TagSet& other) const {
return _tags.equal(other._tags);
}
diff --git a/src/mongo/client/dbclient_rs.h b/src/mongo/client/dbclient_rs.h
index 45eabead460..ffdf0e0ecee 100644
--- a/src/mongo/client/dbclient_rs.h
+++ b/src/mongo/client/dbclient_rs.h
@@ -617,7 +617,7 @@ namespace mongo {
* A simple object for representing the list of tags. The initial state will
* have a valid current tag as long as the list is not empty.
*/
- class TagSet : public boost::noncopyable { // because of BSONArrayIteratorSorted
+ class TagSet {
public:
/**
* Creates an empty tag list that is initially exhausted.
@@ -625,6 +625,12 @@ namespace mongo {
TagSet();
/**
+ * Creates a copy of the given TagSet. The new copy will have the
+ * iterator pointing at the initial position.
+ */
+ explicit TagSet(const TagSet& other);
+
+ /**
* Creates a tag set object that lazily iterates over the tag list.
*
* @param tags the list of tags associated with this option. This object
@@ -661,18 +667,18 @@ namespace mongo {
BSONObjIterator* getIterator() const;
/**
- * Create a new copy of this tag set and wuth the iterator pointing at the
- * head.
- */
- TagSet* clone() const;
-
- /**
* @returns true if the other TagSet has the same tag set specification with
* this tag set, disregarding where the current iterator is pointing to.
*/
bool equals(const TagSet& other) const;
private:
+ /**
+ * This is purposely undefined as the semantics for assignment can be
+ * confusing. This is because BSONArrayIteratorSorted shouldn't be
+ * copied (because of how it manages internal buffer).
+ */
+ TagSet& operator=(const TagSet& other);
BSONObj _currentTag;
bool _isExhausted;
@@ -683,25 +689,21 @@ namespace mongo {
struct ReadPreferenceSetting {
/**
- * @param tag cannot be NULL.
+ * @parm pref the read preference mode.
+ * @param tag the tag set. Note that this object will have the
+ * tag set will have this in a reset state (meaning, this
+ * object's copy of tag will have the iterator in the initial
+ * position).
*/
- ReadPreferenceSetting(ReadPreference pref, TagSet* tag):
- pref(pref), tags(tag->clone()) {
- }
-
- ~ReadPreferenceSetting() {
- delete tags;
+ ReadPreferenceSetting(ReadPreference pref, const TagSet& tag):
+ pref(pref), tags(tag) {
}
inline bool equals(const ReadPreferenceSetting& other) const {
- return pref == other.pref && tags->equals(*other.tags);
+ return pref == other.pref && tags.equals(other.tags);
}
const ReadPreference pref;
-
- /**
- * Note: This object owns this memory.
- */
- TagSet* tags;
+ TagSet tags;
};
}
diff --git a/src/mongo/client/dbclient_rs_test.cpp b/src/mongo/client/dbclient_rs_test.cpp
index 19e94a0fc9f..ccb7b71063e 100644
--- a/src/mongo/client/dbclient_rs_test.cpp
+++ b/src/mongo/client/dbclient_rs_test.cpp
@@ -15,7 +15,8 @@
*/
/**
- * This file contains tests for DBClientReplicaSet.
+ * This file contains tests for DBClientReplicaSet. The tests mocks the servers
+ * the DBClientReplicaSet talks to, so the tests only covers the client side logic.
*/
#include "mongo/bson/bson_field.h"
@@ -25,35 +26,13 @@
#include "mongo/dbtests/mock/mock_conn_registry.h"
#include "mongo/dbtests/mock/mock_replica_set.h"
#include "mongo/unittest/unittest.h"
+#include "mongo/util/assert_util.h"
#include <map>
#include <memory>
#include <string>
#include <vector>
-using std::auto_ptr;
-using std::map;
-using std::make_pair;
-using std::pair;
-using std::string;
-using std::vector;
-using boost::scoped_ptr;
-
-using mongo::BSONField;
-using mongo::BSONObj;
-using mongo::BSONArray;
-using mongo::BSONElement;
-using mongo::ConnectionString;
-using mongo::DBClientCursor;
-using mongo::DBClientReplicaSet;
-using mongo::HostAndPort;
-using mongo::MockReplicaSet;
-using mongo::Query;
-using mongo::ReadPreference;
-using mongo::ReplicaSetMonitor;
-using mongo::ScopedDbConnection;
-using mongo::TagSet;
-
namespace mongo {
// Symbols defined to build the binary correctly.
CmdLine cmdLine;
@@ -73,16 +52,373 @@ namespace mongo {
}
}
-namespace mongo_test {
+namespace {
+ using boost::scoped_ptr;
+ using std::auto_ptr;
+ using std::map;
+ using std::make_pair;
+ using std::pair;
+ using std::string;
+ using std::vector;
+
+ using mongo::AssertionException;
+ using mongo::BSONArray;
+ using mongo::BSONElement;
+ using mongo::BSONField;
+ using mongo::BSONObj;
+ using mongo::ConnectionString;
+ using mongo::DBClientCursor;
+ using mongo::DBClientReplicaSet;
+ using mongo::HostAndPort;
+ using mongo::HostField;
+ using mongo::IdentityNS;
+ using mongo::MockReplicaSet;
+ using mongo::Query;
+ using mongo::ReadPreference;
+ using mongo::ReplicaSetMonitor;
+ using mongo::ScopedDbConnection;
+ using mongo::TagSet;
+
+ /**
+ * Basic fixture with one primary and one secondary.
+ */
+ class BasicRS: public mongo::unittest::Test {
+ protected:
+ void setUp() {
+ _replSet.reset(new MockReplicaSet("test", 2));
+ ConnectionString::setConnectionHook(
+ mongo::MockConnRegistry::get()->getConnStrHook());
+ }
+
+ void tearDown() {
+ ReplicaSetMonitor::remove(_replSet->getSetName(), true);
+ _replSet.reset();
+
+ // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor.
+ mongo::ScopedDbConnection::clearPool();
+ }
+
+ MockReplicaSet* getReplSet() {
+ return _replSet.get();
+ }
+
+ private:
+ boost::scoped_ptr<MockReplicaSet> _replSet;
+ };
+
+ TEST_F(BasicRS, ReadFromPrimary) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryOnly, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str());
+ }
+
+ TEST_F(BasicRS, SecondaryOnly) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryOnly, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str());
+ }
+
+ TEST_F(BasicRS, PrimaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str());
+ }
+
+ TEST_F(BasicRS, SecondaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str());
+ }
+
+ /**
+ * Setup for 2 member replica set will all of the nodes down.
+ */
+ class AllNodesDown: public mongo::unittest::Test {
+ protected:
+ void setUp() {
+ _replSet.reset(new MockReplicaSet("test", 2));
+ ConnectionString::setConnectionHook(
+ mongo::MockConnRegistry::get()->getConnStrHook());
+
+ vector<HostAndPort> hostList(_replSet->getHosts());
+ for (vector<HostAndPort>::const_iterator iter = hostList.begin();
+ iter != hostList.end(); ++iter) {
+ _replSet->kill(iter->toString(true));
+ }
+ }
+
+ void tearDown() {
+ ReplicaSetMonitor::remove(_replSet->getSetName(), true);
+ _replSet.reset();
+
+ // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor.
+ mongo::ScopedDbConnection::clearPool();
+ }
+
+ MockReplicaSet* getReplSet() {
+ return _replSet.get();
+ }
+
+ private:
+ boost::scoped_ptr<MockReplicaSet> _replSet;
+ };
+
+ TEST_F(AllNodesDown, ReadFromPrimary) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryOnly, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ TEST_F(AllNodesDown, SecondaryOnly) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryOnly, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ TEST_F(AllNodesDown, PrimaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ TEST_F(AllNodesDown, SecondaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ TEST_F(AllNodesDown, Nearest) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_Nearest, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ /**
+ * Setup for 2 member replica set with the primary down.
+ */
+ class PrimaryDown: public mongo::unittest::Test {
+ protected:
+ void setUp() {
+ _replSet.reset(new MockReplicaSet("test", 2));
+ ConnectionString::setConnectionHook(
+ mongo::MockConnRegistry::get()->getConnStrHook());
+ _replSet->kill(_replSet->getPrimary());
+ }
+
+ void tearDown() {
+ ReplicaSetMonitor::remove(_replSet->getSetName(), true);
+ _replSet.reset();
+
+ // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor.
+ mongo::ScopedDbConnection::clearPool();
+ }
+
+ MockReplicaSet* getReplSet() {
+ return _replSet.get();
+ }
+
+ private:
+ boost::scoped_ptr<MockReplicaSet> _replSet;
+ };
+
+ TEST_F(PrimaryDown, ReadFromPrimary) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryOnly, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ TEST_F(PrimaryDown, SecondaryOnly) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryOnly, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str());
+ }
+
+ TEST_F(PrimaryDown, PrimaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str());
+ }
+
+ TEST_F(PrimaryDown, SecondaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str());
+ }
+
+ TEST_F(PrimaryDown, Nearest) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_Nearest, BSONArray());
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str());
+ }
+
+ /**
+ * Setup for 2 member replica set with the secondary down.
+ */
+ class SecondaryDown: public mongo::unittest::Test {
+ protected:
+ void setUp() {
+ _replSet.reset(new MockReplicaSet("test", 2));
+ ConnectionString::setConnectionHook(
+ mongo::MockConnRegistry::get()->getConnStrHook());
+
+ _replSet->kill(_replSet->getSecondaries().front());
+ }
+
+ void tearDown() {
+ ReplicaSetMonitor::remove(_replSet->getSetName(), true);
+ _replSet.reset();
+
+ // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor.
+ mongo::ScopedDbConnection::clearPool();
+ }
+
+ MockReplicaSet* getReplSet() {
+ return _replSet.get();
+ }
+
+ private:
+ boost::scoped_ptr<MockReplicaSet> _replSet;
+ };
+
+ TEST_F(SecondaryDown, ReadFromPrimary) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryOnly, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str());
+ }
+
+ TEST_F(SecondaryDown, SecondaryOnly) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryOnly, BSONArray());
+ ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException);
+ }
+
+ TEST_F(SecondaryDown, PrimaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str());
+ }
+
+ TEST_F(SecondaryDown, SecondaryPreferred) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str());
+ }
+
+ TEST_F(SecondaryDown, Nearest) {
+ MockReplicaSet* replSet = getReplSet();
+ DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts());
+
+ Query query;
+ query.readPref(mongo::ReadPreference_Nearest, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
+ auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
+ BSONObj doc = cursor->next();
+ ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str());
+ }
+
/**
* Warning: Tests running this fixture cannot be run in parallel with other tests
* that uses ConnectionString::setConnectionHook
*/
class TaggedFiveMemberRS: public mongo::unittest::Test {
protected:
- static const string IdentityNS;
- static const BSONField<string> HostField;
-
void setUp() {
_replSet.reset(new MockReplicaSet("test", 5));
_originalConnectionHook = ConnectionString::getConnectionHook();
@@ -153,6 +489,8 @@ namespace mongo_test {
ConnectionString::setConnectionHook(_originalConnectionHook);
ReplicaSetMonitor::remove(_replSet->getSetName(), true);
_replSet.reset();
+
+ // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor.
mongo::ScopedDbConnection::clearPool();
}
@@ -165,9 +503,6 @@ namespace mongo_test {
boost::scoped_ptr<MockReplicaSet> _replSet;
};
- const string TaggedFiveMemberRS::IdentityNS("local.me");
- const BSONField<string> TaggedFiveMemberRS::HostField("host", "bad");
-
TEST_F(TaggedFiveMemberRS, ConnShouldPinIfSameSettings) {
MockReplicaSet* replSet = getReplSet();
vector<HostAndPort> seedList;
@@ -179,6 +514,8 @@ namespace mongo_test {
{
Query query;
query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
BSONObj doc = cursor->next();
dest = doc[HostField.name()].str();
@@ -205,6 +542,8 @@ namespace mongo_test {
{
Query query;
query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray());
+
+ // Note: IdentityNS contains the name of the server.
auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
BSONObj doc = cursor->next();
dest = doc[HostField.name()].str();
@@ -233,6 +572,8 @@ namespace mongo_test {
Query query;
query.readPref(mongo::ReadPreference_SecondaryPreferred,
BSON_ARRAY(BSON("dc" << "sf")));
+
+ // Note: IdentityNS contains the name of the server.
auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query);
BSONObj doc = cursor->next();
dest = doc[HostField.name()].str();
@@ -261,6 +602,8 @@ namespace mongo_test {
string dest;
mongo::DBClientConnection& secConn = replConn.slaveConn();
+
+ // Note: IdentityNS contains the name of the server.
auto_ptr<DBClientCursor> cursor = secConn.query(IdentityNS, Query());
BSONObj doc = cursor->next();
dest = doc[HostField.name()].str();
diff --git a/src/mongo/client/distlock.cpp b/src/mongo/client/distlock.cpp
index d1fff0c1124..8b932e73b3a 100644
--- a/src/mongo/client/distlock.cpp
+++ b/src/mongo/client/distlock.cpp
@@ -492,12 +492,58 @@ namespace mongo {
return true;
}
+
+ bool DistributedLock::isLockHeld( double timeout, string* errMsg ) {
+ scoped_ptr<ScopedDbConnection> connPtr(
+ ScopedDbConnection::getInternalScopedDbConnection( _conn.toString(), timeout ) );
+ ScopedDbConnection& conn = *connPtr;
+
+ BSONObj lockObj;
+ try {
+ lockObj = conn->findOne( LocksType::ConfigNS,
+ BSON( LocksType::name(_name) ) ).getOwned();
+ }
+ catch ( DBException& e ) {
+ *errMsg = str::stream() << "error checking whether lock " << _name << " is held "
+ << causedBy( e );
+ return false;
+ }
+ conn.done();
+
+ if ( lockObj.isEmpty() ) {
+ *errMsg = str::stream() << "no lock for " << _name << " exists in the locks collection";
+ return false;
+ }
+
+ if ( lockObj[LocksType::state()].numberInt() < 2 ) {
+ *errMsg = str::stream() << "lock " << _name << " current state is not held ("
+ << lockObj[LocksType::state()].numberInt() << ")";
+ return false;
+ }
+
+ if ( lockObj[LocksType::process()].String() != _processId ) {
+ *errMsg = str::stream() << "lock " << _name << " is currently being held by "
+ << "another process ("
+ << lockObj[LocksType::process()].String() << ")";
+ return false;
+ }
+
+ if ( distLockPinger.willUnlockOID( lockObj[LocksType::lockID()].OID() ) ) {
+ *errMsg = str::stream() << "lock " << _name << " is not held and is currently being "
+ << "scheduled for lazy unlock by "
+ << lockObj[LocksType::lockID()].OID();
+ return false;
+ }
+
+ return true;
+ }
+
// Semantics of this method are basically that if the lock cannot be acquired, returns false, can be retried.
// If the lock should not be tried again (some unexpected error) a LockException is thrown.
// If we are only trying to re-enter a currently held lock, reenter should be true.
// Note: reenter doesn't actually make this lock re-entrant in the normal sense, since it can still only
// be unlocked once, instead it is used to verify that the lock is already held.
- bool DistributedLock::lock_try( const string& why , bool reenter, BSONObj * other ) {
+ bool DistributedLock::lock_try( const string& why , bool reenter, BSONObj * other, double timeout ) {
// TODO: Start pinging only when we actually get the lock?
// If we don't have a thread pinger, make sure we shouldn't have one
@@ -520,7 +566,7 @@ namespace mongo {
other = &dummyOther;
scoped_ptr<ScopedDbConnection> connPtr(
- ScopedDbConnection::getInternalScopedDbConnection( _conn.toString() ) );
+ ScopedDbConnection::getInternalScopedDbConnection( _conn.toString(), timeout ) );
ScopedDbConnection& conn = *connPtr;
BSONObjBuilder queryBuilder;
diff --git a/src/mongo/client/distlock.h b/src/mongo/client/distlock.h
index c51f766f1ba..183826afcce 100644
--- a/src/mongo/client/distlock.h
+++ b/src/mongo/client/distlock.h
@@ -123,7 +123,15 @@ namespace mongo {
* details if not
* @return true if it managed to grab the lock
*/
- bool lock_try( const string& why , bool reenter = false, BSONObj * other = 0 );
+ bool lock_try( const string& why , bool reenter = false, BSONObj * other = 0, double timeout = 0.0 );
+
+ /**
+ * Returns true if we currently believe we hold this lock and it was possible to
+ * confirm that, within 'timeout' seconds, if provided, with the config servers. If the
+ * lock is not held or if we failed to contact the config servers within the timeout,
+ * returns false.
+ */
+ bool isLockHeld( double timeout, string* errMsg );
/**
* Releases a previously taken lock.
@@ -223,9 +231,9 @@ namespace mongo {
return *this;
}
- dist_lock_try( DistributedLock * lock , const std::string& why )
+ dist_lock_try( DistributedLock * lock , const std::string& why, double timeout = 0.0 )
: _lock(lock), _why(why) {
- _got = _lock->lock_try( why , false , &_other );
+ _got = _lock->lock_try( why , false , &_other, timeout );
}
~dist_lock_try() {
@@ -235,16 +243,23 @@ namespace mongo {
}
}
- bool reestablish(){
- return retry();
- }
+ /**
+ * Returns false if the lock is known _not_ to be held, otherwise asks the underlying
+ * lock to issue a 'isLockHeld' call and returns whatever that calls does.
+ */
+ bool isLockHeld( double timeout, string* errMsg) {
+ if ( !_lock ) {
+ *errMsg = "Lock is not currently set up";
+ return false;
+ }
- bool retry() {
- verify( _lock );
- verify( _got );
- verify( ! _other.isEmpty() );
+ if ( !_got ) {
+ *errMsg = str::stream() << "Lock " << _lock->_name << " is currently held by "
+ << _other;
+ return false;
+ }
- return _got = _lock->lock_try( _why , true, &_other );
+ return _lock->isLockHeld( timeout, errMsg );
}
bool got() const { return _got; }
diff --git a/src/mongo/client/syncclusterconnection.cpp b/src/mongo/client/syncclusterconnection.cpp
index 3183f337203..7bb538079eb 100644
--- a/src/mongo/client/syncclusterconnection.cpp
+++ b/src/mongo/client/syncclusterconnection.cpp
@@ -181,7 +181,7 @@ namespace mongo {
if ( lockType > 0 ) { // write $cmd
string errmsg;
if ( ! prepare( errmsg ) )
- throw UserException( 13104 , (string)"SyncClusterConnection::findOne prepare failed: " + errmsg );
+ throw UserException( PrepareConfigsFailedCode , (string)"SyncClusterConnection::findOne prepare failed: " + errmsg );
vector<BSONObj> all;
for ( size_t i=0; i<_conns.size(); i++ ) {
@@ -336,7 +336,31 @@ namespace mongo {
return;
}
- uassert( 10023 , "SyncClusterConnection bulk insert not implemented" , 0);
+ for (vector<BSONObj>::const_iterator it = v.begin(); it != v.end(); ++it ) {
+ BSONObj obj = *it;
+ if ( obj["_id"].type() == EOO ) {
+ string assertMsg = "SyncClusterConnection::insert (batched) obj misses an _id: ";
+ uasserted( 16743, assertMsg + obj.jsonString() );
+ }
+ }
+
+ // fsync all connections before starting the batch.
+ string errmsg;
+ if ( ! prepare( errmsg ) ) {
+ string assertMsg = "SyncClusterConnection::insert (batched) prepare failed: ";
+ throw UserException( 16744, assertMsg + errmsg );
+ }
+
+ // We still want one getlasterror per document, even if they're batched.
+ for ( size_t i=0; i<_conns.size(); i++ ) {
+ for ( vector<BSONObj>::const_iterator it = v.begin(); it != v.end(); ++it ) {
+ _conns[i]->insert( ns, *it, flags );
+ _conns[i]->getLastErrorDetailed();
+ }
+ }
+
+ // We issue a final getlasterror, but this time with an fsync.
+ _checkLast();
}
void SyncClusterConnection::remove( const string &ns , Query query, int flags ) {
diff --git a/src/mongo/db/auth/auth_external_state.cpp b/src/mongo/db/auth/auth_external_state.cpp
index f6e3eb9e387..946b75b322a 100644
--- a/src/mongo/db/auth/auth_external_state.cpp
+++ b/src/mongo/db/auth/auth_external_state.cpp
@@ -30,9 +30,12 @@ namespace mongo {
const PrincipalName& principalName,
BSONObj* result) {
- if (dbname == StringData("$external", StringData::LiteralTag())) {
+ if (dbname == StringData("$external", StringData::LiteralTag()) ||
+ dbname == AuthorizationManager::SERVER_RESOURCE_NAME ||
+ dbname == AuthorizationManager::CLUSTER_RESOURCE_NAME) {
return Status(ErrorCodes::UserNotFound,
- "No privilege documents stored in the $external user source.");
+ mongoutils::str::stream() << "No privilege documents stored in the " <<
+ dbname << " user source.");
}
if (!NamespaceString::validDBName(dbname)) {
diff --git a/src/mongo/db/auth/auth_index_d.cpp b/src/mongo/db/auth/auth_index_d.cpp
index 2f809219341..3ce6c0de43f 100644
--- a/src/mongo/db/auth/auth_index_d.cpp
+++ b/src/mongo/db/auth/auth_index_d.cpp
@@ -23,6 +23,7 @@
#include "mongo/db/index_update.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/namespace_details.h"
+#include "mongo/util/assert_util.h"
#include "mongo/util/log.h"
namespace mongo {
@@ -90,10 +91,21 @@ namespace {
void createSystemIndexes(const NamespaceString& ns) {
if (ns.coll == "system.users") {
- Helpers::ensureIndex(ns.ns().c_str(),
- extendedSystemUsersKeyPattern,
- true, // unique
- extendedSystemUsersIndexName.c_str());
+ try {
+ Helpers::ensureIndex(ns.ns().c_str(),
+ extendedSystemUsersKeyPattern,
+ true, // unique
+ extendedSystemUsersIndexName.c_str());
+ } catch (const DBException& e) {
+ if (e.getCode() == ASSERT_ID_DUPKEY) {
+ log() << "Duplicate key exception while trying to build unique index on " <<
+ ns << ". You most likely have user documents with duplicate \"user\" "
+ "fields. To resolve this, start up with a version of MongoDB prior to "
+ "2.4, drop the duplicate user documents, then start up again with the "
+ "current version." << endl;
+ }
+ throw;
+ }
}
}
diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp
index da97299d719..bcc5a2f16a0 100644
--- a/src/mongo/db/commands/authentication_commands.cpp
+++ b/src/mongo/db/commands/authentication_commands.cpp
@@ -16,10 +16,12 @@
#include "mongo/db/commands/authentication_commands.h"
+#include <boost/scoped_ptr.hpp>
#include <string>
#include <vector>
#include "mongo/base/status.h"
+#include "mongo/client/sasl_client_authenticate.h"
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/authorization_manager.h"
@@ -29,6 +31,7 @@
#include "mongo/db/commands.h"
#include "mongo/db/jsobj.h"
#include "mongo/platform/random.h"
+#include "mongo/util/concurrency/mutex.h"
#include "mongo/util/md5.hpp"
namespace mongo {
@@ -53,8 +56,10 @@ namespace mongo {
class CmdGetNonce : public Command {
public:
- CmdGetNonce() : Command("getnonce") {
- _random = SecureRandom::create();
+ CmdGetNonce() :
+ Command("getnonce"),
+ _randMutex("getnonce"),
+ _random(SecureRandom::create()) {
}
virtual bool requiresAuth() { return false; }
@@ -68,7 +73,7 @@ namespace mongo {
const BSONObj& cmdObj,
std::vector<Privilege>* out) {} // No auth required
bool run(const string&, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
- nonce64 n = _random->nextInt64();
+ nonce64 n = getNextNonce();
stringstream ss;
ss << hex << n;
result.append("nonce", ss.str() );
@@ -77,7 +82,14 @@ namespace mongo {
return true;
}
- SecureRandom* _random;
+ private:
+ nonce64 getNextNonce() {
+ SimpleMutex::scoped_lock lk(_randMutex);
+ return _random->nextInt64();
+ }
+
+ SimpleMutex _randMutex; // Synchronizes accesses to _random.
+ boost::scoped_ptr<SecureRandom> _random;
} cmdGetNonce;
bool CmdAuthenticate::run(const string& dbname , BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
@@ -92,6 +104,7 @@ namespace mongo {
if (dbname != StringData("local", StringData::LiteralTag()) ||
user != internalSecurity.user) {
errmsg = _nonceAuthenticateCommandsDisabledMessage;
+ result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
return false;
}
}
@@ -105,6 +118,7 @@ namespace mongo {
<< endl;
errmsg = "auth fails";
sleepmillis(10);
+ result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
return false;
}
@@ -132,6 +146,7 @@ namespace mongo {
log() << "auth: bad nonce received or getnonce not called. could be a driver bug or a security attack. db:" << dbname << endl;
errmsg = "auth fails";
sleepmillis(30);
+ result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
return false;
}
}
@@ -143,6 +158,7 @@ namespace mongo {
if (!status.isOK()) {
log() << status.reason() << std::endl;
errmsg = "auth fails";
+ result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
return false;
}
pwd = userObj["pwd"].String();
@@ -163,6 +179,7 @@ namespace mongo {
if ( key != computed ) {
log() << "auth: key mismatch " << user << ", ns:" << dbname << endl;
errmsg = "auth fails";
+ result.append(saslCommandCodeFieldName, ErrorCodes::AuthenticationFailed);
return false;
}
diff --git a/src/mongo/db/dbcommands.cpp b/src/mongo/db/dbcommands.cpp
index b06ff459847..2b345c70200 100644
--- a/src/mongo/db/dbcommands.cpp
+++ b/src/mongo/db/dbcommands.cpp
@@ -187,7 +187,9 @@ namespace mongo {
BSONElement e = cmdObj["w"];
if ( e.ok() ) {
- if ( cmdLine.configsvr ) {
+ if ( cmdLine.configsvr && (!e.isNumber() || e.numberInt() > 1) ) {
+ // w:1 on config servers should still work, but anything greater than that
+ // should not.
result.append( "wnote", "can't use w on config servers" );
result.append( "err", "norepl" );
return true;
diff --git a/src/mongo/db/fts/fts_command_mongod.cpp b/src/mongo/db/fts/fts_command_mongod.cpp
index 979222cc72b..6fe534ad681 100644
--- a/src/mongo/db/fts/fts_command_mongod.cpp
+++ b/src/mongo/db/fts/fts_command_mongod.cpp
@@ -89,14 +89,14 @@ namespace mongo {
const IndexDetails& id = d->idx( idxMatches[0] );
BSONObj indexPrefix;
+ FTSIndex* ftsIndex = static_cast<FTSIndex*>(id.getSpec().getType());
if ( language == "" ) {
- FTSIndex* ftsIndex = static_cast<FTSIndex*>(id.getSpec().getType());
language = ftsIndex->getFtsSpec().defaultLanguage();
- Status s = ftsIndex->getFtsSpec().getIndexPrefix( filter, &indexPrefix );
- if ( !s.isOK() ) {
- errmsg = s.toString();
- return false;
- }
+ }
+ Status s = ftsIndex->getFtsSpec().getIndexPrefix( filter, &indexPrefix );
+ if ( !s.isOK() ) {
+ errmsg = s.toString();
+ return false;
}
diff --git a/src/mongo/db/geo/geoparser.cpp b/src/mongo/db/geo/geoparser.cpp
index 3b53b30cdd2..f74022dde76 100644
--- a/src/mongo/db/geo/geoparser.cpp
+++ b/src/mongo/db/geo/geoparser.cpp
@@ -68,7 +68,9 @@ namespace mongo {
}
// ...where the latitude is valid
double lat = thisCoord[1].Number();
+ double lng = thisCoord[0].Number();
if (lat < -90 || lat > 90) { return false; }
+ if (lng < -180 || lng > 180) { return false; }
}
return true;
}
@@ -101,7 +103,8 @@ namespace mongo {
if (coordinates.size() != 2) { return false; }
if (!coordinates[0].isNumber() || !coordinates[1].isNumber()) { return false; }
double lat = coordinates[1].Number();
- return lat >= -90 && lat <= 90;
+ double lng = coordinates[0].Number();
+ return lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180;
}
void GeoParser::parseGeoJSONPoint(const BSONObj& obj, S2Cell* out) {
diff --git a/src/mongo/db/geo/geoparser_test.cpp b/src/mongo/db/geo/geoparser_test.cpp
index 2e7fffb515f..cb3af1a119e 100644
--- a/src/mongo/db/geo/geoparser_test.cpp
+++ b/src/mongo/db/geo/geoparser_test.cpp
@@ -54,6 +54,10 @@ namespace {
// Make sure lat is in range
ASSERT_TRUE(GeoParser::isPoint(fromjson("{'type':'Point', 'coordinates': [0, 90.0]}")));
ASSERT_TRUE(GeoParser::isPoint(fromjson("{'type':'Point', 'coordinates': [0, -90.0]}")));
+ ASSERT_TRUE(GeoParser::isPoint(fromjson("{'type':'Point', 'coordinates': [180, 90.0]}")));
+ ASSERT_TRUE(GeoParser::isPoint(fromjson("{'type':'Point', 'coordinates': [-180, -90.0]}")));
+ ASSERT_FALSE(GeoParser::isPoint(fromjson("{'type':'Point', 'coordinates': [180.01, 90.0]}")));
+ ASSERT_FALSE(GeoParser::isPoint(fromjson("{'type':'Point', 'coordinates': [-180.01, -90.0]}")));
ASSERT_FALSE(GeoParser::isPoint(fromjson("{'type':'Point', 'coordinates': [0, 90.1]}")));
ASSERT_FALSE(GeoParser::isPoint(fromjson("{'type':'Point', 'coordinates': [0, -90.1]}")));
}
@@ -63,6 +67,10 @@ namespace {
fromjson("{'type':'LineString', 'coordinates':[[1,2], [3,4]]}")));
ASSERT_TRUE(GeoParser::isLineString(
fromjson("{'type':'LineString', 'coordinates':[[0,-90], [0,90]]}")));
+ ASSERT_TRUE(GeoParser::isLineString(
+ fromjson("{'type':'LineString', 'coordinates':[[180,-90], [-180,90]]}")));
+ ASSERT_FALSE(GeoParser::isLineString(
+ fromjson("{'type':'LineString', 'coordinates':[[180.1,-90], [-180.1,90]]}")));
ASSERT_FALSE(GeoParser::isLineString(
fromjson("{'type':'LineString', 'coordinates':[[0,-91], [0,90]]}")));
ASSERT_FALSE(GeoParser::isLineString(
@@ -82,6 +90,13 @@ namespace {
TEST(GeoParser, isValidPolygon) {
ASSERT_TRUE(GeoParser::isPolygon(
fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[5,0],[5,5],[0,5],[0,0]] ]}")));
+ // No out of bounds points
+ ASSERT_FALSE(GeoParser::isPolygon(
+ fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[5,0],[5,91],[0,5],[0,0]] ]}")));
+ ASSERT_TRUE(GeoParser::isPolygon(
+ fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[180,0],[5,5],[0,5],[0,0]] ]}")));
+ ASSERT_FALSE(GeoParser::isPolygon(
+ fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[181,0],[5,5],[0,5],[0,0]] ]}")));
// And one with a hole.
ASSERT_TRUE(GeoParser::isPolygon(
fromjson("{'type':'Polygon', 'coordinates':[ [[0,0],[5,0],[5,5],[0,5],[0,0]],"
diff --git a/src/mongo/db/geo/s2cursor.cpp b/src/mongo/db/geo/s2cursor.cpp
index f94971d8e08..56bb9230ce2 100644
--- a/src/mongo/db/geo/s2cursor.cpp
+++ b/src/mongo/db/geo/s2cursor.cpp
@@ -97,6 +97,12 @@ namespace mongo {
BSONObj S2Cursor::currKey() const { return _btreeCursor->currKey(); }
DiskLoc S2Cursor::refLoc() { return DiskLoc(); }
long long S2Cursor::nscanned() { return _nscanned; }
+ bool S2Cursor::getsetdup(DiskLoc loc) { return _btreeCursor->getsetdup(loc); }
+ void S2Cursor::aboutToDeleteBucket(const DiskLoc& b) {
+ if (NULL != _btreeCursor) {
+ _btreeCursor->aboutToDeleteBucket(b);
+ }
+ }
// This is the actual search.
bool S2Cursor::advance() {
diff --git a/src/mongo/db/geo/s2cursor.h b/src/mongo/db/geo/s2cursor.h
index ec4881d40db..d3cfa9e21b1 100644
--- a/src/mongo/db/geo/s2cursor.h
+++ b/src/mongo/db/geo/s2cursor.h
@@ -39,7 +39,8 @@ namespace mongo {
virtual bool isMultiKey() const { return true; }
virtual bool autoDedup() const { return false; }
virtual bool modifiedKeys() const { return true; }
- virtual bool getsetdup(DiskLoc loc) { return false; }
+ virtual bool getsetdup(DiskLoc loc);
+ virtual void aboutToDeleteBucket(const DiskLoc& b);
virtual string toString() { return "S2Cursor"; }
BSONObj indexKeyPattern() { return _keyPattern; }
virtual bool ok();
diff --git a/src/mongo/db/json.cpp b/src/mongo/db/json.cpp
index 74fac9f1b3c..afe08f3b0f5 100644
--- a/src/mongo/db/json.cpp
+++ b/src/mongo/db/json.cpp
@@ -465,6 +465,9 @@ namespace mongo {
}
Status JParse::dbRefObject(const StringData& fieldName, BSONObjBuilder& builder) {
+
+ BSONObjBuilder subBuilder(builder.subobjStart(fieldName));
+
if (!accept(COLON)) {
return parseError("Expecting ':'");
}
@@ -474,6 +477,8 @@ namespace mongo {
if (ret != Status::OK()) {
return ret;
}
+ subBuilder.append("$ref", ns);
+
if (!accept(COMMA)) {
return parseError("Expecting ','");
}
@@ -484,42 +489,12 @@ namespace mongo {
if (!accept(COLON)) {
return parseError("Expecting ':'");
}
- if (accept("ObjectId")) {
- BSONObjBuilder subBuilder(builder.subobjStart(fieldName));
- subBuilder.append("$ref", ns);
- objectId("$id", subBuilder);
- subBuilder.done();
- }
- else if (accept(LBRACE)) {
- BSONObjBuilder subBuilder(builder.subobjStart(fieldName));
- subBuilder.append("$ref", ns);
- if (!acceptField("$oid")) {
- return parseError("Expected field name: \"$oid\"");
- }
- objectIdObject("$id", subBuilder);
- subBuilder.done();
- if (!accept(RBRACE)) {
- return parseError("Expecting '}'");
- }
- }
- else {
- std::string id;
- id.reserve(ID_RESERVE_SIZE);
- Status ret = quotedString(&id);
- if (ret != Status::OK()) {
- return ret;
- }
- if (id.size() != 24) {
- return parseError("Expecting 24 hex digits: " + id);
- }
- if (!isHexString(id)) {
- return parseError("Expecting hex digits: " + id);
- }
- BSONObjBuilder subBuilder(builder.subobjStart(fieldName));
- subBuilder.append("$ref", ns);
- subBuilder.append("$id", OID(id));
- subBuilder.done();
+ Status valueRet = value("$id", subBuilder);
+ if (valueRet != Status::OK()) {
+ return valueRet;
}
+
+ subBuilder.done();
return Status::OK();
}
@@ -661,6 +636,8 @@ namespace mongo {
}
Status JParse::dbRef(const StringData& fieldName, BSONObjBuilder& builder) {
+ BSONObjBuilder subBuilder(builder.subobjStart(fieldName));
+
if (!accept(LPAREN)) {
return parseError("Expecting '('");
}
@@ -670,27 +647,21 @@ namespace mongo {
if (refRet != Status::OK()) {
return refRet;
}
+ subBuilder.append("$ref", ns);
+
if (!accept(COMMA)) {
return parseError("Expecting ','");
}
- std::string id;
- id.reserve(ID_RESERVE_SIZE);
- Status idRet = quotedString(&id);
- if (idRet != Status::OK()) {
- return idRet;
- }
- if (id.size() != 24) {
- return parseError("Expecting 24 hex digits: " + id);
- }
- if (!isHexString(id)) {
- return parseError("Expecting hex digits: " + id);
+
+ Status valueRet = value("$id", subBuilder);
+ if (valueRet != Status::OK()) {
+ return valueRet;
}
+
if (!accept(RPAREN)) {
return parseError("Expecting ')'");
}
- BSONObjBuilder subBuilder(builder.subobjStart(fieldName));
- subBuilder.append("$ref", ns);
- subBuilder.append("$id", OID(id));
+
subBuilder.done();
return Status::OK();
}
diff --git a/src/mongo/db/repl/health.cpp b/src/mongo/db/repl/health.cpp
index 7c2f85f6c87..a45809df732 100644
--- a/src/mongo/db/repl/health.cpp
+++ b/src/mongo/db/repl/health.cpp
@@ -446,6 +446,11 @@ namespace mongo {
bb.append("authenticated", false);
}
+ string syncingTo = m->hbinfo().syncingTo;
+ if (!syncingTo.empty()) {
+ bb.append("syncingTo", syncingTo);
+ }
+
v.push_back(bb.obj());
m = m->next();
}
diff --git a/src/mongo/db/repl/heartbeat.cpp b/src/mongo/db/repl/heartbeat.cpp
index fbac43b1d99..5ba3d5f3427 100644
--- a/src/mongo/db/repl/heartbeat.cpp
+++ b/src/mongo/db/repl/heartbeat.cpp
@@ -122,6 +122,11 @@ namespace mongo {
result.append("hbmsg", theReplSet->hbmsg());
result.append("time", (long long) time(0));
result.appendDate("opTime", theReplSet->lastOpTimeWritten.asDate());
+ const Member *syncTarget = replset::BackgroundSync::get()->getSyncTarget();
+ if (syncTarget) {
+ result.append("syncingTo", syncTarget->fullName());
+ }
+
int v = theReplSet->config().version;
result.append("v", v);
if( v > cmdObj["v"].Int() )
@@ -396,6 +401,10 @@ namespace mongo {
}
mem.health = 1.0;
mem.lastHeartbeatMsg = info["hbmsg"].String();
+ if (info.hasElement("syncingTo")) {
+ mem.syncingTo = info["syncingTo"].String();
+ }
+
if( info.hasElement("opTime") )
mem.opTime = info["opTime"].Date();
diff --git a/src/mongo/db/repl/rs_member.h b/src/mongo/db/repl/rs_member.h
index 967052c4da8..100a2013314 100644
--- a/src/mongo/db/repl/rs_member.h
+++ b/src/mongo/db/repl/rs_member.h
@@ -84,6 +84,7 @@ namespace mongo {
// This is the last time we got a heartbeat request from a given member.
time_t lastHeartbeatRecv;
DiagStr lastHeartbeatMsg;
+ DiagStr syncingTo;
OpTime opTime;
int skew;
bool authIssue;
diff --git a/src/mongo/db/ttl.cpp b/src/mongo/db/ttl.cpp
index d94552cb5fc..584bc20a3bc 100644
--- a/src/mongo/db/ttl.cpp
+++ b/src/mongo/db/ttl.cpp
@@ -50,6 +50,9 @@ namespace mongo {
void doTTLForDB( const string& dbName ) {
+ //check isMaster before becoming god
+ bool isMaster = isMasterNs( dbName.c_str() );
+
Client::GodScope god;
vector<BSONObj> indexes;
@@ -100,7 +103,7 @@ namespace mongo {
nsd->syncUserFlags( ns );
}
// only do deletes if on master
- if ( ! isMasterNs( dbName.c_str() ) ) {
+ if ( ! isMaster ) {
continue;
}
diff --git a/src/mongo/dbtests/gle_test.cpp b/src/mongo/dbtests/gle_test.cpp
new file mode 100644
index 00000000000..1a5f89ad1b2
--- /dev/null
+++ b/src/mongo/dbtests/gle_test.cpp
@@ -0,0 +1,85 @@
+/**
+ * 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 "mongo/dbtests/dbtests.h"
+#include "mongo/util/assert_util.h"
+
+using mongo::MsgAssertionException;
+
+/**
+ * Test getLastError client handling
+ */
+namespace {
+ DBDirectClient _client;
+ static const char* const _ns = "unittests.gle";
+
+ /**
+ * Verify that when the command fails we get back an error message.
+ */
+ class GetLastErrorCommandFailure {
+ public:
+ void run() {
+ _client.insert(_ns, BSON( "test" << "test"));
+ // Cannot mix fsync + j, will make command fail
+ string gleString = _client.getLastError(true, true, 10, 10);
+ ASSERT_NOT_EQUALS(gleString, "");
+ }
+ };
+
+ /**
+ * Verify that the write succeeds
+ */
+ class GetLastErrorClean {
+ public:
+ void run() {
+ _client.insert(_ns, BSON( "test" << "test"));
+ // Make sure there was no error
+ string gleString = _client.getLastError();
+ ASSERT_EQUALS(gleString, "");
+ }
+ };
+
+ /**
+ * Verify that the write succeed first, then error on dup
+ */
+ class GetLastErrorFromDup {
+ public:
+ void run() {
+ _client.insert(_ns, BSON( "_id" << 1));
+ // Make sure there was no error
+ string gleString = _client.getLastError();
+ ASSERT_EQUALS(gleString, "");
+
+ //insert dup
+ _client.insert(_ns, BSON( "_id" << 1));
+ // Make sure there was an error
+ gleString = _client.getLastError();
+ ASSERT_NOT_EQUALS(gleString, "");
+ }
+ };
+
+ class All : public Suite {
+ public:
+ All() : Suite( "gle" ) {
+ }
+
+ void setupTests() {
+ add< GetLastErrorClean >();
+ add< GetLastErrorCommandFailure >();
+ add< GetLastErrorFromDup >();
+ }
+ } myall;
+}
diff --git a/src/mongo/dbtests/jsontests.cpp b/src/mongo/dbtests/jsontests.cpp
index 0afee14a37b..98a5624dbd4 100644
--- a/src/mongo/dbtests/jsontests.cpp
+++ b/src/mongo/dbtests/jsontests.cpp
@@ -860,11 +860,9 @@ namespace JsonTests {
class DBRefConstructor : public Base {
virtual BSONObj bson() const {
BSONObjBuilder b;
- OID o;
- memset( &o, 0, 12 );
BSONObjBuilder subBuilder(b.subobjStart("a"));
subBuilder.append("$ref", "ns");
- subBuilder.append("$id", o);
+ subBuilder.append("$id", "000000000000000000000000");
subBuilder.done();
return b.obj();
}
@@ -877,11 +875,9 @@ namespace JsonTests {
class DBRefConstructorCapitals : public Base {
virtual BSONObj bson() const {
BSONObjBuilder b;
- OID o;
- memset( &o, 0, 12 );
BSONObjBuilder subBuilder(b.subobjStart("a"));
subBuilder.append("$ref", "ns");
- subBuilder.append("$id", o);
+ subBuilder.append("$id", "000000000000000000000000");
subBuilder.done();
return b.obj();
}
@@ -890,14 +886,40 @@ namespace JsonTests {
}
};
- class DBRefObjectIDString : public Base {
+ class DBRefConstructorNumber : public Base {
virtual BSONObj bson() const {
BSONObjBuilder b;
- OID o;
- memset( &o, 0, 12 );
BSONObjBuilder subBuilder(b.subobjStart("a"));
subBuilder.append("$ref", "ns");
- subBuilder.append("$id", o);
+ subBuilder.append("$id", 1);
+ subBuilder.done();
+ return b.obj();
+ }
+ virtual string json() const {
+ return "{ \"a\" : Dbref( \"ns\", 1 ) }";
+ }
+ };
+
+ class DBRefNumberId : public Base {
+ virtual BSONObj bson() const {
+ BSONObjBuilder b;
+ BSONObjBuilder subBuilder(b.subobjStart("a"));
+ subBuilder.append("$ref", "ns");
+ subBuilder.append("$id", 1);
+ subBuilder.done();
+ return b.obj();
+ }
+ virtual string json() const {
+ return "{ \"a\" : { \"$ref\" : \"ns\", \"$id\" : 1 } }";
+ }
+ };
+
+ class DBRefStringId : public Base {
+ virtual BSONObj bson() const {
+ BSONObjBuilder b;
+ BSONObjBuilder subBuilder(b.subobjStart("a"));
+ subBuilder.append("$ref", "ns");
+ subBuilder.append("$id", "000000000000000000000000");
subBuilder.done();
return b.obj();
}
@@ -1605,7 +1627,8 @@ namespace JsonTests {
add< FromJsonTests::Utf8TooShort >();
add< FromJsonTests::DBRefConstructor >();
add< FromJsonTests::DBRefConstructorCapitals >();
- add< FromJsonTests::DBRefObjectIDString >();
+ add< FromJsonTests::DBRefNumberId >();
+ add< FromJsonTests::DBRefStringId >();
add< FromJsonTests::DBRefObjectIDObject >();
add< FromJsonTests::DBRefObjectIDConstructor >();
add< FromJsonTests::Oid >();
diff --git a/src/mongo/dbtests/jstests.cpp b/src/mongo/dbtests/jstests.cpp
index 5e5bd597ee2..67262de778b 100644
--- a/src/mongo/dbtests/jstests.cpp
+++ b/src/mongo/dbtests/jstests.cpp
@@ -18,14 +18,12 @@
*/
#include "pch.h"
-#include "../db/instance.h"
-#include "mongo/db/json.h"
-
-#include "../pch.h"
-#include "../scripting/engine.h"
-#include "../util/timer.h"
-#include "dbtests.h"
+#include "mongo/db/instance.h"
+#include "mongo/scripting/engine.h"
+#include "mongo/util/timer.h"
+#include "mongo/dbtests/dbtests.h"
+#include "mongo/db/json.h"
namespace mongo {
bool dbEval(const string& dbName , BSONObj& cmd, BSONObjBuilder& result, string& errmsg);
@@ -33,14 +31,10 @@ namespace mongo {
namespace JSTests {
- class Fundamental {
+ class BuiltinTests {
public:
void run() {
- // By calling JavaJSImpl() inside run(), we ensure the unit test framework's
- // signal handlers are pre-installed from JNI's perspective. This allows
- // JNI to catch signals generated within the JVM and forward other signals
- // as appropriate.
- ScriptEngine::setup();
+ // Run any tests included with the scripting engine
globalScriptEngine->runTest();
}
};
@@ -48,7 +42,7 @@ namespace JSTests {
class BasicScope {
public:
void run() {
- auto_ptr<Scope> s;
+ scoped_ptr<Scope> s;
s.reset( globalScriptEngine->newScope() );
s->setNumber( "x" , 5 );
@@ -63,18 +57,15 @@ namespace JSTests {
s->setBoolean( "b" , true );
ASSERT( s->getBoolean( "b" ) );
- if ( 0 ) {
- s->setBoolean( "b" , false );
- ASSERT( ! s->getBoolean( "b" ) );
- }
+ s->setBoolean( "b" , false );
+ ASSERT( ! s->getBoolean( "b" ) );
}
};
class ResetScope {
public:
void run() {
- // Not worrying about this for now SERVER-446.
- /*
+ /* Currently reset does not clear data in v8 or spidermonkey scopes. See SECURITY-10
auto_ptr<Scope> s;
s.reset( globalScriptEngine->newScope() );
@@ -90,15 +81,23 @@ namespace JSTests {
class FalseTests {
public:
void run() {
- Scope * s = globalScriptEngine->newScope();
+ // Test falsy javascript values
+ scoped_ptr<Scope> s;
+ s.reset( globalScriptEngine->newScope() );
- ASSERT( ! s->getBoolean( "x" ) );
+ ASSERT( ! s->getBoolean( "notSet" ) );
- s->setString( "z" , "" );
- ASSERT( ! s->getBoolean( "z" ) );
+ s->setString( "emptyString" , "" );
+ ASSERT( ! s->getBoolean( "emptyString" ) );
+ s->setNumber( "notANumberVal" , std::numeric_limits<double>::quiet_NaN());
+ ASSERT( ! s->getBoolean( "notANumberVal" ) );
- delete s ;
+ s->setElement( "nullVal" , BSONObjBuilder().appendNull("null").obj().getField("null") );
+ ASSERT( ! s->getBoolean( "nullVal" ) );
+
+ s->setNumber( "zeroVal" , 0 );
+ ASSERT( ! s->getBoolean( "zeroVal" ) );
}
};
@@ -453,6 +452,22 @@ namespace JSTests {
ASSERT_EQUALS( Array, out.firstElement().type() );
}
+ // symbol
+ {
+ // test mutable object with symbol type
+ BSONObjBuilder builder;
+ builder.appendSymbol("sym", "value");
+ BSONObj in = builder.done();
+ s->setObject( "x", in, false );
+ BSONObj out = s->getObject( "x" );
+ ASSERT_EQUALS( Symbol, out.firstElement().type() );
+
+ // readonly
+ s->setObject( "x", in, true );
+ out = s->getObject( "x" );
+ ASSERT_EQUALS( Symbol, out.firstElement().type() );
+ }
+
delete s;
}
};
@@ -940,70 +955,194 @@ namespace JSTests {
}
};
- class DBRefTest {
- public:
- DBRefTest() {
- _a = "unittest.dbref.a";
- _b = "unittest.dbref.b";
- reset();
- }
- ~DBRefTest() {
- //reset();
- }
+ namespace RoundTripTests {
- void run() {
+ // Inherit from this class to test round tripping of JSON objects
+ class TestRoundTrip {
+ public:
+ virtual ~TestRoundTrip() {}
+ void run() {
- client.insert( _a , BSON( "a" << "17" ) );
+ // Insert in Javascript -> Find using DBDirectClient
- {
- BSONObj fromA = client.findOne( _a , BSONObj() );
- verify( fromA.valid() );
- //cout << "Froma : " << fromA << endl;
+ // Drop the collection
+ client.dropCollection( "unittest.testroundtrip" );
+
+ // Insert in Javascript
+ stringstream jsInsert;
+ jsInsert << "db.testroundtrip.insert(" << jsonIn() << ")";
+ ASSERT_TRUE( client.eval( "unittest" , jsInsert.str() ) );
+
+ // Find using DBDirectClient
+ BSONObj excludeIdProjection = BSON( "_id" << 0 );
+ BSONObj directFind = client.findOne( "unittest.testroundtrip",
+ "",
+ &excludeIdProjection);
+ bsonEquals( bson(), directFind );
+
+
+ // Insert using DBDirectClient -> Find in Javascript
+
+ // Drop the collection
+ client.dropCollection( "unittest.testroundtrip" );
+
+ // Insert using DBDirectClient
+ client.insert( "unittest.testroundtrip" , bson() );
+
+ // Find in Javascript
+ stringstream jsFind;
+ jsFind << "dbref = db.testroundtrip.findOne( { } , { _id : 0 } )\n"
+ << "assert.eq(dbref, " << jsonOut() << ")";
+ ASSERT_TRUE( client.eval( "unittest" , jsFind.str() ) );
+ }
+ protected:
+
+ // Methods that must be defined by child classes
+ virtual BSONObj bson() const = 0;
+ virtual string json() const = 0;
+
+ // This can be overriden if a different meaning of equality besides woCompare is needed
+ virtual void bsonEquals( const BSONObj &expected, const BSONObj &actual ) {
+ if ( expected.woCompare( actual ) ) {
+ out() << "want:" << expected.jsonString() << " size: " << expected.objsize() << endl;
+ out() << "got :" << actual.jsonString() << " size: " << actual.objsize() << endl;
+ out() << expected.hexDump() << endl;
+ out() << actual.hexDump() << endl;
+ }
+ ASSERT( !expected.woCompare( actual ) );
+ }
+
+ // This can be overriden if the JSON representation is altered on the round trip
+ virtual string jsonIn() const {
+ return json();
+ }
+ virtual string jsonOut() const {
+ return json();
+ }
+ };
+
+ class DBRefTest : public TestRoundTrip {
+ virtual BSONObj bson() const {
BSONObjBuilder b;
- b.append( "b" , 18 );
- b.appendDBRef( "c" , "dbref.a" , fromA["_id"].__oid() );
- client.insert( _b , b.obj() );
+ OID o;
+ memset( &o, 0, 12 );
+ BSONObjBuilder subBuilder(b.subobjStart("a"));
+ subBuilder.append("$ref", "ns");
+ subBuilder.append("$id", o);
+ subBuilder.done();
+ return b.obj();
+ }
+ virtual string json() const {
+ return "{ \"a\" : DBRef( \"ns\", ObjectId( \"000000000000000000000000\" ) ) }";
}
- ASSERT( client.eval( "unittest" , "x = db.dbref.b.findOne(); assert.eq( 17 , x.c.fetch().a , 'ref working' );" ) );
+ // A "fetch" function is added to the DBRef object when it is inserted using the
+ // constructor, so we need to compare the fields individually
+ virtual void bsonEquals( const BSONObj &expected, const BSONObj &actual ) {
+ ASSERT_EQUALS( expected["a"].type() , actual["a"].type() );
+ ASSERT_EQUALS( expected["a"]["$id"].OID() , actual["a"]["$id"].OID() );
+ ASSERT_EQUALS( expected["a"]["$ref"].String() , actual["a"]["$ref"].String() );
+ }
+ };
- // BSON DBRef <=> JS DBPointer
- ASSERT( client.eval( "unittest", "x = db.dbref.b.findOne(); db.dbref.b.drop(); x.c = new DBPointer( x.c.ns, x.c.id ); db.dbref.b.insert( x );" ) );
- ASSERT_EQUALS( DBRef, client.findOne( "unittest.dbref.b", "" )[ "c" ].type() );
+ class DBPointerTest : public TestRoundTrip {
+ virtual BSONObj bson() const {
+ BSONObjBuilder b;
+ OID o;
+ memset( &o, 0, 12 );
+ b.appendDBRef( "a" , "ns" , o );
+ return b.obj();
+ }
+ virtual string json() const {
+ return "{ \"a\" : DBPointer( \"ns\", ObjectId( \"000000000000000000000000\" ) ) }";
+ }
+ };
- // BSON Object <=> JS DBRef
- ASSERT( client.eval( "unittest", "x = db.dbref.b.findOne(); db.dbref.b.drop(); x.c = new DBRef( x.c.ns, x.c.id ); db.dbref.b.insert( x );" ) );
- ASSERT_EQUALS( Object, client.findOne( "unittest.dbref.b", "" )[ "c" ].type() );
- ASSERT_EQUALS( string( "dbref.a" ), client.findOne( "unittest.dbref.b", "" )[ "c" ].embeddedObject().getStringField( "$ref" ) );
- }
+ class InformalDBRefTest : public TestRoundTrip {
+ virtual BSONObj bson() const {
+ BSONObjBuilder b;
+ BSONObjBuilder subBuilder(b.subobjStart("a"));
+ subBuilder.append("$ref", "ns");
+ subBuilder.append("$id", "000000000000000000000000");
+ subBuilder.done();
+ return b.obj();
+ }
- void reset() {
- client.dropCollection( _a );
- client.dropCollection( _b );
- }
+ // Don't need to return anything because we are overriding both jsonOut and jsonIn
+ virtual string json() const { return ""; }
- const char * _a;
- const char * _b;
- };
+ // Need to override these because the JSON doesn't actually round trip.
+ // An object with "$ref" and "$id" fields is handled specially and different on the way out.
+ virtual string jsonOut() const {
+ return "{ \"a\" : DBRef( \"ns\", \"000000000000000000000000\" ) }";
+ }
+ virtual string jsonIn() const {
+ stringstream ss;
+ ss << "{ \"a\" : { \"$ref\" : \"ns\" , " <<
+ "\"$id\" : \"000000000000000000000000\" } }";
+ return ss.str();
+ }
+ };
- class InformalDBRef {
- public:
- void run() {
- client.insert( ns(), BSON( "i" << 1 ) );
- BSONObj obj = client.findOne( ns(), BSONObj() );
- client.remove( ns(), BSONObj() );
- client.insert( ns(), BSON( "r" << BSON( "$ref" << "jstests.informaldbref" << "$id" << obj["_id"].__oid() << "foo" << "bar" ) ) );
- obj = client.findOne( ns(), BSONObj() );
- ASSERT_EQUALS( "bar", obj[ "r" ].embeddedObject()[ "foo" ].str() );
-
- ASSERT( client.eval( "unittest", "x = db.jstests.informaldbref.findOne(); y = { r:x.r }; db.jstests.informaldbref.drop(); y.r[ \"a\" ] = \"b\"; db.jstests.informaldbref.save( y );" ) );
- obj = client.findOne( ns(), BSONObj() );
- ASSERT_EQUALS( "bar", obj[ "r" ].embeddedObject()[ "foo" ].str() );
- ASSERT_EQUALS( "b", obj[ "r" ].embeddedObject()[ "a" ].str() );
- }
- private:
- static const char *ns() { return "unittest.jstests.informaldbref"; }
- };
+ class InformalDBRefOIDTest : public TestRoundTrip {
+ virtual BSONObj bson() const {
+ BSONObjBuilder b;
+ OID o;
+ memset( &o, 0, 12 );
+ BSONObjBuilder subBuilder(b.subobjStart("a"));
+ subBuilder.append("$ref", "ns");
+ subBuilder.append("$id", o);
+ subBuilder.done();
+ return b.obj();
+ }
+
+ // Don't need to return anything because we are overriding both jsonOut and jsonIn
+ virtual string json() const { return ""; }
+
+ // Need to override these because the JSON doesn't actually round trip.
+ // An object with "$ref" and "$id" fields is handled specially and different on the way out.
+ virtual string jsonOut() const {
+ return "{ \"a\" : DBRef( \"ns\", ObjectId( \"000000000000000000000000\" ) ) }";
+ }
+ virtual string jsonIn() const {
+ stringstream ss;
+ ss << "{ \"a\" : { \"$ref\" : \"ns\" , " <<
+ "\"$id\" : ObjectId( \"000000000000000000000000\" ) } }";
+ return ss.str();
+ }
+ };
+
+ class InformalDBRefExtraFieldTest : public TestRoundTrip {
+ virtual BSONObj bson() const {
+ BSONObjBuilder b;
+ OID o;
+ memset( &o, 0, 12 );
+ BSONObjBuilder subBuilder(b.subobjStart("a"));
+ subBuilder.append("$ref", "ns");
+ subBuilder.append("$id", o);
+ subBuilder.append("otherfield", "value");
+ subBuilder.done();
+ return b.obj();
+ }
+
+ // Don't need to return anything because we are overriding both jsonOut and jsonIn
+ virtual string json() const { return ""; }
+
+ // Need to override these because the JSON doesn't actually round trip.
+ // An object with "$ref" and "$id" fields is handled specially and different on the way out.
+ virtual string jsonOut() const {
+ return "{ \"a\" : DBRef( \"ns\", ObjectId( \"000000000000000000000000\" ) ) }";
+ }
+ virtual string jsonIn() const {
+ stringstream ss;
+ ss << "{ \"a\" : { \"$ref\" : \"ns\" , " <<
+ "\"$id\" : ObjectId( \"000000000000000000000000\" ) , " <<
+ "\"otherfield\" : \"value\" } }";
+ return ss.str();
+ }
+ };
+
+ } // namespace RoundTripTests
class BinDataType {
public:
@@ -1094,7 +1233,7 @@ namespace JSTests {
Timer t;
double n = 0;
- for ( ; n < 100000; n++ ) {
+ for ( ; n < 10000 ; n++ ) {
s->invoke( f , &empty, &start );
ASSERT_EQUALS( 11 , s->getNumber( "__returnValue" ) );
}
@@ -1173,10 +1312,12 @@ namespace JSTests {
class All : public Suite {
public:
All() : Suite( "js" ) {
+ // Initialize the Javascript interpreter
+ ScriptEngine::setup();
}
void setupTests() {
- add< Fundamental >();
+ add< BuiltinTests >();
add< BasicScope >();
add< ResetScope >();
add< FalseTests >();
@@ -1202,8 +1343,6 @@ namespace JSTests {
add< WeirdObjects >();
add< CodeTests >();
- add< DBRefTest >();
- add< InformalDBRef >();
add< BinDataType >();
add< VarTests >();
@@ -1216,6 +1355,12 @@ namespace JSTests {
add< ScopeOut >();
add< InvalidStoredJS >();
+
+ add< RoundTripTests::DBRefTest >();
+ add< RoundTripTests::DBPointerTest >();
+ add< RoundTripTests::InformalDBRefTest >();
+ add< RoundTripTests::InformalDBRefOIDTest >();
+ add< RoundTripTests::InformalDBRefExtraFieldTest >();
}
} myall;
diff --git a/src/mongo/dbtests/mock/mock_remote_db_server.cpp b/src/mongo/dbtests/mock/mock_remote_db_server.cpp
index e78d245c70c..9d8506b37ba 100644
--- a/src/mongo/dbtests/mock/mock_remote_db_server.cpp
+++ b/src/mongo/dbtests/mock/mock_remote_db_server.cpp
@@ -24,6 +24,7 @@ using std::string;
using std::vector;
namespace mongo {
+
MockRemoteDBServer::CircularBSONIterator::CircularBSONIterator(
const vector<BSONObj>& replyVector) {
for (std::vector<mongo::BSONObj>::const_iterator iter = replyVector.begin();
@@ -54,6 +55,7 @@ namespace mongo {
_cmdCount(0),
_queryCount(0),
_instanceID(0) {
+ insert(IdentityNS, BSON(HostField(hostAndPort)), 0);
}
MockRemoteDBServer::~MockRemoteDBServer() {
diff --git a/src/mongo/dbtests/mock/mock_remote_db_server.h b/src/mongo/dbtests/mock/mock_remote_db_server.h
index 6aaba91113c..0455e755d07 100644
--- a/src/mongo/dbtests/mock/mock_remote_db_server.h
+++ b/src/mongo/dbtests/mock/mock_remote_db_server.h
@@ -19,12 +19,17 @@
#include <string>
#include <vector>
+#include "mongo/bson/bson_field.h"
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/client/dbclientinterface.h"
#include "mongo/platform/unordered_map.h"
#include "mongo/util/concurrency/spin_lock.h"
namespace mongo {
+
+ const std::string IdentityNS("local.me");
+ const BSONField<string> HostField("host");
+
/**
* A very simple mock that acts like a database server. Every object keeps track of its own
* InstanceID, which initially starts at zero and increments every time it is restarted.
@@ -51,6 +56,9 @@ namespace mongo {
* 1. hostAndPort of this server should start with $.
* 2. No other instance has the same hostAndPort as this.
*
+ * This server will also contain the hostAndPort inside the IdentityNS
+ * collection. This is convenient for testing query routing.
+ *
* @param hostAndPort the host name with port for this server.
*
* @see MockConnRegistry
@@ -70,7 +78,7 @@ namespace mongo {
/**
* Shuts down this server. Any operations on this server with an InstanceID
* less than or equal to the current one will throw a mongo::SocketException.
- * To bring the server up again, use the #reboot method.
+ * To bring the server up again, use the reboot method.
*/
void shutdown();
diff --git a/src/mongo/dbtests/replica_set_monitor_test.cpp b/src/mongo/dbtests/replica_set_monitor_test.cpp
index 57ef4756d49..b016b1affc0 100644
--- a/src/mongo/dbtests/replica_set_monitor_test.cpp
+++ b/src/mongo/dbtests/replica_set_monitor_test.cpp
@@ -1414,6 +1414,33 @@ namespace mongo_test {
ASSERT_EQUALS("b", lastHost.host());
}
+ TEST(TagSet, CopyConstructor) {
+ TagSet* copy;
+
+ {
+ BSONArrayBuilder builder;
+ builder.append(BSON("dc" << "nyc"));
+ builder.append(BSON("priority" << "1"));
+ TagSet original(builder.arr());
+
+ original.next();
+
+ copy = new TagSet(original);
+ }
+
+ ASSERT_FALSE(copy->isExhausted());
+ ASSERT(copy->getCurrentTag().equal(BSON("dc" << "nyc")));
+ copy->next();
+
+ ASSERT_FALSE(copy->isExhausted());
+ ASSERT(copy->getCurrentTag().equal(BSON("priority" << "1")));
+ copy->next();
+
+ ASSERT(copy->isExhausted());
+
+ delete copy;
+ }
+
TEST(TagSet, NearestMultiTagsNoMatch) {
vector<ReplicaSetMonitor::Node> nodes =
NodeSetFixtures::getThreeMemberWithTags();
diff --git a/src/mongo/s/config_upgrade_helpers.cpp b/src/mongo/s/config_upgrade_helpers.cpp
index a589e02b460..6495b5d9c80 100644
--- a/src/mongo/s/config_upgrade_helpers.cpp
+++ b/src/mongo/s/config_upgrade_helpers.cpp
@@ -19,6 +19,7 @@
#include "mongo/client/connpool.h"
#include "mongo/db/namespacestring.h"
#include "mongo/s/cluster_client_internal.h"
+#include "mongo/util/timer.h"
namespace mongo {
@@ -249,18 +250,62 @@ namespace mongo {
return e.toStatus("could not create indexes in new collection");
}
- // Copy data over
+ //
+ // Copy data over in batches. A batch size here is way smaller than the maximum size of
+ // a bsonobj. We want to copy efficiently but we don't need to maximize the object size
+ // here.
+ //
+
+ Timer t;
+ int64_t docCount = 0;
+ const int32_t maxBatchSize = BSONObjMaxUserSize / 16;
try {
- ScopedDbConnection& conn = *connPtr;
- scoped_ptr<DBClientCursor> cursor(_safeCursor(conn->query(fromNS, BSONObj())));
+ log() << "About to copy " << fromNS << " to " << toNS << endl;
+ // Lower the query's batchSize so that we incur in getMore()'s more frequently.
+ // The rationale here is that, if for some reason the config server is extremely
+ // slow, we wouldn't time this cursor out.
+ ScopedDbConnection& conn = *connPtr;
+ scoped_ptr<DBClientCursor> cursor(_safeCursor(conn->query(fromNS,
+ BSONObj(),
+ 0 /* nToReturn */,
+ 0 /* nToSkip */,
+ NULL /* fieldsToReturn */,
+ 0 /* queryOptions */,
+ 1024 /* batchSize */)));
+
+ vector<BSONObj> insertBatch;
+ int32_t insertSize = 0;
while (cursor->more()) {
- BSONObj next = cursor->nextSafe();
+ BSONObj next = cursor->nextSafe().getOwned();
+ ++docCount;
+
+ insertBatch.push_back(next);
+ insertSize += next.objsize();
- conn->insert(toNS, next);
+ if (insertSize > maxBatchSize ) {
+ conn->insert(toNS, insertBatch);
+ _checkGLE(conn);
+ insertBatch.clear();
+ insertSize = 0;
+ }
+
+ if (t.seconds() >= 10) {
+ t.reset();
+ log() << "Copied " << docCount << " documents so far from "
+ << fromNS << " to " << toNS << endl;
+ }
+ }
+
+ if (!insertBatch.empty()) {
+ conn->insert(toNS, insertBatch);
_checkGLE(conn);
}
+
+ log() << "Finished copying " << docCount << " documents from "
+ << fromNS << " to " << toNS << endl;
+
}
catch (const DBException& e) {
return e.toStatus("could not copy data into new collection");
diff --git a/src/mongo/s/cursors.cpp b/src/mongo/s/cursors.cpp
index affb7f744fd..4e904e39c4c 100644
--- a/src/mongo/s/cursors.cpp
+++ b/src/mongo/s/cursors.cpp
@@ -203,6 +203,13 @@ namespace mongo {
_cursors.erase( id );
}
+ void CursorCache::removeRef( long long id ) {
+ verify( id );
+ scoped_lock lk( _mutex );
+ _refs.erase( id );
+ _refsNS.erase( id );
+ }
+
void CursorCache::storeRef(const std::string& server, long long id, const std::string& ns) {
LOG(_myLogLevel) << "CursorCache::storeRef server: " << server << " id: " << id << endl;
verify( id );
diff --git a/src/mongo/s/cursors.h b/src/mongo/s/cursors.h
index b42ea7538d7..c250d70ded2 100644
--- a/src/mongo/s/cursors.h
+++ b/src/mongo/s/cursors.h
@@ -105,6 +105,7 @@ namespace mongo {
void remove( long long id );
void storeRef(const std::string& server, long long id, const std::string& ns);
+ void removeRef( long long id );
/** @return the server for id or "" */
string getRef( long long id ) const ;
diff --git a/src/mongo/s/d_migrate.cpp b/src/mongo/s/d_migrate.cpp
index 914b43b8b21..a9507e0b96c 100644
--- a/src/mongo/s/d_migrate.cpp
+++ b/src/mongo/s/d_migrate.cpp
@@ -58,6 +58,7 @@
#include "mongo/s/d_logic.h"
#include "mongo/s/shard.h"
#include "mongo/s/type_chunk.h"
+#include "mongo/util/assert_util.h"
#include "mongo/util/elapsed_tracker.h"
#include "mongo/util/processinfo.h"
#include "mongo/util/queue.h"
@@ -999,7 +1000,7 @@ namespace mongo {
dist_lock_try dlk;
try{
- dlk = dist_lock_try( &lockSetup , (string)"migrate-" + min.toString() );
+ dlk = dist_lock_try( &lockSetup , (string)"migrate-" + min.toString(), 30.0 /*timeout*/ );
}
catch( LockException& e ){
errmsg = str::stream() << "error locking distributed lock for migration " << "migrate-" << min.toString() << causedBy( e );
@@ -1214,6 +1215,22 @@ namespace mongo {
timing.done(4);
// 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";
+
+ string lockHeldMsg;
+ bool lockHeld = dlk.isLockHeld( 30.0 /* timeout */, &lockHeldMsg );
+ if ( !lockHeld ) {
+ errmsg = str::stream() << "not entering migrate critical section because "
+ << lockHeldMsg;
+ warning() << errmsg << endl;
+ return false;
+ }
+
+ log() << "About to enter migrate critical section";
+
{
// 5.a
// we're under the collection lock here, so no other migrate can change maxVersion or ShardChunkManager state
@@ -1386,6 +1403,7 @@ namespace mongo {
BSONObj cmd = cmdBuilder.obj();
LOG(7) << "moveChunk update: " << cmd << migrateLog;
+ int exceptionCode = OkCode;
bool ok = false;
BSONObj cmdResult;
try {
@@ -1399,12 +1417,39 @@ namespace mongo {
catch ( DBException& e ) {
warning() << e << migrateLog;
ok = false;
+ exceptionCode = e.getCode();
BSONObjBuilder b;
e.getInfo().append( b );
cmdResult = b.obj();
+ errmsg = cmdResult.toString();
}
- if ( ! ok ) {
+ if ( exceptionCode == PrepareConfigsFailedCode ) {
+
+ // In the process of issuing the migrate commit, the SyncClusterConnection
+ // checks that the config servers are reachable. If they are not, we are
+ // sure that the applyOps command was not sent to any of the configs, so we
+ // can safely back out of the migration here, by resetting the shard
+ // version that we bumped up to in the donateChunk() call above.
+
+ log() << "About to acquire moveChunk global lock to reset shard version from "
+ << "failed migration" << endl;
+
+ {
+ Lock::GlobalWrite lk;
+
+ // 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;
+
+ errmsg = "Failed to send migrate commit to configs because " + errmsg;
+ return false;
+
+ }
+ else if ( ! ok || exceptionCode != OkCode ) {
// this could be a blip in the connectivity
// wait out a few seconds and check if the commit request made it
@@ -1433,6 +1478,7 @@ namespace mongo {
if ( checkVersion.isEquivalentTo( nextVersion ) ) {
log() << "moveChunk commit confirmed" << migrateLog;
+ errmsg.clear();
}
else {
diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp
index 57a65015e33..f7e647662f9 100644
--- a/src/mongo/s/server.cpp
+++ b/src/mongo/s/server.cpp
@@ -107,6 +107,12 @@ namespace mongo {
try {
r.init();
r.process();
+
+ // Release connections after non-write op
+ if ( ShardConnection::releaseConnectionsAfterResponse && r.expectResponse() ) {
+ LOG(2) << "release thread local connections back to pool" << endl;
+ ShardConnection::releaseMyConnections();
+ }
}
catch ( AssertionException & e ) {
LOG( e.isUserAssertion() ? 1 : 0 ) << "AssertionException while processing op type : " << m.operation() << " to : " << r.getns() << causedBy(e) << endl;
diff --git a/src/mongo/s/shard.h b/src/mongo/s/shard.h
index 44b20792cae..e917baa0986 100644
--- a/src/mongo/s/shard.h
+++ b/src/mongo/s/shard.h
@@ -290,10 +290,18 @@ namespace mongo {
*/
bool runCommand( const string& db , const BSONObj& cmd , BSONObj& res );
+ static bool releaseConnectionsAfterResponse;
+
/** checks all of my thread local connections for the version of this ns */
static void checkMyConnectionVersions( const string & ns );
/**
+ * Returns all the current sharded connections to the pool.
+ * Note: This is *dangerous* if we have GLE state.
+ */
+ static void releaseMyConnections();
+
+ /**
* Clears all connections in the sharded pool, including connections in the
* thread local storage pool of the current thread.
*/
diff --git a/src/mongo/s/shardconnection.cpp b/src/mongo/s/shardconnection.cpp
index 3a56a38a044..61b47904147 100644
--- a/src/mongo/s/shardconnection.cpp
+++ b/src/mongo/s/shardconnection.cpp
@@ -21,6 +21,8 @@
#include <set>
#include "mongo/db/client.h"
+#include "mongo/db/commands.h"
+#include "mongo/db/server_parameters.h"
#include "mongo/s/config.h"
#include "mongo/s/request.h"
#include "mongo/s/shard.h"
@@ -33,6 +35,70 @@ namespace mongo {
DBConnectionPool shardConnectionPool;
+ class ClientConnections;
+
+ /**
+ * Class which tracks ClientConnections (the client connection pool) for each incoming
+ * connection, allowing stats access.
+ */
+
+ class ActiveClientConnections {
+ public:
+
+ ActiveClientConnections() : _mutex( "ActiveClientConnections" ) {
+ }
+
+ void add( const ClientConnections* cc ) {
+ scoped_lock lock( _mutex );
+ _clientConnections.insert( cc );
+ }
+
+ void remove( const ClientConnections* cc ) {
+ scoped_lock lock( _mutex );
+ _clientConnections.erase( cc );
+ }
+
+ // Implemented after ClientConnections
+ void appendInfo( BSONObjBuilder& b );
+
+ private:
+ mongo::mutex _mutex;
+ set<const ClientConnections*> _clientConnections;
+
+ } activeClientConnections;
+
+ /**
+ * Command to allow access to the sharded conn pool information in mongos.
+ * TODO: Refactor with other connection pooling changes
+ */
+ class ShardedPoolStats : public Command {
+ public:
+
+ ShardedPoolStats() : Command( "shardConnPoolStats" ) {}
+ virtual void help( stringstream &help ) const { help << "stats about the shard connection pool"; }
+ virtual LockType locktype() const { return NONE; }
+ virtual bool slaveOk() const { return true; }
+
+ // Same privs as connPoolStats
+ virtual void addRequiredPrivileges( const std::string& dbname,
+ const BSONObj& cmdObj,
+ std::vector<Privilege>* out )
+ {
+ ActionSet actions;
+ actions.addAction( ActionType::connPoolStats );
+ out->push_back( Privilege( AuthorizationManager::SERVER_RESOURCE_NAME, actions ) );
+ }
+
+ virtual bool run ( const string&, mongo::BSONObj&, int, std::string&, mongo::BSONObjBuilder& result, bool ) {
+ // Base pool info
+ shardConnectionPool.appendInfo( result );
+ // Thread connection info
+ activeClientConnections.appendInfo( result );
+ return true;
+ }
+
+ } shardedPoolStatsCmd;
+
/**
* holds all the actual db connections for a client to various servers
* 1 per thread, so doesn't have to be thread safe
@@ -42,14 +108,39 @@ namespace mongo {
struct Status : boost::noncopyable {
Status() : created(0), avail(0) {}
+ // May be read concurrently, but only written from
+ // this thread.
long long created;
DBClientBase* avail;
};
+ // Gets or creates the status object for the host
+ Status* _getStatus( const string& addr ) {
+ scoped_spinlock lock( _lock );
+ Status* &temp = _hosts[addr];
+ if ( ! temp )
+ temp = new Status();
+ return temp;
+ }
- ClientConnections() {}
+ ClientConnections() {
+ // Start tracking client connections
+ activeClientConnections.add( this );
+ }
~ClientConnections() {
+ // Stop tracking these client connections
+ activeClientConnections.remove( this );
+
+ releaseAll( true );
+ }
+
+ void releaseAll( bool fromDestructor = false ) {
+
+ // Don't need spinlock protection because if not in the destructor, we don't
+ // modify _hosts, and if in the destructor we are not accessible to external
+ // threads.
+
for ( HostMap::iterator i=_hosts.begin(); i!=_hosts.end(); ++i ) {
string addr = i->first;
Status* ss = i->second;
@@ -65,17 +156,15 @@ namespace mongo {
release( addr , ss->avail );
ss->avail = 0;
}
- delete ss;
+ if ( fromDestructor ) delete ss;
}
- _hosts.clear();
+ if ( fromDestructor ) _hosts.clear();
}
DBClientBase * get( const string& addr , const string& ns ) {
_check( ns );
- Status* &s = _hosts[addr];
- if ( ! s )
- s = new Status();
+ Status* s = _getStatus( addr );
auto_ptr<DBClientBase> c; // Handles cleanup if there's an exception thrown
if ( s->avail ) {
@@ -83,8 +172,8 @@ namespace mongo {
s->avail = 0;
shardConnectionPool.onHandedOut( c.get() ); // May throw an exception
} else {
- s->created++;
c.reset( shardConnectionPool.get( addr ) );
+ s->created++; // After, so failed creation doesn't get counted
}
return c.release();
}
@@ -152,18 +241,19 @@ namespace mongo {
Shard& shard = all[i];
try {
string sconnString = shard.getConnString();
- Status* &s = _hosts[sconnString];
-
- if ( ! s ){
- s = new Status();
- }
+ Status* s = _getStatus( sconnString );
- if( ! s->avail )
+ if( ! s->avail ) {
s->avail = shardConnectionPool.get( sconnString );
+ s->created++; // After, so failed creation doesn't get counted
+ }
versionManager.checkShardVersionCB( s->avail, ns, false, 1 );
- } catch(...) {
- LOGATMOST(2) << "exception in checkAllVersions shard:" << shard.getName() << endl;
+ }
+ catch ( const std::exception& e ) {
+
+ warning() << "problem while initially checking shard versions on"
+ << " " << shard.getName() << causedBy(e) << endl;
throw;
}
}
@@ -174,12 +264,47 @@ namespace mongo {
}
void _check( const string& ns ) {
- if ( ns.size() == 0 || _seenNS.count( ns ) )
- return;
- _seenNS.insert( ns );
+
+ {
+ // We want to report ns stats too
+ scoped_spinlock lock( _lock );
+ if ( ns.size() == 0 || _seenNS.count( ns ) )
+ return;
+ _seenNS.insert( ns );
+ }
+
checkVersions( ns );
}
+ /**
+ * Appends info about the client connection pool to a BOBuilder
+ * Safe to call with activeClientConnections lock
+ */
+ void appendInfo( BSONObjBuilder& b ) const {
+
+ scoped_spinlock lock( _lock );
+
+ BSONArrayBuilder hostsArrB( b.subarrayStart( "hosts" ) );
+ for ( HostMap::const_iterator i = _hosts.begin(); i != _hosts.end(); ++i ) {
+ BSONObjBuilder bb( hostsArrB.subobjStart() );
+ bb.append( "host", i->first );
+ bb.append( "created", i->second->created );
+ bb.appendBool( "avail", static_cast<bool>( i->second->avail ) );
+ bb.done();
+ }
+ hostsArrB.done();
+
+ BSONArrayBuilder nsArrB( b.subarrayStart( "seenNS" ) );
+ for ( set<string>::const_iterator i = _seenNS.begin(); i != _seenNS.end(); ++i ) {
+ nsArrB.append(*i);
+ }
+ nsArrB.done();
+ }
+
+ // Protects only the creation of new entries in the _hosts and _seenNS map
+ // from external threads. Reading _hosts / _seenNS in this thread doesn't
+ // need protection.
+ mutable SpinLock _lock;
typedef map<string,Status*,DBConnectionPool::serverNameCompare> HostMap;
HostMap _hosts;
set<string> _seenNS;
@@ -213,6 +338,27 @@ namespace mongo {
thread_specific_ptr<ClientConnections> ClientConnections::_perThread;
+ /**
+ * Appends info about all active client shard connections to a BOBuilder
+ */
+ void ActiveClientConnections::appendInfo( BSONObjBuilder& b ) {
+
+ BSONArrayBuilder arr( 64 * 1024 ); // There may be quite a few threads
+
+ {
+ scoped_lock lock( _mutex );
+ for ( set<const ClientConnections*>::const_iterator i = _clientConnections.begin();
+ i != _clientConnections.end(); ++i )
+ {
+ BSONObjBuilder bb( arr.subobjStart() );
+ (*i)->appendInfo( bb );
+ bb.done();
+ }
+ }
+
+ b.appendArray( "threads", arr.obj() );
+ }
+
ShardConnection::ShardConnection( const Shard * s , const string& ns, ChunkManagerPtr manager )
: _addr( s->getConnString() ) , _ns( ns ), _manager( manager ) {
_init();
@@ -323,6 +469,20 @@ namespace mongo {
}
}
+ bool ShardConnection::releaseConnectionsAfterResponse( false );
+
+ ExportedServerParameter<bool> ReleaseConnectionsAfterResponse(
+ ServerParameterSet::getGlobal(),
+ "releaseConnectionsAfterResponse",
+ &ShardConnection::releaseConnectionsAfterResponse,
+ true,
+ true
+ );
+
+ void ShardConnection::releaseMyConnections() {
+ ClientConnections::threadInstance()->releaseAll();
+ }
+
void ShardConnection::clearPool() {
shardConnectionPool.clear();
ClientConnections::threadInstance()->clearPool();
diff --git a/src/mongo/s/shardkey.cpp b/src/mongo/s/shardkey.cpp
index a2ad2ce02f2..b7f37e779e7 100644
--- a/src/mongo/s/shardkey.cpp
+++ b/src/mongo/s/shardkey.cpp
@@ -49,8 +49,10 @@ namespace mongo {
for(set<string>::const_iterator it = patternfields.begin(); it != patternfields.end(); ++it) {
BSONElement e = obj.getFieldDotted(it->c_str());
- if(e.eoo() || e.type() == Array || (e.type() == Object && e.embeddedObject().firstElementFieldName()[0] == '$')) {
- // cant use getGtLtOp here as it returns Equality for unknown $ops and we want to reject them
+ if( e.eoo() ||
+ e.type() == Array ||
+ (e.type() == Object && !e.embeddedObject().okForStorage())) {
+ // Don't allow anything for a shard key we can't store -- like $gt/$lt ops
return false;
}
}
@@ -143,16 +145,26 @@ namespace mongo {
public:
void hasshardkeytest() {
- BSONObj x = fromjson("{ zid : \"abcdefg\", num: 1.0, name: \"eliot\" }");
ShardKeyPattern k( BSON( "num" << 1 ) );
+
+ BSONObj x = fromjson("{ zid : \"abcdefg\", num: 1.0, name: \"eliot\" }");
verify( k.hasShardKey(x) );
verify( !k.hasShardKey( fromjson("{foo:'a'}") ) );
verify( !k.hasShardKey( fromjson("{x: {$gt: 1}}") ) );
+ verify( !k.hasShardKey( fromjson("{num: {$gt: 1}}") ) );
+ BSONObj obj = BSON( "num" << BSON( "$ref" << "coll" << "$id" << 1));
+ verify( k.hasShardKey(obj));
// try compound key
{
ShardKeyPattern k( fromjson("{a:1,b:-1,c:1}") );
verify( k.hasShardKey( fromjson("{foo:'a',a:'b',c:'z',b:9,k:99}") ) );
+ BSONObj obj = BSON( "foo" << "a" <<
+ "a" << BSON("$ref" << "coll" << "$id" << 1) <<
+ "c" << 1 << "b" << 9 << "k" << 99 );
+ verify( k.hasShardKey( obj ) );
+ verify( !k.hasShardKey( fromjson("{foo:'a',a:[1,2],c:'z',b:9,k:99}") ) );
+ verify( !k.hasShardKey( fromjson("{foo:'a',a:{$gt:1},c:'z',b:9,k:99}") ) );
verify( !k.hasShardKey( fromjson("{foo:'a',a:'b',c:'z',bb:9,k:99}") ) );
verify( !k.hasShardKey( fromjson("{k:99}") ) );
}
@@ -162,7 +174,16 @@ namespace mongo {
ShardKeyPattern k( fromjson("{'a.b':1}") );
verify( k.hasShardKey( fromjson("{a:{b:1,c:1},d:1}") ) );
verify( k.hasShardKey( fromjson("{'a.b':1}") ) );
+ BSONObj obj = BSON( "c" << "a" <<
+ "a" << BSON("$ref" << "coll" << "$id" << 1) );
+ verify( !k.hasShardKey( obj ) );
+ obj = BSON( "c" << "a" <<
+ "a" << BSON( "b" << BSON("$ref" << "coll" << "$id" << 1) <<
+ "c" << 1));
+ verify( k.hasShardKey( obj ) );
verify( !k.hasShardKey( fromjson("{'a.c':1}") ) );
+ verify( !k.hasShardKey( fromjson("{'a':[{b:1}, {c:1}]}") ) );
+ verify( !k.hasShardKey( fromjson("{a:{b:[1,2]},d:1}") ) );
verify( !k.hasShardKey( fromjson("{a:{c:1},d:1}") ) );
verify( !k.hasShardKey( fromjson("{a:1}") ) );
verify( !k.hasShardKey( fromjson("{b:1}") ) );
diff --git a/src/mongo/s/strategy_shard.cpp b/src/mongo/s/strategy_shard.cpp
index 2f8667de6d8..0d4adcef155 100644
--- a/src/mongo/s/strategy_shard.cpp
+++ b/src/mongo/s/strategy_shard.cpp
@@ -212,8 +212,14 @@ namespace mongo {
Message response;
bool ok = conn->get()->callRead( r.m() , response);
uassert( 10204 , "dbgrid: getmore: error calling db", ok);
- r.reply( response , "" /*conn->getServerAddress() */ );
+ bool hasMore = (response.singleData()->getCursor() != 0);
+
+ if ( !hasMore ) {
+ cursorCache.removeRef( id );
+ }
+
+ r.reply( response , "" /*conn->getServerAddress() */ );
conn->done();
return;
}
diff --git a/src/mongo/scripting/engine_spidermonkey.cpp b/src/mongo/scripting/engine_spidermonkey.cpp
index 1a0cd117155..e39734305a2 100644
--- a/src/mongo/scripting/engine_spidermonkey.cpp
+++ b/src/mongo/scripting/engine_spidermonkey.cpp
@@ -1071,11 +1071,25 @@ namespace spidermonkey {
JSBool native_helper( JSContext *cx , JSObject *obj , uintN argc, jsval *argv , jsval *rval ) {
try {
Convertor c(cx);
- NativeFunction func = reinterpret_cast<NativeFunction>(
- static_cast<long long>( c.getNumber( obj , "x" ) ) );
- void* data = reinterpret_cast<void*>(
- static_cast<long long>( c.getNumber( obj , "y" ) ) );
- verify( func );
+
+ // get function pointer from JS caller's argument property 'x'
+ massert(16740, "nativeHelper argument requires object with 'x' property",
+ c.hasProperty(obj, "x"));
+ FunctionMap::iterator funcIter = currentScope->_functionMap.find(c.getNumber(obj, "x"));
+ massert(16742, "JavaScript function not in map",
+ funcIter != currentScope->_functionMap.end());
+ NativeFunction func = funcIter->second;
+ verify(func);
+
+ // get data pointer from JS caller's argument property 'y'
+ void* data = NULL;
+ if (c.hasProperty(obj, "y")) {
+ ArgumentMap::iterator argIter =
+ currentScope->_argumentMap.find(c.getNumber(obj, "y"));
+ massert(16741, "nativeHelper 'y' parameter must be in the argumentMap",
+ argIter != currentScope->_argumentMap.end());
+ data = argIter->second;
+ }
BSONObj a;
if ( argc > 0 ) {
@@ -1725,12 +1739,16 @@ namespace spidermonkey {
smlock;
string name = field;
jsval v;
- v = _convertor->toval( static_cast<double>( reinterpret_cast<long long>(func) ) );
+ uint32_t funcId = _functionMap.size();
+ _functionMap.insert(make_pair(funcId, func));
+ v = _convertor->toval(static_cast<double>(funcId));
_convertor->setProperty( _global, (name + "_").c_str(), v );
stringstream code;
if (data) {
- v = _convertor->toval( static_cast<double>( reinterpret_cast<long long>(data) ) );
+ uint32_t argsId = _argumentMap.size();
+ _argumentMap.insert(make_pair(argsId, data));
+ v = _convertor->toval(static_cast<double>(argsId));
_convertor->setProperty( _global, (name + "_data_").c_str(), v );
code << field << "_" << " = { x : " << field << "_ , y: " << field << "_data_ }; ";
} else {
diff --git a/src/mongo/scripting/engine_spidermonkey_internal.h b/src/mongo/scripting/engine_spidermonkey_internal.h
index 26d772c84f7..5b31db677a6 100644
--- a/src/mongo/scripting/engine_spidermonkey_internal.h
+++ b/src/mongo/scripting/engine_spidermonkey_internal.h
@@ -47,6 +47,9 @@ namespace spidermonkey {
using std::string;
+ typedef std::map<uint32_t, NativeFunction> FunctionMap;
+ typedef std::map<uint32_t, void*> ArgumentMap;
+
string trim( string s );
class BSONFieldIterator;
@@ -295,6 +298,11 @@ namespace spidermonkey {
JSContext *SavedContext() const { return _context; }
+ // map from internal function id to function pointer
+ FunctionMap _functionMap;
+ // map from internal function argument id to function pointer
+ ArgumentMap _argumentMap;
+
private:
void _postCreateHacks();
diff --git a/src/mongo/scripting/engine_v8.cpp b/src/mongo/scripting/engine_v8.cpp
index f5adc04fd67..484b748b975 100644
--- a/src/mongo/scripting/engine_v8.cpp
+++ b/src/mongo/scripting/engine_v8.cpp
@@ -17,6 +17,7 @@
#include "mongo/scripting/engine_v8.h"
+#include "mongo/platform/unordered_set.h"
#include "mongo/scripting/v8_db.h"
#include "mongo/scripting/v8_utils.h"
#include "mongo/util/base64.h"
@@ -52,10 +53,15 @@ namespace mongo {
return (BSONHolder*)ptr;
}
+ static v8::Handle<v8::Object> unwrapObject(const v8::Handle<v8::Object>& obj) {
+ return obj->GetInternalField(1).As<v8::Object>();
+ }
+
v8::Persistent<v8::Object> V8Scope::wrapBSONObject(v8::Local<v8::Object> obj,
BSONHolder* data) {
data->_scope = this;
- obj->SetInternalField(0, v8::External::New(data));
+ obj->SetInternalField(0, v8::External::New(data)); // Holder
+ obj->SetInternalField(1, v8::Object::New()); // Object
v8::Persistent<v8::Object> p = v8::Persistent<v8::Object>::New(obj);
bsonHolderTracker.track(p, data);
return p;
@@ -66,9 +72,10 @@ namespace mongo {
v8::HandleScope handle_scope;
v8::Handle<v8::Value> val;
try {
- if (info.This()->HasRealNamedProperty(name)) {
- // value already cached
- return handle_scope.Close(info.This()->GetRealNamedProperty(name));
+ v8::Handle<v8::Object> realObject = unwrapObject(info.Holder());
+ if (realObject->HasOwnProperty(name)) {
+ // value already cached or added
+ return handle_scope.Close(realObject->Get(name));
}
string key = toSTLString(name);
@@ -83,8 +90,12 @@ namespace mongo {
v8::Local<v8::External> scp = v8::External::Cast(*info.Data());
V8Scope* scope = (V8Scope*)(scp->Value());
- val = scope->mongoToV8Element(elmt, false);
- info.This()->ForceSet(name, val, v8::DontEnum);
+ val = scope->mongoToV8Element(elmt, holder->_readOnly);
+
+ if (obj.objsize() > 128 || val->IsObject()) {
+ // Only cache if expected to help (large BSON) or is required due to js semantics
+ realObject->Set(name, val);
+ }
if (elmt.type() == mongo::Object || elmt.type() == mongo::Array) {
// if accessing a subobject, it may get modified and base obj would not know
@@ -103,6 +114,9 @@ namespace mongo {
static v8::Handle<v8::Value> namedGetRO(v8::Local<v8::String> name,
const v8::AccessorInfo &info) {
+ return namedGet(name, info);
+ // Rest of function is unused but left in to ease backporting of SERVER-9267
+
v8::HandleScope handle_scope;
v8::Handle<v8::Value> val;
string key = toSTLString(name);
@@ -130,25 +144,25 @@ namespace mongo {
string key = toSTLString(name);
BSONHolder* holder = unwrapHolder(info.Holder());
holder->_removed.erase(key);
- holder->_extra.push_back(key);
holder->_modified = true;
- // set into JS object
- return v8::Handle<v8::Value>();
+ v8::Handle<v8::Object> realObject = unwrapObject(info.Holder());
+ realObject->Set(name, value_obj);
+ return value_obj;
}
static v8::Handle<v8::Array> namedEnumerator(const v8::AccessorInfo &info) {
v8::HandleScope handle_scope;
BSONHolder* holder = unwrapHolder(info.Holder());
BSONObj obj = holder->_obj;
- v8::Handle<v8::Array> arr = v8::Handle<v8::Array>(v8::Array::New(obj.nFields()));
- int i = 0;
+ v8::Handle<v8::Array> out = v8::Array::New();
+ int outIndex = 0;
v8::Local<v8::External> scp = v8::External::Cast(*info.Data());
V8Scope* scope = (V8Scope*)(scp->Value());
- set<string> added;
+ unordered_set<string> added;
// note here that if keys are parseable number, v8 will access them using index
- for (BSONObjIterator it(obj); it.more(); ++i) {
+ for (BSONObjIterator it(obj); it.more();) {
const BSONElement& f = it.next();
string sname = f.fieldName();
if (holder->_removed.count(sname))
@@ -156,17 +170,21 @@ namespace mongo {
v8::Handle<v8::String> name = scope->v8StringData(sname);
added.insert(sname);
- arr->Set(i, name);
+ out->Set(outIndex++, name);
}
- for (list<string>::iterator it = holder->_extra.begin();
- it != holder->_extra.end(); it++) {
- string sname = *it;
+
+ v8::Handle<v8::Object> realObject = unwrapObject(info.Holder());
+ v8::Handle<v8::Array> fields = realObject->GetOwnPropertyNames();
+ const int len = fields->Length();
+ for (int field=0; field < len; field++) {
+ v8::Handle<v8::String> name = fields->Get(field).As<v8::String>();
+ string sname = toSTLString(name);
if (added.count(sname))
continue;
- arr->Set(i++, scope->v8StringData(sname));
+ out->Set(outIndex++, name);
}
- return handle_scope.Close(arr);
+ return handle_scope.Close(out);
}
v8::Handle<v8::Boolean> namedDelete(v8::Local<v8::String> name, const v8::AccessorInfo& info) {
@@ -174,26 +192,25 @@ namespace mongo {
string key = toSTLString(name);
BSONHolder* holder = unwrapHolder(info.Holder());
holder->_removed.insert(key);
- holder->_extra.remove(key);
holder->_modified = true;
- // also delete in JS obj
- return handle_scope.Close(v8::Handle<v8::Boolean>());
+ v8::Handle<v8::Object> realObject = unwrapObject(info.Holder());
+ realObject->Delete(name);
+ return v8::True();
}
static v8::Handle<v8::Value> indexedGet(uint32_t index, const v8::AccessorInfo &info) {
v8::HandleScope handle_scope;
v8::Handle<v8::Value> val;
try {
+ v8::Handle<v8::Object> realObject = unwrapObject(info.Holder());
+ if (realObject->Has(index)) {
+ // value already cached or added
+ return handle_scope.Close(realObject->Get(index));
+ }
string key = str::stream() << index;
v8::Local<v8::External> scp = v8::External::Cast(*info.Data());
V8Scope* scope = (V8Scope*)(scp->Value());
- v8::Handle<v8::String> name = scope->v8StringData(key);
-
- if (info.This()->HasRealIndexedProperty(index)) {
- // value already cached
- return handle_scope.Close(info.This()->GetRealNamedProperty(name));
- }
BSONHolder* holder = unwrapHolder(info.Holder());
if (holder->_removed.count(key))
@@ -203,8 +220,8 @@ namespace mongo {
BSONElement elmt = obj.getField(key);
if (elmt.eoo())
return handle_scope.Close(v8::Handle<v8::Value>());
- val = scope->mongoToV8Element(elmt, false);
- info.This()->ForceSet(name, val, v8::DontEnum);
+ val = scope->mongoToV8Element(elmt, holder->_readOnly);
+ realObject->Set(index, val);
if (elmt.type() == mongo::Object || elmt.type() == mongo::Array) {
// if accessing a subobject, it may get modified and base obj would not know
@@ -226,14 +243,18 @@ namespace mongo {
string key = str::stream() << index;
BSONHolder* holder = unwrapHolder(info.Holder());
holder->_removed.insert(key);
- holder->_extra.remove(key);
holder->_modified = true;
// also delete in JS obj
- return v8::Handle<v8::Boolean>();
+ v8::Handle<v8::Object> realObject = unwrapObject(info.Holder());
+ realObject->Delete(index);
+ return v8::True();
}
static v8::Handle<v8::Value> indexedGetRO(uint32_t index, const v8::AccessorInfo &info) {
+ return indexedGet(index, info);
+ // Rest of function is unused but left in-place to ease backporting of SERVER-9267
+
v8::HandleScope handle_scope;
v8::Handle<v8::Value> val;
try {
@@ -265,11 +286,11 @@ namespace mongo {
string key = str::stream() << index;
BSONHolder* holder = unwrapHolder(info.Holder());
holder->_removed.erase(key);
- holder->_extra.push_back(key);
holder->_modified = true;
- // set into JS object
- return v8::Handle<v8::Value>();
+ v8::Handle<v8::Object> realObject = unwrapObject(info.Holder());
+ realObject->Set(index, value_obj);
+ return value_obj;
}
v8::Handle<v8::Value> NamedReadOnlySet(v8::Local<v8::String> property,
@@ -298,6 +319,15 @@ namespace mongo {
return v8::Boolean::New(false);
}
+ /**
+ * GC Prologue and Epilogue constants (used to display description constants)
+ */
+ struct GCPrologueState { static const char* name; };
+ const char* GCPrologueState::name = "prologue";
+ struct GCEpilogueState { static const char* name; };
+ const char* GCEpilogueState::name = "epilogue";
+
+ template <typename _GCState>
void gcCallback(v8::GCType type, v8::GCCallbackFlags flags) {
const int verbosity = 1; // log level for stat collection
if (logLevel < verbosity)
@@ -306,12 +336,13 @@ namespace mongo {
v8::HeapStatistics stats;
v8::V8::GetHeapStatistics(&stats);
- LOG(verbosity) << "V8 GC heap stats - "
- << " total: " << stats.total_heap_size()
- << " exec: " << stats.total_heap_size_executable()
- << " used: " << stats.used_heap_size()<< " limit: "
- << stats.heap_size_limit()
- << endl;
+ log() << "V8 GC " << _GCState::name
+ << " heap stats - "
+ << " total: " << stats.total_heap_size()
+ << " exec: " << stats.total_heap_size_executable()
+ << " used: " << stats.used_heap_size()<< " limit: "
+ << stats.heap_size_limit()
+ << endl;
}
V8ScriptEngine::V8ScriptEngine() :
@@ -455,12 +486,6 @@ namespace mongo {
_isolate = v8::Isolate::New();
v8::Isolate::Scope iscope(_isolate);
- // resource constraints must be set on isolate, before any call or lock
- v8::ResourceConstraints rc;
- rc.set_max_young_space_size(4 * 1024 * 1024);
- rc.set_max_old_space_size(64 * 1024 * 1024);
- v8::SetResourceConstraints(&rc);
-
// lock the isolate and enter the context
v8::Locker l(_isolate);
v8::HandleScope handleScope;
@@ -468,7 +493,8 @@ namespace mongo {
v8::Context::Scope context_scope(_context);
// display heap statistics on MarkAndSweep GC run
- v8::V8::AddGCPrologueCallback(gcCallback, v8::kGCTypeMarkSweepCompact);
+ v8::V8::AddGCPrologueCallback(gcCallback<GCPrologueState>, v8::kGCTypeMarkSweepCompact);
+ v8::V8::AddGCEpilogueCallback(gcCallback<GCEpilogueState>, v8::kGCTypeMarkSweepCompact);
// if the isolate runs out of heap space, raise a flag on the StackGuard instead of
// calling abort()
@@ -479,7 +505,7 @@ namespace mongo {
// initialize lazy object template
lzObjectTemplate = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
- lzObjectTemplate->SetInternalFieldCount(1);
+ lzObjectTemplate->SetInternalFieldCount(2);
lzObjectTemplate->SetNamedPropertyHandler(namedGet, namedSet, 0, namedDelete,
namedEnumerator, v8::External::New(this));
lzObjectTemplate->SetIndexedPropertyHandler(indexedGet, indexedSet, 0, indexedDelete,
@@ -490,7 +516,7 @@ namespace mongo {
v8::DontEnum);
roObjectTemplate = v8::Persistent<v8::ObjectTemplate>::New(v8::ObjectTemplate::New());
- roObjectTemplate->SetInternalFieldCount(1);
+ roObjectTemplate->SetInternalFieldCount(2);
roObjectTemplate->SetNamedPropertyHandler(namedGetRO, NamedReadOnlySet, 0,
NamedReadOnlyDelete, namedEnumerator,
v8::External::New(this));
@@ -1250,188 +1276,13 @@ namespace mongo {
return handle_scope.Close(idCons->NewInstance(1, argv));
}
- v8::Local<v8::Object> V8Scope::mongoToV8(const BSONObj& m, bool array, bool readOnly) {
- v8::HandleScope handle_scope;
- v8::Handle<v8::Value> argv[3]; // arguments for v8 instance constructors
- v8::Local<v8::ObjectTemplate> readOnlyObjects;
- v8::Local<v8::Object> o;
-
- // handle DBRef. needs to come first. isn't it? (metagoto)
- static string ref = "$ref";
- if (ref == m.firstElement().fieldName()) {
- const BSONElement& id = m["$id"];
- if (!id.eoo()) { // there's no check on $id exitence in sm implementation. risky ?
- v8::Function* dbRef = getNamedCons("DBRef");
- o = dbRef->NewInstance();
- }
- }
-
- if (!o.IsEmpty()) {
- readOnly = false;
- }
- else if (array) {
- // NOTE Looks like it's impossible to add interceptors to v8 arrays.
- // so array itself will never be read only, but its values can be
- o = v8::Array::New();
- }
- else if (!readOnly) {
- o = v8::Object::New();
- }
- else {
- // NOTE Our readOnly implemention relies on undocumented ObjectTemplate
- // functionality that may be fragile, but it still seems like the best option
- // for now -- fwiw, the v8 docs are pretty sparse. I've determined experimentally
- // that when property handlers are set for an object template, they will attach
- // to objects previously created by that template. To get this to work, though,
- // it is necessary to initialize the template's property handlers before
- // creating objects from the template (as I have in the following few lines
- // of code).
- // NOTE In my first attempt, I configured the permanent property handlers before
- // constructiong the object and replaced the Set() calls below with ForceSet().
- // However, it turns out that ForceSet() only bypasses handlers for named
- // properties and not for indexed properties.
- readOnlyObjects = v8::ObjectTemplate::New();
- // NOTE This internal field will store type info for special db types. For
- // regular objects the field is unnecessary - for simplicity I'm creating just
- // one readOnlyObjects template for objects where the field is & isn't necessary,
- // assuming that the overhead of an internal field is slight.
- readOnlyObjects->SetInternalFieldCount(1);
- readOnlyObjects->SetNamedPropertyHandler(0);
- readOnlyObjects->SetIndexedPropertyHandler(0);
- o = readOnlyObjects->NewInstance();
- }
-
- mongo::BSONObj sub;
-
- for (BSONObjIterator i(m); i.more();) {
- const BSONElement& f = i.next();
-
- v8::Local<v8::Value> v;
- v8::Handle<v8::String> name = v8StringData(f.fieldName());
-
- switch (f.type()) {
- case mongo::Code:
- o->ForceSet(name, newFunction(f.valuestr()));
- break;
- case CodeWScope:
- if (!f.codeWScopeObject().isEmpty())
- log() << "warning: CodeWScope doesn't transfer to db.eval" << endl;
- o->ForceSet(name, newFunction(f.codeWScopeCode()));
- break;
- case mongo::String:
- o->ForceSet(name, v8::String::New(f.valuestr()));
- break;
- case mongo::jstOID: {
- v8::Function * idCons = getObjectIdCons();
- argv[0] = v8::String::New(f.__oid().str().c_str());
- o->ForceSet(name, idCons->NewInstance(1, argv));
- break;
- }
- case mongo::NumberDouble:
- case mongo::NumberInt:
- o->ForceSet(name, v8::Number::New(f.number()));
- break;
- case mongo::Array:
- sub = f.embeddedObject();
- o->ForceSet(name, mongoToV8(sub, true, readOnly));
- break;
- case mongo::Object:
- sub = f.embeddedObject();
- o->ForceSet(name, mongoToLZV8(sub, readOnly));
- break;
- case mongo::Date:
- o->ForceSet(name, v8::Date::New((double) ((long long)f.date().millis)));
- break;
- case mongo::Bool:
- o->ForceSet(name, v8::Boolean::New(f.boolean()));
- break;
- case mongo::jstNULL:
- case mongo::Undefined: // duplicate sm behavior
- o->ForceSet(name, v8::Null());
- break;
- case mongo::RegEx: {
- v8::Function * regex = getNamedCons("RegExp");
- argv[0] = v8::String::New(f.regex());
- argv[1] = v8::String::New(f.regexFlags());
- o->ForceSet(name, regex->NewInstance(2, argv));
- break;
- }
- case mongo::BinData: {
- int len;
- const char *data = f.binData(len);
- stringstream ss;
- base64::encode(ss, data, len);
- argv[0] = v8::Number::New(f.binDataType());
- argv[1] = v8::String::New(ss.str().c_str());
- o->ForceSet(name, getNamedCons("BinData")->NewInstance(2, argv));
- break;
- }
- case mongo::Timestamp: {
- v8::Local<v8::Object> sub = readOnly ? readOnlyObjects->NewInstance() :
- internalFieldObjects->NewInstance();
- sub->ForceSet(v8::String::New("t"), v8::Number::New(f.timestampTime() / 1000));
- sub->ForceSet(v8::String::New("i"), v8::Number::New(f.timestampInc()));
- sub->SetInternalField(0, v8::Uint32::New(f.type()));
- o->ForceSet(name, sub);
- break;
- }
- case mongo::NumberLong: {
- unsigned long long val = f.numberLong();
- v8::Function* numberLong = getNamedCons("NumberLong");
- double floatApprox = (double)(long long)val;
- // values above 2^53 are not accurately represented in JS
- if ((long long)val == (long long)floatApprox && val < 9007199254740992ULL) {
- argv[0] = v8::Number::New(floatApprox);
- o->ForceSet(name, numberLong->NewInstance(1, argv));
- }
- else {
- argv[0] = v8::Number::New(floatApprox);
- argv[1] = v8::Integer::New(val >> 32);
- argv[2] = v8::Integer::New((unsigned long)(val & 0x00000000ffffffff));
- o->ForceSet(name, numberLong->NewInstance(3, argv));
- }
- break;
- }
- case mongo::MinKey: {
- o->ForceSet(name, newMinKeyInstance());
- break;
- }
- case mongo::MaxKey: {
- o->ForceSet(name, newMaxKeyInstance());
- break;
- }
- case mongo::DBRef: {
- v8::Function* dbPointer = getNamedCons("DBPointer");
- argv[0] = v8StringData(f.dbrefNS());
- argv[1] = newId(f.dbrefOID());
- o->ForceSet(name, dbPointer->NewInstance(2, argv));
- break;
- }
- default:
- cout << "can't handle type: ";
- cout << f.type() << " ";
- cout << f.toString();
- cout << endl;
- break;
- }
- }
-
- if (!array && readOnly) {
- readOnlyObjects->SetNamedPropertyHandler(0, NamedReadOnlySet,
- 0, NamedReadOnlyDelete);
- readOnlyObjects->SetIndexedPropertyHandler(0, IndexedReadOnlySet,
- 0, IndexedReadOnlyDelete);
- }
-
- return handle_scope.Close(o);
- }
-
/**
* converts a BSONObj to a Lazy V8 object
*/
v8::Persistent<v8::Object> V8Scope::mongoToLZV8(const BSONObj& m, bool readOnly) {
v8::Local<v8::Object> o;
BSONHolder* own = new BSONHolder(m);
+ own->_readOnly = readOnly;
if (readOnly) {
o = roObjectTemplate->NewInstance();
@@ -1519,6 +1370,7 @@ namespace mongo {
if (!elem.codeWScopeObject().isEmpty())
log() << "warning: CodeWScope doesn't transfer to db.eval" << endl;
return newFunction(elem.codeWScopeCode());
+ case mongo::Symbol:
case mongo::String:
return v8::String::New(elem.valuestr());
case mongo::jstOID:
@@ -1526,14 +1378,22 @@ namespace mongo {
case mongo::NumberDouble:
case mongo::NumberInt:
return v8::Number::New(elem.number());
- case mongo::Array:
+ case mongo::Array: {
// NB: This comment may no longer be accurate.
// for arrays it's better to use non lazy object because:
// - the lazy array is not a true v8 array and requires some v8 src change
// for all methods to work
// - it made several tests about 1.5x slower
// - most times when an array is accessed, all its values will be used
- return mongoToV8(elem.embeddedObject(), true, readOnly);
+
+ // It is faster to allow the v8::Array to grow than call nFields() on the array
+ v8::Handle<v8::Array> array = v8::Array::New();
+ int i = 0;
+ BSONForEach(subElem, elem.embeddedObject()) {
+ array->Set(i++, mongoToV8Element(subElem, readOnly));
+ }
+ return array;
+ }
case mongo::Object:
return mongoToLZV8(elem.embeddedObject(), readOnly);
case mongo::Date:
@@ -1745,8 +1605,14 @@ namespace mongo {
return;
}
if (value->IsArray()) {
- BSONObj sub = v8ToMongo(value->ToObject(), depth);
- b.appendArray(sname, sub);
+ // Note: can't use BSONArrayBuilder because need to call recursively
+ BSONObjBuilder arrBuilder(b.subarrayStart(sname));
+ v8::Handle<v8::Array> array = value.As<v8::Array>();
+ const int len = array->Length();
+ for (int i=0; i < len; i++) {
+ const string name = BSONObjBuilder::numStr(i);
+ v8ToMongoElement(arrBuilder, name, array->Get(i), depth+1, originalParent);
+ }
return;
}
if (value->IsDate()) {
diff --git a/src/mongo/scripting/engine_v8.h b/src/mongo/scripting/engine_v8.h
index 1406da51cac..b86d063afae 100644
--- a/src/mongo/scripting/engine_v8.h
+++ b/src/mongo/scripting/engine_v8.h
@@ -63,17 +63,18 @@ namespace mongo {
*/
void track(v8::Persistent<v8::Value> instanceHandle, _ObjType* instance) {
TrackedPtr* collectionHandle = new TrackedPtr(instance, this);
+ _container.insert(collectionHandle);
instanceHandle.MakeWeak(collectionHandle, deleteOnCollect);
}
/**
- * Free any remaining objects which are being tracked. Invoked when
- * the V8Scope is destructed.
+ * Free any remaining objects and their TrackedPtrs. Invoked when the
+ * V8Scope is destructed.
*/
~ObjTracker() {
if (!_container.empty())
LOG(1) << "freeing " << _container.size() << " uncollected "
<< typeid(_ObjType).name() << " objects" << endl;
- typename set<_ObjType*>::iterator it = _container.begin();
+ typename set<TrackedPtr*>::iterator it = _container.begin();
while (it != _container.end()) {
delete *it;
_container.erase(it++);
@@ -90,7 +91,7 @@ namespace mongo {
TrackedPtr(_ObjType* instance, ObjTracker<_ObjType>* tracker) :
_objPtr(instance),
_tracker(tracker) { }
- _ObjType* _objPtr;
+ scoped_ptr<_ObjType> _objPtr;
ObjTracker<_ObjType>* _tracker;
};
@@ -102,14 +103,13 @@ namespace mongo {
*/
static void deleteOnCollect(v8::Persistent<v8::Value> instanceHandle, void* rawData) {
TrackedPtr* trackedPtr = static_cast<TrackedPtr*>(rawData);
- trackedPtr->_tracker->_container.erase(trackedPtr->_objPtr);
- delete trackedPtr->_objPtr;
+ trackedPtr->_tracker->_container.erase(trackedPtr);
delete trackedPtr;
instanceHandle.Dispose();
}
- // container for all instances of the tracked _ObjType
- set<_ObjType*> _container;
+ // container for all TrackedPtrs created by this ObjTracker instance
+ set<TrackedPtr*> _container;
};
/**
@@ -213,8 +213,6 @@ namespace mongo {
/**
* Convert BSON types to v8 Javascript types
*/
- v8::Local<v8::Object> mongoToV8(const mongo::BSONObj& m, bool array = 0,
- bool readOnly = false);
v8::Persistent<v8::Object> mongoToLZV8(const mongo::BSONObj& m, bool readOnly = false);
v8::Handle<v8::Value> mongoToV8Element(const BSONElement& f, bool readOnly = false);
@@ -447,7 +445,7 @@ namespace mongo {
V8Scope* _scope;
BSONObj _obj;
bool _modified;
- list<string> _extra;
+ bool _readOnly;
set<string> _removed;
};
diff --git a/src/mongo/shell/db.js b/src/mongo/shell/db.js
index edfdcbb7ee1..c343f9b6615 100644
--- a/src/mongo/shell/db.js
+++ b/src/mongo/shell/db.js
@@ -435,7 +435,7 @@ DB.prototype.repairDatabase = function() {
DB.prototype.help = function() {
print("DB methods:");
- print("\tdb.addUser(username, password[, readOnly=false])");
+ print("\tdb.addUser(userDocument)");
print("\tdb.adminCommand(nameOrDocument) - switches to 'admin' db, and runs command [ just calls db.runCommand(...) ]");
print("\tdb.auth(username, password)");
print("\tdb.cloneDatabase(fromhost)");
@@ -761,7 +761,7 @@ DB.prototype.killOP = DB.prototype.killOp;
DB.tsToSeconds = function(x){
if ( x.t && x.i )
- return x.t / 1000;
+ return x.t;
return x / 4294967296; // low 32 bits are ordinal #s within a second
}
diff --git a/src/mongo/shell/types.js b/src/mongo/shell/types.js
index 681c7deadb0..3c5cfa8622b 100644
--- a/src/mongo/shell/types.js
+++ b/src/mongo/shell/types.js
@@ -600,7 +600,11 @@ tojsonObject = function(x, indent, nolint){
var num = 1;
for (var k in keys){
var val = x[k];
- if (val == DB.prototype || val == DBCollection.prototype)
+
+ // skip internal DB types to avoid issues with interceptors
+ if (typeof DB != 'undefined' && val == DB.prototype)
+ continue;
+ if (typeof DBCollection != 'undefined' && val == DBCollection.prototype)
continue;
s += indent + "\"" + k + "\" : " + tojson(val, indent, nolint);
diff --git a/src/mongo/tools/restore.cpp b/src/mongo/tools/restore.cpp
index 35daa4c6f4d..e660bb541a4 100644
--- a/src/mongo/tools/restore.cpp
+++ b/src/mongo/tools/restore.cpp
@@ -459,7 +459,6 @@ private:
int objSize;
BSONObj obj;
obj = fromjson (buf.get(), &objSize);
- uassert(15934, "JSON object size didn't match file size", objSize == fileSize);
return obj;
}
diff --git a/src/mongo/tools/stat.cpp b/src/mongo/tools/stat.cpp
index 9dc436d087d..07194444671 100644
--- a/src/mongo/tools/stat.cpp
+++ b/src/mongo/tools/stat.cpp
@@ -360,7 +360,7 @@ namespace mongo {
(int)ceil(_statUtil.getSeconds()) ) ) );
state->authParams = BSON( "user" << _username <<
"pwd" << _password <<
- "userSource" << _authenticationDatabase <<
+ "userSource" << getAuthenticationDatabase() <<
"mechanism" << _authenticationMechanism );
return true;
}
diff --git a/src/mongo/tools/tool.cpp b/src/mongo/tools/tool.cpp
index dfa20f2c8ea..c2728b88af0 100644
--- a/src/mongo/tools/tool.cpp
+++ b/src/mongo/tools/tool.cpp
@@ -270,7 +270,7 @@ namespace mongo {
int ret = -1;
try {
- if (!useDirectClient)
+ if (!useDirectClient && !_noconnection)
auth();
ret = run();
}
@@ -406,6 +406,18 @@ namespace mongo {
throw UserException( 9998 , "you need to specify fields" );
}
+ std::string Tool::getAuthenticationDatabase() {
+ if (!_authenticationDatabase.empty()) {
+ return _authenticationDatabase;
+ }
+
+ if (!_db.empty()) {
+ return _db;
+ }
+
+ return "admin";
+ }
+
/**
* Validate authentication on the server for the given dbname.
*/
@@ -422,17 +434,7 @@ namespace mongo {
return;
}
- std::string userSource = _authenticationDatabase;
- if ( userSource.empty() ) {
- if ( !_db.empty() ) {
- userSource = _db;
- }
- else {
- userSource = "admin";
- }
- }
-
- _conn->auth( BSON( saslCommandPrincipalSourceFieldName << userSource <<
+ _conn->auth( BSON( saslCommandPrincipalSourceFieldName << getAuthenticationDatabase() <<
saslCommandPrincipalFieldName << _username <<
saslCommandPasswordFieldName << _password <<
saslCommandMechanismFieldName << _authenticationMechanism ) );
diff --git a/src/mongo/tools/tool.h b/src/mongo/tools/tool.h
index 4820ef45c1e..2e7b0823d62 100644
--- a/src/mongo/tools/tool.h
+++ b/src/mongo/tools/tool.h
@@ -81,6 +81,8 @@ namespace mongo {
return _db + "." + _coll;
}
+ string getAuthenticationDatabase();
+
void useStandardOutput( bool mode ) {
_usesstdout = mode;
}
diff --git a/src/mongo/util/assert_util.h b/src/mongo/util/assert_util.h
index 1c783cee05f..1a2f4fb1967 100644
--- a/src/mongo/util/assert_util.h
+++ b/src/mongo/util/assert_util.h
@@ -28,9 +28,11 @@
namespace mongo {
enum CommonErrorCodes {
- DatabaseDifferCaseCode = 13297 ,
- SendStaleConfigCode = 13388 ,
- RecvStaleConfigCode = 9996
+ OkCode = 0,
+ DatabaseDifferCaseCode = 13297 , // uassert( 13297 )
+ SendStaleConfigCode = 13388 , // uassert( 13388 )
+ RecvStaleConfigCode = 9996, // uassert( 9996 )
+ PrepareConfigsFailedCode = 13104 // uassert( 13104 )
};
class AssertionCount {
diff --git a/src/mongo/util/version.cpp b/src/mongo/util/version.cpp
index 2136a70c35e..609fa4afd35 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.1";
+ const char versionString[] = "2.4.2";
// See unit test for example outputs
BSONArray toVersionArray(const char* version){
@@ -227,27 +227,24 @@ namespace mongo {
std::ifstream f("/proc/self/numa_maps", std::ifstream::in);
if (f.is_open()) {
- char line[100]; //we only need the first line
- f.getline(line, sizeof(line));
+ std::string line; //we only need the first line
+ std::getline(f, line);
if (f.fail()) {
warning() << "failed to read from /proc/self/numa_maps: "
<< errnoWithDescription() << startupWarningsLog;
warned = true;
}
else {
- // just in case...
- line[98] = ' ';
- line[99] = '\0';
-
// skip over pointer
- const char* space = strchr(line, ' ');
-
- if ( ! space ) {
+ std::string::size_type where = line.find(' ');
+ if ( (where == std::string::npos) || (++where == line.size()) ) {
log() << startupWarningsLog;
- log() << "** WARNING: cannot parse numa_maps" << startupWarningsLog;
+ log() << "** WARNING: cannot parse numa_maps line: '" << line << "'" << startupWarningsLog;
warned = true;
}
- else if ( ! startsWith(space+1, "interleave") ) {
+ // if the text following the space doesn't begin with 'interleave', then
+ // issue the warning.
+ else if ( line.find("interleave", where) != where ) {
log() << startupWarningsLog;
log() << "** WARNING: You are running on a NUMA machine." << startupWarningsLog;
log() << "** We suggest launching mongod like this to avoid performance problems:" << startupWarningsLog;
diff --git a/src/third_party/pcre-8.30/config.status b/src/third_party/pcre-8.30/config.status
new file mode 100755
index 00000000000..b7e064fea3f
--- /dev/null
+++ b/src/third_party/pcre-8.30/config.status
@@ -0,0 +1,2365 @@
+#! /bin/sh
+# Generated by configure.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -p'
+ fi
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in #(
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by PCRE $as_me 8.30, which was
+generated by GNU Autoconf 2.68. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+# Files that config.status was made for.
+config_files=" Makefile libpcre.pc libpcre16.pc libpcreposix.pc libpcrecpp.pc pcre-config pcre.h pcre_stringpiece.h pcrecpparg.h"
+config_headers=" config.h"
+config_commands=" depfiles libtool script-chmod delete-old-chartables"
+
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+ac_cs_config=""
+ac_cs_version="\
+PCRE config.status 8.30
+configured by ./configure, generated by GNU Autoconf 2.68,
+ with options \"$ac_cs_config\"
+
+Copyright (C) 2010 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='/media/DATA0/data/m/3827/mongo/src/third_party/pcre-8.30'
+srcdir='.'
+INSTALL='/usr/bin/install -c'
+MKDIR_P='/bin/mkdir -p'
+AWK='gawk'
+test -n "$AWK" || AWK=awk
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+if $ac_cs_recheck; then
+ set X '/bin/sh' './configure' $ac_configure_extra_args --no-create --no-recursion
+ shift
+ $as_echo "running CONFIG_SHELL=/bin/sh $*" >&6
+ CONFIG_SHELL='/bin/sh'
+ export CONFIG_SHELL
+ exec "$@"
+fi
+
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="" ac_aux_dir="."
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+AS='as'
+DLLTOOL='dlltool'
+OBJDUMP='objdump'
+macro_version='2.4'
+macro_revision='1.3293'
+enable_shared='yes'
+enable_static='yes'
+pic_mode='default'
+enable_fast_install='yes'
+SHELL='/bin/sh'
+ECHO='printf %s\n'
+host_alias=''
+host='x86_64-unknown-linux-gnu'
+host_os='linux-gnu'
+build_alias=''
+build='x86_64-unknown-linux-gnu'
+build_os='linux-gnu'
+SED='/bin/sed'
+Xsed='/bin/sed -e 1s/^X//'
+GREP='/bin/grep'
+EGREP='/bin/grep -E'
+FGREP='/bin/grep -F'
+LD='/usr/bin/ld -m elf_x86_64'
+NM='/usr/bin/nm -B'
+LN_S='ln -s'
+max_cmd_len='1572864'
+ac_objext='o'
+exeext=''
+lt_unset='unset'
+lt_SP2NL='tr \040 \012'
+lt_NL2SP='tr \015\012 \040\040'
+lt_cv_to_host_file_cmd='func_convert_file_noop'
+lt_cv_to_tool_file_cmd='func_convert_file_noop'
+reload_flag=' -r'
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+deplibs_check_method='pass_all'
+file_magic_cmd='$MAGIC_CMD'
+file_magic_glob=''
+want_nocaseglob='no'
+sharedlib_from_linklib_cmd='printf %s\n'
+AR='ar'
+AR_FLAGS='cru'
+archiver_list_spec='@'
+STRIP='strip'
+RANLIB='ranlib'
+old_postinstall_cmds='chmod 644 $oldlib~$RANLIB $oldlib'
+old_postuninstall_cmds=''
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs~$RANLIB $oldlib'
+lock_old_archive_extraction='no'
+CC='gcc'
+CFLAGS='-O2'
+compiler='g++'
+GCC='yes'
+lt_cv_sys_global_symbol_pipe='sed -n -e '\''s/^.*[ ]\([ABCDGIRSTW][ABCDGIRSTW]*\)[ ][ ]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1 \2 \2/p'\'' | sed '\''/ __gnu_lto/d'\'''
+lt_cv_sys_global_symbol_to_cdecl='sed -n -e '\''s/^T .* \(.*\)$/extern int \1();/p'\'' -e '\''s/^[ABCDGIRSTW]* .* \(.*\)$/extern char \1;/p'\'''
+lt_cv_sys_global_symbol_to_c_name_address='sed -n -e '\''s/^: \([^ ]*\)[ ]*$/ {\"\1\", (void *) 0},/p'\'' -e '\''s/^[ABCDGIRSTW]* \([^ ]*\) \([^ ]*\)$/ {"\2", (void *) \&\2},/p'\'''
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='sed -n -e '\''s/^: \([^ ]*\)[ ]*$/ {\"\1\", (void *) 0},/p'\'' -e '\''s/^[ABCDGIRSTW]* \([^ ]*\) \(lib[^ ]*\)$/ {"\2", (void *) \&\2},/p'\'' -e '\''s/^[ABCDGIRSTW]* \([^ ]*\) \([^ ]*\)$/ {"lib\2", (void *) \&\2},/p'\'''
+nm_file_list_spec='@'
+lt_sysroot=''
+objdir='.libs'
+MAGIC_CMD='file'
+lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+lt_prog_compiler_pic=' -fPIC -DPIC'
+lt_prog_compiler_wl='-Wl,'
+lt_prog_compiler_static=''
+lt_cv_prog_compiler_c_o='yes'
+need_locks='no'
+MANIFEST_TOOL=':'
+DSYMUTIL=''
+NMEDIT=''
+LIPO=''
+OTOOL=''
+OTOOL64=''
+libext='a'
+shrext_cmds='.so'
+extract_expsyms_cmds=''
+archive_cmds_need_lc='no'
+enable_shared_with_static_runtimes='no'
+export_dynamic_flag_spec='${wl}--export-dynamic'
+whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+compiler_needs_object='no'
+old_archive_from_new_cmds=''
+old_archive_from_expsyms_cmds=''
+archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+module_cmds=''
+module_expsym_cmds=''
+with_gnu_ld='yes'
+allow_undefined_flag=''
+no_undefined_flag=''
+hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+hardcode_libdir_flag_spec_ld=''
+hardcode_libdir_separator=''
+hardcode_direct='no'
+hardcode_direct_absolute='no'
+hardcode_minus_L='no'
+hardcode_shlibpath_var='unsupported'
+hardcode_automatic='no'
+inherit_rpath='no'
+link_all_deplibs='unknown'
+always_export_symbols='no'
+export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+include_expsyms=''
+prelink_cmds=''
+postlink_cmds=''
+file_list_spec=''
+variables_saved_for_relink='PATH LD_LIBRARY_PATH LD_RUN_PATH GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH'
+need_lib_prefix='no'
+need_version='no'
+version_type='linux'
+runpath_var='LD_RUN_PATH'
+shlibpath_var='LD_LIBRARY_PATH'
+shlibpath_overrides_runpath='no'
+libname_spec='lib$name'
+library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+soname_spec='${libname}${release}${shared_ext}$major'
+install_override_mode=''
+postinstall_cmds=''
+postuninstall_cmds=''
+finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+finish_eval=''
+hardcode_into_libs='yes'
+sys_lib_search_path_spec='/usr/lib/gcc/x86_64-redhat-linux/4.6.2 /usr/lib64 /lib64 '
+sys_lib_dlsearch_path_spec='/lib /usr/lib /usr/lib64/atlas /usr/lib64/llvm /usr/lib64/tracker-0.12 /usr/lib64/xulrunner-2 '
+hardcode_action='immediate'
+enable_dlopen='unknown'
+enable_dlopen_self='unknown'
+enable_dlopen_self_static='unknown'
+old_striplib='strip --strip-debug'
+striplib='strip --strip-unneeded'
+compiler_lib_search_dirs=''
+predep_objects=''
+postdep_objects=''
+predeps=''
+postdeps=''
+compiler_lib_search_path=''
+LD_CXX='/usr/bin/ld -m elf_x86_64'
+reload_flag_CXX=' -r'
+reload_cmds_CXX='$LD$reload_flag -o $output$reload_objs'
+old_archive_cmds_CXX='$AR $AR_FLAGS $oldlib$oldobjs~$RANLIB $oldlib'
+compiler_CXX='g++'
+GCC_CXX='yes'
+lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+lt_prog_compiler_pic_CXX=' -fPIC -DPIC'
+lt_prog_compiler_wl_CXX='-Wl,'
+lt_prog_compiler_static_CXX=''
+lt_cv_prog_compiler_c_o_CXX='yes'
+archive_cmds_need_lc_CXX='no'
+enable_shared_with_static_runtimes_CXX='no'
+export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+compiler_needs_object_CXX='no'
+old_archive_from_new_cmds_CXX=''
+old_archive_from_expsyms_cmds_CXX=''
+archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+module_cmds_CXX=''
+module_expsym_cmds_CXX=''
+with_gnu_ld_CXX='yes'
+allow_undefined_flag_CXX=''
+no_undefined_flag_CXX=''
+hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+hardcode_libdir_flag_spec_ld_CXX=''
+hardcode_libdir_separator_CXX=''
+hardcode_direct_CXX='no'
+hardcode_direct_absolute_CXX='no'
+hardcode_minus_L_CXX='no'
+hardcode_shlibpath_var_CXX='unsupported'
+hardcode_automatic_CXX='no'
+inherit_rpath_CXX='no'
+link_all_deplibs_CXX='unknown'
+always_export_symbols_CXX='no'
+export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+include_expsyms_CXX=''
+prelink_cmds_CXX=''
+postlink_cmds_CXX=''
+file_list_spec_CXX=''
+hardcode_action_CXX='immediate'
+compiler_lib_search_dirs_CXX='/usr/lib/gcc/x86_64-redhat-linux/4.6.2 /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../lib64 /lib/../lib64 /usr/lib/../lib64 /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../..'
+predep_objects_CXX='/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.6.2/crtbeginS.o'
+postdep_objects_CXX='/usr/lib/gcc/x86_64-redhat-linux/4.6.2/crtendS.o /usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../lib64/crtn.o'
+predeps_CXX=''
+postdeps_CXX='-lstdc++ -lm -lgcc_s -lc -lgcc_s'
+compiler_lib_search_path_CXX='-L/usr/lib/gcc/x86_64-redhat-linux/4.6.2 -L/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.6.2/../../..'
+
+LTCC='gcc'
+LTCFLAGS='-O2'
+compiler='gcc'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in AS DLLTOOL OBJDUMP SHELL ECHO SED GREP EGREP FGREP LD NM LN_S lt_SP2NL lt_NL2SP reload_flag deplibs_check_method file_magic_cmd file_magic_glob want_nocaseglob sharedlib_from_linklib_cmd AR AR_FLAGS archiver_list_spec STRIP RANLIB CC CFLAGS compiler lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl lt_cv_sys_global_symbol_to_c_name_address lt_cv_sys_global_symbol_to_c_name_address_lib_prefix nm_file_list_spec lt_prog_compiler_no_builtin_flag lt_prog_compiler_pic lt_prog_compiler_wl lt_prog_compiler_static lt_cv_prog_compiler_c_o need_locks MANIFEST_TOOL DSYMUTIL NMEDIT LIPO OTOOL OTOOL64 shrext_cmds export_dynamic_flag_spec whole_archive_flag_spec compiler_needs_object with_gnu_ld allow_undefined_flag no_undefined_flag hardcode_libdir_flag_spec hardcode_libdir_flag_spec_ld hardcode_libdir_separator exclude_expsyms include_expsyms file_list_spec variables_saved_for_relink libname_spec library_names_spec soname_spec install_override_mode finish_eval old_striplib striplib compiler_lib_search_dirs predep_objects postdep_objects predeps postdeps compiler_lib_search_path LD_CXX reload_flag_CXX compiler_CXX lt_prog_compiler_no_builtin_flag_CXX lt_prog_compiler_pic_CXX lt_prog_compiler_wl_CXX lt_prog_compiler_static_CXX lt_cv_prog_compiler_c_o_CXX export_dynamic_flag_spec_CXX whole_archive_flag_spec_CXX compiler_needs_object_CXX with_gnu_ld_CXX allow_undefined_flag_CXX no_undefined_flag_CXX hardcode_libdir_flag_spec_CXX hardcode_libdir_flag_spec_ld_CXX hardcode_libdir_separator_CXX exclude_expsyms_CXX include_expsyms_CXX file_list_spec_CXX compiler_lib_search_dirs_CXX predep_objects_CXX postdep_objects_CXX predeps_CXX postdeps_CXX compiler_lib_search_path_CXX; do
+ case `eval \\$ECHO \\""\\$$var"\\"` in
+ *[\\\`\"\$]*)
+ eval "lt_$var=\\\"\`\$ECHO \"\$$var\" | \$SED \"\$sed_quote_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\$$var\\\""
+ ;;
+ esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds old_postinstall_cmds old_postuninstall_cmds old_archive_cmds extract_expsyms_cmds old_archive_from_new_cmds old_archive_from_expsyms_cmds archive_cmds archive_expsym_cmds module_cmds module_expsym_cmds export_symbols_cmds prelink_cmds postlink_cmds postinstall_cmds postuninstall_cmds finish_cmds sys_lib_search_path_spec sys_lib_dlsearch_path_spec reload_cmds_CXX old_archive_cmds_CXX old_archive_from_new_cmds_CXX old_archive_from_expsyms_cmds_CXX archive_cmds_CXX archive_expsym_cmds_CXX module_cmds_CXX module_expsym_cmds_CXX export_symbols_cmds_CXX prelink_cmds_CXX postlink_cmds_CXX; do
+ case `eval \\$ECHO \\""\\$$var"\\"` in
+ *[\\\`\"\$]*)
+ eval "lt_$var=\\\"\`\$ECHO \"\$$var\" | \$SED -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\$$var\\\""
+ ;;
+ esac
+done
+
+ac_aux_dir='.'
+xsi_shell='yes'
+lt_shell_append='yes'
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+
+
+ PACKAGE='pcre'
+ VERSION='8.30'
+ TIMESTAMP=''
+ RM='rm -f'
+ ofile='libtool'
+
+
+
+
+
+
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "libpcre.pc") CONFIG_FILES="$CONFIG_FILES libpcre.pc" ;;
+ "libpcre16.pc") CONFIG_FILES="$CONFIG_FILES libpcre16.pc" ;;
+ "libpcreposix.pc") CONFIG_FILES="$CONFIG_FILES libpcreposix.pc" ;;
+ "libpcrecpp.pc") CONFIG_FILES="$CONFIG_FILES libpcrecpp.pc" ;;
+ "pcre-config") CONFIG_FILES="$CONFIG_FILES pcre-config" ;;
+ "pcre.h") CONFIG_FILES="$CONFIG_FILES pcre.h" ;;
+ "pcre_stringpiece.h") CONFIG_FILES="$CONFIG_FILES pcre_stringpiece.h" ;;
+ "pcrecpparg.h") CONFIG_FILES="$CONFIG_FILES pcrecpparg.h" ;;
+ "script-chmod") CONFIG_COMMANDS="$CONFIG_COMMANDS script-chmod" ;;
+ "delete-old-chartables") CONFIG_COMMANDS="$CONFIG_COMMANDS delete-old-chartables" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+cat >>"$ac_tmp/subs1.awk" <<\_ACAWK &&
+S["am__EXEEXT_FALSE"]=""
+S["am__EXEEXT_TRUE"]="#"
+S["LTLIBOBJS"]=""
+S["LIBOBJS"]=""
+S["LIBBZ2"]=""
+S["LIBZ"]=""
+S["DISTCHECK_CONFIGURE_FLAGS"]="CFLAGS='' CXXFLAGS='' --enable-pcre16 --enable-jit --enable-cpp --enable-unicode-properties"
+S["EXTRA_LIBPCRECPP_LDFLAGS"]=" -version-info 0:0:0 "
+S["EXTRA_LIBPCREPOSIX_LDFLAGS"]=" -version-info 0:0:0"
+S["EXTRA_LIBPCRE16_LDFLAGS"]=" -version-info 0:0:0"
+S["EXTRA_LIBPCRE_LDFLAGS"]=" -version-info 1:0:0"
+S["PCRE_STATIC_CFLAG"]=""
+S["LIBREADLINE"]="-lreadline"
+S["WITH_UTF_FALSE"]=""
+S["WITH_UTF_TRUE"]="#"
+S["WITH_JIT_FALSE"]=""
+S["WITH_JIT_TRUE"]="#"
+S["WITH_REBUILD_CHARTABLES_FALSE"]=""
+S["WITH_REBUILD_CHARTABLES_TRUE"]="#"
+S["WITH_PCRE_CPP_FALSE"]="#"
+S["WITH_PCRE_CPP_TRUE"]=""
+S["WITH_PCRE16_FALSE"]=""
+S["WITH_PCRE16_TRUE"]="#"
+S["WITH_PCRE8_FALSE"]="#"
+S["WITH_PCRE8_TRUE"]=""
+S["pcre_have_bits_type_traits"]="0"
+S["pcre_have_type_traits"]="0"
+S["pcre_have_ulong_long"]="1"
+S["pcre_have_long_long"]="1"
+S["enable_cpp"]="yes"
+S["enable_pcre16"]="no"
+S["enable_pcre8"]="yes"
+S["PCRE_DATE"]="2012-02-04"
+S["PCRE_PRERELEASE"]=""
+S["PCRE_MINOR"]="30"
+S["PCRE_MAJOR"]="8"
+S["CXXCPP"]="g++ -E"
+S["OTOOL64"]=""
+S["OTOOL"]=""
+S["LIPO"]=""
+S["NMEDIT"]=""
+S["DSYMUTIL"]=""
+S["MANIFEST_TOOL"]=":"
+S["RANLIB"]="ranlib"
+S["ac_ct_AR"]="ar"
+S["AR"]="ar"
+S["LN_S"]="ln -s"
+S["NM"]="/usr/bin/nm -B"
+S["ac_ct_DUMPBIN"]=""
+S["DUMPBIN"]=""
+S["LD"]="/usr/bin/ld -m elf_x86_64"
+S["FGREP"]="/bin/grep -F"
+S["SED"]="/bin/sed"
+S["LIBTOOL"]="$(SHELL) $(top_builddir)/libtool"
+S["OBJDUMP"]="objdump"
+S["DLLTOOL"]="dlltool"
+S["AS"]="as"
+S["host_os"]="linux-gnu"
+S["host_vendor"]="unknown"
+S["host_cpu"]="x86_64"
+S["host"]="x86_64-unknown-linux-gnu"
+S["build_os"]="linux-gnu"
+S["build_vendor"]="unknown"
+S["build_cpu"]="x86_64"
+S["build"]="x86_64-unknown-linux-gnu"
+S["EGREP"]="/bin/grep -E"
+S["GREP"]="/bin/grep"
+S["CPP"]="gcc -E"
+S["am__fastdepCXX_FALSE"]="#"
+S["am__fastdepCXX_TRUE"]=""
+S["CXXDEPMODE"]="depmode=gcc3"
+S["ac_ct_CXX"]="g++"
+S["CXXFLAGS"]="-O2"
+S["CXX"]="g++"
+S["am__fastdepCC_FALSE"]="#"
+S["am__fastdepCC_TRUE"]=""
+S["CCDEPMODE"]="depmode=gcc3"
+S["AMDEPBACKSLASH"]="\\"
+S["AMDEP_FALSE"]="#"
+S["AMDEP_TRUE"]=""
+S["am__quote"]=""
+S["am__include"]="include"
+S["DEPDIR"]=".deps"
+S["OBJEXT"]="o"
+S["EXEEXT"]=""
+S["ac_ct_CC"]="gcc"
+S["CPPFLAGS"]=""
+S["LDFLAGS"]=""
+S["CFLAGS"]="-O2"
+S["CC"]="gcc"
+S["AM_BACKSLASH"]="\\"
+S["AM_DEFAULT_VERBOSITY"]="0"
+S["am__untar"]="${AMTAR} xf -"
+S["am__tar"]="${AMTAR} chof - \"$$tardir\""
+S["AMTAR"]="${SHELL} /media/DATA0/data/m/3827/mongo/src/third_party/pcre-8.30/missing --run tar"
+S["am__leading_dot"]="."
+S["SET_MAKE"]=""
+S["AWK"]="gawk"
+S["mkdir_p"]="/bin/mkdir -p"
+S["MKDIR_P"]="/bin/mkdir -p"
+S["INSTALL_STRIP_PROGRAM"]="$(install_sh) -c -s"
+S["STRIP"]="strip"
+S["install_sh"]="${SHELL} /media/DATA0/data/m/3827/mongo/src/third_party/pcre-8.30/install-sh"
+S["MAKEINFO"]="${SHELL} /media/DATA0/data/m/3827/mongo/src/third_party/pcre-8.30/missing --run makeinfo"
+S["AUTOHEADER"]="${SHELL} /media/DATA0/data/m/3827/mongo/src/third_party/pcre-8.30/missing --run autoheader"
+S["AUTOMAKE"]="${SHELL} /media/DATA0/data/m/3827/mongo/src/third_party/pcre-8.30/missing --run automake-1.11"
+S["AUTOCONF"]="${SHELL} /media/DATA0/data/m/3827/mongo/src/third_party/pcre-8.30/missing --run autoconf"
+S["ACLOCAL"]="${SHELL} /media/DATA0/data/m/3827/mongo/src/third_party/pcre-8.30/missing --run aclocal-1.11"
+S["VERSION"]="8.30"
+S["PACKAGE"]="pcre"
+S["CYGPATH_W"]="echo"
+S["am__isrc"]=""
+S["INSTALL_DATA"]="${INSTALL} -m 644"
+S["INSTALL_SCRIPT"]="${INSTALL}"
+S["INSTALL_PROGRAM"]="${INSTALL}"
+S["target_alias"]=""
+S["host_alias"]=""
+S["build_alias"]=""
+S["LIBS"]=""
+S["ECHO_T"]=""
+S["ECHO_N"]="-n"
+S["ECHO_C"]=""
+S["DEFS"]="-DHAVE_CONFIG_H"
+S["mandir"]="${datarootdir}/man"
+S["localedir"]="${datarootdir}/locale"
+S["libdir"]="${exec_prefix}/lib"
+S["psdir"]="${docdir}"
+S["pdfdir"]="${docdir}"
+S["dvidir"]="${docdir}"
+S["htmldir"]="${docdir}/html"
+S["infodir"]="${datarootdir}/info"
+S["docdir"]="${datarootdir}/doc/${PACKAGE_TARNAME}"
+S["oldincludedir"]="/usr/include"
+S["includedir"]="${prefix}/include"
+S["localstatedir"]="${prefix}/var"
+S["sharedstatedir"]="${prefix}/com"
+S["sysconfdir"]="${prefix}/etc"
+S["datadir"]="${datarootdir}"
+S["datarootdir"]="${prefix}/share"
+S["libexecdir"]="${exec_prefix}/libexec"
+S["sbindir"]="${exec_prefix}/sbin"
+S["bindir"]="${exec_prefix}/bin"
+S["program_transform_name"]="s,x,x,"
+S["prefix"]="/usr/local"
+S["exec_prefix"]="${prefix}"
+S["PACKAGE_URL"]=""
+S["PACKAGE_BUGREPORT"]=""
+S["PACKAGE_STRING"]="PCRE 8.30"
+S["PACKAGE_VERSION"]="8.30"
+S["PACKAGE_TARNAME"]="pcre"
+S["PACKAGE_NAME"]="PCRE"
+S["PATH_SEPARATOR"]=":"
+S["SHELL"]="/bin/sh"
+_ACAWK
+cat >>"$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+D["PACKAGE_NAME"]=" \"PCRE\""
+D["PACKAGE_TARNAME"]=" \"pcre\""
+D["PACKAGE_VERSION"]=" \"8.30\""
+D["PACKAGE_STRING"]=" \"PCRE 8.30\""
+D["PACKAGE_BUGREPORT"]=" \"\""
+D["PACKAGE_URL"]=" \"\""
+D["PACKAGE"]=" \"pcre\""
+D["VERSION"]=" \"8.30\""
+D["STDC_HEADERS"]=" 1"
+D["HAVE_SYS_TYPES_H"]=" 1"
+D["HAVE_SYS_STAT_H"]=" 1"
+D["HAVE_STDLIB_H"]=" 1"
+D["HAVE_STRING_H"]=" 1"
+D["HAVE_MEMORY_H"]=" 1"
+D["HAVE_STRINGS_H"]=" 1"
+D["HAVE_INTTYPES_H"]=" 1"
+D["HAVE_STDINT_H"]=" 1"
+D["HAVE_UNISTD_H"]=" 1"
+D["HAVE_DLFCN_H"]=" 1"
+D["LT_OBJDIR"]=" \".libs/\""
+D["STDC_HEADERS"]=" 1"
+D["HAVE_LIMITS_H"]=" 1"
+D["HAVE_SYS_TYPES_H"]=" 1"
+D["HAVE_SYS_STAT_H"]=" 1"
+D["HAVE_DIRENT_H"]=" 1"
+D["HAVE_STRING"]=" 1"
+D["HAVE_STRTOQ"]=" 1"
+D["HAVE_LONG_LONG"]=" 1"
+D["HAVE_UNSIGNED_LONG_LONG"]=" 1"
+D["HAVE_BCOPY"]=" 1"
+D["HAVE_MEMMOVE"]=" 1"
+D["HAVE_STRERROR"]=" 1"
+D["HAVE_ZLIB_H"]=" 1"
+D["HAVE_BZLIB_H"]=" 1"
+D["HAVE_READLINE_READLINE_H"]=" 1"
+D["HAVE_READLINE_HISTORY_H"]=" 1"
+D["SUPPORT_PCRE8"]=" /**/"
+D["PCREGREP_BUFSIZE"]=" 20480"
+D["NEWLINE"]=" 10"
+D["LINK_SIZE"]=" 2"
+D["POSIX_MALLOC_THRESHOLD"]=" 10"
+D["MATCH_LIMIT"]=" 10000000"
+D["MATCH_LIMIT_RECURSION"]=" MATCH_LIMIT"
+D["MAX_NAME_SIZE"]=" 32"
+D["MAX_NAME_COUNT"]=" 10000"
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*([\t (]|$)/ {
+ line = $ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ ac_datarootdir_hack='
+ s&@datadir@&${datarootdir}&g
+ s&@docdir@&${datarootdir}/doc/${PACKAGE_TARNAME}&g
+ s&@infodir@&${datarootdir}/info&g
+ s&@localedir@&${datarootdir}/locale&g
+ s&@mandir@&${datarootdir}/man&g
+ s&\${datarootdir}&${prefix}/share&g' ;;
+esac
+ac_sed_extra="/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}
+
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$_am_arg" : 'X\(//\)[^/]' \| \
+ X"$_am_arg" : 'X\(//\)$' \| \
+ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+ :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+ # Autoconf 2.62 quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ case $CONFIG_FILES in
+ *\'*) eval set x "$CONFIG_FILES" ;;
+ *) set x $CONFIG_FILES ;;
+ esac
+ shift
+ for mf
+ do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir=$dirpart/$fdir; as_fn_mkdir_p
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+ done
+}
+ ;;
+ "libtool":C)
+
+ # See if we are running on zsh, and set the options which allow our
+ # commands through without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+
+ cfgfile="${ofile}T"
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+ $RM "$cfgfile"
+
+ cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+# 2006, 2007, 2008, 2009, 2010 Free Software Foundation,
+# Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING. If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags="CXX "
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Assembler program.
+AS=$lt_AS
+
+# DLL creation program.
+DLLTOOL=$lt_DLLTOOL
+
+# Object dumper program.
+OBJDUMP=$lt_OBJDUMP
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# convert \$build file names to \$host format.
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+
+# convert \$build files to toolchain format.
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method = "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# How to find potential files when deplibs_check_method = "file_magic".
+file_magic_glob=$lt_file_magic_glob
+
+# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+want_nocaseglob=$lt_want_nocaseglob
+
+# Command to associate shared and link libraries.
+sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
+
+# The archiver.
+AR=$lt_AR
+
+# Flags to create an archive.
+AR_FLAGS=$lt_AR_FLAGS
+
+# How to feed a file listing to the archiver.
+archiver_list_spec=$lt_archiver_list_spec
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# Specify filename containing input files for \$NM.
+nm_file_list_spec=$lt_nm_file_list_spec
+
+# The root where to search for dependent libraries,and in which our libraries should be installed.
+lt_sysroot=$lt_sysroot
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Manifest tool.
+MANIFEST_TOOL=$lt_MANIFEST_TOOL
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking. This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# The directories searched by this compiler when creating a shared library.
+compiler_lib_search_dirs=$lt_compiler_lib_search_dirs
+
+# Dependencies to place before and after the objects being linked to
+# create a shared library.
+predep_objects=$lt_predep_objects
+postdep_objects=$lt_postdep_objects
+predeps=$lt_predeps
+postdeps=$lt_postdeps
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ case $host_os in
+ aix3*)
+ cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+_LT_EOF
+ ;;
+ esac
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ if test x"$xsi_shell" = xyes; then
+ sed -e '/^func_dirname ()$/,/^} # func_dirname /c\
+func_dirname ()\
+{\
+\ case ${1} in\
+\ */*) func_dirname_result="${1%/*}${2}" ;;\
+\ * ) func_dirname_result="${3}" ;;\
+\ esac\
+} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+ sed -e '/^func_basename ()$/,/^} # func_basename /c\
+func_basename ()\
+{\
+\ func_basename_result="${1##*/}"\
+} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+ sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\
+func_dirname_and_basename ()\
+{\
+\ case ${1} in\
+\ */*) func_dirname_result="${1%/*}${2}" ;;\
+\ * ) func_dirname_result="${3}" ;;\
+\ esac\
+\ func_basename_result="${1##*/}"\
+} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+ sed -e '/^func_stripname ()$/,/^} # func_stripname /c\
+func_stripname ()\
+{\
+\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\
+\ # positional parameters, so assign one to ordinary parameter first.\
+\ func_stripname_result=${3}\
+\ func_stripname_result=${func_stripname_result#"${1}"}\
+\ func_stripname_result=${func_stripname_result%"${2}"}\
+} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+ sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\
+func_split_long_opt ()\
+{\
+\ func_split_long_opt_name=${1%%=*}\
+\ func_split_long_opt_arg=${1#*=}\
+} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+ sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\
+func_split_short_opt ()\
+{\
+\ func_split_short_opt_arg=${1#??}\
+\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\
+} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+ sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\
+func_lo2o ()\
+{\
+\ case ${1} in\
+\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\
+\ *) func_lo2o_result=${1} ;;\
+\ esac\
+} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+ sed -e '/^func_xform ()$/,/^} # func_xform /c\
+func_xform ()\
+{\
+ func_xform_result=${1%.*}.lo\
+} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+ sed -e '/^func_arith ()$/,/^} # func_arith /c\
+func_arith ()\
+{\
+ func_arith_result=$(( $* ))\
+} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+ sed -e '/^func_len ()$/,/^} # func_len /c\
+func_len ()\
+{\
+ func_len_result=${#1}\
+} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+fi
+
+if test x"$lt_shell_append" = xyes; then
+ sed -e '/^func_append ()$/,/^} # func_append /c\
+func_append ()\
+{\
+ eval "${1}+=\\${2}"\
+} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+ sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\
+func_append_quoted ()\
+{\
+\ func_quote_for_eval "${2}"\
+\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\
+} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+
+
+ # Save a `func_append' function call where possible by direct use of '+='
+ sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+ test 0 -eq $? || _lt_function_replace_fail=:
+else
+ # Save a `func_append' function call even when '+=' is not available
+ sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+ test 0 -eq $? || _lt_function_replace_fail=:
+fi
+
+if test x"$_lt_function_replace_fail" = x":"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5
+$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;}
+fi
+
+
+ mv -f "$cfgfile" "$ofile" ||
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+
+
+ cat <<_LT_EOF >> "$ofile"
+
+# ### BEGIN LIBTOOL TAG CONFIG: CXX
+
+# The linker used to build libraries.
+LD=$lt_LD_CXX
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag_CXX
+reload_cmds=$lt_reload_cmds_CXX
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds_CXX
+
+# A language specific compiler.
+CC=$lt_compiler_CXX
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC_CXX
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_CXX
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_CXX
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_CXX
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object_CXX
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds_CXX
+archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds_CXX
+module_expsym_cmds=$lt_module_expsym_cmds_CXX
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld_CXX
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_CXX
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_CXX
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking. This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct_CXX
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute_CXX
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L_CXX
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic_CXX
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath_CXX
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_CXX
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols_CXX
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_CXX
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_CXX
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_CXX
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds_CXX
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds_CXX
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec_CXX
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_CXX
+
+# The directories searched by this compiler when creating a shared library.
+compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX
+
+# Dependencies to place before and after the objects being linked to
+# create a shared library.
+predep_objects=$lt_predep_objects_CXX
+postdep_objects=$lt_postdep_objects_CXX
+predeps=$lt_predeps_CXX
+postdeps=$lt_postdeps_CXX
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
+
+# ### END LIBTOOL TAG CONFIG: CXX
+_LT_EOF
+
+ ;;
+ "script-chmod":C) chmod a+x pcre-config ;;
+ "delete-old-chartables":C) rm -f pcre_chartables.c ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0