array.h   array.h 
skipping to change at line 89 skipping to change at line 89
} }
void operator++(){ void operator++(){
_pos++; _pos++;
} }
T& operator*(){ T& operator*(){
return _it->_data[_pos]; return _it->_data[_pos];
} }
operator string() const { string toString() const {
stringstream ss; stringstream ss;
ss << _pos; ss << _pos;
return ss.str(); return ss.str();
} }
private: private:
FastArray * _it; FastArray * _it;
int _pos; int _pos;
friend class FastArray; friend class FastArray;
}; };
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 assert_util.h   assert_util.h 
skipping to change at line 24 skipping to change at line 24
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include "../db/lasterror.h" #include "../db/lasterror.h"
namespace mongo { namespace mongo {
enum CommonErrorCodes {
DatabaseDifferCaseCode = 13297 ,
StaleConfigInContextCode = 13388
};
/* these are manipulated outside of mutexes, so be careful */ /* these are manipulated outside of mutexes, so be careful */
struct Assertion { struct Assertion {
Assertion() { Assertion() {
msg[0] = msg[127] = 0; msg[0] = msg[127] = 0;
context[0] = context[127] = 0; context[0] = context[127] = 0;
file = ""; file = "";
line = 0; line = 0;
when = 0; when = 0;
} }
private: private:
skipping to change at line 95 skipping to change at line 100
ExceptionInfo() : msg(""),code(-1){} ExceptionInfo() : msg(""),code(-1){}
ExceptionInfo( const char * m , int c ) ExceptionInfo( const char * m , int c )
: msg( m ) , code( c ){ : msg( m ) , code( c ){
} }
ExceptionInfo( const string& m , int c ) ExceptionInfo( const string& m , int c )
: msg( m ) , code( c ){ : msg( m ) , code( c ){
} }
void append( BSONObjBuilder& b , const char * m = "$err" , const ch ar * c = "code" ) const ; void append( BSONObjBuilder& b , const char * m = "$err" , const ch ar * c = "code" ) const ;
operator string() const { stringstream ss; ss << "exception: " << c ode << " " << msg; return ss.str(); } string toString() const { stringstream ss; ss << "exception: " << c ode << " " << msg; return ss.str(); }
bool empty() const { return msg.empty(); } bool empty() const { return msg.empty(); }
string msg; string msg;
int code; int code;
}; };
class DBException : public std::exception { class DBException : public std::exception {
public: public:
DBException( const ExceptionInfo& ei ) : _ei(ei){} DBException( const ExceptionInfo& ei ) : _ei(ei){}
skipping to change at line 120 skipping to change at line 125
virtual const char* what() const throw(){ return _ei.msg.c_str(); } virtual const char* what() const throw(){ return _ei.msg.c_str(); }
virtual int getCode() const { return _ei.code; } virtual int getCode() const { return _ei.code; }
virtual void appendPrefix( stringstream& ss ) const { } virtual void appendPrefix( stringstream& ss ) const { }
virtual string toString() const { virtual string toString() const {
stringstream ss; ss << getCode() << " " << what(); return ss.st r(); stringstream ss; ss << getCode() << " " << what(); return ss.st r();
return ss.str(); return ss.str();
} }
operator string() const { return toString(); }
const ExceptionInfo& getInfo() const { return _ei; } const ExceptionInfo& getInfo() const { return _ei; }
protected: protected:
ExceptionInfo _ei; ExceptionInfo _ei;
}; };
class AssertionException : public DBException { class AssertionException : public DBException {
public: public:
AssertionException( const ExceptionInfo& ei ) : DBException(ei){} AssertionException( const ExceptionInfo& ei ) : DBException(ei){}
 End of changes. 3 change blocks. 
3 lines changed or deleted 6 lines changed or added


 bson_db.h   bson_db.h 
skipping to change at line 37 skipping to change at line 37
#include "../util/optime.h" #include "../util/optime.h"
namespace mongo { namespace mongo {
/** /**
Timestamps are a special BSON datatype that is used internally for repl ication. Timestamps are a special BSON datatype that is used internally for repl ication.
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)
*/ */
inline BSONObjBuilder& BSONObjBuilder::appendTimestamp( const char *fie ldName , unsigned long long time , unsigned int inc ){ inline BSONObjBuilder& BSONObjBuilder::appendTimestamp( const StringDat a& fieldName , unsigned long long time , unsigned int inc ){
OpTime t( (unsigned) (time / 1000) , inc ); OpTime t( (unsigned) (time / 1000) , inc );
appendTimestamp( fieldName , t.asDate() ); appendTimestamp( fieldName , t.asDate() );
return *this; return *this;
} }
inline OpTime BSONElement::_opTime() const { inline OpTime BSONElement::_opTime() const {
if( type() == mongo::Date || type() == Timestamp ) if( type() == mongo::Date || type() == Timestamp )
return OpTime( *reinterpret_cast< const unsigned long long* >( value() ) ); return OpTime( *reinterpret_cast< const unsigned long long* >( value() ) );
return OpTime(); return OpTime();
} }
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 bsoninlines.h   bsoninlines.h 
skipping to change at line 77 skipping to change at line 77
BSONObjIterator it(*this); BSONObjIterator it(*this);
while ( it.moreWithEOO() ) { while ( it.moreWithEOO() ) {
BSONElement e = it.next(); BSONElement e = it.next();
if ( strcmp(name, e.fieldName()) == 0 ) if ( strcmp(name, e.fieldName()) == 0 )
return true; return true;
} }
} }
return false; return false;
} }
inline BSONElement BSONObj::getField(const char *name) const { inline BSONElement BSONObj::getField(const StringData& name) const {
BSONObjIterator i(*this); BSONObjIterator i(*this);
while ( i.more() ) { while ( i.more() ) {
BSONElement e = i.next(); BSONElement e = i.next();
if ( strcmp(e.fieldName(), name) == 0 ) if ( strcmp(e.fieldName(), name.data()) == 0 )
return e; return e;
} }
return BSONElement(); return BSONElement();
} }
/* add all the fields from the object specified to this object */ /* add all the fields from the object specified to this object */
inline BSONObjBuilder& BSONObjBuilder::appendElements(BSONObj x) { inline BSONObjBuilder& BSONObjBuilder::appendElements(BSONObj x) {
BSONObjIterator it(x); BSONObjIterator it(x);
while ( it.moreWithEOO() ) { while ( it.moreWithEOO() ) {
BSONElement e = it.next(); BSONElement e = it.next();
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 bsonmisc.h   bsonmisc.h 
skipping to change at line 120 skipping to change at line 120
BSONObjBuilderValueStream *s_; BSONObjBuilderValueStream *s_;
}; };
extern Labeler::Label GT; extern Labeler::Label GT;
extern Labeler::Label GTE; extern Labeler::Label GTE;
extern Labeler::Label LT; extern Labeler::Label LT;
extern Labeler::Label LTE; extern Labeler::Label LTE;
extern Labeler::Label NE; extern Labeler::Label NE;
extern Labeler::Label SIZE; extern Labeler::Label SIZE;
// $or helper: OR(BSON("x" << GT << 7), BSON("y" << LT << 6));
// becomes : {$or: [{x: {$gt: 7}}, {y: {$lt: 6}}]}
inline BSONObj OR(const BSONObj& a, const BSONObj& b);
inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c)
;
inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
const BSONObj& d);
inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
const BSONObj& d, const BSONObj& e);
inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
const BSONObj& d, const BSONObj& e, const BSONObj& f);
// definitions in bsonobjbuilder.h b/c of incomplete types
// Utility class to implement BSON( key << val ) as described above. // Utility class to implement BSON( key << val ) as described above.
class BSONObjBuilderValueStream : public boost::noncopyable { class BSONObjBuilderValueStream : public boost::noncopyable {
public: public:
friend class Labeler; friend class Labeler;
BSONObjBuilderValueStream( BSONObjBuilder * builder ); BSONObjBuilderValueStream( BSONObjBuilder * builder );
BSONObjBuilder& operator<<( const BSONElement& e ); BSONObjBuilder& operator<<( const BSONElement& e );
template<class T> template<class T>
BSONObjBuilder& operator<<( T value ); BSONObjBuilder& operator<<( T value );
 End of changes. 1 change blocks. 
0 lines changed or deleted 13 lines changed or added


 bsonobj.h   bsonobj.h 
skipping to change at line 24 skipping to change at line 24
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <set> #include <set>
#include <list> #include <list>
#include <vector> #include <vector>
#include "util/builder.h" #include "util/builder.h"
#include "stringdata.h"
namespace mongo { namespace mongo {
typedef set< BSONElement, BSONElementCmpWithoutField > BSONElementSet; typedef set< BSONElement, BSONElementCmpWithoutField > BSONElementSet;
/** /**
C++ representation of a "BSON" object -- that is, an extended JSO N-style C++ representation of a "BSON" object -- that is, an extended JSO N-style
object in a binary representation. object in a binary representation.
See bsonspec.org. See bsonspec.org.
skipping to change at line 84 skipping to change at line 85
init(msgdata, ifree); init(msgdata, ifree);
} }
BSONObj(const Record *r); BSONObj(const Record *r);
/** Construct an empty BSONObj -- that is, {}. */ /** Construct an empty BSONObj -- that is, {}. */
BSONObj(); BSONObj();
// defensive // defensive
~BSONObj() { _objdata = 0; } ~BSONObj() { _objdata = 0; }
void appendSelfToBufBuilder(BufBuilder& b) const { void appendSelfToBufBuilder(BufBuilder& b) const {
assert( objsize() ); assert( objsize() );
b.append(reinterpret_cast<const void *>( objdata() ), objsize() ); b.appendBuf(reinterpret_cast<const void *>( objdata() ), objsiz e());
} }
/** Readable representation of a BSON object in an extended JSON-st yle notation. /** Readable representation of a BSON object in an extended JSON-st yle notation.
This is an abbreviated representation which might be used for l ogging. This is an abbreviated representation which might be used for l ogging.
*/ */
string toString( bool isArray = false, bool full=false ) const; string toString( bool isArray = false, bool full=false ) const;
operator string() const { return toString(); }
/** Properly formatted JSON string. /** Properly formatted JSON string.
@param pretty if true we try to add some lf's and indentation @param pretty if true we try to add some lf's and indentation
*/ */
string jsonString( JsonStringFormat format = Strict, int pretty = 0 ) const; string jsonString( JsonStringFormat format = Strict, int pretty = 0 ) const;
/** note: addFields always adds _id even if not specified */ /** note: addFields always adds _id even if not specified */
int addFields(BSONObj& from, set<string>& fields); /* returns n add ed */ int addFields(BSONObj& from, set<string>& fields); /* returns n add ed */
/** returns # of top level fields in the object /** returns # of top level fields in the object
skipping to change at line 122 skipping to change at line 122
BSONElement getFieldDotted(const char *name) const; BSONElement getFieldDotted(const char *name) const;
/** return has eoo() true if no match /** return has eoo() true if no match
supports "." notation to reach into embedded objects supports "." notation to reach into embedded objects
*/ */
BSONElement getFieldDotted(const string& name) const { BSONElement getFieldDotted(const string& name) const {
return getFieldDotted( name.c_str() ); return getFieldDotted( name.c_str() );
} }
/** Like getFieldDotted(), but expands multikey arrays and returns all matching objects /** Like getFieldDotted(), but expands multikey arrays and returns all matching objects
*/ */
void getFieldsDotted(const char *name, BSONElementSet &ret ) const; void getFieldsDotted(const StringData& name, BSONElementSet &ret ) const;
/** Like getFieldDotted(), but returns first array encountered whil e traversing the /** Like getFieldDotted(), but returns first array encountered whil e traversing the
dotted fields of name. The name variable is updated to represe nt field dotted fields of name. The name variable is updated to represe nt field
names with respect to the returned element. */ names with respect to the returned element. */
BSONElement getFieldDottedOrArray(const char *&name) const; BSONElement getFieldDottedOrArray(const char *&name) const;
/** Get the field of the specified name. eoo() is true on the retur ned /** Get the field of the specified name. eoo() is true on the retur ned
element if not found. element if not found.
*/ */
BSONElement getField(const char *name) const; BSONElement getField(const StringData& name) const;
/** Get the field of the specified name. eoo() is true on the retur
ned
element if not found.
*/
BSONElement getField(const string name) const {
return getField( name.c_str() );
};
/** Get the field of the specified name. eoo() is true on the retur ned /** Get the field of the specified name. eoo() is true on the retur ned
element if not found. element if not found.
*/ */
BSONElement operator[] (const char *field) const { BSONElement operator[] (const char *field) const {
return getField(field); return getField(field);
} }
BSONElement operator[] (const string& field) const { BSONElement operator[] (const string& field) const {
return getField(field); return getField(field);
skipping to change at line 236 skipping to change at line 229
bool considerFieldName=true) const; bool considerFieldName=true) const;
/**wo='well ordered'. fields must be in same order in each object. /**wo='well ordered'. fields must be in same order in each object.
Ordering is with respect to the signs of the elements Ordering is with respect to the signs of the elements
and allows ascending / descending key mixing. and allows ascending / descending key mixing.
@return <0 if l<r. 0 if l==r. >0 if l>r @return <0 if l<r. 0 if l==r. >0 if l>r
*/ */
int woCompare(const BSONObj& r, const BSONObj &ordering = BSONObj() , int woCompare(const BSONObj& r, const BSONObj &ordering = BSONObj() ,
bool considerFieldName=true) const; bool considerFieldName=true) const;
bool operator<( const BSONObj& other ) const { return woCompare( ot
her ) < 0; }
bool operator<=( const BSONObj& other ) const { return woCompare( o
ther ) <= 0; }
bool operator>( const BSONObj& other ) const { return woCompare( ot
her ) > 0; }
bool operator>=( const BSONObj& other ) const { return woCompare( o
ther ) >= 0; }
/** /**
* @param useDotted whether to treat sort key fields as possibly do tted and expand into them * @param useDotted whether to treat sort key fields as possibly do tted and expand into them
*/ */
int woSortOrder( const BSONObj& r , const BSONObj& sortKey , bool u seDotted=false ) const; int woSortOrder( const BSONObj& r , const BSONObj& sortKey , bool u seDotted=false ) const;
/** This is "shallow equality" -- ints and doubles won't match. fo r a /** This is "shallow equality" -- ints and doubles won't match. fo r a
deep equality test use woCompare (which is slower). deep equality test use woCompare (which is slower).
*/ */
bool woEqual(const BSONObj& r) const { bool woEqual(const BSONObj& r) const {
int os = objsize(); int os = objsize();
 End of changes. 6 change blocks. 
12 lines changed or deleted 13 lines changed or added


 bsonobjbuilder.h   bsonobjbuilder.h 
skipping to change at line 109 skipping to change at line 109
_done(); _done();
} }
} }
/** add all the fields from the object specified to this object */ /** add all the fields from the object specified to this object */
BSONObjBuilder& appendElements(BSONObj x); BSONObjBuilder& appendElements(BSONObj x);
/** append element to the object we are building */ /** append element to the object we are building */
BSONObjBuilder& append( const BSONElement& e) { BSONObjBuilder& append( const BSONElement& e) {
assert( !e.eoo() ); // do not append eoo, that would corrupt us . the builder auto appends when done() is called. assert( !e.eoo() ); // do not append eoo, that would corrupt us . the builder auto appends when done() is called.
_b.append((void*) e.rawdata(), e.size()); _b.appendBuf((void*) e.rawdata(), e.size());
return *this; return *this;
} }
/** append an element but with a new name */ /** append an element but with a new name */
BSONObjBuilder& appendAs(const BSONElement& e, const char *as) { BSONObjBuilder& appendAs(const BSONElement& e, const StringData& f ieldName) {
assert( !e.eoo() ); // do not append eoo, that would corrupt us . the builder auto appends when done() is called. assert( !e.eoo() ); // do not append eoo, that would corrupt us . the builder auto appends when done() is called.
_b.append((char) e.type()); _b.appendNum((char) e.type());
_b.append(as); _b.appendStr(fieldName);
_b.append((void *) e.value(), e.valuesize()); _b.appendBuf((void *) e.value(), e.valuesize());
return *this;
}
/** append an element but with a new name */
BSONObjBuilder& appendAs(const BSONElement& e, const string& as) {
appendAs( e , as.c_str() );
return *this;
}
/** add a subobject as a member */
BSONObjBuilder& append(const char *fieldName, BSONObj subObj) {
_b.append((char) Object);
_b.append(fieldName);
_b.append((void *) subObj.objdata(), subObj.objsize());
return *this; return *this;
} }
/** add a subobject as a member */ /** add a subobject as a member */
BSONObjBuilder& append(const string& fieldName , BSONObj subObj) { BSONObjBuilder& append(const StringData& fieldName, BSONObj subObj)
_b.append((char) Object); {
_b.append(fieldName.c_str(), fieldName.size()+1); _b.appendNum((char) Object);
_b.append((void *) subObj.objdata(), subObj.objsize()); _b.appendStr(fieldName);
_b.appendBuf((void *) subObj.objdata(), subObj.objsize());
return *this; return *this;
} }
/** add header for a new subobject and return bufbuilder for writin g to /** add header for a new subobject and return bufbuilder for writin g to
the subobject's body */ the subobject's body */
BufBuilder &subobjStart(const char *fieldName) { BufBuilder &subobjStart(const StringData& fieldName) {
_b.append((char) Object); _b.appendNum((char) Object);
_b.append(fieldName); _b.appendStr(fieldName);
return _b; return _b;
} }
/** add a subobject as a member with type Array. Thus arr object s hould have "0", "1", ... /** add a subobject as a member with type Array. Thus arr object s hould have "0", "1", ...
style fields in it. style fields in it.
*/ */
BSONObjBuilder& appendArray(const char *fieldName, const BSONObj &s BSONObjBuilder& appendArray(const StringData& fieldName, const BSON
ubObj) { Obj &subObj) {
_b.append((char) Array); _b.appendNum((char) Array);
_b.append(fieldName); _b.appendStr(fieldName);
_b.append((void *) subObj.objdata(), subObj.objsize()); _b.appendBuf((void *) subObj.objdata(), subObj.objsize());
return *this; return *this;
} }
BSONObjBuilder& append(const char *fieldName, BSONArray arr) { BSONObjBuilder& append(const StringData& fieldName, BSONArray arr) {
return appendArray(fieldName, arr); return appendArray(fieldName, arr);
} }
/** add header for a new subarray and return bufbuilder for writing to /** add header for a new subarray and return bufbuilder for writing to
the subarray's body */ the subarray's body */
BufBuilder &subarrayStart(const char *fieldName) { BufBuilder &subarrayStart(const StringData& fieldName) {
_b.append((char) Array); _b.appendNum((char) Array);
_b.append(fieldName); _b.appendStr(fieldName);
return _b; return _b;
} }
/** Append a boolean element */ /** Append a boolean element */
BSONObjBuilder& appendBool(const char *fieldName, int val) { BSONObjBuilder& appendBool(const StringData& fieldName, int val) {
_b.append((char) Bool); _b.appendNum((char) Bool);
_b.append(fieldName); _b.appendStr(fieldName);
_b.append((char) (val?1:0)); _b.appendNum((char) (val?1:0));
return *this; return *this;
} }
/** Append a boolean element */ /** Append a boolean element */
BSONObjBuilder& append(const char *fieldName, bool val) { BSONObjBuilder& append(const StringData& fieldName, bool val) {
_b.append((char) Bool); _b.appendNum((char) Bool);
_b.append(fieldName); _b.appendStr(fieldName);
_b.append((char) (val?1:0)); _b.appendNum((char) (val?1:0));
return *this; return *this;
} }
/** Append a 32 bit integer element */ /** Append a 32 bit integer element */
BSONObjBuilder& append(const char *fieldName, int n) { BSONObjBuilder& append(const StringData& fieldName, int n) {
_b.append((char) NumberInt); _b.appendNum((char) NumberInt);
_b.append(fieldName); _b.appendStr(fieldName);
_b.append(n); _b.appendNum(n);
return *this; return *this;
} }
/** Append a 32 bit integer element */
BSONObjBuilder& append(const string &fieldName, int n) {
return append( fieldName.c_str(), n );
}
/** Append a 32 bit unsigned element - cast to a signed int. */ /** Append a 32 bit unsigned element - cast to a signed int. */
BSONObjBuilder& append(const char *fieldName, unsigned n) { BSONObjBuilder& append(const StringData& fieldName, unsigned n) {
return append(fieldName, (int) n); return append(fieldName, (int) n);
} }
/** Append a NumberLong */ /** Append a NumberLong */
BSONObjBuilder& append(const char *fieldName, long long n) { BSONObjBuilder& append(const StringData& fieldName, long long n) {
_b.append((char) NumberLong); _b.appendNum((char) NumberLong);
_b.append(fieldName); _b.appendStr(fieldName);
_b.append(n); _b.appendNum(n);
return *this; return *this;
} }
/** Append a NumberLong */
BSONObjBuilder& append(const string& fieldName, long long n) {
return append( fieldName.c_str() , n );
}
/** appends a number. if n < max(int)/2 then uses int, otherwise l ong long */ /** appends a number. if n < max(int)/2 then uses int, otherwise l ong long */
BSONObjBuilder& appendIntOrLL( const string& fieldName , long long n ){ BSONObjBuilder& appendIntOrLL( const StringData& fieldName , long l ong n ){
long long x = n; long long x = n;
if ( x < 0 ) if ( x < 0 )
x = x * -1; x = x * -1;
if ( x < ( numeric_limits<int>::max() / 2 ) ) if ( x < ( numeric_limits<int>::max() / 2 ) )
append( fieldName.c_str() , (int)n ); append( fieldName , (int)n );
else else
append( fieldName.c_str() , n ); append( fieldName , n );
return *this; return *this;
} }
/** /**
* appendNumber is a series of method for appending the smallest se nsible type * appendNumber is a series of method for appending the smallest se nsible type
* mostly for JS * mostly for JS
*/ */
BSONObjBuilder& appendNumber( const string& fieldName , int n ){ BSONObjBuilder& appendNumber( const StringData& fieldName , int n )
return append( fieldName.c_str() , n ); {
return append( fieldName , n );
} }
BSONObjBuilder& appendNumber( const string& fieldName , double d ){ BSONObjBuilder& appendNumber( const StringData& fieldName , double
return append( fieldName.c_str() , d ); d ){
return append( fieldName , d );
} }
BSONObjBuilder& appendNumber( const string& fieldName , long long 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.c_str() , (int)l ); append( fieldName , (int)l );
else if ( l < maxDouble ) else if ( l < maxDouble )
append( fieldName.c_str() , (double)l ); append( fieldName , (double)l );
else else
append( fieldName.c_str() , l ); append( fieldName , l );
return *this; return *this;
} }
/** Append a double element */ /** Append a double element */
BSONObjBuilder& append(const char *fieldName, double n) { BSONObjBuilder& append(const StringData& fieldName, double n) {
_b.append((char) NumberDouble); _b.appendNum((char) NumberDouble);
_b.append(fieldName); _b.appendStr(fieldName);
_b.append(n); _b.appendNum(n);
return *this; return *this;
} }
/** tries to append the data as a number /** tries to append the data as a number
* @return true if the data was able to be converted to a number * @return true if the data was able to be converted to a number
*/ */
bool appendAsNumber( const string& fieldName , const string& data ) ; bool appendAsNumber( const StringData& fieldName , const string& da ta );
/** Append a BSON Object ID (OID type). /** Append a BSON Object ID (OID type).
@deprecated Generally, it is preferred to use the append append (name, oid) @deprecated Generally, it is preferred to use the append append (name, oid)
method for this. method for this.
*/ */
BSONObjBuilder& appendOID(const char *fieldName, OID *oid = 0 , boo BSONObjBuilder& appendOID(const StringData& fieldName, OID *oid = 0
l generateIfBlank = false ) { , bool generateIfBlank = false ) {
_b.append((char) jstOID); _b.appendNum((char) jstOID);
_b.append(fieldName); _b.appendStr(fieldName);
if ( oid ) if ( oid )
_b.append( (void *) oid, 12 ); _b.appendBuf( (void *) oid, 12 );
else { else {
OID tmp; OID tmp;
if ( generateIfBlank ) if ( generateIfBlank )
tmp.init(); tmp.init();
else else
tmp.clear(); tmp.clear();
_b.append( (void *) &tmp, 12 ); _b.appendBuf( (void *) &tmp, 12 );
} }
return *this; return *this;
} }
/** /**
Append a BSON Object ID. Append a BSON Object ID.
@param fieldName Field name, e.g., "_id". @param fieldName Field name, e.g., "_id".
@returns the builder object @returns the builder object
*/ */
BSONObjBuilder& append( const char *fieldName, OID oid ) { BSONObjBuilder& append( const StringData& fieldName, OID oid ) {
_b.append((char) jstOID); _b.appendNum((char) jstOID);
_b.append(fieldName); _b.appendStr(fieldName);
_b.append( (void *) &oid, 12 ); _b.appendBuf( (void *) &oid, 12 );
return *this; return *this;
} }
/** /**
Generate and assign an object id for the _id field. Generate and assign an object id for the _id field.
_id should be the first element in the object for good performance. _id should be the first element in the object for good performance.
*/ */
BSONObjBuilder& genOID() { BSONObjBuilder& genOID() {
return append("_id", OID::gen()); return append("_id", OID::gen());
} }
/** Append a time_t date. /** Append a time_t date.
@param dt a C-style 32 bit date value, that is @param dt a C-style 32 bit date value, that is
the number of seconds since January 1, 1970, 00:00:00 GMT the number of seconds since January 1, 1970, 00:00:00 GMT
*/ */
BSONObjBuilder& appendTimeT(const char *fieldName, time_t dt) { BSONObjBuilder& appendTimeT(const StringData& fieldName, time_t dt)
_b.append((char) Date); {
_b.append(fieldName); _b.appendNum((char) Date);
_b.append(static_cast<unsigned long long>(dt) * 1000); _b.appendStr(fieldName);
_b.appendNum(static_cast<unsigned long long>(dt) * 1000);
return *this; return *this;
} }
/** Append a date. /** Append a date.
@param dt a Java-style 64 bit date value, that is @param dt a Java-style 64 bit date value, that is
the number of milliseconds since January 1, 1970, 00:00:00 GMT the number of milliseconds since January 1, 1970, 00:00:00 GMT
*/ */
BSONObjBuilder& appendDate(const char *fieldName, Date_t dt) { BSONObjBuilder& appendDate(const StringData& fieldName, Date_t dt) {
/* easy to pass a time_t to this and get a bad result. thus th is warning. */ /* easy to pass a time_t to this and get a bad result. thus th is warning. */
#if defined(_DEBUG) && defined(MONGO_EXPOSE_MACROS) #if defined(_DEBUG) && defined(MONGO_EXPOSE_MACROS)
if( dt > 0 && dt <= 0xffffffff ) { if( dt > 0 && dt <= 0xffffffff ) {
static int n; static int n;
if( n++ == 0 ) if( n++ == 0 )
log() << "DEV WARNING appendDate() called with a tiny ( but nonzero) date" << endl; log() << "DEV WARNING appendDate() called with a tiny ( but nonzero) date" << endl;
} }
#endif #endif
_b.append((char) Date); _b.appendNum((char) Date);
_b.append(fieldName); _b.appendStr(fieldName);
_b.append(dt); _b.appendNum(dt);
return *this; return *this;
} }
BSONObjBuilder& append(const char *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 char *fieldName, const char *rege BSONObjBuilder& appendRegex(const StringData& fieldName, const char
x, const char *options = "") { *regex, const char *options = "") {
_b.append((char) RegEx); _b.appendNum((char) RegEx);
_b.append(fieldName); _b.appendStr(fieldName);
_b.append(regex); _b.appendStr(regex);
_b.append(options); _b.appendStr(options);
return *this; return *this;
} }
/** 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(string fieldName, string regex, string BSONObjBuilder& appendRegex(const StringData& fieldName, string reg
options = "") { ex, string options = "") {
return appendRegex(fieldName.c_str(), regex.c_str(), options.c_ return appendRegex(fieldName, regex.c_str(), options.c_str());
str());
} }
BSONObjBuilder& appendCode(const char *fieldName, const char *code) BSONObjBuilder& appendCode(const StringData& fieldName, const char
{ *code) {
_b.append((char) Code); _b.appendNum((char) Code);
_b.append(fieldName); _b.appendStr(fieldName);
_b.append((int) strlen(code)+1); _b.appendNum((int) strlen(code)+1);
_b.append(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 char *fieldName, const char *str, int BSONObjBuilder& append(const StringData& fieldName, const char *str
len) { , int len) {
_b.append((char) String); _b.appendNum((char) String);
_b.append(fieldName); _b.appendStr(fieldName);
_b.append((int)len); _b.appendNum((int)len);
_b.append(str, len); _b.appendBuf(str, len);
return *this; return *this;
} }
/** Append a string element */ /** Append a string element */
BSONObjBuilder& append(const char *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 char *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 char *fieldName, const char *sym BSONObjBuilder& appendSymbol(const StringData& fieldName, const cha
bol) { r *symbol) {
_b.append((char) Symbol); _b.appendNum((char) Symbol);
_b.append(fieldName); _b.appendStr(fieldName);
_b.append((int) strlen(symbol)+1); _b.appendNum((int) strlen(symbol)+1);
_b.append(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 char *fieldName ) { BSONObjBuilder& appendNull( const StringData& fieldName ) {
_b.append( (char) jstNULL ); _b.appendNum( (char) jstNULL );
_b.append( 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.
BSONObjBuilder& appendMinKey( const char *fieldName ) { BSONObjBuilder& appendMinKey( const StringData& fieldName ) {
_b.append( (char) MinKey ); _b.appendNum( (char) MinKey );
_b.append( fieldName ); _b.appendStr( fieldName );
return *this; } return *this;
}
// Append an element that is greater than all other keys. // Append an element that is greater than all other keys.
BSONObjBuilder& appendMaxKey( const char *fieldName ) { BSONObjBuilder& appendMaxKey( const StringData& fieldName ) {
_b.append( (char) MaxKey ); _b.appendNum( (char) MaxKey );
_b.append( fieldName ); _b.appendStr( fieldName );
return *this; } return *this;
}
// Append a Timestamp field -- will be updated to next OpTime on db insert. // Append a Timestamp field -- will be updated to next OpTime on db insert.
BSONObjBuilder& appendTimestamp( const char *fieldName ) { BSONObjBuilder& appendTimestamp( const StringData& fieldName ) {
_b.append( (char) Timestamp ); _b.appendNum( (char) Timestamp );
_b.append( fieldName ); _b.appendStr( fieldName );
_b.append( (unsigned long long) 0 ); _b.appendNum( (unsigned long long) 0 );
return *this; } return *this;
}
BSONObjBuilder& appendTimestamp( const char *fieldName , unsigned l BSONObjBuilder& appendTimestamp( const StringData& fieldName , unsi
ong long val ) { gned long long val ) {
_b.append( (char) Timestamp ); _b.appendNum( (char) Timestamp );
_b.append( fieldName ); _b.appendStr( fieldName );
_b.append( val ); _b.appendNum( val );
return *this; } return *this;
}
/** /**
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 char *fieldName , unsigned l ong 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 char *fieldName, const char *ns, BSONObjBuilder& appendDBRef( const StringData& fieldName, const cha
const OID &oid ) { r *ns, const OID &oid ) {
_b.append( (char) DBRef ); _b.appendNum( (char) DBRef );
_b.append( fieldName ); _b.appendStr( fieldName );
_b.append( (int) strlen( ns ) + 1 ); _b.appendNum( (int) strlen( ns ) + 1 );
_b.append( ns ); _b.appendStr( ns );
_b.append( (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.
@param data the byte array @param data the byte array
*/ */
BSONObjBuilder& appendBinData( const char *fieldName, int len, BinD BSONObjBuilder& appendBinData( const StringData& fieldName, int len
ataType type, const char *data ) { , BinDataType type, const char *data ) {
_b.append( (char) BinData ); _b.appendNum( (char) BinData );
_b.append( fieldName ); _b.appendStr( fieldName );
_b.append( len ); _b.appendNum( len );
_b.append( (char) type ); _b.appendNum( (char) type );
_b.append( (void *) data, len ); _b.appendBuf( (void *) data, len );
return *this; return *this;
} }
BSONObjBuilder& appendBinData( const char *fieldName, int len, BinD ataType type, const unsigned char *data ) { BSONObjBuilder& appendBinData( const StringData& fieldName, int len , BinDataType type, const unsigned char *data ) {
return appendBinData(fieldName, len, type, (const char *) data) ; return appendBinData(fieldName, len, type, (const char *) data) ;
} }
/** /**
Subtype 2 is deprecated. Subtype 2 is deprecated.
Append a BSON bindata bytearray element. Append a BSON bindata bytearray element.
@param data a byte array @param data a byte array
@param len the length of data @param len the length of data
*/ */
BSONObjBuilder& appendBinDataArrayDeprecated( const char * fieldNam e , const char * data , int len ){ BSONObjBuilder& appendBinDataArrayDeprecated( const char * fieldNam e , const char * data , int len ){
_b.append( (char) BinData ); _b.appendNum( (char) BinData );
_b.append( fieldName ); _b.appendStr( fieldName );
_b.append( len + 4 ); _b.appendNum( len + 4 );
_b.append( (char)0x2 ); _b.appendNum( (char)0x2 );
_b.append( len ); _b.appendNum( len );
_b.append( (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 char *fieldName, const char BSONObjBuilder& appendCodeWScope( const StringData& fieldName, cons
*code, const BSONObj &scope ) { t char *code, const BSONObj &scope ) {
_b.append( (char) CodeWScope ); _b.appendNum( (char) CodeWScope );
_b.append( fieldName ); _b.appendStr( fieldName );
_b.append( ( int )( 4 + 4 + strlen( code ) + 1 + scope.objsize( _b.appendNum( ( int )( 4 + 4 + strlen( code ) + 1 + scope.objsi
) ) ); ze() ) );
_b.append( ( int ) strlen( code ) + 1 ); _b.appendNum( ( int ) strlen( code ) + 1 );
_b.append( code ); _b.appendStr( code );
_b.append( ( void * )scope.objdata(), scope.objsize() ); _b.appendBuf( ( void * )scope.objdata(), scope.objsize() );
return *this; return *this;
} }
void appendUndefined( const char *fieldName ) { void appendUndefined( const StringData& fieldName ) {
_b.append( (char) Undefined ); _b.appendNum( (char) Undefined );
_b.append( 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 char *code, const BSONObj &scope ){
appendCodeWScope( "$where" , code , scope ); appendCodeWScope( "$where" , code , scope );
} }
void appendWhere( const string &code, const BSONObj &scope ){ void appendWhere( const string &code, const BSONObj &scope ){
appendWhere( code.c_str(), 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 string& field , int type ); void appendMinForType( const StringData& fieldName , int type );
void appendMaxForType( const string& field , 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 char *fieldName, const vector< T >& v als ); BSONObjBuilder& append( const StringData& fieldName, const vector< T >& vals );
template < class T > template < class T >
BSONObjBuilder& append( const char *fieldName, const list< T >& val s ); BSONObjBuilder& append( const StringData& fieldName, const list< T >& vals );
/** The returned BSONObj will free the buffer when it is finished. */ /** The returned BSONObj will free the buffer when it is finished. */
BSONObj obj() { BSONObj obj() {
bool own = owned(); bool own = owned();
massert( 10335 , "builder does not own memory", own ); massert( 10335 , "builder does not own memory", own );
int l; int l;
return BSONObj(decouple(l), true); return BSONObj(decouple(l), true);
} }
/** Fetch the object we have built. /** Fetch the object we have built.
skipping to change at line 611 skipping to change at line 593
BSONObjIterator iterator() const ; BSONObjIterator iterator() const ;
private: private:
char* _done() { char* _done() {
if ( _doneCalled ) if ( _doneCalled )
return _b.buf() + _offset; return _b.buf() + _offset;
_doneCalled = true; _doneCalled = true;
_s.endField(); _s.endField();
_b.append((char) EOO); _b.appendNum((char) EOO);
char *data = _b.buf() + _offset; char *data = _b.buf() + _offset;
int size = _b.len() - _offset; int size = _b.len() - _offset;
*((int*)data) = size; *((int*)data) = size;
if ( _tracker ) if ( _tracker )
_tracker->got( size ); _tracker->got( size );
return data; return data;
} }
BufBuilder &_b; BufBuilder &_b;
BufBuilder _buf; BufBuilder _buf;
skipping to change at line 660 skipping to change at line 642
void appendNull() { void appendNull() {
_b.appendNull(num().c_str()); _b.appendNull(num().c_str());
} }
BSONArray arr(){ return BSONArray(_b.obj()); } BSONArray arr(){ return BSONArray(_b.obj()); }
BSONObj done() { return _b.done(); } BSONObj done() { return _b.done(); }
template <typename T> template <typename T>
BSONArrayBuilder& append(const char *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 char *name = "0" ) {
fill( name ); fill( name );
return _b.subobjStart( num().c_str() ); return _b.subobjStart( num().c_str() );
} }
BufBuilder &subarrayStart( const char *name ) { BufBuilder &subarrayStart( const char *name ) {
fill( name ); fill( name );
return _b.subarrayStart( num().c_str() ); return _b.subarrayStart( num().c_str() );
} }
void appendArray( const char *name, BSONObj subObj ) { void appendArray( const StringData& name, BSONObj subObj ) {
fill( name ); fill( name );
_b.appendArray( num().c_str(), subObj ); _b.appendArray( num().c_str(), 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 char *name ) { void fill( const StringData& name ) {
char *r; char *r;
int n = strtol( name, &r, 10 ); int n = strtol( name.data(), &r, 10 );
uassert( 13048, (string)"can't append to array using string fie uassert( 13048, (string)"can't append to array using string fie
ld name [" + name + "]" , !*r ); ld name [" + name.data() + "]" , !*r );
while( _i < n ) while( _i < n )
append( nullElt() ); append( nullElt() );
} }
static BSONElement nullElt() { static BSONElement nullElt() {
static BSONObj n = nullObj(); static BSONObj n = nullObj();
return n.firstElement(); return n.firstElement();
} }
static BSONObj nullObj() { static BSONObj nullObj() {
skipping to change at line 712 skipping to change at line 694
_b.appendNull( "" ); _b.appendNull( "" );
return _b.obj(); return _b.obj();
} }
string num(){ return _b.numStr(_i++); } string num(){ return _b.numStr(_i++); }
int _i; int _i;
BSONObjBuilder _b; BSONObjBuilder _b;
}; };
template < class T > template < class T >
inline BSONObjBuilder& BSONObjBuilder::append( const char *fieldName, c onst vector< T >& vals ) { inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldN ame, const vector< T >& vals ) {
BSONObjBuilder arrBuilder; BSONObjBuilder arrBuilder;
for ( unsigned int i = 0; i < vals.size(); ++i ) for ( unsigned int i = 0; i < vals.size(); ++i )
arrBuilder.append( numStr( i ).c_str(), vals[ i ] ); arrBuilder.append( numStr( i ), vals[ i ] );
appendArray( fieldName, arrBuilder.done() ); appendArray( fieldName, arrBuilder.done() );
return *this; return *this;
} }
template < class T > template < class T >
inline BSONObjBuilder& BSONObjBuilder::append( const char *fieldName, c onst list< T >& vals ) { inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldN ame, const list< T >& vals ) {
BSONObjBuilder arrBuilder; BSONObjBuilder arrBuilder;
int n = 0; int n = 0;
for( typename list< T >::const_iterator i = vals.begin(); i != vals .end(); i++ ) for( typename list< T >::const_iterator i = vals.begin(); i != vals .end(); i++ )
arrBuilder.append( numStr(n++).c_str(), *i ); arrBuilder.append( numStr(n++), *i );
appendArray( fieldName, arrBuilder.done() ); appendArray( fieldName, arrBuilder.done() );
return *this; return *this;
} }
// $or helper: OR(BSON("x" << GT << 7), BSON("y" << LT 6));
inline BSONObj OR(const BSONObj& a, const BSONObj& b)
{ return BSON( "$or" << BSON_ARRAY(a << b) ); }
inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c)
{ return BSON( "$or" << BSON_ARRAY(a << b << c) ); }
inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
const BSONObj& d)
{ return BSON( "$or" << BSON_ARRAY(a << b << c << d) ); }
inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
const BSONObj& d, const BSONObj& e)
{ return BSON( "$or" << BSON_ARRAY(a << b << c << d << e) ); }
inline BSONObj OR(const BSONObj& a, const BSONObj& b, const BSONObj& c,
const BSONObj& d, const BSONObj& e, const BSONObj& f)
{ return BSON( "$or" << BSON_ARRAY(a << b << c << d << e << f) ); }
} }
 End of changes. 66 change blocks. 
198 lines changed or deleted 198 lines changed or added


 builder.h   builder.h 
skipping to change at line 24 skipping to change at line 24
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include "../stringdata.h"
namespace mongo { namespace mongo {
class StringBuilder; class StringBuilder;
void msgasserted(int msgid, const char *msg); void msgasserted(int msgid, const char *msg);
class BufBuilder { class BufBuilder {
public: public:
BufBuilder(int initsize = 512) : size(initsize) { BufBuilder(int initsize = 512) : size(initsize) {
skipping to change at line 73 skipping to change at line 74
/* leave room for some stuff later */ /* leave room for some stuff later */
char* skip(int n) { return grow(n); } char* skip(int n) { return grow(n); }
/* note this may be deallocated (realloced) if you keep writing. */ /* note this may be deallocated (realloced) if you keep writing. */
char* buf() { return data; } char* buf() { return data; }
const char* buf() const { return data; } const char* buf() const { return data; }
/* assume ownership of the buffer - you must then free() it */ /* assume ownership of the buffer - you must then free() it */
void decouple() { data = 0; } void decouple() { data = 0; }
template<class T> void append(T j) { void appendChar(char j){
*((T*)grow(sizeof(T))) = j; *((char*)grow(sizeof(char))) = j;
} }
void append(short j) { void appendNum(char j){
append<short>(j); *((char*)grow(sizeof(char))) = j;
} }
void append(int j) { void appendNum(short j) {
append<int>(j); *((short*)grow(sizeof(short))) = j;
} }
void append(unsigned j) { void appendNum(int j) {
append<unsigned>(j); *((int*)grow(sizeof(int))) = j;
} }
void append(bool j) { void appendNum(unsigned j) {
append<bool>(j); *((unsigned*)grow(sizeof(unsigned))) = j;
} }
void append(double j) { void appendNum(bool j) {
append<double>(j); *((bool*)grow(sizeof(bool))) = j;
} }
void appendNum(double j) {
void append(const void *src, size_t len) { *((double*)grow(sizeof(double))) = j;
memcpy(grow((int) len), src, len); }
void appendNum(long long j) {
*((long long*)grow(sizeof(long long))) = j;
}
void appendNum(unsigned long long j) {
*((unsigned long long*)grow(sizeof(unsigned long long))) = j;
} }
void append(const char *str) { void appendBuf(const void *src, size_t len) {
append((void*) str, strlen(str)+1); memcpy(grow((int) len), src, len);
} }
void append(const std::string &str) { void appendStr(const StringData &str) {
append( (void *)str.c_str(), str.length() + 1 ); const int len = str.size() + 1;
memcpy(grow(len), str.data(), len);
} }
int len() const { int len() const {
return l; return l;
} }
void setlen( int newLen ){ void setlen( int newLen ){
l = newLen; l = newLen;
} }
/* returns the pre-grow write position */ /* returns the pre-grow write position */
char* grow(int by) { inline char* grow(int by) {
int oldlen = l; int oldlen = l;
l += by; l += by;
if ( l > size ) { if ( l > size ) {
grow_reallocate(); grow_reallocate();
} }
return data + oldlen; return data + oldlen;
} }
/* "slow" portion of 'grow()' */
void grow_reallocate() {
int a = size * 2;
if ( a == 0 )
a = 512;
if ( l > a )
a = l + 16 * 1024;
if( a > 64 * 1024 * 1024 )
msgasserted(10000, "BufBuilder grow() > 64MB");
data = (char *) realloc(data, a);
size= a;
}
int getSize() const { return size; } int getSize() const { return size; }
private: private:
/* "slow" portion of 'grow()' */
void grow_reallocate();
char *data; char *data;
int l; int l;
int size; int size;
friend class StringBuilder; friend class StringBuilder;
}; };
#if defined(_WIN32) #if defined(_WIN32)
#pragma warning( disable : 4996 ) #pragma warning( disable : 4996 )
#endif #endif
 End of changes. 13 change blocks. 
33 lines changed or deleted 30 lines changed or added


 chunk.h   chunk.h 
skipping to change at line 81 skipping to change at line 81
} }
string getns() const; string getns() const;
Shard getShard() const { return _shard; } Shard getShard() const { return _shard; }
void setShard( const Shard& shard ); void setShard( const Shard& shard );
bool contains( const BSONObj& obj ) const; bool contains( const BSONObj& obj ) const;
string toString() const; string toString() const;
operator string() const { return toString(); }
friend ostream& operator << (ostream& out, const Chunk& c){ return (out << c.toString()); } friend ostream& operator << (ostream& out, const Chunk& c){ return (out << c.toString()); }
bool operator==(const Chunk& s) const; bool operator==(const Chunk& s) const;
bool operator!=(const Chunk& s) const{ bool operator!=(const Chunk& s) const{
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;
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 ensureIndex();
void _markModified(); 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 modified(); bool modified();
skipping to change at line 256 skipping to change at line 254
} }
*/ */
class ChunkManager { class ChunkManager {
public: public:
ChunkManager( DBConfig * config , string ns , ShardKeyPattern patte rn , bool unique ); ChunkManager( DBConfig * config , string ns , ShardKeyPattern patte rn , bool unique );
virtual ~ChunkManager(); virtual ~ChunkManager();
string getns() const { return _ns; } string getns() const { return _ns; }
int numChunks(){ rwlock lk( _lock , false ); return _chunkMap.size( ); } int numChunks() const { rwlock lk( _lock , false ); return _chunkMa p.size(); }
bool hasShardKey( const BSONObj& obj ); bool hasShardKey( const BSONObj& obj );
ChunkPtr findChunk( const BSONObj& obj , bool retry = false ); ChunkPtr findChunk( const BSONObj& obj , bool retry = false );
ChunkPtr findChunkOnServer( const Shard& shard ) const; ChunkPtr findChunkOnServer( const Shard& shard ) const;
ShardKeyPattern& getShardKey(){ return _key; } ShardKeyPattern& getShardKey(){ return _key; }
const ShardKeyPattern& getShardKey() const { return _key; } const ShardKeyPattern& getShardKey() const { return _key; }
bool isUnique(){ return _unique; } bool isUnique(){ return _unique; }
void maybeChunkCollection(); void maybeChunkCollection();
/**
* makes sure the shard index is on all servers
*/
void ensureIndex();
void getShardsForQuery( set<Shard>& shards , const BSONObj& query ) ; void getShardsForQuery( set<Shard>& shards , const BSONObj& query ) ;
void getAllShards( set<Shard>& all ); void getAllShards( set<Shard>& all );
void getShardsForRange(set<Shard>& shards, const BSONObj& min, cons t BSONObj& max); // [min, max)
void save(); void save();
string toString() const; string toString() const;
operator string() const { return toString(); }
ShardChunkVersion getVersion( const Shard& shard ) const; ShardChunkVersion getVersion( const Shard& shard ) const;
ShardChunkVersion getVersion() const; ShardChunkVersion getVersion() const;
/** /**
* actually does a query on the server * actually does a query on the server
* doesn't look at any local data * doesn't look at any local data
*/ */
ShardChunkVersion getVersionOnConfigServer() const; ShardChunkVersion getVersionOnConfigServer() const;
/** /**
* this is just an increasing number of how many ChunkManagers we h ave so we know if something has been updated * this is just an increasing number of how many ChunkManagers we h ave so we know if something has been updated
*/ */
unsigned long long getSequenceNumber(){ unsigned long long getSequenceNumber(){
return _sequenceNumber; return _sequenceNumber;
} }
void getInfo( BSONObjBuilder& b ){
b.append( "key" , _key.key() );
b.appendBool( "unique" , _unique );
}
/** /**
* @param me - so i don't get deleted before i'm done * @param me - so i don't get deleted before i'm done
*/ */
void drop( ChunkManagerPtr me ); void drop( ChunkManagerPtr me );
void _printChunks() const; void _printChunks() const;
private: private:
void _reload(); void _reload();
skipping to change at line 329 skipping to change at line 326
map<string,unsigned long long> _maxMarkers; map<string,unsigned long long> _maxMarkers;
ChunkMap _chunkMap; ChunkMap _chunkMap;
ChunkRangeManager _chunkRanges; ChunkRangeManager _chunkRanges;
set<Shard> _shards; set<Shard> _shards;
unsigned long long _sequenceNumber; unsigned long long _sequenceNumber;
RWLock _lock; mutable RWLock _lock;
// This should only be called from Chunk after it has been migrated // This should only be called from Chunk after it has been migrated
void _migrationNotification(Chunk* c); void _migrationNotification(Chunk* c);
friend class Chunk; friend class Chunk;
friend class ChunkRangeManager; // only needed for CRM::assertValid () friend class ChunkRangeManager; // only needed for CRM::assertValid ()
static AtomicUInt NextSequenceNumber; static AtomicUInt NextSequenceNumber;
bool _isValid() const; bool _isValid() const;
}; };
 End of changes. 9 change blocks. 
12 lines changed or deleted 9 lines changed or added


 client.h   client.h 
skipping to change at line 230 skipping to change at line 230
string toString() const; string toString() const;
void gotHandshake( const BSONObj& o ); void gotHandshake( const BSONObj& o );
BSONObj getRemoteID() const { return _remoteId; } BSONObj getRemoteID() const { return _remoteId; }
BSONObj getHandshake() const { return _handshake; } BSONObj getHandshake() const { return _handshake; }
}; };
inline Client& cc() { inline Client& cc() {
return *currentClient.get(); Client * c = currentClient.get();
assert( c );
return *c;
} }
/* each thread which does db operations has a Client object in TLS. /* each thread which does db operations has a Client object in TLS.
call this when your thread starts. call this when your thread starts.
*/ */
inline void Client::initThread(const char *desc) { inline void Client::initThread(const char *desc) {
setThreadName(desc); setThreadName(desc);
assert( currentClient.get() == 0 ); assert( currentClient.get() == 0 );
currentClient.reset( new Client(desc) ); currentClient.reset( new Client(desc) );
mongo::lastError.initThread(); mongo::lastError.initThread();
 End of changes. 1 change blocks. 
1 lines changed or deleted 3 lines changed or added


 clientcursor.h   clientcursor.h 
skipping to change at line 339 skipping to change at line 339
} }
public: public:
void setDoingDeletes( bool doingDeletes ){ void setDoingDeletes( bool doingDeletes ){
_doingDeletes = doingDeletes; _doingDeletes = doingDeletes;
} }
static unsigned byLocSize(); // just for diagnostics static unsigned byLocSize(); // just for diagnostics
static void informAboutToDeleteBucket(const DiskLoc& b); static void informAboutToDeleteBucket(const DiskLoc& b);
static void aboutToDelete(const DiskLoc& dl); static void aboutToDelete(const DiskLoc& dl);
static void find( const string& ns , set<CursorId>& all );
}; };
class ClientCursorMonitor : public BackgroundJob { class ClientCursorMonitor : public BackgroundJob {
public: public:
void run(); void run();
string name() { return "ClientCursorMonitor"; } string name() { return "ClientCursorMonitor"; }
}; };
extern ClientCursorMonitor clientCursorMonitor; extern ClientCursorMonitor clientCursorMonitor;
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 cmdline.h   cmdline.h 
skipping to change at line 48 skipping to change at line 48
bool quota; // --quota bool quota; // --quota
int quotaFiles; // --quotaFiles int quotaFiles; // --quotaFiles
bool cpu; // --cpu show cpu time periodically bool cpu; // --cpu show cpu time periodically
long long oplogSize; // --oplogSize long long oplogSize; // --oplogSize
int defaultProfile; // --profile int defaultProfile; // --profile
int slowMS; // --time in ms that is "slow" int slowMS; // --time in ms that is "slow"
int pretouch; // --pretouch for replication application (e xperimental) int pretouch; // --pretouch for replication application (e xperimental)
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), quiet(false), notablescan(fal se), prealloc(true), smallfiles(false),
quota(false), quotaFiles(8), cpu(false), oplogSize(0), defaultP rofile(0), slowMS(100) 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 );
/** /**
* @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,
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 core.h   core.h 
skipping to change at line 389 skipping to change at line 389
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 double EARTH_RADIUS_MILES;
// 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
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));
 End of changes. 2 change blocks. 
0 lines changed or deleted 4 lines changed or added


 curop.h   curop.h 
skipping to change at line 27 skipping to change at line 27
#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 "db.h" #include "db.h"
namespace mongo { namespace mongo {
/* 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();
} }
}; };
/* Current operation (for the current Client). /* Current operation (for the current Client).
skipping to change at line 265 skipping to change at line 266
} }
else { else {
_progressMeter.finished(); _progressMeter.finished();
} }
_message = msg; _message = msg;
return _progressMeter; return _progressMeter;
} }
string getMessage() const { return _message; } string getMessage() const { return _message.toString(); }
ProgressMeter& getProgressMeter() { return _progressMeter; } ProgressMeter& getProgressMeter() { return _progressMeter; }
friend class Client; friend class Client;
}; };
/* 0 = ok /* 0 = ok
1 = kill current operation and reset this to 0 1 = kill current operation and reset this to 0
future: maybe use this as a "going away" thing on process terminatio n with a higher flag value future: maybe use this as a "going away" thing on process terminatio n with a higher flag value
*/ */
extern class KillCurrentOp { extern class KillCurrentOp {
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 d_logic.h   d_logic.h 
skipping to change at line 160 skipping to change at line 160
bool haveLocalShardingInfo( const string& ns ); bool haveLocalShardingInfo( const string& ns );
/** /**
* @return true if the current threads shard version is ok, or not in s harded version * @return true if the current threads shard version is ok, or not in s harded version
*/ */
bool shardVersionOk( const string& ns , string& errmsg ); bool shardVersionOk( const string& ns , string& errmsg );
/** /**
* @return true if we took care of the message and nothing else should be done * @return true if we took care of the message and nothing else should be done
*/ */
bool handlePossibleShardedMessage( Message &m, DbResponse &dbresponse ) ; bool handlePossibleShardedMessage( Message &m, DbResponse * dbresponse );
void logOpForSharding( const char * opstr , const char * ns , const BSO NObj& obj , BSONObj * patt ); void logOpForSharding( const char * opstr , const char * ns , const BSO NObj& obj , BSONObj * patt );
// ----------------- // -----------------
// --- writeback --- // --- writeback ---
// ----------------- // -----------------
/* queue a write back on a remote server for a failed write */ /* queue a write back on a remote server for a failed write */
void queueWriteBack( const string& remote , const BSONObj& o ); void queueWriteBack( const string& remote , const BSONObj& o );
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 dbclient.h   dbclient.h 
skipping to change at line 83 skipping to change at line 83
QueryOption_AllSupported = QueryOption_CursorTailable | QueryOption _SlaveOk | QueryOption_OplogReplay | QueryOption_NoCursorTimeout | QueryOpt ion_AwaitData | QueryOption_Exhaust QueryOption_AllSupported = QueryOption_CursorTailable | QueryOption _SlaveOk | QueryOption_OplogReplay | QueryOption_NoCursorTimeout | QueryOpt ion_AwaitData | QueryOption_Exhaust
}; };
enum UpdateOptions { enum UpdateOptions {
/** Upsert - that is, insert the item if no matching item is found. */ /** Upsert - that is, insert the item if no matching item is found. */
UpdateOption_Upsert = 1 << 0, UpdateOption_Upsert = 1 << 0,
/** Update multiple documents (if multiple documents match query ex pression). /** Update multiple documents (if multiple documents match query ex pression).
(Default is update a single document and stop.) */ (Default is update a single document and stop.) */
UpdateOption_Multi = 1 << 1 UpdateOption_Multi = 1 << 1,
/** flag from mongo saying this update went everywhere */
UpdateOption_Broadcast = 1 << 2
};
enum RemoveOptions {
/** only delete one option */
RemoveOption_JustOne = 1 << 0,
/** flag from mongo saying this update went everywhere */
RemoveOption_Broadcast = 1 << 1
}; };
class DBClientBase; class DBClientBase;
class ConnectionString { class ConnectionString {
public: public:
enum ConnectionType { MASTER , SET , SYNC }; enum ConnectionType { MASTER , SET , SYNC };
ConnectionString( const HostAndPort& server ){ ConnectionString( const HostAndPort& server ){
_type = MASTER; _type = MASTER;
skipping to change at line 333 skipping to change at line 344
virtual void remove( const string &ns , Query query, bool justOne = 0 ) = 0; virtual void remove( const string &ns , Query query, bool justOne = 0 ) = 0;
virtual void update( const string &ns , Query query , BSONObj obj , bool upsert = 0 , bool multi = 0 ) = 0; virtual void update( const string &ns , Query query , BSONObj obj , bool upsert = 0 , bool multi = 0 ) = 0;
virtual ~DBClientInterface() { } virtual ~DBClientInterface() { }
/** /**
@return a single object that matches the query. if none do, the n the object is empty @return a single object that matches the query. if none do, the n the object is empty
@throws AssertionException @throws AssertionException
*/ */
virtual BSONObj findOne(const string &ns, Query query, const BSONOb j *fieldsToReturn = 0, int queryOptions = 0); virtual BSONObj findOne(const string &ns, const Query& query, const BSONObj *fieldsToReturn = 0, int queryOptions = 0);
}; };
/** /**
DB "commands" DB "commands"
Basically just invocations of connection.$cmd.findOne({...}); Basically just invocations of connection.$cmd.findOne({...});
*/ */
class DBClientWithCommands : public DBClientInterface { class DBClientWithCommands : public DBClientInterface {
set<string> _seenIndexes; set<string> _seenIndexes;
public: public:
skipping to change at line 575 skipping to change at line 586
b.append("0", parm1); b.append("0", parm1);
BSONObj args = b.done(); BSONObj args = b.done();
if ( !eval(dbname, jscode, info, retValue, &args) ) if ( !eval(dbname, jscode, info, retValue, &args) )
return false; return false;
ret = (NumType) retValue.number(); ret = (NumType) retValue.number();
return true; return true;
} }
/** /**
get a list of all the current databases get a list of all the current databases
uses the { listDatabases : 1 } command.
throws on error
*/ */
list<string> getDatabaseNames(); list<string> getDatabaseNames();
/** /**
get a list of all the current collections in db get a list of all the current collections in db
*/ */
list<string> getCollectionNames( const string& db ); list<string> getCollectionNames( const string& db );
bool exists( const string& ns ); bool exists( const string& ns );
skipping to change at line 726 skipping to change at line 739
virtual void killCursor( long long cursorID ) = 0; virtual void killCursor( long long cursorID ) = 0;
static int countCommas( const string& s ){ static int countCommas( const string& s ){
int n = 0; int n = 0;
for ( unsigned i=0; i<s.size(); i++ ) for ( unsigned i=0; i<s.size(); i++ )
if ( s[i] == ',' ) if ( s[i] == ',' )
n++; n++;
return n; return n;
} }
virtual bool callRead( Message& toSend , Message& response ) = 0;
// virtual bool callWrite( Message& toSend , Message& response ) =
0; // TODO: add this if needed
virtual void say( Message& toSend ) = 0;
}; // DBClientBase }; // DBClientBase
class DBClientPaired; class DBClientPaired;
class ConnectException : public UserException { class ConnectException : public UserException {
public: public:
ConnectException(string msg) : UserException(9000,msg) { } ConnectException(string msg) : UserException(9000,msg) { }
}; };
/** /**
skipping to change at line 831 skipping to change at line 849
string toString() { string toString() {
return serverAddress; return serverAddress;
} }
string getServerAddress() const { string getServerAddress() const {
return serverAddress; return serverAddress;
} }
virtual void killCursor( long long cursorID ); virtual void killCursor( long long cursorID );
virtual bool callRead( Message& toSend , Message& response ){
return call( toSend , response );
}
virtual void say( Message &toSend );
protected: protected:
friend class SyncClusterConnection; friend class SyncClusterConnection;
virtual void recv( Message& m ); virtual void recv( Message& m );
virtual bool call( Message &toSend, Message &response, bool assertO k = true ); virtual bool call( Message &toSend, Message &response, bool assertO k = true );
virtual void say( Message &toSend );
virtual void sayPiggyBack( Message &toSend ); virtual void sayPiggyBack( Message &toSend );
virtual void checkResponse( const char *data, int nReturned ); virtual void checkResponse( const char *data, int nReturned );
}; };
/** Use this class to connect to a replica pair of servers. The class will manage /** Use this class to connect to a replica pair of servers. The class will manage
checking for which server in a replica pair is master, and do failov er automatically. checking for which server in a replica pair is master, and do failov er automatically.
On a failover situation, expect at least one operation to return an error (throw On a failover situation, expect at least one operation to return an error (throw
an exception) before the failover is complete. Operations are no t retried. an exception) before the failover is complete. Operations are no t retried.
*/ */
skipping to change at line 884 skipping to change at line 907
*/ */
bool auth(const string &dbname, const string &username, const strin g &pwd, string& errmsg); bool auth(const string &dbname, const string &username, const strin g &pwd, string& errmsg);
/** throws userassertion "no master found" */ /** throws userassertion "no master found" */
virtual virtual
auto_ptr<DBClientCursor> query(const string &ns, Query query, int n ToReturn = 0, int nToSkip = 0, auto_ptr<DBClientCursor> query(const string &ns, Query query, int n ToReturn = 0, int nToSkip = 0,
const BSONObj *fieldsToReturn = 0, i nt queryOptions = 0 , int batchSize = 0 ); const BSONObj *fieldsToReturn = 0, i nt queryOptions = 0 , int batchSize = 0 );
/** throws userassertion "no master found" */ /** throws userassertion "no master found" */
virtual virtual
BSONObj findOne(const string &ns, Query query, const BSONObj *field sToReturn = 0, int queryOptions = 0); BSONObj findOne(const string &ns, const Query& query, const BSONObj *fieldsToReturn = 0, int queryOptions = 0);
/** insert */ /** insert */
virtual void insert( const string &ns , BSONObj obj ) { virtual void insert( const string &ns , BSONObj obj ) {
checkMaster().insert(ns, obj); checkMaster().insert(ns, obj);
} }
/** insert multiple objects. Note that single object insert is asy nchronous, so this version /** insert multiple objects. Note that single object insert is asy nchronous, so this version
is only nominally faster and not worth a special effort to try to use. */ is only nominally faster and not worth a special effort to try to use. */
virtual void insert( const string &ns, const vector< BSONObj >& v ) { virtual void insert( const string &ns, const vector< BSONObj >& v ) {
checkMaster().insert(ns, v); checkMaster().insert(ns, v);
skipping to change at line 932 skipping to change at line 955
DBClientConnection& masterConn(); DBClientConnection& masterConn();
DBClientConnection& slaveConn(); DBClientConnection& slaveConn();
/* TODO - not yet implemented. mongos may need these. */ /* TODO - not yet implemented. mongos may need these. */
virtual bool call( Message &toSend, Message &response, bool assertO k=true ) { assert(false); return false; } virtual bool call( Message &toSend, Message &response, bool assertO k=true ) { assert(false); return false; }
virtual void say( Message &toSend ) { assert(false); } virtual void say( Message &toSend ) { assert(false); }
virtual void sayPiggyBack( Message &toSend ) { assert(false); } virtual void sayPiggyBack( Message &toSend ) { assert(false); }
virtual void checkResponse( const char *data, int nReturned ) { ass ert(false); } virtual void checkResponse( const char *data, int nReturned ) { ass ert(false); }
virtual bool callRead( Message& toSend , Message& response ){
return call( toSend , response );
}
bool isFailed() const { bool isFailed() const {
// TODO: this really should check isFailed on current master as well // TODO: this really should check isFailed on current master as well
return master < Left; return master < Left;
} }
}; };
/** pings server to check if it's up /** pings server to check if it's up
*/ */
bool serverAlive( const string &uri ); bool serverAlive( const string &uri );
 End of changes. 8 change blocks. 
4 lines changed or deleted 32 lines changed or added


 dbclientcursor.h   dbclientcursor.h 
skipping to change at line 41 skipping to change at line 41
class DBClientCursor : boost::noncopyable { class DBClientCursor : boost::noncopyable {
public: public:
/** If true, safe to call next(). Requests more from server if necessary. */ /** If true, safe to call next(). Requests more from server if necessary. */
bool more(); bool more();
/** If true, there is more in our local buffers to be fetched via n ext(). Returns /** If true, there is more in our local buffers to be fetched via n ext(). Returns
false when a getMore request back to server would be required. You can use this false when a getMore request back to server would be required. You can use this
if you want to exhaust whatever data has been fetched to the cl ient already but if you want to exhaust whatever data has been fetched to the cl ient already but
then perhaps stop. then perhaps stop.
*/ */
bool moreInCurrentBatch() { _assertIfNull(); return !_putBack.empty int objsLeftInBatch() const { _assertIfNull(); return _putBack.size
() || pos < nReturned; } () + nReturned - pos; }
bool moreInCurrentBatch() { return objsLeftInBatch() > 0; }
/** next /** next
@return next object in the result cursor. @return next object in the result cursor.
on an error at the remote server, you will get back: on an error at the remote server, you will get back:
{ $err: <string> } { $err: <string> }
if you do not want to handle that yourself, call nextSafe(). if you do not want to handle that yourself, call nextSafe().
*/ */
BSONObj next(); BSONObj next();
/** /**
skipping to change at line 100 skipping to change at line 101
available from the dbclientcursor. available from the dbclientcursor.
*/ */
bool isDead() const { bool isDead() const {
return !this || cursorId == 0; return !this || cursorId == 0;
} }
bool tailable() const { bool tailable() const {
return (opts & QueryOption_CursorTailable) != 0; return (opts & QueryOption_CursorTailable) != 0;
} }
/** see QueryResult::ResultFlagType (db/dbmessage.h) for flag value s /** see ResultFlagType (constants.h) for flag values
mostly these flags are for internal purposes - mostly these flags are for internal purposes -
ResultFlag_ErrSet is the possible exception to that ResultFlag_ErrSet is the possible exception to that
*/ */
bool hasResultFlag( int flag ){ bool hasResultFlag( int flag ){
_assertIfNull(); _assertIfNull();
return (resultFlags & flag) != 0; return (resultFlags & flag) != 0;
} }
DBClientCursor( DBConnector *_connector, const string &_ns, BSONObj _query, int _nToReturn, DBClientCursor( DBConnector *_connector, const string &_ns, BSONObj _query, int _nToReturn,
int _nToSkip, const BSONObj *_fieldsToReturn, int q ueryOptions , int bs ) : int _nToSkip, const BSONObj *_fieldsToReturn, int q ueryOptions , int bs ) :
skipping to change at line 182 skipping to change at line 183
int nReturned; int nReturned;
int pos; int pos;
const char *data; const char *data;
void dataReceived(); void dataReceived();
void requestMore(); void requestMore();
void exhaustReceiveMore(); // for exhaust void exhaustReceiveMore(); // for exhaust
bool _ownCursor; // see decouple() bool _ownCursor; // see decouple()
string _scopedHost; string _scopedHost;
// Don't call from a virtual function // Don't call from a virtual function
void _assertIfNull() { uassert(13348, "connection died", this); } void _assertIfNull() const { uassert(13348, "connection died", this ); }
}; };
/** iterate over objects in current batch only - will not cause a netwo rk call /** iterate over objects in current batch only - will not cause a netwo rk call
*/ */
class DBClientCursorBatchIterator { class DBClientCursorBatchIterator {
public: public:
DBClientCursorBatchIterator( DBClientCursor &c ) : _c( c ), _n() {} DBClientCursorBatchIterator( DBClientCursor &c ) : _c( c ), _n() {}
bool moreInCurrentBatch() { return _c.moreInCurrentBatch(); } bool moreInCurrentBatch() { return _c.moreInCurrentBatch(); }
BSONObj nextSafe() { BSONObj nextSafe() {
massert( 13383, "BatchIterator empty", moreInCurrentBatch() ); massert( 13383, "BatchIterator empty", moreInCurrentBatch() );
 End of changes. 3 change blocks. 
4 lines changed or deleted 5 lines changed or added


 dbhelpers.h   dbhelpers.h 
// dbhelpers.h /* @file dbhelpers.h
db helpers are helper functions and classes that let us easily manipulat
e the local
database instance in-proc.
*/
/** /**
* Copyright (C) 2008 10gen Inc. * Copyright (C) 2008 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3 , * it under the terms of the GNU Affero General Public License, version 3 ,
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* 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/>.
*/ */
/* db helpers are helper functions and classes that let us easily manipulat
e the local
database instance.
*/
#pragma once #pragma once
#include "../pch.h" #include "../pch.h"
#include "client.h" #include "client.h"
#include "db.h" #include "db.h"
namespace mongo { namespace mongo {
const BSONObj reverseNaturalObj = BSON( "$natural" << -1 ); const BSONObj reverseNaturalObj = BSON( "$natural" << -1 );
skipping to change at line 118 skipping to change at line 118
static void upsert( const string& ns , const BSONObj& o ); static void upsert( const string& ns , const BSONObj& o );
/** You do not need to set the database before calling. /** You do not need to set the database before calling.
@return true if collection is empty. @return true if collection is empty.
*/ */
static bool isEmpty(const char *ns); static bool isEmpty(const char *ns);
// TODO: this should be somewhere else probably // TODO: this should be somewhere else probably
static BSONObj toKeyFormat( const BSONObj& o , BSONObj& key ); static BSONObj toKeyFormat( const BSONObj& o , BSONObj& key );
static long long removeRange( const string& ns , const BSONObj& min class RemoveCallback {
, const BSONObj& max , bool yield = false , bool maxInclusive = false ); public:
virtual ~RemoveCallback(){}
virtual void goingToDelete( const BSONObj& o ) = 0;
};
/* removeRange: operation is oplog'd */
static long long removeRange( const string& ns , const BSONObj& min
, const BSONObj& max , bool yield = false , bool maxInclusive = false , Re
moveCallback * callback = 0 );
/* Remove all objects from a collection. /* Remove all objects from a collection.
You do not need to set the database before calling. You do not need to set the database before calling.
*/ */
static void emptyCollection(const char *ns); static void emptyCollection(const char *ns);
}; };
class Database; class Database;
 End of changes. 3 change blocks. 
8 lines changed or deleted 15 lines changed or added


 dbmessage.h   dbmessage.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 Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "diskloc.h" #include "diskloc.h"
#include "jsobj.h" #include "jsobj.h"
#include "namespace.h" #include "namespace.h"
#include "../util/message.h" #include "../util/message.h"
#include "../client/constants.h"
namespace mongo { namespace mongo {
/* db response format /* db response format
Query or GetMore: // see struct QueryResult Query or GetMore: // see struct QueryResult
int resultFlags; int resultFlags;
int64 cursorID; int64 cursorID;
int startingFrom; int startingFrom;
int nReturned; int nReturned;
list of marshalled JSObjects; list of marshalled JSObjects;
*/ */
extern bool objcheck; extern bool objcheck;
#pragma pack(1) #pragma pack(1)
struct QueryResult : public MsgData { struct QueryResult : public MsgData {
enum ResultFlagType {
/* returned, with zero results, when getMore is called but the
cursor id
is not valid at the server. */
ResultFlag_CursorNotFound = 1,
/* { $err : ... } is being returned */
ResultFlag_ErrSet = 2,
/* Have to update config from the server, usually $err is also
set */
ResultFlag_ShardConfigStale = 4,
/* for backward compatability: this let's us know the server su
pports
the QueryOption_AwaitData option. if it doesn't, a repl slav
e client should sleep
a little between getMore's.
*/
ResultFlag_AwaitCapable = 8
};
long long cursorId; long long cursorId;
int startingFrom; int startingFrom;
int nReturned; int nReturned;
const char *data() { const char *data() {
return (char *) (((int *)&nReturned)+1); return (char *) (((int *)&nReturned)+1);
} }
int resultFlags() { int resultFlags() {
return dataAsInt(); return dataAsInt();
} }
int& _resultFlags() { int& _resultFlags() {
skipping to change at line 227 skipping to change at line 210
namespace mongo { namespace mongo {
inline void replyToQuery(int queryResultFlags, inline void replyToQuery(int queryResultFlags,
AbstractMessagingPort* p, Message& requestMsg, AbstractMessagingPort* p, Message& requestMsg,
void *data, int size, void *data, int size,
int nReturned, int startingFrom = 0, int nReturned, int startingFrom = 0,
long long cursorId = 0 long long cursorId = 0
) { ) {
BufBuilder b(32768); BufBuilder b(32768);
b.skip(sizeof(QueryResult)); b.skip(sizeof(QueryResult));
b.append(data, size); b.appendBuf(data, size);
QueryResult *qr = (QueryResult *) b.buf(); QueryResult *qr = (QueryResult *) b.buf();
qr->_resultFlags() = queryResultFlags; qr->_resultFlags() = queryResultFlags;
qr->len = b.len(); qr->len = b.len();
qr->setOperation(opReply); qr->setOperation(opReply);
qr->cursorId = cursorId; qr->cursorId = cursorId;
qr->startingFrom = startingFrom; qr->startingFrom = startingFrom;
qr->nReturned = nReturned; qr->nReturned = nReturned;
b.decouple(); b.decouple();
Message resp(qr, true); Message resp(qr, true);
p->reply(requestMsg, resp, requestMsg.header()->id); p->reply(requestMsg, resp, requestMsg.header()->id);
skipping to change at line 262 skipping to change at line 245
{ {
replyToQuery(queryResultFlags, replyToQuery(queryResultFlags,
p, requestMsg, p, requestMsg,
(void *) responseObj.objdata(), responseObj.objsize(), 1); (void *) responseObj.objdata(), responseObj.objsize(), 1);
} }
/* helper to do a reply using a DbResponse object */ /* helper to do a reply using a DbResponse object */
inline void replyToQuery(int queryResultFlags, Message &m, DbResponse & dbresponse, BSONObj obj) { inline void replyToQuery(int queryResultFlags, Message &m, DbResponse & dbresponse, BSONObj obj) {
BufBuilder b; BufBuilder b;
b.skip(sizeof(QueryResult)); b.skip(sizeof(QueryResult));
b.append((void*) obj.objdata(), obj.objsize()); b.appendBuf((void*) obj.objdata(), obj.objsize());
QueryResult* msgdata = (QueryResult *) b.buf(); QueryResult* msgdata = (QueryResult *) b.buf();
b.decouple(); b.decouple();
QueryResult *qr = msgdata; QueryResult *qr = msgdata;
qr->_resultFlags() = queryResultFlags; qr->_resultFlags() = queryResultFlags;
qr->len = b.len(); qr->len = b.len();
qr->setOperation(opReply); qr->setOperation(opReply);
qr->cursorId = 0; qr->cursorId = 0;
qr->startingFrom = 0; qr->startingFrom = 0;
qr->nReturned = 1; qr->nReturned = 1;
Message *resp = new Message(); Message *resp = new Message();
resp->setData(msgdata, true); // transport will free resp->setData(msgdata, true); // transport will free
dbresponse.response = resp; dbresponse.response = resp;
dbresponse.responseTo = m.header()->id; dbresponse.responseTo = m.header()->id;
} }
string debugString( Message& m );
} // namespace mongo } // namespace mongo
 End of changes. 5 change blocks. 
24 lines changed or deleted 5 lines changed or added


 diskloc.h   diskloc.h 
skipping to change at line 88 skipping to change at line 88
return fileNo != -2; return fileNo != -2;
} }
string toString() const { string toString() const {
if ( isNull() ) if ( isNull() )
return "null"; return "null";
stringstream ss; stringstream ss;
ss << hex << fileNo << ':' << ofs; ss << hex << fileNo << ':' << ofs;
return ss.str(); return ss.str();
} }
operator string() const { return toString(); }
BSONObj toBSONObj() const { BSONObj toBSONObj() const {
return BSON( "file" << fileNo << "offset" << ofs ); return BSON( "file" << fileNo << "offset" << ofs );
} }
int& GETOFS() { int& GETOFS() {
return ofs; return ofs;
} }
int getOfs() const { int getOfs() const {
return ofs; return ofs;
 End of changes. 1 change blocks. 
1 lines changed or deleted 0 lines changed or added


 distlock.h   distlock.h 
skipping to change at line 36 skipping to change at line 36
#include "syncclusterconnection.h" #include "syncclusterconnection.h"
namespace mongo { namespace mongo {
class DistributedLock { class DistributedLock {
public: public:
/** /**
* @param takeoverMinutes how long before we steal lock in minutes * @param takeoverMinutes how long before we steal lock in minutes
*/ */
DistributedLock( const ConnectionString& conn , const string& name , int takeoverMinutes = 10 ); DistributedLock( const ConnectionString& conn , const string& name , unsigned takeoverMinutes = 10 );
int getState(){ int getState(){
return _state.get(); return _state.get();
} }
bool isLocked(){ bool isLocked(){
return _state.get() != 0; return _state.get() != 0;
} }
bool lock_try( string why , BSONObj * other = 0 ); bool lock_try( string why , BSONObj * other = 0 );
void unlock(); void unlock();
private: private:
ConnectionString _conn; ConnectionString _conn;
string _name; string _name;
int _takeoverMinutes; unsigned _takeoverMinutes;
string _ns; string _ns;
BSONObj _id; BSONObj _id;
ThreadLocalValue<int> _state; ThreadLocalValue<int> _state;
}; };
class dist_lock_try { class dist_lock_try {
public: public:
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 embedded_builder.h   embedded_builder.h 
skipping to change at line 53 skipping to change at line 53
addBuilder( next ); addBuilder( next );
} }
} }
void appendAs( const BSONElement &e, string name ) { void appendAs( const BSONElement &e, string name ) {
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.c_str() ); 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.c_str() );
} }
void done() { void done() {
while( ! _builderStorage.empty() ) while( ! _builderStorage.empty() )
popBuilder(); popBuilder();
} }
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 file_allocator.h   file_allocator.h 
skipping to change at line 138 skipping to change at line 138
ss << "failure creating new datafile; lseek failed for fd " << fd << " with errno: " << errnoWithDescription(); ss << "failure creating new datafile; lseek failed for fd " << fd << " with errno: " << errnoWithDescription();
massert( 10440 , ss.str(), filelen == 0 ); massert( 10440 , ss.str(), filelen == 0 );
} }
// Check for end of disk. // Check for end of disk.
massert( 10441 , "Unable to allocate file of desired size" , massert( 10441 , "Unable to allocate file of desired size" ,
size - 1 == lseek(fd, size - 1, SEEK_SET) ); size - 1 == lseek(fd, size - 1, SEEK_SET) );
massert( 10442 , "Unable to allocate file of desired size" , massert( 10442 , "Unable to allocate file of desired size" ,
1 == write(fd, "", 1) ); 1 == write(fd, "", 1) );
lseek(fd, 0, SEEK_SET); lseek(fd, 0, SEEK_SET);
long z = 256 * 1024; const long z = 256 * 1024;
char buf[z]; const boost::scoped_array<char> buf_holder (new char[z]);
char* buf = buf_holder.get();
memset(buf, 0, z); memset(buf, 0, z);
long left = size; long left = size;
while ( left > 0 ) { while ( left > 0 ) {
long towrite = left; long towrite = left;
if ( towrite > z ) if ( towrite > z )
towrite = z; towrite = z;
int written = write( fd , buf , towrite ); int written = write( fd , buf , towrite );
massert( 10443 , errnoWithPrefix("write failed" ), writ ten > 0 ); massert( 10443 , errnoWithPrefix("write failed" ), writ ten > 0 );
left -= written; left -= written;
 End of changes. 1 change blocks. 
2 lines changed or deleted 3 lines changed or added


 goodies.h   goodies.h 
skipping to change at line 602 skipping to change at line 602
ThreadSafeString( const ThreadSafeString& other ) ThreadSafeString( const ThreadSafeString& other )
: _size( other._size ) , _buf( new char[_size] ){ : _size( other._size ) , _buf( new char[_size] ){
strncpy( _buf , other._buf , _size ); strncpy( _buf , other._buf , _size );
} }
~ThreadSafeString(){ ~ThreadSafeString(){
delete[] _buf; delete[] _buf;
_buf = 0; _buf = 0;
} }
operator string() const { string toString() const {
string s = _buf; string s = _buf;
return s; return s;
} }
ThreadSafeString& operator=( const char * str ){ ThreadSafeString& operator=( const char * str ){
size_t s = strlen(str); size_t s = strlen(str);
if ( s >= _size - 2 ) if ( s >= _size - 2 )
s = _size - 2; s = _size - 2;
strncpy( _buf , str , s ); strncpy( _buf , str , s );
_buf[s] = 0; _buf[s] = 0;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 hostandport.h   hostandport.h 
skipping to change at line 52 skipping to change at line 52
: _host( sock.getAddr() ) , _port( sock.getPort() ){ : _host( sock.getAddr() ) , _port( sock.getPort() ){
} }
static HostAndPort me() { static HostAndPort me() {
return HostAndPort("localhost", cmdLine.port); return HostAndPort("localhost", cmdLine.port);
} }
/* uses real hostname instead of localhost */ /* uses real hostname instead of localhost */
static HostAndPort Me(); static HostAndPort Me();
bool operator<(const HostAndPort& r) const { return _host < r._host bool operator<(const HostAndPort& r) const {
|| (_host==r._host&&_port<r._port); } if( _host < r._host )
return true;
if( _host == r._host )
return port() < r.port();
return false;
}
bool operator==(const HostAndPort& r) const {
return _host == r._host && port() == r.port();
}
/* returns true if the host/port combo identifies this process inst ance. */ /* returns true if the host/port combo identifies this process inst ance. */
bool isSelf() const; bool isSelf() const;
bool isLocalHost() const; bool isLocalHost() const;
// @returns host:port // @returns host:port
string toString() const; string toString() const;
operator string() const { return toString(); } operator string() const { return toString(); }
string host() const { return _host; } string host() const { return _host; }
int port() const { return _port >= 0 ? _port : cmdLine.port; } int port() const { return _port >= 0 ? _port : CmdLine::DefaultDBPo rt; }
private: private:
// invariant (except full obj assignment): // invariant (except full obj assignment):
string _host; string _host;
int _port; // -1 indicates unspecified int _port; // -1 indicates unspecified
}; };
/** returns true if strings seem to be the same hostname. /** returns true if strings seem to be the same hostname.
"nyc1" and "nyc1.acme.com" are treated as the same. "nyc1" and "nyc1.acme.com" are treated as the same.
in fact "nyc1.foo.com" and "nyc1.acme.com" are treated the same - in fact "nyc1.foo.com" and "nyc1.acme.com" are treated the same -
 End of changes. 2 change blocks. 
3 lines changed or deleted 12 lines changed or added


 html.h   html.h 
skipping to change at line 54 skipping to change at line 54
} }
template <class T> template <class T>
inline string td(T x) { inline string td(T x) {
stringstream ss; stringstream ss;
ss << "<td>" << x << "</td>"; ss << "<td>" << x << "</td>";
return ss.str(); return ss.str();
} }
inline string td(string x) { inline string td(string x) {
return "<td>" + x + "</td>"; return "<td>" + x + "</td>";
} }
inline string th(string x) {
return "<th>" + x + "</th>";
}
inline string table(const char *headers[] = 0, bool border = true) { inline string table(const char *headers[] = 0, bool border = true) {
stringstream ss; stringstream ss;
ss << "\n<table " ss << "\n<table "
<< (border?"border=1 ":"") << (border?"border=1 ":"")
<< "cellpadding=2 cellspacing=0>\n"; << "cellpadding=2 cellspacing=0>\n";
if( headers ) { if( headers ) {
ss << "<tr>"; ss << "<tr>";
while( *headers ) { while( *headers ) {
ss << "<th>" << *headers << "</th>"; ss << "<th>" << *headers << "</th>";
 End of changes. 1 change blocks. 
0 lines changed or deleted 3 lines changed or added


 index.h   index.h 
skipping to change at line 134 skipping to change at line 134
return info.obj().getBoolField( "dropDups" ); return info.obj().getBoolField( "dropDups" );
} }
/* delete this index. does NOT clean up the system catalog /* delete this index. does NOT clean up the system catalog
(system.indexes or system.namespaces) -- only NamespaceIndex. (system.indexes or system.namespaces) -- only NamespaceIndex.
*/ */
void kill_idx(); void kill_idx();
const IndexSpec& getSpec() const; const IndexSpec& getSpec() const;
operator string() const { string toString() const {
return info.obj().toString(); return info.obj().toString();
} }
}; };
struct IndexChanges/*on an update*/ { struct IndexChanges/*on an update*/ {
BSONObjSetDefaultOrder oldkeys; BSONObjSetDefaultOrder oldkeys;
BSONObjSetDefaultOrder newkeys; BSONObjSetDefaultOrder newkeys;
vector<BSONObj*> removed; // these keys were removed as part of the change vector<BSONObj*> removed; // these keys were removed as part of the change
vector<BSONObj*> added; // these keys were added as part of the c hange vector<BSONObj*> added; // these keys were added as part of the c hange
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 instance.h   instance.h 
skipping to change at line 139 skipping to change at line 139
return "localhost"; // TODO: should this have the port? return "localhost"; // TODO: should this have the port?
} }
virtual bool call( Message &toSend, Message &response, bool assertO k=true ); virtual bool call( Message &toSend, Message &response, bool assertO k=true );
virtual void say( Message &toSend ); virtual void say( Message &toSend );
virtual void sayPiggyBack( Message &toSend ) { virtual void sayPiggyBack( Message &toSend ) {
// don't need to piggy back when connected locally // don't need to piggy back when connected locally
return say( toSend ); return say( toSend );
} }
virtual void killCursor( long long cursorID ); virtual void killCursor( long long cursorID );
virtual bool callRead( Message& toSend , Message& response ){
return call( toSend , response );
}
}; };
extern int lockFile; extern int lockFile;
void acquirePathLock(); void acquirePathLock();
void maybeCreatePidFile(); void maybeCreatePidFile();
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
0 lines changed or deleted 4 lines changed or added


 lasterror.h   lasterror.h 
skipping to change at line 31 skipping to change at line 31
namespace mongo { namespace mongo {
class BSONObjBuilder; class BSONObjBuilder;
class Message; class Message;
struct LastError { struct LastError {
int code; int code;
string msg; string msg;
enum UpdatedExistingType { NotUpdate, True, False } updatedExisting ; enum UpdatedExistingType { NotUpdate, True, False } updatedExisting ;
OID upsertedId; OID upsertedId;
OID writebackId;
long long nObjects; long long nObjects;
int nPrev; int nPrev;
bool valid; bool valid;
bool overridenById; bool overridenById;
bool disabled; bool disabled;
void writeback( OID& oid ){
reset( true );
writebackId = oid;
}
void raiseError(int _code , const char *_msg) { void raiseError(int _code , const char *_msg) {
reset( true ); reset( true );
code = _code; code = _code;
msg = _msg; msg = _msg;
} }
void recordUpdate( bool _updateObjects , long long _nObjects , OID _upsertedId ){ void recordUpdate( bool _updateObjects , long long _nObjects , OID _upsertedId ){
reset( true ); reset( true );
nObjects = _nObjects; nObjects = _nObjects;
updatedExisting = _updateObjects ? True : False; updatedExisting = _updateObjects ? True : False;
if ( _upsertedId.isSet() ) if ( _upsertedId.isSet() )
skipping to change at line 66 skipping to change at line 71
} }
void reset( bool _valid = false ) { void reset( bool _valid = false ) {
code = 0; code = 0;
msg.clear(); msg.clear();
updatedExisting = NotUpdate; updatedExisting = NotUpdate;
nObjects = 0; nObjects = 0;
nPrev = 1; nPrev = 1;
valid = _valid; valid = _valid;
disabled = false; disabled = false;
upsertedId.clear(); upsertedId.clear();
writebackId.clear();
} }
void appendSelf( BSONObjBuilder &b ); void appendSelf( BSONObjBuilder &b );
static LastError noError; static LastError noError;
}; };
extern class LastErrorHolder { extern class LastErrorHolder {
public: public:
LastErrorHolder() : _id( 0 ) {} LastErrorHolder() : _id( 0 ) {}
LastError * get( bool create = false ); LastError * get( bool create = false );
 End of changes. 3 change blocks. 
0 lines changed or deleted 6 lines changed or added


 log.h   log.h 
skipping to change at line 60 skipping to change at line 60
public: public:
virtual ~LazyString() {} virtual ~LazyString() {}
virtual string val() const = 0; virtual string val() const = 0;
}; };
// Utility class for stringifying object only when val() called. // Utility class for stringifying object only when val() called.
template< class T > template< class T >
class LazyStringImpl : public LazyString { class LazyStringImpl : public LazyString {
public: public:
LazyStringImpl( const T &t ) : t_( t ) {} LazyStringImpl( const T &t ) : t_( t ) {}
virtual string val() const { return (string)t_; } virtual string val() const { return t_.toString(); }
private: private:
const T& t_; const T& t_;
}; };
class Tee { class Tee {
public: public:
virtual ~Tee(){} virtual ~Tee(){}
virtual void write(LogLevel level , const string& str) = 0; virtual void write(LogLevel level , const string& str) = 0;
}; };
class Nullstream { class Nullstream {
public: public:
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& ) {
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 153 skipping to change at line 156
} }
virtual void flush(Tee *t = 0) {} virtual void flush(Tee *t = 0) {}
}; };
extern Nullstream nullstream; extern Nullstream nullstream;
class Logstream : public Nullstream { class Logstream : public Nullstream {
static mongo::mutex mutex; static mongo::mutex mutex;
static int doneSetup; static int doneSetup;
stringstream ss; stringstream ss;
LogLevel logLevel; LogLevel logLevel;
static boost::scoped_ptr<ostream> stream;
static FILE* logfile; static FILE* logfile;
static boost::scoped_ptr<ostream> stream;
static vector<Tee*> globalTees;
public: public:
static void logLockless( const char * s ){
if ( doneSetup == 1717 ){
fwrite( s , strlen( s ) , 1 , logfile );
fflush( logfile );
}
else {
cout << s << endl;
}
}
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;
} }
void flush(Tee *t = 0) { void flush(Tee *t = 0) {
// this ensures things are sane // this ensures things are sane
if ( doneSetup == 1717 ) { if ( doneSetup == 1717 ) {
BufBuilder b(512); BufBuilder b(512);
time_t_to_String( time(0) , b.grow(20) ); time_t_to_String( time(0) , b.grow(20) );
b.append( ss.str() ); b.appendStr( ss.str() );
const char *s = b.buf(); const char *s = b.buf();
string threadName = getThreadName(); string threadName = getThreadName();
const char * type = logLevelToString(logLevel); const char * type = logLevelToString(logLevel);
StringBuilder sb; StringBuilder sb;
if (!threadName.empty()){ if (!threadName.empty()){
sb << "[" << threadName << "] "; sb << "[" << threadName << "] ";
} }
sb << type << ( type[0] ? ": " : "" ); sb << type << ( type[0] ? ": " : "" );
sb << s; sb << s;
string out = sb.str(); string out = sb.str();
scoped_lock lk(mutex); scoped_lock lk(mutex);
if( t ) t->write(logLevel,s); if( t ) t->write(logLevel,s);
for ( unsigned i=0; i<globalTees.size(); i++ )
globalTees[i]->write(logLevel,s);
#ifndef _WIN32 #ifndef _WIN32
//syslog( LOG_INFO , "%s" , cc ); //syslog( LOG_INFO , "%s" , cc );
#endif #endif
fwrite(out.data(), out.size(), 1, logfile); fwrite(out.data(), out.size(), 1, logfile);
fflush(logfile); fflush(logfile);
} }
_init(); _init();
} }
Nullstream& setLogLevel(LogLevel l){ 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<<(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 252 skipping to change at line 269
*this << "null"; *this << "null";
else else
*this << *t; *this << *t;
return *this; return *this;
} }
Logstream& prolog() { Logstream& prolog() {
return *this; return *this;
} }
void addGlobalTee( Tee * t ){
globalTees.push_back( t );
}
private: private:
static thread_specific_ptr<Logstream> tsp; static thread_specific_ptr<Logstream> tsp;
Logstream(){ Logstream(){
_init(); _init();
} }
void _init(){ void _init(){
ss.str(""); ss.str("");
logLevel = LL_INFO; logLevel = LL_INFO;
} }
public: public:
 End of changes. 9 change blocks. 
3 lines changed or deleted 24 lines changed or added


 matcher.h   matcher.h 
skipping to change at line 160 skipping to change at line 160
bool hasType( BSONObj::MatchType type ) const; bool hasType( BSONObj::MatchType type ) const;
string toString() const { string toString() const {
return jsobj.toString(); return jsobj.toString();
} }
void addOrConstraint( const shared_ptr< FieldRangeVector > &frv ) { void addOrConstraint( const shared_ptr< FieldRangeVector > &frv ) {
_orConstraints.push_back( frv ); _orConstraints.push_back( frv );
} }
void popOrClause() {
_orMatchers.pop_front();
}
bool sameCriteriaCount( const Matcher &other ) const; bool sameCriteriaCount( const Matcher &other ) const;
private: private:
// Only specify constrainIndexKey if matches() will be called with // Only specify constrainIndexKey if matches() will be called with
// index keys having empty string field names. // index keys having empty string field names.
Matcher( const Matcher &other, const BSONObj &constrainIndexKey ); Matcher( const Matcher &other, const BSONObj &constrainIndexKey );
void addBasic(const BSONElement &e, int c, bool isNot) { void addBasic(const BSONElement &e, int c, bool isNot) {
// TODO May want to selectively ignore these element types base d on op type. // TODO May want to selectively ignore these element types base d on op type.
if ( e.type() == MinKey || e.type() == MaxKey ) if ( e.type() == MinKey || e.type() == MaxKey )
skipping to change at line 222 skipping to change at line 226
public: public:
CoveredIndexMatcher(const BSONObj &pattern, const BSONObj &indexKey Pattern , bool alwaysUseRecord=false ); CoveredIndexMatcher(const BSONObj &pattern, const BSONObj &indexKey Pattern , bool alwaysUseRecord=false );
bool matches(const BSONObj &o){ return _docMatcher->matches( o ); } bool matches(const BSONObj &o){ return _docMatcher->matches( o ); }
bool matches(const BSONObj &key, const DiskLoc &recLoc , MatchDetai ls * details = 0 ); bool matches(const BSONObj &key, const DiskLoc &recLoc , MatchDetai ls * details = 0 );
bool matchesCurrent( Cursor * cursor , MatchDetails * details = 0 ) ; bool matchesCurrent( Cursor * cursor , MatchDetails * details = 0 ) ;
bool needRecord(){ return _needRecord; } bool needRecord(){ return _needRecord; }
Matcher& docMatcher() { return *_docMatcher; } Matcher& docMatcher() { return *_docMatcher; }
// once this is called, shouldn't use this matcher for matching any more // once this is called, shouldn't use this matcher for matching any more
void addOrConstraint( const shared_ptr< FieldRangeVector > &frv ) { void advanceOrClause( const shared_ptr< FieldRangeVector > &frv ) {
_docMatcher->addOrConstraint( frv ); _docMatcher->addOrConstraint( frv );
// TODO this is not an optimal optimization, since we could ski
p an entire
// or clause (if a match is impossible) between calls to advanc
eOrClause()
_docMatcher->popOrClause();
} }
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;
 End of changes. 3 change blocks. 
1 lines changed or deleted 10 lines changed or added


 misc.h   misc.h 
skipping to change at line 30 skipping to change at line 30
#pragma once #pragma once
#include <ctime> #include <ctime>
namespace mongo { namespace mongo {
using namespace std; using namespace std;
inline void time_t_to_String(time_t t, char *buf) { inline void time_t_to_String(time_t t, char *buf) {
#if defined(_WIN32) #if defined(_WIN32)
ctime_s(buf, 64, &t); ctime_s(buf, 32, &t);
#else #else
ctime_r(&t, buf); ctime_r(&t, buf);
#endif #endif
buf[24] = 0; // don't want the \n buf[24] = 0; // don't want the \n
} }
inline string time_t_to_String(time_t t = time(0) ){ inline string time_t_to_String(time_t t = time(0) ){
char buf[64]; char buf[64];
#if defined(_WIN32) #if defined(_WIN32)
ctime_s(buf, sizeof(buf), &t); ctime_s(buf, sizeof(buf), &t);
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 mockdbclient.h   mockdbclient.h 
skipping to change at line 29 skipping to change at line 29
#pragma once #pragma once
#include "../client/dbclient.h" #include "../client/dbclient.h"
#include "../db/commands.h" #include "../db/commands.h"
#include "../db/replpair.h" #include "../db/replpair.h"
class MockDBClientConnection : public DBClientConnection { class MockDBClientConnection : public DBClientConnection {
public: public:
MockDBClientConnection() : connect_() {} MockDBClientConnection() : connect_() {}
virtual virtual
BSONObj findOne(const string &ns, Query query, const BSONObj *fieldsToR eturn = 0, int queryOptions = 0) { BSONObj findOne(const string &ns, const Query& query, const BSONObj *fi eldsToReturn = 0, int queryOptions = 0) {
return one_; return one_;
} }
virtual virtual
bool connect(const string &serverHostname, string& errmsg) { bool connect(const string &serverHostname, string& errmsg) {
return connect_; return connect_;
} }
virtual virtual
bool isMaster(bool& isMaster, BSONObj *info=0) { bool isMaster(bool& isMaster, BSONObj *info=0) {
return isMaster_; return isMaster_;
} }
skipping to change at line 66 skipping to change at line 66
public: public:
struct ConnectionCallback { struct ConnectionCallback {
virtual ~ConnectionCallback() {} virtual ~ConnectionCallback() {}
virtual void beforeCommand() {} virtual void beforeCommand() {}
virtual void afterCommand() {} virtual void afterCommand() {}
}; };
DirectDBClientConnection( ReplPair *rp, ConnectionCallback *cc = 0 ) : DirectDBClientConnection( ReplPair *rp, ConnectionCallback *cc = 0 ) :
rp_( rp ), rp_( rp ),
cc_( cc ) { cc_( cc ) {
} }
virtual BSONObj findOne(const string &ns, Query query, const BSONObj *f virtual BSONObj findOne(const string &ns, const Query& query, const BSO
ieldsToReturn = 0, int queryOptions = 0) { NObj *fieldsToReturn = 0, int queryOptions = 0) {
BSONObj c = query.obj.copy();
if ( cc_ ) cc_->beforeCommand(); if ( cc_ ) cc_->beforeCommand();
SetGlobalReplPair s( rp_ ); SetGlobalReplPair s( rp_ );
BSONObjBuilder result; BSONObjBuilder result;
result.append( "ok", Command::runAgainstRegistered( "admin.$cmd", q uery.obj, result ) ? 1.0 : 0.0 ); result.append( "ok", Command::runAgainstRegistered( "admin.$cmd", c , result ) ? 1.0 : 0.0 );
if ( cc_ ) cc_->afterCommand(); if ( cc_ ) cc_->afterCommand();
return result.obj(); return result.obj();
} }
virtual bool connect( const string &serverHostname, string& errmsg ) { virtual bool connect( const string &serverHostname, string& errmsg ) {
return true; return true;
} }
private: private:
ReplPair *rp_; ReplPair *rp_;
ConnectionCallback *cc_; ConnectionCallback *cc_;
class SetGlobalReplPair { class SetGlobalReplPair {
 End of changes. 3 change blocks. 
4 lines changed or deleted 5 lines changed or added


 namespace.h   namespace.h 
skipping to change at line 142 skipping to change at line 142
perhaps this should move to the NamespaceString helper? perhaps this should move to the NamespaceString helper?
*/ */
string getSisterNS( const char * local ) { string getSisterNS( const char * local ) {
assert( local && local[0] != '.' ); assert( local && local[0] != '.' );
string old(buf); string old(buf);
if ( old.find( "." ) != string::npos ) if ( old.find( "." ) != string::npos )
old = old.substr( 0 , old.find( "." ) ); old = old.substr( 0 , old.find( "." ) );
return old + "." + local; return old + "." + local;
} }
string toString() const {
return (string)buf;
}
operator string() const { operator string() const {
return (string)buf; return (string)buf;
} }
char buf[MaxNsLen]; char buf[MaxNsLen];
}; };
#pragma pack() #pragma pack()
} // namespace mongo } // namespace mongo
skipping to change at line 253 skipping to change at line 257
DiskLoc deletedList[Buckets]; DiskLoc deletedList[Buckets];
long long datasize; long long datasize;
long long nrecords; long long nrecords;
int lastExtentSize; int lastExtentSize;
int nIndexes; int nIndexes;
private: private:
IndexDetails _indexes[NIndexesBase]; IndexDetails _indexes[NIndexesBase];
public: public:
int capped; int capped;
int max; // max # of objects for a capped table. int max; // max # of objects for a capped table. TODO: should this be 64 bit?
double paddingFactor; // 1.0 = no padding. double paddingFactor; // 1.0 = no padding.
int flags; int flags;
DiskLoc capExtent; DiskLoc capExtent;
DiskLoc capFirstNewRecord; DiskLoc capFirstNewRecord;
/* NamespaceDetails version. So we can do backward compatibility i n the future. /* NamespaceDetails version. So we can do backward compatibility i n the future.
See filever.h See filever.h
*/ */
unsigned short dataFileVersion; unsigned short dataFileVersion;
unsigned short indexFileVersion; unsigned short indexFileVersion;
skipping to change at line 282 skipping to change at line 286
/* when a background index build is in progress, we don't count the index in nIndexes until /* when a background index build is in progress, we don't count the index in nIndexes until
complete, yet need to still use it in _indexRecord() - thus we u se this function for that. complete, yet need to still use it in _indexRecord() - thus we u se this function for that.
*/ */
int nIndexesBeingBuilt() const { return nIndexes + backgroundIndexB uildInProgress; } int nIndexesBeingBuilt() const { return nIndexes + backgroundIndexB uildInProgress; }
/* NOTE: be careful with flags. are we manipulating them in read l ocks? if so, /* NOTE: be careful with flags. are we manipulating them in read l ocks? if so,
this isn't thread safe. TODO this isn't thread safe. TODO
*/ */
enum NamespaceFlags { enum NamespaceFlags {
Flag_HaveIdIndex = 1 << 0, // set when we have _id index (ONLY Flag_HaveIdIndex = 1 << 0 // set when we have _id index (ONLY i
if ensureIdIndex was called -- 0 if that has never been called) f ensureIdIndex was called -- 0 if that has never been called)
Flag_CappedDisallowDelete = 1 << 1 // set when deletes not allo
wed during capped table allocation.
}; };
IndexDetails& idx(int idxNo) { IndexDetails& idx(int idxNo) {
if( idxNo < NIndexesBase ) if( idxNo < NIndexesBase )
return _indexes[idxNo]; return _indexes[idxNo];
Extra *e = extra(); Extra *e = extra();
massert(13282, "missing Extra", e); massert(13282, "missing Extra", e);
int i = idxNo - NIndexesBase; int i = idxNo - NIndexesBase;
if( i >= NIndexesExtra ) { if( i >= NIndexesExtra ) {
e = e->next(this); e = e->next(this);
skipping to change at line 357 skipping to change at line 360
multiKeyIndexBits &= ~(((unsigned long long) 1) << i); multiKeyIndexBits &= ~(((unsigned long long) 1) << i);
} }
/* add a new index. does not add to system.indexes etc. - just to NamespaceDetails. /* add a new index. does not add to system.indexes etc. - just to NamespaceDetails.
caller must populate returned object. caller must populate returned object.
*/ */
IndexDetails& addIndex(const char *thisns, bool resetTransient=true ); IndexDetails& addIndex(const char *thisns, bool resetTransient=true );
void aboutToDeleteAnIndex() { flags &= ~Flag_HaveIdIndex; } void aboutToDeleteAnIndex() { flags &= ~Flag_HaveIdIndex; }
void cappedDisallowDelete() { flags |= Flag_CappedDisallowDelete; }
/* returns index of the first index in which the field is present. -1 if not present. */ /* returns index of the first index in which the field is present. -1 if not present. */
int fieldIsIndexed(const char *fieldName); int fieldIsIndexed(const char *fieldName);
void paddingFits() { void paddingFits() {
double x = paddingFactor - 0.01; double x = paddingFactor - 0.01;
if ( x >= 1.0 ) if ( x >= 1.0 )
paddingFactor = x; paddingFactor = x;
} }
void paddingTooSmall() { void paddingTooSmall() {
double x = paddingFactor + 0.6; double x = paddingFactor + 0.6;
skipping to change at line 437 skipping to change at line 438
void dumpDeleted(set<DiskLoc> *extents = 0); void dumpDeleted(set<DiskLoc> *extents = 0);
bool capLooped() const { return capped && capFirstNewRecord.isValid (); } bool capLooped() const { return capped && capFirstNewRecord.isValid (); }
// Start from firstExtent by default. // Start from firstExtent by default.
DiskLoc firstRecord( const DiskLoc &startExtent = DiskLoc() ) const ; DiskLoc firstRecord( const DiskLoc &startExtent = DiskLoc() ) const ;
// Start from lastExtent by default. // Start from lastExtent by default.
DiskLoc lastRecord( const DiskLoc &startExtent = DiskLoc() ) const; DiskLoc lastRecord( const DiskLoc &startExtent = DiskLoc() ) const;
bool inCapExtent( const DiskLoc &dl ) const; bool inCapExtent( const DiskLoc &dl ) const;
void checkMigrate(); void cappedCheckMigrate();
long long storageSize( int * numExtents = 0 ); long long storageSize( int * numExtents = 0 );
private: private:
bool cappedMayDelete() const { return !( flags & Flag_CappedDisallo /** This prevents deletion from a capped collection upon wrap aroun
wDelete ); } d -
so there will be no wrap around, just an exception. Used to be
used by the temp oplogs that were part of the cloneCollection i
mplementation.
*/
Extent *theCapExtent() const { return capExtent.ext(); } Extent *theCapExtent() const { return capExtent.ext(); }
void advanceCapExtent( const char *ns ); void advanceCapExtent( const char *ns );
void maybeComplain( const char *ns, int len ) const; void maybeComplain( const char *ns, int len ) const;
DiskLoc __stdAlloc(int len); DiskLoc __stdAlloc(int len);
DiskLoc __capAlloc(int len); DiskLoc __capAlloc(int len);
DiskLoc _alloc(const char *ns, int len); DiskLoc _alloc(const char *ns, int len);
DiskLoc cappedAlloc(const char *ns, int len); // capped collections
void compact(); // combine adjacent deleted records void compact(); // combine adjacent deleted records
DiskLoc &firstDeletedInCapExtent(); DiskLoc &firstDeletedInCapExtent();
bool nextIsInCapExtent( const DiskLoc &dl ) const; bool nextIsInCapExtent( const DiskLoc &dl ) const;
}; // NamespaceDetails }; // NamespaceDetails
#pragma pack() #pragma pack()
void cappedTruncateAfter(const char *n, DiskLoc);
/* NamespaceDetailsTransient /* NamespaceDetailsTransient
these are things we know / compute about a namespace that are transi ent -- things these are things we know / compute about a namespace that are transi ent -- things
we don't actually store in the .ns file. so mainly caching of frequ ently used we don't actually store in the .ns file. so mainly caching of frequ ently used
information. information.
CAUTION: Are you maintaining this properly on a collection drop()? A dropdatabase()? Be careful. CAUTION: Are you maintaining this properly on a collection drop()? A dropdatabase()? Be careful.
The current field "allIndexKeys" may have too many keys in it on such an occurrence; The current field "allIndexKeys" may have too many keys in it on such an occurrence;
as currently used that does not cause anything terrible to happen. as currently used that does not cause anything terrible to happen.
skipping to change at line 475 skipping to change at line 482
*/ */
class NamespaceDetailsTransient : boost::noncopyable { class NamespaceDetailsTransient : boost::noncopyable {
BOOST_STATIC_ASSERT( sizeof(NamespaceDetails) == 496 ); BOOST_STATIC_ASSERT( sizeof(NamespaceDetails) == 496 );
/* general -------------------------------------------------------- ----- */ /* general -------------------------------------------------------- ----- */
private: private:
string _ns; string _ns;
void reset(); void reset();
static std::map< string, shared_ptr< NamespaceDetailsTransient > > _map; static std::map< string, shared_ptr< NamespaceDetailsTransient > > _map;
public: public:
NamespaceDetailsTransient(const char *ns) : _ns(ns), _keysComputed( false), _qcWriteCount(), _cll_enabled() { } NamespaceDetailsTransient(const char *ns) : _ns(ns), _keysComputed( false), _qcWriteCount(){ }
/* _get() is not threadsafe -- see get_inlock() comments */ /* _get() is not threadsafe -- see get_inlock() comments */
static NamespaceDetailsTransient& _get(const char *ns); static NamespaceDetailsTransient& _get(const char *ns);
/* use get_w() when doing write operations */ /* use get_w() when doing write operations */
static NamespaceDetailsTransient& get_w(const char *ns) { static NamespaceDetailsTransient& get_w(const char *ns) {
DEV assertInWriteLock(); DEV assertInWriteLock();
return _get(ns); return _get(ns);
} }
void addedIndex() { reset(); } void addedIndex() { reset(); }
void deletedIndex() { reset(); } void deletedIndex() { reset(); }
/* Drop cached information on all namespaces beginning with the spe cified prefix. /* Drop cached information on all namespaces beginning with the spe cified prefix.
skipping to change at line 555 skipping to change at line 562
BSONObj indexForPattern( const QueryPattern &pattern ) { BSONObj indexForPattern( const QueryPattern &pattern ) {
return _qcCache[ pattern ].first; return _qcCache[ pattern ].first;
} }
long long nScannedForPattern( const QueryPattern &pattern ) { long long nScannedForPattern( const QueryPattern &pattern ) {
return _qcCache[ pattern ].second; return _qcCache[ pattern ].second;
} }
void registerIndexForPattern( const QueryPattern &pattern, const BS ONObj &indexKey, long long nScanned ) { void registerIndexForPattern( const QueryPattern &pattern, const BS ONObj &indexKey, long long nScanned ) {
_qcCache[ pattern ] = make_pair( indexKey, nScanned ); _qcCache[ pattern ] = make_pair( indexKey, nScanned );
} }
/* for collection-level logging -- see CmdLogCollection -----------
------ */
/* assumed to be in write lock for this */
private:
string _cll_ns; // "local.temp.oplog." + _ns;
bool _cll_enabled;
void cllDrop(); // drop _cll_ns
public:
string cllNS() const { return _cll_ns; }
bool cllEnabled() const { return _cll_enabled; }
void cllStart( int logSizeMb = 256 ); // begin collection level log
ging
void cllInvalidate();
bool cllValidateComplete();
}; /* NamespaceDetailsTransient */ }; /* NamespaceDetailsTransient */
inline NamespaceDetailsTransient& NamespaceDetailsTransient::_get(const char *ns) { inline NamespaceDetailsTransient& NamespaceDetailsTransient::_get(const char *ns) {
shared_ptr< NamespaceDetailsTransient > &t = _map[ ns ]; shared_ptr< NamespaceDetailsTransient > &t = _map[ ns ];
if ( t.get() == 0 ) if ( t.get() == 0 )
t.reset( new NamespaceDetailsTransient(ns) ); t.reset( new NamespaceDetailsTransient(ns) );
return *t; return *t;
} }
/* NamespaceIndex is the ".ns" file you see in the data directory. It is the "system catalog" /* NamespaceIndex is the ".ns" file you see in the data directory. It is the "system catalog"
skipping to change at line 614 skipping to change at line 608
if ( !ht ) if ( !ht )
return -1; return -1;
return ((char *) d) - (char *) ht->nodes; return ((char *) d) - (char *) ht->nodes;
}*/ }*/
NamespaceDetails* details(const char *ns) { NamespaceDetails* details(const char *ns) {
if ( !ht ) if ( !ht )
return 0; return 0;
Namespace n(ns); Namespace n(ns);
NamespaceDetails *d = ht->get(n); NamespaceDetails *d = ht->get(n);
if ( d ) if ( d && d->capped )
d->checkMigrate(); d->cappedCheckMigrate();
return d; return d;
} }
void kill_ns(const char *ns) { void kill_ns(const char *ns) {
if ( !ht ) if ( !ht )
return; return;
Namespace n(ns); Namespace n(ns);
ht->kill(n); ht->kill(n);
for( int i = 0; i<=1; i++ ) { for( int i = 0; i<=1; i++ ) {
 End of changes. 11 change blocks. 
28 lines changed or deleted 20 lines changed or added


 oid.h   oid.h 
skipping to change at line 85 skipping to change at line 85
/* /*
s.width( 16 ); s.width( 16 );
s << a; s << a;
s.width( 8 ); s.width( 8 );
s << b; s << b;
s << dec; s << dec;
*/ */
return s.str(); return s.str();
} }
string toString() const { return str(); }
static OID gen() { OID o; o.init(); return o; } static OID gen() { OID o; o.init(); return o; }
static unsigned staticMachine(){ return _machine; } static unsigned staticMachine(){ return _machine; }
/** /**
sets the contents to a new oid / randomized value sets the contents to a new oid / randomized value
*/ */
void init(); void init();
/** Set to the hex string value specified. */ /** Set to the hex string value specified. */
void init( string s ); void init( string s );
/** Set to the min/max OID that could be generated at given timesta mp. */ /** Set to the min/max OID that could be generated at given timesta mp. */
void init( Date_t date, bool max=false ); void init( Date_t date, bool max=false );
time_t asTimeT(); time_t asTimeT();
Date_t asDateT() { return asTimeT() * (long long)1000; } Date_t asDateT() { return asTimeT() * (long long)1000; }
bool isSet() const { return a || b; } bool isSet() const { return a || b; }
int compare( const OID& other ) const { return memcmp( data , other
.data , 12 ); }
bool operator<( const OID& other ) const { return compare( other )
< 0; }
}; };
#pragma pack() #pragma pack()
ostream& operator<<( ostream &s, const OID &o ); ostream& operator<<( ostream &s, const OID &o );
/** Formatting mode for generating JSON from BSON. /** Formatting mode for generating JSON from BSON.
See <http://mongodb.onconfluence.com/display/DOCS/Mongo+Extended+JS ON> See <http://mongodb.onconfluence.com/display/DOCS/Mongo+Extended+JS ON>
for details. for details.
*/ */
enum JsonStringFormat { enum JsonStringFormat {
 End of changes. 2 change blocks. 
0 lines changed or deleted 8 lines changed or added


 oplog.h   oplog.h 
skipping to change at line 38 skipping to change at line 38
#include "dbhelpers.h" #include "dbhelpers.h"
#include "query.h" #include "query.h"
#include "queryoptimizer.h" #include "queryoptimizer.h"
#include "../client/dbclient.h" #include "../client/dbclient.h"
#include "../util/optime.h" #include "../util/optime.h"
namespace mongo { namespace mongo {
void createOplog(); void createOplog();
void _logOpObjRS(const BSONObj& op);
/** Write operation to the log (local.oplog.$main) /** Write operation to the log (local.oplog.$main)
@param opstr @param opstr
"i" insert "i" insert
"u" update "u" update
"d" delete "d" delete
"c" db cmd "c" db cmd
"n" no-op "n" no-op
"db" declares presence of a database (ns is set to the db name + '. ') "db" declares presence of a database (ns is set to the db name + '. ')
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 optime.h   optime.h 
skipping to change at line 124 skipping to change at line 124
stringstream ss; stringstream ss;
ss << time_t_to_String_short(secs) << ':' << hex << i; ss << time_t_to_String_short(secs) << ':' << hex << i;
return ss.str(); return ss.str();
} }
string toString() const { string toString() const {
stringstream ss; stringstream ss;
ss << hex << secs << ':' << i; ss << hex << secs << ':' << i;
return ss.str(); return ss.str();
} }
operator string() const { return toString(); }
bool operator==(const OpTime& r) const { bool operator==(const OpTime& r) const {
return i == r.i && secs == r.secs; return i == r.i && secs == r.secs;
} }
bool operator!=(const OpTime& r) const { bool operator!=(const OpTime& r) const {
return !(*this == r); return !(*this == r);
} }
bool operator<(const OpTime& r) const { bool operator<(const OpTime& r) const {
if ( secs != r.secs ) if ( secs != r.secs )
return secs < r.secs; return secs < r.secs;
return i < r.i; return i < r.i;
} }
bool operator<=(const OpTime& r) const { bool operator<=(const OpTime& r) const {
return *this < r || *this == r; return *this < r || *this == r;
} }
bool operator>(const OpTime& r) const {
return !(*this <= r);
}
}; };
#pragma pack() #pragma pack()
} // namespace mongo } // namespace mongo
 End of changes. 2 change blocks. 
1 lines changed or deleted 4 lines changed or added


 parallel.h   parallel.h 
skipping to change at line 53 skipping to change at line 52
if ( _server < other._server ) if ( _server < other._server )
return true; return true;
if ( other._server > _server ) if ( other._server > _server )
return false; return false;
return _extra.woCompare( other._extra ) < 0; return _extra.woCompare( other._extra ) < 0;
} }
string toString() const { string toString() const {
StringBuilder ss; StringBuilder ss;
ss << "server:" << _server << " _extra:" << _extra << " _orderO bject:" << _orderObject; ss << "server:" << _server << " _extra:" << _extra.toString() < < " _orderObject:" << _orderObject.toString();
return ss.str(); return ss.str();
} }
operator string() const { operator string() const {
return toString(); return toString();
} }
string _server; string _server;
BSONObj _extra; BSONObj _extra;
BSONObj _orderObject; BSONObj _orderObject;
skipping to change at line 97 skipping to change at line 96
BSONObj explain( const string& server , BSONObj extraFilter = BSONO bj() ); BSONObj explain( const string& server , BSONObj extraFilter = BSONO bj() );
static BSONObj _concatFilter( const BSONObj& filter , const BSONObj & extraFilter ); static BSONObj _concatFilter( const BSONObj& filter , const BSONObj & extraFilter );
virtual void _explain( map< string,list<BSONObj> >& out ) = 0; virtual void _explain( map< string,list<BSONObj> >& out ) = 0;
string _ns; string _ns;
BSONObj _query; BSONObj _query;
int _options; int _options;
BSONObj _fields; BSONObj _fields;
int _batchSize;
bool _done; bool _done;
}; };
class FilteringClientCursor { class FilteringClientCursor {
public: public:
FilteringClientCursor( const BSONObj filter = BSONObj() ); FilteringClientCursor( const BSONObj filter = BSONObj() );
FilteringClientCursor( auto_ptr<DBClientCursor> cursor , const BSON Obj filter = BSONObj() ); FilteringClientCursor( auto_ptr<DBClientCursor> cursor , const BSON Obj filter = BSONObj() );
~FilteringClientCursor(); ~FilteringClientCursor();
 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 58 skipping to change at line 58
query expression to match by itself without ever checking the main object. query expression to match by itself without ever checking the main object.
*/ */
bool exactKeyMatch() const { return exactKeyMatch_; } bool exactKeyMatch() const { return exactKeyMatch_; }
/* If true, the startKey and endKey are unhelpful and the index ord er doesn't match the /* If true, the startKey and endKey are unhelpful and the index ord er doesn't match the
requested sort order */ requested sort order */
bool unhelpful() const { return unhelpful_; } bool unhelpful() const { return unhelpful_; }
int direction() const { return direction_; } int direction() const { return direction_; }
shared_ptr<Cursor> newCursor( const DiskLoc &startLoc = DiskLoc() , int numWanted=0 ) const; shared_ptr<Cursor> newCursor( const DiskLoc &startLoc = DiskLoc() , int numWanted=0 ) const;
shared_ptr<Cursor> newReverseCursor() const; shared_ptr<Cursor> newReverseCursor() const;
BSONObj indexKey() const; BSONObj indexKey() const;
bool willScanTable() const { return !index_ && fbs_.matchPossible() ; }
const char *ns() const { return fbs_.ns(); } const char *ns() const { return fbs_.ns(); }
NamespaceDetails *nsd() const { return d; } NamespaceDetails *nsd() const { return d; }
BSONObj originalQuery() const { return _originalQuery; } BSONObj originalQuery() const { return _originalQuery; }
BSONObj simplifiedQuery( const BSONObj& fields = BSONObj() ) const { return fbs_.simplifiedQuery( fields ); } BSONObj simplifiedQuery( const BSONObj& fields = BSONObj() ) const { return fbs_.simplifiedQuery( fields ); }
const FieldRange &range( const char *fieldName ) const { return fbs _.range( fieldName ); } const FieldRange &range( const char *fieldName ) const { return fbs _.range( fieldName ); }
void registerSelf( long long nScanned ) const; void registerSelf( long long nScanned ) const;
shared_ptr< FieldRangeVector > frv() const { return _frv; } shared_ptr< FieldRangeVector > frv() const { return _frv; }
private: private:
NamespaceDetails *d; NamespaceDetails *d;
int idxNo; int idxNo;
skipping to change at line 124 skipping to change at line 125
virtual void recoverFromYield() { massert( 13336, "yield not suppor ted", false ); } virtual void recoverFromYield() { massert( 13336, "yield not suppor ted", false ); }
/** @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->addOrConstraint( _orConstraint ); _matcher->advanceOrClause( _orConstraint );
_orConstraint.reset(); _orConstraint.reset();
} }
QueryOp *ret = _createChild(); QueryOp *ret = _createChild();
ret->_oldMatcher = _matcher; ret->_oldMatcher = _matcher;
return ret; return ret;
} }
bool complete() const { return _complete; } bool complete() const { return _complete; }
bool error() const { return _error; } bool error() const { return _error; }
bool stopRequested() const { return _stopRequested; } bool stopRequested() const { return _stopRequested; }
ExceptionInfo exception() const { return _exception; } ExceptionInfo exception() const { return _exception; }
skipping to change at line 278 skipping to change at line 279
shared_ptr< QueryOp > runOp( QueryOp &op ); shared_ptr< QueryOp > runOp( QueryOp &op );
template< class T > template< class T >
shared_ptr< T > runOp( T &op ) { shared_ptr< T > runOp( T &op ) {
return dynamic_pointer_cast< T >( runOp( static_cast< QueryOp& >( op ) ) ); return dynamic_pointer_cast< T >( runOp( static_cast< QueryOp& >( op ) ) );
} }
shared_ptr< QueryOp > runOpOnce( QueryOp &op ); shared_ptr< QueryOp > runOpOnce( QueryOp &op );
template< class T > template< class T >
shared_ptr< T > runOpOnce( T &op ) { shared_ptr< T > runOpOnce( T &op ) {
return dynamic_pointer_cast< T >( runOpOnce( static_cast< Query Op& >( op ) ) ); return dynamic_pointer_cast< T >( runOpOnce( static_cast< Query Op& >( op ) ) );
} }
bool mayRunMore() const { return _or ? !_fros.orFinished() : _i == 0; } bool mayRunMore() const { return _or ? ( !_tableScanned && !_fros.o rFinished() ) : _i == 0; }
BSONObj oldExplain() const { assertNotOr(); return _currentQps->exp lain(); } BSONObj oldExplain() const { assertNotOr(); return _currentQps->exp lain(); }
// just report this when only one query op // just report this when only one query op
bool usingPrerecordedPlan() const { bool usingPrerecordedPlan() const {
return !_or && _currentQps->usingPrerecordedPlan(); return !_or && _currentQps->usingPrerecordedPlan();
} }
void setBestGuessOnly() { _bestGuessOnly = true; } void setBestGuessOnly() { _bestGuessOnly = true; }
void mayYield( bool val ) { _mayYield = val; } void mayYield( bool val ) { _mayYield = val; }
private: private:
void assertNotOr() const { void assertNotOr() const {
massert( 13266, "not implemented for $or query", !_or ); massert( 13266, "not implemented for $or query", !_or );
skipping to change at line 301 skipping to change at line 302
const char * _ns; const char * _ns;
bool _or; bool _or;
BSONObj _query; BSONObj _query;
FieldRangeOrSet _fros; FieldRangeOrSet _fros;
auto_ptr< QueryPlanSet > _currentQps; auto_ptr< QueryPlanSet > _currentQps;
int _i; int _i;
bool _honorRecordedPlan; bool _honorRecordedPlan;
bool _bestGuessOnly; bool _bestGuessOnly;
BSONObj _hint; BSONObj _hint;
bool _mayYield; bool _mayYield;
bool _tableScanned;
}; };
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;
}; };
 End of changes. 4 change blocks. 
2 lines changed or deleted 4 lines changed or added


 queryutil.h   queryutil.h 
skipping to change at line 65 skipping to change at line 65
// 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 $ in:{$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
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() &&
min().woCompare( max(), false ) == 0 && min().woCompare( max(), false ) == 0 &&
maxInclusive() && maxInclusive() &&
minInclusive(); minInclusive();
skipping to change at line 94 skipping to change at line 96
} }
return true; return true;
} }
bool nontrivial() const { bool nontrivial() const {
return return
! empty() && ! empty() &&
( minKey.firstElement().woCompare( min(), false ) != 0 || ( minKey.firstElement().woCompare( min(), false ) != 0 ||
maxKey.firstElement().woCompare( max(), false ) != 0 ); maxKey.firstElement().woCompare( max(), false ) != 0 );
} }
bool empty() const { return _intervals.empty(); } bool empty() const { return _intervals.empty(); }
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;
} }
} }
// constructs a range which is the reverse of the current one // constructs a range which is the reverse of the current one
// note - the resulting intervals may not be strictValid() // note - the resulting intervals may not be strictValid()
skipping to change at line 237 skipping to change at line 240
BSONObj simplifiedQuery( const BSONObj &fields = BSONObj() ) const; BSONObj simplifiedQuery( const BSONObj &fields = BSONObj() ) const;
bool matchPossible() const { bool matchPossible() const {
for( map< string, FieldRange >::const_iterator i = _ranges.begi n(); i != _ranges.end(); ++i ) for( map< string, FieldRange >::const_iterator i = _ranges.begi n(); i != _ranges.end(); ++i )
if ( i->second.empty() ) if ( i->second.empty() )
return false; return false;
return true; return true;
} }
QueryPattern pattern( const BSONObj &sort = BSONObj() ) const; QueryPattern pattern( const BSONObj &sort = BSONObj() ) const;
string getSpecial() const; string getSpecial() const;
const FieldRangeSet &operator-=( const FieldRangeSet &other ) { const FieldRangeSet &operator-=( const FieldRangeSet &other ) {
int nUnincluded = 0;
string unincludedKey;
map< string, FieldRange >::iterator i = _ranges.begin(); map< string, FieldRange >::iterator i = _ranges.begin();
map< string, FieldRange >::const_iterator j = other._ranges.beg in(); map< string, FieldRange >::const_iterator j = other._ranges.beg in();
while( i != _ranges.end() && j != other._ranges.end() ) { while( nUnincluded < 2 && i != _ranges.end() && j != other._ran ges.end() ) {
int cmp = i->first.compare( j->first ); int cmp = i->first.compare( j->first );
if ( cmp == 0 ) { if ( cmp == 0 ) {
i->second -= j->second; if ( i->second <= j->second ) {
// nothing
} else {
++nUnincluded;
unincludedKey = i->first;
}
++i; ++i;
++j; ++j;
} else if ( cmp < 0 ) { } else if ( cmp < 0 ) {
++i; ++i;
} else { } else {
++j; // other has a bound we don't, nothing can be done
return *this;
} }
} }
if ( j != other._ranges.end() ) {
// other has a bound we don't, nothing can be done
return *this;
}
if ( nUnincluded > 1 ) {
return *this;
}
if ( nUnincluded == 0 ) {
makeEmpty();
return *this;
}
// nUnincluded == 1
_ranges[ unincludedKey ] -= other._ranges[ unincludedKey ];
appendQueries( other ); appendQueries( other );
return *this; return *this;
} }
const FieldRangeSet &operator&=( const FieldRangeSet &other ) { const FieldRangeSet &operator&=( const FieldRangeSet &other ) {
map< string, FieldRange >::iterator i = _ranges.begin(); map< string, FieldRange >::iterator i = _ranges.begin();
map< string, FieldRange >::const_iterator j = other._ranges.beg in(); map< string, FieldRange >::const_iterator j = other._ranges.beg in();
while( i != _ranges.end() && j != other._ranges.end() ) { while( i != _ranges.end() && j != other._ranges.end() ) {
int cmp = i->first.compare( j->first ); int cmp = i->first.compare( j->first );
if ( cmp == 0 ) { if ( cmp == 0 ) {
i->second &= j->second; i->second &= j->second;
skipping to change at line 285 skipping to change at line 309
return *this; return *this;
} }
// TODO get rid of this // TODO get rid of this
BoundList indexBounds( const BSONObj &keyPattern, int direction ) c onst; BoundList indexBounds( const BSONObj &keyPattern, int direction ) c onst;
private: private:
void appendQueries( const FieldRangeSet &other ) { void appendQueries( const FieldRangeSet &other ) {
for( vector< BSONObj >::const_iterator i = other._queries.begin (); i != other._queries.end(); ++i ) { for( vector< BSONObj >::const_iterator i = other._queries.begin (); i != other._queries.end(); ++i ) {
_queries.push_back( *i ); _queries.push_back( *i );
} }
} }
void makeEmpty() {
for( map< string, FieldRange >::iterator i = _ranges.begin(); i
!= _ranges.end(); ++i ) {
i->second.makeEmpty();
}
}
void processQueryField( const BSONElement &e, bool optimize ); void processQueryField( const BSONElement &e, bool optimize );
void processOpElement( const char *fieldName, const BSONElement &f, bool isNot, bool optimize ); void processOpElement( const char *fieldName, const BSONElement &f, bool isNot, bool optimize );
static FieldRange *trivialRange_; static FieldRange *trivialRange_;
static FieldRange &trivialRange(); static FieldRange &trivialRange();
mutable map< string, FieldRange > _ranges; mutable map< string, FieldRange > _ranges;
const char *_ns; const char *_ns;
// make sure memory for FieldRange BSONElements is owned // make sure memory for FieldRange BSONElements is owned
vector< BSONObj > _queries; vector< BSONObj > _queries;
}; };
skipping to change at line 452 skipping to change at line 481
}; };
// generages FieldRangeSet objects, accounting for or clauses // generages FieldRangeSet objects, accounting for or clauses
class FieldRangeOrSet { class FieldRangeOrSet {
public: public:
FieldRangeOrSet( const char *ns, const BSONObj &query , bool optimi ze=true ); FieldRangeOrSet( const char *ns, const BSONObj &query , bool optimi ze=true );
// if there's a useless or clause, we won't use or ranges to help w ith scanning // if there's a useless or clause, we won't use or ranges to help w ith scanning
bool orFinished() const { return _orFound && _orSets.empty(); } bool orFinished() const { return _orFound && _orSets.empty(); }
// removes first or clause, and removes the field ranges it covers from all subsequent or clauses // removes first or clause, and removes the field ranges it covers from all subsequent or clauses
// this could invalidate the result of the last topFrs() // this could invalidate the result of the last topFrs()
void popOrClause( const char *firstField, const char *secondField ) { void popOrClause() {
massert( 13274, "no or clause to pop", !orFinished() ); massert( 13274, "no or clause to pop", !orFinished() );
const FieldRangeSet &toPop = _orSets.front(); const FieldRangeSet &toPop = _orSets.front();
if ( toPop.hasRange( firstField ) ) { list< FieldRangeSet >::iterator i = _orSets.begin();
if ( secondField && toPop.hasRange( secondField ) ) { ++i;
// modifying existing front is ok - this is the last ti while( i != _orSets.end() ) {
me we'll use it *i -= toPop;
_orSets.front().range( firstField ).setExclusiveBounds( if( !i->matchPossible() ) {
); i = _orSets.erase( i );
} } else {
const FieldRange &r = toPop.range( firstField ); ++i;
list< FieldRangeSet >::iterator i = _orSets.begin();
++i;
while( i != _orSets.end() ) {
if ( i->hasRange( firstField ) ) {
i->range( firstField ) -= r;
if( !i->matchPossible() ) {
i = _orSets.erase( i );
} else {
++i;
}
} else {
++i;
}
} }
} }
_oldOrSets.push_front( toPop ); _oldOrSets.push_front( toPop );
_orSets.pop_front(); _orSets.pop_front();
} }
FieldRangeSet *topFrs() const { FieldRangeSet *topFrs() const {
FieldRangeSet *ret = new FieldRangeSet( _baseSet ); FieldRangeSet *ret = new FieldRangeSet( _baseSet );
*ret &= _orSets.front(); if (_orSets.size()){
*ret &= _orSets.front();
}
return ret; return ret;
} }
void allClausesSimplified( vector< BSONObj > &ret ) const { void allClausesSimplified( vector< BSONObj > &ret ) const {
for( list< FieldRangeSet >::const_iterator i = _orSets.begin(); i != _orSets.end(); ++i ) { for( list< FieldRangeSet >::const_iterator i = _orSets.begin(); i != _orSets.end(); ++i ) {
if ( i->matchPossible() ) { if ( i->matchPossible() ) {
ret.push_back( i->simplifiedQuery() ); ret.push_back( i->simplifiedQuery() );
} }
} }
} }
string getSpecial() const { return _baseSet.getSpecial(); } string getSpecial() const { return _baseSet.getSpecial(); }
bool moreOrClauses() const { return !_orSets.empty(); }
private: private:
FieldRangeSet _baseSet; FieldRangeSet _baseSet;
list< FieldRangeSet > _orSets; list< FieldRangeSet > _orSets;
list< FieldRangeSet > _oldOrSets; // make sure memory is owned list< FieldRangeSet > _oldOrSets; // make sure memory is owned
bool _orFound; bool _orFound;
}; };
/** /**
used for doing field limiting used for doing field limiting
*/ */
skipping to change at line 548 skipping to change at line 570
returns "" for complex regular expressions returns "" for complex regular expressions
used to optimize queries in some simple regex cases that start with '^' used to optimize queries in some simple regex cases that start with '^'
if purePrefix != NULL, sets it to whether the regex can be converte d to a range query if purePrefix != NULL, sets it to whether the regex can be converte d to a range query
*/ */
string simpleRegex(const char* regex, const char* flags, bool* purePref ix=NULL); string simpleRegex(const char* regex, const char* flags, bool* purePref ix=NULL);
/** returns the upper bound of a query that matches prefix */ /** returns the upper bound of a query that matches prefix */
string simpleRegexEnd( string prefix ); string simpleRegexEnd( string prefix );
long long applySkipLimit( long long num , const BSONObj& cmd );
} // namespace mongo } // namespace mongo
 End of changes. 13 change blocks. 
26 lines changed or deleted 49 lines changed or added


 ramlog.h   ramlog.h 
skipping to change at line 21 skipping to change at line 21
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* 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 "log.h" #include "log.h"
#include "mongoutils/html.h"
namespace mongo { namespace mongo {
class RamLog : public Tee { class RamLog : public Tee {
enum { enum {
N = 128, N = 128,
C = 256 C = 256
}; };
char lines[N][C]; char lines[N][C];
unsigned h, n; unsigned h, n;
skipping to change at line 38 skipping to change at line 39
}; };
char lines[N][C]; char lines[N][C];
unsigned h, n; unsigned h, n;
public: public:
RamLog() { RamLog() {
h = 0; n = 0; h = 0; n = 0;
for( int i = 0; i < N; i++ ) for( int i = 0; i < N; i++ )
lines[i][C-1] = 0; lines[i][C-1] = 0;
} }
virtual void write(LogLevel ll, const string& str) { virtual void write(LogLevel ll, const string& str) {
char *p = lines[(h+n)%N]; char *p = lines[(h+n)%N];
if( str.size() < C ) if( str.size() < C )
strcpy(p, str.c_str()); strcpy(p, str.c_str());
else else
memcpy(p, str.c_str(), C-1); memcpy(p, str.c_str(), C-1);
if( n < N ) n++; if( n < N ) n++;
else h = (h+1) % N; else h = (h+1) % N;
} }
vector<const char *> get() const { vector<const char *> get() const {
vector<const char *> v; vector<const char *> v;
for( unsigned x=0, i=h; x++ < n; i=(i+1)%N ) for( unsigned x=0, i=h; x++ < n; i=(i+1)%N )
v.push_back(lines[i]); v.push_back(lines[i]);
return v; return v;
} }
static int repeats(const vector<const char *>& v, int i) {
for( int j = i-1; j >= 0 && j+8 > i; j-- ) {
if( strcmp(v[i]+20,v[j]+20) == 0 ) {
for( int x = 1; ; x++ ) {
if( j+x == i ) return j;
if( i+x>=(int) v.size() ) return -1;
if( strcmp(v[i+x]+20,v[j+x]+20) ) return -1;
}
return -1;
}
}
return -1;
}
static string clean(const vector<const char *>& v, int i, string li
ne="") {
if( line.empty() ) line = v[i];
if( i > 0 && strncmp(v[i], v[i-1], 11) == 0 )
return string(" ") + line.substr(11);
return v[i];
}
static string color(string line) {
string s = str::after(line, "replSet ");
if( str::startsWith(s, "warning") || startsWith(s, "error") )
return html::red(line);
if( str::startsWith(s, "info") ) {
if( str::endsWith(s, " up\n") )
return html::green(line);
else if( str::contains(s, " down ") || str::endsWith(s, " d
own\n") )
return html::yellow(line);
return line; //html::blue(line);
}
return line;
}
/* turn http:... into an anchor */
string linkify(const char *s) {
const char *p = s;
const char *h = strstr(p, "http://");
if( h == 0 ) return s;
const char *sp = h + 7;
while( *sp && *sp != ' ' ) sp++;
string url(h, sp-h);
stringstream ss;
ss << string(s, h-s) << "<a href=\"" << url << "\">" << url << "</
a>" << sp;
return ss.str();
}
void toHTML(stringstream& s) {
bool first = true;
s << "<pre>\n";
vector<const char *> v = get();
for( int i = 0; i < (int)v.size(); i++ ) {
assert( strlen(v[i]) > 20 );
int r = repeats(v, i);
if( r < 0 ) {
s << color( linkify( clean(v,i).c_str() ) );
}
else {
stringstream x;
x << string(v[i], 0, 20);
int nr = (i-r);
int last = i+nr-1;
for( ; r < i ; r++ ) x << '.';
if( 1 ) {
stringstream r;
if( nr == 1 ) r << "repeat last line";
else r << "repeats last " << nr << " lines; ends "
<< string(v[last]+4,0,15);
first = false; s << html::a("", r.str(), clean(v,i,
x.str()));
}
else s << x.str();
s << '\n';
i = last;
}
}
s << "</pre>\n";
}
}; };
} }
 End of changes. 4 change blocks. 
0 lines changed or deleted 90 lines changed or added


 repl.h   repl.h 
skipping to change at line 39 skipping to change at line 39
#include "pdfile.h" #include "pdfile.h"
#include "db.h" #include "db.h"
#include "dbhelpers.h" #include "dbhelpers.h"
#include "query.h" #include "query.h"
#include "queryoptimizer.h" #include "queryoptimizer.h"
#include "../client/dbclient.h" #include "../client/dbclient.h"
#include "../util/optime.h" #include "../util/optime.h"
#include "oplog.h" #include "oplog.h"
#include "../util/concurrency/thread_pool.h" #include "../util/concurrency/thread_pool.h"
#include "oplogreader.h"
namespace mongo { namespace mongo {
/* replication slave? (possibly with slave or repl pair nonmaster) /* replication slave? (possibly with slave or repl pair nonmaster)
--slave cmd line setting -> SimpleSlave --slave cmd line setting -> SimpleSlave
*/ */
typedef enum { NotSlave=0, SimpleSlave, ReplPairSlave } SlaveTypes; typedef enum { NotSlave=0, SimpleSlave, ReplPairSlave } SlaveTypes;
class ReplSettings { class ReplSettings {
public: public:
skipping to change at line 81 skipping to change at line 82
bool cloneFrom(const char *masterHost, string& errmsg, const string& fr omdb, bool logForReplication, bool cloneFrom(const char *masterHost, string& errmsg, const string& fr omdb, bool logForReplication,
bool slaveOk, bool useReplAuth, bool snap shot); bool slaveOk, bool useReplAuth, bool snap shot);
/* A replication exception */ /* A replication exception */
class SyncException : public DBException { class SyncException : public DBException {
public: public:
SyncException() : DBException( "sync exception" , 10001 ){} SyncException() : DBException( "sync exception" , 10001 ){}
}; };
/* started abstracting out the querying of the primary/master's oplog
still fairly awkward but a start.
*/
class OplogReader {
auto_ptr<DBClientConnection> _conn;
auto_ptr<DBClientCursor> cursor;
public:
void reset() {
cursor.reset();
}
void resetConnection() {
cursor.reset();
_conn.reset();
}
DBClientConnection* conn() { return _conn.get(); }
BSONObj findOne(const char *ns, Query& q) {
return conn()->findOne(ns, q);
}
/* ok to call if already connected */
bool connect(string hostname);
void getReady() {
if( cursor.get() && cursor->isDead() ) {
log() << "repl: old cursor isDead, initiating a new one" <<
endl;
reset();
}
}
bool haveCursor() { return cursor.get() != 0; }
void tailingQuery(const char *ns, BSONObj& query) {
assert( !haveCursor() );
log(2) << "repl: " << ns << ".find(" << query.toString() << ')'
<< endl;
cursor = _conn->query( ns, query, 0, 0, 0,
QueryOption_CursorTailable | QueryOption_
SlaveOk | QueryOption_OplogReplay |
QueryOption_AwaitData
);
}
bool more() {
assert( cursor.get() );
return cursor->more();
}
/* old mongod's can't do the await flag... */
bool awaitCapable() {
return cursor->hasResultFlag(QueryResult::ResultFlag_AwaitCapab
le);
}
void peek(vector<BSONObj>& v, int n) {
if( cursor.get() )
cursor->peek(v,n);
}
BSONObj next() {
return cursor->next();
}
void putBack(BSONObj op) {
cursor->putBack(op);
}
};
/* A Source is a source from which we can pull (replicate) data. /* A Source is a source from which we can pull (replicate) data.
stored in collection local.sources. stored in collection local.sources.
Can be a group of things to replicate for several databases. Can be a group of things to replicate for several databases.
{ host: ..., source: ..., only: ..., syncedTo: ..., localLogTs: . .., dbsNextPass: { ... }, incompleteCloneDbs: { ... } } { host: ..., source: ..., only: ..., syncedTo: ..., localLogTs: . .., dbsNextPass: { ... }, incompleteCloneDbs: { ... } }
'source' defaults to 'main'; support for multiple source names is 'source' defaults to 'main'; support for multiple source names is
not done (always use main for now). not done (always use main for now).
*/ */
skipping to change at line 237 skipping to change at line 173
void save(); // write ourself to local.sources void save(); // write ourself to local.sources
// make a jsobj from our member fields of the form // make a jsobj from our member fields of the form
// { host: ..., source: ..., syncedTo: ... } // { host: ..., source: ..., syncedTo: ... }
BSONObj jsobj(); BSONObj jsobj();
bool operator==(const ReplSource&r) const { bool operator==(const ReplSource&r) const {
return hostName == r.hostName && sourceName() == r.sourceName() ; return hostName == r.hostName && sourceName() == r.sourceName() ;
} }
operator string() const { return sourceName() + "@" + hostName; } string toString() const { return sourceName() + "@" + hostName; }
bool haveMoreDbsToSync() const { return !addDbNextPass.empty(); } bool haveMoreDbsToSync() const { return !addDbNextPass.empty(); }
int sleepAdvice() const { int sleepAdvice() const {
if ( !_sleepAdviceTime ) if ( !_sleepAdviceTime )
return 0; return 0;
int wait = _sleepAdviceTime - unsigned( time( 0 ) ); int wait = _sleepAdviceTime - unsigned( time( 0 ) );
return wait > 0 ? wait : 0; return wait > 0 ? wait : 0;
} }
static bool throttledForceResyncDead( const char *requester ); static bool throttledForceResyncDead( const char *requester );
 End of changes. 3 change blocks. 
70 lines changed or deleted 2 lines changed or added


 request.h   request.h 
skipping to change at line 53 skipping to change at line 53
bool expectResponse() const { bool expectResponse() const {
return op() == dbQuery || op() == dbGetMore; return op() == dbQuery || op() == dbGetMore;
} }
bool isCommand() const; bool isCommand() const;
MSGID id() const { MSGID id() const {
return _id; return _id;
} }
DBConfigPtr getConfig() const { DBConfigPtr getConfig() const {
assert( _didInit );
return _config; return _config;
} }
bool isShardingEnabled() const { bool isShardingEnabled() const {
assert( _didInit );
return _config->isShardingEnabled(); return _config->isShardingEnabled();
} }
ChunkManagerPtr getChunkManager() const { ChunkManagerPtr getChunkManager() const {
assert( _didInit );
return _chunkManager; return _chunkManager;
} }
int getClientId() const { int getClientId() const {
return _clientId; return _clientId;
} }
ClientInfo * getClientInfo() const { ClientInfo * getClientInfo() const {
return _clientInfo; return _clientInfo;
} }
skipping to change at line 86 skipping to change at line 89
void reply( Message & response , const string& fromServer ); void reply( Message & response , const string& fromServer );
Message& m() { return _m; } Message& m() { return _m; }
DbMessage& d() { return _d; } DbMessage& d() { return _d; }
AbstractMessagingPort* p() const { return _p; } AbstractMessagingPort* p() const { return _p; }
void process( int attempt = 0 ); void process( int attempt = 0 );
void gotInsert(); void gotInsert();
void init();
void reset( bool reload=false ); void reset( bool reload=false );
private: private:
Message& _m; Message& _m;
DbMessage _d; DbMessage _d;
AbstractMessagingPort* _p; AbstractMessagingPort* _p;
MSGID _id; MSGID _id;
DBConfigPtr _config; DBConfigPtr _config;
ChunkManagerPtr _chunkManager; ChunkManagerPtr _chunkManager;
int _clientId; int _clientId;
ClientInfo * _clientInfo; ClientInfo * _clientInfo;
skipping to change at line 102 skipping to change at line 106
AbstractMessagingPort* _p; AbstractMessagingPort* _p;
MSGID _id; MSGID _id;
DBConfigPtr _config; DBConfigPtr _config;
ChunkManagerPtr _chunkManager; ChunkManagerPtr _chunkManager;
int _clientId; int _clientId;
ClientInfo * _clientInfo; ClientInfo * _clientInfo;
OpCounters* _counter; OpCounters* _counter;
bool _didInit;
}; };
typedef map<int,ClientInfo*> ClientCache; typedef map<int,ClientInfo*> ClientCache;
class ClientInfo { class ClientInfo {
public: public:
ClientInfo( int clientId ); ClientInfo( int clientId );
~ClientInfo(); ~ClientInfo();
string getRemote() const { return _remote; } string getRemote() const { return _remote; }
 End of changes. 6 change blocks. 
1 lines changed or deleted 7 lines changed or added


 rs.h   rs.h 
skipping to change at line 33 skipping to change at line 33
#include "../../util/concurrency/msg.h" #include "../../util/concurrency/msg.h"
#include "../../util/hostandport.h" #include "../../util/hostandport.h"
#include "../commands.h" #include "../commands.h"
#include "rs_exception.h" #include "rs_exception.h"
#include "rs_optime.h" #include "rs_optime.h"
#include "rs_member.h" #include "rs_member.h"
#include "rs_config.h" #include "rs_config.h"
namespace mongo { namespace mongo {
struct HowToFixUp;
struct Target; struct Target;
class DBClientConnection;
class ReplSetImpl; class ReplSetImpl;
class OplogReader;
extern bool replSet; // true if using repl sets extern bool replSet; // true if using repl sets
extern class ReplSet *theReplSet; // null until initialized extern class ReplSet *theReplSet; // null until initialized
extern Tee *rsLog; extern Tee *rsLog;
/* member of a replica set */ /* member of a replica set */
class Member : public List1<Member>::Base { class Member : public List1<Member>::Base {
public: public:
Member(HostAndPort h, unsigned ord, const ReplSetConfig::MemberCfg Member(HostAndPort h, unsigned ord, const ReplSetConfig::MemberCfg
*c); *c, bool self);
string fullName() const { return h().toString(); } string fullName() const { return h().toString(); }
const ReplSetConfig::MemberCfg& config() const { return *_config; } const ReplSetConfig::MemberCfg& config() const { return *_config; }
const HeartbeatInfo& hbinfo() const { return _hbinfo; } const HeartbeatInfo& hbinfo() const { return _hbinfo; }
string lhb() { return _hbinfo.lastHeartbeatMsg; } string lhb() { return _hbinfo.lastHeartbeatMsg; }
MemberState state() const { return _hbinfo.hbstate; } MemberState state() const { return _hbinfo.hbstate; }
const HostAndPort& h() const { return _h; } const HostAndPort& h() const { return _h; }
unsigned id() const { return _hbinfo.id(); } unsigned id() const { return _hbinfo.id(); }
bool hot() const { return _config->hot(); } bool potentiallyHot() const { return _config->potentiallyHot(); } / / not arbiter, not priority 0
void summarizeAsHtml(stringstream& s) const; void summarizeAsHtml(stringstream& s) const;
friend class ReplSetImpl; friend class ReplSetImpl;
private: private:
const ReplSetConfig::MemberCfg *_config; /* todo: when this changes ??? */ const ReplSetConfig::MemberCfg *_config; /* todo: when this changes ??? */
HostAndPort _h; HostAndPort _h;
HeartbeatInfo _hbinfo; HeartbeatInfo _hbinfo;
}; };
class Manager : public task::Server { class Manager : public task::Server {
ReplSetImpl *rs; ReplSetImpl *rs;
bool busyWithElectSelf; bool busyWithElectSelf;
int _primary; int _primary;
const Member* findOtherPrimary(); const Member* findOtherPrimary();
void noteARemoteIsPrimary(const Member *); void noteARemoteIsPrimary(const Member *);
virtual void starting(); virtual void starting();
public: public:
Manager(ReplSetImpl *rs); Manager(ReplSetImpl *rs);
void msgReceivedNewConfig(BSONObj) { assert(false); } void msgReceivedNewConfig(BSONObj);
void msgCheckNewState(); void msgCheckNewState();
}; };
struct Target; struct Target;
class Consensus { class Consensus {
ReplSetImpl &rs; ReplSetImpl &rs;
struct LastYea { struct LastYea {
LastYea() : when(0), who(0xffffffff) { } LastYea() : when(0), who(0xffffffff) { }
time_t when; time_t when;
unsigned who; unsigned who;
}; };
Atomic<LastYea> ly; Atomic<LastYea> ly;
unsigned yea(unsigned memberId); // throws VoteException unsigned yea(unsigned memberId); // throws VoteException
void electionFailed(unsigned meid);
void _electSelf(); void _electSelf();
bool weAreFreshest(bool& allUp, int& nTies); bool weAreFreshest(bool& allUp, int& nTies);
bool sleptLast; // slept last elect() pass bool sleptLast; // slept last elect() pass
public: public:
Consensus(ReplSetImpl *t) : rs(*t) { Consensus(ReplSetImpl *t) : rs(*t) {
sleptLast = false; sleptLast = false;
steppedDown = 0;
} }
/* if we've stepped down, this is when we are allowed to try to ele
ct ourself again.
todo: handle possible weirdnesses at clock skews etc.
*/
time_t steppedDown;
int totalVotes() const; int totalVotes() const;
bool aMajoritySeemsToBeUp() const; bool aMajoritySeemsToBeUp() const;
void electSelf(); void electSelf();
void electCmdReceived(BSONObj, BSONObjBuilder*); void electCmdReceived(BSONObj, BSONObjBuilder*);
void multiCommand(BSONObj cmd, list<Target>& L); void multiCommand(BSONObj cmd, list<Target>& L);
}; };
/** most operations on a ReplSet object should be done while locked. th at logic implemented here. */ /** most operations on a ReplSet object should be done while locked. th at logic implemented here. */
class RSBase : boost::noncopyable { class RSBase : boost::noncopyable {
private: private:
skipping to change at line 144 skipping to change at line 154
/* if true, is locked, and was locked by this thread. note if false , it could be in the lock or not for another /* if true, is locked, and was locked by this thread. note if false , it could be in the lock or not for another
just for asserts & such so we can make the contracts clear on wh o locks what when. just for asserts & such so we can make the contracts clear on wh o locks what when.
we don't use these locks that frequently, so the little bit of o verhead is fine. we don't use these locks that frequently, so the little bit of o verhead is fine.
*/ */
bool lockedByMe() { return _lockedByMe.get(); } bool lockedByMe() { return _lockedByMe.get(); }
}; };
class ReplSetHealthPollTask; class ReplSetHealthPollTask;
/* safe container for our state that keeps member pointer and state var
iables always aligned */
class StateBox : boost::noncopyable {
public:
struct SP { // SP is like pair<MemberState,const Member *> but nice
r
SP() : state(MemberState::RS_STARTUP), primary(0) { }
MemberState state;
const Member *primary;
};
const SP get() {
scoped_lock lk(m);
return sp;
}
MemberState getState() const { return sp.state; }
const Member* getPrimary() const { return sp.primary; }
void change(MemberState s) {
scoped_lock lk(m);
sp.state = s;
// note : we don't correct primary if RS_PRIMARY was set here.
that must be done upstream.
}
void set(MemberState s, const Member *p) {
scoped_lock lk(m);
sp.state = s; sp.primary = p;
}
void setSelfPrimary(const Member *self) {
scoped_lock lk(m);
sp.state = MemberState::RS_PRIMARY;
sp.primary = self;
}
void setOtherPrimary(const Member *mem) {
scoped_lock lk(m);
assert( !sp.state.primary() );
sp.primary = mem;
}
StateBox() : m("StateBox") { }
private:
mutex m;
SP sp;
};
/* information about the entire repl set, such as the various servers i n the set, and their state */ /* information about the entire repl set, such as the various servers i n the set, and their state */
/* note: We currently do not free mem when the set goes away - it is as sumed the replset is a /* note: We currently do not free mem when the set goes away - it is as sumed the replset is a
singleton and long lived. singleton and long lived.
*/ */
class ReplSetImpl : protected RSBase { class ReplSetImpl : protected RSBase {
public: public:
/** info on our state if the replset isn't yet "up". for example, if we are pre-initiation. */ /** info on our state if the replset isn't yet "up". for example, if we are pre-initiation. */
enum StartupStatus { enum StartupStatus {
PRESTART=0, LOADINGCONFIG=1, BADCONFIG=2, EMPTYCONFIG=3, PRESTART=0, LOADINGCONFIG=1, BADCONFIG=2, EMPTYCONFIG=3,
EMPTYUNREACHABLE=4, STARTED=5, SOON=6 EMPTYUNREACHABLE=4, STARTED=5, SOON=6
}; };
static StartupStatus startupStatus; static StartupStatus startupStatus;
static string startupStatusMsg; static string startupStatusMsg;
static string stateAsStr(MemberState state); static string stateAsStr(MemberState state);
static string stateAsHtml(MemberState state); static string stateAsHtml(MemberState state);
/* todo thread */ /* todo thread */
void msgUpdateHBInfo(HeartbeatInfo); void msgUpdateHBInfo(HeartbeatInfo);
bool isPrimary() const { return _myState == PRIMARY; }
bool isSecondary() const { return _myState == SECONDARY; }
//bool initiated() const { return curOpTime.initiated(); } StateBox box;
OpTime lastOpTimeWritten; OpTime lastOpTimeWritten;
long long h; 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:
unsigned _selfId; // stored redundantly we hit this a lot
set<ReplSetHealthPollTask*> healthTasks; set<ReplSetHealthPollTask*> healthTasks;
void endOldHealthTasks(); void endOldHealthTasks();
void startHealthTaskFor(Member *m); void startHealthTaskFor(Member *m);
private: private:
Consensus elect; Consensus elect;
bool ok() const { return _myState != FATAL; } bool ok() const { return !box.getState().fatal(); }
void relinquish(); void relinquish();
protected:
bool _stepDown();
private:
void assumePrimary(); void assumePrimary();
void loadLastOpTimeWritten(); void loadLastOpTimeWritten();
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]; char _hbmsg[256]; // we change this unocked, thus not a c++ string
void sethbmsg(string s) { public:
assert(s.size() < sizeof(_hbmsg)); void sethbmsg(string s, int logLevel = 0) {
strcpy(_hbmsg, s.c_str()); unsigned sz = s.size();
if( sz >= 256 )
memcpy(_hbmsg, s.c_str(), 255);
else {
_hbmsg[sz] = 0;
memcpy(_hbmsg, s.c_str(), sz);
}
log(logLevel) << "replSet " << s << rsLog;
} }
protected:
bool initFromConfig(ReplSetConfig& c); // true if ok; throws if con fig really bad; false if config doesn't include self bool initFromConfig(ReplSetConfig& c); // true if ok; throws if con fig really bad; false if config doesn't include self
void _fillIsMaster(BSONObjBuilder&); void _fillIsMaster(BSONObjBuilder&);
void _fillIsMasterHost(const Member*, vector<string>&, vector<strin g>&, vector<string>&); void _fillIsMasterHost(const Member*, vector<string>&, vector<strin g>&, vector<string>&);
const ReplSetConfig& config() { return *_cfg; } const ReplSetConfig& config() { return *_cfg; }
string name() const { return _name; } /* @return replica set's logi cal name */ string name() const { return _name; } /* @return replica set's logi cal name */
MemberState state() const { return _myState; } MemberState state() const { return box.getState(); }
void _fatal(); void _fatal();
void _getOplogDiagsAsHtml(unsigned server_id, stringstream& ss) con st; void _getOplogDiagsAsHtml(unsigned server_id, stringstream& ss) con st;
void _summarizeAsHtml(stringstream&) const; void _summarizeAsHtml(stringstream&) const;
void _summarizeStatus(BSONObjBuilder&) const; // for replSetGetStat us command void _summarizeStatus(BSONObjBuilder&) const; // for replSetGetStat us command
/* cfgString format is /* cfgString format is
replsetname/host1,host2:port,... replsetname/host1,host2:port,...
where :port is optional. where :port is optional.
throws exception if a problem initializing. */ throws exception if a problem initializing. */
ReplSetImpl(string cfgString); ReplSetImpl(string cfgString);
/* call afer constructing to start - returns fairly quickly after l aunching its threads */ /* call afer constructing to start - returns fairly quickly after l aunching its threads */
void _go(); void _go();
private: private:
MemberState _myState;
string _name; string _name;
const vector<HostAndPort> *_seeds; const vector<HostAndPort> *_seeds;
ReplSetConfig *_cfg; ReplSetConfig *_cfg;
/** load our configuration from admin.replset. try seed machines t oo. /** load our configuration from admin.replset. try seed machines t oo.
@return true if ok; throws if config really bad; false if confi g doesn't include self @return true if ok; throws if config really bad; false if confi g doesn't include self
*/ */
bool _loadConfigFinish(vector<ReplSetConfig>& v); bool _loadConfigFinish(vector<ReplSetConfig>& v);
void loadConfig(); void loadConfig();
list<HostAndPort> memberHostnames() const; list<HostAndPort> memberHostnames() const;
const Member* currentPrimary() const { return _currentPrimary; }
const ReplSetConfig::MemberCfg& myConfig() const { return _self->co nfig(); } const ReplSetConfig::MemberCfg& myConfig() const { return _self->co nfig(); }
const Member *_currentPrimary; bool iAmArbiterOnly() const { return myConfig().arbiterOnly; }
bool iAmPotentiallyHot() const { return myConfig().potentiallyHot()
; }
Member *_self; Member *_self;
List1<Member> _members; /* all members of the set EXCEPT self. */ List1<Member> _members; /* all members of the set EXCEPT self. */
public: public:
unsigned selfId() const { return _selfId; } unsigned selfId() const { return _self->id(); }
shared_ptr<Manager> mgr; shared_ptr<Manager> mgr;
private: private:
Member* head() const { return _members.head(); } Member* head() const { return _members.head(); }
Member* findById(unsigned id) const; Member* findById(unsigned id) const;
void _getTargets(list<Target>&, int &configVersion); void _getTargets(list<Target>&, int &configVersion);
void getTargets(list<Target>&, int &configVersion); void getTargets(list<Target>&, int &configVersion);
void startThreads(); void startThreads();
friend class FeedbackThread; friend class FeedbackThread;
friend class CmdReplSetElect; friend class CmdReplSetElect;
friend class Member; friend class Member;
friend class Manager; friend class Manager;
friend class Consensus; friend class Consensus;
private: private:
/* pulling data from primary related - see rs_sync.cpp */ /* pulling data from primary related - see rs_sync.cpp */
void _syncDoInitialSync();
void syncDoInitialSync(); void syncDoInitialSync();
void _syncThread();
void syncTail();
void syncApply(const BSONObj &o);
void syncRollback(OplogReader& r);
void syncFixUp(HowToFixUp& h, DBClientConnection*);
public:
void syncThread();
}; };
class ReplSet : public ReplSetImpl { class ReplSet : public ReplSetImpl {
public: public:
ReplSet(string cfgString) : ReplSetImpl(cfgString) { ReplSet(string cfgString) : ReplSetImpl(cfgString) { }
}
bool stepDown() { return _stepDown(); }
/* 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 isMaster(const char *client); bool isMaster(const char *client);
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.
void haveNewConfig(ReplSetConfig& c); @param comment write a no-op comment to the oplog about it. onl
y makes sense if one is primary and initiating the reconf.
*/
void haveNewConfig(ReplSetConfig& c, bool comment);
/* if we delete old configs, this needs to assure locking. currentl y we don't so it is ok. */ /* if we delete old configs, this needs to assure locking. currentl y we don't so it is ok. */
const ReplSetConfig& getConfig() { return config(); } const ReplSetConfig& getConfig() { return config(); }
bool lockedByMe() { return RSBase::lockedByMe(); } bool lockedByMe() { return RSBase::lockedByMe(); }
// heartbeat msg to send to others; descriptive diagnostic info // heartbeat msg to send to others; descriptive diagnostic info
string hbmsg() const { return _hbmsg; } string hbmsg() const { return _hbmsg; }
}; };
skipping to change at line 314 skipping to change at line 379
return true; return true;
} }
}; };
/** helpers ----------------- */ /** helpers ----------------- */
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 );
/** inlines ----------------- */ /** inlines ----------------- */
inline Member::Member(HostAndPort h, unsigned ord, const ReplSetConfig: inline Member::Member(HostAndPort h, unsigned ord, const ReplSetConfig:
:MemberCfg *c) : :MemberCfg *c, bool self) :
_config(c), _h(h), _hbinfo(ord) { } _config(c), _h(h), _hbinfo(ord) {
if( self ) {
_hbinfo.health = 1.0;
}
}
inline bool ReplSet::isMaster(const char *client) { inline bool ReplSet::isMaster(const char *client) {
/* todo replset */ /* todo replset */
return isPrimary(); return box.getState().primary();
} }
} }
 End of changes. 30 change blocks. 
31 lines changed or deleted 106 lines changed or added


 rs_config.h   rs_config.h 
skipping to change at line 52 skipping to change at line 52
struct MemberCfg { struct MemberCfg {
MemberCfg() : _id(-1), votes(1), priority(1.0), arbiterOnly(fal se) { } MemberCfg() : _id(-1), votes(1), priority(1.0), arbiterOnly(fal se) { }
int _id; /* ordinal */ int _id; /* ordinal */
unsigned votes; /* how many votes this node gets. default 1. */ unsigned votes; /* how many votes this node gets. default 1. */
HostAndPort h; HostAndPort h;
double priority; /* 0 means can never be primary */ double priority; /* 0 means can never be primary */
bool arbiterOnly; bool arbiterOnly;
void check() const; /* check validity, assert if not. */ void check() const; /* check validity, assert if not. */
BSONObj asBson() const; BSONObj asBson() const;
bool hot() const { bool potentiallyHot() const {
return !arbiterOnly && priority > 0; return !arbiterOnly && priority > 0;
} }
}; };
vector<MemberCfg> members; vector<MemberCfg> members;
string _id; string _id;
int version; int version;
HealthOptions ho; HealthOptions ho;
string md5; string md5;
BSONObj getLastErrorDefaults; BSONObj getLastErrorDefaults;
skipping to change at line 76 skipping to change at line 76
bool empty() const { return version == EMPTYCONFIG; } bool empty() const { return version == EMPTYCONFIG; }
string toString() const { return asBson().toString(); } string toString() const { return asBson().toString(); }
/** validate the settings. does not call check() on each member, yo u have to do that separately. */ /** validate the settings. does not call check() on each member, yo u have to do that separately. */
void check() const; void check() const;
/** check if modification makes sense */ /** check if modification makes sense */
static bool legalChange(const ReplSetConfig& old, const ReplSetConf ig& n, string& errmsg); static bool legalChange(const ReplSetConfig& old, const ReplSetConf ig& n, string& errmsg);
static void receivedNewConfig(BSONObj); //static void receivedNewConfig(BSONObj);
void saveConfigLocally(BSONObj comment); // to local db void saveConfigLocally(BSONObj comment); // to local db
string saveConfigEverywhere(); // returns textual info on what happ ened string saveConfigEverywhere(); // returns textual info on what happ ened
BSONObj asBson() const; BSONObj asBson() const;
private: private:
bool _ok; bool _ok;
void from(BSONObj); void from(BSONObj);
void clear(); void clear();
}; };
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 rs_member.h   rs_member.h 
skipping to change at line 24 skipping to change at line 24
* 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/>.
*/ */
/** replica set member */ /** replica set member */
#pragma once #pragma once
namespace mongo { namespace mongo {
enum MemberState { /*
STARTUP, RS_STARTUP serving still starting up, or still trying to initiat
PRIMARY, e the set
SECONDARY, RS_PRIMARY this server thinks it is primary
RECOVERING, RS_SECONDARY this server thinks it is a secondary (slave mode)
FATAL, RS_RECOVERING recovering/resyncing; after recovery usually auto-tra
STARTUP2, nsitions to secondary
UNKNOWN /* remote node not yet reached */ RS_FATAL something bad has occurred and server is not complete
ly offline with regard to the replica set. fatal error.
RS_STARTUP2 loaded config, still determining who is primary
*/
struct MemberState {
enum MS {
RS_STARTUP,
RS_PRIMARY,
RS_SECONDARY,
RS_RECOVERING,
RS_FATAL,
RS_STARTUP2,
RS_UNKNOWN, /* remote node not yet reached */
RS_ARBITER,
RS_DOWN /* node not reachable for a report */
} s;
MemberState(MS ms = RS_UNKNOWN) : s(ms) { }
explicit MemberState(int ms) : s((MS) ms) { }
bool primary() const { return s == RS_PRIMARY; }
bool secondary() const { return s == RS_SECONDARY; }
bool recovering() const { return s == RS_RECOVERING; }
bool startup2() const { return s == RS_STARTUP2; }
bool fatal() const { return s == RS_FATAL; }
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) { } HeartbeatInfo() : _id(0xffffffff) { }
HeartbeatInfo(unsigned id); HeartbeatInfo(unsigned id);
bool up() const { return health > 0; } bool up() const { return health > 0; }
skipping to change at line 53 skipping to change at line 77
MemberState hbstate; MemberState hbstate;
double health; double health;
time_t upSince; time_t upSince;
time_t lastHeartbeat; time_t lastHeartbeat;
string lastHeartbeatMsg; string lastHeartbeatMsg;
OpTime opTime; OpTime opTime;
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 = UNKNOWN;
health = -1.0; health = -1.0;
lastHeartbeat = upSince = 0; lastHeartbeat = upSince = 0;
} }
inline bool HeartbeatInfo::changed(const HeartbeatInfo& old) const { inline bool HeartbeatInfo::changed(const HeartbeatInfo& old) const {
return health != old.health || return health != old.health ||
hbstate != old.hbstate; hbstate != old.hbstate;
} }
} }
 End of changes. 2 change blocks. 
9 lines changed or deleted 35 lines changed or added


 rs_optime.h   rs_optime.h 
skipping to change at line 25 skipping to change at line 25
* You should have received a copy of the GNU Affero General Public 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 "../../util/optime.h" #include "../../util/optime.h"
namespace mongo { namespace mongo {
const string rsoplog = "local.oplog.rs"; const char rsoplog[] = "local.oplog.rs";
/* /*
class RSOpTime : public OpTime { class RSOpTime : public OpTime {
public: public:
bool initiated() const { return getSecs() != 0; } bool initiated() const { return getSecs() != 0; }
};*/ };*/
/*struct RSOpTime { /*struct RSOpTime {
unsigned long long ord; unsigned long long ord;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 rwlock.h   rwlock.h 
skipping to change at line 185 skipping to change at line 185
check(x); check(x);
} }
return false; return false;
} }
}; };
#endif #endif
class rwlock_try_write {
RWLock& _l;
public:
struct exception { };
rwlock_try_write(RWLock& l, int millis = 0) : _l(l) {
if( !l.lock_try(millis) ) throw exception();
}
~rwlock_try_write() { _l.unlock(); }
};
/* scoped lock */
struct rwlock { struct rwlock {
rwlock( const RWLock& lock , bool write , bool alreadyHaveLock = fa lse ) rwlock( const RWLock& lock , bool write , bool alreadyHaveLock = fa lse )
: _lock( (RWLock&)lock ) , _write( write ){ : _lock( (RWLock&)lock ) , _write( write ){
if ( ! alreadyHaveLock ){ if ( ! alreadyHaveLock ){
if ( _write ) if ( _write )
_lock.lock(); _lock.lock();
else else
_lock.lock_shared(); _lock.lock_shared();
} }
 End of changes. 1 change blocks. 
0 lines changed or deleted 11 lines changed or added


 scanandorder.h   scanandorder.h 
skipping to change at line 77 skipping to change at line 77
} }
if (loc) if (loc)
b.append("$diskLoc", loc->toBSONObj()); b.append("$diskLoc", loc->toBSONObj());
b.done(); b.done();
} else if (loc) { } else if (loc) {
BSONObjBuilder b( bb ); BSONObjBuilder b( bb );
b.appendElements(js); b.appendElements(js);
b.append("$diskLoc", loc->toBSONObj()); b.append("$diskLoc", loc->toBSONObj());
b.done(); b.done();
} else { } else {
bb.append((void*) js.objdata(), js.objsize()); bb.appendBuf((void*) js.objdata(), js.objsize());
} }
} }
typedef multimap<BSONObj,BSONObj,BSONObjCmp> BestMap; typedef multimap<BSONObj,BSONObj,BSONObjCmp> BestMap;
class ScanAndOrder { class ScanAndOrder {
BestMap best; // key -> full object BestMap best; // key -> full object
int startFrom; int startFrom;
int limit; // max to send back. int limit; // max to send back.
KeyType order; KeyType order;
unsigned approxSize; unsigned approxSize;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 shard.h   shard.h 
skipping to change at line 155 skipping to change at line 155
long long _maxSize; // in MBytes, 0 is unlimited long long _maxSize; // in MBytes, 0 is unlimited
bool _isDraining; // shard is currently being removed bool _isDraining; // shard is currently being removed
}; };
class ShardStatus { class ShardStatus {
public: public:
ShardStatus( const Shard& shard , const BSONObj& obj ); ShardStatus( const Shard& shard , const BSONObj& obj );
friend ostream& operator << (ostream& out, const ShardStatus& s) { friend ostream& operator << (ostream& out, const ShardStatus& s) {
out << (string)s; out << s.toString();
return out; return out;
} }
operator string() const { string toString() const {
stringstream ss; stringstream ss;
ss << "shard: " << _shard << " mapped: " << _mapped << " writeL ock: " << _writeLock; ss << "shard: " << _shard << " mapped: " << _mapped << " writeL ock: " << _writeLock;
return ss.str(); return ss.str();
} }
bool operator<( const ShardStatus& other ) const{ bool operator<( const ShardStatus& other ) const{
return _mapped < other._mapped; return _mapped < other._mapped;
} }
Shard shard() const { Shard shard() const {
skipping to change at line 223 skipping to change at line 223
return _addr; return _addr;
} }
bool setVersion() { bool setVersion() {
_finishInit(); _finishInit();
return _setVersion; return _setVersion;
} }
static void sync(); static void sync();
void donotCheckVersion(){
_setVersion = false;
_finishedInit = true;
}
/**
this just passes through excpet it checks for stale configs
*/
bool runCommand( const string& db , const BSONObj& cmd , BSONObj& r
es );
/** checks all of my thread local connections for the version of th
is ns */
static void checkMyConnectionVersions( const string & ns );
private: private:
void _init(); void _init();
void _finishInit(); void _finishInit();
bool _finishedInit; bool _finishedInit;
string _addr; string _addr;
string _ns; string _ns;
DBClientBase* _conn; DBClientBase* _conn;
bool _setVersion; bool _setVersion;
 End of changes. 3 change blocks. 
2 lines changed or deleted 17 lines changed or added


 shardkey.h   shardkey.h 
skipping to change at line 87 skipping to change at line 87
bool partOfShardKey(const string& key ) const { bool partOfShardKey(const string& key ) const {
return patternfields.count( key ) > 0; return patternfields.count( key ) > 0;
} }
/** /**
* @return * @return
* true if 'this' is a prefix (not necessarily contained) of 'other Pattern'. * true if 'this' is a prefix (not necessarily contained) of 'other Pattern'.
*/ */
bool isPrefixOf( const BSONObj& otherPattern ) const; bool isPrefixOf( const BSONObj& otherPattern ) const;
operator string() const {
return pattern.toString();
}
private: private:
BSONObj pattern; BSONObj pattern;
BSONObj gMin; BSONObj gMin;
BSONObj gMax; BSONObj gMax;
/* question: better to have patternfields precomputed or not? depe nds on if we use copy constructor often. */ /* question: better to have patternfields precomputed or not? depe nds on if we use copy constructor often. */
set<string> patternfields; set<string> patternfields;
}; };
inline BSONObj ShardKeyPattern::extractKey(const BSONObj& from) const { inline BSONObj ShardKeyPattern::extractKey(const BSONObj& from) const {
 End of changes. 1 change blocks. 
3 lines changed or deleted 0 lines changed or added


 sock.h   sock.h 
skipping to change at line 157 skipping to change at line 157
template <typename T> template <typename T>
const T& as() const { return *(const T*)(&sa); } const T& as() const { return *(const T*)(&sa); }
string toString(bool includePort=true) const{ string toString(bool includePort=true) const{
string out = getAddr(); string out = getAddr();
if (includePort && getType() != AF_UNIX && getType() != AF_UNSP EC) if (includePort && getType() != AF_UNIX && getType() != AF_UNSP EC)
out += ':' + BSONObjBuilder::numStr(getPort()); out += ':' + BSONObjBuilder::numStr(getPort());
return out; return out;
} }
operator string() const{
return toString();
}
// returns one of AF_INET, AF_INET6, or AF_UNIX // returns one of AF_INET, AF_INET6, or AF_UNIX
sa_family_t getType() const { sa_family_t getType() const {
return sa.ss_family; return sa.ss_family;
} }
unsigned getPort() const { unsigned getPort() const {
switch (getType()){ switch (getType()){
case AF_INET: return ntohs(as<sockaddr_in>().sin_port); case AF_INET: return ntohs(as<sockaddr_in>().sin_port);
case AF_INET6: return ntohs(as<sockaddr_in6>().sin6_port); case AF_INET6: return ntohs(as<sockaddr_in6>().sin6_port);
case AF_UNIX: return 0; case AF_UNIX: return 0;
 End of changes. 1 change blocks. 
4 lines changed or deleted 0 lines changed or added


 strategy.h   strategy.h 
skipping to change at line 35 skipping to change at line 35
class Strategy { class Strategy {
public: public:
Strategy(){} Strategy(){}
virtual ~Strategy() {} virtual ~Strategy() {}
virtual void queryOp( Request& r ) = 0; virtual void queryOp( Request& r ) = 0;
virtual void getMore( Request& r ) = 0; virtual void getMore( Request& r ) = 0;
virtual void writeOp( int op , Request& r ) = 0; virtual void writeOp( int op , Request& r ) = 0;
protected: protected:
void doWrite( int op , Request& r , const Shard& shard ); void doWrite( int op , Request& r , const Shard& shard , bool check Version = true );
void doQuery( Request& r , const Shard& shard ); void doQuery( Request& r , const Shard& shard );
void insert( const Shard& shard , const char * ns , const BSONObj& obj ); void insert( const Shard& shard , const char * ns , const BSONObj& obj );
}; };
extern Strategy * SINGLE; extern Strategy * SINGLE;
extern Strategy * SHARDED; extern Strategy * SHARDED;
bool setShardVersion( DBClientBase & conn , const string& ns , ShardChu nkVersion version , bool authoritative , BSONObj& result ); bool setShardVersion( DBClientBase & conn , const string& ns , ShardChu nkVersion version , bool authoritative , BSONObj& result );
void waitForWriteback( const OID& oid );
} }
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 stringdata.h   stringdata.h 
skipping to change at line 18 skipping to change at line 18
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* 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.
*/ */
#ifndef UTIL_BSON_STRINGDATA_HEADER #ifndef BSON_STRINDATA_HEADER
#define UTIL_BSON_STRINGDATA_HEADER #define BSON_STRINDATA_HEADER
#include <string> #include <string>
#include <cstring> #include <cstring>
namespace mongo { namespace mongo {
using std::string; using std::string;
struct StringData { class StringData {
// TODO - Hook this class up in the BSON machinery public:
// There are two assumptions here that we may want to review then.
// 'data' *always* finishes with a null terminator
// 'size' does *not* account for the null terminator
// These assumptions may make it easier to minimize changes to exis
ting code
const char* const data;
const unsigned size;
StringData( const char* c ) StringData( const char* c )
: data(c), size(strlen(c)) {} : _data(c), _size((unsigned) strlen(c)) {}
StringData( const string& s ) StringData( const string& s )
: data(s.c_str()), size(s.size()) {} : _data(s.c_str()), _size((unsigned) s.size()) {}
struct LiteralTag {}; struct LiteralTag {};
template<size_t N> template<size_t N>
StringData( const char (&val)[N], LiteralTag ) StringData( const char (&val)[N], LiteralTag )
: data(&val[0]), size(N-1) {} : _data(&val[0]), _size(N-1) {}
const char* const data() const { return _data; }
const unsigned size() const { return _size; }
private:
// TODO - Hook this class up in the BSON machinery
// There are two assumptions here that we may want to review then.
// '_data' *always* finishes with a null terminator
// 'size' does *not* account for the null terminator
// These assumptions may make it easier to minimize changes to exis
ting code
const char* const _data;
const unsigned _size;
}; };
} // namespace mongo } // namespace mongo
#endif // UTIL_BSON_STRINGDATA_HEADER #endif // BSON_STRINGDATA_HEADER
 End of changes. 6 change blocks. 
15 lines changed or deleted 20 lines changed or added


 syncclusterconnection.h   syncclusterconnection.h 
skipping to change at line 61 skipping to change at line 61
*/ */
bool prepare( string& errmsg ); bool prepare( string& errmsg );
/** /**
* runs fsync on all servers * runs fsync on all servers
*/ */
bool fsync( string& errmsg ); bool fsync( string& errmsg );
// --- from DBClientInterface // --- from DBClientInterface
virtual BSONObj findOne(const string &ns, Query query, const BSONOb j *fieldsToReturn, int queryOptions); virtual BSONObj findOne(const string &ns, const Query& query, const BSONObj *fieldsToReturn, int queryOptions);
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn, int nToSkip, virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn, int nToSkip,
const BSONObj *fieldsToRetur n, int queryOptions, int batchSize ); const BSONObj *fieldsToRetur n, int queryOptions, int batchSize );
virtual auto_ptr<DBClientCursor> getMore( const string &ns, long lo ng cursorId, int nToReturn, int options ); virtual auto_ptr<DBClientCursor> getMore( const string &ns, long lo ng cursorId, int nToReturn, int options );
virtual void insert( const string &ns, BSONObj obj ); virtual void insert( const string &ns, BSONObj obj );
virtual void insert( const string &ns, const vector< BSONObj >& v ) ; virtual void insert( const string &ns, const vector< BSONObj >& v ) ;
skipping to change at line 88 skipping to change at line 88
virtual void sayPiggyBack( Message &toSend ); virtual void sayPiggyBack( Message &toSend );
virtual void killCursor( long long cursorID ); virtual void killCursor( long long cursorID );
virtual string getServerAddress() const { return _address; } virtual string getServerAddress() const { return _address; }
virtual bool isFailed() const { return false; } virtual bool isFailed() const { return false; }
virtual string toString() { return _toString(); } virtual string toString() { return _toString(); }
virtual BSONObj getLastErrorDetailed(); virtual BSONObj getLastErrorDetailed();
virtual bool callRead( Message& toSend , Message& response );
private: private:
SyncClusterConnection( SyncClusterConnection& prev ); SyncClusterConnection( SyncClusterConnection& prev );
string _toString() const; string _toString() const;
bool _commandOnActive(const string &dbname, const BSONObj& cmd, BSO NObj &info, int options=0); bool _commandOnActive(const string &dbname, const BSONObj& cmd, BSO NObj &info, int options=0);
auto_ptr<DBClientCursor> _queryOnActive(const string &ns, Query que ry, int nToReturn, int nToSkip, auto_ptr<DBClientCursor> _queryOnActive(const string &ns, Query que ry, int nToReturn, int nToSkip,
const BSONObj *fieldsToRetu rn, int queryOptions, int batchSize ); const BSONObj *fieldsToRetu rn, int queryOptions, int batchSize );
int _lockType( const string& name ); int _lockType( const string& name );
void _checkLast(); void _checkLast();
void _connect( string host ); void _connect( string host );
 End of changes. 2 change blocks. 
1 lines changed or deleted 3 lines changed or added


 util.h   util.h 
skipping to change at line 83 skipping to change at line 83
bool isSet() const { bool isSet() const {
return _combined > 0; return _combined > 0;
} }
string toString() const { string toString() const {
stringstream ss; stringstream ss;
ss << _major << "|" << _minor; ss << _major << "|" << _minor;
return ss.str(); return ss.str();
} }
operator unsigned long long() const { return _combined; } operator unsigned long long() const { return _combined; }
operator string() const { return toString(); }
ShardChunkVersion& operator=( const BSONElement& elem ){ ShardChunkVersion& operator=( const BSONElement& elem ){
switch ( elem.type() ){ switch ( elem.type() ){
case Timestamp: case Timestamp:
case NumberLong: case NumberLong:
case Date: case Date:
_combined = elem._numberLong(); _combined = elem._numberLong();
break; break;
case EOO: case EOO:
_combined = 0; _combined = 0;
skipping to change at line 112 skipping to change at line 111
inline ostream& operator<<( ostream &s , const ShardChunkVersion& v){ inline ostream& operator<<( ostream &s , const ShardChunkVersion& v){
s << v._major << "|" << v._minor; s << v._major << "|" << v._minor;
return s; return s;
} }
/** /**
* your config info for a given shard/chunk is out of date * your config info for a given shard/chunk is out of date
*/ */
class StaleConfigException : public AssertionException { class StaleConfigException : public AssertionException {
public: public:
StaleConfigException( const string& ns , const string& raw) StaleConfigException( const string& ns , const string& raw , bool j
: AssertionException( (string)"ns: " + ns + " " + raw , 9996 ){ ustConnection = false )
: AssertionException( (string)"ns: " + ns + " " + raw , 9996 )
,
_justConnection(justConnection) ,
_ns(ns){
} }
virtual ~StaleConfigException() throw(){} virtual ~StaleConfigException() throw(){}
virtual void appendPrefix( stringstream& ss ) const { ss << "StaleC onfigException: "; } virtual void appendPrefix( stringstream& ss ) const { ss << "StaleC onfigException: "; }
bool justConnection() const { return _justConnection; }
string getns() const { return _ns; }
static bool parse( const string& big , string& ns , string& raw ){
string::size_type start = big.find( '[' );
if ( start == string::npos )
return false;
string::size_type end = big.find( ']' ,start );
if ( end == string::npos )
return false;
ns = big.substr( start + 1 , ( end - start ) - 1 );
raw = big.substr( end + 1 );
return true;
}
private: private:
bool _justConnection;
string _ns;
}; };
bool checkShardVersion( DBClientBase & conn , const string& ns , bool a uthoritative = false , int tryNumber = 1 ); bool checkShardVersion( DBClientBase & conn , const string& ns , bool a uthoritative = false , int tryNumber = 1 );
} }
 End of changes. 4 change blocks. 
3 lines changed or deleted 25 lines changed or added


 v8_db.h   v8_db.h 
skipping to change at line 51 skipping to change at line 51
v8::Handle<v8::Value> mongoConsExternal(const v8::Arguments& args); v8::Handle<v8::Value> mongoConsExternal(const v8::Arguments& args);
v8::Handle<v8::Value> mongoFind(const v8::Arguments& args); v8::Handle<v8::Value> mongoFind(const v8::Arguments& args);
v8::Handle<v8::Value> mongoInsert(const v8::Arguments& args); v8::Handle<v8::Value> mongoInsert(const v8::Arguments& args);
v8::Handle<v8::Value> mongoRemove(const v8::Arguments& args); v8::Handle<v8::Value> mongoRemove(const v8::Arguments& args);
v8::Handle<v8::Value> mongoUpdate(const v8::Arguments& args); v8::Handle<v8::Value> mongoUpdate(const v8::Arguments& args);
v8::Handle<v8::Value> internalCursorCons(const v8::Arguments& args); v8::Handle<v8::Value> internalCursorCons(const v8::Arguments& args);
v8::Handle<v8::Value> internalCursorNext(const v8::Arguments& args); v8::Handle<v8::Value> internalCursorNext(const v8::Arguments& args);
v8::Handle<v8::Value> internalCursorHasNext(const v8::Arguments& args); v8::Handle<v8::Value> internalCursorHasNext(const v8::Arguments& args);
v8::Handle<v8::Value> internalCursorObjsLeftInBatch(const v8::Arguments & args);
// DB members // DB members
v8::Handle<v8::Value> dbInit(const v8::Arguments& args); v8::Handle<v8::Value> dbInit(const v8::Arguments& args);
v8::Handle<v8::Value> collectionInit( const v8::Arguments& args ); v8::Handle<v8::Value> collectionInit( const v8::Arguments& args );
v8::Handle<v8::Value> objectIdInit( const v8::Arguments& args ); v8::Handle<v8::Value> objectIdInit( const v8::Arguments& args );
v8::Handle<v8::Value> dbRefInit( const v8::Arguments& args ); v8::Handle<v8::Value> dbRefInit( const v8::Arguments& args );
v8::Handle<v8::Value> dbPointerInit( const v8::Arguments& args ); v8::Handle<v8::Value> dbPointerInit( const v8::Arguments& args );
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 value.h   value.h 
skipping to change at line 44 skipping to change at line 44
Atomic<T>() { } Atomic<T>() { }
void operator=(const T& a) { void operator=(const T& a) {
scoped_lock lk(_atomicMutex); scoped_lock lk(_atomicMutex);
val = a; } val = a; }
operator T() const { operator T() const {
scoped_lock lk(_atomicMutex); scoped_lock lk(_atomicMutex);
return val; } return val; }
/** example:
Atomic<int> q;
...
{
Atomic<int>::tran t(q);
if( q.ref() > 0 )
q.ref()--;
}
*/
class tran : private scoped_lock { class tran : private scoped_lock {
Atomic<T>& _a; Atomic<T>& _a;
public: public:
tran(Atomic<T>& a) : scoped_lock(_atomicMutex), _a(a) { } tran(Atomic<T>& a) : scoped_lock(_atomicMutex), _a(a) { }
T& ref() { return _a.val; } T& ref() { return _a.val; }
}; };
}; };
/** this string COULD be mangled but with the double buffering, assumin g writes /** this string COULD be mangled but with the double buffering, assumin g writes
are infrequent, it's unlikely. thus, this is reasonable for lockless s etting of are infrequent, it's unlikely. thus, this is reasonable for lockless s etting of
 End of changes. 1 change blocks. 
0 lines changed or deleted 9 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/