bsoninlines.h   bsoninlines.h 
skipping to change at line 263 skipping to change at line 263
inline void BSONElement::validate() const { inline void BSONElement::validate() const {
const BSONType t = type(); const BSONType t = type();
switch( t ) { switch( t ) {
case DBRef: case DBRef:
case Code: case Code:
case Symbol: case Symbol:
case mongo::String: { case mongo::String: {
int x = valuestrsize(); int x = valuestrsize();
if ( x > 0 && valuestr()[x-1] == 0 ) if ( x > 0 && x < BSONObjMaxSize && valuestr()[x-1] == 0 )
return; return;
StringBuilder buf; StringBuilder buf;
buf << "Invalid dbref/code/string/symbol size: " << x << " str nlen:" << mongo::strnlen( valuestr() , x ); buf << "Invalid dbref/code/string/symbol size: " << x << " str nlen:" << mongo::strnlen( valuestr() , x );
msgasserted( 10321 , buf.str() ); msgasserted( 10321 , buf.str() );
break; break;
} }
case CodeWScope: { case CodeWScope: {
int totalSize = *( int * )( value() ); int totalSize = *( int * )( value() );
massert( 10322 , "Invalid CodeWScope size", totalSize >= 8 ); massert( 10322 , "Invalid CodeWScope size", totalSize >= 8 );
int strSizeWNull = *( int * )( value() + 4 ); int strSizeWNull = *( int * )( value() + 4 );
skipping to change at line 349 skipping to change at line 349
case BinData: case BinData:
massert( 10317 , "Insufficient bytes to calculate element size ", maxLen == -1 || remain > 3 ); massert( 10317 , "Insufficient bytes to calculate element size ", maxLen == -1 || remain > 3 );
x = valuestrsize() + 4 + 1/*subtype*/; x = valuestrsize() + 4 + 1/*subtype*/;
break; break;
case RegEx: case RegEx:
{ {
const char *p = value(); const char *p = value();
size_t len1 = ( maxLen == -1 ) ? strlen( p ) : mongo::strnlen( p, remain ); size_t len1 = ( maxLen == -1 ) ? strlen( p ) : mongo::strnlen( p, remain );
//massert( 10318 , "Invalid regex string", len1 != -1 ); // ER H - 4/28/10 - don't think this does anything //massert( 10318 , "Invalid regex string", len1 != -1 ); // ER H - 4/28/10 - don't think this does anything
p = p + len1 + 1; p = p + len1 + 1;
size_t len2 = ( maxLen == -1 ) ? strlen( p ) : mongo::strnlen( size_t len2;
p, remain - len1 - 1 ); if( maxLen == -1 )
len2 = strlen( p );
else {
size_t x = remain - len1 - 1;
assert( x <= 0x7fffffff );
len2 = mongo::strnlen( p, (int) x );
}
//massert( 10319 , "Invalid regex options string", len2 != -1 ); // ERH - 4/28/10 - don't think this does anything //massert( 10319 , "Invalid regex options string", len2 != -1 ); // ERH - 4/28/10 - don't think this does anything
x = (int) (len1 + 1 + len2 + 1); x = (int) (len1 + 1 + len2 + 1);
} }
break; break;
default: { default: {
StringBuilder ss; StringBuilder ss;
ss << "BSONElement: bad type " << (int) type(); ss << "BSONElement: bad type " << (int) type();
string msg = ss.str(); string msg = ss.str();
massert( 10320 , msg.c_str(),false); massert( 10320 , msg.c_str(),false);
} }
 End of changes. 2 change blocks. 
3 lines changed or deleted 9 lines changed or added


 bsonobj.h   bsonobj.h 
skipping to change at line 30 skipping to change at line 30
#include <set> #include <set>
#include <list> #include <list>
#include <vector> #include <vector>
#include "util/builder.h" #include "util/builder.h"
#include "stringdata.h" #include "stringdata.h"
namespace mongo { namespace mongo {
typedef set< BSONElement, BSONElementCmpWithoutField > BSONElementSet; typedef set< BSONElement, BSONElementCmpWithoutField > BSONElementSet;
const int BSONObjMaxSize = 32 * 1024 * 1024;
/** /**
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.
See bsonspec.org. See bsonspec.org.
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
pass them around by value. The reference counts used to implement t his pass them around by value. The reference counts used to implement t his
do not use locking, so copying and destroying BSONObj's are not thre ad-safe do not use locking, so copying and destroying BSONObj's are not thre ad-safe
operations. operations.
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 bsonobjbuilder.h   bsonobjbuilder.h 
skipping to change at line 235 skipping to change at line 235
* mostly for JS * mostly for JS
*/ */
BSONObjBuilder& appendNumber( const StringData& fieldName , int n ) { BSONObjBuilder& appendNumber( const StringData& fieldName , int n ) {
return append( fieldName , n ); return append( fieldName , n );
} }
BSONObjBuilder& appendNumber( const StringData& fieldName , double d ){ BSONObjBuilder& appendNumber( const StringData& fieldName , double d ){
return append( fieldName , d ); return append( fieldName , d );
} }
BSONObjBuilder& appendNumber( const StringData& fieldName , size_t
n ){
static size_t maxInt = (size_t)pow( 2.0 , 30.0 );
if ( n < maxInt )
append( fieldName , (int)n );
else
append( fieldName , (long long)n );
return *this;
}
BSONObjBuilder& appendNumber( const StringData& fieldName , long lo ng l ){ BSONObjBuilder& appendNumber( const StringData& fieldName , long lo ng l ){
static long long maxInt = (int)pow( 2.0 , 30.0 ); static long long maxInt = (int)pow( 2.0 , 30.0 );
static long long maxDouble = (long long)pow( 2.0 , 40.0 ); static long long maxDouble = (long long)pow( 2.0 , 40.0 );
if ( l < maxInt ) if ( l < maxInt )
append( fieldName , (int)l ); append( fieldName , (int)l );
else if ( l < maxDouble ) else if ( l < maxDouble )
append( fieldName , (double)l ); append( fieldName , (double)l );
else else
append( fieldName , l ); append( fieldName , l );
skipping to change at line 337 skipping to change at line 347
return *this; return *this;
} }
BSONObjBuilder& append(const StringData& fieldName, Date_t dt) { BSONObjBuilder& append(const StringData& fieldName, Date_t dt) {
return appendDate(fieldName, dt); return appendDate(fieldName, dt);
} }
/** Append a regular expression value /** Append a regular expression value
@param regex the regular expression pattern @param regex the regular expression pattern
@param regex options such as "i" or "g" @param regex options such as "i" or "g"
*/ */
BSONObjBuilder& appendRegex(const StringData& fieldName, const char *regex, const char *options = "") { BSONObjBuilder& appendRegex(const StringData& fieldName, const Stri ngData& regex, const StringData& options = "") {
_b.appendNum((char) RegEx); _b.appendNum((char) RegEx);
_b.appendStr(fieldName); _b.appendStr(fieldName);
_b.appendStr(regex); _b.appendStr(regex);
_b.appendStr(options); _b.appendStr(options);
return *this; return *this;
} }
/** Append a regular expression value
@param regex the regular expression pattern BSONObjBuilder& appendCode(const StringData& fieldName, const Strin
@param regex options such as "i" or "g" gData& code) {
*/
BSONObjBuilder& appendRegex(const StringData& fieldName, string reg
ex, string options = "") {
return appendRegex(fieldName, regex.c_str(), options.c_str());
}
BSONObjBuilder& appendCode(const StringData& fieldName, const char
*code) {
_b.appendNum((char) Code); _b.appendNum((char) Code);
_b.appendStr(fieldName); _b.appendStr(fieldName);
_b.appendNum((int) strlen(code)+1); _b.appendNum((int) code.size()+1);
_b.appendStr(code); _b.appendStr(code);
return *this; return *this;
} }
/** Append a string element. len DOES include terminating nul */ /** Append a string element. len DOES include terminating nul */
BSONObjBuilder& append(const StringData& fieldName, const char *str , int len) { BSONObjBuilder& append(const StringData& fieldName, const char *str , int len) {
_b.appendNum((char) String); _b.appendNum((char) String);
_b.appendStr(fieldName); _b.appendStr(fieldName);
_b.appendNum((int)len); _b.appendNum((int)len);
_b.appendBuf(str, len); _b.appendBuf(str, len);
return *this; return *this;
} }
/** Append a string element */ /** Append a string element */
BSONObjBuilder& append(const StringData& fieldName, const char *str ) { BSONObjBuilder& append(const StringData& fieldName, const char *str ) {
skipping to change at line 368 skipping to change at line 373
/** Append a string element. len DOES include terminating nul */ /** Append a string element. len DOES include terminating nul */
BSONObjBuilder& append(const StringData& fieldName, const char *str , int len) { BSONObjBuilder& append(const StringData& fieldName, const char *str , int len) {
_b.appendNum((char) String); _b.appendNum((char) String);
_b.appendStr(fieldName); _b.appendStr(fieldName);
_b.appendNum((int)len); _b.appendNum((int)len);
_b.appendBuf(str, len); _b.appendBuf(str, len);
return *this; return *this;
} }
/** Append a string element */ /** Append a string element */
BSONObjBuilder& append(const StringData& fieldName, const char *str ) { BSONObjBuilder& append(const StringData& fieldName, const char *str ) {
return append(fieldName, str, (int) strlen(str)+1); return append(fieldName, str, (int) strlen(str)+1);
} }
/** Append a string element */ /** Append a string element */
BSONObjBuilder& append(const StringData& fieldName, string str) { BSONObjBuilder& append(const StringData& fieldName, string str) {
return append(fieldName, str.c_str(), (int) str.size()+1); return append(fieldName, str.c_str(), (int) str.size()+1);
} }
BSONObjBuilder& appendSymbol(const StringData& fieldName, const cha
r *symbol) { BSONObjBuilder& appendSymbol(const StringData& fieldName, const Str
ingData& symbol) {
_b.appendNum((char) Symbol); _b.appendNum((char) Symbol);
_b.appendStr(fieldName); _b.appendStr(fieldName);
_b.appendNum((int) strlen(symbol)+1); _b.appendNum((int) symbol.size()+1);
_b.appendStr(symbol); _b.appendStr(symbol);
return *this; } return *this; }
/** Append a Null element to the object */ /** Append a Null element to the object */
BSONObjBuilder& appendNull( const StringData& fieldName ) { BSONObjBuilder& appendNull( const StringData& fieldName ) {
_b.appendNum( (char) jstNULL ); _b.appendNum( (char) jstNULL );
_b.appendStr( fieldName ); _b.appendStr( fieldName );
return *this; } return *this; }
// Append an element that is less than all other keys. // Append an element that is less than all other keys.
skipping to change at line 426 skipping to change at line 432
Timestamps are a special BSON datatype that is used internally for replication. Timestamps are a special BSON datatype that is used internally for replication.
Append a timestamp element to the object being ebuilt. Append a timestamp element to the object being ebuilt.
@param time - in millis (but stored in seconds) @param time - in millis (but stored in seconds)
*/ */
BSONObjBuilder& appendTimestamp( const StringData& fieldName , unsi gned long long time , unsigned int inc ); BSONObjBuilder& appendTimestamp( const StringData& fieldName , unsi gned long long time , unsigned int inc );
/* /*
Append an element of the deprecated DBRef type. Append an element of the deprecated DBRef type.
@deprecated @deprecated
*/ */
BSONObjBuilder& appendDBRef( const StringData& fieldName, const cha r *ns, const OID &oid ) { BSONObjBuilder& appendDBRef( const StringData& fieldName, const Str ingData& ns, const OID &oid ) {
_b.appendNum( (char) DBRef ); _b.appendNum( (char) DBRef );
_b.appendStr( fieldName ); _b.appendStr( fieldName );
_b.appendNum( (int) strlen( ns ) + 1 ); _b.appendNum( (int) ns.size() + 1 );
_b.appendStr( ns ); _b.appendStr( ns );
_b.appendBuf( (void *) &oid, 12 ); _b.appendBuf( (void *) &oid, 12 );
return *this; return *this;
} }
/** Append a binary data element /** Append a binary data element
@param fieldName name of the field @param fieldName name of the field
@param len length of the binary data in bytes @param len length of the binary data in bytes
@param subtype subtype information for the data. @see enum BinD ataType in bsontypes.h. @param subtype subtype information for the data. @see enum BinD ataType in bsontypes.h.
Use BinDataGeneral if you don't care about the type. Use BinDataGeneral if you don't care about the type.
skipping to change at line 473 skipping to change at line 479
_b.appendNum( len + 4 ); _b.appendNum( len + 4 );
_b.appendNum( (char)0x2 ); _b.appendNum( (char)0x2 );
_b.appendNum( len ); _b.appendNum( len );
_b.appendBuf( (void *) data, len ); _b.appendBuf( (void *) data, len );
return *this; return *this;
} }
/** Append to the BSON object a field of type CodeWScope. This is a javascript code /** Append to the BSON object a field of type CodeWScope. This is a javascript code
fragment accompanied by some scope that goes with it. fragment accompanied by some scope that goes with it.
*/ */
BSONObjBuilder& appendCodeWScope( const StringData& fieldName, cons t char *code, const BSONObj &scope ) { BSONObjBuilder& appendCodeWScope( const StringData& fieldName, cons t StringData& code, const BSONObj &scope ) {
_b.appendNum( (char) CodeWScope ); _b.appendNum( (char) CodeWScope );
_b.appendStr( fieldName ); _b.appendStr( fieldName );
_b.appendNum( ( int )( 4 + 4 + strlen( code ) + 1 + scope.objsi _b.appendNum( ( int )( 4 + 4 + code.size() + 1 + scope.objsize(
ze() ) ); ) ) );
_b.appendNum( ( int ) strlen( code ) + 1 ); _b.appendNum( ( int ) code.size() + 1 );
_b.appendStr( code ); _b.appendStr( code );
_b.appendBuf( ( void * )scope.objdata(), scope.objsize() ); _b.appendBuf( ( void * )scope.objdata(), scope.objsize() );
return *this; return *this;
} }
void appendUndefined( const StringData& fieldName ) { void appendUndefined( const StringData& fieldName ) {
_b.appendNum( (char) Undefined ); _b.appendNum( (char) Undefined );
_b.appendStr( fieldName ); _b.appendStr( fieldName );
} }
/* helper function -- see Query::where() for primary way to do this . */ /* helper function -- see Query::where() for primary way to do this . */
void appendWhere( const char *code, const BSONObj &scope ){ void appendWhere( const StringData& code, const BSONObj &scope ){
appendCodeWScope( "$where" , code , scope ); appendCodeWScope( "$where" , code , scope );
} }
void appendWhere( const string &code, const BSONObj &scope ){
appendWhere( code.c_str(), scope );
}
/** /**
these are the min/max when comparing, not strict min/max element s for a given type these are the min/max when comparing, not strict min/max element s for a given type
*/ */
void appendMinForType( const StringData& fieldName , int type ); void appendMinForType( const StringData& fieldName , int type );
void appendMaxForType( const StringData& fieldName , int type ); void appendMaxForType( const StringData& fieldName , int type );
/** Append an array of values. */ /** Append an array of values. */
template < class T > template < class T >
BSONObjBuilder& append( const StringData& fieldName, const vector< T >& vals ); BSONObjBuilder& append( const StringData& fieldName, const vector< T >& vals );
skipping to change at line 670 skipping to change at line 673
void doneFast() { _b.doneFast(); } void doneFast() { _b.doneFast(); }
template <typename T> template <typename T>
BSONArrayBuilder& append(const StringData& name, const T& x){ BSONArrayBuilder& append(const StringData& name, const T& x){
fill( name ); fill( name );
append( x ); append( x );
return *this; return *this;
} }
BufBuilder &subobjStart( const char *name = "0" ) { BufBuilder &subobjStart( const StringData& name = "0" ) {
fill( name ); fill( name );
return _b.subobjStart( num().c_str() ); return _b.subobjStart( num() );
} }
BufBuilder &subarrayStart( const char *name ) { BufBuilder &subarrayStart( const char *name ) {
fill( name ); fill( name );
return _b.subarrayStart( num().c_str() ); return _b.subarrayStart( num() );
} }
void appendArray( const StringData& name, BSONObj subObj ) { void appendArray( const StringData& name, BSONObj subObj ) {
fill( name ); fill( name );
_b.appendArray( num().c_str(), subObj ); _b.appendArray( num(), subObj );
} }
void appendAs( const BSONElement &e, const char *name ) { void appendAs( const BSONElement &e, const char *name ) {
fill( name ); fill( name );
append( e ); append( e );
} }
private: private:
void fill( const StringData& name ) { void fill( const StringData& name ) {
char *r; char *r;
 End of changes. 18 change blocks. 
30 lines changed or deleted 33 lines changed or added


 btree.h   btree.h 
skipping to change at line 238 skipping to change at line 238
/** /**
* find the first instance of the key * find the first instance of the key
* does not handle dups * does not handle dups
* returned DiskLock isNull if can't find anything with that * returned DiskLock isNull if can't find anything with that
*/ */
DiskLoc findSingle( const IndexDetails& , const DiskLoc& thisLoc, c onst BSONObj& key ); DiskLoc findSingle( const IndexDetails& , const DiskLoc& thisLoc, c onst BSONObj& key );
/* advance one key position in the index: */ /* advance one key position in the index: */
DiskLoc advance(const DiskLoc& thisLoc, int& keyOfs, int direction, const char *caller); DiskLoc advance(const DiskLoc& thisLoc, int& keyOfs, int direction, const char *caller);
void advanceTo(const IndexDetails &id, DiskLoc &thisLoc, int &keyOf void advanceTo(DiskLoc &thisLoc, int &keyOfs, const BSONObj &keyBeg
s, const BSONObj &keyBegin, int keyBeginLen, const vector< const BSONElemen in, int keyBeginLen, bool afterKey, const vector< const BSONElement * > &ke
t * > &keyEnd, const Ordering &order, int direction ); yEnd, const vector< bool > &keyEndInclusive, const Ordering &order, int dir
ection );
void customLocate(DiskLoc &thisLoc, int &keyOfs, const BSONObj &key
Begin, int keyBeginLen, bool afterKey, const vector< const BSONElement * >
&keyEnd, const vector< bool > &keyEndInclusive, const Ordering &order, int
direction, pair< DiskLoc, int > &bestParent );
DiskLoc getHead(const DiskLoc& thisLoc); DiskLoc getHead(const DiskLoc& thisLoc);
/* get tree shape */ /* get tree shape */
void shape(stringstream&); void shape(stringstream&);
static void a_test(IndexDetails&); static void a_test(IndexDetails&);
private: private:
void fixParentPtrs(const DiskLoc& thisLoc); void fixParentPtrs(const DiskLoc& thisLoc);
skipping to change at line 262 skipping to change at line 263
return keyOfs >= n ? BSONObj() : keyNode(keyOfs).key; return keyOfs >= n ? BSONObj() : keyNode(keyOfs).key;
} }
static BtreeBucket* allocTemp(); /* caller must release with free() */ static BtreeBucket* allocTemp(); /* caller must release with free() */
void insertHere(DiskLoc thisLoc, int keypos, void insertHere(DiskLoc thisLoc, int keypos,
DiskLoc recordLoc, const BSONObj& key, const Orderi ng &order, DiskLoc recordLoc, const BSONObj& key, const Orderi ng &order,
DiskLoc lchild, DiskLoc rchild, IndexDetails&); DiskLoc lchild, DiskLoc rchild, IndexDetails&);
int _insert(DiskLoc thisLoc, DiskLoc recordLoc, int _insert(DiskLoc thisLoc, DiskLoc recordLoc,
const BSONObj& key, const Ordering &order, bool dupsAll owed, const BSONObj& key, const Ordering &order, bool dupsAll owed,
DiskLoc lChild, DiskLoc rChild, IndexDetails&); DiskLoc lChild, DiskLoc rChild, IndexDetails&);
bool find(const IndexDetails& idx, const BSONObj& key, DiskLoc reco rdLoc, const Ordering &order, int& pos, bool assertIfDup); bool find(const IndexDetails& idx, const BSONObj& key, DiskLoc reco rdLoc, const Ordering &order, int& pos, bool assertIfDup);
bool customFind( int l, int h, const BSONObj &keyBegin, int keyBegi nLen, const vector< const BSONElement * > &keyEnd, const Ordering &order, i nt direction, DiskLoc &thisLoc, int &keyOfs, pair< DiskLoc, int > &bestPare nt ); bool customFind( int l, int h, const BSONObj &keyBegin, int keyBegi nLen, bool afterKey, const vector< const BSONElement * > &keyEnd, const vec tor< bool > &keyEndInclusive, const Ordering &order, int direction, DiskLoc &thisLoc, int &keyOfs, pair< DiskLoc, int > &bestParent );
static void findLargestKey(const DiskLoc& thisLoc, DiskLoc& largest Loc, int& largestKey); static void findLargestKey(const DiskLoc& thisLoc, DiskLoc& largest Loc, int& largestKey);
static int customBSONCmp( const BSONObj &l, const BSONObj &rBegin, int rBeginLen, const vector< const BSONElement * > &rEnd, const Ordering &o ); static int customBSONCmp( const BSONObj &l, const BSONObj &rBegin, int rBeginLen, bool rSup, const vector< const BSONElement * > &rEnd, const vector< bool > &rEndInclusive, const Ordering &o, int direction );
public: public:
// simply builds and returns a dup key error message string // simply builds and returns a dup key error message string
static string dupKeyError( const IndexDetails& idx , const BSONObj& key ); static string dupKeyError( const IndexDetails& idx , const BSONObj& key );
}; };
#pragma pack() #pragma pack()
class BtreeCursor : public Cursor { class BtreeCursor : public Cursor {
public: public:
BtreeCursor( NamespaceDetails *_d, int _idxNo, const IndexDetails&, const BSONObj &startKey, const BSONObj &endKey, bool endKeyInclusive, int direction ); BtreeCursor( NamespaceDetails *_d, int _idxNo, const IndexDetails&, const BSONObj &startKey, const BSONObj &endKey, bool endKeyInclusive, int direction );
skipping to change at line 367 skipping to change at line 368
} }
void forgetEndKey() { endKey = BSONObj(); } void forgetEndKey() { endKey = BSONObj(); }
virtual CoveredIndexMatcher *matcher() const { return _matcher.get( ); } virtual CoveredIndexMatcher *matcher() const { return _matcher.get( ); }
virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher ) { virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher ) {
_matcher = matcher; _matcher = matcher;
} }
virtual long long nscanned() { return _nscanned; }
// for debugging only // for debugging only
DiskLoc getBucket() const { return bucket; } DiskLoc getBucket() const { return bucket; }
private: private:
/* Our btrees may (rarely) have "unused" keys when items are delete d. /* Our btrees may (rarely) have "unused" keys when items are delete d.
Skip past them. Skip past them.
*/ */
bool skipUnusedKeys( bool mayJump ); bool skipUnusedKeys( bool mayJump );
bool skipOutOfRangeKeysAndCheckEnd(); bool skipOutOfRangeKeysAndCheckEnd();
void skipAndCheck(); void skipAndCheck();
void checkEnd(); void checkEnd();
// selective audits on construction // selective audits on construction
void audit(); void audit();
// set initial bucket // set initial bucket
void init(); void init();
void advanceTo( const BSONObj &keyBegin, int keyBeginLen, const vec // if afterKey is true, we want the first key with values of the ke
tor< const BSONElement * > &keyEnd); yBegin fields greater than keyBegin
void advanceTo( const BSONObj &keyBegin, int keyBeginLen, bool afte
rKey, const vector< const BSONElement * > &keyEnd, const vector< bool > &ke
yEndInclusive );
friend class BtreeBucket; friend class BtreeBucket;
set<DiskLoc> dups; set<DiskLoc> dups;
NamespaceDetails *d; NamespaceDetails *d;
int idxNo; int idxNo;
BSONObj startKey; BSONObj startKey;
BSONObj endKey; BSONObj endKey;
bool endKeyInclusive_; bool endKeyInclusive_;
skipping to change at line 411 skipping to change at line 415
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;
shared_ptr< FieldRangeVector > bounds_; shared_ptr< FieldRangeVector > bounds_;
auto_ptr< FieldRangeVector::Iterator > _boundsIterator; auto_ptr< FieldRangeVector::Iterator > _boundsIterator;
const IndexSpec& _spec; const IndexSpec& _spec;
shared_ptr< CoveredIndexMatcher > _matcher; shared_ptr< CoveredIndexMatcher > _matcher;
bool _independentFieldRanges; bool _independentFieldRanges;
long long _nscanned;
}; };
inline bool IndexDetails::hasKey(const BSONObj& key) { inline bool IndexDetails::hasKey(const BSONObj& key) {
return head.btree()->exists(*this, head, key, Ordering::make(keyPat tern())); return head.btree()->exists(*this, head, key, Ordering::make(keyPat tern()));
} }
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, Ordering::mak e(keyPattern()), self); return head.btree()->wouldCreateDup(*this, head, key, Ordering::mak e(keyPattern()), self);
} }
/* build btree from the bottom up */ /* build btree from the bottom up */
 End of changes. 6 change blocks. 
7 lines changed or deleted 18 lines changed or added


 chunk.h   chunk.h 
skipping to change at line 97 skipping to change at line 97
return ! ( *this == s ); return ! ( *this == s );
} }
// if min/max key is pos/neg infinity // if min/max key is pos/neg infinity
bool minIsInf() const; bool minIsInf() const;
bool maxIsInf() const; bool maxIsInf() const;
BSONObj pickSplitPoint() const; BSONObj pickSplitPoint() const;
ChunkPtr split(); ChunkPtr split();
void pickSplitVector( vector<BSONObj>* splitPoints ) const; void pickSplitVector( vector<BSONObj>* splitPoints , int chunkSize ) const;
ChunkPtr multiSplit( const vector<BSONObj>& splitPoints ); ChunkPtr multiSplit( const vector<BSONObj>& splitPoints );
/** /**
* @return size of shard in bytes * @return size of shard in bytes
* talks to mongod to do this * talks to mongod to do this
*/ */
long getPhysicalSize() const; long getPhysicalSize() const;
int countObjects(int maxcount=0) const; int countObjects(int maxcount=0) const;
skipping to change at line 129 skipping to change at line 129
bool moveAndCommit( const Shard& to , string& errmsg ); bool moveAndCommit( const Shard& to , string& errmsg );
const char * getNS(){ return "config.chunks"; } const char * getNS(){ return "config.chunks"; }
void serialize(BSONObjBuilder& to, ShardChunkVersion myLastMod=0); void serialize(BSONObjBuilder& to, ShardChunkVersion myLastMod=0);
void unserialize(const BSONObj& from); void unserialize(const BSONObj& from);
string modelServer() const; string modelServer() const;
void appendShortVersion( const char * name , BSONObjBuilder& b ); void appendShortVersion( const char * name , BSONObjBuilder& b );
void _markModified();
static int MaxChunkSize; static int MaxChunkSize;
string genID() const; string genID() const;
static string genID( const string& ns , const BSONObj& min ); static string genID( const string& ns , const BSONObj& min );
const ChunkManager* getManager() const { return _manager; } const ChunkManager* getManager() const { return _manager; }
bool getModified() { return _modified; } bool modified();
void setModified( bool modified ) { _modified = modified; }
ShardChunkVersion getVersionOnConfigServer() const; ShardChunkVersion getVersionOnConfigServer() const;
private: private:
bool _splitIfShould( long dataWritten ); bool _splitIfShould( long dataWritten );
// main shard info // main shard info
ChunkManager * _manager; ChunkManager * _manager;
ShardKeyPattern skey() const; ShardKeyPattern skey() const;
 End of changes. 3 change blocks. 
3 lines changed or deleted 4 lines changed or added


 clientcursor.h   clientcursor.h 
skipping to change at line 79 skipping to change at line 79
public: public:
static void assertNoCursors(); static void assertNoCursors();
/* use this to assure we don't in the background time out cursor wh ile it is under use. /* use this to assure we don't in the background time out cursor wh ile it is under use.
if you are using noTimeout() already, there is no risk anyway. if you are using noTimeout() already, there is no risk anyway.
Further, this mechanism guards against two getMore requests on t he same cursor executing Further, this mechanism guards against two getMore requests on t he same cursor executing
at the same time - which might be bad. That should never happen , but if a client driver at the same time - which might be bad. That should never happen , but if a client driver
had a bug, it could (or perhaps some sort of attack situation). had a bug, it could (or perhaps some sort of attack situation).
*/ */
class Pointer : boost::noncopyable { class Pointer : boost::noncopyable {
public:
ClientCursor *_c; ClientCursor *_c;
public:
ClientCursor * c() { return _c; }
void release() { void release() {
if( _c ) { if( _c ) {
assert( _c->_pinValue >= 100 ); assert( _c->_pinValue >= 100 );
_c->_pinValue -= 100; _c->_pinValue -= 100;
_c = 0;
} }
_c = 0;
} }
~Pointer() { release(); }
Pointer(long long cursorid) { Pointer(long long cursorid) {
recursive_scoped_lock lock(ccmutex); recursive_scoped_lock lock(ccmutex);
_c = ClientCursor::find_inlock(cursorid, true); _c = ClientCursor::find_inlock(cursorid, true);
if( _c ) { if( _c ) {
if( _c->_pinValue >= 100 ) { if( _c->_pinValue >= 100 ) {
_c = 0; _c = 0;
uassert(12051, "clientcursor already in use? driver problem?", false); uasserted(12051, "clientcursor already in use? driv er problem?");
} }
_c->_pinValue += 100; _c->_pinValue += 100;
} }
} }
~Pointer() {
release();
}
}; };
// This object assures safe and reliable cleanup of the ClientCurso r. // This object assures safe and reliable cleanup of the ClientCurso r.
// The implementation assumes that there will be no duplicate ids a mong cursors // The implementation assumes that there will be no duplicate ids a mong cursors
// (which is assured if cursors must last longer than 1 second). // (which is assured if cursors must last longer than 1 second).
class CleanupPointer : boost::noncopyable { class CleanupPointer : boost::noncopyable {
public: public:
CleanupPointer() : _c( 0 ), _id( -1 ) {} CleanupPointer() : _c( 0 ), _id( -1 ) {}
void reset( ClientCursor *c = 0 ) { void reset( ClientCursor *c = 0 ) {
if ( c == _c ) { if ( c == _c )
return; return;
}
if ( _c ) { if ( _c ) {
// be careful in case cursor was deleted by someone els e // be careful in case cursor was deleted by someone els e
ClientCursor::erase( _id ); ClientCursor::erase( _id );
} }
if ( c ) { if ( c ) {
_c = c; _c = c;
_id = c->cursorid; _id = c->cursorid;
} else { } else {
_c = 0; _c = 0;
_id = -1; _id = -1;
} }
} }
~CleanupPointer() { ~CleanupPointer() {
DESTRUCTOR_GUARD ( reset(); ); DESTRUCTOR_GUARD ( reset(); );
skipping to change at line 163 skipping to change at line 159
_db( cc().database() ) _db( cc().database() )
{ {
assert( _db ); assert( _db );
assert( str::startsWith(_ns, _db->name) ); assert( str::startsWith(_ns, _db->name) );
if( queryOptions & QueryOption_NoCursorTimeout ) if( queryOptions & QueryOption_NoCursorTimeout )
noTimeout(); noTimeout();
recursive_scoped_lock lock(ccmutex); recursive_scoped_lock 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;
}
shared_ptr< ParsedQuery > pq; shared_ptr< ParsedQuery > pq;
shared_ptr< FieldMatcher > fields; // which fields query wants retu rned 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);
skipping to change at line 217 skipping to change at line 212
cc->prepareToYield( _data ); cc->prepareToYield( _data );
_unlock.reset(new dbtempreleasecond()); _unlock.reset(new dbtempreleasecond());
} }
} }
~YieldLock(){ ~YieldLock(){
if ( _unlock ){ if ( _unlock ){
log( LL_WARNING ) << "ClientCursor::YieldLock not close d properly" << endl; log( LL_WARNING ) << "ClientCursor::YieldLock not close d properly" << endl;
relock(); relock();
} }
} }
bool stillOk(){ bool stillOk(){
if ( ! _canYield ) if ( ! _canYield )
return true; return true;
relock(); relock();
return ClientCursor::recoverFromYield( _data ); return ClientCursor::recoverFromYield( _data );
} }
void relock(){ void relock(){
_unlock.reset(); _unlock.reset();
} }
private: private:
bool _canYield; const bool _canYield;
YieldData _data; YieldData _data;
scoped_ptr<dbtempreleasecond> _unlock; scoped_ptr<dbtempreleasecond> _unlock;
}; };
// --- some pass through helpers for Cursor --- // --- some pass through helpers for Cursor ---
BSONObj indexKeyPattern() { BSONObj indexKeyPattern() { return c->indexKeyPattern(); }
return c->indexKeyPattern(); bool ok() { return c->ok(); }
} bool advance(){ return c->advance(); }
BSONObj current() { return c->current(); }
bool ok(){
return c->ok();
}
bool advance(){
return c->advance();
}
bool currentMatches(){ bool currentMatches(){
if ( ! c->matcher() ) if ( ! c->matcher() )
return true; return true;
return c->matcher()->matchesCurrent( c.get() ); return c->matcher()->matchesCurrent( c.get() );
} }
BSONObj current(){
return c->current();
}
private: private:
void setLastLoc_inlock(DiskLoc); void setLastLoc_inlock(DiskLoc);
static ClientCursor* find_inlock(CursorId id, bool warn = true) { static ClientCursor* find_inlock(CursorId id, bool warn = true) {
CCById::iterator it = clientCursorsById.find(id); CCById::iterator it = clientCursorsById.find(id);
if ( it == clientCursorsById.end() ) { if ( it == clientCursorsById.end() ) {
if ( warn ) if ( warn )
OCCASIONALLY out() << "ClientCursor::find(): cursor not found in map " << id << " (ok after a drop)\n"; OCCASIONALLY out() << "ClientCursor::find(): cursor not found in map " << id << " (ok after a drop)\n";
return 0; return 0;
} }
 End of changes. 22 change blocks. 
36 lines changed or deleted 13 lines changed or added


 cmdline.h   cmdline.h 
skipping to change at line 30 skipping to change at line 30
namespace mongo { namespace mongo {
/* command line options /* command line options
*/ */
/* concurrency: OK/READ */ /* concurrency: OK/READ */
struct CmdLine { struct CmdLine {
int port; // --port int port; // --port
string bind_ip; // --bind_ip string bind_ip; // --bind_ip
bool rest; // --rest bool rest; // --rest
bool jsonp; // --jsonp
string _replSet; // --replSet[/<seedlist>] string _replSet; // --replSet[/<seedlist>]
string ourSetName() const { string ourSetName() const {
string setname; string setname;
size_t sl = _replSet.find('/'); size_t sl = _replSet.find('/');
if( sl == string::npos ) if( sl == string::npos )
return _replSet; return _replSet;
return _replSet.substr(0, sl); return _replSet.substr(0, sl);
} }
skipping to change at line 66 skipping to change at line 67
int pretouch; // --pretouch for replication application (e xperimental) int pretouch; // --pretouch for replication application (e xperimental)
bool moveParanoia; // for move chunk paranoia bool moveParanoia; // for move chunk paranoia
enum { enum {
DefaultDBPort = 27017, DefaultDBPort = 27017,
ConfigServerPort = 27019, ConfigServerPort = 27019,
ShardServerPort = 27018 ShardServerPort = 27018
}; };
CmdLine() : CmdLine() :
port(DefaultDBPort), rest(false), quiet(false), notablescan(fal se), prealloc(true), smallfiles(false), port(DefaultDBPort), rest(false), jsonp(false), quiet(false), n otablescan(false), prealloc(true), smallfiles(false),
quota(false), quotaFiles(8), cpu(false), oplogSize(0), defaultP rofile(0), slowMS(100), pretouch(0), moveParanoia( true ) quota(false), quotaFiles(8), cpu(false), oplogSize(0), defaultP rofile(0), slowMS(100), pretouch(0), moveParanoia( true )
{ } { }
static void addGlobalOptions( boost::program_options::options_descr iption& general , static void addGlobalOptions( boost::program_options::options_descr iption& general ,
boost::program_options::options_descr iption& hidden ); boost::program_options::options_descr iption& hidden );
static void addWindowsOptions( boost::program_options::options_desc
ription& windows ,
boost::program_options::options_descr
iption& hidden );
/** /**
* @return true if should run program, false if should exit * @return true if should run program, false if should exit
*/ */
static bool store( int argc , char ** argv , static bool store( int argc , char ** argv ,
boost::program_options::options_description& vis ible, boost::program_options::options_description& vis ible,
boost::program_options::options_description& hid den, boost::program_options::options_description& hid den,
boost::program_options::positional_options_descr iption& positional, boost::program_options::positional_options_descr iption& positional,
boost::program_options::variables_map &output ); boost::program_options::variables_map &output );
}; };
 End of changes. 3 change blocks. 
1 lines changed or deleted 7 lines changed or added


 connections.h   connections.h 
skipping to change at line 47 skipping to change at line 47
} }
throws exception on connect error (but fine to try again later with a new throws exception on connect error (but fine to try again later with a new
scopedconn object for same host). scopedconn object for same host).
*/ */
class ScopedConn { class ScopedConn {
public: public:
/** throws assertions if connect failure etc. */ /** throws assertions if connect failure etc. */
ScopedConn(string hostport); ScopedConn(string hostport);
~ScopedConn(); ~ScopedConn();
DBClientConnection* operator->();
/* If we were to run a query and not exhaust the cursor, future use
of the connection would be problematic.
So here what we do is wrapper known safe methods and not allow c
ursor-style queries at all. This makes
ScopedConn limited in functionality but very safe. More non-cur
sor wrappers can be added here if needed.
*/
bool runCommand(const string &dbname, const BSONObj& cmd, BSONObj &
info, int options=0) {
return conn()->runCommand(dbname, cmd, info, options);
}
unsigned long long count(const string &ns) {
return conn()->count(ns);
}
BSONObj findOne(const string &ns, const Query& q, const BSONObj *fi
eldsToReturn = 0, int queryOptions = 0) {
return conn()->findOne(ns, q, fieldsToReturn, queryOptions);
}
private: private:
auto_ptr<scoped_lock> connLock; auto_ptr<scoped_lock> connLock;
static mutex mapMutex; static mutex mapMutex;
struct X { struct X {
mutex z; mutex z;
DBClientConnection cc; DBClientConnection cc;
X() : z("X"), cc(/*reconnect*/ true, 0, X() : z("X"), cc(/*reconnect*/true, 0, /*timeout*/10) {
/*timeout*/ theReplSet ? theReplSet->config().
ho.heartbeatTimeoutMillis/1000.0 : 10.0) {
cc._logLevel = 2; cc._logLevel = 2;
} }
} *x; } *x;
typedef map<string,ScopedConn::X*> M; typedef map<string,ScopedConn::X*> M;
static M& _map; static M& _map;
DBClientConnection* conn() { return &x->cc; }
}; };
inline ScopedConn::ScopedConn(string hostport) { inline ScopedConn::ScopedConn(string hostport) {
bool first = false; bool first = false;
{ {
scoped_lock lk(mapMutex); scoped_lock lk(mapMutex);
x = _map[hostport]; x = _map[hostport];
if( x == 0 ) { if( x == 0 ) {
x = _map[hostport] = new X(); x = _map[hostport] = new X();
first = true; first = true;
skipping to change at line 104 skipping to change at line 87
// we already locked above... // we already locked above...
string err; string err;
x->cc.connect(hostport, err); x->cc.connect(hostport, err);
} }
inline ScopedConn::~ScopedConn() { inline ScopedConn::~ScopedConn() {
// conLock releases... // conLock releases...
} }
/*inline DBClientConnection* ScopedConn::operator->() { inline DBClientConnection* ScopedConn::operator->() {
return &x->cc; return &x->cc;
}*/ }
} }
 End of changes. 5 change blocks. 
27 lines changed or deleted 4 lines changed or added


 core.h   core.h 
skipping to change at line 394 skipping to change at line 394
StringBuilder buf(32); StringBuilder buf(32);
buf << "(" << _x << "," << _y << ")"; buf << "(" << _x << "," << _y << ")";
return buf.str(); return buf.str();
} }
double _x; double _x;
double _y; double _y;
}; };
extern double EARTH_RADIUS_KM; extern const double EARTH_RADIUS_KM;
extern double EARTH_RADIUS_MILES; extern const double EARTH_RADIUS_MILES;
inline double deg2rad(double deg) { return deg * (M_PI/180); }
inline double rad2deg(double rad) { return rad * (180/M_PI); }
// WARNING: _x and _y MUST be longitude and latitude in that order // WARNING: _x and _y MUST be longitude and latitude in that order
// note: multiply by earth radius for distance // note: multiply by earth radius for distance
inline double spheredist_rad( const Point& p1, const Point& p2 ) { inline double spheredist_rad( const Point& p1, const Point& p2 ) {
// this uses the n-vector formula: http://en.wikipedia.org/wiki/N-v ector // this uses the n-vector formula: http://en.wikipedia.org/wiki/N-v ector
// If you try to match the code to the formula, note that I inline the cross-product. // If you try to match the code to the formula, note that I inline the cross-product.
// TODO: optimize with SSE // TODO: optimize with SSE
double sin_x1(sin(p1._x)), cos_x1(cos(p1._x)); double sin_x1(sin(p1._x)), cos_x1(cos(p1._x));
double sin_y1(sin(p1._y)), cos_y1(cos(p1._y)); double sin_y1(sin(p1._y)), cos_y1(cos(p1._y));
double sin_x2(sin(p2._x)), cos_x2(cos(p2._x)); double sin_x2(sin(p2._x)), cos_x2(cos(p2._x));
double sin_y2(sin(p2._y)), cos_y2(cos(p2._y)); double sin_y2(sin(p2._y)), cos_y2(cos(p2._y));
double cross_prod = double cross_prod =
(cos_y1*cos_x1 * cos_y2*cos_x2) + (cos_y1*cos_x1 * cos_y2*cos_x2) +
(cos_y1*sin_x1 * cos_y2*sin_x2) + (cos_y1*sin_x1 * cos_y2*sin_x2) +
(sin_y1 * sin_y2); (sin_y1 * sin_y2);
if (cross_prod >= 1 || cross_prod <= -1){
// fun with floats
assert( fabs(cross_prod)-1 < 1e-6 );
return cross_prod > 0 ? 0 : M_PI;
}
return acos(cross_prod); return acos(cross_prod);
} }
// note: return is still in radians as that can be multiplied by radius to get arc length // note: return is still in radians as that can be multiplied by radius to get arc length
inline double spheredist_deg( const Point& p1, const Point& p2 ) { inline double spheredist_deg( const Point& p1, const Point& p2 ) {
return spheredist_rad( return spheredist_rad(
Point( p1._x * (M_PI/180), p1._y * (M_PI/180)), Point( deg2rad(p1._x), deg2rad(p1._y) ),
Point( p2._x * (M_PI/180), p2._y * (M_PI/180)) Point( deg2rad(p2._x), deg2rad(p2._y) )
); );
} }
} }
 End of changes. 3 change blocks. 
4 lines changed or deleted 13 lines changed or added


 curop.h   curop.h 
skipping to change at line 23 skipping to change at line 23
* *
* You should have received a copy of the GNU Affero General Public Lice nse * You should have received a copy of the GNU Affero General Public Lice nse
* 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 "namespace.h" #include "namespace.h"
#include "client.h" #include "client.h"
#include "../bson/util/atomic_int.h" #include "../bson/util/atomic_int.h"
#include "../util/concurrency/spin_lock.h"
#include "db.h" #include "db.h"
namespace mongo { namespace mongo {
/* lifespan is different than CurOp because of recursives with DBDirect Client */ /* lifespan is different than CurOp because of recursives with DBDirect Client */
class OpDebug { class OpDebug {
public: public:
StringBuilder str; StringBuilder str;
void reset(){ void reset(){
str.reset(); str.reset();
} }
}; };
class CachedBSONObj {
public:
static BSONObj _tooBig; // { $msg : "query not recording (too large
)" }
CachedBSONObj(){
_size = (int*)_buf;
reset();
}
void reset( int sz = 0 ){
_size[0] = sz;
}
void set( const BSONObj& o ){
_lock.lock();
try {
int sz = o.objsize();
if ( sz > (int) sizeof(_buf) ) {
reset(1); // flag as too big and return
}
else {
memcpy(_buf, o.objdata(), sz );
}
_lock.unlock();
}
catch ( ... ){
_lock.unlock();
throw;
}
}
int size() const { return *_size; }
bool have() const { return size() > 0; }
BSONObj get( bool threadSafe ){
_lock.lock();
BSONObj o;
try {
o = _get( threadSafe );
_lock.unlock();
}
catch ( ... ){
_lock.unlock();
throw;
}
return o;
}
void append( BSONObjBuilder& b , const StringData& name ){
_lock.lock();
try {
b.append( name , _get( false ) );
_lock.unlock();
}
catch ( ... ){
_lock.unlock();
throw;
}
}
private:
/** you have to be locked when you call this */
BSONObj _get( bool getCopy ){
int sz = size();
if ( sz == 0 )
return BSONObj();
if ( sz == 1 )
return _tooBig;
return BSONObj( _buf ).copy();
}
SpinLock _lock;
char _buf[512];
int * _size;
};
/* Current operation (for the current Client). /* Current operation (for the current Client).
an embedded member of Client class, and typically used from within t he mutex there. */ an embedded member of Client class, and typically used from within t he mutex there. */
class CurOp : boost::noncopyable { class CurOp : boost::noncopyable {
static AtomicUInt _nextOpNum; static AtomicUInt _nextOpNum;
static BSONObj _tooBig; // { $msg : "query not recording (too large )" }
Client * _client; Client * _client;
CurOp * _wrapped; CurOp * _wrapped;
unsigned long long _start; unsigned long long _start;
unsigned long long _checkpoint; unsigned long long _checkpoint;
unsigned long long _end; unsigned long long _end;
bool _active; bool _active;
int _op; int _op;
bool _command; bool _command;
int _lockType; // see concurrency.h for values int _lockType; // see concurrency.h for values
bool _waitingForLock; bool _waitingForLock;
int _dbprofile; // 0=off, 1=slow, 2=all int _dbprofile; // 0=off, 1=slow, 2=all
AtomicUInt _opNum; AtomicUInt _opNum;
char _ns[Namespace::MaxNsLen+2]; char _ns[Namespace::MaxNsLen+2];
struct SockAddr _remote; struct SockAddr _remote;
char _queryBuf[256]; CachedBSONObj _query;
void resetQuery(int x=0) { *((int *)_queryBuf) = x; }
OpDebug _debug; OpDebug _debug;
ThreadSafeString _message; ThreadSafeString _message;
ProgressMeter _progressMeter; ProgressMeter _progressMeter;
void _reset(){ void _reset(){
_command = false; _command = false;
_lockType = 0; _lockType = 0;
_dbprofile = 0; _dbprofile = 0;
skipping to change at line 84 skipping to change at line 170
_message = ""; _message = "";
_progressMeter.finished(); _progressMeter.finished();
} }
void setNS(const char *ns) { void setNS(const char *ns) {
strncpy(_ns, ns, Namespace::MaxNsLen); strncpy(_ns, ns, Namespace::MaxNsLen);
} }
public: public:
int querySize() const { return *((int *) _queryBuf); } bool haveQuery() const { return _query.have(); }
bool haveQuery() const { return querySize() != 0; } BSONObj query( bool threadSafe = false ){ return _query.get( thread
Safe ); }
BSONObj query( bool threadSafe = false);
void ensureStarted(){ void ensureStarted(){
if ( _start == 0 ) if ( _start == 0 )
_start = _checkpoint = curTimeMicros64(); _start = _checkpoint = curTimeMicros64();
} }
void enter( Client::Context * context ){ void enter( Client::Context * context ){
ensureStarted(); ensureStarted();
setNS( context->ns() ); setNS( context->ns() );
if ( context->_db && context->_db->profile > _dbprofile ) if ( context->_db && context->_db->profile > _dbprofile )
_dbprofile = context->_db->profile; _dbprofile = context->_db->profile;
skipping to change at line 113 skipping to change at line 197
_checkpoint = now; _checkpoint = now;
} }
void reset(){ void reset(){
_reset(); _reset();
_start = _checkpoint = 0; _start = _checkpoint = 0;
_active = true; _active = true;
_opNum = _nextOpNum++; _opNum = _nextOpNum++;
_ns[0] = '?'; // just in case not set later _ns[0] = '?'; // just in case not set later
_debug.reset(); _debug.reset();
resetQuery(); _query.reset();
} }
void reset( const SockAddr & remote, int op ) { void reset( const SockAddr & remote, int op ) {
reset(); reset();
_remote = remote; _remote = remote;
_op = op; _op = op;
} }
void markCommand(){ void markCommand(){
_command = true; _command = true;
skipping to change at line 195 skipping to change at line 279
int elapsedMillis() { int elapsedMillis() {
unsigned long long total = curTimeMicros64() - startTime(); unsigned long long total = curTimeMicros64() - startTime();
return (int) (total / 1000); return (int) (total / 1000);
} }
int elapsedSeconds() { int elapsedSeconds() {
return elapsedMillis() / 1000; return elapsedMillis() / 1000;
} }
void setQuery(const BSONObj& query) { void setQuery(const BSONObj& query) {
if( query.objsize() > (int) sizeof(_queryBuf) ) { _query.set( query );
resetQuery(1); // flag as too big and return
return;
}
memcpy(_queryBuf, query.objdata(), query.objsize());
} }
Client * getClient() const { Client * getClient() const {
return _client; return _client;
} }
CurOp( Client * client , CurOp * wrapped = 0 ) { CurOp( Client * client , CurOp * wrapped = 0 ) {
_client = client; _client = client;
_wrapped = wrapped; _wrapped = wrapped;
if ( _wrapped ){ if ( _wrapped ){
_client->_curOp = this; _client->_curOp = this;
} }
_start = _checkpoint = 0; _start = _checkpoint = 0;
_active = false; _active = false;
_reset(); _reset();
_op = 0; _op = 0;
// These addresses should never be written to again. The zeroe s are // These addresses should never be written to again. The zeroe s are
// placed here as a precaution because currentOp may be accesse d // placed here as a precaution because currentOp may be accesse d
// without the db mutex. // without the db mutex.
memset(_ns, 0, sizeof(_ns)); memset(_ns, 0, sizeof(_ns));
memset(_queryBuf, 0, sizeof(_queryBuf));
} }
~CurOp(); ~CurOp();
BSONObj info() { BSONObj info() {
if( ! cc().getAuthenticationInfo()->isAuthorized("admin") ) { if( ! cc().getAuthenticationInfo()->isAuthorized("admin") ) {
BSONObjBuilder b; BSONObjBuilder b;
b.append("err", "unauthorized"); b.append("err", "unauthorized");
return b.obj(); return b.obj();
} }
return infoNoauth(); return infoNoauth();
} }
BSONObj infoNoauth( int attempt = 0 ); BSONObj infoNoauth();
string getRemoteString( bool includePort = true ){ string getRemoteString( bool includePort = true ){
return _remote.toString(includePort); return _remote.toString(includePort);
} }
ProgressMeter& setMessage( const char * msg , long long progressMet erTotal = 0 , int secondsBetween = 3 ){ ProgressMeter& setMessage( const char * msg , long long progressMet erTotal = 0 , int secondsBetween = 3 ){
if ( progressMeterTotal ){ if ( progressMeterTotal ){
if ( _progressMeter.isActive() ){ if ( _progressMeter.isActive() ){
cout << "about to assert, old _message: " << _message < < " new message:" << msg << endl; cout << "about to assert, old _message: " << _message < < " new message:" << msg << endl;
 End of changes. 9 change blocks. 
16 lines changed or deleted 97 lines changed or added


 cursor.h   cursor.h 
skipping to change at line 99 skipping to change at line 99
@param deep - match was against an array, so we know it is multi key. this is legacy and kept @param deep - match was against an array, so we know it is multi key. this is legacy and kept
for backwards datafile compatibility. 'deep' can be eliminated next time we for backwards datafile compatibility. 'deep' can be eliminated next time we
force a data file conversion. 7Jul09 force a data file conversion. 7Jul09
*/ */
virtual bool getsetdup(DiskLoc loc) = 0; virtual bool getsetdup(DiskLoc loc) = 0;
virtual BSONObj prettyIndexBounds() const { return BSONArray(); } virtual BSONObj prettyIndexBounds() const { return BSONArray(); }
virtual bool capped() const { return false; } virtual bool capped() const { return false; }
virtual long long nscanned() = 0;
// The implementation may return different matchers depending on th e // The implementation may return different matchers depending on th e
// position of the cursor. If matcher() is nonzero at the start, // position of the cursor. If matcher() is nonzero at the start,
// matcher() should be checked each time advance() is called. // matcher() should be checked each time advance() is called.
virtual CoveredIndexMatcher *matcher() const { return 0; } virtual CoveredIndexMatcher *matcher() const { return 0; }
// A convenience function for setting the value of matcher() manual ly // A convenience function for setting the value of matcher() manual ly
// so it may accessed later. Implementations which must generate // so it may accessed later. Implementations which must generate
// their own matcher() should assert here. // their own matcher() should assert here.
virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher ) { virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher ) {
massert( 13285, "manual matcher config not allowed", false ); massert( 13285, "manual matcher config not allowed", false );
skipping to change at line 127 skipping to change at line 129
}; };
const AdvanceStrategy *forward(); const AdvanceStrategy *forward();
const AdvanceStrategy *reverse(); const AdvanceStrategy *reverse();
/* table-scan style cursor */ /* table-scan style cursor */
class BasicCursor : public Cursor { class BasicCursor : public Cursor {
protected: protected:
DiskLoc curr, last; DiskLoc curr, last;
const AdvanceStrategy *s; const AdvanceStrategy *s;
void incNscanned() { if ( !curr.isNull() ) { ++_nscanned; } }
private: private:
bool tailable_; bool tailable_;
shared_ptr< CoveredIndexMatcher > _matcher; shared_ptr< CoveredIndexMatcher > _matcher;
long long _nscanned;
void init() { void init() {
tailable_ = false; tailable_ = false;
} }
public: public:
bool ok() { bool ok() {
return !curr.isNull(); return !curr.isNull();
} }
Record* _current() { Record* _current() {
assert( ok() ); assert( ok() );
return curr.rec(); return curr.rec();
skipping to change at line 156 skipping to change at line 160
} }
virtual DiskLoc currLoc() { virtual DiskLoc currLoc() {
return curr; return curr;
} }
virtual DiskLoc refLoc() { virtual DiskLoc refLoc() {
return curr.isNull() ? last : curr; return curr.isNull() ? last : curr;
} }
bool advance(); bool advance();
BasicCursor(DiskLoc dl, const AdvanceStrategy *_s = forward()) : cu BasicCursor(DiskLoc dl, const AdvanceStrategy *_s = forward()) : cu
rr(dl), s( _s ) { rr(dl), s( _s ), _nscanned() {
incNscanned();
init(); init();
} }
BasicCursor(const AdvanceStrategy *_s = forward()) : s( _s ) { BasicCursor(const AdvanceStrategy *_s = forward()) : s( _s ), _nsca nned() {
init(); init();
} }
virtual string toString() { virtual string toString() {
return "BasicCursor"; return "BasicCursor";
} }
virtual void setTailable() { virtual void setTailable() {
if ( !curr.isNull() || !last.isNull() ) if ( !curr.isNull() || !last.isNull() )
tailable_ = true; tailable_ = true;
} }
virtual bool tailable() { virtual bool tailable() {
skipping to change at line 183 skipping to change at line 188
virtual bool supportGetMore() { return true; } virtual bool supportGetMore() { return true; }
virtual bool supportYields() { return true; } virtual bool supportYields() { return true; }
virtual CoveredIndexMatcher *matcher() const { return _matcher.get( ); } virtual CoveredIndexMatcher *matcher() const { return _matcher.get( ); }
virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher ) { virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher ) {
_matcher = matcher; _matcher = matcher;
} }
virtual long long nscanned() { return _nscanned; }
}; };
/* used for order { $natural: -1 } */ /* used for order { $natural: -1 } */
class ReverseCursor : public BasicCursor { class ReverseCursor : public BasicCursor {
public: public:
ReverseCursor(DiskLoc dl) : BasicCursor( dl, reverse() ) { } ReverseCursor(DiskLoc dl) : BasicCursor( dl, reverse() ) { }
ReverseCursor() : BasicCursor( reverse() ) { } ReverseCursor() : BasicCursor( reverse() ) { }
virtual string toString() { virtual string toString() {
return "ReverseCursor"; return "ReverseCursor";
} }
 End of changes. 6 change blocks. 
3 lines changed or deleted 10 lines changed or added


 database.h   database.h 
skipping to change at line 36 skipping to change at line 36
/** /**
* Database represents a database database * Database represents a database database
* Each database database has its own set of files -- dbname.ns, dbname .0, dbname.1, ... * Each database database has its own set of files -- dbname.ns, dbname .0, dbname.1, ...
* NOT memory mapped * NOT memory mapped
*/ */
class Database { class Database {
public: public:
static bool _openAllFiles; static bool _openAllFiles;
Database(const char *nm, bool& newDb, const string& _path = dbpath) Database(const char *nm, /*out*/ bool& newDb, const string& _path =
; dbpath);
private:
~Database() { ~Database();
magic = 0; public:
btreeStore->closeFiles(name, path); /* you must use this to close - there is essential code in this met
size_t n = files.size(); hod that is not in the ~Database destructor.
for ( size_t i = 0; i < n; i++ ) thus the destructor is private. this could be cleaned up one da
delete files[i]; y...
} */
static void closeDatabase( const char *db, const string& path );
/** /**
* tries to make sure that this hasn't been deleted * tries to make sure that this hasn't been deleted
*/ */
bool isOk(){ bool isOk() const { return magic == 781231; }
return magic == 781231;
}
bool isEmpty(){ bool isEmpty(){
return ! namespaceIndex.allocated(); return ! namespaceIndex.allocated();
} }
boost::filesystem::path fileName( int n ) { boost::filesystem::path fileName( int n ) const {
stringstream ss; stringstream ss;
ss << name << '.' << n; ss << name << '.' << n;
boost::filesystem::path fullName; boost::filesystem::path fullName;
fullName = boost::filesystem::path(path); fullName = boost::filesystem::path(path);
if ( directoryperdb ) if ( directoryperdb )
fullName /= name; fullName /= name;
fullName /= ss.str(); fullName /= ss.str();
return fullName; return fullName;
} }
bool exists(int n) { bool exists(int n) const {
return boost::filesystem::exists( fileName( n ) ); return boost::filesystem::exists( fileName( n ) );
} }
void openAllFiles() { void openAllFiles() {
int n = 0; int n = 0;
while( exists(n) ) { while( exists(n) ) {
getFile(n); getFile(n);
n++; n++;
} }
// If last file is empty, consider it preallocated and make sur e it's not mapped // If last file is empty, consider it preallocated and make sur e it's not mapped
skipping to change at line 178 skipping to change at line 175
int n = (int) files.size(); int n = (int) files.size();
if ( n > 0 ) { if ( n > 0 ) {
n--; n--;
} else { } else {
return 0; return 0;
} }
return getFile(n); return getFile(n);
} }
/** /**
* @return true if success, false otherwise * @return true if success. false if bad level or error creating p rofile ns
*/ */
bool setProfilingLevel( int newLevel , string& errmsg ); bool setProfilingLevel( int newLevel , string& errmsg );
void finishInit(); void finishInit();
static bool validDBName( const string& ns ); static bool validDBName( const string& ns );
long long fileSize(){ long long fileSize(){
long long size=0; long long size=0;
for (int n=0; exists(n); n++) for (int n=0; exists(n); n++)
size += boost::filesystem::file_size( fileName(n) ); size += boost::filesystem::file_size( fileName(n) );
return size; return size;
} }
void flushFiles( bool sync ); void flushFiles( bool sync );
vector<MongoDataFile*> files; vector<MongoDataFile*> files;
string name; // "alleyinsider" const string name; // "alleyinsider"
string path; const string path;
NamespaceIndex namespaceIndex; NamespaceIndex namespaceIndex;
int profile; // 0=off. int profile; // 0=off.
string profileName; // "alleyinsider.system.profile" const string profileName; // "alleyinsider.system.profile"
multimap<DiskLoc, ClientCursor*> ccByLoc; multimap<DiskLoc, ClientCursor*> ccByLoc;
int magic; // used for making sure the object is still loaded in me mory int magic; // used for making sure the object is still loaded in me mory
}; };
} // namespace mongo } // namespace mongo
 End of changes. 8 change blocks. 
21 lines changed or deleted 18 lines changed or added


 db.h   db.h 
skipping to change at line 128 skipping to change at line 128
_size -= (int)m.erase( _todb( ns ) ); _size -= (int)m.erase( _todb( ns ) );
} }
/* force - force close even if something underway - use at shutdown */ /* force - force close even if something underway - use at shutdown */
bool closeAll( const string& path , BSONObjBuilder& result, bool fo rce ); bool closeAll( const string& path , BSONObjBuilder& result, bool fo rce );
int size(){ int size(){
return _size; return _size;
} }
void forEach(boost::function<void(Database *)> f) const {
dbMutex.assertAtLeastReadLocked();
for ( Paths::const_iterator i=_paths.begin(); i!=_paths.end();
i++ ){
DBs m = i->second;
for( DBs::const_iterator j=m.begin(); j!=m.end(); j++ ){
f(j->second);
}
}
}
/** /**
* gets all unique db names, ignoring paths * gets all unique db names, ignoring paths
*/ */
void getAllShortNames( set<string>& all ) const { void getAllShortNames( set<string>& all ) const {
dbMutex.assertAtLeastReadLocked(); dbMutex.assertAtLeastReadLocked();
for ( Paths::const_iterator i=_paths.begin(); i!=_paths.end(); i++ ){ for ( Paths::const_iterator i=_paths.begin(); i!=_paths.end(); i++ ){
DBs m = i->second; DBs m = i->second;
for( DBs::const_iterator j=m.begin(); j!=m.end(); j++ ){ for( DBs::const_iterator j=m.begin(); j!=m.end(); j++ ){
all.insert( j->first ); all.insert( j->first );
} }
skipping to change at line 166 skipping to change at line 176
return ns.substr( 0 , i ); return ns.substr( 0 , i );
} }
Paths _paths; Paths _paths;
int _size; int _size;
}; };
extern DatabaseHolder dbHolder; extern DatabaseHolder dbHolder;
// shared functionality for removing references to a database from this
program instance
// does not delete the files on disk
void closeDatabase( const char *cl, const string& path = dbpath );
struct dbtemprelease { struct dbtemprelease {
Client::Context * _context; Client::Context * _context;
int _locktype; int _locktype;
dbtemprelease() { dbtemprelease() {
_context = cc().getContext(); _context = cc().getContext();
_locktype = dbMutex.getState(); _locktype = dbMutex.getState();
assert( _locktype ); assert( _locktype );
if ( _locktype > 0 ) { if ( _locktype > 0 ) {
 End of changes. 2 change blocks. 
5 lines changed or deleted 11 lines changed or added


 dbclient.h   dbclient.h 
skipping to change at line 798 skipping to change at line 798
boost::scoped_ptr<SockAddr> server; boost::scoped_ptr<SockAddr> server;
bool failed; // true if some sort of fatal error has ever happened bool failed; // true if some sort of fatal error has ever happened
bool autoReconnect; bool autoReconnect;
time_t lastReconnectTry; time_t lastReconnectTry;
HostAndPort _server; // remember for reconnects HostAndPort _server; // remember for reconnects
string _serverString; string _serverString;
int _port; int _port;
void _checkConnection(); void _checkConnection();
void checkConnection() { if( failed ) _checkConnection(); } void checkConnection() { if( failed ) _checkConnection(); }
map< string, pair<string,string> > authCache; map< string, pair<string,string> > authCache;
double _timeout; int _timeout;
bool _connect( string& errmsg ); bool _connect( string& errmsg );
public: public:
/** /**
@param _autoReconnect if true, automatically reconnect on a conn ection failure @param _autoReconnect if true, automatically reconnect on a conn ection failure
@param cp used by DBClientReplicaSet. You do not need to specif y this parameter @param cp used by DBClientReplicaSet. You do not need to specif y this parameter
@param timeout tcp timeout in seconds - this is for read/write, not connect. @param timeout tcp timeout in seconds - this is for read/write, not connect.
Connect timeout is fixed, but short, at 5 seconds. Connect timeout is fixed, but short, at 5 seconds.
*/ */
DBClientConnection(bool _autoReconnect=false, DBClientReplicaSet* c p=0, double timeout=0) : DBClientConnection(bool _autoReconnect=false, DBClientReplicaSet* c p=0, int timeout=0) :
clientSet(cp), failed(false), autoReconnect(_autoReconnect) , lastReconnectTry(0), _timeout(timeout) { } clientSet(cp), failed(false), autoReconnect(_autoReconnect) , lastReconnectTry(0), _timeout(timeout) { }
/** Connect to a Mongo database server. /** Connect to a Mongo database server.
If autoReconnect is true, you can try to use the DBClientConnect ion even when If autoReconnect is true, you can try to use the DBClientConnect ion even when
false was returned -- it will try to connect again. false was returned -- it will try to connect again.
@param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 ) @param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 )
If you use IPv6 you must add a port number ( ::1:27017 ) If you use IPv6 you must add a port number ( ::1:27017 )
@param errmsg any relevant error message will appended to the st ring @param errmsg any relevant error message will appended to the st ring
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 dbwebserver.h   dbwebserver.h 
skipping to change at line 41 skipping to change at line 41
public: public:
DbWebHandler( const string& name , double priority , bool requiresR EST ); DbWebHandler( const string& name , double priority , bool requiresR EST );
virtual ~DbWebHandler(){} virtual ~DbWebHandler(){}
virtual bool handles( const string& url ) const { return url == _de faultUrl; } virtual bool handles( const string& url ) const { return url == _de faultUrl; }
virtual bool requiresREST( const string& url ) const { return _requ iresREST; } virtual bool requiresREST( const string& url ) const { return _requ iresREST; }
virtual void handle( const char *rq, // the full request virtual void handle( const char *rq, // the full request
string url, string url,
BSONObj params,
// set these and return them: // set these and return them:
string& responseMsg, string& responseMsg,
int& responseCode, int& responseCode,
vector<string>& headers, // if completely empt y, content-type: text/html will be added vector<string>& headers, // if completely empt y, content-type: text/html will be added
const SockAddr &from const SockAddr &from
) = 0; ) = 0;
string toString() const { return _toString; } string toString() const { return _toString; }
static DbWebHandler * findHandler( const string& url ); static DbWebHandler * findHandler( const string& url );
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 debug_util.h   debug_util.h 
skipping to change at line 81 skipping to change at line 81
// Sets SIGTRAP handler to launch GDB // Sets SIGTRAP handler to launch GDB
// Noop unless on *NIX and compiled with _DEBUG // Noop unless on *NIX and compiled with _DEBUG
void setupSIGTRAPforGDB(); void setupSIGTRAPforGDB();
extern int tlogLevel; extern int tlogLevel;
inline void breakpoint(){ inline void breakpoint(){
if ( tlogLevel < 0 ) if ( tlogLevel < 0 )
return; return;
#ifdef _WIN32
DEV DebugBreak();
#endif
#ifndef _WIN32 #ifndef _WIN32
// code to raise a breakpoint in GDB // code to raise a breakpoint in GDB
ONCE { ONCE {
//prevent SIGTRAP from crashing the program if default action i s specified and we are not in gdb //prevent SIGTRAP from crashing the program if default action i s specified and we are not in gdb
struct sigaction current; struct sigaction current;
sigaction(SIGTRAP, NULL, &current); sigaction(SIGTRAP, NULL, &current);
if (current.sa_handler == SIG_DFL){ if (current.sa_handler == SIG_DFL){
signal(SIGTRAP, SIG_IGN); signal(SIGTRAP, SIG_IGN);
} }
} }
 End of changes. 1 change blocks. 
0 lines changed or deleted 3 lines changed or added


 embedded_builder.h   embedded_builder.h 
skipping to change at line 57 skipping to change at line 57
if ( e.type() == Object && e.valuesize() == 5 ) { // empty obje ct -- this way we can add to it later if ( e.type() == Object && e.valuesize() == 5 ) { // empty obje ct -- this way we can add to it later
string dummyName = name + ".foo"; string dummyName = name + ".foo";
prepareContext( dummyName ); prepareContext( dummyName );
return; return;
} }
prepareContext( name ); prepareContext( name );
back()->appendAs( e, name ); back()->appendAs( e, name );
} }
BufBuilder &subarrayStartAs( string name ) { BufBuilder &subarrayStartAs( string name ) {
prepareContext( name ); prepareContext( name );
return back()->subarrayStart( name.c_str() ); return back()->subarrayStart( name );
} }
void done() { void done() {
while( ! _builderStorage.empty() ) while( ! _builderStorage.empty() )
popBuilder(); popBuilder();
} }
static string splitDot( string & str ) { static string splitDot( string & str ) {
size_t pos = str.find( '.' ); size_t pos = str.find( '.' );
if ( pos == string::npos ) if ( pos == string::npos )
return ""; return "";
string ret = str.substr( 0, pos ); string ret = str.substr( 0, pos );
str = str.substr( pos + 1 ); str = str.substr( pos + 1 );
return ret; return ret;
} }
private: private:
void addBuilder( const string &name ) { void addBuilder( const string &name ) {
shared_ptr< BSONObjBuilder > newBuilder( new BSONObjBuilder( ba ck()->subobjStart( name.c_str() ) ) ); shared_ptr< BSONObjBuilder > newBuilder( new BSONObjBuilder( ba ck()->subobjStart( name ) ) );
_builders.push_back( make_pair( name, newBuilder.get() ) ); _builders.push_back( make_pair( name, newBuilder.get() ) );
_builderStorage.push_back( newBuilder ); _builderStorage.push_back( newBuilder );
} }
void popBuilder() { void popBuilder() {
back()->done(); back()->done();
_builders.pop_back(); _builders.pop_back();
_builderStorage.pop_back(); _builderStorage.pop_back();
} }
BSONObjBuilder *back() { return _builders.back().second; } BSONObjBuilder *back() { return _builders.back().second; }
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 engine.h   engine.h 
skipping to change at line 23 skipping to change at line 23
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* 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 "../pch.h" #include "../pch.h"
#include "../db/jsobj.h" #include "../db/jsobj.h"
extern const char * jsconcatcode; // TODO: change name to mongoJSCode
namespace mongo { namespace mongo {
struct JSFile {
const char* name;
const StringData& source;
};
namespace JSFiles {
extern const JSFile collection;
extern const JSFile db;
extern const JSFile mongo;
extern const JSFile mr;
extern const JSFile query;
extern const JSFile servers;
extern const JSFile utils;
}
typedef unsigned long long ScriptingFunction; typedef unsigned long long ScriptingFunction;
typedef BSONObj (*NativeFunction) ( const BSONObj &args ); typedef BSONObj (*NativeFunction) ( const BSONObj &args );
class Scope : boost::noncopyable { class Scope : boost::noncopyable {
public: public:
Scope(); Scope();
virtual ~Scope(); virtual ~Scope();
virtual void reset() = 0; virtual void reset() = 0;
virtual void init( BSONObj * data ) = 0; virtual void init( BSONObj * data ) = 0;
void init( const char * data ){ void init( const char * data ){
BSONObj o( data , 0 ); BSONObj o( data , 0 );
init( &o ); init( &o );
} }
virtual void localConnect( const char * dbName ) = 0; virtual void localConnect( const char * dbName ) = 0;
virtual void externalSetup() = 0; virtual void externalSetup() = 0;
class NoDBAccess {
Scope * _s;
public:
NoDBAccess( Scope * s ){
_s = s;
}
~NoDBAccess(){
_s->rename( "____db____" , "db" );
}
};
NoDBAccess disableDBAccess( const char * why ){
rename( "db" , "____db____" );
return NoDBAccess( this );
}
virtual double getNumber( const char *field ) = 0; virtual double getNumber( const char *field ) = 0;
virtual int getNumberInt( const char *field ){ return (int)getNumbe r( field ); } virtual int getNumberInt( const char *field ){ return (int)getNumbe r( field ); }
virtual long long getNumberLongLong( const char *field ){ return (l ong long)getNumber( field ); } virtual long long getNumberLongLong( const char *field ){ return (l ong long)getNumber( field ); }
virtual string getString( const char *field ) = 0; virtual string getString( const char *field ) = 0;
virtual bool getBoolean( const char *field ) = 0; virtual bool getBoolean( const char *field ) = 0;
virtual BSONObj getObject( const char *field ) = 0; virtual BSONObj getObject( const char *field ) = 0;
virtual int type( const char *field ) = 0; virtual int type( const char *field ) = 0;
void append( BSONObjBuilder & builder , const char * fieldName , co nst char * scopeName ); void append( BSONObjBuilder & builder , const char * fieldName , co nst char * scopeName );
virtual void setElement( const char *field , const BSONElement& e ) = 0; virtual void setElement( const char *field , const BSONElement& e ) = 0;
virtual void setNumber( const char *field , double val ) = 0; virtual void setNumber( const char *field , double val ) = 0;
virtual void setString( const char *field , const char * val ) = 0; virtual void setString( const char *field , const char * val ) = 0;
virtual void setObject( const char *field , const BSONObj& obj , bo ol readOnly=true ) = 0; virtual void setObject( const char *field , const BSONObj& obj , bo ol readOnly=true ) = 0;
virtual void setBoolean( const char *field , bool val ) = 0; virtual void setBoolean( const char *field , bool val ) = 0;
virtual void setThis( const BSONObj * obj ) = 0; virtual void setThis( const BSONObj * obj ) = 0;
virtual ScriptingFunction createFunction( const char * code ); virtual ScriptingFunction createFunction( const char * code );
virtual void rename( const char * from , const char * to ) = 0;
/** /**
* @return 0 on success * @return 0 on success
*/ */
virtual int invoke( ScriptingFunction func , const BSONObj& args, i nt timeoutMs = 0 , bool ignoreReturn = false ) = 0; virtual int invoke( ScriptingFunction func , const BSONObj& args, i nt timeoutMs = 0 , bool ignoreReturn = false ) = 0;
void invokeSafe( ScriptingFunction func , const BSONObj& args, int timeoutMs = 0 ){ void invokeSafe( ScriptingFunction func , const BSONObj& args, int timeoutMs = 0 ){
int res = invoke( func , args , timeoutMs ); int res = invoke( func , args , timeoutMs );
if ( res == 0 ) if ( res == 0 )
return; return;
throw UserException( 9004 , (string)"invoke failed: " + getErro r() ); throw UserException( 9004 , (string)"invoke failed: " + getErro r() );
} }
virtual string getError() = 0; virtual string getError() = 0;
int invoke( const char* code , const BSONObj& args, int timeoutMs = 0 ); int invoke( const char* code , const BSONObj& args, int timeoutMs = 0 );
void invokeSafe( const char* code , const BSONObj& args, int timeou tMs = 0 ){ void invokeSafe( const char* code , const BSONObj& args, int timeou tMs = 0 ){
if ( invoke( code , args , timeoutMs ) == 0 ) if ( invoke( code , args , timeoutMs ) == 0 )
return; return;
throw UserException( 9005 , (string)"invoke failed: " + getErro r() ); throw UserException( 9005 , (string)"invoke failed: " + getErro r() );
} }
virtual bool exec( const string& code , const string& name , bool p virtual bool exec( const StringData& code , const string& name , bo
rintResult , bool reportError , bool assertOnError, int timeoutMs = 0 ) = 0 ol printResult , bool reportError , bool assertOnError, int timeoutMs = 0 )
; = 0;
virtual void execSetup( const string& code , const string& name = " virtual void execSetup( const StringData& code , const string& name
setup" ){ = "setup" ){
exec( code , name , false , true , true , 0 ); exec( code , name , false , true , true , 0 );
} }
void execSetup( const JSFile& file){
execSetup(file.source, file.name);
}
void execCoreFiles(){
// keeping same order as in SConstruct
execSetup(JSFiles::utils);
execSetup(JSFiles::db);
execSetup(JSFiles::mongo);
execSetup(JSFiles::mr);
execSetup(JSFiles::query);
execSetup(JSFiles::collection);
}
virtual bool execFile( const string& filename , bool printResult , bool reportError , bool assertOnError, int timeoutMs = 0 ); virtual bool execFile( const string& filename , bool printResult , bool reportError , bool assertOnError, int timeoutMs = 0 );
virtual void injectNative( const char *field, NativeFunction func ) = 0; virtual void injectNative( const char *field, NativeFunction func ) = 0;
virtual void gc() = 0; virtual void gc() = 0;
void loadStored( bool ignoreNotConnected = false ); void loadStored( bool ignoreNotConnected = false );
/** /**
if any changes are made to .system.js, call this if any changes are made to .system.js, call this
 End of changes. 6 change blocks. 
7 lines changed or deleted 51 lines changed or added


 engine_v8.h   engine_v8.h 
skipping to change at line 59 skipping to change at line 59
virtual int type( const char *field ); virtual int type( const char *field );
virtual void setNumber( const char *field , double val ); virtual void setNumber( const char *field , double val );
virtual void setString( const char *field , const char * val ); virtual void setString( const char *field , const char * val );
virtual void setBoolean( const char *field , bool val ); virtual void setBoolean( const char *field , bool val );
virtual void setElement( const char *field , const BSONElement& e ) ; virtual void setElement( const char *field , const BSONElement& e ) ;
virtual void setObject( const char *field , const BSONObj& obj , bo ol readOnly); virtual void setObject( const char *field , const BSONObj& obj , bo ol readOnly);
virtual void setThis( const BSONObj * obj ); virtual void setThis( const BSONObj * obj );
virtual void rename( const char * from , const char * to );
virtual ScriptingFunction _createFunction( const char * code ); virtual ScriptingFunction _createFunction( const char * code );
Local< v8::Function > __createFunction( const char * code ); Local< v8::Function > __createFunction( const char * code );
virtual int invoke( ScriptingFunction func , const BSONObj& args, i nt timeoutMs = 0 , bool ignoreReturn = false ); virtual int invoke( ScriptingFunction func , const BSONObj& args, i nt timeoutMs = 0 , bool ignoreReturn = false );
virtual bool exec( const string& code , const string& name , bool p rintResult , bool reportError , bool assertOnError, int timeoutMs ); virtual bool exec( const StringData& code , const string& name , bo ol printResult , bool reportError , bool assertOnError, int timeoutMs );
virtual string getError(){ return _error; } virtual string getError(){ return _error; }
virtual void injectNative( const char *field, NativeFunction func ) ; virtual void injectNative( const char *field, NativeFunction func ) ;
void gc(); void gc();
Handle< Context > context() const { return _context; } Handle< Context > context() const { return _context; }
private: private:
void _startCall(); void _startCall();
 End of changes. 2 change blocks. 
1 lines changed or deleted 3 lines changed or added


 goodies.h   goodies.h 
skipping to change at line 53 skipping to change at line 53
namespace mongo { namespace mongo {
inline pthread_t GetCurrentThreadId() { inline pthread_t GetCurrentThreadId() {
return pthread_self(); return pthread_self();
} }
/* use "addr2line -CFe <exe>" to parse. */ /* use "addr2line -CFe <exe>" to parse. */
inline void printStackTrace( ostream &o = cout ) { inline void printStackTrace( ostream &o = cout ) {
void *b[20]; void *b[20];
size_t size; size_t size;
char **strings;
size_t i; size_t i;
size = backtrace(b, 20); size = backtrace(b, 20);
strings = backtrace_symbols(b, size);
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
o << hex << b[i] << dec << ' '; o << hex << b[i] << dec << ' ';
o << '\n'; o << endl;
char **strings;
strings = backtrace_symbols(b, size);
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
o << ' ' << strings[i] << '\n'; o << ' ' << strings[i] << '\n';
o.flush(); o.flush();
free (strings); free (strings);
} }
#else #else
inline void printStackTrace( ostream &o = cout ) { } inline void printStackTrace( ostream &o = cout ) { }
#endif #endif
/* set to TRUE if we are exiting */ /* set to TRUE if we are exiting */
 End of changes. 3 change blocks. 
4 lines changed or deleted 5 lines changed or added


 lasterror.h   lasterror.h 
skipping to change at line 99 skipping to change at line 99
LastError * _le; LastError * _le;
bool _prev; bool _prev;
}; };
static LastError noError; static LastError noError;
}; };
extern class LastErrorHolder { extern class LastErrorHolder {
public: public:
LastErrorHolder() : _id( 0 ) {} LastErrorHolder() : _id( 0 ) {}
~LastErrorHolder();
LastError * get( bool create = false ); LastError * get( bool create = false );
LastError * getSafe(){ LastError * getSafe(){
LastError * le = get(false); LastError * le = get(false);
if ( ! le ){ if ( ! le ){
log( LL_ERROR ) << " no LastError! id: " << getID() << end l; log( LL_ERROR ) << " no LastError! id: " << getID() << end l;
assert( le ); assert( le );
} }
return le; return le;
} }
skipping to change at line 143 skipping to change at line 144
// disable causes get() to return 0. // disable causes get() to return 0.
LastError *disableForCommand(); // only call once per command invoc ation! LastError *disableForCommand(); // only call once per command invoc ation!
private: private:
ThreadLocalValue<int> _id; ThreadLocalValue<int> _id;
boost::thread_specific_ptr<LastError> _tl; boost::thread_specific_ptr<LastError> _tl;
struct Status { struct Status {
time_t time; time_t time;
LastError *lerr; LastError *lerr;
}; };
typedef map<int,Status> IDMap;
static mongo::mutex _idsmutex; static mongo::mutex _idsmutex;
map<int,Status> _ids; IDMap _ids;
} lastError; } lastError;
void raiseError(int code , const char *msg); void raiseError(int code , const char *msg);
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
1 lines changed or deleted 4 lines changed or added


 log.h   log.h 
skipping to change at line 83 skipping to change at line 83
virtual Nullstream& operator<< (Tee* tee) { virtual Nullstream& operator<< (Tee* tee) {
return *this; return *this;
} }
virtual ~Nullstream() {} virtual ~Nullstream() {}
virtual Nullstream& operator<<(const char *) { virtual Nullstream& operator<<(const char *) {
return *this; return *this;
} }
virtual Nullstream& operator<<(const string& ) { virtual Nullstream& operator<<(const string& ) {
return *this; return *this;
} }
virtual Nullstream& operator<<(const StringData& ) {
return *this;
}
virtual Nullstream& operator<<(char *) { virtual Nullstream& operator<<(char *) {
return *this; return *this;
} }
virtual Nullstream& operator<<(char) { virtual Nullstream& operator<<(char) {
return *this; return *this;
} }
virtual Nullstream& operator<<(int) { virtual Nullstream& operator<<(int) {
return *this; return *this;
} }
virtual Nullstream& operator<<(ExitCode) { virtual Nullstream& operator<<(ExitCode) {
skipping to change at line 172 skipping to change at line 175
static void setLogFile(FILE* f){ static void setLogFile(FILE* f){
scoped_lock lk(mutex); scoped_lock lk(mutex);
logfile = f; logfile = f;
} }
static int magicNumber(){ static int magicNumber(){
return 1717; return 1717;
} }
static int getLogDesc() {
int fd = -1;
if (logfile != NULL)
fd = fileno( logfile );
return fd;
}
inline void flush(Tee *t = 0); inline void flush(Tee *t = 0);
inline Nullstream& setLogLevel(LogLevel l){ inline Nullstream& setLogLevel(LogLevel l){
logLevel = l; logLevel = l;
return *this; return *this;
} }
/** note these are virtual */ /** note these are virtual */
Logstream& operator<<(const char *x) { ss << x; return *this; } Logstream& operator<<(const char *x) { ss << x; return *this; }
Logstream& operator<<(const string& x) { ss << x; return *this; } Logstream& operator<<(const string& x) { ss << x; return *this; }
Logstream& operator<<(const StringData& x) { ss << x.data(); return *this; }
Logstream& operator<<(char *x) { ss << x; return *this; } Logstream& operator<<(char *x) { ss << x; return *this; }
Logstream& operator<<(char x) { ss << x; return *this; } Logstream& operator<<(char x) { ss << x; return *this; }
Logstream& operator<<(int x) { ss << x; return *this; } Logstream& operator<<(int x) { ss << x; return *this; }
Logstream& operator<<(ExitCode x) { ss << x; return *this; } Logstream& operator<<(ExitCode x) { ss << x; return *this; }
Logstream& operator<<(long x) { ss << x; return *this; } Logstream& operator<<(long x) { ss << x; return *this; }
Logstream& operator<<(unsigned long x) { ss << x; return *this; } Logstream& operator<<(unsigned long x) { ss << x; return *this; }
Logstream& operator<<(unsigned x) { ss << x; return *this; } Logstream& operator<<(unsigned x) { ss << x; return *this; }
Logstream& operator<<(double x) { ss << x; return *this; } Logstream& operator<<(double x) { ss << x; return *this; }
Logstream& operator<<(void *x) { ss << x; return *this; } Logstream& operator<<(void *x) { ss << x; return *this; }
Logstream& operator<<(const void *x) { ss << x; return *this; } Logstream& operator<<(const void *x) { ss << x; return *this; }
skipping to change at line 378 skipping to change at line 389
handy for use as parm in uassert/massert. handy for use as parm in uassert/massert.
*/ */
string errnoWithPrefix( const char * prefix ); string errnoWithPrefix( const char * prefix );
void Logstream::logLockless( const StringData& s ){ void Logstream::logLockless( const StringData& s ){
if ( doneSetup == 1717 ){ if ( doneSetup == 1717 ){
if(fwrite(s.data(), s.size(), 1, logfile)){ if(fwrite(s.data(), s.size(), 1, logfile)){
fflush(logfile); fflush(logfile);
}else{ }else{
int x = errno; int x = errno;
cout << "Failed to write to logfile: " << errnoWithDescript ion(x) << ": " << out << endl; cout << "Failed to write to logfile: " << errnoWithDescript ion(x) << endl;
} }
} }
else { else {
cout << s.data() << endl; cout << s.data();
cout.flush();
} }
} }
void Logstream::flush(Tee *t) { void Logstream::flush(Tee *t) {
// this ensures things are sane // this ensures things are sane
if ( doneSetup == 1717 ) { if ( doneSetup == 1717 ) {
string msg = ss.str(); string msg = ss.str();
string threadName = getThreadName(); string threadName = getThreadName();
const char * type = logLevelToString(logLevel); const char * type = logLevelToString(logLevel);
 End of changes. 5 change blocks. 
2 lines changed or deleted 14 lines changed or added


 matcher.h   matcher.h 
skipping to change at line 242 skipping to change at line 242
CoveredIndexMatcher *nextClauseMatcher( const BSONObj &indexKeyPatt ern, bool alwaysUseRecord=false ) { CoveredIndexMatcher *nextClauseMatcher( const BSONObj &indexKeyPatt ern, bool alwaysUseRecord=false ) {
return new CoveredIndexMatcher( _docMatcher, indexKeyPattern, a lwaysUseRecord ); return new CoveredIndexMatcher( _docMatcher, indexKeyPattern, a lwaysUseRecord );
} }
private: private:
CoveredIndexMatcher(const shared_ptr< Matcher > &docMatcher, const BSONObj &indexKeyPattern , bool alwaysUseRecord=false ); CoveredIndexMatcher(const shared_ptr< Matcher > &docMatcher, const BSONObj &indexKeyPattern , bool alwaysUseRecord=false );
void init( bool alwaysUseRecord ); void init( bool alwaysUseRecord );
shared_ptr< Matcher > _docMatcher; shared_ptr< Matcher > _docMatcher;
Matcher _keyMatcher; Matcher _keyMatcher;
bool _needRecord; bool _needRecord;
bool _useRecordOnly;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 message.h   message.h 
skipping to change at line 89 skipping to change at line 89
virtual ~AbstractMessagingPort() { } virtual ~AbstractMessagingPort() { }
virtual void reply(Message& received, Message& response, MSGID resp onseTo) = 0; // like the reply below, but doesn't rely on received.data sti ll being available virtual void reply(Message& received, Message& response, MSGID resp onseTo) = 0; // like the reply below, but doesn't rely on received.data sti ll being available
virtual void reply(Message& received, Message& response) = 0; virtual void reply(Message& received, Message& response) = 0;
virtual HostAndPort remote() const = 0; virtual HostAndPort remote() const = 0;
virtual unsigned remotePort() const = 0; virtual unsigned remotePort() const = 0;
virtual int getClientId(){ virtual int getClientId(){
int x = remotePort(); int x = remotePort();
x = x << 16; x = x << 16;
x |= ( ( 0xFF0 & (long long)this ) >> 8 ); // lowest byte in po inter often meaningless
return x; return x;
} }
}; };
class MessagingPort : public AbstractMessagingPort { class MessagingPort : public AbstractMessagingPort {
public: public:
MessagingPort(int sock, const SockAddr& farEnd); MessagingPort(int sock, const SockAddr& farEnd);
// in some cases the timeout will actually be 2x this value - eg we do a partial send, // in some cases the timeout will actually be 2x this value - eg we do a partial send,
// then the timeout fires, then we try to send again, then the time out fires again with // then the timeout fires, then we try to send again, then the time out fires again with
// no data sent, then we detect that the other side is down // no data sent, then we detect that the other side is down
MessagingPort(double timeout = 0, int logLevel = 0 ); MessagingPort(int timeout = 0, int logLevel = 0 );
virtual ~MessagingPort(); virtual ~MessagingPort();
void shutdown(); void shutdown();
bool connect(SockAddr& farEnd); bool connect(SockAddr& farEnd);
/* it's assumed if you reuse a message object, that it doesn't cros s MessagingPort's. /* it's assumed if you reuse a message object, that it doesn't cros s MessagingPort's.
also, the Message data will go out of scope on the subsequent re cv call. also, the Message data will go out of scope on the subsequent re cv call.
*/ */
skipping to change at line 136 skipping to change at line 135
// recv len or throw SocketException // recv len or throw SocketException
void recv( char * data , int len ); void recv( char * data , int len );
int unsafe_recv( char *buf, int max ); int unsafe_recv( char *buf, int max );
private: private:
int sock; int sock;
PiggyBackData * piggyBackData; PiggyBackData * piggyBackData;
public: public:
SockAddr farEnd; SockAddr farEnd;
double _timeout; int _timeout;
int _logLevel; // passed to log() when logging errors int _logLevel; // passed to log() when logging errors
static void closeAllSockets(unsigned tagMask = 0xffffffff); static void closeAllSockets(unsigned tagMask = 0xffffffff);
/* ports can be tagged with various classes. see closeAllSockets(t ag). defaults to 0. */ /* ports can be tagged with various classes. see closeAllSockets(t ag). defaults to 0. */
unsigned tag; unsigned tag;
friend class PiggyBackData; friend class PiggyBackData;
}; };
 End of changes. 3 change blocks. 
3 lines changed or deleted 2 lines changed or added


 minilex.h   minilex.h 
skipping to change at line 20 skipping to change at line 20
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* 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/>.
*/ */
#error does anything use this?
namespace mongo { namespace mongo {
#if defined(_WIN32) #if defined(_WIN32)
} // namespace mongo } // namespace mongo
#include <hash_map> #include <hash_map>
using namespace stdext; using namespace stdext;
namespace mongo { namespace mongo {
skipping to change at line 67 skipping to change at line 69
return true; return true;
return false; return false;
} }
}; };
typedef hash_map<const char*, int, hash<const char *>, eq_str > strhash map; typedef hash_map<const char*, int, hash<const char *>, eq_str > strhash map;
#endif #endif
struct MiniLex { /*
struct MiniLexNotUsed {
strhashmap reserved; strhashmap reserved;
bool ic[256]; // ic=Identifier Character bool ic[256]; // ic=Identifier Character
bool starter[256]; bool starter[256];
// dm: very dumb about comments and escaped quotes -- but we are fa ster then at least, // dm: very dumb about comments and escaped quotes -- but we are fa ster then at least,
// albeit returning too much (which is ok for jsbobj current usage) . // albeit returning too much (which is ok for jsbobj current usage) .
void grabVariables(char *code /*modified and must stay in scope*/, strhashmap& vars) { void grabVariables(char *code , strhashmap& vars) { // 'code' modif ied and must stay in scope*/
char *p = code; char *p = code;
char last = 0; char last = 0;
while ( *p ) { while ( *p ) {
if ( starter[*p] ) { if ( starter[*p] ) {
char *q = p+1; char *q = p+1;
while ( *q && ic[*q] ) q++; while ( *q && ic[*q] ) q++;
const char *identifier = p; const char *identifier = p;
bool done = *q == 0; bool done = *q == 0;
*q = 0; *q = 0;
if ( !reserved.count(identifier) ) { if ( !reserved.count(identifier) ) {
skipping to change at line 159 skipping to change at line 162
reserved["this"] = true; reserved["this"] = true;
reserved["throw"] = true; reserved["throw"] = true;
reserved["try"] = true; reserved["try"] = true;
reserved["typeof"] = true; reserved["typeof"] = true;
reserved["var"] = true; reserved["var"] = true;
reserved["void"] = true; reserved["void"] = true;
reserved["while"] = true; reserved["while"] = true;
reserved["with "] = true; reserved["with "] = true;
} }
}; };
*/
} // namespace mongo } // namespace mongo
 End of changes. 4 change blocks. 
2 lines changed or deleted 6 lines changed or added


 mmap.h   mmap.h 
skipping to change at line 183 skipping to change at line 183
private: private:
static void updateLength( const char *filename, long &length ); static void updateLength( const char *filename, long &length );
HANDLE fd; HANDLE fd;
HANDLE maphandle; HANDLE maphandle;
void *view; void *view;
long len; long len;
string _filename; string _filename;
#ifdef _WIN32
boost::shared_ptr<mutex> _flushMutex;
#endif
protected: protected:
// only posix mmap implementations will support this // only posix mmap implementations will support this
virtual void _lock(); virtual void _lock();
virtual void _unlock(); virtual void _unlock();
}; };
void printMemInfo( const char * where ); void printMemInfo( const char * where );
#include "ramstore.h" #include "ramstore.h"
 End of changes. 1 change blocks. 
0 lines changed or deleted 4 lines changed or added


 multicmd.h   multicmd.h 
skipping to change at line 46 skipping to change at line 46
class _MultiCommandJob : public BackgroundJob { class _MultiCommandJob : public BackgroundJob {
public: public:
BSONObj& cmd; BSONObj& cmd;
Target& d; Target& d;
_MultiCommandJob(BSONObj& _cmd, Target& _d) : cmd(_cmd), d(_d) { } _MultiCommandJob(BSONObj& _cmd, Target& _d) : cmd(_cmd), d(_d) { }
private: private:
string name() { return "MultiCommandJob"; } string name() { return "MultiCommandJob"; }
void run() { void run() {
try { try {
ScopedConn c(d.toHost); ScopedConn c(d.toHost);
d.ok = c.runCommand("admin", cmd, d.result); d.ok = c->runCommand("admin", cmd, d.result);
} }
catch(DBException&) { catch(DBException&) {
DEV log() << "dev caught dbexception on multiCommand " << d .toHost << rsLog; DEV log() << "dev caught dbexception on multiCommand " << d .toHost << rsLog;
} }
} }
}; };
inline void multiCommand(BSONObj cmd, list<Target>& L) { inline void multiCommand(BSONObj cmd, list<Target>& L) {
typedef shared_ptr<_MultiCommandJob> P; typedef shared_ptr<_MultiCommandJob> P;
list<P> jobs; list<P> jobs;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 mutex.h   mutex.h 
skipping to change at line 23 skipping to change at line 23
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* 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 <map> #include <map>
#include <set> #include <set>
#include "../heapcheck.h"
namespace mongo { namespace mongo {
extern bool __destroyingStatics; extern bool __destroyingStatics;
class mutex; class mutex;
// only used on _DEBUG builds: // only used on _DEBUG builds:
class MutexDebugger { class MutexDebugger {
typedef const char * mid; // mid = mutex ID typedef const char * mid; // mid = mutex ID
typedef map<mid,int> Preceeding; typedef map<mid,int> Preceeding;
map< mid, int > maxNest; map< mid, int > maxNest;
skipping to change at line 50 skipping to change at line 52
// so // so
// a.lock(); b.lock(); is fine // a.lock(); b.lock(); is fine
// b.lock(); alone is fine too // b.lock(); alone is fine too
// only checked on _DEBUG builds. // only checked on _DEBUG builds.
string a,b; string a,b;
void aBreakPoint(){} void aBreakPoint(){}
void programEnding(); void programEnding();
MutexDebugger(); MutexDebugger();
void entering(mid m) { void entering(mid m) {
if( magic != 0x12345678 ) return; if( this == 0 ) return;
assert( magic == 0x12345678 );
Preceeding *_preceeding = us.get(); Preceeding *_preceeding = us.get();
if( _preceeding == 0 ) if( _preceeding == 0 )
us.reset( _preceeding = new Preceeding() ); us.reset( _preceeding = new Preceeding() );
Preceeding &preceeding = *_preceeding; Preceeding &preceeding = *_preceeding;
if( a == m ) { if( a == m ) {
aBreakPoint(); aBreakPoint();
if( preceeding[b.c_str()] ) { if( preceeding[b.c_str()] ) {
cout << "mutex problem " << b << " was locked before " << a << endl; cout << "mutex problem " << b << " was locked before " << a << endl;
skipping to change at line 109 skipping to change at line 112
} }
} }
} }
} }
if( failed ) { if( failed ) {
cout << err << endl; cout << err << endl;
assert( 0 ); assert( 0 );
} }
} }
void leaving(mid m) { void leaving(mid m) {
if( magic != 0x12345678 ) return; if( this == 0 ) return; // still in startup pre-main()
Preceeding& preceeding = *us.get(); Preceeding& preceeding = *us.get();
preceeding[m]--; preceeding[m]--;
if( preceeding[m] < 0 ) { if( preceeding[m] < 0 ) {
cout << "ERROR: lock count for " << m << " is " << preceedi ng[m] << endl; cout << "ERROR: lock count for " << m << " is " << preceedi ng[m] << endl;
assert( preceeding[m] >= 0 ); assert( preceeding[m] >= 0 );
} }
} }
}; };
extern MutexDebugger &mutexDebugger; extern MutexDebugger &mutexDebugger;
skipping to change at line 145 skipping to change at line 148
#endif #endif
#if defined(_DEBUG) #if defined(_DEBUG)
mutex(const char *name) mutex(const char *name)
: _name(name) : _name(name)
#else #else
mutex(const char *) mutex(const char *)
#endif #endif
{ {
_m = new boost::mutex(); _m = new boost::mutex();
IGNORE_OBJECT( _m ); // Turn-off heap checking on _m
} }
~mutex() { ~mutex() {
if( !__destroyingStatics ) { if( !__destroyingStatics ) {
UNIGNORE_OBJECT( _m );
delete _m; delete _m;
} }
} }
class scoped_lock : boost::noncopyable { class scoped_lock : boost::noncopyable {
#if defined(_DEBUG) #if defined(_DEBUG)
mongo::mutex *mut; mongo::mutex *mut;
#endif #endif
public: public:
scoped_lock( mongo::mutex &m ) : _l( m.boost() ) { scoped_lock( mongo::mutex &m ) : _l( m.boost() ) {
#if defined(_DEBUG) #if defined(_DEBUG)
 End of changes. 5 change blocks. 
2 lines changed or deleted 7 lines changed or added


 ntservice.h   ntservice.h 
skipping to change at line 26 skipping to change at line 26
*/ */
#pragma once #pragma once
#if defined(_WIN32) #if defined(_WIN32)
#include <windows.h> #include <windows.h>
namespace mongo { namespace mongo {
typedef bool ( *ServiceCallback )( void ); typedef bool ( *ServiceCallback )( void );
void serviceParamsCheck( program_options::variables_map& params, const std::string dbpath, int argc, char* argv[] );
class ServiceController { class ServiceController {
public: public:
ServiceController(); ServiceController();
virtual ~ServiceController() {} virtual ~ServiceController() {}
static bool installService( const std::wstring& serviceName, const std::wstring& displayName, const std::wstring& serviceDesc, const std::wstr ing& serviceUser, const std::wstring& servicePassword, const std::string db path, int argc, char* argv[] ); static bool installService( const std::wstring& serviceName, const std::wstring& displayName, const std::wstring& serviceDesc, const std::wstr ing& serviceUser, const std::wstring& servicePassword, const std::string db path, int argc, char* argv[] );
static bool removeService( const std::wstring& serviceName ); static bool removeService( const std::wstring& serviceName );
static bool startService( const std::wstring& serviceName, ServiceC allback startService ); static bool startService( const std::wstring& serviceName, ServiceC allback startService );
static bool reportStatus( DWORD reportState, DWORD waitHint = 0 ); static bool reportStatus( DWORD reportState, DWORD waitHint = 0 );
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 oplogreader.h   oplogreader.h 
skipping to change at line 20 skipping to change at line 20
/* started abstracting out the querying of the primary/master's oplog /* started abstracting out the querying of the primary/master's oplog
still fairly awkward but a start. still fairly awkward but a start.
*/ */
class OplogReader { class OplogReader {
auto_ptr<DBClientConnection> _conn; auto_ptr<DBClientConnection> _conn;
auto_ptr<DBClientCursor> cursor; auto_ptr<DBClientCursor> cursor;
public: public:
OplogReader() { OplogReader() {
DEV log() << "TEMP *** OplogReader()" << endl;
} }
~OplogReader() { ~OplogReader() {
DEV log() << "TEMP *** ~OplogReader()" << endl;
} }
void resetCursor() { void resetCursor() {
DEV log() << "TEMP *** OplogReader::resetCursor" << endl;
cursor.reset(); cursor.reset();
} }
void resetConnection() { void resetConnection() {
DEV log() << "TEMP *** OplogReader::resetConnection" << endl;
cursor.reset(); cursor.reset();
_conn.reset(); _conn.reset();
} }
DBClientConnection* conn() { return _conn.get(); } DBClientConnection* conn() { return _conn.get(); }
BSONObj findOne(const char *ns, const Query& q) { BSONObj findOne(const char *ns, const Query& q) {
return conn()->findOne(ns, q); return conn()->findOne(ns, q);
} }
BSONObj getLastOp(const char *ns) { BSONObj getLastOp(const char *ns) {
return findOne(ns, Query().sort(reverseNaturalObj)); return findOne(ns, Query().sort(reverseNaturalObj));
 End of changes. 4 change blocks. 
4 lines changed or deleted 0 lines changed or added


 parallel.h   parallel.h 
skipping to change at line 272 skipping to change at line 272
bool join(); bool join();
private: private:
CommandResult( const string& server , const string& db , const BSONObj& cmd ); CommandResult( const string& server , const string& db , const BSONObj& cmd );
string _server; string _server;
string _db; string _db;
BSONObj _cmd; BSONObj _cmd;
scoped_ptr<boost::thread> _thr; boost::thread _thr;
BSONObj _res; BSONObj _res;
bool _done; bool _done;
bool _ok; bool _ok;
friend class Future; friend class Future;
}; };
static void commandThread( shared_ptr<CommandResult> res ); static void commandThread();
static shared_ptr<CommandResult> spawnCommand( const string& server , const string& db , const BSONObj& cmd ); static shared_ptr<CommandResult> spawnCommand( const string& server , const string& db , const BSONObj& cmd );
private:
static shared_ptr<CommandResult> * _grab;
}; };
} }
#include "undef_macros.h" #include "undef_macros.h"
 End of changes. 3 change blocks. 
2 lines changed or deleted 5 lines changed or added


 pch.h   pch.h 
skipping to change at line 115 skipping to change at line 115
// pdfile versions // pdfile versions
const int VERSION = 4; const int VERSION = 4;
const int VERSION_MINOR = 5; const int VERSION_MINOR = 5;
enum ExitCode { enum ExitCode {
EXIT_CLEAN = 0 , EXIT_CLEAN = 0 ,
EXIT_BADOPTIONS = 2 , EXIT_BADOPTIONS = 2 ,
EXIT_REPLICATION_ERROR = 3 , EXIT_REPLICATION_ERROR = 3 ,
EXIT_NEED_UPGRADE = 4 , EXIT_NEED_UPGRADE = 4 ,
EXIT_KILL = 12 , EXIT_KILL = 12 ,
EXIT_ABRUBT = 14 , EXIT_ABRUPT = 14 ,
EXIT_NTSERVICE_ERROR = 20 , EXIT_NTSERVICE_ERROR = 20 ,
EXIT_JAVA = 21 , EXIT_JAVA = 21 ,
EXIT_OOM_MALLOC = 42 , EXIT_OOM_MALLOC = 42 ,
EXIT_OOM_REALLOC = 43 , EXIT_OOM_REALLOC = 43 ,
EXIT_FS = 45 , EXIT_FS = 45 ,
EXIT_CLOCK_SKEW = 47 , EXIT_CLOCK_SKEW = 47 ,
EXIT_NET_ERROR = 48 , EXIT_NET_ERROR = 48 ,
EXIT_POSSIBLE_CORRUPTION = 60 , // this means we detected a possibl e corruption situation, like a buf overflow EXIT_POSSIBLE_CORRUPTION = 60 , // this means we detected a possibl e corruption situation, like a buf overflow
EXIT_UNCAUGHT = 100 , // top level exception that wasn't caught EXIT_UNCAUGHT = 100 , // top level exception that wasn't caught
EXIT_TEST = 101 , EXIT_TEST = 101 ,
}; };
void dbexit( ExitCode returnCode, const char *whyMsg = ""); void dbexit( ExitCode returnCode, const char *whyMsg = "", bool tryToGe tLock = false);
/** /**
this is here so you can't just type exit() to quit the program this is here so you can't just type exit() to quit the program
you should either use dbexit to shutdown cleanly, or ::exit to tell the system to quit you should either use dbexit to shutdown cleanly, or ::exit to tell the system to quit
if you use this, you'll get a link error since mongo::exit isn't def ined if you use this, you'll get a link error since mongo::exit isn't def ined
*/ */
void exit( ExitCode returnCode ); void exit( ExitCode returnCode );
bool inShutdown(); bool inShutdown();
} // namespace mongo } // namespace mongo
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 pdfile.h   pdfile.h 
skipping to change at line 83 skipping to change at line 83
return header; return header;
} }
/* return max size an extent may be */ /* return max size an extent may be */
static int maxSize(); static int maxSize();
void flush( bool sync ); void flush( bool sync );
private: private:
void badOfs(int) const; void badOfs(int) const;
void badOfs2(int) const;
int defaultSize( const char *filename ) const; int defaultSize( const char *filename ) const;
Extent* getExtent(DiskLoc loc); Extent* getExtent(DiskLoc loc);
Extent* _getExtent(DiskLoc loc); Extent* _getExtent(DiskLoc loc);
Record* recordAt(DiskLoc dl); Record* recordAt(DiskLoc dl);
Record* makeRecord(DiskLoc dl, int size); Record* makeRecord(DiskLoc dl, int size);
void grow(DiskLoc dl, int size); void grow(DiskLoc dl, int size);
MMF mmf; MMF mmf;
skipping to change at line 357 skipping to change at line 358
return (Record*) _p.at(ofs, -1); return (Record*) _p.at(ofs, -1);
} }
inline void MongoDataFile::grow(DiskLoc dl, int size) { inline void MongoDataFile::grow(DiskLoc dl, int size) {
int ofs = dl.getOfs(); int ofs = dl.getOfs();
_p.grow(ofs, size); _p.grow(ofs, size);
} }
inline Record* MongoDataFile::makeRecord(DiskLoc dl, int size) { inline Record* MongoDataFile::makeRecord(DiskLoc dl, int size) {
int ofs = dl.getOfs(); int ofs = dl.getOfs();
assert( ofs >= DataFileHeader::HeaderSize ); if( ofs < DataFileHeader::HeaderSize ) badOfs(ofs); // will uassert - external call to keep out of the normal code path
return (Record*) _p.at(ofs, size); return (Record*) _p.at(ofs, size);
} }
inline DiskLoc Record::getNext(const DiskLoc& myLoc) { inline DiskLoc Record::getNext(const DiskLoc& myLoc) {
if ( nextOfs != DiskLoc::NullOfs ) { if ( nextOfs != DiskLoc::NullOfs ) {
/* defensive */ /* defensive */
if ( nextOfs >= 0 && nextOfs < 10 ) { if ( nextOfs >= 0 && nextOfs < 10 ) {
sayDbContext("Assertion failure - Record::getNext() referen cing a deleted record?"); sayDbContext("Assertion failure - Record::getNext() referen cing a deleted record?");
return DiskLoc(); return DiskLoc();
} }
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 queryoptimizer.h   queryoptimizer.h 
skipping to change at line 117 skipping to change at line 117
} }
_init(); _init();
} }
virtual void next() = 0; virtual void next() = 0;
virtual bool mayRecordPlan() const = 0; virtual bool mayRecordPlan() const = 0;
virtual bool prepareToYield() { massert( 13335, "yield not supporte d", false ); return false; } virtual bool prepareToYield() { massert( 13335, "yield not supporte d", false ); return false; }
virtual void recoverFromYield() { massert( 13336, "yield not suppor ted", false ); } virtual void recoverFromYield() { massert( 13336, "yield not suppor ted", false ); }
virtual long long nscanned() = 0;
/** @return a copy of the inheriting class, which will be run with its own /** @return a copy of the inheriting class, which will be run with its own
query plan. If multiple plan sets are required for an $or query, query plan. If multiple plan sets are required for an $or query,
the QueryOp of the winning plan from a given set will b e cloned the QueryOp of the winning plan from a given set will b e cloned
to generate QueryOps for the subsequent plan set. This function to generate QueryOps for the subsequent plan set. This function
should only be called after the query op has completed executing. should only be called after the query op has completed executing.
*/ */
QueryOp *createChild() { QueryOp *createChild() {
if( _orConstraint.get() ) { if( _orConstraint.get() ) {
_matcher->advanceOrClause( _orConstraint ); _matcher->advanceOrClause( _orConstraint );
_orConstraint.reset(); _orConstraint.reset();
skipping to change at line 315 skipping to change at line 317
class MultiCursor : public Cursor { class MultiCursor : public Cursor {
public: public:
class CursorOp : public QueryOp { class CursorOp : public QueryOp {
public: public:
CursorOp() {} CursorOp() {}
CursorOp( const QueryOp &other ) : QueryOp( other ) {} CursorOp( const QueryOp &other ) : QueryOp( other ) {}
virtual shared_ptr< Cursor > newCursor() const = 0; virtual shared_ptr< Cursor > newCursor() const = 0;
}; };
// takes ownership of 'op' // takes ownership of 'op'
MultiCursor( const char *ns, const BSONObj &pattern, const BSONObj &order, shared_ptr< CursorOp > op = shared_ptr< CursorOp >(), bool mayYield = false ) MultiCursor( const char *ns, const BSONObj &pattern, const BSONObj &order, shared_ptr< CursorOp > op = shared_ptr< CursorOp >(), bool mayYield = false )
: _mps( new MultiPlanScanner( ns, pattern, order, 0, true, BSONObj( ), BSONObj(), !op.get(), mayYield ) ) { : _mps( new MultiPlanScanner( ns, pattern, order, 0, true, BSONObj( ), BSONObj(), !op.get(), mayYield ) ), _nscanned() {
if ( op.get() ) { if ( op.get() ) {
_op = op; _op = op;
} else { } else {
_op.reset( new NoOp() ); _op.reset( new NoOp() );
} }
if ( _mps->mayRunMore() ) { if ( _mps->mayRunMore() ) {
nextClause(); nextClause();
if ( !ok() ) { if ( !ok() ) {
advance(); advance();
} }
} else { } else {
_c.reset( new BasicCursor( DiskLoc() ) ); _c.reset( new BasicCursor( DiskLoc() ) );
} }
} }
// used to handoff a query to a getMore() // used to handoff a query to a getMore()
MultiCursor( auto_ptr< MultiPlanScanner > mps, const shared_ptr< Cu rsor > &c, const shared_ptr< CoveredIndexMatcher > &matcher, const QueryOp &op ) MultiCursor( auto_ptr< MultiPlanScanner > mps, const shared_ptr< Cu rsor > &c, const shared_ptr< CoveredIndexMatcher > &matcher, const QueryOp &op )
: _op( new NoOp( op ) ), _c( c ), _mps( mps ), _matcher( matcher ) { : _op( new NoOp( op ) ), _c( c ), _mps( mps ), _matcher( matcher ), _nscanned( -1 ) {
_mps->setBestGuessOnly(); _mps->setBestGuessOnly();
_mps->mayYield( false ); // with a NoOp, there's no need to yie ld in QueryPlanSet _mps->mayYield( false ); // with a NoOp, there's no need to yie ld in QueryPlanSet
if ( !ok() ) { if ( !ok() ) {
// would have been advanced by UserQueryOp if possible // would have been advanced by UserQueryOp if possible
advance(); advance();
} }
} }
virtual bool ok() { return _c->ok(); } virtual bool ok() { return _c->ok(); }
virtual Record* _current() { return _c->_current(); } virtual Record* _current() { return _c->_current(); }
virtual BSONObj current() { return _c->current(); } virtual BSONObj current() { return _c->current(); }
skipping to change at line 368 skipping to change at line 370
} }
virtual bool supportGetMore() { return true; } virtual bool supportGetMore() { return true; }
virtual bool supportYields() { return _c->supportYields(); } virtual bool supportYields() { return _c->supportYields(); }
// with update we could potentially get the same document on multip le // with update we could potentially get the same document on multip le
// indexes, but update appears to already handle this with seenObje cts // indexes, but update appears to already handle this with seenObje cts
// so we don't have to do anything special here. // so we don't have to do anything special here.
virtual bool getsetdup(DiskLoc loc) { virtual bool getsetdup(DiskLoc loc) {
return _c->getsetdup( loc ); return _c->getsetdup( loc );
} }
virtual CoveredIndexMatcher *matcher() const { return _matcher.get( ); } virtual CoveredIndexMatcher *matcher() const { return _matcher.get( ); }
// return -1 if we're a getmore handoff
virtual long long nscanned() { return _nscanned >= 0 ? _nscanned +
_c->nscanned() : _nscanned; }
// just for testing // just for testing
shared_ptr< Cursor > sub_c() const { return _c; } shared_ptr< Cursor > sub_c() const { return _c; }
private: private:
class NoOp : public CursorOp { class NoOp : public CursorOp {
public: public:
NoOp() {} NoOp() {}
NoOp( const QueryOp &other ) : CursorOp( other ) {} NoOp( const QueryOp &other ) : CursorOp( other ) {}
virtual void _init() { setComplete(); } virtual void _init() { setComplete(); }
virtual void next() {} virtual void next() {}
virtual bool mayRecordPlan() const { return false; } virtual bool mayRecordPlan() const { return false; }
virtual QueryOp *_createChild() const { return new NoOp(); } virtual QueryOp *_createChild() const { return new NoOp(); }
virtual shared_ptr< Cursor > newCursor() const { return qp().ne wCursor(); } virtual shared_ptr< Cursor > newCursor() const { return qp().ne wCursor(); }
virtual long long nscanned() { assert( false ); return 0; }
}; };
void nextClause() { void nextClause() {
if ( _nscanned >= 0 && _c.get() ) {
_nscanned += _c->nscanned();
}
shared_ptr< CursorOp > best = _mps->runOpOnce( *_op ); shared_ptr< CursorOp > best = _mps->runOpOnce( *_op );
if ( ! best->complete() ) if ( ! best->complete() )
throw MsgAssertionException( best->exception() ); throw MsgAssertionException( best->exception() );
_c = best->newCursor(); _c = best->newCursor();
_matcher = best->matcher(); _matcher = best->matcher();
_op = best; _op = best;
} }
shared_ptr< CursorOp > _op; shared_ptr< CursorOp > _op;
shared_ptr< Cursor > _c; shared_ptr< Cursor > _c;
auto_ptr< MultiPlanScanner > _mps; auto_ptr< MultiPlanScanner > _mps;
shared_ptr< CoveredIndexMatcher > _matcher; shared_ptr< CoveredIndexMatcher > _matcher;
long long _nscanned;
}; };
// NOTE min, max, and keyPattern will be updated to be consistent with the selected index. // NOTE min, max, and keyPattern will be updated to be consistent with the selected index.
IndexDetails *indexDetailsForRange( const char *ns, string &errmsg, BSO NObj &min, BSONObj &max, BSONObj &keyPattern ); IndexDetails *indexDetailsForRange( const char *ns, string &errmsg, BSO NObj &min, BSONObj &max, BSONObj &keyPattern );
inline bool isSimpleIdQuery( const BSONObj& query ){ inline bool isSimpleIdQuery( const BSONObj& query ){
BSONObjIterator i(query); BSONObjIterator i(query);
if( !i.more() ) return false; if( !i.more() ) return false;
BSONElement e = i.next(); BSONElement e = i.next();
if( i.more() ) return false; if( i.more() ) return false;
 End of changes. 7 change blocks. 
2 lines changed or deleted 12 lines changed or added


 queryutil.h   queryutil.h 
skipping to change at line 63 skipping to change at line 63
}; };
// 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 isNot=false , 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 );
const FieldRange &operator|=( const FieldRange &other ); const FieldRange &operator|=( const FieldRange &other );
// does not remove fully contained ranges (eg [1,3] - [2,2] doesn't remove anything) // does not remove fully contained ranges (eg [1,3] - [2,2] doesn't remove anything)
// in future we can change so that an or on $in:[3] combined with $ in:{$gt:2} doesn't scan 3 a second time // in future we can change so that an or on $in:[3] combined with $ gt:2 doesn't scan 3 a second time
const FieldRange &operator-=( const FieldRange &other ); const FieldRange &operator-=( const FieldRange &other );
// true iff other includes this // true iff other includes this
bool operator<=( const FieldRange &other ); bool 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[ _i ntervals.size() - 1 ]._upper._bound; } BSONElement max() const { assert( !empty() ); return _intervals[ _i ntervals.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() &&
skipping to change at line 92 skipping to change at line 92
for( vector< FieldInterval >::const_iterator i = _intervals.beg in(); i != _intervals.end(); ++i ) { for( vector< FieldInterval >::const_iterator i = _intervals.beg in(); i != _intervals.end(); ++i ) {
if ( !i->equality() ) { if ( !i->equality() ) {
return false; return false;
} }
} }
return true; return true;
} }
bool nontrivial() const { bool nontrivial() const {
return return
! empty() && ! empty() &&
( minKey.firstElement().woCompare( min(), false ) != 0 || ( _intervals.size() != 1 ||
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(); }
void makeEmpty() { _intervals.clear(); } void makeEmpty() { _intervals.clear(); }
const vector< FieldInterval > &intervals() const { return _i ntervals; } const vector< FieldInterval > &intervals() const { return _i ntervals; }
string getSpecial() const { return _special; } string getSpecial() const { return _special; }
void setExclusiveBounds() { void setExclusiveBounds() {
for( vector< FieldInterval >::iterator i = _intervals.begin(); i != _intervals.end(); ++i ) { for( vector< FieldInterval >::iterator i = _intervals.begin(); i != _intervals.end(); ++i ) {
i->_lower._inclusive = false; i->_lower._inclusive = false;
i->_upper._inclusive = false; i->_upper._inclusive = false;
skipping to change at line 223 skipping to change at line 224
return f->second; return f->second;
} }
FieldRange &range( const char *fieldName ) { FieldRange &range( const char *fieldName ) {
map< string, FieldRange >::iterator f = _ranges.find( fieldName ); map< string, FieldRange >::iterator f = _ranges.find( fieldName );
if ( f == _ranges.end() ) if ( f == _ranges.end() )
return trivialRange(); return trivialRange();
return f->second; return f->second;
} }
int nNontrivialRanges() const { int nNontrivialRanges() const {
int count = 0; int count = 0;
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.nontrivial() ) if ( i->second.nontrivial() )
++count; ++count;
}
return count; return count;
} }
const char *ns() const { return _ns; } const char *ns() const { return _ns; }
// 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;
skipping to change at line 384 skipping to change at line 386
j != _ranges[ i ].intervals().end(); ++j ) { j != _ranges[ i ].intervals().end(); ++j ) {
a << BSONArray( BSON_ARRAY( j->_lower._bound << j->_upp er._bound ).clientReadable() ); a << BSONArray( BSON_ARRAY( j->_lower._bound << j->_upp er._bound ).clientReadable() );
} }
a.done(); a.done();
} }
return b.obj(); return b.obj();
} }
bool matches( const BSONObj &obj ) const; bool matches( const BSONObj &obj ) const;
class Iterator { class Iterator {
public: public:
Iterator( const FieldRangeVector &v ) : _v( v ), _i( _v._ranges Iterator( const FieldRangeVector &v ) : _v( v ), _i( _v._ranges
.size(), -1 ), _cmp( _v._ranges.size(), 0 ), _superlative( _v._ranges.size( .size(), -1 ), _cmp( _v._ranges.size(), 0 ), _inc( _v._ranges.size(), false
), 0 ) { ), _after() {
static BSONObj minObj = minObject();
static BSONElement minElt = minObj.firstElement();
static BSONObj maxObj = maxObject();
static BSONElement maxElt = maxObj.firstElement();
BSONObjIterator i( _v._keyPattern );
for( int j = 0; j < (int)_superlative.size(); ++j ) {
int number = (int) i.next().number();
bool forward = ( ( number >= 0 ? 1 : -1 ) * ( _v._direc
tion >= 0 ? 1 : -1 ) > 0 );
_superlative[ j ] = forward ? &maxElt : &minElt;
}
} }
static BSONObj minObject() { static BSONObj minObject() {
BSONObjBuilder b; BSONObjBuilder b;
b.appendMinKey( "" ); b.appendMinKey( "" );
return b.obj(); return b.obj();
} }
static BSONObj maxObject() { static BSONObj maxObject() {
BSONObjBuilder b; BSONObjBuilder b;
b.appendMaxKey( "" ); b.appendMaxKey( "" );
return b.obj(); return b.obj();
skipping to change at line 427 skipping to change at line 419
_i[ 0 ] = _v._ranges[ 0 ].intervals().size(); _i[ 0 ] = _v._ranges[ 0 ].intervals().size();
} }
return ok(); return ok();
} }
// return value // return value
// -2 end of iteration // -2 end of iteration
// -1 no skipping // -1 no skipping
// >= 0 skip parameter // >= 0 skip parameter
int advance( const BSONObj &curr ); int advance( const BSONObj &curr );
const vector< const BSONElement * > &cmp() const { return _cmp; } const vector< const BSONElement * > &cmp() const { return _cmp; }
const vector< bool > &inc() const { return _inc; }
bool after() const { return _after; }
void prepDive();
void setZero( int i ) { void setZero( int i ) {
for( int j = i; j < (int)_i.size(); ++j ) { for( int j = i; j < (int)_i.size(); ++j ) {
_i[ j ] = 0; _i[ j ] = 0;
} }
} }
void setMinus( int i ) { void setMinus( int i ) {
for( int j = i; j < (int)_i.size(); ++j ) { for( int j = i; j < (int)_i.size(); ++j ) {
_i[ j ] = -1; _i[ j ] = -1;
} }
} }
skipping to change at line 462 skipping to change at line 457
const FieldInterval &fi = _v._ranges[ i ].intervals()[ _i[ i ] ]; const FieldInterval &fi = _v._ranges[ i ].intervals()[ _i[ i ] ];
b.appendAs( fi._upper._bound, "" ); b.appendAs( fi._upper._bound, "" );
} }
return b.obj(); return b.obj();
} }
// check // check
private: private:
const FieldRangeVector &_v; const FieldRangeVector &_v;
vector< int > _i; vector< int > _i;
vector< const BSONElement* > _cmp; vector< const BSONElement* > _cmp;
vector< const BSONElement* > _superlative; vector< bool > _inc;
bool _after;
}; };
private: private:
int matchingLowElement( const BSONElement &e, int i, bool direction ) const; int matchingLowElement( const BSONElement &e, int i, bool direction , bool &lowEquality ) const;
bool matchesElement( const BSONElement &e, int i, bool direction ) const; bool matchesElement( const BSONElement &e, int i, bool direction ) const;
vector< FieldRange > _ranges; vector< FieldRange > _ranges;
BSONObj _keyPattern; BSONObj _keyPattern;
int _direction; int _direction;
vector< BSONObj > _queries; // make sure mem owned vector< BSONObj > _queries; // make sure mem owned
}; };
// generages FieldRangeSet objects, accounting for or clauses // generages FieldRangeSet objects, accounting for or clauses
class FieldRangeOrSet { class FieldRangeOrSet {
public: public:
 End of changes. 8 change blocks. 
19 lines changed or deleted 14 lines changed or added


 replpair.h   replpair.h 
skipping to change at line 165 skipping to change at line 165
inline void notMasterUnless(bool expr) { inline void notMasterUnless(bool expr) {
uassert( 10107 , "not master" , expr ); uassert( 10107 , "not master" , expr );
} }
/* we allow queries to SimpleSlave's -- but not to the slave (nonmaster ) member of a replica pair /* we allow queries to SimpleSlave's -- but not to the slave (nonmaster ) member of a replica pair
so that queries to a pair are realtime consistent as much as possibl e. use setSlaveOk() to so that queries to a pair are realtime consistent as much as possibl e. use setSlaveOk() to
query the nonmaster member of a replica pair. query the nonmaster member of a replica pair.
*/ */
inline void replVerifyReadsOk(ParsedQuery& pq) { inline void replVerifyReadsOk(ParsedQuery& pq) {
if( replSet ) { if( replSet ) {
/* todo: speed up the secondary case. as written here there ar e 2 mutex entries, it can be 1. */ /* todo: speed up the secondary case. as written here there ar e 2 mutex entries, it can b 1. */
if( isMaster() ) return; if( isMaster() ) return;
notMasterUnless( pq.hasOption(QueryOption_SlaveOk) && theReplSe uassert(13435, "not master and slaveok=false", pq.hasOption(Que
t && theReplSet->isSecondary() ); ryOption_SlaveOk));
uassert(13436, "not master or secondary, can't read", theReplSe
t && theReplSet->isSecondary() );
} else { } else {
notMasterUnless(isMaster() || pq.hasOption(QueryOption_SlaveOk) || replSettings.slave == SimpleSlave ); notMasterUnless(isMaster() || pq.hasOption(QueryOption_SlaveOk) || replSettings.slave == SimpleSlave );
} }
} }
inline bool isMasterNs( const char *ns ) { inline bool isMasterNs( const char *ns ) {
char cl[ 256 ]; char cl[ 256 ];
nsToDatabase( ns, cl ); nsToDatabase( ns, cl );
return isMaster( cl ); return isMaster( cl );
} }
 End of changes. 2 change blocks. 
3 lines changed or deleted 5 lines changed or added


 rs.h   rs.h 
skipping to change at line 209 skipping to change at line 209
sp.state = s; sp.primary = p; sp.state = s; sp.primary = p;
} }
void setSelfPrimary(const Member *self) { change(MemberState::RS_PR IMARY, self); } void setSelfPrimary(const Member *self) { change(MemberState::RS_PR IMARY, self); }
void setOtherPrimary(const Member *mem) { void setOtherPrimary(const Member *mem) {
scoped_lock lk(m); scoped_lock lk(m);
assert( !sp.state.primary() ); assert( !sp.state.primary() );
sp.primary = mem; sp.primary = mem;
} }
void noteRemoteIsPrimary(const Member *remote) { void noteRemoteIsPrimary(const Member *remote) {
scoped_lock lk(m); scoped_lock lk(m);
if( !sp.state.secondary() && !sp.state.fatal() ) if( !sp.state.secondary() )
sp.state = MemberState::RS_RECOVERING; sp.state = MemberState::RS_RECOVERING;
sp.primary = remote; sp.primary = remote;
} }
StateBox() : m("StateBox") { } StateBox() : m("StateBox") { }
private: private:
mutex m; mutex m;
SP sp; SP sp;
}; };
void parseReplsetCmdLine(string cfgString, string& setname, vector<Host AndPort>& seeds, set<HostAndPort>& seedSet ); void parseReplsetCmdLine(string cfgString, string& setname, vector<Host AndPort>& seeds, set<HostAndPort>& seedSet );
skipping to change at line 259 skipping to change at line 259
StateBox box; StateBox box;
OpTime lastOpTimeWritten; OpTime lastOpTimeWritten;
long long lastH; // hash we use to make sure we are reading the rig ht flow of ops and aren't on an out-of-date "fork" long long lastH; // hash we use to make sure we are reading the rig ht flow of ops and aren't on an out-of-date "fork"
private: private:
set<ReplSetHealthPollTask*> healthTasks; set<ReplSetHealthPollTask*> healthTasks;
void endOldHealthTasks(); void endOldHealthTasks();
void startHealthTaskFor(Member *m); void startHealthTaskFor(Member *m);
private:
Consensus elect; Consensus elect;
bool ok() const { return !box.getState().fatal(); }
void relinquish(); void relinquish();
void forgetPrimary(); void forgetPrimary();
protected: protected:
bool _stepDown(); bool _stepDown();
private: private:
void assumePrimary(); void assumePrimary();
void loadLastOpTimeWritten(); void loadLastOpTimeWritten();
void changeState(MemberState s); void changeState(MemberState s);
protected: protected:
// "heartbeat message" // "heartbeat message"
// sent in requestHeartbeat respond in field "hbm" // sent in requestHeartbeat respond in field "hbm"
char _hbmsg[256]; // we change this unlocked, thus not an stl::stri ng char _hbmsg[256]; // we change this unlocked, thus not an stl::stri ng
time_t _hbmsgTime; // when it was logged time_t _hbmsgTime; // when it was logged
public: public:
void sethbmsg(string s, int logLevel = 0); void sethbmsg(string s, int logLevel = 0);
protected: protected:
bool initFromConfig(ReplSetConfig& c, bool reconf=false); // true i f ok; throws if config really bad; false if config doesn't include self bool initFromConfig(ReplSetConfig& c, bool reconf=false); // true i f ok; throws if config really bad; false if config doesn't include self
void _fillIsMaster(BSONObjBuilder&); void _fillIsMaster(BSONObjBuilder&);
skipping to change at line 360 skipping to change at line 365
bool stepDown() { return _stepDown(); } bool stepDown() { return _stepDown(); }
string selfFullName() { string selfFullName() {
lock lk(this); lock lk(this);
return _self->fullName(); return _self->fullName();
} }
/* call after constructing to start - returns fairly quickly after la[unching its threads */ /* call after constructing to start - returns fairly quickly after la[unching its threads */
void go() { _go(); } void go() { _go(); }
void fatal() { _fatal(); } void fatal() { _fatal(); }
bool isPrimary() { return box.getState().primary(); } bool isPrimary();
bool isSecondary() { return box.getState().secondary(); } bool isSecondary();
MemberState state() const { return ReplSetImpl::state(); } MemberState state() const { return ReplSetImpl::state(); }
string name() const { return ReplSetImpl::name(); } string name() const { return ReplSetImpl::name(); }
const ReplSetConfig& config() { return ReplSetImpl::config(); } const ReplSetConfig& config() { return ReplSetImpl::config(); }
void getOplogDiagsAsHtml(unsigned server_id, stringstream& ss) cons t { _getOplogDiagsAsHtml(server_id,ss); } void getOplogDiagsAsHtml(unsigned server_id, stringstream& ss) cons t { _getOplogDiagsAsHtml(server_id,ss); }
void summarizeAsHtml(stringstream& ss) const { _summarizeAsHtml(ss) ; } void summarizeAsHtml(stringstream& ss) const { _summarizeAsHtml(ss) ; }
void summarizeStatus(BSONObjBuilder& b) const { _summarizeStatus(b ); } void summarizeStatus(BSONObjBuilder& b) const { _summarizeStatus(b ); }
void fillIsMaster(BSONObjBuilder& b) { _fillIsMaster(b); } void fillIsMaster(BSONObjBuilder& b) { _fillIsMaster(b); }
/* we have a new config (reconfig) - apply it. /* we have a new config (reconfig) - apply it.
@param comment write a no-op comment to the oplog about it. onl y makes sense if one is primary and initiating the reconf. @param comment write a no-op comment to the oplog about it. onl y makes sense if one is primary and initiating the reconf.
skipping to change at line 425 skipping to change at line 429
/** inlines ----------------- */ /** inlines ----------------- */
inline Member::Member(HostAndPort h, unsigned ord, const ReplSetConfig: :MemberCfg *c, bool self) : inline Member::Member(HostAndPort h, unsigned ord, const ReplSetConfig: :MemberCfg *c, bool self) :
_config(*c), _h(h), _hbinfo(ord) _config(*c), _h(h), _hbinfo(ord)
{ {
if( self ) if( self )
_hbinfo.health = 1.0; _hbinfo.health = 1.0;
} }
inline bool ReplSet::isPrimary() {
/* todo replset */
return box.getState().primary();
}
inline bool ReplSet::isSecondary() {
return box.getState().secondary();
}
} }
 End of changes. 8 change blocks. 
4 lines changed or deleted 17 lines changed or added


 rs_member.h   rs_member.h 
skipping to change at line 69 skipping to change at line 69
bool operator!=(const MemberState& r) const { return s != r.s; } bool operator!=(const MemberState& r) const { return s != r.s; }
}; };
/* this is supposed to be just basic information on a member, /* this is supposed to be just basic information on a member,
and copy constructable. */ and copy constructable. */
class HeartbeatInfo { class HeartbeatInfo {
unsigned _id; unsigned _id;
public: public:
HeartbeatInfo() : _id(0xffffffff),hbstate(MemberState::RS_UNKNOWN), health(-1.0),downSince(0),skew(INT_MIN) { } HeartbeatInfo() : _id(0xffffffff),hbstate(MemberState::RS_UNKNOWN), health(-1.0),downSince(0),skew(INT_MIN) { }
HeartbeatInfo(unsigned id); HeartbeatInfo(unsigned id);
bool up() const { return health > 0; }
unsigned id() const { return _id; } unsigned id() const { return _id; }
MemberState hbstate; MemberState hbstate;
double health; double health;
time_t upSince; time_t upSince;
long long downSince; long long downSince;
time_t lastHeartbeat; time_t lastHeartbeat;
string lastHeartbeatMsg; string lastHeartbeatMsg;
OpTime opTime; OpTime opTime;
int skew; int skew;
bool up() const { return health > 0; }
/** health is set to -1 on startup. that means we haven't even che
cked yet. 0 means we checked and it failed. */
bool maybeUp() const { return health != 0; }
long long timeDown() const; // ms long long timeDown() const; // ms
/* true if changed in a way of interest to the repl set manager. */ /* true if changed in a way of interest to the repl set manager. */
bool changed(const HeartbeatInfo& old) const; bool changed(const HeartbeatInfo& old) const;
}; };
inline HeartbeatInfo::HeartbeatInfo(unsigned id) : _id(id) { inline HeartbeatInfo::HeartbeatInfo(unsigned id) : _id(id) {
hbstate = MemberState::RS_UNKNOWN; hbstate = MemberState::RS_UNKNOWN;
health = -1.0; health = -1.0;
downSince = 0; downSince = 0;
 End of changes. 2 change blocks. 
6 lines changed or deleted 1 lines changed or added


 shard.h   shard.h 
skipping to change at line 133 skipping to change at line 133
return runCommand( db , BSON( simple << 1 ) ); return runCommand( db , BSON( simple << 1 ) );
} }
BSONObj runCommand( const string& db , const BSONObj& cmd ) const ; BSONObj runCommand( const string& db , const BSONObj& cmd ) const ;
ShardStatus getStatus() const ; ShardStatus getStatus() const ;
static void getAllShards( vector<Shard>& all ); static void getAllShards( vector<Shard>& all );
static void printShardInfo( ostream& out ); static void printShardInfo( ostream& out );
/** /**
* picks a Shard for more load * @parm current - shard where the chunk/database currently lives i
n
* @return the currently emptiest shard, if best then current, or E
MPTY
*/ */
static Shard pick(); static Shard pick( const Shard& current = EMPTY );
static void reloadShardInfo(); static void reloadShardInfo();
static void removeShard( const string& name ); static void removeShard( const string& name );
static bool isMember( const string& addr ); static bool isMember( const string& addr );
static Shard EMPTY; static Shard EMPTY;
private: private:
 End of changes. 2 change blocks. 
2 lines changed or deleted 5 lines changed or added


 sock.h   sock.h 
skipping to change at line 117 skipping to change at line 117
if ( setsockopt( sock , SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)) < 0 ) if ( setsockopt( sock , SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)) < 0 )
out() << "Failed to set socket opt, SO_REUSEADDR" << endl; out() << "Failed to set socket opt, SO_REUSEADDR" << endl;
} }
#endif #endif
inline string makeUnixSockPath(int port){ inline string makeUnixSockPath(int port){
return "/tmp/mongodb-" + BSONObjBuilder::numStr(port) + ".sock"; return "/tmp/mongodb-" + BSONObjBuilder::numStr(port) + ".sock";
} }
inline void setSockTimeouts(int sock, double secs) { inline void setSockTimeouts(int sock, int secs) {
struct timeval tv; struct timeval tv;
tv.tv_sec = (int)secs; tv.tv_sec = secs;
tv.tv_usec = (int)((long long)(secs*1000*1000) % (1000*1000)); tv.tv_usec = 0;
bool report = logLevel > 3; // solaris doesn't provide these bool report = logLevel > 3; // solaris doesn't provide these
DEV report = true; DEV report = true;
bool ok = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, s izeof(tv) ) == 0; bool ok = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, s izeof(tv) ) == 0;
if( report && !ok ) log() << "unabled to set SO_RCVTIMEO" << endl; if( report && !ok ) log() << "unabled to set SO_RCVTIMEO" << endl;
ok = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *) &tv, sizeof (tv) ) == 0; ok = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *) &tv, sizeof (tv) ) == 0;
DEV if( report && !ok ) log() << "unabled to set SO_RCVTIMEO" << en dl; DEV if( report && !ok ) log() << "unabled to set SO_RCVTIMEO" << en dl;
} }
// If an ip address is passed in, just return that. If a hostname is p assed // If an ip address is passed in, just return that. If a hostname is p assed
// in, look up its ip and return that. Returns "" on failure. // in, look up its ip and return that. Returns "" on failure.
 End of changes. 2 change blocks. 
3 lines changed or deleted 3 lines changed or added


 spin_lock.h   spin_lock.h 
skipping to change at line 19 skipping to change at line 19
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* 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/>.
*/ */
#ifndef CONCURRENCY_SPINLOCK_HEADER #pragma once
#define CONCURRENCY_SPINLOCK_HEADER
#include "pch.h"
#include "rwlock.h"
namespace mongo { namespace mongo {
/** /**
* BIG WARNING - COMPILES, BUT NOT READY FOR USE - BIG WARNING * The spinlock currently requires late GCC support routines to be effi
* cient.
* The spinlock currently requires late GCC support * Other platforms default to a mutex implemenation.
* routines. Support for other platforms will be added soon.
*/ */
class SpinLock{ class SpinLock {
public: public:
SpinLock(); SpinLock();
~SpinLock(); ~SpinLock();
void lock(); void lock();
void unlock(); void unlock();
private: private:
bool _locked; #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
volatile bool _locked;
#elif defined(_WIN32)
CRITICAL_SECTION _cs;
#else
// default to a scoped mutex if not implemented
RWLock _mutex;
#endif
// Non-copyable, non-assignable // Non-copyable, non-assignable
SpinLock(SpinLock&); SpinLock(SpinLock&);
SpinLock& operator=(SpinLock&); SpinLock& operator=(SpinLock&);
}; };
} // namespace mongo } // namespace mongo
#endif // CONCURRENCY_SPINLOCK_HEADER
 End of changes. 5 change blocks. 
8 lines changed or deleted 16 lines changed or added


 task.h   task.h 
skipping to change at line 46 skipping to change at line 46
/** for a repeating task, stop after current invocation ends. c an be called by other threads /** for a repeating task, stop after current invocation ends. c an be called by other threads
as long as the Task is still in scope. as long as the Task is still in scope.
*/ */
void halt(); void halt();
private: private:
unsigned n, repeat; unsigned n, repeat;
friend void fork(Task* t); friend void fork(Task* t);
friend void repeat(Task* t, unsigned millis); friend void repeat(Task* t, unsigned millis);
virtual void run(); virtual void run();
virtual void ending() { } //virtual void ending() { }
void begin(); void begin();
}; };
/** run once */ /** run once */
void fork(Task *t); void fork(Task *t);
/** run doWork() over and over, with a pause between runs of millis */ /** run doWork() over and over, with a pause between runs of millis */
void repeat(Task *t, unsigned millis); void repeat(Task *t, unsigned millis);
/*** Example *** /*** Example ***
 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 , bool localDBAllowed=true, string defaultDB="tes enum DBAccess{
t" , NONE,
string defaultCollection="", bool usesstdout=true ); ALL,
NO_LOCAL
};
Tool( string name , DBAccess access=ALL, string defaultDB="test" ,
string defaultCollection="", bool usesstdout=true);
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();
} }
skipping to change at line 128 skipping to change at line 134
boost::program_options::variables_map _params; boost::program_options::variables_map _params;
}; };
class BSONTool : public Tool { class BSONTool : public Tool {
bool _objcheck; bool _objcheck;
auto_ptr<Matcher> _matcher; auto_ptr<Matcher> _matcher;
public: public:
BSONTool( const char * name , bool objcheck = false ); BSONTool( const char * name , DBAccess access=ALL, bool objcheck = false );
virtual int doRun() = 0; virtual int doRun() = 0;
virtual void gotObject( const BSONObj& obj ) = 0; virtual void gotObject( const BSONObj& obj ) = 0;
virtual int run(); virtual int run();
long long processFile( const path& file ); long long processFile( const path& file );
}; };
 End of changes. 2 change blocks. 
4 lines changed or deleted 9 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 map< string, set<string> > _allMyUris;
extern bool _nokillop; 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();
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 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/