summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaszlo Boszormenyi (GCS) <gcs@debian.org>2014-04-27 22:12:11 +0200
committerLaszlo Boszormenyi (GCS) <gcs@debian.org>2014-04-27 22:12:11 +0200
commitf0716c5e9c213302422db87c1c36c1d177853e8e (patch)
tree44f26826e6dde7c32ad2f57f206d7da74e994625 /src
parent547377230880c8e9def9ee9458ae69d298918467 (diff)
Imported Upstream version 2.4.10upstream/2.4.10
Diffstat (limited to 'src')
-rw-r--r--src/mongo/client/distlock.cpp35
-rw-r--r--src/mongo/client/distlock.h25
-rw-r--r--src/mongo/client/gridfs.cpp2
-rw-r--r--src/mongo/db/db.cpp87
-rw-r--r--src/mongo/db/geo/s2index.cpp14
-rw-r--r--src/mongo/db/index.cpp27
-rw-r--r--src/mongo/db/instance.cpp23
-rw-r--r--src/mongo/db/namespace_details.cpp26
-rw-r--r--src/mongo/db/namespace_details.h1
-rw-r--r--src/mongo/db/namespacestring.h1
-rw-r--r--src/mongo/db/oplog.cpp21
-rw-r--r--src/mongo/db/pdfile.cpp30
-rw-r--r--src/mongo/db/pipeline/value.cpp13
-rw-r--r--src/mongo/db/repl/consensus.cpp1
-rw-r--r--src/mongo/db/repl/manager.cpp6
-rw-r--r--src/mongo/db/repl/rs_sync.cpp15
-rw-r--r--src/mongo/dbtests/d_chunk_manager_tests.cpp14
-rw-r--r--src/mongo/s/balance.cpp1
-rw-r--r--src/mongo/s/commands_admin.cpp2
-rw-r--r--src/mongo/s/config.cpp12
-rw-r--r--src/mongo/s/d_chunk_manager.cpp2
-rw-r--r--src/mongo/s/server.cpp3
-rw-r--r--src/mongo/shell/replsettest.js5
-rw-r--r--src/mongo/shell/shell_utils_extended.cpp2
-rw-r--r--src/mongo/util/file_allocator.cpp10
-rw-r--r--src/mongo/util/processinfo.h14
-rw-r--r--src/mongo/util/processinfo_win32.cpp11
-rw-r--r--src/mongo/util/version.cpp2
-rw-r--r--src/third_party/v8/src/spaces-inl.h2
29 files changed, 299 insertions, 108 deletions
diff --git a/src/mongo/client/distlock.cpp b/src/mongo/client/distlock.cpp
index 0e38a64f953..a2f56e564bf 100644
--- a/src/mongo/client/distlock.cpp
+++ b/src/mongo/client/distlock.cpp
@@ -131,19 +131,32 @@ namespace mongo {
continue;
}
- // remove really old entries from the lockpings collection if they're not holding a lock
- // (this may happen if an instance of a process was taken down and no new instance came up to
- // replace it for a quite a while)
- // if the lock is taken, the take-over mechanism should handle the situation
- auto_ptr<DBClientCursor> c = conn->query( LocksType::ConfigNS , BSONObj() );
- // TODO: Would be good to make clear whether query throws or returns empty on errors
- uassert( 16060, str::stream() << "cannot query locks collection on config server " << conn.getHost(), c.get() );
+ // Remove really old entries from the lockpings collection if they're not
+ // holding a lock. This may happen if an instance of a process was taken down
+ // and no new instance came up to replace it for a quite a while.
+ // NOTE this is NOT the same as the standard take-over mechanism, which forces
+ // the lock entry.
+ BSONObj fieldsToReturn = BSON( LocksType::state() << 1 <<
+ LocksType::process() << 1 );
+ auto_ptr<DBClientCursor> activeLocks =
+ conn->query( LocksType::ConfigNS,
+ BSON( LocksType::state() << GT << 0 ) );
+
+ uassert( 16060,
+ str::stream() << "cannot query locks collection on config server "
+ << conn.getHost(),
+ activeLocks.get() );
set<string> pids;
- while ( c->more() ) {
- BSONObj lock = c->next();
- if ( ! lock[LocksType::process()].eoo() ) {
- pids.insert( lock[LocksType::process()].valuestrsafe() );
+ while ( activeLocks->more() ) {
+ BSONObj lock = activeLocks->nextSafe();
+
+ if ( !lock[LocksType::process()].eoo() ) {
+ pids.insert( lock[LocksType::process()].str() );
+ }
+ else {
+ warning() << "found incorrect lock document during lock ping cleanup: "
+ << lock.toString() << endl;
}
}
diff --git a/src/mongo/client/distlock.h b/src/mongo/client/distlock.h
index 183826afcce..774d94a0df8 100644
--- a/src/mongo/client/distlock.h
+++ b/src/mongo/client/distlock.h
@@ -57,12 +57,19 @@ namespace mongo {
};
/**
- * The distributed lock is a configdb backed way of synchronizing system-wide tasks. A task must be identified by a
- * unique name across the system (e.g., "balancer"). A lock is taken by writing a document in the configdb's locks
- * collection with that name.
+ * The distributed lock is a configdb backed way of synchronizing system-wide tasks. A task
+ * must be identified by a unique name across the system (e.g., "balancer"). A lock is taken
+ * by writing a document in the configdb's locks collection with that name.
*
- * To be maintained, each taken lock needs to be revalidated ("pinged") within a pre-established amount of time. This
- * class does this maintenance automatically once a DistributedLock object was constructed.
+ * To be maintained, each taken lock needs to be revalidated ("pinged") within a
+ * pre-established amount of time. This class does this maintenance automatically once a
+ * DistributedLock object was constructed. The ping procedure records the local time to
+ * the ping document, but that time is untrusted and is only used as a point of reference
+ * of whether the ping was refreshed or not. Ultimately, the clock a configdb is the source
+ * of truth when determining whether a ping is still fresh or not. This is achieved by
+ * (1) remembering the ping document time along with config server time when unable to
+ * take a lock, and (2) ensuring all config servers report similar times and have similar
+ * time rates (the difference in times must start and stay small).
*/
class DistributedLock {
public:
@@ -147,9 +154,13 @@ namespace mongo {
const ConnectionString& getRemoteConnection();
/**
- * Check the skew between a cluster of servers
+ * Checks the skew among a cluster of servers and returns true if the min and max clock
+ * times among the servers are within maxClockSkew.
*/
- static bool checkSkew( const ConnectionString& cluster, unsigned skewChecks = NUM_LOCK_SKEW_CHECKS, unsigned long long maxClockSkew = MAX_LOCK_CLOCK_SKEW, unsigned long long maxNetSkew = MAX_LOCK_NET_SKEW );
+ static bool checkSkew( const ConnectionString& cluster,
+ unsigned skewChecks = NUM_LOCK_SKEW_CHECKS,
+ unsigned long long maxClockSkew = MAX_LOCK_CLOCK_SKEW,
+ unsigned long long maxNetSkew = MAX_LOCK_NET_SKEW );
/**
* Get the remote time from a server or cluster
diff --git a/src/mongo/client/gridfs.cpp b/src/mongo/client/gridfs.cpp
index e2d1038d6ee..6d58ec690c2 100644
--- a/src/mongo/client/gridfs.cpp
+++ b/src/mongo/client/gridfs.cpp
@@ -37,7 +37,7 @@
namespace mongo {
- const unsigned DEFAULT_CHUNK_SIZE = 256 * 1024;
+ const unsigned DEFAULT_CHUNK_SIZE = 255 * 1024;
GridFSChunk::GridFSChunk( BSONObj o ) {
_data = o;
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index ec337c89885..046101a29bf 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -77,6 +77,7 @@ namespace mongo {
extern int diagLogging;
extern unsigned lenForNewNsFiles;
extern int lockFile;
+ extern bool checkNsFilesOnLoad;
extern string repairpath;
static void setupSignalHandlers();
@@ -321,6 +322,8 @@ namespace mongo {
Client::GodScope gs;
LOG(1) << "enter repairDatabases (to check pdfile version #)" << endl;
+ checkNsFilesOnLoad = false; // we are mainly just checking the header - don't scan the whole .ns file for every db here.
+
Lock::GlobalWrite lk;
vector< string > dbNames;
getDatabaseNames( dbNames );
@@ -361,12 +364,12 @@ namespace mongo {
}
}
else {
- if (h->versionMinor == PDFILE_VERSION_MINOR_22_AND_OLDER) {
- const string systemIndexes = cc().database()->name + ".system.indexes";
- shared_ptr<Cursor> cursor(theDataFileMgr.findAll(systemIndexes));
- for ( ; cursor && cursor->ok(); cursor->advance()) {
- const BSONObj index = cursor->current();
- const BSONObj key = index.getObjectField("key");
+ const string systemIndexes = cc().database()->name + ".system.indexes";
+ shared_ptr<Cursor> cursor(theDataFileMgr.findAll(systemIndexes));
+ for ( ; cursor && cursor->ok(); cursor->advance()) {
+ const BSONObj index = cursor->current();
+ const BSONObj key = index.getObjectField("key");
+ if (h->versionMinor == PDFILE_VERSION_MINOR_22_AND_OLDER) {
const string plugin = IndexPlugin::findPluginName(key);
if (IndexPlugin::existedBefore24(plugin))
continue;
@@ -377,6 +380,21 @@ namespace mongo {
<< "http://dochub.mongodb.org/core/upgrade-2.4"
<< startupWarningsLog;
}
+ else {
+ verify(h->versionMinor == PDFILE_VERSION_MINOR_24_AND_NEWER);
+ try {
+ IndexSpec(key, index, IndexSpec::RulesFor24);
+ }
+ catch (const DBException& e) {
+ error() << "Encountered an unrecognized index spec: " << index << endl;
+ error() << "Reason this index spec could not be loaded: \"" << e.what()
+ << "\"" << endl;
+ error() << "The index cannot be used with this version of MongoDB; "
+ << "exiting..." << endl;
+ cc().shutdown();
+ dbexit(EXIT_UNCAUGHT);
+ }
+ }
}
Database::closeDatabase( dbName.c_str(), dbpath );
}
@@ -389,6 +407,8 @@ namespace mongo {
cc().shutdown();
dbexit( EXIT_CLEAN );
}
+
+ checkNsFilesOnLoad = true;
}
void clearTmpFiles() {
@@ -528,39 +548,47 @@ namespace mongo {
/// warn if readahead > 256KB (gridfs chunk size)
static void checkReadAhead(const string& dir) {
#ifdef __linux__
- const dev_t dev = getPartition(dir);
-
- // This path handles the case where the filesystem uses the whole device (including LVM)
- string path = str::stream() <<
- "/sys/dev/block/" << major(dev) << ':' << minor(dev) << "/queue/read_ahead_kb";
-
- if (!boost::filesystem::exists(path)){
- // This path handles the case where the filesystem is on a partition.
- path = str::stream()
- << "/sys/dev/block/" << major(dev) << ':' << minor(dev) // this is a symlink
- << "/.." // parent directory of a partition is for the whole device
- << "/queue/read_ahead_kb";
- }
+ try {
+ const dev_t dev = getPartition(dir);
+
+ // This path handles the case where the filesystem uses the whole device (including LVM)
+ string path = str::stream() <<
+ "/sys/dev/block/" << major(dev) << ':' << minor(dev) << "/queue/read_ahead_kb";
+
+ if (!boost::filesystem::exists(path)){
+ // This path handles the case where the filesystem is on a partition.
+ path = str::stream()
+ << "/sys/dev/block/" << major(dev) << ':' << minor(dev) // this is a symlink
+ << "/.." // parent directory of a partition is for the whole device
+ << "/queue/read_ahead_kb";
+ }
- if (boost::filesystem::exists(path)) {
- ifstream file (path.c_str());
- if (file.is_open()) {
- int kb;
- file >> kb;
- if (kb > 256) {
- log() << startupWarningsLog;
+ if (boost::filesystem::exists(path)) {
+ ifstream file (path.c_str());
+ if (file.is_open()) {
+ int kb;
+ file >> kb;
+ if (kb > 256) {
+ log() << startupWarningsLog;
- log() << "** WARNING: Readahead for " << dir << " is set to " << kb << "KB"
+ log() << "** WARNING: Readahead for " << dir << " is set to " << kb << "KB"
<< startupWarningsLog;
- log() << "** We suggest setting it to 256KB (512 sectors) or less"
+ log() << "** We suggest setting it to 256KB (512 sectors) or less"
<< startupWarningsLog;
- log() << "** http://dochub.mongodb.org/core/readahead"
+ log() << "** http://dochub.mongodb.org/core/readahead"
<< startupWarningsLog;
+ }
}
}
}
+ catch (const std::exception& e) {
+ log() << "unable to validate readahead settings due to error: " << e.what()
+ << startupWarningsLog;
+ log() << "for more information, see http://dochub.mongodb.org/core/readahead"
+ << startupWarningsLog;
+ }
#endif // __linux__
}
@@ -1415,6 +1443,7 @@ namespace mongo {
sigaddset( &asyncSignals, SIGINT );
sigaddset( &asyncSignals, SIGTERM );
sigaddset( &asyncSignals, SIGUSR1 );
+ sigaddset( &asyncSignals, SIGXCPU );
set_terminate( myterminate );
set_new_handler( my_new_handler );
diff --git a/src/mongo/db/geo/s2index.cpp b/src/mongo/db/geo/s2index.cpp
index d52f0ad2991..412d425f2f8 100644
--- a/src/mongo/db/geo/s2index.cpp
+++ b/src/mongo/db/geo/s2index.cpp
@@ -365,6 +365,11 @@ namespace mongo {
uassert(16688, "finestIndexedLevel must be <= 30", params.finestIndexedLevel <= 30);
uassert(16689, "finestIndexedLevel must be >= coarsestIndexedLevel",
params.finestIndexedLevel >= params.coarsestIndexedLevel);
+ massert(17289,
+ str::stream() << "unsupported geo index version { "
+ << spec->info["2dsphereIndexVersion"]
+ << " }, only support versions: [1]",
+ configValueWithDefault(spec, "2dsphereIndexVersion", 1) == 1);
// Categorize the fields we're indexing and make sure we have a geo field.
int geoFields = 0;
@@ -388,6 +393,15 @@ namespace mongo {
return new S2IndexType(SPHERE_2D_NAME, this, spec, params);
}
+ virtual BSONObj adjustIndexSpec( const BSONObj& spec ) const {
+ BSONElement indexVersionElt = spec["2dsphereIndexVersion"];
+ uassert(17290,
+ str::stream() << "unsupported geo index version { " << indexVersionElt
+ << " }, only support versions: [1]",
+ indexVersionElt.eoo() || indexVersionElt.numberInt() == 1);
+ return spec;
+ }
+
int configValueWithDefault(const IndexSpec* spec, const string& name, int def) const {
BSONElement e = spec->info[name];
if (e.isNumber()) { return e.numberInt(); }
diff --git a/src/mongo/db/index.cpp b/src/mongo/db/index.cpp
index f7346978313..e4366977081 100644
--- a/src/mongo/db/index.cpp
+++ b/src/mongo/db/index.cpp
@@ -324,6 +324,8 @@ namespace mongo {
getDur().writingInt(dfh->versionMinor) = PDFILE_VERSION_MINOR_24_AND_NEWER;
}
+ extern BSONObj id_obj; // { _id : 1 }
+
bool prepareToBuildIndex(const BSONObj& io,
bool mayInterrupt,
bool god,
@@ -334,9 +336,11 @@ namespace mongo {
// the collection for which we are building an index
sourceNS = io.getStringField("ns");
+ NamespaceString nss(sourceNS);
uassert(10096, "invalid ns to index", sourceNS.find( '.' ) != string::npos);
- massert(10097, str::stream() << "bad table to index name on add index attempt current db: " << cc().database()->name << " source: " << sourceNS ,
- cc().database()->name == nsToDatabase(sourceNS));
+ uassert(17072, "cannot create indexes on the system.indexes collection",
+ !nss.isSystemDotIndexes());
+ massert(10097, str::stream() << "bad table to index name on add index attempt current db: " << cc().database()->name << " source: " << sourceNS , cc().database()->name == nsToDatabase(sourceNS));
// logical name of the index. todo: get rid of the name, we don't need it!
const char *name = io.getStringField("name");
@@ -393,10 +397,10 @@ namespace mongo {
all be treated as the same pattern.
*/
if ( IndexDetails::isIdIndexPattern(key) ) {
- if( !god ) {
- ensureHaveIdIndex( sourceNS.c_str(), mayInterrupt );
- return false;
- }
+ //if( !god ) {
+ //ensureHaveIdIndex( sourceNS.c_str(), mayInterrupt );
+ //return false;
+ //}
}
else {
/* is buildIndexes:false set for this replica set member?
@@ -435,7 +439,14 @@ namespace mongo {
}
// idea is to put things we use a lot earlier
b.append("v", v);
- b.append(o["key"]);
+ if ( IndexDetails::isIdIndexPattern(o["key"].Obj()) ) {
+ b.append("name", "_id_");
+ b.append("key", id_obj);
+ }
+ else {
+ b.append( o["name"] );
+ b.append(o["key"]);
+ }
if( o["unique"].trueValue() )
b.appendBool("unique", true); // normalize to bool true in case was int 1 or something...
b.append(o["ns"]);
@@ -446,7 +457,7 @@ namespace mongo {
while ( i.more() ) {
BSONElement e = i.next();
string s = e.fieldName();
- if( s != "_id" && s != "v" && s != "ns" && s != "unique" && s != "key" )
+ if( s != "_id" && s != "v" && s != "ns" && s != "unique" && s != "key" && s != "name" )
b.append(e);
}
}
diff --git a/src/mongo/db/instance.cpp b/src/mongo/db/instance.cpp
index 926cdeecdb6..b95bcb1bfea 100644
--- a/src/mongo/db/instance.cpp
+++ b/src/mongo/db/instance.cpp
@@ -792,16 +792,19 @@ namespace mongo {
}
}
- theDataFileMgr.insertWithObjMod(ns,
- // May be modified in the call to add an _id field.
- js,
- // Only permit interrupting an (index build) insert if the
- // insert comes from a socket client request rather than a
- // parent operation using the client interface. The parent
- // operation might not support interrupts.
- cc().curop()->parent() == NULL,
- false);
- logOp("i", ns, js);
+ DiskLoc dl = theDataFileMgr.
+ insertWithObjMod(ns,
+ // May be modified in the call to add an _id field.
+ js,
+ // Only permit interrupting an (index build) insert if the
+ // insert comes from a socket client request rather than a
+ // parent operation using the client interface. The parent
+ // operation might not support interrupts.
+ cc().curop()->parent() == NULL,
+ false);
+ if (!dl.isNull()) {
+ logOp("i", ns, js);
+ }
}
NOINLINE_DECL void insertMulti(bool keepGoing, const char *ns, vector<BSONObj>& objs, CurOp& op) {
diff --git a/src/mongo/db/namespace_details.cpp b/src/mongo/db/namespace_details.cpp
index 0fc7bdf5eb5..382522bb50a 100644
--- a/src/mongo/db/namespace_details.cpp
+++ b/src/mongo/db/namespace_details.cpp
@@ -122,6 +122,29 @@ namespace mongo {
}
#endif
+ void NamespaceDetails::onLoad(const Namespace& k) {
+
+ if( k.isExtra() ) {
+ /* overflow storage for indexes - so don't treat as a NamespaceDetails object. */
+ return;
+ }
+
+ if( indexBuildsInProgress ) {
+ verify( Lock::isW() ); // TODO(erh) should this be per db?
+ if( indexBuildsInProgress ) {
+ log() << "indexBuildsInProgress was " << indexBuildsInProgress << " for " << k
+ << ", indicating an abnormal db shutdown" << endl;
+ getDur().writingInt( indexBuildsInProgress ) = 0;
+ }
+ }
+ }
+
+ static void namespaceOnLoadCallback(const Namespace& k, NamespaceDetails& v) {
+ v.onLoad(k);
+ }
+
+ bool checkNsFilesOnLoad = true;
+
NOINLINE_DECL void NamespaceIndex::_init() {
verify( !ht );
@@ -174,6 +197,9 @@ namespace mongo {
verify( len <= 0x7fffffff );
ht = new HashTable<Namespace,NamespaceDetails>(p, (int) len, "namespace index");
+ if( checkNsFilesOnLoad )
+ ht->iterAll(namespaceOnLoadCallback);
+
}
static void namespaceGetNamespacesCallback( const Namespace& k , NamespaceDetails& v , void * extra ) {
diff --git a/src/mongo/db/namespace_details.h b/src/mongo/db/namespace_details.h
index 0e7e324da67..3f381605250 100644
--- a/src/mongo/db/namespace_details.h
+++ b/src/mongo/db/namespace_details.h
@@ -405,6 +405,7 @@ namespace mongo {
/** Make all linked Extra objects writeable as well */
NamespaceDetails *writingWithExtra();
+ void onLoad( const Namespace& k );
private:
DiskLoc _alloc(const char *ns, int len);
void maybeComplain( const char *ns, int len ) const;
diff --git a/src/mongo/db/namespacestring.h b/src/mongo/db/namespacestring.h
index d108bbaac72..96d78230b39 100644
--- a/src/mongo/db/namespacestring.h
+++ b/src/mongo/db/namespacestring.h
@@ -46,6 +46,7 @@ namespace mongo {
bool isSystem() const { return strncmp(coll.c_str(), "system.", 7) == 0; }
bool isCommand() const { return coll == "$cmd"; }
+ bool isSystemDotIndexes() const { return strncmp(coll.c_str(), "system.indexes", 14) == 0; }
/**
* @return true if the namespace is valid. Special namespaces for internal use are considered as valid.
diff --git a/src/mongo/db/oplog.cpp b/src/mongo/db/oplog.cpp
index b88ad66ac03..33990367d92 100644
--- a/src/mongo/db/oplog.cpp
+++ b/src/mongo/db/oplog.cpp
@@ -95,7 +95,15 @@ namespace mongo {
*/
if( theReplSet ) {
if( !(theReplSet->lastOpTimeWritten<ts) ) {
- log() << "replSet error possible failover clock skew issue? " << theReplSet->lastOpTimeWritten.toString() << ' ' << endl;
+ log() << "replication oplog stream went back in time. previous timestamp: "
+ << theReplSet->lastOpTimeWritten << " newest timestamp: " << ts
+ << ". attempting to sync directly from primary." << endl;
+ std::string errmsg;
+ BSONObjBuilder result;
+ if (!theReplSet->forceSyncFrom(theReplSet->box.getPrimary()->fullName(),
+ errmsg, result)) {
+ log() << "Can't sync from primary: " << errmsg << endl;
+ }
}
theReplSet->lastOpTimeWritten = ts;
theReplSet->lastH = h;
@@ -222,8 +230,15 @@ namespace mongo {
*/
if( theReplSet ) {
if( !(theReplSet->lastOpTimeWritten<ts) ) {
- log() << "replSet ERROR possible failover clock skew issue? " << theReplSet->lastOpTimeWritten << ' ' << ts << rsLog;
- log() << "replSet " << theReplSet->isPrimary() << rsLog;
+ log() << "replication oplog stream went back in time. previous timestamp: "
+ << theReplSet->lastOpTimeWritten << " newest timestamp: " << ts
+ << ". attempting to sync directly from primary." << endl;
+ std::string errmsg;
+ BSONObjBuilder result;
+ if (!theReplSet->forceSyncFrom(theReplSet->box.getPrimary()->fullName(),
+ errmsg, result)) {
+ log() << "Can't sync from primary: " << errmsg << endl;
+ }
}
theReplSet->lastOpTimeWritten = ts;
theReplSet->lastH = hashNew;
diff --git a/src/mongo/db/pdfile.cpp b/src/mongo/db/pdfile.cpp
index 4085dfd2b3f..aa49b156a28 100644
--- a/src/mongo/db/pdfile.cpp
+++ b/src/mongo/db/pdfile.cpp
@@ -1316,8 +1316,10 @@ namespace mongo {
void DataFileMgr::insertAndLog( const char *ns, const BSONObj &o, bool god, bool fromMigrate ) {
BSONObj tmp = o;
- insertWithObjMod( ns, tmp, false, god );
- logOp( "i", ns, tmp, 0, 0, fromMigrate );
+ DiskLoc loc = insertWithObjMod( ns, tmp, false, god );
+ if (!loc.isNull()) {
+ logOp( "i", ns, tmp, 0, 0, fromMigrate );
+ }
}
/** @param o the object to insert. can be modified to add _id and thus be an in/out param
@@ -1475,16 +1477,20 @@ namespace mongo {
}
try {
- IndexDetails& idx = tableToIndex->getNextIndexDetails(tabletoidxns.c_str());
- // It's important that this is outside the inner try/catch so that we never try to call
- // kill_idx on a half-formed disk loc (if this asserts).
- getDur().writingDiskLoc(idx.info) = loc;
+ {
+ IndexDetails& idx = tableToIndex->getNextIndexDetails(tabletoidxns.c_str());
+ // It's important that this is outside the inner try/catch so that we never try to call
+ // kill_idx on a half-formed disk loc (if this asserts).
+ getDur().writingDiskLoc(idx.info) = loc;
+ }
try {
+ IndexDetails& idx = tableToIndex->getNextIndexDetails(tabletoidxns.c_str());
getDur().writingInt(tableToIndex->indexBuildsInProgress) += 1;
buildAnIndex(tabletoidxns, tableToIndex, idx, background, mayInterrupt);
}
catch (DBException& e) {
+ log() << "error building index: " << e << endl;
// save our error msg string as an exception or dropIndexes will overwrite our message
LastError *le = lastError.get();
int savecode = 0;
@@ -1499,7 +1505,10 @@ namespace mongo {
}
// Recalculate the index # so we can remove it from the list in the next catch
+
idxNo = IndexBuildsInProgress::get(tabletoidxns.c_str(), idxName);
+ IndexDetails& idx = tableToIndex->idx(idxNo);
+
// roll back this index
idx.kill_idx();
@@ -1519,6 +1528,7 @@ namespace mongo {
<< tableToIndex->nIndexes << endl;
// We cannot use idx here, as it may point to a different index entry if it was
// flipped during building
+
IndexDetails temp = tableToIndex->idx(idxNo);
*getDur().writing(&tableToIndex->idx(idxNo)) =
tableToIndex->idx(tableToIndex->nIndexes);
@@ -1531,6 +1541,7 @@ namespace mongo {
tableToIndex->setIndexIsMultikey(tabletoidxns.c_str(), tableToIndex->nIndexes,
tempMultikey);
+
idxNo = tableToIndex->nIndexes;
}
@@ -1542,10 +1553,10 @@ namespace mongo {
tableToIndex->addIndex(tabletoidxns.c_str());
getDur().writingInt(tableToIndex->indexBuildsInProgress) -= 1;
- IndexType* indexType = idx.getSpec().getType();
+ IndexType* indexType = tableToIndex->idx(idxNo).getSpec().getType();
const IndexPlugin *plugin = indexType ? indexType->getPlugin() : NULL;
if (plugin) {
- plugin->postBuildHook( idx.getSpec() );
+ plugin->postBuildHook( tableToIndex->idx(idxNo).getSpec() );
}
}
@@ -1589,7 +1600,8 @@ namespace mongo {
Lock::assertWriteLocked(ns);
NamespaceDetails* nsd = nsdetails(ns);
- for (int i=offset; i<nsd->getTotalIndexCount(); i++) {
+ // offset is 0-based, so we subtract one from the index count
+ for (int i = offset; i < (nsd->getTotalIndexCount() - 1); i++) {
if (i < NamespaceDetails::NIndexesMax-1) {
*getDur().writing(&nsd->idx(i)) = nsd->idx(i+1);
nsd->setIndexIsMultikey(ns, i, nsd->isMultikey(i+1));
diff --git a/src/mongo/db/pipeline/value.cpp b/src/mongo/db/pipeline/value.cpp
index 207dc4e37b8..6045207c764 100644
--- a/src/mongo/db/pipeline/value.cpp
+++ b/src/mongo/db/pipeline/value.cpp
@@ -513,19 +513,15 @@ namespace mongo {
}
string Value::coerceToString() const {
- stringstream ss;
switch(getType()) {
case NumberDouble:
- ss << _storage.doubleValue;
- return ss.str();
+ return str::stream() << _storage.doubleValue;
case NumberInt:
- ss << _storage.intValue;
- return ss.str();
+ return str::stream() << _storage.intValue;
case NumberLong:
- ss << _storage.longValue;
- return ss.str();
+ return str::stream() << _storage.longValue;
case Code:
case Symbol:
@@ -533,8 +529,7 @@ namespace mongo {
return getStringData().toString();
case Timestamp:
- ss << getTimestamp().toStringPretty();
- return ss.str();
+ return getTimestamp().toStringPretty();
case Date:
return tmToISODateString(coerceToTm());
diff --git a/src/mongo/db/repl/consensus.cpp b/src/mongo/db/repl/consensus.cpp
index dcb31408c11..a2459477432 100644
--- a/src/mongo/db/repl/consensus.cpp
+++ b/src/mongo/db/repl/consensus.cpp
@@ -253,7 +253,6 @@ namespace mongo {
try {
vote = yea(whoid);
dassert( hopeful->id() == whoid );
- rs.relinquish();
log() << "replSet info voting yea for " << hopeful->fullName() << " (" << whoid << ')' << rsLog;
}
catch(VoteException&) {
diff --git a/src/mongo/db/repl/manager.cpp b/src/mongo/db/repl/manager.cpp
index cbc3a3e7baa..4e9708a1d19 100644
--- a/src/mongo/db/repl/manager.cpp
+++ b/src/mongo/db/repl/manager.cpp
@@ -80,11 +80,7 @@ namespace mongo {
}
if (rs->box.getState().primary()) {
- // make sure exactly one primary steps down
- if (rs->selfId() < m->id()) {
- return;
- }
-
+ log() << "stepping down; another primary seen in replicaset";
rs->relinquish();
}
diff --git a/src/mongo/db/repl/rs_sync.cpp b/src/mongo/db/repl/rs_sync.cpp
index e6e31943a9f..f904d86c5ad 100644
--- a/src/mongo/db/repl/rs_sync.cpp
+++ b/src/mongo/db/repl/rs_sync.cpp
@@ -585,13 +585,6 @@ namespace replset {
bool golive = false;
lock rsLock( this );
- Lock::GlobalWrite writeLock;
-
- // make sure we're not primary, secondary, rollback, or fatal already
- if (box.getState().primary() || box.getState().secondary() ||
- box.getState().fatal()) {
- return false;
- }
if (_maintenanceMode > 0) {
// we're not actually going live
@@ -603,6 +596,14 @@ namespace replset {
return false;
}
+ Lock::GlobalWrite writeLock;
+
+ // make sure we're not primary, secondary, rollback, or fatal already
+ if (box.getState().primary() || box.getState().secondary() ||
+ box.getState().fatal()) {
+ return false;
+ }
+
minvalid = getMinValid();
if( minvalid <= lastOpTimeWritten ) {
golive=true;
diff --git a/src/mongo/dbtests/d_chunk_manager_tests.cpp b/src/mongo/dbtests/d_chunk_manager_tests.cpp
index e50961d3ee7..be7639f5794 100644
--- a/src/mongo/dbtests/d_chunk_manager_tests.cpp
+++ b/src/mongo/dbtests/d_chunk_manager_tests.cpp
@@ -362,6 +362,20 @@ namespace {
ASSERT( cloned->belongsToMe( split1 ) );
ASSERT( cloned->belongsToMe( split2 ) );
ASSERT( ! cloned->belongsToMe( max ) );
+
+ ASSERT_FALSE( cloned->getNextChunk( BSON( "a" << MinKey << "b" << 0 ), &min, &max ));
+ ASSERT_EQUALS( BSON( "a" << 10 << "b" << 0 ), min );
+ ASSERT_EQUALS( BSON( "a" << 15 << "b" << 0 ), max );
+
+ ASSERT_FALSE( cloned->getNextChunk( BSON( "a" << 10 << "b" << 0 ), &min, &max ));
+ ASSERT_EQUALS( BSON( "a" << 15 << "b" << 0 ), min );
+ ASSERT_EQUALS( BSON( "a" << 18 << "b" << 0 ), max );
+
+ ASSERT_FALSE( cloned->getNextChunk( BSON( "a" << 15 << "b" << 0 ), &min, &max ));
+ ASSERT_EQUALS( BSON( "a" << 18 << "b" << 0 ), min );
+ ASSERT_EQUALS( BSON( "a" << 20 << "b" << 0 ), max );
+
+ ASSERT( cloned->getNextChunk( BSON( "a" << 18 << "b" << 0 ), &min, &max ));
}
};
diff --git a/src/mongo/s/balance.cpp b/src/mongo/s/balance.cpp
index 2cf9d06d131..7e12e1c47b8 100644
--- a/src/mongo/s/balance.cpp
+++ b/src/mongo/s/balance.cpp
@@ -467,6 +467,7 @@ namespace mongo {
conn.done();
warning() << "Skipping balancing round because data inconsistency"
<< " was detected amongst the config servers." << endl;
+ sleepsecs( sleepTime );
continue;
}
diff --git a/src/mongo/s/commands_admin.cpp b/src/mongo/s/commands_admin.cpp
index 91577d33b97..d7061f6fa86 100644
--- a/src/mongo/s/commands_admin.cpp
+++ b/src/mongo/s/commands_admin.cpp
@@ -663,7 +663,7 @@ namespace mongo {
result << "collectionsharded" << ns;
// only initially move chunks when using a hashed shard key
- if (isHashedShardKey) {
+ if (isHashedShardKey && isEmpty) {
// Reload the new config info. If we created more than one initial chunk, then
// we need to move them around to balance.
diff --git a/src/mongo/s/config.cpp b/src/mongo/s/config.cpp
index b8698a10687..9e042938607 100644
--- a/src/mongo/s/config.cpp
+++ b/src/mongo/s/config.cpp
@@ -34,6 +34,8 @@
#include "mongo/s/type_chunk.h"
#include "mongo/s/type_collection.h"
#include "mongo/s/type_database.h"
+#include "mongo/s/type_locks.h"
+#include "mongo/s/type_lockpings.h"
#include "mongo/s/type_settings.h"
#include "mongo/s/type_shard.h"
#include "mongo/util/net/message.h"
@@ -985,6 +987,16 @@ namespace mongo {
conn->get()->ensureIndex(ShardType::ConfigNS, BSON(ShardType::host() << 1), true);
+ conn->get()->ensureIndex(LocksType::ConfigNS,
+ BSON( LocksType::lockID() << 1 ), true);
+
+ conn->get()->ensureIndex(LockpingsType::ConfigNS,
+ BSON( LockpingsType::ping() << 1 ), false);
+
+ conn->get()->ensureIndex(LocksType::ConfigNS,
+ BSON( LocksType::state() << 1 <<
+ LocksType::process() << 1 ), false);
+
conn->done();
}
catch ( DBException& e ) {
diff --git a/src/mongo/s/d_chunk_manager.cpp b/src/mongo/s/d_chunk_manager.cpp
index 4eb360702bc..98a6d90d341 100644
--- a/src/mongo/s/d_chunk_manager.cpp
+++ b/src/mongo/s/d_chunk_manager.cpp
@@ -426,7 +426,7 @@ namespace mongo {
BSONObj startKey = min;
for ( vector<BSONObj>::const_iterator it = splitKeys.begin() ; it != splitKeys.end() ; ++it ) {
BSONObj split = *it;
- p->_chunksMap[min] = split.getOwned();
+ p->_chunksMap[startKey] = split.getOwned();
p->_chunksMap.insert( make_pair( split.getOwned() , max.getOwned() ) );
p->_version.incMinor();
startKey = split;
diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp
index e6aa728d7a3..5bcfe291519 100644
--- a/src/mongo/s/server.cpp
+++ b/src/mongo/s/server.cpp
@@ -197,6 +197,9 @@ namespace mongo {
signal(SIGTERM, sighandler);
signal(SIGINT, sighandler);
+#if defined(SIGXCPU)
+ signal(SIGXCPU, sighandler);
+#endif
#if defined(SIGQUIT)
signal( SIGQUIT , printStackAndExit );
diff --git a/src/mongo/shell/replsettest.js b/src/mongo/shell/replsettest.js
index a9c8c36b050..6b84da39a06 100644
--- a/src/mongo/shell/replsettest.js
+++ b/src/mongo/shell/replsettest.js
@@ -489,12 +489,13 @@ ReplSetTest.prototype.initiate = function( cfg , initCmd , timeout ) {
}
}
-ReplSetTest.prototype.reInitiate = function() {
+ReplSetTest.prototype.reInitiate = function(timeout) {
var master = this.nodes[0];
var c = master.getDB("local")['system.replset'].findOne();
var config = this.getReplSetConfig();
+ var timeout = timeout || 60000;
config.version = c.version + 1;
- this.initiate( config , 'replSetReconfig' );
+ this.initiate( config , 'replSetReconfig', timeout );
}
ReplSetTest.prototype.getLastOpTimeWritten = function() {
diff --git a/src/mongo/shell/shell_utils_extended.cpp b/src/mongo/shell/shell_utils_extended.cpp
index 1e68882a3bc..2808bab7688 100644
--- a/src/mongo/shell/shell_utils_extended.cpp
+++ b/src/mongo/shell/shell_utils_extended.cpp
@@ -26,6 +26,7 @@
#include "mongo/util/file.h"
#include "mongo/util/md5.hpp"
#include "mongo/util/net/sock.h"
+#include "mongo/util/scopeguard.h"
#include "mongo/util/text.h"
namespace mongo {
@@ -144,6 +145,7 @@ namespace mongo {
stringstream ss;
FILE* f = fopen(e.valuestrsafe(), "rb");
uassert(CANT_OPEN_FILE, "couldn't open file", f );
+ ON_BLOCK_EXIT(fclose, f);
md5digest d;
md5_state_t st;
diff --git a/src/mongo/util/file_allocator.cpp b/src/mongo/util/file_allocator.cpp
index e59bce6934b..7876744f7d5 100644
--- a/src/mongo/util/file_allocator.cpp
+++ b/src/mongo/util/file_allocator.cpp
@@ -39,6 +39,7 @@
#include "mongo/platform/posix_fadvise.h"
#include "mongo/util/mongoutils/str.h"
#include "mongo/util/paths.h"
+#include "mongo/util/processinfo.h"
#include "mongo/util/time_support.h"
#include "mongo/util/timer.h"
@@ -186,6 +187,15 @@ namespace mongo {
size - 1 == lseek(fd, size - 1, SEEK_SET) );
uassert( 10442 , str::stream() << "Unable to allocate new file of size " << size << ' ' << errnoWithDescription(),
1 == write(fd, "", 1) );
+
+ // File expansion is completed here. Do not do the zeroing out on OS-es where there
+ // is no risk of triggering allocation-related bugs such as
+ // http://support.microsoft.com/kb/2731284.
+ //
+ if (!ProcessInfo::isDataFileZeroingNeeded()) {
+ return;
+ }
+
lseek(fd, 0, SEEK_SET);
const long z = 256 * 1024;
diff --git a/src/mongo/util/processinfo.h b/src/mongo/util/processinfo.h
index 8e9044d39e4..03fcdd85993 100644
--- a/src/mongo/util/processinfo.h
+++ b/src/mongo/util/processinfo.h
@@ -92,6 +92,11 @@ namespace mongo {
bool hasNumaEnabled() const { return sysInfo().hasNuma; }
/**
+ * Determine if file zeroing is necessary for newly allocated data files.
+ */
+ static bool isDataFileZeroingNeeded() { return systemInfo->fileZeroNeeded; }
+
+ /**
* Get extra system stats
*/
void appendSystemDetails( BSONObjBuilder& details ) const {
@@ -145,12 +150,19 @@ namespace mongo {
string cpuArch;
bool hasNuma;
BSONObj _extraStats;
+
+ // This is an OS specific value, which determines whether files should be zero-filled
+ // at allocation time in order to avoid Microsoft KB 2731284.
+ //
+ bool fileZeroNeeded;
+
SystemInfo() :
addrSize( 0 ),
memSize( 0 ),
numCores( 0 ),
pageSize( 0 ),
- hasNuma( false ) {
+ hasNuma( false ),
+ fileZeroNeeded (false) {
// populate SystemInfo during construction
collectSystemInfo();
}
diff --git a/src/mongo/util/processinfo_win32.cpp b/src/mongo/util/processinfo_win32.cpp
index 3f42eb12698..d6f88e88a59 100644
--- a/src/mongo/util/processinfo_win32.cpp
+++ b/src/mongo/util/processinfo_win32.cpp
@@ -100,7 +100,7 @@ namespace mongo {
void ProcessInfo::SystemInfo::collectSystemInfo() {
BSONObjBuilder bExtra;
stringstream verstr;
- OSVERSIONINFOEX osvi; // os version
+ OSVERSIONINFOEX osvi; // os version
MEMORYSTATUSEX mse; // memory stats
SYSTEM_INFO ntsysinfo; //system stats
@@ -142,6 +142,15 @@ namespace mongo {
osName += "Windows 7";
else
osName += "Windows Server 2008 R2";
+
+ // Windows 6.1 is either Windows 7 or Windows 2008 R2. There is no SP2 for
+ // either of these two operating systems, but the check will hold if one
+ // were released. This code assumes that SP2 will include fix for
+ // http://support.microsoft.com/kb/2731284.
+ //
+ if ((osvi.wServicePackMajor >= 0) && (osvi.wServicePackMajor < 2)) {
+ fileZeroNeeded = true;
+ }
break;
case 0:
if ( osvi.wProductType == VER_NT_WORKSTATION )
diff --git a/src/mongo/util/version.cpp b/src/mongo/util/version.cpp
index a5622e4dbbb..e27c3843a4a 100644
--- a/src/mongo/util/version.cpp
+++ b/src/mongo/util/version.cpp
@@ -47,7 +47,7 @@ namespace mongo {
* 1.2.3-rc4-pre-
* If you really need to do something else you'll need to fix _versionArray()
*/
- const char versionString[] = "2.4.9";
+ const char versionString[] = "2.4.10";
// See unit test for example outputs
BSONArray toVersionArray(const char* version){
diff --git a/src/third_party/v8/src/spaces-inl.h b/src/third_party/v8/src/spaces-inl.h
index ed78fc7a15f..d84019084cc 100644
--- a/src/third_party/v8/src/spaces-inl.h
+++ b/src/third_party/v8/src/spaces-inl.h
@@ -164,7 +164,7 @@ Page* Page::Initialize(Heap* heap,
Executability executable,
PagedSpace* owner) {
Page* page = reinterpret_cast<Page*>(chunk);
- ASSERT(chunk->size() <= static_cast<size_t>(kPageSize));
+ ASSERT(page->area_size() <= kNonCodeObjectAreaSize);
ASSERT(chunk->owner() == owner);
owner->IncreaseCapacity(page->area_size());
owner->Free(page->area_start(), page->area_size());