Compare commits
75 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27aa3b67d4 | ||
|
|
9dcac11bd7 | ||
|
|
ef213b85e3 | ||
|
|
a92bead078 | ||
|
|
58f19f39f9 | ||
|
|
48b6a237d2 | ||
|
|
8cffdd6ed0 | ||
|
|
be489c6705 | ||
|
|
ecae23c29f | ||
|
|
5ac1a08dbb | ||
|
|
d79f8e1ea1 | ||
|
|
74fe4041a0 | ||
|
|
68bcdb17fb | ||
|
|
60b052f024 | ||
|
|
15147c7e3f | ||
|
|
5bf66857bc | ||
|
|
637dbb7bb2 | ||
|
|
ccf56ae4c2 | ||
|
|
650e5b099f | ||
|
|
658c2213e4 | ||
|
|
47ffbdfd53 | ||
|
|
b4774a4fcd | ||
|
|
c9181b253b | ||
|
|
dc46130624 | ||
|
|
797db1f61f | ||
|
|
9243ee9097 | ||
|
|
598ef8ba63 | ||
|
|
fc58c9babf | ||
|
|
8fa4644f25 | ||
|
|
1b4e06c64e | ||
|
|
c1007834f6 | ||
|
|
19672f06ef | ||
|
|
1868b5c37c | ||
|
|
4e8cafb9e9 | ||
|
|
fe2d4d93f2 | ||
|
|
c76768d3e8 | ||
|
|
e9ef03782c | ||
|
|
4e6d4b0a3d | ||
|
|
57956a51fc | ||
|
|
53749fc2d5 | ||
|
|
e171d10a10 | ||
|
|
1a7ad0ec4a | ||
|
|
839236d869 | ||
|
|
351b01e2a9 | ||
|
|
a0e88a89ea | ||
|
|
1561c0a3e2 | ||
|
|
9945f76ea7 | ||
|
|
d946d442d2 | ||
|
|
cddcfc5c94 | ||
|
|
4731f0bc59 | ||
|
|
5b29dec970 | ||
|
|
828178f05a | ||
|
|
f8339b000d | ||
|
|
811623e385 | ||
|
|
4fb7888bfe | ||
|
|
adb8a476bc | ||
|
|
601f3d44fa | ||
|
|
fc7f36ad70 | ||
|
|
a57baf1d05 | ||
|
|
da5872874f | ||
|
|
7109c020a3 | ||
|
|
3e286b07bb | ||
|
|
1cab1d1c7c | ||
|
|
d979fd7da6 | ||
|
|
6de759673d | ||
|
|
2f3fc62619 | ||
|
|
6a05e9026e | ||
|
|
2b2f91fad0 | ||
|
|
1bab750b19 | ||
|
|
b44262e4ef | ||
|
|
dac3b92e7c | ||
|
|
514f8bbab6 | ||
|
|
35885ba8de | ||
|
|
656cd5df27 | ||
|
|
41a2421ab9 |
34
SConstruct
34
SConstruct
@@ -359,7 +359,7 @@ if GetOption( "extralib" ) is not None:
|
||||
|
||||
# ------ SOURCE FILE SETUP -----------
|
||||
|
||||
commonFiles = Split( "stdafx.cpp buildinfo.cpp db/common.cpp db/jsobj.cpp db/json.cpp db/lasterror.cpp db/nonce.cpp db/queryutil.cpp db/cmdline.cpp shell/mongo.cpp" )
|
||||
commonFiles = Split( "stdafx.cpp buildinfo.cpp db/common.cpp db/jsobj.cpp db/json.cpp db/lasterror.cpp db/nonce.cpp db/queryutil.cpp shell/mongo.cpp" )
|
||||
commonFiles += [ "util/background.cpp" , "util/mmap.cpp" , "util/sock.cpp" , "util/util.cpp" , "util/message.cpp" ,
|
||||
"util/assert_util.cpp" , "util/httpclient.cpp" , "util/md5main.cpp" , "util/base64.cpp", "util/debug_util.cpp",
|
||||
"util/thread_pool.cpp" ]
|
||||
@@ -384,7 +384,7 @@ else:
|
||||
coreDbFiles = [ "db/commands.cpp" ]
|
||||
coreServerFiles = [ "util/message_server_port.cpp" , "util/message_server_asio.cpp" ]
|
||||
|
||||
serverOnlyFiles = Split( "db/query.cpp db/update.cpp db/introspect.cpp db/btree.cpp db/clientcursor.cpp db/tests.cpp db/repl.cpp db/btreecursor.cpp db/cloner.cpp db/namespace.cpp db/matcher.cpp db/dbeval.cpp db/dbwebserver.cpp db/dbhelpers.cpp db/instance.cpp db/database.cpp db/pdfile.cpp db/cursor.cpp db/security_commands.cpp db/client.cpp db/security.cpp util/miniwebserver.cpp db/storage.cpp db/reccache.cpp db/queryoptimizer.cpp db/extsort.cpp db/mr.cpp s/d_util.cpp" )
|
||||
serverOnlyFiles = Split( "db/query.cpp db/update.cpp db/introspect.cpp db/btree.cpp db/clientcursor.cpp db/tests.cpp db/repl.cpp db/btreecursor.cpp db/cloner.cpp db/namespace.cpp db/matcher.cpp db/dbeval.cpp db/dbwebserver.cpp db/dbhelpers.cpp db/instance.cpp db/database.cpp db/pdfile.cpp db/cursor.cpp db/security_commands.cpp db/client.cpp db/security.cpp util/miniwebserver.cpp db/storage.cpp db/reccache.cpp db/queryoptimizer.cpp db/extsort.cpp db/mr.cpp s/d_util.cpp db/cmdline.cpp" )
|
||||
serverOnlyFiles += [ "db/index.cpp" ] + Glob( "db/index_*.cpp" )
|
||||
|
||||
serverOnlyFiles += Glob( "db/dbcommands*.cpp" )
|
||||
@@ -404,7 +404,7 @@ else:
|
||||
nojni = True
|
||||
|
||||
coreShardFiles = []
|
||||
shardServerFiles = coreShardFiles + Glob( "s/strategy*.cpp" ) + [ "s/commands_admin.cpp" , "s/commands_public.cpp" , "s/request.cpp" , "s/cursors.cpp" , "s/server.cpp" , "s/chunk.cpp" , "s/shardkey.cpp" , "s/config.cpp" , "s/s_only.cpp" ]
|
||||
shardServerFiles = coreShardFiles + Glob( "s/strategy*.cpp" ) + [ "s/commands_admin.cpp" , "s/commands_public.cpp" , "s/request.cpp" , "s/cursors.cpp" , "s/server.cpp" , "s/chunk.cpp" , "s/shardkey.cpp" , "s/config.cpp" , "s/s_only.cpp" , "db/cmdline.cpp" ]
|
||||
serverOnlyFiles += coreShardFiles + [ "s/d_logic.cpp" ]
|
||||
|
||||
serverOnlyFiles += [ "db/module.cpp" ] + Glob( "db/modules/*.cpp" )
|
||||
@@ -457,10 +457,13 @@ if GetOption( "prefix" ):
|
||||
installDir = GetOption( "prefix" )
|
||||
|
||||
def findVersion( root , choices ):
|
||||
for c in choices:
|
||||
if ( os.path.exists( root + c ) ):
|
||||
return root + c
|
||||
raise "can't find a version of [" + root + "] choices: " + choices
|
||||
if not isinstance(root, list):
|
||||
root = [root]
|
||||
for r in root:
|
||||
for c in choices:
|
||||
if ( os.path.exists( r + c ) ):
|
||||
return r + c
|
||||
raise RuntimeError("can't find a version of [" + repr(root) + "] choices: " + repr(choices))
|
||||
|
||||
def choosePathExist( choices , default=None):
|
||||
for c in choices:
|
||||
@@ -556,13 +559,26 @@ elif "win32" == os.sys.platform:
|
||||
boostDir = "C:/Program Files" + x + "/Boost/boost_1_" + str(bv) + extra
|
||||
if os.path.exists( boostDir ):
|
||||
return boostDir
|
||||
if os.path.exists( "C:/boost" ):
|
||||
return "C:/boost"
|
||||
if os.path.exists( "/boost" ):
|
||||
return "/boost"
|
||||
return None
|
||||
|
||||
|
||||
boostDir = find_boost()
|
||||
if boostDir is None:
|
||||
print( "can't find boost" )
|
||||
Exit(1)
|
||||
|
||||
if force64 and os.path.exists( boostDir + "/lib/vs2010_64" ):
|
||||
env.Append( LIBPATH=[ boostDir + "/lib/vs2010_64" ] )
|
||||
elif not force64 and os.path.exists( boostDir + "/lib/vs2010_32" ):
|
||||
env.Append( LIBPATH=[ boostDir + "/lib/vs2010_32" ] )
|
||||
else:
|
||||
env.Append( LIBPATH=[ boostDir + "/Lib" ] )
|
||||
|
||||
|
||||
serverOnlyFiles += [ "util/ntservice.cpp" ]
|
||||
|
||||
boostLibs = []
|
||||
@@ -579,8 +595,8 @@ elif "win32" == os.sys.platform:
|
||||
env.Append( LIBPATH=[ javaHome + "/Lib" ] )
|
||||
javaLibs += [ "jvm" ];
|
||||
|
||||
winSDKHome = findVersion( "C:/Program Files/Microsoft SDKs/Windows/" ,
|
||||
[ "v6.0" , "v6.0a" , "v6.1" ] )
|
||||
winSDKHome = findVersion( [ "C:/Program Files/Microsoft SDKs/Windows/", "C:/Program Files (x86)/Microsoft SDKs/Windows/" ] ,
|
||||
[ "v6.0" , "v6.0a" , "v6.1", "v7.0A" ] )
|
||||
|
||||
env.Append( CPPPATH=[ boostDir , "pcre-7.4" , winSDKHome + "/Include" ] )
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ def checkOk():
|
||||
print( "excpted version [" + m + "]" )
|
||||
|
||||
from subprocess import Popen, PIPE
|
||||
diff = Popen( [ "git", "diff", "origin/v1.2" ], stdout=PIPE ).communicate()[ 0 ]
|
||||
diff = Popen( [ "git", "diff", "origin/v1.4" ], stdout=PIPE ).communicate()[ 0 ]
|
||||
if len(diff) > 0:
|
||||
print( diff )
|
||||
raise Exception( "build bot broken?" )
|
||||
|
||||
@@ -39,9 +39,14 @@ def foundxulrunner( env , options ):
|
||||
env.Prepend( RPATH=[ libroot ] )
|
||||
|
||||
env.Prepend( CPPPATH=[ incroot + "stable/" ,
|
||||
incroot + "unstable/" ] )
|
||||
incroot + "unstable/" ,
|
||||
incroot ] )
|
||||
env.Prepend( CPPPATH=[ "/usr/include/nspr/" ] )
|
||||
|
||||
env.Append( CPPDEFINES=[ "XULRUNNER" , "OLDJS" ] )
|
||||
if best.find( "1.9.0" ) >= 0 or best.endswith("1.9"):
|
||||
env.Append( CPPDEFINES=[ "XULRUNNER190" ] )
|
||||
if best.endswith( "1.9.1.9" ):
|
||||
pass
|
||||
else:
|
||||
env.Append( CPPDEFINES=[ "XULRUNNER190" ] )
|
||||
return True
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
namespace mongo {
|
||||
|
||||
CmdLine cmdLine;
|
||||
|
||||
const char * curNs = "in client mode";
|
||||
|
||||
bool dbexitCalled = false;
|
||||
|
||||
@@ -115,9 +115,11 @@ namespace mongo {
|
||||
}
|
||||
|
||||
ScopedDbConnection::~ScopedDbConnection() {
|
||||
if ( _conn && ! _conn->isFailed() ) {
|
||||
/* see done() comments above for why we log this line */
|
||||
log() << "~ScopedDBConnection: _conn != null" << endl;
|
||||
if ( _conn ){
|
||||
if ( ! _conn->isFailed() ) {
|
||||
/* see done() comments above for why we log this line */
|
||||
log() << "~ScopedDBConnection: _conn != null" << endl;
|
||||
}
|
||||
kill();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,8 +61,10 @@ namespace mongo {
|
||||
void flush();
|
||||
DBClientBase *get(const string& host);
|
||||
void release(const string& host, DBClientBase *c) {
|
||||
if ( c->isFailed() )
|
||||
if ( c->isFailed() ){
|
||||
delete c;
|
||||
return;
|
||||
}
|
||||
scoped_lock L(poolMutex);
|
||||
pools[host]->pool.push(c);
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace mongo {
|
||||
/* --- dbclientcommands --- */
|
||||
|
||||
bool DBClientWithCommands::isOk(const BSONObj& o) {
|
||||
return o.getIntField("ok") == 1;
|
||||
return o["ok"].trueValue();
|
||||
}
|
||||
|
||||
inline bool DBClientWithCommands::runCommand(const string &dbname, const BSONObj& cmd, BSONObj &info, int options) {
|
||||
@@ -769,6 +769,8 @@ namespace mongo {
|
||||
}
|
||||
if ( !connector->call( toSend, *m, false ) )
|
||||
return false;
|
||||
if ( ! m->data )
|
||||
return false;
|
||||
dataReceived();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -919,7 +919,7 @@ namespace mongo {
|
||||
|
||||
bool isFailed() const {
|
||||
// TODO: this really should check isFailed on current master as well
|
||||
return master > NotSetR;
|
||||
return master < Left;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
33
db/btree.cpp
33
db/btree.cpp
@@ -665,13 +665,18 @@ found:
|
||||
if ( split_debug )
|
||||
out() << " " << thisLoc.toString() << ".split" << endl;
|
||||
|
||||
int mid = n / 2;
|
||||
int split = n / 2;
|
||||
if ( keypos == n ) { // see SERVER-983
|
||||
split = 0.9 * n;
|
||||
if ( split > n - 2 )
|
||||
split = n - 2;
|
||||
}
|
||||
|
||||
DiskLoc rLoc = addBucket(idx);
|
||||
BtreeBucket *r = rLoc.btreemod();
|
||||
if ( split_debug )
|
||||
out() << " mid:" << mid << ' ' << keyNode(mid).key.toString() << " n:" << n << endl;
|
||||
for ( int i = mid+1; i < n; i++ ) {
|
||||
out() << " split:" << split << ' ' << keyNode(split).key.toString() << " n:" << n << endl;
|
||||
for ( int i = split+1; i < n; i++ ) {
|
||||
KeyNode kn = keyNode(i);
|
||||
r->pushBack(kn.recordLoc, kn.key, order, kn.prevChildBucket);
|
||||
}
|
||||
@@ -684,18 +689,18 @@ found:
|
||||
rLoc.btree()->fixParentPtrs(rLoc);
|
||||
|
||||
{
|
||||
KeyNode middle = keyNode(mid);
|
||||
nextChild = middle.prevChildBucket; // middle key gets promoted, its children will be thisLoc (l) and rLoc (r)
|
||||
KeyNode splitkey = keyNode(split);
|
||||
nextChild = splitkey.prevChildBucket; // splitkey key gets promoted, its children will be thisLoc (l) and rLoc (r)
|
||||
if ( split_debug ) {
|
||||
out() << " middle key:" << middle.key.toString() << endl;
|
||||
out() << " splitkey key:" << splitkey.key.toString() << endl;
|
||||
}
|
||||
|
||||
// promote middle to a parent node
|
||||
// promote splitkey to a parent node
|
||||
if ( parent.isNull() ) {
|
||||
// make a new parent if we were the root
|
||||
DiskLoc L = addBucket(idx);
|
||||
BtreeBucket *p = L.btreemod();
|
||||
p->pushBack(middle.recordLoc, middle.key, order, thisLoc);
|
||||
p->pushBack(splitkey.recordLoc, splitkey.key, order, thisLoc);
|
||||
p->nextChild = rLoc;
|
||||
p->assertValid( order );
|
||||
parent = idx.head = L;
|
||||
@@ -708,22 +713,22 @@ found:
|
||||
*/
|
||||
rLoc.btreemod()->parent = parent;
|
||||
if ( split_debug )
|
||||
out() << " promoting middle key " << middle.key.toString() << endl;
|
||||
parent.btree()->_insert(parent, middle.recordLoc, middle.key, order, /*dupsallowed*/true, thisLoc, rLoc, idx);
|
||||
out() << " promoting splitkey key " << splitkey.key.toString() << endl;
|
||||
parent.btree()->_insert(parent, splitkey.recordLoc, splitkey.key, order, /*dupsallowed*/true, thisLoc, rLoc, idx);
|
||||
}
|
||||
}
|
||||
|
||||
truncateTo(mid, order); // note this may trash middle.key. thus we had to promote it before finishing up here.
|
||||
truncateTo(split, order); // note this may trash splitkey.key. thus we had to promote it before finishing up here.
|
||||
|
||||
// add our new key, there is room now
|
||||
{
|
||||
|
||||
if ( keypos <= mid ) {
|
||||
if ( keypos <= split ) {
|
||||
if ( split_debug )
|
||||
out() << " keypos<mid, insertHere() the new key" << endl;
|
||||
out() << " keypos<split, insertHere() the new key" << endl;
|
||||
insertHere(thisLoc, keypos, recordLoc, key, order, lchild, rchild, idx);
|
||||
} else {
|
||||
int kp = keypos-mid-1;
|
||||
int kp = keypos-split-1;
|
||||
assert(kp>=0);
|
||||
rLoc.btree()->insertHere(rLoc, kp, recordLoc, key, order, lchild, rchild, idx);
|
||||
}
|
||||
|
||||
@@ -245,4 +245,21 @@ namespace mongo {
|
||||
return b.obj();
|
||||
}
|
||||
|
||||
int Client::recommendedYieldMicros(){
|
||||
int num = 0;
|
||||
{
|
||||
scoped_lock bl(clientsMutex);
|
||||
num = clients.size();
|
||||
}
|
||||
|
||||
if ( --num <= 0 ) // -- is for myself
|
||||
return 0;
|
||||
|
||||
if ( num > 50 )
|
||||
num = 50;
|
||||
|
||||
num *= 100;
|
||||
return num;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ namespace mongo {
|
||||
static mongo::mutex clientsMutex;
|
||||
static set<Client*> clients; // always be in clientsMutex when manipulating this
|
||||
|
||||
static int recommendedYieldMicros();
|
||||
|
||||
class GodScope {
|
||||
bool _prev;
|
||||
public:
|
||||
|
||||
@@ -232,6 +232,7 @@ namespace mongo {
|
||||
|
||||
{
|
||||
dbtempreleasecond unlock;
|
||||
sleepmicros( Client::recommendedYieldMicros() );
|
||||
}
|
||||
|
||||
if ( ClientCursor::find( id , false ) == 0 ){
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
namespace po = boost::program_options;
|
||||
|
||||
namespace mongo {
|
||||
CmdLine cmdLine;
|
||||
|
||||
void setupSignals();
|
||||
BSONArray argvArray;
|
||||
|
||||
@@ -113,16 +113,26 @@ namespace mongo {
|
||||
bool atLeastReadLocked() { return _state.get() != 0; }
|
||||
void assertAtLeastReadLocked() { assert(atLeastReadLocked()); }
|
||||
|
||||
void lock() {
|
||||
bool _checkWriteLockAlready(){
|
||||
//DEV cout << "LOCK" << endl;
|
||||
DEV assert( haveClient() );
|
||||
|
||||
int s = _state.get();
|
||||
if( s > 0 ) {
|
||||
_state.set(s+1);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
massert( 10293 , (string)"internal error: locks are not upgradeable: " + sayClientState() , s == 0 );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void lock() {
|
||||
|
||||
if ( _checkWriteLockAlready() )
|
||||
return;
|
||||
|
||||
_state.set(1);
|
||||
|
||||
curopWaitingForLock( 1 );
|
||||
@@ -131,6 +141,26 @@ namespace mongo {
|
||||
|
||||
_minfo.entered();
|
||||
}
|
||||
|
||||
bool lock_try() {
|
||||
if ( _checkWriteLockAlready() )
|
||||
return true;
|
||||
|
||||
curopWaitingForLock( 1 );
|
||||
|
||||
boost::system_time until = get_system_time();
|
||||
until += boost::posix_time::milliseconds(0);
|
||||
bool got = _m.timed_lock( until );
|
||||
curopGotLock();
|
||||
|
||||
if ( got ){
|
||||
_minfo.entered();
|
||||
_state.set(1);
|
||||
}
|
||||
|
||||
return got;
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
//DEV cout << "UNLOCK" << endl;
|
||||
int s = _state.get();
|
||||
@@ -227,12 +257,18 @@ namespace mongo {
|
||||
void lock() {
|
||||
#ifdef HAVE_READLOCK
|
||||
m.lock();
|
||||
#error this should be impossible?
|
||||
#else
|
||||
boost::detail::thread::lock_ops<boost::recursive_mutex>::lock(m);
|
||||
#endif
|
||||
_minfo.entered();
|
||||
}
|
||||
|
||||
bool lock_try(){
|
||||
lock();
|
||||
return true;
|
||||
}
|
||||
|
||||
void releaseEarly() {
|
||||
assertWriteLocked(); // aso must not be recursive, although we don't verify that in the old boost version
|
||||
assert( !_releasedEarly.get() );
|
||||
@@ -326,6 +362,23 @@ namespace mongo {
|
||||
}
|
||||
bool _got;
|
||||
};
|
||||
|
||||
struct writelocktry {
|
||||
writelocktry( const string&ns ){
|
||||
_got = dbMutex.lock_try();
|
||||
}
|
||||
~writelocktry() {
|
||||
if ( _got ){
|
||||
dbunlocking_write();
|
||||
dbMutex.unlock();
|
||||
}
|
||||
}
|
||||
bool got(){
|
||||
return _got;
|
||||
}
|
||||
bool _got;
|
||||
};
|
||||
|
||||
|
||||
struct atleastreadlock {
|
||||
atleastreadlock( const string& ns ){
|
||||
|
||||
10
db/curop.h
10
db/curop.h
@@ -108,15 +108,19 @@ namespace mongo {
|
||||
Top::global.record( _ns , _op , _lockType , now - _checkpoint , _command );
|
||||
_checkpoint = now;
|
||||
}
|
||||
|
||||
void reset( const sockaddr_in & remote, int op ) {
|
||||
|
||||
void reset(){
|
||||
_reset();
|
||||
_start = _checkpoint = 0;
|
||||
_active = true;
|
||||
_opNum = _nextOpNum++;
|
||||
_ns[0] = '?'; // just in case not set later
|
||||
_debug.reset();
|
||||
resetQuery();
|
||||
resetQuery();
|
||||
}
|
||||
|
||||
void reset( const sockaddr_in & remote, int op ) {
|
||||
reset();
|
||||
_remote = remote;
|
||||
_op = op;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace mongo {
|
||||
return preallocateOnly ? 0 : p;
|
||||
}
|
||||
|
||||
MongoDataFile* addAFile( int sizeNeeded = 0, bool preallocateNextFile = false ) {
|
||||
MongoDataFile* addAFile( int sizeNeeded, bool preallocateNextFile ) {
|
||||
int n = (int) files.size();
|
||||
MongoDataFile *ret = getFile( n, sizeNeeded );
|
||||
if ( preallocateNextFile )
|
||||
@@ -168,12 +168,15 @@ namespace mongo {
|
||||
getFile( n, 0, true );
|
||||
}
|
||||
|
||||
MongoDataFile* suitableFile( int sizeNeeded ) {
|
||||
MongoDataFile* suitableFile( int sizeNeeded, bool preallocate ) {
|
||||
MongoDataFile* f = newestFile();
|
||||
if ( !f ) {
|
||||
f = addAFile( sizeNeeded, preallocate );
|
||||
}
|
||||
for ( int i = 0; i < 8; i++ ) {
|
||||
if ( f->getHeader()->unusedLength >= sizeNeeded )
|
||||
break;
|
||||
f = addAFile( sizeNeeded );
|
||||
f = addAFile( sizeNeeded, preallocate );
|
||||
if ( f->getHeader()->fileLength >= MongoDataFile::maxSize() ) // this is as big as they get so might as well stop
|
||||
break;
|
||||
}
|
||||
@@ -183,12 +186,16 @@ namespace mongo {
|
||||
Extent* allocExtent( const char *ns, int size, bool capped ) {
|
||||
Extent *e = DataFileMgr::allocFromFreeList( ns, size, capped );
|
||||
if( e ) return e;
|
||||
return suitableFile( size )->createExtent( ns, size, capped );
|
||||
return suitableFile( size, !capped )->createExtent( ns, size, capped );
|
||||
}
|
||||
|
||||
MongoDataFile* newestFile() {
|
||||
int n = (int) files.size();
|
||||
if ( n > 0 ) n--;
|
||||
if ( n > 0 ) {
|
||||
n--;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return getFile(n);
|
||||
}
|
||||
|
||||
|
||||
28
db/db.cpp
28
db/db.cpp
@@ -45,6 +45,8 @@
|
||||
|
||||
namespace mongo {
|
||||
|
||||
CmdLine cmdLine;
|
||||
|
||||
bool useJNI = true;
|
||||
|
||||
/* only off if --nocursors which is for debugging. */
|
||||
@@ -191,22 +193,22 @@ namespace mongo {
|
||||
LastError *le = new LastError();
|
||||
lastError.reset(le);
|
||||
|
||||
MessagingPort& dbMsgPort = *connGrab;
|
||||
auto_ptr<MessagingPort> dbMsgPort( connGrab );
|
||||
connGrab = 0;
|
||||
Client& c = cc();
|
||||
|
||||
try {
|
||||
|
||||
c.getAuthenticationInfo()->isLocalHost = dbMsgPort.farEnd.isLocalHost();
|
||||
c.getAuthenticationInfo()->isLocalHost = dbMsgPort->farEnd.isLocalHost();
|
||||
|
||||
Message m;
|
||||
while ( 1 ) {
|
||||
m.reset();
|
||||
|
||||
if ( !dbMsgPort.recv(m) ) {
|
||||
if ( !dbMsgPort->recv(m) ) {
|
||||
if( !cmdLine.quiet )
|
||||
log() << "end connection " << dbMsgPort.farEnd.toString() << endl;
|
||||
dbMsgPort.shutdown();
|
||||
log() << "end connection " << dbMsgPort->farEnd.toString() << endl;
|
||||
dbMsgPort->shutdown();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -218,11 +220,11 @@ namespace mongo {
|
||||
lastError.startRequest( m , le );
|
||||
|
||||
DbResponse dbresponse;
|
||||
if ( !assembleResponse( m, dbresponse, dbMsgPort.farEnd.sa ) ) {
|
||||
out() << curTimeMillis() % 10000 << " end msg " << dbMsgPort.farEnd.toString() << endl;
|
||||
if ( !assembleResponse( m, dbresponse, dbMsgPort->farEnd.sa ) ) {
|
||||
out() << curTimeMillis() % 10000 << " end msg " << dbMsgPort->farEnd.toString() << endl;
|
||||
/* todo: we may not wish to allow this, even on localhost: very low priv accounts could stop us. */
|
||||
if ( dbMsgPort.farEnd.isLocalHost() ) {
|
||||
dbMsgPort.shutdown();
|
||||
if ( dbMsgPort->farEnd.isLocalHost() ) {
|
||||
dbMsgPort->shutdown();
|
||||
sleepmillis(50);
|
||||
problem() << "exiting end msg" << endl;
|
||||
dbexit(EXIT_CLEAN);
|
||||
@@ -233,17 +235,17 @@ namespace mongo {
|
||||
}
|
||||
|
||||
if ( dbresponse.response )
|
||||
dbMsgPort.reply(m, *dbresponse.response, dbresponse.responseTo);
|
||||
dbMsgPort->reply(m, *dbresponse.response, dbresponse.responseTo);
|
||||
}
|
||||
|
||||
}
|
||||
catch ( AssertionException& ) {
|
||||
problem() << "AssertionException in connThread, closing client connection" << endl;
|
||||
dbMsgPort.shutdown();
|
||||
dbMsgPort->shutdown();
|
||||
}
|
||||
catch ( SocketException& ) {
|
||||
problem() << "SocketException in connThread, closing client connection" << endl;
|
||||
dbMsgPort.shutdown();
|
||||
dbMsgPort->shutdown();
|
||||
}
|
||||
catch ( const ClockSkewException & ) {
|
||||
exitCleanly( EXIT_CLOCK_SKEW );
|
||||
@@ -427,6 +429,8 @@ namespace mongo {
|
||||
class DataFileSync : public BackgroundJob {
|
||||
public:
|
||||
void run(){
|
||||
if ( _sleepsecs > 2100 )
|
||||
_sleepsecs = 2100;
|
||||
log(1) << "will flush memory every: " << _sleepsecs << " seconds" << endl;
|
||||
int time_flushing = 0;
|
||||
while ( ! inShutdown() ){
|
||||
|
||||
5
db/db.h
5
db/db.h
@@ -141,8 +141,11 @@ namespace mongo {
|
||||
|
||||
string _todb( const string& ns ) const {
|
||||
size_t i = ns.find( '.' );
|
||||
if ( i == string::npos )
|
||||
if ( i == string::npos ){
|
||||
uassert( 13074 , "db name can't be empty" , ns.size() );
|
||||
return ns;
|
||||
}
|
||||
uassert( 13075 , "db name can't be empty" , i > 0 );
|
||||
return ns.substr( 0 , i );
|
||||
}
|
||||
|
||||
|
||||
@@ -317,9 +317,10 @@ namespace mongo {
|
||||
|
||||
bool authed = cc().getAuthenticationInfo()->isAuthorizedReads("admin");
|
||||
|
||||
result.append("version", versionString);
|
||||
result.append("uptime",(double) (time(0)-started));
|
||||
result.appendDate( "localTime" , jsTime() );
|
||||
|
||||
|
||||
{
|
||||
BSONObjBuilder t;
|
||||
|
||||
@@ -339,6 +340,8 @@ namespace mongo {
|
||||
|
||||
BSONObjBuilder t( result.subobjStart( "mem" ) );
|
||||
|
||||
t.append("bits", ( sizeof(int*) == 4 ? 32 : 64 ) );
|
||||
|
||||
ProcessInfo p;
|
||||
if ( p.supported() ){
|
||||
t.appendNumber( "resident" , p.getResidentSize() );
|
||||
@@ -1020,19 +1023,26 @@ namespace mongo {
|
||||
|
||||
namespace {
|
||||
long long getIndexSizeForCollection(string db, string ns, BSONObjBuilder* details=NULL, int scale = 1 ){
|
||||
DBDirectClient client;
|
||||
auto_ptr<DBClientCursor> indexes =
|
||||
client.query(db + ".system.indexes", QUERY( "ns" << ns));
|
||||
dbMutex.assertAtLeastReadLocked();
|
||||
|
||||
long long totalSize = 0;
|
||||
while (indexes->more()){
|
||||
BSONObj index = indexes->nextSafe();
|
||||
NamespaceDetails * nsd = nsdetails( (ns + ".$" + index["name"].valuestrsafe()).c_str() );
|
||||
if (!nsd)
|
||||
continue; // nothing to do here
|
||||
totalSize += nsd->datasize;
|
||||
if (details)
|
||||
details->appendNumber(index["name"].valuestrsafe(), nsd->datasize / scale );
|
||||
NamespaceDetails * nsd = nsdetails( ns.c_str() );
|
||||
if ( ! nsd )
|
||||
return 0;
|
||||
|
||||
long long totalSize = 0;
|
||||
|
||||
NamespaceDetails::IndexIterator ii = nsd->ii();
|
||||
while ( ii.more() ){
|
||||
IndexDetails& d = ii.next();
|
||||
string collNS = d.indexNamespace();
|
||||
NamespaceDetails * mine = nsdetails( collNS.c_str() );
|
||||
if ( ! mine ){
|
||||
log() << "error: have index [" << collNS << "] but no NamespaceDetails" << endl;
|
||||
continue;
|
||||
}
|
||||
totalSize += mine->datasize;
|
||||
if ( details )
|
||||
details->appendNumber( d.indexName() , mine->datasize / scale );
|
||||
}
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
@@ -241,6 +241,8 @@ namespace mongo {
|
||||
if ( from.localhost() )
|
||||
return true;
|
||||
|
||||
Client::GodScope gs;
|
||||
|
||||
if ( db.findOne( "admin.system.users" , BSONObj() , 0 , QueryOption_SlaveOk ).isEmpty() )
|
||||
return true;
|
||||
|
||||
@@ -315,6 +317,7 @@ namespace mongo {
|
||||
responseMsg = "not allowed\n";
|
||||
return;
|
||||
}
|
||||
headers.push_back( "Content-Type: application/json" );
|
||||
generateServerStatus( url , responseMsg );
|
||||
responseCode = 200;
|
||||
return;
|
||||
@@ -519,7 +522,7 @@ namespace mongo {
|
||||
BSONObj query = queryBuilder.obj();
|
||||
|
||||
auto_ptr<DBClientCursor> cursor = db.query( ns.c_str() , query, num , skip );
|
||||
|
||||
uassert( 13085 , "query failed for dbwebserver" , cursor.get() );
|
||||
if ( one ) {
|
||||
if ( cursor->more() ) {
|
||||
BSONObj obj = cursor->next();
|
||||
|
||||
46
db/index.cpp
46
db/index.cpp
@@ -206,6 +206,8 @@ namespace mongo {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool insertArrayNull = false;
|
||||
|
||||
if ( allFound ) {
|
||||
if ( arrElt.eoo() ) {
|
||||
@@ -231,29 +233,45 @@ namespace mongo {
|
||||
}
|
||||
}
|
||||
else if ( fixed.size() > 1 ){
|
||||
// x : [] - need to insert undefined
|
||||
BSONObjBuilder b(_sizeTracker);
|
||||
for( unsigned j = 0; j < fixed.size(); ++j ) {
|
||||
if ( j == arrIdx )
|
||||
b.appendUndefined( "" );
|
||||
else
|
||||
b.appendAs( fixed[ j ], "" );
|
||||
}
|
||||
keys.insert( b.obj() );
|
||||
insertArrayNull = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// nonterminal array element to expand, so recurse
|
||||
assert( !arrElt.eoo() );
|
||||
BSONObjIterator i( arrElt.embeddedObject() );
|
||||
while( i.more() ) {
|
||||
BSONElement e = i.next();
|
||||
if ( e.type() == Object )
|
||||
_getKeys( fieldNames, fixed, e.embeddedObject(), keys );
|
||||
if ( i.more() ){
|
||||
while( i.more() ) {
|
||||
BSONElement e = i.next();
|
||||
if ( e.type() == Object )
|
||||
_getKeys( fieldNames, fixed, e.embeddedObject(), keys );
|
||||
}
|
||||
}
|
||||
else {
|
||||
insertArrayNull = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( insertArrayNull ){
|
||||
// x : [] - need to insert undefined
|
||||
BSONObjBuilder b(_sizeTracker);
|
||||
for( unsigned j = 0; j < fixed.size(); ++j ) {
|
||||
if ( j == arrIdx ){
|
||||
b.appendUndefined( "" );
|
||||
}
|
||||
else {
|
||||
BSONElement e = fixed[j];
|
||||
if ( e.eoo() )
|
||||
b.appendNull( "" );
|
||||
else
|
||||
b.appendAs( e , "" );
|
||||
}
|
||||
}
|
||||
keys.insert( b.obj() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Pull out the relevant key objects from obj, so we
|
||||
can index them. Note that the set is multiple elements
|
||||
only when it's a "multikey" array.
|
||||
|
||||
@@ -893,14 +893,14 @@ namespace mongo {
|
||||
public:
|
||||
typedef multiset<GeoPoint> Holder;
|
||||
|
||||
GeoHopper( const Geo2dType * g , unsigned max , const GeoHash& n , const BSONObj& filter = BSONObj() )
|
||||
: GeoAccumulator( g , filter ) , _max( max ) , _near( n ) {
|
||||
GeoHopper( const Geo2dType * g , unsigned max , const GeoHash& n , const BSONObj& filter = BSONObj() , double maxDistance = numeric_limits<double>::max() )
|
||||
: GeoAccumulator( g , filter ) , _max( max ) , _near( n ), _maxDistance( maxDistance ) {
|
||||
|
||||
}
|
||||
|
||||
virtual bool checkDistance( const GeoHash& h , double& d ){
|
||||
d = _g->distance( _near , h );
|
||||
bool good = _points.size() < _max || d < farthest();
|
||||
bool good = d < _maxDistance && ( _points.size() < _max || d < farthest() );
|
||||
GEODEBUG( "\t\t\t\t\t\t\t checkDistance " << _near << "\t" << h << "\t" << d
|
||||
<< " ok: " << good << " farthest: " << farthest() );
|
||||
return good;
|
||||
@@ -926,6 +926,7 @@ namespace mongo {
|
||||
unsigned _max;
|
||||
GeoHash _near;
|
||||
Holder _points;
|
||||
double _maxDistance;
|
||||
|
||||
};
|
||||
|
||||
@@ -999,10 +1000,10 @@ namespace mongo {
|
||||
|
||||
class GeoSearch {
|
||||
public:
|
||||
GeoSearch( const Geo2dType * g , const GeoHash& n , int numWanted=100 , BSONObj filter=BSONObj() )
|
||||
GeoSearch( const Geo2dType * g , const GeoHash& n , int numWanted=100 , BSONObj filter=BSONObj() , double maxDistance = numeric_limits<double>::max() )
|
||||
: _spec( g ) , _n( n ) , _start( n ) ,
|
||||
_numWanted( numWanted ) , _filter( filter ) ,
|
||||
_hopper( new GeoHopper( g , numWanted , n , filter ) )
|
||||
_numWanted( numWanted ) , _filter( filter ) , _maxDistance( maxDistance ) ,
|
||||
_hopper( new GeoHopper( g , numWanted , n , filter , maxDistance ) )
|
||||
{
|
||||
assert( g->getDetails() );
|
||||
_nscanned = 0;
|
||||
@@ -1042,6 +1043,10 @@ namespace mongo {
|
||||
if ( ! _prefix.constrains() )
|
||||
break;
|
||||
_prefix = _prefix.up();
|
||||
|
||||
double temp = _spec->distance( _prefix , _start );
|
||||
if ( temp > ( _maxDistance * 2 ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
GEODEBUG( "done part 1" );
|
||||
@@ -1105,6 +1110,7 @@ namespace mongo {
|
||||
GeoHash _prefix;
|
||||
int _numWanted;
|
||||
BSONObj _filter;
|
||||
double _maxDistance;
|
||||
shared_ptr<GeoHopper> _hopper;
|
||||
|
||||
long long _nscanned;
|
||||
@@ -1201,11 +1207,13 @@ namespace mongo {
|
||||
if ( ! _cur.isEmpty() || _stack.size() )
|
||||
return true;
|
||||
|
||||
if ( ! moreToDo() )
|
||||
return false;
|
||||
while ( moreToDo() ){
|
||||
fillStack();
|
||||
if ( ! _cur.isEmpty() )
|
||||
return true;
|
||||
}
|
||||
|
||||
fillStack();
|
||||
return ! _cur.isEmpty();
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool advance(){
|
||||
@@ -1296,12 +1304,13 @@ namespace mongo {
|
||||
while ( _max.hasPrefix( _prefix ) && _max.advance( 1 , _found , this ) );
|
||||
|
||||
if ( ! _prefix.constrains() ){
|
||||
// we've exhausted the btree
|
||||
GEODEBUG( "\t exhausted the btree" );
|
||||
_state = DONE;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( _g->distance( _prefix , _start ) > _maxDistance ){
|
||||
GEODEBUG( "\tpast circle bounds" );
|
||||
GeoHash tr = _prefix;
|
||||
tr.move( 1 , 1 );
|
||||
if ( _g->distance( tr , _start ) > _maxDistance )
|
||||
@@ -1322,6 +1331,7 @@ namespace mongo {
|
||||
|
||||
virtual bool checkDistance( const GeoHash& h , double& d ){
|
||||
d = _g->distance( _start , h );
|
||||
GEODEBUG( "\t " << h << "\t" << d );
|
||||
return d <= ( _maxDistance + .01 );
|
||||
}
|
||||
|
||||
@@ -1474,7 +1484,16 @@ namespace mongo {
|
||||
switch ( e.embeddedObject().firstElement().getGtLtOp() ){
|
||||
case BSONObj::opNEAR: {
|
||||
e = e.embeddedObject().firstElement();
|
||||
shared_ptr<GeoSearch> s( new GeoSearch( this , _tohash(e) , numWanted , query ) );
|
||||
double maxDistance = numeric_limits<double>::max();
|
||||
if ( e.isABSONObj() && e.embeddedObject().nFields() > 2 ){
|
||||
BSONObjIterator i(e.embeddedObject());
|
||||
i.next();
|
||||
i.next();
|
||||
BSONElement e = i.next();
|
||||
if ( e.isNumber() )
|
||||
maxDistance = e.numberDouble();
|
||||
}
|
||||
shared_ptr<GeoSearch> s( new GeoSearch( this , _tohash(e) , numWanted , query , maxDistance ) );
|
||||
s->exec();
|
||||
auto_ptr<Cursor> c;
|
||||
c.reset( new GeoSearchCursor( s ) );
|
||||
@@ -1564,7 +1583,11 @@ namespace mongo {
|
||||
if ( cmdObj["query"].type() == Object )
|
||||
filter = cmdObj["query"].embeddedObject();
|
||||
|
||||
GeoSearch gs( g , n , numWanted , filter );
|
||||
double maxDistance = numeric_limits<double>::max();
|
||||
if ( cmdObj["maxDistance"].isNumber() )
|
||||
maxDistance = cmdObj["maxDistance"].number();
|
||||
|
||||
GeoSearch gs( g , n , numWanted , filter , maxDistance );
|
||||
|
||||
if ( cmdObj["start"].type() == String){
|
||||
GeoHash start = (string) cmdObj["start"].valuestr();
|
||||
|
||||
@@ -96,11 +96,13 @@ namespace mongo {
|
||||
scoped_lock bl(Client::clientsMutex);
|
||||
for( set<Client*>::iterator i = Client::clients.begin(); i != Client::clients.end(); i++ ) {
|
||||
Client *c = *i;
|
||||
assert( c );
|
||||
if ( c == &me )
|
||||
continue;
|
||||
CurOp& co = *(c->curop());
|
||||
if( all || co.active() )
|
||||
vals.push_back( co.infoNoauth() );
|
||||
CurOp* co = c->curop();
|
||||
assert( co );
|
||||
if( all || co->active() )
|
||||
vals.push_back( co->infoNoauth() );
|
||||
}
|
||||
}
|
||||
b.append("inprog", vals);
|
||||
|
||||
@@ -72,8 +72,14 @@ namespace mongo {
|
||||
|
||||
LastError * LastErrorHolder::_get( bool create ){
|
||||
int id = _id.get();
|
||||
if ( id == 0 )
|
||||
return _tl.get();
|
||||
if ( id == 0 ){
|
||||
LastError * le = _tl.get();
|
||||
if ( ! le && create ){
|
||||
le = new LastError();
|
||||
_tl.reset( le );
|
||||
}
|
||||
return le;
|
||||
}
|
||||
|
||||
scoped_lock lock(_idsmutex);
|
||||
map<int,Status>::iterator i = _ids.find( id );
|
||||
|
||||
@@ -45,6 +45,8 @@ _ disallow system* manipulations from the database.
|
||||
|
||||
namespace mongo {
|
||||
|
||||
const int MaxExtentSize = 0x7ff00000;
|
||||
|
||||
map<string, unsigned> BackgroundOperation::dbsInProg;
|
||||
set<string> BackgroundOperation::nsInProg;
|
||||
|
||||
@@ -195,7 +197,7 @@ namespace mongo {
|
||||
// $nExtents is just for testing - always allocate new extents
|
||||
// rather than reuse existing extents so we have some predictibility
|
||||
// in the extent size used by our tests
|
||||
database->suitableFile( (int) size )->createExtent( ns, (int) size, newCapped );
|
||||
database->suitableFile( (int) size, false )->createExtent( ns, (int) size, newCapped );
|
||||
}
|
||||
} else {
|
||||
while ( size > 0 ) {
|
||||
@@ -204,11 +206,6 @@ namespace mongo {
|
||||
Extent *e = database->allocExtent( ns, desiredExtentSize, newCapped );
|
||||
size -= e->length;
|
||||
}
|
||||
if ( !newCapped ) {
|
||||
// check if it's time to preallocate a new file, and if so queue that job for a bg thread
|
||||
// safe to call this multiple times - the implementation will only preallocate one file
|
||||
database->preallocateAFile();
|
||||
}
|
||||
}
|
||||
|
||||
NamespaceDetails *d = nsdetails(ns);
|
||||
@@ -357,7 +354,7 @@ namespace mongo {
|
||||
|
||||
Extent* MongoDataFile::createExtent(const char *ns, int approxSize, bool newCapped, int loops) {
|
||||
massert( 10357 , "shutdown in progress", !goingAway );
|
||||
massert( 10358 , "bad new extent size", approxSize >= 0 && approxSize <= 0x7ff00000 );
|
||||
massert( 10358 , "bad new extent size", approxSize >= 0 && approxSize <= MaxExtentSize );
|
||||
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;
|
||||
@@ -902,10 +899,9 @@ namespace mongo {
|
||||
idx.head,
|
||||
dl, *changes[x].added[i], idxKey, /*dupsAllowed*/true, idx);
|
||||
}
|
||||
catch (AssertionException&) {
|
||||
catch (AssertionException& e) {
|
||||
ss << " exception update index ";
|
||||
out() << " caught assertion update index " << idx.indexNamespace() << '\n';
|
||||
problem() << " caught assertion update index " << idx.indexNamespace() << endl;
|
||||
problem() << " caught assertion update index " << idx.indexNamespace() << " " << e << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -919,11 +915,19 @@ namespace mongo {
|
||||
}
|
||||
|
||||
int followupExtentSize(int len, int lastExtentLen) {
|
||||
assert( len < MaxExtentSize );
|
||||
int x = initialExtentSize(len);
|
||||
int y = (int) (lastExtentLen < 4000000 ? lastExtentLen * 4.0 : lastExtentLen * 1.2);
|
||||
int sz = y > x ? y : x;
|
||||
|
||||
if ( sz < lastExtentLen )
|
||||
sz = lastExtentLen;
|
||||
else if ( sz > MaxExtentSize )
|
||||
sz = MaxExtentSize;
|
||||
|
||||
sz = ((int)sz) & 0xffffff00;
|
||||
assert( sz > len );
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
@@ -1141,7 +1145,7 @@ namespace mongo {
|
||||
break;
|
||||
}
|
||||
}
|
||||
progress.done();
|
||||
progress.finished();
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -1192,7 +1196,7 @@ namespace mongo {
|
||||
|
||||
// throws DBException
|
||||
static void buildAnIndex(string ns, NamespaceDetails *d, IndexDetails& idx, int idxNo, bool background) {
|
||||
log() << "building new index on " << idx.keyPattern() << " for " << ns << endl;
|
||||
log() << "building new index on " << idx.keyPattern() << " for " << ns << ( background ? " background" : "" ) << endl;
|
||||
Timer t;
|
||||
unsigned long long n;
|
||||
|
||||
@@ -1528,7 +1532,9 @@ namespace mongo {
|
||||
assumes ns is capped and no indexes
|
||||
*/
|
||||
Record* DataFileMgr::fast_oplog_insert(NamespaceDetails *d, const char *ns, int len) {
|
||||
assert( d );
|
||||
RARELY assert( d == nsdetails(ns) );
|
||||
DEV assert( d == nsdetails(ns) );
|
||||
|
||||
DiskLoc extentLoc;
|
||||
int lenWHdr = len + Record::HeaderSize;
|
||||
|
||||
30
db/repl.cpp
30
db/repl.cpp
@@ -102,7 +102,7 @@ namespace mongo {
|
||||
return;
|
||||
info = _comment;
|
||||
if ( n != state && !cmdLine.quiet )
|
||||
log() << "pair: setting master=" << n << " was " << state << '\n';
|
||||
log() << "pair: setting master=" << n << " was " << state << endl;
|
||||
state = n;
|
||||
}
|
||||
|
||||
@@ -732,7 +732,7 @@ namespace mongo {
|
||||
( replPair && replSettings.fastsync ) ) {
|
||||
DBDirectClient c;
|
||||
if ( c.exists( "local.oplog.$main" ) ) {
|
||||
BSONObj op = c.findOne( "local.oplog.$main", Query().sort( BSON( "$natural" << -1 ) ) );
|
||||
BSONObj op = c.findOne( "local.oplog.$main", QUERY( "op" << NE << "n" ).sort( BSON( "$natural" << -1 ) ) );
|
||||
if ( !op.isEmpty() ) {
|
||||
tmp.syncedTo = op[ "ts" ].date();
|
||||
tmp._lastSavedLocalTs = op[ "ts" ].date();
|
||||
@@ -938,6 +938,7 @@ namespace mongo {
|
||||
}
|
||||
|
||||
Client::Context ctx( ns );
|
||||
ctx.getClient()->curop()->reset();
|
||||
|
||||
bool empty = ctx.db()->isEmpty();
|
||||
bool incompleteClone = incompleteCloneDbs.count( clientName ) != 0;
|
||||
@@ -1052,7 +1053,7 @@ namespace mongo {
|
||||
BSONObj last = conn->findOne( _ns.c_str(), Query( b.done() ).sort( BSON( "$natural" << -1 ) ) );
|
||||
if ( !last.isEmpty() ) {
|
||||
BSONElement ts = last.getField( "ts" );
|
||||
massert( 10386 , "non Date ts found", ts.type() == Date || ts.type() == Timestamp );
|
||||
massert( 10386 , (string)"non Date ts found:" + last.jsonString() , ts.type() == Date || ts.type() == Timestamp );
|
||||
syncedTo = OpTime( ts.date() );
|
||||
}
|
||||
}
|
||||
@@ -1606,6 +1607,7 @@ namespace mongo {
|
||||
ReplInfo r("replMain load sources");
|
||||
dblock lk;
|
||||
ReplSource::loadAll(sources);
|
||||
replSettings.fastsync = false; // only need this param for initial reset
|
||||
}
|
||||
|
||||
if ( sources.empty() ) {
|
||||
@@ -1718,22 +1720,21 @@ namespace mongo {
|
||||
sleepsecs(4);
|
||||
Client::initThread("replmaster");
|
||||
while( 1 ) {
|
||||
{
|
||||
dblock lk;
|
||||
cc().getAuthenticationInfo()->authorize("admin");
|
||||
}
|
||||
sleepsecs(10);
|
||||
/* write a keep-alive like entry to the log. this will make things like
|
||||
printReplicationStatus() and printSlaveReplicationStatus() stay up-to-date
|
||||
even when things are idle.
|
||||
*/
|
||||
{
|
||||
writelock lk("");
|
||||
try {
|
||||
logKeepalive();
|
||||
}
|
||||
catch(...) {
|
||||
log() << "caught exception in replMasterThread()" << endl;
|
||||
writelocktry lk("");
|
||||
if ( lk.got() ){
|
||||
cc().getAuthenticationInfo()->authorize("admin");
|
||||
try {
|
||||
logKeepalive();
|
||||
}
|
||||
catch(...) {
|
||||
log() << "caught exception in replMasterThread()" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1860,6 +1861,9 @@ namespace mongo {
|
||||
createOplog();
|
||||
boost::thread t(replMasterThread);
|
||||
}
|
||||
|
||||
while( replSettings.fastsync ) // don't allow writes until we've set up from log
|
||||
sleepmillis( 50 );
|
||||
}
|
||||
|
||||
/* called from main at server startup */
|
||||
|
||||
27
db/repl.h
27
db/repl.h
@@ -205,7 +205,10 @@ namespace mongo {
|
||||
public:
|
||||
MemIds() : size_() {}
|
||||
friend class IdTracker;
|
||||
void reset() { imp_.clear(); }
|
||||
void reset() {
|
||||
imp_.clear();
|
||||
size_ = 0;
|
||||
}
|
||||
bool get( const char *ns, const BSONObj &id ) { return imp_[ ns ].count( id ); }
|
||||
void set( const char *ns, const BSONObj &id, bool val ) {
|
||||
if ( val ) {
|
||||
@@ -424,7 +427,7 @@ namespace mongo {
|
||||
auto_ptr< Cursor > _c;
|
||||
DiskLoc startLoc( const DiskLoc &rec ) {
|
||||
Extent *e = rec.rec()->myExtent( rec );
|
||||
if ( e->myLoc != _qp.nsd()->capExtent )
|
||||
if ( !_qp.nsd()->capLooped() || ( e->myLoc != _qp.nsd()->capExtent ) )
|
||||
return e->firstRecord;
|
||||
// Likely we are on the fresh side of capExtent, so return first fresh record.
|
||||
// If we are on the stale side of capExtent, then the collection is small and it
|
||||
@@ -432,14 +435,22 @@ namespace mongo {
|
||||
return _qp.nsd()->capFirstNewRecord;
|
||||
}
|
||||
|
||||
// should never have an empty extent in the oplog, so don't worry about that case
|
||||
DiskLoc prevLoc( const DiskLoc &rec ) {
|
||||
Extent *e = rec.rec()->myExtent( rec );
|
||||
if ( e->xprev.isNull() )
|
||||
e = _qp.nsd()->lastExtent.ext();
|
||||
else
|
||||
e = e->xprev.ext();
|
||||
if ( e->myLoc != _qp.nsd()->capExtent )
|
||||
return e->firstRecord;
|
||||
if ( _qp.nsd()->capLooped() ) {
|
||||
if ( e->xprev.isNull() )
|
||||
e = _qp.nsd()->lastExtent.ext();
|
||||
else
|
||||
e = e->xprev.ext();
|
||||
if ( e->myLoc != _qp.nsd()->capExtent )
|
||||
return e->firstRecord;
|
||||
} else {
|
||||
if ( !e->xprev.isNull() ) {
|
||||
e = e->xprev.ext();
|
||||
return e->firstRecord;
|
||||
}
|
||||
}
|
||||
return DiskLoc(); // reached beginning of collection
|
||||
}
|
||||
void createClientCursor( const DiskLoc &startLoc = DiskLoc() ) {
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace mongo {
|
||||
case opReply:
|
||||
case dbMsg:
|
||||
case dbKillCursors:
|
||||
log() << "unexpected op in Top::record: " << op << endl;
|
||||
//log() << "unexpected op in Top::record: " << op << endl;
|
||||
break;
|
||||
default:
|
||||
log() << "unknown op in Top::record: " << op << endl;
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
#include "repl.h"
|
||||
#include "update.h"
|
||||
|
||||
//#define DEBUGUPDATE(x) cout << x << endl;
|
||||
#define DEBUGUPDATE(x)
|
||||
|
||||
namespace mongo {
|
||||
|
||||
//#define DEBUGUPDATE(x) cout << x << endl;
|
||||
#define DEBUGUPDATE(x)
|
||||
|
||||
const char* Mod::modNames[] = { "$inc", "$set", "$push", "$pushAll", "$pull", "$pullAll" , "$pop", "$unset" ,
|
||||
"$bitand" , "$bitor" , "$bit" , "$addToSet" };
|
||||
unsigned Mod::modNamesNum = sizeof(Mod::modNames)/sizeof(char*);
|
||||
@@ -67,7 +67,7 @@ namespace mongo {
|
||||
ms.incint = elt.numberInt() + in.numberInt();
|
||||
}
|
||||
|
||||
ms.appendIncValue( bb );
|
||||
ms.appendIncValue( bb , false );
|
||||
}
|
||||
|
||||
template< class Builder >
|
||||
@@ -310,11 +310,12 @@ namespace mongo {
|
||||
|
||||
// Perform this check first, so that we don't leave a partially modified object on uassert.
|
||||
for ( ModHolder::const_iterator i = _mods.begin(); i != _mods.end(); ++i ) {
|
||||
DEBUGUPDATE( "\t\t prepare : " << i->first );
|
||||
ModState& ms = mss->_mods[i->first];
|
||||
|
||||
const Mod& m = i->second;
|
||||
BSONElement e = obj.getFieldDotted(m.fieldName);
|
||||
|
||||
|
||||
ms.m = &m;
|
||||
ms.old = e;
|
||||
|
||||
@@ -406,6 +407,7 @@ namespace mongo {
|
||||
mss->amIInPlacePossible( false );
|
||||
}
|
||||
}
|
||||
|
||||
return auto_ptr<ModSetState>( mss );
|
||||
}
|
||||
|
||||
@@ -424,7 +426,7 @@ namespace mongo {
|
||||
// [dm] the BSONElementManipulator statements below are for replication (correct?)
|
||||
case Mod::INC:
|
||||
m.m->incrementMe( m.old );
|
||||
m.fixedName = "$set";
|
||||
m.fixedOpName = "$set";
|
||||
m.fixed = &(m.old);
|
||||
break;
|
||||
case Mod::SET:
|
||||
@@ -477,6 +479,7 @@ namespace mongo {
|
||||
|
||||
template< class Builder >
|
||||
void ModSetState::createNewFromMods( const string& root , Builder& b , const BSONObj &obj ){
|
||||
DEBUGUPDATE( "\t\t createNewFromMods root: " << root );
|
||||
BSONObjIteratorSorted es( obj );
|
||||
BSONElement e = es.next();
|
||||
|
||||
@@ -488,6 +491,8 @@ namespace mongo {
|
||||
while ( e.type() && m != mend ){
|
||||
string field = root + e.fieldName();
|
||||
FieldCompareResult cmp = compareDottedFieldNames( m->second.m->fieldName , field );
|
||||
|
||||
DEBUGUPDATE( "\t\t\t" << field << "\t" << m->second.m->fieldName << "\t" << cmp );
|
||||
|
||||
switch ( cmp ){
|
||||
|
||||
@@ -802,23 +807,26 @@ namespace mongo {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( modsIsIndexed && multi ){
|
||||
c->noteLocation();
|
||||
}
|
||||
|
||||
const BSONObj& onDisk = loc.obj();
|
||||
|
||||
|
||||
ModSet * useMods = mods.get();
|
||||
bool forceRewrite = false;
|
||||
|
||||
auto_ptr<ModSet> mymodset;
|
||||
if ( u->getMatchDetails().elemMatchKey && mods->hasDynamicArray() ){
|
||||
useMods = mods->fixDynamicArray( u->getMatchDetails().elemMatchKey );
|
||||
mymodset.reset( useMods );
|
||||
forceRewrite = true;
|
||||
}
|
||||
|
||||
|
||||
auto_ptr<ModSetState> mss = useMods->prepare( onDisk );
|
||||
|
||||
bool indexHack = multi && ( modsIsIndexed || ! mss->canApplyInPlace() );
|
||||
|
||||
if ( indexHack )
|
||||
c->noteLocation();
|
||||
|
||||
if ( modsIsIndexed <= 0 && mss->canApplyInPlace() ){
|
||||
mss->applyModsInPlace();// const_cast<BSONObj&>(onDisk) );
|
||||
|
||||
@@ -850,7 +858,7 @@ namespace mongo {
|
||||
pattern = patternBuilder.obj();
|
||||
}
|
||||
|
||||
if ( mss->needOpLogRewrite() ){
|
||||
if ( forceRewrite || mss->needOpLogRewrite() ){
|
||||
DEBUGUPDATE( "\t rewrite update: " << mss->getOpLogRewrite() );
|
||||
logOp("u", ns, mss->getOpLogRewrite() , &pattern );
|
||||
}
|
||||
@@ -861,7 +869,7 @@ namespace mongo {
|
||||
numModded++;
|
||||
if ( ! multi )
|
||||
break;
|
||||
if ( multi && modsIsIndexed )
|
||||
if ( indexHack )
|
||||
c->checkLocation();
|
||||
continue;
|
||||
}
|
||||
|
||||
72
db/update.h
72
db/update.h
@@ -100,12 +100,13 @@ namespace mongo {
|
||||
}
|
||||
}
|
||||
|
||||
bool isIndexed( const set<string>& idxKeys ) const {
|
||||
static bool isIndexed( const string& fullName , const set<string>& idxKeys ){
|
||||
const char * fieldName = fullName.c_str();
|
||||
// check if there is an index key that is a parent of mod
|
||||
for( const char *dot = strchr( fieldName, '.' ); dot; dot = strchr( dot + 1, '.' ) )
|
||||
if ( idxKeys.count( string( fieldName, dot - fieldName ) ) )
|
||||
return true;
|
||||
string fullName = fieldName;
|
||||
|
||||
// check if there is an index key equal to mod
|
||||
if ( idxKeys.count(fullName) )
|
||||
return true;
|
||||
@@ -113,6 +114,49 @@ namespace mongo {
|
||||
set< string >::const_iterator j = idxKeys.upper_bound( fullName );
|
||||
if ( j != idxKeys.end() && j->find( fullName ) == 0 && (*j)[fullName.size()] == '.' )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isIndexed( const set<string>& idxKeys ) const {
|
||||
string fullName = fieldName;
|
||||
|
||||
if ( isIndexed( fullName , idxKeys ) )
|
||||
return true;
|
||||
|
||||
if ( strstr( fieldName , "." ) ){
|
||||
// check for a.0.1
|
||||
StringBuilder buf( fullName.size() + 1 );
|
||||
for ( size_t i=0; i<fullName.size(); i++ ){
|
||||
char c = fullName[i];
|
||||
buf << c;
|
||||
|
||||
if ( c != '.' )
|
||||
continue;
|
||||
|
||||
if ( ! isdigit( fullName[i+1] ) )
|
||||
continue;
|
||||
|
||||
bool possible = true;
|
||||
size_t j=i+2;
|
||||
for ( ; j<fullName.size(); j++ ){
|
||||
char d = fullName[j];
|
||||
if ( d == '.' )
|
||||
break;
|
||||
if ( isdigit( d ) )
|
||||
continue;
|
||||
possible = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( possible )
|
||||
i = j;
|
||||
}
|
||||
string x = buf.str();
|
||||
if ( isIndexed( x , idxKeys ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -327,7 +371,7 @@ namespace mongo {
|
||||
const Mod * m;
|
||||
BSONElement old;
|
||||
|
||||
const char * fixedName;
|
||||
const char * fixedOpName;
|
||||
BSONElement * fixed;
|
||||
int pushStartSize;
|
||||
|
||||
@@ -337,7 +381,7 @@ namespace mongo {
|
||||
long long inclong;
|
||||
|
||||
ModState(){
|
||||
fixedName = 0;
|
||||
fixedOpName = 0;
|
||||
fixed = 0;
|
||||
pushStartSize = -1;
|
||||
incType = EOO;
|
||||
@@ -352,7 +396,7 @@ namespace mongo {
|
||||
}
|
||||
|
||||
bool needOpLogRewrite() const {
|
||||
if ( fixed || fixedName || incType )
|
||||
if ( fixed || fixedOpName || incType )
|
||||
return true;
|
||||
|
||||
switch( op() ){
|
||||
@@ -369,18 +413,18 @@ namespace mongo {
|
||||
void appendForOpLog( BSONObjBuilder& b ) const {
|
||||
if ( incType ){
|
||||
BSONObjBuilder bb( b.subobjStart( "$set" ) );
|
||||
appendIncValue( bb );
|
||||
appendIncValue( bb , true );
|
||||
bb.done();
|
||||
return;
|
||||
}
|
||||
|
||||
const char * name = fixedName ? fixedName : Mod::modNames[op()];
|
||||
const char * name = fixedOpName ? fixedOpName : Mod::modNames[op()];
|
||||
|
||||
BSONObjBuilder bb( b.subobjStart( name ) );
|
||||
if ( fixed )
|
||||
bb.appendAs( *fixed , m->fieldName );
|
||||
else
|
||||
bb.append( m->elt );
|
||||
bb.appendAs( m->elt , m->fieldName );
|
||||
bb.done();
|
||||
}
|
||||
|
||||
@@ -390,14 +434,16 @@ namespace mongo {
|
||||
}
|
||||
|
||||
template< class Builder >
|
||||
void appendIncValue( Builder& b ) const {
|
||||
void appendIncValue( Builder& b , bool useFullName ) const {
|
||||
const char * n = useFullName ? m->fieldName : m->shortFieldName;
|
||||
|
||||
switch ( incType ){
|
||||
case NumberDouble:
|
||||
b.append( m->shortFieldName , incdouble ); break;
|
||||
b.append( n , incdouble ); break;
|
||||
case NumberLong:
|
||||
b.append( m->shortFieldName , inclong ); break;
|
||||
b.append( n , inclong ); break;
|
||||
case NumberInt:
|
||||
b.append( m->shortFieldName , incint ); break;
|
||||
b.append( n , incint ); break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -470,7 +516,7 @@ namespace mongo {
|
||||
break;
|
||||
|
||||
case Mod::INC:
|
||||
ms.fixedName = "$set";
|
||||
ms.fixedOpName = "$set";
|
||||
case Mod::SET: {
|
||||
m._checkForAppending( m.elt );
|
||||
b.appendAs( m.elt, m.shortFieldName );
|
||||
|
||||
@@ -306,11 +306,14 @@ namespace BasicTests {
|
||||
ASSERT_EQUALS( 1, lexNumCmp( "f12g", "f12f" ) );
|
||||
ASSERT_EQUALS( 1, lexNumCmp( "aa{", "aab" ) );
|
||||
ASSERT_EQUALS( 1, lexNumCmp( "aa{", "aa1" ) );
|
||||
ASSERT_EQUALS( 1, lexNumCmp( "a1{", "a11" ) );
|
||||
ASSERT_EQUALS( -1, lexNumCmp( "a1{", "a11" ) );
|
||||
ASSERT_EQUALS( 1, lexNumCmp( "a1{a", "a1{" ) );
|
||||
ASSERT_EQUALS( -1, lexNumCmp( "a1{", "a1{a" ) );
|
||||
ASSERT_EQUALS( 1, lexNumCmp("21", "11") );
|
||||
ASSERT_EQUALS( -1, lexNumCmp("11", "21") );
|
||||
|
||||
ASSERT_EQUALS( -1 , lexNumCmp( "a.0" , "a.1" ) );
|
||||
ASSERT_EQUALS( -1 , lexNumCmp( "a.0.b" , "a.1" ) );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -72,6 +72,9 @@ namespace BtreeTests {
|
||||
bt()->assertValid( order(), true );
|
||||
ASSERT_EQUALS( nKeys, bt()->fullValidate( dl(), order() ) );
|
||||
}
|
||||
void dump() {
|
||||
bt()->dumpTree( dl(), order() );
|
||||
}
|
||||
void insert( BSONObj &key ) {
|
||||
bt()->bt_insert( dl(), recordLoc(), key, order(), true, id(), true );
|
||||
}
|
||||
@@ -206,10 +209,12 @@ namespace BtreeTests {
|
||||
class MissingLocateMultiBucket : public Base {
|
||||
public:
|
||||
void run() {
|
||||
for ( int i = 0; i < 10; ++i ) {
|
||||
BSONObj k = key( 'b' + 2 * i );
|
||||
insert( k );
|
||||
for ( int i = 0; i < 8; ++i ) {
|
||||
insert( i );
|
||||
}
|
||||
insert( 9 );
|
||||
insert( 8 );
|
||||
// dump();
|
||||
BSONObj straddle = key( 'i' );
|
||||
locate( straddle, 0, false, dl(), 1 );
|
||||
straddle = key( 'k' );
|
||||
@@ -219,8 +224,34 @@ namespace BtreeTests {
|
||||
BSONObj key( char c ) {
|
||||
return simpleKey( c, 800 );
|
||||
}
|
||||
void insert( int i ) {
|
||||
BSONObj k = key( 'b' + 2 * i );
|
||||
Base::insert( k );
|
||||
}
|
||||
};
|
||||
|
||||
class SERVER983 : public Base {
|
||||
public:
|
||||
void run() {
|
||||
for ( int i = 0; i < 10; ++i ) {
|
||||
insert( i );
|
||||
}
|
||||
// dump();
|
||||
BSONObj straddle = key( 'o' );
|
||||
locate( straddle, 0, false, dl(), 1 );
|
||||
straddle = key( 'q' );
|
||||
locate( straddle, 0, false, dl(), -1 );
|
||||
}
|
||||
private:
|
||||
BSONObj key( char c ) {
|
||||
return simpleKey( c, 800 );
|
||||
}
|
||||
void insert( int i ) {
|
||||
BSONObj k = key( 'b' + 2 * i );
|
||||
Base::insert( k );
|
||||
}
|
||||
};
|
||||
|
||||
class All : public Suite {
|
||||
public:
|
||||
All() : Suite( "btree" ){
|
||||
@@ -233,6 +264,7 @@ namespace BtreeTests {
|
||||
add< SplitLeftHeavyBucket >();
|
||||
add< MissingLocate >();
|
||||
add< MissingLocateMultiBucket >();
|
||||
add< SERVER983 >();
|
||||
}
|
||||
} myall;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace po = boost::program_options;
|
||||
|
||||
namespace mongo {
|
||||
|
||||
CmdLine cmdLine;
|
||||
|
||||
namespace regression {
|
||||
|
||||
map<string,Suite*> * mongo::regression::Suite::_suites = 0;
|
||||
|
||||
@@ -978,7 +978,9 @@ namespace QueryTests {
|
||||
for( int j = -1; j < i; ++j ) {
|
||||
auto_ptr< DBClientCursor > c = client().query( ns(), QUERY( "ts" << GTE << j ), 0, 0, 0, QueryOption_OplogReplay );
|
||||
ASSERT( c->more() );
|
||||
ASSERT_EQUALS( ( j > min ? j : min ), c->next()[ "ts" ].numberInt() );
|
||||
BSONObj next = c->next();
|
||||
ASSERT( !next[ "ts" ].eoo() );
|
||||
ASSERT_EQUALS( ( j > min ? j : min ), next[ "ts" ].numberInt() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -987,6 +989,40 @@ namespace QueryTests {
|
||||
int _old;
|
||||
};
|
||||
|
||||
class FindingStartPartiallyFull : public CollectionBase {
|
||||
public:
|
||||
FindingStartPartiallyFull() : CollectionBase( "findingstart" ), _old( __findingStartInitialTimeout ) {
|
||||
__findingStartInitialTimeout = 0;
|
||||
}
|
||||
~FindingStartPartiallyFull() {
|
||||
__findingStartInitialTimeout = _old;
|
||||
}
|
||||
|
||||
void run() {
|
||||
BSONObj info;
|
||||
ASSERT( client().runCommand( "unittests", BSON( "create" << "querytests.findingstart" << "capped" << true << "size" << 10000 << "$nExtents" << 5 << "autoIndexId" << false ), info ) );
|
||||
|
||||
int i = 0;
|
||||
for( ; i < 150; client().insert( ns(), BSON( "ts" << i++ ) ) );
|
||||
|
||||
for( int k = 0; k < 5; ++k ) {
|
||||
client().insert( ns(), BSON( "ts" << i++ ) );
|
||||
int min = client().query( ns(), Query().sort( BSON( "$natural" << 1 ) ) )->next()[ "ts" ].numberInt();
|
||||
for( int j = -1; j < i; ++j ) {
|
||||
auto_ptr< DBClientCursor > c = client().query( ns(), QUERY( "ts" << GTE << j ), 0, 0, 0, QueryOption_OplogReplay );
|
||||
ASSERT( c->more() );
|
||||
BSONObj next = c->next();
|
||||
ASSERT( !next[ "ts" ].eoo() );
|
||||
ASSERT_EQUALS( ( j > min ? j : min ), next[ "ts" ].numberInt() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int _old;
|
||||
};
|
||||
|
||||
|
||||
class WhatsMyUri : public CollectionBase {
|
||||
public:
|
||||
WhatsMyUri() : CollectionBase( "whatsmyuri" ) {}
|
||||
@@ -1069,6 +1105,7 @@ namespace QueryTests {
|
||||
add< HelperTest >();
|
||||
add< HelperByIdTest >();
|
||||
add< FindingStart >();
|
||||
add< FindingStartPartiallyFull >();
|
||||
add< WhatsMyUri >();
|
||||
|
||||
add< parsedtests::basic1 >();
|
||||
|
||||
@@ -1053,7 +1053,8 @@ namespace ReplTests {
|
||||
check();
|
||||
ASSERT( !s_.inMem() );
|
||||
|
||||
s_.reset();
|
||||
s_.reset( 4 * sizeof( BSONObj ) - 1 );
|
||||
s_.mayUpgradeStorage();
|
||||
ASSERT( s_.inMem() );
|
||||
}
|
||||
private:
|
||||
|
||||
32
debian/changelog
vendored
32
debian/changelog
vendored
@@ -1,3 +1,35 @@
|
||||
mongodb (1.4.4) unstable; urgency=low
|
||||
|
||||
* bug fixes, see http://jira.mongodb.org/browse/SERVER/fixforversion/10166
|
||||
|
||||
-- Richard Kreuter <richard@10gen.com> Tue, 29 Jun 2010 16:56:28 -0500
|
||||
|
||||
mongodb (1.4.3) unstable; urgency=low
|
||||
|
||||
* bug fixes, see http://jira.mongodb.org/browse/SERVER/fixforversion/10156
|
||||
|
||||
-- Richard Kreuter <richard@10gen.com> Tue, 24 May 2010 16:56:28 -0500
|
||||
|
||||
mongodb (1.4.2) unstable; urgency=low
|
||||
|
||||
* bug fixes, see http://jira.mongodb.org/browse/SERVER/fixforversion/10155
|
||||
|
||||
-- Richard Kreuter <richard@10gen.com> Tue, 27 Apr 2010 16:56:28 -0500
|
||||
|
||||
|
||||
mongodb (1.4.1) unstable; urgency=low
|
||||
|
||||
* bug fixes, see http://jira.mongodb.org/browse/SERVER/fixforversion/10144
|
||||
|
||||
-- Richard Kreuter <richard@10gen.com> Wed, 14 Apr 2010 16:56:28 -0500
|
||||
|
||||
|
||||
mongodb (1.4.0) unstable; urgency=low
|
||||
|
||||
* stable release, see http://jira.mongodb.org/browse/SERVER/fixforversion/10133
|
||||
|
||||
-- Richard Kreuter <richard@10gen.com> Wed, 22 Mar 2010 16:56:28 -0500
|
||||
|
||||
mongodb (1.3.5) unstable; urgency=low
|
||||
|
||||
* bug fixes
|
||||
|
||||
2
debian/mongodb.upstart
vendored
2
debian/mongodb.upstart
vendored
@@ -11,5 +11,5 @@ stop on runlevel [06]
|
||||
script
|
||||
ENABLE_MONGODB="yes"
|
||||
if [ -f /etc/default/mongodb ]; then . /etc/default/mongodb; fi
|
||||
if [ "x$ENABLE_MONGODB" = "xyes" ]; then start-stop-daemon --start --quiet --chuid mongodb --exec /usr/bin/mongod -- --config /etc/mongodb.conf; fi
|
||||
if [ "x$ENABLE_MONGODB" = "xyes" ]; then exec start-stop-daemon --start --quiet --chuid mongodb --exec /usr/bin/mongod -- --config /etc/mongodb.conf; fi
|
||||
end script
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = MongoDB
|
||||
PROJECT_NUMBER = 1.3.5
|
||||
PROJECT_NUMBER = 1.4.4
|
||||
OUTPUT_DIRECTORY = docs
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
@@ -70,18 +70,18 @@ t = startMongod( "--port", ports[ 1 ], "--dbpath", "/data/db/" + baseName + "_to
|
||||
for( i = 0; i < 1000; ++i ) {
|
||||
f.a.save( { i: i } );
|
||||
}
|
||||
assert.eq( 1000, f.a.find().count() );
|
||||
assert.eq( 1000, f.a.find().count() , "A1" );
|
||||
|
||||
assert.commandWorked( t.cloneCollection( "localhost:" + ports[ 0 ], "a" ) );
|
||||
assert.eq( 1000, t.a.find().count() );
|
||||
assert.eq( 1000, t.a.find().count() , "A2" );
|
||||
|
||||
t.a.drop();
|
||||
|
||||
assert.commandWorked( t.cloneCollection( "localhost:" + ports[ 0 ], "a", { i: { $gte: 10, $lt: 20 } } ) );
|
||||
assert.eq( 10, t.a.find().count() );
|
||||
assert.eq( 10, t.a.find().count() , "A3" );
|
||||
|
||||
t.a.drop();
|
||||
assert.eq( 0, t.system.indexes.find().count() );
|
||||
assert.eq( 0, t.system.indexes.find().count() , "prep 2");
|
||||
|
||||
f.a.ensureIndex( { i: 1 } );
|
||||
assert.eq( 2, f.system.indexes.find().count(), "expected index missing" );
|
||||
@@ -91,7 +91,7 @@ if ( t.system.indexes.find().count() != 2 ) {
|
||||
}
|
||||
assert.eq( 2, t.system.indexes.find().count(), "expected index missing" );
|
||||
// Verify index works
|
||||
assert.eq( 50, t.a.find( { i: 50 } ).hint( { i: 1 } ).explain().indexBounds[0][0].i );
|
||||
assert.eq( 50, t.a.find( { i: 50 } ).hint( { i: 1 } ).explain().indexBounds[0][0].i , "verify 1" );
|
||||
assert.eq( 1, t.a.find( { i: 50 } ).hint( { i: 1 } ).toArray().length, "match length did not match expected" );
|
||||
|
||||
// Check that capped-ness is preserved on clone
|
||||
@@ -119,14 +119,15 @@ f.a.save( { i: 200000 } );
|
||||
f.a.save( { i: -1 } );
|
||||
f.a.remove( { i: 0 } );
|
||||
f.a.update( { i: 99998 }, { i: 99998, x: "y" } );
|
||||
assert.eq( 100001, f.a.count() , "D0" );
|
||||
ret = finishstartclone();
|
||||
finishclone( ret );
|
||||
|
||||
assert.eq( 100000, t.a.find().count() );
|
||||
assert.eq( 1, t.a.find( { i: 200000 } ).count() );
|
||||
assert.eq( 0, t.a.find( { i: -1 } ).count() );
|
||||
assert.eq( 0, t.a.find( { i: 0 } ).count() );
|
||||
assert.eq( 1, t.a.find( { i: 99998, x: "y" } ).count() );
|
||||
assert.eq( 100000, t.a.find().count() , "D1" );
|
||||
assert.eq( 1, t.a.find( { i: 200000 } ).count() , "D2" );
|
||||
assert.eq( 0, t.a.find( { i: -1 } ).count() , "D3" );
|
||||
assert.eq( 0, t.a.find( { i: 0 } ).count() , "D4" );
|
||||
assert.eq( 1, t.a.find( { i: 99998, x: "y" } ).count() , "D5" );
|
||||
|
||||
|
||||
// Now test oplog running out of space -- specify small size clone oplog for test.
|
||||
@@ -136,7 +137,7 @@ t.a.drop();
|
||||
for( i = 0; i < 200000; ++i ) {
|
||||
f.a.save( { i: i } );
|
||||
}
|
||||
assert.eq( 200000, f.a.count() );
|
||||
assert.eq( 200000, f.a.count() , "E1" );
|
||||
|
||||
startstartclone( ", logSizeMb:1" );
|
||||
ret = finishstartclone();
|
||||
@@ -145,6 +146,8 @@ for( i = 200000; i < 250000; ++i ) {
|
||||
f.a.save( { i: i } );
|
||||
}
|
||||
|
||||
assert.eq( 250000, f.a.count() , "F0" );
|
||||
|
||||
assert.commandFailed( dofinishclonecmd( ret ) );
|
||||
|
||||
// Make sure the same works with standard size op log.
|
||||
@@ -154,7 +157,7 @@ t.a.drop();
|
||||
for( i = 0; i < 200000; ++i ) {
|
||||
f.a.save( { i: i } );
|
||||
}
|
||||
assert.eq( 200000, f.a.count() );
|
||||
assert.eq( 200000, f.a.count() , "F1" );
|
||||
|
||||
startstartclone();
|
||||
ret = finishstartclone();
|
||||
@@ -162,10 +165,10 @@ ret = finishstartclone();
|
||||
for( i = 200000; i < 250000; ++i ) {
|
||||
f.a.save( { i: i } );
|
||||
}
|
||||
assert.eq( 250000, f.a.count() );
|
||||
assert.eq( 250000, f.a.count() , "F2" );
|
||||
|
||||
finishclone( ret );
|
||||
assert.eq( 250000, t.a.find().count() );
|
||||
assert.eq( 250000, t.a.find().count() , "F3" );
|
||||
|
||||
// Test startCloneCollection and finishCloneCollection commands.
|
||||
f.a.drop();
|
||||
@@ -174,7 +177,7 @@ t.a.drop();
|
||||
for( i = 0; i < 100000; ++i ) {
|
||||
f.a.save( { i: i } );
|
||||
}
|
||||
assert.eq( 100000, f.a.count() );
|
||||
assert.eq( 100000, f.a.count() , "G1" );
|
||||
|
||||
startstartclone();
|
||||
|
||||
@@ -182,9 +185,9 @@ sleep( 200 );
|
||||
f.a.save( { i: -1 } );
|
||||
|
||||
ret = finishstartclone();
|
||||
assert.eq( 100001, t.a.find().count() );
|
||||
assert.eq( 100001, t.a.find().count() , "G2" );
|
||||
|
||||
f.a.save( { i: -2 } );
|
||||
assert.eq( 100002, f.a.find().count() );
|
||||
assert.eq( 100002, f.a.find().count() , "G3" );
|
||||
finishclone( ret );
|
||||
assert.eq( 100002, t.a.find().count() );
|
||||
assert.eq( 100002, t.a.find().count() , "G4" );
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
// check that there is preallocation on explicit createCollection() and no unncessary preallocation after restart
|
||||
|
||||
port = allocatePorts( 1 )[ 0 ];
|
||||
|
||||
var baseName = "jstests_preallocate";
|
||||
|
||||
vsize = function() {
|
||||
return m.getDB( "admin" ).runCommand( "serverStatus" ).mem.virtual;
|
||||
}
|
||||
var baseName = "jstests_preallocate2";
|
||||
|
||||
var m = startMongod( "--port", port, "--dbpath", "/data/db/" + baseName );
|
||||
|
||||
assert.eq( 0, m.getDBs().totalSize );
|
||||
|
||||
m.getDB( baseName ).createCollection( baseName + "1" );
|
||||
|
||||
assert.soon( function() { return m.getDBs().totalSize > 100000000; }, "expected second file to bring total size over 100MB" );
|
||||
|
||||
stopMongod( port );
|
||||
|
||||
var m = startMongoProgram( "mongod", "--port", port, "--dbpath", "/data/db/" + baseName );
|
||||
|
||||
11
jstests/disk/preallocate2.js
Normal file
11
jstests/disk/preallocate2.js
Normal file
@@ -0,0 +1,11 @@
|
||||
// check that there is preallocation on insert
|
||||
|
||||
port = allocatePorts( 1 )[ 0 ];
|
||||
|
||||
var baseName = "jstests_preallocate2";
|
||||
|
||||
var m = startMongod( "--port", port, "--dbpath", "/data/db/" + baseName );
|
||||
|
||||
m.getDB( baseName )[ baseName ].save( {i:1} );
|
||||
|
||||
assert.soon( function() { return m.getDBs().totalSize > 100000000; }, "expected second file to bring total size over 100MB" );
|
||||
@@ -41,3 +41,8 @@ assert.close( fast.stats.avgDistance , a( t.find( { loc : { $near : [ 50 , 50 ]
|
||||
printjson( t.find( { loc : { $near : [ 50 , 50 ] } } ).explain() )
|
||||
|
||||
|
||||
assert.lt( 3 , a( t.find( { loc : { $near : [ 50 , 50 ] } } ).limit(50) ) , "C1" )
|
||||
assert.gt( 3 , a( t.find( { loc : { $near : [ 50 , 50 , 3 ] } } ).limit(50) ) , "C2" )
|
||||
|
||||
|
||||
|
||||
|
||||
23
jstests/index_arr1.js
Normal file
23
jstests/index_arr1.js
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
t = db.index_arr1
|
||||
t.drop()
|
||||
|
||||
t.insert( { _id : 1 , a : 5 , b : [ { x : 1 } ] } )
|
||||
t.insert( { _id : 2 , a : 5 , b : [] } )
|
||||
t.insert( { _id : 3 , a : 5 } )
|
||||
|
||||
assert.eq( 3 , t.find( { a : 5 } ).itcount() , "A1" )
|
||||
|
||||
t.ensureIndex( { a : 1 , "b.x" : 1 } )
|
||||
|
||||
//t.find().sort( { a : 1 } )._addSpecial( "$returnKey" , 1 ).forEach( printjson )
|
||||
//t.find( { a : 5 } ).forEach( printjson )
|
||||
|
||||
assert.eq( 3 , t.find( { a : 5 } ).itcount() , "A2" ); // SERVER-1082
|
||||
|
||||
|
||||
assert.eq( 2 , t.getIndexes().length , "B1" )
|
||||
t.insert( { _id : 4 , a : 5 , b : [] } )
|
||||
t.ensureIndex( { a : 1 , "b.a" : 1 , "b.c" : 1 } )
|
||||
assert.eq( 3 , t.getIndexes().length , "B2" )
|
||||
|
||||
51
jstests/index_arr2.js
Normal file
51
jstests/index_arr2.js
Normal file
@@ -0,0 +1,51 @@
|
||||
NUM = 20;
|
||||
M = 5;
|
||||
|
||||
t = db.xxx;
|
||||
|
||||
function test( withIndex ){
|
||||
t.drop();
|
||||
|
||||
// insert a bunch of items to force queries to use the index.
|
||||
newObject = {
|
||||
_id : 1,
|
||||
a : [
|
||||
{ b : { c : 1 } }
|
||||
]
|
||||
}
|
||||
|
||||
now = (new Date()).getTime() / 1000;
|
||||
for (created = now - NUM; created <= now; created++ ) {
|
||||
newObject['created'] = created;
|
||||
t.insert(newObject);
|
||||
newObject['_id'] ++;
|
||||
}
|
||||
|
||||
// change the last M items.
|
||||
query = {
|
||||
'created' : { '$gte' : now - M }
|
||||
}
|
||||
|
||||
Z = t.find( query ).count();
|
||||
|
||||
if ( withIndex ){
|
||||
//t.ensureIndex( { 'a.b.c' : 1, 'created' : -1 } )
|
||||
//t.ensureIndex( { created : -1 } )
|
||||
t.ensureIndex( { 'a.b.c' : 1 } , { name : "x" } )
|
||||
}
|
||||
|
||||
t.update(query, { '$set' : { "a.0.b.c" : 0 } } , false , true )
|
||||
assert.eq( Z , db.getLastErrorObj().n , "num updated withIndex:" + withIndex );
|
||||
|
||||
// now see how many were actually updated.
|
||||
query['a.b.c'] = 0;
|
||||
|
||||
count = t.count(query);
|
||||
|
||||
assert.eq( Z , count , "count after withIndex:" + withIndex );
|
||||
}
|
||||
|
||||
test( false )
|
||||
test( true );
|
||||
|
||||
|
||||
@@ -7,6 +7,11 @@ var rt = new ReplTest( "basic1" );
|
||||
m = rt.start( true );
|
||||
s = rt.start( false );
|
||||
|
||||
function block(){
|
||||
am.runCommand( { getlasterror : 1 , w : 2 , wtimeout : 3000 } )
|
||||
sleep(3000); // 1.4 branch doesn't support w
|
||||
}
|
||||
|
||||
function hash( db ){
|
||||
var s = "";
|
||||
var a = db.getCollectionNames();
|
||||
@@ -90,13 +95,56 @@ checkMR( am.mr );
|
||||
checkMR( as.mr );
|
||||
checkNumCollections( "MR2" );
|
||||
|
||||
sleep( 3000 );
|
||||
block();
|
||||
checkNumCollections( "MR3" );
|
||||
|
||||
var res = am.mr.mapReduce( m , r , { out : "xyz" } );
|
||||
sleep( 3000 );
|
||||
block();
|
||||
|
||||
checkNumCollections( "MR4" );
|
||||
|
||||
|
||||
t = am.rpos;
|
||||
t.insert( { _id : 1 , a : [ { n : "a" , c : 1 } , { n : "b" , c : 1 } , { n : "c" , c : 1 } ] , b : [ 1 , 2 , 3 ] } )
|
||||
block();
|
||||
check( "after pos 1 " );
|
||||
|
||||
t.update( { "a.n" : "b" } , { $inc : { "a.$.c" : 1 } } )
|
||||
block();
|
||||
check( "after pos 2 " );
|
||||
|
||||
t.update( { "b" : 2 } , { $inc : { "b.$" : 1 } } )
|
||||
block();
|
||||
check( "after pos 3 " );
|
||||
|
||||
t.update( { "b" : 3} , { $set : { "b.$" : 17 } } )
|
||||
block();
|
||||
check( "after pos 4 " );
|
||||
|
||||
printjson( am.rpos.findOne() )
|
||||
printjson( as.rpos.findOne() )
|
||||
|
||||
//am.getSisterDB( "local" ).getCollection( "oplog.$main" ).find().limit(10).sort( { $natural : -1 } ).forEach( printjson )
|
||||
|
||||
|
||||
t = am.b;
|
||||
t.update( { "_id" : "fun"}, { $inc : {"a.b.c.x" : 6743} } , true, false)
|
||||
block()
|
||||
check( "b 1" );
|
||||
|
||||
t.update( { "_id" : "fun"}, { $inc : {"a.b.c.x" : 5} } , true, false)
|
||||
block()
|
||||
check( "b 2" );
|
||||
|
||||
t.update( { "_id" : "fun"}, { $inc : {"a.b.c.x" : 100, "a.b.c.y" : 911} } , true, false)
|
||||
block()
|
||||
assert.eq( { _id : "fun" , a : { b : { c : { x : 6848 , y : 911 } } } } , as.b.findOne() , "b 3" );
|
||||
//printjson( t.findOne() )
|
||||
//printjson( as.b.findOne() )
|
||||
//am.getSisterDB( "local" ).getCollection( "oplog.$main" ).find().sort( { $natural : -1 } ).limit(3).forEach( printjson )
|
||||
check( "b 4" );
|
||||
|
||||
|
||||
rt.stop();
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
ports = allocatePorts( 3 );
|
||||
|
||||
var baseName = "repl_snapshot2";
|
||||
var baseName = "repl_snapshot3";
|
||||
var basePath = "/data/db/" + baseName;
|
||||
|
||||
a = new MongodRunner( ports[ 0 ], basePath + "-arbiter" );
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
t = db.tilde;
|
||||
t = db.update_arraymatch2;
|
||||
t.drop();
|
||||
|
||||
t.insert( { } );
|
||||
|
||||
25
jstests/update_multi3.js
Normal file
25
jstests/update_multi3.js
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
t = db.update_multi3;
|
||||
|
||||
function test( useIndex ){
|
||||
t.drop();
|
||||
|
||||
if ( useIndex )
|
||||
t.ensureIndex({k:1})
|
||||
|
||||
for (i=0; i<10; i++) {
|
||||
t.save({ _id : i , k: 'x', a: []});
|
||||
}
|
||||
|
||||
t.update({k: 'x'}, {$push: {a: 'y'}}, false, true);
|
||||
|
||||
t.find( { k : "x" } ).forEach(
|
||||
function(z){
|
||||
assert.eq( [ "y" ] , z.a , "useIndex: " + useIndex )
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
test( false )
|
||||
test( true )
|
||||
20
jstests/updated.js
Normal file
20
jstests/updated.js
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
t = db.updated;
|
||||
t.drop()
|
||||
|
||||
o = { _id : Math.random() ,
|
||||
items:[null,null,null,null]
|
||||
};
|
||||
|
||||
t.insert( o );
|
||||
assert.eq( o , t.findOne() , "A1" );
|
||||
|
||||
o.items[0] = {amount:9000,itemId:1};
|
||||
t.update({},{$set:{"items.0":o.items[0]}});
|
||||
assert.eq( o , t.findOne() , "A2" );
|
||||
|
||||
o.items[0].amount += 1000;
|
||||
o.items[1] = {amount:1,itemId:2};
|
||||
t.update({},{$inc:{"items.0.amount":1000},$set:{"items.1":o.items[1]}});
|
||||
assert.eq( o , t.findOne() , "A3" );
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: mongo
|
||||
Version: 1.3.5
|
||||
Version: 1.4.4
|
||||
Release: mongodb_1%{?dist}
|
||||
Summary: mongo client shell and tools
|
||||
License: AGPL 3.0
|
||||
@@ -68,8 +68,13 @@ scons -c
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%pre server
|
||||
/usr/sbin/useradd -M -r -U -d /var/lib/mongo -s /bin/false \
|
||||
-c mongod mongod > /dev/null 2>&1
|
||||
if ! /usr/bin/id -g mongod &>/dev/null; then
|
||||
/usr/sbin/groupadd -r mongod
|
||||
fi
|
||||
if ! /usr/bin/id mongod &>/dev/null; then
|
||||
/usr/sbin/useradd -M -r -g mongod -d /var/lib/mongo -s /bin/false \
|
||||
-c mongod mongod > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
%post server
|
||||
if test $1 = 1
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
#include "chunk.h"
|
||||
|
||||
namespace mongo {
|
||||
|
||||
|
||||
CmdLine cmdLine;
|
||||
Database *database = 0;
|
||||
string mongosCommand;
|
||||
string ourHostname;
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#endif
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsdate.h"
|
||||
#include "jsregexp.h"
|
||||
|
||||
|
||||
@@ -32,6 +32,6 @@
|
||||
|
||||
namespace mongo {
|
||||
|
||||
const char versionString[] = "1.3.6-pre-";
|
||||
const char versionString[] = "1.4.4";
|
||||
|
||||
} // namespace mongo
|
||||
|
||||
@@ -32,6 +32,8 @@ namespace po = boost::program_options;
|
||||
|
||||
namespace mongo {
|
||||
|
||||
CmdLine cmdLine;
|
||||
|
||||
Tool::Tool( string name , bool localDBAllowed , string defaultDB , string defaultCollection ) :
|
||||
_name( name ) , _db( defaultDB ) , _coll( defaultCollection ) , _conn(0), _paired(false) {
|
||||
|
||||
@@ -157,6 +159,7 @@ namespace mongo {
|
||||
if ( _params.count( "directoryperdb" ) ) {
|
||||
directoryperdb = true;
|
||||
}
|
||||
assert( lastError.get( true ) );
|
||||
Client::initThread("tools");
|
||||
_conn = new DBDirectClient();
|
||||
_host = "DIRECT";
|
||||
|
||||
@@ -143,6 +143,7 @@ namespace mongo {
|
||||
dbexit( EXIT_BADOPTIONS );
|
||||
assert( 0 );
|
||||
}
|
||||
fclose( test );
|
||||
|
||||
_path = lp;
|
||||
_enabled = 1;
|
||||
|
||||
@@ -195,6 +195,8 @@ namespace mongo {
|
||||
boost::thread::sleep(xt);
|
||||
}
|
||||
inline void sleepmicros(int s) {
|
||||
if ( s <= 0 )
|
||||
return;
|
||||
boost::xtime xt;
|
||||
boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
xt.sec += ( s / 1000000 );
|
||||
@@ -215,6 +217,8 @@ namespace mongo {
|
||||
}
|
||||
}
|
||||
inline void sleepmicros(int s) {
|
||||
if ( s <= 0 )
|
||||
return;
|
||||
struct timespec t;
|
||||
t.tv_sec = (int)(s / 1000000);
|
||||
t.tv_nsec = s % 1000000;
|
||||
@@ -650,43 +654,54 @@ namespace mongo {
|
||||
|
||||
// for convenience, '{' is greater than anything and stops number parsing
|
||||
inline int lexNumCmp( const char *s1, const char *s2 ) {
|
||||
int nret = 0;
|
||||
while( *s1 && *s2 ) {
|
||||
|
||||
bool p1 = ( *s1 == '{' );
|
||||
bool p2 = ( *s2 == '{' );
|
||||
if ( p1 && !p2 )
|
||||
return 1;
|
||||
if ( p2 && !p1 )
|
||||
return -1;
|
||||
|
||||
bool n1 = isNumber( *s1 );
|
||||
bool n2 = isNumber( *s2 );
|
||||
|
||||
if ( n1 && n2 ) {
|
||||
if ( nret == 0 ) {
|
||||
nret = *s1 > *s2 ? 1 : ( *s1 == *s2 ? 0 : -1 );
|
||||
}
|
||||
} else if ( n1 ) {
|
||||
return 1;
|
||||
} else if ( n2 ) {
|
||||
return -1;
|
||||
} else {
|
||||
if ( nret ) {
|
||||
return nret;
|
||||
}
|
||||
if ( *s1 > *s2 ) {
|
||||
char * e1;
|
||||
char * e2;
|
||||
long l1 = strtol( s1 , &e1 , 10 );
|
||||
long l2 = strtol( s2 , &e2 , 10 );
|
||||
|
||||
if ( l1 > l2 )
|
||||
return 1;
|
||||
} else if ( *s2 > *s1 ) {
|
||||
else if ( l1 < l2 )
|
||||
return -1;
|
||||
}
|
||||
nret = 0;
|
||||
}
|
||||
++s1; ++s2;
|
||||
|
||||
s1 = e1;
|
||||
s2 = e2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( n1 )
|
||||
return 1;
|
||||
|
||||
if ( n2 )
|
||||
return -1;
|
||||
|
||||
if ( *s1 > *s2 )
|
||||
return 1;
|
||||
|
||||
if ( *s2 > *s1 )
|
||||
return -1;
|
||||
|
||||
s1++; s2++;
|
||||
}
|
||||
if ( *s1 ) {
|
||||
|
||||
if ( *s1 )
|
||||
return 1;
|
||||
} else if ( *s2 ) {
|
||||
if ( *s2 )
|
||||
return -1;
|
||||
}
|
||||
return nret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace mongo
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace mongo {
|
||||
|
||||
void threadRun(){
|
||||
assert( grab );
|
||||
MessagingPort * p = grab;
|
||||
auto_ptr<MessagingPort> p( grab );
|
||||
grab = 0;
|
||||
|
||||
Message m;
|
||||
@@ -45,12 +45,11 @@ namespace mongo {
|
||||
break;
|
||||
}
|
||||
|
||||
handler->process( m , p );
|
||||
handler->process( m , p.get() );
|
||||
}
|
||||
}
|
||||
catch ( ... ){
|
||||
problem() << "uncaught exception in PortMessageServer::threadRun, closing connection" << endl;
|
||||
delete p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace mongo {
|
||||
HANDLE maphandle;
|
||||
void *view;
|
||||
long len;
|
||||
string _filename;
|
||||
};
|
||||
|
||||
void printMemInfo( const char * where );
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace mongo {
|
||||
|
||||
void* MemoryMappedFile::map(const char *filename, long &length, int options) {
|
||||
// length may be updated by callee.
|
||||
_filename = filename;
|
||||
theFileAllocator().allocateAsap( filename, length );
|
||||
len = length;
|
||||
|
||||
|
||||
@@ -46,13 +46,14 @@ namespace mongo {
|
||||
buf << s;
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
|
||||
unsigned mapped = 0;
|
||||
|
||||
void* MemoryMappedFile::map(const char *_filename, long &length, int options) {
|
||||
void* MemoryMappedFile::map(const char *filenameIn, long &length, int options) {
|
||||
_filename = filenameIn;
|
||||
/* big hack here: Babble uses db names with colons. doesn't seem to work on windows. temporary perhaps. */
|
||||
char filename[256];
|
||||
strncpy(filename, _filename, 255);
|
||||
strncpy(filename, filenameIn, 255);
|
||||
filename[255] = 0;
|
||||
{
|
||||
size_t len = strlen( filename );
|
||||
@@ -107,13 +108,13 @@ namespace mongo {
|
||||
bool success = FlushViewOfFile(view, 0); // 0 means whole mapping
|
||||
if (!success){
|
||||
int err = GetLastError();
|
||||
out() << "FlushViewOfFile failed " << err << endl;
|
||||
out() << "FlushViewOfFile failed " << err << " file: " << _filename << endl;
|
||||
}
|
||||
|
||||
success = FlushFileBuffers(fd);
|
||||
if (!success){
|
||||
int err = GetLastError();
|
||||
out() << "FlushFileBuffers failed " << err << endl;
|
||||
out() << "FlushFileBuffers failed " << err << " file: " << _filename << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "ntservice.h"
|
||||
#include <direct.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
@@ -32,17 +33,26 @@ namespace mongo {
|
||||
}
|
||||
|
||||
bool ServiceController::installService( const std::wstring& serviceName, const std::wstring& displayName, const std::wstring& serviceDesc, int argc, char* argv[] ) {
|
||||
assert(argc >= 1);
|
||||
|
||||
stringstream commandLine;
|
||||
|
||||
if ( strchr(argv[0], ':') ) { // a crude test for fully qualified path
|
||||
commandLine << '"' << argv[0] << "\" ";
|
||||
} else {
|
||||
char buffer[256];
|
||||
assert( _getcwd(buffer, 256) );
|
||||
commandLine << '"' << buffer << '\\' << argv[0] << "\" ";
|
||||
}
|
||||
|
||||
std::string commandLine;
|
||||
|
||||
for ( int i = 0; i < argc; i++ ) {
|
||||
for ( int i = 1; i < argc; i++ ) {
|
||||
std::string arg( argv[ i ] );
|
||||
|
||||
// replace install command to indicate process is being started as a service
|
||||
if ( arg == "--install" )
|
||||
arg = "--service";
|
||||
|
||||
commandLine += arg + " ";
|
||||
commandLine << arg << " ";
|
||||
}
|
||||
|
||||
SC_HANDLE schSCManager = ::OpenSCManager( null, null, SC_MANAGER_ALL_ACCESS );
|
||||
@@ -50,7 +60,7 @@ namespace mongo {
|
||||
return false;
|
||||
|
||||
std::basic_ostringstream< TCHAR > commandLineWide;
|
||||
commandLineWide << commandLine.c_str();
|
||||
commandLineWide << commandLine.str().c_str();
|
||||
|
||||
// create new service
|
||||
SC_HANDLE schService = ::CreateService( schSCManager, serviceName.c_str(), displayName.c_str(),
|
||||
@@ -101,11 +111,14 @@ namespace mongo {
|
||||
|
||||
SERVICE_STATUS serviceStatus;
|
||||
|
||||
// stop service if running
|
||||
// stop service if its running
|
||||
if ( ::ControlService( schService, SERVICE_CONTROL_STOP, &serviceStatus ) ) {
|
||||
while ( ::QueryServiceStatus( schService, &serviceStatus ) ) {
|
||||
if ( serviceStatus.dwCurrentState == SERVICE_STOP_PENDING )
|
||||
Sleep( 1000 );
|
||||
{
|
||||
Sleep( 1000 );
|
||||
}
|
||||
else { break; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,13 @@ namespace mongo {
|
||||
sprintf( name , "/proc/%d/stat" , pid );
|
||||
|
||||
FILE * f = fopen( name , "r");
|
||||
|
||||
if ( ! f ){
|
||||
stringstream ss;
|
||||
ss << "couldn't open [" << name << "] " << OUTPUT_ERRNO;
|
||||
string s = ss.str();
|
||||
msgasserted( 13276 , s.c_str() );
|
||||
}
|
||||
|
||||
int found = fscanf(f,
|
||||
"%d %s %c "
|
||||
"%d %d %d %d %d "
|
||||
|
||||
Reference in New Issue
Block a user