allocator.h   allocator.h 
skipping to change at line 37 skipping to change at line 37
inline void * ourrealloc(void *ptr, size_t size) { inline void * ourrealloc(void *ptr, size_t size) {
void *x = realloc(ptr, size); void *x = realloc(ptr, size);
if ( x == 0 ) dbexit( EXIT_OOM_REALLOC , "realloc fails"); if ( x == 0 ) dbexit( EXIT_OOM_REALLOC , "realloc fails");
return x; return x;
} }
#define malloc mongo::ourmalloc #define malloc mongo::ourmalloc
#define realloc mongo::ourrealloc #define realloc mongo::ourrealloc
#if defined(_WIN32)
inline void our_debug_free(void *p) {
#if 0
// this is not safe if you malloc < 4 bytes so we don't use anymore
unsigned *u = (unsigned *) p;
u[0] = 0xEEEEEEEE;
#endif
free(p);
}
#define free our_debug_free
#endif
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
12 lines changed or deleted 0 lines changed or added


 assert_util.h   assert_util.h 
skipping to change at line 69 skipping to change at line 69
enum { enum {
AssertRegular = 0, AssertRegular = 0,
AssertW = 1, AssertW = 1,
AssertMsg = 2, AssertMsg = 2,
AssertUser = 3 AssertUser = 3
}; };
/* last assert of diff types: regular, wassert, msgassert, uassert: */ /* last assert of diff types: regular, wassert, msgassert, uassert: */
extern Assertion lastAssert[4]; extern Assertion lastAssert[4];
class AssertionCount {
public:
AssertionCount();
void rollover();
void condrollover( int newValue );
int regular;
int warning;
int msg;
int user;
int rollovers;
};
extern AssertionCount assertionCount;
class DBException : public std::exception { class DBException : public std::exception {
public: public:
virtual const char* what() const throw() = 0; virtual const char* what() const throw() = 0;
virtual string toString() const { virtual string toString() const {
return what(); return what();
} }
virtual int getCode() = 0; virtual int getCode() = 0;
operator string() const { return toString(); } operator string() const { return toString(); }
}; };
 End of changes. 1 change blocks. 
0 lines changed or deleted 15 lines changed or added


 btree.h   btree.h 
skipping to change at line 56 skipping to change at line 56
recordLoc.GETOFS() &= ~1; recordLoc.GETOFS() &= ~1;
} }
void setUnused() { void setUnused() {
/* Setting ofs to odd is the sentinel for unused, as real recor dLoc's are always /* Setting ofs to odd is the sentinel for unused, as real recor dLoc's are always
even numbers. even numbers.
Note we need to keep its value basically the same as we use the recordLoc Note we need to keep its value basically the same as we use the recordLoc
as part of the key in the index (to handle duplicate keys ef ficiently). as part of the key in the index (to handle duplicate keys ef ficiently).
*/ */
recordLoc.GETOFS() |= 1; recordLoc.GETOFS() |= 1;
} }
int isUnused() { int isUnused() const {
return recordLoc.getOfs() & 1; return recordLoc.getOfs() & 1;
} }
int isUsed() { int isUsed() const {
return !isUnused(); return !isUnused();
} }
}; };
#pragma pack() #pragma pack()
class BucketBasics; class BucketBasics;
/* wrapper - this is our in memory representation of the key. _KeyNode is the disk representation. */ /* wrapper - this is our in memory representation of the key. _KeyNode is the disk representation. */
class KeyNode { class KeyNode {
skipping to change at line 88 skipping to change at line 88
/* this class is all about the storage management */ /* this class is all about the storage management */
class BucketBasics { class BucketBasics {
friend class BtreeBuilder; friend class BtreeBuilder;
friend class KeyNode; friend class KeyNode;
public: public:
void dumpTree(DiskLoc thisLoc, const BSONObj &order); void dumpTree(DiskLoc thisLoc, const BSONObj &order);
bool isHead() { return parent.isNull(); } bool isHead() { return parent.isNull(); }
void assertValid(const BSONObj &order, bool force = false); void assertValid(const BSONObj &order, bool force = false);
int fullValidate(const DiskLoc& thisLoc, const BSONObj &order); /* traverses everything */ int fullValidate(const DiskLoc& thisLoc, const BSONObj &order); /* traverses everything */
protected:
void modified(const DiskLoc& thisLoc);
KeyNode keyNode(int i) const { KeyNode keyNode(int i) const {
if ( i >= n ){ if ( i >= n ){
massert( 13000 , (string)"invalid keyNode: " + BSON( "i" < < i << "n" << n ).jsonString() , i < n ); massert( 13000 , (string)"invalid keyNode: " + BSON( "i" < < i << "n" << n ).jsonString() , i < n );
} }
return KeyNode(*this, k(i)); return KeyNode(*this, k(i));
} }
protected:
void modified(const DiskLoc& thisLoc);
char * dataAt(short ofs) { char * dataAt(short ofs) {
return data + ofs; return data + ofs;
} }
void init(); // initialize a new node void init(); // initialize a new node
/* returns false if node is full and must be split /* returns false if node is full and must be split
keypos is where to insert -- inserted after that key #. so keyp os=0 is the leftmost one. keypos is where to insert -- inserted after that key #. so keyp os=0 is the leftmost one.
*/ */
bool basicInsert(const DiskLoc& thisLoc, int keypos, const DiskLoc& recordLoc, const BSONObj& key, const BSONObj &order); bool basicInsert(const DiskLoc& thisLoc, int keypos, const DiskLoc& recordLoc, const BSONObj& key, const BSONObj &order);
skipping to change at line 157 skipping to change at line 160
stringstream ss; stringstream ss;
ss << " Bucket info:" << endl; ss << " Bucket info:" << endl;
ss << " n: " << n << endl; ss << " n: " << n << endl;
ss << " parent: " << parent.toString() << endl; ss << " parent: " << parent.toString() << endl;
ss << " nextChild: " << parent.toString() << endl; ss << " nextChild: " << parent.toString() << endl;
ss << " Size: " << _Size << " flags:" << flags << endl; ss << " Size: " << _Size << " flags:" << flags << endl;
ss << " emptySize: " << emptySize << " topSize: " << topSize << endl; ss << " emptySize: " << emptySize << " topSize: " << topSize << endl;
return ss.str(); return ss.str();
} }
bool isUsed( int i ) const {
return k(i).isUsed();
}
protected: protected:
void _shape(int level, stringstream&); void _shape(int level, stringstream&);
DiskLoc nextChild; // child bucket off and to the right of the high est key. DiskLoc nextChild; // child bucket off and to the right of the high est key.
int _Size; // total size of this btree node in bytes. constant. int _Size; // total size of this btree node in bytes. constant.
int Size() const; int Size() const;
int flags; int flags;
int emptySize; // size of the empty region int emptySize; // size of the empty region
int topSize; // size of the data at the top of the bucket (keys are at the beginning or 'bottom') int topSize; // size of the data at the top of the bucket (keys are at the beginning or 'bottom')
int n; // # of keys so far. int n; // # of keys so far.
int reserved; int reserved;
skipping to change at line 373 skipping to change at line 380
const IndexDetails& indexDetails; const IndexDetails& indexDetails;
BSONObj order; BSONObj order;
DiskLoc bucket; DiskLoc bucket;
int keyOfs; int keyOfs;
int direction; // 1=fwd,-1=reverse int direction; // 1=fwd,-1=reverse
BSONObj keyAtKeyOfs; // so we can tell if things moved around on us between the query and the getMore call BSONObj keyAtKeyOfs; // so we can tell if things moved around on us between the query and the getMore call
DiskLoc locAtKeyOfs; DiskLoc locAtKeyOfs;
BoundList bounds_; BoundList bounds_;
unsigned boundIndex_; unsigned boundIndex_;
const IndexSpec& _spec;
}; };
#pragma pack() #pragma pack()
inline bool IndexDetails::hasKey(const BSONObj& key) { inline bool IndexDetails::hasKey(const BSONObj& key) {
return head.btree()->exists(*this, head, key, keyPattern()); return head.btree()->exists(*this, head, key, keyPattern());
} }
inline bool IndexDetails::wouldCreateDup(const BSONObj& key, DiskLoc se lf) { inline bool IndexDetails::wouldCreateDup(const BSONObj& key, DiskLoc se lf) {
return head.btree()->wouldCreateDup(*this, head, key, keyPattern(), self); return head.btree()->wouldCreateDup(*this, head, key, keyPattern(), self);
} }
 End of changes. 6 change blocks. 
4 lines changed or deleted 12 lines changed or added


 chunk.h   chunk.h 
skipping to change at line 120 skipping to change at line 120
virtual void serialize(BSONObjBuilder& to); virtual void serialize(BSONObjBuilder& to);
virtual void unserialize(const BSONObj& from); virtual void unserialize(const BSONObj& from);
virtual string modelServer(); virtual string modelServer();
virtual void save( bool check=false ); virtual void save( bool check=false );
void ensureIndex(); void ensureIndex();
void _markModified(); void _markModified();
static long MaxChunkSize; static int MaxChunkSize;
private: private:
// main shard info // main shard info
ChunkManager * _manager; ChunkManager * _manager;
ShardKeyPattern skey() const; ShardKeyPattern skey() const;
string _ns; string _ns;
BSONObj _min; BSONObj _min;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 clientcursor.h   clientcursor.h 
skipping to change at line 126 skipping to change at line 126
recursive_boostlock lock(ccmutex); recursive_boostlock lock(ccmutex);
cursorid = allocCursorId_inlock(); cursorid = allocCursorId_inlock();
clientCursorsById.insert( make_pair(cursorid, this) ); clientCursorsById.insert( make_pair(cursorid, this) );
} }
~ClientCursor(); ~ClientCursor();
DiskLoc lastLoc() const { DiskLoc lastLoc() const {
return _lastLoc; return _lastLoc;
} }
auto_ptr< FieldMatcher > filter; // which fields query wants return ed shared_ptr< FieldMatcher > fields; // which fields query wants retu rned
Message originalMessage; // this is effectively an auto ptr for dat a the matcher points to Message originalMessage; // this is effectively an auto ptr for dat a the matcher points to
/* Get rid of cursors for namespaces that begin with nsprefix. /* Get rid of cursors for namespaces that begin with nsprefix.
Used by drop, dropIndexes, dropDatabase. Used by drop, dropIndexes, dropDatabase.
*/ */
static void invalidate(const char *nsPrefix); static void invalidate(const char *nsPrefix);
/** /**
* do a dbtemprelease * do a dbtemprelease
* note: caller should check matcher.docMatcher().atomic() first an d not yield if atomic - * note: caller should check matcher.docMatcher().atomic() first an d not yield if atomic -
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 commands.h   commands.h 
skipping to change at line 28 skipping to change at line 28
#pragma once #pragma once
#include "../stdafx.h" #include "../stdafx.h"
#include "jsobj.h" #include "jsobj.h"
namespace mongo { namespace mongo {
class BSONObj; class BSONObj;
class BSONObjBuilder; class BSONObjBuilder;
class BufBuilder; class BufBuilder;
class Client;
// db "commands" (sent via db.$cmd.findOne(...)) // db "commands" (sent via db.$cmd.findOne(...))
// subclass to make a command. // subclass to make a command.
class Command { class Command {
public: public:
enum LockType { READ = -1 , NONE = 0 , WRITE = 1 };
string name; string name;
/* run the given command /* run the given command
implement this... implement this...
fromRepl - command is being invoked as part of replication synci ng. In this situation you fromRepl - command is being invoked as part of replication synci ng. In this situation you
normally do not want to log the command to the local oplog. normally do not want to log the command to the local oplog.
return value is true if succeeded. if false, set errmsg text. return value is true if succeeded. if false, set errmsg text.
*/ */
virtual bool run(const char *ns, BSONObj& cmdObj, string& errmsg, B SONObjBuilder& result, bool fromRepl) = 0; virtual bool run(const char *ns, BSONObj& cmdObj, string& errmsg, B SONObjBuilder& result, bool fromRepl) = 0;
/* true if a read lock is sufficient /*
note: logTheTop() MUST be false if readOnly note: logTheTop() MUST be false if READ
if NONE, can't use Client::Context setup
use with caution
*/ */
virtual bool readOnly() { virtual LockType locktype() = 0;
return false;
}
/* Return true if only the admin ns has privileges to run this comm and. */ /* Return true if only the admin ns has privileges to run this comm and. */
virtual bool adminOnly() { virtual bool adminOnly() {
return false; return false;
} }
/* Like adminOnly, but even stricter: we must either be authenticat ed for admin db, /* Like adminOnly, but even stricter: we must either be authenticat ed for admin db,
or, if running without auth, on the local interface. or, if running without auth, on the local interface.
When localHostOnlyIfNoAuth() is true, adminOnly() must also be t rue. When localHostOnlyIfNoAuth() is true, adminOnly() must also be t rue.
skipping to change at line 108 skipping to change at line 112
return cmdObj["query"].embeddedObject(); return cmdObj["query"].embeddedObject();
if ( cmdObj["q"].type() == Object ) if ( cmdObj["q"].type() == Object )
return cmdObj["q"].embeddedObject(); return cmdObj["q"].embeddedObject();
return BSONObj(); return BSONObj();
} }
static map<string,Command*> * _commands; static map<string,Command*> * _commands;
public: public:
static bool runAgainstRegistered(const char *ns, BSONObj& jsobj, BS ONObjBuilder& anObjBuilder); static bool runAgainstRegistered(const char *ns, BSONObj& jsobj, BS ONObjBuilder& anObjBuilder);
static bool readOnly( const string& name ); static LockType locktype( const string& name );
static Command * findCommand( const string& name ); static Command * findCommand( const string& name );
}; };
bool _runCommands(const char *ns, BSONObj& jsobj, BufBuilder &b, BSONOb jBuilder& anObjBuilder, bool fromRepl, int queryOptions); bool _runCommands(const char *ns, BSONObj& jsobj, BufBuilder &b, BSONOb jBuilder& anObjBuilder, bool fromRepl, int queryOptions);
} // namespace mongo } // namespace mongo
 End of changes. 5 change blocks. 
6 lines changed or deleted 10 lines changed or added


 concurrency.h   concurrency.h 
skipping to change at line 38 skipping to change at line 38
*/ */
#pragma once #pragma once
#if BOOST_VERSION >= 103500 #if BOOST_VERSION >= 103500
#include <boost/thread/shared_mutex.hpp> #include <boost/thread/shared_mutex.hpp>
#undef assert #undef assert
#define assert xassert #define assert xassert
#define HAVE_READLOCK #define HAVE_READLOCK
#else #else
#warning built with boost version 1.34 or older limited concurrency #warning built with boost version 1.34 or older - limited concurrency
#endif #endif
namespace mongo { namespace mongo {
inline bool readLockSupported(){ inline bool readLockSupported(){
#ifdef HAVE_READLOCK #ifdef HAVE_READLOCK
return true; return true;
#else #else
return false; return false;
#endif #endif
skipping to change at line 327 skipping to change at line 327
dbunlocking_read(); dbunlocking_read();
dbMutex.unlock_shared(); dbMutex.unlock_shared();
} }
} }
bool got(){ bool got(){
return _got; return _got;
} }
bool _got; bool _got;
}; };
struct atleastreadlock {
atleastreadlock( const string& ns ){
_prev = dbMutex.getState();
if ( _prev == 0 )
dbMutex.lock_shared();
}
~atleastreadlock(){
if ( _prev == 0 )
dbMutex.unlock_shared();
}
int _prev;
};
class mongolock { class mongolock {
bool _writelock; bool _writelock;
public: public:
mongolock(bool write) : _writelock(write) { mongolock(bool write) : _writelock(write) {
if( _writelock ) { if( _writelock ) {
dbMutex.lock(); dbMutex.lock();
} }
else else
dbMutex.lock_shared(); dbMutex.lock_shared();
} }
 End of changes. 2 change blocks. 
1 lines changed or deleted 15 lines changed or added


 dbclient.h   dbclient.h 
skipping to change at line 24 skipping to change at line 24
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include "../stdafx.h" #include "../stdafx.h"
#include "../util/message.h" #include "../util/message.h"
#include "../db/jsobj.h" #include "../db/jsobj.h"
#include "../db/json.h" #include "../db/json.h"
#include <stack>
namespace mongo { namespace mongo {
/** the query field 'options' can have these bits set: */ /** the query field 'options' can have these bits set: */
enum QueryOptions { enum QueryOptions {
/** Tailable means cursor is not closed when the last data is retri eved. rather, the cursor marks /** Tailable means cursor is not closed when the last data is retri eved. rather, the cursor marks
the final object's position. you can resume using the cursor la ter, from where it was located, the final object's position. you can resume using the cursor la ter, from where it was located,
if more data were received. Set on dbQuery and dbGetMore. if more data were received. Set on dbQuery and dbGetMore.
like any "latent cursor", the cursor may become invalid at some point -- for example if that like any "latent cursor", the cursor may become invalid at some point -- for example if that
skipping to change at line 213 skipping to change at line 214
bool init(); bool init();
public: public:
/** If true, safe to call next(). Requests more from server if necessary. */ /** If true, safe to call next(). Requests more from server if necessary. */
bool more(); bool more();
/** If true, there is more in our local buffers to be fetched via n ext(). Returns /** If true, there is more in our local buffers to be fetched via n ext(). Returns
false when a getMore request back to server would be required. You can use this false when a getMore request back to server would be required. You can use this
if you want to exhaust whatever data has been fetched to the cl ient already but if you want to exhaust whatever data has been fetched to the cl ient already but
then perhaps stop. then perhaps stop.
*/ */
bool moreInCurrentBatch() { return pos < nReturned; } bool moreInCurrentBatch() { return !_putBack.empty() || pos < nRetu rned; }
/** next /** next
@return next object in the result cursor. @return next object in the result cursor.
on an error at the remote server, you will get back: on an error at the remote server, you will get back:
{ $err: <string> } { $err: <string> }
if you do not want to handle that yourself, call nextSafe(). if you do not want to handle that yourself, call nextSafe().
*/ */
BSONObj next(); BSONObj next();
/**
restore an object previously returned by next() to the cursor
*/
void putBack( const BSONObj &o ) { _putBack.push( o.getOwned() ); }
/** throws AssertionException if get back { $err : ... } */ /** throws AssertionException if get back { $err : ... } */
BSONObj nextSafe() { BSONObj nextSafe() {
BSONObj o = next(); BSONObj o = next();
BSONElement e = o.firstElement(); BSONElement e = o.firstElement();
assert( strcmp(e.fieldName(), "$err") != 0 ); assert( strcmp(e.fieldName(), "$err") != 0 );
return o; return o;
} }
/** /**
iterate the rest of the cursor and return the number if items iterate the rest of the cursor and return the number if items
skipping to change at line 256 skipping to change at line 262
available from the dbclientcursor. available from the dbclientcursor.
*/ */
bool isDead() const { bool isDead() const {
return cursorId == 0; return cursorId == 0;
} }
bool tailable() const { bool tailable() const {
return (opts & QueryOption_CursorTailable) != 0; return (opts & QueryOption_CursorTailable) != 0;
} }
/** see QueryResult::ResultFlagType (db/dbmessage.h) for flag value
s
mostly these flags are for internal purposes -
ResultFlag_ErrSet is the possible exception to that
*/
bool hasResultFlag( int flag ){ bool hasResultFlag( int flag ){
return (resultFlags & flag) != 0; return (resultFlags & flag) != 0;
} }
public:
DBClientCursor( DBConnector *_connector, const string &_ns, BSONObj _query, int _nToReturn, DBClientCursor( DBConnector *_connector, const string &_ns, BSONObj _query, int _nToReturn,
int _nToSkip, const BSONObj *_fieldsToReturn, int q ueryOptions ) : int _nToSkip, const BSONObj *_fieldsToReturn, int q ueryOptions , int bs ) :
connector(_connector), connector(_connector),
ns(_ns), ns(_ns),
query(_query), query(_query),
nToReturn(_nToReturn), nToReturn(_nToReturn),
haveLimit( _nToReturn > 0 && !(queryOptions & QueryOption_C ursorTailable)),
nToSkip(_nToSkip), nToSkip(_nToSkip),
fieldsToReturn(_fieldsToReturn), fieldsToReturn(_fieldsToReturn),
opts(queryOptions), opts(queryOptions),
batchSize(bs),
m(new Message()), m(new Message()),
cursorId(), cursorId(),
nReturned(), nReturned(),
pos(), pos(),
data(), data(),
_ownCursor( true ) { _ownCursor( true ) {
} }
DBClientCursor( DBConnector *_connector, const string &_ns, long lo ng _cursorId, int _nToReturn, int options ) : DBClientCursor( DBConnector *_connector, const string &_ns, long lo ng _cursorId, int _nToReturn, int options ) :
connector(_connector), connector(_connector),
ns(_ns), ns(_ns),
nToReturn( _nToReturn ), nToReturn( _nToReturn ),
haveLimit( _nToReturn > 0 && !(options & QueryOption_Cursor Tailable)),
opts( options ), opts( options ),
m(new Message()), m(new Message()),
cursorId( _cursorId ), cursorId( _cursorId ),
nReturned(), nReturned(),
pos(), pos(),
data(), data(),
_ownCursor( true ) { _ownCursor( true ) {
} }
virtual ~DBClientCursor(); virtual ~DBClientCursor();
long long getCursorId() const { return cursorId; } long long getCursorId() const { return cursorId; }
/** by default we "own" the cursor and will send the server a KillC ursor /** by default we "own" the cursor and will send the server a KillC ursor
message when ~DBClientCursor() is called. This function overrid es that. message when ~DBClientCursor() is called. This function overrid es that.
*/ */
void decouple() { _ownCursor = false; } void decouple() { _ownCursor = false; }
private: private:
int nextBatchSize();
DBConnector *connector; DBConnector *connector;
string ns; string ns;
BSONObj query; BSONObj query;
int nToReturn; int nToReturn;
bool haveLimit;
int nToSkip; int nToSkip;
const BSONObj *fieldsToReturn; const BSONObj *fieldsToReturn;
int opts; int opts;
int batchSize;
auto_ptr<Message> m; auto_ptr<Message> m;
stack< BSONObj > _putBack;
int resultFlags; int resultFlags;
long long cursorId; long long cursorId;
int nReturned; int nReturned;
int pos; int pos;
const char *data; const char *data;
void dataReceived(); void dataReceived();
void requestMore(); void requestMore();
bool _ownCursor; // see decouple() bool _ownCursor; // see decouple()
}; };
/** /**
The interface that any db connection should implement The interface that any db connection should implement
*/ */
class DBClientInterface : boost::noncopyable { class DBClientInterface : boost::noncopyable {
public: public:
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0, virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0,
const BSONObj *fieldsToRetur n = 0, int queryOptions = 0) = 0; const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 ) = 0;
virtual auto_ptr<DBClientCursor> getMore( const string &ns, long lo ng cursorId, int nToReturn = 0, int options = 0 ) = 0; virtual auto_ptr<DBClientCursor> getMore( const string &ns, long lo ng cursorId, int nToReturn = 0, int options = 0 ) = 0;
virtual void insert( const string &ns, BSONObj obj ) = 0; virtual void insert( const string &ns, BSONObj obj ) = 0;
virtual void insert( const string &ns, const vector< BSONObj >& v ) = 0; virtual void insert( const string &ns, const vector< BSONObj >& v ) = 0;
virtual void remove( const string &ns , Query query, bool justOne = 0 ) = 0; virtual void remove( const string &ns , Query query, bool justOne = 0 ) = 0;
virtual void update( const string &ns , Query query , BSONObj obj , bool upsert = 0 , bool multi = 0 ) = 0; virtual void update( const string &ns , Query query , BSONObj obj , bool upsert = 0 , bool multi = 0 ) = 0;
skipping to change at line 669 skipping to change at line 688
nToReturn: n to return. 0 = unlimited nToReturn: n to return. 0 = unlimited
nToSkip: start with the nth item nToSkip: start with the nth item
fieldsToReturn: fieldsToReturn:
optional template of which fields to select. if unspecified, retur ns all fields optional template of which fields to select. if unspecified, retur ns all fields
queryOptions: see options enum at top of this file queryOptions: see options enum at top of this file
@return cursor. 0 if error (connection failure) @return cursor. 0 if error (connection failure)
@throws AssertionException @throws AssertionException
*/ */
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0, virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0,
const BSONObj *fieldsToRetur n = 0, int queryOptions = 0); const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 );
/** @param cursorId id of cursor to retrieve /** @param cursorId id of cursor to retrieve
@return an handle to a previously allocated cursor @return an handle to a previously allocated cursor
@throws AssertionException @throws AssertionException
*/ */
virtual auto_ptr<DBClientCursor> getMore( const string &ns, long lo ng cursorId, int nToReturn = 0, int options = 0 ); virtual auto_ptr<DBClientCursor> getMore( const string &ns, long lo ng cursorId, int nToReturn = 0, int options = 0 );
/** /**
insert an object into the database insert an object into the database
*/ */
skipping to change at line 763 skipping to change at line 782
*/ */
void connect(string serverHostname) { void connect(string serverHostname) {
string errmsg; string errmsg;
if( !connect(serverHostname.c_str(), errmsg) ) if( !connect(serverHostname.c_str(), errmsg) )
throw ConnectException(string("can't connect ") + errmsg); throw ConnectException(string("can't connect ") + errmsg);
} }
virtual bool auth(const string &dbname, const string &username, con st string &pwd, string& errmsg, bool digestPassword = true); virtual bool auth(const string &dbname, const string &username, con st string &pwd, string& errmsg, bool digestPassword = true);
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0, virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0,
const BSONObj *fieldsToRetur n = 0, int queryOptions = 0) { const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 ) {
checkConnection(); checkConnection();
return DBClientBase::query( ns, query, nToReturn, nToSkip, fiel dsToReturn, queryOptions ); return DBClientBase::query( ns, query, nToReturn, nToSkip, fiel dsToReturn, queryOptions , batchSize );
} }
/** /**
@return true if this connection is currently in a failed state. When autoreconnect is on, @return true if this connection is currently in a failed state. When autoreconnect is on,
a connection will transition back to an ok state after r econnecting. a connection will transition back to an ok state after r econnecting.
*/ */
bool isFailed() const { bool isFailed() const {
return failed; return failed;
} }
skipping to change at line 843 skipping to change at line 862
*/ */
bool connect(string hostpairstring); bool connect(string hostpairstring);
/** Authorize. Authorizes both sides of the pair as needed. /** Authorize. Authorizes both sides of the pair as needed.
*/ */
bool auth(const string &dbname, const string &username, const strin g &pwd, string& errmsg); bool auth(const string &dbname, const string &username, const strin g &pwd, string& errmsg);
/** throws userassertion "no master found" */ /** throws userassertion "no master found" */
virtual virtual
auto_ptr<DBClientCursor> query(const string &ns, Query query, int n ToReturn = 0, int nToSkip = 0, auto_ptr<DBClientCursor> query(const string &ns, Query query, int n ToReturn = 0, int nToSkip = 0,
const BSONObj *fieldsToReturn = 0, i nt queryOptions = 0); const BSONObj *fieldsToReturn = 0, i nt queryOptions = 0 , int batchSize = 0 );
/** throws userassertion "no master found" */ /** throws userassertion "no master found" */
virtual virtual
BSONObj findOne(const string &ns, Query query, const BSONObj *field sToReturn = 0, int queryOptions = 0); BSONObj findOne(const string &ns, Query query, const BSONObj *field sToReturn = 0, int queryOptions = 0);
/** insert */ /** insert */
virtual void insert( const string &ns , BSONObj obj ) { virtual void insert( const string &ns , BSONObj obj ) {
checkMaster().insert(ns, obj); checkMaster().insert(ns, obj);
} }
 End of changes. 18 change blocks. 
8 lines changed or deleted 28 lines changed or added


 dbmessage.h   dbmessage.h 
skipping to change at line 181 skipping to change at line 181
}; };
/* a request to run a query, received from the database */ /* a request to run a query, received from the database */
class QueryMessage { class QueryMessage {
public: public:
const char *ns; const char *ns;
int ntoskip; int ntoskip;
int ntoreturn; int ntoreturn;
int queryOptions; int queryOptions;
BSONObj query; BSONObj query;
auto_ptr< FieldMatcher > fields; BSONObj fields;
/* parses the message into the above fields */ /* parses the message into the above fields */
QueryMessage(DbMessage& d) { QueryMessage(DbMessage& d) {
ns = d.getns(); ns = d.getns();
ntoskip = d.pullInt(); ntoskip = d.pullInt();
ntoreturn = d.pullInt(); ntoreturn = d.pullInt();
query = d.nextJsObj(); query = d.nextJsObj();
if ( d.moreJSObjs() ) { if ( d.moreJSObjs() ) {
BSONObj o = d.nextJsObj(); fields = d.nextJsObj();
if (!o.isEmpty()){
fields = auto_ptr< FieldMatcher >(new FieldMatcher() );
fields->add( o );
}
} }
queryOptions = d.msg().data->dataAsInt(); queryOptions = d.msg().data->dataAsInt();
} }
}; };
} // namespace mongo } // namespace mongo
#include "../client/dbclient.h" #include "../client/dbclient.h"
namespace mongo { namespace mongo {
 End of changes. 2 change blocks. 
6 lines changed or deleted 2 lines changed or added


 engine.h   engine.h 
skipping to change at line 123 skipping to change at line 123
long long _loadedVersion; long long _loadedVersion;
set<string> _storedNames; set<string> _storedNames;
static long long _lastVersion; static long long _lastVersion;
map<string,ScriptingFunction> _cachedFunctions; map<string,ScriptingFunction> _cachedFunctions;
static int _numScopes; static int _numScopes;
}; };
void installGlobalUtils( Scope& scope ); void installGlobalUtils( Scope& scope );
class DBClientWithCommands;
class ScriptEngine : boost::noncopyable { class ScriptEngine : boost::noncopyable {
public: public:
ScriptEngine(); ScriptEngine();
virtual ~ScriptEngine(); virtual ~ScriptEngine();
virtual Scope * newScope() { virtual Scope * newScope() {
Scope *s = createScope(); Scope *s = createScope();
if ( s && _scopeInitCallback ) if ( s && _scopeInitCallback )
_scopeInitCallback( *s ); _scopeInitCallback( *s );
installGlobalUtils( *s ); installGlobalUtils( *s );
skipping to change at line 149 skipping to change at line 151
static void setup(); static void setup();
auto_ptr<Scope> getPooledScope( const string& pool ); auto_ptr<Scope> getPooledScope( const string& pool );
void threadDone(); void threadDone();
struct Unlocker { virtual ~Unlocker() {} }; struct Unlocker { virtual ~Unlocker() {} };
virtual auto_ptr<Unlocker> newThreadUnlocker() { return auto_ptr< U nlocker >( new Unlocker ); } virtual auto_ptr<Unlocker> newThreadUnlocker() { return auto_ptr< U nlocker >( new Unlocker ); }
void setScopeInitCallback( void ( *func )( Scope & ) ) { _scopeInit Callback = func; } void setScopeInitCallback( void ( *func )( Scope & ) ) { _scopeInit Callback = func; }
static void setConnectCallback( void ( *func )( DBClientWithCommand
s& ) ) { _connectCallback = func; }
static void runConnectCallback( DBClientWithCommands &c ) {
if ( _connectCallback )
_connectCallback( c );
}
protected: protected:
virtual Scope * createScope() = 0; virtual Scope * createScope() = 0;
private: private:
void ( *_scopeInitCallback )( Scope & ); void ( *_scopeInitCallback )( Scope & );
static void ( *_connectCallback )( DBClientWithCommands & );
}; };
extern ScriptEngine * globalScriptEngine; extern ScriptEngine * globalScriptEngine;
} }
 End of changes. 3 change blocks. 
0 lines changed or deleted 9 lines changed or added


 extsort.h   extsort.h 
skipping to change at line 25 skipping to change at line 25
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "../stdafx.h" #include "../stdafx.h"
#include "jsobj.h" #include "jsobj.h"
#include "namespace.h" #include "namespace.h"
#include "curop.h" #include "curop.h"
#include "../util/array.h"
namespace mongo { namespace mongo {
/** /**
for sorting by BSONObj and attaching a value for sorting by BSONObj and attaching a value
*/ */
class BSONObjExternalSorter : boost::noncopyable { class BSONObjExternalSorter : boost::noncopyable {
public: public:
typedef pair<BSONObj,DiskLoc> Data; typedef pair<BSONObj,DiskLoc> Data;
private: private:
static BSONObj extSortOrder;
static int extSortComp( const void *lv, const void *rv ){
RARELY killCurrentOp.checkForInterrupt();
_compares++;
Data * l = (Data*)lv;
Data * r = (Data*)rv;
int cmp = l->first.woCompare( r->first , extSortOrder );
if ( cmp )
return cmp;
return l->second.compare( r->second );
};
class FileIterator : boost::noncopyable { class FileIterator : boost::noncopyable {
public: public:
FileIterator( string file ); FileIterator( string file );
~FileIterator(); ~FileIterator();
bool more(); bool more();
Data next(); Data next();
private: private:
MemoryMappedFile _file; MemoryMappedFile _file;
char * _buf; char * _buf;
char * _end; char * _end;
skipping to change at line 60 skipping to change at line 74
public: public:
MyCmp( const BSONObj & order = BSONObj() ) : _order( order ){} MyCmp( const BSONObj & order = BSONObj() ) : _order( order ){}
bool operator()( const Data &l, const Data &r ) const { bool operator()( const Data &l, const Data &r ) const {
RARELY killCurrentOp.checkForInterrupt(); RARELY killCurrentOp.checkForInterrupt();
_compares++; _compares++;
int x = l.first.woCompare( r.first , _order ); int x = l.first.woCompare( r.first , _order );
if ( x ) if ( x )
return x < 0; return x < 0;
return l.second.compare( r.second ) < 0; return l.second.compare( r.second ) < 0;
}; };
private: private:
BSONObj _order; BSONObj _order;
}; };
public: public:
typedef list<Data> InMemory; typedef FastArray<Data> InMemory;
class Iterator : boost::noncopyable { class Iterator : boost::noncopyable {
public: public:
Iterator( BSONObjExternalSorter * sorter ); Iterator( BSONObjExternalSorter * sorter );
~Iterator(); ~Iterator();
bool more(); bool more();
Data next(); Data next();
private: private:
skipping to change at line 106 skipping to change at line 121
auto_ptr<Iterator> iterator(){ auto_ptr<Iterator> iterator(){
uassert( 10052 , "not sorted" , _sorted ); uassert( 10052 , "not sorted" , _sorted );
return auto_ptr<Iterator>( new Iterator( this ) ); return auto_ptr<Iterator>( new Iterator( this ) );
} }
int numFiles(){ int numFiles(){
return _files.size(); return _files.size();
} }
long getCurSizeSoFar(){ return _curSizeSoFar; }
void hintNumObjects( long long numObjects ){
if ( numObjects < _arraySize )
_arraySize = (int)(numObjects + 100);
}
private: private:
void _sortInMem();
void sort( string file ); void sort( string file );
void finishMap(); void finishMap();
BSONObj _order; BSONObj _order;
long _maxFilesize; long _maxFilesize;
path _root; path _root;
int _arraySize;
InMemory * _cur; InMemory * _cur;
long _curSizeSoFar; long _curSizeSoFar;
list<string> _files; list<string> _files;
bool _sorted; bool _sorted;
static unsigned long long _compares; static unsigned long long _compares;
}; };
} }
 End of changes. 7 change blocks. 
1 lines changed or deleted 26 lines changed or added


 goodies.h   goodies.h 
skipping to change at line 500 skipping to change at line 500
_holder = holder; _holder = holder;
} }
~TicketHolderReleaser(){ ~TicketHolderReleaser(){
_holder->release(); _holder->release();
} }
private: private:
TicketHolder * _holder; TicketHolder * _holder;
}; };
/**
* this is a thread safe string
* you will never get a bad pointer, though data may be mungedd
*/
class ThreadSafeString {
public:
ThreadSafeString( size_t size=256 )
: _size( 256 ) , _buf( new char[256] ){
memset( _buf , 0 , _size );
}
ThreadSafeString( const ThreadSafeString& other )
: _size( other._size ) , _buf( new char[_size] ){
strncpy( _buf , other._buf , _size );
}
~ThreadSafeString(){
delete[] _buf;
_buf = 0;
}
operator string() const {
string s = _buf;
return s;
}
ThreadSafeString& operator=( const char * str ){
size_t s = strlen(str);
if ( s >= _size - 2 )
s = _size - 2;
strncpy( _buf , str , s );
_buf[s] = 0;
return *this;
}
bool operator==( const ThreadSafeString& other ) const {
return strcmp( _buf , other._buf ) == 0;
}
bool operator==( const char * str ) const {
return strcmp( _buf , str ) == 0;
}
bool operator!=( const char * str ) const {
return strcmp( _buf , str );
}
bool empty() const {
return _buf[0] == 0;
}
private:
size_t _size;
char * _buf;
};
ostream& operator<<( ostream &s, const ThreadSafeString &o );
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
0 lines changed or deleted 58 lines changed or added


 httpclient.h   httpclient.h 
skipping to change at line 26 skipping to change at line 26
*/ */
#pragma once #pragma once
#include "../stdafx.h" #include "../stdafx.h"
namespace mongo { namespace mongo {
class HttpClient { class HttpClient {
public: public:
int get( string url , map<string,string>& headers, stringstream& da
ta ); class Result {
public:
Result(){}
const string& getEntireResponse() const {
return _entireResponse;
}
private:
int _code;
string _entireResponse;
friend class HttpClient;
};
/**
* @return response code
*/
int get( string url , Result * result = 0 );
/**
* @return response code
*/
int post( string url , string body , Result * result = 0 );
private:
int _go( const char * command , string url , const char * body , Re
sult * result );
}; };
} }
 End of changes. 1 change blocks. 
2 lines changed or deleted 28 lines changed or added


 index.h   index.h 
skipping to change at line 22 skipping to change at line 22
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "../stdafx.h" #include "../stdafx.h"
#include "diskloc.h"
#include "jsobj.h"
#include <map>
namespace mongo { namespace mongo {
class IndexSpec;
class IndexType; // TODO: this name sucks
class IndexPlugin;
class IndexDetails;
enum IndexSuitability { USELESS = 0 , HELPFUL = 1 , OPTIMAL = 2 };
/**
* this represents an instance of a index plugin
* done this way so parsing, etc... can be cached
* so if there is a FTS IndexPlugin, for each index using FTS
* there will be 1 of these, and it can have things pre-parsed, etc...
*/
class IndexType : boost::noncopyable {
public:
IndexType( const IndexPlugin * plugin , const IndexSpec * spec );
virtual ~IndexType();
virtual void getKeys( const BSONObj &obj, BSONObjSetDefaultOrder &k
eys ) const = 0;
virtual auto_ptr<Cursor> newCursor( const BSONObj& query , const BS
ONObj& order , int numWanted ) const = 0;
/** optional op : changes query to match what's in the index */
virtual BSONObj fixKey( const BSONObj& in ) { return in; }
/** optional op : compare 2 objects with regards to this index */
virtual int compare( const BSONObj& l , const BSONObj& r ) const;
/** @return plugin */
const IndexPlugin * getPlugin() const { return _plugin; }
const BSONObj& keyPattern() const;
virtual IndexSuitability suitability( const BSONObj& query , const
BSONObj& order ) const ;
protected:
const IndexPlugin * _plugin;
const IndexSpec * _spec;
};
/**
* this represents a plugin
* a plugin could be something like full text search, sparse index, etc
...
* 1 of these exists per type of index per server
* 1 IndexType is created per index using this plugin
*/
class IndexPlugin : boost::noncopyable {
public:
IndexPlugin( const string& name );
virtual ~IndexPlugin(){}
virtual IndexType* generate( const IndexSpec * spec ) const = 0;
static IndexPlugin* get( const string& name ){
if ( ! _plugins )
return 0;
map<string,IndexPlugin*>::iterator i = _plugins->find( name );
if ( i == _plugins->end() )
return 0;
return i->second;
}
string getName() const { return _name; }
private:
string _name;
static map<string,IndexPlugin*> * _plugins;
};
/* precomputed details about an index, used for inserting keys on updat es /* precomputed details about an index, used for inserting keys on updat es
stored/cached in NamespaceDetailsTransient, or can be used standalon e stored/cached in NamespaceDetailsTransient, or can be used standalon e
*/ */
class IndexSpec { class IndexSpec {
public: public:
BSONObj keyPattern; // e.g., { name : 1 } BSONObj keyPattern; // e.g., { name : 1 }
BSONObj info; // this is the same as IndexDetails::info.obj() BSONObj info; // this is the same as IndexDetails::info.obj()
IndexSpec(){ IndexSpec()
: _details(0) , _finishedInit(false){
} }
IndexSpec( const BSONObj& k , const BSONObj& m = BSONObj() ) IndexSpec( const BSONObj& k , const BSONObj& m = BSONObj() )
: keyPattern(k) , info(m){ : keyPattern(k) , info(m) , _details(0) , _finishedInit(false){
_init(); _init();
} }
/** /**
this is a DiscLoc of an IndexDetails info this is a DiscLoc of an IndexDetails info
should have a key field should have a key field
*/ */
IndexSpec( const DiskLoc& loc ){ IndexSpec( const DiskLoc& loc ){
reset( loc ); reset( loc );
} }
void reset( const DiskLoc& loc ){ void reset( const DiskLoc& loc );
info = loc.obj(); void reset( const IndexDetails * details );
keyPattern = info["key"].embeddedObjectUserCheck();
if ( keyPattern.objsize() == 0 ) {
out() << info.toString() << endl;
assert(false);
}
_init();
}
void getKeys( const BSONObj &obj, BSONObjSetDefaultOrder &keys ) co nst; void getKeys( const BSONObj &obj, BSONObjSetDefaultOrder &keys ) co nst;
private: BSONElement missingField() const { return _nullElt; }
string getTypeName() const {
if ( _indexType.get() )
return _indexType->getPlugin()->getName();
return "";
}
IndexType* getType() const {
return _indexType.get();
}
const IndexDetails * getDetails() const {
return _details;
}
IndexSuitability suitability( const BSONObj& query , const BSONObj&
order ) const ;
protected:
IndexSuitability _suitability( const BSONObj& query , const BSONObj
& order ) const ;
void _getKeys( vector<const char*> fieldNames , vector<BSONElement> fixed , const BSONObj &obj, BSONObjSetDefaultOrder &keys ) const; void _getKeys( vector<const char*> fieldNames , vector<BSONElement> fixed , const BSONObj &obj, BSONObjSetDefaultOrder &keys ) const;
BSONSizeTracker _sizeTracker;
vector<const char*> _fieldNames; vector<const char*> _fieldNames;
vector<BSONElement> _fixed; vector<BSONElement> _fixed;
BSONObj _nullKey; BSONObj _nullKey;
BSONObj _nullObj; BSONObj _nullObj;
BSONElement _nullElt; BSONElement _nullElt;
shared_ptr<IndexType> _indexType;
const IndexDetails * _details;
void _init(); void _init();
public:
bool _finishedInit;
friend class IndexType;
}; };
/* Details about a particular index. There is one of these effective ly for each object in /* Details about a particular index. There is one of these effective ly for each object in
system.namespaces (although this also includes the head pointer, which is not in that system.namespaces (although this also includes the head pointer, which is not in that
collection). collection).
** MemoryMapped Record ** (i.e., this is on disk data) ** MemoryMapped Record ** (i.e., this is on disk data)
*/ */
class IndexDetails { class IndexDetails {
public: public:
skipping to change at line 178 skipping to change at line 274
/* if set, when building index, if any duplicates, drop the duplica ting object */ /* if set, when building index, if any duplicates, drop the duplica ting object */
bool dropDups() const { bool dropDups() const {
return info.obj().getBoolField( "dropDups" ); return info.obj().getBoolField( "dropDups" );
} }
/* delete this index. does NOT clean up the system catalog /* delete this index. does NOT clean up the system catalog
(system.indexes or system.namespaces) -- only NamespaceIndex. (system.indexes or system.namespaces) -- only NamespaceIndex.
*/ */
void kill_idx(); void kill_idx();
const IndexSpec& getSpec() const;
operator string() const { operator string() const {
return info.obj().toString(); return info.obj().toString();
} }
}; };
struct IndexChanges/*on an update*/ { struct IndexChanges/*on an update*/ {
BSONObjSetDefaultOrder oldkeys; BSONObjSetDefaultOrder oldkeys;
BSONObjSetDefaultOrder newkeys; BSONObjSetDefaultOrder newkeys;
vector<BSONObj*> removed; // these keys were removed as part of the change vector<BSONObj*> removed; // these keys were removed as part of the change
vector<BSONObj*> added; // these keys were added as part of the c hange vector<BSONObj*> added; // these keys were added as part of the c hange
 End of changes. 10 change blocks. 
12 lines changed or deleted 116 lines changed or added


 jsobj.h   jsobj.h 
skipping to change at line 483 skipping to change at line 483
/** Get the scope SavedContext of a CodeWScope data element. */ /** Get the scope SavedContext of a CodeWScope data element. */
const char * codeWScopeScopeData() const { const char * codeWScopeScopeData() const {
// TODO fix // TODO fix
return codeWScopeCode() + strlen( codeWScopeCode() ) + 1; return codeWScopeCode() + strlen( codeWScopeCode() ) + 1;
} }
/** Get the embedded object this element holds. */ /** Get the embedded object this element holds. */
BSONObj embeddedObject() const; BSONObj embeddedObject() const;
/* uasserts if not an object */ /* uasserts if not an object */
BSONObj embeddedObjectUserCheck(); BSONObj embeddedObjectUserCheck() const;
BSONObj codeWScopeObject() const; BSONObj codeWScopeObject() const;
string ascode() const { string ascode() const {
switch( type() ){ switch( type() ){
case String: case String:
case Code: case Code:
return valuestr(); return valuestr();
case CodeWScope: case CodeWScope:
return codeWScopeCode(); return codeWScopeCode();
skipping to change at line 653 skipping to change at line 653
fieldNameSize_ = (int)strlen( fieldName() ) + 1; fieldNameSize_ = (int)strlen( fieldName() ) + 1;
return fieldNameSize_; return fieldNameSize_;
} }
mutable int totalSize; /* caches the computed size */ mutable int totalSize; /* caches the computed size */
}; };
int getGtLtOp(const BSONElement& e); int getGtLtOp(const BSONElement& e);
struct BSONElementCmpWithoutField { struct BSONElementCmpWithoutField {
bool operator()( const BSONElement &l, const BSONElement &r ) const { bool operator()( const BSONElement &l, const BSONElement &r ) const {
return l.woCompare( r, false ); return l.woCompare( r, false ) < 0;
} }
}; };
typedef set< BSONElement, BSONElementCmpWithoutField > BSONElementSet; typedef set< BSONElement, BSONElementCmpWithoutField > BSONElementSet;
/** /**
C++ representation of a "BSON" object -- that is, an extended JSO N-style C++ representation of a "BSON" object -- that is, an extended JSO N-style
object in a binary representation. object in a binary representation.
Note that BSONObj's have a smart pointer capability built in -- so y ou can Note that BSONObj's have a smart pointer capability built in -- so y ou can
skipping to change at line 995 skipping to change at line 995
opIN = 0x8, // { x : { $in : [1,2,3] } } opIN = 0x8, // { x : { $in : [1,2,3] } }
NE = 0x9, NE = 0x9,
opSIZE = 0x0A, opSIZE = 0x0A,
opALL = 0x0B, opALL = 0x0B,
NIN = 0x0C, NIN = 0x0C,
opEXISTS = 0x0D, opEXISTS = 0x0D,
opMOD = 0x0E, opMOD = 0x0E,
opTYPE = 0x0F, opTYPE = 0x0F,
opREGEX = 0x10, opREGEX = 0x10,
opOPTIONS = 0x11, opOPTIONS = 0x11,
opELEM_MATCH = 0x12 opELEM_MATCH = 0x12,
opNEAR = 0x13
}; };
}; };
ostream& operator<<( ostream &s, const BSONObj &o ); ostream& operator<<( ostream &s, const BSONObj &o );
ostream& operator<<( ostream &s, const BSONElement &e ); ostream& operator<<( ostream &s, const BSONElement &e );
struct BSONArray: BSONObj { struct BSONArray: BSONObj {
// Don't add anything other than forwarding constructors!!! // Don't add anything other than forwarding constructors!!!
BSONArray(): BSONObj() {} BSONArray(): BSONObj() {}
explicit BSONArray(const BSONObj& obj): BSONObj(obj) {} explicit BSONArray(const BSONObj& obj): BSONObj(obj) {}
}; };
skipping to change at line 1047 skipping to change at line 1048
BSON( "name" << "joe" << "age" << 33 ) BSON( "name" << "joe" << "age" << 33 )
with auto-generated object id: with auto-generated object id:
BSON( GENOID << "name" << "joe" << "age" << 33 ) BSON( GENOID << "name" << "joe" << "age" << 33 )
The labels GT, GTE, LT, LTE, NE can be helpful for stream-oriented cons truction The labels GT, GTE, LT, LTE, NE can be helpful for stream-oriented cons truction
of a BSONObj, particularly when assembling a Query. For example, of a BSONObj, particularly when assembling a Query. For example,
BSON( "a" << GT << 23.4 << NE << 30 << "b" << 2 ) produces the object BSON( "a" << GT << 23.4 << NE << 30 << "b" << 2 ) produces the object
{ a: { \$gt: 23.4, \$ne: 30 }, b: 2 }. { a: { \$gt: 23.4, \$ne: 30 }, b: 2 }.
*/ */
#define BSON(x) (( mongo::BSONObjBuilder() << x ).obj()) #define BSON(x) (( mongo::BSONObjBuilder(64) << x ).obj())
/** Use BSON_ARRAY macro like BSON macro, but without keys /** Use BSON_ARRAY macro like BSON macro, but without keys
BSONArray arr = BSON_ARRAY( "hello" << 1 << BSON( "foo" << BSON_ARRAY( "bar" << "baz" << "qux" ) ) ); BSONArray arr = BSON_ARRAY( "hello" << 1 << BSON( "foo" << BSON_ARRAY( "bar" << "baz" << "qux" ) ) );
*/ */
#define BSON_ARRAY(x) (( mongo::BSONArrayBuilder() << x ).arr()) #define BSON_ARRAY(x) (( mongo::BSONArrayBuilder() << x ).arr())
/* Utility class to auto assign object IDs. /* Utility class to auto assign object IDs.
Example: Example:
cout << BSON( GENOID << "z" << 3 ); // { _id : ..., z : 3 } cout << BSON( GENOID << "z" << 3 ); // { _id : ..., z : 3 }
*/ */
extern struct IDLabeler { } GENOID; extern struct IDLabeler { } GENOID;
BSONObjBuilder& operator<<(BSONObjBuilder& b, IDLabeler& id);
/* Utility class to add a Date element with the current time /* Utility class to add a Date element with the current time
Example: Example:
cout << BSON( "created" << DATENOW ); // { created : "2009-10-09 1 1:41:42" } cout << BSON( "created" << DATENOW ); // { created : "2009-10-09 1 1:41:42" }
*/ */
extern struct DateNowLabeler { } DATENOW; extern struct DateNowLabeler { } DATENOW;
// Utility class to implement GT, GTE, etc as described above. // Utility class to implement GT, GTE, etc as described above.
class Labeler { class Labeler {
public: public:
skipping to change at line 1126 skipping to change at line 1126
private: private:
const char * _fieldName; const char * _fieldName;
BSONObjBuilder * _builder; BSONObjBuilder * _builder;
bool haveSubobj() const { return _subobj.get() != 0; } bool haveSubobj() const { return _subobj.get() != 0; }
BSONObjBuilder *subobj(); BSONObjBuilder *subobj();
auto_ptr< BSONObjBuilder > _subobj; auto_ptr< BSONObjBuilder > _subobj;
}; };
/** /**
used in conjuction with BSONObjBuilder, allows for proper buffer siz
e to prevent crazy memory usage
*/
class BSONSizeTracker {
public:
#define BSONSizeTrackerSize 10
BSONSizeTracker(){
_pos = 0;
for ( int i=0; i<BSONSizeTrackerSize; i++ )
_sizes[i] = 512; // this is the default, so just be consist
ent
}
~BSONSizeTracker(){
}
void got( int size ){
_sizes[_pos++] = size;
if ( _pos >= BSONSizeTrackerSize )
_pos = 0;
}
/**
* right now choosing largest size
*/
int getSize() const {
int x = 16; // sane min
for ( int i=0; i<BSONSizeTrackerSize; i++ ){
if ( _sizes[i] > x )
x = _sizes[i];
}
return x;
}
private:
int _pos;
int _sizes[BSONSizeTrackerSize];
};
/**
utility for creating a BSONObj utility for creating a BSONObj
*/ */
class BSONObjBuilder : boost::noncopyable { class BSONObjBuilder : boost::noncopyable {
public: public:
/** @param initsize this is just a hint as to the final size of the object */ /** @param initsize this is just a hint as to the final size of the object */
BSONObjBuilder(int initsize=512) : b(buf_), buf_(initsize), offset_ ( 0 ), s_( this ) { BSONObjBuilder(int initsize=512) : b(buf_), buf_(initsize), offset_ ( 0 ), s_( this ) , _tracker(0) {
b.skip(4); /*leave room for size field*/ b.skip(4); /*leave room for size field*/
} }
/** @param baseBuilder construct a BSONObjBuilder using an existing BufBuilder */ /** @param baseBuilder construct a BSONObjBuilder using an existing BufBuilder */
BSONObjBuilder( BufBuilder &baseBuilder ) : b( baseBuilder ), buf_( BSONObjBuilder( BufBuilder &baseBuilder ) : b( baseBuilder ), buf_(
0 ), offset_( baseBuilder.len() ), s_( this ) { 0 ), offset_( baseBuilder.len() ), s_( this ) , _tracker(0) {
b.skip( 4 );
}
BSONObjBuilder( const BSONSizeTracker & tracker ) : b(buf_) , buf_(
tracker.getSize() ), offset_(0), s_( this ) , _tracker( (BSONSizeTracker*)(
&tracker) ){
b.skip( 4 ); b.skip( 4 );
} }
/** add all the fields from the object specified to this object */ /** add all the fields from the object specified to this object */
BSONObjBuilder& appendElements(BSONObj x); BSONObjBuilder& appendElements(BSONObj x);
/** append element to the object we are building */ /** append element to the object we are building */
void append( const BSONElement& e) { void append( const BSONElement& e) {
assert( !e.eoo() ); // do not append eoo, that would corrupt us . the builder auto appends when done() is called. assert( !e.eoo() ); // do not append eoo, that would corrupt us . the builder auto appends when done() is called.
b.append((void*) e.rawdata(), e.size()); b.append((void*) e.rawdata(), e.size());
skipping to change at line 1249 skipping to change at line 1292
void appendIntOrLL( const string& fieldName , long long n ){ void appendIntOrLL( const string& fieldName , long long n ){
long long x = n; long long x = n;
if ( x < 0 ) if ( x < 0 )
x = x * -1; x = x * -1;
if ( x < ( numeric_limits<int>::max() / 2 ) ) if ( x < ( numeric_limits<int>::max() / 2 ) )
append( fieldName.c_str() , (int)n ); append( fieldName.c_str() , (int)n );
else else
append( fieldName.c_str() , n ); append( fieldName.c_str() , n );
} }
/**
* appendNumber is a series of method for appending the smallest se
nsible type
* mostly for JS
*/
void appendNumber( const string& fieldName , int n ){
append( fieldName.c_str() , n );
}
void appendNumber( const string& fieldName , double d ){
append( fieldName.c_str() , d );
}
void appendNumber( const string& fieldName , long long l ){
static long long maxInt = (int)pow( 2.0 , 30.0 );
static long long maxDouble = (long long)pow( 2.0 , 40.0 );
if ( l < maxInt )
append( fieldName.c_str() , (int)l );
else if ( l < maxDouble )
append( fieldName.c_str() , (double)l );
append( fieldName.c_str() , l );
}
/** Append a double element */ /** Append a double element */
BSONObjBuilder& append(const char *fieldName, double n) { BSONObjBuilder& append(const char *fieldName, double n) {
b.append((char) NumberDouble); b.append((char) NumberDouble);
b.append(fieldName); b.append(fieldName);
b.append(n); b.append(n);
return *this; return *this;
} }
/** tries to append the data as a number /** tries to append the data as a number
* @return true if the data was able to be converted to a number * @return true if the data was able to be converted to a number
skipping to change at line 1507 skipping to change at line 1573
char *x = _done(); char *x = _done();
assert( x ); assert( x );
l = b.len(); l = b.len();
b.decouple(); b.decouple();
return x; return x;
} }
void decouple() { void decouple() {
b.decouple(); // post done() call version. be sure jsobj fr ees... b.decouple(); // post done() call version. be sure jsobj fr ees...
} }
void appendKeys( const BSONObj& keyPattern , const BSONObj& values
);
private: private:
static const string numStrs[100]; // cache of 0 to 99 inclusive static const string numStrs[100]; // cache of 0 to 99 inclusive
public: public:
static string numStr( int i ) { static string numStr( int i ) {
if (i>=0 && i<100) if (i>=0 && i<100)
return numStrs[i]; return numStrs[i];
stringstream o; stringstream o;
o << i; o << i;
return o.str(); return o.str();
} }
/** Stream oriented way to add field names and values. */ /** Stream oriented way to add field names and values. */
BSONObjBuilderValueStream &operator<<(const char * name ) { BSONObjBuilderValueStream &operator<<(const char * name ) {
s_.endField( name ); s_.endField( name );
return s_; return s_;
} }
/** Stream oriented way to add field names and values. */
BSONObjBuilder& operator<<( IDLabeler ) {
OID oid;
oid.init();
appendOID("_id", &oid);
return *this;
}
// prevent implicit string conversions which would allow bad things like BSON( BSON( "foo" << 1 ) << 2 ) // prevent implicit string conversions which would allow bad things like BSON( BSON( "foo" << 1 ) << 2 )
struct ForceExplicitString { struct ForceExplicitString {
ForceExplicitString( const string &str ) : str_( str ) {} ForceExplicitString( const string &str ) : str_( str ) {}
string str_; string str_;
}; };
/** Stream oriented way to add field names and values. */ /** Stream oriented way to add field names and values. */
BSONObjBuilderValueStream &operator<<( const ForceExplicitString& n ame ) { BSONObjBuilderValueStream &operator<<( const ForceExplicitString& n ame ) {
return operator<<( name.str_.c_str() ); return operator<<( name.str_.c_str() );
} }
skipping to change at line 1557 skipping to change at line 1633
void marshalArray( const char *fieldName, const BSONObj &arr ) { void marshalArray( const char *fieldName, const BSONObj &arr ) {
b.append( (char) Array ); b.append( (char) Array );
b.append( fieldName ); b.append( fieldName );
b.append( (void *) arr.objdata(), arr.objsize() ); b.append( (void *) arr.objdata(), arr.objsize() );
} }
char* _done() { char* _done() {
s_.endField(); s_.endField();
b.append((char) EOO); b.append((char) EOO);
char *data = b.buf() + offset_; char *data = b.buf() + offset_;
*((int*)data) = b.len() - offset_; int size = b.len() - offset_;
*((int*)data) = size;
if ( _tracker )
_tracker->got( size );
return data; return data;
} }
BufBuilder &b; BufBuilder &b;
BufBuilder buf_; BufBuilder buf_;
int offset_; int offset_;
BSONObjBuilderValueStream s_; BSONObjBuilderValueStream s_;
BSONSizeTracker * _tracker;
}; };
class BSONArrayBuilder : boost::noncopyable{ class BSONArrayBuilder : boost::noncopyable{
public: public:
BSONArrayBuilder() :i(0), b() {} BSONArrayBuilder() :i(0), b() {}
template <typename T> template <typename T>
BSONArrayBuilder& append(const T& x){ BSONArrayBuilder& append(const T& x){
b.append(num().c_str(), x); b.append(num().c_str(), x);
return *this; return *this;
skipping to change at line 1695 skipping to change at line 1775
}; };
#pragma pack() #pragma pack()
extern JSObj1 js1; extern JSObj1 js1;
#ifdef _DEBUG #ifdef _DEBUG
#define CHECK_OBJECT( o , msg ) massert( 10337 , (string)"object not valid " + (msg) , (o).isValid() ) #define CHECK_OBJECT( o , msg ) massert( 10337 , (string)"object not valid " + (msg) , (o).isValid() )
#else #else
#define CHECK_OBJECT( o , msg ) #define CHECK_OBJECT( o , msg )
#endif #endif
inline BSONObj BSONElement::embeddedObjectUserCheck() { inline BSONObj BSONElement::embeddedObjectUserCheck() const {
uassert( 10065 , "invalid parameter: expected an object", isABSONO bj() ); uassert( 10065 , "invalid parameter: expected an object", isABSONO bj() );
return BSONObj(value()); return BSONObj(value());
} }
inline BSONObj BSONElement::embeddedObject() const { inline BSONObj BSONElement::embeddedObject() const {
assert( isABSONObj() ); assert( isABSONObj() );
return BSONObj(value()); return BSONObj(value());
} }
inline BSONObj BSONElement::codeWScopeObject() const { inline BSONObj BSONElement::codeWScopeObject() const {
 End of changes. 14 change blocks. 
10 lines changed or deleted 96 lines changed or added


 matcher.h   matcher.h 
skipping to change at line 34 skipping to change at line 34
#include <pcrecpp.h> #include <pcrecpp.h>
namespace mongo { namespace mongo {
class CoveredIndexMatcher; class CoveredIndexMatcher;
class Matcher; class Matcher;
class RegexMatcher { class RegexMatcher {
public: public:
const char *fieldName; const char *fieldName;
const char *regex;
const char *flags;
string prefix;
pcrecpp::RE *re; pcrecpp::RE *re;
RegexMatcher() { bool isNot;
re = 0; RegexMatcher() : re( 0 ), isNot() {}
}
~RegexMatcher() { ~RegexMatcher() {
delete re; delete re;
} }
}; };
struct element_lt struct element_lt
{ {
bool operator()(const BSONElement& l, const BSONElement& r) const bool operator()(const BSONElement& l, const BSONElement& r) const
{ {
int x = (int) l.canonicalType() - (int) r.canonicalType(); int x = (int) l.canonicalType() - (int) r.canonicalType();
skipping to change at line 60 skipping to change at line 62
return compareElementValues(l,r) < 0; return compareElementValues(l,r) < 0;
} }
}; };
class ElementMatcher { class ElementMatcher {
public: public:
ElementMatcher() { ElementMatcher() {
} }
ElementMatcher( BSONElement _e , int _op ); ElementMatcher( BSONElement _e , int _op, bool _isNot );
ElementMatcher( BSONElement _e , int _op , const BSONObj& array ) :
toMatch( _e ) , compareOp( _op ) {
myset.reset( new set<BSONElement,element_lt>() );
BSONObjIterator i( array ); ElementMatcher( BSONElement _e , int _op , const BSONObj& array, bo
while ( i.more() ) { ol _isNot );
BSONElement ie = i.next();
myset->insert(ie);
}
}
~ElementMatcher() { } ~ElementMatcher() { }
BSONElement toMatch; BSONElement toMatch;
int compareOp; int compareOp;
bool isNot;
shared_ptr< set<BSONElement,element_lt> > myset; shared_ptr< set<BSONElement,element_lt> > myset;
// these are for specific operators // these are for specific operators
int mod; int mod;
int modm; int modm;
BSONType type; BSONType type;
shared_ptr<Matcher> subMatcher; shared_ptr<Matcher> subMatcher;
vector< shared_ptr<Matcher> > allMatchers;
}; };
class Where; // used for $where javascript eval class Where; // used for $where javascript eval
class DiskLoc; class DiskLoc;
/* Match BSON objects against a query pattern. /* Match BSON objects against a query pattern.
e.g. e.g.
db.foo.find( { a : 3 } ); db.foo.find( { a : 3 } );
skipping to change at line 128 skipping to change at line 124
} }
// Only specify constrainIndexKey if matches() will be called with // Only specify constrainIndexKey if matches() will be called with
// index keys having empty string field names. // index keys having empty string field names.
Matcher(const BSONObj &pattern, const BSONObj &constrainIndexKey = BSONObj()); Matcher(const BSONObj &pattern, const BSONObj &constrainIndexKey = BSONObj());
~Matcher(); ~Matcher();
bool matches(const BSONObj& j); bool matches(const BSONObj& j);
bool keyMatch() const { return !all && !haveSize && !hasArray; } bool keyMatch() const { return !all && !haveSize && !hasArray && !h aveNot; }
bool atomic() const { return _atomic; } bool atomic() const { return _atomic; }
private: private:
void addBasic(const BSONElement &e, int c) { void addBasic(const BSONElement &e, int c, bool isNot) {
// TODO May want to selectively ignore these element types base d on op type. // TODO May want to selectively ignore these element types base d on op type.
if ( e.type() == MinKey || e.type() == MaxKey ) if ( e.type() == MinKey || e.type() == MaxKey )
return; return;
basics.push_back( ElementMatcher( e , c ) ); basics.push_back( ElementMatcher( e , c, isNot ) );
} }
void addRegex(const char *fieldName, const char *regex, const char
*flags, bool isNot = false);
bool addOp( const BSONElement &e, const BSONElement &fe, bool isNot
, const char *& regex, const char *&flags );
int valuesMatch(const BSONElement& l, const BSONElement& r, int op, const ElementMatcher& bm); int valuesMatch(const BSONElement& l, const BSONElement& r, int op, const ElementMatcher& bm);
Where *where; // set if query uses $where Where *where; // set if query uses $where
BSONObj jsobj; // the query pattern. e.g., { name : "joe" } BSONObj jsobj; // the query pattern. e.g., { name : "joe" }
BSONObj constrainIndexKey_; BSONObj constrainIndexKey_;
vector<ElementMatcher> basics; vector<ElementMatcher> basics;
bool haveSize; bool haveSize;
bool all; bool all;
bool hasArray; bool hasArray;
bool haveNot;
/* $atomic - if true, a multi document operation (some removes, upd ates) /* $atomic - if true, a multi document operation (some removes, upd ates)
should be done atomically. in that case, we do not yi eld - should be done atomically. in that case, we do not yi eld -
i.e. we stay locked the whole time. i.e. we stay locked the whole time.
http://www.mongodb.org/display/DOCS/Removing[ http://www.mongodb.org/display/DOCS/Removing[
*/ */
bool _atomic; bool _atomic;
RegexMatcher regexs[4]; RegexMatcher regexs[4];
int nRegex; int nRegex;
skipping to change at line 171 skipping to change at line 171
vector< shared_ptr< BSONObjBuilder > > _builders; vector< shared_ptr< BSONObjBuilder > > _builders;
friend class CoveredIndexMatcher; friend class CoveredIndexMatcher;
}; };
// If match succeeds on index key, then attempt to match full document. // If match succeeds on index key, then attempt to match full document.
class CoveredIndexMatcher : boost::noncopyable { class CoveredIndexMatcher : boost::noncopyable {
public: public:
CoveredIndexMatcher(const BSONObj &pattern, const BSONObj &indexKey Pattern); CoveredIndexMatcher(const BSONObj &pattern, const BSONObj &indexKey Pattern);
bool matches(const BSONObj &o){ return _docMatcher.matches( o ); } bool matches(const BSONObj &o){ return _docMatcher.matches( o ); }
bool matches(const BSONObj &key, const DiskLoc &recLoc); bool matches(const BSONObj &key, const DiskLoc &recLoc , bool * loa ded = 0 );
bool needRecord(){ return _needRecord; } bool needRecord(){ return _needRecord; }
Matcher& docMatcher() { return _docMatcher; } Matcher& docMatcher() { return _docMatcher; }
private: private:
Matcher _keyMatcher; Matcher _keyMatcher;
Matcher _docMatcher; Matcher _docMatcher;
bool _needRecord; bool _needRecord;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 12 change blocks. 
19 lines changed or deleted 21 lines changed or added


 message.h   message.h 
skipping to change at line 77 skipping to change at line 77
*/ */
bool recv(Message& m); bool recv(Message& m);
void reply(Message& received, Message& response, MSGID responseTo); void reply(Message& received, Message& response, MSGID responseTo);
void reply(Message& received, Message& response); void reply(Message& received, Message& response);
bool call(Message& toSend, Message& response); bool call(Message& toSend, Message& response);
void say(Message& toSend, int responseTo = -1); void say(Message& toSend, int responseTo = -1);
void piggyBack( Message& toSend , int responseTo = -1 ); void piggyBack( Message& toSend , int responseTo = -1 );
virtual unsigned remotePort(); virtual unsigned remotePort();
int send( const char * data , const int len );
int recv( char * data , int max );
private: private:
int sock; int sock;
PiggyBackData * piggyBackData; PiggyBackData * piggyBackData;
public: public:
SockAddr farEnd; SockAddr farEnd;
friend class PiggyBackData; friend class PiggyBackData;
}; };
//#pragma pack() //#pragma pack()
 End of changes. 1 change blocks. 
0 lines changed or deleted 3 lines changed or added


 mmap.h   mmap.h 
skipping to change at line 66 skipping to change at line 66
private: private:
void created(); void created();
HANDLE fd; HANDLE fd;
HANDLE maphandle; HANDLE maphandle;
void *view; void *view;
long len; long len;
}; };
void printMemInfo( const char * where );
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 namespace.h   namespace.h 
skipping to change at line 474 skipping to change at line 474
todo: cleanup code, need abstractions and separation todo: cleanup code, need abstractions and separation
*/ */
class NamespaceDetailsTransient : boost::noncopyable { class NamespaceDetailsTransient : boost::noncopyable {
/* general -------------------------------------------------------- ----- */ /* general -------------------------------------------------------- ----- */
private: private:
string _ns; string _ns;
void reset(); void reset();
static std::map< string, shared_ptr< NamespaceDetailsTransient > > _map; static std::map< string, shared_ptr< NamespaceDetailsTransient > > _map;
public: public:
NamespaceDetailsTransient(const char *ns) : _ns(ns), _keysComputed( false), _qcWriteCount(), _cll_enabled() { } NamespaceDetailsTransient(const char *ns) : _ns(ns), _keysComputed( false), _qcWriteCount(), _cll_enabled() { }
/* _get() is not threadsafe */ /* _get() is not threadsafe -- see get_inlock() comments */
static NamespaceDetailsTransient& _get(const char *ns); static NamespaceDetailsTransient& _get(const char *ns);
/* use get_w() when doing write operations */ /* use get_w() when doing write operations */
static NamespaceDetailsTransient& get_w(const char *ns) { static NamespaceDetailsTransient& get_w(const char *ns) {
DEV assertInWriteLock(); DEV assertInWriteLock();
return _get(ns); return _get(ns);
} }
void addedIndex() { reset(); } void addedIndex() { reset(); }
void deletedIndex() { reset(); } void deletedIndex() { reset(); }
/* Drop cached information on all namespaces beginning with the spe cified prefix. /* Drop cached information on all namespaces beginning with the spe cified prefix.
Can be useful as index namespaces share the same start as the re gular collection. Can be useful as index namespaces share the same start as the re gular collection.
skipping to change at line 508 skipping to change at line 508
set<string>& indexKeys() { set<string>& indexKeys() {
DEV assertInWriteLock(); DEV assertInWriteLock();
if ( !_keysComputed ) if ( !_keysComputed )
computeIndexKeys(); computeIndexKeys();
return _indexKeys; return _indexKeys;
} }
/* IndexSpec caching */ /* IndexSpec caching */
private: private:
map<const IndexDetails*,IndexSpec> _indexSpecs; map<const IndexDetails*,IndexSpec> _indexSpecs;
static boost::mutex _isMutex;
public: public:
const IndexSpec& getIndexSpec( const IndexDetails * details ){ const IndexSpec& getIndexSpec( const IndexDetails * details ){
DEV assertInWriteLock();
IndexSpec& spec = _indexSpecs[details]; IndexSpec& spec = _indexSpecs[details];
if ( spec.info.isEmpty() ){ if ( ! spec._finishedInit ){
spec.reset( details->info ); boostlock lk(_isMutex);
if ( ! spec._finishedInit ){
spec.reset( details );
assert( spec._finishedInit );
}
} }
return spec; return spec;
} }
/* query cache (for query optimizer) ------------------------------ ------- */ /* query cache (for query optimizer) ------------------------------ ------- */
private: private:
int _qcWriteCount; int _qcWriteCount;
map< QueryPattern, pair< BSONObj, long long > > _qcCache; map< QueryPattern, pair< BSONObj, long long > > _qcCache;
public: public:
static boost::mutex _qcMutex; static boost::mutex _qcMutex;
 End of changes. 4 change blocks. 
4 lines changed or deleted 8 lines changed or added


 query.h   query.h 
skipping to change at line 74 skipping to change at line 74
Note that on Update, there is only one object, which is different Note that on Update, there is only one object, which is different
from insert where you can pass a list of objects to insert in the db. from insert where you can pass a list of objects to insert in the db.
Note that the update field layout is very similar layout to Query. Note that the update field layout is very similar layout to Query.
*/ */
// struct QueryOptions, QueryResult, QueryResultFlags in: // struct QueryOptions, QueryResult, QueryResultFlags in:
#include "../client/dbclient.h" #include "../client/dbclient.h"
namespace mongo { namespace mongo {
extern const int MaxBytesToReturnToClientAtOnce;
// for an existing query (ie a ClientCursor), send back additional info rmation. // for an existing query (ie a ClientCursor), send back additional info rmation.
QueryResult* getMore(const char *ns, int ntoreturn, long long cursorid , CurOp& op); QueryResult* getMore(const char *ns, int ntoreturn, long long cursorid , CurOp& op);
struct UpdateResult { struct UpdateResult {
bool existing; bool existing;
bool mod; bool mod;
long long num; long long num;
UpdateResult( bool e, bool m, unsigned long long n ) UpdateResult( bool e, bool m, unsigned long long n )
: existing(e) , mod(m), num(n ){} : existing(e) , mod(m), num(n ){}
skipping to change at line 113 skipping to change at line 115
*/ */
UpdateResult updateObjects(const char *ns, const BSONObj& updateobj, BS ONObj pattern, bool upsert, bool multi , bool logop , OpDebug& debug ); UpdateResult updateObjects(const char *ns, const BSONObj& updateobj, BS ONObj pattern, bool upsert, bool multi , bool logop , OpDebug& debug );
// If justOne is true, deletedId is set to the id of the deleted object . // If justOne is true, deletedId is set to the id of the deleted object .
long long deleteObjects(const char *ns, BSONObj pattern, bool justOne, bool logop = false, bool god=false); long long deleteObjects(const char *ns, BSONObj pattern, bool justOne, bool logop = false, bool god=false);
long long runCount(const char *ns, const BSONObj& cmd, string& err); long long runCount(const char *ns, const BSONObj& cmd, string& err);
auto_ptr< QueryResult > runQuery(Message& m, QueryMessage& q, CurOp& cu rop ); auto_ptr< QueryResult > runQuery(Message& m, QueryMessage& q, CurOp& cu rop );
/* This is for languages whose "objects" are not well ordered (JSON is
well ordered).
[ { a : ... } , { b : ... } ] -> { a : ..., b : ... }
*/
inline BSONObj transformOrderFromArrayFormat(BSONObj order) {
/* note: this is slow, but that is ok as order will have very few p
ieces */
BSONObjBuilder b;
char p[2] = "0";
while ( 1 ) {
BSONObj j = order.getObjectField(p);
if ( j.isEmpty() )
break;
BSONElement e = j.firstElement();
uassert( 10102 , "bad order array", !e.eoo());
uassert( 10103 , "bad order array [2]", e.isNumber());
b.append(e);
(*p)++;
uassert( 10104 , "too many ordering elements", *p <= '9');
}
return b.obj();
}
/**
* this represents a total user query
* includes fields from the query message, both possible query levels
* parses everything up front
*/
class ParsedQuery {
public:
ParsedQuery( QueryMessage& qm )
: _ns( qm.ns ) , _ntoskip( qm.ntoskip ) , _ntoreturn( qm.ntoret
urn ) , _options( qm.queryOptions ){
init( qm.query );
initFields( qm.fields );
}
ParsedQuery( const char* ns , int ntoskip , int ntoreturn , int que
ryoptions , const BSONObj& query , const BSONObj& fields )
: _ns( ns ) , _ntoskip( ntoskip ) , _ntoreturn( ntoreturn ) , _
options( queryoptions ){
init( query );
initFields( fields );
}
~ParsedQuery(){}
const char * ns() const { return _ns; }
const BSONObj& getFilter() const { return _filter; }
FieldMatcher* getFields() const { return _fields.get(); }
shared_ptr<FieldMatcher> getFieldPtr() const { return _fields; }
int getSkip() const { return _ntoskip; }
int getNumToReturn() const { return _ntoreturn; }
bool wantMore() const { return _wantMore; }
int getOptions() const { return _options; }
bool hasOption( int x ) const { return x & _options; }
bool isExplain() const { return _explain; }
bool isSnapshot() const { return _snapshot; }
bool returnKey() const { return _returnKey; }
const BSONObj& getMin() const { return _min; }
const BSONObj& getMax() const { return _max; }
const BSONObj& getOrder() const { return _order; }
const BSONElement& getHint() const { return _hint; }
bool couldBeCommand() const {
/* we assume you are using findOne() for running a cmd... */
return _ntoreturn == 1 && strstr( _ns , ".$cmd" );
}
bool hasIndexSpecifier() const {
return ! _hint.eoo() || ! _min.isEmpty() || ! _max.isEmpty();
}
/* if ntoreturn is zero, we return up to 101 objects. on the subse
quent getmore, there
is only a size limit. The idea is that on a find() where one do
esn't use much results,
we don't return much, but once getmore kicks in, we start pushin
g significant quantities.
The n limit (vs. size) is important when someone fetches only on
e small field from big
objects, which causes massive scanning server-side.
*/
bool enoughForFirstBatch( int n , int len ) const {
if ( _ntoreturn == 0 )
return ( len > 1024 * 1024 ) || n >= 101;
return n >= _ntoreturn || len > MaxBytesToReturnToClientAtOnce;
}
private:
void init( const BSONObj& q ){
_reset();
uassert( 10105 , "bad skip value in query", _ntoskip >= 0);
if ( _ntoreturn < 0 ){
/* _ntoreturn greater than zero is simply a hint on how man
y objects to send back per
"cursor batch".
A negative number indicates a hard limit.
*/
_wantMore = false;
_ntoreturn = -_ntoreturn;
}
BSONElement e = q["query"];
if ( ! e.isABSONObj() )
e = q["$query"];
if ( e.isABSONObj() ){
_filter = e.embeddedObject();
_initTop( q );
}
else {
_filter = q;
}
}
void _reset(){
_wantMore = true;
_explain = false;
_snapshot = false;
_returnKey = false;
}
void _initTop( const BSONObj& top ){
BSONObjIterator i( top );
while ( i.more() ){
BSONElement e = i.next();
const char * name = e.fieldName();
if ( strcmp( "$orderby" , name ) == 0 ||
strcmp( "orderby" , name ) == 0 ){
if ( e.type() == Object )
_order = e.embeddedObject();
else if ( e.type() == Array )
_order = transformOrderFromArrayFormat( _order );
else
assert( 0 );
}
else if ( strcmp( "$explain" , name ) == 0 )
_explain = e.trueValue();
else if ( strcmp( "$snapshot" , name ) == 0 )
_snapshot = e.trueValue();
else if ( strcmp( "$min" , name ) == 0 )
_min = e.embeddedObject();
else if ( strcmp( "$max" , name ) == 0 )
_max = e.embeddedObject();
else if ( strcmp( "$hint" , name ) == 0 )
_hint = e;
else if ( strcmp( "$returnKey" , name ) == 0 )
_returnKey = e.trueValue();
}
if ( _snapshot ){
uassert( 12001 , "E12001 can't sort with $snapshot", _order
.isEmpty() );
uassert( 12002 , "E12002 can't use hint with $snapshot", _h
int.eoo() );
}
}
void initFields( const BSONObj& fields ){
if ( fields.isEmpty() )
return;
_fields.reset( new FieldMatcher() );
_fields->add( fields );
}
ParsedQuery( const ParsedQuery& other ){
assert(0);
}
const char* _ns;
int _ntoskip;
int _ntoreturn;
int _options;
BSONObj _filter;
shared_ptr< FieldMatcher > _fields;
bool _wantMore;
bool _explain;
bool _snapshot;
bool _returnKey;
BSONObj _min;
BSONObj _max;
BSONElement _hint;
BSONObj _order;
};
} // namespace mongo } // namespace mongo
#include "clientcursor.h" #include "clientcursor.h"
 End of changes. 2 change blocks. 
0 lines changed or deleted 201 lines changed or added


 queryoptimizer.h   queryoptimizer.h 
skipping to change at line 35 skipping to change at line 35
namespace mongo { namespace mongo {
class IndexDetails; class IndexDetails;
class QueryPlan : boost::noncopyable { class QueryPlan : boost::noncopyable {
public: public:
QueryPlan(NamespaceDetails *_d, QueryPlan(NamespaceDetails *_d,
int _idxNo, // -1 = no index int _idxNo, // -1 = no index
const FieldRangeSet &fbs, const FieldRangeSet &fbs,
const BSONObj &order, const BSONObj &order,
const BSONObj &startKey = BSONObj(), const BSONObj &startKey = BSONObj(),
const BSONObj &endKey = BSONObj() ); const BSONObj &endKey = BSONObj() ,
string special="" );
/* If true, no other index can do better. */ /* If true, no other index can do better. */
bool optimal() const { return optimal_; } bool optimal() const { return optimal_; }
/* ScanAndOrder processing will be required if true */ /* ScanAndOrder processing will be required if true */
bool scanAndOrderRequired() const { return scanAndOrderRequired_; } bool scanAndOrderRequired() const { return scanAndOrderRequired_; }
/* When true, the index we are using has keys such that it can comp letely resolve the /* When true, the index we are using has keys such that it can comp letely resolve the
query expression to match by itself without ever checking the main object. query expression to match by itself without ever checking the main object.
*/ */
bool exactKeyMatch() const { return exactKeyMatch_; } bool exactKeyMatch() const { return exactKeyMatch_; }
/* If true, the startKey and endKey are unhelpful and the index ord er doesn't match the /* If true, the startKey and endKey are unhelpful and the index ord er doesn't match the
requested sort order */ requested sort order */
bool unhelpful() const { return unhelpful_; } bool unhelpful() const { return unhelpful_; }
int direction() const { return direction_; } int direction() const { return direction_; }
auto_ptr< Cursor > newCursor( const DiskLoc &startLoc = DiskLoc() ) const; auto_ptr< Cursor > newCursor( const DiskLoc &startLoc = DiskLoc() , int numWanted=0 ) const;
auto_ptr< Cursor > newReverseCursor() const; auto_ptr< Cursor > newReverseCursor() const;
BSONObj indexKey() const; BSONObj indexKey() const;
const char *ns() const { return fbs_.ns(); } const char *ns() const { return fbs_.ns(); }
NamespaceDetails *nsd() const { return d; } NamespaceDetails *nsd() const { return d; }
BSONObj query() const { return fbs_.query(); } BSONObj query() const { return fbs_.query(); }
BSONObj simplifiedQuery( const BSONObj& fields = BSONObj() ) const { return fbs_.simplifiedQuery( fields ); } BSONObj simplifiedQuery( const BSONObj& fields = BSONObj() ) const { return fbs_.simplifiedQuery( fields ); }
const FieldRange &range( const char *fieldName ) const { return fbs _.range( fieldName ); } const FieldRange &range( const char *fieldName ) const { return fbs _.range( fieldName ); }
void registerSelf( long long nScanned ) const; void registerSelf( long long nScanned ) const;
// just for testing // just for testing
BoundList indexBounds() const { return indexBounds_; } BoundList indexBounds() const { return indexBounds_; }
skipping to change at line 73 skipping to change at line 74
const FieldRangeSet &fbs_; const FieldRangeSet &fbs_;
const BSONObj &order_; const BSONObj &order_;
const IndexDetails *index_; const IndexDetails *index_;
bool optimal_; bool optimal_;
bool scanAndOrderRequired_; bool scanAndOrderRequired_;
bool exactKeyMatch_; bool exactKeyMatch_;
int direction_; int direction_;
BoundList indexBounds_; BoundList indexBounds_;
bool endKeyInclusive_; bool endKeyInclusive_;
bool unhelpful_; bool unhelpful_;
string _special;
}; };
// Inherit from this interface to implement a new query operation. // Inherit from this interface to implement a new query operation.
// The query optimizer will clone the QueryOp that is provided, giving // The query optimizer will clone the QueryOp that is provided, giving
// each clone its own query plan. // each clone its own query plan.
class QueryOp { class QueryOp {
public: public:
QueryOp() : complete_(), qp_(), error_() {} QueryOp() : complete_(), qp_(), error_() {}
virtual ~QueryOp() {} virtual ~QueryOp() {}
/** this gets called after a query plan is set? ERH 2/16/10 */
virtual void init() = 0; virtual void init() = 0;
virtual void next() = 0; virtual void next() = 0;
virtual bool mayRecordPlan() const = 0; virtual bool mayRecordPlan() const = 0;
// Return a copy of the inheriting class, which will be run with it
s own /** @return a copy of the inheriting class, which will be run with
// query plan. its own
query plan.
*/
virtual QueryOp *clone() const = 0; virtual QueryOp *clone() const = 0;
bool complete() const { return complete_; } bool complete() const { return complete_; }
bool error() const { return error_; } bool error() const { return error_; }
string exceptionMessage() const { return exceptionMessage_; } string exceptionMessage() const { return exceptionMessage_; }
const QueryPlan &qp() const { return *qp_; } const QueryPlan &qp() const { return *qp_; }
// To be called by QueryPlanSet::Runner only. // To be called by QueryPlanSet::Runner only.
void setQueryPlan( const QueryPlan *qp ) { qp_ = qp; } void setQueryPlan( const QueryPlan *qp ) { qp_ = qp; }
void setExceptionMessage( const string &exceptionMessage ) { void setExceptionMessage( const string &exceptionMessage ) {
error_ = true; error_ = true;
exceptionMessage_ = exceptionMessage; exceptionMessage_ = exceptionMessage;
 End of changes. 5 change blocks. 
5 lines changed or deleted 11 lines changed or added


 queryutil.h   queryutil.h 
skipping to change at line 51 skipping to change at line 51
bool valid() const { bool valid() const {
int cmp = lower_.bound_.woCompare( upper_.bound_, false ); int cmp = lower_.bound_.woCompare( upper_.bound_, false );
return ( cmp < 0 || ( cmp == 0 && lower_.inclusive_ && upper_.i nclusive_ ) ); return ( cmp < 0 || ( cmp == 0 && lower_.inclusive_ && upper_.i nclusive_ ) );
} }
}; };
// range of a field's value that may be determined from query -- used t o // range of a field's value that may be determined from query -- used t o
// determine index limits // determine index limits
class FieldRange { class FieldRange {
public: public:
FieldRange( const BSONElement &e = BSONObj().firstElement() , bool optimize=true ); FieldRange( const BSONElement &e = BSONObj().firstElement() , bool isNot=false , bool optimize=true );
const FieldRange &operator&=( const FieldRange &other ); const FieldRange &operator&=( const FieldRange &other );
BSONElement min() const { assert( !empty() ); return intervals_[ 0 ].lower_.bound_; } BSONElement min() const { assert( !empty() ); return intervals_[ 0 ].lower_.bound_; }
BSONElement max() const { assert( !empty() ); return intervals_[ in tervals_.size() - 1 ].upper_.bound_; } BSONElement max() const { assert( !empty() ); return intervals_[ in tervals_.size() - 1 ].upper_.bound_; }
bool minInclusive() const { assert( !empty() ); return intervals_[ 0 ].lower_.inclusive_; } bool minInclusive() const { assert( !empty() ); return intervals_[ 0 ].lower_.inclusive_; }
bool maxInclusive() const { assert( !empty() ); return intervals_[ intervals_.size() - 1 ].upper_.inclusive_; } bool maxInclusive() const { assert( !empty() ); return intervals_[ intervals_.size() - 1 ].upper_.inclusive_; }
bool equality() const { bool equality() const {
return return
!empty() && !empty() &&
min().woCompare( max(), false ) == 0 && min().woCompare( max(), false ) == 0 &&
maxInclusive() && maxInclusive() &&
minInclusive(); minInclusive();
} }
bool nontrivial() const { bool nontrivial() const {
return return
! empty() && ! empty() &&
( minKey.firstElement().woCompare( min(), false ) != 0 || ( minKey.firstElement().woCompare( min(), false ) != 0 ||
maxKey.firstElement().woCompare( max(), false ) != 0 ); maxKey.firstElement().woCompare( max(), false ) != 0 );
} }
bool empty() const { return intervals_.empty(); } bool empty() const { return intervals_.empty(); }
const vector< FieldInterval > &intervals() const { return in tervals_; } const vector< FieldInterval > &intervals() const { return in tervals_; }
string getSpecial() const { return _special; }
private: private:
BSONObj addObj( const BSONObj &o ); BSONObj addObj( const BSONObj &o );
string simpleRegexEnd( string regex );
vector< FieldInterval > intervals_; vector< FieldInterval > intervals_;
vector< BSONObj > objData_; vector< BSONObj > objData_;
string _special;
}; };
// implements query pattern matching, used to determine if a query is // implements query pattern matching, used to determine if a query is
// similar to an earlier query and should use the same plan // similar to an earlier query and should use the same plan
class QueryPattern { class QueryPattern {
public: public:
friend class FieldRangeSet; friend class FieldRangeSet;
enum Type { enum Type {
Equality, Equality,
LowerBound, LowerBound,
skipping to change at line 174 skipping to change at line 176
// if fields is specified, order fields of returned object to match those of 'fields' // if fields is specified, order fields of returned object to match those of 'fields'
BSONObj simplifiedQuery( const BSONObj &fields = BSONObj() ) const; BSONObj simplifiedQuery( const BSONObj &fields = BSONObj() ) const;
bool matchPossible() const { bool matchPossible() const {
for( map< string, FieldRange >::const_iterator i = ranges_.begi n(); i != ranges_.end(); ++i ) for( map< string, FieldRange >::const_iterator i = ranges_.begi n(); i != ranges_.end(); ++i )
if ( i->second.empty() ) if ( i->second.empty() )
return false; return false;
return true; return true;
} }
QueryPattern pattern( const BSONObj &sort = BSONObj() ) const; QueryPattern pattern( const BSONObj &sort = BSONObj() ) const;
BoundList indexBounds( const BSONObj &keyPattern, int direction ) c onst; BoundList indexBounds( const BSONObj &keyPattern, int direction ) c onst;
string getSpecial() const;
private: private:
void processOpElement( const char *fieldName, const BSONElement &f, bool isNot, bool optimize );
static FieldRange *trivialRange_; static FieldRange *trivialRange_;
static FieldRange &trivialRange(); static FieldRange &trivialRange();
mutable map< string, FieldRange > ranges_; mutable map< string, FieldRange > ranges_;
const char *ns_; const char *ns_;
BSONObj query_; BSONObj query_;
}; };
/** /**
used for doing field limiting used for doing field limiting
*/ */
class FieldMatcher { class FieldMatcher {
public: public:
FieldMatcher(bool include=false) : errmsg(NULL), include_(include) {} FieldMatcher(bool include=false) : _include(include){}
void add( const BSONObj& o ); void add( const BSONObj& o );
void append( BSONObjBuilder& b , const BSONElement& e ) const; void append( BSONObjBuilder& b , const BSONElement& e ) const;
BSONObj getSpec() const; BSONObj getSpec() const;
const char* errmsg; //null if FieldMatcher is valid
private: private:
void add( const string& field, bool include ); void add( const string& field, bool include );
void appendArray( BSONObjBuilder& b , const BSONObj& a ) const; void appendArray( BSONObjBuilder& b , const BSONObj& a ) const;
bool include_; // true if default at this level is to include bool _include; // true if default at this level is to include
//TODO: benchmark vector<pair> vs map //TODO: benchmark vector<pair> vs map
typedef map<string, boost::shared_ptr<FieldMatcher> > FieldMap; typedef map<string, boost::shared_ptr<FieldMatcher> > FieldMap;
FieldMap fields_; FieldMap _fields;
BSONObj source_; BSONObj _source;
}; };
/** returns a string that when used as a matcher, would match a super s
et of regex()
returns "" for complex regular expressions
used to optimize queries in some simple regex cases that start with
'^'
if purePrefix != NULL, sets it to whether the regex can be converte
d to a range query
*/
string simpleRegex(const char* regex, const char* flags, bool* purePref
ix=NULL);
/** returns the upper bound of a query that matches prefix */
string simpleRegexEnd( string prefix );
} // namespace mongo } // namespace mongo
 End of changes. 11 change blocks. 
8 lines changed or deleted 25 lines changed or added


 repl.h   repl.h 
skipping to change at line 61 skipping to change at line 61
public: public:
SlaveTypes slave; SlaveTypes slave;
/* true means we are master and doing replication. if we are not w riting to oplog (no --master or repl pairing), /* true means we are master and doing replication. if we are not w riting to oplog (no --master or repl pairing),
this won't be true. this won't be true.
*/ */
bool master; bool master;
int opIdMem; int opIdMem;
bool fastsync;
bool autoresync; bool autoresync;
int slavedelay;
ReplSettings() ReplSettings()
: slave(NotSlave) , master(false) , opIdMem(100000000) , autore sync(false) { : slave(NotSlave) , master(false) , opIdMem(100000000) , fastsy nc() , autoresync(false), slavedelay() {
} }
}; };
extern ReplSettings replSettings; extern ReplSettings replSettings;
bool cloneFrom(const char *masterHost, string& errmsg, const string& fr omdb, bool logForReplication, bool cloneFrom(const char *masterHost, string& errmsg, const string& fr omdb, bool logForReplication,
bool slaveOk, bool useReplAuth, bool snap shot); bool slaveOk, bool useReplAuth, bool snap shot);
/* A replication exception */ /* A replication exception */
skipping to change at line 131 skipping to change at line 135
void syncToTailOfRemoteLog(); void syncToTailOfRemoteLog();
// call with the db mutex // call with the db mutex
OpTime nextLastSavedLocalTs() const; OpTime nextLastSavedLocalTs() const;
void setLastSavedLocalTs( const OpTime &nextLocalTs ); void setLastSavedLocalTs( const OpTime &nextLocalTs );
// call without the db mutex // call without the db mutex
void resetSlave(); void resetSlave();
// call with the db mutex // call with the db mutex
// returns false if the slave has been reset // returns false if the slave has been reset
bool updateSetsWithLocalOps( OpTime &localLogTail, bool mayUnlock ) ; bool updateSetsWithLocalOps( OpTime &localLogTail, bool mayUnlock ) ;
string ns() const { return string( "local.oplog.$" ) + sourceName() ; } string ns() const { return string( "local.oplog.$" ) + sourceName() ; }
unsigned _sleepAdviceTime;
public: public:
static void applyOperation(const BSONObj& op); static void applyOperation(const BSONObj& op);
bool replacing; // in "replace mode" -- see CmdReplacePeer bool replacing; // in "replace mode" -- see CmdReplacePeer
bool paired; // --pair in use bool paired; // --pair in use
string hostName; // ip addr or hostname plus optionally, ":<port >" string hostName; // ip addr or hostname plus optionally, ":<port >"
string _sourceName; // a logical source name. string _sourceName; // a logical source name.
string sourceName() const { string sourceName() const {
return _sourceName.empty() ? "main" : _sourceName; return _sourceName.empty() ? "main" : _sourceName;
} }
skipping to change at line 176 skipping to change at line 181
// make a jsobj from our member fields of the form // make a jsobj from our member fields of the form
// { host: ..., source: ..., syncedTo: ... } // { host: ..., source: ..., syncedTo: ... }
BSONObj jsobj(); BSONObj jsobj();
bool operator==(const ReplSource&r) const { bool operator==(const ReplSource&r) const {
return hostName == r.hostName && sourceName() == r.sourceName() ; return hostName == r.hostName && sourceName() == r.sourceName() ;
} }
operator string() const { return sourceName() + "@" + hostName; } operator string() const { return sourceName() + "@" + hostName; }
bool haveMoreDbsToSync() const { return !addDbNextPass.empty(); } bool haveMoreDbsToSync() const { return !addDbNextPass.empty(); }
int sleepAdvice() const {
if ( !_sleepAdviceTime )
return 0;
int wait = _sleepAdviceTime - unsigned( time( 0 ) );
return wait > 0 ? wait : 0;
}
static bool throttledForceResyncDead( const char *requester ); static bool throttledForceResyncDead( const char *requester );
static void forceResyncDead( const char *requester ); static void forceResyncDead( const char *requester );
void forceResync( const char *requester ); void forceResync( const char *requester );
}; };
/* Write operation to the log (local.oplog.$main) /* Write operation to the log (local.oplog.$main)
"i" insert "i" insert
"u" update "u" update
"d" delete "d" delete
 End of changes. 5 change blocks. 
1 lines changed or deleted 12 lines changed or added


 replset.h   replset.h 
skipping to change at line 52 skipping to change at line 52
public: public:
enum ReplState { enum ReplState {
State_CantArb = -3, State_CantArb = -3,
State_Confused = -2, State_Confused = -2,
State_Negotiating = -1, State_Negotiating = -1,
State_Slave = 0, State_Slave = 0,
State_Master = 1 State_Master = 1
}; };
int state; int state;
string info; // commentary about our current state ThreadSafeString info; // commentary about our current state
string arbHost; // "-" for no arbiter. "host[:port]" string arbHost; // "-" for no arbiter. "host[:port]"
int remotePort; int remotePort;
string remoteHost; string remoteHost;
string remote; // host:port if port specified. string remote; // host:port if port specified.
// int date; // -1 not yet set; 0=slave; 1=master // int date; // -1 not yet set; 0=slave; 1=master
string getInfo() { string getInfo() {
stringstream ss; stringstream ss;
ss << " state: "; ss << " state: ";
if ( state == 1 ) ss << "1 State_Master "; if ( state == 1 ) ss << "1 State_Master ";
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 scanandorder.h   scanandorder.h 
skipping to change at line 43 skipping to change at line 43
public: public:
BSONObj pattern; // e.g., { ts : -1 } BSONObj pattern; // e.g., { ts : -1 }
public: public:
KeyType(BSONObj _keyPattern) { KeyType(BSONObj _keyPattern) {
pattern = _keyPattern; pattern = _keyPattern;
assert( !pattern.isEmpty() ); assert( !pattern.isEmpty() );
} }
// returns the key value for o // returns the key value for o
BSONObj getKeyFromObject(BSONObj o) { BSONObj getKeyFromObject(BSONObj o) {
return o.extractFields(pattern); return o.extractFields(pattern,true);
} }
}; };
/* todo: /* todo:
_ respect limit _ respect limit
_ check for excess mem usage _ check for excess mem usage
_ response size limit from runquery; push it up a bit. _ response size limit from runquery; push it up a bit.
*/ */
inline void fillQueryResultFromObj(BufBuilder& bb, FieldMatcher *filter , BSONObj& js) { inline void fillQueryResultFromObj(BufBuilder& bb, FieldMatcher *filter , BSONObj& js) {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 sock.h   sock.h 
skipping to change at line 265 skipping to change at line 265
void closeAll(){ void closeAll(){
set<int>* s; set<int>* s;
{ {
boostlock lk( _mutex ); boostlock lk( _mutex );
s = _sockets; s = _sockets;
_sockets = new set<int>(); _sockets = new set<int>();
} }
for ( set<int>::iterator i=s->begin(); i!=s->end(); i++ ){ for ( set<int>::iterator i=s->begin(); i!=s->end(); i++ ){
int sock = *i; int sock = *i;
log() << "going to close listening socket: " << sock << end l; log() << "\t going to close listening socket: " << sock << endl;
closesocket( sock ); closesocket( sock );
} }
} }
static ListeningSockets* get(); static ListeningSockets* get();
private: private:
boost::mutex _mutex; boost::mutex _mutex;
set<int>* _sockets; set<int>* _sockets;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 syncclusterconnection.h   syncclusterconnection.h 
skipping to change at line 49 skipping to change at line 49
bool prepare( string& errmsg ); bool prepare( string& errmsg );
/** /**
* runs fsync on all servers * runs fsync on all servers
*/ */
bool fsync( string& errmsg ); bool fsync( string& errmsg );
// --- from DBClientInterface // --- from DBClientInterface
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn, int nToSkip, virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn, int nToSkip,
const BSONObj *fieldsToRetur n, int queryOptions); const BSONObj *fieldsToRetur n, int queryOptions, int batchSize );
virtual auto_ptr<DBClientCursor> getMore( const string &ns, long lo ng cursorId, int nToReturn, int options ); virtual auto_ptr<DBClientCursor> getMore( const string &ns, long lo ng cursorId, int nToReturn, int options );
virtual void insert( const string &ns, BSONObj obj ); virtual void insert( const string &ns, BSONObj obj );
virtual void insert( const string &ns, const vector< BSONObj >& v ) ; virtual void insert( const string &ns, const vector< BSONObj >& v ) ;
virtual void remove( const string &ns , Query query, bool justOne ) ; virtual void remove( const string &ns , Query query, bool justOne ) ;
virtual void update( const string &ns , Query query , BSONObj obj , bool upsert , bool multi ); virtual void update( const string &ns , Query query , BSONObj obj , bool upsert , bool multi );
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 tool.h   tool.h 
skipping to change at line 38 skipping to change at line 38
#include "client/dbclient.h" #include "client/dbclient.h"
#include "db/instance.h" #include "db/instance.h"
using std::string; using std::string;
namespace mongo { namespace mongo {
class Tool { class Tool {
public: public:
Tool( string name , string defaultDB="test" , string defaultCollect ion=""); Tool( string name , bool localDBAllowed=true, string defaultDB="tes t" , string defaultCollection="");
virtual ~Tool(); virtual ~Tool();
int main( int argc , char ** argv ); int main( int argc , char ** argv );
boost::program_options::options_description_easy_init add_options() { boost::program_options::options_description_easy_init add_options() {
return _options->add_options(); return _options->add_options();
} }
boost::program_options::options_description_easy_init add_hidden_op tions(){ boost::program_options::options_description_easy_init add_hidden_op tions(){
return _hidden_options->add_options(); return _hidden_options->add_options();
} }
void addPositionArg( const char * name , int pos ){ void addPositionArg( const char * name , int pos ){
_positonalOptions.add( name , pos ); _positonalOptions.add( name , pos );
} }
string getParam( string name , string def="" ){ string getParam( string name , string def="" ){
if ( _params.count( name ) ) if ( _params.count( name ) )
return _params[name.c_str()].as<string>(); return _params[name.c_str()].as<string>();
return def; return def;
} }
int getParam( string name , int def ){
if ( _params.count( name ) )
return _params[name.c_str()].as<int>();
return def;
}
bool hasParam( string name ){ bool hasParam( string name ){
return _params.count( name ); return _params.count( name );
} }
string getNS(){ string getNS(){
if ( _coll.size() == 0 ){ if ( _coll.size() == 0 ){
cerr << "no collection specified!" << endl; cerr << "no collection specified!" << endl;
throw -1; throw -1;
} }
return _db + "." + _coll; return _db + "." + _coll;
 End of changes. 2 change blocks. 
1 lines changed or deleted 6 lines changed or added


 update.h   update.h 
skipping to change at line 135 skipping to change at line 135
void _checkForAppending( const BSONElement& e ) const { void _checkForAppending( const BSONElement& e ) const {
if ( e.type() == Object ){ if ( e.type() == Object ){
// this is a tiny bit slow, but rare and important // this is a tiny bit slow, but rare and important
// only when setting something TO an object, not setting so mething in an object // only when setting something TO an object, not setting so mething in an object
// and it checks for { $set : { x : { 'a.b' : 1 } } } // and it checks for { $set : { x : { 'a.b' : 1 } } }
// which is feel has been common // which is feel has been common
uassert( 12527 , "not okForStorage" , e.embeddedObject().ok ForStorage() ); uassert( 12527 , "not okForStorage" , e.embeddedObject().ok ForStorage() );
} }
} }
bool isEach() const {
if ( elt.type() != Object )
return false;
BSONElement e = elt.embeddedObject().firstElement();
if ( e.type() != Array )
return false;
return strcmp( e.fieldName() , "$each" ) == 0;
}
BSONObj getEach() const {
return elt.embeddedObjectUserCheck().firstElement().embeddedObj
ectUserCheck();
}
void parseEach( BSONElementSet& s ) const {
BSONObjIterator i(getEach());
while ( i.more() ){
s.insert( i.next() );
}
}
}; };
/** /**
* stores a set of Mods * stores a set of Mods
* once created, should never be changed * once created, should never be changed
*/ */
class ModSet : boost::noncopyable { class ModSet : boost::noncopyable {
typedef map<string,Mod> ModHolder; typedef map<string,Mod> ModHolder;
ModHolder _mods; ModHolder _mods;
int _isIndexed; int _isIndexed;
skipping to change at line 407 skipping to change at line 426
void createNewFromMods( const string& root , BSONObjBuilder& b , co nst BSONObj &obj ); void createNewFromMods( const string& root , BSONObjBuilder& b , co nst BSONObj &obj );
void _appendNewFromMods( const string& root , ModState& m , BSONObj Builder& b , set<string>& onedownseen ); void _appendNewFromMods( const string& root , ModState& m , BSONObj Builder& b , set<string>& onedownseen );
void appendNewFromMod( ModState& ms , BSONObjBuilder& b ){ void appendNewFromMod( ModState& ms , BSONObjBuilder& b ){
//const Mod& m = *(ms.m); // HACK //const Mod& m = *(ms.m); // HACK
Mod& m = *((Mod*)(ms.m)); // HACK Mod& m = *((Mod*)(ms.m)); // HACK
switch ( m.op ){ switch ( m.op ){
case Mod::PUSH: { case Mod::PUSH:
BSONObjBuilder arr( b.subarrayStart( m.shortFieldName ) ); case Mod::ADDTOSET: {
arr.appendAs( m.elt, "0" ); if ( m.isEach() ){
arr.done(); b.appendArray( m.shortFieldName , m.getEach() );
}
else {
BSONObjBuilder arr( b.subarrayStart( m.shortFieldName )
);
arr.appendAs( m.elt, "0" );
arr.done();
}
break; break;
} }
case Mod::PUSH_ALL: { case Mod::PUSH_ALL: {
b.appendAs( m.elt, m.shortFieldName ); b.appendAs( m.elt, m.shortFieldName );
break; break;
} }
case Mod::UNSET: case Mod::UNSET:
case Mod::PULL: case Mod::PULL:
 End of changes. 2 change blocks. 
4 lines changed or deleted 31 lines changed or added


 utils.h   utils.h 
skipping to change at line 28 skipping to change at line 28
#pragma once #pragma once
#include "../scripting/engine.h" #include "../scripting/engine.h"
namespace mongo { namespace mongo {
namespace shellUtils { namespace shellUtils {
extern std::string _dbConnect; extern std::string _dbConnect;
extern std::string _dbAuth; extern std::string _dbAuth;
extern map< const void*, string > _allMyUris;
extern bool _nokillop;
void RecordMyLocation( const char *_argv0 ); void RecordMyLocation( const char *_argv0 );
void installShellUtils( Scope& scope ); void installShellUtils( Scope& scope );
// Scoped management of mongo program instances. Simple implementa tion: // Scoped management of mongo program instances. Simple implementa tion:
// destructor kills all mongod instances created by the shell. // destructor kills all mongod instances created by the shell.
struct MongoProgramScope { struct MongoProgramScope {
MongoProgramScope() {} // Avoid 'unused variable' warning. MongoProgramScope() {} // Avoid 'unused variable' warning.
~MongoProgramScope(); ~MongoProgramScope();
}; };
void KillMongoProgramInstances(); void KillMongoProgramInstances();
void initScope( Scope &scope ); void initScope( Scope &scope );
void onConnect( DBClientWithCommands &c );
} }
} }
 End of changes. 2 change blocks. 
0 lines changed or deleted 3 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/