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 | |||