assert_util.h   assert_util.h 
skipping to change at line 84 skipping to change at line 84
int regular; int regular;
int warning; int warning;
int msg; int msg;
int user; int user;
int rollovers; int rollovers;
}; };
extern AssertionCount assertionCount; extern AssertionCount assertionCount;
struct ExceptionInfo {
ExceptionInfo() : msg(""),code(-1){}
ExceptionInfo( const char * m , int c )
: msg( m ) , code( c ){
}
ExceptionInfo( const string& m , int c )
: msg( m ) , code( c ){
}
void append( BSONObjBuilder& b , const char * m = "$err" , const ch
ar * c = "code" ) const ;
operator string() const { stringstream ss; ss << "exception: " << c
ode << " " << msg; return ss.str(); }
bool empty() const { return msg.empty(); }
string msg;
int code;
};
class DBException : public std::exception { class DBException : public std::exception {
public: public:
virtual const char* what() const throw() = 0; DBException( const ExceptionInfo& ei ) : _ei(ei){}
DBException( const char * msg , int code ) : _ei(msg,code){}
DBException( const string& msg , int code ) : _ei(msg,code){}
virtual ~DBException() throw() { }
virtual const char* what() const throw(){ return _ei.msg.c_str(); }
virtual int getCode() const { return _ei.code; }
virtual void appendPrefix( stringstream& ss ) const { }
virtual string toString() const { virtual string toString() const {
return what(); stringstream ss; ss << getCode() << " " << what(); return ss.st
r();
return ss.str();
} }
virtual int getCode() const = 0;
operator string() const { stringstream ss; ss << getCode() << " " < operator string() const { return toString(); }
< what(); return ss.str(); }
const ExceptionInfo& getInfo() const { return _ei; }
protected:
ExceptionInfo _ei;
}; };
class AssertionException : public DBException { class AssertionException : public DBException {
public: public:
int code;
string msg; AssertionException( const ExceptionInfo& ei ) : DBException(ei){}
AssertionException() { code = 0; } AssertionException( const char * msg , int code ) : DBException(msg
,code){}
AssertionException( const string& msg , int code ) : DBException(ms
g,code){}
virtual ~AssertionException() throw() { } virtual ~AssertionException() throw() { }
virtual bool severe() {
return true; virtual bool severe() { return true; }
} virtual bool isUserAssertion() { return false; }
virtual bool isUserAssertion() {
return false;
}
virtual int getCode() const { return code; }
virtual const char* what() const throw() { return msg.c_str(); }
/* true if an interrupted exception - see KillCurrentOp */ /* true if an interrupted exception - see KillCurrentOp */
bool interrupted() { bool interrupted() {
return code == 11600 || code == 11601; return _ei.code == 11600 || _ei.code == 11601;
} }
}; };
/* UserExceptions are valid errors that a user can cause, like out of d isk space or duplicate key */ /* UserExceptions are valid errors that a user can cause, like out of d isk space or duplicate key */
class UserException : public AssertionException { class UserException : public AssertionException {
public: public:
UserException(int c , const string& m) { UserException(int c , const string& m) : AssertionException( m , c
code = c; ){}
msg = m;
} virtual bool severe() { return false; }
virtual bool severe() { virtual bool isUserAssertion() { return true; }
return false; virtual void appendPrefix( stringstream& ss ) const { ss << "useras
} sert:"; }
virtual bool isUserAssertion() {
return true;
}
virtual string toString() const {
return "userassert:" + msg;
}
}; };
class MsgAssertionException : public AssertionException { class MsgAssertionException : public AssertionException {
public: public:
MsgAssertionException(int c, const char *m) { MsgAssertionException( const ExceptionInfo& ei ) : AssertionExcepti
code = c; on( ei ){}
msg = m; MsgAssertionException(int c, const string& m) : AssertionException(
} m , c ){}
MsgAssertionException(int c, const string& m) { virtual bool severe() { return false; }
code = c; virtual void appendPrefix( stringstream& ss ) const { ss << "masser
msg = m; t:"; }
}
virtual bool severe() {
return false;
}
virtual string toString() const {
return "massert:" + msg;
}
}; };
void asserted(const char *msg, const char *file, unsigned line); void asserted(const char *msg, const char *file, unsigned line);
void wasserted(const char *msg, const char *file, unsigned line); void wasserted(const char *msg, const char *file, unsigned line);
void uasserted(int msgid, const char *msg); void uasserted(int msgid, const char *msg);
inline void uasserted(int msgid , string msg) { uasserted(msgid, msg.c_ str()); } inline void uasserted(int msgid , string msg) { uasserted(msgid, msg.c_ str()); }
void uassert_nothrow(const char *msg); // reported via lasterror, but d on't throw exception void uassert_nothrow(const char *msg); // reported via lasterror, but d on't throw exception
void msgassertedNoTrace(int msgid, const char *msg); void msgassertedNoTrace(int msgid, const char *msg);
void msgasserted(int msgid, const char *msg); void msgasserted(int msgid, const char *msg);
inline void msgasserted(int msgid, string msg) { msgasserted(msgid, msg .c_str()); } inline void msgasserted(int msgid, string msg) { msgasserted(msgid, msg .c_str()); }
 End of changes. 9 change blocks. 
44 lines changed or deleted 66 lines changed or added


 balancer_policy.h   balancer_policy.h 
skipping to change at line 43 skipping to change at line 43
* moving, it returns NULL. * moving, it returns NULL.
* *
* @param ns is the collections namepace. * @param ns is the collections namepace.
* @param shardLimitMap is a map from shardId to an object that des cribes (for now) space * @param shardLimitMap is a map from shardId to an object that des cribes (for now) space
* cap and usage. E.g.: { "maxSize" : <size_in_MB> , "usedSize" : < size_in_MB> }. * cap and usage. E.g.: { "maxSize" : <size_in_MB> , "usedSize" : < size_in_MB> }.
* @param shardToChunksMap is a map from shardId to chunks that liv e there. A chunk's format * @param shardToChunksMap is a map from shardId to chunks that liv e there. A chunk's format
* is { }. * is { }.
* @param balancedLastTime is the number of chunks effectively move d in the last round. * @param balancedLastTime is the number of chunks effectively move d in the last round.
* @returns NULL or ChunkInfo of the best move to make towards bala cing the collection. * @returns NULL or ChunkInfo of the best move to make towards bala cing the collection.
*/ */
static ChunkInfo* balance( const string& ns, const map< string, BSO typedef map< string,BSONObj > ShardToLimitsMap;
NObj>& shardLimitsMap, typedef map< string,vector<BSONObj> > ShardToChunksMap;
const map< string,vector<BSONObj> >& sha static ChunkInfo* balance( const string& ns, const ShardToLimitsMap
rdToChunksMap, int balancedLastTime ); & shardToLimitsMap,
const ShardToChunksMap& shardToChunksMap
, int balancedLastTime );
// below exposed for testing purposes only -- treat it as private - - // below exposed for testing purposes only -- treat it as private - -
static BSONObj pickChunk( const vector<BSONObj>& from, const vector <BSONObj>& to ); static BSONObj pickChunk( const vector<BSONObj>& from, const vector <BSONObj>& to );
/** /**
* Returns true if a shard can receive new chunks based on that sha * Returns true if a shard cannot receive any new chunks bacause it
rd's 'shardLimits' information. reache 'shardLimits'.
* Expects the optional fields "maxSize", can in size in MB, and "u * Expects the optional fields "maxSize", can in size in MB, and "u
sedSize", currently used size in MB, sedSize", currently used size
* on 'shardLimits'. * in MB, on 'shardLimits'.
*/ */
static bool isReceiver( BSONObj shardLimits ); static bool isSizeMaxed( BSONObj shardLimits );
/** /**
* Returns true if 'shardLimist' contains a field "draining". * Returns true if 'shardLimist' contains a field "draining". Expec
ts the optional field
* "isDraining" on 'shrdLimits'.
*/ */
static bool isDraining( BSONObj shardLimits ); static bool isDraining( BSONObj shardLimits );
private:
// Convenience types
typedef ShardToChunksMap::const_iterator ShardToChunksIter;
typedef ShardToLimitsMap::const_iterator ShardToLimitsIter;
}; };
struct BalancerPolicy::ChunkInfo { struct BalancerPolicy::ChunkInfo {
const string ns; const string ns;
const string to; const string to;
const string from; const string from;
const BSONObj chunk; const BSONObj chunk;
ChunkInfo( const string& a_ns , const string& a_to , const string& a_from , const BSONObj& a_chunk ) ChunkInfo( const string& a_ns , const string& a_to , const string& a_from , const BSONObj& a_chunk )
: ns( a_ns ) , to( a_to ) , from( a_from ), chunk( a_chunk ){} : ns( a_ns ) , to( a_to ) , from( a_from ), chunk( a_chunk ){}
 End of changes. 5 change blocks. 
11 lines changed or deleted 21 lines changed or added


 bson.h   bson.h 
skipping to change at line 38 skipping to change at line 38
BSONObj and its helpers BSONObj and its helpers
"BSON" stands for "binary JSON" -- ie a binary way to represent objects that would be "BSON" stands for "binary JSON" -- ie a binary way to represent objects that would be
represented in JSON (plus a few extensions useful for databases & other languages). represented in JSON (plus a few extensions useful for databases & other languages).
http://www.bsonspec.org/ http://www.bsonspec.org/
*/ */
#pragma once #pragma once
#if defined(MONGO_EXPOSE_MACROS)
#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
BSON can be used header only.
*/
#endif
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <boost/utility.hpp> #include <boost/utility.hpp>
namespace bson { namespace bson {
class assertion : public std::exception { class assertion : public std::exception {
public: public:
virtual const char* what() const throw() { return "BsonAssertion"; } virtual const char* what() const throw() { return "BsonAssertion"; }
}; };
} }
skipping to change at line 59 skipping to change at line 66
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; std::cout << "assertion failure in bson library" << std::endl;
throw bson::assertion(); throw bson::assertion();
} }
} }
#endif #endif
#if !defined(uassert) #if !defined(uassert)
inline void uasserted(unsigned msgid, std::string) {
throw bson::assertion();
}
inline void uassert(unsigned msgid, std::string msg, bool expr) { inline void uassert(unsigned msgid, std::string msg, bool expr) {
if( !expr ) if( !expr )
throw bson::assertion(); 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();
} }
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();
} }
 End of changes. 3 change blocks. 
1 lines changed or deleted 14 lines changed or added


 bson_db.h   bson_db.h 
skipping to change at line 51 skipping to change at line 51
} }
inline OpTime BSONElement::_opTime() const { inline OpTime BSONElement::_opTime() const {
return OpTime( *reinterpret_cast< const unsigned long long* >( valu e() ) ); return OpTime( *reinterpret_cast< const unsigned long long* >( valu e() ) );
} }
inline string BSONElement::_asCode() const { inline string BSONElement::_asCode() const {
switch( type() ){ switch( type() ){
case mongo::String: case mongo::String:
case Code: case Code:
return valuestr(); return string(valuestr(), valuestrsize()-1);
case CodeWScope: case CodeWScope:
return codeWScopeCode(); return string(codeWScopeCode(), *(int*)(valuestr())-1);
default: default:
log() << "can't convert type: " << (int)(type()) << " to code" << endl; log() << "can't convert type: " << (int)(type()) << " to code" << endl;
} }
uassert( 10062 , "not code" , 0 ); uassert( 10062 , "not code" , 0 );
return ""; return "";
} }
inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<(DateNowLab eler& id){ inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<(DateNowLab eler& id){
_builder->appendDate(_fieldName, jsTime()); _builder->appendDate(_fieldName, jsTime());
_fieldName = 0; _fieldName = 0;
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 bsonelement.h   bsonelement.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 <vector> #include <vector>
#include <string.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;
class BSONElement;
/* l and r MUST have same type when called: check that first. */
int compareElementValues(const BSONElement& l, const BSONElement& r);
/** BSONElement represents an "element" in a BSONObj. So for the object { a : 3, b : "abc" }, /** BSONElement represents an "element" in a BSONObj. So for the object { a : 3, b : "abc" },
'a : 3' is the first element (key+value). 'a : 3' is the first element (key+value).
The BSONElement object points into the BSONObj's data. Thus the BSONOb j must stay in scope The BSONElement object points into the BSONObj's data. Thus the BSONOb j must stay in scope
for the life of the BSONElement. for the life of the BSONElement.
internals: internals:
<type><fieldName ><value> <type><fieldName ><value>
-------- size() ------------ -------- size() ------------
skipping to change at line 213 skipping to change at line 218
*/ */
const char * valuestr() const { const char * valuestr() const {
return value() + 4; return value() + 4;
} }
/** Get the string value of the element. If not a string returns "". * / /** Get the string value of the element. If not a string returns "". * /
const char *valuestrsafe() const { const char *valuestrsafe() const {
return type() == mongo::String ? valuestr() : ""; return type() == mongo::String ? valuestr() : "";
} }
/** Get the string value of the element. If not a string returns "". * / /** Get the string value of the element. If not a string returns "". * /
string str() const { return valuestrsafe(); } string str() const {
return type() == mongo::String ? string(valuestr(), valuestrsize()-
1) : string();
}
/** Get javascript code of a CodeWScope data element. */ /** Get javascript code of a CodeWScope data element. */
const char * codeWScopeCode() const { const char * codeWScopeCode() const {
return value() + 8; return value() + 8;
} }
/** Get the scope SavedContext of a CodeWScope data element. */ /** Get the scope SavedContext of a CodeWScope data element. */
const char * codeWScopeScopeData() const { const char * codeWScopeScopeData() const {
// TODO fix // TODO fix
return codeWScopeCode() + strlen( codeWScopeCode() ) + 1; return codeWScopeCode() + strlen( codeWScopeCode() ) + 1;
} }
skipping to change at line 384 skipping to change at line 391
int fieldNameSize() const { int fieldNameSize() const {
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 {
uassert(13111, "unexpected or missing type value in BSON object", t if ( t != type() ){
== type()); stringstream ss;
ss << "wrong type for BSONElement (" << fieldName() << ") " <<
type() << " != " << t;
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;
} }
}; };
inline int BSONElement::canonicalType() const { inline int BSONElement::canonicalType() const {
BSONType t = type(); BSONType t = type();
 End of changes. 4 change blocks. 
3 lines changed or deleted 15 lines changed or added


 bsoninlines.h   bsoninlines.h 
skipping to change at line 275 skipping to change at line 275
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(), strSize WNull ) ); (strSizeWNull - 1) == strnlen( codeWScopeCode(), strSi zeWNull ) );
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 425 skipping to change at line 425
s << "MaxKey"; s << "MaxKey";
break; break;
case MinKey: case MinKey:
s << "MinKey"; s << "MinKey";
break; break;
case CodeWScope: case CodeWScope:
s << "CodeWScope( " s << "CodeWScope( "
<< codeWScopeCode() << ", " << codeWScopeObject().toString( ) << ")"; << codeWScopeCode() << ", " << codeWScopeObject().toString( ) << ")";
break; break;
case Code: case Code:
if ( valuestrsize() > 80 ) if ( valuestrsize() > 80 ) {
s << string(valuestr()).substr(0, 70) << "..."; s.write(valuestr(), 70);
else { s << "...";
s << valuestr(); } else {
s.write(valuestr(), valuestrsize()-1);
} }
break; break;
case Symbol: case Symbol:
case mongo::String: case mongo::String:
if ( valuestrsize() > 80 ) s << '"';
s << '"' << string(valuestr()).substr(0, 70) << "...\""; if ( valuestrsize() > 80 ) {
else { s.write(valuestr(), 70);
s << '"' << valuestr() << '"'; s << "...\"";
} else {
s.write(valuestr(), valuestrsize()-1);
s << '"';
} }
break; break;
case DBRef: case DBRef:
s << "DBRef('" << valuestr() << "',"; s << "DBRef('" << valuestr() << "',";
{ {
mongo::OID *x = (mongo::OID *) (valuestr() + valuestrsize() ); mongo::OID *x = (mongo::OID *) (valuestr() + valuestrsize() );
s << *x << ')'; s << *x << ')';
} }
break; break;
case jstOID: case jstOID:
skipping to change at line 574 skipping to change at line 578
inline ostream& operator<<( ostream &s, const BSONObj &o ) { inline ostream& operator<<( ostream &s, const BSONObj &o ) {
return s << o.toString(); return s << o.toString();
} }
inline ostream& operator<<( ostream &s, const BSONElement &e ) { inline ostream& operator<<( ostream &s, const BSONElement &e ) {
return s << e.toString(); return s << e.toString();
} }
inline void BSONElement::Val(BSONObj& v) const { v = Obj(); } inline void BSONElement::Val(BSONObj& v) const { v = Obj(); }
template<typename T>
inline BSONFieldValue<BSONObj> BSONField<T>::query( const char * q , co
nst T& t ) const {
BSONObjBuilder b;
b.append( q , t );
return BSONFieldValue<BSONObj>( _name , b.obj() );
}
} }
 End of changes. 4 change blocks. 
9 lines changed or deleted 21 lines changed or added


 bsonobj.h   bsonobj.h 
skipping to change at line 94 skipping to change at line 94
b.append(reinterpret_cast<const void *>( objdata() ), objsize() ); b.append(reinterpret_cast<const void *>( objdata() ), objsize() );
} }
/** 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 ) const; string toString( bool isArray = false ) const;
operator string() const { return toString(); } operator string() const { return toString(); }
/** Properly formatted JSON string. /** Properly formatted JSON string.
@param pretty if tru1 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
note: iterates to count the fields note: iterates to count the fields
*/ */
int nFields() const; int nFields() const;
/** adds the field names to the fields set. does NOT clear it (app ends). */ /** adds the field names to the fields set. does NOT clear it (app ends). */
int getFieldNames(set<string>& fields) const; int getFieldNames(set<string>& fields) const;
/** return has eoo() true if no match /** return has eoo() true if no match
supports "." notation to reach into embedded objects supports "." notation to reach into embedded objects
*/ */
BSONElement getFieldDotted(const char *name) const; BSONElement getFieldDotted(const char *name) const;
/** return has eoo() true if no match
supports "." notation to reach into embedded objects
*/
BSONElement getFieldDotted(const string& name) const {
return getFieldDotted( name.c_str() );
}
/** Like getFieldDotted(), but expands multikey arrays and returns all matching objects /** Like getFieldDotted(), but expands multikey arrays and returns all matching objects
*/ */
void getFieldsDotted(const char *name, BSONElementSet &ret ) const; void getFieldsDotted(const char *name, BSONElementSet &ret ) const;
/** Like getFieldDotted(), but returns first array encountered whil e traversing the /** Like getFieldDotted(), but returns first array encountered whil e traversing the
dotted fields of name. The name variable is updated to represe nt field dotted fields of name. The name variable is updated to represe nt field
names with respect to the returned element. */ names with respect to the returned element. */
BSONElement getFieldDottedOrArray(const char *&name) const; BSONElement getFieldDottedOrArray(const char *&name) const;
/** Get the field of the specified name. eoo() is true on the retur ned /** Get the field of the specified name. eoo() is true on the retur ned
element if not found. element if not found.
skipping to change at line 240 skipping to change at line 247
bool considerFieldName=true) const; bool considerFieldName=true) const;
/**wo='well ordered'. fields must be in same order in each object. /**wo='well ordered'. fields must be in same order in each object.
Ordering is with respect to the signs of the elements Ordering is with respect to the signs of the elements
and allows ascending / descending key mixing. and allows ascending / descending key mixing.
@return <0 if l<r. 0 if l==r. >0 if l>r @return <0 if l<r. 0 if l==r. >0 if l>r
*/ */
int woCompare(const BSONObj& r, const BSONObj &ordering = BSONObj() , int woCompare(const BSONObj& r, const BSONObj &ordering = BSONObj() ,
bool considerFieldName=true) const; bool considerFieldName=true) const;
int woSortOrder( const BSONObj& r , const BSONObj& sortKey ) const; /**
* @param useDotted whether to treat sort key fields as possibly do
tted and expand into them
*/
int woSortOrder( const BSONObj& r , const BSONObj& sortKey , bool u
seDotted=false ) const;
/** This is "shallow equality" -- ints and doubles won't match. fo r a /** This is "shallow equality" -- ints and doubles won't match. fo r a
deep equality test use woCompare (which is slower). deep equality test use woCompare (which is slower).
*/ */
bool woEqual(const BSONObj& r) const { bool woEqual(const BSONObj& r) const {
int os = objsize(); int os = objsize();
if ( os == r.objsize() ) { if ( os == r.objsize() ) {
return (os == 0 || memcmp(objdata(),r.objdata(),os)==0); return (os == 0 || memcmp(objdata(),r.objdata(),os)==0);
} }
return false; return false;
 End of changes. 3 change blocks. 
2 lines changed or deleted 14 lines changed or added


 bsonobjbuilder.h   bsonobjbuilder.h 
skipping to change at line 36 skipping to change at line 36
#include <cmath> #include <cmath>
using namespace std; using namespace std;
namespace mongo { namespace mongo {
#if defined(_WIN32) #if defined(_WIN32)
// warning: 'this' : used in base member initializer list // warning: 'this' : used in base member initializer list
#pragma warning( disable : 4355 ) #pragma warning( disable : 4355 )
#endif #endif
template<typename T>
class BSONFieldValue {
public:
BSONFieldValue( const string& name , const T& t ){
_name = name;
_t = t;
}
const T& value() const { return _t; }
const string& name() const { return _name; }
private:
string _name;
T _t;
};
template<typename T>
class BSONField {
public:
BSONField( const string& name , const string& longName="" )
: _name(name), _longName(longName){}
const string& name() const { return _name; }
operator string() const { return _name; }
BSONFieldValue<T> make( const T& t ) const {
return BSONFieldValue<T>( _name , t );
}
BSONFieldValue<BSONObj> gt( const T& t ) const { return query( "$gt
" , t ); }
BSONFieldValue<BSONObj> lt( const T& t ) const { return query( "$lt
" , t ); }
BSONFieldValue<BSONObj> query( const char * q , const T& t ) const;
BSONFieldValue<T> operator()( const T& t ) const {
return BSONFieldValue<T>( _name , t );
}
private:
string _name;
string _longName;
};
/** Utility for creating a BSONObj. /** Utility for creating a BSONObj.
See also the BSON() and BSON_ARRAY() macros. See also the BSON() and BSON_ARRAY() macros.
*/ */
class BSONObjBuilder : boost::noncopyable { class BSONObjBuilder : boost::noncopyable {
public: public:
/** @param initsize this is just a hint as to the final size of the object */ /** @param initsize this is just a hint as to the final size of the object */
BSONObjBuilder(int initsize=512) : _b(_buf), _buf(initsize), _offse t( 0 ), _s( this ) , _tracker(0) , _doneCalled(false) { BSONObjBuilder(int initsize=512) : _b(_buf), _buf(initsize), _offse t( 0 ), _s( this ) , _tracker(0) , _doneCalled(false) {
_b.skip(4); /*leave room for size field*/ _b.skip(4); /*leave room for size field*/
} }
skipping to change at line 313 skipping to change at line 355
BSONObjBuilder& appendRegex(string fieldName, string regex, string options = "") { BSONObjBuilder& appendRegex(string fieldName, string regex, string options = "") {
return appendRegex(fieldName.c_str(), regex.c_str(), options.c_ str()); return appendRegex(fieldName.c_str(), regex.c_str(), options.c_ str());
} }
BSONObjBuilder& appendCode(const char *fieldName, const char *code) { BSONObjBuilder& appendCode(const char *fieldName, const char *code) {
_b.append((char) Code); _b.append((char) Code);
_b.append(fieldName); _b.append(fieldName);
_b.append((int) strlen(code)+1); _b.append((int) strlen(code)+1);
_b.append(code); _b.append(code);
return *this; return *this;
} }
/** Append a string element */ /** Append a string element. len DOES include terminating nul */
BSONObjBuilder& append(const char *fieldName, const char *str) { BSONObjBuilder& append(const char *fieldName, const char *str, int
len) {
_b.append((char) String); _b.append((char) String);
_b.append(fieldName); _b.append(fieldName);
_b.append((int) strlen(str)+1); _b.append((int)len);
_b.append(str); _b.append(str, len);
return *this; return *this;
} }
/** Append a string element */ /** Append a string element */
BSONObjBuilder& append(const char *fieldName, const char *str) {
return append(fieldName, str, (int) strlen(str)+1);
}
/** Append a string element */
BSONObjBuilder& append(const char *fieldName, string str) { BSONObjBuilder& append(const char *fieldName, string str) {
return append(fieldName, str.c_str()); return append(fieldName, str.c_str(), (int) str.size()+1);
} }
BSONObjBuilder& appendSymbol(const char *fieldName, const char *sym bol) { BSONObjBuilder& appendSymbol(const char *fieldName, const char *sym bol) {
_b.append((char) Symbol); _b.append((char) Symbol);
_b.append(fieldName); _b.append(fieldName);
_b.append((int) strlen(symbol)+1); _b.append((int) strlen(symbol)+1);
_b.append(symbol); _b.append(symbol);
return *this; } return *this; }
/** Append a Null element to the object */ /** Append a Null element to the object */
BSONObjBuilder& appendNull( const char *fieldName ) { BSONObjBuilder& appendNull( const char *fieldName ) {
skipping to change at line 530 skipping to change at line 576
/** Stream oriented way to add field names and values. */ /** Stream oriented way to add field names and values. */
BSONObjBuilderValueStream &operator<<( const ForceExplicitString& n ame ) { BSONObjBuilderValueStream &operator<<( const ForceExplicitString& n ame ) {
return operator<<( name.str_.c_str() ); return operator<<( name.str_.c_str() );
} }
Labeler operator<<( const Labeler::Label &l ) { Labeler operator<<( const Labeler::Label &l ) {
massert( 10336 , "No subobject started", _s.subobjStarted() ); massert( 10336 , "No subobject started", _s.subobjStarted() );
return _s << l; return _s << l;
} }
template<typename T>
BSONObjBuilderValueStream& operator<<( const BSONField<T>& f ) {
_s.endField( f.name().c_str() );
return _s;
}
template<typename T>
BSONObjBuilder& operator<<( const BSONFieldValue<T>& v ) {
append( v.name().c_str() , v.value() );
return *this;
}
/** @return true if we are using our own bufbuilder, and not an alt ernate that was given to us in our constructor */ /** @return true if we are using our own bufbuilder, and not an alt ernate that was given to us in our constructor */
bool owned() const { return &_b == &_buf; } bool owned() const { return &_b == &_buf; }
BSONObjIterator iterator() const ; BSONObjIterator iterator() const ;
private: private:
char* _done() { char* _done() {
if ( _doneCalled ) if ( _doneCalled )
return _b.buf() + _offset; return _b.buf() + _offset;
 End of changes. 6 change blocks. 
5 lines changed or deleted 66 lines changed or added


 btree.h   btree.h 
skipping to change at line 87 skipping to change at line 87
class BucketBasics { class BucketBasics {
friend class BtreeBuilder; friend class BtreeBuilder;
friend class KeyNode; friend class KeyNode;
public: public:
void dumpTree(DiskLoc thisLoc, const BSONObj &order); void dumpTree(DiskLoc thisLoc, const BSONObj &order);
bool isHead() { return parent.isNull(); } bool isHead() { return parent.isNull(); }
void assertValid(const Ordering &order, bool force = false); void assertValid(const Ordering &order, bool force = false);
void assertValid(const BSONObj &orderObj, bool force = false) { void assertValid(const BSONObj &orderObj, bool force = false) {
return assertValid(Ordering::make(orderObj),force); return assertValid(Ordering::make(orderObj),force);
} }
int fullValidate(const DiskLoc& thisLoc, const BSONObj &order); /* traverses everything */ int fullValidate(const DiskLoc& thisLoc, const BSONObj &order, int *unusedCount = 0); /* traverses everything */
KeyNode keyNode(int i) const { KeyNode keyNode(int i) const {
if ( i >= n ){ if ( i >= n ){
massert( 13000 , (string)"invalid keyNode: " + BSON( "i" < < i << "n" << n ).jsonString() , i < n ); massert( 13000 , (string)"invalid keyNode: " + BSON( "i" < < i << "n" << n ).jsonString() , i < n );
} }
return KeyNode(*this, k(i)); return KeyNode(*this, k(i));
} }
protected: protected:
skipping to change at line 109 skipping to change at line 109
char * dataAt(short ofs) { char * dataAt(short ofs) {
return data + ofs; return data + ofs;
} }
void init(); // initialize a new node void init(); // initialize a new node
/* returns false if node is full and must be split /* returns false if node is full and must be split
keypos is where to insert -- inserted after that key #. so keyp os=0 is the leftmost one. keypos is where to insert -- inserted after that key #. so keyp os=0 is the leftmost one.
*/ */
bool basicInsert(const DiskLoc& thisLoc, int keypos, const DiskLoc& recordLoc, const BSONObj& key, const Ordering &order); bool basicInsert(const DiskLoc& thisLoc, int &keypos, const DiskLoc & recordLoc, const BSONObj& key, const Ordering &order);
/** /**
* @return true if works, false if not enough space * @return true if works, false if not enough space
*/ */
bool _pushBack(const DiskLoc& recordLoc, BSONObj& key, const Orderi ng &order, DiskLoc prevChild); bool _pushBack(const DiskLoc& recordLoc, BSONObj& key, const Orderi ng &order, DiskLoc prevChild);
void pushBack(const DiskLoc& recordLoc, BSONObj& key, const Orderin g &order, DiskLoc prevChild){ void pushBack(const DiskLoc& recordLoc, BSONObj& key, const Orderin g &order, DiskLoc prevChild){
bool ok = _pushBack( recordLoc , key , order , prevChild ); bool ok = _pushBack( recordLoc , key , order , prevChild );
assert(ok); assert(ok);
} }
void popBack(DiskLoc& recLoc, BSONObj& key); void popBack(DiskLoc& recLoc, BSONObj& key);
skipping to change at line 133 skipping to change at line 133
We "repack" when we run out of space before considering the node We "repack" when we run out of space before considering the node
to be full. to be full.
*/ */
enum Flags { Packed=1 }; enum Flags { Packed=1 };
DiskLoc& childForPos(int p) { DiskLoc& childForPos(int p) {
return p == n ? nextChild : k(p).prevChildBucket; return p == n ? nextChild : k(p).prevChildBucket;
} }
int totalDataSize() const; int totalDataSize() const;
void pack( const Ordering &order ); void pack( const Ordering &order, int &refPos);
void setNotPacked(); void setNotPacked();
void setPacked(); void setPacked();
int _alloc(int bytes); int _alloc(int bytes);
void _unalloc(int bytes); void _unalloc(int bytes);
void truncateTo(int N, const Ordering &order); void truncateTo(int N, const Ordering &order, int &refPos);
void markUnused(int keypos); void markUnused(int keypos);
/* BtreeBuilder uses the parent var as a temp place to maintain a l inked list chain. /* BtreeBuilder uses the parent var as a temp place to maintain a l inked list chain.
we use tempNext() when we do that to be less confusing. (one mig ht have written a union in C) we use tempNext() when we do that to be less confusing. (one mig ht have written a union in C)
*/ */
DiskLoc& tempNext() { return parent; } DiskLoc& tempNext() { return parent; }
public: public:
DiskLoc parent; DiskLoc parent;
skipping to change at line 365 skipping to change at line 365
} }
void forgetEndKey() { endKey = BSONObj(); } void forgetEndKey() { endKey = BSONObj(); }
virtual CoveredIndexMatcher *matcher() const { return _matcher.get( ); } virtual CoveredIndexMatcher *matcher() const { return _matcher.get( ); }
virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher ) { virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher ) {
_matcher = matcher; _matcher = matcher;
} }
// for debugging only
DiskLoc getBucket() const { return bucket; }
private: private:
/* Our btrees may (rarely) have "unused" keys when items are delete d. /* Our btrees may (rarely) have "unused" keys when items are delete d.
Skip past them. Skip past them.
*/ */
void skipUnusedKeys(); void skipUnusedKeys();
/* Check if the current key is beyond endKey. */ /* Check if the current key is beyond endKey. */
void checkEnd(); void checkEnd();
// selective audits on construction // selective audits on construction
 End of changes. 5 change blocks. 
4 lines changed or deleted 7 lines changed or added


 chunk.h   chunk.h 
skipping to change at line 43 skipping to change at line 43
namespace mongo { namespace mongo {
class DBConfig; class DBConfig;
class Chunk; class Chunk;
class ChunkRange; class ChunkRange;
class ChunkManager; class ChunkManager;
class ChunkRangeMangager; class ChunkRangeMangager;
class ChunkObjUnitTest; class ChunkObjUnitTest;
typedef unsigned long long ShardChunkVersion; struct ShardChunkVersion {
union {
struct {
int _minor;
int _major;
};
unsigned long long _combined;
};
ShardChunkVersion( int major=0, int minor=0 )
: _minor(minor),_major(major){
}
ShardChunkVersion( unsigned long long ll )
: _combined( ll ){
}
ShardChunkVersion incMajor() const {
return ShardChunkVersion( _major + 1 , 0 );
}
void operator++(){
_minor++;
}
unsigned long long toLong() const {
return _combined;
}
bool isSet() const {
return _combined > 0;
}
string toString() const {
stringstream ss;
ss << _major << "|" << _minor;
return ss.str();
}
operator unsigned long long() const { return _combined; }
operator string() const { return toString(); }
ShardChunkVersion& operator=( const BSONElement& elem ){
switch ( elem.type() ){
case Timestamp:
case NumberLong:
case Date:
_combined = elem._numberLong();
break;
case EOO:
_combined = 0;
break;
default:
assert(0);
}
return *this;
}
};
typedef shared_ptr<Chunk> ChunkPtr; typedef shared_ptr<Chunk> ChunkPtr;
// key is max for each Chunk or ChunkRange // key is max for each Chunk or ChunkRange
typedef map<BSONObj,ChunkPtr,BSONObjCmp> ChunkMap; typedef map<BSONObj,ChunkPtr,BSONObjCmp> ChunkMap;
typedef map<BSONObj,shared_ptr<ChunkRange>,BSONObjCmp> ChunkRangeMap; typedef map<BSONObj,shared_ptr<ChunkRange>,BSONObjCmp> ChunkRangeMap;
/** /**
config.chunks config.chunks
{ ns : "alleyinsider.fs.chunks" , min : {} , max : {} , server : "lo calhost:30001" } { ns : "alleyinsider.fs.chunks" , min : {} , max : {} , server : "lo calhost:30001" }
x is in a shard iff x is in a shard iff
min <= x < max min <= x < max
*/ */
class Chunk : public Model , boost::noncopyable, public boost::enable_s hared_from_this<Chunk> { class Chunk : boost::noncopyable, public boost::enable_shared_from_this <Chunk> {
public: public:
Chunk( ChunkManager * info ); Chunk( ChunkManager * info );
Chunk( ChunkManager * info , const BSONObj& min, const BSONObj& max , const Shard& shard);
const BSONObj& getMin() const { return _min; } const BSONObj& getMin() const { return _min; }
const BSONObj& getMax() const { return _max; } const BSONObj& getMax() const { return _max; }
void setMin(const BSONObj& o){ void setMin(const BSONObj& o){
_min = o; _min = o;
} }
void setMax(const BSONObj& o){ void setMax(const BSONObj& o){
_max = o; _max = o;
} }
Shard getShard() const{ string getns() const;
return _shard; Shard getShard() const { return _shard; }
}
void setShard( const Shard& shard ); void setShard( const Shard& shard );
bool contains( const BSONObj& obj ) const; bool contains( const BSONObj& obj ) const;
string toString() const; string toString() const;
operator string() const { return toString(); } operator string() const { return toString(); }
friend ostream& operator << (ostream& out, const Chunk& c){ return (out << c.toString()); } friend ostream& operator << (ostream& out, const Chunk& c){ return (out << c.toString()); }
bool operator==(const Chunk& s) const; bool operator==(const Chunk& s) const;
skipping to change at line 122 skipping to change at line 181
bool splitIfShould( long dataWritten ); bool splitIfShould( long dataWritten );
/* /*
* moves either this shard or newShard if it makes sense too * moves either this shard or newShard if it makes sense too
* @return whether or not a shard was moved * @return whether or not a shard was moved
*/ */
bool moveIfShould( ChunkPtr newShard = ChunkPtr() ); bool moveIfShould( ChunkPtr newShard = ChunkPtr() );
bool moveAndCommit( const Shard& to , string& errmsg ); bool moveAndCommit( const Shard& to , string& errmsg );
virtual const char * getNS(){ return "config.chunks"; } const char * getNS(){ return "config.chunks"; }
virtual void serialize(BSONObjBuilder& to); void serialize(BSONObjBuilder& to, ShardChunkVersion myLastMod=0);
virtual void unserialize(const BSONObj& from); void unserialize(const BSONObj& from);
virtual string modelServer(); string modelServer();
void appendShortVersion( const char * name , BSONObjBuilder& b ); void appendShortVersion( const char * name , BSONObjBuilder& b );
virtual void save( bool check=false );
void ensureIndex(); void ensureIndex();
void _markModified(); void _markModified();
static int MaxChunkSize; static int MaxChunkSize;
string genID();
static string genID( const string& ns , const BSONObj& min ); static string genID( const string& ns , const BSONObj& min );
const ChunkManager* getManager() const { return _manager; } const ChunkManager* getManager() const { return _manager; }
bool modified();
private: private:
// main shard info // main shard info
ChunkManager * _manager; ChunkManager * _manager;
ShardKeyPattern skey() const; ShardKeyPattern skey() const;
string _ns;
BSONObj _min; BSONObj _min;
BSONObj _max; BSONObj _max;
Shard _shard; Shard _shard;
ShardChunkVersion _lastmod; ShardChunkVersion _lastmod;
bool _modified; bool _modified;
// transient stuff // transient stuff
long _dataWritten; long _dataWritten;
skipping to change at line 254 skipping to change at line 312
key: { ts : 1 } , key: { ts : 1 } ,
shards: [ { min: 1, max: 100, server: a } , { min: 101, max: 200 , server : b } ] shards: [ { min: 1, max: 100, server: a } , { min: 101, max: 200 , server : b } ]
} }
*/ */
class ChunkManager { class ChunkManager {
public: public:
ChunkManager( DBConfig * config , string ns , ShardKeyPattern patte rn , bool unique ); ChunkManager( DBConfig * config , string ns , ShardKeyPattern patte rn , bool unique );
virtual ~ChunkManager(); virtual ~ChunkManager();
string getns() const { string getns() const { return _ns; }
return _ns;
}
int numChunks(){ rwlock lk( _lock , false ); return _chunks.size(); int numChunks(){ rwlock lk( _lock , false ); return _chunkMap.size(
} ); }
ChunkPtr getChunk( int i ){ rwlock lk( _lock , false ); return _chu
nks[i]; }
bool hasShardKey( const BSONObj& obj ); bool hasShardKey( const BSONObj& obj );
ChunkPtr findChunk( const BSONObj& obj , bool retry = false ); ChunkPtr findChunk( const BSONObj& obj , bool retry = false );
ChunkPtr findChunkOnServer( const Shard& shard ) const; ChunkPtr findChunkOnServer( const Shard& shard ) const;
ShardKeyPattern& getShardKey(){ return _key; } ShardKeyPattern& getShardKey(){ return _key; }
const ShardKeyPattern& getShardKey() const { return _key; } const ShardKeyPattern& getShardKey() const { return _key; }
bool isUnique(){ return _unique; } bool isUnique(){ return _unique; }
/** /**
skipping to change at line 306 skipping to change at line 361
*/ */
unsigned long long getSequenceNumber(){ unsigned long long getSequenceNumber(){
return _sequenceNumber; return _sequenceNumber;
} }
/** /**
* @param me - so i don't get deleted before i'm done * @param me - so i don't get deleted before i'm done
*/ */
void drop( ChunkManagerPtr me ); void drop( ChunkManagerPtr me );
void _printChunks() const;
private: private:
void _reload(); void _reload();
void _reload_inlock(); void _reload_inlock();
void _load(); void _load();
void save_inlock();
ShardChunkVersion getVersion_inlock() const;
void ensureIndex_inlock();
DBConfig * _config; DBConfig * _config;
string _ns; string _ns;
ShardKeyPattern _key; ShardKeyPattern _key;
bool _unique; bool _unique;
vector<ChunkPtr> _chunks;
map<string,unsigned long long> _maxMarkers; map<string,unsigned long long> _maxMarkers;
ChunkMap _chunkMap; ChunkMap _chunkMap;
ChunkRangeManager _chunkRanges; ChunkRangeManager _chunkRanges;
set<Shard> _shards;
unsigned long long _sequenceNumber; unsigned long long _sequenceNumber;
RWLock _lock; RWLock _lock;
// This should only be called from Chunk after it has been migrated // This should only be called from Chunk after it has been migrated
void _migrationNotification(Chunk* c); void _migrationNotification(Chunk* c);
friend class Chunk; friend class Chunk;
friend class ChunkRangeManager; // only needed for CRM::assertValid () friend class ChunkRangeManager; // only needed for CRM::assertValid ()
static AtomicUInt NextSequenceNumber; static AtomicUInt NextSequenceNumber;
bool _isValid() const; bool _isValid() const;
void _printChunks() const;
/** /**
* @return number of Chunk matching the query or -1 for all chunks. * @return number of Chunk matching the query or -1 for all chunks.
*/ */
int _getChunksForQuery( vector<shared_ptr<ChunkRange> >& chunks , c onst BSONObj& query ); int _getChunksForQuery( vector<shared_ptr<ChunkRange> >& chunks , c onst BSONObj& query );
}; };
// like BSONObjCmp. for use as an STL comparison functor // like BSONObjCmp. for use as an STL comparison functor
// key-order in "order" argument must match key-order in shardkey // key-order in "order" argument must match key-order in shardkey
class ChunkCmp { class ChunkCmp {
skipping to change at line 366 skipping to change at line 427
bool operator()( const ChunkRange &l, const ChunkRange &r ) const { bool operator()( const ChunkRange &l, const ChunkRange &r ) const {
return _cmp(l.getMin(), r.getMin()); return _cmp(l.getMin(), r.getMin());
} }
bool operator()( const shared_ptr<ChunkRange> l, const shared_ptr<C hunkRange> r ) const { bool operator()( const shared_ptr<ChunkRange> l, const shared_ptr<C hunkRange> r ) const {
return operator()(*l, *r); return operator()(*l, *r);
} }
private: private:
BSONObjCmp _cmp; BSONObjCmp _cmp;
}; };
/*
struct chunk_lock {
chunk_lock( const Chunk* c ){
}
Chunk _c;
};
*/
inline string Chunk::genID(){ return genID(_manager->getns(), _min); }
} // namespace mongo } // namespace mongo
 End of changes. 17 change blocks. 
21 lines changed or deleted 92 lines changed or added


 client.h   client.h 
skipping to change at line 32 skipping to change at line 32
todo: switch to asio...this will fit nicely with that. todo: switch to asio...this will fit nicely with that.
*/ */
#pragma once #pragma once
#include "../pch.h" #include "../pch.h"
#include "security.h" #include "security.h"
#include "namespace.h" #include "namespace.h"
#include "lasterror.h" #include "lasterror.h"
#include "stats/top.h" #include "stats/top.h"
#include "repl/rs.h" //#include "repl/rs.h"
namespace mongo { namespace mongo {
extern class ReplSet *theReplSet;
class AuthenticationInfo; class AuthenticationInfo;
class Database; class Database;
class CurOp; class CurOp;
class Command; class Command;
class Client; class Client;
extern boost::thread_specific_ptr<Client> currentClient; extern boost::thread_specific_ptr<Client> currentClient;
class Client : boost::noncopyable { class Client : boost::noncopyable {
public: public:
static mongo::mutex clientsMutex; static mongo::mutex clientsMutex;
static set<Client*> clients; // always be in clientsMutex when mani pulating this static set<Client*> clients; // always be in clientsMutex when mani pulating this
static int recommendedYieldMicros(); static int recommendedYieldMicros( int * writers = 0 , int * reader s = 0 );
class GodScope { class GodScope {
bool _prev; bool _prev;
public: public:
GodScope(); GodScope();
~GodScope(); ~GodScope();
}; };
/* Set database we want to use, then, restores when we finish (are out of scope) /* Set database we want to use, then, restores when we finish (are out of scope)
Note this is also helpful if an exception happens as the state i f fixed up. Note this is also helpful if an exception happens as the state i f fixed up.
skipping to change at line 85 skipping to change at line 87
* this will set _db and create if needed * this will set _db and create if needed
* will also set _client->_context to this * will also set _client->_context to this
*/ */
void _finishInit( bool doauth=true); void _finishInit( bool doauth=true);
void _auth( int lockState = dbMutex.getState() ); void _auth( int lockState = dbMutex.getState() );
public: public:
Context(const string& ns, string path=dbpath, mongolock * lock = 0 , bool doauth=true ) Context(const string& ns, string path=dbpath, mongolock * lock = 0 , bool doauth=true )
: _client( currentClient.get() ) , _oldContext( _client->_c ontext ) , : _client( currentClient.get() ) , _oldContext( _client->_c ontext ) ,
_path( path ) , _lock( lock ) , _path( path ) , _lock( lock ) ,
_ns( ns ){ _ns( ns ), _db(0){
_finishInit( doauth ); _finishInit( doauth );
} }
/* this version saves the context but doesn't yet set the new o ne: */ /* this version saves the context but doesn't yet set the new o ne: */
Context() Context()
: _client( currentClient.get() ) , _oldContext( _client->_c ontext ), : _client( currentClient.get() ) , _oldContext( _client->_c ontext ),
_path( dbpath ) , _lock(0) , _justCreated(false){ _path( dbpath ) , _lock(0) , _justCreated(false), _db(0){
_client->_context = this; _client->_context = this;
clear(); clear();
} }
/** /**
* if you are doing this after allowing a write there could be a race condition * if you are doing this after allowing a write there could be a race condition
* if someone closes that db. this checks that the DB is still valid * if someone closes that db. this checks that the DB is still valid
*/ */
Context( string ns , Database * db, bool doauth=true ); Context( string ns , Database * db, bool doauth=true );
 End of changes. 5 change blocks. 
4 lines changed or deleted 6 lines changed or added


 clientcursor.h   clientcursor.h 
skipping to change at line 64 skipping to change at line 64
DiskLoc _lastLoc; // use getter and setter n ot this (important) DiskLoc _lastLoc; // use getter and setter n ot this (important)
unsigned _idleAgeMillis; // how long has the cursor been around, relative to server idle time unsigned _idleAgeMillis; // how long has the cursor been around, relative to server idle time
/* 0 = normal /* 0 = normal
1 = no timeout allowed 1 = no timeout allowed
100 = in use (pinned) -- see Pointer class 100 = in use (pinned) -- see Pointer class
*/ */
unsigned _pinValue; unsigned _pinValue;
bool _doingDeletes; bool _doingDeletes;
ElapsedTracker _yieldSometimesTracker;
static CCById clientCursorsById; static CCById clientCursorsById;
static CCByLoc byLoc; static CCByLoc byLoc;
static boost::recursive_mutex ccmutex; // must use this for all s tatics above! static boost::recursive_mutex ccmutex; // must use this for all s tatics above!
static CursorId allocCursorId_inlock(); static CursorId allocCursorId_inlock();
public: public:
/* use this to assure we don't in the background time out cursor wh ile it is under use. /* use this to assure we don't in the background time out cursor wh ile it is under use.
if you are using noTimeout() already, there is no risk anyway. if you are using noTimeout() already, there is no risk anyway.
skipping to change at line 114 skipping to change at line 115
/*const*/ CursorId cursorid; /*const*/ CursorId cursorid;
string ns; string ns;
shared_ptr<Cursor> c; shared_ptr<Cursor> c;
int pos; // # objects into the cursor so far int pos; // # objects into the cursor so far
BSONObj query; BSONObj query;
int _queryOptions; // see enum QueryOptions dbclient.h int _queryOptions; // see enum QueryOptions dbclient.h
OpTime _slaveReadTill; OpTime _slaveReadTill;
ClientCursor(int queryOptions, shared_ptr<Cursor>& _c, const char * _ns) : ClientCursor(int queryOptions, shared_ptr<Cursor>& _c, const char * _ns) :
_idleAgeMillis(0), _pinValue(0), _idleAgeMillis(0), _pinValue(0),
_doingDeletes(false), _doingDeletes(false), _yieldSometimesTracker(128,10),
ns(_ns), c(_c), ns(_ns), c(_c),
pos(0), _queryOptions(queryOptions) pos(0), _queryOptions(queryOptions)
{ {
if( queryOptions & QueryOption_NoCursorTimeout ) if( queryOptions & QueryOption_NoCursorTimeout )
noTimeout(); noTimeout();
recursive_scoped_lock lock(ccmutex); recursive_scoped_lock lock(ccmutex);
cursorid = allocCursorId_inlock(); cursorid = allocCursorId_inlock();
clientCursorsById.insert( make_pair(cursorid, this) ); clientCursorsById.insert( make_pair(cursorid, this) );
} }
~ClientCursor(); ~ClientCursor();
skipping to change at line 140 skipping to change at line 141
shared_ptr< ParsedQuery > pq; shared_ptr< ParsedQuery > pq;
shared_ptr< FieldMatcher > fields; // which fields query wants retu rned shared_ptr< FieldMatcher > fields; // which fields query wants retu rned
Message originalMessage; // this is effectively an auto ptr for dat a the matcher points to Message originalMessage; // this is effectively an auto ptr for dat a the matcher points to
/* Get rid of cursors for namespaces that begin with nsprefix. /* Get rid of cursors for namespaces that begin with nsprefix.
Used by drop, dropIndexes, dropDatabase. Used by drop, dropIndexes, dropDatabase.
*/ */
static void invalidate(const char *nsPrefix); static void invalidate(const char *nsPrefix);
/** /**
* @param microsToSleep -1 : ask client
* >=0 : sleep for that amount
* do a dbtemprelease * do a dbtemprelease
* note: caller should check matcher.docMatcher().atomic() first an d not yield if atomic - * note: caller should check matcher.docMatcher().atomic() first an d not yield if atomic -
* we don't do herein as this->matcher (above) is only initia lized for true queries/getmore. * we don't do herein as this->matcher (above) is only initia lized for true queries/getmore.
* (ie not set for remote/update) * (ie not set for remote/update)
* @return if the cursor is still valid. * @return if the cursor is still valid.
* if false is returned, then this ClientCursor should be c onsidered deleted - * if false is returned, then this ClientCursor should be c onsidered deleted -
* in fact, the whole database could be gone. * in fact, the whole database could be gone.
*/ */
bool yield(); bool yield( int microsToSleep = -1 );
/**
* @return same as yield()
*/
bool yieldSometimes();
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 ngDeletes ) { : _cc( cc ) , _id( cc->cursorid ) , _doingDeletes( cc->_doi ngDeletes ) {
cc->updateLocation(); cc->updateLocation();
_unlock.reset(new dbtempreleasecond()); _unlock.reset(new dbtempreleasecond());
} }
~YieldLock(){ ~YieldLock(){
assert( ! _unlock ); assert( ! _unlock );
} }
 End of changes. 4 change blocks. 
2 lines changed or deleted 10 lines changed or added


 commands.h   commands.h 
skipping to change at line 115 skipping to change at line 115
protected: protected:
BSONObj getQuery( const BSONObj& cmdObj ){ BSONObj getQuery( const BSONObj& cmdObj ){
if ( cmdObj["query"].type() == Object ) if ( cmdObj["query"].type() == Object )
return cmdObj["query"].embeddedObject(); return cmdObj["query"].embeddedObject();
if ( cmdObj["q"].type() == Object ) if ( cmdObj["q"].type() == Object )
return cmdObj["q"].embeddedObject(); return cmdObj["q"].embeddedObject();
return BSONObj(); return BSONObj();
} }
void logIfSlow( const string& msg) const;
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;
Timer _timer; // started right before call
ing run
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; }
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);
 End of changes. 2 change blocks. 
0 lines changed or deleted 5 lines changed or added


 concurrency.h   concurrency.h 
skipping to change at line 32 skipping to change at line 32
name level name level
Logstream::mutex 1 Logstream::mutex 1
ClientCursor::ccmutex 2 ClientCursor::ccmutex 2
dblock 3 dblock 3
End func name with _inlock to indicate "caller must lock before callin g". End func name with _inlock to indicate "caller must lock before callin g".
*/ */
#pragma once #pragma once
#include "../util/concurrency/locks.h" #include "../util/concurrency/rwlock.h"
#include "../util/mmap.h"
namespace mongo { namespace mongo {
inline bool readLockSupported(){
return true;
}
string sayClientState(); string sayClientState();
bool haveClient(); bool haveClient();
void curopWaitingForLock( int type ); void curopWaitingForLock( int type );
void curopGotLock(); void curopGotLock();
/* mutex time stats */ /* mutex time stats */
class MutexInfo { class MutexInfo {
unsigned long long start, enter, timeLocked; // all in microseconds unsigned long long start, enter, timeLocked; // all in microseconds
int locked; int locked;
skipping to change at line 97 skipping to change at line 94
ThreadLocalValue<bool> _releasedEarly; ThreadLocalValue<bool> _releasedEarly;
public: public:
MongoMutex(const char * name) : _m(name) { } MongoMutex(const char * name) : _m(name) { }
/** /**
* @return * @return
* > 0 write lock * > 0 write lock
* = 0 no lock * = 0 no lock
* < 0 read lock * < 0 read lock
*/ */
int getState(){ return _state.get(); } int getState() { return _state.get(); }
bool isWriteLocked() { return getState() > 0; }
void assertWriteLocked() { void assertWriteLocked() {
assert( getState() > 0 ); assert( getState() > 0 );
DEV assert( !_releasedEarly.get() ); DEV assert( !_releasedEarly.get() );
} }
bool atLeastReadLocked() { return _state.get() != 0; } bool atLeastReadLocked() { return _state.get() != 0; }
void assertAtLeastReadLocked() { assert(atLeastReadLocked()); } void assertAtLeastReadLocked() { assert(atLeastReadLocked()); }
bool _checkWriteLockAlready(){ bool _checkWriteLockAlready(){
//DEV cout << "LOCK" << endl; //DEV cout << "LOCK" << endl;
DEV assert( haveClient() ); DEV assert( haveClient() );
skipping to change at line 131 skipping to change at line 129
if ( _checkWriteLockAlready() ) if ( _checkWriteLockAlready() )
return; return;
_state.set(1); _state.set(1);
curopWaitingForLock( 1 ); curopWaitingForLock( 1 );
_m.lock(); _m.lock();
curopGotLock(); curopGotLock();
_minfo.entered(); _minfo.entered();
MongoFile::lockAll();
} }
bool lock_try( int millis ) { bool lock_try( int millis ) {
if ( _checkWriteLockAlready() ) if ( _checkWriteLockAlready() )
return true; return true;
curopWaitingForLock( 1 ); curopWaitingForLock( 1 );
bool got = _m.lock_try( millis ); bool got = _m.lock_try( millis );
curopGotLock(); curopGotLock();
if ( got ){ if ( got ){
_minfo.entered(); _minfo.entered();
_state.set(1); _state.set(1);
MongoFile::lockAll();
} }
return got; return got;
} }
void unlock() { void unlock() {
//DEV cout << "UNLOCK" << endl; //DEV cout << "UNLOCK" << endl;
int s = _state.get(); int s = _state.get();
if( s > 1 ) { if( s > 1 ) {
_state.set(s-1); _state.set(s-1);
return; return;
} }
if( s != 1 ) { if( s != 1 ) {
if( _releasedEarly.get() ) { if( _releasedEarly.get() ) {
_releasedEarly.set(false); _releasedEarly.set(false);
return; return;
} }
massert( 12599, "internal error: attempt to unlock when was n't in a write lock", false); massert( 12599, "internal error: attempt to unlock when was n't in a write lock", false);
} }
MongoFile::unlockAll();
_state.set(0); _state.set(0);
_minfo.leaving(); _minfo.leaving();
_m.unlock(); _m.unlock();
} }
/* unlock (write lock), and when unlock() is called later, /* unlock (write lock), and when unlock() is called later,
be smart then and don't unlock it again. be smart then and don't unlock it again.
*/ */
void releaseEarly() { void releaseEarly() {
assert( getState() == 1 ); // must not be recursive assert( getState() == 1 ); // must not be recursive
 End of changes. 6 change blocks. 
6 lines changed or deleted 10 lines changed or added


 connpool.h   connpool.h 
skipping to change at line 68 skipping to change at line 68
{ {
ScopedDbConnection c("myserver"); ScopedDbConnection c("myserver");
c.conn()... c.conn()...
} }
*/ */
class DBConnectionPool { class DBConnectionPool {
mongo::mutex _mutex; mongo::mutex _mutex;
map<string,PoolForHost> _pools; // servername -> pool map<string,PoolForHost> _pools; // servername -> pool
list<DBConnectionHook*> _hooks; list<DBConnectionHook*> _hooks;
DBClientBase* _get( const string& ident );
DBClientBase* _finishCreate( const string& ident , DBClientBase* co
nn );
public: public:
DBConnectionPool() : _mutex("DBConnectionPool") { } DBConnectionPool() : _mutex("DBConnectionPool") { }
~DBConnectionPool(); ~DBConnectionPool();
void onCreate( DBClientBase * conn ); void onCreate( DBClientBase * conn );
void onHandedOut( DBClientBase * conn ); void onHandedOut( DBClientBase * conn );
void flush(); void flush();
DBClientBase *get(const string& host); DBClientBase *get(const string& host);
DBClientBase *get(const ConnectionString& host);
void release(const string& host, DBClientBase *c) { void release(const string& host, DBClientBase *c) {
if ( c->isFailed() ){ if ( c->isFailed() ){
delete c; delete c;
return; return;
} }
scoped_lock L(_mutex); scoped_lock L(_mutex);
_pools[host].pool.push(c); _pools[host].pool.push(c);
} }
void addHook( DBConnectionHook * hook ); void addHook( DBConnectionHook * hook );
void appendInfo( BSONObjBuilder& b ); void appendInfo( BSONObjBuilder& b );
skipping to change at line 132 skipping to change at line 139
: _host(host), _conn( pool.get(host) ) { : _host(host), _conn( pool.get(host) ) {
} }
ScopedDbConnection(const string& host, DBClientBase* conn ) ScopedDbConnection(const string& host, DBClientBase* conn )
: _host( host ) , _conn( conn ){ : _host( host ) , _conn( conn ){
} }
ScopedDbConnection(const Shard& shard ); ScopedDbConnection(const Shard& shard );
ScopedDbConnection(const Shard* shard ); ScopedDbConnection(const Shard* shard );
ScopedDbConnection(const ConnectionString& url )
: _host(url.toString()), _conn( pool.get(url) ) {
}
string getHost() const { return _host; } string getHost() const { return _host; }
/** Force closure of the connection. You should call this if you l eave it in /** Force closure of the connection. You should call this if you l eave it in
a bad state. Destructor will do this too, but it is verbose. a bad state. Destructor will do this too, but it is verbose.
*/ */
void kill() { void kill() {
delete _conn; delete _conn;
_conn = 0; _conn = 0;
} }
 End of changes. 4 change blocks. 
0 lines changed or deleted 12 lines changed or added


 dbclient.h   dbclient.h 
skipping to change at line 67 skipping to change at line 67
QueryOption_NoCursorTimeout = 1 << 4, QueryOption_NoCursorTimeout = 1 << 4,
/** Use with QueryOption_CursorTailable. If we are at the end of t he data, block for a while rather /** Use with QueryOption_CursorTailable. If we are at the end of t he data, block for a while rather
than returning no data. After a timeout period, we do return as normal. than returning no data. After a timeout period, we do return as normal.
*/ */
QueryOption_AwaitData = 1 << 5, QueryOption_AwaitData = 1 << 5,
/** Stream the data down full blast in multiple "more" packages, on the assumption that the client /** Stream the data down full blast in multiple "more" packages, on the assumption that the client
will fully read all data queried. Faster when you are pulling a lot of data and know you want to will fully read all data queried. Faster when you are pulling a lot of data and know you want to
pull it all down. Note: it is not allowed to not read all the data unless you close the connection. pull it all down. Note: it is not allowed to not read all the data unless you close the connection.
*/
Use the query( boost::function<void(const BSONObj&)> f, ... ) v
ersion of the connection's query()
method, and it will take care of all the details for you.
*/
QueryOption_Exhaust = 1 << 6 QueryOption_Exhaust = 1 << 6
}; };
enum UpdateOptions { enum UpdateOptions {
/** Upsert - that is, insert the item if no matching item is found. */ /** Upsert - that is, insert the item if no matching item is found. */
UpdateOption_Upsert = 1 << 0, UpdateOption_Upsert = 1 << 0,
/** Update multiple documents (if multiple documents match query ex pression). /** Update multiple documents (if multiple documents match query ex pression).
(Default is update a single document and stop.) */ (Default is update a single document and stop.) */
UpdateOption_Multi = 1 << 1 UpdateOption_Multi = 1 << 1
}; };
class DBClientBase;
class ConnectionString {
public:
enum ConnectionType { MASTER , SET , SYNC };
ConnectionString( const HostAndPort& server ){
_type = MASTER;
_servers.push_back( server );
_finishInit();
}
ConnectionString( ConnectionType type , const vector<HostAndPort>&
servers )
: _type( type ) , _servers( servers ){
_finishInit();
}
ConnectionString( ConnectionType type , const string& s ){
_type = type;
_fillServers( s );
switch ( _type ){
case MASTER:
assert( _servers.size() == 1 );
break;
default:
assert( _servers.size() > 0 );
}
_finishInit();
}
ConnectionString( const string& s , ConnectionType favoredMultipleT
ype ){
_fillServers( s );
if ( _servers.size() == 1 ){
_type = MASTER;
}
else {
_type = favoredMultipleType;
assert( _type != MASTER );
}
_finishInit();
}
string toString() const {
return _string;
}
operator string() const {
return toString();
}
DBClientBase* connect( string& errmsg ) const;
private:
void _fillServers( string s ){
string::size_type idx;
while ( ( idx = s.find( ',' ) ) != string::npos ){
_servers.push_back( s.substr( 0 , idx ) );
s = s.substr( idx + 1 );
}
_servers.push_back( s );
}
void _finishInit(){
stringstream ss;
for ( unsigned i=0; i<_servers.size(); i++ ){
if ( i > 0 )
ss << ",";
ss << _servers[i].toString();
}
_string = ss.str();
}
ConnectionType _type;
vector<HostAndPort> _servers;
string _string;
};
/** /**
* 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 216 skipping to change at line 299
/** /**
interface that handles communication with the db interface that handles communication with the db
*/ */
class DBConnector { class DBConnector {
public: public:
virtual ~DBConnector() {} virtual ~DBConnector() {}
virtual bool call( Message &toSend, Message &response, bool assertO k=true ) = 0; virtual bool call( Message &toSend, Message &response, bool assertO k=true ) = 0;
virtual void say( Message &toSend ) = 0; virtual void say( Message &toSend ) = 0;
virtual void sayPiggyBack( Message &toSend ) = 0; virtual void sayPiggyBack( Message &toSend ) = 0;
virtual void checkResponse( const string &data, int nReturned ) {} virtual void checkResponse( const char* data, int nReturned ) {}
/* used by QueryOption_Exhaust. To use that your subclass must imp lement this. */ /* used by QueryOption_Exhaust. To use that your subclass must imp lement this. */
virtual void recv( Message& m ) { assert(false); } virtual void recv( Message& m ) { assert(false); }
}; };
/** /**
The interface that any db connection should implement The interface that any db connection should implement
*/ */
class DBClientInterface : boost::noncopyable { class DBClientInterface : boost::noncopyable {
public: public:
skipping to change at line 336 skipping to change at line 419
*/ */
bool createCollection(const string &ns, long long size = 0, bool ca pped = false, int max = 0, BSONObj *info = 0); bool createCollection(const string &ns, long long size = 0, bool ca pped = false, int max = 0, BSONObj *info = 0);
/** Get error result from the last operation on this connection. /** Get error result from the last operation on this connection.
@return error message text, or empty string if no error. @return error message text, or empty string if no error.
*/ */
string getLastError(); string getLastError();
/** Get error result from the last operation on this connect ion. /** Get error result from the last operation on this connect ion.
@return full error object. @return full error object.
*/ */
BSONObj getLastErrorDetailed(); virtual BSONObj getLastErrorDetailed();
static string getLastErrorString( const BSONObj& res ); static string getLastErrorString( const BSONObj& res );
/** Return the last error which has occurred, even if not the very last operation. /** Return the last error which has occurred, even if not the very last operation.
@return { err : <error message>, nPrev : <how_many_ops_back_occu rred>, ok : 1 } @return { err : <error message>, nPrev : <how_many_ops_back_occu rred>, ok : 1 }
result.err will be null if no error has occurred. result.err will be null if no error has occurred.
*/ */
BSONObj getPrevError(); BSONObj getPrevError();
skipping to change at line 831 skipping to change at line 914
/* 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 ); master = ( ( master == Left ) ? NotSetR : NotSetL );
} }
string getServerAddress() const { string getServerAddress() const {
return left.getServerAddress() + "," + right.getServerAddress() ; return left.getServerAddress() + "," + right.getServerAddress() ;
} }
DBClientConnection& masterConn();
DBClientConnection& slaveConn(); DBClientConnection& slaveConn();
/* TODO - not yet implemented. mongos may need these. */ /* TODO - not yet implemented. mongos may need these. */
virtual bool call( Message &toSend, Message &response, bool assertO k=true ) { assert(false); return false; } virtual bool call( Message &toSend, Message &response, bool assertO k=true ) { assert(false); return false; }
virtual void say( Message &toSend ) { assert(false); } virtual void say( Message &toSend ) { assert(false); }
virtual void sayPiggyBack( Message &toSend ) { assert(false); } virtual void sayPiggyBack( Message &toSend ) { assert(false); }
virtual void checkResponse( const char *data, int nReturned ) { ass ert(false); } virtual void checkResponse( const char *data, int nReturned ) { ass ert(false); }
bool isFailed() const { bool isFailed() const {
// TODO: this really should check isFailed on current master as well // TODO: this really should check isFailed on current master as well
 End of changes. 5 change blocks. 
3 lines changed or deleted 90 lines changed or added


 dbtests.h   dbtests.h 
skipping to change at line 24 skipping to change at line 24
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "framework.h" #include "framework.h"
using namespace mongo; using namespace mongo;
using namespace mongo::regression; using namespace mongo::regression;
using boost::shared_ptr;
 End of changes. 1 change blocks. 
0 lines changed or deleted 0 lines changed or added


 debug_util.h   debug_util.h 
skipping to change at line 43 skipping to change at line 43
typedef char CHARS[400]; typedef char CHARS[400];
typedef struct _OWS { typedef struct _OWS {
int size; int size;
char type; char type;
char string[400]; char string[400];
} *OWS; } *OWS;
#if defined(_DEBUG) #if defined(_DEBUG)
# define MONGO_DEV if( 1 ) enum {DEBUG_BUILD = 1};
#else #else
# define MONGO_DEV if( 0 ) enum {DEBUG_BUILD = 0};
#endif #endif
#define MONGO_DEV if( DEBUG_BUILD )
#define DEV MONGO_DEV #define DEV MONGO_DEV
#define MONGO_DEBUGGING if( 0 ) #define MONGO_DEBUGGING if( 0 )
#define DEBUGGING MONGO_DEBUGGING #define DEBUGGING MONGO_DEBUGGING
// The following declare one unique counter per enclosing function. // The following declare one unique counter per enclosing function.
// NOTE The implementation double-increments on a match, but we don't reall y care. // NOTE The implementation double-increments on a match, but we don't reall y care.
#define MONGO_SOMETIMES( occasion, howOften ) for( static unsigned occasion = 0; ++occasion % howOften == 0; ) #define MONGO_SOMETIMES( occasion, howOften ) for( static unsigned occasion = 0; ++occasion % howOften == 0; )
#define SOMETIMES MONGO_SOMETIMES #define SOMETIMES MONGO_SOMETIMES
 End of changes. 3 change blocks. 
2 lines changed or deleted 4 lines changed or added


 file_allocator.h   file_allocator.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.
*/ */
#include "../pch.h" #include "../pch.h"
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#if defined(__freebsd__) #if defined(__freebsd__) || defined(__openbsd__)
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
#ifndef O_NOATIME #ifndef O_NOATIME
#define O_NOATIME 0 #define O_NOATIME 0
#endif #endif
namespace mongo { namespace mongo {
/* Handles allocation of contiguous files on disk. Allocation may be /* Handles allocation of contiguous files on disk. Allocation may be
 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 27 skipping to change at line 27
*/ */
#pragma once #pragma once
#include "../bson/util/misc.h" #include "../bson/util/misc.h"
#include "concurrency/mutex.h" #include "concurrency/mutex.h"
namespace mongo { namespace mongo {
void setThreadName(const char * name); void setThreadName(const char * name);
string getThreadName();
template<class T> template<class T>
inline string ToString(const T& t) { inline string ToString(const T& t) {
stringstream s; stringstream s;
s << t; s << t;
return s.str(); return s.str();
} }
#if !defined(_WIN32) && !defined(NOEXECINFO) && !defined(__freebsd__) && !d efined(__sun__) #if !defined(_WIN32) && !defined(NOEXECINFO) && !defined(__freebsd__) && !d efined(__openbsd__) && !defined(__sun__)
} // namespace mongo } // namespace mongo
#include <pthread.h> #include <pthread.h>
#include <execinfo.h> #include <execinfo.h>
namespace mongo { namespace mongo {
inline pthread_t GetCurrentThreadId() { inline pthread_t GetCurrentThreadId() {
return pthread_self(); return pthread_self();
skipping to change at line 282 skipping to change at line 283
// simple scoped timer // simple scoped timer
class Timer { class Timer {
public: public:
Timer() { Timer() {
reset(); reset();
} }
Timer( unsigned long long start ) { Timer( unsigned long long start ) {
old = start; old = start;
} }
int seconds(){ int seconds() const {
return (int)(micros() / 1000000); return (int)(micros() / 1000000);
} }
int millis() { int millis() const {
return (long)(micros() / 1000); return (long)(micros() / 1000);
} }
unsigned long long micros() { unsigned long long micros() const {
unsigned long long n = curTimeMicros64(); unsigned long long n = curTimeMicros64();
return n - old; return n - old;
} }
unsigned long long micros(unsigned long long & n) { // returns cur time in addition to timer result unsigned long long micros(unsigned long long & n) const { // return s cur time in addition to timer result
n = curTimeMicros64(); n = curTimeMicros64();
return n - old; return n - old;
} }
unsigned long long startTime(){ unsigned long long startTime(){
return old; return old;
} }
void reset() { void reset() {
old = curTimeMicros64(); old = curTimeMicros64();
} }
private: private:
 End of changes. 6 change blocks. 
5 lines changed or deleted 6 lines changed or added


 gridfs.h   gridfs.h 
skipping to change at line 30 skipping to change at line 30
#include "dbclient.h" #include "dbclient.h"
#include "redef_macros.h" #include "redef_macros.h"
namespace mongo { namespace mongo {
typedef unsigned long long gridfs_offset; typedef unsigned long long gridfs_offset;
class GridFS; class GridFS;
class GridFile; class GridFile;
class Chunk { class GridFSChunk {
public: public:
Chunk( BSONObj data ); GridFSChunk( BSONObj data );
Chunk( BSONObj fileId , int chunkNumber , const char * data , int l GridFSChunk( BSONObj fileId , int chunkNumber , const char * data ,
en ); int len );
int len(){ int len(){
int len; int len;
const char * data = _data["data"].binDataClean( len ); _data["data"].binDataClean( len );
int * foo = (int*)data;
assert( len == foo[0] );
return len; return len;
} }
const char * data( int & len ){ const char * data( int & len ){
const char * data = _data["data"].binDataClean( len ); return _data["data"].binDataClean( len );
int * foo = (int*)data;
assert( len == foo[0] );
len = len;
return data;
} }
private: private:
BSONObj _data; BSONObj _data;
friend class GridFS; friend class GridFS;
}; };
/** /**
this is the main entry point into the mongo grid fs this is the main entry point into the mongo grid fs
*/ */
skipping to change at line 133 skipping to change at line 126
private: private:
DBClientBase& _client; DBClientBase& _client;
string _dbName; string _dbName;
string _prefix; string _prefix;
string _filesNS; string _filesNS;
string _chunksNS; string _chunksNS;
unsigned int _chunkSize; unsigned int _chunkSize;
// insert fileobject. All chunks must be in DB. // insert fileobject. All chunks must be in DB.
BSONObj insertFile(const string& name, const OID& id, unsigned leng th, const string& contentType); BSONObj insertFile(const string& name, const OID& id, gridfs_offset length, const string& contentType);
friend class GridFile; friend class GridFile;
}; };
/** /**
wrapper for a file stored in the Mongo database wrapper for a file stored in the Mongo database
*/ */
class GridFile { class GridFile {
public: public:
/** /**
skipping to change at line 185 skipping to change at line 178
BSONElement getFileField( const string& name ){ BSONElement getFileField( const string& name ){
return _obj[name]; return _obj[name];
} }
BSONObj getMetadata(); BSONObj getMetadata();
int getNumChunks(){ int getNumChunks(){
return (int) ceil( (double)getContentLength() / (double)getChun kSize() ); return (int) ceil( (double)getContentLength() / (double)getChun kSize() );
} }
Chunk getChunk( int n ); GridFSChunk getChunk( int n );
/** /**
write the file to the output stream write the file to the output stream
*/ */
gridfs_offset write( ostream & out ); gridfs_offset write( ostream & out );
/** /**
write the file to this filename write the file to this filename
*/ */
gridfs_offset write( const string& where ); gridfs_offset write( const string& where );
 End of changes. 6 change blocks. 
15 lines changed or deleted 8 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 requestHeartbeat(string setname, string memberFullName, BSONObj& r esult, int myConfigVersion, int& theirConfigVersion, bool checkEmpty = fals e);
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


 hostandport.h   hostandport.h 
skipping to change at line 59 skipping to change at line 59
bool operator<(const HostAndPort& r) const { return _host < r._host || (_host==r._host&&_port<r._port); } bool operator<(const HostAndPort& r) const { return _host < r._host || (_host==r._host&&_port<r._port); }
/* returns true if the host/port combo identifies this process inst ance. */ /* returns true if the host/port combo identifies this process inst ance. */
bool isSelf() const; bool isSelf() const;
bool isLocalHost() const; bool isLocalHost() const;
// @returns host:port // @returns host:port
string toString() const; string toString() const;
operator string() const { return toString(); }
string host() const { return _host; } string host() const { return _host; }
int port() const { return _port >= 0 ? _port : cmdLine.port; } int port() const { return _port >= 0 ? _port : cmdLine.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
}; };
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 html.h   html.h 
skipping to change at line 94 skipping to change at line 94
ss << "</head>\n<body>\n"; ss << "</head>\n<body>\n";
return ss.str(); return ss.str();
} }
inline string red(string contentHtml, bool color=true) { inline string red(string contentHtml, bool color=true) {
if( !color ) return contentHtml; if( !color ) return contentHtml;
stringstream ss; stringstream ss;
ss << "<span style=\"color:#A00;\">" << contentHtml << "</span> "; ss << "<span style=\"color:#A00;\">" << contentHtml << "</span> ";
return ss.str(); return ss.str();
} }
inline string grey(string contentHtml, bool color=true) {
if( !color ) return contentHtml;
stringstream ss;
ss << "<span style=\"color:#888;\">" << contentHtml << "</span>
";
return ss.str();
}
inline string blue(string contentHtml, bool color=true) { inline string blue(string contentHtml, bool color=true) {
if( !color ) return contentHtml; if( !color ) return contentHtml;
stringstream ss; stringstream ss;
ss << "<span style=\"color:#00A;\">" << contentHtml << "</span> "; ss << "<span style=\"color:#00A;\">" << contentHtml << "</span> ";
return ss.str(); return ss.str();
} }
inline string yellow(string contentHtml, bool color=true) { inline string yellow(string contentHtml, bool color=true) {
if( !color ) return contentHtml; if( !color ) return contentHtml;
stringstream ss; stringstream ss;
ss << "<span style=\"color:#A80;\">" << contentHtml << "</span> "; ss << "<span style=\"color:#A80;\">" << contentHtml << "</span> ";
 End of changes. 1 change blocks. 
0 lines changed or deleted 7 lines changed or added


 instance.h   instance.h 
skipping to change at line 109 skipping to change at line 109
response = 0; response = 0;
exhaust = 0; exhaust = 0;
} }
~DbResponse() { delete response; } ~DbResponse() { delete response; }
}; };
bool assembleResponse( Message &m, DbResponse &dbresponse, const SockAd dr &client = unknownAddress ); bool assembleResponse( Message &m, DbResponse &dbresponse, const SockAd dr &client = unknownAddress );
void getDatabaseNames( vector< string > &names , const string& usePath = dbpath ); void getDatabaseNames( vector< string > &names , const string& usePath = dbpath );
/* returns true if there is no data on this server. useful when starti
ng replication.
local database does NOT count.
*/
bool haveDatabases();
// --- local client --- // --- local client ---
class DBDirectClient : public DBClientBase { class DBDirectClient : public DBClientBase {
public: public:
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0, virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0,
const BSONObj *fieldsToRetur n = 0, int queryOptions = 0); const BSONObj *fieldsToRetur n = 0, int queryOptions = 0);
virtual bool isFailed() const { virtual bool isFailed() const {
return false; return false;
 End of changes. 1 change blocks. 
0 lines changed or deleted 6 lines changed or added


 lasterror.h   lasterror.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 "../bson/oid.h"
namespace mongo { namespace mongo {
class BSONObjBuilder; class BSONObjBuilder;
class Message; class Message;
struct LastError { struct LastError {
int code; int code;
string msg; string msg;
enum UpdatedExistingType { NotUpdate, True, False } updatedExisting ; enum UpdatedExistingType { NotUpdate, True, False } updatedExisting ;
/* todo: nObjects should be 64 bit */ OID upsertedId;
long long nObjects; long long nObjects;
int nPrev; int nPrev;
bool valid; bool valid;
bool overridenById; bool overridenById;
bool disabled; bool disabled;
void raiseError(int _code , const char *_msg) { void raiseError(int _code , const char *_msg) {
reset( true ); reset( true );
code = _code; code = _code;
msg = _msg; msg = _msg;
} }
void recordUpdate( bool _updatedExisting, long long nChanged ) { void recordUpdate( bool _updateObjects , long long _nObjects , OID _upsertedId ){
reset( true ); reset( true );
nObjects = nChanged; nObjects = _nObjects;
updatedExisting = _updatedExisting ? True : False; updatedExisting = _updateObjects ? True : False;
if ( _upsertedId.isSet() )
upsertedId = _upsertedId;
} }
void recordDelete( long long nDeleted ) { void recordDelete( long long nDeleted ) {
reset( true ); reset( true );
nObjects = nDeleted; nObjects = nDeleted;
} }
LastError() { LastError() {
overridenById = false; overridenById = false;
reset(); reset();
} }
void reset( bool _valid = false ) { void reset( bool _valid = false ) {
code = 0; code = 0;
msg.clear(); msg.clear();
updatedExisting = NotUpdate; updatedExisting = NotUpdate;
nObjects = 0; nObjects = 0;
nPrev = 1; nPrev = 1;
valid = _valid; valid = _valid;
disabled = false; disabled = false;
upsertedId.clear();
} }
void appendSelf( BSONObjBuilder &b ); void appendSelf( BSONObjBuilder &b );
static LastError noError; static LastError noError;
}; };
extern class LastErrorHolder { extern class LastErrorHolder {
public: public:
LastErrorHolder() : _id( 0 ) {} LastErrorHolder() : _id( 0 ) {}
LastError * get( bool create = false ); LastError * get( bool create = false );
LastError * getSafe(){
LastError * le = get(false);
assert( le );
return le;
}
LastError * _get( bool create = false ); // may return a disabled L astError LastError * _get( bool create = false ); // may return a disabled L astError
void reset( LastError * le ); void reset( LastError * le );
/** ok to call more than once. */ /** ok to call more than once. */
void initThread(); void initThread();
/** /**
* id of 0 means should use thread local management * id of 0 means should use thread local management
skipping to change at line 110 skipping to change at line 121
struct Status { struct Status {
time_t time; time_t time;
LastError *lerr; LastError *lerr;
}; };
static mongo::mutex _idsmutex; static mongo::mutex _idsmutex;
map<int,Status> _ids; map<int,Status> _ids;
} lastError; } lastError;
void raiseError(int code , const char *msg); void raiseError(int code , const char *msg);
inline void recordUpdate( bool updatedExisting, int nChanged ) {
LastError *le = lastError.get();
if ( le )
le->recordUpdate( updatedExisting, nChanged );
}
inline void recordDelete( int nDeleted ) {
LastError *le = lastError.get();
if ( le )
le->recordDelete( nDeleted );
}
} // namespace mongo } // namespace mongo
 End of changes. 7 change blocks. 
16 lines changed or deleted 15 lines changed or added


 log.h   log.h 
skipping to change at line 30 skipping to change at line 30
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include "../bson/util/builder.h" #include "../bson/util/builder.h"
#ifndef _WIN32 #ifndef _WIN32
//#include <syslog.h> //#include <syslog.h>
#endif #endif
namespace mongo { namespace mongo {
using boost::shared_ptr; enum LogLevel { LL_DEBUG , LL_INFO , LL_NOTICE , LL_WARNING , LL_ERROR
, LL_SEVERE };
inline const char * logLevelToString( LogLevel l ){
switch ( l ){
case LL_DEBUG:
case LL_INFO:
case LL_NOTICE:
return "";
case LL_WARNING:
return "warning" ;
case LL_ERROR:
return "ERROR";
case LL_SEVERE:
return "SEVERE";
default:
return "UNKNOWN";
}
}
// Utility interface for stringifying object only when val() called.
class LazyString { class LazyString {
public: public:
virtual ~LazyString() {} virtual ~LazyString() {}
virtual string val() const = 0; virtual string val() const = 0;
}; };
// Utility class for stringifying object only when val() called. // Utility class for stringifying object only when val() called.
template< class T > template< class T >
class LazyStringImpl : public LazyString { class LazyStringImpl : public LazyString {
public: public:
LazyStringImpl( const T &t ) : t_( t ) {} LazyStringImpl( const T &t ) : t_( t ) {}
virtual string val() const { return (string)t_; } virtual string val() const { return (string)t_; }
private: private:
const T& t_; const T& t_;
}; };
class Tee { class Tee {
public: public:
virtual ~Tee(){} virtual ~Tee(){}
virtual void write(const string& str) = 0; virtual void write(LogLevel level , const string& str) = 0;
}; };
class Nullstream { class Nullstream {
public: public:
virtual Nullstream& operator<< (Tee* tee) { virtual Nullstream& operator<< (Tee* tee) {
return *this; return *this;
} }
virtual ~Nullstream() {} virtual ~Nullstream() {}
virtual Nullstream& operator<<(const char *) { virtual Nullstream& operator<<(const char *) {
return *this; return *this;
skipping to change at line 136 skipping to change at line 152
return *this; return *this;
} }
virtual void flush(Tee *t = 0) {} virtual void flush(Tee *t = 0) {}
}; };
extern Nullstream nullstream; extern Nullstream nullstream;
class Logstream : public Nullstream { class Logstream : public Nullstream {
static mongo::mutex mutex; static mongo::mutex mutex;
static int doneSetup; static int doneSetup;
stringstream ss; stringstream ss;
LogLevel logLevel;
public: public:
static int magicNumber(){ static int magicNumber(){
return 1717; return 1717;
} }
void flush(Tee *t = 0) { void flush(Tee *t = 0) {
// this ensures things are sane // this ensures things are sane
if ( doneSetup == 1717 ) { if ( doneSetup == 1717 ) {
BufBuilder b(512); BufBuilder b(512);
time_t_to_String( time(0) , b.grow(20) ); time_t_to_String( time(0) , b.grow(20) );
b.append( ss.str() ); b.append( ss.str() );
const char *s = b.buf(); const char *s = b.buf();
string threadName = getThreadName();
const char * type = logLevelToString(logLevel);
scoped_lock lk(mutex); scoped_lock lk(mutex);
if( t ) t->write(s); if( t ) t->write(logLevel,s);
#ifndef _WIN32 #ifndef _WIN32
//syslog( LOG_INFO , "%s" , cc ); //syslog( LOG_INFO , "%s" , cc );
#endif #endif
if ( ! threadName.empty() ){
cout << "[" << threadName << "] ";
}
cout << type << ( type[0] ? ": " : "" );
cout << s; cout << s;
cout.flush(); cout.flush();
} }
_init(); _init();
} }
Nullstream& setLogLevel(LogLevel l){
logLevel = l;
return *this;
}
/** note these are virtual */ /** note these are virtual */
Logstream& operator<<(const char *x) { ss << x; return *this; } Logstream& operator<<(const char *x) { ss << x; return *this; }
Logstream& operator<<(char *x) { ss << x; return *this; } Logstream& operator<<(char *x) { ss << x; return *this; }
Logstream& operator<<(char x) { ss << x; return *this; } Logstream& operator<<(char x) { ss << x; return *this; }
Logstream& operator<<(int x) { ss << x; return *this; } Logstream& operator<<(int x) { ss << x; return *this; }
Logstream& operator<<(ExitCode x) { ss << x; return *this; } Logstream& operator<<(ExitCode x) { ss << x; return *this; }
Logstream& operator<<(long x) { ss << x; return *this; } Logstream& operator<<(long x) { ss << x; return *this; }
Logstream& operator<<(unsigned long x) { ss << x; return *this; } Logstream& operator<<(unsigned long x) { ss << x; return *this; }
Logstream& operator<<(unsigned x) { ss << x; return *this; } Logstream& operator<<(unsigned x) { ss << x; return *this; }
Logstream& operator<<(double x) { ss << x; return *this; } Logstream& operator<<(double x) { ss << x; return *this; }
skipping to change at line 216 skipping to change at line 247
return *this; return *this;
} }
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;
} }
public: public:
static Logstream& get() { static Logstream& get() {
Logstream *p = tsp.get(); Logstream *p = tsp.get();
if( p == 0 ) if( p == 0 )
tsp.reset( p = new Logstream() ); tsp.reset( p = new Logstream() );
return *p; return *p;
} }
}; };
skipping to change at line 263 skipping to change at line 295
return nullstream; return nullstream;
return Logstream::get().prolog(); return Logstream::get().prolog();
} }
inline Nullstream& log( int level ) { inline Nullstream& log( int level ) {
if ( level > logLevel ) if ( level > logLevel )
return nullstream; return nullstream;
return Logstream::get().prolog(); return Logstream::get().prolog();
} }
inline Nullstream& log( LogLevel l ) {
return Logstream::get().prolog().setLogLevel( l );
}
inline Nullstream& log() { inline Nullstream& log() {
return Logstream::get().prolog(); return Logstream::get().prolog();
} }
/* TODOCONCURRENCY */ /* TODOCONCURRENCY */
inline ostream& stdcout() { inline ostream& stdcout() {
return cout; return cout;
} }
/* default impl returns "" -- mongod overrides */ /* default impl returns "" -- mongod overrides */
 End of changes. 10 change blocks. 
4 lines changed or deleted 41 lines changed or added


 message.h   message.h 
skipping to change at line 35 skipping to change at line 35
extern bool noUnixSocket; extern bool noUnixSocket;
class Message; class Message;
class MessagingPort; class MessagingPort;
class PiggyBackData; class PiggyBackData;
typedef AtomicUInt MSGID; typedef AtomicUInt MSGID;
class Listener { class Listener {
public: public:
Listener(const string &ip, int p, bool logConnect=true ) : _port(p) Listener(const string &ip, int p, bool logConnect=true ) : _port(p)
, _ip(ip), _logConnect(logConnect) { } , _ip(ip), _logConnect(logConnect), _elapsedTime(0){ }
virtual ~Listener() {} virtual ~Listener() {
if ( _timeTracker == this )
_timeTracker = 0;
}
void initAndListen(); // never returns unless error (start a thread ) void initAndListen(); // never returns unless error (start a thread )
/* spawn a thread, etc., then return */ /* spawn a thread, etc., then return */
virtual void accepted(int sock, const SockAddr& from); virtual void accepted(int sock, const SockAddr& from);
virtual void accepted(MessagingPort *mp){ virtual void accepted(MessagingPort *mp){
assert(!"You must overwrite one of the accepted methods"); assert(!"You must overwrite one of the accepted methods");
} }
const int _port; const int _port;
/**
* @return a rough estimate of elepased time since the server start
ed
*/
long long getMyElapsedTimeMillis() const { return _elapsedTime; }
void setAsTimeTracker(){
_timeTracker = this;
}
static const Listener* getTimeTracker(){
return _timeTracker;
}
static long long getElapsedTimeMillis() {
if ( _timeTracker )
return _timeTracker->getMyElapsedTimeMillis();
return 0;
}
private: private:
string _ip; string _ip;
bool _logConnect; bool _logConnect;
long long _elapsedTime;
static const Listener* _timeTracker;
}; };
class AbstractMessagingPort { class AbstractMessagingPort {
public: public:
virtual ~AbstractMessagingPort() { } virtual ~AbstractMessagingPort() { }
virtual void reply(Message& received, Message& response, MSGID resp onseTo) = 0; // like the reply below, but doesn't rely on received.data sti ll being available virtual void reply(Message& received, Message& response, MSGID resp onseTo) = 0; // like the reply below, but doesn't rely on received.data sti ll being available
virtual void reply(Message& received, Message& response) = 0; virtual void reply(Message& received, Message& response) = 0;
virtual HostAndPort remote() const = 0; virtual HostAndPort remote() const = 0;
virtual unsigned remotePort() const = 0; virtual unsigned remotePort() const = 0;
skipping to change at line 370 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:
virtual const char* what() const throw() { return "socket exception SocketException() : DBException( "socket exception" , 9001 ){}
"; }
virtual int getCode() const { return 9001; }
}; };
MSGID nextMessageId(); MSGID nextMessageId();
void setClientId( int id ); void setClientId( int id );
int getClientId(); int getClientId();
extern TicketHolder connTicketHolder; extern TicketHolder connTicketHolder;
class ElapsedTracker {
public:
ElapsedTracker( int hitsBetweenMarks , int msBetweenMarks )
: _h( hitsBetweenMarks ) , _ms( msBetweenMarks ) , _pings(0){
_last = Listener::getElapsedTimeMillis();
}
/**
* call this for every iteration
* returns true if one of the triggers has gone off
*/
bool ping(){
if ( ( ++_pings % _h ) == 0 ){
_last = Listener::getElapsedTimeMillis();
return true;
}
long long now = Listener::getElapsedTimeMillis();
if ( now - _last > _ms ){
_last = now;
return true;
}
return false;
}
private:
int _h;
int _ms;
unsigned long long _pings;
long long _last;
};
} // namespace mongo } // namespace mongo
 End of changes. 5 change blocks. 
6 lines changed or deleted 66 lines changed or added


 mmap.h   mmap.h 
skipping to change at line 30 skipping to change at line 30
namespace mongo { namespace mongo {
/* the administrative-ish stuff here */ /* the administrative-ish stuff here */
class MongoFile : boost::noncopyable { class MongoFile : boost::noncopyable {
protected: protected:
virtual void close() = 0; virtual void close() = 0;
virtual void flush(bool sync) = 0; virtual void flush(bool sync) = 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
virtual void _lock() {}
virtual void _unlock() {}
public: public:
virtual ~MongoFile() {} virtual ~MongoFile() {}
virtual long length() = 0; virtual long length() = 0;
enum Options { enum Options {
SEQUENTIAL = 1 // hint - e.g. FILE_FLAG_SEQUENTIAL_SCAN on wind ows SEQUENTIAL = 1 // hint - e.g. FILE_FLAG_SEQUENTIAL_SCAN on wind ows
}; };
static int flushAll( bool sync ); // returns n flushed static int flushAll( bool sync ); // returns n flushed
static long long totalMappedLength(); static long long totalMappedLength();
static void closeAllFiles( stringstream &message ); static void closeAllFiles( stringstream &message );
// Locking allows writes. Reads are always allowed
static void lockAll();
static void unlockAll();
/* can be "overriden" if necessary */ /* can be "overriden" if necessary */
static bool exists(boost::filesystem::path p) { static bool exists(boost::filesystem::path p) {
return boost::filesystem::exists(p); return boost::filesystem::exists(p);
} }
}; };
#ifndef _DEBUG
// no-ops in production
inline void MongoFile::lockAll() {}
inline void MongoFile::unlockAll() {}
#endif
struct MongoFileAllowWrites {
MongoFileAllowWrites(){
MongoFile::lockAll();
}
~MongoFileAllowWrites(){
MongoFile::unlockAll();
}
};
/** template for what a new storage engine's class definition must impl ement /** template for what a new storage engine's class definition must impl ement
PRELIMINARY - subject to change. PRELIMINARY - subject to change.
*/ */
class StorageContainerTemplate : public MongoFile { class StorageContainerTemplate : public MongoFile {
protected: protected:
virtual void close(); virtual void close();
virtual void flush(bool sync); virtual void flush(bool sync);
public: public:
virtual long length(); virtual long length();
skipping to change at line 140 skipping to change at line 165
} }
private: private:
static void updateLength( const char *filename, long &length ); static void updateLength( const char *filename, long &length );
HANDLE fd; HANDLE fd;
HANDLE maphandle; HANDLE maphandle;
void *view; void *view;
long len; long len;
string _filename; string _filename;
protected:
// only posix mmap implementations will support this
virtual void _lock();
virtual void _unlock();
}; };
void printMemInfo( const char * where ); void printMemInfo( const char * where );
#include "ramstore.h" #include "ramstore.h"
//#define _RAMSTORE //#define _RAMSTORE
#if defined(_RAMSTORE) #if defined(_RAMSTORE)
typedef RamStoreFile MMF; typedef RamStoreFile MMF;
#else #else
 End of changes. 4 change blocks. 
0 lines changed or deleted 31 lines changed or added


 msg.h   msg.h 
skipping to change at line 44 skipping to change at line 44
/** typical usage is: task::fork( foo.task() ); */ /** typical usage is: task::fork( foo.task() ); */
shared_ptr<Task> taskPtr() { return shared_ptr<Task>(static_cas t<Task*>(this)); } 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; }
protected:
/* this needn't be abstract; i left it that way for now so i re
member
to call Client::initThread() when using in mongo... */
virtual void starting() = 0;
private: private:
virtual bool initClient() { return true; }
virtual string name() { return _name; } virtual string name() { return _name; }
void doWork(); void doWork();
deque<lam> d; deque<lam> d;
boost::mutex m; boost::mutex m;
boost::condition c; boost::condition c;
string _name; string _name;
bool rq;
}; };
} }
} }
 End of changes. 3 change blocks. 
0 lines changed or deleted 10 lines changed or added


 multicmd.h   multicmd.h 
skipping to change at line 34 skipping to change at line 34
namespace mongo { namespace mongo {
struct Target { struct Target {
Target(string hostport) : toHost(hostport), ok(false) { } Target(string hostport) : toHost(hostport), ok(false) { }
Target() : ok(false) { } Target() : ok(false) { }
string toHost; string toHost;
bool ok; bool ok;
BSONObj result; BSONObj result;
}; };
/** send a command in parallel to many servers, and collect the results
. */
void multiCommand(BSONObj cmd, list<Target>& L);
/* -- implementation ------------- */ /* -- implementation ------------- */
class _MultiCommandJob : public BackgroundJob { class _MultiCommandJob : public BackgroundJob {
public: public:
BSONObj& cmd; BSONObj& cmd;
Target& d; Target& d;
_MultiCommandJob(BSONObj& _cmd, Target& _d) : cmd(_cmd), d(_d) { } _MultiCommandJob(BSONObj& _cmd, Target& _d) : cmd(_cmd), d(_d) { }
private: private:
string name() { return "MultiCommandJob"; } string name() { return "MultiCommandJob"; }
void run() { void run() {
 End of changes. 1 change blocks. 
4 lines changed or deleted 0 lines changed or added


 mutex.h   mutex.h 
skipping to change at line 46 skipping to change at line 46
unsigned magic; unsigned magic;
public: public:
// set these to create an assert that // set these to create an assert that
// b must never be locked before a // b must never be locked before a
// so // so
// a.lock(); b.lock(); is fine // a.lock(); b.lock(); is fine
// b.lock(); alone is fine too // b.lock(); alone is fine too
// only checked on _DEBUG builds. // only checked on _DEBUG builds.
string a,b; string a,b;
void aBreakPoint(){}
void programEnding(); void programEnding();
MutexDebugger(); MutexDebugger();
void entering(mid m) { void entering(mid m) {
if( magic != 0x12345678 ) return; if( magic != 0x12345678 ) return;
Preceeding *_preceeding = us.get(); Preceeding *_preceeding = us.get();
if( _preceeding == 0 ) if( _preceeding == 0 )
us.reset( _preceeding = new Preceeding() ); us.reset( _preceeding = new Preceeding() );
Preceeding &preceeding = *_preceeding; Preceeding &preceeding = *_preceeding;
if( a == m ) { if( a == m ) {
aBreakPoint();
if( preceeding[b.c_str()] ) { if( preceeding[b.c_str()] ) {
cout << "mutex problem " << b << " was locked before " << a << endl; cout << "mutex problem " << b << " was locked before " << a << endl;
assert(false); assert(false);
} }
} }
preceeding[m]++; preceeding[m]++;
if( preceeding[m] > 1 ) { if( preceeding[m] > 1 ) {
// recursive re-locking. // recursive re-locking.
if( preceeding[m] > maxNest[m] ) if( preceeding[m] > maxNest[m] )
 End of changes. 2 change blocks. 
0 lines changed or deleted 2 lines changed or added


 namespace.h   namespace.h 
skipping to change at line 393 skipping to change at line 393
//returns offset in indexes[] //returns offset in indexes[]
int findIndexByKeyPattern(const BSONObj& keyPattern) { int findIndexByKeyPattern(const BSONObj& keyPattern) {
IndexIterator i = ii(); IndexIterator i = ii();
while( i.more() ) { while( i.more() ) {
if( i.next().keyPattern() == keyPattern ) if( i.next().keyPattern() == keyPattern )
return i.pos()-1; return i.pos()-1;
} }
return -1; return -1;
} }
void findIndexByType( const string& name , vector<int>& matches ) {
IndexIterator i = ii();
while ( i.more() ){
if ( i.next().getSpec().getTypeName() == name )
matches.push_back( i.pos() - 1 );
}
}
/* @return -1 = not found /* @return -1 = not found
generally id is first index, so not that expensive an operation (assuming present). generally id is first index, so not that expensive an operation (assuming present).
*/ */
int findIdIndex() { int findIdIndex() {
IndexIterator i = ii(); IndexIterator i = ii();
while( i.more() ) { while( i.more() ) {
if( i.next().isIdIndex() ) if( i.next().isIdIndex() )
return i.pos()-1; return i.pos()-1;
} }
return -1; return -1;
 End of changes. 1 change blocks. 
0 lines changed or deleted 8 lines changed or added


 oid.h   oid.h 
skipping to change at line 122 skipping to change at line 122
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() */
TenGen, TenGen,
/** Javascript JSON compatible */ /** Javascript JSON compatible */
JS JS
}; };
/* l and r MUST have same type when called: check that first. */
int compareElementValues(const BSONElement& l, const BSONElement& r);
inline ostream& operator<<( ostream &s, const OID &o ) { inline ostream& operator<<( ostream &s, const OID &o ) {
s << o.str(); s << o.str();
return s; return s;
} }
} }
 End of changes. 1 change blocks. 
3 lines changed or deleted 0 lines changed or added


 oplog.h   oplog.h 
skipping to change at line 182 skipping to change at line 182
shared_ptr<Cursor> c = _qp.newCursor( startLoc ); shared_ptr<Cursor> c = _qp.newCursor( startLoc );
_findingStartCursor = new ClientCursor(QueryOption_NoCursorTime out, c, _qp.ns()); _findingStartCursor = new ClientCursor(QueryOption_NoCursorTime out, c, _qp.ns());
} }
void destroyClientCursor() { void destroyClientCursor() {
if ( _findingStartCursor ) { if ( _findingStartCursor ) {
ClientCursor::erase( _findingStartCursor->cursorid ); ClientCursor::erase( _findingStartCursor->cursorid );
_findingStartCursor = 0; _findingStartCursor = 0;
} }
} }
void maybeRelease() { void maybeRelease() {
RARELY { if ( ! _findingStartCursor->yieldSometimes() ){
CursorId id = _findingStartCursor->cursorid; _findingStartCursor = 0;
_findingStartCursor->updateLocation();
{
dbtemprelease t;
}
_findingStartCursor = ClientCursor::find( id, false );
} }
} }
void init() { void init() {
// Use a ClientCursor here so we can release db mutex while sca nning // Use a ClientCursor here so we can release db mutex while sca nning
// oplog (can take quite a while with large oplogs). // oplog (can take quite a while with large oplogs).
shared_ptr<Cursor> c = _qp.newReverseCursor(); shared_ptr<Cursor> c = _qp.newReverseCursor();
_findingStartCursor = new ClientCursor(QueryOption_NoCursorTime out, c, _qp.ns()); _findingStartCursor = new ClientCursor(QueryOption_NoCursorTime out, c, _qp.ns());
_findingStartTimer.reset(); _findingStartTimer.reset();
_findingStartMode = Initial; _findingStartMode = Initial;
BSONElement tsElt = _qp.originalQuery()[ "ts" ]; BSONElement tsElt = _qp.originalQuery()[ "ts" ];
massert( 13044, "no ts field in query", !tsElt.eoo() ); massert( 13044, "no ts field in query", !tsElt.eoo() );
BSONObjBuilder b; BSONObjBuilder b;
b.append( tsElt ); b.append( tsElt );
BSONObj tsQuery = b.obj(); BSONObj tsQuery = b.obj();
_matcher.reset(new CoveredIndexMatcher(tsQuery, _qp.indexKey()) ); _matcher.reset(new CoveredIndexMatcher(tsQuery, _qp.indexKey()) );
} }
}; };
void pretouchOperation(const BSONObj& op);
void applyOperation_inlock(const BSONObj& op);
} }
 End of changes. 2 change blocks. 
7 lines changed or deleted 5 lines changed or added


 optime.h   optime.h 
skipping to change at line 26 skipping to change at line 26
*/ */
#pragma once #pragma once
#include "../db/concurrency.h" #include "../db/concurrency.h"
namespace mongo { namespace mongo {
void exitCleanly( ExitCode code ); void exitCleanly( ExitCode code );
struct ClockSkewException : public DBException { struct ClockSkewException : public DBException {
virtual const char* what() const throw() { return "clock skew excep ClockSkewException() : DBException( "clock skew exception" , 20001
tion"; } ){}
virtual int getCode() const { return 20001; }
}; };
/* replsets use RSOpTime. /* replsets use RSOpTime.
M/S uses OpTime. M/S uses OpTime.
But this is useable from both. But this is useable from both.
*/ */
typedef unsigned long long ReplTime; typedef unsigned long long ReplTime;
/* Operation sequence #. A combination of current second plus an ordin al value. /* Operation sequence #. A combination of current second plus an ordin al value.
*/ */
skipping to change at line 98 skipping to change at line 97
/* 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 *((unsigned long long *) &i);
} }
long long asLL() const {
return *((long long *) &i);
}
// unsigned long long& asDate() { return *((unsigned long lon g *) &i); } // unsigned long long& asDate() { return *((unsigned long lon g *) &i); }
bool isNull() { bool isNull() const { return secs == 0; }
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();
} }
skipping to change at line 130 skipping to change at line 130
return i == r.i && secs == r.secs; return i == r.i && secs == r.secs;
} }
bool operator!=(const OpTime& r) const { bool operator!=(const OpTime& r) const {
return !(*this == r); return !(*this == r);
} }
bool operator<(const OpTime& r) const { bool operator<(const OpTime& r) const {
if ( secs != r.secs ) if ( secs != r.secs )
return secs < r.secs; return secs < r.secs;
return i < r.i; return i < r.i;
} }
bool operator<=(const OpTime& r) const {
return *this < r || *this == r;
}
}; };
#pragma pack() #pragma pack()
} // namespace mongo } // namespace mongo
 End of changes. 4 change blocks. 
6 lines changed or deleted 9 lines changed or added


 parallel.h   parallel.h 
skipping to change at line 19 skipping to change at line 19
* 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.
*/ */
/** /**
tools for wokring in parallel/sharded/clustered environment tools for working in parallel/sharded/clustered environment
*/ */
#include "../pch.h" #include "../pch.h"
#include "dbclient.h" #include "dbclient.h"
#include "redef_macros.h" #include "redef_macros.h"
#include "../db/dbmessage.h" #include "../db/dbmessage.h"
#include "../db/matcher.h" #include "../db/matcher.h"
namespace mongo { namespace mongo {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 pch.h   pch.h 
skipping to change at line 40 skipping to change at line 40
# define _CRT_SECURE_NO_WARNINGS # define _CRT_SECURE_NO_WARNINGS
#endif #endif
#if defined(WIN32) #if defined(WIN32)
// so you don't have to define this yourself as the code seems to use it... // so you don't have to define this yourself as the code seems to use it...
#undef _WIN32 #undef _WIN32
#define _WIN32 #define _WIN32
#endif #endif
#if defined(_WIN32) #if defined(_WIN32)
# define NOMINMAX # ifndef NOMINMAX
# define NOMINMAX
# endif
# include <winsock2.h> //this must be included before the first windows.h i nclude # include <winsock2.h> //this must be included before the first windows.h i nclude
# include <ws2tcpip.h> # include <ws2tcpip.h>
# include <wspiapi.h>
# include <windows.h> # include <windows.h>
#endif #endif
#include <ctime> #include <ctime>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <memory> #include <memory>
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
skipping to change at line 90 skipping to change at line 93
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#include <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
#include <boost/thread/recursive_mutex.hpp> #include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/xtime.hpp> #include <boost/thread/xtime.hpp>
#undef assert #undef assert
#define assert MONGO_assert #define assert MONGO_assert
namespace mongo { namespace mongo {
using namespace std; using namespace std;
using boost::shared_ptr;
#if defined(_DEBUG) #if defined(_DEBUG)
const bool debug=true; const bool debug=true;
#else #else
const bool debug=false; const bool debug=false;
#endif #endif
// pdfile versions // pdfile versions
const int VERSION = 4; const int VERSION = 4;
const int VERSION_MINOR = 5; const int VERSION_MINOR = 5;
 End of changes. 3 change blocks. 
1 lines changed or deleted 5 lines changed or added


 pdfile.h   pdfile.h 
skipping to change at line 51 skipping to change at line 51
class OpDebug; class OpDebug;
void dropDatabase(string db); void dropDatabase(string db);
bool repairDatabase(string db, string &errmsg, bool preserveClonedFiles OnFailure = false, bool backupOriginalFiles = false); bool repairDatabase(string db, string &errmsg, bool preserveClonedFiles OnFailure = false, bool backupOriginalFiles = false);
/* low level - only drops this ns */ /* low level - only drops this ns */
void dropNS(const string& dropNs); void dropNS(const string& dropNs);
/* deletes this ns, indexes and cursors */ /* deletes this ns, indexes and cursors */
void dropCollection( const string &name, string &errmsg, BSONObjBuilder &result ); void dropCollection( const string &name, string &errmsg, BSONObjBuilder &result );
bool userCreateNS(const char *ns, BSONObj j, string& err, bool logForRe plication); bool userCreateNS(const char *ns, BSONObj j, string& err, bool logForRe plication, bool *deferIdIndex = 0);
shared_ptr<Cursor> findTableScan(const char *ns, const BSONObj& order, const DiskLoc &startLoc=DiskLoc()); shared_ptr<Cursor> findTableScan(const char *ns, const BSONObj& order, const DiskLoc &startLoc=DiskLoc());
// -1 if library unavailable. // -1 if library unavailable.
boost::intmax_t freeSpace(); boost::intmax_t freeSpace();
/*--------------------------------------------------------------------- */ /*--------------------------------------------------------------------- */
class MongoDataFile { class MongoDataFile {
friend class DataFileMgr; friend class DataFileMgr;
friend class BasicCursor; friend class BasicCursor;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 query.h   query.h 
skipping to change at line 82 skipping to change at line 82
namespace mongo { namespace mongo {
extern const int MaxBytesToReturnToClientAtOnce; extern const int MaxBytesToReturnToClientAtOnce;
// for an existing query (ie a ClientCursor), send back additional info rmation. // for an existing query (ie a ClientCursor), send back additional info rmation.
struct GetMoreWaitException { }; struct GetMoreWaitException { };
QueryResult* processGetMore(const char *ns, int ntoreturn, long long cu rsorid , CurOp& op, int pass, bool& exhaust); QueryResult* processGetMore(const char *ns, int ntoreturn, long long cu rsorid , CurOp& op, int pass, bool& exhaust);
struct UpdateResult { struct UpdateResult {
bool existing; bool existing; // if existing objects were modified
bool mod; bool mod; // was this a $ mod
long long num; long long num; // how many objects touched
OID upserted; // if something was upserted, the new _id of the obj
UpdateResult( bool e, bool m, unsigned long long n ) ect
: existing(e) , mod(m), num(n ){}
int oldCode(){ UpdateResult( bool e, bool m, unsigned long long n , const BSONObj&
if ( ! num ) upsertedObject = BSONObj() )
return 0; : existing(e) , mod(m), num(n){
upserted.clear();
if ( existing ){ BSONElement id = upsertedObject["_id"];
if ( mod ) if ( ! e && n == 1 && id.type() == jstOID ){
return 2; upserted = id.OID();
return 1;
} }
if ( mod )
return 3;
return 4;
} }
}; };
/* returns true if an existing object was updated, false if no existing object was found. /* returns true if an existing object was updated, false if no existing object was found.
multi - update multiple objects - mostly useful with things like $se t multi - update multiple objects - mostly useful with things like $se t
god - allow access to system namespaces god - allow access to system namespaces
*/ */
UpdateResult updateObjects(const char *ns, const BSONObj& updateobj, BS ONObj pattern, bool upsert, bool multi , bool logop , OpDebug& debug ); UpdateResult updateObjects(const char *ns, const BSONObj& updateobj, BS ONObj pattern, bool upsert, bool multi , bool logop , OpDebug& debug );
UpdateResult _updateObjects(bool god, const char *ns, const BSONObj& up dateobj, BSONObj pattern, bool upsert, bool multi , bool logop , OpDebug& d ebug ); UpdateResult _updateObjects(bool god, const char *ns, const BSONObj& up dateobj, BSONObj pattern, bool upsert, bool multi , bool logop , OpDebug& d ebug );
// If justOne is true, deletedId is set to the id of the deleted object . // If justOne is true, deletedId is set to the id of the deleted object .
 End of changes. 5 change blocks. 
17 lines changed or deleted 13 lines changed or added


 queryoptimizer.h   queryoptimizer.h 
skipping to change at line 128 skipping to change at line 128
_matcher->addOrConstraint( _orConstraint ); _matcher->addOrConstraint( _orConstraint );
_haveOrConstraint = false; _haveOrConstraint = false;
} }
QueryOp *ret = _createChild(); QueryOp *ret = _createChild();
ret->_oldMatcher = _matcher; ret->_oldMatcher = _matcher;
return ret; return ret;
} }
bool complete() const { return _complete; } bool complete() const { return _complete; }
bool error() const { return _error; } bool error() const { return _error; }
bool stopRequested() const { return _stopRequested; } bool stopRequested() const { return _stopRequested; }
string exceptionMessage() const { return _exceptionMessage; } ExceptionInfo exception() const { return _exception; }
const QueryPlan &qp() const { return *_qp; } const QueryPlan &qp() const { return *_qp; }
// To be called by QueryPlanSet::Runner only. // To be called by QueryPlanSet::Runner only.
void setQueryPlan( const QueryPlan *qp ) { _qp = qp; } void setQueryPlan( const QueryPlan *qp ) { _qp = qp; }
void setExceptionMessage( const string &exceptionMessage ) { void setException( const DBException &e ) {
_error = true; _error = true;
_exceptionMessage = exceptionMessage; _exception = e.getInfo();
} }
shared_ptr< CoveredIndexMatcher > matcher() const { return _matcher ; } shared_ptr< CoveredIndexMatcher > matcher() const { return _matcher ; }
protected: protected:
void setComplete() { void setComplete() {
_haveOrConstraint = true; _haveOrConstraint = true;
_orConstraint = qp().simplifiedQuery( qp().indexKey(), true ); _orConstraint = qp().simplifiedQuery( qp().indexKey(), true );
_complete = true; _complete = true;
} }
void setStop() { setComplete(); _stopRequested = true; } void setStop() { setComplete(); _stopRequested = true; }
virtual void _init() = 0; virtual void _init() = 0;
virtual QueryOp *_createChild() const = 0; virtual QueryOp *_createChild() const = 0;
virtual bool alwaysUseRecord() const { return false; } virtual bool alwaysUseRecord() const { return false; }
private: private:
bool _complete; bool _complete;
bool _stopRequested; bool _stopRequested;
string _exceptionMessage; ExceptionInfo _exception;
const QueryPlan *_qp; const QueryPlan *_qp;
bool _error; bool _error;
shared_ptr< CoveredIndexMatcher > _matcher; shared_ptr< CoveredIndexMatcher > _matcher;
shared_ptr< CoveredIndexMatcher > _oldMatcher; shared_ptr< CoveredIndexMatcher > _oldMatcher;
bool _haveOrConstraint; bool _haveOrConstraint;
BSONObj _orConstraint; BSONObj _orConstraint;
}; };
// Set of candidate query plans for a particular query. Used for runni ng // Set of candidate query plans for a particular query. Used for runni ng
// a QueryOp on these plans. // a QueryOp on these plans.
skipping to change at line 178 skipping to change at line 178
typedef boost::shared_ptr< QueryPlan > PlanPtr; typedef boost::shared_ptr< QueryPlan > PlanPtr;
typedef vector< PlanPtr > PlanSet; typedef vector< PlanPtr > PlanSet;
QueryPlanSet( const char *ns, QueryPlanSet( const char *ns,
auto_ptr< FieldRangeSet > frs, auto_ptr< FieldRangeSet > frs,
const BSONObj &originalQuery, const BSONObj &originalQuery,
const BSONObj &order, const BSONObj &order,
const BSONElement *hint = 0, const BSONElement *hint = 0,
bool honorRecordedPlan = true, bool honorRecordedPlan = true,
const BSONObj &min = BSONObj(), const BSONObj &min = BSONObj(),
const BSONObj &max = BSONObj() ); const BSONObj &max = BSONObj(),
bool bestGuessOnly = false );
int nPlans() const { return plans_.size(); } int nPlans() const { return plans_.size(); }
shared_ptr< QueryOp > runOp( QueryOp &op ); shared_ptr< QueryOp > runOp( QueryOp &op );
template< class T > template< class T >
shared_ptr< T > runOp( T &op ) { shared_ptr< T > runOp( T &op ) {
return dynamic_pointer_cast< T >( runOp( static_cast< QueryOp& >( op ) ) ); return dynamic_pointer_cast< T >( runOp( static_cast< QueryOp& >( op ) ) );
} }
BSONObj explain() const; BSONObj explain() const;
bool usingPrerecordedPlan() const { return usingPrerecordedPlan_; } bool usingPrerecordedPlan() const { return usingPrerecordedPlan_; }
PlanPtr getBestGuess() const; PlanPtr getBestGuess() const;
void setBestGuessOnly() { _bestGuessOnly = true; }
//for testing //for testing
const FieldRangeSet &fbs() const { return *fbs_; } const FieldRangeSet &fbs() const { return *fbs_; }
private: private:
void addOtherPlans( bool checkFirst ); void addOtherPlans( bool checkFirst );
void addPlan( PlanPtr plan, bool checkFirst ) { void addPlan( PlanPtr plan, bool checkFirst ) {
if ( checkFirst && plan->indexKey().woCompare( plans_[ 0 ]->ind exKey() ) == 0 ) if ( checkFirst && plan->indexKey().woCompare( plans_[ 0 ]->ind exKey() ) == 0 )
return; return;
plans_.push_back( plan ); plans_.push_back( plan );
} }
void init(); void init();
skipping to change at line 255 skipping to change at line 255
// subsequent $or queries, even though there may be a significant aggre gate // subsequent $or queries, even though there may be a significant aggre gate
// $nor component that would not be represented in QueryPattern. // $nor component that would not be represented in QueryPattern.
class MultiPlanScanner { class MultiPlanScanner {
public: public:
MultiPlanScanner( const char *ns, MultiPlanScanner( const char *ns,
const BSONObj &query, const BSONObj &query,
const BSONObj &order, const BSONObj &order,
const BSONElement *hint = 0, const BSONElement *hint = 0,
bool honorRecordedPlan = true, bool honorRecordedPlan = true,
const BSONObj &min = BSONObj(), const BSONObj &min = BSONObj(),
const BSONObj &max = BSONObj() ); const BSONObj &max = BSONObj(),
bool bestGuessOnly = false );
shared_ptr< QueryOp > runOp( QueryOp &op ); shared_ptr< QueryOp > runOp( QueryOp &op );
template< class T > template< class T >
shared_ptr< T > runOp( T &op ) { shared_ptr< T > runOp( T &op ) {
return dynamic_pointer_cast< T >( runOp( static_cast< QueryOp& >( op ) ) ); return dynamic_pointer_cast< T >( runOp( static_cast< QueryOp& >( op ) ) );
} }
shared_ptr< QueryOp > runOpOnce( QueryOp &op ); shared_ptr< QueryOp > runOpOnce( QueryOp &op );
template< class T > template< class T >
shared_ptr< T > runOpOnce( T &op ) { shared_ptr< T > runOpOnce( T &op ) {
return dynamic_pointer_cast< T >( runOpOnce( static_cast< Query Op& >( op ) ) ); return dynamic_pointer_cast< T >( runOpOnce( static_cast< Query Op& >( op ) ) );
} }
skipping to change at line 299 skipping to change at line 300
class MultiCursor : public Cursor { class MultiCursor : public Cursor {
public: public:
class CursorOp : public QueryOp { class CursorOp : public QueryOp {
public: public:
CursorOp() {} CursorOp() {}
CursorOp( const QueryOp &other ) : QueryOp( other ) {} CursorOp( const QueryOp &other ) : QueryOp( other ) {}
virtual shared_ptr< Cursor > newCursor() const = 0; virtual shared_ptr< Cursor > newCursor() const = 0;
}; };
// takes ownership of 'op' // takes ownership of 'op'
MultiCursor( const char *ns, const BSONObj &pattern, const BSONObj &order, shared_ptr< CursorOp > op = shared_ptr< CursorOp >() ) MultiCursor( const char *ns, const BSONObj &pattern, const BSONObj &order, shared_ptr< CursorOp > op = shared_ptr< CursorOp >() )
: _mps( new MultiPlanScanner( ns, pattern, order ) ) { : _mps( new MultiPlanScanner( ns, pattern, order, 0, true, BSONObj( ), BSONObj(), !op.get() ) ) {
if ( op.get() ) { if ( op.get() ) {
_op = op; _op = op;
} else { } else {
_op.reset( new NoOp() ); _op.reset( new NoOp() );
_mps->setBestGuessOnly();
} }
if ( _mps->mayRunMore() ) { if ( _mps->mayRunMore() ) {
nextClause(); nextClause();
if ( !ok() ) { if ( !ok() ) {
advance(); advance();
} }
} else { } else {
_c.reset( new BasicCursor( DiskLoc() ) ); _c.reset( new BasicCursor( DiskLoc() ) );
} }
} }
skipping to change at line 351 skipping to change at line 351
_c->checkLocation(); _c->checkLocation();
} }
virtual bool supportGetMore() { return true; } virtual bool supportGetMore() { return true; }
// 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
shared_ptr< Cursor > sub_c() const { return _c; }
private: private:
class NoOp : public CursorOp { class NoOp : public CursorOp {
public: public:
NoOp() {} NoOp() {}
NoOp( const QueryOp &other ) : CursorOp( other ) {} NoOp( const QueryOp &other ) : CursorOp( other ) {}
virtual void _init() { setComplete(); } virtual void _init() { setComplete(); }
virtual void next() {} virtual void next() {}
virtual bool mayRecordPlan() const { return false; } virtual bool mayRecordPlan() const { return false; }
virtual QueryOp *_createChild() const { return new NoOp(); } virtual QueryOp *_createChild() const { return new NoOp(); }
virtual shared_ptr< Cursor > newCursor() const { return qp().ne wCursor(); } virtual shared_ptr< Cursor > newCursor() const { return qp().ne wCursor(); }
private:
shared_ptr< CoveredIndexMatcher > _matcher;
shared_ptr< CoveredIndexMatcher > _oldMatcher;
}; };
void nextClause() { void nextClause() {
shared_ptr< CursorOp > best = _mps->runOpOnce( *_op ); shared_ptr< CursorOp > best = _mps->runOpOnce( *_op );
massert( 10401 , best->exceptionMessage(), best->complete() ); if ( ! best->complete() )
throw MsgAssertionException( best->exception() );
_c = best->newCursor(); _c = best->newCursor();
_matcher = best->matcher(); _matcher = best->matcher();
_op = best; _op = best;
} }
shared_ptr< CursorOp > _op; shared_ptr< CursorOp > _op;
shared_ptr< Cursor > _c; shared_ptr< Cursor > _c;
auto_ptr< MultiPlanScanner > _mps; auto_ptr< MultiPlanScanner > _mps;
shared_ptr< CoveredIndexMatcher > _matcher; shared_ptr< CoveredIndexMatcher > _matcher;
}; };
// NOTE min, max, and keyPattern will be updated to be consistent with the selected index. // NOTE min, max, and keyPattern will be updated to be consistent with the selected index.
IndexDetails *indexDetailsForRange( const char *ns, string &errmsg, BSO NObj &min, BSONObj &max, BSONObj &keyPattern ); IndexDetails *indexDetailsForRange( const char *ns, string &errmsg, BSO NObj &min, BSONObj &max, BSONObj &keyPattern );
inline bool isSimpleIdQuery( const BSONObj& query ){ inline bool isSimpleIdQuery( const BSONObj& query ){
return BSONObjIterator i(query);
strcmp( query.firstElement().fieldName() , "_id" ) == 0 && if( !i.more() ) return false;
query.nFields() == 1 && BSONElement e = i.next();
query.firstElement().isSimpleType(); if( i.more() ) return false;
if( strcmp("_id", e.fieldName()) != 0 ) return false;
return e.isSimpleType(); // e.g. not something like { _id : { $gt :
...
} }
// matcher() will always work on the returned cursor // matcher() will always work on the returned cursor
inline shared_ptr< Cursor > bestGuessCursor( const char *ns, const BSON Obj &query, const BSONObj &sort ) { inline shared_ptr< Cursor > bestGuessCursor( const char *ns, const BSON Obj &query, const BSONObj &sort ) {
if( !query.getField( "$or" ).eoo() ) { if( !query.getField( "$or" ).eoo() ) {
return shared_ptr< Cursor >( new MultiCursor( ns, query, sort ) ); return shared_ptr< Cursor >( new MultiCursor( ns, query, sort ) );
} else { } else {
auto_ptr< FieldRangeSet > frs( new FieldRangeSet( ns, query ) ) ; auto_ptr< FieldRangeSet > frs( new FieldRangeSet( ns, query ) ) ;
shared_ptr< Cursor > ret = QueryPlanSet( ns, frs, query, sort ) .getBestGuess()->newCursor(); shared_ptr< Cursor > ret = QueryPlanSet( ns, frs, query, sort ) .getBestGuess()->newCursor();
if ( !query.isEmpty() ) { if ( !query.isEmpty() ) {
 End of changes. 13 change blocks. 
17 lines changed or deleted 20 lines changed or added


 queryutil.h   queryutil.h 
skipping to change at line 70 skipping to change at line 70
BSONElement max() const { assert( !empty() ); return _intervals[ _i ntervals.size() - 1 ]._upper._bound; } BSONElement max() const { assert( !empty() ); return _intervals[ _i ntervals.size() - 1 ]._upper._bound; }
bool minInclusive() const { assert( !empty() ); return _intervals[ 0 ]._lower._inclusive; } bool minInclusive() const { assert( !empty() ); return _intervals[ 0 ]._lower._inclusive; }
bool maxInclusive() const { assert( !empty() ); return _intervals[ _intervals.size() - 1 ]._upper._inclusive; } bool maxInclusive() const { assert( !empty() ); return _intervals[ _intervals.size() - 1 ]._upper._inclusive; }
bool equality() const { bool equality() const {
return return
!empty() && !empty() &&
min().woCompare( max(), false ) == 0 && min().woCompare( max(), false ) == 0 &&
maxInclusive() && maxInclusive() &&
minInclusive(); minInclusive();
} }
bool inQuery() const {
if ( equality() ) {
return true;
}
for( vector< FieldInterval >::const_iterator i = _intervals.beg
in(); i != _intervals.end(); ++i ) {
if ( !i->equality() ) {
return false;
}
}
return true;
}
bool nontrivial() const { bool nontrivial() const {
return return
! empty() && ! empty() &&
( minKey.firstElement().woCompare( min(), false ) != 0 || ( minKey.firstElement().woCompare( min(), false ) != 0 ||
maxKey.firstElement().woCompare( max(), false ) != 0 ); maxKey.firstElement().woCompare( max(), false ) != 0 );
} }
bool empty() const { return _intervals.empty(); } bool empty() const { return _intervals.empty(); }
const vector< FieldInterval > &intervals() const { return _i ntervals; } const vector< FieldInterval > &intervals() const { return _i ntervals; }
string getSpecial() const { return _special; } string getSpecial() const { return _special; }
void setExclusiveBounds() { void setExclusiveBounds() {
 End of changes. 1 change blocks. 
0 lines changed or deleted 12 lines changed or added


 ramlog.h   ramlog.h 
skipping to change at line 38 skipping to change at line 38
}; };
char lines[N][C]; char lines[N][C];
unsigned h, n; unsigned h, n;
public: public:
RamLog() { RamLog() {
h = 0; n = 0; h = 0; n = 0;
for( int i = 0; i < N; i++ ) for( int i = 0; i < N; i++ )
lines[i][C-1] = 0; lines[i][C-1] = 0;
} }
virtual void write(const string& str) { virtual void write(LogLevel ll, const string& str) {
char *p = lines[(h+n)%N]; char *p = lines[(h+n)%N];
if( str.size() < C ) if( str.size() < C )
strcpy(p, str.c_str()); strcpy(p, str.c_str());
else else
memcpy(p, str.c_str(), C-1); memcpy(p, str.c_str(), C-1);
if( n < N ) n++; if( n < N ) n++;
else h = (h+1) % N; else h = (h+1) % N;
} }
vector<const char *> get() const { vector<const char *> get() const {
vector<const char *> v; vector<const char *> v;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 repl.h   repl.h 
skipping to change at line 80 skipping to change at line 80
}; };
extern ReplSettings replSettings; extern ReplSettings replSettings;
bool cloneFrom(const char *masterHost, string& errmsg, const string& fr omdb, bool logForReplication, bool cloneFrom(const char *masterHost, string& errmsg, const string& fr omdb, bool logForReplication,
bool slaveOk, bool useReplAuth, bool snap shot); bool slaveOk, bool useReplAuth, bool snap shot);
/* A replication exception */ /* A replication exception */
class SyncException : public DBException { class SyncException : public DBException {
public: public:
virtual const char* what() const throw() { return "sync exception"; SyncException() : DBException( "sync exception" , 10001 ){}
}
virtual int getCode() const { return 10001; }
}; };
/* A Source is a source from which we can pull (replicate) data. /* A Source is a source from which we can pull (replicate) data.
stored in collection local.sources. stored in collection local.sources.
Can be a group of things to replicate for several databases. Can be a group of things to replicate for several databases.
{ host: ..., source: ..., only: ..., syncedTo: ..., localLogTs: . .., dbsNextPass: { ... }, incompleteCloneDbs: { ... } } { host: ..., source: ..., only: ..., syncedTo: ..., localLogTs: . .., dbsNextPass: { ... }, incompleteCloneDbs: { ... } }
'source' defaults to 'main'; support for multiple source names is 'source' defaults to 'main'; support for multiple source names is
 End of changes. 1 change blocks. 
3 lines changed or deleted 1 lines changed or added


 request.h   request.h 
skipping to change at line 86 skipping to change at line 86
void reply( Message & response , const string& fromServer ); void reply( Message & response , const string& fromServer );
Message& m() { return _m; } Message& m() { return _m; }
DbMessage& d() { return _d; } DbMessage& d() { return _d; }
AbstractMessagingPort* p() const { return _p; } AbstractMessagingPort* p() const { return _p; }
void process( int attempt = 0 ); void process( int attempt = 0 );
void gotInsert(); void gotInsert();
private:
void reset( bool reload=false ); void reset( bool reload=false );
private:
Message& _m; Message& _m;
DbMessage _d; DbMessage _d;
AbstractMessagingPort* _p; AbstractMessagingPort* _p;
MSGID _id; MSGID _id;
DBConfigPtr _config; DBConfigPtr _config;
ChunkManagerPtr _chunkManager; ChunkManagerPtr _chunkManager;
int _clientId; int _clientId;
ClientInfo * _clientInfo; ClientInfo * _clientInfo;
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 resource.h   resource.h 
//{{NO_DEPENDENCIES}} //{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file. // Microsoft Visual C++ generated include file.
// Used by db.rc // Used by db.rc
// //
#define IDI_ICON2 102 #define IDI_ICON2 102
// Next default values for new objects // Next default values for new objects
// //
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103 #define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101 #define _APS_NEXT_SYMED_VALUE 101
#endif #endif
#endif #endif
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 rs.h   rs.h 
skipping to change at line 26 skipping to change at line 26
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "../../util/concurrency/list.h" #include "../../util/concurrency/list.h"
#include "../../util/concurrency/value.h" #include "../../util/concurrency/value.h"
#include "../../util/concurrency/msg.h" #include "../../util/concurrency/msg.h"
#include "../../util/hostandport.h" #include "../../util/hostandport.h"
#include "../commands.h" #include "../commands.h"
#include "rs_exception.h"
#include "rs_optime.h" #include "rs_optime.h"
#include "rsmember.h" #include "rsmember.h"
#include "rs_config.h" #include "rs_config.h"
namespace mongo { namespace mongo {
struct Target; struct Target;
class ReplSetImpl; class ReplSetImpl;
extern bool replSet; // true if using repl sets extern bool replSet; // true if using repl sets
extern class ReplSet *theReplSet; // null until initialized extern class ReplSet *theReplSet; // null until initialized
skipping to change at line 60 skipping to change at line 61
void summarizeAsHtml(stringstream& s) const; void summarizeAsHtml(stringstream& s) const;
friend class ReplSetImpl; friend class ReplSetImpl;
private: private:
const ReplSetConfig::MemberCfg *_config; /* todo: when this changes ??? */ const ReplSetConfig::MemberCfg *_config; /* todo: when this changes ??? */
HostAndPort _h; HostAndPort _h;
HeartbeatInfo _hbinfo; HeartbeatInfo _hbinfo;
}; };
class Manager : public task::Server { class Manager : public task::Server {
bool got(const any&);
ReplSetImpl *rs; ReplSetImpl *rs;
bool busyWithElectSelf;
int _primary; int _primary;
const Member* findOtherPrimary(); const Member* findOtherPrimary();
void noteARemoteIsPrimary(const Member *); void noteARemoteIsPrimary(const Member *);
virtual void starting();
public: public:
Manager(ReplSetImpl *rs); Manager(ReplSetImpl *rs);
void msgReceivedNewConfig(BSONObj) { assert(false); } void msgReceivedNewConfig(BSONObj) { assert(false); }
void msgCheckNewState(); void msgCheckNewState();
}; };
struct Target;
class Consensus { class Consensus {
ReplSetImpl &rs; ReplSetImpl &rs;
struct LastYea { struct LastYea {
LastYea() : when(0), who(0xffffffff) { } LastYea() : when(0), who(0xffffffff) { }
time_t when; time_t when;
unsigned who; unsigned who;
}; };
Atomic<LastYea> ly; Atomic<LastYea> ly;
unsigned yea(unsigned memberId); // throws VoteException unsigned yea(unsigned memberId); // throws VoteException
void _electSelf(); void _electSelf();
bool weAreFreshest(bool& allUp); bool weAreFreshest(bool& allUp, int& nTies);
bool sleptLast; // slept last elect() pass
public: public:
Consensus(ReplSetImpl *t) : rs(*t) { } Consensus(ReplSetImpl *t) : rs(*t) {
sleptLast = false;
}
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);
}; };
/** most operations on a ReplSet object should be done while locked. */ /** most operations on a ReplSet object should be done while locked. */
class RSBase : boost::noncopyable { class RSBase : boost::noncopyable {
private: private:
mutex m; mutex m;
int _locked; int _locked;
ThreadLocalValue<bool> _lockedByMe;
protected: protected:
RSBase() : m("RSBase"), _locked(0) { } RSBase() : m("RSBase"), _locked(0) { }
class lock : scoped_lock { class lock : scoped_lock {
RSBase& _b; RSBase& _b;
public: public:
lock(RSBase* b) : scoped_lock(b->m), _b(*b) { lock(RSBase* b) : scoped_lock(b->m), _b(*b) {
DEV assert(b->_locked == 0); DEV assert(_b._locked == 0);
b->_locked++; _b._locked++;
_b._lockedByMe.set(true);
cout << "RSLOCKED" << endl;
} }
~lock() { ~lock() {
cout << "RSUNLOCKED" << endl;
assert( _b._lockedByMe.get() );
DEV assert(_b._locked == 1); DEV assert(_b._locked == 1);
_b._lockedByMe.set(false);
_b._locked--; _b._locked--;
} }
}; };
public:
/* for asserts */
bool locked() const { return _locked != 0; } bool locked() const { return _locked != 0; }
/* if true, is locked, and was locked by this thread. note if false
, it could be in the lock or not for another
just for asserts & such so we can make the contracts clear on wh
o locks what when.
we don't use these locks that frequently, so the little bit of o
verhead is fine.
*/
bool lockedByMe() { return _lockedByMe.get(); }
}; };
/* 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 : RSBase { class ReplSetImpl : 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 {
skipping to change at line 133 skipping to change at line 154
static StartupStatus startupStatus; static StartupStatus startupStatus;
static string startupStatusMsg; static string startupStatusMsg;
static string stateAsStr(MemberState state); static string stateAsStr(MemberState state);
static string stateAsHtml(MemberState state); static string stateAsHtml(MemberState state);
/* todo thread */ /* todo thread */
void msgUpdateHBInfo(HeartbeatInfo); void msgUpdateHBInfo(HeartbeatInfo);
bool isPrimary() const { return _myState == PRIMARY; } bool isPrimary() const { return _myState == PRIMARY; }
bool isSecondary() const { return _myState == SECONDARY; } bool isSecondary() const { return _myState == SECONDARY; }
//bool initiated() const { return curOpTime.initiated(); }
OpTime lastOpTimeWritten;
long long h;
private:
unsigned _selfId; // stored redundantly we hit this a lot
private: private:
Consensus elect; Consensus elect;
bool ok() const { return _myState != FATAL; } bool ok() const { return _myState != FATAL; }
void relinquish(); void relinquish();
void assumePrimary(); void assumePrimary();
void loadLastOpTimeWritten();
protected: protected:
void _fillIsMaster(BSONObjBuilder&); void _fillIsMaster(BSONObjBuilder&);
const ReplSetConfig& config() { return *_cfg; } const ReplSetConfig& config() { return *_cfg; }
string name() const { return _name; } /* @return replica set's logi cal name */ string name() const { return _name; } /* @return replica set's logi cal name */
MemberState state() const { return _myState; } MemberState state() const { return _myState; }
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
skipping to change at line 183 skipping to change at line 212
list<HostAndPort> memberHostnames() const; list<HostAndPort> memberHostnames() const;
const Member* currentPrimary() const { return _currentPrimary; } const Member* currentPrimary() const { return _currentPrimary; }
const ReplSetConfig::MemberCfg& myConfig() const { return _self->co nfig(); } const ReplSetConfig::MemberCfg& myConfig() const { return _self->co nfig(); }
private: private:
const Member *_currentPrimary; const Member *_currentPrimary;
Member *_self; Member *_self;
List1<Member> _members; /* all members of the set EXCEPT self. */ List1<Member> _members; /* all members of the set EXCEPT self. */
public: public:
unsigned selfId() const { return _selfId; }
shared_ptr<Manager> mgr; shared_ptr<Manager> mgr;
private: private:
Member* head() const { return _members.head(); } Member* head() const { return _members.head(); }
Member* findById(unsigned id) const; Member* findById(unsigned id) const;
void getTargets(list<Target>&); void _getTargets(list<Target>&, int &configVersion);
void getTargets(list<Target>&, int &configVersion);
void startThreads(); void startThreads();
friend class FeedbackThread; friend class FeedbackThread;
friend class CmdReplSetElect; friend class CmdReplSetElect;
friend class Member; friend class Member;
friend class Manager; friend class Manager;
friend class Consensus; friend class Consensus;
}; };
class ReplSet : public ReplSetImpl { class ReplSet : public ReplSetImpl {
public: public:
 End of changes. 18 change blocks. 
6 lines changed or deleted 40 lines changed or added


 rs_config.h   rs_config.h 
skipping to change at line 28 skipping to change at line 28
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "../../util/hostandport.h" #include "../../util/hostandport.h"
#include "health.h" #include "health.h"
namespace mongo { namespace mongo {
/* singleton config object is stored here */
const string rsConfigNs = "local.system.replset"; const string rsConfigNs = "local.system.replset";
class ReplSetConfig { class ReplSetConfig {
enum { EMPTYCONFIG = -2 }; enum { EMPTYCONFIG = -2 };
public: public:
/* if something is misconfigured, throws an exception. /* if something is misconfigured, throws an exception.
if couldn't be queried or is just blank, ok() will be false. if couldn't be queried or is just blank, ok() will be false.
*/ */
ReplSetConfig(const HostAndPort& h); ReplSetConfig(const HostAndPort& h);
skipping to change at line 73 skipping to change at line 74
/** @return true if could connect, and there is no cfg object there at all */ /** @return true if could connect, and there is no cfg object there at all */
bool empty() const { return version == EMPTYCONFIG; } bool empty() const { return version == EMPTYCONFIG; }
string toString() const { return asBson().toString(); } string toString() const { return asBson().toString(); }
/** validate the settings. does not call check() on each member, yo u have to do that separately. */ /** validate the settings. does not call check() on each member, yo u have to do that separately. */
void check() const; void check() const;
static void receivedNewConfig(BSONObj); static void receivedNewConfig(BSONObj);
void saveConfigLocally(); // to local db void saveConfigLocally(BSONObj comment); // to local db
string saveConfigEverywhere(); // returns textual info on what happ ened string saveConfigEverywhere(); // returns textual info on what happ ened
BSONObj asBson() const; BSONObj asBson() const;
private: private:
bool _ok; bool _ok;
void from(BSONObj); void from(BSONObj);
void clear(); void clear();
}; };
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 rs_optime.h   rs_optime.h 
skipping to change at line 21 skipping to change at line 21
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Lice nse * You should have received a copy of the GNU Affero General Public Lice nse
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "../../util/optime.h"
namespace mongo { namespace mongo {
const string rsoplog = "local.oplog.rs"; const string rsoplog = "local.oplog.rs";
struct RSOpTime { /*
class RSOpTime : public OpTime {
public:
bool initiated() const { return getSecs() != 0; }
};*/
/*struct RSOpTime {
unsigned long long ord; unsigned long long ord;
RSOpTime() : ord(0) { } RSOpTime() : ord(0) { }
bool initiated() const { return ord > 0; } bool initiated() const { return ord > 0; }
void initiate() { void initiate() {
assert( !initiated() ); assert( !initiated() );
ord = 1000000; ord = 1000000;
} }
ReplTime inc() { ReplTime inc() {
DEV assertInWriteLock(); DEV assertInWriteLock();
return ++ord; return ++ord;
} }
string toString() const { return str::stream() << ord; } string toString() const { return str::stream() << ord; }
/* query the oplog and set the highest value herein. acquires a db read lock. throws. */ // query the oplog and set the highest value herein. acquires a db read lock. throws.
void load(); void load();
}; };
extern RSOpTime rsOpTime; extern RSOpTime rsOpTime;*/
} }
 End of changes. 4 change blocks. 
3 lines changed or deleted 11 lines changed or added


 rsmember.h   rsmember.h 
skipping to change at line 48 skipping to change at line 48
public: public:
HeartbeatInfo() : _id(0xffffffff) { } HeartbeatInfo() : _id(0xffffffff) { }
HeartbeatInfo(unsigned id); HeartbeatInfo(unsigned id);
bool up() const { return health > 0; } bool up() const { return health > 0; }
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;
bool changed(const HeartbeatInfo& old) const; bool changed(const HeartbeatInfo& old) const;
}; };
inline HeartbeatInfo::HeartbeatInfo(unsigned id) : _id(id) { inline HeartbeatInfo::HeartbeatInfo(unsigned id) : _id(id) {
hbstate = UNKNOWN; hbstate = UNKNOWN;
health = -1.0; health = -1.0;
lastHeartbeat = upSince = 0; lastHeartbeat = upSince = 0;
} }
inline bool HeartbeatInfo::changed(const HeartbeatInfo& old) const { inline bool HeartbeatInfo::changed(const HeartbeatInfo& old) const {
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 shard.h   shard.h 
skipping to change at line 136 skipping to change at line 136
static void getAllShards( vector<Shard>& all ); static void getAllShards( vector<Shard>& all );
/** /**
* picks a Shard for more load * picks a Shard for more load
*/ */
static Shard pick(); static Shard pick();
static void reloadShardInfo(); static void reloadShardInfo();
static void removeShard( const string& name );
static bool isMember( const string& addr );
static Shard EMPTY; static Shard EMPTY;
private: private:
string _name; string _name;
string _addr; string _addr;
long long _maxSize; // in MBytes, 0 is unlimited long long _maxSize; // in MBytes, 0 is unlimited
bool _isDraining; // shard is currently being removed bool _isDraining; // shard is currently being removed
}; };
class ShardStatus { class ShardStatus {
skipping to change at line 209 skipping to change at line 213
DBClientBase* get(){ DBClientBase* get(){
assert( _conn ); assert( _conn );
return _conn; return _conn;
} }
string getHost() const { string getHost() const {
return _addr; return _addr;
} }
bool setVersion() const {
return _setVersion;
}
static void sync(); static void sync();
private: private:
void _init(); void _init();
string _addr; string _addr;
string _ns; string _ns;
DBClientBase* _conn; DBClientBase* _conn;
bool _setVersion;
}; };
} }
 End of changes. 3 change blocks. 
0 lines changed or deleted 9 lines changed or added


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


 sock.h   sock.h 
skipping to change at line 27 skipping to change at line 27
#pragma once #pragma once
#include "../pch.h" #include "../pch.h"
#include <stdio.h> #include <stdio.h>
#include <sstream> #include <sstream>
#include "goodies.h" #include "goodies.h"
#include "../db/jsobj.h" #include "../db/jsobj.h"
#define SOCK_FAMILY_UNKNOWN_ERROR 13078
namespace mongo { namespace mongo {
const int SOCK_FAMILY_UNKNOWN_ERROR=13078;
#if defined(_WIN32) #if defined(_WIN32)
typedef short sa_family_t; typedef short sa_family_t;
typedef int socklen_t; typedef int socklen_t;
inline int getLastError() { inline int getLastError() {
return WSAGetLastError(); return WSAGetLastError();
} }
inline const char* gai_strerror(int code) { inline const char* gai_strerror(int code) {
return ::gai_strerrorA(code); return ::gai_strerrorA(code);
} }
skipping to change at line 70 skipping to change at line 70
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <errno.h> #include <errno.h>
#include <netdb.h> #include <netdb.h>
#ifdef __openbsd__
# include <sys/uio.h>
#endif
#ifndef AI_ADDRCONFIG
# define AI_ADDRCONFIG 0
#endif
namespace mongo { namespace mongo {
inline void closesocket(int s) { inline void closesocket(int s) {
close(s); close(s);
} }
const int INVALID_SOCKET = -1; const int INVALID_SOCKET = -1;
typedef int SOCKET; typedef int SOCKET;
inline void disableNagle(int sock) { inline void disableNagle(int sock) {
skipping to change at line 114 skipping to change at line 121
#endif #endif
inline string makeUnixSockPath(int port){ inline string makeUnixSockPath(int port){
return "/tmp/mongodb-" + BSONObjBuilder::numStr(port) + ".sock"; return "/tmp/mongodb-" + BSONObjBuilder::numStr(port) + ".sock";
} }
inline void setSockTimeouts(int sock, int secs) { inline void setSockTimeouts(int sock, int secs) {
struct timeval tv; struct timeval tv;
tv.tv_sec = secs; tv.tv_sec = secs;
tv.tv_usec = 0; tv.tv_usec = 0;
massert( 13083, "unable to set SO_RCVTIMEO", bool report = logLevel > 3; // solaris doesn't provide these
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, siz DEV report = true;
eof(tv) ) == 0 ); bool ok = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, s
massert( 13084, "unable to set SO_SNDTIMEO", izeof(tv) ) == 0;
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *) &tv, siz if( report && !ok ) log() << "unabled to set SO_RCVTIMEO" << endl;
eof(tv) ) == 0 ); ok = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *) &tv, sizeof
(tv) ) == 0;
DEV if( report && !ok ) log() << "unabled to set SO_RCVTIMEO" << en
dl;
} }
// If an ip address is passed in, just return that. If a hostname is p assed // If an ip address is passed in, just return that. If a hostname is p assed
// in, look up its ip and return that. Returns "" on failure. // in, look up its ip and return that. Returns "" on failure.
string hostbyname(const char *hostname); string hostbyname(const char *hostname);
void enableIPv6(bool state=true); void enableIPv6(bool state=true);
bool IPv6Enabled(); bool IPv6Enabled();
struct SockAddr { struct SockAddr {
skipping to change at line 284 skipping to change at line 293
} }
static ListeningSockets* get(); static ListeningSockets* get();
private: private:
mongo::mutex _mutex; mongo::mutex _mutex;
set<int>* _sockets; set<int>* _sockets;
static ListeningSockets* _instance; static ListeningSockets* _instance;
}; };
#undef SOCK_FAMILY_UNKNOWN_ERROR
} // namespace mongo } // namespace mongo
 End of changes. 5 change blocks. 
10 lines changed or deleted 18 lines changed or added


 str.h   str.h 
skipping to change at line 31 skipping to change at line 31
(1) are not database specific, rather, true utilities (1) are not database specific, rather, true utilities
(2) are cross platform (2) are cross platform
(3) may require boost headers, but not libs (3) may require boost headers, but not libs
(4) are clean and easy to use in any c++ project without pulling in lots of other stuff (4) are clean and easy to use in any c++ project without pulling in lots of other stuff
Note: within this module, we use int for all offsets -- there are no uns igned offsets Note: within this module, we use int for all offsets -- there are no uns igned offsets
and no size_t's. If you need 3 gigabyte long strings, don't use this mo dule. and no size_t's. If you need 3 gigabyte long strings, don't use this mo dule.
*/ */
#include <string> #include <string>
#include <sstream>
namespace mongoutils { namespace mongoutils {
namespace str { namespace str {
using namespace std; using namespace std;
/** the idea here is to make one liners easy. e.g.: /** the idea here is to make one liners easy. e.g.:
return str::stream() << 1 << ' ' << 2; return str::stream() << 1 << ' ' << 2;
skipping to change at line 60 skipping to change at line 61
template<class T> template<class T>
stream& operator<<(const T& v) { stream& operator<<(const T& v) {
ss << v; ss << v;
return *this; return *this;
} }
operator std::string () const { return ss.str(); } operator std::string () const { return ss.str(); }
}; };
inline bool startsWith(const char *str, const char *prefix) { inline bool startsWith(const char *str, const char *prefix) {
size_t l = strlen(prefix); const char *s = str;
if ( strlen(str) < l ) return false; const char *p = prefix;
return strncmp(str, prefix, l) == 0; while( *p ) {
if( *p != *s ) return false;
p++; s++;
}
return true;
} }
inline bool startsWith(string s, string p) { return startsWith(s.c_ str(), p.c_str()); } inline bool startsWith(string s, string p) { return startsWith(s.c_ str(), p.c_str()); }
inline bool endsWith(string s, string p) { inline bool endsWith(string s, string p) {
int l = p.size(); int l = p.size();
int x = s.size(); int x = s.size();
if( x < l ) return false; if( x < l ) return false;
return strncmp(s.c_str()+x-l, p.c_str(), l) == 0; return strncmp(s.c_str()+x-l, p.c_str(), l) == 0;
} }
 End of changes. 2 change blocks. 
3 lines changed or deleted 8 lines changed or added


 strategy.h   strategy.h 
skipping to change at line 47 skipping to change at line 47
void insert( const Shard& shard , const char * ns , const BSONObj& obj ); void insert( const Shard& shard , const char * ns , const BSONObj& obj );
}; };
extern Strategy * SINGLE; extern Strategy * SINGLE;
extern Strategy * SHARDED; extern Strategy * SHARDED;
bool setShardVersion( DBClientBase & conn , const string& ns , ShardChu nkVersion version , bool authoritative , BSONObj& result ); bool setShardVersion( DBClientBase & conn , const string& ns , ShardChu nkVersion version , bool authoritative , BSONObj& result );
bool lockNamespaceOnServer( const Shard& shard , const string& ns );
bool lockNamespaceOnServer( DBClientBase& conn , const string& ns );
} }
 End of changes. 1 change blocks. 
3 lines changed or deleted 0 lines changed or added


 syncclusterconnection.h   syncclusterconnection.h 
skipping to change at line 86 skipping to change at line 86
virtual bool call( Message &toSend, Message &response, bool assertO k ); virtual bool call( Message &toSend, Message &response, bool assertO k );
virtual void say( Message &toSend ); virtual void say( Message &toSend );
virtual void sayPiggyBack( Message &toSend ); virtual void sayPiggyBack( Message &toSend );
virtual void killCursor( long long cursorID ); virtual void killCursor( long long cursorID );
virtual string getServerAddress() const { return _address; } virtual string getServerAddress() const { return _address; }
virtual bool isFailed() const { return false; } virtual bool isFailed() const { return false; }
virtual string toString() { return _toString(); } virtual string toString() { return _toString(); }
virtual BSONObj getLastErrorDetailed();
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 );
string _address; string _address;
vector<DBClientConnection*> _conns; vector<DBClientConnection*> _conns;
map<string,int> _lockTypes; map<string,int> _lockTypes;
mongo::mutex _mutex; mongo::mutex _mutex;
BSONObj _lastError;
}; };
}; };
#include "undef_macros.h" #include "undef_macros.h"
 End of changes. 2 change blocks. 
0 lines changed or deleted 4 lines changed or added


 task.h   task.h 
skipping to change at line 33 skipping to change at line 33
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 ng and the caller. that way a shared_ptr is kept to the task - both by the task while runni ng and the caller. that way
the task object gets cleaned up once the last reference goes aw ay. 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 task here. virtual void doWork() = 0; // implement the ta
virtual string name() = 0; // name the thread sk here.
virtual string name() = 0; // name the threada
public: public:
Task(); Task();
/** for a repeating task, stop after current invocation ends. * / /** for a repeating task, stop after current invocation ends. * /
void halt(); void halt();
private: private:
shared_ptr<Task> me; shared_ptr<Task> me;
unsigned n, repeat; unsigned n, repeat;
friend void fork(shared_ptr<Task> t); friend void fork(shared_ptr<Task> t);
friend void repeat(shared_ptr<Task> t, unsigned millis); friend void repeat(shared_ptr<Task> t, unsigned millis);
 End of changes. 1 change blocks. 
2 lines changed or deleted 3 lines changed or added


 text.h   text.h 
skipping to change at line 117 skipping to change at line 117
/* like toWideString but UNICODE macro sensitive */ /* like toWideString but UNICODE macro sensitive */
# if !defined(_UNICODE) # if !defined(_UNICODE)
#error temp error #error temp error
inline std::string toNativeString(const char *s) { return s; } inline std::string toNativeString(const char *s) { return s; }
# else # else
inline std::wstring toNativeString(const char *s) { return toWideString (s); } inline std::wstring toNativeString(const char *s) { return toWideString (s); }
# endif # endif
#endif #endif
// expect that n contains a base ten number and nothing else after it
// NOTE win version hasn't been tested directly
inline long long parseLL( const char *n ) {
long long ret;
uassert( 13307, "cannot convert empty string to long long", *n != 0
);
#if !defined(_WIN32)
char *endPtr = 0;
errno = 0;
ret = strtoll( n, &endPtr, 10 );
uassert( 13305, "could not convert string to long long", *endPtr ==
0 && errno == 0 );
#elif _MSC_VER>=1600 // 1600 is VS2k10 1500 is VS2k8
size_t endLen = 0;
try {
ret = stoll( n, &endLen, 10 );
} catch ( ... ) {
endLen = 0;
}
uassert( 13306, "could not convert string to long long", endLen !=
0 && n[ endLen ] == 0 );
#else // stoll() wasn't introduced until VS 2010.
char* endPtr = 0;
ret = _strtoi64( n, &endPtr, 10 );
uassert( 13310, "could not convert string to long long", (*endPtr =
= 0) && (ret != _I64_MAX) && (ret != _I64_MIN) );
#endif // !defined(_WIN32)
return ret;
}
} }
 End of changes. 1 change blocks. 
0 lines changed or deleted 29 lines changed or added


 update.h   update.h 
skipping to change at line 132 skipping to change at line 132
string fullName = fieldName; string fullName = fieldName;
if ( isIndexed( fullName , idxKeys ) ) if ( isIndexed( fullName , idxKeys ) )
return true; return true;
if ( strstr( fieldName , "." ) ){ if ( strstr( fieldName , "." ) ){
// check for a.0.1 // check for a.0.1
StringBuilder buf( fullName.size() + 1 ); StringBuilder buf( fullName.size() + 1 );
for ( size_t i=0; i<fullName.size(); i++ ){ for ( size_t i=0; i<fullName.size(); i++ ){
char c = fullName[i]; char c = fullName[i];
if ( c == '$' &&
i > 0 && fullName[i-1] == '.' &&
fullName[i+1] == '.' ){
i++;
continue;
}
buf << c; buf << c;
if ( c != '.' ) if ( c != '.' )
continue; continue;
if ( ! isdigit( fullName[i+1] ) ) if ( ! isdigit( fullName[i+1] ) )
continue; continue;
bool possible = true; bool possible = true;
size_t j=i+2; size_t j=i+2;
 End of changes. 1 change blocks. 
0 lines changed or deleted 8 lines changed or added


 util.h   util.h 
skipping to change at line 35 skipping to change at line 35
some generic sharding utils that can be used in mongod or mongos some generic sharding utils that can be used in mongod or mongos
*/ */
namespace mongo { namespace mongo {
/** /**
* your config info for a given shard/chunk is out of date * your config info for a given shard/chunk is out of date
*/ */
class StaleConfigException : public AssertionException { class StaleConfigException : public AssertionException {
public: public:
StaleConfigException( const string& ns , const string& raw){ StaleConfigException( const string& ns , const string& raw)
code = 9996; : AssertionException( (string)"ns: " + ns + " " + raw , 9996 ){
stringstream s;
s << "StaleConfigException ns: " << ns << " " << raw;
msg = s.str();
log(1) << msg << endl;
} }
virtual ~StaleConfigException() throw(){} virtual ~StaleConfigException() throw(){}
virtual void appendPrefix( stringstream& ss ) const { ss << "StaleC onfigException: "; }
private: private:
}; };
void checkShardVersion( DBClientBase & conn , const string& ns , bool a uthoritative = false ); bool checkShardVersion( DBClientBase & conn , const string& ns , bool a uthoritative = false );
} }
 End of changes. 3 change blocks. 
7 lines changed or deleted 4 lines changed or added


 value.h   value.h 
// value.h /* @file value.h
concurrency helpers Atomic<T> and DiagStr
*/
/** /**
* Copyright (C) 2008 10gen Inc. * Copyright (C) 2008 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3 , * it under the terms of the GNU Affero General Public License, version 3 ,
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful,b * This program is distributed in the hope that it will be useful,b
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
skipping to change at line 23 skipping to change at line 25
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
namespace mongo { namespace mongo {
/** this string COULD be mangled but with the double buffering, assumin
g writes
are infrequent, it's unlikely. thus, this is reasonable for lockless s
etting of
diagnostic strings, where their content isn't critical.
*/
class DiagStr {
char buf1[256];
char buf2[256];
char *p;
public:
DiagStr() {
memset(buf1, 0, 256);
memset(buf2, 0, 256);
p = buf1;
}
const char * get() const { return p; }
void set(const char *s) {
char *q = (p==buf1) ? buf2 : buf1;
strncpy(q, s, 255);
p = q;
}
};
extern mutex _atomicMutex; extern mutex _atomicMutex;
/** atomic wrapper for a value. enters a mutex on each access. must /** atomic wrapper for a value. enters a mutex on each access. must
be copyable. be copyable.
*/ */
template<typename T> template<typename T>
class Atomic : boost::noncopyable { class Atomic : boost::noncopyable {
T val; T val;
public: public:
Atomic<T>() { } Atomic<T>() { }
skipping to change at line 74 skipping to change at line 52
return val; } return val; }
class tran : private scoped_lock { class tran : private scoped_lock {
Atomic<T>& _a; Atomic<T>& _a;
public: public:
tran(Atomic<T>& a) : scoped_lock(_atomicMutex), _a(a) { } tran(Atomic<T>& a) : scoped_lock(_atomicMutex), _a(a) { }
T& ref() { return _a.val; } T& ref() { return _a.val; }
}; };
}; };
/** this string COULD be mangled but with the double buffering, assumin
g writes
are infrequent, it's unlikely. thus, this is reasonable for lockless s
etting of
diagnostic strings, where their content isn't critical.
*/
class DiagStr {
char buf1[256];
char buf2[256];
char *p;
public:
DiagStr() {
memset(buf1, 0, 256);
memset(buf2, 0, 256);
p = buf1;
}
const char * get() const { return p; }
void set(const char *s) {
char *q = (p==buf1) ? buf2 : buf1;
strncpy(q, s, 255);
p = q;
}
};
} }
 End of changes. 3 change blocks. 
27 lines changed or deleted 29 lines changed or added

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