From 12663be3f934feaf4443708188f6c8f2aef37f36 Mon Sep 17 00:00:00 2001 From: Dwight Date: Wed, 30 Jun 2010 17:28:57 -0400 Subject: defer creating the id index on a clone until we first insert all the data --- db/cloner.cpp | 23 ++++++++++++++++++++++- db/oplog.cpp | 2 +- db/pdfile.cpp | 27 ++++++++++++++++++--------- db/pdfile.h | 2 +- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/db/cloner.cpp b/db/cloner.cpp index c23a3d5f32b..a84b238fee5 100644 --- a/db/cloner.cpp +++ b/db/cloner.cpp @@ -165,6 +165,9 @@ namespace mongo { } } + extern bool inDBRepair; + void ensureIdIndexForNewNs(const char *ns); + bool Cloner::go(const char *masterHost, string& errmsg, const string& fromdb, bool logForRepl, bool slaveOk, bool useReplAuth, bool snapshot) { massert( 10289 , "useReplAuth is not written to replication log", !useReplAuth || !logForRepl ); @@ -256,19 +259,37 @@ namespace mongo { assert(p); string to_name = todb + p; + bool wantIdIndex = false; { string err; const char *toname = to_name.c_str(); - userCreateNS(toname, options, err, logForRepl); + /* we defer building id index for performance - building it in batch is much faster */ + userCreateNS(toname, options, err, logForRepl, &wantIdIndex); } log(1) << "\t\t cloning " << from_name << " -> " << to_name << endl; Query q; if( snapshot ) q.snapshot(); copy(from_name, to_name.c_str(), false, logForRepl, masterSameProcess, slaveOk, q); + + if( wantIdIndex ) { + /* we need dropDups to be true as we didn't do a true snapshot and this is before applying oplog operations + that occur during the initial sync. inDBRepair makes dropDups be true. + */ + bool old = inDBRepair; + try { + inDBRepair = true; + ensureIdIndexForNewNs(to_name.c_str()); + } + catch(...) { + inDBRepair = old; + throw; + } + } } // now build the indexes + string system_indexes_from = fromdb + ".system.indexes"; string system_indexes_to = todb + ".system.indexes"; /* [dm]: is the ID index sometimes not called "_id_"? There is other code in the system that looks for a "_id" prefix diff --git a/db/oplog.cpp b/db/oplog.cpp index 71cb8863c44..c2727d64970 100644 --- a/db/oplog.cpp +++ b/db/oplog.cpp @@ -231,7 +231,7 @@ namespace mongo { } /*@ @param opstr: - c userCreateNs + c userCreateNS i insert n no-op / keepalive d delete / remove diff --git a/db/pdfile.cpp b/db/pdfile.cpp index d00c51545cb..2da558c5f82 100644 --- a/db/pdfile.cpp +++ b/db/pdfile.cpp @@ -123,7 +123,7 @@ namespace mongo { void ensureIdIndexForNewNs(const char *ns) { if ( ( strstr( ns, ".system." ) == 0 || legalClientSystemNS( ns , false ) ) && strstr( ns, ".$freelist" ) == 0 ){ - log( 1 ) << "adding _id index for new collection" << endl; + log( 1 ) << "adding _id index for collection " << ns << endl; ensureHaveIdIndex( ns ); } } @@ -161,7 +161,7 @@ namespace mongo { return z; } - bool _userCreateNS(const char *ns, const BSONObj& options, string& err) { + bool _userCreateNS(const char *ns, const BSONObj& options, string& err, bool *deferIdIndex) { if ( nsdetails(ns) ) { err = "collection already exists"; return false; @@ -223,15 +223,22 @@ namespace mongo { NamespaceDetails *d = nsdetails(ns); assert(d); + bool ensure = false; if ( options.getField( "autoIndexId" ).type() ) { if ( options["autoIndexId"].trueValue() ){ - ensureIdIndexForNewNs( ns ); + ensure = true; } } else { if ( !newCapped ) { - ensureIdIndexForNewNs( ns ); + ensure=true; } } + if( ensure ) { + if( deferIdIndex ) + *deferIdIndex = true; + else + ensureIdIndexForNewNs( ns ); + } if ( mx > 0 ) d->max = mx; @@ -239,14 +246,16 @@ namespace mongo { return true; } - // { ..., capped: true, size: ..., max: ... } - // returns true if successful - bool userCreateNS(const char *ns, BSONObj options, string& err, bool logForReplication) { + /** { ..., capped: true, size: ..., max: ... } + @param deferIdIndex - if not not, defers id index creation. sets the bool value to true if we wanted to create the id index. + @return true if successful + */ + bool userCreateNS(const char *ns, BSONObj options, string& err, bool logForReplication, bool *deferIdIndex) { const char *coll = strchr( ns, '.' ) + 1; massert( 10356 , "invalid ns", coll && *coll ); char cl[ 256 ]; nsToDatabase( ns, cl ); - bool ok = _userCreateNS(ns, options, err); + bool ok = _userCreateNS(ns, options, err, deferIdIndex); if ( logForReplication && ok ) { if ( options.getField( "create" ).eoo() ) { BSONObjBuilder b; @@ -679,7 +688,7 @@ namespace mongo { NamespaceDetails *freeExtents = nsdetails(s.c_str()); if( freeExtents == 0 ) { string err; - _userCreateNS(s.c_str(), BSONObj(), err); + _userCreateNS(s.c_str(), BSONObj(), err, 0); freeExtents = nsdetails(s.c_str()); massert( 10361 , "can't create .$freelist", freeExtents); } diff --git a/db/pdfile.h b/db/pdfile.h index 5cef15bd927..0c1293e6f19 100644 --- a/db/pdfile.h +++ b/db/pdfile.h @@ -48,7 +48,7 @@ namespace mongo { /* deletes this ns, indexes and cursors */ void dropCollection( const string &name, string &errmsg, BSONObjBuilder &result ); - bool userCreateNS(const char *ns, BSONObj j, string& err, bool logForReplication); + bool userCreateNS(const char *ns, BSONObj j, string& err, bool logForReplication, bool *deferIdIndex = 0); shared_ptr findTableScan(const char *ns, const BSONObj& order, const DiskLoc &startLoc=DiskLoc()); // -1 if library unavailable. -- cgit v1.2.1