bson.h | bson.h | |||
---|---|---|---|---|
skipping to change at line 48 | skipping to change at line 48 | |||
#if defined(MONGO_EXPOSE_MACROS) | #if defined(MONGO_EXPOSE_MACROS) | |||
#error this header is for client programs, not the mongo database itself. i nclude jsobj.h instead. | #error this header is for client programs, not the mongo database itself. i nclude jsobj.h instead. | |||
/* because we define simplistic assert helpers here that don't pull in a bu nch of util -- so that | /* because we define simplistic assert helpers here that don't pull in a bu nch of util -- so that | |||
BSON can be used header only. | BSON can be used header only. | |||
*/ | */ | |||
#endif | #endif | |||
#include <iostream> | #include <iostream> | |||
#include <sstream> | #include <sstream> | |||
#include <boost/utility.hpp> | #include <boost/utility.hpp> | |||
#include "util/builder.h" | ||||
namespace bson { | namespace bson { | |||
using std::string; | ||||
using std::stringstream; | ||||
class assertion : public std::exception { | class assertion : public std::exception { | |||
public: | public: | |||
virtual const char* what() const throw() { return "BsonAssertion"; | assertion( unsigned u , const string& s ) | |||
} | : id( u ) , msg( s ){ | |||
mongo::StringBuilder ss; | ||||
ss << "BsonAssertion id: " << u << " " << s; | ||||
full = ss.str(); | ||||
} | ||||
virtual ~assertion() throw() {} | ||||
virtual const char* what() const throw() { return full.c_str(); } | ||||
unsigned id; | ||||
string msg; | ||||
string full; | ||||
}; | }; | |||
} | } | |||
namespace mongo { | namespace mongo { | |||
#if !defined(assert) | #if !defined(assert) | |||
inline void assert(bool expr) { | inline void assert(bool expr) { | |||
if(!expr) { | if(!expr) { | |||
std::cout << "assertion failure in bson library" << std::endl; | throw bson::assertion( 0 , "assertion failure in bson library" | |||
throw bson::assertion(); | ); | |||
} | } | |||
} | } | |||
#endif | #endif | |||
#if !defined(uassert) | #if !defined(uassert) | |||
inline void uasserted(unsigned msgid, std::string) { | inline void uasserted(unsigned msgid, std::string s) { | |||
throw bson::assertion(); | throw bson::assertion( msgid , s ); | |||
} | } | |||
inline void uassert(unsigned msgid, std::string msg, bool expr) { | inline void uassert(unsigned msgid, std::string msg, bool expr) { | |||
if( !expr ) | if( !expr ) | |||
uasserted( msgid , msg ); | uasserted( msgid , msg ); | |||
} | } | |||
inline void msgasserted(int msgid, const char *msg) { | inline void msgasserted(int msgid, const char *msg) { | |||
throw bson::assertion(); | throw bson::assertion( msgid , msg ); | |||
} | } | |||
inline void msgasserted(int msgid, const std::string &msg) { msgasserte d(msgid, msg.c_str()); } | inline void msgasserted(int msgid, const std::string &msg) { msgasserte d(msgid, msg.c_str()); } | |||
inline void massert(unsigned msgid, std::string msg, bool expr) { | inline void massert(unsigned msgid, std::string msg, bool expr) { | |||
if(!expr) { | if(!expr) { | |||
std::cout << "assertion failure in bson library: " << msgid << ' ' << msg << std::endl; | std::cout << "assertion failure in bson library: " << msgid << ' ' << msg << std::endl; | |||
throw bson::assertion(); | throw bson::assertion( msgid , msg ); | |||
} | } | |||
} | } | |||
#endif | #endif | |||
} | } | |||
#include "../bson/bsontypes.h" | #include "../bson/bsontypes.h" | |||
#include "../bson/oid.h" | #include "../bson/oid.h" | |||
#include "../bson/bsonelement.h" | #include "../bson/bsonelement.h" | |||
#include "../bson/bsonobj.h" | #include "../bson/bsonobj.h" | |||
#include "../bson/bsonmisc.h" | #include "../bson/bsonmisc.h" | |||
End of changes. 7 change blocks. | ||||
8 lines changed or deleted | 25 lines changed or added | |||
bsonelement.h | bsonelement.h | |||
---|---|---|---|---|
skipping to change at line 22 | skipping to change at line 22 | |||
* 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 <vector> | #include <vector> | |||
#include <string.h> | #include <string.h> | |||
#include "util/builder.h" | ||||
namespace bson { | namespace bson { | |||
typedef mongo::BSONElement be; | typedef mongo::BSONElement be; | |||
typedef mongo::BSONObj bo; | typedef mongo::BSONObj bo; | |||
typedef mongo::BSONObjBuilder bob; | typedef mongo::BSONObjBuilder bob; | |||
} | } | |||
namespace mongo { | namespace mongo { | |||
class OpTime; | class OpTime; | |||
skipping to change at line 88 | skipping to change at line 89 | |||
void Val(int& v) const { v = Int(); } | void Val(int& v) const { v = Int(); } | |||
void Val(double& v) const { v = Double(); } | void Val(double& v) const { v = Double(); } | |||
void Val(string& v) const { v = String(); } | void Val(string& v) const { v = String(); } | |||
/** Use ok() to check if a value is assigned: | /** Use ok() to check if a value is assigned: | |||
if( myObj["foo"].ok() ) ... | if( myObj["foo"].ok() ) ... | |||
*/ | */ | |||
bool ok() const { return !eoo(); } | bool ok() const { return !eoo(); } | |||
string toString( bool includeFieldName = true, bool full=false) const; | string toString( bool includeFieldName = true, bool full=false) const; | |||
operator string() const { return toString(); } | void toString(StringBuilder& s, bool includeFieldName = true, bool full =false) const; | |||
string jsonString( JsonStringFormat format, bool includeFieldNames = tr ue, int pretty = 0 ) const; | string jsonString( JsonStringFormat format, bool includeFieldNames = tr ue, int pretty = 0 ) const; | |||
operator string() const { return toString(); } | ||||
/** Returns the type of the element */ | /** Returns the type of the element */ | |||
BSONType type() const { return (BSONType) *data; } | BSONType type() const { return (BSONType) *data; } | |||
/** retrieve a field within this element | /** retrieve a field within this element | |||
throws exception if *this is not an embedded object | throws exception if *this is not an embedded object | |||
*/ | */ | |||
BSONElement operator[] (const string& field) const; | BSONElement operator[] (const string& field) const; | |||
/** returns the tyoe of the element fixed for the main type | /** returns the tyoe of the element fixed for the main type | |||
skipping to change at line 392 | skipping to change at line 394 | |||
if ( fieldNameSize_ == -1 ) | if ( fieldNameSize_ == -1 ) | |||
fieldNameSize_ = (int)strlen( fieldName() ) + 1; | fieldNameSize_ = (int)strlen( fieldName() ) + 1; | |||
return fieldNameSize_; | return fieldNameSize_; | |||
} | } | |||
mutable int totalSize; /* caches the computed size */ | mutable int totalSize; /* caches the computed size */ | |||
friend class BSONObjIterator; | friend class BSONObjIterator; | |||
friend class BSONObj; | friend class BSONObj; | |||
const BSONElement& chk(int t) const { | const BSONElement& chk(int t) const { | |||
if ( t != type() ){ | if ( t != type() ){ | |||
stringstream ss; | StringBuilder ss; | |||
ss << "wrong type for BSONElement (" << fieldName() << ") " << type() << " != " << t; | ss << "wrong type for BSONElement (" << fieldName() << ") " << type() << " != " << t; | |||
uasserted(13111, ss.str() ); | uasserted(13111, ss.str() ); | |||
} | } | |||
return *this; | return *this; | |||
} | } | |||
const BSONElement& chk(bool expr) const { | const BSONElement& chk(bool expr) const { | |||
uassert(13118, "unexpected or missing type value in BSON object", e xpr); | uassert(13118, "unexpected or missing type value in BSON object", e xpr); | |||
return *this; | return *this; | |||
} | } | |||
}; | }; | |||
End of changes. 4 change blocks. | ||||
2 lines changed or deleted | 4 lines changed or added | |||
bsoninlines.h | bsoninlines.h | |||
---|---|---|---|---|
skipping to change at line 22 | skipping to change at line 22 | |||
* 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 <map> | #include <map> | |||
#include "util/atomic_int.h" | #include "util/atomic_int.h" | |||
#include "util/misc.h" | ||||
#include "../util/hex.h" | #include "../util/hex.h" | |||
namespace mongo { | namespace mongo { | |||
inline BSONObjIterator BSONObj::begin() { | inline BSONObjIterator BSONObj::begin() { | |||
return BSONObjIterator(*this); | return BSONObjIterator(*this); | |||
} | } | |||
inline BSONObj BSONElement::embeddedObjectUserCheck() const { | inline BSONObj BSONElement::embeddedObjectUserCheck() const { | |||
uassert( 10065 , "invalid parameter: expected an object", isABSONO bj() ); | uassert( 10065 , "invalid parameter: expected an object", isABSONO bj() ); | |||
skipping to change at line 215 | skipping to change at line 216 | |||
inline BSONSortedElements bson2set( const BSONObj& obj ){ | inline BSONSortedElements bson2set( const BSONObj& obj ){ | |||
BSONSortedElements s; | BSONSortedElements s; | |||
BSONObjIterator it(obj); | BSONObjIterator it(obj); | |||
while ( it.more() ) | while ( it.more() ) | |||
s.insert( it.next() ); | s.insert( it.next() ); | |||
return s; | return s; | |||
} | } | |||
inline string BSONObj::toString( bool isArray, bool full ) const { | inline string BSONObj::toString( bool isArray, bool full ) const { | |||
if ( isEmpty() ) return "{}"; | if ( isEmpty() ) return "{}"; | |||
StringBuilder s; | ||||
toString(s, isArray, full); | ||||
return s.str(); | ||||
} | ||||
inline void BSONObj::toString(StringBuilder& s, bool isArray, bool ful | ||||
l ) const { | ||||
if ( isEmpty() ){ | ||||
s << "{}"; | ||||
return; | ||||
} | ||||
stringstream s; | ||||
s << ( isArray ? "[ " : "{ " ); | s << ( isArray ? "[ " : "{ " ); | |||
BSONObjIterator i(*this); | BSONObjIterator i(*this); | |||
bool first = true; | bool first = true; | |||
while ( 1 ) { | while ( 1 ) { | |||
massert( 10327 , "Object does not end with EOO", i.moreWithEOO () ); | massert( 10327 , "Object does not end with EOO", i.moreWithEOO () ); | |||
BSONElement e = i.next( true ); | BSONElement e = i.next( true ); | |||
massert( 10328 , "Invalid element size", e.size() > 0 ); | massert( 10328 , "Invalid element size", e.size() > 0 ); | |||
massert( 10329 , "Element too large", e.size() < ( 1 << 30 ) ) ; | massert( 10329 , "Element too large", e.size() < ( 1 << 30 ) ) ; | |||
int offset = (int) (e.rawdata() - this->objdata()); | int offset = (int) (e.rawdata() - this->objdata()); | |||
massert( 10330 , "Element extends past end of object", | massert( 10330 , "Element extends past end of object", | |||
skipping to change at line 238 | skipping to change at line 247 | |||
e.validate(); | e.validate(); | |||
bool end = ( e.size() + offset == this->objsize() ); | bool end = ( e.size() + offset == this->objsize() ); | |||
if ( e.eoo() ) { | if ( e.eoo() ) { | |||
massert( 10331 , "EOO Before end of object", end ); | massert( 10331 , "EOO Before end of object", end ); | |||
break; | break; | |||
} | } | |||
if ( first ) | if ( first ) | |||
first = false; | first = false; | |||
else | else | |||
s << ", "; | s << ", "; | |||
s << e.toString( !isArray, full ); | e.toString(s, !isArray, full ); | |||
} | } | |||
s << ( isArray ? " ]" : " }" ); | s << ( isArray ? " ]" : " }" ); | |||
return s.str(); | ||||
} | } | |||
extern unsigned getRandomNumber(); | extern unsigned getRandomNumber(); | |||
inline void BSONElement::validate() const { | inline void BSONElement::validate() const { | |||
const BSONType t = type(); | const BSONType t = type(); | |||
switch( t ) { | switch( t ) { | |||
case DBRef: | case DBRef: | |||
case Code: | case Code: | |||
case Symbol: | case Symbol: | |||
case mongo::String: { | case mongo::String: { | |||
int x = valuestrsize(); | int x = valuestrsize(); | |||
if ( t == mongo::String && x + fieldNameSize() + 5 != size() ){ | ||||
StringBuilder buf; | ||||
buf << "Invalid string size. element size: " << size() << | ||||
" fieldNameSize: " << fieldNameSize() << " valuestrsize(): " << valuestrsi | ||||
ze(); | ||||
cout << "ELIOT : " << buf.str() << endl; | ||||
msgasserted( 13292 , buf.str() ); | ||||
} | ||||
if ( x > 0 && valuestr()[x-1] == 0 ) | if ( x > 0 && valuestr()[x-1] == 0 ) | |||
return; | return; | |||
StringBuilder buf; | StringBuilder buf; | |||
buf << "Invalid dbref/code/string/symbol size: " << x << " str nlen:" << strnlen( valuestr() , x ); | buf << "Invalid dbref/code/string/symbol size: " << x << " str nlen:" << mongo::strnlen( valuestr() , x ); | |||
msgasserted( 10321 , buf.str() ); | msgasserted( 10321 , buf.str() ); | |||
break; | break; | |||
} | } | |||
case CodeWScope: { | case CodeWScope: { | |||
int totalSize = *( int * )( value() ); | int totalSize = *( int * )( value() ); | |||
massert( 10322 , "Invalid CodeWScope size", totalSize >= 8 ); | massert( 10322 , "Invalid CodeWScope size", totalSize >= 8 ); | |||
int strSizeWNull = *( int * )( value() + 4 ); | int strSizeWNull = *( int * )( value() + 4 ); | |||
massert( 10323 , "Invalid CodeWScope string size", totalSize > = strSizeWNull + 4 + 4 ); | massert( 10323 , "Invalid CodeWScope string size", totalSize > = strSizeWNull + 4 + 4 ); | |||
massert( 10324 , "Invalid CodeWScope string size", | massert( 10324 , "Invalid CodeWScope string size", | |||
strSizeWNull > 0 && | strSizeWNull > 0 && | |||
(strSizeWNull - 1) == strnlen( codeWScopeCode(), strSi zeWNull ) ); | (strSizeWNull - 1) == mongo::strnlen( codeWScopeCode() , strSizeWNull ) ); | |||
massert( 10325 , "Invalid CodeWScope size", totalSize >= strSi zeWNull + 4 + 4 + 4 ); | massert( 10325 , "Invalid CodeWScope size", totalSize >= strSi zeWNull + 4 + 4 + 4 ); | |||
int objSize = *( int * )( value() + 4 + 4 + strSizeWNull ); | int objSize = *( int * )( value() + 4 + 4 + strSizeWNull ); | |||
massert( 10326 , "Invalid CodeWScope object size", totalSize = = 4 + 4 + strSizeWNull + objSize ); | massert( 10326 , "Invalid CodeWScope object size", totalSize = = 4 + 4 + strSizeWNull + objSize ); | |||
// Subobject validation handled elsewhere. | // Subobject validation handled elsewhere. | |||
} | } | |||
case Object: | case Object: | |||
// We expect Object size validation to be handled elsewhere. | // We expect Object size validation to be handled elsewhere. | |||
default: | default: | |||
break; | break; | |||
} | } | |||
skipping to change at line 345 | skipping to change at line 346 | |||
massert( 10316 , "Insufficient bytes to calculate element size ", maxLen == -1 || remain > 3 ); | massert( 10316 , "Insufficient bytes to calculate element size ", maxLen == -1 || remain > 3 ); | |||
x = objsize(); | x = objsize(); | |||
break; | break; | |||
case BinData: | case BinData: | |||
massert( 10317 , "Insufficient bytes to calculate element size ", maxLen == -1 || remain > 3 ); | massert( 10317 , "Insufficient bytes to calculate element size ", maxLen == -1 || remain > 3 ); | |||
x = valuestrsize() + 4 + 1/*subtype*/; | x = valuestrsize() + 4 + 1/*subtype*/; | |||
break; | break; | |||
case RegEx: | case RegEx: | |||
{ | { | |||
const char *p = value(); | const char *p = value(); | |||
size_t len1 = ( maxLen == -1 ) ? strlen( p ) : strnlen( p, rema in ); | size_t len1 = ( maxLen == -1 ) ? strlen( p ) : mongo::strnlen( p, remain ); | |||
//massert( 10318 , "Invalid regex string", len1 != -1 ); // ER H - 4/28/10 - don't think this does anything | //massert( 10318 , "Invalid regex string", len1 != -1 ); // ER H - 4/28/10 - don't think this does anything | |||
p = p + len1 + 1; | p = p + len1 + 1; | |||
size_t len2 = ( maxLen == -1 ) ? strlen( p ) : strnlen( p, rema in - len1 - 1 ); | size_t len2 = ( maxLen == -1 ) ? strlen( p ) : mongo::strnlen( p, remain - len1 - 1 ); | |||
//massert( 10319 , "Invalid regex options string", len2 != -1 ); // ERH - 4/28/10 - don't think this does anything | //massert( 10319 , "Invalid regex options string", len2 != -1 ); // ERH - 4/28/10 - don't think this does anything | |||
x = (int) (len1 + 1 + len2 + 1); | x = (int) (len1 + 1 + len2 + 1); | |||
} | } | |||
break; | break; | |||
default: { | default: { | |||
stringstream ss; | StringBuilder ss; | |||
ss << "BSONElement: bad type " << (int) type(); | ss << "BSONElement: bad type " << (int) type(); | |||
string msg = ss.str(); | string msg = ss.str(); | |||
massert( 10320 , msg.c_str(),false); | massert( 10320 , msg.c_str(),false); | |||
} | } | |||
} | } | |||
totalSize = x + fieldNameSize() + 1; // BSONType | totalSize = x + fieldNameSize() + 1; // BSONType | |||
return totalSize; | return totalSize; | |||
} | } | |||
inline string BSONElement::toString( bool includeFieldName, bool full ) const { | inline string BSONElement::toString( bool includeFieldName, bool full ) const { | |||
stringstream s; | StringBuilder s; | |||
toString(s, includeFieldName, full); | ||||
return s.str(); | ||||
} | ||||
inline void BSONElement::toString(StringBuilder& s, bool includeFieldNa | ||||
me, bool full ) const { | ||||
if ( includeFieldName && type() != EOO ) | if ( includeFieldName && type() != EOO ) | |||
s << fieldName() << ": "; | s << fieldName() << ": "; | |||
switch ( type() ) { | switch ( type() ) { | |||
case EOO: | case EOO: | |||
return "EOO"; | s << "EOO"; | |||
break; | ||||
case mongo::Date: | case mongo::Date: | |||
s << "new Date(" << date() << ')'; | s << "new Date(" << date() << ')'; | |||
break; | break; | |||
case RegEx: | case RegEx: | |||
{ | { | |||
s << "/" << regex() << '/'; | s << "/" << regex() << '/'; | |||
const char *p = regexFlags(); | const char *p = regexFlags(); | |||
if ( p ) s << p; | if ( p ) s << p; | |||
} | } | |||
break; | break; | |||
skipping to change at line 404 | skipping to change at line 410 | |||
case NumberLong: | case NumberLong: | |||
s << _numberLong(); | s << _numberLong(); | |||
break; | break; | |||
case NumberInt: | case NumberInt: | |||
s << _numberInt(); | s << _numberInt(); | |||
break; | break; | |||
case mongo::Bool: | case mongo::Bool: | |||
s << ( boolean() ? "true" : "false" ); | s << ( boolean() ? "true" : "false" ); | |||
break; | break; | |||
case Object: | case Object: | |||
s << embeddedObject().toString(false, full); | embeddedObject().toString(s, false, full); | |||
break; | break; | |||
case mongo::Array: | case mongo::Array: | |||
s << embeddedObject().toString(true, full); | embeddedObject().toString(s, true, full); | |||
break; | break; | |||
case Undefined: | case Undefined: | |||
s << "undefined"; | s << "undefined"; | |||
break; | break; | |||
case jstNULL: | case jstNULL: | |||
s << "null"; | s << "null"; | |||
break; | break; | |||
case MaxKey: | case MaxKey: | |||
s << "MaxKey"; | s << "MaxKey"; | |||
break; | break; | |||
skipping to change at line 470 | skipping to change at line 476 | |||
s << '(' << binDataType() << ", " << toHex(data, len) << ') '; | s << '(' << binDataType() << ", " << toHex(data, len) << ') '; | |||
} | } | |||
break; | break; | |||
case Timestamp: | case Timestamp: | |||
s << "Timestamp " << timestampTime() << "|" << timestampInc(); | s << "Timestamp " << timestampTime() << "|" << timestampInc(); | |||
break; | break; | |||
default: | default: | |||
s << "?type=" << type(); | s << "?type=" << type(); | |||
break; | break; | |||
} | } | |||
return s.str(); | ||||
} | } | |||
/* 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 | |||
*/ | */ | |||
inline BSONElement BSONObj::getFieldDotted(const char *name) const { | inline BSONElement BSONObj::getFieldDotted(const char *name) const { | |||
BSONElement e = getField( name ); | BSONElement e = getField( name ); | |||
if ( e.eoo() ) { | if ( e.eoo() ) { | |||
const char *p = strchr(name, '.'); | const char *p = strchr(name, '.'); | |||
if ( p ) { | if ( p ) { | |||
End of changes. 16 change blocks. | ||||
22 lines changed or deleted | 27 lines changed or added | |||
bsonobj.h | bsonobj.h | |||
---|---|---|---|---|
skipping to change at line 92 | skipping to change at line 92 | |||
void appendSelfToBufBuilder(BufBuilder& b) const { | void appendSelfToBufBuilder(BufBuilder& b) const { | |||
assert( objsize() ); | assert( objsize() ); | |||
b.appendBuf(reinterpret_cast<const void *>( objdata() ), objsiz e()); | 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; | |||
void toString(StringBuilder& s, bool isArray = false, bool full=fal se ) const; | ||||
/** 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 145 | skipping to change at line 146 | |||
*/ | */ | |||
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); | |||
} | } | |||
BSONElement operator[] (int field) const { | BSONElement operator[] (int field) const { | |||
stringstream ss; | StringBuilder ss; | |||
ss << field; | ss << field; | |||
string s = ss.str(); | string s = ss.str(); | |||
return getField(s.c_str()); | return getField(s.c_str()); | |||
} | } | |||
/** @return true if field exists */ | /** @return true if field exists */ | |||
bool hasField( const char * name )const { | bool hasField( const char * name )const { | |||
return ! getField( name ).eoo(); | return ! getField( name ).eoo(); | |||
} | } | |||
skipping to change at line 370 | skipping to change at line 371 | |||
private: | private: | |||
const char *_objdata; | const char *_objdata; | |||
}; | }; | |||
const char *_objdata; | const char *_objdata; | |||
boost::shared_ptr< Holder > _holder; | boost::shared_ptr< Holder > _holder; | |||
void init(const char *data, bool ifree) { | void init(const char *data, bool ifree) { | |||
if ( ifree ) | if ( ifree ) | |||
_holder.reset( new Holder( data ) ); | _holder.reset( new Holder( data ) ); | |||
_objdata = data; | _objdata = data; | |||
if ( ! isValid() ){ | if ( ! isValid() ){ | |||
stringstream ss; | StringBuilder ss; | |||
ss << "Invalid BSONObj spec size: " << objsize() << " (" << | int os = objsize(); | |||
hex << objsize() << dec << ")"; | ss << "Invalid BSONObj spec size: " << os << " (" << toHex( | |||
&os, 4 ) << ")"; | ||||
try { | try { | |||
BSONElement e = firstElement(); | BSONElement e = firstElement(); | |||
ss << " first element:" << e.toString() << " "; | ss << " first element:" << e.toString() << " "; | |||
} | } | |||
catch ( ... ){} | catch ( ... ){} | |||
string s = ss.str(); | string s = ss.str(); | |||
massert( 10334 , s , 0 ); | massert( 10334 , s , 0 ); | |||
} | } | |||
} | } | |||
}; | }; | |||
End of changes. 3 change blocks. | ||||
4 lines changed or deleted | 6 lines changed or added | |||
bsonobjbuilder.h | bsonobjbuilder.h | |||
---|---|---|---|---|
skipping to change at line 130 | skipping to change at line 130 | |||
} | } | |||
/** add a subobject as a member */ | /** add a subobject as a member */ | |||
BSONObjBuilder& append(const StringData& fieldName, BSONObj subObj) { | BSONObjBuilder& append(const StringData& fieldName, BSONObj subObj) { | |||
_b.appendNum((char) Object); | _b.appendNum((char) Object); | |||
_b.appendStr(fieldName); | _b.appendStr(fieldName); | |||
_b.appendBuf((void *) subObj.objdata(), subObj.objsize()); | _b.appendBuf((void *) subObj.objdata(), subObj.objsize()); | |||
return *this; | return *this; | |||
} | } | |||
/** add a subobject as a member */ | ||||
BSONObjBuilder& appendObject(const StringData& fieldName, const cha | ||||
r * objdata , int size = 0 ){ | ||||
assert( objdata ); | ||||
if ( size == 0 ){ | ||||
size = *((int*)objdata); | ||||
} | ||||
assert( size > 4 && size < 100000000 ); | ||||
_b.appendNum((char) Object); | ||||
_b.appendStr(fieldName); | ||||
_b.appendBuf((void*)objdata, size ); | ||||
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 StringData& fieldName) { | BufBuilder &subobjStart(const StringData& fieldName) { | |||
_b.appendNum((char) Object); | _b.appendNum((char) Object); | |||
_b.appendStr(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. | |||
skipping to change at line 511 | skipping to change at line 526 | |||
/** Fetch the object we have built. | /** Fetch the object we have built. | |||
BSONObjBuilder still frees the object when the build er goes out of | BSONObjBuilder still frees the object when the build er goes out of | |||
scope -- very important to keep in mind. Use obj() if you | scope -- very important to keep in mind. Use obj() if you | |||
would like the BSONObj to last longer than the build er. | would like the BSONObj to last longer than the build er. | |||
*/ | */ | |||
BSONObj done() { | BSONObj done() { | |||
return BSONObj(_done()); | return BSONObj(_done()); | |||
} | } | |||
// Like 'done' above, but does not construct a BSONObj to return to | ||||
the caller. | ||||
void doneFast() { | ||||
(void)_done(); | ||||
} | ||||
/** Peek at what is in the builder, but leave the builder ready for more appends. | /** Peek at what is in the builder, but leave the builder ready for more appends. | |||
The returned object is only valid until the next modification o r destruction of the builder. | The returned object is only valid until the next modification o r destruction of the builder. | |||
Intended use case: append a field if not already there. | Intended use case: append a field if not already there. | |||
*/ | */ | |||
BSONObj asTempObj() { | BSONObj asTempObj() { | |||
BSONObj temp(_done()); | BSONObj temp(_done()); | |||
_b.setlen(_b.len()-1); //next append should overwrite the EOO | _b.setlen(_b.len()-1); //next append should overwrite the EOO | |||
_doneCalled = false; | _doneCalled = false; | |||
return temp; | return temp; | |||
} | } | |||
skipping to change at line 539 | skipping to change at line 559 | |||
} | } | |||
void decouple() { | void decouple() { | |||
_b.decouple(); // post done() call version. be sure jsobj f rees... | _b.decouple(); // post done() call version. be sure jsobj f rees... | |||
} | } | |||
void appendKeys( const BSONObj& keyPattern , const BSONObj& values ); | void appendKeys( const BSONObj& keyPattern , const BSONObj& values ); | |||
static string numStr( int i ) { | static string numStr( int i ) { | |||
if (i>=0 && i<100) | if (i>=0 && i<100) | |||
return numStrs[i]; | return numStrs[i]; | |||
stringstream o; | StringBuilder o; | |||
o << i; | o << i; | |||
return o.str(); | return o.str(); | |||
} | } | |||
/** Stream oriented way to add field names and values. */ | /** Stream oriented way to add field names and values. */ | |||
BSONObjBuilderValueStream &operator<<(const char * name ) { | BSONObjBuilderValueStream &operator<<(const char * name ) { | |||
_s.endField( name ); | _s.endField( name ); | |||
return _s; | return _s; | |||
} | } | |||
skipping to change at line 641 | skipping to change at line 661 | |||
} | } | |||
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(); } | |||
void doneFast() { _b.doneFast(); } | ||||
template <typename T> | template <typename T> | |||
BSONArrayBuilder& append(const StringData& name, const T& x){ | BSONArrayBuilder& append(const StringData& name, const T& x){ | |||
fill( name ); | fill( name ); | |||
append( x ); | append( x ); | |||
return *this; | return *this; | |||
} | } | |||
BufBuilder &subobjStart( const char *name = "0" ) { | BufBuilder &subobjStart( const char *name = "0" ) { | |||
fill( name ); | fill( name ); | |||
return _b.subobjStart( num().c_str() ); | return _b.subobjStart( num().c_str() ); | |||
skipping to change at line 672 | skipping to change at line 694 | |||
void appendAs( const BSONElement &e, const char *name ) { | void appendAs( const BSONElement &e, const char *name ) { | |||
fill( name ); | fill( name ); | |||
append( e ); | append( e ); | |||
} | } | |||
private: | private: | |||
void fill( const StringData& name ) { | void fill( const StringData& name ) { | |||
char *r; | char *r; | |||
int n = strtol( name.data(), &r, 10 ); | int n = strtol( name.data(), &r, 10 ); | |||
uassert( 13048, (string)"can't append to array using string fie | if ( *r ) | |||
ld name [" + name.data() + "]" , !*r ); | uasserted( 13048, (string)"can't append to array using stri | |||
ng field name [" + name.data() + "]" ); | ||||
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() { | |||
End of changes. 5 change blocks. | ||||
3 lines changed or deleted | 28 lines changed or added | |||
btree.h | btree.h | |||
---|---|---|---|---|
skipping to change at line 289 | skipping to change at line 289 | |||
return !bucket.isNull(); | return !bucket.isNull(); | |||
} | } | |||
bool eof() { | bool eof() { | |||
return !ok(); | return !ok(); | |||
} | } | |||
virtual bool advance(); | virtual bool advance(); | |||
virtual void noteLocation(); // updates keyAtKeyOfs... | virtual void noteLocation(); // updates keyAtKeyOfs... | |||
virtual void checkLocation(); | virtual void checkLocation(); | |||
virtual bool supportGetMore() { return true; } | virtual bool supportGetMore() { return true; } | |||
virtual bool supportYields() { return true; } | ||||
/* used for multikey index traversal to avoid sending back dups. se e Matcher::matches(). | /* used for multikey index traversal to avoid sending back dups. se e Matcher::matches(). | |||
if a multikey index traversal: | if a multikey index traversal: | |||
if loc has already been sent, returns true. | if loc has already been sent, returns true. | |||
otherwise, marks loc as sent. | otherwise, marks loc as sent. | |||
@return true if the loc has not been seen | @return true if the loc has not been seen | |||
*/ | */ | |||
virtual bool getsetdup(DiskLoc loc) { | virtual bool getsetdup(DiskLoc loc) { | |||
if( multikey ) { | if( multikey ) { | |||
pair<set<DiskLoc>::iterator, bool> p = dups.insert(loc); | pair<set<DiskLoc>::iterator, bool> p = dups.insert(loc); | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
builder.h | builder.h | |||
---|---|---|---|---|
skipping to change at line 106 | skipping to change at line 106 | |||
*((long long*)grow(sizeof(long long))) = j; | *((long long*)grow(sizeof(long long))) = j; | |||
} | } | |||
void appendNum(unsigned long long j) { | void appendNum(unsigned long long j) { | |||
*((unsigned long long*)grow(sizeof(unsigned long long))) = j; | *((unsigned long long*)grow(sizeof(unsigned long long))) = j; | |||
} | } | |||
void appendBuf(const void *src, size_t len) { | void appendBuf(const void *src, size_t len) { | |||
memcpy(grow((int) len), src, len); | memcpy(grow((int) len), src, len); | |||
} | } | |||
void appendStr(const StringData &str) { | void appendStr(const StringData &str , bool includeEOO = true ) { | |||
const int len = str.size() + 1; | const int len = str.size() + ( includeEOO ? 1 : 0 ); | |||
memcpy(grow(len), str.data(), len); | 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; | |||
} | } | |||
skipping to change at line 188 | skipping to change at line 188 | |||
} | } | |||
StringBuilder& operator<<( short x ){ | StringBuilder& operator<<( short x ){ | |||
SBNUM( x , 8 , "%hd" ); | SBNUM( x , 8 , "%hd" ); | |||
} | } | |||
StringBuilder& operator<<( char c ){ | StringBuilder& operator<<( char c ){ | |||
_buf.grow( 1 )[0] = c; | _buf.grow( 1 )[0] = c; | |||
return *this; | return *this; | |||
} | } | |||
#undef SBNUM | #undef SBNUM | |||
void append( const char * str ){ | void write( const char* buf, int len){ | |||
int x = (int) strlen( str ); | memcpy( _buf.grow( len ) , buf , len ); | |||
memcpy( _buf.grow( x ) , str , x ); | ||||
} | } | |||
StringBuilder& operator<<( const char * str ){ | ||||
append( str ); | void append( const StringData& str ){ | |||
return *this; | memcpy( _buf.grow( str.size() ) , str.data() , str.size() ); | |||
} | } | |||
StringBuilder& operator<<( const std::string& s ){ | StringBuilder& operator<<( const StringData& str ){ | |||
append( s.c_str() ); | append( str ); | |||
return *this; | return *this; | |||
} | } | |||
// access | // access | |||
void reset( int maxSize = 0 ){ | void reset( int maxSize = 0 ){ | |||
_buf.reset( maxSize ); | _buf.reset( maxSize ); | |||
} | } | |||
std::string str(){ | std::string str(){ | |||
End of changes. 4 change blocks. | ||||
10 lines changed or deleted | 9 lines changed or added | |||
clientcursor.h | clientcursor.h | |||
---|---|---|---|---|
skipping to change at line 201 | skipping to change at line 201 | |||
static int yieldSuggest(); | static int yieldSuggest(); | |||
static void staticYield( int micros ); | static void staticYield( int micros ); | |||
struct YieldData { CursorId _id; bool _doingDeletes; }; | struct YieldData { CursorId _id; bool _doingDeletes; }; | |||
void prepareToYield( YieldData &data ); | void prepareToYield( YieldData &data ); | |||
static bool recoverFromYield( const YieldData &data ); | static bool recoverFromYield( const YieldData &data ); | |||
struct YieldLock : boost::noncopyable { | struct YieldLock : boost::noncopyable { | |||
explicit YieldLock( ptr<ClientCursor> cc ) | explicit YieldLock( ptr<ClientCursor> cc ) | |||
: _cc( cc ) , _id( cc->cursorid ) , _doingDeletes( cc->_doi | : _cc( cc ) , _id( cc->cursorid ) , _doingDeletes( cc->_doi | |||
ngDeletes ) { | ngDeletes ), _canYield(cc->c->supportYields()) { | |||
cc->updateLocation(); | if ( _canYield ){ | |||
_unlock.reset(new dbtempreleasecond()); | cc->updateLocation(); | |||
_unlock.reset(new dbtempreleasecond()); | ||||
} | ||||
} | } | |||
~YieldLock(){ | ~YieldLock(){ | |||
if ( _unlock ){ | if ( _unlock ){ | |||
log( LL_WARNING ) << "ClientCursor::YieldLock not close d properly" << endl; | log( LL_WARNING ) << "ClientCursor::YieldLock not close d properly" << endl; | |||
relock(); | relock(); | |||
} | } | |||
} | } | |||
bool stillOk(){ | bool stillOk(){ | |||
if ( ! _canYield ) | ||||
return true; | ||||
relock(); | relock(); | |||
if ( ClientCursor::find( _id , false ) == 0 ){ | if ( ClientCursor::find( _id , false ) == 0 ){ | |||
// i was deleted | // i was deleted | |||
return false; | return false; | |||
} | } | |||
_cc->_doingDeletes = _doingDeletes; | _cc->_doingDeletes = _doingDeletes; | |||
return true; | return true; | |||
} | } | |||
void relock(){ | void relock(){ | |||
_unlock.reset(); | if ( _canYield ) | |||
_unlock.reset(); | ||||
} | } | |||
private: | private: | |||
ClientCursor * _cc; | ClientCursor * _cc; | |||
CursorId _id; | CursorId _id; | |||
bool _doingDeletes; | bool _doingDeletes; | |||
bool _canYield; | ||||
scoped_ptr<dbtempreleasecond> _unlock; | scoped_ptr<dbtempreleasecond> _unlock; | |||
}; | }; | |||
// --- some pass through helpers for Cursor --- | // --- some pass through helpers for Cursor --- | |||
BSONObj indexKeyPattern() { | BSONObj indexKeyPattern() { | |||
return c->indexKeyPattern(); | return c->indexKeyPattern(); | |||
} | } | |||
End of changes. 4 change blocks. | ||||
5 lines changed or deleted | 12 lines changed or added | |||
cmdline.h | cmdline.h | |||
---|---|---|---|---|
skipping to change at line 28 | skipping to change at line 28 | |||
#include "../pch.h" | #include "../pch.h" | |||
namespace mongo { | namespace mongo { | |||
/* command line options | /* command line options | |||
*/ | */ | |||
/* concurrency: OK/READ */ | /* concurrency: OK/READ */ | |||
struct CmdLine { | struct CmdLine { | |||
int port; // --port | int port; // --port | |||
string bind_ip; // --bind_ip | ||||
bool rest; // --rest | bool rest; // --rest | |||
string replSet; // --replSet <seedlist> | string replSet; // --replSet <seedlist> | |||
string source; // --source | string source; // --source | |||
string only; // --only | string only; // --only | |||
bool quiet; // --quiet | bool quiet; // --quiet | |||
bool notablescan; // --notablescan | bool notablescan; // --notablescan | |||
bool prealloc; // --noprealloc | bool prealloc; // --noprealloc | |||
bool smallfiles; // --smallfiles | bool smallfiles; // --smallfiles | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
commands.h | commands.h | |||
---|---|---|---|---|
skipping to change at line 124 | skipping to change at line 124 | |||
static void logIfSlow( const Timer& cmdTimer, const string& msg); | static void logIfSlow( const Timer& cmdTimer, const string& msg); | |||
static map<string,Command*> * _commands; | static map<string,Command*> * _commands; | |||
static map<string,Command*> * _commandsByBestName; | static map<string,Command*> * _commandsByBestName; | |||
static map<string,Command*> * _webCommands; | static map<string,Command*> * _webCommands; | |||
public: | public: | |||
static const map<string,Command*>* commandsByBestName() { return _c ommandsByBestName; } | static const map<string,Command*>* commandsByBestName() { return _c ommandsByBestName; } | |||
static const map<string,Command*>* webCommands() { return _webComma nds; } | static const map<string,Command*>* webCommands() { return _webComma nds; } | |||
/** @return if command was found and executed */ | ||||
static bool runAgainstRegistered(const char *ns, BSONObj& jsobj, BS ONObjBuilder& anObjBuilder); | static bool runAgainstRegistered(const char *ns, BSONObj& jsobj, BS ONObjBuilder& anObjBuilder); | |||
static LockType locktype( const string& name ); | static LockType locktype( const string& name ); | |||
static Command * findCommand( const string& name ); | static Command * findCommand( const string& name ); | |||
}; | }; | |||
bool _runCommands(const char *ns, BSONObj& jsobj, BufBuilder &b, BSONOb jBuilder& anObjBuilder, bool fromRepl, int queryOptions); | bool _runCommands(const char *ns, BSONObj& jsobj, BufBuilder &b, BSONOb jBuilder& anObjBuilder, bool fromRepl, int queryOptions); | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
core.h | core.h | |||
---|---|---|---|---|
skipping to change at line 66 | skipping to change at line 66 | |||
}; | }; | |||
extern GeoBitSets geoBitSets; | extern GeoBitSets geoBitSets; | |||
class GeoHash { | class GeoHash { | |||
public: | public: | |||
GeoHash() | GeoHash() | |||
: _hash(0),_bits(0){ | : _hash(0),_bits(0){ | |||
} | } | |||
GeoHash( const char * hash ){ | explicit GeoHash( const char * hash ){ | |||
init( hash ); | init( hash ); | |||
} | } | |||
GeoHash( const string& hash ){ | explicit GeoHash( const string& hash ){ | |||
init( hash ); | init( hash ); | |||
} | } | |||
GeoHash( const BSONElement& e , unsigned bits=32 ){ | explicit GeoHash( const BSONElement& e , unsigned bits=32 ){ | |||
_bits = bits; | _bits = bits; | |||
if ( e.type() == BinData ){ | if ( e.type() == BinData ){ | |||
int len = 0; | int len = 0; | |||
_copy( (char*)&_hash , e.binData( len ) ); | _copy( (char*)&_hash , e.binData( len ) ); | |||
assert( len == 8 ); | assert( len == 8 ); | |||
_bits = bits; | _bits = bits; | |||
} | } | |||
else { | else { | |||
cout << "GeoHash cons e : " << e << endl; | cout << "GeoHash cons e : " << e << endl; | |||
uassert(13047,"wrong type for geo index. if you're using a pre-release version, need to rebuild index",0); | uassert(13047,"wrong type for geo index. if you're using a pre-release version, need to rebuild index",0); | |||
skipping to change at line 307 | skipping to change at line 307 | |||
void append( BSONObjBuilder& b , const char * name ) const { | void append( BSONObjBuilder& b , const char * name ) const { | |||
char buf[8]; | char buf[8]; | |||
_copy( buf , (char*)&_hash ); | _copy( buf , (char*)&_hash ); | |||
b.appendBinData( name , 8 , bdtCustom , buf ); | b.appendBinData( name , 8 , bdtCustom , buf ); | |||
} | } | |||
long long getHash() const { | long long getHash() const { | |||
return _hash; | return _hash; | |||
} | } | |||
unsigned getBits() const { | ||||
return _bits; | ||||
} | ||||
GeoHash commonPrefix( const GeoHash& other ) const { | GeoHash commonPrefix( const GeoHash& other ) const { | |||
unsigned i=0; | unsigned i=0; | |||
for ( ; i<_bits && i<other._bits; i++ ){ | for ( ; i<_bits && i<other._bits; i++ ){ | |||
if ( getBitX( i ) == other.getBitX( i ) && | if ( getBitX( i ) == other.getBitX( i ) && | |||
getBitY( i ) == other.getBitY( i ) ) | getBitY( i ) == other.getBitY( i ) ) | |||
continue; | continue; | |||
break; | break; | |||
} | } | |||
return GeoHash(_hash,i); | return GeoHash(_hash,i); | |||
} | } | |||
skipping to change at line 349 | skipping to change at line 354 | |||
virtual GeoHash hash( double x , double y ) const = 0; | virtual GeoHash hash( double x , double y ) const = 0; | |||
}; | }; | |||
class Point { | class Point { | |||
public: | public: | |||
Point( const GeoConvert * g , const GeoHash& hash ){ | Point( const GeoConvert * g , const GeoHash& hash ){ | |||
g->unhash( hash , _x , _y ); | g->unhash( hash , _x , _y ); | |||
} | } | |||
Point( const BSONElement& e ){ | explicit Point( const BSONElement& e ){ | |||
BSONObjIterator i(e.Obj()); | BSONObjIterator i(e.Obj()); | |||
_x = i.next().number(); | _x = i.next().number(); | |||
_y = i.next().number(); | _y = i.next().number(); | |||
} | } | |||
Point( const BSONObj& o ){ | explicit Point( const BSONObj& o ){ | |||
BSONObjIterator i(o); | BSONObjIterator i(o); | |||
_x = i.next().number(); | _x = i.next().number(); | |||
_y = i.next().number(); | _y = i.next().number(); | |||
} | } | |||
Point( double x , double y ) | Point( double x , double y ) | |||
: _x( x ) , _y( y ){ | : _x( x ) , _y( y ){ | |||
} | } | |||
Point() : _x(0),_y(0){ | Point() : _x(0),_y(0){ | |||
} | } | |||
GeoHash hash( const GeoConvert * g ){ | GeoHash hash( const GeoConvert * g ){ | |||
return g->hash( _x , _y ); | return g->hash( _x , _y ); | |||
} | } | |||
double distance( Point& p ) const { | double distance( const Point& p ) const { | |||
double a = _x - p._x; | double a = _x - p._x; | |||
double b = _y - p._y; | double b = _y - p._y; | |||
return sqrt( ( a * a ) + ( b * b ) ); | return sqrt( ( a * a ) + ( b * b ) ); | |||
} | } | |||
string toString() const { | string toString() const { | |||
StringBuilder buf(32); | StringBuilder buf(32); | |||
buf << "(" << _x << "," << _y << ")"; | buf << "(" << _x << "," << _y << ")"; | |||
return buf.str(); | return buf.str(); | |||
End of changes. 7 change blocks. | ||||
6 lines changed or deleted | 10 lines changed or added | |||
curop.h | curop.h | |||
---|---|---|---|---|
skipping to change at line 84 | skipping to change at line 84 | |||
_message = ""; | _message = ""; | |||
_progressMeter.finished(); | _progressMeter.finished(); | |||
} | } | |||
void setNS(const char *ns) { | void setNS(const char *ns) { | |||
strncpy(_ns, ns, Namespace::MaxNsLen); | strncpy(_ns, ns, Namespace::MaxNsLen); | |||
} | } | |||
public: | public: | |||
bool haveQuery() const { return *((int *) _queryBuf) != 0; } | int querySize() const { return *((int *) _queryBuf); } | |||
bool haveQuery() const { return querySize() != 0; } | ||||
BSONObj query() { | BSONObj query() { | |||
if( *((int *) _queryBuf) == 1 ) { | if( querySize() == 1 ) { | |||
return _tooBig; | return _tooBig; | |||
} | } | |||
BSONObj o(_queryBuf); | BSONObj o(_queryBuf); | |||
return o; | return o; | |||
} | } | |||
void ensureStarted(){ | void ensureStarted(){ | |||
if ( _start == 0 ) | if ( _start == 0 ) | |||
_start = _checkpoint = curTimeMicros64(); | _start = _checkpoint = curTimeMicros64(); | |||
} | } | |||
skipping to change at line 242 | skipping to change at line 243 | |||
BSONObj info() { | BSONObj info() { | |||
if( ! cc().getAuthenticationInfo()->isAuthorized("admin") ) { | if( ! cc().getAuthenticationInfo()->isAuthorized("admin") ) { | |||
BSONObjBuilder b; | BSONObjBuilder b; | |||
b.append("err", "unauthorized"); | b.append("err", "unauthorized"); | |||
return b.obj(); | return b.obj(); | |||
} | } | |||
return infoNoauth(); | return infoNoauth(); | |||
} | } | |||
BSONObj infoNoauth(); | BSONObj infoNoauth( int attempt = 0 ); | |||
string getRemoteString( bool includePort = true ){ | string getRemoteString( bool includePort = true ){ | |||
return _remote.toString(includePort); | return _remote.toString(includePort); | |||
} | } | |||
ProgressMeter& setMessage( const char * msg , long long progressMet erTotal = 0 , int secondsBetween = 3 ){ | ProgressMeter& setMessage( const char * msg , long long progressMet erTotal = 0 , int secondsBetween = 3 ){ | |||
if ( progressMeterTotal ){ | if ( progressMeterTotal ){ | |||
if ( _progressMeter.isActive() ){ | if ( _progressMeter.isActive() ){ | |||
cout << "about to assert, old _message: " << _message < < " new message:" << msg << endl; | cout << "about to assert, old _message: " << _message < < " new message:" << msg << endl; | |||
End of changes. 3 change blocks. | ||||
3 lines changed or deleted | 4 lines changed or added | |||
cursor.h | cursor.h | |||
---|---|---|---|---|
skipping to change at line 81 | skipping to change at line 81 | |||
/* called after every query block is iterated -- i.e. between getMo re() blocks | /* called after every query block is iterated -- i.e. between getMo re() blocks | |||
so you can note where we are, if necessary. | so you can note where we are, if necessary. | |||
*/ | */ | |||
virtual void noteLocation() { } | virtual void noteLocation() { } | |||
/* called before query getmore block is iterated */ | /* called before query getmore block is iterated */ | |||
virtual void checkLocation() { } | virtual void checkLocation() { } | |||
virtual bool supportGetMore() = 0; | virtual bool supportGetMore() = 0; | |||
virtual bool supportYields() = 0; | ||||
virtual string toString() { return "abstract?"; } | virtual string toString() { return "abstract?"; } | |||
/* used for multikey index traversal to avoid sending back dups. se e Matcher::matches(). | /* used for multikey index traversal to avoid sending back dups. se e Matcher::matches(). | |||
if a multikey index traversal: | if a multikey index traversal: | |||
if loc has already been sent, returns true. | if loc has already been sent, returns true. | |||
otherwise, marks loc as sent. | otherwise, marks loc as sent. | |||
@param deep - match was against an array, so we know it is multi key. this is legacy and kept | @param deep - match was against an array, so we know it is multi key. this is legacy and kept | |||
for backwards datafile compatibility. 'deep' can be eliminated next time we | for backwards datafile compatibility. 'deep' can be eliminated next time we | |||
force a data file conversion. 7Jul09 | force a data file conversion. 7Jul09 | |||
skipping to change at line 174 | skipping to change at line 175 | |||
virtual void setTailable() { | virtual void setTailable() { | |||
if ( !curr.isNull() || !last.isNull() ) | if ( !curr.isNull() || !last.isNull() ) | |||
tailable_ = true; | tailable_ = true; | |||
} | } | |||
virtual bool tailable() { | virtual bool tailable() { | |||
return tailable_; | return tailable_; | |||
} | } | |||
virtual bool getsetdup(DiskLoc loc) { return false; } | virtual bool getsetdup(DiskLoc loc) { return false; } | |||
virtual bool supportGetMore() { return true; } | virtual bool supportGetMore() { return true; } | |||
virtual bool supportYields() { return true; } | ||||
virtual CoveredIndexMatcher *matcher() const { return _matcher.get( ); } | virtual CoveredIndexMatcher *matcher() const { return _matcher.get( ); } | |||
virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher ) { | virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher ) { | |||
_matcher = matcher; | _matcher = matcher; | |||
} | } | |||
}; | }; | |||
/* used for order { $natural: -1 } */ | /* used for order { $natural: -1 } */ | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 2 lines changed or added | |||
d_logic.h | d_logic.h | |||
---|---|---|---|---|
skipping to change at line 110 | skipping to change at line 110 | |||
ShardedConnectionInfo(); | ShardedConnectionInfo(); | |||
const OID& getID() const { return _id; } | const OID& getID() const { return _id; } | |||
bool hasID() const { return _id.isSet(); } | bool hasID() const { return _id.isSet(); } | |||
void setID( const OID& id ); | void setID( const OID& id ); | |||
ConfigVersion& getVersion( const string& ns ); // TODO: this is dan geroues | ConfigVersion& getVersion( const string& ns ); // TODO: this is dan geroues | |||
void setVersion( const string& ns , const ConfigVersion& version ); | void setVersion( const string& ns , const ConfigVersion& version ); | |||
static ShardedConnectionInfo* get( bool create ); | static ShardedConnectionInfo* get( bool create ); | |||
static void reset(); | ||||
bool inForceMode() const { | bool inForceMode() const { | |||
return _forceMode; | return _forceMode; | |||
} | } | |||
void enterForceMode(){ _forceMode = true; } | void enterForceMode(){ _forceMode = true; } | |||
void leaveForceMode(){ _forceMode = false; } | void leaveForceMode(){ _forceMode = false; } | |||
private: | private: | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
database.h | database.h | |||
---|---|---|---|---|
skipping to change at line 191 | skipping to change at line 191 | |||
static bool validDBName( const string& ns ); | static bool validDBName( const string& ns ); | |||
long long fileSize(){ | long long fileSize(){ | |||
long long size=0; | long long size=0; | |||
for (int n=0; exists(n); n++) | for (int n=0; exists(n); n++) | |||
size += boost::filesystem::file_size( fileName(n) ); | size += boost::filesystem::file_size( fileName(n) ); | |||
return size; | return size; | |||
} | } | |||
void flushFiles( bool sync ); | ||||
vector<MongoDataFile*> files; | vector<MongoDataFile*> files; | |||
string name; // "alleyinsider" | string name; // "alleyinsider" | |||
string path; | string path; | |||
NamespaceIndex namespaceIndex; | NamespaceIndex namespaceIndex; | |||
int profile; // 0=off. | int profile; // 0=off. | |||
string profileName; // "alleyinsider.system.profile" | string profileName; // "alleyinsider.system.profile" | |||
int magic; // used for making sure the object is still loaded in me mory | int magic; // used for making sure the object is still loaded in me mory | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 2 lines changed or added | |||
dbclient.h | dbclient.h | |||
---|---|---|---|---|
skipping to change at line 101 | skipping to change at line 101 | |||
RemoveOption_JustOne = 1 << 0, | RemoveOption_JustOne = 1 << 0, | |||
/** flag from mongo saying this update went everywhere */ | /** flag from mongo saying this update went everywhere */ | |||
RemoveOption_Broadcast = 1 << 1 | RemoveOption_Broadcast = 1 << 1 | |||
}; | }; | |||
class DBClientBase; | class DBClientBase; | |||
class ConnectionString { | class ConnectionString { | |||
public: | public: | |||
enum ConnectionType { MASTER , SET , SYNC }; | enum ConnectionType { INVALID , MASTER , PAIR , SET , SYNC }; | |||
ConnectionString( const HostAndPort& server ){ | ConnectionString( const HostAndPort& server ){ | |||
_type = MASTER; | _type = MASTER; | |||
_servers.push_back( server ); | _servers.push_back( server ); | |||
_finishInit(); | _finishInit(); | |||
} | } | |||
ConnectionString( ConnectionType type , const vector<HostAndPort>& servers ) | ConnectionString( ConnectionType type , const vector<HostAndPort>& servers ) | |||
: _type( type ) , _servers( servers ){ | : _type( type ) , _servers( servers ){ | |||
_finishInit(); | _finishInit(); | |||
} | } | |||
ConnectionString( ConnectionType type , const string& s ){ | ConnectionString( ConnectionType type , const string& s , const str ing& setName = "" ){ | |||
_type = type; | _type = type; | |||
_setName = setName; | ||||
_fillServers( s ); | _fillServers( s ); | |||
switch ( _type ){ | switch ( _type ){ | |||
case MASTER: | case MASTER: | |||
assert( _servers.size() == 1 ); | assert( _servers.size() == 1 ); | |||
break; | break; | |||
case SET: | ||||
assert( _setName.size() ); | ||||
assert( _servers.size() > 1 ); | ||||
break; | ||||
case PAIR: | ||||
assert( _servers.size() == 2 ); | ||||
break; | ||||
default: | default: | |||
assert( _servers.size() > 0 ); | assert( _servers.size() > 0 ); | |||
} | } | |||
_finishInit(); | _finishInit(); | |||
} | } | |||
ConnectionString( const string& s , ConnectionType favoredMultipleT ype ){ | ConnectionString( const string& s , ConnectionType favoredMultipleT ype ){ | |||
_fillServers( s ); | _fillServers( s ); | |||
if ( _servers.size() == 1 ){ | if ( _servers.size() == 1 ){ | |||
_type = MASTER; | _type = MASTER; | |||
} | } | |||
else { | else { | |||
_type = favoredMultipleType; | _type = favoredMultipleType; | |||
assert( _type != MASTER ); | assert( _type != MASTER ); | |||
} | } | |||
_finishInit(); | _finishInit(); | |||
} | } | |||
bool isValid() const { return _type != INVALID; } | ||||
string toString() const { | string toString() const { | |||
return _string; | return _string; | |||
} | } | |||
operator string() const { | ||||
return toString(); | ||||
} | ||||
DBClientBase* connect( string& errmsg ) const; | DBClientBase* connect( string& errmsg ) const; | |||
static ConnectionString parse( const string& url , string& errmsg ) | ||||
; | ||||
private: | private: | |||
ConnectionString(){ | ||||
_type = INVALID; | ||||
} | ||||
void _fillServers( string s ){ | void _fillServers( string s ){ | |||
string::size_type idx; | string::size_type idx; | |||
while ( ( idx = s.find( ',' ) ) != string::npos ){ | while ( ( idx = s.find( ',' ) ) != string::npos ){ | |||
_servers.push_back( s.substr( 0 , idx ) ); | _servers.push_back( s.substr( 0 , idx ) ); | |||
s = s.substr( idx + 1 ); | s = s.substr( idx + 1 ); | |||
} | } | |||
_servers.push_back( s ); | _servers.push_back( s ); | |||
} | } | |||
void _finishInit(){ | void _finishInit(){ | |||
skipping to change at line 175 | skipping to change at line 187 | |||
if ( i > 0 ) | if ( i > 0 ) | |||
ss << ","; | ss << ","; | |||
ss << _servers[i].toString(); | ss << _servers[i].toString(); | |||
} | } | |||
_string = ss.str(); | _string = ss.str(); | |||
} | } | |||
ConnectionType _type; | ConnectionType _type; | |||
vector<HostAndPort> _servers; | vector<HostAndPort> _servers; | |||
string _string; | string _string; | |||
string _setName; | ||||
}; | }; | |||
/** | /** | |||
* controls how much a clients cares about writes | * controls how much a clients cares about writes | |||
* default is NORMAL | * default is NORMAL | |||
*/ | */ | |||
enum WriteConcern { | enum WriteConcern { | |||
W_NONE = 0 , // TODO: not every connection type fully supports this | W_NONE = 0 , // TODO: not every connection type fully supports this | |||
W_NORMAL = 1 | W_NORMAL = 1 | |||
// TODO SAFE = 2 | // TODO SAFE = 2 | |||
skipping to change at line 744 | skipping to change at line 757 | |||
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 callRead( Message& toSend , Message& response ) = 0; | |||
// virtual bool callWrite( Message& toSend , Message& response ) = 0; // TODO: add this if needed | // virtual bool callWrite( Message& toSend , Message& response ) = 0; // TODO: add this if needed | |||
virtual void say( Message& toSend ) = 0; | virtual void say( Message& toSend ) = 0; | |||
virtual ConnectionString::ConnectionType type() const = 0; | ||||
}; // DBClientBase | }; // DBClientBase | |||
class DBClientPaired; | class DBClientReplicaSet; | |||
class ConnectException : public UserException { | class ConnectException : public UserException { | |||
public: | public: | |||
ConnectException(string msg) : UserException(9000,msg) { } | ConnectException(string msg) : UserException(9000,msg) { } | |||
}; | }; | |||
/** | /** | |||
A basic connection to the database. | A basic connection to the database. | |||
This is the main entry point for talking to a simple Mongo setup | This is the main entry point for talking to a simple Mongo setup | |||
*/ | */ | |||
class DBClientConnection : public DBClientBase { | class DBClientConnection : public DBClientBase { | |||
DBClientPaired *clientPaired; | DBClientReplicaSet *clientSet; | |||
boost::scoped_ptr<MessagingPort> p; | boost::scoped_ptr<MessagingPort> p; | |||
boost::scoped_ptr<SockAddr> server; | boost::scoped_ptr<SockAddr> server; | |||
bool failed; // true if some sort of fatal error has ever happened | bool failed; // true if some sort of fatal error has ever happened | |||
bool autoReconnect; | bool autoReconnect; | |||
time_t lastReconnectTry; | time_t lastReconnectTry; | |||
string serverAddress; // remember for reconnects | HostAndPort _server; // remember for reconnects | |||
string _serverString; | ||||
int _port; | ||||
void _checkConnection(); | void _checkConnection(); | |||
void checkConnection() { if( failed ) _checkConnection(); } | void checkConnection() { if( failed ) _checkConnection(); } | |||
map< string, pair<string,string> > authCache; | map< string, pair<string,string> > authCache; | |||
int _timeout; | int _timeout; | |||
bool _connect( string& errmsg ); | ||||
public: | public: | |||
/** | /** | |||
@param _autoReconnect if true, automatically reconnect on a conn ection failure | @param _autoReconnect if true, automatically reconnect on a conn ection failure | |||
@param cp used by DBClientPaired. You do not need to specify th is parameter | @param cp used by DBClientReplicaSet. You do not need to specif y this parameter | |||
@param timeout tcp timeout in seconds - this is for read/write, not connect. | @param timeout tcp timeout in seconds - this is for read/write, not connect. | |||
Connect timeout is fixed, but short, at 5 seconds. | Connect timeout is fixed, but short, at 5 seconds. | |||
*/ | */ | |||
DBClientConnection(bool _autoReconnect=false, DBClientPaired* cp=0, | DBClientConnection(bool _autoReconnect=false, DBClientReplicaSet* c | |||
int timeout=0) : | p=0, int timeout=0) : | |||
clientPaired(cp), failed(false), autoReconnect(_autoReconne | clientSet(cp), failed(false), autoReconnect(_autoReconnect) | |||
ct), lastReconnectTry(0), _timeout(timeout) { } | , lastReconnectTry(0), _timeout(timeout) { } | |||
/** Connect to a Mongo database server. | /** Connect to a Mongo database server. | |||
If autoReconnect is true, you can try to use the DBClientConnect ion even when | If autoReconnect is true, you can try to use the DBClientConnect ion even when | |||
false was returned -- it will try to connect again. | false was returned -- it will try to connect again. | |||
@param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 ) | @param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 ) | |||
If you use IPv6 you must add a port number ( ::1:27017 ) | If you use IPv6 you must add a port number ( ::1:27017 ) | |||
@param errmsg any relevant error message will appended to the st ring | @param errmsg any relevant error message will appended to the st ring | |||
@deprecated please use HostAndPort | ||||
@return false if fails to connect. | @return false if fails to connect. | |||
*/ | */ | |||
virtual bool connect(const string &serverHostname, string& errmsg); | virtual bool connect(const char * hostname, string& errmsg){ | |||
// TODO: remove this method | ||||
HostAndPort t( hostname ); | ||||
return connect( t , errmsg ); | ||||
} | ||||
/** Connect to a Mongo database server. | ||||
If autoReconnect is true, you can try to use the DBClientConnect | ||||
ion even when | ||||
false was returned -- it will try to connect again. | ||||
@param server server to connect to. | ||||
@param errmsg any relevant error message will appended to the st | ||||
ring | ||||
@return false if fails to connect. | ||||
*/ | ||||
virtual bool connect(const HostAndPort& server, string& errmsg); | ||||
/** Connect to a Mongo database server. Exception throwing version . | /** Connect to a Mongo database server. Exception throwing version . | |||
Throws a UserException if cannot connect. | Throws a UserException if cannot connect. | |||
If autoReconnect is true, you can try to use the DBClientConnect ion even when | If autoReconnect is true, you can try to use the DBClientConnect ion even when | |||
false was returned -- it will try to connect again. | false was returned -- it will try to connect again. | |||
@param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 ) | @param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 ) | |||
*/ | */ | |||
void connect(string serverHostname) { | void connect(const string& serverHostname) { | |||
string errmsg; | string errmsg; | |||
if( !connect(serverHostname.c_str(), errmsg) ) | if( !connect(HostAndPort(serverHostname), errmsg) ) | |||
throw ConnectException(string("can't connect ") + errmsg); | throw ConnectException(string("can't connect ") + errmsg); | |||
} | } | |||
virtual bool auth(const string &dbname, const string &username, con st string &pwd, string& errmsg, bool digestPassword = true); | virtual bool auth(const string &dbname, const string &username, con st string &pwd, string& errmsg, bool digestPassword = true); | |||
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y=Query(), int nToReturn = 0, int nToSkip = 0, | virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y=Query(), int nToReturn = 0, int nToSkip = 0, | |||
const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 ) { | const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 ) { | |||
checkConnection(); | checkConnection(); | |||
return DBClientBase::query( ns, query, nToReturn, nToSkip, fiel dsToReturn, queryOptions , batchSize ); | return DBClientBase::query( ns, query, nToReturn, nToSkip, fiel dsToReturn, queryOptions , batchSize ); | |||
} | } | |||
skipping to change at line 833 | skipping to change at line 867 | |||
bool isFailed() const { | bool isFailed() const { | |||
return failed; | return failed; | |||
} | } | |||
MessagingPort& port() { | MessagingPort& port() { | |||
return *p; | return *p; | |||
} | } | |||
string toStringLong() const { | string toStringLong() const { | |||
stringstream ss; | stringstream ss; | |||
ss << serverAddress; | ss << _serverString; | |||
if ( failed ) ss << " failed"; | if ( failed ) ss << " failed"; | |||
return ss.str(); | return ss.str(); | |||
} | } | |||
/** Returns the address of the server */ | /** Returns the address of the server */ | |||
string toString() { | string toString() { | |||
return serverAddress; | return _serverString; | |||
} | } | |||
string getServerAddress() const { | string getServerAddress() const { | |||
return serverAddress; | return _serverString; | |||
} | } | |||
virtual void killCursor( long long cursorID ); | virtual void killCursor( long long cursorID ); | |||
virtual bool callRead( Message& toSend , Message& response ){ | virtual bool callRead( Message& toSend , Message& response ){ | |||
return call( toSend , response ); | return call( toSend , response ); | |||
} | } | |||
virtual void say( Message &toSend ); | virtual void say( Message &toSend ); | |||
virtual bool call( Message &toSend, Message &response, bool assertO k = true ); | ||||
virtual ConnectionString::ConnectionType type() const { return Conn ectionString::MASTER; } | ||||
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 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 | /** Use this class to connect to a replica set of servers. The class w | |||
will manage | ill manage | |||
checking for which server in a replica pair is master, and do failov | checking for which server in a replica set is master, and do failove | |||
er automatically. | r automatically. | |||
This can also be used to connect to replica pairs since pairs are a | ||||
subset of sets | ||||
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. | |||
*/ | */ | |||
class DBClientPaired : public DBClientBase { | class DBClientReplicaSet : public DBClientBase { | |||
DBClientConnection left,right; | string _name; | |||
enum State { | DBClientConnection * _currentMaster; | |||
NotSetL=0, | vector<HostAndPort> _servers; | |||
NotSetR=1, | vector<DBClientConnection*> _conns; | |||
Left, Right | ||||
} master; | ||||
void _checkMaster(); | void _checkMaster(); | |||
DBClientConnection& checkMaster(); | DBClientConnection * checkMaster(); | |||
public: | public: | |||
/** Call connect() after constructing. autoReconnect is always on f | /** Call connect() after constructing. autoReconnect is always on f | |||
or DBClientPaired connections. */ | or DBClientReplicaSet connections. */ | |||
DBClientPaired(); | DBClientReplicaSet( const string& name , const vector<HostAndPort>& | |||
servers ); | ||||
virtual ~DBClientReplicaSet(); | ||||
/** Returns false is neither member of the pair were reachable, or neither is | /** Returns false if nomember of the set were reachable, or neither is | |||
master, although, | master, although, | |||
when false returned, you can still try to use this connection ob ject, it will | when false returned, you can still try to use this connection ob ject, it will | |||
try reconnects. | try reconnects. | |||
*/ | */ | |||
bool connect(const string &serverHostname1, const string &serverHos | bool connect(); | |||
tname2); | ||||
/** Connect to a server pair using a host pair string of the form | ||||
hostname[:port],hostname[:port] | ||||
*/ | ||||
bool connect(string hostpairstring); | ||||
/** Authorize. Authorizes both sides of the pair as needed. | /** Authorize. Authorizes all nodes as needed | |||
*/ | */ | |||
bool auth(const string &dbname, const string &username, const strin g &pwd, string& errmsg); | virtual bool auth(const string &dbname, const string &username, con st string &pwd, string& errmsg, bool digestPassword = true ); | |||
/** 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, const Query& query, const BSONObj *fieldsToReturn = 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); | |||
} | } | |||
/** remove */ | /** remove */ | |||
virtual void remove( const string &ns , Query obj , bool justOne = 0 ) { | virtual void remove( const string &ns , Query obj , bool justOne = 0 ) { | |||
checkMaster().remove(ns, obj, justOne); | checkMaster()->remove(ns, obj, justOne); | |||
} | } | |||
/** update */ | /** update */ | |||
virtual void update( const string &ns , Query query , BSONObj obj , bool upsert = 0 , bool multi = 0 ) { | virtual void update( const string &ns , Query query , BSONObj obj , bool upsert = 0 , bool multi = 0 ) { | |||
return checkMaster().update(ns, query, obj, upsert,multi); | return checkMaster()->update(ns, query, obj, upsert,multi); | |||
} | } | |||
virtual void killCursor( long long cursorID ){ | virtual void killCursor( long long cursorID ){ | |||
checkMaster().killCursor( cursorID ); | checkMaster()->killCursor( cursorID ); | |||
} | } | |||
string toString(); | string toString(); | |||
/* this is the callback from our underlying connections to notify u s that we got a "not master" error. | /* this is the callback from our underlying connections to notify u s that we got a "not master" error. | |||
*/ | */ | |||
void isntMaster() { | void isntMaster() { | |||
master = ( ( master == Left ) ? NotSetR : NotSetL ); | _currentMaster = 0; | |||
} | } | |||
string getServerAddress() const { | string getServerAddress() const; | |||
return left.getServerAddress() + "," + right.getServerAddress() | ||||
; | ||||
} | ||||
DBClientConnection& masterConn(); | DBClientConnection& masterConn(); | |||
DBClientConnection& slaveConn(); | DBClientConnection& slaveConn(); | |||
/* TODO - not yet implemented. mongos may need these. */ | virtual bool call( Message &toSend, Message &response, bool assertO | |||
virtual bool call( Message &toSend, Message &response, bool assertO | k=true ) { return checkMaster()->call( toSend , response , assertOk ); } | |||
k=true ) { assert(false); return false; } | virtual void say( Message &toSend ) { checkMaster()->say( toSend ); | |||
virtual void say( Message &toSend ) { assert(false); } | } | |||
virtual bool callRead( Message& toSend , Message& response ){ retur | ||||
n checkMaster()->callRead( toSend , response ); } | ||||
virtual ConnectionString::ConnectionType type() const { return Conn | ||||
ectionString::SET; } | ||||
protected: | ||||
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 | return _currentMaster == 0 || _currentMaster->isFailed(); | |||
well | ||||
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 ); | |||
DBClientBase * createDirectClient(); | DBClientBase * createDirectClient(); | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 44 change blocks. | ||||
67 lines changed or deleted | 100 lines changed or added | |||
dbclientcursor.h | dbclientcursor.h | |||
---|---|---|---|---|
skipping to change at line 120 | skipping to change at line 120 | |||
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 ) : | |||
connector(_connector), | connector(_connector), | |||
ns(_ns), | ns(_ns), | |||
query(_query), | query(_query), | |||
nToReturn(_nToReturn), | nToReturn(_nToReturn), | |||
haveLimit( _nToReturn > 0 && !(queryOptions & QueryOption_C ursorTailable)), | haveLimit( _nToReturn > 0 && !(queryOptions & QueryOption_C ursorTailable)), | |||
nToSkip(_nToSkip), | nToSkip(_nToSkip), | |||
fieldsToReturn(_fieldsToReturn), | fieldsToReturn(_fieldsToReturn), | |||
opts(queryOptions), | opts(queryOptions), | |||
batchSize(bs), | batchSize(bs==1?2:bs), | |||
m(new Message()), | m(new Message()), | |||
cursorId(), | cursorId(), | |||
nReturned(), | nReturned(), | |||
pos(), | pos(), | |||
data(), | data(), | |||
_ownCursor( true ){ | _ownCursor( true ){ | |||
} | } | |||
DBClientCursor( DBConnector *_connector, const string &_ns, long lo ng _cursorId, int _nToReturn, int options ) : | DBClientCursor( DBConnector *_connector, const string &_ns, long lo ng _cursorId, int _nToReturn, int options ) : | |||
connector(_connector), | connector(_connector), | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
goodies.h | goodies.h | |||
---|---|---|---|---|
skipping to change at line 163 | skipping to change at line 163 | |||
else | else | |||
gmtime_s(buf, &t); | gmtime_s(buf, &t); | |||
#else | #else | |||
if ( local ) | if ( local ) | |||
localtime_r(&t, buf); | localtime_r(&t, buf); | |||
else | else | |||
gmtime_r(&t, buf); | gmtime_r(&t, buf); | |||
#endif | #endif | |||
} | } | |||
inline string terseCurrentTime(){ | inline void terseCurrentTime( stringstream& ss , bool seconds = false ) { | |||
struct tm t; | struct tm t; | |||
time_t_to_Struct( time(0) , &t ); | time_t_to_Struct( time(0) , &t ); | |||
ss | ||||
<< ( 1900 + t.tm_year ) << "-" << ( 1 + t.tm_mon ) << "-" << t. | ||||
tm_mday | ||||
<< "_" | ||||
<< t.tm_hour << "-" << t.tm_min; | ||||
if ( seconds ) | ||||
ss << "-" << t.tm_sec; | ||||
} | ||||
inline string terseCurrentTime(){ | ||||
stringstream ss; | stringstream ss; | |||
ss << ( 1900 + t.tm_year ) << "-" | terseCurrentTime(ss); | |||
<< t.tm_mon << "-" | ||||
<< t.tm_mday << "-" | ||||
<< t.tm_hour << "-" | ||||
<< t.tm_min; | ||||
return ss.str(); | return ss.str(); | |||
} | } | |||
#define MONGO_asctime _asctime_not_threadsafe_ | #define MONGO_asctime _asctime_not_threadsafe_ | |||
#define asctime MONGO_asctime | #define asctime MONGO_asctime | |||
#define MONGO_gmtime _gmtime_not_threadsafe_ | #define MONGO_gmtime _gmtime_not_threadsafe_ | |||
#define gmtime MONGO_gmtime | #define gmtime MONGO_gmtime | |||
#define MONGO_localtime _localtime_not_threadsafe_ | #define MONGO_localtime _localtime_not_threadsafe_ | |||
#define localtime MONGO_localtime | #define localtime MONGO_localtime | |||
#define MONGO_ctime _ctime_is_not_threadsafe_ | #define MONGO_ctime _ctime_is_not_threadsafe_ | |||
skipping to change at line 354 | skipping to change at line 361 | |||
#if defined(BOOST_LITTLE_ENDIAN) | #if defined(BOOST_LITTLE_ENDIAN) | |||
inline unsigned long fixEndian(unsigned long x) { | inline unsigned long fixEndian(unsigned long x) { | |||
return x; | return x; | |||
} | } | |||
#else | #else | |||
inline unsigned long fixEndian(unsigned long x) { | inline unsigned long fixEndian(unsigned long x) { | |||
return swapEndian(x); | return swapEndian(x); | |||
} | } | |||
#endif | #endif | |||
// Like strlen, but only scans up to n bytes. | ||||
// Returns -1 if no '0' found. | ||||
inline int strnlen( const char *s, int n ) { | ||||
for( int i = 0; i < n; ++i ) | ||||
if ( !s[ i ] ) | ||||
return i; | ||||
return -1; | ||||
} | ||||
#if !defined(_WIN32) | #if !defined(_WIN32) | |||
typedef int HANDLE; | typedef int HANDLE; | |||
inline void strcpy_s(char *dst, unsigned len, const char *src) { | inline void strcpy_s(char *dst, unsigned len, const char *src) { | |||
strcpy(dst, src); | strcpy(dst, src); | |||
} | } | |||
#else | #else | |||
typedef void *HANDLE; | typedef void *HANDLE; | |||
#endif | #endif | |||
/* thread local "value" rather than a pointer | /* thread local "value" rather than a pointer | |||
End of changes. 4 change blocks. | ||||
15 lines changed or deleted | 14 lines changed or added | |||
health.h | health.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 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 | |||
namespace mongo { | namespace mongo { | |||
/* throws */ | /* throws */ | |||
bool requestHeartbeat(string setname, string memberFullName, BSONObj& r esult, int myConfigVersion, int& theirConfigVersion, bool checkEmpty = fals e); | bool requestHeartbeat(string setname, string fromHost, string memberFul lName, BSONObj& result, int myConfigVersion, int& theirConfigVersion, bool checkEmpty = false); | |||
struct HealthOptions { | struct HealthOptions { | |||
HealthOptions() { | HealthOptions() { | |||
heartbeatSleepMillis = 2000; | heartbeatSleepMillis = 2000; | |||
heartbeatTimeoutMillis = 10000; | heartbeatTimeoutMillis = 10000; | |||
heartbeatConnRetries = 3; | heartbeatConnRetries = 3; | |||
} | } | |||
bool isDefault() const { | bool isDefault() const { | |||
return !( heartbeatSleepMillis != 2000 || heartbeatTimeoutMilli s != 10000 || heartbeatConnRetries != 3 ); | return !( heartbeatSleepMillis != 2000 || heartbeatTimeoutMilli s != 10000 || heartbeatConnRetries != 3 ); | |||
} | } | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
hex.h | hex.h | |||
---|---|---|---|---|
skipping to change at line 51 | skipping to change at line 51 | |||
for (int i=0; i<len; ++i){ | for (int i=0; i<len; ++i){ | |||
char c = in[i]; | char c = in[i]; | |||
char hi = hexchars[(c & 0xF0) >> 4]; | char hi = hexchars[(c & 0xF0) >> 4]; | |||
char lo = hexchars[(c & 0x0F)]; | char lo = hexchars[(c & 0x0F)]; | |||
out << hi << lo; | out << hi << lo; | |||
} | } | |||
return out.str(); | return out.str(); | |||
} | } | |||
inline string toHexLower(const void* inRaw, int len){ | ||||
static const char hexchars[] = "0123456789abcdef"; | ||||
StringBuilder out; | ||||
const char* in = reinterpret_cast<const char*>(inRaw); | ||||
for (int i=0; i<len; ++i){ | ||||
char c = in[i]; | ||||
char hi = hexchars[(c & 0xF0) >> 4]; | ||||
char lo = hexchars[(c & 0x0F)]; | ||||
out << hi << lo; | ||||
} | ||||
return out.str(); | ||||
} | ||||
} | } | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 16 lines changed or added | |||
hostandport.h | hostandport.h | |||
---|---|---|---|---|
skipping to change at line 65 | skipping to change at line 65 | |||
if( _host == r._host ) | if( _host == r._host ) | |||
return port() < r.port(); | return port() < r.port(); | |||
return false; | return false; | |||
} | } | |||
bool operator==(const HostAndPort& r) const { | bool operator==(const HostAndPort& r) const { | |||
return _host == r._host && port() == r.port(); | 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; // defined in message.cpp | |||
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::DefaultDBPo rt; } | int port() const { return _port >= 0 ? _port : CmdLine::DefaultDBPo rt; } | |||
void setPort( int port ) { _port = port; } | ||||
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 - | |||
skipping to change at line 100 | skipping to change at line 101 | |||
return str::before(a, '.') == str::before(b, '.'); | return str::before(a, '.') == str::before(b, '.'); | |||
} | } | |||
inline HostAndPort HostAndPort::Me() { | inline HostAndPort HostAndPort::Me() { | |||
string h = getHostName(); | string h = getHostName(); | |||
assert( !h.empty() ); | assert( !h.empty() ); | |||
assert( h != "localhost" ); | assert( h != "localhost" ); | |||
return HostAndPort(h, cmdLine.port); | return HostAndPort(h, cmdLine.port); | |||
} | } | |||
inline bool HostAndPort::isSelf() const { | ||||
int p = _port == -1 ? CmdLine::DefaultDBPort : _port; | ||||
if( p != cmdLine.port ) | ||||
return false; | ||||
return sameHostname(getHostName(), _host) || isLocalHost(); | ||||
} | ||||
inline string HostAndPort::toString() const { | inline string HostAndPort::toString() const { | |||
stringstream ss; | stringstream ss; | |||
ss << _host; | ss << _host; | |||
if( _port != -1 ) ss << ':' << _port; | if ( _port != -1 ){ | |||
ss << ':'; | ||||
#if defined(_DEBUG) | ||||
if( _port >= 44000 && _port < 44100 ) { | ||||
log() << "warning: special debug port 44xxx used" << endl; | ||||
ss << _port+1; | ||||
} | ||||
else | ||||
ss << _port; | ||||
#else | ||||
ss << _port; | ||||
#endif | ||||
} | ||||
return ss.str(); | return ss.str(); | |||
} | } | |||
inline bool HostAndPort::isLocalHost() const { | inline bool HostAndPort::isLocalHost() const { | |||
return _host == "localhost" || _host == "127.0.0.1" || _host == ":: 1"; | return _host == "localhost" || startsWith(_host.c_str(), "127.") || _host == "::1"; | |||
} | } | |||
inline HostAndPort::HostAndPort(string s) { | inline HostAndPort::HostAndPort(string s) { | |||
const char *p = s.c_str(); | const char *p = s.c_str(); | |||
uassert(13110, "HostAndPort: bad config string", *p); | uassert(13110, "HostAndPort: bad config string", *p); | |||
const char *colon = strrchr(p, ':'); | const char *colon = strrchr(p, ':'); | |||
if( colon ) { | if( colon ) { | |||
int port = atoi(colon+1); | int port = atoi(colon+1); | |||
uassert(13095, "HostAndPort: bad port #", port > 0); | uassert(13095, "HostAndPort: bad port #", port > 0); | |||
_host = string(p,colon-p); | _host = string(p,colon-p); | |||
End of changes. 5 change blocks. | ||||
11 lines changed or deleted | 16 lines changed or added | |||
html.h | html.h | |||
---|---|---|---|---|
skipping to change at line 58 | skipping to change at line 58 | |||
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) { | inline string th(string x) { | |||
return "<th>" + x + "</th>"; | return "<th>" + x + "</th>"; | |||
} | } | |||
inline void tablecell( stringstream& ss , bool b ){ | ||||
ss << "<td>" << (b ? "<b>X</b>" : "") << "</td>"; | ||||
} | ||||
template< typename T> | ||||
inline void tablecell( stringstream& ss , const T& t ){ | ||||
ss << "<td>" << t << "</td>"; | ||||
} | ||||
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>"; | |||
headers++; | headers++; | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 9 lines changed or added | |||
instance.h | instance.h | |||
---|---|---|---|---|
skipping to change at line 143 | skipping to change at line 143 | |||
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 ){ | virtual bool callRead( Message& toSend , Message& response ){ | |||
return call( toSend , response ); | return call( toSend , response ); | |||
} | } | |||
virtual ConnectionString::ConnectionType type() const { return Conn | ||||
ectionString::MASTER; } | ||||
}; | }; | |||
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 | 3 lines changed or added | |||
log.h | log.h | |||
---|---|---|---|---|
skipping to change at line 158 | skipping to change at line 158 | |||
}; | }; | |||
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 FILE* logfile; | static FILE* logfile; | |||
static boost::scoped_ptr<ostream> stream; | static boost::scoped_ptr<ostream> stream; | |||
static vector<Tee*> globalTees; | static vector<Tee*> * globalTees; | |||
public: | public: | |||
static void logLockless( const char * s ){ | static void logLockless( const StringData& s ){ | |||
if ( doneSetup == 1717 ){ | if ( doneSetup == 1717 ){ | |||
fwrite( s , strlen( s ) , 1 , logfile ); | fwrite( s.data() , s.size() , 1 , logfile ); | |||
fflush( logfile ); | fflush( logfile ); | |||
} | } | |||
else { | else { | |||
cout << s << endl; | cout << s.data() << 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); | string msg = ss.str(); | |||
time_t_to_String( time(0) , b.grow(20) ); | ||||
b.appendStr( ss.str() ); | ||||
const char *s = b.buf(); | ||||
string threadName = getThreadName(); | string threadName = getThreadName(); | |||
const char * type = logLevelToString(logLevel); | const char * type = logLevelToString(logLevel); | |||
StringBuilder sb; | int spaceNeeded = msg.size() + 64 + threadName.size(); | |||
int bufSize = 128; | ||||
while ( bufSize < spaceNeeded ) | ||||
bufSize += 128; | ||||
BufBuilder b(bufSize); | ||||
time_t_to_String( time(0) , b.grow(20) ); | ||||
if (!threadName.empty()){ | if (!threadName.empty()){ | |||
sb << "[" << threadName << "] "; | b.appendChar( '[' ); | |||
b.appendStr( threadName , false ); | ||||
b.appendChar( ']' ); | ||||
b.appendChar( ' ' ); | ||||
} | } | |||
sb << type << ( type[0] ? ": " : "" ); | if ( type[0] ){ | |||
sb << s; | b.appendStr( type , false ); | |||
string out = sb.str(); | b.appendStr( ": " , false ); | |||
} | ||||
b.appendStr( msg ); | ||||
string out( b.buf() , b.len() - 1); | ||||
scoped_lock lk(mutex); | scoped_lock lk(mutex); | |||
if( t ) t->write(logLevel,s); | if( t ) t->write(logLevel,out); | |||
for ( unsigned i=0; i<globalTees.size(); i++ ) | if ( globalTees ){ | |||
globalTees[i]->write(logLevel,s); | for ( unsigned i=0; i<globalTees->size(); i++ ) | |||
(*globalTees)[i]->write(logLevel,out); | ||||
} | ||||
#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(); | |||
} | } | |||
skipping to change at line 270 | skipping to change at line 281 | |||
else | else | |||
*this << *t; | *this << *t; | |||
return *this; | return *this; | |||
} | } | |||
Logstream& prolog() { | Logstream& prolog() { | |||
return *this; | return *this; | |||
} | } | |||
void addGlobalTee( Tee * t ){ | void addGlobalTee( Tee * t ){ | |||
globalTees.push_back( t ); | if ( ! globalTees ) | |||
globalTees = new vector<Tee*>(); | ||||
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; | |||
skipping to change at line 378 | skipping to change at line 391 | |||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_SYSTEM | |||
|FORMAT_MESSAGE_ALLOCATE_BUFFER | |FORMAT_MESSAGE_ALLOCATE_BUFFER | |||
|FORMAT_MESSAGE_IGNORE_INSERTS, | |FORMAT_MESSAGE_IGNORE_INSERTS, | |||
NULL, | NULL, | |||
x, 0, | x, 0, | |||
(LPTSTR) &errorText, // output | (LPTSTR) &errorText, // output | |||
0, // minimum size for output buffer | 0, // minimum size for output buffer | |||
NULL); | NULL); | |||
if( errorText ) { | if( errorText ) { | |||
string x = toUtf8String(errorText); | string x = toUtf8String(errorText); | |||
s << x; | for( string::iterator i = x.begin(); i != x.end(); i++ ) { | |||
if( *i == '\n' || *i == '\r' ) | ||||
break; | ||||
s << *i; | ||||
} | ||||
LocalFree(errorText); | LocalFree(errorText); | |||
} | } | |||
else | else | |||
s << strerror(x); | s << strerror(x); | |||
/* | /* | |||
DWORD n = FormatMessage( | DWORD n = FormatMessage( | |||
FORMAT_MESSAGE_ALLOCATE_BUFFER | | FORMAT_MESSAGE_ALLOCATE_BUFFER | | |||
FORMAT_MESSAGE_FROM_SYSTEM | | FORMAT_MESSAGE_FROM_SYSTEM | | |||
FORMAT_MESSAGE_IGNORE_INSERTS, | FORMAT_MESSAGE_IGNORE_INSERTS, | |||
NULL, x, | NULL, x, | |||
End of changes. 11 change blocks. | ||||
19 lines changed or deleted | 36 lines changed or added | |||
message.h | message.h | |||
---|---|---|---|---|
skipping to change at line 395 | skipping to change at line 395 | |||
// if just one buffer, keep it in _buf, otherwise keep a sequence o f buffers in _data | // if just one buffer, keep it in _buf, otherwise keep a sequence o f buffers in _data | |||
MsgData * _buf; | MsgData * _buf; | |||
// byte buffer(s) - the first must contain at least a full MsgData unless using _buf for storage instead | // byte buffer(s) - the first must contain at least a full MsgData unless using _buf for storage instead | |||
typedef vector< pair< char*, int > > MsgVec; | typedef vector< pair< char*, int > > MsgVec; | |||
MsgVec _data; | MsgVec _data; | |||
bool _freeIt; | bool _freeIt; | |||
}; | }; | |||
class SocketException : public DBException { | class SocketException : public DBException { | |||
public: | public: | |||
SocketException() : DBException( "socket exception" , 9001 ){} | enum Type { CLOSED , RECV_ERROR , SEND_ERROR } type; | |||
SocketException( Type t ) : DBException( "socket exception" , 9001 | ||||
) , type(t){} | ||||
bool shouldPrint() const { | ||||
return type != CLOSED; | ||||
} | ||||
}; | }; | |||
MSGID nextMessageId(); | MSGID nextMessageId(); | |||
void setClientId( int id ); | void setClientId( int id ); | |||
int getClientId(); | int getClientId(); | |||
extern TicketHolder connTicketHolder; | extern TicketHolder connTicketHolder; | |||
class ElapsedTracker { | class ElapsedTracker { | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 8 lines changed or added | |||
miniwebserver.h | miniwebserver.h | |||
---|---|---|---|---|
skipping to change at line 41 | skipping to change at line 41 | |||
virtual void doRequest( | virtual void doRequest( | |||
const char *rq, // the full request | const char *rq, // the full request | |||
string url, | string url, | |||
// set these and return them: | // set these and return them: | |||
string& responseMsg, | string& responseMsg, | |||
int& responseCode, | int& responseCode, | |||
vector<string>& headers, // if completely empty, content-type: text/html will be added | vector<string>& headers, // if completely empty, content-type: text/html will be added | |||
const SockAddr &from | const SockAddr &from | |||
) = 0; | ) = 0; | |||
protected: | // --- static helpers ---- | |||
string parseURL( const char * buf ); | ||||
string parseMethod( const char * headers ); | static void parseParams( BSONObj & params , string query ); | |||
string getHeader( const char * headers , string name ); | ||||
void parseParams( BSONObj & params , string query ); | static string parseURL( const char * buf ); | |||
static string parseMethod( const char * headers ); | ||||
static string getHeader( const char * headers , string name ); | ||||
static const char *body( const char *buf ); | static const char *body( const char *buf ); | |||
static string urlDecode(const char* s); | static string urlDecode(const char* s); | |||
static string urlDecode(string s) {return urlDecode(s.c_str());} | static string urlDecode(string s) {return urlDecode(s.c_str());} | |||
private: | private: | |||
void accepted(int s, const SockAddr &from); | void accepted(int s, const SockAddr &from); | |||
static bool fullReceive( const char *buf ); | static bool fullReceive( const char *buf ); | |||
}; | }; | |||
End of changes. 1 change blocks. | ||||
5 lines changed or deleted | 7 lines changed or added | |||
misc.h | misc.h | |||
---|---|---|---|---|
skipping to change at line 86 | skipping to change at line 86 | |||
Date_t(unsigned long long m): millis(m) {} | Date_t(unsigned long long m): millis(m) {} | |||
operator unsigned long long&() { return millis; } | operator unsigned long long&() { return millis; } | |||
operator const unsigned long long&() const { return millis; } | operator const unsigned long long&() const { return millis; } | |||
string toString() const { | string toString() const { | |||
char buf[64]; | char buf[64]; | |||
time_t_to_String(millis/1000, buf); | time_t_to_String(millis/1000, buf); | |||
return buf; | return buf; | |||
} | } | |||
}; | }; | |||
// Like strlen, but only scans up to n bytes. | ||||
// Returns -1 if no '0' found. | ||||
inline int strnlen( const char *s, int n ) { | ||||
for( int i = 0; i < n; ++i ) | ||||
if ( !s[ i ] ) | ||||
return i; | ||||
return -1; | ||||
} | ||||
} | } | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 8 lines changed or added | |||
mmap.h | mmap.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 | |||
namespace mongo { | namespace mongo { | |||
/* the administrative-ish stuff here */ | /* the administrative-ish stuff here */ | |||
class MongoFile : boost::noncopyable { | class MongoFile : boost::noncopyable { | |||
public: | ||||
/** Flushable has to fail nicely if the underlying object gets kill | ||||
ed */ | ||||
class Flushable { | ||||
public: | ||||
virtual ~Flushable(){} | ||||
virtual void flush() = 0; | ||||
}; | ||||
protected: | protected: | |||
virtual void close() = 0; | virtual void close() = 0; | |||
virtual void flush(bool sync) = 0; | virtual void flush(bool sync) = 0; | |||
/** | ||||
* returns a thread safe object that you can call flush on | ||||
* Flushable has to fail nicely if the underlying object gets kille | ||||
d | ||||
*/ | ||||
virtual Flushable * prepareFlush() = 0; | ||||
void created(); /* subclass must call after create */ | void created(); /* subclass must call after create */ | |||
void destroyed(); /* subclass must call in destructor */ | void destroyed(); /* subclass must call in destructor */ | |||
// only supporting on posix mmap | // only supporting on posix mmap | |||
virtual void _lock() {} | virtual void _lock() {} | |||
virtual void _unlock() {} | virtual void _unlock() {} | |||
public: | public: | |||
virtual ~MongoFile() {} | virtual ~MongoFile() {} | |||
skipping to change at line 148 | skipping to change at line 162 | |||
uassert(13077, "couldn't open/map file", p); | uassert(13077, "couldn't open/map file", p); | |||
return Pointer(p); | return Pointer(p); | |||
}*/ | }*/ | |||
/* Creates with length if DNE, otherwise uses existing file length, | /* Creates with length if DNE, otherwise uses existing file length, | |||
passed length. | passed length. | |||
*/ | */ | |||
void* map(const char *filename, long &length, int options = 0 ); | void* map(const char *filename, long &length, int options = 0 ); | |||
void flush(bool sync); | void flush(bool sync); | |||
virtual Flushable * prepareFlush(); | ||||
/*void* viewOfs() { | /*void* viewOfs() { | |||
return view; | return view; | |||
}*/ | }*/ | |||
long length() { | long length() { | |||
return len; | return len; | |||
} | } | |||
private: | private: | |||
End of changes. 3 change blocks. | ||||
0 lines changed or deleted | 17 lines changed or added | |||
mockdbclient.h | mockdbclient.h | |||
---|---|---|---|---|
skipping to change at line 33 | skipping to change at line 33 | |||
#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, const Query& query, const BSONObj *fi eldsToReturn = 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 char * serverHostname, string& errmsg) { | |||
return connect_; | ||||
} | ||||
virtual | ||||
bool connect(const HostAndPort& , 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_; | |||
} | } | |||
void one( const BSONObj &one ) { | void one( const BSONObj &one ) { | |||
one_ = one; | one_ = one; | |||
} | } | |||
void connect( bool val ) { | void connect( bool val ) { | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 5 lines changed or added | |||
msg.h | msg.h | |||
---|---|---|---|---|
skipping to change at line 30 | skipping to change at line 30 | |||
#include <deque> | #include <deque> | |||
#include "task.h" | #include "task.h" | |||
namespace mongo { | namespace mongo { | |||
namespace task { | namespace task { | |||
typedef boost::function<void()> lam; | typedef boost::function<void()> lam; | |||
class Server : private Task { | /** typical usage is: task::fork( serverPtr ); */ | |||
class Server : public Task { | ||||
public: | public: | |||
/** send a message to the port */ | /** send a message to the port */ | |||
void send(lam); | void send(lam); | |||
/** typical usage is: task::fork( foo.task() ); */ | ||||
shared_ptr<Task> taskPtr() { return shared_ptr<Task>(static_cas | ||||
t<Task*>(this)); } | ||||
Server(string name) : _name(name) { } | Server(string name) : _name(name) { } | |||
virtual ~Server() { } | virtual ~Server() { } | |||
/** send message but block until function completes */ | /** send message but block until function completes */ | |||
void call(const lam&); | void call(const lam&); | |||
void requeue() { rq = true; } | void requeue() { rq = true; } | |||
protected: | protected: | |||
/* this needn't be abstract; i left it that way for now so i re member | /* this needn't be abstract; i left it that way for now so i re member | |||
End of changes. 2 change blocks. | ||||
5 lines changed or deleted | 2 lines changed or added | |||
namespace.h | namespace.h | |||
---|---|---|---|---|
skipping to change at line 242 | skipping to change at line 242 | |||
/* called when loaded from disk */ | /* called when loaded from disk */ | |||
void onLoad(const Namespace& k); | void onLoad(const Namespace& k); | |||
NamespaceDetails( const DiskLoc &loc, bool _capped ); | NamespaceDetails( const DiskLoc &loc, bool _capped ); | |||
DiskLoc firstExtent; | DiskLoc firstExtent; | |||
DiskLoc lastExtent; | DiskLoc lastExtent; | |||
/* NOTE: capped collections override the meaning of deleted list. | /* NOTE: capped collections override the meaning of deleted list. | |||
deletedList[0] points to a list of free records (DeletedRe cord's) for all extents in | deletedList[0] points to a list of free records (DeletedRe cord's) for all extents in | |||
the namespace. | the capped namespace. | |||
deletedList[1] points to the last record in the prev exten t. When the "current extent" | deletedList[1] points to the last record in the prev exten t. When the "current extent" | |||
changes, this value is updated. !deletedList[1].isValid() when this value is not | changes, this value is updated. !deletedList[1].isValid() when this value is not | |||
yet computed. | yet computed. | |||
*/ | */ | |||
DiskLoc deletedList[Buckets]; | DiskLoc deletedList[Buckets]; | |||
void dumpExtents(); | ||||
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]; | |||
private: | ||||
Extent *theCapExtent() const { return capExtent.ext(); } | ||||
void advanceCapExtent( const char *ns ); | ||||
DiskLoc __capAlloc(int len); | ||||
DiskLoc cappedAlloc(const char *ns, int len); | ||||
DiskLoc &cappedFirstDeletedInCurExtent(); | ||||
bool nextIsInCapExtent( const DiskLoc &dl ) const; | ||||
public: | public: | |||
DiskLoc& cappedListOfAllDeletedRecords() { return deletedList[0]; } | ||||
DiskLoc& cappedLastDelRecLastExtent() { return deletedList[1]; } | ||||
void cappedDumpDelInfo(); | ||||
bool capLooped() const { return capped && capFirstNewRecord.isValid | ||||
(); } | ||||
bool inCapExtent( const DiskLoc &dl ) const; | ||||
void cappedCheckMigrate(); | ||||
void cappedTruncateAfter(const char *ns, DiskLoc after, bool inclus | ||||
ive); /** remove rest of the capped collection from this point onward */ | ||||
int capped; | int capped; | |||
int max; // max # of objects for a capped table. TODO: should this be 64 bit? | 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; | |||
unsigned long long multiKeyIndexBits; | unsigned long long multiKeyIndexBits; | |||
skipping to change at line 429 | skipping to change at line 450 | |||
return Buckets-1; | return Buckets-1; | |||
} | } | |||
/* allocate a new record. lenToAlloc includes headers. */ | /* allocate a new record. lenToAlloc includes headers. */ | |||
DiskLoc alloc(const char *ns, int lenToAlloc, DiskLoc& extentLoc); | DiskLoc alloc(const char *ns, int lenToAlloc, DiskLoc& extentLoc); | |||
/* add a given record to the deleted chains for this NS */ | /* add a given record to the deleted chains for this NS */ | |||
void addDeletedRec(DeletedRecord *d, DiskLoc dloc); | void addDeletedRec(DeletedRecord *d, DiskLoc dloc); | |||
void dumpDeleted(set<DiskLoc> *extents = 0); | void dumpDeleted(set<DiskLoc> *extents = 0); | |||
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; | ||||
void cappedCheckMigrate(); | ||||
long long storageSize( int * numExtents = 0 ); | long long storageSize( int * numExtents = 0 ); | |||
private: | private: | |||
/** This prevents deletion from a capped collection upon wrap aroun | DiskLoc _alloc(const char *ns, int len); | |||
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(); } | ||||
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 _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(); | ||||
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 658 | skipping to change at line 664 | |||
void maybeMkdir() const; | void maybeMkdir() const; | |||
MMF f; | MMF f; | |||
HashTable<Namespace,NamespaceDetails,MMF::Pointer> *ht; | HashTable<Namespace,NamespaceDetails,MMF::Pointer> *ht; | |||
string dir_; | string dir_; | |||
string database_; | string database_; | |||
}; | }; | |||
extern string dbpath; // --dbpath parm | extern string dbpath; // --dbpath parm | |||
extern bool directoryperdb; | extern bool directoryperdb; | |||
extern string pidfilepath; // --pidfilepath param | ||||
// Rename a namespace within current 'client' db. | // Rename a namespace within current 'client' db. | |||
// (Arguments should include db name) | // (Arguments should include db name) | |||
void renameNamespace( const char *from, const char *to ); | void renameNamespace( const char *from, const char *to ); | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 14 change blocks. | ||||
20 lines changed or deleted | 25 lines changed or added | |||
oid.h | oid.h | |||
---|---|---|---|---|
skipping to change at line 20 | skipping to change at line 20 | |||
* | * | |||
* 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 "../util/hex.h" | ||||
namespace mongo { | namespace mongo { | |||
#pragma pack(1) | #pragma pack(1) | |||
/** Object ID type. | /** Object ID type. | |||
BSON objects typically have an _id field for the object id. This f ield should be the first | BSON objects typically have an _id field for the object id. This f ield should be the first | |||
member of the object when present. class OID is a special type tha t is a 12 byte id which | member of the object when present. class OID is a special type tha t is a 12 byte id which | |||
is likely to be unique to the system. You may also use other types for _id's. | is likely to be unique to the system. You may also use other types for _id's. | |||
When _id field is missing from a BSON object, on an insert the data base may insert one | When _id field is missing from a BSON object, on an insert the data base may insert one | |||
automatically in certain circumstances. | automatically in certain circumstances. | |||
skipping to change at line 59 | skipping to change at line 61 | |||
bool operator==(const OID& r) { | bool operator==(const OID& r) { | |||
return a==r.a&&b==r.b; | return a==r.a&&b==r.b; | |||
} | } | |||
bool operator!=(const OID& r) { | bool operator!=(const OID& r) { | |||
return a!=r.a||b!=r.b; | return a!=r.a||b!=r.b; | |||
} | } | |||
/** The object ID output as 24 hex digits. */ | /** The object ID output as 24 hex digits. */ | |||
string str() const { | string str() const { | |||
stringstream s; | return toHexLower(data, 12); | |||
s << hex; | ||||
// s.fill( '0' ); | ||||
// s.width( 2 ); | ||||
// fill wasn't working so doing manually... | ||||
for( int i = 0; i < 8; i++ ) { | ||||
unsigned u = data[i]; | ||||
if( u < 16 ) s << '0'; | ||||
s << u; | ||||
} | ||||
const unsigned char * raw = (const unsigned char*)&b; | ||||
for( int i = 0; i < 4; i++ ) { | ||||
unsigned u = raw[i]; | ||||
if( u < 16 ) s << '0'; | ||||
s << u; | ||||
} | ||||
/* | ||||
s.width( 16 ); | ||||
s << a; | ||||
s.width( 8 ); | ||||
s << b; | ||||
s << dec; | ||||
*/ | ||||
return s.str(); | ||||
} | } | |||
string toString() const { return 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 | |||
*/ | */ | |||
skipping to change at line 113 | skipping to change at line 92 | |||
bool isSet() const { return a || b; } | bool isSet() const { return a || b; } | |||
int compare( const OID& other ) const { return memcmp( data , other .data , 12 ); } | int compare( const OID& other ) const { return memcmp( data , other .data , 12 ); } | |||
bool operator<( const OID& other ) const { return compare( other ) < 0; } | 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 ); | |||
inline StringBuilder& operator<< (StringBuilder& s, const OID& o) { ret urn (s << o.str()); } | ||||
/** 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 { | |||
/** strict RFC format */ | /** strict RFC format */ | |||
Strict, | Strict, | |||
/** 10gen format, which is close to JS format. This form is unders tandable by | /** 10gen format, which is close to JS format. This form is unders tandable by | |||
javascript running inside the Mongo server via eval() */ | javascript running inside the Mongo server via eval() */ | |||
End of changes. 3 change blocks. | ||||
24 lines changed or deleted | 4 lines changed or added | |||
oplogreader.h | oplogreader.h | |||
---|---|---|---|---|
skipping to change at line 19 | skipping to change at line 19 | |||
namespace mongo { | namespace mongo { | |||
/* started abstracting out the querying of the primary/master's oplog | /* started abstracting out the querying of the primary/master's oplog | |||
still fairly awkward but a start. | still fairly awkward but a start. | |||
*/ | */ | |||
class OplogReader { | class OplogReader { | |||
auto_ptr<DBClientConnection> _conn; | auto_ptr<DBClientConnection> _conn; | |||
auto_ptr<DBClientCursor> cursor; | auto_ptr<DBClientCursor> cursor; | |||
public: | public: | |||
OplogReader() { | ||||
DEV log() << "TEMP *** OplogReader()" << endl; | ||||
} | ||||
~OplogReader() { | ||||
DEV log() << "TEMP *** ~OplogReader()" << endl; | ||||
} | ||||
void resetCursor() { | void resetCursor() { | |||
DEV log() << "TEMP *** OplogReader::resetCursor" << endl; | ||||
cursor.reset(); | cursor.reset(); | |||
} | } | |||
void resetConnection() { | void resetConnection() { | |||
DEV log() << "TEMP *** OplogReader::resetConnection" << endl; | ||||
cursor.reset(); | cursor.reset(); | |||
_conn.reset(); | _conn.reset(); | |||
} | } | |||
DBClientConnection* conn() { return _conn.get(); } | DBClientConnection* conn() { return _conn.get(); } | |||
BSONObj findOne(const char *ns, const Query& q) { | BSONObj findOne(const char *ns, const Query& q) { | |||
return conn()->findOne(ns, q); | return conn()->findOne(ns, q); | |||
} | } | |||
BSONObj getLastOp(const char *ns) { | BSONObj getLastOp(const char *ns) { | |||
return findOne(ns, Query().sort(reverseNaturalObj)); | return findOne(ns, Query().sort(reverseNaturalObj)); | |||
End of changes. 3 change blocks. | ||||
0 lines changed or deleted | 9 lines changed or added | |||
optime.h | optime.h | |||
---|---|---|---|---|
skipping to change at line 95 | skipping to change at line 95 | |||
return last; | return last; | |||
} | } | |||
/* We store OpTime's in the database as BSON Date datatype -- we ne eded some sort of | /* We store OpTime's in the database as BSON Date datatype -- we ne eded some sort of | |||
64 bit "container" for these values. While these are not really " Dates", that seems a | 64 bit "container" for these values. While these are not really " Dates", that seems a | |||
better choice for now than say, Number, which is floating point. Note the BinData type | better choice for now than say, Number, which is floating point. Note the BinData type | |||
is perhaps the cleanest choice, lacking a true unsigned64 datatype , but BinData has 5 | is perhaps the cleanest choice, lacking a true unsigned64 datatype , but BinData has 5 | |||
bytes of overhead. | bytes of overhead. | |||
*/ | */ | |||
unsigned long long asDate() const { | unsigned long long asDate() const { | |||
return *((unsigned long long *) &i); | return reinterpret_cast<const unsigned long long*>(&i)[0]; | |||
} | } | |||
long long asLL() const { | long long asLL() const { | |||
return *((long long *) &i); | return reinterpret_cast<const long long*>(&i)[0]; | |||
} | } | |||
// unsigned long long& asDate() { return *((unsigned long lon g *) &i); } | ||||
bool isNull() const { return secs == 0; } | bool isNull() const { return secs == 0; } | |||
string toStringLong() const { | string toStringLong() const { | |||
char buf[64]; | char buf[64]; | |||
time_t_to_String(secs, buf); | time_t_to_String(secs, buf); | |||
stringstream ss; | stringstream ss; | |||
ss << buf << ' '; | ss << buf << ' '; | |||
ss << hex << secs << ':' << i; | ss << hex << secs << ':' << i; | |||
return ss.str(); | return ss.str(); | |||
End of changes. 3 change blocks. | ||||
3 lines changed or deleted | 2 lines changed or added | |||
parallel.h | parallel.h | |||
---|---|---|---|---|
skipping to change at line 75 | skipping to change at line 75 | |||
/** | /** | |||
* this is a cursor that works over a set of servers | * this is a cursor that works over a set of servers | |||
* can be used in serial/paralellel as controlled by sub classes | * can be used in serial/paralellel as controlled by sub classes | |||
*/ | */ | |||
class ClusteredCursor { | class ClusteredCursor { | |||
public: | public: | |||
ClusteredCursor( QueryMessage& q ); | ClusteredCursor( QueryMessage& q ); | |||
ClusteredCursor( const string& ns , const BSONObj& q , int options= 0 , const BSONObj& fields=BSONObj() ); | ClusteredCursor( const string& ns , const BSONObj& q , int options= 0 , const BSONObj& fields=BSONObj() ); | |||
virtual ~ClusteredCursor(); | virtual ~ClusteredCursor(); | |||
/** call before using */ | ||||
void init(); | ||||
virtual bool more() = 0; | virtual bool more() = 0; | |||
virtual BSONObj next() = 0; | virtual BSONObj next() = 0; | |||
static BSONObj concatQuery( const BSONObj& query , const BSONObj& e xtraFilter ); | static BSONObj concatQuery( const BSONObj& query , const BSONObj& e xtraFilter ); | |||
virtual string type() const = 0; | virtual string type() const = 0; | |||
virtual BSONObj explain(); | virtual BSONObj explain(); | |||
protected: | protected: | |||
auto_ptr<DBClientCursor> query( const string& server , int num = 0 | ||||
, BSONObj extraFilter = BSONObj() ); | virtual void _init() = 0; | |||
auto_ptr<DBClientCursor> query( const string& server , int num = 0 | ||||
, BSONObj extraFilter = BSONObj() , int skipLeft = 0 ); | ||||
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; | int _batchSize; | |||
bool _didInit; | ||||
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(); | |||
void reset( auto_ptr<DBClientCursor> cursor ); | void reset( auto_ptr<DBClientCursor> cursor ); | |||
skipping to change at line 189 | skipping to change at line 197 | |||
class SerialServerClusteredCursor : public ClusteredCursor { | class SerialServerClusteredCursor : public ClusteredCursor { | |||
public: | public: | |||
SerialServerClusteredCursor( const set<ServerAndQuery>& servers , Q ueryMessage& q , int sortOrder=0); | SerialServerClusteredCursor( const set<ServerAndQuery>& servers , Q ueryMessage& q , int sortOrder=0); | |||
virtual bool more(); | virtual bool more(); | |||
virtual BSONObj next(); | virtual BSONObj next(); | |||
virtual string type() const { return "SerialServer"; } | virtual string type() const { return "SerialServer"; } | |||
private: | private: | |||
virtual void _explain( map< string,list<BSONObj> >& out ); | virtual void _explain( map< string,list<BSONObj> >& out ); | |||
void _init(){} | ||||
vector<ServerAndQuery> _servers; | vector<ServerAndQuery> _servers; | |||
unsigned _serverIndex; | unsigned _serverIndex; | |||
FilteringClientCursor _current; | FilteringClientCursor _current; | |||
int _needToSkip; | int _needToSkip; | |||
}; | }; | |||
/** | /** | |||
* runs a query in parellel across N servers | * runs a query in parellel across N servers | |||
skipping to change at line 210 | skipping to change at line 220 | |||
*/ | */ | |||
class ParallelSortClusteredCursor : public ClusteredCursor { | class ParallelSortClusteredCursor : public ClusteredCursor { | |||
public: | public: | |||
ParallelSortClusteredCursor( const set<ServerAndQuery>& servers , Q ueryMessage& q , const BSONObj& sortKey ); | ParallelSortClusteredCursor( const set<ServerAndQuery>& servers , Q ueryMessage& q , const BSONObj& sortKey ); | |||
ParallelSortClusteredCursor( const set<ServerAndQuery>& servers , c onst string& ns , | ParallelSortClusteredCursor( const set<ServerAndQuery>& servers , c onst string& ns , | |||
const Query& q , int options=0, const BSONObj& fields=BSONObj() ); | const Query& q , int options=0, const BSONObj& fields=BSONObj() ); | |||
virtual ~ParallelSortClusteredCursor(); | virtual ~ParallelSortClusteredCursor(); | |||
virtual bool more(); | virtual bool more(); | |||
virtual BSONObj next(); | virtual BSONObj next(); | |||
virtual string type() const { return "ParallelSort"; } | virtual string type() const { return "ParallelSort"; } | |||
private: | protected: | |||
void _init(); | void _init(); | |||
virtual void _explain( map< string,list<BSONObj> >& out ); | virtual void _explain( map< string,list<BSONObj> >& out ); | |||
int _numServers; | int _numServers; | |||
set<ServerAndQuery> _servers; | set<ServerAndQuery> _servers; | |||
BSONObj _sortKey; | BSONObj _sortKey; | |||
FilteringClientCursor * _cursors; | FilteringClientCursor * _cursors; | |||
int _needToSkip; | int _needToSkip; | |||
End of changes. 5 change blocks. | ||||
3 lines changed or deleted | 13 lines changed or added | |||
pch.h | pch.h | |||
---|---|---|---|---|
skipping to change at line 21 | skipping to change at line 21 | |||
* | * | |||
* 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. | |||
*/ | */ | |||
#pragma once | #ifndef MONGO_PCH_H | |||
#define MONGO_PCH_H | ||||
#if defined(MONGO_EXPOSE_MACROS) | #if defined(MONGO_EXPOSE_MACROS) | |||
# define JS_C_STRINGS_ARE_UTF8 | # define JS_C_STRINGS_ARE_UTF8 | |||
# undef SUPPORT_UCP | # undef SUPPORT_UCP | |||
# define SUPPORT_UCP | # define SUPPORT_UCP | |||
# undef SUPPORT_UTF8 | # undef SUPPORT_UTF8 | |||
# define SUPPORT_UTF8 | # define SUPPORT_UTF8 | |||
# undef _CRT_SECURE_NO_WARNINGS | # undef _CRT_SECURE_NO_WARNINGS | |||
# define _CRT_SECURE_NO_WARNINGS | # define _CRT_SECURE_NO_WARNINGS | |||
#endif | #endif | |||
skipping to change at line 168 | skipping to change at line 169 | |||
} // namespace mongo | } // namespace mongo | |||
namespace mongo { | namespace mongo { | |||
typedef char _TCHAR; | typedef char _TCHAR; | |||
using boost::uint32_t; | using boost::uint32_t; | |||
using boost::uint64_t; | using boost::uint64_t; | |||
} // namespace mongo | } // namespace mongo | |||
#endif // MONGO_PCH_H | ||||
End of changes. 2 change blocks. | ||||
1 lines changed or deleted | 2 lines changed or added | |||
pdfile.h | pdfile.h | |||
---|---|---|---|---|
skipping to change at line 79 | skipping to change at line 79 | |||
*/ | */ | |||
Extent* createExtent(const char *ns, int approxSize, bool capped = false, int loops = 0); | Extent* createExtent(const char *ns, int approxSize, bool capped = false, int loops = 0); | |||
DataFileHeader *getHeader() { | DataFileHeader *getHeader() { | |||
return header; | return header; | |||
} | } | |||
/* return max size an extent may be */ | /* return max size an extent may be */ | |||
static int maxSize(); | static int maxSize(); | |||
void flush( bool sync ); | ||||
private: | private: | |||
int defaultSize( const char *filename ) const; | int defaultSize( const char *filename ) const; | |||
Extent* getExtent(DiskLoc loc); | Extent* getExtent(DiskLoc loc); | |||
Extent* _getExtent(DiskLoc loc); | Extent* _getExtent(DiskLoc loc); | |||
Record* recordAt(DiskLoc dl); | Record* recordAt(DiskLoc dl); | |||
Record* makeRecord(DiskLoc dl, int size); | Record* makeRecord(DiskLoc dl, int size); | |||
void grow(DiskLoc dl, int size); | void grow(DiskLoc dl, int size); | |||
MMF mmf; | MMF mmf; | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 2 lines changed or added | |||
processinfo.h | processinfo.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 <sys/types.h> | #include <sys/types.h> | |||
#include <string> | ||||
#ifndef _WIN32 | #ifndef _WIN32 | |||
#include <unistd.h> | #include <unistd.h> | |||
#else | #else | |||
typedef int pid_t; | typedef int pid_t; | |||
int getpid(); | int getpid(); | |||
#endif | #endif | |||
namespace mongo { | namespace mongo { | |||
skipping to change at line 62 | skipping to change at line 63 | |||
bool supported(); | bool supported(); | |||
bool blockCheckSupported(); | bool blockCheckSupported(); | |||
bool blockInMemory( char * start ); | bool blockInMemory( char * start ); | |||
private: | private: | |||
pid_t _pid; | pid_t _pid; | |||
}; | }; | |||
void writePidFile( const std::string& path ); | ||||
} | } | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 3 lines changed or added | |||
queryoptimizer.h | queryoptimizer.h | |||
---|---|---|---|---|
skipping to change at line 360 | skipping to change at line 360 | |||
} | } | |||
virtual BSONObj currKey() const { return _c->currKey(); } | virtual BSONObj currKey() const { return _c->currKey(); } | |||
virtual DiskLoc refLoc() { return _c->refLoc(); } | virtual DiskLoc refLoc() { return _c->refLoc(); } | |||
virtual void noteLocation() { | virtual void noteLocation() { | |||
_c->noteLocation(); | _c->noteLocation(); | |||
} | } | |||
virtual void checkLocation() { | virtual void checkLocation() { | |||
_c->checkLocation(); | _c->checkLocation(); | |||
} | } | |||
virtual bool supportGetMore() { return true; } | virtual bool supportGetMore() { return true; } | |||
virtual bool supportYields() { return _c->supportYields(); } | ||||
// with update we could potentially get the same document on multip le | // with update we could potentially get the same document on multip le | |||
// indexes, but update appears to already handle this with seenObje cts | // indexes, but update appears to already handle this with seenObje cts | |||
// so we don't have to do anything special here. | // so we don't have to do anything special here. | |||
virtual bool getsetdup(DiskLoc loc) { | virtual bool getsetdup(DiskLoc loc) { | |||
return _c->getsetdup( loc ); | return _c->getsetdup( loc ); | |||
} | } | |||
virtual CoveredIndexMatcher *matcher() const { return _matcher.get( ); } | virtual CoveredIndexMatcher *matcher() const { return _matcher.get( ); } | |||
// just for testing | // just for testing | |||
shared_ptr< Cursor > sub_c() const { return _c; } | shared_ptr< Cursor > sub_c() const { return _c; } | |||
private: | private: | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
ramlog.h | ramlog.h | |||
---|---|---|---|---|
skipping to change at line 50 | skipping to change at line 50 | |||
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 { | void get( vector<const char*>& v) const { | |||
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; | ||||
} | } | |||
static int repeats(const vector<const char *>& v, int i) { | static int repeats(const vector<const char *>& v, int i) { | |||
for( int j = i-1; j >= 0 && j+8 > i; j-- ) { | for( int j = i-1; j >= 0 && j+8 > i; j-- ) { | |||
if( strcmp(v[i]+20,v[j]+20) == 0 ) { | if( strcmp(v[i]+20,v[j]+20) == 0 ) { | |||
for( int x = 1; ; x++ ) { | for( int x = 1; ; x++ ) { | |||
if( j+x == i ) return j; | if( j+x == i ) return j; | |||
if( i+x>=(int) v.size() ) return -1; | if( i+x>=(int) v.size() ) return -1; | |||
if( strcmp(v[i+x]+20,v[j+x]+20) ) return -1; | if( strcmp(v[i+x]+20,v[j+x]+20) ) return -1; | |||
} | } | |||
skipping to change at line 93 | skipping to change at line 91 | |||
if( str::endsWith(s, " up\n") ) | if( str::endsWith(s, " up\n") ) | |||
return html::green(line); | return html::green(line); | |||
else if( str::contains(s, " down ") || str::endsWith(s, " d own\n") ) | else if( str::contains(s, " down ") || str::endsWith(s, " d own\n") ) | |||
return html::yellow(line); | return html::yellow(line); | |||
return line; //html::blue(line); | return line; //html::blue(line); | |||
} | } | |||
return line; | return line; | |||
} | } | |||
/* turn http:... into an anchor */ | /* turn http:... into an anchor */ | |||
string linkify(const char *s) { | string linkify(const char *s) { | |||
const char *p = s; | const char *p = s; | |||
const char *h = strstr(p, "http://"); | const char *h = strstr(p, "http://"); | |||
if( h == 0 ) return s; | if( h == 0 ) return s; | |||
const char *sp = h + 7; | const char *sp = h + 7; | |||
while( *sp && *sp != ' ' ) sp++; | while( *sp && *sp != ' ' ) sp++; | |||
string url(h, sp-h); | string url(h, sp-h); | |||
stringstream ss; | stringstream ss; | |||
ss << string(s, h-s) << "<a href=\"" << url << "\">" << url << "</ | ss << string(s, h-s) << "<a href=\"" << url << "\">" << url << | |||
a>" << sp; | "</a>" << sp; | |||
return ss.str(); | return ss.str(); | |||
} | } | |||
void toHTML(stringstream& s) { | void toHTML(stringstream& s) { | |||
vector<const char*> v; | ||||
get( v ); | ||||
bool first = true; | bool first = true; | |||
s << "<pre>\n"; | s << "<pre>\n"; | |||
vector<const char *> v = get(); | ||||
for( int i = 0; i < (int)v.size(); i++ ) { | for( int i = 0; i < (int)v.size(); i++ ) { | |||
assert( strlen(v[i]) > 20 ); | assert( strlen(v[i]) > 20 ); | |||
int r = repeats(v, i); | int r = repeats(v, i); | |||
if( r < 0 ) { | if( r < 0 ) { | |||
s << color( linkify( clean(v,i).c_str() ) ); | s << color( linkify( clean(v,i).c_str() ) ); | |||
} | } | |||
else { | else { | |||
stringstream x; | stringstream x; | |||
x << string(v[i], 0, 20); | x << string(v[i], 0, 20); | |||
int nr = (i-r); | int nr = (i-r); | |||
int last = i+nr-1; | int last = i+nr-1; | |||
for( ; r < i ; r++ ) x << '.'; | for( ; r < i ; r++ ) x << '.'; | |||
if( 1 ) { | if( 1 ) { | |||
stringstream r; | stringstream r; | |||
if( nr == 1 ) r << "repeat last line"; | if( nr == 1 ) r << "repeat last line"; | |||
End of changes. 8 change blocks. | ||||
18 lines changed or deleted | 18 lines changed or added | |||
rs.h | rs.h | |||
---|---|---|---|---|
skipping to change at line 72 | skipping to change at line 72 | |||
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); | |||
~Manager(); | ||||
void msgReceivedNewConfig(BSONObj); | 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) { } | |||
skipping to change at line 111 | skipping to change at line 112 | |||
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 { | |||
public: | ||||
const unsigned magic; | ||||
void assertValid() { assert( magic == 0x12345677 ); } | ||||
private: | private: | |||
mutex m; | mutex m; | |||
int _locked; | int _locked; | |||
ThreadLocalValue<bool> _lockedByMe; | ThreadLocalValue<bool> _lockedByMe; | |||
protected: | protected: | |||
RSBase() : m("RSBase"), _locked(0) { } | RSBase() : magic(0x12345677), m("RSBase"), _locked(0) { } | |||
~RSBase() { | ||||
log() << "~RSBase should never be called?" << rsLog; | ||||
assert(false); | ||||
} | ||||
class lock { | class lock { | |||
RSBase& rsbase; | RSBase& rsbase; | |||
auto_ptr<scoped_lock> sl; | auto_ptr<scoped_lock> sl; | |||
public: | public: | |||
lock(RSBase* b) : rsbase(*b) { | lock(RSBase* b) : rsbase(*b) { | |||
if( rsbase._lockedByMe.get() ) | if( rsbase._lockedByMe.get() ) | |||
return; // recursive is ok... | return; // recursive is ok... | |||
sl.reset( new scoped_lock(rsbase.m) ); | sl.reset( new scoped_lock(rsbase.m) ); | |||
skipping to change at line 168 | skipping to change at line 176 | |||
SP() : state(MemberState::RS_STARTUP), primary(0) { } | SP() : state(MemberState::RS_STARTUP), primary(0) { } | |||
MemberState state; | MemberState state; | |||
const Member *primary; | const Member *primary; | |||
}; | }; | |||
const SP get() { | const SP get() { | |||
scoped_lock lk(m); | scoped_lock lk(m); | |||
return sp; | return sp; | |||
} | } | |||
MemberState getState() const { return sp.state; } | MemberState getState() const { return sp.state; } | |||
const Member* getPrimary() const { return sp.primary; } | const Member* getPrimary() const { return sp.primary; } | |||
void change(MemberState s) { | void change(MemberState s, const Member *self) { | |||
scoped_lock lk(m); | scoped_lock lk(m); | |||
sp.state = s; | sp.state = s; | |||
// note : we don't correct primary if RS_PRIMARY was set here. | if( s.primary() ) { | |||
that must be done upstream. | sp.primary = self; | |||
} | ||||
else { | ||||
if( self == sp.primary ) | ||||
sp.primary = 0; | ||||
} | ||||
} | } | |||
void set(MemberState s, const Member *p) { | void set(MemberState s, const Member *p) { | |||
scoped_lock lk(m); | scoped_lock lk(m); | |||
sp.state = s; sp.primary = p; | sp.state = s; sp.primary = p; | |||
} | } | |||
void setSelfPrimary(const Member *self) { | void setSelfPrimary(const Member *self) { change(MemberState::RS_PR | |||
scoped_lock lk(m); | IMARY, self); } | |||
sp.state = MemberState::RS_PRIMARY; | ||||
sp.primary = self; | ||||
} | ||||
void setOtherPrimary(const Member *mem) { | void setOtherPrimary(const Member *mem) { | |||
scoped_lock lk(m); | scoped_lock lk(m); | |||
assert( !sp.state.primary() ); | assert( !sp.state.primary() ); | |||
sp.primary = mem; | sp.primary = mem; | |||
} | } | |||
StateBox() : m("StateBox") { } | StateBox() : m("StateBox") { } | |||
private: | private: | |||
mutex m; | mutex m; | |||
SP sp; | SP sp; | |||
}; | }; | |||
void parseReplsetCmdLine(string cfgString, string& setname, vector<Host | ||||
AndPort>& seeds, set<HostAndPort>& seedSet ); | ||||
/** Parameter given to the --replSet command line option (parsed). | ||||
Syntax is "<setname>/<seedhost1>,<seedhost2>" | ||||
where setname is a name and seedhost is "<host>[:<port>]" */ | ||||
class ReplSetCmdline { | ||||
public: | ||||
ReplSetCmdline(string cfgString) { parseReplsetCmdLine(cfgString, s | ||||
etname, seeds, seedSet); } | ||||
string setname; | ||||
vector<HostAndPort> seeds; | ||||
set<HostAndPort> seedSet; | ||||
}; | ||||
/* 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 | |||
skipping to change at line 226 | skipping to change at line 249 | |||
private: | private: | |||
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 !box.getState().fatal(); } | bool ok() const { return !box.getState().fatal(); } | |||
void relinquish(); | void relinquish(); | |||
void forgetPrimary(); | ||||
protected: | protected: | |||
bool _stepDown(); | bool _stepDown(); | |||
private: | private: | |||
void assumePrimary(); | void assumePrimary(); | |||
void loadLastOpTimeWritten(); | void loadLastOpTimeWritten(); | |||
void changeState(MemberState s); | void changeState(MemberState s); | |||
protected: | protected: | |||
// "heartbeat message" | // "heartbeat message" | |||
// sent in requestHeartbeat respond in field "hbm" | // sent in requestHeartbeat respond in field "hbm" | |||
char _hbmsg[256]; // we change this unocked, thus not a c++ string | char _hbmsg[256]; // we change this unocked, thus not a c++ string | |||
public: | public: | |||
void sethbmsg(string s, int logLevel = 0) { | void sethbmsg(string s, int logLevel = 0) { | |||
unsigned sz = s.size(); | unsigned sz = s.size(); | |||
if( sz >= 256 ) | if( sz >= 256 ) | |||
memcpy(_hbmsg, s.c_str(), 255); | memcpy(_hbmsg, s.c_str(), 255); | |||
else { | else { | |||
_hbmsg[sz] = 0; | _hbmsg[sz] = 0; | |||
memcpy(_hbmsg, s.c_str(), sz); | memcpy(_hbmsg, s.c_str(), sz); | |||
} | } | |||
log(logLevel) << "replSet " << s << rsLog; | if( !s.empty() ) | |||
log(logLevel) << "replSet " << s << rsLog; | ||||
} | } | |||
protected: | 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 box.getState(); } | 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 | /* throws exception if a problem initializing. */ | |||
replsetname/host1,host2:port,... | ReplSetImpl(ReplSetCmdline&); | |||
where :port is optional. | ||||
throws exception if a problem initializing. */ | ||||
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: | |||
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 ReplSetConfig::MemberCfg& myConfig() const { return _self->co nfig(); } | const ReplSetConfig::MemberCfg& myConfig() const { return _self->co nfig(); } | |||
bool iAmArbiterOnly() const { return myConfig().arbiterOnly; } | bool iAmArbiterOnly() const { return myConfig().arbiterOnly; } | |||
bool iAmPotentiallyHot() const { return myConfig().potentiallyHot() ; } | bool iAmPotentiallyHot() const { return myConfig().potentiallyHot() ; } | |||
protected: | ||||
Member *_self; | Member *_self; | |||
private: | ||||
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 _self->id(); } | unsigned selfId() const { return _self->id(); } | |||
shared_ptr<Manager> mgr; | 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; | |||
skipping to change at line 311 | skipping to change at line 336 | |||
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 syncDoInitialSync(); | |||
void _syncThread(); | void _syncThread(); | |||
void syncTail(); | void syncTail(); | |||
void syncApply(const BSONObj &o); | void syncApply(const BSONObj &o); | |||
void syncRollback(OplogReader& r); | void syncRollback(OplogReader& r); | |||
void syncFixUp(HowToFixUp& h, DBClientConnection*); | void syncFixUp(HowToFixUp& h, OplogReader& r); | |||
public: | public: | |||
void syncThread(); | void syncThread(); | |||
}; | }; | |||
class ReplSet : public ReplSetImpl { | class ReplSet : public ReplSetImpl { | |||
public: | public: | |||
ReplSet(string cfgString) : ReplSetImpl(cfgString) { } | ReplSet(ReplSetCmdline& replSetCmdline) : ReplSetImpl(replSetCmdlin e) { } | |||
bool stepDown() { return _stepDown(); } | bool stepDown() { return _stepDown(); } | |||
string selfFullName() { | ||||
lock lk(this); | ||||
return _self->fullName(); | ||||
} | ||||
/* call after constructing to start - returns fairly quickly after la[unching its threads */ | /* call after constructing to start - returns fairly quickly after la[unching its threads */ | |||
void go() { _go(); } | void go() { _go(); } | |||
void fatal() { _fatal(); } | void fatal() { _fatal(); } | |||
bool 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 ); } | |||
skipping to change at line 373 | skipping to change at line 403 | |||
} | } | |||
if( theReplSet == 0 ) { | if( theReplSet == 0 ) { | |||
result.append("startupStatus", ReplSet::startupStatus); | result.append("startupStatus", ReplSet::startupStatus); | |||
errmsg = ReplSet::startupStatusMsg.empty() ? "replset unkno wn error 2" : ReplSet::startupStatusMsg; | errmsg = ReplSet::startupStatusMsg.empty() ? "replset unkno wn error 2" : ReplSet::startupStatusMsg; | |||
return false; | return false; | |||
} | } | |||
return true; | return true; | |||
} | } | |||
}; | }; | |||
/** helpers ----------------- */ | ||||
void parseReplsetCmdLine(string cfgString, string& setname, vector<Host | ||||
AndPort>& seeds, set<HostAndPort>& seedSet ); | ||||
/** inlines ----------------- */ | /** inlines ----------------- */ | |||
inline Member::Member(HostAndPort h, unsigned ord, const ReplSetConfig: :MemberCfg *c, bool self) : | inline Member::Member(HostAndPort h, unsigned ord, const ReplSetConfig: :MemberCfg *c, bool self) : | |||
_config(c), _h(h), _hbinfo(ord) { | _config(c), _h(h), _hbinfo(ord) { | |||
if( self ) { | if( self ) { | |||
_hbinfo.health = 1.0; | _hbinfo.health = 1.0; | |||
} | } | |||
} | } | |||
inline bool ReplSet::isMaster(const char *client) { | inline bool ReplSet::isMaster(const char *client) { | |||
End of changes. 17 change blocks. | ||||
23 lines changed or deleted | 50 lines changed or added | |||
rs_member.h | rs_member.h | |||
---|---|---|---|---|
skipping to change at line 63 | skipping to change at line 63 | |||
bool operator==(const MemberState& r) const { return s == r.s; } | bool operator==(const MemberState& r) const { return s == r.s; } | |||
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),skew(INT_MIN) { } | |||
HeartbeatInfo(unsigned id); | HeartbeatInfo(unsigned id); | |||
bool up() const { return health > 0; } | bool up() const { return health > 0; } | |||
unsigned id() const { return _id; } | unsigned id() const { return _id; } | |||
MemberState hbstate; | MemberState hbstate; | |||
double health; | double health; | |||
time_t upSince; | time_t upSince; | |||
time_t lastHeartbeat; | time_t lastHeartbeat; | |||
string lastHeartbeatMsg; | string lastHeartbeatMsg; | |||
OpTime opTime; | OpTime opTime; | |||
int skew; | ||||
/* true if changed in a way of interest to the repl set manager. */ | ||||
bool changed(const HeartbeatInfo& old) const; | bool changed(const HeartbeatInfo& old) const; | |||
}; | }; | |||
inline HeartbeatInfo::HeartbeatInfo(unsigned id) : _id(id) { | inline HeartbeatInfo::HeartbeatInfo(unsigned id) : _id(id) { | |||
health = -1.0; | health = -1.0; | |||
lastHeartbeat = upSince = 0; | lastHeartbeat = upSince = 0; | |||
skew = INT_MIN; | ||||
} | } | |||
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. 3 change blocks. | ||||
1 lines changed or deleted | 5 lines changed or added | |||
stringdata.h | stringdata.h | |||
---|---|---|---|---|
skipping to change at line 41 | skipping to change at line 41 | |||
: _data(c), _size((unsigned) strlen(c)) {} | : _data(c), _size((unsigned) strlen(c)) {} | |||
StringData( const string& s ) | StringData( const string& s ) | |||
: _data(s.c_str()), _size((unsigned) 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) {} | |||
// Construct a StringData explicitly, for the case where the | ||||
// length of the string is already known. 'c' must be a | ||||
// pointer to a null-terminated string, and strlenOfc must be | ||||
// the length that std::strlen(c) would return, a.k.a the | ||||
// index of the terminator in c. | ||||
StringData( const char* c, size_t strlenOfc ) | ||||
: _data(c), _size((unsigned) strlenOfc) {} | ||||
const char* const data() const { return _data; } | const char* const data() const { return _data; } | |||
const unsigned size() const { return _size; } | const unsigned size() const { return _size; } | |||
private: | private: | |||
// TODO - Hook this class up in the BSON machinery | // TODO - Hook this class up in the BSON machinery | |||
// There are two assumptions here that we may want to review then. | // There are two assumptions here that we may want to review then. | |||
// '_data' *always* finishes with a null terminator | // '_data' *always* finishes with a null terminator | |||
// 'size' does *not* account for the null terminator | // 'size' does *not* account for the null terminator | |||
// These assumptions may make it easier to minimize changes to exis ting code | // These assumptions may make it easier to minimize changes to exis ting code | |||
const char* const _data; | const char* const _data; | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 8 lines changed or added | |||
syncclusterconnection.h | syncclusterconnection.h | |||
---|---|---|---|---|
skipping to change at line 90 | skipping to change at line 90 | |||
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 ); | virtual bool callRead( Message& toSend , Message& response ); | |||
virtual ConnectionString::ConnectionType type() const { return Conn | ||||
ectionString::SYNC; } | ||||
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. 1 change blocks. | ||||
0 lines changed or deleted | 3 lines changed or added | |||
task.h | task.h | |||
---|---|---|---|---|
skipping to change at line 28 | skipping to change at line 28 | |||
#pragma once | #pragma once | |||
#include "../background.h" | #include "../background.h" | |||
namespace mongo { | namespace mongo { | |||
namespace task { | namespace task { | |||
/** abstraction around threads. simpler than BackgroundJob which i s used behind the scenes. | /** abstraction around threads. simpler than BackgroundJob which i s used behind the scenes. | |||
a shared_ptr is kept to the task - both by the task while runni | allocate the Task dynamically. when the thread terminates, the | |||
ng and the caller. that way | Task object will delete itself. | |||
the task object gets cleaned up once the last reference goes aw | ||||
ay. | ||||
*/ | */ | |||
class Task : private BackgroundJob { | class Task : private BackgroundJob { | |||
protected: | protected: | |||
virtual void doWork() = 0; // implement the ta sk here. | virtual void doWork() = 0; // implement the ta sk here. | |||
virtual string name() = 0; // name the threada | virtual string name() = 0; // name the threada | |||
public: | public: | |||
Task(); | Task(); | |||
/** for a repeating task, stop after current invocation ends. c an be called by other threads | /** for a repeating task, stop after current invocation ends. c an be called by other threads | |||
as long as the Task is still in scope. | as long as the Task is still in scope. | |||
*/ | */ | |||
void halt(); | void halt(); | |||
private: | private: | |||
shared_ptr<Task> me; | ||||
unsigned n, repeat; | unsigned n, repeat; | |||
friend void fork(shared_ptr<Task> t); | friend void fork(Task* t); | |||
friend void repeat(shared_ptr<Task> t, unsigned millis); | friend void repeat(Task* t, unsigned millis); | |||
virtual void run(); | virtual void run(); | |||
virtual void ending(); | virtual void ending() { } | |||
void begin(shared_ptr<Task>); | void begin(); | |||
}; | }; | |||
/** run once */ | /** run once */ | |||
void fork(shared_ptr<Task> t); | void fork(Task *t); | |||
/** run doWork() over and over, with a pause between runs of millis */ | /** run doWork() over and over, with a pause between runs of millis */ | |||
void repeat(shared_ptr<Task> t, unsigned millis); | void repeat(Task *t, unsigned millis); | |||
/*** Example *** | /*** Example *** | |||
inline void sample() { | inline void sample() { | |||
class Sample : public Task { | class Sample : public Task { | |||
public: | public: | |||
int result; | int result; | |||
virtual void doWork() { result = 1234; } | virtual void doWork() { result = 1234; } | |||
Sample() : result(0) { } | Sample() : result(0) { } | |||
}; | }; | |||
shared_ptr<Sample> q( new Sample() ); | shared_ptr<Sample> q( new Sample() ); | |||
End of changes. 6 change blocks. | ||||
11 lines changed or deleted | 8 lines changed or added | |||
util.h | util.h | |||
---|---|---|---|---|
skipping to change at line 143 | skipping to change at line 143 | |||
ns = big.substr( start + 1 , ( end - start ) - 1 ); | ns = big.substr( start + 1 , ( end - start ) - 1 ); | |||
raw = big.substr( end + 1 ); | raw = big.substr( end + 1 ); | |||
return true; | return true; | |||
} | } | |||
private: | private: | |||
bool _justConnection; | bool _justConnection; | |||
string _ns; | 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 ); | |||
void resetShardVersion( DBClientBase * conn ); | ||||
} | } | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||