Compare commits
55 Commits
SERVER-569
...
r1.8.0-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
460d32f86b | ||
|
|
b2927d9860 | ||
|
|
b3a113564f | ||
|
|
0e97d8b44b | ||
|
|
3bc93cc5dc | ||
|
|
2bc1b84422 | ||
|
|
b28116bafe | ||
|
|
43f5f6f9bc | ||
|
|
ec9dbe2b51 | ||
|
|
085553d8dd | ||
|
|
5d5b9dc17e | ||
|
|
a14508a41e | ||
|
|
3754755c30 | ||
|
|
e451c5699d | ||
|
|
eb3d063c95 | ||
|
|
7a20ea7d74 | ||
|
|
4d75f1be77 | ||
|
|
9d1f1a1fe3 | ||
|
|
c3c2a3d41d | ||
|
|
e521301d18 | ||
|
|
d2749d18ee | ||
|
|
fa09f824ed | ||
|
|
66af39a8b3 | ||
|
|
fe13a93925 | ||
|
|
9f47ba6ca4 | ||
|
|
e3b4054f66 | ||
|
|
e0e5a4061d | ||
|
|
87dd5720e4 | ||
|
|
b1eb83e61c | ||
|
|
f53b65645f | ||
|
|
bbf18b270c | ||
|
|
081b046b72 | ||
|
|
00bee15013 | ||
|
|
72f754439a | ||
|
|
85bff78d00 | ||
|
|
dc65bd51ae | ||
|
|
e5839f0a76 | ||
|
|
28267f6792 | ||
|
|
162418c1dd | ||
|
|
b47f248e0f | ||
|
|
af4f0597fd | ||
|
|
ad4abbc55b | ||
|
|
a0b0d4eb70 | ||
|
|
13608bb283 | ||
|
|
83282b72fa | ||
|
|
caaff8dfbe | ||
|
|
22596b3c06 | ||
|
|
d328f5b1a5 | ||
|
|
09ed6d9098 | ||
|
|
b2963ff3b2 | ||
|
|
bd46051947 | ||
|
|
ed6273ba49 | ||
|
|
f6734a4784 | ||
|
|
d38d0f8f57 | ||
|
|
f6074c8024 |
@@ -37,7 +37,12 @@ namespace mongo {
|
||||
}
|
||||
|
||||
void PoolForHost::done( DBClientBase * c ) {
|
||||
_pool.push(c);
|
||||
if ( _pool.size() >= _maxPerHost ) {
|
||||
delete c;
|
||||
}
|
||||
else {
|
||||
_pool.push(c);
|
||||
}
|
||||
}
|
||||
|
||||
DBClientBase * PoolForHost::get() {
|
||||
@@ -86,6 +91,8 @@ namespace mongo {
|
||||
_created++;
|
||||
}
|
||||
|
||||
unsigned PoolForHost::_maxPerHost = 50;
|
||||
|
||||
// ------ DBConnectionPool ------
|
||||
|
||||
DBConnectionPool pool;
|
||||
|
||||
@@ -57,6 +57,9 @@ namespace mongo {
|
||||
void done( DBClientBase * c );
|
||||
|
||||
void flush();
|
||||
|
||||
static void setMaxPerHost( unsigned max ) { _maxPerHost = max; }
|
||||
static unsigned getMaxPerHost() { return _maxPerHost; }
|
||||
private:
|
||||
|
||||
struct StoredConnection {
|
||||
@@ -71,6 +74,8 @@ namespace mongo {
|
||||
std::stack<StoredConnection> _pool;
|
||||
long long _created;
|
||||
ConnectionString::ConnectionType _type;
|
||||
|
||||
static unsigned _maxPerHost;
|
||||
};
|
||||
|
||||
class DBConnectionHook {
|
||||
|
||||
@@ -183,18 +183,16 @@ namespace mongo {
|
||||
|
||||
|
||||
HostAndPort ReplicaSetMonitor::getMaster() {
|
||||
bool good = false;
|
||||
{
|
||||
scoped_lock lk( _lock );
|
||||
good = _master >= 0 && _nodes[_master].ok;
|
||||
if ( _master >= 0 && _nodes[_master].ok )
|
||||
return _nodes[_master].addr;
|
||||
}
|
||||
|
||||
if ( ! good )
|
||||
_check();
|
||||
|
||||
uassert( 10009 , str::stream() << "ReplicaSetMonitor no master found for set: " << _name , _master >= 0 );
|
||||
|
||||
|
||||
_check();
|
||||
|
||||
scoped_lock lk( _lock );
|
||||
uassert( 10009 , str::stream() << "ReplicaSetMonitor no master found for set: " << _name , _master >= 0 );
|
||||
return _nodes[_master].addr;
|
||||
}
|
||||
|
||||
|
||||
62
db/btree.cpp
62
db/btree.cpp
@@ -1114,16 +1114,17 @@ namespace mongo {
|
||||
|
||||
/** remove a key from the index */
|
||||
bool BtreeBucket::unindex(const DiskLoc thisLoc, IndexDetails& id, const BSONObj& key, const DiskLoc recordLoc ) const {
|
||||
if ( key.objsize() > KeyMax ) {
|
||||
OCCASIONALLY problem() << "unindex: key too large to index, skipping " << id.indexNamespace() << /* ' ' << key.toString() << */ endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
int pos;
|
||||
bool found;
|
||||
DiskLoc loc = locate(id, thisLoc, key, Ordering::make(id.keyPattern()), pos, found, recordLoc, 1);
|
||||
if ( found ) {
|
||||
|
||||
if ( key.objsize() > KeyMax ) {
|
||||
OCCASIONALLY problem() << "unindex: key too large to index but was found for " << id.indexNamespace() << " reIndex suggested" << endl;
|
||||
}
|
||||
|
||||
loc.btreemod()->delKeyAtPos(loc, id, pos, Ordering::make(id.keyPattern()));
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1740,13 +1741,18 @@ namespace mongo {
|
||||
}
|
||||
|
||||
void BtreeBuilder::mayCommitProgressDurably() {
|
||||
RARELY {
|
||||
getDur().commitIfNeeded();
|
||||
if ( getDur().commitIfNeeded() ) {
|
||||
b = cur.btreemod();
|
||||
}
|
||||
}
|
||||
|
||||
void BtreeBuilder::addKey(BSONObj& key, DiskLoc loc) {
|
||||
if ( key.objsize() > KeyMax ) {
|
||||
problem() << "Btree::insert: key too large to index, skipping " << idx.indexNamespace()
|
||||
<< ' ' << key.objsize() << ' ' << key.toString() << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if( !dupsAllowed ) {
|
||||
if( n > 0 ) {
|
||||
int cmp = keyLast.woCompare(key, order);
|
||||
@@ -1760,15 +1766,9 @@ namespace mongo {
|
||||
}
|
||||
|
||||
if ( ! b->_pushBack(loc, key, ordering, DiskLoc()) ) {
|
||||
// no room
|
||||
if ( key.objsize() > KeyMax ) {
|
||||
problem() << "Btree::insert: key too large to index, skipping " << idx.indexNamespace() << ' ' << key.objsize() << ' ' << key.toString() << endl;
|
||||
}
|
||||
else {
|
||||
// bucket was full
|
||||
newBucket();
|
||||
b->pushBack(loc, key, ordering, DiskLoc());
|
||||
}
|
||||
// bucket was full
|
||||
newBucket();
|
||||
b->pushBack(loc, key, ordering, DiskLoc());
|
||||
}
|
||||
n++;
|
||||
mayCommitProgressDurably();
|
||||
@@ -1790,6 +1790,11 @@ namespace mongo {
|
||||
|
||||
DiskLoc xloc = loc;
|
||||
while( !xloc.isNull() ) {
|
||||
if ( getDur().commitIfNeeded() ) {
|
||||
b = cur.btreemod();
|
||||
up = upLoc.btreemod();
|
||||
}
|
||||
|
||||
BtreeBucket *x = xloc.btreemod();
|
||||
BSONObj k;
|
||||
DiskLoc r;
|
||||
@@ -1833,18 +1838,21 @@ namespace mongo {
|
||||
}
|
||||
|
||||
BtreeBuilder::~BtreeBuilder() {
|
||||
if( !committed ) {
|
||||
log(2) << "Rolling back partially built index space" << endl;
|
||||
DiskLoc x = first;
|
||||
while( !x.isNull() ) {
|
||||
DiskLoc next = x.btree()->tempNext();
|
||||
string ns = idx.indexNamespace();
|
||||
theDataFileMgr._deleteRecord(nsdetails(ns.c_str()), ns.c_str(), x.rec(), x);
|
||||
x = next;
|
||||
DESTRUCTOR_GUARD(
|
||||
if( !committed ) {
|
||||
log(2) << "Rolling back partially built index space" << endl;
|
||||
DiskLoc x = first;
|
||||
while( !x.isNull() ) {
|
||||
DiskLoc next = x.btree()->tempNext();
|
||||
string ns = idx.indexNamespace();
|
||||
theDataFileMgr._deleteRecord(nsdetails(ns.c_str()), ns.c_str(), x.rec(), x);
|
||||
x = next;
|
||||
getDur().commitIfNeeded();
|
||||
}
|
||||
assert( idx.head.isNull() );
|
||||
log(2) << "done rollback" << endl;
|
||||
}
|
||||
assert( idx.head.isNull() );
|
||||
log(2) << "done rollback" << endl;
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -169,11 +169,6 @@ namespace mongo {
|
||||
uassert( 13005 , "can't create db, keeps getting closed" , _db );
|
||||
}
|
||||
|
||||
_client->_context = this;
|
||||
_client->_curOp->enter( this );
|
||||
if ( doauth )
|
||||
_auth( lockState );
|
||||
|
||||
switch ( _client->_curOp->getOp() ) {
|
||||
case dbGetMore: // getMore's are special and should be handled else where
|
||||
case dbUpdate: // update & delete check shard version in instance.cpp, so don't check here as well
|
||||
@@ -188,6 +183,11 @@ namespace mongo {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_client->_context = this;
|
||||
_client->_curOp->enter( this );
|
||||
if ( doauth )
|
||||
_auth( lockState );
|
||||
}
|
||||
|
||||
void Client::Context::_auth( int lockState ) {
|
||||
|
||||
@@ -91,6 +91,13 @@ namespace mongo {
|
||||
_c = 0;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* call this if during a yield, the cursor got deleted
|
||||
* if so, we don't want to use the point address
|
||||
*/
|
||||
void deleted() {
|
||||
_c = 0;
|
||||
}
|
||||
~Pointer() { release(); }
|
||||
Pointer(long long cursorid) {
|
||||
recursive_scoped_lock lock(ccmutex);
|
||||
|
||||
@@ -244,6 +244,7 @@ namespace mongo {
|
||||
string temp = ctx.db()->name + ".system.indexes";
|
||||
copy( temp.c_str() , temp.c_str() , /*isindex*/true , logForRepl , false , true , BSON( "ns" << ns ) );
|
||||
}
|
||||
getDur().commitIfNeeded();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -723,7 +723,11 @@ int main(int argc, char* argv[]) {
|
||||
dbExecCommand = argv[0];
|
||||
|
||||
srand(curTimeMicros());
|
||||
#if( BOOST_VERSION >= 104500 )
|
||||
boost::filesystem::path::default_name_check( boost::filesystem2::no_check );
|
||||
#else
|
||||
boost::filesystem::path::default_name_check( boost::filesystem::no_check );
|
||||
#endif
|
||||
|
||||
{
|
||||
unsigned x = 0x12345678;
|
||||
@@ -1099,6 +1103,11 @@ namespace mongo {
|
||||
oss << "Backtrace:" << endl;
|
||||
printStackTrace( oss );
|
||||
rawOut( oss.str() );
|
||||
|
||||
if( cmdLine.dur ) {
|
||||
::exit(EXIT_ABRUPT);
|
||||
}
|
||||
|
||||
dbexit( EXIT_ABRUPT );
|
||||
}
|
||||
|
||||
|
||||
@@ -406,6 +406,8 @@ namespace mongo {
|
||||
t.appendBool( "supported" , false );
|
||||
}
|
||||
|
||||
timeBuilder.appendNumber( "middle of mem" , Listener::getElapsedTimeMillis() - start );
|
||||
|
||||
t.appendNumber( "mapped" , MemoryMappedFile::totalMappedLength() / ( 1024 * 1024 ) );
|
||||
|
||||
t.done();
|
||||
|
||||
31
db/dur.cpp
31
db/dur.cpp
@@ -211,14 +211,14 @@ namespace mongo {
|
||||
return p;
|
||||
}
|
||||
|
||||
void DurableImpl::commitIfNeeded() {
|
||||
#if defined(_DEBUG)
|
||||
commitJob._nSinceCommitIfNeededCall = 0;
|
||||
#endif
|
||||
bool DurableImpl::commitIfNeeded() {
|
||||
DEV commitJob._nSinceCommitIfNeededCall = 0;
|
||||
if (commitJob.bytes() > UncommittedBytesLimit) { // should this also fire if CmdLine::DurAlwaysCommit?
|
||||
stats.curr->_earlyCommits++;
|
||||
groupCommit();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Used in _DEBUG builds to check that we didn't overwrite the last intent
|
||||
@@ -369,7 +369,7 @@ namespace mongo {
|
||||
// faults after remapping, so doing a little bit at a time will avoid big load spikes on
|
||||
// remapping.
|
||||
unsigned long long now = curTimeMicros64();
|
||||
double fraction = (now-lastRemap)/20000000.0;
|
||||
double fraction = (now-lastRemap)/2000000.0;
|
||||
lastRemap = now;
|
||||
|
||||
rwlock lk(MongoFile::mmmutex, false);
|
||||
@@ -522,7 +522,9 @@ namespace mongo {
|
||||
}
|
||||
|
||||
// starvation on read locks could occur. so if read lock acquisition is slow, try to get a
|
||||
// write lock instead. otherwise writes could use too much RAM.
|
||||
// write lock instead. otherwise journaling could be delayed too long (too much data will
|
||||
// not accumulate though, as commitIfNeeded logic will have executed in the meantime if there
|
||||
// has been writes)
|
||||
writelock lk;
|
||||
groupCommit();
|
||||
}
|
||||
@@ -587,18 +589,11 @@ namespace mongo {
|
||||
void recover();
|
||||
|
||||
void releasingWriteLock() {
|
||||
try {
|
||||
#if defined(_DEBUG)
|
||||
commitJob._nSinceCommitIfNeededCall = 0; // implicit commit if needed
|
||||
#endif
|
||||
if (commitJob.bytes() > UncommittedBytesLimit || cmdLine.durOptions & CmdLine::DurAlwaysCommit) {
|
||||
stats.curr->_earlyCommits++;
|
||||
groupCommit();
|
||||
}
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
log() << "exception in dur::releasingWriteLock causing immediate shutdown: " << e.what() << endl;
|
||||
abort(); // based on myTerminate()
|
||||
// implicit commitIfNeeded check on each write unlock
|
||||
DEV commitJob._nSinceCommitIfNeededCall = 0; // implicit commit if needed
|
||||
if( commitJob.bytes() > UncommittedBytesLimit || cmdLine.durOptions & CmdLine::DurAlwaysCommit ) {
|
||||
stats.curr->_earlyCommits++;
|
||||
groupCommit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
7
db/dur.h
7
db/dur.h
@@ -96,8 +96,9 @@ namespace mongo {
|
||||
(like creating an index or update with $atomic) can call this
|
||||
whenever the db is in a sane state and it will prevent commits
|
||||
from growing too large.
|
||||
@return true if commited
|
||||
*/
|
||||
virtual void commitIfNeeded() = 0;
|
||||
virtual bool commitIfNeeded() = 0;
|
||||
|
||||
/** Declare write intent for a DiskLoc. @see DiskLoc::writing() */
|
||||
inline DiskLoc& writingDiskLoc(DiskLoc& d) { return *((DiskLoc*) writingPtr(&d, sizeof(d))); }
|
||||
@@ -172,7 +173,7 @@ namespace mongo {
|
||||
void createdFile(string filename, unsigned long long len) { }
|
||||
bool awaitCommit() { return false; }
|
||||
bool commitNow() { return false; }
|
||||
void commitIfNeeded() { }
|
||||
bool commitIfNeeded() { return false; }
|
||||
void setNoJournal(void *dst, void *src, unsigned len);
|
||||
void syncDataAndTruncateJournal() {}
|
||||
};
|
||||
@@ -185,7 +186,7 @@ namespace mongo {
|
||||
void createdFile(string filename, unsigned long long len);
|
||||
bool awaitCommit();
|
||||
bool commitNow();
|
||||
void commitIfNeeded();
|
||||
bool commitIfNeeded();
|
||||
void setNoJournal(void *dst, void *src, unsigned len);
|
||||
void syncDataAndTruncateJournal();
|
||||
};
|
||||
|
||||
@@ -262,6 +262,7 @@ namespace mongo {
|
||||
log() << "warning caught exception in preallocateFiles, continuing" << endl;
|
||||
}
|
||||
}
|
||||
j.open();
|
||||
}
|
||||
|
||||
void removeOldJournalFile(path p) {
|
||||
@@ -515,7 +516,7 @@ namespace mongo {
|
||||
|
||||
scoped_lock lk(_curLogFileMutex);
|
||||
|
||||
if ( inShutdown() )
|
||||
if ( inShutdown() || !_curLogFile )
|
||||
return;
|
||||
|
||||
j.updateLSNFile();
|
||||
|
||||
@@ -63,10 +63,10 @@ namespace mongo {
|
||||
_open();
|
||||
}
|
||||
|
||||
private:
|
||||
/** open a journal file to journal operations to. */
|
||||
void open();
|
||||
|
||||
private:
|
||||
void _open();
|
||||
void closeCurrentJournalFile();
|
||||
void removeUnneededJournalFiles();
|
||||
|
||||
@@ -73,16 +73,17 @@ namespace mongo {
|
||||
if( m.count(u) ) {
|
||||
uasserted(13531, str::stream() << "unexpected files in journal directory " << dir.string() << " : " << fileName);
|
||||
}
|
||||
if( !m.empty() && !m.count(u-1) ) {
|
||||
uasserted(13532,
|
||||
str::stream() << "unexpected file in journal directory " << dir.string()
|
||||
<< " : " << fileName << " : can't find its preceeding file");
|
||||
}
|
||||
m.insert( pair<unsigned,path>(u,filepath) );
|
||||
}
|
||||
}
|
||||
for( map<unsigned,path>::iterator i = m.begin(); i != m.end(); ++i )
|
||||
for( map<unsigned,path>::iterator i = m.begin(); i != m.end(); ++i ) {
|
||||
if( i != m.begin() && m.count(i->first - 1) == 0 ) {
|
||||
uasserted(13532,
|
||||
str::stream() << "unexpected file in journal directory " << dir.string()
|
||||
<< " : " << filesystem::path(i->second).leaf() << " : can't find its preceeding file");
|
||||
}
|
||||
files.push_back(i->second);
|
||||
}
|
||||
}
|
||||
|
||||
/** read through the memory mapped data of a journal file (journal/j._<n> file)
|
||||
@@ -186,8 +187,10 @@ namespace mongo {
|
||||
}
|
||||
|
||||
RecoveryJob::~RecoveryJob() {
|
||||
if( !_mmfs.empty() )
|
||||
close();
|
||||
DESTRUCTOR_GUARD(
|
||||
if( !_mmfs.empty() )
|
||||
close();
|
||||
)
|
||||
}
|
||||
|
||||
void RecoveryJob::close() {
|
||||
@@ -445,8 +448,8 @@ namespace mongo {
|
||||
}
|
||||
} brunittest;
|
||||
|
||||
|
||||
RecoveryJob RecoveryJob::_instance;
|
||||
// can't free at termination because order of destruction of global vars is arbitrary
|
||||
RecoveryJob &RecoveryJob::_instance = *(new RecoveryJob());
|
||||
|
||||
} // namespace dur
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace mongo {
|
||||
*/
|
||||
class RecoveryJob : boost::noncopyable {
|
||||
public:
|
||||
RecoveryJob() :_lastDataSyncedFromLastRun(0), _mx("recovery") { _lastSeqMentionedInConsoleLog = 1; }
|
||||
RecoveryJob() :_lastDataSyncedFromLastRun(0), _mx("recovery"), _recovering(false) { _lastSeqMentionedInConsoleLog = 1; }
|
||||
void go(vector<path>& files);
|
||||
~RecoveryJob();
|
||||
void processSection(const void *, unsigned len);
|
||||
@@ -39,7 +39,7 @@ namespace mongo {
|
||||
|
||||
bool _recovering; // are we in recovery or WRITETODATAFILES
|
||||
|
||||
static RecoveryJob _instance;
|
||||
static RecoveryJob &_instance;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,11 +342,7 @@ namespace mongo {
|
||||
|
||||
bool MongoMMF::create(string fname, unsigned long long& len, bool sequentialHint) {
|
||||
setPath(fname);
|
||||
bool preExisting = MemoryMappedFile::exists(fname.c_str());
|
||||
_view_write = map(fname.c_str(), len, sequentialHint ? SEQUENTIAL : 0);
|
||||
if( cmdLine.dur && _view_write && !preExisting ) {
|
||||
getDur().createdFile(fname, len);
|
||||
}
|
||||
return finishOpening();
|
||||
}
|
||||
|
||||
|
||||
@@ -182,6 +182,7 @@ namespace mongo {
|
||||
maybeMkdir();
|
||||
unsigned long long l = lenForNewNsFiles;
|
||||
if( f.create(pathString, l, true) ) {
|
||||
getDur().createdFile(pathString, l); // always a new file
|
||||
len = l;
|
||||
assert( len == lenForNewNsFiles );
|
||||
p = f.getView();
|
||||
@@ -194,6 +195,7 @@ namespace mongo {
|
||||
dbexit( EXIT_FS );
|
||||
}
|
||||
|
||||
|
||||
assert( len <= 0x7fffffff );
|
||||
ht = new HashTable<Namespace,NamespaceDetails>(p, (int) len, "namespace index");
|
||||
if( checkNsFilesOnLoad )
|
||||
|
||||
@@ -252,6 +252,10 @@ namespace mongo {
|
||||
while ( size > 0 ) {
|
||||
int max = MongoDataFile::maxSize() - DataFileHeader::HeaderSize;
|
||||
int desiredExtentSize = (int) (size > max ? max : size);
|
||||
if ( desiredExtentSize < Extent::minSize() ) {
|
||||
desiredExtentSize = Extent::minSize();
|
||||
}
|
||||
desiredExtentSize &= 0xffffff00;
|
||||
Extent *e = database->allocExtent( ns, desiredExtentSize, newCapped );
|
||||
size -= e->length;
|
||||
}
|
||||
@@ -403,7 +407,7 @@ namespace mongo {
|
||||
uassert( 10084 , "can't map file memory - mongo requires 64 bit build for larger datasets", _mb != 0);
|
||||
else
|
||||
uassert( 10085 , "can't map file memory", _mb != 0);
|
||||
header()->init(fileNo, size);
|
||||
header()->init(fileNo, size, filename);
|
||||
}
|
||||
|
||||
void MongoDataFile::flush( bool sync ) {
|
||||
@@ -435,11 +439,11 @@ namespace mongo {
|
||||
|
||||
Extent* MongoDataFile::createExtent(const char *ns, int approxSize, bool newCapped, int loops) {
|
||||
massert( 10357 , "shutdown in progress", ! inShutdown() );
|
||||
massert( 10358 , "bad new extent size", approxSize >= 0 && approxSize <= Extent::maxSize() );
|
||||
massert( 10358 , "bad new extent size", approxSize >= Extent::minSize() && approxSize <= Extent::maxSize() );
|
||||
massert( 10359 , "header==0 on new extent: 32 bit mmap space exceeded?", header() ); // null if file open failed
|
||||
int ExtentSize = approxSize <= header()->unusedLength ? approxSize : header()->unusedLength;
|
||||
DiskLoc loc;
|
||||
if ( ExtentSize <= 0 ) {
|
||||
if ( ExtentSize < Extent::minSize() ) {
|
||||
/* not there could be a lot of looping here is db just started and
|
||||
no files are open yet. we might want to do something about that. */
|
||||
if ( loops > 8 ) {
|
||||
@@ -1187,7 +1191,9 @@ namespace mongo {
|
||||
op->setMessage( "index: (3/3) btree-middle" );
|
||||
log(t.seconds() > 10 ? 0 : 1 ) << "\t done building bottom layer, going to commit" << endl;
|
||||
btBuilder.commit();
|
||||
wassert( btBuilder.getn() == nkeys || dropDups );
|
||||
if ( btBuilder.getn() != nkeys && ! dropDups ) {
|
||||
warning() << "not all entries were added to the index, probably some keys were too large" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
log(1) << "\t fastBuildIndex dupsToDrop:" << dupsToDrop.size() << endl;
|
||||
|
||||
@@ -272,6 +272,7 @@ namespace mongo {
|
||||
Extent* getPrevExtent() { return xprev.isNull() ? 0 : DataFileMgr::getExtent(xprev); }
|
||||
|
||||
static int maxSize();
|
||||
static int minSize() { return 0x100; }
|
||||
/**
|
||||
* @param len lengt of record we need
|
||||
* @param lastRecord size of last extent which is a factor in next extent size
|
||||
@@ -325,11 +326,12 @@ namespace mongo {
|
||||
|
||||
bool uninitialized() const { return version == 0; }
|
||||
|
||||
void init(int fileno, int filelength) {
|
||||
void init(int fileno, int filelength, const char* filename) {
|
||||
if ( uninitialized() ) {
|
||||
if( !(filelength > 32768 ) ) {
|
||||
massert(13640, str::stream() << "DataFileHeader looks corrupt at file open filelength:" << filelength << " fileno:" << fileno, false);
|
||||
}
|
||||
getDur().createdFile(filename, filelength);
|
||||
assert( HeaderSize == 8192 );
|
||||
DataFileHeader *h = getDur().writing(this);
|
||||
h->fileLength = filelength;
|
||||
|
||||
10
db/query.cpp
10
db/query.cpp
@@ -380,8 +380,16 @@ namespace mongo {
|
||||
}
|
||||
}
|
||||
c->advance();
|
||||
}
|
||||
|
||||
if ( ! cc->yieldSometimes() ) {
|
||||
ClientCursor::erase(cursorid);
|
||||
cursorid = 0;
|
||||
cc = 0;
|
||||
p.deleted();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( cc ) {
|
||||
cc->updateLocation();
|
||||
cc->mayUpgradeStorage();
|
||||
|
||||
@@ -1426,6 +1426,8 @@ namespace mongo {
|
||||
break;
|
||||
}
|
||||
op = oplogReader.next();
|
||||
|
||||
getDur().commitIfNeeded();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +143,8 @@ namespace mongo {
|
||||
// simple progress metering
|
||||
log() << "replSet initialSyncOplogApplication " << n << rsLog;
|
||||
}
|
||||
|
||||
getDur().commitIfNeeded();
|
||||
}
|
||||
catch (DBException& e) {
|
||||
if( e.getCode() == 11000 || e.getCode() == 11001 ) {
|
||||
|
||||
@@ -44,6 +44,9 @@ namespace mongo {
|
||||
}
|
||||
|
||||
void Top::record( const string& ns , int op , int lockType , long long micros , bool command ) {
|
||||
if ( ns[0] == '?' )
|
||||
return;
|
||||
|
||||
//cout << "record: " << ns << "\t" << op << "\t" << command << endl;
|
||||
scoped_lock lk(_lock);
|
||||
|
||||
|
||||
6
debian/changelog
vendored
6
debian/changelog
vendored
@@ -1,3 +1,9 @@
|
||||
mongodb (1.8.0-rc1) unstable; urgency=low
|
||||
|
||||
* see http://jira.mongodb.org/browse/SERVER/fixforversion/10246
|
||||
|
||||
-- Richard Kreuter <richard@10gen.com> Tue, 1 Mar 2011 16:56:28 -0500
|
||||
|
||||
mongodb (1.8.0-rc0) unstable; urgency=low
|
||||
|
||||
* see http://jira.mongodb.org/browse/SERVER/fixforversion/10245
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = MongoDB
|
||||
PROJECT_NUMBER = 1.8.0-rc0
|
||||
PROJECT_NUMBER = 1.8.0-rc2
|
||||
OUTPUT_DIRECTORY = docs/doxygen
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
@@ -32,9 +32,14 @@ f.ensureIndex( { x: 1 , y: 1 } );
|
||||
assert.eq( 0 , f.count() , "2. initial count should be zero" );
|
||||
|
||||
f.save( { x: 1 , y : 1 } );
|
||||
f.save( { y: 2 } );
|
||||
assert.eq( 2 , f.count() , "2. count after initial insert should be 2" );
|
||||
f.save( { x: null , y : 1 } );
|
||||
|
||||
res = db.runCommand( { checkShardingIndex: "test.jstests_shardingindex" , keyPattern: {x:1, y:1} , force: true });
|
||||
assert.eq( false , res.ok , "2a" );
|
||||
assert.eq( true , res.ok , "2a " + tojson(res) );
|
||||
|
||||
f.save( { y: 2 } );
|
||||
assert.eq( 3 , f.count() , "2. count after initial insert should be 3" );
|
||||
res = db.runCommand( { checkShardingIndex: "test.jstests_shardingindex" , keyPattern: {x:1, y:1} , force: true });
|
||||
assert.eq( false , res.ok , "2b " + tojson(res) );
|
||||
|
||||
print("PASSED");
|
||||
|
||||
@@ -5,12 +5,9 @@ coll.drop();
|
||||
|
||||
coll.ensureIndex({"k": 1, "v": 1});
|
||||
coll.insert({k: "x", v: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"});
|
||||
/* TODO inconsistent behavior w/ too large to index - this fails but the next assert works.
|
||||
* SERVER-1716
|
||||
* assert.eq(1, coll.find({"k": "x"}).count());
|
||||
*/
|
||||
assert.eq(0, coll.find({"k": "x"}).count()); // SERVER-1716
|
||||
|
||||
coll.dropIndexes();
|
||||
coll.ensureIndex({"k": 1, "v": 1});
|
||||
|
||||
assert.eq(1, coll.find({"k": "x"}).count());
|
||||
assert.eq(0, coll.find({"k": "x"}).count());
|
||||
|
||||
@@ -175,7 +175,7 @@ assert( ! s.admin.runCommand( { shardcollection : "test.foo9" , key : { a : 1 }
|
||||
// --- listDatabases ---
|
||||
|
||||
r = db.getMongo().getDBs()
|
||||
assert.eq( 4 , r.databases.length , "listDatabases 1 : " + tojson( r ) )
|
||||
assert.eq( 3 , r.databases.length , "listDatabases 1 : " + tojson( r ) )
|
||||
assert.lt( 10000 , r.totalSize , "listDatabases 2 : " + tojson( r ) );
|
||||
|
||||
s.stop()
|
||||
|
||||
11
jstests/slowNightly/newcollection2.js
Normal file
11
jstests/slowNightly/newcollection2.js
Normal file
@@ -0,0 +1,11 @@
|
||||
// Alocate collection forcing just a small size remainder in 2nd extent
|
||||
|
||||
port = allocatePorts( 1 )[ 0 ]
|
||||
var baseName = "jstests_disk_newcollection2";
|
||||
var m = startMongod( "--noprealloc", "--smallfiles", "--port", port, "--dbpath", "/data/db/" + baseName );
|
||||
db = m.getDB( "test" );
|
||||
|
||||
db.createCollection( baseName, {size:0x1FFC0000-0x10-8192} );
|
||||
var v = db[ baseName ].validate();
|
||||
printjson( v );
|
||||
assert( v.valid );
|
||||
@@ -43,6 +43,15 @@ function diff(){
|
||||
assert.lt( 20 , diff() , "big differential here" );
|
||||
print( diff() )
|
||||
|
||||
{
|
||||
// quick test for SERVER-2686
|
||||
var mydbs = db.getMongo().getDBs().databases;
|
||||
for ( var i=0; i<mydbs.length; i++ ) {
|
||||
assert( mydbs[i].name != "local" , "mongos listDatabases can't return local" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
assert.soon( function(){
|
||||
var d = diff();
|
||||
return d < 5;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: mongo
|
||||
Version: 1.8.0-rc0
|
||||
Version: 1.8.0-rc1
|
||||
Release: mongodb_1%{?dist}
|
||||
Summary: mongo client shell and tools
|
||||
License: AGPL 3.0
|
||||
|
||||
@@ -275,6 +275,15 @@ namespace mongo {
|
||||
while ( ! inShutdown() ) {
|
||||
|
||||
try {
|
||||
|
||||
// first make sure we should even be running
|
||||
if ( ! grid.shouldBalance() ) {
|
||||
log(1) << "skipping balancing round because balancing is disabled" << endl;
|
||||
sleepsecs( 30 );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
ScopedDbConnection conn( config );
|
||||
|
||||
_ping( conn.conn() );
|
||||
@@ -294,14 +303,6 @@ namespace mongo {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! grid.shouldBalance() ) {
|
||||
log(1) << "skipping balancing round because balancing is disabled" << endl;;
|
||||
conn.done();
|
||||
|
||||
sleepsecs( 30 );
|
||||
continue;
|
||||
}
|
||||
|
||||
log(1) << "*** start balancing round" << endl;
|
||||
|
||||
vector<CandidateChunkPtr> candidateChunks;
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace mongo {
|
||||
|
||||
bool BalancerPolicy::isDraining( BSONObj limits ) {
|
||||
BSONElement draining = limits[ ShardFields::draining.name() ];
|
||||
if ( draining.eoo() || ! draining.Bool() ) {
|
||||
if ( draining.eoo() || ! draining.trueValue() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace mongo {
|
||||
|
||||
bool BalancerPolicy::hasOpsQueued( BSONObj limits ) {
|
||||
BSONElement opsQueued = limits[ LimitsFields::hasOpsQueued.name() ];
|
||||
if ( opsQueued.eoo() || ! opsQueued.Bool() ) {
|
||||
if ( opsQueued.eoo() || ! opsQueued.trueValue() ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -534,7 +534,7 @@ namespace mongo {
|
||||
result.append( "cause" , res );
|
||||
return false;
|
||||
}
|
||||
|
||||
config->getChunkManager( ns , true );
|
||||
return true;
|
||||
}
|
||||
} splitCollectionCmd;
|
||||
@@ -959,6 +959,13 @@ namespace mongo {
|
||||
BSONArrayBuilder bb( result.subarrayStart( "databases" ) );
|
||||
for ( map<string,long long>::iterator i=sizes.begin(); i!=sizes.end(); ++i ) {
|
||||
string name = i->first;
|
||||
|
||||
if ( name == "local" ) {
|
||||
// we don't return local
|
||||
// since all shards have their own independant local
|
||||
continue;
|
||||
}
|
||||
|
||||
long long size = i->second;
|
||||
totalSize += size;
|
||||
|
||||
|
||||
@@ -1162,7 +1162,7 @@ namespace mongo {
|
||||
string system_indexes = cc().database()->name + ".system.indexes";
|
||||
for ( unsigned i=0; i<all.size(); i++ ) {
|
||||
BSONObj idx = all[i];
|
||||
theDataFileMgr.insert( system_indexes.c_str() , idx.objdata() , idx.objsize() );
|
||||
theDataFileMgr.insertAndLog( system_indexes.c_str() , idx );
|
||||
}
|
||||
|
||||
timing.done(1);
|
||||
|
||||
118
s/d_split.cpp
118
s/d_split.cpp
@@ -178,18 +178,37 @@ namespace mongo {
|
||||
}
|
||||
|
||||
// for now, the only check is that all shard keys are filled
|
||||
// null is ok,
|
||||
// TODO if $exist for nulls were picking the index, it could be used instead efficiently
|
||||
while ( cc->ok() ) {
|
||||
BSONObj currKey = c->currKey();
|
||||
BSONForEach(key, currKey) {
|
||||
if ( key.type() == jstNULL ) {
|
||||
ostringstream os;
|
||||
os << "found null value in key " << bc->prettyKey( currKey );
|
||||
log() << "checkShardingIndex for '" << ns << "' failed: " << os.str() << endl;
|
||||
|
||||
BSONObjIterator i( currKey );
|
||||
int n = 0;
|
||||
while ( i.more() ) {
|
||||
BSONElement key = i.next();
|
||||
n++;
|
||||
|
||||
errmsg = os.str();
|
||||
return false;
|
||||
}
|
||||
if ( key.type() && key.type() != jstNULL )
|
||||
continue;
|
||||
|
||||
BSONObj obj = c->current();
|
||||
BSONObjIterator j( keyPattern );
|
||||
BSONElement real;
|
||||
for ( int x=0; x<n; x++ )
|
||||
real = j.next();
|
||||
|
||||
real = obj.getFieldDotted( real.fieldName() );
|
||||
|
||||
if ( real.type() )
|
||||
continue;
|
||||
|
||||
ostringstream os;
|
||||
os << "found null value in key " << bc->prettyKey( currKey ) << " for doc: " << real["_id"];
|
||||
log() << "checkShardingIndex for '" << ns << "' failed: " << os.str() << endl;
|
||||
|
||||
errmsg = os.str();
|
||||
return false;
|
||||
}
|
||||
cc->advance();
|
||||
}
|
||||
@@ -353,48 +372,61 @@ namespace mongo {
|
||||
// at the end. If a key appears more times than entries allowed on a chunk, we issue a warning and
|
||||
// split on the following key.
|
||||
set<BSONObj> tooFrequentKeys;
|
||||
splitKeys.push_back( c->currKey() );
|
||||
while ( cc->ok() ) {
|
||||
currCount++;
|
||||
BSONObj currKey = c->currKey();
|
||||
|
||||
DEV assert( currKey.woCompare( max ) <= 0 );
|
||||
|
||||
if ( currCount > keyCount ) {
|
||||
// Do not use this split key if it is the same used in the previous split point.
|
||||
if ( currKey.woCompare( splitKeys.back() ) == 0 ) {
|
||||
tooFrequentKeys.insert( currKey.getOwned() );
|
||||
splitKeys.push_back( c->currKey().getOwned() );
|
||||
while ( 1 ) {
|
||||
while ( cc->ok() ) {
|
||||
currCount++;
|
||||
BSONObj currKey = c->currKey();
|
||||
|
||||
DEV assert( currKey.woCompare( max ) <= 0 );
|
||||
|
||||
if ( currCount > keyCount ) {
|
||||
// Do not use this split key if it is the same used in the previous split point.
|
||||
if ( currKey.woCompare( splitKeys.back() ) == 0 ) {
|
||||
tooFrequentKeys.insert( currKey.getOwned() );
|
||||
|
||||
}
|
||||
else {
|
||||
splitKeys.push_back( currKey.getOwned() );
|
||||
currCount = 0;
|
||||
numChunks++;
|
||||
|
||||
LOG(4) << "picked a split key: " << bc->prettyKey( currKey ) << endl;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
splitKeys.push_back( currKey.getOwned() );
|
||||
currCount = 0;
|
||||
numChunks++;
|
||||
|
||||
LOG(4) << "picked a split key: " << bc->prettyKey( currKey ) << endl;
|
||||
|
||||
cc->advance();
|
||||
|
||||
// Stop if we have enough split points.
|
||||
if ( maxSplitPoints && ( numChunks >= maxSplitPoints ) ) {
|
||||
log() << "max number of requested split points reached (" << numChunks
|
||||
<< ") before the end of chunk " << ns << " " << min << " -->> " << max
|
||||
<< endl;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cc->advance();
|
||||
|
||||
// Stop if we have enough split points.
|
||||
if ( maxSplitPoints && ( numChunks >= maxSplitPoints ) ) {
|
||||
log() << "max number of requested split points reached (" << numChunks
|
||||
<< ") before the end of chunk " << ns << " " << min << " -->> " << max
|
||||
<< endl;
|
||||
break;
|
||||
if ( ! cc->yieldSometimes() ) {
|
||||
// we were near and and got pushed to the end
|
||||
// i think returning the splits we've already found is fine
|
||||
|
||||
// don't use the btree cursor pointer to acces keys beyond this point but ok
|
||||
// to use it for format the keys we've got already
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! cc->yieldSometimes() ) {
|
||||
// we were near and and got pushed to the end
|
||||
// i think returning the splits we've already found is fine
|
||||
|
||||
// don't use the btree cursor pointer to acces keys beyond this point but ok
|
||||
// to use it for format the keys we've got already
|
||||
|
||||
if ( splitKeys.size() > 1 || ! force )
|
||||
break;
|
||||
}
|
||||
|
||||
force = false;
|
||||
keyCount = currCount / 2;
|
||||
currCount = 0;
|
||||
log() << "splitVector doing another cycle because of force, keyCount now: " << keyCount << endl;
|
||||
|
||||
c.reset( new BtreeCursor( d , d->idxNo(*idx) , *idx , min , max , false , 1 ) );
|
||||
cc.reset( new ClientCursor( QueryOption_NoCursorTimeout , c , ns ) );
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
171
s/d_state.cpp
171
s/d_state.cpp
@@ -60,6 +60,7 @@ namespace mongo {
|
||||
}
|
||||
|
||||
void ShardingState::gotShardName( const string& name ) {
|
||||
scoped_lock lk(_mutex);
|
||||
if ( _shardName.size() == 0 ) {
|
||||
// TODO SERVER-2299 verify the name is sound w.r.t IPs
|
||||
_shardName = name;
|
||||
@@ -78,7 +79,7 @@ namespace mongo {
|
||||
}
|
||||
|
||||
void ShardingState::gotShardHost( string host ) {
|
||||
|
||||
scoped_lock lk(_mutex);
|
||||
size_t slash = host.find( '/' );
|
||||
if ( slash != string::npos )
|
||||
host = host.substr( 0 , slash );
|
||||
@@ -386,79 +387,128 @@ namespace mongo {
|
||||
help << " example: { setShardVersion : 'alleyinsider.foo' , version : 1 , configdb : '' } ";
|
||||
}
|
||||
|
||||
virtual LockType locktype() const { return WRITE; } // TODO: figure out how to make this not need to lock
|
||||
virtual LockType locktype() const { return NONE; }
|
||||
|
||||
bool checkConfigOrInit( const string& configdb , bool authoritative , string& errmsg , BSONObjBuilder& result , bool locked=false ) const {
|
||||
if ( configdb.size() == 0 ) {
|
||||
errmsg = "no configdb";
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( shardingState.enabled() ) {
|
||||
if ( configdb == shardingState.getConfigServer() )
|
||||
return true;
|
||||
|
||||
result.append( "configdb" , BSON( "stored" << shardingState.getConfigServer() <<
|
||||
"given" << configdb ) );
|
||||
errmsg = "specified a different configdb!";
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! authoritative ) {
|
||||
result.appendBool( "need_authoritative" , true );
|
||||
errmsg = "first setShardVersion";
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( locked ) {
|
||||
shardingState.enable( configdb );
|
||||
configServer.init( configdb );
|
||||
return true;
|
||||
}
|
||||
|
||||
dblock lk;
|
||||
return checkConfigOrInit( configdb , authoritative , errmsg , result , true );
|
||||
}
|
||||
|
||||
bool checkMongosID( ShardedConnectionInfo* info, const BSONElement& id, string errmsg ) {
|
||||
if ( id.type() != jstOID ) {
|
||||
// TODO: fix this
|
||||
//errmsg = "need serverID to be an OID";
|
||||
//return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
OID clientId = id.__oid();
|
||||
if ( ! info->hasID() ) {
|
||||
info->setID( clientId );
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( clientId != info->getID() ) {
|
||||
errmsg = "server id has changed!";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool run(const string& , BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool) {
|
||||
|
||||
// Steps
|
||||
// 1. check basic config
|
||||
// 2. extract params from command
|
||||
// 3. fast check
|
||||
// 4. slow check (LOCKS)
|
||||
|
||||
// step 1
|
||||
|
||||
lastError.disableForCommand();
|
||||
ShardedConnectionInfo* info = ShardedConnectionInfo::get( true );
|
||||
|
||||
bool authoritative = cmdObj.getBoolField( "authoritative" );
|
||||
|
||||
// check config server is ok or enable sharding
|
||||
if ( ! checkConfigOrInit( cmdObj["configdb"].valuestrsafe() , authoritative , errmsg , result ) )
|
||||
return false;
|
||||
|
||||
string configdb = cmdObj["configdb"].valuestrsafe();
|
||||
{
|
||||
// configdb checking
|
||||
if ( configdb.size() == 0 ) {
|
||||
errmsg = "no configdb";
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( shardingState.enabled() ) {
|
||||
if ( configdb != shardingState.getConfigServer() ) {
|
||||
errmsg = "specified a different configdb!";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( ! authoritative ) {
|
||||
result.appendBool( "need_authoritative" , true );
|
||||
errmsg = "first setShardVersion";
|
||||
return false;
|
||||
}
|
||||
shardingState.enable( configdb );
|
||||
configServer.init( configdb );
|
||||
}
|
||||
}
|
||||
|
||||
// check shard name/hosts are correct
|
||||
if ( cmdObj["shard"].type() == String ) {
|
||||
shardingState.gotShardName( cmdObj["shard"].String() );
|
||||
shardingState.gotShardHost( cmdObj["shardHost"].String() );
|
||||
}
|
||||
|
||||
{
|
||||
// setting up ids
|
||||
if ( cmdObj["serverID"].type() != jstOID ) {
|
||||
// TODO: fix this
|
||||
//errmsg = "need serverID to be an OID";
|
||||
//return 0;
|
||||
}
|
||||
else {
|
||||
OID clientId = cmdObj["serverID"].__oid();
|
||||
if ( ! info->hasID() ) {
|
||||
info->setID( clientId );
|
||||
}
|
||||
else if ( clientId != info->getID() ) {
|
||||
errmsg = "server id has changed!";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long long version = extractVersion( cmdObj["version"] , errmsg );
|
||||
|
||||
if ( errmsg.size() ) {
|
||||
|
||||
// make sure we have the mongos id for writebacks
|
||||
if ( ! checkMongosID( info , cmdObj["serverID"] , errmsg ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
// step 2
|
||||
|
||||
string ns = cmdObj["setShardVersion"].valuestrsafe();
|
||||
if ( ns.size() == 0 ) {
|
||||
errmsg = "need to speciy fully namespace";
|
||||
errmsg = "need to speciy namespace";
|
||||
return false;
|
||||
}
|
||||
|
||||
const ConfigVersion version = extractVersion( cmdObj["version"] , errmsg );
|
||||
if ( errmsg.size() )
|
||||
return false;
|
||||
|
||||
// step 3
|
||||
|
||||
const ConfigVersion oldVersion = info->getVersion(ns);
|
||||
const ConfigVersion globalVersion = shardingState.getVersion(ns);
|
||||
|
||||
result.appendTimestamp( "oldVersion" , oldVersion );
|
||||
|
||||
if ( globalVersion > 0 && version > 0 ) {
|
||||
// this means there is no reset going on an either side
|
||||
// so its safe to make some assuptions
|
||||
|
||||
if ( version == globalVersion ) {
|
||||
// mongos and mongod agree!
|
||||
if ( oldVersion != version ) {
|
||||
assert( oldVersion < globalVersion );
|
||||
info->setVersion( ns , version );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// step 4
|
||||
dblock setShardVersionLock; // TODO: can we get rid of this??
|
||||
|
||||
if ( oldVersion > 0 && globalVersion == 0 ) {
|
||||
// this had been reset
|
||||
info->setVersion( ns , 0 );
|
||||
@@ -475,7 +525,6 @@ namespace mongo {
|
||||
result.appendBool( "need_authoritative" , true );
|
||||
result.append( "ns" , ns );
|
||||
result.appendTimestamp( "globalVersion" , globalVersion );
|
||||
result.appendTimestamp( "oldVersion" , oldVersion );
|
||||
errmsg = "dropping needs to be authoritative";
|
||||
return false;
|
||||
}
|
||||
@@ -491,7 +540,6 @@ namespace mongo {
|
||||
if ( version < oldVersion ) {
|
||||
errmsg = "you already have a newer version of collection '" + ns + "'";
|
||||
result.append( "ns" , ns );
|
||||
result.appendTimestamp( "oldVersion" , oldVersion );
|
||||
result.appendTimestamp( "newVersion" , version );
|
||||
result.appendTimestamp( "globalVersion" , globalVersion );
|
||||
return false;
|
||||
@@ -510,7 +558,7 @@ namespace mongo {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( globalVersion == 0 && ! cmdObj.getBoolField( "authoritative" ) ) {
|
||||
if ( globalVersion == 0 && ! authoritative ) {
|
||||
// need authoritative for first look
|
||||
result.append( "ns" , ns );
|
||||
result.appendBool( "need_authoritative" , true );
|
||||
@@ -518,6 +566,7 @@ namespace mongo {
|
||||
return false;
|
||||
}
|
||||
|
||||
Timer relockTime;
|
||||
{
|
||||
dbtemprelease unlock;
|
||||
|
||||
@@ -530,11 +579,11 @@ namespace mongo {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( relockTime.millis() >= ( cmdLine.slowMS - 10 ) ) {
|
||||
log() << "setShardVersion - relocking slow: " << relockTime.millis() << endl;
|
||||
}
|
||||
|
||||
info->setVersion( ns , version );
|
||||
result.appendTimestamp( "oldVersion" , oldVersion );
|
||||
result.append( "ok" , 1 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -635,10 +684,10 @@ namespace mongo {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isWriteOp && version.majorVersion() == clientVersion.majorVersion() ) {
|
||||
if ( version.majorVersion() == clientVersion.majorVersion() ) {
|
||||
// this means there was just a split
|
||||
// since on a split w/o a migrate this server is ok
|
||||
// going to accept write
|
||||
// going to accept
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -769,8 +769,8 @@ DB.prototype.listCommands = function(){
|
||||
}
|
||||
}
|
||||
|
||||
DB.prototype.printShardingStatus = function(){
|
||||
printShardingStatus( this.getSiblingDB( "config" ) );
|
||||
DB.prototype.printShardingStatus = function( verbose ){
|
||||
printShardingStatus( this.getSiblingDB( "config" ) , verbose );
|
||||
}
|
||||
|
||||
DB.autocomplete = function(obj){
|
||||
|
||||
@@ -478,7 +478,7 @@ printShardingStatus = function( configDB , verbose ){
|
||||
output( "\t\t\t\t" + z.shard + "\t" + z.nChunks );
|
||||
} )
|
||||
|
||||
if ( totalChunks < 1000 || verbose ){
|
||||
if ( totalChunks < 20 || verbose ){
|
||||
configDB.chunks.find( { "ns" : coll._id } ).sort( { min : 1 } ).forEach(
|
||||
function(chunk){
|
||||
output( "\t\t\t" + tojson( chunk.min ) + " -->> " + tojson( chunk.max ) +
|
||||
|
||||
@@ -69,13 +69,13 @@ public:
|
||||
Writer writer(out, m);
|
||||
|
||||
// use low-latency "exhaust" mode if going over the network
|
||||
if (typeid(connBase) == typeid(DBClientConnection&)) {
|
||||
if (!_usingMongos && typeid(connBase) == typeid(DBClientConnection&)) {
|
||||
DBClientConnection& conn = static_cast<DBClientConnection&>(connBase);
|
||||
boost::function<void(const BSONObj&)> castedWriter(writer); // needed for overload resolution
|
||||
conn.query( castedWriter, coll.c_str() , q , NULL, queryOptions | QueryOption_Exhaust);
|
||||
}
|
||||
else {
|
||||
//This branch should only be taken with DBDirectClient which doesn't support exhaust mode
|
||||
//This branch should only be taken with DBDirectClient or mongos which doesn't support exhaust mode
|
||||
scoped_ptr<DBClientCursor> cursor(connBase.query( coll.c_str() , q , 0 , 0 , 0 , queryOptions ));
|
||||
while ( cursor->more() ) {
|
||||
writer(cursor->next());
|
||||
@@ -303,8 +303,6 @@ public:
|
||||
opLogStart = op["ts"]._numberLong();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// check if we're outputting to stdout
|
||||
string out = getParam("out");
|
||||
if ( out == "-" ) {
|
||||
@@ -318,6 +316,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// TODO: when mongos supports QueryOption_Exaust add a version check (SERVER-2628)
|
||||
BSONObj isdbgrid;
|
||||
conn("true").simpleCommand("admin", &isdbgrid, "isdbgrid");
|
||||
_usingMongos = isdbgrid["isdbgrid"].trueValue();
|
||||
}
|
||||
|
||||
path root( out );
|
||||
string db = _db;
|
||||
|
||||
@@ -358,6 +363,7 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool _usingMongos;
|
||||
BSONObj _query;
|
||||
};
|
||||
|
||||
|
||||
@@ -101,7 +101,11 @@ namespace mongo {
|
||||
// we want durability to be disabled.
|
||||
cmdLine.dur = false;
|
||||
|
||||
boost::filesystem::path::default_name_check( boost::filesystem::no_check );
|
||||
#if( BOOST_VERSION >= 104500 )
|
||||
boost::filesystem::path::default_name_check( boost::filesystem2::no_check );
|
||||
#else
|
||||
boost::filesystem::path::default_name_check( boost::filesystem::no_check );
|
||||
#endif
|
||||
|
||||
_name = argv[0];
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace mongo {
|
||||
assert( a );
|
||||
while( 1 ) {
|
||||
a *= 2;
|
||||
wassert( a <= 128*1024*1024 );
|
||||
wassert( a <= 256*1024*1024 );
|
||||
assert( a <= 512*1024*1024 );
|
||||
if( _len < a )
|
||||
break;
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace mongo {
|
||||
}
|
||||
ssize_t written = write(_fd, buf, len);
|
||||
if( written != (ssize_t) len ) {
|
||||
log() << "write fails written:" << written << " len:" << len << " buf:" << buf << " errno:" << errno << endl;
|
||||
log() << "write fails written:" << written << " len:" << len << " buf:" << buf << ' ' << errnoWithDescription() << endl;
|
||||
uasserted(13515, str::stream() << "error appending to file " << _fd << ' ' << errnoWithDescription());
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,10 @@ namespace mongo {
|
||||
|
||||
#ifndef O_NOATIME
|
||||
#define O_NOATIME (0)
|
||||
#endif
|
||||
|
||||
#ifndef MAP_NORESERVE
|
||||
#define MAP_NORESERVE (0)
|
||||
#endif
|
||||
|
||||
void* MemoryMappedFile::map(const char *filename, unsigned long long &length, int options) {
|
||||
@@ -118,7 +122,7 @@ namespace mongo {
|
||||
}
|
||||
|
||||
void* MemoryMappedFile::createPrivateMap() {
|
||||
void * x = mmap( /*start*/0 , len , PROT_READ|PROT_WRITE , MAP_PRIVATE , fd , 0 );
|
||||
void * x = mmap( /*start*/0 , len , PROT_READ|PROT_WRITE , MAP_PRIVATE|MAP_NORESERVE , fd , 0 );
|
||||
if( x == MAP_FAILED ) {
|
||||
if ( errno == ENOMEM ) {
|
||||
if( sizeof(void*) == 4 ) {
|
||||
@@ -140,7 +144,7 @@ namespace mongo {
|
||||
|
||||
void* MemoryMappedFile::remapPrivateView(void *oldPrivateAddr) {
|
||||
// don't unmap, just mmap over the old region
|
||||
void * x = mmap( oldPrivateAddr, len , PROT_READ|PROT_WRITE , MAP_PRIVATE|MAP_FIXED , fd , 0 );
|
||||
void * x = mmap( oldPrivateAddr, len , PROT_READ|PROT_WRITE , MAP_PRIVATE|MAP_NORESERVE|MAP_FIXED , fd , 0 );
|
||||
if( x == MAP_FAILED ) {
|
||||
int err = errno;
|
||||
error() << "13601 Couldn't remap private view: " << errnoWithDescription(err) << endl;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
namespace mongo {
|
||||
|
||||
const char versionString[] = "1.8.0-rc0";
|
||||
const char versionString[] = "1.8.0-rc2";
|
||||
|
||||
string mongodVersion() {
|
||||
stringstream ss;
|
||||
|
||||
Reference in New Issue
Block a user