2d_index_cursor.h   2d_index_cursor.h 
skipping to change at line 60 skipping to change at line 60
* Parse the query, figure out if it's a near or a non-near predic ate, and create the * Parse the query, figure out if it's a near or a non-near predic ate, and create the
* appropriate sub-cursor. * appropriate sub-cursor.
*/ */
virtual Status seek(const BSONObj& position); virtual Status seek(const BSONObj& position);
/** /**
* We pay attention to the numWanted option. * We pay attention to the numWanted option.
*/ */
virtual Status setOptions(const CursorOptions& options); virtual Status setOptions(const CursorOptions& options);
// Not implemented:
virtual Status seek(const vector<const BSONElement*>& position,
const vector<bool>& inclusive) { return Status:
:OK(); }
virtual Status skip(const vector<const BSONElement*>& position,
const vector<bool>& inclusive) { return Status:
:OK(); }
// Implemented: // Implemented:
virtual bool isEOF() const; virtual bool isEOF() const;
virtual BSONObj getKey() const; virtual BSONObj getKey() const;
virtual DiskLoc getValue() const; virtual DiskLoc getValue() const;
virtual void next(); virtual void next();
virtual string toString(); virtual string toString();
virtual Status savePosition(); virtual Status savePosition();
virtual Status restorePosition(); virtual Status restorePosition();
virtual void aboutToDeleteBucket(const DiskLoc& bucket);
virtual void explainDetails(BSONObjBuilder* b); virtual void explainDetails(BSONObjBuilder* b);
private: private:
TwoDAccessMethod* _accessMethod; TwoDAccessMethod* _accessMethod;
int _numWanted; int _numWanted;
scoped_ptr<twod_internal::GeoCursorBase> _underlyingCursor; scoped_ptr<twod_internal::GeoCursorBase> _underlyingCursor;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 2 change blocks. 
9 lines changed or deleted 0 lines changed or added


 accumulator.h   accumulator.h 
skipping to change at line 22 skipping to change at line 22
* *
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* 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 "mongo/pch.h" #include "mongo/pch.h"
#include <boost/unordered_set.hpp> #include <boost/unordered_set.hpp>
#include "db/pipeline/value.h"
#include "db/pipeline/expression.h"
#include "bson/bsontypes.h"
namespace mongo { #include "mongo/bson/bsontypes.h"
class ExpressionContext; #include "mongo/db/pipeline/value.h"
class Accumulator : namespace mongo {
public ExpressionNary { class Accumulator : public RefCountable {
public: public:
// virtuals from ExpressionNary /** Process input and update internal state.
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio * merging should be true when processing outputs from getValue(tr
n); ue).
virtual void addToBsonObj(BSONObjBuilder *pBuilder, */
StringData fieldName, void process(const Value& input, bool merging) {
bool requireExpression) const; processInternal(input, merging);
virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const; }
/*
Get the accumulated value.
@returns the accumulated value /** Marks the end of the evaluate() phase and return accumulated re
sult.
* toBeMerged should be true when the outputs will be merged by pr
ocess().
*/ */
virtual Value getValue() const = 0; virtual Value getValue(bool toBeMerged) const = 0;
protected: /// The name of the op as used in a serialization of the pipeline.
Accumulator(); virtual const char* getOpName() const = 0;
/* int memUsageForSorter() const {
Convenience method for doing this for accumulators. The pattern dassert(_memUsageBytes != 0); // This would mean subclass didn'
is always the same, so a common implementation works, but require t set it
s return _memUsageBytes;
knowing the operator name. }
@param pBuilder the builder to add to
@param fieldName the projected name
@param opName the operator name
*/
void opToBson(BSONObjBuilder *pBuilder, StringData opName,
StringData fieldName, bool requireExpression) const;
};
class AccumulatorAddToSet : /// Reset this accumulator to a fresh state ready to receive input.
public Accumulator { virtual void reset() = 0;
public:
// virtuals from Expression
virtual Value evaluate(const Document& pDocument) const;
virtual Value getValue() const;
virtual const char *getOpName() const;
/* protected:
Create an appending accumulator. Accumulator() : _memUsageBytes(0) {}
@param pCtx the expression context /// Update subclass's internal state based on input
@returns the created accumulator virtual void processInternal(const Value& input, bool merging) = 0;
*/
static intrusive_ptr<Accumulator> create(
const intrusive_ptr<ExpressionContext> &pCtx);
private: /// subclasses are expected to update this as necessary
AccumulatorAddToSet(const intrusive_ptr<ExpressionContext> &pTheCtx int _memUsageBytes;
); };
typedef boost::unordered_set<Value, Value::Hash > SetType;
mutable SetType set; class AccumulatorAddToSet : public Accumulator {
mutable SetType::iterator itr;
intrusive_ptr<ExpressionContext> pCtx;
};
/*
This isn't a finished accumulator, but rather a convenient base class
for others such as $first, $last, $max, $min, and similar. It just
provides a holder for a single Value, and the getter for that. The
holder is protected so derived classes can manipulate it.
*/
class AccumulatorSingleValue :
public Accumulator {
public: public:
// virtuals from Expression virtual void processInternal(const Value& input, bool merging);
virtual Value getValue() const; virtual Value getValue(bool toBeMerged) const;
virtual const char* getOpName() const;
virtual void reset();
protected: static intrusive_ptr<Accumulator> create();
AccumulatorSingleValue();
mutable Value pValue; /* current min/max */ private:
AccumulatorAddToSet();
typedef boost::unordered_set<Value, Value::Hash> SetType;
SetType set;
}; };
class AccumulatorFirst : class AccumulatorFirst : public Accumulator {
public AccumulatorSingleValue {
public: public:
// virtuals from Expression virtual void processInternal(const Value& input, bool merging);
virtual Value evaluate(const Document& pDocument) const; virtual Value getValue(bool toBeMerged) const;
virtual const char *getOpName() const; virtual const char* getOpName() const;
virtual void reset();
/* static intrusive_ptr<Accumulator> create();
Create the accumulator.
@returns the created accumulator
*/
static intrusive_ptr<Accumulator> create(
const intrusive_ptr<ExpressionContext> &pCtx);
private: private:
mutable bool _haveFirst;
AccumulatorFirst(); AccumulatorFirst();
bool _haveFirst;
Value _first;
}; };
class AccumulatorLast : class AccumulatorLast : public Accumulator {
public AccumulatorSingleValue {
public: public:
// virtuals from Expression virtual void processInternal(const Value& input, bool merging);
virtual Value evaluate(const Document& pDocument) const; virtual Value getValue(bool toBeMerged) const;
virtual const char *getOpName() const; virtual const char* getOpName() const;
virtual void reset();
/* static intrusive_ptr<Accumulator> create();
Create the accumulator.
@returns the created accumulator
*/
static intrusive_ptr<Accumulator> create(
const intrusive_ptr<ExpressionContext> &pCtx);
private: private:
AccumulatorLast(); AccumulatorLast();
Value _last;
}; };
class AccumulatorSum : class AccumulatorSum : public Accumulator {
public Accumulator {
public: public:
// virtuals from Accumulator virtual void processInternal(const Value& input, bool merging);
virtual Value evaluate(const Document& pDocument) const; virtual Value getValue(bool toBeMerged) const;
virtual Value getValue() const; virtual const char* getOpName() const;
virtual const char *getOpName() const; virtual void reset();
/* static intrusive_ptr<Accumulator> create();
Create a summing accumulator.
@param pCtx the expression context
@returns the created accumulator
*/
static intrusive_ptr<Accumulator> create(
const intrusive_ptr<ExpressionContext> &pCtx);
protected: /* reused by AccumulatorAvg */ protected: /* reused by AccumulatorAvg */
AccumulatorSum(); AccumulatorSum();
mutable BSONType totalType; BSONType totalType;
mutable long long longTotal; long long longTotal;
mutable double doubleTotal; double doubleTotal;
// count is only used by AccumulatorAvg, but lives here to avoid co unting non-numeric values // count is only used by AccumulatorAvg, but lives here to avoid co unting non-numeric values
mutable long long count; long long count;
}; };
class AccumulatorMinMax : class AccumulatorMinMax : public Accumulator {
public AccumulatorSingleValue {
public: public:
// virtuals from Expression virtual void processInternal(const Value& input, bool merging);
virtual Value evaluate(const Document& pDocument) const; virtual Value getValue(bool toBeMerged) const;
virtual const char *getOpName() const; virtual const char* getOpName() const;
virtual void reset();
/* static intrusive_ptr<Accumulator> createMin();
Create either the max or min accumulator. static intrusive_ptr<Accumulator> createMax();
@returns the created accumulator
*/
static intrusive_ptr<Accumulator> createMin(
const intrusive_ptr<ExpressionContext> &pCtx);
static intrusive_ptr<Accumulator> createMax(
const intrusive_ptr<ExpressionContext> &pCtx);
private: private:
AccumulatorMinMax(int theSense); AccumulatorMinMax(int theSense);
int sense; /* 1 for min, -1 for max; used to "scale" comparison */ Value _val;
const int _sense; /* 1 for min, -1 for max; used to "scale" compari
son */
}; };
class AccumulatorPush : class AccumulatorPush : public Accumulator {
public Accumulator {
public: public:
// virtuals from Expression virtual void processInternal(const Value& input, bool merging);
virtual Value evaluate(const Document& pDocument) const; virtual Value getValue(bool toBeMerged) const;
virtual Value getValue() const; virtual const char* getOpName() const;
virtual const char *getOpName() const; virtual void reset();
/* static intrusive_ptr<Accumulator> create();
Create an appending accumulator.
@param pCtx the expression context
@returns the created accumulator
*/
static intrusive_ptr<Accumulator> create(
const intrusive_ptr<ExpressionContext> &pCtx);
private: private:
AccumulatorPush(const intrusive_ptr<ExpressionContext> &pTheCtx); AccumulatorPush();
mutable vector<Value> vpValue; vector<Value> vpValue;
intrusive_ptr<ExpressionContext> pCtx;
}; };
class AccumulatorAvg : class AccumulatorAvg : public AccumulatorSum {
public AccumulatorSum {
typedef AccumulatorSum Super; typedef AccumulatorSum Super;
public: public:
// virtuals from Accumulator virtual void processInternal(const Value& input, bool merging);
virtual Value evaluate(const Document& pDocument) const; virtual Value getValue(bool toBeMerged) const;
virtual Value getValue() const; virtual const char* getOpName() const;
virtual const char *getOpName() const; virtual void reset();
/* static intrusive_ptr<Accumulator> create();
Create an averaging accumulator.
@param pCtx the expression context
@returns the created accumulator
*/
static intrusive_ptr<Accumulator> create(
const intrusive_ptr<ExpressionContext> &pCtx);
private: private:
static const char subTotalName[]; AccumulatorAvg();
static const char countName[];
AccumulatorAvg(const intrusive_ptr<ExpressionContext> &pCtx);
intrusive_ptr<ExpressionContext> pCtx;
}; };
} }
 End of changes. 43 change blocks. 
166 lines changed or deleted 94 lines changed or added


 action_set.h   action_set.h 
skipping to change at line 27 skipping to change at line 27
#include <bitset> #include <bitset>
#include "mongo/base/status.h" #include "mongo/base/status.h"
#include "mongo/db/auth/action_type.h" #include "mongo/db/auth/action_type.h"
namespace mongo { namespace mongo {
/* /*
* An ActionSet is a bitmask of ActionTypes that represents a set of a ctions. * An ActionSet is a bitmask of ActionTypes that represents a set of a ctions.
* These are the actions that a Privilege can grant a principal to per form on a resource. * These are the actions that a Privilege can grant a user to perform on a resource.
*/ */
class ActionSet { class ActionSet {
public: public:
ActionSet() : _actions(0) {} ActionSet() : _actions(0) {}
void addAction(const ActionType& action); void addAction(const ActionType& action);
void addAllActionsFromSet(const ActionSet& actionSet); void addAllActionsFromSet(const ActionSet& actionSet);
void addAllActions(); void addAllActions();
void removeAction(const ActionType& action); void removeAction(const ActionType& action);
void removeAllActionsFromSet(const ActionSet& actionSet); void removeAllActionsFromSet(const ActionSet& actionSet);
void removeAllActions(); void removeAllActions();
bool empty() const { return _actions.none(); } bool empty() const { return _actions.none(); }
bool equals(const ActionSet& other) const { return this->_actions =
= other._actions; }
bool contains(const ActionType& action) const; bool contains(const ActionType& action) const;
// Returns true only if this ActionSet contains all the actions pre sent in the 'other' // Returns true only if this ActionSet contains all the actions pre sent in the 'other'
// ActionSet. // ActionSet.
bool isSupersetOf(const ActionSet& other) const; bool isSupersetOf(const ActionSet& other) const;
// Returns the string representation of this ActionSet // Returns the string representation of this ActionSet
std::string toString() const; std::string toString() const;
// Takes a comma-separated string of action type string representat ions and returns // Takes a comma-separated string of action type string representat ions and returns
// an int bitmask of the actions. // an int bitmask of the actions.
static Status parseActionSetFromString(const std::string& actionsSt ring, ActionSet* result); static Status parseActionSetFromString(const std::string& actionsSt ring, ActionSet* result);
private: private:
// bitmask of actions this privilege grants // bitmask of actions this privilege grants
std::bitset<ActionType::NUM_ACTION_TYPES> _actions; std::bitset<ActionType::NUM_ACTION_TYPES> _actions;
}; };
static inline bool operator==(const ActionSet& lhs, const ActionSet& rh
s) {
return lhs.equals(rhs);
}
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
1 lines changed or deleted 9 lines changed or added


 algorithm.h   algorithm.h 
skipping to change at line 114 skipping to change at line 114
std::vector<Element>::iterator where = children.begin(); std::vector<Element>::iterator where = children.begin();
const std::vector<Element>::iterator end = children.end(); const std::vector<Element>::iterator end = children.end();
for( ; where != end; ++where ) { for( ; where != end; ++where ) {
// Detach from its current location. // Detach from its current location.
where->remove(); where->remove();
// Make it the new rightmost element. // Make it the new rightmost element.
parent.pushBack(*where); parent.pushBack(*where);
} }
} }
/** Remove any consecutive children that compare as identical according
to 'comp'. The
* children must be sorted (see sortChildren, above), and the equality
comparator here
* must be compatible with the comparator used for the sort.
*/
template<typename EqualityComparator>
void deduplicateChildren(Element parent, EqualityComparator equal) {
Element current = parent.leftChild();
while (current.ok()) {
Element next = current.rightSibling();
if (next.ok() && equal(current, next)) {
next.remove();
} else {
current = next;
}
}
}
/** A less-than ordering for Elements that compares based on woCompare
*/
class woLess {
// TODO: This should possibly derive from std::binary_function.
public:
woLess(bool considerFieldName = true)
: _considerFieldName(considerFieldName) {
}
inline bool operator()(const ConstElement& left, const ConstElement
& right) const {
return left.compareWithElement(right, _considerFieldName) < 0;
}
private:
const bool _considerFieldName;
};
/** A greater-than ordering for Elements that compares based on woCompa
re */
class woGreater {
// TODO: This should possibly derive from std::binary_function.
public:
woGreater(bool considerFieldName = true)
: _considerFieldName(considerFieldName) {
}
inline bool operator()(const ConstElement& left, const ConstElement
& right) const {
return left.compareWithElement(right, _considerFieldName) > 0;
}
private:
const bool _considerFieldName;
};
/** An equality predicate for elements that compares based on woCompare
*/
class woEqual {
// TODO: This should possibly derive from std::binary_function.
public:
woEqual(bool considerFieldName = true)
: _considerFieldName(considerFieldName) {
}
inline bool operator()(const ConstElement& left, const ConstElement
& right) const {
return left.compareWithElement(right, _considerFieldName) == 0;
}
private:
const bool _considerFieldName;
};
/** An equality predicate for elements that compares based on woCompare
*/
class woEqualTo {
// TODO: This should possibly derive from std::binary_function.
public:
woEqualTo(const ConstElement& value, bool considerFieldName = true)
: _value(value)
, _considerFieldName(considerFieldName) {
}
inline bool operator()(const ConstElement& elt) const {
return _value.compareWithElement(elt, _considerFieldName) == 0;
}
private:
const ConstElement& _value;
const bool _considerFieldName;
};
/** Return the element that is 'n' Elements to the left in the sibling chain of 'element'. */ /** Return the element that is 'n' Elements to the left in the sibling chain of 'element'. */
template<typename ElementType> template<typename ElementType>
ElementType getNthLeftSibling(ElementType element, std::size_t n) { ElementType getNthLeftSibling(ElementType element, std::size_t n) {
while (element.ok() && (n-- != 0)) while (element.ok() && (n-- != 0))
element = element.leftSibling(); element = element.leftSibling();
return element; return element;
} }
/** Return the element that is 'n' Elements to the right in the sibling chain of 'element'. */ /** Return the element that is 'n' Elements to the right in the sibling chain of 'element'. */
template<typename ElementType> template<typename ElementType>
 End of changes. 1 change blocks. 
0 lines changed or deleted 88 lines changed or added


 atomic_intrinsics_win32.h   atomic_intrinsics_win32.h 
skipping to change at line 91 skipping to change at line 91
~AtomicIntrinsics(); ~AtomicIntrinsics();
}; };
/** /**
* Instantiation of AtomicIntrinsics<> for 64-bit word sizes. * Instantiation of AtomicIntrinsics<> for 64-bit word sizes.
*/ */
template <typename T> template <typename T>
class AtomicIntrinsics<T, typename boost::enable_if_c<sizeof(T) == size of(LONGLONG)>::type> { class AtomicIntrinsics<T, typename boost::enable_if_c<sizeof(T) == size of(LONGLONG)>::type> {
public: public:
#if defined(NTDDI_VERSION) && defined(NTDDI_VISTA) && (NTDDI_VERSION >= NTD DI_VISTA) #if defined(NTDDI_VERSION) && defined(NTDDI_WS03SP2) && (NTDDI_VERSION >= N TDDI_WS03SP2)
static const bool kHaveInterlocked64 = true; static const bool kHaveInterlocked64 = true;
#else #else
static const bool kHaveInterlocked64 = false; static const bool kHaveInterlocked64 = false;
#endif #endif
static T compareAndSwap(volatile T* dest, T expected, T newValue) { static T compareAndSwap(volatile T* dest, T expected, T newValue) {
return InterlockedImpl<kHaveInterlocked64>::compareAndSwap(dest , expected, newValue); return InterlockedImpl<kHaveInterlocked64>::compareAndSwap(dest , expected, newValue);
} }
static T swap(volatile T* dest, T newValue) { static T swap(volatile T* dest, T newValue) {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 auth_index_d.h   auth_index_d.h 
skipping to change at line 20 skipping to change at line 20
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/base/string_data.h" #include "mongo/base/string_data.h"
#include "mongo/db/namespacestring.h" #include "mongo/db/namespace_string.h"
namespace mongo { namespace mongo {
namespace authindex { namespace authindex {
/** /**
* Ensures that exactly the appropriate indexes are present on system c ollections supporting * Ensures that exactly the appropriate indexes are present on system c ollections supporting
* authentication and authorization in database "dbname". * authentication and authorization in database "dbname".
* *
* It is appropriate to call this function on new or existing databases , though it is primarily * It is appropriate to call this function on new or existing databases , though it is primarily
* intended for use on existing databases. Under no circumstances may it be called on databases * intended for use on existing databases. Under no circumstances may it be called on databases
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 authentication_commands.h   authentication_commands.h 
skipping to change at line 40 skipping to change at line 40
virtual bool slaveOk() const { virtual bool slaveOk() const {
return true; return true;
} }
virtual LockType locktype() const { return NONE; } virtual LockType locktype() const { return NONE; }
virtual void help(stringstream& ss) const { ss << "internal"; } virtual void help(stringstream& ss) const { ss << "internal"; }
virtual void addRequiredPrivileges(const std::string& dbname, virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj, const BSONObj& cmdObj,
std::vector<Privilege>* out) {} // No auth required std::vector<Privilege>* out) {} // No auth required
CmdAuthenticate() : Command("authenticate") {} CmdAuthenticate() : Command("authenticate") {}
bool run(const string& dbname , BSONObj& cmdObj, int options, strin g& errmsg, BSONObjBuilder& result, bool fromRepl); bool run(const string& dbname , BSONObj& cmdObj, int options, strin g& errmsg, BSONObjBuilder& result, bool fromRepl);
private:
bool authenticateCR(const string& dbname,
BSONObj& cmdObj,
string& errmsg,
BSONObjBuilder& result);
bool authenticateX509(const string& dbname,
BSONObj& cmdObj,
string& errmsg,
BSONObjBuilder& result);
}; };
extern CmdAuthenticate cmdAuthenticate; extern CmdAuthenticate cmdAuthenticate;
} }
 End of changes. 1 change blocks. 
0 lines changed or deleted 10 lines changed or added


 authorization_manager.h   authorization_manager.h 
/** /**
* Copyright (C) 2012 10gen Inc. * Copyright (C) 2013 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3 , * it under the terms of the GNU Affero General Public License, version 3 ,
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <boost/scoped_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <string> #include <string>
#include <vector>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
#include "mongo/base/status.h" #include "mongo/base/status.h"
#include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h" #include "mongo/db/auth/authz_manager_external_state.h"
#include "mongo/db/auth/auth_external_state.h"
#include "mongo/db/auth/principal.h"
#include "mongo/db/auth/principal_name.h"
#include "mongo/db/auth/principal_set.h"
#include "mongo/db/auth/privilege.h"
#include "mongo/db/auth/privilege_set.h" #include "mongo/db/auth/privilege_set.h"
#include "mongo/db/auth/user.h"
#include "mongo/db/auth/user_name.h"
#include "mongo/db/auth/user_name_hash.h"
#include "mongo/db/jsobj.h"
#include "mongo/platform/unordered_map.h"
namespace mongo { namespace mongo {
/** /**
* Internal secret key info. * Internal secret key info.
*/ */
struct AuthInfo { struct AuthInfo {
AuthInfo(); AuthInfo();
string user; std::string user;
string pwd; std::string pwd;
BSONObj authParams;
}; };
extern AuthInfo internalSecurity; // set at startup and not changed aft er initialization. extern AuthInfo internalSecurity; // set at startup and not changed aft er initialization.
/** /**
* Contains all the authorization logic for a single client connection. * Contains server/cluster-wide information about Authorization.
It contains a set of
* the principals which have been authenticated, as well as a set of pr
ivileges that have been
* granted by those principals to perform various actions.
* An AuthorizationManager object is present within every mongo::Client
object, therefore there
* is one per thread that corresponds to an incoming client connection.
*/ */
class AuthorizationManager { class AuthorizationManager {
MONGO_DISALLOW_COPYING(AuthorizationManager); MONGO_DISALLOW_COPYING(AuthorizationManager);
public: public:
// The newly constructed AuthorizationManager takes ownership of "e
xternalState"
explicit AuthorizationManager(AuthzManagerExternalState* externalSt
ate);
~AuthorizationManager();
static const std::string SERVER_RESOURCE_NAME; static const std::string SERVER_RESOURCE_NAME;
static const std::string CLUSTER_RESOURCE_NAME; static const std::string CLUSTER_RESOURCE_NAME;
static const std::string USER_NAME_FIELD_NAME; static const std::string USER_NAME_FIELD_NAME;
static const std::string USER_SOURCE_FIELD_NAME; static const std::string USER_SOURCE_FIELD_NAME;
static const std::string PASSWORD_FIELD_NAME; static const std::string PASSWORD_FIELD_NAME;
// TODO: Make the following functions no longer static.
/**
* Sets whether or not we allow old style (pre v2.4) privilege docu
ments for this whole
* server.
*/
static void setSupportOldStylePrivilegeDocuments(bool enabled); static void setSupportOldStylePrivilegeDocuments(bool enabled);
// Sets whether or not access control enforcement is enabled for th /**
is whole server.. * Returns true if we allow old style privilege privilege documents
for this whole server.
*/
static bool getSupportOldStylePrivilegeDocuments();
/**
* Sets whether or not access control enforcement is enabled for th
is whole server.
*/
static void setAuthEnabled(bool enabled); static void setAuthEnabled(bool enabled);
// Returns true if access control is enabled on this server. /**
* Returns true if access control is enabled on this server.
*/
static bool isAuthEnabled(); static bool isAuthEnabled();
// Checks to see if "doc" is a valid privilege document, assuming i AuthzManagerExternalState* getExternalState() const;
t is stored in the
// "system.users" collection of database "dbname". // Gets the privilege information document for "userName" on "dbnam
e".
// //
// Returns Status::OK() if the document is good, or Status(ErrorCod // On success, returns Status::OK() and stores a shared-ownership c
es::BadValue), otherwise. opy of the document into
static Status checkValidPrivilegeDocument(const StringData& dbname, // "result".
const BSONObj& doc); Status getPrivilegeDocument(const std::string& dbname,
const UserName& userName,
BSONObj* result) const;
// Takes ownership of the externalState. // Returns true if there exists at least one privilege document in
explicit AuthorizationManager(AuthExternalState* externalState); the given database.
~AuthorizationManager(); bool hasPrivilegeDocument(const std::string& dbname) const;
// Should be called at the beginning of every new request. This pe // Creates the given user object in the given database.
rforms the checks Status insertPrivilegeDocument(const std::string& dbname, const BSO
// necessary to determine if localhost connections should be given NObj& userObj) const;
full access.
// TODO: try to eliminate the need for this call.
void startRequest();
// Adds "principal" to the authorization manager, and takes ownersh
ip of it.
void addAuthorizedPrincipal(Principal* principal);
// Returns the authenticated principal with the given name. Return
s NULL
// if no such user is found.
// Ownership of the returned Principal remains with _authenticatedP
rincipals
Principal* lookupPrincipal(const PrincipalName& name);
// Gets an iterator over the names of all authenticated principals
stored in this manager.
PrincipalSet::NameIterator getAuthenticatedPrincipalNames();
// Removes any authenticated principals whose authorization credent
ials came from the given
// database, and revokes any privileges that were granted via that
principal.
void logoutDatabase(const std::string& dbname);
// Grant this connection the given privilege.
Status acquirePrivilege(const Privilege& privilege,
const PrincipalName& authorizingPrincipal);
// Adds a new principal with the given principal name and authorize
s it with full access.
// Used to grant internal threads full access.
void grantInternalAuthorization(const std::string& principalName);
// Checks if this connection has been authenticated as an internal
user.
bool hasInternalAuthorization();
// Checks if this connection has the privileges required to perform
the given action
// on the given resource. Contains all the authorization logic inc
luding handling things
// like the localhost exception. Returns true if the action may pr
oceed on the resource.
// Note: this may acquire a database read lock (for automatic privi
lege acquisition).
bool checkAuthorization(const std::string& resource, ActionType act
ion);
// Same as above but takes an ActionSet instead of a single ActionT
ype. Returns true if
// all of the actions may proceed on the resource.
bool checkAuthorization(const std::string& resource, ActionSet acti
ons);
// Parses the privilege documents and acquires all privileges that
the privilege document
// grants
Status acquirePrivilegesFromPrivilegeDocument(const std::string& db
name,
const PrincipalName&
principal,
const BSONObj& privil
egeDocument);
// Returns the privilege document with the given user name in the g // Updates the given user object with the given update modifier.
iven database. Currently Status updatePrivilegeDocument(const UserName& user, const BSONObj&
// this information comes from the system.users collection in that updateObj) const;
database.
Status getPrivilegeDocument(const std::string& dbname,
const PrincipalName& userName,
BSONObj* result) {
return _externalState->getPrivilegeDocument(dbname, userName, r
esult);
}
// Checks if this connection has the privileges necessary to perfor
m a query on the given
// namespace.
Status checkAuthForQuery(const std::string& ns);
// Checks if this connection has the privileges necessary to perfor
m an update on the given
// namespace.
Status checkAuthForUpdate(const std::string& ns, bool upsert);
// Checks if this connection has the privileges necessary to perfor
m an insert to the given
// namespace.
Status checkAuthForInsert(const std::string& ns);
// Checks if this connection has the privileges necessary to perfor
m a delete on the given
// namespace.
Status checkAuthForDelete(const std::string& ns);
// Checks if this connection has the privileges necessary to perfor
m a getMore on the given
// namespace.
Status checkAuthForGetMore(const std::string& ns);
// Checks if this connection is authorized for the given Privilege. // Checks to see if "doc" is a valid privilege document, assuming i
Status checkAuthForPrivilege(const Privilege& privilege); t is stored in the
// "system.users" collection of database "dbname".
//
// Returns Status::OK() if the document is good, or Status(ErrorCod
es::BadValue), otherwise.
Status checkValidPrivilegeDocument(const StringData& dbname, const
BSONObj& doc);
// Checks if this connection is authorized for all the given Privil // Parses the privilege document and returns a PrivilegeSet of all
eges. the Privileges that
Status checkAuthForPrivileges(const vector<Privilege>& privileges); // the privilege document grants.
Status buildPrivilegeSet(const std::string& dbname,
const UserName& user,
const BSONObj& privilegeDocument,
PrivilegeSet* result) const;
// Given a database name and a readOnly flag return an ActionSet de scribing all the actions // Given a database name and a readOnly flag return an ActionSet de scribing all the actions
// that an old-style user with those attributes should be given. // that an old-style user with those attributes should be given.
static ActionSet getActionsForOldStyleUser(const std::string& dbnam ActionSet getActionsForOldStyleUser(const std::string& dbname, bool
e, bool readOnly); readOnly) const;
// Parses the privilege document and returns a PrivilegeSet of all
the Privileges that
// the privilege document grants.
static Status buildPrivilegeSet(const std::string& dbname,
const PrincipalName& principal,
const BSONObj& privilegeDocument,
PrivilegeSet* result);
// Returns an ActionSet of all actions that can be be granted to us ers. This does not // Returns an ActionSet of all actions that can be be granted to us ers. This does not
// include internal-only actions. // include internal-only actions.
static ActionSet getAllUserActions(); ActionSet getAllUserActions() const;
/**
* Returns the User object for the given userName in the out param
"acquiredUser".
* If the user cache already has a user object for this user, it i
ncrements the refcount
* on that object and gives out a pointer to it. If no user objec
t for this user name
* exists yet in the cache, reads the user's privilege document fr
om disk, builds up
* a User object, sets the refcount to 1, and gives that out.
* The AuthorizationManager retains ownership of the returned User
object.
* On non-OK Status return values, acquiredUser will not be modifi
ed.
*/
Status acquireUser(const UserName& userName, User** acquiredUser);
/**
* Decrements the refcount of the given User object. If the refcou
nt has gone to zero,
* deletes the User. Caller must stop using its pointer to "user"
after calling this.
*/
void releaseUser(User* user);
private: private:
// Finds the set of privileges attributed to "principal" in databas
e "dbname",
// and adds them to the set of acquired privileges.
void _acquirePrivilegesForPrincipalFromDatabase(const std::string&
dbname,
const PrincipalName
& principal);
// Checks to see if the given privilege is allowed, performing impl
icit privilege
// acquisition if enabled and necessary to resolve the privilege.
Status _probeForPrivilege(const Privilege& privilege);
// Parses the old-style (pre 2.4) privilege document and returns a PrivilegeSet of all the // Parses the old-style (pre 2.4) privilege document and returns a PrivilegeSet of all the
// Privileges that the privilege document grants. // Privileges that the privilege document grants.
static Status _buildPrivilegeSetFromOldStylePrivilegeDocument( Status _buildPrivilegeSetFromOldStylePrivilegeDocument(
const std::string& dbname, const std::string& dbname,
const PrincipalName& principal, const UserName& user,
const BSONObj& privilegeDocument, const BSONObj& privilegeDocument,
PrivilegeSet* result); PrivilegeSet* result) const ;
// Parses extended-form (2.4+) privilege documents and returns a Pr ivilegeSet of all the // Parses extended-form (2.4+) privilege documents and returns a Pr ivilegeSet of all the
// privileges that the document grants. // privileges that the document grants.
// //
// The document, "privilegeDocument", is assumed to describe privil eges for "principal", and // The document, "privilegeDocument", is assumed to describe privil eges for "principal", and
// to come from database "dbname". // to come from database "dbname".
static Status _buildPrivilegeSetFromExtendedPrivilegeDocument( Status _buildPrivilegeSetFromExtendedPrivilegeDocument(
const std::string& dbname, const std::string& dbname,
const PrincipalName& principal, const UserName& user,
const BSONObj& privilegeDocument, const BSONObj& privilegeDocument,
PrivilegeSet* result); PrivilegeSet* result) const;
// Returns a new privilege that has replaced the actions needed to /**
handle special casing * Parses privDoc and initializes the user object with the informat
// certain namespaces like system.users and system.profile. ion extracted from the
Privilege _modifyPrivilegeForSpecialCases(const Privilege& privileg * privilege document.
e); */
Status _initializeUserFromPrivilegeDocument(User* user,
const BSONObj& privDoc)
const;
static bool _doesSupportOldStylePrivileges; static bool _doesSupportOldStylePrivileges;
// True if access control enforcement is enabled on this node (ie i t was started with // True if access control enforcement is enabled on this node (ie i t was started with
// --auth or --keyFile). // --auth or --keyFile).
// This is a config setting, set at startup and not changing after initialization. // This is a config setting, set at startup and not changing after initialization.
static bool _authEnabled; static bool _authEnabled;
scoped_ptr<AuthExternalState> _externalState; // Integer that represents what format version the privilege docume
nts in the system are.
// All the privileges that have been acquired by the authenticated // The current version is 2. When upgrading to v2.6 or later from
principals. v2.4 or prior, the
PrivilegeSet _acquiredPrivileges; // version is 1. After running the upgrade process to upgrade to t
// All principals who have been authenticated on this connection he new privilege document
PrincipalSet _authenticatedPrincipals; // format, the version will be 2.
int _version;
scoped_ptr<AuthzManagerExternalState> _externalState;
/**
* Caches User objects with information about user privileges, to a
void the need to
* go to disk to read user privilege documents whenever possible.
Every User object
* has a reference count - the AuthorizationManager must not delete
a User object in the
* cache unless its reference count is zero.
*/
unordered_map<UserName, User*> _userCache;
/**
* Protects _userCache.
*/
boost::mutex _lock;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 29 change blocks. 
179 lines changed or deleted 142 lines changed or added


 background.h   background.h 
skipping to change at line 24 skipping to change at line 24
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* background.h /* background.h
Concurrency coordination for administrative operations. Concurrency coordination for administrative operations.
*/ */
#pragma once #pragma once
#include "mongo/db/namespacestring.h" #include <map>
#include <set>
#include <string>
#include <sstream>
#include "mongo/base/string_data.h"
#include "mongo/db/namespace_string.h"
#include "mongo/util/concurrency/mutex.h"
namespace mongo { namespace mongo {
/* these are administrative operations / jobs /* these are administrative operations / jobs
for a namespace running in the background, and that only one for a namespace running in the background, and that only one
at a time per namespace is permitted, and that if in progress, at a time per namespace is permitted, and that if in progress,
you aren't allowed to do other NamespaceDetails major manipulations you aren't allowed to do other NamespaceDetails major manipulations
(such as dropping ns or db) even in the foreground and must (such as dropping ns or db) even in the foreground and must
instead uassert. instead uassert.
It's assumed this is not for super-high RPS things, so we don't do It's assumed this is not for super-high RPS things, so we don't do
anything special in the implementation here to be fast. anything special in the implementation here to be fast.
*/ */
class BackgroundOperation : public boost::noncopyable { class BackgroundOperation : public boost::noncopyable {
public: public:
static bool inProgForDb(const char *db); static bool inProgForDb(const StringData& db);
static bool inProgForNs(const char *ns); static bool inProgForNs(const StringData& ns);
static void assertNoBgOpInProgForDb(const char *db); static void assertNoBgOpInProgForDb(const StringData& db);
static void assertNoBgOpInProgForNs(const char *ns); static void assertNoBgOpInProgForNs(const StringData& ns);
static void dump(stringstream&); static void dump(std::stringstream&);
/* check for in progress before instantiating */ /* check for in progress before instantiating */
BackgroundOperation(const char *ns); BackgroundOperation(const StringData& ns);
virtual ~BackgroundOperation(); virtual ~BackgroundOperation();
private: private:
NamespaceString _ns; NamespaceString _ns;
static map<string, unsigned> dbsInProg; static std::map<std::string, unsigned> dbsInProg;
static set<string> nsInProg; static std::set<std::string> nsInProg;
static SimpleMutex m; static SimpleMutex m;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 4 change blocks. 
9 lines changed or deleted 16 lines changed or added


 bson-inl.h   bson-inl.h 
skipping to change at line 210 skipping to change at line 210
r = j.next(); r = j.next();
if ( l.eoo() ) if ( l.eoo() )
return r.eoo(); return r.eoo();
} while( l == r ); } while( l == r );
return false; return false;
} }
inline NOINLINE_DECL void BSONObj::_assertInvalid() const { inline NOINLINE_DECL void BSONObj::_assertInvalid() const {
StringBuilder ss; StringBuilder ss;
int os = objsize(); int os = objsize();
ss << "BSONObj size: " << os << " (0x" << toHex( &os, 4 ) << ") is invalid. " ss << "BSONObj size: " << os << " (0x" << integerToHex( os ) << ") is invalid. "
<< "Size must be between 0 and " << BSONObjMaxInternalSize << "Size must be between 0 and " << BSONObjMaxInternalSize
<< "(" << ( BSONObjMaxInternalSize/(1024*1024) ) << "MB)"; << "(" << ( BSONObjMaxInternalSize/(1024*1024) ) << "MB)";
try { try {
BSONElement e = firstElement(); BSONElement e = firstElement();
ss << " First element: " << e.toString(); ss << " First element: " << e.toString();
} }
catch ( ... ) { } catch ( ... ) { }
massert( 10334 , ss.str() , 0 ); massert( 10334 , ss.str() , 0 );
} }
skipping to change at line 453 skipping to change at line 453
typedef std::set<BSONElement, BSONElementFieldNameCmp> BSONSortedElemen ts; typedef std::set<BSONElement, BSONElementFieldNameCmp> BSONSortedElemen ts;
inline BSONSortedElements bson2set( const BSONObj& obj ) { inline BSONSortedElements bson2set( const BSONObj& obj ) {
BSONSortedElements s; BSONSortedElements s;
BSONObjIterator it(obj); BSONObjIterator it(obj);
while ( it.more() ) while ( it.more() )
s.insert( it.next() ); s.insert( it.next() );
return s; return s;
} }
inline std::string BSONObj::toString( bool isArray, bool full ) const { inline std::string BSONObj::toString( bool isArray, bool full ) const {
if ( isEmpty() ) return "{}"; if ( isEmpty() ) return (isArray ? "[]" : "{}");
StringBuilder s; StringBuilder s;
toString(s, isArray, full); toString(s, isArray, full);
return s.str(); return s.str();
} }
inline void BSONObj::toString( StringBuilder& s, bool isArray, bool fu ll, int depth ) const { inline void BSONObj::toString( StringBuilder& s, bool isArray, bool fu ll, int depth ) const {
if ( isEmpty() ) { if ( isEmpty() ) {
s << "{}"; s << (isArray ? "[]" : "{}");
return; return;
} }
s << ( isArray ? "[ " : "{ " ); s << ( isArray ? "[ " : "{ " );
BSONObjIterator i(*this); BSONObjIterator i(*this);
bool first = true; bool first = true;
while ( 1 ) { while ( 1 ) {
massert( 10327 , "Object does not end with EOO", i.moreWithEOO () ); massert( 10327 , "Object does not end with EOO", i.moreWithEOO () );
BSONElement e = i.next( true ); BSONElement e = i.next( true );
massert( 10328 , "Invalid element size", e.size() > 0 ); massert( 10328 , "Invalid element size", e.size() > 0 );
 End of changes. 3 change blocks. 
3 lines changed or deleted 3 lines changed or added


 bson_extract.h   bson_extract.h 
skipping to change at line 53 skipping to change at line 53
* ErrorCodes::NoSuchKey if there are no matches for "fieldName", and E rrorCodes::TypeMismatch * ErrorCodes::NoSuchKey if there are no matches for "fieldName", and E rrorCodes::TypeMismatch
* if the type of the matching element is not "type". For return value s other than * if the type of the matching element is not "type". For return value s other than
* Status::OK(), the resulting value of "*outElement" is undefined. * Status::OK(), the resulting value of "*outElement" is undefined.
*/ */
Status bsonExtractTypedField(const BSONObj& object, Status bsonExtractTypedField(const BSONObj& object,
const StringData& fieldName, const StringData& fieldName,
BSONType type, BSONType type,
BSONElement* outElement); BSONElement* outElement);
/** /**
* Finds a bool-like element named "fieldName" in "object".
*
* Returns Status::OK() and sets *out to the found element's boolean va
lue on success. Returns
* ErrorCodes::NoSuchKey if there are no matches for "fieldName", and E
rrorCodes::TypeMismatch
* if the type of the matching element is not Bool or a number type. F
or return values other
* than Status::OK(), the resulting value of "*out" is undefined.
*/
Status bsonExtractBooleanField(const BSONObj& object,
const StringData& fieldName,
bool* out);
/**
* Finds a string-typed element named "fieldName" in "object" and store s its value in "out". * Finds a string-typed element named "fieldName" in "object" and store s its value in "out".
* *
* Returns Status::OK() and sets *out to the found element's string val ue on success. Returns * Returns Status::OK() and sets *out to the found element's string val ue on success. Returns
* ErrorCodes::NoSuchKey if there are no matches for "fieldName", and E rrorCodes::TypeMismatch * ErrorCodes::NoSuchKey if there are no matches for "fieldName", and E rrorCodes::TypeMismatch
* if the type of the matching element is not String. For return value s other than * if the type of the matching element is not String. For return value s other than
* Status::OK(), the resulting value of "*out" is undefined. * Status::OK(), the resulting value of "*out" is undefined.
*/ */
Status bsonExtractStringField(const BSONObj& object, Status bsonExtractStringField(const BSONObj& object,
const StringData& fieldName, const StringData& fieldName,
std::string* out); std::string* out);
 End of changes. 1 change blocks. 
0 lines changed or deleted 15 lines changed or added


 bsonelement.h   bsonelement.h 
skipping to change at line 26 skipping to change at line 26
*/ */
#pragma once #pragma once
#include <string.h> // strlen #include <string.h> // strlen
#include <string> #include <string>
#include <vector> #include <vector>
#include "mongo/bson/bsontypes.h" #include "mongo/bson/bsontypes.h"
#include "mongo/bson/oid.h" #include "mongo/bson/oid.h"
#include "mongo/platform/cstdint.h"
#include "mongo/platform/float_utils.h" #include "mongo/platform/float_utils.h"
namespace mongo { namespace mongo {
class OpTime; class OpTime;
class BSONObj; class BSONObj;
class BSONElement; class BSONElement;
class BSONObjBuilder; class BSONObjBuilder;
} }
namespace bson { namespace bson {
skipping to change at line 61 skipping to change at line 62
internals: internals:
<type><fieldName ><value> <type><fieldName ><value>
-------- size() ------------ -------- size() ------------
-fieldNameSize- -fieldNameSize-
value() value()
type() type()
*/ */
class BSONElement { class BSONElement {
public: public:
/** These functions, which start with a capital letter, throw a Use rException if the /** These functions, which start with a capital letter, throw a Msg AssertionException if the
element is not of the required type. Example: element is not of the required type. Example:
std::string foo = obj["foo"].String(); // std::exception if not a std::string type or DNE std::string foo = obj["foo"].String(); // std::exception if not a std::string type or DNE
*/ */
std::string String() const { return chk(mongo::String).value str(); } std::string String() const { return chk(mongo::String).value str(); }
Date_t Date() const { return chk(mongo::Date).date(); } Date_t Date() const { return chk(mongo::Date).date(); }
double Number() const { return chk(isNumber()).number() ; } double Number() const { return chk(isNumber()).number() ; }
double Double() const { return chk(NumberDouble)._numbe rDouble(); } double Double() const { return chk(NumberDouble)._numbe rDouble(); }
long long Long() const { return chk(NumberLong)._numberL ong(); } long long Long() const { return chk(NumberLong)._numberL ong(); }
int Int() const { return chk(NumberInt)._numberIn t(); } int Int() const { return chk(NumberInt)._numberIn t(); }
bool Bool() const { return chk(mongo::Bool).boolean (); } bool Bool() const { return chk(mongo::Bool).boolean (); }
std::vector<BSONElement> Array() const; // see implementation for d etailed comments std::vector<BSONElement> Array() const; // see implementation for d etailed comments
mongo::OID OID() const { return chk(jstOID).__oid(); } mongo::OID OID() const { return chk(jstOID).__oid(); }
void Null() const { chk(isNull()); } // throw UserE void Null() const { chk(isNull()); } // throw MsgAs
xception if not null sertionException if not null
void OK() const { chk(ok()); } // throw UserE void OK() const { chk(ok()); } // throw MsgAs
xception if element DNE sertionException if element DNE
/** @return the embedded object associated with this field. /** @return the embedded object associated with this field.
Note the returned object is a reference to within the parent bs on object. If that Note the returned object is a reference to within the parent bs on object. If that
object is out of scope, this pointer will no longer be valid. C all getOwned() on the object is out of scope, this pointer will no longer be valid. C all getOwned() on the
returned BSONObj if you need your own copy. returned BSONObj if you need your own copy.
throws UserException if the element is not of type object. throws UserException if the element is not of type object.
*/ */
BSONObj Obj() const; BSONObj Obj() const;
/** populate v with the value of the element. If type does not mat ch, throw exception. /** populate v with the value of the element. If type does not mat ch, throw exception.
skipping to change at line 145 skipping to change at line 146
/** field name of the element. e.g., for /** field name of the element. e.g., for
name : "Joe" name : "Joe"
"name" is the fieldname "name" is the fieldname
*/ */
const char * fieldName() const { const char * fieldName() const {
if ( eoo() ) return ""; // no fieldname for it. if ( eoo() ) return ""; // no fieldname for it.
return data + 1; return data + 1;
} }
/**
* NOTE: size includes the NULL terminator.
*/
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_;
} }
const StringData fieldNameStringData() const {
return StringData(fieldName(), fieldNameSize() - 1);
}
/** raw data of the element's value (so be careful). */ /** raw data of the element's value (so be careful). */
const char * value() const { const char * value() const {
return (data + fieldNameSize() + 1); return (data + fieldNameSize() + 1);
} }
/** size in bytes of the element's value (when applicable). */ /** size in bytes of the element's value (when applicable). */
int valuesize() const { int valuesize() const {
return size() - fieldNameSize() - 1; return size() - fieldNameSize() - 1;
} }
bool isBoolean() const { return type() == mongo::Bool; } bool isBoolean() const { return type() == mongo::Bool; }
skipping to change at line 238 skipping to change at line 246
/** Size (length) of a string element. /** Size (length) of a string element.
You must assure of type String first. You must assure of type String first.
@return string size including terminating null @return string size including terminating null
*/ */
int valuestrsize() const { int valuestrsize() const {
return *reinterpret_cast< const int* >( value() ); return *reinterpret_cast< const int* >( value() );
} }
// for objects the size *includes* the size of the size field // for objects the size *includes* the size of the size field
int objsize() const { size_t objsize() const {
return *reinterpret_cast< const int* >( value() ); return static_cast< const size_t >( *reinterpret_cast< const ui
nt32_t* >( value() ) );
} }
/** Get a string's value. Also gives you start of the real data fo r an embedded object. /** Get a string's value. Also gives you start of the real data fo r an embedded object.
You must assure data is of an appropriate type first -- see als o valuestrsafe(). You must assure data is of an appropriate type first -- see als o valuestrsafe().
*/ */
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 " ". */
 End of changes. 6 change blocks. 
7 lines changed or deleted 16 lines changed or added


 bsonobjiterator.h   bsonobjiterator.h 
skipping to change at line 23 skipping to change at line 23
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <boost/preprocessor/cat.hpp> // like the ## operator but works wit h __LINE__ #include <boost/preprocessor/cat.hpp> // like the ## operator but works wit h __LINE__
#include "mongo/bson/bsonobj.h" #include "mongo/bson/bsonobj.h"
#include "mongo/base/disallow_copying.h"
namespace mongo { namespace mongo {
/** iterator for a BSONObj /** iterator for a BSONObj
Note each BSONObj ends with an EOO element: so you will get more() o n an empty Note each BSONObj ends with an EOO element: so you will get more() o n an empty
object, although next().eoo() will be true. object, although next().eoo() will be true.
The BSONObj must stay in scope for the duration of the iterator's ex ecution. The BSONObj must stay in scope for the duration of the iterator's ex ecution.
skipping to change at line 99 skipping to change at line 100
return BSONElement(_pos); return BSONElement(_pos);
} }
private: private:
const char* _pos; const char* _pos;
const char* _theend; const char* _theend;
}; };
/** Base class implementing ordered iteration through BSONElements. */ /** Base class implementing ordered iteration through BSONElements. */
class BSONIteratorSorted { class BSONIteratorSorted {
MONGO_DISALLOW_COPYING(BSONIteratorSorted);
public: public:
~BSONIteratorSorted() { ~BSONIteratorSorted() {
verify( _fields ); verify( _fields );
delete[] _fields; delete[] _fields;
_fields = 0; _fields = 0;
} }
bool more() { bool more() {
return _cur < _nfields; return _cur < _nfields;
} }
 End of changes. 2 change blocks. 
0 lines changed or deleted 2 lines changed or added


 btree_access_method.h   btree_access_method.h 
skipping to change at line 51 skipping to change at line 51
// superclass and subclasses (like this) can use them. // superclass and subclasses (like this) can use them.
using BtreeBasedAccessMethod::_descriptor; using BtreeBasedAccessMethod::_descriptor;
using BtreeBasedAccessMethod::_interface; using BtreeBasedAccessMethod::_interface;
using BtreeBasedAccessMethod::_ordering; using BtreeBasedAccessMethod::_ordering;
BtreeAccessMethod(IndexDescriptor* descriptor); BtreeAccessMethod(IndexDescriptor* descriptor);
virtual ~BtreeAccessMethod() { } virtual ~BtreeAccessMethod() { }
virtual Status newCursor(IndexCursor** out); virtual Status newCursor(IndexCursor** out);
// TODO(hk): Keep bucket deletion internal to this class.
private: private:
virtual void getKeys(const BSONObj& obj, BSONObjSet* keys); virtual void getKeys(const BSONObj& obj, BSONObjSet* keys);
// Our keys differ for V0 and V1. // Our keys differ for V0 and V1.
scoped_ptr<BtreeKeyGenerator> _keyGenerator; scoped_ptr<BtreeKeyGenerator> _keyGenerator;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
2 lines changed or deleted 0 lines changed or added


 btree_index_cursor.h   btree_index_cursor.h 
skipping to change at line 32 skipping to change at line 32
#include "mongo/db/diskloc.h" #include "mongo/db/diskloc.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/index/btree_interface.h" #include "mongo/db/index/btree_interface.h"
#include "mongo/db/index/index_cursor.h" #include "mongo/db/index/index_cursor.h"
#include "mongo/db/index/index_descriptor.h" #include "mongo/db/index/index_descriptor.h"
namespace mongo { namespace mongo {
class BtreeIndexCursor : public IndexCursor { class BtreeIndexCursor : public IndexCursor {
public: public:
virtual ~BtreeIndexCursor() { } virtual ~BtreeIndexCursor();
bool isEOF() const; bool isEOF() const;
// XXX SHORT TERM HACKS THAT MUST DIE: 2d index // See nasty comment in .cpp
virtual DiskLoc getBucket() const; virtual DiskLoc getBucket() const;
// XXX SHORT TERM HACKS THAT MUST DIE: 2d index
virtual int getKeyOfs() const; virtual int getKeyOfs() const;
// XXX SHORT TERM HACKS THAT MUST DIE: btree deletion /**
virtual void aboutToDeleteBucket(const DiskLoc& bucket); * Called from btree.cpp when we're about to delete a Btree bucket.
*/
static void aboutToDeleteBucket(const DiskLoc& bucket);
virtual Status setOptions(const CursorOptions& options); virtual Status setOptions(const CursorOptions& options);
virtual Status seek(const BSONObj& position); virtual Status seek(const BSONObj& position);
virtual Status seek(const vector<const BSONElement*>& position, // Btree-specific seeking functions.
const vector<bool>& inclusive); Status seek(const vector<const BSONElement*>& position,
const vector<bool>& inclusive);
virtual Status skip(const vector<const BSONElement*>& position,
const vector<bool>& inclusive); Status skip(const BSONObj &keyBegin, int keyBeginLen, bool afterKey
,
const vector<const BSONElement*>& keyEnd,
const vector<bool>& keyEndInclusive);
virtual BSONObj getKey() const; virtual BSONObj getKey() const;
virtual DiskLoc getValue() const; virtual DiskLoc getValue() const;
virtual void next(); virtual void next();
virtual Status savePosition(); virtual Status savePosition();
virtual Status restorePosition(); virtual Status restorePosition();
virtual string toString(); virtual string toString();
private: private:
// We keep the constructor private and only allow the AM to create us. // We keep the constructor private and only allow the AM to create us.
friend class BtreeAccessMethod; friend class BtreeAccessMethod;
// For handling bucket deletion.
static unordered_set<BtreeIndexCursor*> _activeCursors;
static SimpleMutex _activeCursorsMutex;
// Go forward by default. // Go forward by default.
BtreeIndexCursor(IndexDescriptor *descriptor, Ordering ordering, Bt reeInterface *interface); BtreeIndexCursor(IndexDescriptor *descriptor, Ordering ordering, Bt reeInterface *interface);
void skipUnusedKeys(); void skipUnusedKeys();
bool isSavedPositionValid(); bool isSavedPositionValid();
// Move to the next/prev. key. Used by normal getNext and also ski pping unused keys. // Move to the next/prev. key. Used by normal getNext and also ski pping unused keys.
void advance(const char* caller); void advance(const char* caller);
 End of changes. 6 change blocks. 
11 lines changed or deleted 18 lines changed or added


 btreecursor.h   btreecursor.h 
skipping to change at line 26 skipping to change at line 26
#pragma once #pragma once
#include <set> #include <set>
#include <vector> #include <vector>
#include "mongo/db/cursor.h" #include "mongo/db/cursor.h"
#include "mongo/db/diskloc.h" #include "mongo/db/diskloc.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/namespace_details.h" #include "mongo/db/namespace_details.h"
#include "mongo/db/index/btree_index_cursor.h"
#include "mongo/db/index/index_access_method.h" #include "mongo/db/index/index_access_method.h"
namespace mongo { namespace mongo {
class FieldRangeVector; class FieldRangeVector;
class FieldRangeVectorIterator; class FieldRangeVectorIterator;
/** /**
* A Cursor class for btree iteration. * A Cursor class for btree iteration.
* *
skipping to change at line 139 skipping to change at line 140
virtual void setKeyFieldsOnly( const shared_ptr<Projection::KeyOnly >& keyFieldsOnly ) { virtual void setKeyFieldsOnly( const shared_ptr<Projection::KeyOnly >& keyFieldsOnly ) {
_keyFieldsOnly = keyFieldsOnly; _keyFieldsOnly = keyFieldsOnly;
} }
virtual long long nscanned() { return _nscanned; } virtual long long nscanned() { return _nscanned; }
// XXX(hk): geo uses this for restoring state...for now. // XXX(hk): geo uses this for restoring state...for now.
virtual const DiskLoc getBucket() const; virtual const DiskLoc getBucket() const;
// XXX(hk): geo uses this too. :( // XXX(hk): geo uses this too. :(
virtual int getKeyOfs() const; virtual int getKeyOfs() const;
// XXX(hk): deletions go through a lengthy, scary path (btree.cpp -
> clientcursor.cpp ->
// cursor.cpp -> btreecursor.cpp) and this is part of it...for now.
virtual void aboutToDeleteBucket(const DiskLoc& b);
private: private:
BtreeCursor( NamespaceDetails* nsd, int theIndexNo, const IndexDeta ils& idxDetails ); BtreeCursor( NamespaceDetails* nsd, int theIndexNo, const IndexDeta ils& idxDetails );
virtual void init( const BSONObj& startKey, virtual void init( const BSONObj& startKey,
const BSONObj& endKey, const BSONObj& endKey,
bool endKeyInclusive, bool endKeyInclusive,
int direction ); int direction );
virtual void init( const shared_ptr<FieldRangeVector>& bounds, virtual void init( const shared_ptr<FieldRangeVector>& bounds,
skipping to change at line 209 skipping to change at line 207
bool _boundsMustMatch; // If iteration is aborted before a key matc hing _bounds is bool _boundsMustMatch; // If iteration is aborted before a key matc hing _bounds is
// identified, the cursor may be left pointi ng at a key that is not // identified, the cursor may be left pointi ng at a key that is not
// within bounds (_bounds->matchesKey( currK ey() ) may be false). // within bounds (_bounds->matchesKey( currK ey() ) may be false).
// _boundsMustMatch will be set to false acc ordingly. // _boundsMustMatch will be set to false acc ordingly.
shared_ptr<CoveredIndexMatcher> _matcher; shared_ptr<CoveredIndexMatcher> _matcher;
shared_ptr<Projection::KeyOnly> _keyFieldsOnly; shared_ptr<Projection::KeyOnly> _keyFieldsOnly;
bool _independentFieldRanges; bool _independentFieldRanges;
long long _nscanned; long long _nscanned;
// These variables are for index traversal. // These variables are for index traversal.
scoped_ptr<IndexCursor> _indexCursor; scoped_ptr<BtreeIndexCursor> _indexCursor;
scoped_ptr<IndexAccessMethod> _indexAM; scoped_ptr<IndexAccessMethod> _indexAM;
scoped_ptr<IndexDescriptor> _indexDescriptor; scoped_ptr<IndexDescriptor> _indexDescriptor;
bool _hitEnd; bool _hitEnd;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
5 lines changed or deleted 2 lines changed or added


 bufreader.h   bufreader.h 
skipping to change at line 100 skipping to change at line 100
/** return current position pointer, and advance by len */ /** return current position pointer, and advance by len */
const void* skip(unsigned len) { const void* skip(unsigned len) {
const char *nxt = ((char *) _pos) + len; const char *nxt = ((char *) _pos) + len;
if( _end < nxt ) throw eof(); if( _end < nxt ) throw eof();
const void *p = _pos; const void *p = _pos;
_pos = nxt; _pos = nxt;
return p; return p;
} }
/// reads a NUL terminated string
StringData readCStr() {
const char* start = static_cast<const char*>(pos());
size_t len = strnlen(start, remaining()-1);
if (start[len] != '\0') throw eof(); // no NUL byte in remainin
g bytes
skip(len + 1/*NUL byte*/);
return StringData(start, len);
}
void readStr(string& s) { void readStr(string& s) {
StringBuilder b; s = readCStr().toString();
while( 1 ) {
char ch;
read(ch);
if( ch == 0 )
break;
b << ch;
}
s = b.str();
} }
const void* pos() { return _pos; } const void* pos() { return _pos; }
const void* start() { return _start; } const void* start() { return _start; }
private: private:
const void *_start; const void *_start;
const void *_pos; const void *_pos;
const void *_end; const void *_end;
}; };
 End of changes. 2 change blocks. 
9 lines changed or deleted 11 lines changed or added


 client.h   client.h 
skipping to change at line 33 skipping to change at line 33
*/ */
#pragma once #pragma once
#include "mongo/pch.h" #include "mongo/pch.h"
#include "mongo/db/client_basic.h" #include "mongo/db/client_basic.h"
#include "mongo/db/d_concurrency.h" #include "mongo/db/d_concurrency.h"
#include "mongo/db/lasterror.h" #include "mongo/db/lasterror.h"
#include "mongo/db/lockstate.h" #include "mongo/db/lockstate.h"
#include "mongo/db/namespace-inl.h"
#include "mongo/db/stats/top.h" #include "mongo/db/stats/top.h"
#include "mongo/util/concurrency/rwlock.h" #include "mongo/util/concurrency/rwlock.h"
#include "mongo/util/concurrency/threadlocal.h" #include "mongo/util/concurrency/threadlocal.h"
#include "mongo/util/paths.h" #include "mongo/util/paths.h"
namespace mongo { namespace mongo {
extern class ReplSet *theReplSet; extern class ReplSet *theReplSet;
class AuthenticationInfo; class AuthenticationInfo;
class Database; class Database;
 End of changes. 1 change blocks. 
1 lines changed or deleted 0 lines changed or added


 clientOnly-private.h   clientOnly-private.h 
skipping to change at line 17 skipping to change at line 17
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
namespace mongo { namespace mongo {
class mutex;
namespace shell_utils { namespace shell_utils {
extern mongo::mutex &mongoProgramOutputMutex; extern mongo::mutex &mongoProgramOutputMutex;
} }
} }
 End of changes. 2 change blocks. 
0 lines changed or deleted 3 lines changed or added


 client_basic.h   client_basic.h 
skipping to change at line 28 skipping to change at line 28
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
#include "mongo/util/net/hostandport.h" #include "mongo/util/net/hostandport.h"
#include "mongo/util/net/message_port.h" #include "mongo/util/net/message_port.h"
namespace mongo { namespace mongo {
class AuthenticationInfo; class AuthenticationInfo;
class AuthenticationSession; class AuthenticationSession;
class AuthorizationManager; class AuthorizationSession;
/** /**
* this is the base class for Client and ClientInfo * this is the base class for Client and ClientInfo
* Client is for mongod * Client is for mongod
* ClientInfo is for mongos * ClientInfo is for mongos
* They should converge slowly * They should converge slowly
* The idea is this has the basic api so that not all code has to be du plicated * The idea is this has the basic api so that not all code has to be du plicated
*/ */
class ClientBasic : boost::noncopyable { class ClientBasic : boost::noncopyable {
public: public:
virtual ~ClientBasic(); virtual ~ClientBasic();
AuthenticationSession* getAuthenticationSession(); AuthenticationSession* getAuthenticationSession();
void resetAuthenticationSession(AuthenticationSession* newSession); void resetAuthenticationSession(AuthenticationSession* newSession);
void swapAuthenticationSession(boost::scoped_ptr<AuthenticationSess ion>& other); void swapAuthenticationSession(boost::scoped_ptr<AuthenticationSess ion>& other);
bool hasAuthorizationManager() const; bool hasAuthorizationSession() const;
AuthorizationManager* getAuthorizationManager() const; AuthorizationSession* getAuthorizationSession() const;
void setAuthorizationManager(AuthorizationManager* authorizationMan void setAuthorizationSession(AuthorizationSession* authorizationSes
ager); sion);
bool getIsLocalHostConnection() { bool getIsLocalHostConnection() {
if (!hasRemote()) { if (!hasRemote()) {
return false; return false;
} }
return getRemote().isLocalHost(); return getRemote().isLocalHost();
} }
virtual bool hasRemote() const { return _messagingPort; } virtual bool hasRemote() const { return _messagingPort; }
virtual HostAndPort getRemote() const { virtual HostAndPort getRemote() const {
skipping to change at line 70 skipping to change at line 70
AbstractMessagingPort * port() const { return _messagingPort; } AbstractMessagingPort * port() const { return _messagingPort; }
static ClientBasic* getCurrent(); static ClientBasic* getCurrent();
static bool hasCurrent(); static bool hasCurrent();
protected: protected:
ClientBasic(AbstractMessagingPort* messagingPort); ClientBasic(AbstractMessagingPort* messagingPort);
private: private:
boost::scoped_ptr<AuthenticationSession> _authenticationSession; boost::scoped_ptr<AuthenticationSession> _authenticationSession;
boost::scoped_ptr<AuthorizationManager> _authorizationManager; boost::scoped_ptr<AuthorizationSession> _authorizationSession;
AbstractMessagingPort* const _messagingPort; AbstractMessagingPort* const _messagingPort;
}; };
} }
 End of changes. 3 change blocks. 
6 lines changed or deleted 6 lines changed or added


 clientcursor.h   clientcursor.h 
skipping to change at line 40 skipping to change at line 40
#include "cursor.h" #include "cursor.h"
#include "jsobj.h" #include "jsobj.h"
#include "../util/net/message.h" #include "../util/net/message.h"
#include "../util/background.h" #include "../util/background.h"
#include "cc_by_loc.h" #include "cc_by_loc.h"
#include "diskloc.h" #include "diskloc.h"
#include "dbhelpers.h" #include "dbhelpers.h"
#include "matcher.h" #include "matcher.h"
#include "projection.h" #include "projection.h"
#include "s/d_chunk_manager.h"
#include "mongo/db/keypattern.h" #include "mongo/db/keypattern.h"
#include "mongo/s/collection_metadata.h"
#include "mongo/util/elapsed_tracker.h" #include "mongo/util/elapsed_tracker.h"
namespace mongo { namespace mongo {
typedef boost::recursive_mutex::scoped_lock recursive_scoped_lock; typedef boost::recursive_mutex::scoped_lock recursive_scoped_lock;
class Cursor; /* internal server cursor base class */ class Cursor; /* internal server cursor base class */
class ClientCursor; class ClientCursor;
class ParsedQuery; class ParsedQuery;
/* todo: make this map be per connection. this will prevent cursor hij acking security attacks perhaps. /* todo: make this map be per connection. this will prevent cursor hij acking security attacks perhaps.
skipping to change at line 291 skipping to change at line 291
void fillQueryResultFromObj( BufBuilder &b, const MatchDetails* det ails = NULL ) const; void fillQueryResultFromObj( BufBuilder &b, const MatchDetails* det ails = NULL ) const;
bool currentIsDup() { return _c->getsetdup( _c->currLoc() ); } bool currentIsDup() { return _c->getsetdup( _c->currLoc() ); }
bool currentMatches() { bool currentMatches() {
if ( ! _c->matcher() ) if ( ! _c->matcher() )
return true; return true;
return _c->matcher()->matchesCurrent( _c.get() ); return _c->matcher()->matchesCurrent( _c.get() );
} }
void setChunkManager( ShardChunkManagerPtr manager ){ _chunkManager void setCollMetadata( CollectionMetadataPtr metadata ){ _collMetada
= manager; } ta = metadata; }
ShardChunkManagerPtr getChunkManager(){ return _chunkManager; } CollectionMetadataPtr getCollMetadata(){ return _collMetadata; }
private: private:
void setLastLoc_inlock(DiskLoc); void setLastLoc_inlock(DiskLoc);
static ClientCursor* find_inlock(CursorId id, bool warn = true) { static ClientCursor* find_inlock(CursorId id, bool warn = true) {
CCById::iterator it = clientCursorsById.find(id); CCById::iterator it = clientCursorsById.find(id);
if ( it == clientCursorsById.end() ) { if ( it == clientCursorsById.end() ) {
if ( warn ) { if ( warn ) {
OCCASIONALLY out() << "ClientCursor::find(): cursor not found in map '" << id OCCASIONALLY out() << "ClientCursor::find(): cursor not found in map '" << id
<< "' (ok after a drop)" << endl; << "' (ok after a drop)" << endl;
skipping to change at line 374 skipping to change at line 374
/** Just for testing. */ /** Just for testing. */
OpTime getSlaveReadTill() const { return _slaveReadTill; } OpTime getSlaveReadTill() const { return _slaveReadTill; }
public: // static methods public: // static methods
static void idleTimeReport(unsigned millis); static void idleTimeReport(unsigned millis);
static void appendStats( BSONObjBuilder& result ); static void appendStats( BSONObjBuilder& result );
static unsigned numCursors() { return clientCursorsById.size(); } static unsigned numCursors() { return clientCursorsById.size(); }
static void informAboutToDeleteBucket(const DiskLoc& b);
static void aboutToDelete( const StringData& ns, static void aboutToDelete( const StringData& ns,
const NamespaceDetails* nsd, const NamespaceDetails* nsd,
const DiskLoc& dl ); const DiskLoc& dl );
static void find( const string& ns , set<CursorId>& all ); static void find( const string& ns , set<CursorId>& all );
private: // methods private: // methods
// cursors normally timeout after an inactivity period to prevent e xcess memory use // cursors normally timeout after an inactivity period to prevent e xcess memory use
// setting this prevents timeout of the cursor in question. // setting this prevents timeout of the cursor in question.
void noTimeout() { _pinValue++; } void noTimeout() { _pinValue++; }
CCByLoc& byLoc() { return _db->ccByLoc; }
Record* _recordForYield( RecordNeeds need ); Record* _recordForYield( RecordNeeds need );
static bool _erase_inlock(ClientCursor* cursor); static bool _erase_inlock(ClientCursor* cursor);
private: private:
CursorId _cursorid; CursorId _cursorid;
const string _ns; const string _ns;
Database * _db; Database * _db;
skipping to change at line 419 skipping to change at line 416
/* 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; // when true we are the delete and aboutToDelet e shouldn't manipulate us bool _doingDeletes; // when true we are the delete and aboutToDelet e shouldn't manipulate us
ElapsedTracker _yieldSometimesTracker; ElapsedTracker _yieldSometimesTracker;
ShardChunkManagerPtr _chunkManager; CollectionMetadataPtr _collMetadata;
public: public:
shared_ptr<ParsedQuery> pq; shared_ptr<ParsedQuery> pq;
shared_ptr<Projection> fields; // which fields query wants returned shared_ptr<Projection> fields; // which fields query wants returned
private: // static members private: // static members
static CCById clientCursorsById; static CCById clientCursorsById;
static long long numberTimedOut; static long long numberTimedOut;
static boost::recursive_mutex& ccmutex; // must use this for all statics above! static boost::recursive_mutex& ccmutex; // must use this for all statics above!
 End of changes. 6 change blocks. 
8 lines changed or deleted 5 lines changed or added


 cmdline.h   cmdline.h 
skipping to change at line 23 skipping to change at line 23
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include <vector> #include <vector>
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/platform/process_id.h"
#include "mongo/util/net/listen.h" #include "mongo/util/net/listen.h"
namespace boost { namespace boost {
namespace program_options { namespace program_options {
class options_description; class options_description;
class positional_options_description; class positional_options_description;
class variables_map; class variables_map;
} }
} }
skipping to change at line 128 skipping to change at line 129
std::string socket; // UNIX domain socket directory std::string socket; // UNIX domain socket directory
int maxConns; // Maximum number of simultaneous open conne ctions. int maxConns; // Maximum number of simultaneous open conne ctions.
std::string keyFile; // Path to keyfile, or empty if none. std::string keyFile; // Path to keyfile, or empty if none.
std::string pidFile; // Path to pid file, or empty if none. std::string pidFile; // Path to pid file, or empty if none.
std::string logpath; // Path to log file, if logging to a file; o therwise, empty. std::string logpath; // Path to log file, if logging to a file; o therwise, empty.
bool logAppend; // True if logging to a file in append mode. bool logAppend; // True if logging to a file in append mode.
bool logWithSyslog; // True if logging to syslog; must not be se t if logpath is set. bool logWithSyslog; // True if logging to syslog; must not be se t if logpath is set.
std::string clusterAuthMode; // Cluster authentication mode
bool isHttpInterfaceEnabled; // True if the dbwebserver should be e
nabled.
#ifndef _WIN32 #ifndef _WIN32
pid_t parentProc; // --fork pid of initial process ProcessId parentProc; // --fork pid of initial process
pid_t leaderProc; // --fork pid of leader process ProcessId leaderProc; // --fork pid of leader process
#endif #endif
#ifdef MONGO_SSL #ifdef MONGO_SSL
bool sslOnNormalPorts; // --sslOnNormalPorts bool sslOnNormalPorts; // --sslOnNormalPorts
std::string sslPEMKeyFile; // --sslPEMKeyFile std::string sslPEMKeyFile; // --sslPEMKeyFile
std::string sslPEMKeyPassword; // --sslPEMKeyPassword std::string sslPEMKeyPassword; // --sslPEMKeyPassword
std::string sslClusterFile; // --sslInternalKeyFile
std::string sslClusterPassword; // --sslInternalKeyPassword
std::string sslCAFile; // --sslCAFile std::string sslCAFile; // --sslCAFile
std::string sslCRLFile; // --sslCRLFile std::string sslCRLFile; // --sslCRLFile
bool sslWeakCertificateValidation; bool sslWeakCertificateValidation; // --sslWeakCertificateValidatio
bool sslFIPSMode; n
bool sslFIPSMode; // --sslFIPSMode
#endif #endif
/** /**
* Switches to enable experimental (unsupported) features. * Switches to enable experimental (unsupported) features.
*/ */
struct ExperimentalFeatures { struct ExperimentalFeatures {
ExperimentalFeatures() ExperimentalFeatures()
: indexStatsCmdEnabled(false) : indexStatsCmdEnabled(false)
, storageDetailsCmdEnabled(false) , storageDetailsCmdEnabled(false)
{} {}
skipping to change at line 195 skipping to change at line 200
}; };
// todo move to cmdline.cpp? // todo move to cmdline.cpp?
inline CmdLine::CmdLine() : inline CmdLine::CmdLine() :
port(DefaultDBPort), rest(false), jsonp(false), indexBuildRetry(tru e), quiet(false), port(DefaultDBPort), rest(false), jsonp(false), indexBuildRetry(tru e), quiet(false),
noTableScan(false), prealloc(true), preallocj(true), smallfiles(siz eof(int*) == 4), noTableScan(false), prealloc(true), preallocj(true), smallfiles(siz eof(int*) == 4),
configsvr(false), quota(false), quotaFiles(8), cpu(false), configsvr(false), quota(false), quotaFiles(8), cpu(false),
durOptions(0), objcheck(true), oplogSize(0), defaultProfile(0), durOptions(0), objcheck(true), oplogSize(0), defaultProfile(0),
slowMS(100), defaultLocalThresholdMillis(15), pretouch(0), movePara noia( false ), slowMS(100), defaultLocalThresholdMillis(15), pretouch(0), movePara noia( false ),
syncdelay(60), noUnixSocket(false), doFork(0), socket("/tmp"), maxC onns(DEFAULT_MAX_CONN), syncdelay(60), noUnixSocket(false), doFork(0), socket("/tmp"), maxC onns(DEFAULT_MAX_CONN),
logAppend(false), logWithSyslog(false) logAppend(false), logWithSyslog(false), isHttpInterfaceEnabled(fals e)
{ {
started = time(0); started = time(0);
journalCommitInterval = 0; // 0 means use default journalCommitInterval = 0; // 0 means use default
dur = false; dur = false;
#if defined(_DURABLEDEFAULTON) #if defined(_DURABLEDEFAULTON)
dur = true; dur = true;
#endif #endif
if( sizeof(void*) == 8 ) if( sizeof(void*) == 8 )
dur = true; dur = true;
 End of changes. 7 change blocks. 
6 lines changed or deleted 13 lines changed or added


 collection.h   collection.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 Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/db/namespace.h" #include "mongo/db/namespace_details.h"
namespace mongo { namespace mongo {
class Collection { class Collection {
public: public:
NamespaceDetails * const d; NamespaceDetails * const d;
NamespaceDetailsTransient * const nsd; NamespaceDetailsTransient * const nsd;
}; };
} }
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 commands.h   commands.h 
skipping to change at line 22 skipping to change at line 22
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <vector> #include <vector>
#include "mongo/db/auth/action_set.h" #include "mongo/base/status.h"
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/privilege.h" #include "mongo/db/auth/privilege.h"
#include "mongo/db/client_basic.h" #include "mongo/db/client_basic.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/util/mongoutils/str.h"
namespace mongo { namespace mongo {
class BSONObj; class BSONObj;
class BSONObjBuilder; class BSONObjBuilder;
class Client; class Client;
class Timer; class Timer;
/** mongodb "commands" (sent via db.$cmd.findOne(...)) /** mongodb "commands" (sent via db.$cmd.findOne(...))
subclass to make a command. define a singleton object for it. subclass to make a command. define a singleton object for it.
skipping to change at line 109 skipping to change at line 106
return false; return false;
} }
/* Override and return true to if true,log the operation (logOp()) to the replication log. /* Override and return true to if true,log the operation (logOp()) to the replication log.
(not done if fromRepl of course) (not done if fromRepl of course)
Note if run() returns false, we do NOT log. Note if run() returns false, we do NOT log.
*/ */
virtual bool logTheOp() { return false; } virtual bool logTheOp() { return false; }
/**
* Override and return fales if the command opcounters should not b
e incremented on
* behalf of this command.
*/
virtual bool shouldAffectCommandCounter() const { return true; }
virtual void help( stringstream& help ) const; virtual void help( stringstream& help ) const;
/** /**
* Appends to "*out" the privileges required to run this command on * Checks if the given client is authorized to run this command on
database "dbname" with database "dbname"
* the invocation described by "cmdObj". * with the invocation described by "cmdObj".
*/ */
virtual void addRequiredPrivileges(const std::string& dbname, virtual Status checkAuthForCommand(ClientBasic* client,
const BSONObj& cmdObj, const std::string& dbname,
std::vector<Privilege>* out) = 0 const BSONObj& cmdObj);
;
/* Return true if a replica set secondary should go into "recoverin g" /* Return true if a replica set secondary should go into "recoverin g"
(unreadable) state while running this command. (unreadable) state while running this command.
*/ */
virtual bool maintenanceMode() const { return false; } virtual bool maintenanceMode() const { return false; }
/* Return true if command should be permitted when a replica set se condary is in "recovering" /* Return true if command should be permitted when a replica set se condary is in "recovering"
(unreadable) state. (unreadable) state.
*/ */
virtual bool maintenanceOk() const { return true; /* assumed true p rior to commit */ } virtual bool maintenanceOk() const { return true; /* assumed true p rior to commit */ }
/** @param webUI expose the command in the web ui as localhost:2801 7/<name> /** @param webUI expose the command in the web ui as localhost:2801 7/<name>
@param oldName an optional old, deprecated name for the command @param oldName an optional old, deprecated name for the command
*/ */
Command(const char *_name, bool webUI = false, const char *oldName = 0); Command(StringData _name, bool webUI = false, StringData oldName = StringData());
virtual ~Command() {} virtual ~Command() {}
protected: protected:
/**
* Appends to "*out" the privileges required to run this command on
database "dbname" with
* the invocation described by "cmdObj". New commands shouldn't im
plement this, they should
* implement checkAuthForCommand instead.
*/
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {
// The default implementation of addRequiredPrivileges should n
ever be hit.
fassertFailed(16940);
}
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();
} }
static void logIfSlow( const Timer& cmdTimer, const string& msg); static void logIfSlow( const Timer& cmdTimer, const string& msg);
skipping to change at line 189 skipping to change at line 205
BSONObjBuilder& result, BSONObjBuilder& result,
bool fromRepl ); bool fromRepl );
// Helper for setting errmsg and ok field in command result object. // Helper for setting errmsg and ok field in command result object.
static void appendCommandStatus(BSONObjBuilder& result, bool ok, co nst std::string& errmsg); static void appendCommandStatus(BSONObjBuilder& result, bool ok, co nst std::string& errmsg);
// Set by command line. Controls whether or not testing-only comma nds should be available. // Set by command line. Controls whether or not testing-only comma nds should be available.
static int testCommandsEnabled; static int testCommandsEnabled;
}; };
class CmdShutdown : public Command {
public:
virtual bool requiresAuth() { return true; }
virtual bool adminOnly() const { return true; }
virtual bool localHostOnlyIfNoAuth(const BSONObj& cmdObj) { return
true; }
virtual bool logTheOp() {
return false;
}
virtual bool slaveOk() const {
return true;
}
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {
ActionSet actions;
actions.addAction(ActionType::shutdown);
out->push_back(Privilege(AuthorizationManager::SERVER_RESOURCE_
NAME, actions));
}
virtual LockType locktype() const { return NONE; }
virtual void help( stringstream& help ) const;
CmdShutdown() : Command("shutdown") {}
bool run(const string& dbname, BSONObj& cmdObj, int options, string
& errmsg, BSONObjBuilder& result, bool fromRepl);
private:
bool shutdownHelper();
};
bool _runCommands(const char *ns, BSONObj& jsobj, BufBuilder &b, BSONOb jBuilder& anObjBuilder, bool fromRepl, int queryOptions); bool _runCommands(const char *ns, BSONObj& jsobj, BufBuilder &b, BSONOb jBuilder& anObjBuilder, bool fromRepl, int queryOptions);
} // namespace mongo } // namespace mongo
 End of changes. 8 change blocks. 
41 lines changed or deleted 31 lines changed or added


 config.h   config.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/>.
*/ */
/* This file is things related to the "grid configuration": /* This file is things related to the "grid configuration":
- what machines make up the db component of our cloud - what machines make up the db component of our cloud
- where various ranges of things live - where various ranges of things live
*/ */
#pragma once #pragma once
#include "../db/namespace.h"
#include "../client/model.h"
#include "mongo/client/dbclient_rs.h" #include "mongo/client/dbclient_rs.h"
#include "mongo/s/chunk.h"
#include "chunk.h" #include "mongo/s/shard.h"
#include "shard.h" #include "mongo/s/shardkey.h"
#include "shardkey.h"
namespace mongo { namespace mongo {
class ConfigServer; class ConfigServer;
class DBConfig; class DBConfig;
typedef boost::shared_ptr<DBConfig> DBConfigPtr; typedef boost::shared_ptr<DBConfig> DBConfigPtr;
extern DBConfigPtr configServerPtr; extern DBConfigPtr configServerPtr;
extern ConfigServer& configServer; extern ConfigServer& configServer;
skipping to change at line 222 skipping to change at line 219
return _primary.getConnString(); return _primary.getConnString();
} }
/** /**
call at startup, this will initiate connection to the grid db call at startup, this will initiate connection to the grid db
*/ */
bool init( vector<string> configHosts ); bool init( vector<string> configHosts );
bool init( const std::string& s ); bool init( const std::string& s );
/**
* Check hosts are unique. Returns true if all configHosts
* hostname:port entries are unique. Otherwise return false
* and fill errmsg with message containing the offending server.
*/
bool checkHostsAreUnique( const vector<string>& configHosts, string
* errmsg );
bool allUp(); bool allUp();
bool allUp( string& errmsg ); bool allUp( string& errmsg );
int dbConfigVersion(); int dbConfigVersion();
int dbConfigVersion( DBClientBase& conn ); int dbConfigVersion( DBClientBase& conn );
void reloadSettings(); void reloadSettings();
/** /**
* Create a metadata change log entry in the config.changelog colle ction. * Create a metadata change log entry in the config.changelog colle ction.
 End of changes. 3 change blocks. 
6 lines changed or deleted 11 lines changed or added


 connections.h   connections.h 
skipping to change at line 24 skipping to change at line 24
* *
* You should have received a copy of the GNU Affero General Public Lice nse * You should have received a copy of the GNU Affero General Public Lice nse
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <map> #include <map>
#include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/security_key.h"
#include "mongo/db/repl/rs.h" // extern Tee* rslog #include "mongo/db/repl/rs.h" // extern Tee* rslog
namespace mongo { namespace mongo {
/** here we keep a single connection (with reconnect) for a set of host s, /** here we keep a single connection (with reconnect) for a set of host s,
one each, and allow one user at a time per host. if in use already for that one each, and allow one user at a time per host. if in use already for that
host, we block. so this is an easy way to keep a 1-deep pool of co nnections host, we block. so this is an easy way to keep a 1-deep pool of co nnections
that many threads can share. that many threads can share.
thread-safe. thread-safe.
skipping to change at line 56 skipping to change at line 57
// A flag to keep ScopedConns open when all other sockets are disco nnected // A flag to keep ScopedConns open when all other sockets are disco nnected
static const unsigned keepOpen; static const unsigned keepOpen;
/** throws assertions if connect failure etc. */ /** throws assertions if connect failure etc. */
ScopedConn(const std::string& hostport); ScopedConn(const std::string& hostport);
~ScopedConn() { ~ScopedConn() {
// conLock releases... // conLock releases...
} }
void reconnect() { void reconnect() {
connInfo->cc.reset(new DBClientConnection(true, 0, connInfo->ge tTimeout())); connInfo->cc.reset(new DBClientConnection(true, 0, connInfo->ge tTimeout()));
connInfo->cc->_logLevel = 2; connInfo->cc->_logLevel = logger::LogSeverity::Debug(2);
connInfo->connected = false; connInfo->connected = false;
connect(); connect();
} }
void setTimeout(time_t timeout) { void setTimeout(time_t timeout) {
connInfo->setTimeout(timeout); connInfo->setTimeout(timeout);
} }
/* If we were to run a query and not exhaust the cursor, future use of the connection would be problematic. /* If we were to run a query and not exhaust the cursor, future use of the connection would be problematic.
So here what we do is wrapper known safe methods and not allow c ursor-style queries at all. This makes So here what we do is wrapper known safe methods and not allow c ursor-style queries at all. This makes
skipping to change at line 91 skipping to change at line 92
static mongo::mutex mapMutex; static mongo::mutex mapMutex;
struct ConnectionInfo { struct ConnectionInfo {
mongo::mutex lock; mongo::mutex lock;
scoped_ptr<DBClientConnection> cc; scoped_ptr<DBClientConnection> cc;
bool connected; bool connected;
ConnectionInfo() : lock("ConnectionInfo"), ConnectionInfo() : lock("ConnectionInfo"),
cc(new DBClientConnection(/*reconnect*/ true, cc(new DBClientConnection(/*reconnect*/ true,
/*replicaSet*/ 0, /*replicaSet*/ 0,
/*timeout*/ ReplSetConfig::DEFAUL T_HB_TIMEOUT)), /*timeout*/ ReplSetConfig::DEFAUL T_HB_TIMEOUT)),
connected(false) { connected(false) {
cc->_logLevel = 2; cc->_logLevel = logger::LogSeverity::Debug(2);
} }
void tagPort() { void tagPort() {
MessagingPort& mp = cc->port(); MessagingPort& mp = cc->port();
mp.tag |= ScopedConn::keepOpen; mp.tag |= ScopedConn::keepOpen;
} }
void setTimeout(time_t timeout) { void setTimeout(time_t timeout) {
_timeout = timeout; _timeout = timeout;
cc->setSoTimeout(_timeout); cc->setSoTimeout(_timeout);
skipping to change at line 131 skipping to change at line 132
return false; return false;
} }
connInfo->connected = true; connInfo->connected = true;
connInfo->tagPort(); connInfo->tagPort();
// if we cannot authenticate against a member, then either its ke y file // if we cannot authenticate against a member, then either its ke y file
// or our key file has to change. if our key file has to change, we'll // or our key file has to change. if our key file has to change, we'll
// be rebooting. if their file has to change, they'll be rebooted so the // be rebooting. if their file has to change, they'll be rebooted so the
// connection created above will go dead, reconnect, and reauth. // connection created above will go dead, reconnect, and reauth.
if (AuthorizationManager::isAuthEnabled()) { if (AuthorizationManager::isAuthEnabled()) {
if (!connInfo->cc->auth("local", return authenticateInternalUser(connInfo->cc.get());
internalSecurity.user,
internalSecurity.pwd,
err,
false)) {
log() << "could not authenticate against " << _hostport <
< ", " << err << rsLog;
return false;
}
} }
return true; return true;
} }
}; };
inline ScopedConn::ScopedConn(const std::string& hostport) : _hostport( hostport) { inline ScopedConn::ScopedConn(const std::string& hostport) : _hostport( hostport) {
bool first = false; bool first = false;
{ {
scoped_lock lk(mapMutex); scoped_lock lk(mapMutex);
 End of changes. 4 change blocks. 
11 lines changed or deleted 4 lines changed or added


 const_element-inl.h   const_element-inl.h 
skipping to change at line 175 skipping to change at line 175
} }
inline StringData ConstElement::getFieldName() const { inline StringData ConstElement::getFieldName() const {
return _basis.getFieldName(); return _basis.getFieldName();
} }
inline Element::RepIdx ConstElement::getIdx() const { inline Element::RepIdx ConstElement::getIdx() const {
return _basis.getIdx(); return _basis.getIdx();
} }
inline std::string ConstElement::toString() const {
return _basis.toString();
}
template<typename Builder>
inline void ConstElement::writeElement(Builder* builder, const StringDa
ta* fieldName) const {
return _basis.writeElement(builder, fieldName);
}
inline bool operator==(const ConstElement& l, const ConstElement& r) { inline bool operator==(const ConstElement& l, const ConstElement& r) {
return l._basis == r._basis; return l._basis == r._basis;
} }
inline bool operator!=(const ConstElement& l, const ConstElement& r) { inline bool operator!=(const ConstElement& l, const ConstElement& r) {
return !(l == r); return !(l == r);
} }
inline bool operator==(const Element& l, const ConstElement& r) { inline bool operator==(const Element& l, const ConstElement& r) {
return ConstElement(l) == r; return ConstElement(l) == r;
 End of changes. 1 change blocks. 
0 lines changed or deleted 10 lines changed or added


 const_element.h   const_element.h 
skipping to change at line 91 skipping to change at line 91
inline void writeTo(BSONObjBuilder* builder) const; inline void writeTo(BSONObjBuilder* builder) const;
inline void writeArrayTo(BSONArrayBuilder* builder) const; inline void writeArrayTo(BSONArrayBuilder* builder) const;
inline bool ok() const; inline bool ok() const;
inline const Document& getDocument() const; inline const Document& getDocument() const;
inline BSONType getType() const; inline BSONType getType() const;
inline bool isType(BSONType type) const; inline bool isType(BSONType type) const;
inline StringData getFieldName() const; inline StringData getFieldName() const;
inline Element::RepIdx getIdx() const; inline Element::RepIdx getIdx() const;
inline std::string toString() const;
friend bool operator==(const ConstElement&, const ConstElement&); friend bool operator==(const ConstElement&, const ConstElement&);
private: private:
friend class Document;
template<typename Builder>
inline void writeElement(Builder* builder, const StringData* fieldN
ame = NULL) const;
Element _basis; Element _basis;
}; };
/** See notes for operator==(const Element&, const Element&). The multi ple variants listed /** See notes for operator==(const Element&, const Element&). The multi ple variants listed
* here enable cross type comparisons between Elements and ConstElemen ts. * here enable cross type comparisons between Elements and ConstElemen ts.
*/ */
inline bool operator==(const ConstElement& l, const ConstElement& r); inline bool operator==(const ConstElement& l, const ConstElement& r);
inline bool operator!=(const ConstElement& l, const ConstElement& r); inline bool operator!=(const ConstElement& l, const ConstElement& r);
inline bool operator==(const Element& l, const ConstElement& r); inline bool operator==(const Element& l, const ConstElement& r);
inline bool operator!=(const Element& l, const ConstElement& r); inline bool operator!=(const Element& l, const ConstElement& r);
 End of changes. 2 change blocks. 
0 lines changed or deleted 8 lines changed or added


 counters.h   counters.h 
// counters.h // Copyright 2012 the V8 project authors. All rights reserved.
/* // Redistribution and use in source and binary forms, with or without
* Copyright (C) 2010 10gen Inc. // modification, are permitted provided that the following conditions are
* // met:
* This program is free software: you can redistribute it and/or modify //
* it under the terms of the GNU Affero General Public License, version // * Redistributions of source code must retain the above copyright
3, // notice, this list of conditions and the following disclaimer.
* as published by the Free Software Foundation. // * Redistributions in binary form must reproduce the above
* // copyright notice, this list of conditions and the following
* This program is distributed in the hope that it will be useful, // disclaimer in the documentation and/or other materials provided
* but WITHOUT ANY WARRANTY; without even the implied warranty of // with the distribution.
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // * Neither the name of Google Inc. nor the names of its
* GNU Affero General Public License for more details. // contributors may be used to endorse or promote products derived
* // from this software without specific prior written permission.
* You should have received a copy of the GNU Affero General Public Lice //
nse // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* along with this program. If not, see <http://www.gnu.org/licenses/>. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*/ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
#pragma once // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#include "mongo/pch.h" // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
#include "../jsobj.h" // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#include "../../util/net/message.h" // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#include "../../util/processinfo.h" // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#include "../../util/concurrency/spin_lock.h" // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "mongo/db/pdfile.h"
#ifndef V8_COUNTERS_H_
namespace mongo { #define V8_COUNTERS_H_
/** #include "../include/v8.h"
* for storing operation counters #include "allocation.h"
* note: not thread safe. ok with that for speed
*/ namespace v8 {
class OpCounters { namespace internal {
public:
// StatsCounters is an interface for plugging into external
OpCounters(); // counters for monitoring. Counters can be looked up and
void incInsertInWriteLock(int n) { _insert.x += n; } // manipulated by name.
void gotInsert() { _insert++; }
void gotQuery() { _query++; } class StatsTable {
void gotUpdate() { _update++; } public:
void gotDelete() { _delete++; } // Register an application-defined function where
void gotGetMore() { _getmore++; } // counters can be looked up.
void gotCommand() { _command++; } void SetCounterFunction(CounterLookupCallback f) {
lookup_function_ = f;
void gotOp( int op , bool isCommand ); }
BSONObj getObj() const; // Register an application-defined function to create
// a histogram for passing to the AddHistogramSample function
// thse are used by snmp, and other things, do not remove void SetCreateHistogramFunction(CreateHistogramCallback f) {
const AtomicUInt * getInsert() const { return &_insert; } create_histogram_function_ = f;
const AtomicUInt * getQuery() const { return &_query; } }
const AtomicUInt * getUpdate() const { return &_update; }
const AtomicUInt * getDelete() const { return &_delete; } // Register an application-defined function to add a sample
const AtomicUInt * getGetMore() const { return &_getmore; } // to a histogram created with CreateHistogram function
const AtomicUInt * getCommand() const { return &_command; } void SetAddHistogramSampleFunction(AddHistogramSampleCallback f) {
add_histogram_sample_function_ = f;
private: }
void _checkWrap();
bool HasCounterFunction() const {
// todo: there will be a lot of cache line contention on these. ne return lookup_function_ != NULL;
ed to do something }
// else eventually.
AtomicUInt _insert; // Lookup the location of a counter by name. If the lookup
AtomicUInt _query; // is successful, returns a non-NULL pointer for writing the
AtomicUInt _update; // value of the counter. Each thread calling this function
AtomicUInt _delete; // may receive a different location to store it's counter.
AtomicUInt _getmore; // The return value must not be cached and re-used across
AtomicUInt _command; // threads, although a single thread is free to cache it.
}; int* FindLocation(const char* name) {
if (!lookup_function_) return NULL;
extern OpCounters globalOpCounters; return lookup_function_(name);
extern OpCounters replOpCounters; }
class NetworkCounter { // Create a histogram by name. If the create is successful,
public: // returns a non-NULL pointer for use with AddHistogramSample
NetworkCounter() : _bytesIn(0), _bytesOut(0), _requests(0), _overfl // function. min and max define the expected minimum and maximum
ows(0) {} // sample values. buckets is the maximum number of buckets
void hit( long long bytesIn , long long bytesOut ); // that the samples will be grouped into.
void append( BSONObjBuilder& b ); void* CreateHistogram(const char* name,
private: int min,
long long _bytesIn; int max,
long long _bytesOut; size_t buckets) {
long long _requests; if (!create_histogram_function_) return NULL;
return create_histogram_function_(name, min, max, buckets);
}
// Add a sample to a histogram created with the CreateHistogram
// function.
void AddHistogramSample(void* histogram, int sample) {
if (!add_histogram_sample_function_) return;
return add_histogram_sample_function_(histogram, sample);
}
private:
StatsTable();
CounterLookupCallback lookup_function_;
CreateHistogramCallback create_histogram_function_;
AddHistogramSampleCallback add_histogram_sample_function_;
friend class Isolate;
DISALLOW_COPY_AND_ASSIGN(StatsTable);
};
// StatsCounters are dynamically created values which can be tracked in
// the StatsTable. They are designed to be lightweight to create and
// easy to use.
//
// Internally, a counter represents a value in a row of a StatsTable.
// The row has a 32bit value for each process/thread in the table and also
// a name (stored in the table metadata). Since the storage location can b
e
// thread-specific, this class cannot be shared across threads.
//
// This class is designed to be POD initialized. It will be registered wit
h
// the counter system on first use. For example:
// StatsCounter c = { "c:myctr", NULL, false };
struct StatsCounter {
const char* name_;
int* ptr_;
bool lookup_done_;
// Sets the counter to a specific value.
void Set(int value) {
int* loc = GetPtr();
if (loc) *loc = value;
}
// Increments the counter.
void Increment() {
int* loc = GetPtr();
if (loc) (*loc)++;
}
void Increment(int value) {
int* loc = GetPtr();
if (loc)
(*loc) += value;
}
// Decrements the counter.
void Decrement() {
int* loc = GetPtr();
if (loc) (*loc)--;
}
void Decrement(int value) {
int* loc = GetPtr();
if (loc) (*loc) -= value;
}
// Is this counter enabled?
// Returns false if table is full.
bool Enabled() {
return GetPtr() != NULL;
}
// Get the internal pointer to the counter. This is used
// by the code generator to emit code that manipulates a
// given counter without calling the runtime system.
int* GetInternalPointer() {
int* loc = GetPtr();
ASSERT(loc != NULL);
return loc;
}
protected:
// Returns the cached address of this counter location.
int* GetPtr() {
if (lookup_done_) return ptr_;
lookup_done_ = true;
ptr_ = FindLocationInStatsTable();
return ptr_;
}
private:
int* FindLocationInStatsTable() const;
};
// StatsCounterTimer t = { { L"t:foo", NULL, false }, 0, 0 };
struct StatsCounterTimer {
StatsCounter counter_;
int64_t start_time_;
int64_t stop_time_;
// Start the timer.
void Start();
// Stop the timer and record the results.
void Stop();
// Returns true if the timer is running.
bool Running() {
return counter_.Enabled() && start_time_ != 0 && stop_time_ == 0;
}
};
// A Histogram represents a dynamically created histogram in the StatsTable
.
//
// This class is designed to be POD initialized. It will be registered wit
h
// the histogram system on first use. For example:
// Histogram h = { "myhist", 0, 10000, 50, NULL, false };
struct Histogram {
const char* name_;
int min_;
int max_;
int num_buckets_;
void* histogram_;
bool lookup_done_;
// Add a single sample to this histogram.
void AddSample(int sample);
// Returns true if this histogram is enabled.
bool Enabled() {
return GetHistogram() != NULL;
}
protected:
// Returns the handle to the histogram.
void* GetHistogram() {
if (!lookup_done_) {
lookup_done_ = true;
histogram_ = CreateHistogram();
}
return histogram_;
}
private:
void* CreateHistogram() const;
};
// A HistogramTimer allows distributions of results to be created
// HistogramTimer t = { {L"foo", 0, 10000, 50, NULL, false}, 0, 0 };
struct HistogramTimer {
Histogram histogram_;
int64_t start_time_;
int64_t stop_time_;
// Start the timer.
void Start();
// Stop the timer and record the results.
void Stop();
// Returns true if the timer is running.
bool Running() {
return histogram_.Enabled() && (start_time_ != 0) && (stop_time_ == 0);
}
};
// Helper class for scoping a HistogramTimer.
class HistogramTimerScope BASE_EMBEDDED {
public:
explicit HistogramTimerScope(HistogramTimer* timer) :
timer_(timer) {
timer_->Start();
}
~HistogramTimerScope() {
timer_->Stop();
}
private:
HistogramTimer* timer_;
};
long long _overflows; } } // namespace v8::internal
SpinLock _lock; #endif // V8_COUNTERS_H_
};
extern NetworkCounter networkCounter;
}
 End of changes. 3 change blocks. 
86 lines changed or deleted 273 lines changed or added


 curop.h   curop.h 
skipping to change at line 25 skipping to change at line 25
* You should have received a copy of the GNU Affero General Public Lice nse * You should have received a copy of the GNU Affero General Public Lice nse
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <vector> #include <vector>
#include "mongo/bson/util/atomic_int.h" #include "mongo/bson/util/atomic_int.h"
#include "mongo/db/client.h" #include "mongo/db/client.h"
#include "mongo/db/namespace-inl.h" #include "mongo/db/storage/namespace.h"
#include "mongo/util/concurrency/spin_lock.h" #include "mongo/util/concurrency/spin_lock.h"
#include "mongo/util/net/hostandport.h" #include "mongo/util/net/hostandport.h"
#include "mongo/util/progress_meter.h" #include "mongo/util/progress_meter.h"
#include "mongo/util/time_support.h" #include "mongo/util/time_support.h"
namespace mongo { namespace mongo {
class CurOp; class CurOp;
/* lifespan is different than CurOp because of recursives with DBDirect Client */ /* lifespan is different than CurOp because of recursives with DBDirect Client */
skipping to change at line 123 skipping to change at line 123
} }
void reset( int sz = 0 ) { void reset( int sz = 0 ) {
_lock.lock(); _lock.lock();
_reset( sz ); _reset( sz );
_lock.unlock(); _lock.unlock();
} }
void set( const BSONObj& o ) { void set( const BSONObj& o ) {
scoped_spinlock lk(_lock); scoped_spinlock lk(_lock);
int sz = o.objsize(); size_t sz = o.objsize();
if ( sz > (int) sizeof(_buf) ) { if ( sz > sizeof(_buf) ) {
_reset(TOO_BIG_SENTINEL); _reset(TOO_BIG_SENTINEL);
} }
else { else {
memcpy(_buf, o.objdata(), sz ); memcpy(_buf, o.objdata(), sz );
} }
} }
int size() const { return *_size; } int size() const { return *_size; }
bool have() const { return size() > 0; } bool have() const { return size() > 0; }
 End of changes. 2 change blocks. 
3 lines changed or deleted 3 lines changed or added


 cursor.h   cursor.h 
skipping to change at line 111 skipping to change at line 111
/* Implement these if you want the cursor to be "tailable" */ /* Implement these if you want the cursor to be "tailable" */
/* Request that the cursor starts tailing after advancing past last record. */ /* Request that the cursor starts tailing after advancing past last record. */
/* The implementation may or may not honor this request. */ /* The implementation may or may not honor this request. */
virtual void setTailable() {} virtual void setTailable() {}
/* indicates if tailing is enabled. */ /* indicates if tailing is enabled. */
virtual bool tailable() { virtual bool tailable() {
return false; return false;
} }
virtual void aboutToDeleteBucket(const DiskLoc& b) { }
/* optional to implement. if implemented, means 'this' is a protot ype */ /* optional to implement. if implemented, means 'this' is a protot ype */
virtual Cursor* clone() { virtual Cursor* clone() {
return 0; return 0;
} }
virtual BSONObj indexKeyPattern() { virtual BSONObj indexKeyPattern() {
return BSONObj(); return BSONObj();
} }
virtual bool supportGetMore() = 0; virtual bool supportGetMore() = 0;
skipping to change at line 214 skipping to change at line 212
/** /**
* Manually set the value of keyFieldsOnly() so it may be accessed later. Implementations * Manually set the value of keyFieldsOnly() so it may be accessed later. Implementations
* that generate their own keyFieldsOnly() must assert. * that generate their own keyFieldsOnly() must assert.
*/ */
virtual void setKeyFieldsOnly( const shared_ptr<Projection::KeyOnly > &keyFieldsOnly ) { virtual void setKeyFieldsOnly( const shared_ptr<Projection::KeyOnly > &keyFieldsOnly ) {
massert( 16159, "manual keyFieldsOnly config not allowed", fals e ); massert( 16159, "manual keyFieldsOnly config not allowed", fals e );
} }
virtual void explainDetails( BSONObjBuilder& b ) { return; } virtual void explainDetails( BSONObjBuilder& b ) { return; }
/// Should getmore handle locking for you
virtual bool requiresLock() { return true; }
/// Should this cursor be destroyed when it's namespace is deleted
virtual bool shouldDestroyOnNSDeletion() { return true; }
}; };
// strategy object implementing direction of traversal. // strategy object implementing direction of traversal.
class AdvanceStrategy { class AdvanceStrategy {
public: public:
virtual ~AdvanceStrategy() { } virtual ~AdvanceStrategy() { }
virtual DiskLoc next( const DiskLoc &prev ) const = 0; virtual DiskLoc next( const DiskLoc &prev ) const = 0;
}; };
const AdvanceStrategy *forward(); const AdvanceStrategy *forward();
 End of changes. 2 change blocks. 
2 lines changed or deleted 6 lines changed or added


 d_logic.h   d_logic.h 
skipping to change at line 23 skipping to change at line 23
* *
* You should have received a copy of the GNU Affero General Public Lice nse * You should have received a copy of the GNU Affero General Public Lice nse
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/pch.h" #include "mongo/pch.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/s/d_chunk_manager.h" #include "mongo/s/collection_metadata.h"
#include "mongo/s/chunk_version.h" #include "mongo/s/chunk_version.h"
#include "mongo/util/concurrency/ticketholder.h" #include "mongo/util/concurrency/ticketholder.h"
namespace mongo { namespace mongo {
class Database; class Database;
class DiskLoc; class DiskLoc;
typedef ChunkVersion ConfigVersion;
// -------------- // --------------
// --- global state --- // --- global state ---
// -------------- // --------------
class ShardingState { class ShardingState {
public: public:
ShardingState(); ShardingState();
bool enabled() const { return _enabled; } bool enabled() const { return _enabled; }
const string& getConfigServer() const { return _configServer; } const string& getConfigServer() const { return _configServer; }
skipping to change at line 63 skipping to change at line 61
string getShardName() { return _shardName; } string getShardName() { return _shardName; }
string getShardHost() { return _shardHost; } string getShardHost() { return _shardHost; }
/** Reverts back to a state where this mongod is not sharded. */ /** Reverts back to a state where this mongod is not sharded. */
void resetShardingState(); void resetShardingState();
// versioning support // versioning support
bool hasVersion( const string& ns ); bool hasVersion( const string& ns );
bool hasVersion( const string& ns , ConfigVersion& version ); bool hasVersion( const string& ns , ChunkVersion& version );
const ConfigVersion getVersion( const string& ns ) const; const ChunkVersion getVersion( const string& ns ) const;
/** /**
* Uninstalls the manager for a given collection. This should be us * Uninstalls the metadata for a given collection. This should be u
ed when the collection is dropped. sed when the collection
* is dropped.
* *
* NOTE: * NOTE:
* An existing collection with no chunks on this shard will have * An existing collection with no chunks on this shard will have
a manager on version 0, which is different than a metadata on version 0,
* a dropped collection, which will not have a manager. * which is different than a dropped collection, which will not h
ave metadata.
* *
* TODO * TODO:
* When sharding state is enabled, absolutely all collections sho * All collections should have metadata. (The non-sharded ones ar
uld have a manager. (The non-sharded ones are e a degenerate case of
* a be degenerate case of one-chunk collections). * one-chunk collections).
* For now, a dropped collection and an non-sharded one are indis
tinguishable (SERVER-1849)
* *
* @param ns the collection to be dropped * @param ns the collection to be dropped
*/ */
void resetVersion( const string& ns ); void resetVersion( const string& ns );
/** /**
* Requests to access a collection at a certain version. If the col * Requests to access a collection at a certain version. If the col
lection's manager is not at that version it lection's metadata is not
* will try to update itself to the newest version. The request is * at that version it will try to update itself to the newest versi
only granted if the version is the current or on. The request is only
* the newest one. * granted if the version is the current or the newest one.
* *
* @param ns collection to be accessed * @param ns collection to be accessed
* @param version (IN) the client believe this collection is on and * @param version (IN) the client believe this collection is on and
(OUT) the version the manager is actually in (OUT) the version the
* metadata is actually in
* @return true if the access can be allowed at the provided versio n * @return true if the access can be allowed at the provided versio n
*/ */
bool trySetVersion( const string& ns , ConfigVersion& version ); bool trySetVersion( const string& ns , ChunkVersion& version );
void appendInfo( BSONObjBuilder& b ); void appendInfo( BSONObjBuilder& b );
// querying support // querying support
bool needShardChunkManager( const string& ns ) const; bool needCollectionMetadata( const string& ns ) const;
ShardChunkManagerPtr getShardChunkManager( const string& ns ); CollectionMetadataPtr getCollectionMetadata( const string& ns );
// chunk migrate and split support // chunk migrate and split support
/** /**
* Creates and installs a new chunk manager for a given collection * Creates and installs a new chunk metadata for a given collection
by "forgetting" about one of its chunks. by "forgetting" about
* The new manager uses the provided version, which has to be highe * one of its chunks. The new metadata uses the provided version,
r than the current manager's. which has to be higher
* One exception: if the forgotten chunk is the last one in this sh * than the current metadata's shard version.
ard for the collection, version has to be 0. *
* One exception: if the forgotten chunk is the last one in this sh
ard for the collection,
* version has to be 0.
* *
* If it runs successfully, clients need to grab the new version to access the collection. * If it runs successfully, clients need to grab the new version to access the collection.
* *
* @param ns the collection * @param ns the collection
* @param min max the chunk to eliminate from the current manager * @param min max the chunk to eliminate from the current metadata
* @param version at which the new manager should be at * @param version at which the new metadata should be at
*/ */
void donateChunk( const string& ns , const BSONObj& min , const BSO NObj& max , ChunkVersion version ); void donateChunk( const string& ns , const BSONObj& min , const BSO NObj& max , ChunkVersion version );
/** /**
* Creates and installs a new chunk manager for a given collection * Creates and installs new chunk metadata for a given collection b
by reclaiming a previously donated chunk. y reclaiming a previously
* The previous manager's version has to be provided. * donated chunk. The previous metadata's shard version has to be
provided.
* *
* If it runs successfully, clients that became stale by the previo * If it runs successfully, clients that became stale by the previo
us donateChunk will be able to access the us donateChunk will be
* collection again. * able to access the collection again.
* *
* @param ns the collection * @param ns the collection
* @param min max the chunk to reclaim and add to the current manag * @param min max the chunk to reclaim and add to the current metad
er ata
* @param version at which the new manager should be at * @param version at which the new metadata should be at
*/ */
void undoDonateChunk( const string& ns , const BSONObj& min , const BSONObj& max , ChunkVersion version ); void undoDonateChunk( const string& ns , const BSONObj& min , const BSONObj& max , ChunkVersion version );
/** /**
* Creates and installs a new chunk manager for a given collection * Remembers a chunk range between 'min' and 'max' as a range which
by splitting one of its chunks in two or more. will have data migrated
* The version for the first split chunk should be provided. The su * into it. This data can then be protected against cleanup of orp
bsequent chunks' version would be the latter with the haned data.
* minor portion incremented. *
* Overlapping pending ranges will be removed, so it is only safe t
o use this when you know
* your metadata view is definitive, such as at the start of a migr
ation.
*
* @return false with errMsg if the range is owned by this shard
*/
bool notePending( const string& ns,
const BSONObj& min,
const BSONObj& max,
string* errMsg );
/**
* Stops tracking a chunk range between 'min' and 'max' that previo
usly was having data
* migrated into it. This data is no longer protected against clea
nup of orphaned data.
*
* To avoid removing pending ranges of other operations, ensure tha
t this is only used when
* a migration is still active.
* TODO: Because migrations may currently be active when a collecti
on drops, an epoch is
* necessary to ensure the pending metadata change is still applica
ble.
*
* @return false with errMsg if the range is owned by the shard or
the epoch of the metadata
* has changed
*/
bool forgetPending( const string& ns,
const BSONObj& min,
const BSONObj& max,
const OID& epoch,
string* errMsg );
/**
* Creates and installs a new chunk metadata for a given collection
by splitting one of its
* chunks in two or more. The version for the first split chunk sho
uld be provided. The
* subsequent chunks' version would be the latter with the minor po
rtion incremented.
* *
* The effect on clients will depend on the version used. If the ma * The effect on clients will depend on the version used. If the ma
jor portion is the same as the current shards, jor portion is the same
* clients shouldn't perceive the split. * as the current shards, clients shouldn't perceive the split.
* *
* @param ns the collection * @param ns the collection
* @param min max the chunk that should be split * @param min max the chunk that should be split
* @param splitKeys point in which to split * @param splitKeys point in which to split
* @param version at which the new manager should be at * @param version at which the new metadata should be at
*/ */
void splitChunk( const string& ns , const BSONObj& min , const BSON Obj& max , const vector<BSONObj>& splitKeys , void splitChunk( const string& ns , const BSONObj& min , const BSON Obj& max , const vector<BSONObj>& splitKeys ,
ChunkVersion version ); ChunkVersion version );
bool inCriticalMigrateSection(); bool inCriticalMigrateSection();
/** /**
* @return true if we are NOT in the critical section * @return true if we are NOT in the critical section
*/ */
bool waitTillNotInCriticalSection( int maxSecondsToWait ); bool waitTillNotInCriticalSection( int maxSecondsToWait );
skipping to change at line 165 skipping to change at line 199
string _shardName; string _shardName;
string _shardHost; string _shardHost;
// protects state below // protects state below
mutable mongo::mutex _mutex; mutable mongo::mutex _mutex;
// protects accessing the config server // protects accessing the config server
// Using a ticket holder so we can have multiple redundant tries at any given time // Using a ticket holder so we can have multiple redundant tries at any given time
mutable TicketHolder _configServerTickets; mutable TicketHolder _configServerTickets;
// map from a namespace into the ensemble of chunk ranges that are // Map from a namespace into the metadata we need for each collecti
stored in this mongod on on this shard
// a ShardChunkManager carries all state we need for a collection a typedef map<string,CollectionMetadataPtr> CollectionMetadataMap;
t this shard, including its version information CollectionMetadataMap _collMetadata;
typedef map<string,ShardChunkManagerPtr> ChunkManagersMap;
ChunkManagersMap _chunks;
}; };
extern ShardingState shardingState; extern ShardingState shardingState;
/** /**
* one per connection from mongos * one per connection from mongos
* holds version state for each namespace * holds version state for each namespace
*/ */
class ShardedConnectionInfo { class ShardedConnectionInfo {
public: public:
ShardedConnectionInfo(); ShardedConnectionInfo();
const OID& getID() const { return _id; } const OID& getID() const { return _id; }
bool hasID() const { return _id.isSet(); } bool hasID() const { return _id.isSet(); }
void setID( const OID& id ); void setID( const OID& id );
const ConfigVersion getVersion( const string& ns ) const; const ChunkVersion getVersion( const string& ns ) const;
void setVersion( const string& ns , const ConfigVersion& version ); void setVersion( const string& ns , const ChunkVersion& version );
static ShardedConnectionInfo* get( bool create ); static ShardedConnectionInfo* get( bool create );
static void reset(); static void reset();
static void addHook(); static void addHook();
bool inForceVersionOkMode() const { bool inForceVersionOkMode() const {
return _forceVersionOk; return _forceVersionOk;
} }
void enterForceVersionOkMode() { _forceVersionOk = true; } void enterForceVersionOkMode() { _forceVersionOk = true; }
void leaveForceVersionOkMode() { _forceVersionOk = false; } void leaveForceVersionOkMode() { _forceVersionOk = false; }
private: private:
OID _id; OID _id;
bool _forceVersionOk; // if this is true, then chunk version #s are n't check, and all ops are allowed bool _forceVersionOk; // if this is true, then chunk version #s are n't check, and all ops are allowed
typedef map<string,ConfigVersion> NSVersionMap; typedef map<string,ChunkVersion> NSVersionMap;
NSVersionMap _versions; NSVersionMap _versions;
static boost::thread_specific_ptr<ShardedConnectionInfo> _tl; static boost::thread_specific_ptr<ShardedConnectionInfo> _tl;
}; };
struct ShardForceVersionOkModeBlock { struct ShardForceVersionOkModeBlock {
ShardForceVersionOkModeBlock() { ShardForceVersionOkModeBlock() {
info = ShardedConnectionInfo::get( false ); info = ShardedConnectionInfo::get( false );
if ( info ) if ( info )
info->enterForceVersionOkMode(); info->enterForceVersionOkMode();
skipping to change at line 239 skipping to change at line 272
/** /**
* @return true if we have any shard info for the ns * @return true if we have any shard info for the ns
*/ */
bool haveLocalShardingInfo( const string& ns ); bool haveLocalShardingInfo( const string& ns );
/** /**
* @return true if the current threads shard version is ok, or not in s harded version * @return true if the current threads shard version is ok, or not in s harded version
* Also returns an error message and the Config/ChunkVersions causing c onflicts * Also returns an error message and the Config/ChunkVersions causing c onflicts
*/ */
bool shardVersionOk( const string& ns , string& errmsg, ConfigVersion& bool shardVersionOk( const string& ns,
received, ConfigVersion& wanted ); string& errmsg,
ChunkVersion& received,
ChunkVersion& wanted );
/** /**
* @return true if we took care of the message and nothing else should be done * @return true if we took care of the message and nothing else should be done
*/ */
struct DbResponse; struct DbResponse;
bool _handlePossibleShardedMessage( Message &m, DbResponse * dbresponse ); bool _handlePossibleShardedMessage( Message &m, DbResponse * dbresponse );
/** What does this do? document please? */ /** What does this do? document please? */
inline bool handlePossibleShardedMessage( Message &m, DbResponse * dbre sponse ) { inline bool handlePossibleShardedMessage( Message &m, DbResponse * dbre sponse ) {
skipping to change at line 264 skipping to change at line 300
/** /**
* If a migration for the chunk in 'ns' where 'obj' lives is occurring, save this log entry * If a migration for the chunk in 'ns' where 'obj' lives is occurring, save this log entry
* if it's relevant. The entries saved here are later transferred to th e receiving side of * if it's relevant. The entries saved here are later transferred to th e receiving side of
* the migration. A relevant entry is an insertion, a deletion, or an u pdate. * the migration. A relevant entry is an insertion, a deletion, or an u pdate.
*/ */
void logOpForSharding( const char * opstr, void logOpForSharding( const char * opstr,
const char * ns, const char * ns,
const BSONObj& obj, const BSONObj& obj,
BSONObj * patt, BSONObj * patt,
const BSONObj* fullObj ); const BSONObj* fullObj,
bool forMigrateCleanup );
void aboutToDeleteForSharding( const StringData& ns, const Database* db , const DiskLoc& dl ); void aboutToDeleteForSharding( const StringData& ns, const Database* db , const DiskLoc& dl );
} }
 End of changes. 23 change blocks. 
64 lines changed or deleted 111 lines changed or added


 database.h   database.h 
skipping to change at line 39 skipping to change at line 39
class MongoDataFile; class MongoDataFile;
/** /**
* Database represents a database database * Database represents a database database
* Each database database has its own set of files -- dbname.ns, dbname .0, dbname.1, ... * Each database database has its own set of files -- dbname.ns, dbname .0, dbname.1, ...
* NOT memory mapped * NOT memory mapped
*/ */
class Database { class Database {
public: public:
// you probably need to be in dbHolderMutex when constructing this // you probably need to be in dbHolderMutex when constructing this
Database(const char *nm, /*out*/ bool& newDb, const string& _path = Database(const char *nm, /*out*/ bool& newDb, const string& path =
dbpath); dbpath);
private:
~Database(); // closes files and other cleanup see below.
public:
/* you must use this to close - there is essential code in this met hod that is not in the ~Database destructor. /* you must use this to close - there is essential code in this met hod that is not in the ~Database destructor.
thus the destructor is private. this could be cleaned up one da y... thus the destructor is private. this could be cleaned up one da y...
*/ */
static void closeDatabase( const char *db, const string& path ); static void closeDatabase( const string& db, const string& path );
const string& name() const { return _name; }
const string& path() const { return _path; }
void openAllFiles();
void clearTmpCollections(); void clearTmpCollections();
/** /**
* tries to make sure that this hasn't been deleted * tries to make sure that this hasn't been deleted
*/ */
bool isOk() const { return magic == 781231; } bool isOk() const { return _magic == 781231; }
bool isEmpty() { return ! namespaceIndex.allocated(); } bool isEmpty() { return ! _namespaceIndex.allocated(); }
/** /**
* total file size of Database in bytes * total file size of Database in bytes
*/ */
long long fileSize() const; long long fileSize() const;
int numFiles() const; int numFiles() const;
/** /**
* returns file valid for file number n * returns file valid for file number n
*/ */
boost::filesystem::path fileName( int n ) const; boost::filesystem::path fileName( int n ) const;
private:
bool exists(int n) const;
bool openExistingFile( int n );
public:
/** /**
* return file n. if it doesn't exist, create it * return file n. if it doesn't exist, create it
*/ */
MongoDataFile* getFile( int n, int sizeNeeded = 0, bool preallocate Only = false ); MongoDataFile* getFile( int n, int sizeNeeded = 0, bool preallocate Only = false );
MongoDataFile* addAFile( int sizeNeeded, bool preallocateNextFile ) ; MongoDataFile* addAFile( int sizeNeeded, bool preallocateNextFile ) ;
/** /**
* makes sure we have an extra file at the end that is empty * makes sure we have an extra file at the end that is empty
* safe to call this multiple times - the implementation will only preallocate one file * safe to call this multiple times - the implementation will only preallocate one file
skipping to change at line 106 skipping to change at line 101
*/ */
bool setProfilingLevel( int newLevel , string& errmsg ); bool setProfilingLevel( int newLevel , string& errmsg );
void flushFiles( bool sync ); void flushFiles( bool sync );
/** /**
* @return true if ns is part of the database * @return true if ns is part of the database
* ns=foo.bar, db=foo returns true * ns=foo.bar, db=foo returns true
*/ */
bool ownsNS( const string& ns ) const { bool ownsNS( const string& ns ) const {
if ( ! startsWith( ns , name ) ) if ( ! startsWith( ns , _name ) )
return false; return false;
return ns[name.size()] == '.'; return ns[_name.size()] == '.';
} }
const RecordStats& recordStats() const { return _recordStats; } const RecordStats& recordStats() const { return _recordStats; }
RecordStats& recordStats() { return _recordStats; } RecordStats& recordStats() { return _recordStats; }
int getProfilingLevel() const { return _profile; }
const char* getProfilingNS() const { return _profileName.c_str(); }
CCByLoc& ccByLoc() { return _ccByLoc; }
const NamespaceIndex& namespaceIndex() const { return _namespaceInd
ex; }
NamespaceIndex& namespaceIndex() { return _namespaceIndex; }
/**
* @return name of an existing database with same text name but dif
ferent
* casing, if one exists. Otherwise the empty string is returned.
If
* 'duplicates' is specified, it is filled with all duplicate names
.
*/
static string duplicateUncasedName( bool inholderlockalready, const
string &name, const string &path, set< string > *duplicates = 0 );
private: private:
~Database(); // closes files and other cleanup see below.
/** /**
* @throws DatabaseDifferCaseCode if the name is a duplicate based on * @throws DatabaseDifferCaseCode if the name is a duplicate based on
* case insensitive matching. * case insensitive matching.
*/ */
void checkDuplicateUncasedNames(bool inholderlockalready) const; void checkDuplicateUncasedNames(bool inholderlockalready) const;
public:
bool exists(int n) const;
void openAllFiles();
/** /**
* @return name of an existing database with same text name but dif * throws exception if error encounted
ferent * @return true if the file was opened
* casing, if one exists. Otherwise the empty string is returned. * false if no errors, but file doesn't exist
If
* 'duplicates' is specified, it is filled with all duplicate names
.
*/ */
static string duplicateUncasedName( bool inholderlockalready, const bool openExistingFile( int n );
string &name, const string &path, set< string > *duplicates = 0 );
const string name; // "alleyinsider"
const string path;
private: const string _name; // "alleyinsider"
const string _path; // "/data/db"
// must be in the dbLock when touching this (and write locked when writing to of course) // must be in the dbLock when touching this (and write locked when writing to of course)
// however during Database object construction we aren't, which is ok as it isn't yet visible // however during Database object construction we aren't, which is ok as it isn't yet visible
// to others and we are in the dbholder lock then. // to others and we are in the dbholder lock then.
vector<MongoDataFile*> _files; vector<MongoDataFile*> _files;
public: // this should be private later NamespaceIndex _namespaceIndex;
const string _profileName; // "alleyinsider.system.profile"
NamespaceIndex namespaceIndex; CCByLoc _ccByLoc; // use by ClientCursor
const string profileName; // "alleyinsider.system.profile"
CCByLoc ccByLoc;
int magic; // used for making sure the object is still loaded in me
mory
int getProfilingLevel() const { return _profile; }
private:
RecordStats _recordStats; RecordStats _recordStats;
int _profile; // 0=off. int _profile; // 0=off.
int _magic; // used for making sure the object is still loaded in m
emory
}; };
} // namespace mongo } // namespace mongo
 End of changes. 18 change blocks. 
38 lines changed or deleted 51 lines changed or added


 databaseholder.h   databaseholder.h 
skipping to change at line 22 skipping to change at line 22
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/db/database.h" #include "mongo/db/database.h"
#include "mongo/db/namespacestring.h" #include "mongo/db/namespace_string.h"
namespace mongo { namespace mongo {
/** /**
* path + dbname -> Database * path + dbname -> Database
*/ */
class DatabaseHolder { class DatabaseHolder {
typedef map<string,Database*> DBs; typedef map<string,Database*> DBs;
typedef map<string,DBs> Paths; typedef map<string,DBs> Paths;
// todo: we want something faster than this if called a lot: // todo: we want something faster than this if called a lot:
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 dbclient_rs.h   dbclient_rs.h 
skipping to change at line 640 skipping to change at line 640
*/ */
explicit TagSet(const BSONArray& tags); explicit TagSet(const BSONArray& tags);
/** /**
* Advance to the next tag. * Advance to the next tag.
* *
* @throws AssertionException if iterator is exhausted before this is called. * @throws AssertionException if iterator is exhausted before this is called.
*/ */
void next(); void next();
/**
* Rests the iterator to point to the first element (if there is a
tag).
*/
void reset();
// //
// Getters // Getters
// //
/** /**
* @return the current tag. Returned tag is invalid if isExhausted is true. * @return the current tag. Returned tag is invalid if isExhausted is true.
*/ */
const BSONObj& getCurrentTag() const; const BSONObj& getCurrentTag() const;
/** /**
skipping to change at line 666 skipping to change at line 671
* destroying the returned iterator. * destroying the returned iterator.
*/ */
BSONObjIterator* getIterator() const; BSONObjIterator* getIterator() const;
/** /**
* @returns true if the other TagSet has the same tag set specifica tion with * @returns true if the other TagSet has the same tag set specifica tion with
* this tag set, disregarding where the current iterator is poi nting to. * this tag set, disregarding where the current iterator is poi nting to.
*/ */
bool equals(const TagSet& other) const; bool equals(const TagSet& other) const;
const BSONArray& getTagBSON() const;
private: private:
/** /**
* This is purposely undefined as the semantics for assignment can be * This is purposely undefined as the semantics for assignment can be
* confusing. This is because BSONArrayIteratorSorted shouldn't be * confusing. This is because BSONArrayIteratorSorted shouldn't be
* copied (because of how it manages internal buffer). * copied (because of how it manages internal buffer).
*/ */
TagSet& operator=(const TagSet& other); TagSet& operator=(const TagSet& other);
BSONObj _currentTag; BSONObj _currentTag;
bool _isExhausted; bool _isExhausted;
// Important: do not re-order _tags & _tagIterator // Important: do not re-order _tags & _tagIterator
BSONArray _tags; BSONArray _tags;
BSONArrayIteratorSorted _tagIterator; scoped_ptr<BSONArrayIteratorSorted> _tagIterator;
}; };
struct ReadPreferenceSetting { struct ReadPreferenceSetting {
/** /**
* @parm pref the read preference mode. * @parm pref the read preference mode.
* @param tag the tag set. Note that this object will have the * @param tag the tag set. Note that this object will have the
* tag set will have this in a reset state (meaning, this * tag set will have this in a reset state (meaning, this
* object's copy of tag will have the iterator in the initial * object's copy of tag will have the iterator in the initial
* position). * position).
*/ */
ReadPreferenceSetting(ReadPreference pref, const TagSet& tag): ReadPreferenceSetting(ReadPreference pref, const TagSet& tag):
pref(pref), tags(tag) { pref(pref), tags(tag) {
} }
inline bool equals(const ReadPreferenceSetting& other) const { inline bool equals(const ReadPreferenceSetting& other) const {
return pref == other.pref && tags.equals(other.tags); return pref == other.pref && tags.equals(other.tags);
} }
BSONObj toBSON() const;
const ReadPreference pref; const ReadPreference pref;
TagSet tags; TagSet tags;
}; };
} }
 End of changes. 4 change blocks. 
1 lines changed or deleted 11 lines changed or added


 dbclientcursor.h   dbclientcursor.h 
skipping to change at line 81 skipping to change at line 81
/** /**
restore an object previously returned by next() to the cursor restore an object previously returned by next() to the cursor
*/ */
void putBack( const BSONObj &o ) { _putBack.push( o.getOwned() ); } void putBack( const BSONObj &o ) { _putBack.push( o.getOwned() ); }
/** throws AssertionException if get back { $err : ... } */ /** throws AssertionException if get back { $err : ... } */
BSONObj nextSafe() { BSONObj nextSafe() {
BSONObj o = next(); BSONObj o = next();
if( strcmp(o.firstElementFieldName(), "$err") == 0 ) { if( strcmp(o.firstElementFieldName(), "$err") == 0 ) {
string s = "nextSafe(): " + o.toString(); string s = "nextSafe(): " + o.toString();
if( logLevel >= 5 ) LOG(5) << s;
log() << s << endl;
uasserted(13106, s); uasserted(13106, s);
} }
return o; return o;
} }
/** peek ahead at items buffered for future next() calls. /** peek ahead at items buffered for future next() calls.
never requests new data from the server. so peek only effectiv e never requests new data from the server. so peek only effectiv e
with what is already buffered. with what is already buffered.
WARNING: no support for _putBack yet! WARNING: no support for _putBack yet!
*/ */
skipping to change at line 133 skipping to change at line 132
/** see ResultFlagType (constants.h) for flag values /** see ResultFlagType (constants.h) for flag values
mostly these flags are for internal purposes - mostly these flags are for internal purposes -
ResultFlag_ErrSet is the possible exception to that ResultFlag_ErrSet is the possible exception to that
*/ */
bool hasResultFlag( int flag ) { bool hasResultFlag( int flag ) {
_assertIfNull(); _assertIfNull();
return (resultFlags & flag) != 0; return (resultFlags & flag) != 0;
} }
/// Change batchSize after construction. Can change after requestin
g first batch.
void setBatchSize(int newBatchSize) { batchSize = newBatchSize; }
DBClientCursor( DBClientBase* client, const string &_ns, BSONObj _q uery, int _nToReturn, DBClientCursor( DBClientBase* client, const string &_ns, BSONObj _q uery, int _nToReturn,
int _nToSkip, const BSONObj *_fieldsToReturn, int q ueryOptions , int bs ) : int _nToSkip, const BSONObj *_fieldsToReturn, int q ueryOptions , int bs ) :
_client(client), _client(client),
ns(_ns), ns(_ns),
query(_query), query(_query),
nToReturn(_nToReturn), nToReturn(_nToReturn),
haveLimit( _nToReturn > 0 && !(queryOptions & QueryOption_Curso rTailable)), haveLimit( _nToReturn > 0 && !(queryOptions & QueryOption_Curso rTailable)),
nToSkip(_nToSkip), nToSkip(_nToSkip),
fieldsToReturn(_fieldsToReturn), fieldsToReturn(_fieldsToReturn),
opts(queryOptions), opts(queryOptions),
 End of changes. 2 change blocks. 
2 lines changed or deleted 5 lines changed or added


 dbclientinterface.h   dbclientinterface.h 
skipping to change at line 25 skipping to change at line 25
* 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 "mongo/pch.h" #include "mongo/pch.h"
#include <boost/function.hpp>
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/logger/log_severity.h"
#include "mongo/platform/atomic_word.h" #include "mongo/platform/atomic_word.h"
#include "mongo/util/net/message.h" #include "mongo/util/net/message.h"
#include "mongo/util/net/message_port.h" #include "mongo/util/net/message_port.h"
namespace mongo { namespace mongo {
/** the query field 'options' can have these bits set: */ /** the query field 'options' can have these bits set: */
enum QueryOptions { enum QueryOptions {
/** Tailable means cursor is not closed when the last data is retri eved. rather, the cursor marks /** Tailable means cursor is not closed when the last data is retri eved. rather, the cursor marks
the final object's position. you can resume using the cursor la ter, from where it was located, the final object's position. you can resume using the cursor la ter, from where it was located,
skipping to change at line 579 skipping to change at line 582
}; };
/** /**
DB "commands" DB "commands"
Basically just invocations of connection.$cmd.findOne({...}); Basically just invocations of connection.$cmd.findOne({...});
*/ */
class DBClientWithCommands : public DBClientInterface { class DBClientWithCommands : public DBClientInterface {
set<string> _seenIndexes; set<string> _seenIndexes;
public: public:
/** controls how chatty the client is about network errors & such. See log.h */ /** controls how chatty the client is about network errors & such. See log.h */
int _logLevel; logger::LogSeverity _logLevel;
DBClientWithCommands() : _logLevel(0), DBClientWithCommands() : _logLevel(logger::LogSeverity::Log()),
_cachedAvailableOptions( (enum QueryOptions)0 ), _cachedAvailableOptions( (enum QueryOptions)0 ),
_haveCachedAvailableOptions(false) { } _haveCachedAvailableOptions(false) { }
/** helper function. run a simple command where the command expres sion is simply /** helper function. run a simple command where the command expres sion is simply
{ command : 1 } { command : 1 }
@param info -- where to put result object. may be null if call er doesn't need that info @param info -- where to put result object. may be null if call er doesn't need that info
@param command -- command name @param command -- command name
@return true if the command returned "ok". @return true if the command returned "ok".
*/ */
bool simpleCommand(const string &dbname, BSONObj *info, const strin g &command); bool simpleCommand(const string &dbname, BSONObj *info, const strin g &command);
skipping to change at line 616 skipping to change at line 619
virtual bool runCommand(const string &dbname, const BSONObj& cmd, B SONObj &info, virtual bool runCommand(const string &dbname, const BSONObj& cmd, B SONObj &info,
int options=0); int options=0);
/** /**
* Authenticate a user. * Authenticate a user.
* *
* The "params" BSONObj should be initialized with some of the fiel ds below. Which fields * The "params" BSONObj should be initialized with some of the fiel ds below. Which fields
* are required depends on the mechanism, which is mandatory. * are required depends on the mechanism, which is mandatory.
* *
* "mechanism": The string name of the sasl mechanism to use. Mandatory. * "mechanism": The string name of the sasl mechanism to use. Mandatory.
* "user": The string name of the principal to authenticate. M andatory. * "user": The string name of the user to authenticate. Mandat ory.
* "userSource": The database target of the auth command, which identifies the location * "userSource": The database target of the auth command, which identifies the location
* of the credential information for the principal. May be "$external" if * of the credential information for the user. May be "$ex ternal" if
* credential information is stored outside of the mongo cl uster. Mandatory. * credential information is stored outside of the mongo cl uster. Mandatory.
* "pwd": The password data. * "pwd": The password data.
* "digestPassword": Boolean, set to true if the "pwd" is undig ested (default). * "digestPassword": Boolean, set to true if the "pwd" is undig ested (default).
* "serviceName": The GSSAPI service name to use. Defaults to "mongodb". * "serviceName": The GSSAPI service name to use. Defaults to "mongodb".
* "serviceHostname": The GSSAPI hostname to use. Defaults to the name of the remote * "serviceHostname": The GSSAPI hostname to use. Defaults to the name of the remote
* host. * host.
* *
* Other fields in "params" are silently ignored. * Other fields in "params" are silently ignored.
* *
* Returns normally on success, and throws on error. Throws a DBEx ception with getCode() == * Returns normally on success, and throws on error. Throws a DBEx ception with getCode() ==
skipping to change at line 659 skipping to change at line 662
* @param info the result object for the logout command (provided f or backwards * @param info the result object for the logout command (provided f or backwards
* compatibility with mongo shell) * compatibility with mongo shell)
*/ */
virtual void logout(const string& dbname, BSONObj& info); virtual void logout(const string& dbname, BSONObj& info);
/** count number of objects in collection ns that match the query c riteria specified /** count number of objects in collection ns that match the query c riteria specified
throws UserAssertion if database returns an error throws UserAssertion if database returns an error
*/ */
virtual unsigned long long count(const string &ns, const BSONObj& q uery = BSONObj(), int options=0, int limit=0, int skip=0 ); virtual unsigned long long count(const string &ns, const BSONObj& q uery = BSONObj(), int options=0, int limit=0, int skip=0 );
string createPasswordDigest( const string &username , const string &clearTextPassword ); static string createPasswordDigest(const string &username, const st ring &clearTextPassword);
/** returns true in isMaster parm if this db is the current master /** returns true in isMaster parm if this db is the current master
of a replica pair. of a replica pair.
pass in info for more details e.g.: pass in info for more details e.g.:
{ "ismaster" : 1.0 , "msg" : "not paired" , "ok" : 1.0 } { "ismaster" : 1.0 , "msg" : "not paired" , "ok" : 1.0 }
returns true if command invoked successfully. returns true if command invoked successfully.
*/ */
virtual bool isMaster(bool& isMaster, BSONObj *info=0); virtual bool isMaster(bool& isMaster, BSONObj *info=0);
skipping to change at line 980 skipping to change at line 983
* Use the MONGODB-CR protocol to authenticate as "username" agains t the database "dbname", * Use the MONGODB-CR protocol to authenticate as "username" agains t the database "dbname",
* with the given password. If digestPassword is false, the passwo rd is assumed to be * with the given password. If digestPassword is false, the passwo rd is assumed to be
* pre-digested. Returns false on failure, and sets "errmsg". * pre-digested. Returns false on failure, and sets "errmsg".
*/ */
bool _authMongoCR(const string &dbname, bool _authMongoCR(const string &dbname,
const string &username, const string &username,
const string &pwd, const string &pwd,
string& errmsg, string& errmsg,
bool digestPassword); bool digestPassword);
/**
* Use the MONGODB-X509 protocol to authenticate as "username. The
certificate details
* has already been communicated automatically as part of the conne
ct call.
* Returns false on failure and set "errmsg".
*/
bool _authX509(const string&dbname,
const string &username,
string& errmsg);
private: private:
enum QueryOptions _cachedAvailableOptions; enum QueryOptions _cachedAvailableOptions;
bool _haveCachedAvailableOptions; bool _haveCachedAvailableOptions;
}; };
/** /**
abstract class that implements the core db operations abstract class that implements the core db operations
*/ */
class DBClientBase : public DBClientWithCommands, public DBConnector { class DBClientBase : public DBClientWithCommands, public DBConnector {
protected: protected:
skipping to change at line 1172 skipping to change at line 1184
false was returned -- it will try to connect again. false was returned -- it will try to connect again.
@param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 ) @param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 )
*/ */
void connect(const string& serverHostname) { void connect(const string& serverHostname) {
string errmsg; string errmsg;
if( !connect(HostAndPort(serverHostname), errmsg) ) if( !connect(HostAndPort(serverHostname), errmsg) )
throw ConnectException(string("can't connect ") + errmsg); throw ConnectException(string("can't connect ") + errmsg);
} }
/**
* Logs out the connection for the given database.
*
* @param dbname the database to logout from.
* @param info the result object for the logout command (provided f
or backwards
* compatibility with mongo shell)
*/
virtual void logout(const string& dbname, BSONObj& info);
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y=Query(), int nToReturn = 0, int nToSkip = 0, virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y=Query(), int nToReturn = 0, int nToSkip = 0,
const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 ) { const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 ) {
checkConnection(); checkConnection();
return DBClientBase::query( ns, query, nToReturn, nToSkip, fiel dsToReturn, queryOptions , batchSize ); return DBClientBase::query( ns, query, nToReturn, nToSkip, fiel dsToReturn, queryOptions , batchSize );
} }
virtual unsigned long long query( boost::function<void(DBClientCurs orBatchIterator &)> f, virtual unsigned long long query( boost::function<void(DBClientCurs orBatchIterator &)> f,
const string& ns, const string& ns,
Query query, Query query,
const BSONObj *fieldsToReturn, const BSONObj *fieldsToReturn,
 End of changes. 9 change blocks. 
5 lines changed or deleted 29 lines changed or added


 dbhelpers.h   dbhelpers.h 
skipping to change at line 140 skipping to change at line 140
/** /**
* Takes a namespace range, specified by a min and max and qualifie d by an index pattern, * Takes a namespace range, specified by a min and max and qualifie d by an index pattern,
* and removes all the documents in that range found by iterating * and removes all the documents in that range found by iterating
* over the given index. Caller is responsible for insuring that mi n/max are * over the given index. Caller is responsible for insuring that mi n/max are
* compatible with the given keyPattern (e.g min={a:100} is compati ble with * compatible with the given keyPattern (e.g min={a:100} is compati ble with
* keyPattern={a:1,b:1} since it can be extended to {a:100,b:minKey }, but * keyPattern={a:1,b:1} since it can be extended to {a:100,b:minKey }, but
* min={b:100} is not compatible). * min={b:100} is not compatible).
* *
* Caller must hold a write lock on 'ns' * Caller must hold a write lock on 'ns'
* *
* Returns -1 when no usable index exists
*
* Does oplog the individual document deletions. * Does oplog the individual document deletions.
* // TODO: Refactor this mechanism, it is growing too large * // TODO: Refactor this mechanism, it is growing too large
*/ */
static long long removeRange( const KeyRange& range, static long long removeRange( const KeyRange& range,
bool maxInclusive = false, bool maxInclusive = false,
bool secondaryThrottle = false, bool secondaryThrottle = false,
RemoveCallback * callback = 0, RemoveCallback * callback = 0,
bool fromMigrate = false, bool fromMigrate = false,
bool onlyRemoveOrphanedDocs = false ) ; bool onlyRemoveOrphanedDocs = false ) ;
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 dbmessage.h   dbmessage.h 
skipping to change at line 25 skipping to change at line 25
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/bson/bson_validate.h" #include "mongo/bson/bson_validate.h"
#include "mongo/client/constants.h" #include "mongo/client/constants.h"
#include "mongo/db/instance.h" #include "mongo/db/instance.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/namespace-inl.h"
#include "mongo/util/net/message.h" #include "mongo/util/net/message.h"
namespace mongo { namespace mongo {
/* db response format /* db response format
Query or GetMore: // see struct QueryResult Query or GetMore: // see struct QueryResult
int resultFlags; int resultFlags;
int64 cursorID; int64 cursorID;
int startingFrom; int startingFrom;
 End of changes. 1 change blocks. 
1 lines changed or deleted 0 lines changed or added


 document-inl.h   document-inl.h 
skipping to change at line 50 skipping to change at line 50
} }
inline Element Document::root() { inline Element Document::root() {
return _root; return _root;
} }
inline ConstElement Document::root() const { inline ConstElement Document::root() const {
return _root; return _root;
} }
inline std::string Document::toString() const {
return getObject().toString();
}
inline bool Document::isInPlaceModeEnabled() const {
return getCurrentInPlaceMode() == kInPlaceEnabled;
}
} // namespace mutablebson } // namespace mutablebson
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
0 lines changed or deleted 8 lines changed or added


 document.h   document.h 
skipping to change at line 145 skipping to change at line 145
/** Clone a document. /** Clone a document.
* *
* This should only be called by MutableDocument and tests * This should only be called by MutableDocument and tests
* *
* The new document shares all the fields' values with the origina l. * The new document shares all the fields' values with the origina l.
* This is not a deep copy. Only the fields on the top-level docu ment * This is not a deep copy. Only the fields on the top-level docu ment
* are cloned. * are cloned.
*/ */
Document clone() const { return Document(storage().clone().get()); } Document clone() const { return Document(storage().clone().get()); }
/// members for Sorter
struct SorterDeserializeSettings {}; // unused
void serializeForSorter(BufBuilder& buf) const;
static Document deserializeForSorter(BufReader& buf, const SorterDe
serializeSettings&);
int memUsageForSorter() const { return getApproximateSize(); }
Document getOwned() const { return *this; }
// TEMP for compatibility with legacy intrusive_ptr<Document> // TEMP for compatibility with legacy intrusive_ptr<Document>
Document& operator*() { return *this; } Document& operator*() { return *this; }
const Document& operator*() const { return *this; } const Document& operator*() const { return *this; }
Document* operator->() { return this; } Document* operator->() { return this; }
const Document* operator->() const { return this; } const Document* operator->() const { return this; }
const void* getPtr() const { return _storage.get(); } const void* getPtr() const { return _storage.get(); }
void reset() { return _storage.reset(); } void reset() { return _storage.reset(); }
static Document createFromBsonObj(BSONObj* pBsonObj) { return Docum ent(*pBsonObj); } static Document createFromBsonObj(BSONObj* pBsonObj) { return Docum ent(*pBsonObj); }
size_t getFieldCount() const { return size(); } size_t getFieldCount() const { return size(); }
Value getValue(StringData fieldName) const { return getField(fieldN ame); } Value getValue(StringData fieldName) const { return getField(fieldN ame); }
skipping to change at line 319 skipping to change at line 326
*/ */
Document freeze() { Document freeze() {
// This essentially moves _storage into a new Document by way o f temp. // This essentially moves _storage into a new Document by way o f temp.
Document ret; Document ret;
intrusive_ptr<const DocumentStorage> temp (storagePtr(), /*inc_ ref_count=*/false); intrusive_ptr<const DocumentStorage> temp (storagePtr(), /*inc_ ref_count=*/false);
temp.swap(ret._storage); temp.swap(ret._storage);
_storage = NULL; _storage = NULL;
return ret; return ret;
} }
/// Used to simplify the common pattern of creating a value of the
document.
Value freezeToValue() {
return Value(freeze());
}
/** Borrow a readable reference to this Document. /** Borrow a readable reference to this Document.
* *
* Note that unlike freeze(), this indicates intention to continue * Note that unlike freeze(), this indicates intention to continue
* modifying this document. The returned Document will not observe * modifying this document. The returned Document will not observe
* future changes to this MutableDocument. * future changes to this MutableDocument.
*/ */
Document peek() { Document peek() {
return Document(storagePtr()); return Document(storagePtr());
} }
skipping to change at line 403 skipping to change at line 415
Document::FieldPair fp (_it->nameSD(), _it->val); Document::FieldPair fp (_it->nameSD(), _it->val);
_it.advance(); _it.advance();
return fp; return fp;
} }
private: private:
// We'll hang on to the original document to ensure we keep its sto rage alive // We'll hang on to the original document to ensure we keep its sto rage alive
Document _doc; Document _doc;
DocumentStorageIterator _it; DocumentStorageIterator _it;
}; };
/// Macro to create Document literals. Syntax is the same as the BSON("
name" << 123) macro.
#define DOC(fields) ((DocumentStream() << fields).done())
/** Macro to create Array-typed Value literals.
* Syntax is the same as the BSON_ARRAY(123 << "foo") macro.
*/
#define DOC_ARRAY(fields) ((ValueArrayStream() << fields).done())
// These classes are only for the implementation of the DOC and DOC_ARR
AY macros.
// They should not be used for any other reason.
class DocumentStream {
// The stream alternates between DocumentStream taking a fieldname
// and ValueStream taking a Value.
class ValueStream {
public:
ValueStream(DocumentStream& builder) :builder(builder) {}
DocumentStream& operator << (const Value& val) {
builder._md[name] = val;
return builder;
}
/// support anything directly supported by a value constructor
template <typename T>
DocumentStream& operator << (const T& val) {
return *this << Value(val);
}
StringData name;
DocumentStream& builder;
};
public:
DocumentStream() :_stream(*this) {}
ValueStream& operator << (const StringData& name) {
_stream.name = name;
return _stream;
}
Document done() { return _md.freeze(); }
private:
ValueStream _stream;
MutableDocument _md;
};
class ValueArrayStream {
public:
ValueArrayStream& operator << (const Value& val) {
_array.push_back(val);
return *this;
}
/// support anything directly supported by a value constructor
template <typename T>
ValueArrayStream& operator << (const T& val) {
return *this << Value(val);
}
Value done() { return Value::consume(_array); }
private:
vector<Value> _array;
};
} }
namespace std { namespace std {
template<> template<>
inline void swap(mongo::Document& lhs, mongo::Document& rhs) { lhs.swap (rhs); } inline void swap(mongo::Document& lhs, mongo::Document& rhs) { lhs.swap (rhs); }
} }
/* ======================= INLINED IMPLEMENTATIONS ======================== == */ /* ======================= INLINED IMPLEMENTATIONS ======================== == */
namespace mongo { namespace mongo {
 End of changes. 3 change blocks. 
0 lines changed or deleted 83 lines changed or added


 document_source.h   document_source.h 
skipping to change at line 22 skipping to change at line 22
* *
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* 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 "mongo/pch.h" #include "mongo/pch.h"
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
#include "util/intrusive_counter.h"
#include "db/clientcursor.h" #include "mongo/db/clientcursor.h"
#include "db/jsobj.h" #include "mongo/db/jsobj.h"
#include "db/matcher.h" #include "mongo/db/matcher.h"
#include "db/pipeline/document.h" #include "mongo/db/pipeline/document.h"
#include "db/pipeline/expression.h"
#include "mongo/db/pipeline/expression_context.h" #include "mongo/db/pipeline/expression_context.h"
#include "db/pipeline/value.h" #include "mongo/db/pipeline/expression.h"
#include "util/string_writer.h" #include "mongo/db/pipeline/value.h"
#include "mongo/db/projection.h" #include "mongo/db/projection.h"
#include "mongo/db/sorter/sorter.h"
#include "mongo/s/shard.h" #include "mongo/s/shard.h"
#include "mongo/util/intrusive_counter.h"
namespace mongo { namespace mongo {
class Accumulator; class Accumulator;
class Cursor; class Cursor;
class Document; class Document;
class Expression; class Expression;
class ExpressionContext; class ExpressionContext;
class ExpressionFieldPath; class ExpressionFieldPath;
class ExpressionObject; class ExpressionObject;
class DocumentSourceLimit; class DocumentSourceLimit;
class DocumentSource : class DocumentSource : public IntrusiveCounterUnsigned {
public IntrusiveCounterUnsigned,
public StringWriter {
public: public:
virtual ~DocumentSource(); virtual ~DocumentSource();
// virtuals from StringWriter
virtual void writeString(stringstream &ss) const;
/** /**
Set the step for a user-specified pipeline step. Set the step for a user-specified pipeline step.
The step is used for diagnostics. The step is used for diagnostics.
@param step step number 0 to n. @param step step number 0 to n.
*/ */
void setPipelineStep(int step); void setPipelineStep(int step);
/** /**
skipping to change at line 367 skipping to change at line 363
ShardOutput::const_iterator listEnd; ShardOutput::const_iterator listEnd;
}; };
/** /**
* Constructs and returns Documents from the BSONObj objects produced b y a supplied Cursor. * Constructs and returns Documents from the BSONObj objects produced b y a supplied Cursor.
* An object of this type may only be used by one thread, see SERVER-61 23. * An object of this type may only be used by one thread, see SERVER-61 23.
*/ */
class DocumentSourceCursor : class DocumentSourceCursor :
public DocumentSource { public DocumentSource {
public: public:
/**
* Holds a Cursor and all associated state required to access the c
ursor. An object of this
* type may only be used by one thread.
*/
struct CursorWithContext {
/** Takes a read lock that will be held for the lifetime of the
object. */
CursorWithContext( const string& ns );
// Must be the first struct member for proper construction and
destruction, as other
// members may depend on the read lock it acquires.
Client::ReadContext _readContext;
shared_ptr<ShardChunkManager> _chunkMgr;
ClientCursor::Holder _cursor;
};
// virtuals from DocumentSource // virtuals from DocumentSource
virtual ~DocumentSourceCursor(); virtual ~DocumentSourceCursor();
virtual bool eof(); virtual bool eof();
virtual bool advance(); virtual bool advance();
virtual Document getCurrent(); virtual Document getCurrent();
virtual void setSource(DocumentSource *pSource); virtual void setSource(DocumentSource *pSource);
/** /**
* Release the Cursor and the read lock it requires, but without ch anging the other data. * Release the Cursor and the read lock it requires, but without ch anging the other data.
* Releasing the lock is required for proper concurrency, see SERVE R-6123. This * Releasing the lock is required for proper concurrency, see SERVE R-6123. This
* functionality is also used by the explain version of pipeline ex ecution. * functionality is also used by the explain version of pipeline ex ecution.
*/ */
virtual void dispose(); virtual void dispose();
/** /**
Create a document source based on a cursor. * Create a document source based on a passed-in cursor.
*
This is usually put at the beginning of a chain of document sourc * This is usually put at the beginning of a chain of document sour
es ces
in order to fetch data from the database. * in order to fetch data from the database.
*
@param pCursor the cursor to use to fetch data * The DocumentSource takes ownership of the cursor and will destro
@param pExpCtx the expression context for the pipeline y it
*/ * when the DocumentSource is finished with the cursor, if it hasn'
t
* already been destroyed.
*
* @param ns the namespace the cursor is over
* @param cursorId the id of the cursor to use
* @param pExpCtx the expression context for the pipeline
*/
static intrusive_ptr<DocumentSourceCursor> create( static intrusive_ptr<DocumentSourceCursor> create(
const shared_ptr<CursorWithContext>& cursorWithContext, const string& ns,
CursorId cursorId,
const intrusive_ptr<ExpressionContext> &pExpCtx); const intrusive_ptr<ExpressionContext> &pExpCtx);
/* /*
Record the namespace. Required for explain. Record the namespace. Required for explain.
@param namespace the namespace @param namespace the namespace
*/ */
void setNamespace(const string &ns);
/* /*
Record the query that was specified for the cursor this wraps, if Record the query that was specified for the cursor this wraps, if
any. any.
This should be captured after any optimizations are applied to This should be captured after any optimizations are applied to
the pipeline so that it reflects what is really used. the pipeline so that it reflects what is really used.
This gets used for explain output. This gets used for explain output.
skipping to change at line 449 skipping to change at line 435
*/ */
void setSort(const BSONObj& sort) { _sort = sort; } void setSort(const BSONObj& sort) { _sort = sort; }
void setProjection(const BSONObj& projection, const ParsedDeps& dep s); void setProjection(const BSONObj& projection, const ParsedDeps& dep s);
protected: protected:
// virtuals from DocumentSource // virtuals from DocumentSource
virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c onst; virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c onst;
private: private:
DocumentSourceCursor( DocumentSourceCursor(
const shared_ptr<CursorWithContext>& cursorWithContext, const string& ns,
CursorId cursorId,
const intrusive_ptr<ExpressionContext> &pExpCtx); const intrusive_ptr<ExpressionContext> &pExpCtx);
void findNext(); void findNext();
bool unstarted; bool unstarted;
bool hasCurrent; bool hasCurrent;
Document pCurrent; Document pCurrent;
string ns; // namespace // BSONObj members must outlive _projection and cursor.
/*
The bson dependencies must outlive the Cursor wrapped by this
source. Therefore, bson dependencies must appear before pCursor
in order cause its destructor to be called *after* pCursor's.
*/
BSONObj _query; BSONObj _query;
BSONObj _sort; BSONObj _sort;
shared_ptr<Projection> _projection; // shared with pClientCursor shared_ptr<Projection> _projection; // shared with pClientCursor
ParsedDeps _dependencies; ParsedDeps _dependencies;
shared_ptr<CursorWithContext> _cursorWithContext; string ns; // namespace
CursorId _cursorId;
ClientCursor::Holder& cursor(); CollectionMetadataPtr _collMetadata;
const ShardChunkManager* chunkMgr() { return _cursorWithContext->_c
hunkMgr.get(); }
bool canUseCoveredIndex(); bool canUseCoveredIndex(ClientCursor* cursor);
/* /*
Yield the cursor sometimes. Yield the cursor sometimes.
If the state of the world changed during the yield such that we If the state of the world changed during the yield such that we
are unable to continue execution of the query, this will release the are unable to continue execution of the query, this will release the
client cursor, and throw an error. NOTE This differs from the client cursor, and throw an error. NOTE This differs from the
behavior of most other operations, see SERVER-2454. behavior of most other operations, see SERVER-2454.
*/ */
void yieldSometimes(); void yieldSometimes(ClientCursor* cursor);
}; };
/* /*
This contains all the basic mechanics for filtering a stream of This contains all the basic mechanics for filtering a stream of
Documents, except for the actual predicate evaluation itself. This w as Documents, except for the actual predicate evaluation itself. This w as
factored out so we could create DocumentSources that use both Matcher factored out so we could create DocumentSources that use both Matcher
style predicates as well as full Expressions. style predicates as well as full Expressions.
*/ */
class DocumentSourceFilterBase : class DocumentSourceFilterBase :
public DocumentSource { public DocumentSource {
skipping to change at line 643 skipping to change at line 623
Accumulators become fields in the Documents that result from Accumulators become fields in the Documents that result from
grouping. Each unique group document must have it's own grouping. Each unique group document must have it's own
accumulator; the accumulator factory is used to create that. accumulator; the accumulator factory is used to create that.
@param fieldName the name the accumulator result will have in the @param fieldName the name the accumulator result will have in the
result documents result documents
@param pAccumulatorFactory used to create the accumulator for the @param pAccumulatorFactory used to create the accumulator for the
group field group field
*/ */
void addAccumulator(const std::string& fieldName, void addAccumulator(const std::string& fieldName,
intrusive_ptr<Accumulator> (*pAccumulatorFactor intrusive_ptr<Accumulator> (*pAccumulatorFactor
y)( y)(),
const intrusive_ptr<ExpressionContext> &),
const intrusive_ptr<Expression> &pExpression); const intrusive_ptr<Expression> &pExpression);
/** /**
Create a grouping DocumentSource from BSON. Create a grouping DocumentSource from BSON.
This is a convenience method that uses the above, and operates on This is a convenience method that uses the above, and operates on
a BSONElement that has been deteremined to be an Object with an a BSONElement that has been deteremined to be an Object with an
element named $group. element named $group.
@param pBsonElement the BSONELement that defines the group @param pBsonElement the BSONELement that defines the group
skipping to change at line 675 skipping to change at line 654
static const char groupName[]; static const char groupName[];
protected: protected:
// virtuals from DocumentSource // virtuals from DocumentSource
virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c onst; virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c onst;
private: private:
DocumentSourceGroup(const intrusive_ptr<ExpressionContext> &pExpCtx ); DocumentSourceGroup(const intrusive_ptr<ExpressionContext> &pExpCtx );
/// Spill groups map to disk and returns an iterator to the file.
shared_ptr<Sorter<Value, Value>::Iterator> spill();
// Only used by spill. Would be function-local if that were legal i
n C++03.
class SpillSTLComparator;
/* /*
Before returning anything, this source must fetch everything from Before returning anything, this source must fetch everything from
the underlying source and group it. populate() is used to do tha t the underlying source and group it. populate() is used to do tha t
on the first call to any method on this source. The populated on the first call to any method on this source. The populated
boolean indicates that this has been done. boolean indicates that this has been done.
*/ */
void populate(); void populate();
bool populated; bool populated;
intrusive_ptr<Expression> pIdExpression; intrusive_ptr<Expression> pIdExpression;
typedef boost::unordered_map<Value, typedef vector<intrusive_ptr<Accumulator> > Accumulators;
vector<intrusive_ptr<Accumulator> >, Value::Hash> GroupsType; typedef boost::unordered_map<Value, Accumulators, Value::Hash> Grou
GroupsType groups; psMap;
GroupsMap groups;
/* /*
The field names for the result documents and the accumulator The field names for the result documents and the accumulator
factories for the result documents. The Expressions are the factories for the result documents. The Expressions are the
common expressions used by each instance of each accumulator common expressions used by each instance of each accumulator
in order to find the right-hand side of what gets added to the in order to find the right-hand side of what gets added to the
accumulator. Note that each of those is the same for each group, accumulator. Note that each of those is the same for each group,
so we can share them across all groups by adding them to the so we can share them across all groups by adding them to the
accumulators after we use the factories to make a new set of accumulators after we use the factories to make a new set of
accumulators for each new group. accumulators for each new group.
These three vectors parallel each other. These three vectors parallel each other.
*/ */
vector<string> vFieldName; vector<string> vFieldName;
vector<intrusive_ptr<Accumulator> (*)( vector<intrusive_ptr<Accumulator> (*)()> vpAccumulatorFactory;
const intrusive_ptr<ExpressionContext> &)> vpAccumulatorFactory
;
vector<intrusive_ptr<Expression> > vpExpression; vector<intrusive_ptr<Expression> > vpExpression;
Document makeDocument(const GroupsType::iterator &rIter); Document makeDocument(const Value& id, const Accumulators& accums, bool mergeableOutput);
GroupsType::iterator groupsIterator; bool _spilled;
const bool _extSortAllowed;
const int _maxMemoryUsageBytes;
// only used when !_spilled
GroupsMap::iterator groupsIterator;
// only used when _spilled
scoped_ptr<Sorter<Value, Value>::Iterator> _sorterIterator;
pair<Value, Value> _firstPartOfNextGroup;
Value _currentId;
Accumulators _currentAccumulators;
bool _doneAfterNextAdvance;
bool _done;
}; };
class DocumentSourceMatch : class DocumentSourceMatch :
public DocumentSourceFilterBase { public DocumentSourceFilterBase {
public: public:
// virtuals from DocumentSource // virtuals from DocumentSource
virtual ~DocumentSourceMatch(); virtual ~DocumentSourceMatch();
virtual const char *getSourceName() const; virtual const char *getSourceName() const;
/** /**
skipping to change at line 830 skipping to change at line 827
static const char projectName[]; static const char projectName[];
/** projection as specified by the user */ /** projection as specified by the user */
BSONObj getRaw() const { return _raw; } BSONObj getRaw() const { return _raw; }
protected: protected:
// virtuals from DocumentSource // virtuals from DocumentSource
virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c onst; virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c onst;
private: private:
DocumentSourceProject(const intrusive_ptr<ExpressionContext> &pExpC DocumentSourceProject(const intrusive_ptr<ExpressionContext>& pExpC
tx); tx,
const intrusive_ptr<ExpressionObject>& exprOb
j);
// configuration state // configuration state
intrusive_ptr<ExpressionObject> pEO; intrusive_ptr<ExpressionObject> pEO;
BSONObj _raw; BSONObj _raw;
#if defined(_DEBUG) #if defined(_DEBUG)
// this is used in DEBUG builds to ensure we are compatible // this is used in DEBUG builds to ensure we are compatible
Projection _simpleProjection; Projection _simpleProjection;
#endif #endif
}; };
skipping to change at line 929 skipping to change at line 927
/* /*
Before returning anything, this source must fetch everything from Before returning anything, this source must fetch everything from
the underlying source and group it. populate() is used to do tha t the underlying source and group it. populate() is used to do tha t
on the first call to any method on this source. The populated on the first call to any method on this source. The populated
boolean indicates that this has been done. boolean indicates that this has been done.
*/ */
void populate(); void populate();
bool populated; bool populated;
// These are called by populate()
void populateAll(); // no limit
void populateOne(); // limit == 1
void populateTopK(); // limit > 1
/* these two parallel each other */ /* these two parallel each other */
typedef vector<intrusive_ptr<ExpressionFieldPath> > SortPaths; typedef vector<intrusive_ptr<ExpressionFieldPath> > SortPaths;
SortPaths vSortKey; SortPaths vSortKey;
vector<char> vAscending; // used like vector<bool> but without spec ialization vector<char> vAscending; // used like vector<bool> but without spec ialization
struct KeyAndDoc { /// Extracts the fields in vSortKey from the Document;
explicit KeyAndDoc(const Document& d, const SortPaths& sp); // Value extractKey(const Document& d) const;
extracts sort key
Value key; // array of keys if vSortKey.size() > 1
Document doc;
};
friend void swap(KeyAndDoc& l, KeyAndDoc& r);
/// Compare two KeyAndDocs according to the specified sort key. /// Compare two Values according to the specified sort key.
int compare(const KeyAndDoc& lhs, const KeyAndDoc& rhs) const; int compare(const Value& lhs, const Value& rhs) const;
/* typedef Sorter<Value, Document> MySorter;
This is a utility class just for the STL sort that is done
inside. // For MySorter
*/
class Comparator { class Comparator {
public: public:
explicit Comparator(const DocumentSourceSort& source): _source( source) {} explicit Comparator(const DocumentSourceSort& source): _source( source) {}
bool operator()(const KeyAndDoc& lhs, const KeyAndDoc& rhs) con int operator()(const MySorter::Data& lhs, const MySorter::Data&
st { rhs) const {
return (_source.compare(lhs, rhs) < 0); return _source.compare(lhs.first, rhs.first);
} }
private: private:
const DocumentSourceSort& _source; const DocumentSourceSort& _source;
}; };
deque<KeyAndDoc> documents;
intrusive_ptr<DocumentSourceLimit> limitSrc; intrusive_ptr<DocumentSourceLimit> limitSrc;
bool _done;
Document _current;
scoped_ptr<MySorter::Iterator> _output;
}; };
inline void swap(DocumentSourceSort::KeyAndDoc& l, DocumentSourceSort::
KeyAndDoc& r) {
l.key.swap(r.key);
l.doc.swap(r.doc);
}
class DocumentSourceLimit : class DocumentSourceLimit :
public SplittableDocumentSource { public SplittableDocumentSource {
public: public:
// virtuals from DocumentSource // virtuals from DocumentSource
virtual ~DocumentSourceLimit(); virtual ~DocumentSourceLimit();
virtual bool eof(); virtual bool eof();
virtual bool advance(); virtual bool advance();
virtual Document getCurrent(); virtual Document getCurrent();
virtual const char *getSourceName() const; virtual const char *getSourceName() const;
 End of changes. 30 change blocks. 
99 lines changed or deleted 83 lines changed or added


 element.h   element.h 
skipping to change at line 56 skipping to change at line 56
* *
* - Topology mutation: These methods are to either add other Elements to the Document * - Topology mutation: These methods are to either add other Elements to the Document
* tree as siblings or children (when applicable) of the current Ele ment, to remove the * tree as siblings or children (when applicable) of the current Ele ment, to remove the
* Element from the tree, or to remove children of the Element (when applicable). * Element from the tree, or to remove children of the Element (when applicable).
* *
* - Navigation: These methods are used to navigate the Document tree by returning other * - Navigation: These methods are used to navigate the Document tree by returning other
* Elements in specified relationships to the current Element. In th is regard, Elements * Elements in specified relationships to the current Element. In th is regard, Elements
* act much like STL iterators that walk over the Document tree. One important * act much like STL iterators that walk over the Document tree. One important
* difference is that Elements are never invalidated, even when 'rem ove' is called. If * difference is that Elements are never invalidated, even when 'rem ove' is called. If
* you have two Elements that alias the same element in the Document tree, modifications * you have two Elements that alias the same element in the Document tree, modifications
* through one Element will be visible via the other (modulo one exc * through one Element will be visible via the other.
eption noted below
* for Element::setValueElement).
* *
* - Value access: These methods provide access to the value in the Do cument tree that the * - Value access: These methods provide access to the value in the Do cument tree that the
* current Element represents. All leaf (a.k.a. 'primitive', or non- Object and * current Element represents. All leaf (a.k.a. 'primitive', or non- Object and
* non-Array) like Elements will always be able to provide a value. However, there are * non-Array) like Elements will always be able to provide a value. However, there are
* cases where non-leaf Elements (representing Objects or Arrays) ca nnot provide a * cases where non-leaf Elements (representing Objects or Arrays) ca nnot provide a
* value. Therefore, you must always call 'hasValue' to determine if the value is * value. Therefore, you must always call 'hasValue' to determine if the value is
* available before calling 'getValue'. Similarly, you must determin e the type of the * available before calling 'getValue'. Similarly, you must determin e the type of the
* Element by calling getType() and only call the matching typed get Value. * Element by calling getType() and only call the matching typed get Value.
* *
* - Comparison: It is possible to compare one Element with another to determine ordering * - Comparison: It is possible to compare one Element with another to determine ordering
skipping to change at line 360 skipping to change at line 359
*/ */
Status setValueArray(const BSONObj& value); Status setValueArray(const BSONObj& value);
/** Set the value of this Element to the given binary data. */ /** Set the value of this Element to the given binary data. */
Status setValueBinary(uint32_t len, mongo::BinDataType binType, con st void* data); Status setValueBinary(uint32_t len, mongo::BinDataType binType, con st void* data);
/** Set the value of this Element to Undefined. */ /** Set the value of this Element to Undefined. */
Status setValueUndefined(); Status setValueUndefined();
/** Set the value of this Element to the given OID. */ /** Set the value of this Element to the given OID. */
Status setValueOID(const OID& value); Status setValueOID(OID value);
/** Set the value of this Element to the given boolean. */ /** Set the value of this Element to the given boolean. */
Status setValueBool(bool value); Status setValueBool(bool value);
/** Set the value of this Element to the given date. */ /** Set the value of this Element to the given date. */
Status setValueDate(Date_t value); Status setValueDate(Date_t value);
/** Set the value of this Element to Null. */ /** Set the value of this Element to Null. */
Status setValueNull(); Status setValueNull();
/** Set the value of this Element to the given regex parameters. */ /** Set the value of this Element to the given regex parameters. */
Status setValueRegex(const StringData& re, const StringData& flags) ; Status setValueRegex(const StringData& re, const StringData& flags) ;
/** Set the value of this Element to the given db ref parameters. * / /** Set the value of this Element to the given db ref parameters. * /
Status setValueDBRef(const StringData& ns, const OID& oid); Status setValueDBRef(const StringData& ns, OID oid);
/** Set the value of this Element to the given code data. */ /** Set the value of this Element to the given code data. */
Status setValueCode(const StringData& value); Status setValueCode(const StringData& value);
/** Set the value of this Element to the given symbol. */ /** Set the value of this Element to the given symbol. */
Status setValueSymbol(const StringData& value); Status setValueSymbol(const StringData& value);
/** Set the value of this Element to the given code and scope data. */ /** Set the value of this Element to the given code and scope data. */
Status setValueCodeWithScope(const StringData& code, const BSONObj& scope); Status setValueCodeWithScope(const StringData& code, const BSONObj& scope);
skipping to change at line 405 skipping to change at line 404
/** Set the value of this Element to MinKey. */ /** Set the value of this Element to MinKey. */
Status setValueMinKey(); Status setValueMinKey();
/** Set the value of this Element to MaxKey. */ /** Set the value of this Element to MaxKey. */
Status setValueMaxKey(); Status setValueMaxKey();
// //
// Value mutation API from variant types. // Value mutation API from variant types.
// //
/** Set the name, type, and value of this Element to those of the p
rovided Element. The
* Element 'value' must be in a "detached" state, meaning that it
is newly constructed
* and not attached to any other Element in the Document.
*
* WARNING: This is the one violation of the 'no Element invalidat
ion rule'. The
* Element passed in as 'value' will be modified to point to this
Element because the
* source Element referred to by 'value' *is invalidated*. Any Ele
ment objects that
* alias 'value' are therefore also invalidated. This shouldn't be
a problem since you
* should pass the return value of Document::makeElement[Type] imm
ediately to this
* call, meaning you should never construct an Element that aliase
s value. Accessing
* the invalidated Element after this call will result in undefine
d behavior. You have
* been warned.
*/
Status setValueElement(Element* value);
/** Set the value of this element to equal the value of the provide d BSONElement /** Set the value of this element to equal the value of the provide d BSONElement
* 'value'. The name of this Element is not modified. * 'value'. The name of this Element is not modified.
* *
* The contents of value are copied. * The contents of value are copied.
*/ */
Status setValueBSONElement(const BSONElement& value); Status setValueBSONElement(const BSONElement& value);
/** Set the value of this Element to a numeric type appropriate to hold the given /** Set the value of this Element to a numeric type appropriate to hold the given
* SafeNum value. * SafeNum value.
*/ */
Status setValueSafeNum(const SafeNum& value); Status setValueSafeNum(const SafeNum value);
// //
// Accessors // Accessors
// //
/** Returns true if this Element represents a valid part of the Doc ument. */ /** Returns true if this Element represents a valid part of the Doc ument. */
bool ok() const; bool ok() const;
/** Returns the Document to which this Element belongs. */ /** Returns the Document to which this Element belongs. */
inline Document& getDocument(); inline Document& getDocument();
skipping to change at line 493 skipping to change at line 477
Status appendArray(const StringData& fieldName, const BSONObj& valu e); Status appendArray(const StringData& fieldName, const BSONObj& valu e);
/** Append the provided binary data as a new field with the provide d name. */ /** Append the provided binary data as a new field with the provide d name. */
Status appendBinary(const StringData& fieldName, Status appendBinary(const StringData& fieldName,
uint32_t len, mongo::BinDataType binType, const void* data); uint32_t len, mongo::BinDataType binType, const void* data);
/** Append an undefined value as a new field with the provided name . */ /** Append an undefined value as a new field with the provided name . */
Status appendUndefined(const StringData& fieldName); Status appendUndefined(const StringData& fieldName);
/** Append the provided OID as a new field with the provided name. */ /** Append the provided OID as a new field with the provided name. */
Status appendOID(const StringData& fieldName, const mongo::OID& val ue); Status appendOID(const StringData& fieldName, mongo::OID value);
/** Append the provided bool as a new field with the provided name. */ /** Append the provided bool as a new field with the provided name. */
Status appendBool(const StringData& fieldName, bool value); Status appendBool(const StringData& fieldName, bool value);
/** Append the provided date as a new field with the provided name. */ /** Append the provided date as a new field with the provided name. */
Status appendDate(const StringData& fieldName, Date_t value); Status appendDate(const StringData& fieldName, Date_t value);
/** Append a null as a new field with the provided name. */ /** Append a null as a new field with the provided name. */
Status appendNull(const StringData& fieldName); Status appendNull(const StringData& fieldName);
/** Append the provided regex data as a new field with the provided name. */ /** Append the provided regex data as a new field with the provided name. */
Status appendRegex(const StringData& fieldName, Status appendRegex(const StringData& fieldName,
const StringData& re, const StringData& flags); const StringData& re, const StringData& flags);
/** Append the provided DBRef data as a new field with the provided name. */ /** Append the provided DBRef data as a new field with the provided name. */
Status appendDBRef(const StringData& fieldName, Status appendDBRef(const StringData& fieldName,
const StringData& ns, const mongo::OID& oid); const StringData& ns, mongo::OID oid);
/** Append the provided code data as a new field with the iven name . */ /** Append the provided code data as a new field with the iven name . */
Status appendCode(const StringData& fieldName, const StringData& va lue); Status appendCode(const StringData& fieldName, const StringData& va lue);
/** Append the provided symbol data as a new field with the provide d name. */ /** Append the provided symbol data as a new field with the provide d name. */
Status appendSymbol(const StringData& fieldName, const StringData& value); Status appendSymbol(const StringData& fieldName, const StringData& value);
/** Append the provided code and scope data as a new field with the provided name. */ /** Append the provided code and scope data as a new field with the provided name. */
Status appendCodeWithScope(const StringData& fieldName, Status appendCodeWithScope(const StringData& fieldName,
const StringData& code, const BSONObj& s cope); const StringData& code, const BSONObj& s cope);
skipping to change at line 545 skipping to change at line 529
Status appendMaxKey(const StringData& fieldName); Status appendMaxKey(const StringData& fieldName);
/** Append the given BSONElement. The data in 'value' is copied. */ /** Append the given BSONElement. The data in 'value' is copied. */
Status appendElement(const BSONElement& value); Status appendElement(const BSONElement& value);
/** Append the provided number as field of the appropriate numeric type with the /** Append the provided number as field of the appropriate numeric type with the
* provided name. * provided name.
*/ */
Status appendSafeNum(const StringData& fieldName, SafeNum value); Status appendSafeNum(const StringData& fieldName, SafeNum value);
/** Convert this element to its JSON representation */
std::string toString() const;
private: private:
friend class Document; friend class Document;
friend class ConstElement;
friend bool operator==(const Element&, const Element&); friend bool operator==(const Element&, const Element&);
inline Element(Document* doc, RepIdx repIdx); inline Element(Document* doc, RepIdx repIdx);
Status addChild(Element e, bool front); Status addChild(Element e, bool front);
StringData getValueStringOrSymbol() const; StringData getValueStringOrSymbol() const;
Status setValue(Element* newValue); Status setValue(Element* newValue, bool inPlace = false);
template<typename Builder> template<typename Builder>
inline void writeElement(Builder* builder) const; inline void writeElement(Builder* builder, const StringData* fieldN ame = NULL) const;
template<typename Builder> template<typename Builder>
inline void writeChildren(Builder* builder) const; inline void writeChildren(Builder* builder) const;
Document* _doc; Document* _doc;
RepIdx _repIdx; RepIdx _repIdx;
}; };
/** Element comparison support. Comparison is like STL iterator compari sion: equal Elements /** Element comparison support. Comparison is like STL iterator compari sion: equal Elements
* refer to the same underlying data. The equality does *not* mean tha t the underlying * refer to the same underlying data. The equality does *not* mean tha t the underlying
 End of changes. 11 change blocks. 
34 lines changed or deleted 13 lines changed or added


 emulated_cursor.h   emulated_cursor.h 
skipping to change at line 137 skipping to change at line 137
virtual bool getsetdup(DiskLoc loc) { virtual bool getsetdup(DiskLoc loc) {
if (_shouldGetSetDup) { if (_shouldGetSetDup) {
pair<unordered_set<DiskLoc, DiskLoc::Hasher>::iterator, boo l> p = _dups.insert(loc); pair<unordered_set<DiskLoc, DiskLoc::Hasher>::iterator, boo l> p = _dups.insert(loc);
return !p.second; return !p.second;
} else { } else {
return false; return false;
} }
} }
virtual void aboutToDeleteBucket(const DiskLoc& b) {
_indexCursor->aboutToDeleteBucket(b);
}
private: private:
EmulatedCursor(IndexDescriptor* descriptor, IndexAccessMethod* inde xAccessMethod, EmulatedCursor(IndexDescriptor* descriptor, IndexAccessMethod* inde xAccessMethod,
const BSONObj& order, int numWanted, const BSONObj& keyPattern) const BSONObj& order, int numWanted, const BSONObj& keyPattern)
: _descriptor(descriptor), _indexAccessMethod(indexAccessMethod ), : _descriptor(descriptor), _indexAccessMethod(indexAccessMethod ),
_keyPattern(keyPattern), _pluginName(IndexNames::findPluginNa me(keyPattern)) { _keyPattern(keyPattern), _pluginName(IndexNames::findPluginNa me(keyPattern)) {
IndexCursor *cursor; IndexCursor *cursor;
indexAccessMethod->newCursor(&cursor); indexAccessMethod->newCursor(&cursor);
_indexCursor.reset(cursor); _indexCursor.reset(cursor);
 End of changes. 1 change blocks. 
4 lines changed or deleted 0 lines changed or added


 engine_v8.h   engine_v8.h 
skipping to change at line 76 skipping to change at line 76
void track(v8::Persistent<v8::Value> instanceHandle, _ObjType* inst ance) { void track(v8::Persistent<v8::Value> instanceHandle, _ObjType* inst ance) {
TrackedPtr* collectionHandle = new TrackedPtr(instance, this); TrackedPtr* collectionHandle = new TrackedPtr(instance, this);
_container.insert(collectionHandle); _container.insert(collectionHandle);
instanceHandle.MakeWeak(collectionHandle, deleteOnCollect); instanceHandle.MakeWeak(collectionHandle, deleteOnCollect);
} }
/** /**
* Free any remaining objects and their TrackedPtrs. Invoked when the * Free any remaining objects and their TrackedPtrs. Invoked when the
* V8Scope is destructed. * V8Scope is destructed.
*/ */
~ObjTracker() { ~ObjTracker() {
if (!_container.empty()) if (!_container.empty()) {
LOG(1) << "freeing " << _container.size() << " uncollected " LOG(1) << "freeing " << _container.size() << " uncollected "
<< typeid(_ObjType).name() << " objects" << endl; << typeid(_ObjType).name() << " objects" << endl;
}
typename set<TrackedPtr*>::iterator it = _container.begin(); typename set<TrackedPtr*>::iterator it = _container.begin();
while (it != _container.end()) { while (it != _container.end()) {
delete *it; delete *it;
_container.erase(it++); _container.erase(it++);
} }
} }
private: private:
/** /**
* Simple struct which contains a pointer to the tracked object, an d a pointer * Simple struct which contains a pointer to the tracked object, an d a pointer
* to the ObjTracker which owns it. This is the argument supplied to v8's * to the ObjTracker which owns it. This is the argument supplied to v8's
skipping to change at line 206 skipping to change at line 207
int timeoutMs = 0, bool ignoreReturn = false, int timeoutMs = 0, bool ignoreReturn = false,
bool readOnlyArgs = false, bool readOnlyRecv = f alse); bool readOnlyArgs = false, bool readOnlyRecv = f alse);
virtual bool exec(const StringData& code, const string& name, bool printResult, virtual bool exec(const StringData& code, const string& name, bool printResult,
bool reportError, bool assertOnError, int timeout Ms); bool reportError, bool assertOnError, int timeout Ms);
// functions to create v8 object and function templates // functions to create v8 object and function templates
virtual void injectNative(const char* field, NativeFunction func, v oid* data = 0); virtual void injectNative(const char* field, NativeFunction func, v oid* data = 0);
void injectNative(const char* field, NativeFunction func, v8::Handl e<v8::Object>& obj, void injectNative(const char* field, NativeFunction func, v8::Handl e<v8::Object>& obj,
void* data = 0); void* data = 0);
void injectV8Function(const char* name, v8Function func);
void injectV8Function(const char* name, v8Function func, v8::Handle // These functions inject a function (either an unwrapped function
<v8::Object>& obj); pointer or a pre-wrapped
void injectV8Function(const char* name, v8Function func, v8::Handle // FunctionTemplate) into the provided object. If no object is prov
<v8::Template>& t); ided, the function will
// be injected at global scope. These functions take care of settin
g the function and class
// name on the returned FunctionTemplate.
v8::Handle<v8::FunctionTemplate> injectV8Function(const char* name,
v8Function func);
v8::Handle<v8::FunctionTemplate> injectV8Function(const char* name,
v8Function func,
v8::Handle<v8::Ob
ject>& obj);
v8::Handle<v8::FunctionTemplate> injectV8Function(const char* name,
v8::Handle<v8::Fu
nctionTemplate> ft,
v8::Handle<v8::Ob
ject>& obj);
// Injects a method into the provided prototype
v8::Handle<v8::FunctionTemplate> injectV8Method(const char* name,
v8Function func,
v8::Handle<v8::Obje
ctTemplate>& proto);
v8::Handle<v8::FunctionTemplate> createV8Function(v8Function func); v8::Handle<v8::FunctionTemplate> createV8Function(v8Function func);
virtual ScriptingFunction _createFunction(const char* code, virtual ScriptingFunction _createFunction(const char* code,
ScriptingFunction functio nNumber = 0); ScriptingFunction functio nNumber = 0);
v8::Local<v8::Function> __createFunction(const char* code, v8::Local<v8::Function> __createFunction(const char* code,
ScriptingFunction function Number = 0); ScriptingFunction function Number = 0);
/** /**
* Convert BSON types to v8 Javascript types * Convert BSON types to v8 Javascript types
*/ */
v8::Persistent<v8::Object> mongoToLZV8(const mongo::BSONObj& m, boo l readOnly = false); v8::Handle<v8::Object> mongoToLZV8(const mongo::BSONObj& m, bool re adOnly = false);
v8::Handle<v8::Value> mongoToV8Element(const BSONElement& f, bool r eadOnly = false); v8::Handle<v8::Value> mongoToV8Element(const BSONElement& f, bool r eadOnly = false);
/** /**
* Convert v8 Javascript types to BSON types * Convert v8 Javascript types to BSON types
*/ */
mongo::BSONObj v8ToMongo(v8::Handle<v8::Object> obj, int depth = 0) ; mongo::BSONObj v8ToMongo(v8::Handle<v8::Object> obj, int depth = 0) ;
void v8ToMongoElement(BSONObjBuilder& b, void v8ToMongoElement(BSONObjBuilder& b,
const StringData& sname, const StringData& sname,
v8::Handle<v8::Value> value, v8::Handle<v8::Value> value,
int depth = 0, int depth = 0,
BSONObj* originalParent = 0); BSONObj* originalParent = 0);
void v8ToMongoObject(BSONObjBuilder& b, void v8ToMongoObject(BSONObjBuilder& b,
const StringData& sname, const StringData& sname,
v8::Handle<v8::Value> value, v8::Handle<v8::Value> value,
int depth, int depth,
BSONObj* originalParent); BSONObj* originalParent);
void v8ToMongoNumber(BSONObjBuilder& b, void v8ToMongoNumber(BSONObjBuilder& b,
const StringData& elementName, const StringData& elementName,
v8::Handle<v8::Value> value, v8::Handle<v8::Number> value,
BSONObj* originalParent); BSONObj* originalParent);
void v8ToMongoNumberLong(BSONObjBuilder& b,
const StringData& elementName,
v8::Handle<v8::Object> obj);
void v8ToMongoInternal(BSONObjBuilder& b,
const StringData& elementName,
v8::Handle<v8::Object> obj);
void v8ToMongoRegex(BSONObjBuilder& b, void v8ToMongoRegex(BSONObjBuilder& b,
const StringData& elementName, const StringData& elementName,
v8::Handle<v8::Object> v8Regex); v8::Handle<v8::RegExp> v8Regex);
void v8ToMongoDBRef(BSONObjBuilder& b, void v8ToMongoDBRef(BSONObjBuilder& b,
const StringData& elementName, const StringData& elementName,
v8::Handle<v8::Object> obj); v8::Handle<v8::Object> obj);
void v8ToMongoBinData(BSONObjBuilder& b, void v8ToMongoBinData(BSONObjBuilder& b,
const StringData& elementName, const StringData& elementName,
v8::Handle<v8::Object> obj); v8::Handle<v8::Object> obj);
void v8ToMongoObjectID(BSONObjBuilder& b, OID v8ToMongoObjectID(v8::Handle<v8::Object> obj);
const StringData& elementName,
v8::Handle<v8::Object> obj);
v8::Function* getNamedCons(const char* name);
v8::Function* getObjectIdCons();
v8::Local<v8::Value> newId(const OID& id); v8::Local<v8::Value> newId(const OID& id);
/** /**
* Convert a JavaScript exception to a stl string. Requires * Convert a JavaScript exception to a stl string. Requires
* access to the V8Scope instance to report source context informat ion. * access to the V8Scope instance to report source context informat ion.
*/ */
std::string v8ExceptionToSTLString(const v8::TryCatch* try_catch); std::string v8ExceptionToSTLString(const v8::TryCatch* try_catch);
/** /**
* GC callback for weak references to BSON objects (via BSONHolder)
*/
v8::Persistent<v8::Object> wrapBSONObject(v8::Local<v8::Object> obj
, BSONHolder* data);
/**
* Create a V8 string with a local handle * Create a V8 string with a local handle
*/ */
static inline v8::Handle<v8::String> v8StringData(StringData str) { static inline v8::Handle<v8::String> v8StringData(StringData str) {
return v8::String::New(str.rawData(), str.size()); return v8::String::New(str.rawData(), str.size());
} }
/** /**
* Get the isolate this scope belongs to (can be called from any th read, but v8 requires * Get the isolate this scope belongs to (can be called from any th read, but v8 requires
* the new thread enter the isolate and context. Only one thread can enter the isolate. * the new thread enter the isolate and context. Only one thread can enter the isolate.
*/ */
v8::Isolate* getIsolate() { return _isolate; } v8::Isolate* getIsolate() { return _isolate; }
/** /**
* Get the JS context this scope executes within. * Get the JS context this scope executes within.
*/ */
v8::Persistent<v8::Context> getContext() { return _context; } v8::Persistent<v8::Context> getContext() { return _context; }
/**
* Get the global JS object
*/
v8::Persistent<v8::Object> getGlobal() { return _global; }
ObjTracker<BSONHolder> bsonHolderTracker; ObjTracker<BSONHolder> bsonHolderTracker;
ObjTracker<DBClientWithCommands> dbClientWithCommandsTracker; ObjTracker<DBClientWithCommands> dbClientWithCommandsTracker;
ObjTracker<DBClientBase> dbClientBaseTracker; ObjTracker<DBClientBase> dbClientBaseTracker;
ObjTracker<DBClientCursor> dbClientCursorTracker; ObjTracker<DBClientCursor> dbClientCursorTracker;
// These are all named after the JS constructor name + FT
v8::Handle<v8::FunctionTemplate> ObjectIdFT() const { return
_ObjectIdFT; }
v8::Handle<v8::FunctionTemplate> DBRefFT() const { return
_DBRefFT; }
v8::Handle<v8::FunctionTemplate> DBPointerFT() const { return
_DBPointerFT; }
v8::Handle<v8::FunctionTemplate> BinDataFT() const { return
_BinDataFT; }
v8::Handle<v8::FunctionTemplate> NumberLongFT() const { return
_NumberLongFT; }
v8::Handle<v8::FunctionTemplate> NumberIntFT() const { return
_NumberIntFT; }
v8::Handle<v8::FunctionTemplate> TimestampFT() const { return
_TimestampFT; }
v8::Handle<v8::FunctionTemplate> MinKeyFT() const { return
_MinKeyFT; }
v8::Handle<v8::FunctionTemplate> MaxKeyFT() const { return
_MaxKeyFT; }
v8::Handle<v8::FunctionTemplate> MongoFT() const { return
_MongoFT; }
v8::Handle<v8::FunctionTemplate> DBFT() const { return
_DBFT; }
v8::Handle<v8::FunctionTemplate> DBCollectionFT() const { return
_DBCollectionFT; }
v8::Handle<v8::FunctionTemplate> DBQueryFT() const { return
_DBQueryFT; }
v8::Handle<v8::FunctionTemplate> InternalCursorFT() const { return
_InternalCursorFT; }
v8::Handle<v8::FunctionTemplate> LazyBsonFT() const { return
_LazyBsonFT; }
v8::Handle<v8::FunctionTemplate> ROBsonFT() const { return
_ROBsonFT; }
template <size_t N>
v8::Handle<v8::String> strLitToV8(const char (&str)[N]) {
// Note that _strLitMap is keyed on string pointer not string
// value. This is OK because each string literal has a constant
// pointer for the program's lifetime. This works best if (but
does
// not require) the linker interns all string literals giving
// identical strings used in different places the same pointer.
StrLitMap::iterator it = _strLitMap.find(str);
if (it != _strLitMap.end())
return it->second;
StringData sd (str, StringData::LiteralTag());
v8::Handle<v8::String> v8Str = v8StringData(sd);
// We never need to Dispose since this should last as long as V
8Scope exists
_strLitMap[str] = v8::Persistent<v8::String>::New(v8Str);
return v8Str;
}
private: private:
/** /**
* Attach data to obj such that the data has the same lifetime as t
he Object obj points to.
* obj must have been created by either LazyBsonFT or ROBsonFT.
*/
void wrapBSONObject(v8::Handle<v8::Object> obj, BSONObj data, bool
readOnly);
/**
* Trampoline to call a c++ function with a specific signature (V8S cope*, v8::Arguments&). * Trampoline to call a c++ function with a specific signature (V8S cope*, v8::Arguments&).
* Handles interruption, exceptions, etc. * Handles interruption, exceptions, etc.
*/ */
static v8::Handle<v8::Value> v8Callback(const v8::Arguments& args); static v8::Handle<v8::Value> v8Callback(const v8::Arguments& args);
/** /**
* Interpreter agnostic 'Native Callback' trampoline. Note this is only called * Interpreter agnostic 'Native Callback' trampoline. Note this is only called
* from v8Callback(). * from v8Callback().
*/ */
static v8::Handle<v8::Value> nativeCallback(V8Scope* scope, const v 8::Arguments& args); static v8::Handle<v8::Value> nativeCallback(V8Scope* scope, const v 8::Arguments& args);
skipping to change at line 347 skipping to change at line 395
* be supported. * be supported.
*/ */
void registerOpId(); void registerOpId();
/** /**
* Unregister this scope with the mongo op id. * Unregister this scope with the mongo op id.
*/ */
void unregisterOpId(); void unregisterOpId();
/** /**
* Creates a new instance of the MinKey object
*/
v8::Local<v8::Object> newMinKeyInstance();
/**
* Creates a new instance of the MaxKey object
*/
v8::Local<v8::Object> newMaxKeyInstance();
/**
* Create a new function; primarily used for BSON/V8 conversion. * Create a new function; primarily used for BSON/V8 conversion.
*/ */
v8::Local<v8::Value> newFunction(const StringData& code); v8::Local<v8::Value> newFunction(const StringData& code);
template <typename _HandleType> template <typename _HandleType>
bool checkV8ErrorState(const _HandleType& resultHandle, bool checkV8ErrorState(const _HandleType& resultHandle,
const v8::TryCatch& try_catch, const v8::TryCatch& try_catch,
bool reportError = true, bool reportError = true,
bool assertOnError = true); bool assertOnError = true);
template <size_t N>
v8::Handle<v8::String> strLitToV8(const char (&str)[N]) {
// Note that _strLitMap is keyed on string pointer not string
// value. This is OK because each string literal has a constant
// pointer for the program's lifetime. This works best if (but
does
// not require) the linker interns all string literals giving
// identical strings used in different places the same pointer.
StrLitMap::iterator it = _strLitMap.find(str);
if (it != _strLitMap.end())
return it->second;
StringData sd (str, StringData::LiteralTag());
v8::Handle<v8::String> v8Str = v8StringData(sd);
// We never need to Dispose since this should last as long as V
8Scope exists
_strLitMap[str] = v8::Persistent<v8::String>::New(v8Str);
return v8Str;
}
V8ScriptEngine* _engine; V8ScriptEngine* _engine;
v8::Persistent<v8::Context> _context; v8::Persistent<v8::Context> _context;
v8::Persistent<v8::Object> _global; v8::Persistent<v8::Object> _global;
string _error; string _error;
vector<v8::Persistent<v8::Value> > _funcs; vector<v8::Persistent<v8::Value> > _funcs;
enum ConnectState { NOT, LOCAL, EXTERNAL }; enum ConnectState { NOT, LOCAL, EXTERNAL };
ConnectState _connectState; ConnectState _connectState;
v8::Persistent<v8::FunctionTemplate> lzFunctionTemplate; // These are all named after the JS constructor name + FT
v8::Persistent<v8::ObjectTemplate> lzObjectTemplate; v8::Persistent<v8::FunctionTemplate> _ObjectIdFT;
v8::Persistent<v8::ObjectTemplate> roObjectTemplate; v8::Persistent<v8::FunctionTemplate> _DBRefFT;
v8::Persistent<v8::ObjectTemplate> lzArrayTemplate; v8::Persistent<v8::FunctionTemplate> _DBPointerFT;
v8::Persistent<v8::ObjectTemplate> internalFieldObjects; v8::Persistent<v8::FunctionTemplate> _BinDataFT;
v8::Persistent<v8::FunctionTemplate> _NumberLongFT;
v8::Persistent<v8::FunctionTemplate> _NumberIntFT;
v8::Persistent<v8::FunctionTemplate> _TimestampFT;
v8::Persistent<v8::FunctionTemplate> _MinKeyFT;
v8::Persistent<v8::FunctionTemplate> _MaxKeyFT;
v8::Persistent<v8::FunctionTemplate> _MongoFT;
v8::Persistent<v8::FunctionTemplate> _DBFT;
v8::Persistent<v8::FunctionTemplate> _DBCollectionFT;
v8::Persistent<v8::FunctionTemplate> _DBQueryFT;
v8::Persistent<v8::FunctionTemplate> _InternalCursorFT;
v8::Persistent<v8::FunctionTemplate> _LazyBsonFT;
v8::Persistent<v8::FunctionTemplate> _ROBsonFT;
v8::Persistent<v8::Function> _jsRegExpConstructor;
v8::Isolate* _isolate; v8::Isolate* _isolate;
V8CpuProfiler _cpuProfiler; V8CpuProfiler _cpuProfiler;
// See comments in strLitToV8 // See comments in strLitToV8
typedef unordered_map<const char*, v8::Handle<v8::String> > StrLitM ap; typedef unordered_map<const char*, v8::Handle<v8::String> > StrLitM ap;
StrLitMap _strLitMap; StrLitMap _strLitMap;
mongo::mutex _interruptLock; // protects interruption-related flags mongo::mutex _interruptLock; // protects interruption-related flags
bool _inNativeExecution; // protected by _interruptLock bool _inNativeExecution; // protected by _interruptLock
bool _pendingKill; // protected by _interruptLock bool _pendingKill; // protected by _interruptLock
int _opId; // op id for this scope int _opId; // op id for this scope
}; };
/// Helper to extract V8Scope for an Isolate
inline V8Scope* getScope(v8::Isolate* isolate) {
return static_cast<V8Scope*>(isolate->GetData());
}
class V8ScriptEngine : public ScriptEngine { class V8ScriptEngine : public ScriptEngine {
public: public:
V8ScriptEngine(); V8ScriptEngine();
virtual ~V8ScriptEngine(); virtual ~V8ScriptEngine();
virtual Scope* createScope() { return new V8Scope(this); } virtual Scope* createScope() { return new V8Scope(this); }
virtual void runTest() {} virtual void runTest() {}
bool utf8Ok() const { return true; } bool utf8Ok() const { return true; }
/** /**
* Interrupt a single active v8 execution context * Interrupt a single active v8 execution context
skipping to change at line 499 skipping to change at line 535
*/ */
template <typename _HandleType> template <typename _HandleType>
bool V8Scope::checkV8ErrorState(const _HandleType& resultHandle, bool V8Scope::checkV8ErrorState(const _HandleType& resultHandle,
const v8::TryCatch& try_catch, const v8::TryCatch& try_catch,
bool reportError, bool reportError,
bool assertOnError) { bool assertOnError) {
bool haveError = false; bool haveError = false;
if (try_catch.HasCaught() && try_catch.CanContinue()) { if (try_catch.HasCaught() && try_catch.CanContinue()) {
// normal JS exception // normal JS exception
_error = string("JavaScript execution failed: ") + v8ExceptionT oSTLString(&try_catch); _error = v8ExceptionToSTLString(&try_catch);
haveError = true; haveError = true;
} }
else if (hasOutOfMemoryException()) { else if (hasOutOfMemoryException()) {
// out of memory exception (treated as terminal) // out of memory exception (treated as terminal)
_error = "JavaScript execution failed -- v8 is out of memory"; _error = "JavaScript execution failed -- v8 is out of memory";
haveError = true; haveError = true;
} }
else if (resultHandle.IsEmpty() || try_catch.HasCaught()) { else if (resultHandle.IsEmpty() || try_catch.HasCaught()) {
// terminal exception (due to empty handle, termination, etc.) // terminal exception (due to empty handle, termination, etc.)
_error = "JavaScript execution failed"; _error = "JavaScript execution failed";
 End of changes. 17 change blocks. 
67 lines changed or deleted 126 lines changed or added


 error_codes.h   error_codes.h 
skipping to change at line 65 skipping to change at line 65
EmptyArrayOperation = 21, EmptyArrayOperation = 21,
InvalidBSON = 22, InvalidBSON = 22,
AlreadyInitialized = 23, AlreadyInitialized = 23,
LockTimeout = 24, LockTimeout = 24,
RemoteValidationError = 25, RemoteValidationError = 25,
NamespaceNotFound = 26, NamespaceNotFound = 26,
IndexNotFound = 27, IndexNotFound = 27,
PathNotViable = 28, PathNotViable = 28,
NonExistentPath = 29, NonExistentPath = 29,
InvalidPath = 30, InvalidPath = 30,
RoleNotFound = 31,
RolesNotRelated = 32,
PrivilegeNotFound = 33,
CannotBackfillArray = 34,
UserModificationFailed = 35,
RemoteChangeDetected = 36,
FileRenameFailed = 37,
FileNotOpen = 38,
FileStreamFailed = 39,
ConflictingUpdateOperators = 40,
FileAlreadyOpen = 41,
LogWriteFailed = 42,
MaxError MaxError
}; };
static const char* errorString(Error err); static const char* errorString(Error err);
/** /**
* Parse an Error from its "name". Returns UnknownError if "name" is unrecognized. * Parse an Error from its "name". Returns UnknownError if "name" is unrecognized.
* *
* NOTE: Also returns UnknownError for the string "UnknownError". * NOTE: Also returns UnknownError for the string "UnknownError".
*/ */
 End of changes. 1 change blocks. 
0 lines changed or deleted 12 lines changed or added


 expression.h   expression.h 
skipping to change at line 48 skipping to change at line 48
// array types // array types
ALL, ELEM_MATCH_OBJECT, ELEM_MATCH_VALUE, SIZE, ALL, ELEM_MATCH_OBJECT, ELEM_MATCH_VALUE, SIZE,
// leaf types // leaf types
LTE, LT, EQ, GT, GTE, REGEX, MOD, EXISTS, MATCH_IN, NIN, LTE, LT, EQ, GT, GTE, REGEX, MOD, EXISTS, MATCH_IN, NIN,
// special types // special types
TYPE_OPERATOR, GEO, WHERE, TYPE_OPERATOR, GEO, WHERE,
// things that maybe shouldn't even be nodes // things that maybe shouldn't even be nodes
ATOMIC ATOMIC, ALWAYS_FALSE
}; };
MatchExpression( MatchType type ); MatchExpression( MatchType type );
virtual ~MatchExpression(){} virtual ~MatchExpression(){}
/** /**
* determins if the doc matches the expression * determins if the doc matches the expression
* there could be an expression that looks at fields, or the entire doc * there could be an expression that looks at fields, or the entire doc
*/ */
virtual bool matches( const MatchableDocument* doc, MatchDetails* d etails = 0 ) const = 0; virtual bool matches( const MatchableDocument* doc, MatchDetails* d etails = 0 ) const = 0;
skipping to change at line 107 skipping to change at line 107
return true; return true;
} }
virtual void debugString( StringBuilder& debug, int level = 0 ) con st; virtual void debugString( StringBuilder& debug, int level = 0 ) con st;
virtual bool equivalent( const MatchExpression* other ) const { virtual bool equivalent( const MatchExpression* other ) const {
return other->matchType() == ATOMIC; return other->matchType() == ATOMIC;
} }
}; };
class FalseMatchExpression : public MatchExpression {
public:
FalseMatchExpression() : MatchExpression( ALWAYS_FALSE ){}
virtual bool matches( const MatchableDocument* doc, MatchDetails* d
etails = 0 ) const {
return false;
}
virtual bool matchesSingleElement( const BSONElement& e ) const {
return false;
}
virtual void debugString( StringBuilder& debug, int level = 0 ) con
st;
virtual bool equivalent( const MatchExpression* other ) const {
return other->matchType() == ALWAYS_FALSE;
}
};
} }
 End of changes. 2 change blocks. 
1 lines changed or deleted 23 lines changed or added


 expression_array.h   expression_array.h 
skipping to change at line 30 skipping to change at line 30
#include <vector> #include <vector>
#include "mongo/base/status.h" #include "mongo/base/status.h"
#include "mongo/bson/bsonobj.h" #include "mongo/bson/bsonobj.h"
#include "mongo/bson/bsonmisc.h" #include "mongo/bson/bsonmisc.h"
#include "mongo/db/matcher/expression.h" #include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_leaf.h" #include "mongo/db/matcher/expression_leaf.h"
namespace mongo { namespace mongo {
/**
* this SHOULD extend from ArrayMatchingMatchExpression
* the only reason it can't is
> db.foo.insert( { x : 5 } )
> db.foo.insert( { x : [5] } )
> db.foo.find( { x : { $all : [ 5 ] } } )
{ "_id" : ObjectId("5162b5c3f98a76ce1e70ed0c"), "x" : 5 }
{ "_id" : ObjectId("5162b5c5f98a76ce1e70ed0d"), "x" : [ 5 ] }
* the { x : 5} doc should NOT match
*
*/
class AllMatchExpression : public MatchExpression {
public:
AllMatchExpression() : MatchExpression( ALL ){}
Status init( const StringData& path );
ArrayFilterEntries* getArrayFilterEntries() { return &_arrayEntries
; }
virtual bool matches( const MatchableDocument* doc, MatchDetails* d
etails = 0 ) const;
virtual bool matchesSingleElement( const BSONElement& e ) const;
virtual void debugString( StringBuilder& debug, int level ) const;
bool equivalent( const MatchExpression* other ) const;
private:
bool _match( const BSONElementSet& all ) const;
StringData _path;
FieldRef _fieldRef;
ArrayFilterEntries _arrayEntries;
};
class ArrayMatchingMatchExpression : public MatchExpression { class ArrayMatchingMatchExpression : public MatchExpression {
public: public:
ArrayMatchingMatchExpression( MatchType matchType ) : MatchExpressi on( matchType ){} ArrayMatchingMatchExpression( MatchType matchType ) : MatchExpressi on( matchType ){}
virtual ~ArrayMatchingMatchExpression(){} virtual ~ArrayMatchingMatchExpression(){}
Status initPath( const StringData& path );
virtual bool matches( const MatchableDocument* doc, MatchDetails* d etails ) const; virtual bool matches( const MatchableDocument* doc, MatchDetails* d etails ) const;
/** /**
* @param e - has to be an array. calls matchesArray with e as an array * @param e - has to be an array. calls matchesArray with e as an array
*/ */
virtual bool matchesSingleElement( const BSONElement& e ) const; virtual bool matchesSingleElement( const BSONElement& e ) const;
virtual bool matchesArray( const BSONObj& anArray, MatchDetails* de tails ) const = 0; virtual bool matchesArray( const BSONObj& anArray, MatchDetails* de tails ) const = 0;
bool equivalent( const MatchExpression* other ) const; bool equivalent( const MatchExpression* other ) const;
protected: const StringData& path() const { return _path; }
private:
StringData _path; StringData _path;
ElementPath _elementPath;
}; };
class ElemMatchObjectMatchExpression : public ArrayMatchingMatchExpress ion { class ElemMatchObjectMatchExpression : public ArrayMatchingMatchExpress ion {
public: public:
ElemMatchObjectMatchExpression() : ArrayMatchingMatchExpression( EL EM_MATCH_OBJECT ){} ElemMatchObjectMatchExpression() : ArrayMatchingMatchExpression( EL EM_MATCH_OBJECT ){}
Status init( const StringData& path, const MatchExpression* sub ); Status init( const StringData& path, const MatchExpression* sub );
bool matchesArray( const BSONObj& anArray, MatchDetails* details ) const; bool matchesArray( const BSONObj& anArray, MatchDetails* details ) const;
virtual void debugString( StringBuilder& debug, int level ) const; virtual void debugString( StringBuilder& debug, int level ) const;
skipping to change at line 149 skipping to change at line 119
virtual bool matchesSingleElement( const BSONElement& e ) const; virtual bool matchesSingleElement( const BSONElement& e ) const;
virtual void debugString( StringBuilder& debug, int level ) const; virtual void debugString( StringBuilder& debug, int level ) const;
virtual bool equivalent( const MatchExpression* other ) const; virtual bool equivalent( const MatchExpression* other ) const;
private: private:
bool _allMatch( const BSONObj& anArray ) const; bool _allMatch( const BSONObj& anArray ) const;
StringData _path; StringData _path;
ElementPath _elementPath;
std::vector< const ArrayMatchingMatchExpression* > _list; std::vector< const ArrayMatchingMatchExpression* > _list;
}; };
class SizeMatchExpression : public ArrayMatchingMatchExpression { class SizeMatchExpression : public ArrayMatchingMatchExpression {
public: public:
SizeMatchExpression() : ArrayMatchingMatchExpression( SIZE ){} SizeMatchExpression() : ArrayMatchingMatchExpression( SIZE ){}
Status init( const StringData& path, int size ); Status init( const StringData& path, int size );
virtual bool matchesArray( const BSONObj& anArray, MatchDetails* de tails ) const; virtual bool matchesArray( const BSONObj& anArray, MatchDetails* de tails ) const;
 End of changes. 5 change blocks. 
37 lines changed or deleted 6 lines changed or added


 expression_context.h   expression_context.h 
skipping to change at line 35 skipping to change at line 35
class InterruptStatus; class InterruptStatus;
class ExpressionContext : class ExpressionContext :
public IntrusiveCounterUnsigned { public IntrusiveCounterUnsigned {
public: public:
virtual ~ExpressionContext(); virtual ~ExpressionContext();
void setDoingMerge(bool b); void setDoingMerge(bool b);
void setInShard(bool b); void setInShard(bool b);
void setInRouter(bool b); void setInRouter(bool b);
void setExtSortAllowed(bool b) { extSortAllowed = b; }
bool getDoingMerge() const; bool getDoingMerge() const;
bool getInShard() const; bool getInShard() const;
bool getInRouter() const; bool getInRouter() const;
bool getExtSortAllowed() const { return extSortAllowed; }
/** /**
Used by a pipeline to check for interrupts so that killOp() work s. Used by a pipeline to check for interrupts so that killOp() work s.
@throws if the operation has been interrupted @throws if the operation has been interrupted
*/ */
void checkForInterrupt(); void checkForInterrupt();
ExpressionContext* clone(); ExpressionContext* clone();
static ExpressionContext *create(InterruptStatus *pStatus); static ExpressionContext *create(InterruptStatus *pStatus);
private: private:
ExpressionContext(InterruptStatus *pStatus); ExpressionContext(InterruptStatus *pStatus);
bool doingMerge; bool doingMerge;
bool inShard; bool inShard;
bool inRouter; bool inRouter;
bool extSortAllowed;
unsigned intCheckCounter; // interrupt check counter unsigned intCheckCounter; // interrupt check counter
InterruptStatus *const pStatus; InterruptStatus *const pStatus;
}; };
} }
/* ======================= INLINED IMPLEMENTATIONS ======================== == */ /* ======================= INLINED IMPLEMENTATIONS ======================== == */
namespace mongo { namespace mongo {
inline void ExpressionContext::setDoingMerge(bool b) { inline void ExpressionContext::setDoingMerge(bool b) {
 End of changes. 3 change blocks. 
0 lines changed or deleted 3 lines changed or added


 expression_leaf.h   expression_leaf.h 
skipping to change at line 33 skipping to change at line 33
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
#include "mongo/bson/bsonobj.h" #include "mongo/bson/bsonobj.h"
#include "mongo/bson/bsonmisc.h" #include "mongo/bson/bsonmisc.h"
#include "mongo/db/matcher/expression.h" #include "mongo/db/matcher/expression.h"
namespace mongo { namespace mongo {
class LeafMatchExpression : public MatchExpression { class LeafMatchExpression : public MatchExpression {
public: public:
LeafMatchExpression( MatchType matchType ) : MatchExpression( match LeafMatchExpression( MatchType matchType )
Type ) { : MatchExpression( matchType ) {
_allHaveToMatch = false;
} }
virtual ~LeafMatchExpression(){} virtual ~LeafMatchExpression(){}
virtual LeafMatchExpression* shallowClone() const = 0; virtual LeafMatchExpression* shallowClone() const = 0;
virtual bool matches( const MatchableDocument* doc, MatchDetails* d etails = 0 ) const; virtual bool matches( const MatchableDocument* doc, MatchDetails* d etails = 0 ) const;
virtual bool matchesSingleElement( const BSONElement& e ) const = 0 ; virtual bool matchesSingleElement( const BSONElement& e ) const = 0 ;
const StringData path() const { return _path; } const StringData path() const { return _path; }
bool allHaveToMatch() const { return _allHaveToMatch; }
protected: protected:
void initPath( const StringData& path ); Status initPath( const StringData& path );
bool _allHaveToMatch;
private: private:
bool _matches( const FieldRef& fieldRef,
const MatchableDocument* doc,
MatchDetails* details ) const;
bool _matchesElementExpandArray( const BSONElement& e ) const;
StringData _path; StringData _path;
FieldRef _fieldRef; ElementPath _elementPath;
}; };
// ----- // -----
class ComparisonMatchExpression : public LeafMatchExpression { class ComparisonMatchExpression : public LeafMatchExpression {
public: public:
ComparisonMatchExpression( MatchType type ) : LeafMatchExpression( type ){} ComparisonMatchExpression( MatchType type ) : LeafMatchExpression( type ){}
Status init( const StringData& path, const BSONElement& rhs ); Status init( const StringData& path, const BSONElement& rhs );
skipping to change at line 232 skipping to change at line 224
virtual void debugString( StringBuilder& debug, int level ) const; virtual void debugString( StringBuilder& debug, int level ) const;
virtual bool equivalent( const MatchExpression* other ) const; virtual bool equivalent( const MatchExpression* other ) const;
private: private:
bool _matches( const StringData& path, bool _matches( const StringData& path,
const MatchableDocument* doc, const MatchableDocument* doc,
MatchDetails* details = 0 ) const; MatchDetails* details = 0 ) const;
StringData _path; StringData _path;
ElementPath _elementPath;
int _type; int _type;
}; };
/** /**
* INTERNAL * INTERNAL
* terrible name * terrible name
* holds the entries of an $in or $all * holds the entries of an $in or $all
* either scalars or regex * either scalars or regex
*/ */
class ArrayFilterEntries { class ArrayFilterEntries {
skipping to change at line 277 skipping to change at line 270
BSONElementSet _equalities; BSONElementSet _equalities;
std::vector<RegexMatchExpression*> _regexes; std::vector<RegexMatchExpression*> _regexes;
}; };
/** /**
* query operator: $in * query operator: $in
*/ */
class InMatchExpression : public LeafMatchExpression { class InMatchExpression : public LeafMatchExpression {
public: public:
InMatchExpression() : LeafMatchExpression( MATCH_IN ){} InMatchExpression() : LeafMatchExpression( MATCH_IN ){}
void init( const StringData& path ); Status init( const StringData& path );
virtual LeafMatchExpression* shallowClone() const; virtual LeafMatchExpression* shallowClone() const;
ArrayFilterEntries* getArrayFilterEntries() { return &_arrayEntries ; } ArrayFilterEntries* getArrayFilterEntries() { return &_arrayEntries ; }
virtual bool matchesSingleElement( const BSONElement& e ) const; virtual bool matchesSingleElement( const BSONElement& e ) const;
virtual void debugString( StringBuilder& debug, int level ) const; virtual void debugString( StringBuilder& debug, int level ) const;
virtual bool equivalent( const MatchExpression* other ) const; virtual bool equivalent( const MatchExpression* other ) const;
 End of changes. 7 change blocks. 
14 lines changed or deleted 6 lines changed or added


 extsort.h   extsort.h 
skipping to change at line 25 skipping to change at line 25
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/pch.h" #include "mongo/pch.h"
#include "mongo/db/index.h" #include "mongo/db/index.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/namespace-inl.h"
#include "mongo/db/curop-inl.h" #include "mongo/db/curop-inl.h"
#include "mongo/util/array.h" #include "mongo/util/array.h"
#define MONGO_USE_NEW_SORTER 1 #define MONGO_USE_NEW_SORTER 1
#if MONGO_USE_NEW_SORTER #if MONGO_USE_NEW_SORTER
# include "mongo/db/sorter/sorter.h" # include "mongo/db/sorter/sorter.h"
#endif #endif
namespace mongo { namespace mongo {
 End of changes. 1 change blocks. 
1 lines changed or deleted 0 lines changed or added


 field_parser-inl.h   field_parser-inl.h 
skipping to change at line 17 skipping to change at line 17
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public 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/>.
*/ */
#include "mongo/s/field_parser.h" #include "mongo/db/field_parser.h"
#include "mongo/util/mongoutils/str.h" #include "mongo/util/mongoutils/str.h"
namespace mongo { namespace mongo {
using mongoutils::str::stream; using mongoutils::str::stream;
// Extracts an array into a vector // Extracts an array into a vector
template<typename T> template<typename T>
FieldParser::FieldState FieldParser::extract(BSONObj doc, FieldParser::FieldState FieldParser::extract(BSONObj doc,
const BSONField<vector<T> >& field, const BSONField<vector<T> >& field,
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 field_ref.h   field_ref.h 
skipping to change at line 20 skipping to change at line 20
* 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 <boost/scoped_array.hpp> #include <boost/scoped_array.hpp>
#include <iosfwd>
#include <string> #include <string>
#include <vector> #include <vector>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
#include "mongo/base/string_data.h" #include "mongo/base/string_data.h"
namespace mongo { namespace mongo {
/** /**
* A FieldPath represents a path in a document, starting from the root. The path * A FieldPath represents a path in a document, starting from the root. The path
skipping to change at line 66 skipping to change at line 67
* undefined otherwise. * undefined otherwise.
*/ */
void setPart(size_t i, const StringData& part); void setPart(size_t i, const StringData& part);
/** /**
* Returns the 'i-th' field part. Assumes i < size(). Behavior is u ndefined otherwise. * Returns the 'i-th' field part. Assumes i < size(). Behavior is u ndefined otherwise.
*/ */
StringData getPart(size_t i) const; StringData getPart(size_t i) const;
/** /**
* Returns true when 'this' FieldRef is a prefix of 'other'. Equali
ty is not considered
* a prefix.
*/
bool isPrefixOf( const FieldRef& other ) const;
/**
* Returns the number of field parts in the prefix that 'this' and
'other' share.
*/
size_t commonPrefixSize( const FieldRef& other ) const;
/**
* Returns a copy of the full dotted field in its current state (i. e., some parts may * Returns a copy of the full dotted field in its current state (i. e., some parts may
* have been replaced since the parse() call). * have been replaced since the parse() call).
*/ */
std::string dottedField( size_t offset = 0 ) const; std::string dottedField( size_t offset = 0 ) const;
/** /**
* Compares the full dotted path represented by this FieldRef to ot
her
*/
bool equalsDottedField( const StringData& other ) const;
/**
* Return 0 if 'this' is equal to 'other' lexicographically, -1 if
is it less than or
* +1 if it is greater than.
*/
int compare( const FieldRef& other ) const;
/**
* Resets the internal state. See note in parse() call. * Resets the internal state. See note in parse() call.
*/ */
void clear(); void clear();
// //
// accessors // accessors
// //
/** /**
* Returns the number of parts in this FieldRef. * Returns the number of parts in this FieldRef.
*/ */
size_t numParts() const { return _size; } size_t numParts() const { return _size; }
/** /**
* Returns the number of fields parts that were replaced so far. Re placing the same * Returns the number of fields parts that were replaced so far. Re placing the same
* fields several times only counts for 1. * fields several times only counts for 1.
*/ */
size_t numReplaced() const; size_t numReplaced() const;
/**
* compares the full dotted path represented by this FieldRef to ot
her
*/
bool equalsDottedField( const StringData& other ) const;
private: private:
// Dotted fields are most often not longer than three parts. We use a mixed structure // Dotted fields are most often not longer than four parts. We use a mixed structure
// here that will not require any extra memory allocation when that is the case. And // here that will not require any extra memory allocation when that is the case. And
// handle larger dotted fields if it is. The idea is not to penaliz e the common case // handle larger dotted fields if it is. The idea is not to penaliz e the common case
// with allocations. // with allocations.
static const size_t kReserveAhead = 4; static const size_t kReserveAhead = 4;
size_t _size; // # of field parts st
ored
StringData _fixed[kReserveAhead]; // first kResevedAhead
field components
std::vector<StringData> _variable; // remaining field com
ponents
// Areas that _fixed and _variable point to.
boost::scoped_array<char> _fieldBase; // concatenation of nu
ll-terminated parts
std::vector<std::string> _replacements; // added with the setP
art call
/** Converts the field part index to the variable part equivalent * / /** Converts the field part index to the variable part equivalent * /
size_t getIndex(size_t i) const { return i-kReserveAhead; } size_t getIndex(size_t i) const { return i-kReserveAhead; }
/** /**
* Returns the new number of parts after appending 'part' to this f ield path. It * Returns the new number of parts after appending 'part' to this f ield path. It
* assumes that 'part' is pointing to an internally allocated area. * assumes that 'part' is pointing to an internally allocated area.
*/ */
size_t appendPart(const StringData& part); size_t appendPart(const StringData& part);
// number of field parts stored
size_t _size;
// first kResevedAhead field components
StringData _fixed[kReserveAhead];
// remaining field components
std::vector<StringData> _variable;
// concatenation of null-terminated parts pointed to by _fixed and
_variable
boost::scoped_array<char> _fieldBase;
// back memory added with the setPart call pointed to by _fized and
_variable
std::vector<std::string> _replacements;
}; };
inline bool operator==(const FieldRef& lhs, const FieldRef& rhs) {
return lhs.compare(rhs) == 0;
}
inline bool operator!=(const FieldRef& lhs, const FieldRef& rhs) {
return lhs.compare(rhs) != 0;
}
inline bool operator<(const FieldRef& lhs, const FieldRef& rhs) {
return lhs.compare(rhs) < 0;
}
inline bool operator<=(const FieldRef& lhs, const FieldRef& rhs) {
return lhs.compare(rhs) <= 0;
}
inline bool operator>(const FieldRef& lhs, const FieldRef& rhs) {
return lhs.compare(rhs) > 0;
}
inline bool operator>=(const FieldRef& lhs, const FieldRef& rhs) {
return lhs.compare(rhs) >= 0;
}
std::ostream& operator<<(std::ostream& stream, const FieldRef& value);
} // namespace mongo } // namespace mongo
 End of changes. 8 change blocks. 
20 lines changed or deleted 70 lines changed or added


 file_allocator.h   file_allocator.h 
skipping to change at line 24 skipping to change at line 24
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include "mongo/pch.h" #include "mongo/pch.h"
#include <list> #include <list>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
#include "mongo/util/concurrency/mutex.h"
namespace mongo { namespace mongo {
/* /*
* Handles allocation of contiguous files on disk. Allocation may be * Handles allocation of contiguous files on disk. Allocation may be
* requested asynchronously or synchronously. * requested asynchronously or synchronously.
* singleton * singleton
*/ */
class FileAllocator : boost::noncopyable { class FileAllocator : boost::noncopyable {
/* /*
* The public functions may not be called concurrently. The alloca tion * The public functions may not be called concurrently. The alloca tion
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 fsync.h   fsync.h 
skipping to change at line 19 skipping to change at line 19
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/util/concurrency/mutex.h"
namespace mongo { namespace mongo {
// Use this for blocking during an fsync-and-lock // Use this for blocking during an fsync-and-lock
extern SimpleMutex filesLockedFsync; extern SimpleMutex filesLockedFsync;
bool lockedForWriting(); bool lockedForWriting();
} }
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 geoparser.h   geoparser.h 
/** /**
* Copyright (C) 2008-2012 10gen Inc. * Copyright (C) 2013 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3 , * it under the terms of the GNU Affero General Public License, version 3 ,
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/db/jsobj.h"
#include <vector>
#include "third_party/s2/s2.h"
#include "mongo/db/geo/shapes.h" #include "mongo/db/geo/shapes.h"
#include "mongo/db/jsobj.h"
class S2Cap;
class S2Cell;
class S2Polyline;
class S2Polygon;
namespace mongo { namespace mongo {
// This class parses geographic data. // This class parses geographic data.
// It parses a subset of GeoJSON and creates S2 shapes from it. // It parses a subset of GeoJSON and creates S2 shapes from it.
// See http://geojson.org/geojson-spec.html for the spec. // See http://geojson.org/geojson-spec.html for the spec.
// //
// This class also parses the ad-hoc geo formats that MongoDB introduce d. // This class also parses the ad-hoc geo formats that MongoDB introduce d.
// //
// The parseFoo methods that return a bool internally call isFoo and re
turn true
// if the foo is parsed correctly.
// The parseFoo methods that do not return a bool assume isFoo is true.
//
// We assume that if you're trying to parse something, you know it's va lid. // We assume that if you're trying to parse something, you know it's va lid.
class GeoParser { class GeoParser {
public: public:
// Try to parse GeoJSON, then try legacy format, return true if eit
her succeed.
// These call the various isPoint and parsePoint methods below.
// You can just use these bool parsePoint(...) methods.
static bool parsePoint(const BSONObj &obj, S2Point *out);
static bool parsePoint(const BSONObj &obj, S2Cell *out);
static bool parsePoint(const BSONObj &obj, Point *out);
// Check to see if it's GeoJSON or if it's legacy geo.
static bool isPoint(const BSONObj &obj); static bool isPoint(const BSONObj &obj);
static void parsePoint(const BSONObj &obj, PointWithCRS *out);
static bool isGeoJSONPoint(const BSONObj &obj); static bool isLine(const BSONObj &obj);
static void parseGeoJSONPoint(const BSONObj &obj, S2Point *out); static void parseLine(const BSONObj &obj, LineWithCRS *out);
static void parseGeoJSONPoint(const BSONObj &obj, S2Cell *out);
static void parseGeoJSONPoint(const BSONObj &obj, Point *out); static bool isBox(const BSONObj &obj);
static void parseBox(const BSONObj &obj, BoxWithCRS *out);
static bool isLegacyPoint(const BSONObj &obj);
static void parseLegacyPoint(const BSONObj &obj, S2Point *out);
static void parseLegacyPoint(const BSONObj &obj, Point *out);
static bool parseLineString(const BSONObj &obj, S2Polyline *out);
static bool isLineString(const BSONObj &obj);
static bool isGeoJSONLineString(const BSONObj &obj);
static void parseGeoJSONLineString(const BSONObj &obj, S2Polyline *
out);
static bool parsePolygon(const BSONObj &obj, S2Polygon *out);
static bool parsePolygon(const BSONObj &obj, Polygon *out);
static bool isPolygon(const BSONObj &obj); static bool isPolygon(const BSONObj &obj);
static bool isGeoJSONPolygon(const BSONObj &obj); static void parsePolygon(const BSONObj &obj, PolygonWithCRS *out);
static bool isLegacyPolygon(const BSONObj &obj);
static void parseGeoJSONPolygon(const BSONObj &obj, S2Polygon *out) // AKA $center or $centerSphere
; static bool isCap(const BSONObj &obj);
static void parseLegacyPolygon(const BSONObj &obj, Polygon *out); static void parseCap(const BSONObj &obj, CapWithCRS *out);
static bool isLegacyBox(const BSONObj &obj); static bool isMultiPoint(const BSONObj &obj);
static void parseLegacyBox(const BSONObj &obj, Box *out); static void parseMultiPoint(const BSONObj &obj, MultiPointWithCRS *
out);
static bool isLegacyCenter(const BSONObj &obj); static bool isMultiLine(const BSONObj &obj);
static void parseLegacyCenter(const BSONObj &obj, Circle *out); static void parseMultiLine(const BSONObj &obj, MultiLineWithCRS *ou
t);
static bool isLegacyCenterSphere(const BSONObj &obj); static bool isMultiPolygon(const BSONObj &obj);
static void parseLegacyCenterSphere(const BSONObj &obj, S2Cap *out) static void parseMultiPolygon(const BSONObj &obj, MultiPolygonWithC
; RS *out);
static bool isGeometryCollection(const BSONObj &obj);
static void parseGeometryCollection(const BSONObj &obj, GeometryCol
lection *out);
// Return true if the CRS field is 1. missing, or 2. is well-formed and // Return true if the CRS field is 1. missing, or 2. is well-formed and
// has a datum we accept. Otherwise, return false. // has a datum we accept. Otherwise, return false.
// NOTE(hk): If this is ever used anywhere but internally, consider // NOTE(hk): If this is ever used anywhere but internally, consider
// returning states: missing, invalid, unknown, ok, etc. -- whateve r // returning states: missing, invalid, unknown, ok, etc. -- whateve r
// needed. // needed.
static bool crsIsOK(const BSONObj& obj); static bool crsIsOK(const BSONObj& obj);
}; };
} // namespace mongo } // namespace mongo
 End of changes. 14 change blocks. 
50 lines changed or deleted 28 lines changed or added


 geoquery.h   geoquery.h 
skipping to change at line 17 skipping to change at line 17
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once
#include "mongo/db/geo/geoparser.h" #include "mongo/db/geo/geoparser.h"
#include "mongo/db/geo/shapes.h"
#include "mongo/util/mongoutils/str.h" #include "mongo/util/mongoutils/str.h"
#include "third_party/s2/s2.h" #include "third_party/s2/s2regionunion.h"
#include "third_party/s2/s2cap.h"
#include "third_party/s2/s2regioncoverer.h"
#include "third_party/s2/s2cell.h"
#include "third_party/s2/s2polyline.h"
#include "third_party/s2/s2polygon.h"
#include "third_party/s2/s2regioncoverer.h"
#pragma once
namespace mongo { namespace mongo {
class GeometryContainer { class GeometryContainer {
public: public:
bool parseFrom(const BSONObj &obj); bool parseFrom(const BSONObj &obj);
// Does we intersect the provided data? Sadly there is no common g /**
ood * To check intersection, we iterate over the otherContainer's geom
// way to check this, so we do different things for all pairs of etries, checking each
// geometry_of(query,data). * geometry to see if we intersect it. If we intersect one geometr
y, we intersect the
* entire other container.
*/
bool intersects(const GeometryContainer& otherContainer) const; bool intersects(const GeometryContainer& otherContainer) const;
bool intersects(const S2Cell& otherPoint) const;
bool intersects(const S2Polyline& otherLine) const; /**
bool intersects(const S2Polygon& otherPolygon) const; * To check containment, we iterate over the otherContainer's geome
// And, within. tries. If we don't
* contain any sub-geometry of the otherContainer, the otherContain
er is not contained
* within us. If each sub-geometry of the otherContainer is contai
ned within us, we contain
* the entire otherContainer.
*/
bool contains(const GeometryContainer& otherContainer) const; bool contains(const GeometryContainer& otherContainer) const;
bool supportsContains() const { /**
return NULL != _polygon.get() * Only polygons (and aggregate types thereof) support contains.
|| NULL != _cap.get() */
|| NULL != _oldPolygon.get() bool supportsContains() const;
|| NULL != _oldCircle.get();
} bool hasS2Region() const;
bool hasS2Region() const {
return NULL != _cell
|| NULL != _line
|| NULL != _polygon
|| NULL != _cap;
}
// Used by s2cursor only to generate a covering of the query object . // Used by s2cursor only to generate a covering of the query object .
// One region is not NULL and this returns it. // One region is not NULL and this returns it.
const S2Region& getRegion() const; const S2Region& getRegion() const;
private: private:
// Does 'this' intersect with the provided type?
bool intersects(const S2Cell& otherPoint) const;
bool intersects(const S2Polyline& otherLine) const;
bool intersects(const S2Polygon& otherPolygon) const;
// These three just iterate over the geometries and call the 3 meth
ods above.
bool intersects(const MultiPointWithCRS& otherMultiPoint) const;
bool intersects(const MultiLineWithCRS& otherMultiLine) const;
bool intersects(const MultiPolygonWithCRS& otherMultiPolygon) const
;
// Used when 'this' has a polygon somewhere, either in _polygon or
_multiPolygon or
// _geometryCollection.
bool contains(const S2Cell& otherCell, const S2Point& otherPoint) c
onst;
bool contains(const S2Polyline& otherLine) const;
bool contains(const S2Polygon& otherPolygon) const;
// Only one of these shared_ptrs should be non-NULL. S2Region is a // Only one of these shared_ptrs should be non-NULL. S2Region is a
// superclass but it only supports testing against S2Cells. We nee d // superclass but it only supports testing against S2Cells. We nee d
// the most specific class we can get. // the most specific class we can get.
shared_ptr<S2Cell> _cell; shared_ptr<PointWithCRS> _point;
// If we have _cell we have _point. We need _cell in some cases, _ shared_ptr<LineWithCRS> _line;
point in others. shared_ptr<PolygonWithCRS> _polygon;
shared_ptr<S2Point> _point; shared_ptr<CapWithCRS> _cap;
shared_ptr<MultiPointWithCRS> _multiPoint;
shared_ptr<S2Polyline> _line; shared_ptr<MultiLineWithCRS> _multiLine;
shared_ptr<S2Polygon> _polygon; shared_ptr<MultiPolygonWithCRS> _multiPolygon;
shared_ptr<S2Cap> _cap; shared_ptr<GeometryCollection> _geometryCollection;
// Legacy shapes. shared_ptr<BoxWithCRS> _box;
shared_ptr<Polygon> _oldPolygon;
shared_ptr<Box> _oldBox; shared_ptr<S2RegionUnion> _region;
shared_ptr<Circle> _oldCircle;
shared_ptr<Point> _oldPoint;
}; };
class NearQuery { class NearQuery {
public: public:
NearQuery() : maxDistance(std::numeric_limits<double>::max()), from NearQuery() : minDistance(0), maxDistance(std::numeric_limits<doubl
Radians(false) {} e>::max()),
NearQuery(const string& f) : field(f), maxDistance(std::numeric_lim fromRadians(false) {}
its<double>::max()), NearQuery(const string& f) : field(f), minDistance(0),
maxDistance(std::numeric_limits<double
>::max()),
fromRadians(false) {} fromRadians(false) {}
bool parseFrom(const BSONObj &obj, double radius); bool parseFrom(const BSONObj &obj, double radius);
bool parseFromGeoNear(const BSONObj &obj, double radius); bool parseFromGeoNear(const BSONObj &obj, double radius);
string field; string field;
S2Point centroid; PointWithCRS centroid;
// Distance IN METERS that we're willing to search. // Min and max distance IN METERS from centroid that we're willing
to search.
double minDistance;
double maxDistance; double maxDistance;
// Did we convert to this distance from radians? (If so, we output distances in radians.) // Did we convert to this distance from radians? (If so, we output distances in radians.)
bool fromRadians; bool fromRadians;
}; };
// This represents either a $within or a $geoIntersects. // This represents either a $within or a $geoIntersects.
class GeoQuery { class GeoQuery {
public: public:
GeoQuery() : field(""), predicate(INVALID) {} GeoQuery() : field(""), predicate(INVALID) {}
GeoQuery(const string& f) : field(f), predicate(INVALID) {} GeoQuery(const string& f) : field(f), predicate(INVALID) {}
 End of changes. 11 change blocks. 
49 lines changed or deleted 68 lines changed or added


 goodies.h   goodies.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 <sstream>
#include <boost/detail/endian.hpp> #include <boost/detail/endian.hpp>
#include <boost/thread/condition_variable.hpp>
#include "mongo/bson/util/misc.h" #include "mongo/bson/util/misc.h"
#include "mongo/util/concurrency/mutex.h"
namespace mongo { namespace mongo {
/* @return a dump of the buffer as hex byte ascii output */ /* @return a dump of the buffer as hex byte ascii output */
string hexdump(const char *data, unsigned len); string hexdump(const char *data, unsigned len);
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();
} }
bool isPrime(int n); bool isPrime(int n);
int nextPrime(int n); int nextPrime(int n);
 End of changes. 4 change blocks. 
5 lines changed or deleted 2 lines changed or added


 grid.h   grid.h 
skipping to change at line 42 skipping to change at line 42
* TODO: used shard_ptr for DBConfig pointers * TODO: used shard_ptr for DBConfig pointers
*/ */
class Grid { class Grid {
public: public:
Grid() : _lock( "Grid" ) , _allowLocalShard( true ) { } Grid() : _lock( "Grid" ) , _allowLocalShard( true ) { }
/** /**
* gets the config the db. * gets the config the db.
* will return an empty DBConfig if not in db already * will return an empty DBConfig if not in db already
*/ */
DBConfigPtr getDBConfig( string ns , bool create=true , const strin g& shardNameHint="" ); DBConfigPtr getDBConfig( const StringData& ns , bool create=true , const string& shardNameHint="" );
/** /**
* removes db entry. * removes db entry.
* on next getDBConfig call will fetch from db * on next getDBConfig call will fetch from db
*/ */
void removeDB( const std::string& db ); void removeDB( const std::string& db );
/** /**
* removes db entry - only this DBConfig object will be removed, * removes db entry - only this DBConfig object will be removed,
* other DBConfigs which may have been created in the meantime wil l not be harmed * other DBConfigs which may have been created in the meantime wil l not be harmed
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 hash.h   hash.h 
/** @file hash.h */ /**
* Copyright (C) 2008-2012 10gen Inc.
/* Copyright 2009 10gen Inc. *
* * This program is free software: you can redistribute it and/or modify
* Licensed under the Apache License, Version 2.0 (the "License"); * it under the terms of the GNU Affero General Public License, version 3
* you may not use this file except in compliance with the License. ,
* You may obtain a copy of the License at * as published by the Free Software Foundation.
* *
* http://www.apache.org/licenses/LICENSE-2.0 * This program is distributed in the hope that it will be useful,
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
* Unless required by applicable law or agreed to in writing, software * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* distributed under the License is distributed on an "AS IS" BASIS, * GNU Affero General Public License for more details.
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli *
ed. * You should have received a copy of the GNU Affero General Public Licen
* See the License for the specific language governing permissions and se
* limitations under the License. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
namespace mongoutils { #include "mongo/pch.h"
#include "mongo/db/jsobj.h"
/** @return hash of a pointer to an unsigned. so you get a 32 bit hash #include <iostream>
out, regardless of whether
pointers are 32 or 64 bit on the particular platform. namespace mongo {
is there a faster way to impl this that hashes just as well? class GeoHash;
*/ struct Point;
inline unsigned hashPointer(void *v) { std::ostream& operator<<(std::ostream &s, const GeoHash &h);
unsigned x = 0;
unsigned char *p = (unsigned char *) &v; /* This class maps an unsigned x,y coordinate pair to a hash value.
for( unsigned i = 0; i < sizeof(void*); i++ ) { * To hash values more interesting than unsigned, use the GeoHashConver
x = x * 131 + p[i]; ter,
} * which maps doubles to unsigned values.
return x; */
} class GeoHash {
public:
inline unsigned hash(unsigned u) { GeoHash();
unsigned char *p = (unsigned char *) &u; // The strings are binary values of length <= 64,
return (((((p[3] * 131) + p[2]) * 131) + p[1]) * 131) + p[0]; // examples: 1001010100101, 1
} explicit GeoHash(const string& hash);
explicit GeoHash(const char *s);
} // bits is how many bits are used to hash each of x and y.
GeoHash(unsigned x, unsigned y, unsigned bits = 32);
GeoHash(const GeoHash& old);
// hash is a raw hash value. we just copy these into our private f
ields.
GeoHash(long long hash, unsigned bits);
// This only works if e is BinData. To get a GeoHash from other BS
ONElements,
// use the converter class.
explicit GeoHash(const BSONElement& e, unsigned bits = 32);
// Convert from the hashed value to unsigned.
void unhash(unsigned *x, unsigned *y) const;
/** Is the 'bit'-th most significant bit set? (NOT the least signi
ficant) */
static bool isBitSet(unsigned val, unsigned bit);
/** Return a GeoHash with one bit of precision lost. */
GeoHash up() const;
bool hasPrefix(const GeoHash& other) const;
string toString() const;
string toStringHex1() const;
void setBit(unsigned pos, bool value);
bool getBit(unsigned pos) const;
bool getBitX(unsigned pos) const;
bool getBitY(unsigned pos) const;
// XXX: what does this really do?
BSONObj wrap(const char* name = "") const;
// XXX what does this do
bool constrains() const;
bool canRefine() const;
// XXX comment better
bool atMinX() const;
bool atMinY() const;
// XXX comment better
bool atMaxX() const;
bool atMaxY() const;
// XXX: what does this do
void move(int x, int y);
GeoHash& operator=(const GeoHash& h);
bool operator==(const GeoHash& h) const;
bool operator!=(const GeoHash& h) const;
bool operator<(const GeoHash& h) const;
// Append the hash in s to our current hash. We expect s to be '0'
or '1' or '\0',
// though we also treat non-'1' values as '0'.
GeoHash& operator+=(const char* s);
GeoHash operator+(const char *s) const;
GeoHash operator+(const std::string& s) const;
// Append the hash to the builder provided.
void appendToBuilder(BSONObjBuilder* b, const char * name) const;
long long getHash() const;
unsigned getBits() const;
GeoHash commonPrefix(const GeoHash& other) const;
private:
// XXX not sure why this is done exactly. Why does binary
// data need to be reversed? byte ordering of some sort?
static void _copyAndReverse(char *dst, const char *src);
// Create a hash from the provided string. Used by the string and
char* cons.
void initFromString(const char *s);
/* Keep the upper _bits*2 bits of _hash, clear the lower bits.
* Maybe there's junk in there? XXX Not sure why this is done.
*/
void clearUnusedBits();
// XXX: what does this do
void _move(unsigned offset, int d);
// XXX: this is nasty and has no example
void unhash_fast(unsigned *x, unsigned *y) const;
void unhash_slow(unsigned *x, unsigned *y) const;
long long _hash;
// Bits per field. Our hash is 64 bits, and we have an X and a Y f
ield,
// so this is 1 to 32.
unsigned _bits;
};
/* Convert between various types and the GeoHash. We need additional in
formation (scaling etc.)
* to convert to/from GeoHash. The additional information doesn't chan
ge often and is the same
* for all conversions, so we stick all the conversion methods here wit
h their associated
* data.
*/
class GeoHashConverter {
public:
struct Parameters {
// How many bits to use for the hash?
int bits;
// X/Y values must be [min, max]
double min;
double max;
// Values are scaled by this when converted to/from hash scale.
double scaling;
};
GeoHashConverter(const Parameters &params);
int getBits() const { return _params.bits; }
double getError() const { return _error; }
double getErrorSphere() const { return _errorSphere ;}
double getMin() const { return _params.min; }
double getMax() const { return _params.max; }
double distanceBetweenHashes(const GeoHash& a, const GeoHash& b) co
nst;
/**
* Hashing functions. Convert the following types to a GeoHash:
* BSONElement
* BSONObj
* Point
* double, double
*/
GeoHash hash(const Point &p) const;
GeoHash hash(const BSONElement& e) const;
GeoHash hash(const BSONObj& o) const;
// src is printed out as debugging information. I'm not sure if it
's actually
// somehow the 'source' of o? Anyway, this is nasty, very nasty.
XXX
GeoHash hash(const BSONObj& o, const BSONObj* src) const;
GeoHash hash(double x, double y) const;
/** Unhashing functions.
* Convert from a hash to the following types:
* double, double
* Point
* BSONObj
*/
// XXX: these should have consistent naming
Point unhashToPoint(const GeoHash &h) const;
Point unhashToPoint(const BSONElement &e) const;
BSONObj unhashToBSONObj(const GeoHash& h) const;
void unhash(const GeoHash &h, double *x, double *y) const;
double sizeOfDiag(const GeoHash& a) const;
// XXX: understand/clean this.
double sizeEdge(const GeoHash& a) const;
private:
// Convert from an unsigned in [0, (max-min)*scaling] to [min, max]
double convertFromHashScale(unsigned in) const;
// Convert from a double that is [min, max] to an unsigned in [0, (
max-min)*scaling]
unsigned convertToHashScale(double in) const;
Parameters _params;
// We compute these based on the _params:
double _error;
double _errorSphere;
};
} // namespace mongo
 End of changes. 2 change blocks. 
17 lines changed or deleted 17 lines changed or added


 hash_index_cursor.h   hash_index_cursor.h 
skipping to change at line 40 skipping to change at line 40
public: public:
HashIndexCursor(const string& hashedField, HashSeed seed, int hashV ersion, HashIndexCursor(const string& hashedField, HashSeed seed, int hashV ersion,
IndexDescriptor* descriptor); IndexDescriptor* descriptor);
virtual ~HashIndexCursor() { } virtual ~HashIndexCursor() { }
virtual Status setOptions(const CursorOptions& options); virtual Status setOptions(const CursorOptions& options);
virtual Status seek(const BSONObj &position); virtual Status seek(const BSONObj &position);
// Returns an error.
virtual Status seek(const vector<const BSONElement*>& position,
const vector<bool>& inclusive);
// Returns an error.
virtual Status skip(const vector<const BSONElement*>& position,
const vector<bool>& inclusive);
bool isEOF() const; bool isEOF() const;
BSONObj getKey() const; BSONObj getKey() const;
DiskLoc getValue() const; DiskLoc getValue() const;
void next(); void next();
string toString(); string toString();
Status savePosition(); Status savePosition();
Status restorePosition(); Status restorePosition();
void aboutToDeleteBucket(const DiskLoc& bucket);
private: private:
string _hashedField; string _hashedField;
scoped_ptr<BtreeCursor> _oldCursor; scoped_ptr<BtreeCursor> _oldCursor;
// Default of zero. // Default of zero.
HashSeed _seed; HashSeed _seed;
// Default of zero. // Default of zero.
int _hashVersion; int _hashVersion;
IndexDescriptor *_descriptor; IndexDescriptor *_descriptor;
 End of changes. 2 change blocks. 
10 lines changed or deleted 0 lines changed or added


 hasher.h   hasher.h 
skipping to change at line 70 skipping to change at line 70
private: private:
HasherFactory(); HasherFactory();
}; };
class BSONElementHasher : private boost::noncopyable { class BSONElementHasher : private boost::noncopyable {
public: public:
/* The hash function we use can be given a seed, to effectively ran domize it /* The hash function we use can be given a seed, to effectively ran domize it
* by choosing from among a family of hash functions. When it is no t specified, * by choosing from among a family of hash functions. When it is no t specified,
* use this. * use this.
*
* WARNING: do not change the hash see value. Hash-based sharding c
lusters will
* expect that value to be zero.
*/ */
static const int DEFAULT_HASH_SEED = 0; static const int DEFAULT_HASH_SEED = 0;
/* This computes a 64-bit hash of the value part of BSONElement "e" , /* This computes a 64-bit hash of the value part of BSONElement "e" ,
* preceded by the seed "seed". Squashes element (and any sub-elem ents) * preceded by the seed "seed". Squashes element (and any sub-elem ents)
* of the same canonical type, so hash({a:{b:4}}) will be the same * of the same canonical type, so hash({a:{b:4}}) will be the same
* as hash({a:{b:4.1}}). In particular, this squashes doubles to 64 -bit long * as hash({a:{b:4.1}}). In particular, this squashes doubles to 64 -bit long
* ints via truncation, so floating point values round towards 0 to the * ints via truncation, so floating point values round towards 0 to the
* nearest int representable as a 64-bit long. * nearest int representable as a 64-bit long.
* *
 End of changes. 1 change blocks. 
0 lines changed or deleted 4 lines changed or added


 hex.h   hex.h 
skipping to change at line 60 skipping to change at line 60
char c = in[i]; char c = in[i];
char hi = hexchars[(c & 0xF0) >> 4]; char hi = hexchars[(c & 0xF0) >> 4];
char lo = hexchars[(c & 0x0F)]; char lo = hexchars[(c & 0x0F)];
out << hi << lo; out << hi << lo;
} }
return out.str(); return out.str();
} }
template <typename T> std::string integerToHex(T val);
inline std::string toHexLower(const void* inRaw, int len) { inline std::string toHexLower(const void* inRaw, int len) {
static const char hexchars[] = "0123456789abcdef"; static const char hexchars[] = "0123456789abcdef";
StringBuilder out; StringBuilder out;
const char* in = reinterpret_cast<const char*>(inRaw); const char* in = reinterpret_cast<const char*>(inRaw);
for (int i=0; i<len; ++i) { for (int i=0; i<len; ++i) {
char c = in[i]; char c = in[i];
char hi = hexchars[(c & 0xF0) >> 4]; char hi = hexchars[(c & 0xF0) >> 4];
char lo = hexchars[(c & 0x0F)]; char lo = hexchars[(c & 0x0F)];
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 index.h   index.h 
skipping to change at line 28 skipping to change at line 28
#pragma once #pragma once
#include "mongo/pch.h" #include "mongo/pch.h"
#include <vector> #include <vector>
#include "mongo/db/diskloc.h" #include "mongo/db/diskloc.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/key.h" #include "mongo/db/key.h"
#include "mongo/db/namespace.h" #include "mongo/db/storage/namespace.h"
namespace mongo { namespace mongo {
/* Details about a particular index. There is one of these effectively for each object in /* Details about a particular index. There is one of these effectively for each object in
system.namespaces (although this also includes the head pointer, whi ch is not in that system.namespaces (although this also includes the head pointer, whi ch is not in that
collection). collection).
** MemoryMapped Record ** (i.e., this is on disk data) ** MemoryMapped Record ** (i.e., this is on disk data)
*/ */
class IndexDetails { class IndexDetails {
skipping to change at line 87 skipping to change at line 87
/** /**
* @return offset into keyPattern for key * @return offset into keyPattern for key
-1 if doesn't exist -1 if doesn't exist
*/ */
int keyPatternOffset( const string& key ) const; int keyPatternOffset( const string& key ) const;
bool inKeyPattern( const string& key ) const { return keyPatternOff set( key ) >= 0; } bool inKeyPattern( const string& key ) const { return keyPatternOff set( key ) >= 0; }
/* true if the specified key is in the index */ /* true if the specified key is in the index */
bool hasKey(const BSONObj& key); bool hasKey(const BSONObj& key);
// returns name of this index's storage area // returns name of this index's storage area (database.collection.$
// database.table.$index index)
string indexNamespace() const { string indexNamespace() const {
BSONObj io = info.obj(); return indexNamespaceFromObj(info.obj());
}
// returns the name of an index's storage area (database.collection
.$index) from a BSONObj
static string indexNamespaceFromObj(const BSONObj& io) {
string s; string s;
s.reserve(Namespace::MaxNsLen); s.reserve(Namespace::MaxNsLen);
s = io.getStringField("ns"); s = io.getStringField("ns");
verify( !s.empty() ); verify( !s.empty() );
s += ".$"; s += ".$";
s += io.getStringField("name"); s += io.getStringField("name");
return s; return s;
} }
string indexName() const { // e.g. "ts_1" string indexName() const { // e.g. "ts_1"
skipping to change at line 175 skipping to change at line 178
/** @return true if supported. supported means we can use the inde x, including adding new keys. /** @return true if supported. supported means we can use the inde x, including adding new keys.
it may not mean we can build the index version in quest ion: we may not maintain building it may not mean we can build the index version in quest ion: we may not maintain building
of indexes in old formats in the future. of indexes in old formats in the future.
*/ */
static bool isASupportedIndexVersionNumber(int v) { return (v&1)==v ; } // v == 0 || v == 1 static bool isASupportedIndexVersionNumber(int v) { return (v&1)==v ; } // v == 0 || v == 1
}; };
class NamespaceDetails; class NamespaceDetails;
// changedId should be initialized to false // changedId should be initialized to false
void assureSysIndexesEmptied(const char *ns, IndexDetails *exceptForIdI // @return how many things were deleted
ndex); int assureSysIndexesEmptied(const char *ns, IndexDetails *exceptForIdIn
dex);
int removeFromSysIndexes(const char *ns, const char *idxName); int removeFromSysIndexes(const char *ns, const char *idxName);
/** /**
* Prepare to build an index. Does not actually build it (except for a special _id case). * Prepare to build an index. Does not actually build it (except for a special _id case).
* - We validate that the params are good * - We validate that the params are good
* - That the index does not already exist * - That the index does not already exist
* - Creates the source collection if it DNE * - Creates the source collection if it DNE
* *
* example of 'io': * example of 'io':
* { ns : 'test.foo', name : 'z', key : { z : 1 } } * { ns : 'test.foo', name : 'z', key : { z : 1 } }
 End of changes. 4 change blocks. 
6 lines changed or deleted 12 lines changed or added


 index_cursor.h   index_cursor.h 
skipping to change at line 51 skipping to change at line 51
class IndexCursor { class IndexCursor {
public: public:
virtual ~IndexCursor() { } virtual ~IndexCursor() { }
// XXX SHORT TERM HACKS THAT MUST DIE: 2d index // XXX SHORT TERM HACKS THAT MUST DIE: 2d index
virtual DiskLoc getBucket() const { return DiskLoc(); } virtual DiskLoc getBucket() const { return DiskLoc(); }
// XXX SHORT TERM HACKS THAT MUST DIE: 2d index // XXX SHORT TERM HACKS THAT MUST DIE: 2d index
virtual int getKeyOfs() const { return 0; } virtual int getKeyOfs() const { return 0; }
// XXX SHORT TERM HACKS THAT MUST DIE: btree deletion
virtual void aboutToDeleteBucket(const DiskLoc& bucket) { }
/** /**
* Set options on the cursor (direction). See CursorOptions below. * Set options on the cursor (direction). See CursorOptions below.
*/ */
virtual Status setOptions(const CursorOptions& options) = 0; virtual Status setOptions(const CursorOptions& options) = 0;
/** /**
* A cursor doesn't point anywhere by default. You must seek to th e start position. * A cursor doesn't point anywhere by default. You must seek to th e start position.
* The provided position must be a predicate that the index underst ands. The * The provided position must be a predicate that the index underst ands. The
* predicate must describe one value, though there may be several i nstances * predicate must describe one value, though there may be several i nstances
* *
* Possible return values: * Possible return values:
* 1. Success: seeked to the position. * 1. Success: seeked to the position.
* 2. Success: seeked to 'closest' key oriented according to the cu rsor's direction. * 2. Success: seeked to 'closest' key oriented according to the cu rsor's direction.
* 3. Error: can't seek to the position. * 3. Error: can't seek to the position.
*/ */
virtual Status seek(const BSONObj& position) = 0; virtual Status seek(const BSONObj& position) = 0;
/**
* Same contract as the seek above. This method is here because of
the historical
* super-tight coupling of the BtreeCursor, the Btree access method
s, and various query
* logic (FieldRangeVector) which expect to be able to seek with th
e arguments below.
*
* DEPRECATED. Only the Btree should implement this. If/when quer
y processing is cleaned
* up, this will likely die.
*
* Seek to the provided position.
* We expect that position.size() == inclusive.size().
* If inclusive[i] is true, the i-th field of the key can be equal
to position[i].
* If inclusive[i] is false, the i-th field of the key cannot be.
Whether or not it
* is less than or greater than position[i] depends on the directio
n of the cursor.
*/
virtual Status seek(const vector<const BSONElement*>& position,
const vector<bool>& inclusive) = 0;
/**
* Seek to a key from our current position, as opposed to the root
of the tree.
* Aforementioned tight coupling between query and Btree expects to
have quick skips from
* the current position in the cursor. See comments for the two ar
gument seek(...) above.
*
* DEPRECATED. Only the Btree should implement this. If/when quer
y processing is cleaned
* up, this will die.
*/
virtual Status skip(const vector<const BSONElement*>& position,
const vector<bool>& inclusive) = 0;
// //
// Iteration support // Iteration support
// //
// Are we out of documents? // Are we out of documents?
virtual bool isEOF() const = 0; virtual bool isEOF() const = 0;
// Move to the next key/value pair. Assumes !isEOF(). // Move to the next key/value pair. Assumes !isEOF().
virtual void next() = 0; virtual void next() = 0;
 End of changes. 2 change blocks. 
42 lines changed or deleted 0 lines changed or added


 index_descriptor.h   index_descriptor.h 
skipping to change at line 143 skipping to change at line 143
// Return the info object. // Return the info object.
BSONObj infoObj() { return _infoObj; } BSONObj infoObj() { return _infoObj; }
// Set multikey attribute. We never unset it. // Set multikey attribute. We never unset it.
void setMultikey() { void setMultikey() {
_namespaceDetails->setIndexIsMultikey(parentNS().c_str(), _inde xNumber); _namespaceDetails->setIndexIsMultikey(parentNS().c_str(), _inde xNumber);
} }
// Is this index being created in the background? // Is this index being created in the background?
bool isBackgroundIndex() { bool isBackgroundIndex() {
return _indexNumber >= _namespaceDetails->nIndexes; return _indexNumber >= _namespaceDetails->getCompletedIndexCoun t();
} }
private: private:
// Related catalog information. // Related catalog information.
NamespaceDetails* _namespaceDetails; NamespaceDetails* _namespaceDetails;
// What # index are we in the catalog represented by _namespaceDeta ils? Needed for setting // What # index are we in the catalog represented by _namespaceDeta ils? Needed for setting
// and getting multikey. // and getting multikey.
int _indexNumber; int _indexNumber;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 index_rebuilder.h   index_rebuilder.h 
skipping to change at line 47 skipping to change at line 47
*/ */
void checkDB(const std::string& dbname, bool* firstTime); void checkDB(const std::string& dbname, bool* firstTime);
/** /**
* Actually retry an index build on a given namespace. * Actually retry an index build on a given namespace.
* @param dbName the name of the database for accessing db.system.i ndexes * @param dbName the name of the database for accessing db.system.i ndexes
* @param nsd the namespace details of the namespace building the i ndex * @param nsd the namespace details of the namespace building the i ndex
* @param index the offset into nsd's index array of the partially- built index * @param index the offset into nsd's index array of the partially- built index
*/ */
void retryIndexBuild(const std::string& dbName, void retryIndexBuild(const std::string& dbName,
NamespaceDetails* nsd, NamespaceDetails* nsd );
const int index);
}; };
extern IndexRebuilder indexRebuilder; extern IndexRebuilder indexRebuilder;
} }
 End of changes. 1 change blocks. 
2 lines changed or deleted 1 lines changed or added


 initialize_server_global_state.h   initialize_server_global_state.h 
skipping to change at line 25 skipping to change at line 25
*/ */
#pragma once #pragma once
namespace mongo { namespace mongo {
/** /**
* Perform initialization activity common across all mongo server types . * Perform initialization activity common across all mongo server types .
* *
* Set up logging, daemonize the process, configure SSL, etc. * Set up logging, daemonize the process, configure SSL, etc.
*/
bool initializeServerGlobalState();
/**
* Forks and detaches the server, on platforms that support it, if cmdL
ine.doFork is true.
* *
* If isMongodShutdownSpecialCase, perform this processing knowing that * Call after processing the command line but before running mongo init
* we're only bringing this process up to kill another mongod. ializers.
*
* TODO: Untie the knot that requires the isMongodShutdownSpecialCase p
arameter.
*/ */
bool initializeServerGlobalState(bool isMongodShutdownSpecialCase = fal se); void forkServerOrDie();
void setupCoreSignals(); void setupCoreSignals();
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
6 lines changed or deleted 9 lines changed or added


 initializer.h   initializer.h 
skipping to change at line 83 skipping to change at line 83
* *
* It's a programming error for this to fail, but if it does it will re turn a status other * It's a programming error for this to fail, but if it does it will re turn a status other
* than Status::OK. * than Status::OK.
* *
* This means that the few initializers that might want to terminate th e program by failing * This means that the few initializers that might want to terminate th e program by failing
* should probably arrange to terminate the process themselves. * should probably arrange to terminate the process themselves.
*/ */
Status runGlobalInitializers(const InitializerContext::ArgumentVector& args, Status runGlobalInitializers(const InitializerContext::ArgumentVector& args,
const InitializerContext::EnvironmentMap& env); const InitializerContext::EnvironmentMap& env);
Status runGlobalInitializers(int argc, const char* const* argv, const c
har* const* envp);
/** /**
* Same as runGlobalInitializers(), except prints a brief message to st d::cerr * Same as runGlobalInitializers(), except prints a brief message to st d::cerr
* and terminates the process on failure. * and terminates the process on failure.
*/ */
void runGlobalInitializersOrDie(const InitializerContext::ArgumentVecto
r& args,
const InitializerContext::EnvironmentMa
p& env);
void runGlobalInitializersOrDie(int argc, const char* const* argv, cons t char* const* envp); void runGlobalInitializersOrDie(int argc, const char* const* argv, cons t char* const* envp);
} // namespace mongo } // namespace mongo
 End of changes. 2 change blocks. 
5 lines changed or deleted 3 lines changed or added


 instance.h   instance.h 
skipping to change at line 140 skipping to change at line 140
extern int lockFile; extern int lockFile;
#ifdef _WIN32 #ifdef _WIN32
extern HANDLE lockFileHandle; extern HANDLE lockFileHandle;
#endif #endif
void acquirePathLock(bool doingRepair=false); // if doingRepair=true do n't consider unclean shutdown an error void acquirePathLock(bool doingRepair=false); // if doingRepair=true do n't consider unclean shutdown an error
void maybeCreatePidFile(); void maybeCreatePidFile();
void exitCleanly( ExitCode code ); void exitCleanly( ExitCode code );
void checkAndInsert(const char *ns, BSONObj& js);
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 intervalbtreecursor.h   intervalbtreecursor.h 
skipping to change at line 76 skipping to change at line 76
virtual BSONObj current() { return currLoc().obj(); } virtual BSONObj current() { return currLoc().obj(); }
virtual DiskLoc currLoc(); virtual DiskLoc currLoc();
virtual bool advance(); virtual bool advance();
virtual BSONObj currKey() const; virtual BSONObj currKey() const;
virtual DiskLoc refLoc() { return currLoc(); } virtual DiskLoc refLoc() { return currLoc(); }
virtual void aboutToDeleteBucket( const DiskLoc& b ); static void aboutToDeleteBucket( const DiskLoc& b );
virtual BSONObj indexKeyPattern() { return _indexDetails.keyPattern (); } virtual BSONObj indexKeyPattern() { return _indexDetails.keyPattern (); }
virtual bool supportGetMore() { return false; } virtual bool supportGetMore() { return false; }
virtual void noteLocation(); virtual void noteLocation();
virtual void checkLocation(); virtual void checkLocation();
virtual bool supportYields() { return true; } virtual bool supportYields() { return true; }
skipping to change at line 104 skipping to change at line 104
virtual bool modifiedKeys() const { return _multikeyFlag; } virtual bool modifiedKeys() const { return _multikeyFlag; }
virtual BSONObj prettyIndexBounds() const; virtual BSONObj prettyIndexBounds() const;
virtual long long nscanned() { return _nscanned; } virtual long long nscanned() { return _nscanned; }
virtual CoveredIndexMatcher* matcher() const { return _matcher.get( ); } virtual CoveredIndexMatcher* matcher() const { return _matcher.get( ); }
virtual void setMatcher( shared_ptr<CoveredIndexMatcher> matcher ) { _matcher = matcher; } virtual void setMatcher( shared_ptr<CoveredIndexMatcher> matcher ) { _matcher = matcher; }
virtual ~IntervalBtreeCursor();
private: private:
IntervalBtreeCursor( NamespaceDetails* namespaceDetails, IntervalBtreeCursor( NamespaceDetails* namespaceDetails,
const IndexDetails& indexDetails, const IndexDetails& indexDetails,
const BSONObj& lowerBound, const BSONObj& lowerBound,
bool lowerBoundInclusive, bool lowerBoundInclusive,
const BSONObj& upperBound, const BSONObj& upperBound,
bool upperBoundInclusive ); bool upperBoundInclusive );
// For handling bucket deletion.
static unordered_set<IntervalBtreeCursor*> _activeCursors;
static SimpleMutex _activeCursorsMutex;
void init(); void init();
/** /**
* @return a location in the btree, determined by the parameters sp ecified. * @return a location in the btree, determined by the parameters sp ecified.
* @param key - The key to search for. * @param key - The key to search for.
* @param afterKey - If true, return the first btree key greater th an the supplied 'key'. * @param afterKey - If true, return the first btree key greater th an the supplied 'key'.
* If false, return the first key equal to the supplied 'key'. * If false, return the first key equal to the supplied 'key'.
*/ */
BtreeKeyLocation locateKey( const BSONObj& key, bool afterKey ); BtreeKeyLocation locateKey( const BSONObj& key, bool afterKey );
 End of changes. 3 change blocks. 
1 lines changed or deleted 7 lines changed or added


 is_master.h   is_master.h 
skipping to change at line 67 skipping to change at line 67
return true; return true;
return false; return false;
} }
inline bool isMaster(const char * dbname = 0) { inline bool isMaster(const char * dbname = 0) {
if( _isMaster() ) if( _isMaster() )
return true; return true;
if ( ! dbname ) { if ( ! dbname ) {
Database *database = cc().database(); Database *database = cc().database();
verify( database ); verify( database );
dbname = database->name.c_str(); dbname = database->name().c_str();
} }
return strcmp( dbname , "local" ) == 0; return strcmp( dbname , "local" ) == 0;
} }
inline bool isMasterNs( const char *ns ) { inline bool isMasterNs( const char *ns ) {
if ( _isMaster() ) if ( _isMaster() )
return true; return true;
verify( ns ); verify( ns );
if ( ! str::startsWith( ns , "local" ) ) if ( ! str::startsWith( ns , "local" ) )
return false; return false;
return ns[5] == 0 || ns[5] == '.'; return ns[5] == 0 || ns[5] == '.';
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 jsregexp.h   jsregexp.h 
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- // Copyright 2012 the V8 project authors. All rights reserved.
* // Redistribution and use in source and binary forms, with or without
* ***** BEGIN LICENSE BLOCK ***** // modification, are permitted provided that the following conditions are
* Version: MPL 1.1/GPL 2.0/LGPL 2.1 // met:
* //
* The contents of this file are subject to the Mozilla Public License Vers // * Redistributions of source code must retain the above copyright
ion // notice, this list of conditions and the following disclaimer.
* 1.1 (the "License"); you may not use this file except in compliance with // * Redistributions in binary form must reproduce the above
* the License. You may obtain a copy of the License at // copyright notice, this list of conditions and the following
* http://www.mozilla.org/MPL/ // disclaimer in the documentation and/or other materials provided
* // with the distribution.
* Software distributed under the License is distributed on an "AS IS" basi // * Neither the name of Google Inc. nor the names of its
s, // contributors may be used to endorse or promote products derived
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License // from this software without specific prior written permission.
* for the specific language governing rights and limitations under the //
* License. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* The Original Code is Mozilla Communicator client code, released // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* March 31, 1998. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* The Initial Developer of the Original Code is // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* Netscape Communications Corporation. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* Portions created by the Initial Developer are Copyright (C) 1998 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* the Initial Developer. All Rights Reserved. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* Contributor(s): // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Alternatively, the contents of this file may be used under the terms of #ifndef V8_JSREGEXP_H_
* either of the GNU General Public License Version 2 or later (the "GPL"), #define V8_JSREGEXP_H_
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL
"), #include "allocation.h"
* in which case the provisions of the GPL or the LGPL are applicable inste #include "assembler.h"
ad #include "zone-inl.h"
* of those above. If you wish to allow use of your version of this file on
ly namespace v8 {
* under the terms of either the GPL or the LGPL, and not to allow others t namespace internal {
o
* use your version of this file under the terms of the MPL, indicate your class NodeVisitor;
* decision by deleting the provisions above and replace them with the noti class RegExpCompiler;
ce class RegExpMacroAssembler;
* and other provisions required by the GPL or the LGPL. If you do not dele class RegExpNode;
te class RegExpTree;
* the provisions above, a recipient may use your version of this file unde class BoyerMooreLookahead;
r
* the terms of any one of the MPL, the GPL or the LGPL. class RegExpImpl {
* public:
* ***** END LICENSE BLOCK ***** */ // Whether V8 is compiled with native regexp support or not.
static bool UsesNativeRegExp() {
#ifndef jsregexp_h___ #ifdef V8_INTERPRETED_REGEXP
#define jsregexp_h___ return false;
/* #else
* JS regular expression interface. return true;
*/
#include <stddef.h>
#include "jspubtd.h"
#include "jsstr.h"
#ifdef JS_THREADSAFE
#include "jsdhash.h"
#endif #endif
}
// Creates a regular expression literal in the old space.
// This function calls the garbage collector if necessary.
static Handle<Object> CreateRegExpLiteral(Handle<JSFunction> constructor,
Handle<String> pattern,
Handle<String> flags,
bool* has_pending_exception);
// Returns a string representation of a regular expression.
// Implements RegExp.prototype.toString, see ECMA-262 section 15.10.6.4.
// This function calls the garbage collector if necessary.
static Handle<String> ToString(Handle<Object> value);
// Parses the RegExp pattern and prepares the JSRegExp object with
// generic data and choice of implementation - as well as what
// the implementation wants to store in the data field.
// Returns false if compilation fails.
static Handle<Object> Compile(Handle<JSRegExp> re,
Handle<String> pattern,
Handle<String> flags,
Zone* zone);
// See ECMA-262 section 15.10.6.2.
// This function calls the garbage collector if necessary.
static Handle<Object> Exec(Handle<JSRegExp> regexp,
Handle<String> subject,
int index,
Handle<JSArray> lastMatchInfo);
// Prepares a JSRegExp object with Irregexp-specific data.
static void IrregexpInitialize(Handle<JSRegExp> re,
Handle<String> pattern,
JSRegExp::Flags flags,
int capture_register_count);
static void AtomCompile(Handle<JSRegExp> re,
Handle<String> pattern,
JSRegExp::Flags flags,
Handle<String> match_pattern);
static Handle<Object> AtomExec(Handle<JSRegExp> regexp,
Handle<String> subject,
int index,
Handle<JSArray> lastMatchInfo);
enum IrregexpResult { RE_FAILURE = 0, RE_SUCCESS = 1, RE_EXCEPTION = -1 }
;
// Prepare a RegExp for being executed one or more times (using
// IrregexpExecOnce) on the subject.
// This ensures that the regexp is compiled for the subject, and that
// the subject is flat.
// Returns the number of integer spaces required by IrregexpExecOnce
// as its "registers" argument. If the regexp cannot be compiled,
// an exception is set as pending, and this function returns negative.
static int IrregexpPrepare(Handle<JSRegExp> regexp,
Handle<String> subject);
// Calculate the size of offsets vector for the case of global regexp
// and the number of matches this vector is able to store.
static int GlobalOffsetsVectorSize(Handle<JSRegExp> regexp,
int registers_per_match,
int* max_matches);
// Execute a regular expression on the subject, starting from index.
// If matching succeeds, return the number of matches. This can be large
r
// than one in the case of global regular expressions.
// The captures and subcaptures are stored into the registers vector.
// If matching fails, returns RE_FAILURE.
// If execution fails, sets a pending exception and returns RE_EXCEPTION.
static int IrregexpExecRaw(Handle<JSRegExp> regexp,
Handle<String> subject,
int index,
Vector<int> registers);
// Execute an Irregexp bytecode pattern.
// On a successful match, the result is a JSArray containing
// captured positions. On a failure, the result is the null value.
// Returns an empty handle in case of an exception.
static Handle<Object> IrregexpExec(Handle<JSRegExp> regexp,
Handle<String> subject,
int index,
Handle<JSArray> lastMatchInfo);
// Array index in the lastMatchInfo array.
static const int kLastCaptureCount = 0;
static const int kLastSubject = 1;
static const int kLastInput = 2;
static const int kFirstCapture = 3;
static const int kLastMatchOverhead = 3;
// Direct offset into the lastMatchInfo array.
static const int kLastCaptureCountOffset =
FixedArray::kHeaderSize + kLastCaptureCount * kPointerSize;
static const int kLastSubjectOffset =
FixedArray::kHeaderSize + kLastSubject * kPointerSize;
static const int kLastInputOffset =
FixedArray::kHeaderSize + kLastInput * kPointerSize;
static const int kFirstCaptureOffset =
FixedArray::kHeaderSize + kFirstCapture * kPointerSize;
// Used to access the lastMatchInfo array.
static int GetCapture(FixedArray* array, int index) {
return Smi::cast(array->get(index + kFirstCapture))->value();
}
static void SetLastCaptureCount(FixedArray* array, int to) {
array->set(kLastCaptureCount, Smi::FromInt(to));
}
static void SetLastSubject(FixedArray* array, String* to) {
array->set(kLastSubject, to);
}
static void SetLastInput(FixedArray* array, String* to) {
array->set(kLastInput, to);
}
static void SetCapture(FixedArray* array, int index, int to) {
array->set(index + kFirstCapture, Smi::FromInt(to));
}
static int GetLastCaptureCount(FixedArray* array) {
return Smi::cast(array->get(kLastCaptureCount))->value();
}
// For acting on the JSRegExp data FixedArray.
static int IrregexpMaxRegisterCount(FixedArray* re);
static void SetIrregexpMaxRegisterCount(FixedArray* re, int value);
static int IrregexpNumberOfCaptures(FixedArray* re);
static int IrregexpNumberOfRegisters(FixedArray* re);
static ByteArray* IrregexpByteCode(FixedArray* re, bool is_ascii);
static Code* IrregexpNativeCode(FixedArray* re, bool is_ascii);
// Limit the space regexps take up on the heap. In order to limit this w
e
// would like to keep track of the amount of regexp code on the heap. Th
is
// is not tracked, however. As a conservative approximation we track the
// total regexp code compiled including code that has subsequently been f
reed
// and the total executable memory at any point.
static const int kRegExpExecutableMemoryLimit = 16 * MB;
static const int kRegWxpCompiledLimit = 1 * MB;
private:
static String* last_ascii_string_;
static String* two_byte_cached_string_;
static bool CompileIrregexp(
Handle<JSRegExp> re, Handle<String> sample_subject, bool is_ascii);
static inline bool EnsureCompiledIrregexp(
Handle<JSRegExp> re, Handle<String> sample_subject, bool is_ascii);
// Set the subject cache. The previous string buffer is not deleted, so
the
// caller should ensure that it doesn't leak.
static void SetSubjectCache(String* subject,
char* utf8_subject,
int uft8_length,
int character_position,
int utf8_position);
// A one element cache of the last utf8_subject string and its length. T
he
// subject JS String object is cached in the heap. We also cache a
// translation between position and utf8 position.
static char* utf8_subject_cache_;
static int utf8_length_cache_;
static int utf8_position_;
static int character_position_;
};
// Represents the location of one element relative to the intersection of
// two sets. Corresponds to the four areas of a Venn diagram.
enum ElementInSetsRelation {
kInsideNone = 0,
kInsideFirst = 1,
kInsideSecond = 2,
kInsideBoth = 3
};
// Represents code units in the range from from_ to to_, both ends are
// inclusive.
class CharacterRange {
public:
CharacterRange() : from_(0), to_(0) { }
// For compatibility with the CHECK_OK macro
CharacterRange(void* null) { ASSERT_EQ(NULL, null); } //NOLINT
CharacterRange(uc16 from, uc16 to) : from_(from), to_(to) { }
static void AddClassEscape(uc16 type, ZoneList<CharacterRange>* ranges,
Zone* zone);
static Vector<const int> GetWordBounds();
static inline CharacterRange Singleton(uc16 value) {
return CharacterRange(value, value);
}
static inline CharacterRange Range(uc16 from, uc16 to) {
ASSERT(from <= to);
return CharacterRange(from, to);
}
static inline CharacterRange Everything() {
return CharacterRange(0, 0xFFFF);
}
bool Contains(uc16 i) { return from_ <= i && i <= to_; }
uc16 from() const { return from_; }
void set_from(uc16 value) { from_ = value; }
uc16 to() const { return to_; }
void set_to(uc16 value) { to_ = value; }
bool is_valid() { return from_ <= to_; }
bool IsEverything(uc16 max) { return from_ == 0 && to_ >= max; }
bool IsSingleton() { return (from_ == to_); }
void AddCaseEquivalents(ZoneList<CharacterRange>* ranges, bool is_ascii,
Zone* zone);
static void Split(ZoneList<CharacterRange>* base,
Vector<const int> overlay,
ZoneList<CharacterRange>** included,
ZoneList<CharacterRange>** excluded,
Zone* zone);
// Whether a range list is in canonical form: Ranges ordered by from valu
e,
// and ranges non-overlapping and non-adjacent.
static bool IsCanonical(ZoneList<CharacterRange>* ranges);
// Convert range list to canonical form. The characters covered by the ra
nges
// will still be the same, but no character is in more than one range, an
d
// adjacent ranges are merged. The resulting list may be shorter than the
// original, but cannot be longer.
static void Canonicalize(ZoneList<CharacterRange>* ranges);
// Negate the contents of a character range in canonical form.
static void Negate(ZoneList<CharacterRange>* src,
ZoneList<CharacterRange>* dst,
Zone* zone);
static const int kStartMarker = (1 << 24);
static const int kPayloadMask = (1 << 24) - 1;
private:
uc16 from_;
uc16 to_;
};
// A set of unsigned integers that behaves especially well on small
// integers (< 32). May do zone-allocation.
class OutSet: public ZoneObject {
public:
OutSet() : first_(0), remaining_(NULL), successors_(NULL) { }
OutSet* Extend(unsigned value, Zone* zone);
bool Get(unsigned value);
static const unsigned kFirstLimit = 32;
private:
// Destructively set a value in this set. In most cases you want
// to use Extend instead to ensure that only one instance exists
// that contains the same values.
void Set(unsigned value, Zone* zone);
// The successors are a list of sets that contain the same values
// as this set and the one more value that is not present in this
// set.
ZoneList<OutSet*>* successors(Zone* zone) { return successors_; }
OutSet(uint32_t first, ZoneList<unsigned>* remaining)
: first_(first), remaining_(remaining), successors_(NULL) { }
uint32_t first_;
ZoneList<unsigned>* remaining_;
ZoneList<OutSet*>* successors_;
friend class Trace;
};
// A mapping from integers, specified as ranges, to a set of integers.
// Used for mapping character ranges to choices.
class DispatchTable : public ZoneObject {
public:
explicit DispatchTable(Zone* zone) : tree_(zone) { }
class Entry {
public:
Entry() : from_(0), to_(0), out_set_(NULL) { }
Entry(uc16 from, uc16 to, OutSet* out_set)
: from_(from), to_(to), out_set_(out_set) { }
uc16 from() { return from_; }
uc16 to() { return to_; }
void set_to(uc16 value) { to_ = value; }
void AddValue(int value, Zone* zone) {
out_set_ = out_set_->Extend(value, zone);
}
OutSet* out_set() { return out_set_; }
private:
uc16 from_;
uc16 to_;
OutSet* out_set_;
};
class Config {
public:
typedef uc16 Key;
typedef Entry Value;
static const uc16 kNoKey;
static const Entry NoValue() { return Value(); }
static inline int Compare(uc16 a, uc16 b) {
if (a == b)
return 0;
else if (a < b)
return -1;
else
return 1;
}
};
void AddRange(CharacterRange range, int value, Zone* zone);
OutSet* Get(uc16 value);
void Dump();
template <typename Callback>
void ForEach(Callback* callback) {
return tree()->ForEach(callback);
}
private:
// There can't be a static empty set since it allocates its
// successors in a zone and caches them.
OutSet* empty() { return &empty_; }
OutSet empty_;
ZoneSplayTree<Config>* tree() { return &tree_; }
ZoneSplayTree<Config> tree_;
};
#define FOR_EACH_NODE_TYPE(VISIT) \
VISIT(End) \
VISIT(Action) \
VISIT(Choice) \
VISIT(BackReference) \
VISIT(Assertion) \
VISIT(Text)
#define FOR_EACH_REG_EXP_TREE_TYPE(VISIT) \
VISIT(Disjunction) \
VISIT(Alternative) \
VISIT(Assertion) \
VISIT(CharacterClass) \
VISIT(Atom) \
VISIT(Quantifier) \
VISIT(Capture) \
VISIT(Lookahead) \
VISIT(BackReference) \
VISIT(Empty) \
VISIT(Text)
#define FORWARD_DECLARE(Name) class RegExp##Name;
FOR_EACH_REG_EXP_TREE_TYPE(FORWARD_DECLARE)
#undef FORWARD_DECLARE
class TextElement {
public:
enum Type {UNINITIALIZED, ATOM, CHAR_CLASS};
TextElement() : type(UNINITIALIZED) { }
explicit TextElement(Type t) : type(t), cp_offset(-1) { }
static TextElement Atom(RegExpAtom* atom);
static TextElement CharClass(RegExpCharacterClass* char_class);
int length();
Type type;
union {
RegExpAtom* u_atom;
RegExpCharacterClass* u_char_class;
} data;
int cp_offset;
};
class Trace;
struct NodeInfo {
NodeInfo()
: being_analyzed(false),
been_analyzed(false),
follows_word_interest(false),
follows_newline_interest(false),
follows_start_interest(false),
at_end(false),
visited(false),
replacement_calculated(false) { }
// Returns true if the interests and assumptions of this node
// matches the given one.
bool Matches(NodeInfo* that) {
return (at_end == that->at_end) &&
(follows_word_interest == that->follows_word_interest) &&
(follows_newline_interest == that->follows_newline_interest) &&
(follows_start_interest == that->follows_start_interest);
}
// Updates the interests of this node given the interests of the
// node preceding it.
void AddFromPreceding(NodeInfo* that) {
at_end |= that->at_end;
follows_word_interest |= that->follows_word_interest;
follows_newline_interest |= that->follows_newline_interest;
follows_start_interest |= that->follows_start_interest;
}
bool HasLookbehind() {
return follows_word_interest ||
follows_newline_interest ||
follows_start_interest;
}
// Sets the interests of this node to include the interests of the
// following node.
void AddFromFollowing(NodeInfo* that) {
follows_word_interest |= that->follows_word_interest;
follows_newline_interest |= that->follows_newline_interest;
follows_start_interest |= that->follows_start_interest;
}
void ResetCompilationState() {
being_analyzed = false;
been_analyzed = false;
}
bool being_analyzed: 1;
bool been_analyzed: 1;
// These bits are set of this node has to know what the preceding
// character was.
bool follows_word_interest: 1;
bool follows_newline_interest: 1;
bool follows_start_interest: 1;
bool at_end: 1;
bool visited: 1;
bool replacement_calculated: 1;
};
// Details of a quick mask-compare check that can look ahead in the
// input stream.
class QuickCheckDetails {
public:
QuickCheckDetails()
: characters_(0),
mask_(0),
value_(0),
cannot_match_(false) { }
explicit QuickCheckDetails(int characters)
: characters_(characters),
mask_(0),
value_(0),
cannot_match_(false) { }
bool Rationalize(bool ascii);
// Merge in the information from another branch of an alternation.
void Merge(QuickCheckDetails* other, int from_index);
// Advance the current position by some amount.
void Advance(int by, bool ascii);
void Clear();
bool cannot_match() { return cannot_match_; }
void set_cannot_match() { cannot_match_ = true; }
struct Position {
Position() : mask(0), value(0), determines_perfectly(false) { }
uc16 mask;
uc16 value;
bool determines_perfectly;
};
int characters() { return characters_; }
void set_characters(int characters) { characters_ = characters; }
Position* positions(int index) {
ASSERT(index >= 0);
ASSERT(index < characters_);
return positions_ + index;
}
uint32_t mask() { return mask_; }
uint32_t value() { return value_; }
private:
// How many characters do we have quick check information from. This is
// the same for all branches of a choice node.
int characters_;
Position positions_[4];
// These values are the condensate of the above array after Rationalize()
.
uint32_t mask_;
uint32_t value_;
// If set to true, there is no way this quick check can match at all.
// E.g., if it requires to be at the start of the input, and isn't.
bool cannot_match_;
};
extern int kUninitializedRegExpNodePlaceHolder;
struct JSRegExpStatics { class RegExpNode: public ZoneObject {
JSString *input; /* input string to match (perl $_, GC root) public:
*/ explicit RegExpNode(Zone* zone)
JSBool multiline; /* whether input contains newlines (perl $* : replacement_(NULL), trace_count_(0), zone_(zone) {
) */ bm_info_[0] = bm_info_[1] = NULL;
uint16 parenCount; /* number of valid elements in parens[] */ }
uint16 moreLength; /* number of allocated elements in morePare virtual ~RegExpNode();
ns */ virtual void Accept(NodeVisitor* visitor) = 0;
JSSubString parens[9]; /* last set of parens matched (perl $1, $2) // Generates a goto to this node or actually generates the code at this p
*/ oint.
JSSubString *moreParens; /* null or realloc'd vector for $10, etc. * virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0;
/ // How many characters must this node consume at a minimum in order to
JSSubString lastMatch; /* last string matched (perl $&) */ // succeed. If we have found at least 'still_to_find' characters that
JSSubString lastParen; /* last paren matched (perl $+) */ // must be consumed there is no need to ask any following nodes whether
JSSubString leftContext; /* input to left of last match (perl $`) */ // they are sure to eat any more characters. The not_at_start argument i
JSSubString rightContext; /* input to right of last match (perl $') * s
/ // used to indicate that we know we are not at the start of the input. I
}; n
// this case anchored branches will always fail and can be ignored when
/* // determining how many characters are consumed on success.
* This struct holds a bitmap representation of a class from a regexp. virtual int EatsAtLeast(int still_to_find,
* There's a list of these referenced by the classList field in the JSRegEx int recursion_depth,
p bool not_at_start) = 0;
* struct below. The initial state has startIndex set to the offset in the // Emits some quick code that checks whether the preloaded characters mat
* original regexp source of the beginning of the class contents. The first ch.
* use of the class converts the source representation into a bitmap. // Falls through on certain failure, jumps to the label on possible succe
* ss.
*/ // If the node cannot make a quick check it does nothing and returns fals
typedef struct RECharSet { e.
JSPackedBool converted; bool EmitQuickCheck(RegExpCompiler* compiler,
JSPackedBool sense; Trace* trace,
uint16 length; bool preload_has_checked_bounds,
union { Label* on_possible_success,
uint8 *bits; QuickCheckDetails* details_return,
struct { bool fall_through_on_failure);
size_t startIndex; // For a given number of characters this returns a mask and a value. The
size_t length; // next n characters are anded with the mask and compared with the value.
} src; // A comparison failure indicates the node cannot match the next n charac
} u; ters.
} RECharSet; // A comparison success indicates the node may match.
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
/* RegExpCompiler* compiler,
* This macro is safe because moreParens is guaranteed to be allocated and int characters_filled_in,
big bool not_at_start) = 0;
* enough to hold parenCount, or else be null when parenCount is 0. static const int kNodeIsTooComplexForGreedyLoops = -1;
*/ virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoo
#define REGEXP_PAREN_SUBSTRING(res, num) ps; }
\ // Only returns the successor for a text node of length 1 that matches an
(((jsuint)(num) < (jsuint)(res)->parenCount) y
\ // character and that has no guards on it.
? ((jsuint)(num) < 9) virtual RegExpNode* GetSuccessorOfOmnivorousTextNode(
\ RegExpCompiler* compiler) {
? &(res)->parens[num] return NULL;
\ }
: &(res)->moreParens[(num) - 9]
\ // Collects information on the possible code units (mod 128) that can mat
: &js_EmptySubString) ch if
// we look forward. This is used for a Boyer-Moore-like string searching
typedef struct RENode RENode; // implementation. TODO(erikcorry): This should share more code with
// EatsAtLeast, GetQuickCheckDetails. The budget argument is used to lim
struct JSRegExp { it
jsrefcount nrefs; /* reference count */ // the number of nodes we are willing to look at in order to create this
uint16 flags; /* flags, see jsapi.h's JSREG_* defines */ data.
uint16 cloneIndex; /* index in fp->vars or funobj->slots of static const int kFillInBMBudget = 200;
cloned regexp object */ virtual void FillInBMInfo(int offset,
size_t parenCount; /* number of parenthesized submatches */ int recursion_depth,
size_t classCount; /* count [...] bitmaps */ int budget,
RECharSet *classList; /* list of [...] bitmaps */ BoyerMooreLookahead* bm,
JSString *source; /* locked source string, sans // */ bool not_at_start) {
jsbytecode program[1]; /* regular expression bytecode */ UNREACHABLE();
}; }
extern JSRegExp * // If we know that the input is ASCII then there are some nodes that can
js_NewRegExp(JSContext *cx, JSTokenStream *ts, // never match. This method returns a node that can be substituted for
JSString *str, uintN flags, JSBool flat); // itself, or NULL if the node can never match.
virtual RegExpNode* FilterASCII(int depth) { return this; }
extern JSRegExp * // Helper for FilterASCII.
js_NewRegExpOpt(JSContext *cx, JSTokenStream *ts, RegExpNode* replacement() {
JSString *str, JSString *opt, JSBool flat); ASSERT(info()->replacement_calculated);
return replacement_;
#define HOLD_REGEXP(cx, re) JS_ATOMIC_INCREMENT(&(re)->nrefs) }
#define DROP_REGEXP(cx, re) js_DestroyRegExp(cx, re) RegExpNode* set_replacement(RegExpNode* replacement) {
info()->replacement_calculated = true;
extern void replacement_ = replacement;
js_DestroyRegExp(JSContext *cx, JSRegExp *re); return replacement; // For convenience.
}
/*
* Execute re on input str at *indexp, returning null in *rval on mismatch. // We want to avoid recalculating the lookahead info, so we store it on t
* On match, return true if test is true, otherwise return an array object. he
* Update *indexp and cx->regExpStatics always on match. // node. Only info that is for this node is stored. We can tell that th
*/ e
extern JSBool // info is for this node when offset == 0, so the information is calculat
js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp ed
, // relative to this node.
JSBool test, jsval *rval); void SaveBMInfo(BoyerMooreLookahead* bm, bool not_at_start, int offset) {
if (offset == 0) set_bm_info(not_at_start, bm);
/* }
* These two add and remove GC roots, respectively, so their calls must be
* well-ordered. Label* label() { return &label_; }
*/ // If non-generic code is generated for a node (i.e. the node is not at t
extern JSBool he
js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res); // start of the trace) then it cannot be reused. This variable sets a li
mit
extern void // on how often we allow that to happen before we insist on starting a ne
js_FreeRegExpStatics(JSContext *cx, JSRegExpStatics *res); w
// trace and generating generic code for a node that can be reused by flu
#define JSVAL_IS_REGEXP(cx, v) shing
\ // the deferred actions in the current trace and generating a goto.
(JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) && static const int kMaxCopiesCodeGenerated = 10;
\
OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_RegExpClass) NodeInfo* info() { return &info_; }
extern JSClass js_RegExpClass; BoyerMooreLookahead* bm_info(bool not_at_start) {
return bm_info_[not_at_start ? 1 : 0];
extern JSObject * }
js_InitRegExpClass(JSContext *cx, JSObject *obj);
Zone* zone() const { return zone_; }
/*
* Export js_regexp_toString to the decompiler. protected:
*/ enum LimitResult { DONE, CONTINUE };
extern JSBool RegExpNode* replacement_;
js_regexp_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval); LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace);
/* void set_bm_info(bool not_at_start, BoyerMooreLookahead* bm) {
* Create, serialize/deserialize, or clone a RegExp object. bm_info_[not_at_start ? 1 : 0] = bm;
*/ }
extern JSObject *
js_NewRegExpObject(JSContext *cx, JSTokenStream *ts, private:
jschar *chars, size_t length, uintN flags); static const int kFirstCharBudget = 10;
Label label_;
extern JSBool NodeInfo info_;
js_XDRRegExp(JSXDRState *xdr, JSObject **objp); // This variable keeps track of how many times code has been generated fo
r
extern JSObject * // this node (in different traces). We don't keep track of where the
js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent); // generated code is located unless the code is generated at the start of
// a trace, in which case it is generic and can be reused by flushing the
/* // deferred operations in the current trace and generating a goto.
* Get and set the per-object (clone or clone-parent) lastIndex slot. int trace_count_;
*/ BoyerMooreLookahead* bm_info_[2];
extern JSBool
js_GetLastIndex(JSContext *cx, JSObject *obj, jsdouble *lastIndex); Zone* zone_;
};
// A simple closed interval.
class Interval {
public:
Interval() : from_(kNone), to_(kNone) { }
Interval(int from, int to) : from_(from), to_(to) { }
Interval Union(Interval that) {
if (that.from_ == kNone)
return *this;
else if (from_ == kNone)
return that;
else
return Interval(Min(from_, that.from_), Max(to_, that.to_));
}
bool Contains(int value) {
return (from_ <= value) && (value <= to_);
}
bool is_empty() { return from_ == kNone; }
int from() const { return from_; }
int to() const { return to_; }
static Interval Empty() { return Interval(); }
static const int kNone = -1;
private:
int from_;
int to_;
};
class SeqRegExpNode: public RegExpNode {
public:
explicit SeqRegExpNode(RegExpNode* on_success)
: RegExpNode(on_success->zone()), on_success_(on_success) { }
RegExpNode* on_success() { return on_success_; }
void set_on_success(RegExpNode* node) { on_success_ = node; }
virtual RegExpNode* FilterASCII(int depth);
virtual void FillInBMInfo(int offset,
int recursion_depth,
int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
on_success_->FillInBMInfo(
offset, recursion_depth + 1, budget - 1, bm, not_at_start);
if (offset == 0) set_bm_info(not_at_start, bm);
}
protected:
RegExpNode* FilterSuccessor(int depth);
private:
RegExpNode* on_success_;
};
class ActionNode: public SeqRegExpNode {
public:
enum Type {
SET_REGISTER,
INCREMENT_REGISTER,
STORE_POSITION,
BEGIN_SUBMATCH,
POSITIVE_SUBMATCH_SUCCESS,
EMPTY_MATCH_CHECK,
CLEAR_CAPTURES
};
static ActionNode* SetRegister(int reg, int val, RegExpNode* on_success);
static ActionNode* IncrementRegister(int reg, RegExpNode* on_success);
static ActionNode* StorePosition(int reg,
bool is_capture,
RegExpNode* on_success);
static ActionNode* ClearCaptures(Interval range, RegExpNode* on_success);
static ActionNode* BeginSubmatch(int stack_pointer_reg,
int position_reg,
RegExpNode* on_success);
static ActionNode* PositiveSubmatchSuccess(int stack_pointer_reg,
int restore_reg,
int clear_capture_count,
int clear_capture_from,
RegExpNode* on_success);
static ActionNode* EmptyMatchCheck(int start_register,
int repetition_register,
int repetition_limit,
RegExpNode* on_success);
virtual void Accept(NodeVisitor* visitor);
virtual void Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int still_to_find,
int recursion_depth,
bool not_at_start);
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
int filled_in,
bool not_at_start) {
return on_success()->GetQuickCheckDetails(
details, compiler, filled_in, not_at_start);
}
virtual void FillInBMInfo(int offset,
int recursion_depth,
int budget,
BoyerMooreLookahead* bm,
bool not_at_start);
Type type() { return type_; }
// TODO(erikcorry): We should allow some action nodes in greedy loops.
virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoo
ps; }
private:
union {
struct {
int reg;
int value;
} u_store_register;
struct {
int reg;
} u_increment_register;
struct {
int reg;
bool is_capture;
} u_position_register;
struct {
int stack_pointer_register;
int current_position_register;
int clear_register_count;
int clear_register_from;
} u_submatch;
struct {
int start_register;
int repetition_register;
int repetition_limit;
} u_empty_match_check;
struct {
int range_from;
int range_to;
} u_clear_captures;
} data_;
ActionNode(Type type, RegExpNode* on_success)
: SeqRegExpNode(on_success),
type_(type) { }
Type type_;
friend class DotPrinter;
};
class TextNode: public SeqRegExpNode {
public:
TextNode(ZoneList<TextElement>* elms,
RegExpNode* on_success)
: SeqRegExpNode(on_success),
elms_(elms) { }
TextNode(RegExpCharacterClass* that,
RegExpNode* on_success)
: SeqRegExpNode(on_success),
elms_(new(zone()) ZoneList<TextElement>(1, zone())) {
elms_->Add(TextElement::CharClass(that), zone());
}
virtual void Accept(NodeVisitor* visitor);
virtual void Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int still_to_find,
int recursion_depth,
bool not_at_start);
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
int characters_filled_in,
bool not_at_start);
ZoneList<TextElement>* elements() { return elms_; }
void MakeCaseIndependent(bool is_ascii);
virtual int GreedyLoopTextLength();
virtual RegExpNode* GetSuccessorOfOmnivorousTextNode(
RegExpCompiler* compiler);
virtual void FillInBMInfo(int offset,
int recursion_depth,
int budget,
BoyerMooreLookahead* bm,
bool not_at_start);
void CalculateOffsets();
virtual RegExpNode* FilterASCII(int depth);
private:
enum TextEmitPassType {
NON_ASCII_MATCH, // Check for characters that can't match.
SIMPLE_CHARACTER_MATCH, // Case-dependent single character check.
NON_LETTER_CHARACTER_MATCH, // Check characters that have no case equi
vs.
CASE_CHARACTER_MATCH, // Case-independent single character check
.
CHARACTER_CLASS_MATCH // Character class.
};
static bool SkipPass(int pass, bool ignore_case);
static const int kFirstRealPass = SIMPLE_CHARACTER_MATCH;
static const int kLastPass = CHARACTER_CLASS_MATCH;
void TextEmitPass(RegExpCompiler* compiler,
TextEmitPassType pass,
bool preloaded,
Trace* trace,
bool first_element_checked,
int* checked_up_to);
int Length();
ZoneList<TextElement>* elms_;
};
class AssertionNode: public SeqRegExpNode {
public:
enum AssertionNodeType {
AT_END,
AT_START,
AT_BOUNDARY,
AT_NON_BOUNDARY,
AFTER_NEWLINE
};
static AssertionNode* AtEnd(RegExpNode* on_success) {
return new(on_success->zone()) AssertionNode(AT_END, on_success);
}
static AssertionNode* AtStart(RegExpNode* on_success) {
return new(on_success->zone()) AssertionNode(AT_START, on_success);
}
static AssertionNode* AtBoundary(RegExpNode* on_success) {
return new(on_success->zone()) AssertionNode(AT_BOUNDARY, on_success);
}
static AssertionNode* AtNonBoundary(RegExpNode* on_success) {
return new(on_success->zone()) AssertionNode(AT_NON_BOUNDARY, on_succes
s);
}
static AssertionNode* AfterNewline(RegExpNode* on_success) {
return new(on_success->zone()) AssertionNode(AFTER_NEWLINE, on_success)
;
}
virtual void Accept(NodeVisitor* visitor);
virtual void Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int still_to_find,
int recursion_depth,
bool not_at_start);
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
int filled_in,
bool not_at_start);
virtual void FillInBMInfo(int offset,
int recursion_depth,
int budget,
BoyerMooreLookahead* bm,
bool not_at_start);
AssertionNodeType type() { return type_; }
void set_type(AssertionNodeType type) { type_ = type; }
private:
void EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace);
enum IfPrevious { kIsNonWord, kIsWord };
void BacktrackIfPrevious(RegExpCompiler* compiler,
Trace* trace,
IfPrevious backtrack_if_previous);
AssertionNode(AssertionNodeType t, RegExpNode* on_success)
: SeqRegExpNode(on_success), type_(t) { }
AssertionNodeType type_;
};
class BackReferenceNode: public SeqRegExpNode {
public:
BackReferenceNode(int start_reg,
int end_reg,
RegExpNode* on_success)
: SeqRegExpNode(on_success),
start_reg_(start_reg),
end_reg_(end_reg) { }
virtual void Accept(NodeVisitor* visitor);
int start_register() { return start_reg_; }
int end_register() { return end_reg_; }
virtual void Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int still_to_find,
int recursion_depth,
bool not_at_start);
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
int characters_filled_in,
bool not_at_start) {
return;
}
virtual void FillInBMInfo(int offset,
int recursion_depth,
int budget,
BoyerMooreLookahead* bm,
bool not_at_start);
private:
int start_reg_;
int end_reg_;
};
class EndNode: public RegExpNode {
public:
enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS };
explicit EndNode(Action action, Zone* zone)
: RegExpNode(zone), action_(action) { }
virtual void Accept(NodeVisitor* visitor);
virtual void Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int still_to_find,
int recursion_depth,
bool not_at_start) { return 0; }
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
int characters_filled_in,
bool not_at_start) {
// Returning 0 from EatsAtLeast should ensure we never get here.
UNREACHABLE();
}
virtual void FillInBMInfo(int offset,
int recursion_depth,
int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
// Returning 0 from EatsAtLeast should ensure we never get here.
UNREACHABLE();
}
private:
Action action_;
};
class NegativeSubmatchSuccess: public EndNode {
public:
NegativeSubmatchSuccess(int stack_pointer_reg,
int position_reg,
int clear_capture_count,
int clear_capture_start,
Zone* zone)
: EndNode(NEGATIVE_SUBMATCH_SUCCESS, zone),
stack_pointer_register_(stack_pointer_reg),
current_position_register_(position_reg),
clear_capture_count_(clear_capture_count),
clear_capture_start_(clear_capture_start) { }
virtual void Emit(RegExpCompiler* compiler, Trace* trace);
private:
int stack_pointer_register_;
int current_position_register_;
int clear_capture_count_;
int clear_capture_start_;
};
class Guard: public ZoneObject {
public:
enum Relation { LT, GEQ };
Guard(int reg, Relation op, int value)
: reg_(reg),
op_(op),
value_(value) { }
int reg() { return reg_; }
Relation op() { return op_; }
int value() { return value_; }
private:
int reg_;
Relation op_;
int value_;
};
class GuardedAlternative {
public:
explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL
) { }
void AddGuard(Guard* guard, Zone* zone);
RegExpNode* node() { return node_; }
void set_node(RegExpNode* node) { node_ = node; }
ZoneList<Guard*>* guards() { return guards_; }
private:
RegExpNode* node_;
ZoneList<Guard*>* guards_;
};
class AlternativeGeneration;
class ChoiceNode: public RegExpNode {
public:
explicit ChoiceNode(int expected_size, Zone* zone)
: RegExpNode(zone),
alternatives_(new(zone)
ZoneList<GuardedAlternative>(expected_size, zone)),
table_(NULL),
not_at_start_(false),
being_calculated_(false) { }
virtual void Accept(NodeVisitor* visitor);
void AddAlternative(GuardedAlternative node) {
alternatives()->Add(node, zone());
}
ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
DispatchTable* GetTable(bool ignore_case);
virtual void Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int still_to_find,
int recursion_depth,
bool not_at_start);
int EatsAtLeastHelper(int still_to_find,
int recursion_depth,
RegExpNode* ignore_this_node,
bool not_at_start);
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
int characters_filled_in,
bool not_at_start);
virtual void FillInBMInfo(int offset,
int recursion_depth,
int budget,
BoyerMooreLookahead* bm,
bool not_at_start);
bool being_calculated() { return being_calculated_; }
bool not_at_start() { return not_at_start_; }
void set_not_at_start() { not_at_start_ = true; }
void set_being_calculated(bool b) { being_calculated_ = b; }
virtual bool try_to_emit_quick_check_for_alternative(int i) { return true
; }
virtual RegExpNode* FilterASCII(int depth);
protected:
int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative);
ZoneList<GuardedAlternative>* alternatives_;
private:
friend class DispatchTableConstructor;
friend class Analysis;
void GenerateGuard(RegExpMacroAssembler* macro_assembler,
Guard* guard,
Trace* trace);
int CalculatePreloadCharacters(RegExpCompiler* compiler, int eats_at_leas
t);
void EmitOutOfLineContinuation(RegExpCompiler* compiler,
Trace* trace,
GuardedAlternative alternative,
AlternativeGeneration* alt_gen,
int preload_characters,
bool next_expects_preload);
DispatchTable* table_;
// If true, this node is never checked at the start of the input.
// Allows a new trace to start with at_start() set to false.
bool not_at_start_;
bool being_calculated_;
};
class NegativeLookaheadChoiceNode: public ChoiceNode {
public:
explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail,
GuardedAlternative then_do_this,
Zone* zone)
: ChoiceNode(2, zone) {
AddAlternative(this_must_fail);
AddAlternative(then_do_this);
}
virtual int EatsAtLeast(int still_to_find,
int recursion_depth,
bool not_at_start);
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
int characters_filled_in,
bool not_at_start);
virtual void FillInBMInfo(int offset,
int recursion_depth,
int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
alternatives_->at(1).node()->FillInBMInfo(
offset, recursion_depth + 1, budget - 1, bm, not_at_start);
if (offset == 0) set_bm_info(not_at_start, bm);
}
// For a negative lookahead we don't emit the quick check for the
// alternative that is expected to fail. This is because quick check cod
e
// starts by loading enough characters for the alternative that takes few
est
// characters, but on a negative lookahead the negative branch did not ta
ke
// part in that calculation (EatsAtLeast) so the assumptions don't hold.
virtual bool try_to_emit_quick_check_for_alternative(int i) { return i !=
0; }
virtual RegExpNode* FilterASCII(int depth);
};
class LoopChoiceNode: public ChoiceNode {
public:
explicit LoopChoiceNode(bool body_can_be_zero_length, Zone* zone)
: ChoiceNode(2, zone),
loop_node_(NULL),
continue_node_(NULL),
body_can_be_zero_length_(body_can_be_zero_length) { }
void AddLoopAlternative(GuardedAlternative alt);
void AddContinueAlternative(GuardedAlternative alt);
virtual void Emit(RegExpCompiler* compiler, Trace* trace);
virtual int EatsAtLeast(int still_to_find,
int recursion_depth,
bool not_at_start);
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
int characters_filled_in,
bool not_at_start);
virtual void FillInBMInfo(int offset,
int recursion_depth,
int budget,
BoyerMooreLookahead* bm,
bool not_at_start);
RegExpNode* loop_node() { return loop_node_; }
RegExpNode* continue_node() { return continue_node_; }
bool body_can_be_zero_length() { return body_can_be_zero_length_; }
virtual void Accept(NodeVisitor* visitor);
virtual RegExpNode* FilterASCII(int depth);
private:
// AddAlternative is made private for loop nodes because alternatives
// should not be added freely, we need to keep track of which node
// goes back to the node itself.
void AddAlternative(GuardedAlternative node) {
ChoiceNode::AddAlternative(node);
}
RegExpNode* loop_node_;
RegExpNode* continue_node_;
bool body_can_be_zero_length_;
};
// Improve the speed that we scan for an initial point where a non-anchored
// regexp can match by using a Boyer-Moore-like table. This is done by
// identifying non-greedy non-capturing loops in the nodes that eat any
// character one at a time. For example in the middle of the regexp
// /foo[\s\S]*?bar/ we find such a loop. There is also such a loop implici
tly
// inserted at the start of any non-anchored regexp.
//
// When we have found such a loop we look ahead in the nodes to find the se
t of
// characters that can come at given distances. For example for the regexp
// /.?foo/ we know that there are at least 3 characters ahead of us, and th
e
// sets of characters that can occur are [any, [f, o], [o]]. We find a rang
e in
// the lookahead info where the set of characters is reasonably constrained
. In
// our example this is from index 1 to 2 (0 is not constrained). We can now
// look 3 characters ahead and if we don't find one of [f, o] (the union of
// [f, o] and [o]) then we can skip forwards by the range size (in this cas
e 2).
//
// For Unicode input strings we do the same, but modulo 128.
//
// We also look at the first string fed to the regexp and use that to get a
hint
// of the character frequencies in the inputs. This affects the assessment
of
// whether the set of characters is 'reasonably constrained'.
//
// We also have another lookahead mechanism (called quick check in the code
),
// which uses a wide load of multiple characters followed by a mask and com
pare
// to determine whether a match is possible at this point.
enum ContainedInLattice {
kNotYet = 0,
kLatticeIn = 1,
kLatticeOut = 2,
kLatticeUnknown = 3 // Can also mean both in and out.
};
inline ContainedInLattice Combine(ContainedInLattice a, ContainedInLattice
b) {
return static_cast<ContainedInLattice>(a | b);
}
ContainedInLattice AddRange(ContainedInLattice a,
const int* ranges,
int ranges_size,
Interval new_range);
class BoyerMoorePositionInfo : public ZoneObject {
public:
explicit BoyerMoorePositionInfo(Zone* zone)
: map_(new(zone) ZoneList<bool>(kMapSize, zone)),
map_count_(0),
w_(kNotYet),
s_(kNotYet),
d_(kNotYet),
surrogate_(kNotYet) {
for (int i = 0; i < kMapSize; i++) {
map_->Add(false, zone);
}
}
bool& at(int i) { return map_->at(i); }
static const int kMapSize = 128;
static const int kMask = kMapSize - 1;
int map_count() const { return map_count_; }
void Set(int character);
void SetInterval(const Interval& interval);
void SetAll();
bool is_non_word() { return w_ == kLatticeOut; }
bool is_word() { return w_ == kLatticeIn; }
private:
ZoneList<bool>* map_;
int map_count_; // Number of set bits in the map.
ContainedInLattice w_; // The \w character class.
ContainedInLattice s_; // The \s character class.
ContainedInLattice d_; // The \d character class.
ContainedInLattice surrogate_; // Surrogate UTF-16 code units.
};
class BoyerMooreLookahead : public ZoneObject {
public:
BoyerMooreLookahead(int length, RegExpCompiler* compiler, Zone* zone);
int length() { return length_; }
int max_char() { return max_char_; }
RegExpCompiler* compiler() { return compiler_; }
int Count(int map_number) {
return bitmaps_->at(map_number)->map_count();
}
BoyerMoorePositionInfo* at(int i) { return bitmaps_->at(i); }
void Set(int map_number, int character) {
if (character > max_char_) return;
BoyerMoorePositionInfo* info = bitmaps_->at(map_number);
info->Set(character);
}
void SetInterval(int map_number, const Interval& interval) {
if (interval.from() > max_char_) return;
BoyerMoorePositionInfo* info = bitmaps_->at(map_number);
if (interval.to() > max_char_) {
info->SetInterval(Interval(interval.from(), max_char_));
} else {
info->SetInterval(interval);
}
}
void SetAll(int map_number) {
bitmaps_->at(map_number)->SetAll();
}
void SetRest(int from_map) {
for (int i = from_map; i < length_; i++) SetAll(i);
}
bool EmitSkipInstructions(RegExpMacroAssembler* masm);
private:
// This is the value obtained by EatsAtLeast. If we do not have at least
this
// many characters left in the sample string then the match is bound to f
ail.
// Therefore it is OK to read a character this far ahead of the current m
atch
// point.
int length_;
RegExpCompiler* compiler_;
// 0x7f for ASCII, 0xffff for UTF-16.
int max_char_;
ZoneList<BoyerMoorePositionInfo*>* bitmaps_;
int GetSkipTable(int min_lookahead,
int max_lookahead,
Handle<ByteArray> boolean_skip_table);
bool FindWorthwhileInterval(int* from, int* to);
int FindBestInterval(
int max_number_of_chars, int old_biggest_points, int* from, int* to);
};
// There are many ways to generate code for a node. This class encapsulate
s
// the current way we should be generating. In other words it encapsulates
// the current state of the code generator. The effect of this is that we
// generate code for paths that the matcher can take through the regular
// expression. A given node in the regexp can be code-generated several ti
mes
// as it can be part of several traces. For example for the regexp:
// /foo(bar|ip)baz/ the code to match baz will be generated twice, once as
part
// of the foo-bar-baz trace and once as part of the foo-ip-baz trace. The
code
// to match foo is generated only once (the traces have a common prefix).
The
// code to store the capture is deferred and generated (twice) after the pl
aces
// where baz has been matched.
class Trace {
public:
// A value for a property that is either known to be true, know to be fal
se,
// or not known.
enum TriBool {
UNKNOWN = -1, FALSE = 0, TRUE = 1
};
class DeferredAction {
public:
DeferredAction(ActionNode::Type type, int reg)
: type_(type), reg_(reg), next_(NULL) { }
DeferredAction* next() { return next_; }
bool Mentions(int reg);
int reg() { return reg_; }
ActionNode::Type type() { return type_; }
private:
ActionNode::Type type_;
int reg_;
DeferredAction* next_;
friend class Trace;
};
class DeferredCapture : public DeferredAction {
public:
DeferredCapture(int reg, bool is_capture, Trace* trace)
: DeferredAction(ActionNode::STORE_POSITION, reg),
cp_offset_(trace->cp_offset()),
is_capture_(is_capture) { }
int cp_offset() { return cp_offset_; }
bool is_capture() { return is_capture_; }
private:
int cp_offset_;
bool is_capture_;
void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; }
};
class DeferredSetRegister : public DeferredAction {
public:
DeferredSetRegister(int reg, int value)
: DeferredAction(ActionNode::SET_REGISTER, reg),
value_(value) { }
int value() { return value_; }
private:
int value_;
};
class DeferredClearCaptures : public DeferredAction {
public:
explicit DeferredClearCaptures(Interval range)
: DeferredAction(ActionNode::CLEAR_CAPTURES, -1),
range_(range) { }
Interval range() { return range_; }
private:
Interval range_;
};
class DeferredIncrementRegister : public DeferredAction {
public:
explicit DeferredIncrementRegister(int reg)
: DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { }
};
Trace()
: cp_offset_(0),
actions_(NULL),
backtrack_(NULL),
stop_node_(NULL),
loop_label_(NULL),
characters_preloaded_(0),
bound_checked_up_to_(0),
flush_budget_(100),
at_start_(UNKNOWN) { }
// End the trace. This involves flushing the deferred actions in the tra
ce
// and pushing a backtrack location onto the backtrack stack. Once this
is
// done we can start a new trace or go to one that has already been
// generated.
void Flush(RegExpCompiler* compiler, RegExpNode* successor);
int cp_offset() { return cp_offset_; }
DeferredAction* actions() { return actions_; }
// A trivial trace is one that has no deferred actions or other state tha
t
// affects the assumptions used when generating code. There is no record
ed
// backtrack location in a trivial trace, so with a trivial trace we will
// generate code that, on a failure to match, gets the backtrack location
// from the backtrack stack rather than using a direct jump instruction.
We
// always start code generation with a trivial trace and non-trivial trac
es
// are created as we emit code for nodes or add to the list of deferred
// actions in the trace. The location of the code generated for a node u
sing
// a trivial trace is recorded in a label in the node so that gotos can b
e
// generated to that code.
bool is_trivial() {
return backtrack_ == NULL &&
actions_ == NULL &&
cp_offset_ == 0 &&
characters_preloaded_ == 0 &&
bound_checked_up_to_ == 0 &&
quick_check_performed_.characters() == 0 &&
at_start_ == UNKNOWN;
}
TriBool at_start() { return at_start_; }
void set_at_start(bool at_start) { at_start_ = at_start ? TRUE : FALSE; }
Label* backtrack() { return backtrack_; }
Label* loop_label() { return loop_label_; }
RegExpNode* stop_node() { return stop_node_; }
int characters_preloaded() { return characters_preloaded_; }
int bound_checked_up_to() { return bound_checked_up_to_; }
int flush_budget() { return flush_budget_; }
QuickCheckDetails* quick_check_performed() { return &quick_check_performe
d_; }
bool mentions_reg(int reg);
// Returns true if a deferred position store exists to the specified
// register and stores the offset in the out-parameter. Otherwise
// returns false.
bool GetStoredPosition(int reg, int* cp_offset);
// These set methods and AdvanceCurrentPositionInTrace should be used onl
y on
// new traces - the intention is that traces are immutable after creation
.
void add_action(DeferredAction* new_action) {
ASSERT(new_action->next_ == NULL);
new_action->next_ = actions_;
actions_ = new_action;
}
void set_backtrack(Label* backtrack) { backtrack_ = backtrack; }
void set_stop_node(RegExpNode* node) { stop_node_ = node; }
void set_loop_label(Label* label) { loop_label_ = label; }
void set_characters_preloaded(int count) { characters_preloaded_ = count;
}
void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; }
void set_flush_budget(int to) { flush_budget_ = to; }
void set_quick_check_performed(QuickCheckDetails* d) {
quick_check_performed_ = *d;
}
void InvalidateCurrentCharacter();
void AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler);
private:
int FindAffectedRegisters(OutSet* affected_registers, Zone* zone);
void PerformDeferredActions(RegExpMacroAssembler* macro,
int max_register,
OutSet& affected_registers,
OutSet* registers_to_pop,
OutSet* registers_to_clear,
Zone* zone);
void RestoreAffectedRegisters(RegExpMacroAssembler* macro,
int max_register,
OutSet& registers_to_pop,
OutSet& registers_to_clear);
int cp_offset_;
DeferredAction* actions_;
Label* backtrack_;
RegExpNode* stop_node_;
Label* loop_label_;
int characters_preloaded_;
int bound_checked_up_to_;
QuickCheckDetails quick_check_performed_;
int flush_budget_;
TriBool at_start_;
};
class NodeVisitor {
public:
virtual ~NodeVisitor() { }
#define DECLARE_VISIT(Type) \
virtual void Visit##Type(Type##Node* that) = 0;
FOR_EACH_NODE_TYPE(DECLARE_VISIT)
#undef DECLARE_VISIT
virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); }
};
// Node visitor used to add the start set of the alternatives to the
// dispatch table of a choice node.
class DispatchTableConstructor: public NodeVisitor {
public:
DispatchTableConstructor(DispatchTable* table, bool ignore_case,
Zone* zone)
: table_(table),
choice_index_(-1),
ignore_case_(ignore_case),
zone_(zone) { }
void BuildTable(ChoiceNode* node);
void AddRange(CharacterRange range) {
table()->AddRange(range, choice_index_, zone_);
}
void AddInverse(ZoneList<CharacterRange>* ranges);
#define DECLARE_VISIT(Type) \
virtual void Visit##Type(Type##Node* that);
FOR_EACH_NODE_TYPE(DECLARE_VISIT)
#undef DECLARE_VISIT
DispatchTable* table() { return table_; }
void set_choice_index(int value) { choice_index_ = value; }
protected:
DispatchTable* table_;
int choice_index_;
bool ignore_case_;
Zone* zone_;
};
// Assertion propagation moves information about assertions such as
// \b to the affected nodes. For instance, in /.\b./ information must
// be propagated to the first '.' that whatever follows needs to know
// if it matched a word or a non-word, and to the second '.' that it
// has to check if it succeeds a word or non-word. In this case the
// result will be something like:
//
// +-------+ +------------+
// | . | | . |
// +-------+ ---> +------------+
// | word? | | check word |
// +-------+ +------------+
class Analysis: public NodeVisitor {
public:
Analysis(bool ignore_case, bool is_ascii)
: ignore_case_(ignore_case),
is_ascii_(is_ascii),
error_message_(NULL) { }
void EnsureAnalyzed(RegExpNode* node);
#define DECLARE_VISIT(Type) \
virtual void Visit##Type(Type##Node* that);
FOR_EACH_NODE_TYPE(DECLARE_VISIT)
#undef DECLARE_VISIT
virtual void VisitLoopChoice(LoopChoiceNode* that);
bool has_failed() { return error_message_ != NULL; }
const char* error_message() {
ASSERT(error_message_ != NULL);
return error_message_;
}
void fail(const char* error_message) {
error_message_ = error_message;
}
private:
bool ignore_case_;
bool is_ascii_;
const char* error_message_;
DISALLOW_IMPLICIT_CONSTRUCTORS(Analysis);
};
struct RegExpCompileData {
RegExpCompileData()
: tree(NULL),
node(NULL),
simple(true),
contains_anchor(false),
capture_count(0) { }
RegExpTree* tree;
RegExpNode* node;
bool simple;
bool contains_anchor;
Handle<String> error;
int capture_count;
};
class RegExpEngine: public AllStatic {
public:
struct CompilationResult {
explicit CompilationResult(const char* error_message)
: error_message(error_message),
code(HEAP->the_hole_value()),
num_registers(0) {}
CompilationResult(Object* code, int registers)
: error_message(NULL),
code(code),
num_registers(registers) {}
const char* error_message;
Object* code;
int num_registers;
};
static CompilationResult Compile(RegExpCompileData* input,
bool ignore_case,
bool global,
bool multiline,
Handle<String> pattern,
Handle<String> sample_subject,
bool is_ascii, Zone* zone);
static void DotPrint(const char* label, RegExpNode* node, bool ignore_cas
e);
};
class OffsetsVector {
public:
inline OffsetsVector(int num_registers, Isolate* isolate)
: offsets_vector_length_(num_registers) {
if (offsets_vector_length_ > Isolate::kJSRegexpStaticOffsetsVectorSize)
{
vector_ = NewArray<int>(offsets_vector_length_);
} else {
vector_ = isolate->jsregexp_static_offsets_vector();
}
}
inline ~OffsetsVector() {
if (offsets_vector_length_ > Isolate::kJSRegexpStaticOffsetsVectorSize)
{
DeleteArray(vector_);
vector_ = NULL;
}
}
inline int* vector() { return vector_; }
inline int length() { return offsets_vector_length_; }
static const int kStaticOffsetsVectorSize =
Isolate::kJSRegexpStaticOffsetsVectorSize;
private:
static Address static_offsets_vector_address(Isolate* isolate) {
return reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vecto
r());
}
int* vector_;
int offsets_vector_length_;
friend class ExternalReference;
};
extern JSBool } } // namespace v8::internal
js_SetLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex);
#endif /* jsregexp_h___ */ #endif // V8_JSREGEXP_H_
 End of changes. 5 change blocks. 
203 lines changed or deleted 1694 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 <boost/thread/tss.hpp>
#include <string>
#include "mongo/bson/oid.h" #include "mongo/bson/oid.h"
#include "mongo/util/log.h"
namespace mongo { namespace mongo {
class BSONObjBuilder; class BSONObjBuilder;
class Message; class Message;
struct LastError { struct LastError {
int code; int code;
string msg; std::string msg;
enum UpdatedExistingType { NotUpdate, True, False } updatedExisting ; enum UpdatedExistingType { NotUpdate, True, False } updatedExisting ;
OID upsertedId; OID upsertedId;
OID writebackId; // this shouldn't get reset so that old GLE are ha ndled OID writebackId; // this shouldn't get reset so that old GLE are ha ndled
int writebackSince; int writebackSince;
long long nObjects; long long nObjects;
int nPrev; int nPrev;
bool valid; bool valid;
bool disabled; bool disabled;
void writeback( OID& oid ) { void writeback(const OID& oid) {
reset( true ); reset( true );
writebackId = oid; writebackId = oid;
writebackSince = 0; writebackSince = 0;
} }
void raiseError(int _code , const char *_msg) { void raiseError(int _code , const char *_msg) {
reset( true ); reset( true );
code = _code; code = _code;
msg = _msg; msg = _msg;
} }
void recordUpdate( bool _updateObjects , long long _nObjects , OID _upsertedId ) { void recordUpdate( bool _updateObjects , long long _nObjects , OID _upsertedId ) {
 End of changes. 4 change blocks. 
2 lines changed or deleted 6 lines changed or added


 list.h   list.h 
// list.h // Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_LIST_H_
#define V8_LIST_H_
#include "utils.h"
namespace v8 {
namespace internal {
// ------------------------------------------------------------------------
----
// The list is a template for very light-weight lists. We are not
// using the STL because we want full control over space and speed of
// the code. This implementation is based on code by Robert Griesemer
// and Rob Pike.
//
// The list is parameterized by the type of its elements (T) and by an
// allocation policy (P). The policy is used for allocating lists in
// the C free store or the zone; see zone.h.
// Forward defined as
// template <typename T,
// class AllocationPolicy = FreeStoreAllocationPolicy> class List
;
template <typename T, class AllocationPolicy>
class List {
public:
explicit List(AllocationPolicy allocator = AllocationPolicy()) {
Initialize(0, allocator);
}
INLINE(explicit List(int capacity,
AllocationPolicy allocator = AllocationPolicy())) {
Initialize(capacity, allocator);
}
INLINE(~List()) { DeleteData(data_); }
// Deallocates memory used by the list and leaves the list in a consisten
t
// empty state.
void Free() {
DeleteData(data_);
Initialize(0);
}
INLINE(void* operator new(size_t size,
AllocationPolicy allocator = AllocationPolicy()
)) {
return allocator.New(static_cast<int>(size));
}
INLINE(void operator delete(void* p)) {
AllocationPolicy::Delete(p);
}
// Please the MSVC compiler. We should never have to execute this.
INLINE(void operator delete(void* p, AllocationPolicy allocator)) {
UNREACHABLE();
}
// Returns a reference to the element at index i. This reference is
// not safe to use after operations that can change the list's
// backing store (e.g. Add).
inline T& operator[](int i) const {
ASSERT(0 <= i);
ASSERT(i < length_);
return data_[i];
}
inline T& at(int i) const { return operator[](i); }
inline T& last() const { return at(length_ - 1); }
inline T& first() const { return at(0); }
INLINE(bool is_empty() const) { return length_ == 0; }
INLINE(int length() const) { return length_; }
INLINE(int capacity() const) { return capacity_; }
Vector<T> ToVector() const { return Vector<T>(data_, length_); }
Vector<const T> ToConstVector() { return Vector<const T>(data_, length_);
}
// Adds a copy of the given 'element' to the end of the list,
// expanding the list if necessary.
void Add(const T& element, AllocationPolicy allocator = AllocationPolicy(
));
// Add all the elements from the argument list to this list.
void AddAll(const List<T, AllocationPolicy>& other,
AllocationPolicy allocator = AllocationPolicy());
// Add all the elements from the vector to this list.
void AddAll(const Vector<T>& other,
AllocationPolicy allocator = AllocationPolicy());
// Inserts the element at the specific index.
void InsertAt(int index, const T& element,
AllocationPolicy allocator = AllocationPolicy());
// Added 'count' elements with the value 'value' and returns a
// vector that allows access to the elements. The vector is valid
// until the next change is made to this list.
Vector<T> AddBlock(T value, int count,
AllocationPolicy allocator = AllocationPolicy());
// Removes the i'th element without deleting it even if T is a
// pointer type; moves all elements above i "down". Returns the
// removed element. This function's complexity is linear in the
// size of the list.
T Remove(int i);
// Remove the given element from the list. Returns whether or not
// the input is included in the list in the first place.
bool RemoveElement(const T& elm);
// Removes the last element without deleting it even if T is a
// pointer type. Returns the removed element.
INLINE(T RemoveLast()) { return Remove(length_ - 1); }
// Deletes current list contents and allocates space for 'length' element
s.
INLINE(void Allocate(int length,
AllocationPolicy allocator = AllocationPolicy()));
// Clears the list by setting the length to zero. Even if T is a
// pointer type, clearing the list doesn't delete the entries.
INLINE(void Clear());
// Drops all but the first 'pos' elements from the list.
INLINE(void Rewind(int pos));
// Drop the last 'count' elements from the list.
INLINE(void RewindBy(int count)) { Rewind(length_ - count); }
bool Contains(const T& elm) const;
int CountOccurrences(const T& elm, int start, int end) const;
// Iterate through all list entries, starting at index 0.
void Iterate(void (*callback)(T* x));
template<class Visitor>
void Iterate(Visitor* visitor);
// Sort all list entries (using QuickSort)
void Sort(int (*cmp)(const T* x, const T* y));
void Sort();
INLINE(void Initialize(int capacity,
AllocationPolicy allocator = AllocationPolicy()));
private:
T* data_;
int capacity_;
int length_;
INLINE(T* NewData(int n, AllocationPolicy allocator)) {
return static_cast<T*>(allocator.New(n * sizeof(T)));
}
INLINE(void DeleteData(T* data)) {
AllocationPolicy::Delete(data);
}
// Increase the capacity of a full list, and add an element.
// List must be full already.
void ResizeAdd(const T& element, AllocationPolicy allocator);
// Inlined implementation of ResizeAdd, shared by inlined and
// non-inlined versions of ResizeAdd.
void ResizeAddInternal(const T& element, AllocationPolicy allocator);
/** // Resize the list.
* Copyright (C) 2008 10gen Inc. void Resize(int new_capacity, AllocationPolicy allocator);
*
* 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
,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
*/
#pragma once
namespace mongo {
/* DON'T USE THIS. it was a dumb idea.
this class uses a mutex for writes, but not for reads.
we can get fancier later...
struct Member : public List1<Member>::Base {
const char *host;
int port;
};
List1<Member> _members;
_members.head()->next();
*/
template<typename T>
class List1 : boost::noncopyable {
public:
/* next() and head() return 0 at end of list */
List1() : _head(0), _m("List1"), _orphans(0) { }
class Base {
friend class List1;
T *_next;
public:
Base() : _next(0){}
~Base() { wassert(false); } // we never want this to happen
T* next() const { return _next; }
};
/** note this is safe:
T* p = mylist.head();
if( p )
use(p);
and this is not:
if( mylist.head() )
use( mylist.head() ); // could become 0
*/
T* head() const { return (T*) _head; }
void push(T* t) {
verify( t->_next == 0 );
scoped_lock lk(_m);
t->_next = (T*) _head;
_head = t;
}
// intentionally leaks.
void orphanAll() {
scoped_lock lk(_m);
_head = 0;
}
/* t is not deleted, but is removed from the list. (orphaned) */
void orphan(T* t) {
scoped_lock lk(_m);
T *&prev = (T*&) _head;
T *n = prev;
while( n != t ) {
uassert( 14050 , "List1: item to orphan not in list", n );
prev = n->_next;
n = prev;
}
prev = t->_next;
if( ++_orphans > 500 )
log() << "warning List1 orphans=" << _orphans << endl;
}
private:
volatile T *_head;
mongo::mutex _m;
int _orphans;
};
DISALLOW_COPY_AND_ASSIGN(List);
}; };
class Map;
class Code;
template<typename T> class Handle;
typedef List<Map*> MapList;
typedef List<Code*> CodeList;
typedef List<Handle<Map> > MapHandleList;
typedef List<Handle<Code> > CodeHandleList;
// Perform binary search for an element in an already sorted
// list. Returns the index of the element of -1 if it was not found.
// |cmp| is a predicate that takes a pointer to an element of the List
// and returns +1 if it is greater, -1 if it is less than the element
// being searched.
template <typename T, class P>
int SortedListBSearch(const List<T>& list, P cmp);
template <typename T>
int SortedListBSearch(const List<T>& list, T elem);
} } // namespace v8::internal
#endif // V8_LIST_H_
 End of changes. 4 change blocks. 
98 lines changed or deleted 194 lines changed or added


 log.h   log.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 <string.h>
#include <sstream>
#include <errno.h>
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/thread/tss.hpp>
#include "mongo/base/status.h" #include "mongo/base/status.h"
#include "mongo/bson/util/builder.h" #include "mongo/bson/util/builder.h"
#include "mongo/util/concurrency/mutex.h" #include "mongo/logger/logger.h"
#include "mongo/util/debug_util.h" #include "mongo/logger/logstream_builder.h"
#include "mongo/util/exit_code.h" #include "mongo/logger/tee.h"
#include "mongo/util/concurrency/thread_name.h"
#ifndef _WIN32
#include <syslog.h>
#endif
namespace mongo { namespace mongo {
enum ExitCode; namespace logger {
typedef void (*ExtraLogContextFn)(BufBuilder& builder);
// using negative numbers so these are always less than ::mongo::loglev Status registerExtraLogContextFn(ExtraLogContextFn contextFn);
el (see MONGO_LOG)
enum LogLevel { LL_DEBUG=-1000 , LL_INFO , LL_NOTICE , LL_WARNING , LL } // namespace logger
_ERROR , LL_SEVERE };
using logger::LogstreamBuilder;
inline const char * logLevelToString( LogLevel l ) { using logger::LabeledLevel;
switch ( l ) { using logger::Tee;
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";
}
}
#ifndef _WIN32
inline const int logLevelToSysLogLevel( LogLevel l) {
switch ( l ) {
case LL_DEBUG:
return LOG_DEBUG;
case LL_INFO:
return LOG_INFO;
case LL_NOTICE:
return LOG_NOTICE;
case LL_WARNING:
return LOG_WARNING;
case LL_ERROR:
return LOG_ERR;
case LL_SEVERE:
return LOG_EMERG;
default:
return LL_INFO;
}
}
#endif
class LabeledLevel {
public:
LabeledLevel( int level ) : _level( level ) {}
LabeledLevel( const char* label, int level ) : _label( label ), _le
vel( level ) {}
LabeledLevel( const string& label, int level ) : _label( label ), _
level( level ) {}
LabeledLevel operator+( int i ) const {
return LabeledLevel( _label, _level + i );
}
LabeledLevel operator+( const char* label ) const {
if( _label == "" )
return LabeledLevel( label, _level );
return LabeledLevel( _label + string("::") + label, _level );
}
LabeledLevel operator+( const std::string& label ) const {
return LabeledLevel( _label + string("::") + label, _level );
}
LabeledLevel operator-( int i ) const {
return LabeledLevel( _label, _level - i );
}
const string& getLabel() const { return _label; }
int getLevel() const { return _level; }
private:
string _label;
int _level;
};
inline bool operator<( const LabeledLevel& ll, const int i ) { return l
l.getLevel() < i; }
inline bool operator<( const int i, const LabeledLevel& ll ) { return i
< ll.getLevel(); }
inline bool operator>( const LabeledLevel& ll, const int i ) { return l
l.getLevel() > i; }
inline bool operator>( const int i, const LabeledLevel& ll ) { return i
> ll.getLevel(); }
inline bool operator<=( const LabeledLevel& ll, const int i ) { return
ll.getLevel() <= i; }
inline bool operator<=( const int i, const LabeledLevel& ll ) { return
i <= ll.getLevel(); }
inline bool operator>=( const LabeledLevel& ll, const int i ) { return
ll.getLevel() >= i; }
inline bool operator>=( const int i, const LabeledLevel& ll ) { return
i >= ll.getLevel(); }
inline bool operator==( const LabeledLevel& ll, const int i ) { return
ll.getLevel() == i; }
inline bool operator==( const int i, const LabeledLevel& ll ) { return
i == ll.getLevel(); }
class LazyString {
public:
virtual ~LazyString() {}
virtual string val() const = 0;
};
// Utility class for stringifying object only when val() called.
template< class T >
class LazyStringImpl : public LazyString {
public:
LazyStringImpl( const T &t ) : t_( t ) {}
virtual string val() const { return t_.toString(); }
private:
const T& t_;
};
class Tee {
public:
virtual ~Tee() {}
virtual void write(LogLevel level , const string& str) = 0;
};
class Nullstream {
public:
virtual Nullstream& operator<< (Tee* tee) {
return *this;
}
virtual ~Nullstream() {}
virtual Nullstream& operator<<(const char *) {
return *this;
}
virtual Nullstream& operator<<(const string& ) {
return *this;
}
virtual Nullstream& operator<<(const StringData& ) {
return *this;
}
virtual Nullstream& operator<<(char *) {
return *this;
}
virtual Nullstream& operator<<(char) {
return *this;
}
virtual Nullstream& operator<<(int) {
return *this;
}
virtual Nullstream& operator<<(ExitCode) {
return *this;
}
virtual Nullstream& operator<<(unsigned long) {
return *this;
}
virtual Nullstream& operator<<(long) {
return *this;
}
virtual Nullstream& operator<<(unsigned) {
return *this;
}
virtual Nullstream& operator<<(unsigned short) {
return *this;
}
virtual Nullstream& operator<<(double) {
return *this;
}
virtual Nullstream& operator<<(void *) {
return *this;
}
virtual Nullstream& operator<<(const void *) {
return *this;
}
virtual Nullstream& operator<<(long long) {
return *this;
}
virtual Nullstream& operator<<(unsigned long long) {
return *this;
}
virtual Nullstream& operator<<(bool) {
return *this;
}
virtual Nullstream& operator<<(const LazyString&) {
return *this;
}
template< class T >
Nullstream& operator<<(T *t) {
return operator<<( static_cast<void*>( t ) );
}
template< class T >
Nullstream& operator<<(const T *t) {
return operator<<( static_cast<const void*>( t ) );
}
template< class T >
Nullstream& operator<<(const boost::shared_ptr<T> &p ) {
T * t = p.get();
if ( ! t )
*this << "null";
else
*this << *t;
return *this;
}
template< class T >
Nullstream& operator<<(const T &t) {
return operator<<( static_cast<const LazyString&>( LazyStringIm
pl< T >( t ) ) );
}
virtual Nullstream& operator<< (std::ostream& ( *endl )(std::ostrea
m&)) {
return *this;
}
virtual Nullstream& operator<< (std::ios_base& (*hex)(std::ios_base
&)) {
return *this;
}
virtual void flush(Tee *t = 0) {}
};
extern Nullstream nullstream;
class Logstream : public Nullstream {
static mongo::mutex mutex;
static int doneSetup;
std::stringstream ss;
int indent;
LogLevel logLevel;
static FILE* logfile;
static boost::scoped_ptr<std::ostream> stream;
static std::vector<Tee*> * globalTees;
static bool isSyslog;
public:
// Type for optional function for inserting context information in
log messages. See
// registerExtraLogContextFn, below.
typedef void (*ExtraLogContextFn)(BufBuilder& builder);
static void logLockless( const StringData& s );
static void setLogFile(FILE* f);
#ifndef _WIN32
static void useSyslog(const char * name) {
std::cout << "using syslog ident: " << name << std::endl;
// openlog requires heap allocated non changing pointer
// this should only be called once per pragram execution
char * newName = (char *) malloc( strlen(name) + 1 );
strcpy( newName , name);
openlog( newName , LOG_PID | LOG_CONS | LOG_ODELAY , LOG_USER )
;
isSyslog = true;
}
#endif
static int magicNumber() { return 1717; }
static int getLogDesc() {
int fd = -1;
if (logfile != NULL)
#if defined(_WIN32)
// the ISO C++ conformant name is _fileno
fd = _fileno( logfile );
#else
fd = fileno( logfile );
#endif
return fd;
}
void flush(Tee *t = 0);
inline Nullstream& setLogLevel(LogLevel l) {
logLevel = l;
return *this;
}
/** note these are virtual */
Logstream& operator<<(const char *x) { ss << x; return *this; }
Logstream& operator<<(const string& x) { ss << x; return *this; }
Logstream& operator<<(const StringData& 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<<(ExitCode 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 x) { ss << x; return *this; }
Logstream& operator<<(unsigned short x){ ss << x; return *this; }
Logstream& operator<<(double x) { ss << x; return *this; }
Logstream& operator<<(void *x) { ss << x; return *this; }
Logstream& operator<<(const void *x) { ss << x; return *this; }
Logstream& operator<<(long long x) { ss << x; return *this; }
Logstream& operator<<(unsigned long long x) { ss << x; return *this
; }
Logstream& operator<<(bool x) { ss << x; return *this
; }
Logstream& operator<<(const LazyString& x) {
ss << x.val();
return *this;
}
Nullstream& operator<< (Tee* tee) {
ss << '\n';
flush(tee);
return *this;
}
Logstream& operator<< (std::ostream& ( *_endl )(std::ostream&)) {
ss << '\n';
flush(0);
return *this;
}
Logstream& operator<< (std::ios_base& (*_hex)(std::ios_base&)) {
ss << _hex;
return *this;
}
Logstream& prolog() {
return *this;
}
void addGlobalTee( Tee * t ) {
if ( ! globalTees )
globalTees = new std::vector<Tee*>();
globalTees->push_back( t );
}
void removeGlobalTee( Tee * tee );
void indentInc(){ indent++; }
void indentDec(){ indent--; }
int getIndent() const { return indent; }
// Replace any pre-existing function for appending context informat
ion to log lines with
// "contextFn". Returns Status::OK on first call, and ErrorCodes::
AlreadyInitialized if
// called more than once. Returns ErrorCodes::BadValue if contextF
n is NULL.
static Status registerExtraLogContextFn(ExtraLogContextFn contextFn
);
private:
Logstream() {
indent = 0;
_init();
}
void _init() {
ss.str("");
logLevel = LL_INFO;
}
public:
static Logstream& get();
};
extern int logLevel;
extern int tlogLevel;
inline Nullstream& out( int level = 0 ) {
if ( level > logLevel )
return nullstream;
return Logstream::get();
}
/* flush the log stream if the log level is /**
at the specified level or higher. */ * Returns a LogstreamBuilder for logging a message with LogSeverity::S
inline void logflush(int level = 0) { evere().
if( level > logLevel ) */
Logstream::get().flush(0); inline LogstreamBuilder severe() {
return LogstreamBuilder(logger::globalLogDomain(),
getThreadName(),
logger::LogSeverity::Severe());
} }
/* without prolog */ /**
inline Nullstream& _log( int level = 0 ) { * Returns a LogstreamBuilder for logging a message with LogSeverity::E
if ( level > logLevel ) rror().
return nullstream; */
return Logstream::get(); inline LogstreamBuilder error() {
return LogstreamBuilder(logger::globalLogDomain(),
getThreadName(),
logger::LogSeverity::Error());
} }
/** logging which we may not want during unit tests (dbtests) runs. /**
set tlogLevel to -1 to suppress tlog() output in a test program. */ * Returns a LogstreamBuilder for logging a message with LogSeverity::W
Nullstream& tlog( int level = 0 ); arning().
*/
// log if debug build or if at a certain level inline LogstreamBuilder warning() {
inline Nullstream& dlog( int level ) { return LogstreamBuilder(logger::globalLogDomain(),
if ( level <= logLevel || DEBUG_BUILD ) getThreadName(),
return Logstream::get().prolog(); logger::LogSeverity::Warning());
return nullstream;
} }
#define MONGO_LOG(level) \ /**
( MONGO_likely( ::mongo::logLevel < (level) ) ) \ * Returns a LogstreamBuilder for logging a message with LogSeverity::L
? ::mongo::nullstream : ::mongo::logWithLevel(level) og().
#define LOG MONGO_LOG */
inline LogstreamBuilder log() {
inline Nullstream& log() { return LogstreamBuilder(logger::globalLogDomain(),
return Logstream::get().prolog(); getThreadName(),
logger::LogSeverity::Log());
} }
// Use MONGO_LOG() instead of this /**
inline Nullstream& logWithLevel( int level ) { * Synonym for log().
if ( level > logLevel ) */
return nullstream; inline LogstreamBuilder out() { return log(); }
return Logstream::get().prolog();
}
inline Nullstream& logWithLevel( LogLevel l ) { /**
return Logstream::get().prolog().setLogLevel( l ); * For logging which we may not want during unit tests (dbtests) runs.
} Set tlogLevel to -1 to
* suppress MONGO_TLOG() output in a test program.
*/
extern int tlogLevel;
inline Nullstream& logWithLevel( const LabeledLevel& ll ) { #define MONGO_LOG(DLEVEL) \
Nullstream& stream = logWithLevel( ll.getLevel() ); if (!(::mongo::logger::globalLogDomain())->shouldLog(::mongo::Logstream
if( ll.getLabel() != "" ) Builder::severityCast(DLEVEL))) {} \
stream << "[" << ll.getLabel() << "] "; else LogstreamBuilder(::mongo::logger::globalLogDomain(), getThreadName
return stream; (), ::mongo::LogstreamBuilder::severityCast(DLEVEL))
}
inline Nullstream& error() { #define LOG MONGO_LOG
return logWithLevel( LL_ERROR );
}
inline Nullstream& warning() { #define MONGO_DLOG(DLEVEL) \
return logWithLevel( LL_WARNING ); if (!(DEBUG_BUILD) && !::mongo::logger::globalLogDomain()->shouldLog(::
} mongo::LogstreamBuilder::severityCast(DLEVEL))) {} \
else LogstreamBuilder(::mongo::logger::globalLogDomain(), getThreadName
(), ::mongo::LogstreamBuilder::severityCast(DLEVEL))
#define MONGO_TLOG(DLEVEL) \
if ((!::mongo::debug && ((DLEVEL) > tlogLevel)) || !::mongo::logger::gl
obalLogDomain()->shouldLog(::mongo::LogstreamBuilder::severityCast(DLEVEL))
) {} \
else LogstreamBuilder(::mongo::logger::globalLogDomain(), getThreadName
(), ::mongo::LogstreamBuilder::severityCast(DLEVEL))
/* default impl returns "" -- mongod overrides */ /* default impl returns "" -- mongod overrides */
extern const char * (*getcurns)(); extern const char * (*getcurns)();
inline Nullstream& problem( int level = 0 ) { inline LogstreamBuilder problem() {
if ( level > logLevel ) std::string curns = getcurns();
return nullstream; curns.push_back(' ');
Logstream& l = Logstream::get().prolog(); return log().setBaseMessage(curns);
l << ' ' << getcurns() << ' ';
return l;
} }
/** /**
log to a file rather than stdout * Rotates the log files. Returns true if all logs rotate successfully
defined in assert_util.cpp .
*/ */
bool initLogging( const string& logpath , bool append );
bool rotateLogs(); bool rotateLogs();
std::string toUtf8String(const std::wstring& wide);
/** output the error # and error message with prefix. /** output the error # and error message with prefix.
handy for use as parm in uassert/massert. handy for use as parm in uassert/massert.
*/ */
string errnoWithPrefix( const char * prefix ); string errnoWithPrefix( const char * prefix );
// Guard that alters the indentation level used by log messages on the
current thread.
// Used only by mongodump (mongo/tools/dump.cpp). Do not introduce new
uses.
struct LogIndentLevel { struct LogIndentLevel {
LogIndentLevel(){ LogIndentLevel();
Logstream::get().indentInc(); ~LogIndentLevel();
}
~LogIndentLevel(){
Logstream::get().indentDec();
}
}; };
extern Tee* const warnings; // Things put here go in serverStatus extern Tee* const warnings; // Things put here go in serverStatus
extern Tee* const startupWarningsLog; // Things put here get reported i n MMS extern Tee* const startupWarningsLog; // Things put here get reported i n MMS
string errnoWithDescription(int errorcode = -1); string errnoWithDescription(int errorcode = -1);
void rawOut( const string &s ); void rawOut( const StringData &s );
/** /**
* Write the current context (backtrace), along with the optional "msg" . * Write the current context (backtrace), along with the optional "msg" .
*/ */
void logContext(const char *msg = NULL); void logContext(const char *msg = NULL);
} // namespace mongo } // namespace mongo
 End of changes. 19 change blocks. 
441 lines changed or deleted 86 lines changed or added


 matchable.h   matchable.h 
skipping to change at line 23 skipping to change at line 23
* 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 "mongo/bson/bsonobj.h" #include "mongo/bson/bsonobj.h"
#include "mongo/db/field_ref.h" #include "mongo/db/field_ref.h"
#include "mongo/db/matcher/path.h"
namespace mongo { namespace mongo {
class MatchableDocument { class MatchableDocument {
public: public:
virtual ~MatchableDocument(); virtual ~MatchableDocument();
virtual BSONObj toBSON() const = 0; virtual BSONObj toBSON() const = 0;
virtual BSONElement getFieldDottedOrArray( const FieldRef& path, virtual ElementIterator* getIterator( const ElementPath& path ) con
size_t* idxPath, st = 0;
bool* inArray ) const =
0;
virtual void getFieldsDotted( const StringData& name,
BSONElementSet &ret,
bool expandLastArray = true ) const =
0;
}; };
class BSONMatchableDocument : public MatchableDocument { class BSONMatchableDocument : public MatchableDocument {
public: public:
BSONMatchableDocument( const BSONObj& obj ); BSONMatchableDocument( const BSONObj& obj );
virtual ~BSONMatchableDocument(); virtual ~BSONMatchableDocument();
virtual BSONObj toBSON() const { return _obj; } virtual BSONObj toBSON() const { return _obj; }
virtual BSONElement getFieldDottedOrArray( const FieldRef& path, virtual ElementIterator* getIterator( const ElementPath& path ) con
size_t* idxPath, st {
bool* inArray ) const; return new BSONElementIterator( path, _obj );
}
virtual void getFieldsDotted( const StringData& name,
BSONElementSet &ret,
bool expandLastArray = true ) const;
private: private:
BSONObj _obj; BSONObj _obj;
}; };
} }
 End of changes. 3 change blocks. 
16 lines changed or deleted 7 lines changed or added


 matcher.h   matcher.h 
skipping to change at line 41 skipping to change at line 41
struct element_lt { struct element_lt {
bool operator()(const BSONElement& l, const BSONElement& r) const { bool operator()(const BSONElement& l, const BSONElement& r) const {
int x = (int) l.canonicalType() - (int) r.canonicalType(); int x = (int) l.canonicalType() - (int) r.canonicalType();
if ( x < 0 ) return true; if ( x < 0 ) return true;
else if ( x > 0 ) return false; else if ( x > 0 ) return false;
return compareElementValues(l,r) < 0; return compareElementValues(l,r) < 0;
} }
}; };
} }
#include "matcher_old.h"
#include "mongo/db/matcher/matcher.h" #include "mongo/db/matcher/matcher.h"
namespace mongo { namespace mongo {
//typedef MatcherOld Matcher; //typedef MatcherOld Matcher;
typedef Matcher2 Matcher; typedef Matcher2 Matcher;
} }
 End of changes. 1 change blocks. 
1 lines changed or deleted 0 lines changed or added


 message_port.h   message_port.h 
skipping to change at line 43 skipping to change at line 43
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;
long long connectionId() const { return _connectionId; } long long connectionId() const { return _connectionId; }
void setConnectionId( long long connectionId ); void setConnectionId( long long connectionId );
void setX509SubjectName(const std::string& x509SubjectName){
_x509SubjectName = x509SubjectName;
}
std::string getX509SubjectName(){
return _x509SubjectName;
}
public: public:
// TODO make this private with some helpers // TODO make this private with some helpers
/* ports can be tagged with various classes. see closeAllSockets(t ag). defaults to 0. */ /* ports can be tagged with various classes. see closeAllSockets(t ag). defaults to 0. */
unsigned tag; unsigned tag;
private: private:
long long _connectionId; long long _connectionId;
std::string _x509SubjectName;
}; };
class MessagingPort : public AbstractMessagingPort { class MessagingPort : public AbstractMessagingPort {
public: public:
MessagingPort(int fd, const SockAddr& remote); MessagingPort(int fd, const SockAddr& remote);
// in some cases the timeout will actually be 2x this value - eg we do a partial send, // in some cases the timeout will actually be 2x this value - eg we do a partial send,
// then the timeout fires, then we try to send again, then the time out fires again with // then the timeout fires, then we try to send again, then the time out fires again with
// no data sent, then we detect that the other side is down // no data sent, then we detect that the other side is down
MessagingPort(double so_timeout = 0, int logLevel = 0 ); MessagingPort(double so_timeout = 0,
logger::LogSeverity logLevel = logger::LogSeverity::L
og() );
MessagingPort(boost::shared_ptr<Socket> socket); MessagingPort(boost::shared_ptr<Socket> socket);
virtual ~MessagingPort(); virtual ~MessagingPort();
void setSocketTimeout(double timeout); void setSocketTimeout(double timeout);
void shutdown(); void shutdown();
/* it's assumed if you reuse a message object, that it doesn't cros s MessagingPort's. /* it's assumed if you reuse a message object, that it doesn't cros s MessagingPort's.
 End of changes. 3 change blocks. 
1 lines changed or deleted 12 lines changed or added


 metadata_loader.h   metadata_loader.h 
skipping to change at line 21 skipping to change at line 21
* 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 <string> #include <string>
#include "mongo/base/status.h"
#include "mongo/client/dbclientinterface.h" #include "mongo/client/dbclientinterface.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
namespace mongo { namespace mongo {
class CollectionManager; class CollectionMetadata;
class CollectionType; class CollectionType;
class DBClientCursor; class DBClientCursor;
/** /**
* The MetadataLoader is responsible for interfacing with the config se rvers and obtaining * The MetadataLoader is responsible for interfacing with the config se rvers and obtaining
* the data that CollectionManagers are made of. Effectively, the loade * the data that CollectionMetadatas are made of. Effectively, the load
r is the "builder" er is the "builder"
* class for that manager. * class for that metadata.
* *
* The loader will go out of its way to try to fetch the smaller amount possible of data * The loader will go out of its way to try to fetch the smaller amount possible of data
* from the config server without sacrificing the freshness and accurac y of the managers is * from the config server without sacrificing the freshness and accurac y of the metadata it
* builds. (See ConfigDiffTracker class.) * builds. (See ConfigDiffTracker class.)
* *
* The class is not thread safe. * The class is not thread safe.
*/ */
class MetadataLoader { class MetadataLoader {
public: public:
/** /**
* Takes a connection string to the config servers to be used for l oading data. Note * Takes a connection string to the config servers to be used for l oading data. Note
* that we make no restrictions about which connection string that is, including * that we make no restrictions about which connection string that is, including
* CUSTOM, which we rely on in testing. * CUSTOM, which we rely on in testing.
*/ */
explicit MetadataLoader(ConnectionString configLoc); explicit MetadataLoader( const ConnectionString& configLoc );
~MetadataLoader(); ~MetadataLoader();
/** /**
* Returns a new manager's instance representing the chunkset of th * Fills a new metadata instance representing the chunkset of the c
e collection 'ns' ollection 'ns'
* (or its entirety, if not sharded) that lives on 'shard'. Optiona * (or its entirety, if not sharded) that lives on 'shard' with dat
lly, uses an a from the config server.
* 'oldManager' for the same 'ns'/'shard'; the contents of 'oldMang * Optionally, uses an 'oldMetadata' for the same 'ns'/'shard'; the
er' can help contents of
* reducing the amount of data read from the config servers. * 'oldMetadata' can help reducing the amount of data read from the
config servers.
* *
* If the collection's information can't be loaded, returns NULL an * OK on success.
d fill in 'errMsg' *
* with a description, if 'errMsg' was provided. * Failure return values:
*/ * Abnormal:
CollectionManager* makeCollectionManager(const string& ns, * @return FailedToParse if there was an error parsing the remote c
const string& shard, onfig data
const CollectionManager* o * Normal:
ldManager, * @return NamespaceNotFound if the collection no longer exists
string* errMsg); * @return HostUnreachable if there was an error contacting the con
fig servers
/** * @return RemoteChangeDetected if the data loaded was modified by
* Returns a new manager's instance representing an non-sharded, em another operation
pty collection with
* the initial version number (1|0|oid).
*/ */
CollectionManager* makeEmptyCollectionManager(); Status makeCollectionMetadata( const string& ns,
const string& shard,
const CollectionMetadata* oldMetadat
a,
CollectionMetadata* metadata ) const
;
private: private:
ConnectionString _configLoc; ConnectionString _configLoc;
/** /**
* Returns true and fills in the internal state of 'manager' to por * Returns OK and fills in the internal state of 'metadata' with ge
tray the portion of neral collection
* the collection 'ns' that lives in 'shard'. If provided, uses the * information, not including chunks.
contents of *
* 'oldManager' as a base, which allows less data to be brought fro * If information about the collection can be accessed or is invali
m the config d, returns:
* server. If information about the collection can be accessed or i * @return NamespaceNotFound if the collection no longer exists
s invalid, returns * @return FailedToParse if there was an error parsing the remote c
* false and fills in an error description on '*errMsg', which is m onfig data
andatory here. * @return HostUnreachable if there was an error contacting the con
fig servers
* @return RemoteChangeDetected if the collection doc loaded is une
xpectedly different
*
*/ */
bool initCollection(const string& ns, Status initCollection( const string& ns,
const string& shard, const string& shard,
const CollectionManager* oldManager, CollectionMetadata* metadata ) const;
CollectionManager* manager,
string* errMsg);
/** /**
* Returns true and fills in the chunk state of 'manager' to portra * Returns OK and fills in the chunk state of 'metadata' to portray
y the chunks of the the chunks of the
* collection 'ns' that sit in 'shard'. If provided, uses the conte * collection 'ns' that sit in 'shard'. If provided, uses the conte
nts of 'oldManager' nts of 'oldMetadata'
* as a base (see description in initCollection above). If informat * as a base (see description in initCollection above).
ion about the *
* chunks can be accessed or is invalid, returns false and fills in * If information about the chunks can be accessed or is invalid, r
an error eturns:
* description on '*errMsg', which is mandatory here. * @return HostUnreachable if there was an error contacting the con
fig servers
* @return RemoteChangeDetected if the chunks loaded are unexpected
ly different
* TODO: @return FailedToParse
*/ */
bool initChunks(const CollectionType& collDoc, Status initChunks( const string& ns,
const string& ns, const string& shard,
const string& shard, const CollectionMetadata* oldMetadata,
const CollectionManager* oldManager, CollectionMetadata* metadata ) const;
CollectionManager* manager,
string* errMsg);
}; };
} // namespace mongo } // namespace mongo
 End of changes. 12 change blocks. 
58 lines changed or deleted 67 lines changed or added


 modifier_interface.h   modifier_interface.h 
skipping to change at line 129 skipping to change at line 129
* for logging purposes. An array based operator may check the contents of the * for logging purposes. An array based operator may check the contents of the
* array before operating on it. * array before operating on it.
*/ */
virtual Status log(mutablebson::Element logRoot) const = 0; virtual Status log(mutablebson::Element logRoot) const = 0;
}; };
struct ModifierInterface::ExecInfo { struct ModifierInterface::ExecInfo {
static const int MAX_NUM_FIELDS = 2; static const int MAX_NUM_FIELDS = 2;
ExecInfo() : inPlace(false), noOp(false) { /**
* An update mod may specify that it wishes to the applied only if
the context
* of the update turns out a certain way.
*/
enum UpdateContext {
// This mod wants to be applied only if the update turns out to
be an insert.
INSERT_CONTEXT,
// This mod wants to be applied only if the update is not an in
sert.
UPDATE_CONTEXT,
// This mod doesn't care if the update will be an update or an
upsert.
ANY_CONTEXT
};
ExecInfo() : inPlace(false), noOp(false), context(ANY_CONTEXT) {
for (int i = 0; i < MAX_NUM_FIELDS; i++) { for (int i = 0; i < MAX_NUM_FIELDS; i++) {
fieldRef[i] = NULL; fieldRef[i] = NULL;
} }
} }
// The fields of concern to the driver: no other op may modify the fields listed here. // The fields of concern to the driver: no other op may modify the fields listed here.
FieldRef* fieldRef[MAX_NUM_FIELDS]; // not owned here FieldRef* fieldRef[MAX_NUM_FIELDS]; // not owned here
bool inPlace; bool inPlace;
bool noOp; bool noOp;
UpdateContext context;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 2 change blocks. 
1 lines changed or deleted 21 lines changed or added


 modifier_set.h   modifier_set.h 
skipping to change at line 35 skipping to change at line 35
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/ops/modifier_interface.h" #include "mongo/db/ops/modifier_interface.h"
namespace mongo { namespace mongo {
class ModifierSet : public ModifierInterface { class ModifierSet : public ModifierInterface {
MONGO_DISALLOW_COPYING(ModifierSet); MONGO_DISALLOW_COPYING(ModifierSet);
public: public:
ModifierSet(); enum ModifierSetMode { SET_NORMAL, SET_ON_INSERT };
explicit ModifierSet(ModifierSetMode mode = SET_NORMAL);
// //
// Modifier interface implementation // Modifier interface implementation
// //
virtual ~ModifierSet(); virtual ~ModifierSet();
/** /**
* A 'modExpr' is a BSONElement {<fieldname>: <value>} coming from a $set mod such as * A 'modExpr' is a BSONElement {<fieldname>: <value>} coming from a $set mod such as
* {$set: {<fieldname: <value>}}. init() extracts the field name an d the value to be * {$set: {<fieldname: <value>}}. init() extracts the field name an d the value to be
skipping to change at line 82 skipping to change at line 83
virtual Status log(mutablebson::Element logRoot) const; virtual Status log(mutablebson::Element logRoot) const;
private: private:
// Access to each component of fieldName that's the target of this mod. // Access to each component of fieldName that's the target of this mod.
FieldRef _fieldRef; FieldRef _fieldRef;
// 0 or index for $-positional in _fieldRef. // 0 or index for $-positional in _fieldRef.
size_t _posDollar; size_t _posDollar;
// If on 'on insert' mode, We'd like to apply this mod only if we'r
e in a upsert.
const ModifierSetMode _setMode;
// Element of the $set expression. // Element of the $set expression.
BSONElement _val; BSONElement _val;
// The instance of the field in the provided doc. This state is val id after a // The instance of the field in the provided doc. This state is val id after a
// prepare() was issued and until a log() is issued. The document t his mod is // prepare() was issued and until a log() is issued. The document t his mod is
// being prepared against must be live throughout all the calls. // being prepared against must be live throughout all the calls.
struct PreparedState; struct PreparedState;
scoped_ptr<PreparedState> _preparedState; scoped_ptr<PreparedState> _preparedState;
}; };
 End of changes. 2 change blocks. 
1 lines changed or deleted 6 lines changed or added


 msg.h   msg.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
#include <deque> #include <deque>
#include <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
#include <boost/function.hpp>
#include "task.h" #include "task.h"
namespace mongo { namespace mongo {
namespace task { namespace task {
typedef boost::function<void()> lam; typedef boost::function<void()> lam;
/** typical usage is: task::fork( new Server("threadname") ); */ /** typical usage is: task::fork( new Server("threadname") ); */
class Server : public Task { class Server : public Task {
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 mutable_bson_test_utils.h   mutable_bson_test_utils.h 
skipping to change at line 36 skipping to change at line 36
// //
// Utilities for mutable BSON unit tests. // Utilities for mutable BSON unit tests.
// //
/** /**
* Catch all comparator between a mutable 'doc' and the expected BSON ' exp'. It compares * Catch all comparator between a mutable 'doc' and the expected BSON ' exp'. It compares
* (a) 'doc's generated object, (b) 'exp', the expected object, and (c) 'doc(exp)', a * (a) 'doc's generated object, (b) 'exp', the expected object, and (c) 'doc(exp)', a
* document created from 'exp'. Returns true if all three are equal, ot herwise false. * document created from 'exp'. Returns true if all three are equal, ot herwise false.
*/ */
bool checkDoc(const Document& doc, const BSONObj& exp); bool checkDoc(const Document& lhs, const BSONObj& rhs);
bool checkDoc(const Document& lhs, const Document& rhs);
inline bool operator==(const Document& lhs, const Document& rhs) {
return checkDoc(lhs, rhs);
}
inline bool operator==(const BSONObj& lhs, const Document& rhs) {
return checkDoc(rhs, lhs);
}
inline bool operator==(const Document& lhs, const BSONObj& rhs) {
return checkDoc(lhs, rhs);
}
/** Stream out a document; useful within ASSERT calls */
std::ostream& operator<<(std::ostream& stream, const Document& doc);
/** Stream out an element; useful within ASSERT calls */ /** Stream out an element; useful within ASSERT calls */
std::ostream& operator<<(std::ostream& stream, const ConstElement& elt) ; std::ostream& operator<<(std::ostream& stream, const ConstElement& elt) ;
} // namespace mutablebson } // namespace mutablebson
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
1 lines changed or deleted 17 lines changed or added


 namespace-inl.h   namespace-inl.h 
// @file namespace-inl.h // namespace-inl.h
/** /**
* Copyright (C) 2009 10gen Inc. * Copyright (C) 2009 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3 , * it under the terms of the GNU Affero General Public License, version 3 ,
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/db/namespace.h"
namespace mongo { namespace mongo {
inline Namespace& Namespace::operator=(const StringData& ns) { inline Namespace& Namespace::operator=(const StringData& ns) {
// we fill the remaining space with all zeroes here. as the full N amespace struct is in // we fill the remaining space with all zeroes here. as the full N amespace struct is in
// the datafiles (the .ns files specifically), that is helpful as t hen they are deterministic // the datafiles (the .ns files specifically), that is helpful as t hen they are deterministic
// in the bytes they have for a given sequence of operations. that makes testing and debugging // in the bytes they have for a given sequence of operations. that makes testing and debugging
// the data files easier. // the data files easier.
// //
// if profiling indicates this method is a significant bottleneck, we could have a version we // if profiling indicates this method is a significant bottleneck, we could have a version we
// use for reads which does not fill with zeroes, and keep the zero ing behavior on writes. // use for reads which does not fill with zeroes, and keep the zero ing behavior on writes.
skipping to change at line 63 skipping to change at line 61
inline int Namespace::hash() const { inline int Namespace::hash() const {
unsigned x = 0; unsigned x = 0;
const char *p = buf; const char *p = buf;
while ( *p ) { while ( *p ) {
x = x * 131 + *p; x = x * 131 + *p;
p++; p++;
} }
return (x & 0x7fffffff) | 0x8000000; // must be > 0 return (x & 0x7fffffff) | 0x8000000; // must be > 0
} }
/* future : this doesn't need to be an inline. */
inline string Namespace::getSisterNS( const char * local ) const {
verify( local && local[0] != '.' );
string old(buf);
if ( old.find( "." ) != string::npos )
old = old.substr( 0 , old.find( "." ) );
return old + "." + local;
}
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
12 lines changed or deleted 1 lines changed or added


 namespace.h   namespace.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 Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/pch.h"
#include <cstring> #include <cstring>
#include <string> #include <string>
#include "mongo/base/string_data.h"
namespace mongo { namespace mongo {
#pragma pack(1) #pragma pack(1)
/**
* This is used for storing a namespace on disk in a fixed witdh form
* it should only be used for that, not for passing internally
* for that, please use NamespaceString
*/
class Namespace { class Namespace {
public: public:
Namespace(const StringData& ns) { *this = ns; } Namespace(const StringData& ns) { *this = ns; }
Namespace& operator=(const StringData& ns); Namespace& operator=(const StringData& ns);
bool hasDollarSign() const { return strchr( buf , '$' ) > 0; }
void kill() { buf[0] = 0x7f; } void kill() { buf[0] = 0x7f; }
bool operator==(const char *r) const { return strcmp(buf, r) == 0; } bool operator==(const char *r) const { return strcmp(buf, r) == 0; }
bool operator==(const Namespace& r) const { return strcmp(buf, r.bu f) == 0; } bool operator==(const Namespace& r) const { return strcmp(buf, r.bu f) == 0; }
bool operator!=(const char *r) const { return strcmp(buf, r) != 0;
}
bool operator!=(const Namespace& r) const { return strcmp(buf, r.bu
f) != 0; }
bool hasDollarSign() const { return strchr( buf , '$' ) > 0; }
int hash() const; // value returned is always > 0 int hash() const; // value returned is always > 0
size_t size() const { return strlen( buf ); } size_t size() const { return strlen( buf ); }
string toString() const { return buf; } std::string toString() const { return buf; }
operator string() const { return buf; } operator std::string() const { return buf; }
/* NamespaceDetails::Extra was added after fact to allow chaining o f data blocks to support more than 10 indexes /* NamespaceDetails::Extra was added after fact to allow chaining o f data blocks to support more than 10 indexes
(more than 10 IndexDetails). It's a bit hacky because of this l ate addition with backward (more than 10 IndexDetails). It's a bit hacky because of this l ate addition with backward
file support. */ file support. */
string extraName(int i) const; std::string extraName(int i) const;
bool isExtra() const; /* ends with $extr... -- when true an extra b lock not a normal NamespaceDetails block */ bool isExtra() const; /* ends with $extr... -- when true an extra b lock not a normal NamespaceDetails block */
/** ( foo.bar ).getSisterNS( "blah" ) == foo.blah
perhaps this should move to the NamespaceString helper?
*/
string getSisterNS( const char * local ) const;
enum MaxNsLenValue { MaxNsLen = 128 }; enum MaxNsLenValue { MaxNsLen = 128 };
private: private:
char buf[MaxNsLen]; char buf[MaxNsLen];
}; };
#pragma pack() #pragma pack()
} // namespace mongo } // namespace mongo
#include "mongo/db/storage/namespace-inl.h"
 End of changes. 10 change blocks. 
11 lines changed or deleted 18 lines changed or added


 namespace_details-inl.h   namespace_details-inl.h 
// @file namespace-inl.h // namespace_details-inl.h
/** /**
* Copyright (C) 2009 10gen Inc. * Copyright (C) 2009 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3 , * it under the terms of the GNU Affero General Public License, version 3 ,
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
skipping to change at line 59 skipping to change at line 59
inline int NamespaceDetails::idxNo(const IndexDetails& idx) { inline int NamespaceDetails::idxNo(const IndexDetails& idx) {
IndexIterator i = ii(); IndexIterator i = ii();
while( i.more() ) { while( i.more() ) {
if( &i.next() == &idx ) if( &i.next() == &idx )
return i.pos()-1; return i.pos()-1;
} }
massert( 10349 , "E12000 idxNo fails", false); massert( 10349 , "E12000 idxNo fails", false);
return -1; return -1;
} }
inline int NamespaceDetails::findIndexByKeyPattern(const BSONObj& keyPa inline int NamespaceDetails::findIndexByKeyPattern(const BSONObj& keyPa
ttern) { ttern,
IndexIterator i = ii(); bool includeBackgrou
ndInProgress) {
IndexIterator i = ii(includeBackgroundInProgress);
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;
} }
inline const IndexDetails* NamespaceDetails::findIndexByPrefix( const B SONObj &keyPattern , inline const IndexDetails* NamespaceDetails::findIndexByPrefix( const B SONObj &keyPattern ,
bool re quireSingleKey ) { bool re quireSingleKey ) {
const IndexDetails* bestMultiKeyIndex = NULL; const IndexDetails* bestMultiKeyIndex = NULL;
skipping to change at line 86 skipping to change at line 87
return &currentIndex; return &currentIndex;
} else { } else {
bestMultiKeyIndex = &currentIndex; bestMultiKeyIndex = &currentIndex;
} }
} }
} }
return requireSingleKey ? NULL : bestMultiKeyIndex; return requireSingleKey ? NULL : bestMultiKeyIndex;
} }
// @return offset in indexes[] // @return offset in indexes[]
inline int NamespaceDetails::findIndexByName(const char *name) { inline int NamespaceDetails::findIndexByName(const char *name,
IndexIterator i = ii(); bool includeBackgroundInPr
ogress) {
IndexIterator i = ii(includeBackgroundInProgress);
while( i.more() ) { while( i.more() ) {
if ( strcmp(i.next().info.obj().getStringField("name"),name) == 0 ) if ( strcmp(i.next().info.obj().getStringField("name"),name) == 0 )
return i.pos()-1; return i.pos()-1;
} }
return -1; return -1;
} }
inline NamespaceDetails::IndexIterator::IndexIterator(NamespaceDetails *_d, inline NamespaceDetails::IndexIterator::IndexIterator(NamespaceDetails *_d,
bool includeBackg roundInProgress) { bool includeBackg roundInProgress) {
d = _d; d = _d;
i = 0; i = 0;
n = includeBackgroundInProgress ? d->getTotalIndexCount() : d->nInd exes; n = includeBackgroundInProgress ? d->getTotalIndexCount() : d->_nIn dexes;
} }
} }
 End of changes. 4 change blocks. 
7 lines changed or deleted 11 lines changed or added


 namespace_details.h   namespace_details.h 
skipping to change at line 27 skipping to change at line 27
#pragma once #pragma once
#include "mongo/pch.h" #include "mongo/pch.h"
#include "mongo/db/d_concurrency.h" #include "mongo/db/d_concurrency.h"
#include "mongo/db/diskloc.h" #include "mongo/db/diskloc.h"
#include "mongo/db/index.h" #include "mongo/db/index.h"
#include "mongo/db/index_names.h" #include "mongo/db/index_names.h"
#include "mongo/db/index_set.h" #include "mongo/db/index_set.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/mongommf.h" #include "mongo/db/mongommf.h"
#include "mongo/db/namespace.h" #include "mongo/db/namespace_string.h"
#include "mongo/db/namespacestring.h"
#include "mongo/db/querypattern.h" #include "mongo/db/querypattern.h"
#include "mongo/db/storage/namespace.h"
#include "mongo/db/storage/namespace_index.h"
#include "mongo/platform/unordered_map.h" #include "mongo/platform/unordered_map.h"
#include "mongo/util/hashtab.h"
namespace mongo { namespace mongo {
class Database; class Database;
/** @return true if a client can modify this namespace even though it i s under ".system." /** @return true if a client can modify this namespace even though it i s under ".system."
For example <dbname>.system.users is ok for regular clients to upda te. For example <dbname>.system.users is ok for regular clients to upda te.
@param write used when .system.js @param write used when .system.js
*/ */
bool legalClientSystemNS( const string& ns , bool write ); bool legalClientSystemNS( const string& ns , bool write );
skipping to change at line 58 skipping to change at line 58
extern int bucketSizes[]; extern int bucketSizes[];
#pragma pack(1) #pragma pack(1)
/* NamespaceDetails : this is the "header" for a collection that has al l its details. /* NamespaceDetails : this is the "header" for a collection that has al l its details.
It's in the .ns file and this is a memory mapped region (thus the pa ck pragma above). It's in the .ns file and this is a memory mapped region (thus the pa ck pragma above).
*/ */
class NamespaceDetails { class NamespaceDetails {
public: public:
enum { NIndexesMax = 64, NIndexesExtra = 30, NIndexesBase = 10 }; enum { NIndexesMax = 64, NIndexesExtra = 30, NIndexesBase = 10 };
private:
/*-------- data fields, as present on disk : */ /*-------- data fields, as present on disk : */
DiskLoc firstExtent;
DiskLoc lastExtent; DiskLoc _firstExtent;
DiskLoc _lastExtent;
/* NOTE: capped collections v1 override the meaning of deletedList. /* NOTE: capped collections v1 override the meaning of deletedList.
deletedList[0] points to a list of free records (DeletedRe cord's) for all extents in deletedList[0] points to a list of free records (DeletedRe cord's) for all extents in
the capped namespace. the capped namespace.
deletedList[1] points to the last record in the prev exten t. When the "current extent" deletedList[1] points to the last record in the prev exten t. When the "current extent"
changes, this value is updated. !deletedList[1].isValid() when this value is not changes, this value is updated. !deletedList[1].isValid() when this value is not
yet computed. yet computed.
*/ */
DiskLoc deletedList[Buckets]; DiskLoc _deletedList[Buckets];
// ofs 168 (8 byte aligned) // ofs 168 (8 byte aligned)
struct Stats { struct Stats {
// datasize and nrecords MUST Be adjacent code assumes! // datasize and nrecords MUST Be adjacent code assumes!
long long datasize; // this includes padding, but not record he aders long long datasize; // this includes padding, but not record he aders
long long nrecords; long long nrecords;
} stats; } _stats;
int lastExtentSize;
int nIndexes; int _lastExtentSize;
private: int _nIndexes;
// ofs 192 // ofs 192
IndexDetails _indexes[NIndexesBase]; IndexDetails _indexes[NIndexesBase];
// ofs 352 (16 byte aligned) // ofs 352 (16 byte aligned)
int _isCapped; // there is wasted space her e if I'm right (ERH) int _isCapped; // there is wasted space her e if I'm right (ERH)
int _maxDocsInCapped; // max # of objects for a ca pped table, -1 for inf. int _maxDocsInCapped; // max # of objects for a ca pped table, -1 for inf.
double _paddingFactor; // 1.0 = no padding. double _paddingFactor; // 1.0 = no padding.
// ofs 386 (16) // ofs 386 (16)
int _systemFlags; // things that the system sets/cares about int _systemFlags; // things that the system sets/cares about
public:
DiskLoc capExtent; // the "current" extent we're writing too for a DiskLoc _capExtent; // the "current" extent we're writing too for a
capped collection capped collection
DiskLoc capFirstNewRecord; DiskLoc _capFirstNewRecord;
unsigned short dataFileVersion; // NamespaceDetails version.
So we can do backward compatibility in the future. See filever.h unsigned short _dataFileVersion; // NamespaceDetails version.
unsigned short indexFileVersion; So we can do backward compatibility in the future. See filever.h
unsigned long long multiKeyIndexBits; unsigned short _indexFileVersion;
private: unsigned long long _multiKeyIndexBits;
// ofs 400 (16) // ofs 400 (16)
unsigned long long reservedA; unsigned long long _reservedA;
long long extraOffset; // where the $extra info is l long long _extraOffset; // where the $extra info is l
ocated (bytes relative to this) ocated (bytes relative to this)
public:
int indexBuildsInProgress; // Number of indexes currentl int _indexBuildsInProgress; // Number of indexes current
y being built ly being built
private:
int _userFlags; int _userFlags;
char reserved[72]; char _reserved[72];
/*-------- end data 496 bytes */ /*-------- end data 496 bytes */
public: public:
explicit NamespaceDetails( const DiskLoc &loc, bool _capped ); explicit NamespaceDetails( const DiskLoc &loc, bool _capped );
class Extra { class Extra {
long long _next; long long _next;
public: public:
IndexDetails details[NIndexesExtra]; IndexDetails details[NIndexesExtra];
private: private:
unsigned reserved2; unsigned reserved2;
skipping to change at line 133 skipping to change at line 140
if( _next == 0 ) return 0; if( _next == 0 ) return 0;
return (Extra*) (((char *) d) + _next); return (Extra*) (((char *) d) + _next);
} }
void setNext(long ofs) { *getDur().writing(&_next) = ofs; } void setNext(long ofs) { *getDur().writing(&_next) = ofs; }
void copy(NamespaceDetails *d, const Extra& e) { void copy(NamespaceDetails *d, const Extra& e) {
memcpy(this, &e, sizeof(Extra)); memcpy(this, &e, sizeof(Extra));
_next = 0; _next = 0;
} }
}; };
Extra* extra() { Extra* extra() {
if( extraOffset == 0 ) return 0; if( _extraOffset == 0 ) return 0;
return (Extra *) (((char *) this) + extraOffset); return (Extra *) (((char *) this) + _extraOffset);
} }
/* add extra space for indexes when more than 10 */ /* add extra space for indexes when more than 10 */
Extra* allocExtra(const char *ns, int nindexessofar); Extra* allocExtra(const char *ns, int nindexessofar);
void copyingFrom(const char *thisns, NamespaceDetails *src); // mus t be called when renaming a NS to fix up extra void copyingFrom(const char *thisns, NamespaceDetails *src); // mus t be called when renaming a NS to fix up extra
/* dump info on this namespace. for debugging. */ /* dump info on this namespace. for debugging. */
void dump(const Namespace& k); void dump(const Namespace& k);
/* dump info on all extents for this namespace. for debugging. */ /* dump info on all extents for this namespace. for debugging. */
void dumpExtents(); void dumpExtents();
public:
const DiskLoc& capExtent() const { return _capExtent; }
const DiskLoc capFirstNewRecord() const { return _capFirstNewRecord
; }
DiskLoc& capExtent() { return _capExtent; }
DiskLoc& capFirstNewRecord() { return _capFirstNewRecord; }
private: private:
Extent *theCapExtent() const { return capExtent.ext(); } Extent *theCapExtent() const { return _capExtent.ext(); }
void advanceCapExtent( const char *ns ); void advanceCapExtent( const char *ns );
DiskLoc __capAlloc(int len); DiskLoc __capAlloc(int len);
DiskLoc cappedAlloc(const char *ns, int len); DiskLoc cappedAlloc(const char *ns, int len);
DiskLoc &cappedFirstDeletedInCurExtent(); DiskLoc &cappedFirstDeletedInCurExtent();
bool nextIsInCapExtent( const DiskLoc &dl ) const; bool nextIsInCapExtent( const DiskLoc &dl ) const;
public: public:
const DiskLoc& firstExtent() const { return _firstExtent; }
const DiskLoc& lastExtent() const { return _lastExtent; }
DiskLoc& firstExtent() { return _firstExtent; }
DiskLoc& lastExtent() { return _lastExtent; }
void setFirstExtent( DiskLoc newFirstExtent );
void setLastExtent( DiskLoc newLastExtent );
void setFirstExtentInvalid();
void setLastExtentInvalid();
long long dataSize() const { return _stats.datasize; }
long long numRecords() const { return _stats.nrecords; }
void incrementStats( long long dataSizeIncrement,
long long numRecordsIncrement );
void setStats( long long dataSizeIncrement,
long long numRecordsIncrement );
bool isCapped() const { return _isCapped; } bool isCapped() const { return _isCapped; }
long long maxCappedDocs() const; long long maxCappedDocs() const;
void setMaxCappedDocs( long long max ); void setMaxCappedDocs( long long max );
int lastExtentSize() const { return _lastExtentSize; }
void setLastExtentSize( int newMax );
const DiskLoc& deletedListEntry( int bucket ) const { return _delet
edList[bucket]; }
DiskLoc& deletedListEntry( int bucket ) { return _deletedList[bucke
t]; }
void orphanDeletedList();
/** /**
* @param max in and out, will be adjusted * @param max in and out, will be adjusted
* @return if the value is valid at all * @return if the value is valid at all
*/ */
static bool validMaxCappedDocs( long long* max ); static bool validMaxCappedDocs( long long* max );
DiskLoc& cappedListOfAllDeletedRecords() { return deletedList[0]; } DiskLoc& cappedListOfAllDeletedRecords() { return _deletedList[0];
DiskLoc& cappedLastDelRecLastExtent() { return deletedList[1]; } }
DiskLoc& cappedLastDelRecLastExtent() { return _deletedList[1];
}
void cappedDumpDelInfo(); void cappedDumpDelInfo();
bool capLooped() const { return _isCapped && capFirstNewRecord.isVa lid(); } bool capLooped() const { return _isCapped && _capFirstNewRecord.isV alid(); }
bool inCapExtent( const DiskLoc &dl ) const; bool inCapExtent( const DiskLoc &dl ) const;
void cappedCheckMigrate(); void cappedCheckMigrate();
/** /**
* Truncate documents newer than the document at 'end' from the cap ped * Truncate documents newer than the document at 'end' from the cap ped
* collection. The collection cannot be completely emptied using t his * collection. The collection cannot be completely emptied using t his
* function. An assertion will be thrown if that is attempted. * function. An assertion will be thrown if that is attempted.
* @param inclusive - Truncate 'end' as well iff true * @param inclusive - Truncate 'end' as well iff true
*/ */
void cappedTruncateAfter(const char *ns, DiskLoc end, bool inclusiv e); void cappedTruncateAfter(const char *ns, DiskLoc end, bool inclusiv e);
/** Remove all documents from the capped collection */ /** Remove all documents from the capped collection */
void emptyCappedCollection(const char *ns); void emptyCappedCollection(const char *ns);
/* when a background index build is in progress, we don't count the index in nIndexes until /* when a background index build is in progress, we don't count the index in nIndexes until
complete, yet need to still use it in _indexRecord() - thus we u se this function for that. complete, yet need to still use it in _indexRecord() - thus we u se this function for that.
*/ */
int getTotalIndexCount() const { return nIndexes + indexBuildsInPro int getTotalIndexCount() const { return _nIndexes + _indexBuildsInP
gress; } rogress; }
int getCompletedIndexCount() const { return _nIndexes; }
int getIndexBuildsInProgress() const { return _indexBuildsInProgres
s; }
/* NOTE: be careful with flags. are we manipulating them in read l ocks? if so, /* NOTE: be careful with flags. are we manipulating them in read l ocks? if so,
this isn't thread safe. TODO this isn't thread safe. TODO
*/ */
enum SystemFlags { enum SystemFlags {
Flag_HaveIdIndex = 1 << 0 // set when we have _id index (ONLY i f ensureIdIndex was called -- 0 if that has never been called) Flag_HaveIdIndex = 1 << 0 // set when we have _id index (ONLY i f ensureIdIndex was called -- 0 if that has never been called)
}; };
enum UserFlags { enum UserFlags {
Flag_UsePowerOf2Sizes = 1 << 0 Flag_UsePowerOf2Sizes = 1 << 0
skipping to change at line 222 skipping to change at line 270
return IndexIterator(this, includeBackgroundInProgress); return IndexIterator(this, includeBackgroundInProgress);
} }
/* hackish - find our index # in the indexes array */ /* hackish - find our index # in the indexes array */
int idxNo(const IndexDetails& idx); int idxNo(const IndexDetails& idx);
/* multikey indexes are indexes where there are more than one key i n the index /* multikey indexes are indexes where there are more than one key i n the index
for a single document. see multikey in docs. for a single document. see multikey in docs.
for these, we have to do some dedup work on queries. for these, we have to do some dedup work on queries.
*/ */
bool isMultikey(int i) const { return (multiKeyIndexBits & (((unsig ned long long) 1) << i)) != 0; } bool isMultikey(int i) const { return (_multiKeyIndexBits & (((unsi gned long long) 1) << i)) != 0; }
void setIndexIsMultikey(const char *thisns, int i, bool multikey = true); void setIndexIsMultikey(const char *thisns, int i, bool multikey = true);
/** /**
* This fetches the IndexDetails for the next empty index slot. The caller must populate * This fetches the IndexDetails for the next empty index slot. The caller must populate
* returned object. This handles allocating extra index space, if necessary. * returned object. This handles allocating extra index space, if necessary.
*/ */
IndexDetails& getNextIndexDetails(const char* thisns); IndexDetails& getNextIndexDetails(const char* thisns);
/** /**
* Add a new index. This does not add it to system.indexes etc. - just to NamespaceDetails. * Add a new index. This does not add it to system.indexes etc. - just to NamespaceDetails.
skipping to change at line 283 skipping to change at line 331
} }
void paddingTooSmall() { void paddingTooSmall() {
MONGO_SOMETIMES(sometimes, 4) { // do this on a sampled basis t o journal less MONGO_SOMETIMES(sometimes, 4) { // do this on a sampled basis t o journal less
/* the more indexes we have, the higher the cost of a move. so we take that into /* the more indexes we have, the higher the cost of a move. so we take that into
account herein. note on a move that insert() calls padd ingFits(), thus account herein. note on a move that insert() calls padd ingFits(), thus
here for example with no inserts and nIndexes = 1 we hav e here for example with no inserts and nIndexes = 1 we hav e
.001*4-.001 or a 3:1 ratio to non moves -> 75% nonmoves. insert heavy .001*4-.001 or a 3:1 ratio to non moves -> 75% nonmoves. insert heavy
can pushes this down considerably. further tweaking will be a good idea but can pushes this down considerably. further tweaking will be a good idea but
this should be an adequate starting point. this should be an adequate starting point.
*/ */
double N = min(nIndexes,7) + 3; double N = min(_nIndexes,7) + 3;
double x = _paddingFactor + (0.001 * N); double x = _paddingFactor + (0.001 * N);
if ( x <= 2.0 ) { if ( x <= 2.0 ) {
setPaddingFactor( x ); setPaddingFactor( x );
} }
} }
} }
// @return offset in indexes[] // @return offset in indexes[]
int findIndexByName(const char *name); int findIndexByName(const char *name, bool includeBackgroundInProgr ess = false);
// @return offset in indexes[] // @return offset in indexes[]
int findIndexByKeyPattern(const BSONObj& keyPattern); int findIndexByKeyPattern(const BSONObj& keyPattern,
bool includeBackgroundInProgress = false)
;
void findIndexByType( const string& name , vector<int>& matches ) { void findIndexByType( const string& name , vector<int>& matches ) {
IndexIterator i = ii(); IndexIterator i = ii();
while ( i.more() ) { while ( i.more() ) {
if ( IndexNames::findPluginName(i.next().keyPattern()) == n ame ) if ( IndexNames::findPluginName(i.next().keyPattern()) == n ame )
matches.push_back( i.pos() - 1 ); matches.push_back( i.pos() - 1 );
} }
} }
/* Returns the index entry for the first index whose prefix contain s /* Returns the index entry for the first index whose prefix contain s
* 'keyPattern'. If 'requireSingleKey' is true, skip indices that c ontain * 'keyPattern'. If 'requireSingleKey' is true, skip indices that c ontain
* array attributes. Otherwise, returns NULL. * array attributes. Otherwise, returns NULL.
*/ */
const IndexDetails* findIndexByPrefix( const BSONObj &keyPattern , const IndexDetails* findIndexByPrefix( const BSONObj &keyPattern ,
bool requireSingleKey ); bool requireSingleKey );
void removeIndex( int idx );
/**
* removes things beteen getCompletedIndexCount() and getTotalIndex
Count()
* this should only be used for crash recovery
*/
void blowAwayInProgressIndexEntries();
/**
* @return the info for the index to retry
*/
BSONObj prepOneUnfinishedIndex();
/**
* swaps all meta data for 2 indexes
* a and b are 2 index ids, whose contents will be swapped
* must have a lock on the entire collection to do this
*/
void swapIndex( const char* ns, int a, int b );
/* Updates the expireAfterSeconds field of the given index to the v alue in newExpireSecs. /* Updates the expireAfterSeconds field of the given index to the v alue in newExpireSecs.
* The specified index must already contain an expireAfterSeconds f ield, and the value in * The specified index must already contain an expireAfterSeconds f ield, and the value in
* that field and newExpireSecs must both be numeric. * that field and newExpireSecs must both be numeric.
*/ */
void updateTTLIndex( int idxNo , const BSONElement& newExpireSecs ) ; void updateTTLIndex( int idxNo , const BSONElement& newExpireSecs ) ;
const int systemFlags() const { return _systemFlags; } const int systemFlags() const { return _systemFlags; }
bool isSystemFlagSet( int flag ) const { return _systemFlags & flag ; } bool isSystemFlagSet( int flag ) const { return _systemFlags & flag ; }
void setSystemFlag( int flag ); void setSystemFlag( int flag );
void clearSystemFlag( int flag ); void clearSystemFlag( int flag );
skipping to change at line 401 skipping to change at line 470
/* add a given record to the deleted chains for this NS */ /* add a given record to the deleted chains for this NS */
void addDeletedRec(DeletedRecord *d, DiskLoc dloc); void addDeletedRec(DeletedRecord *d, DiskLoc dloc);
void dumpDeleted(set<DiskLoc> *extents = 0); void dumpDeleted(set<DiskLoc> *extents = 0);
// Start from firstExtent by default. // Start from firstExtent by default.
DiskLoc firstRecord( const DiskLoc &startExtent = DiskLoc() ) const ; DiskLoc firstRecord( const DiskLoc &startExtent = DiskLoc() ) const ;
// Start from lastExtent by default. // Start from lastExtent by default.
DiskLoc lastRecord( const DiskLoc &startExtent = DiskLoc() ) const; DiskLoc lastRecord( const DiskLoc &startExtent = DiskLoc() ) const;
long long storageSize( int * numExtents = 0 , BSONArrayBuilder * ex tentInfo = 0 ) const; long long storageSize( int * numExtents = 0 , BSONArrayBuilder * ex tentInfo = 0 ) const;
int averageObjectSize() { int averageObjectSize() {
if ( stats.nrecords == 0 ) if ( _stats.nrecords == 0 )
return 5; return 5;
return (int) (stats.datasize / stats.nrecords); return (int) (_stats.datasize / _stats.nrecords);
} }
NamespaceDetails *writingWithoutExtra() { NamespaceDetails *writingWithoutExtra() {
return ( NamespaceDetails* ) getDur().writingPtr( this, sizeof( NamespaceDetails ) ); return ( NamespaceDetails* ) getDur().writingPtr( this, sizeof( NamespaceDetails ) );
} }
/** Make all linked Extra objects writeable as well */ /** Make all linked Extra objects writeable as well */
NamespaceDetails *writingWithExtra(); NamespaceDetails *writingWithExtra();
class IndexBuildBlock {
public:
IndexBuildBlock( const string& ns, const string& indexName );
~IndexBuildBlock();
private:
string _ns;
string _indexName;
};
private: private:
void _removeIndex( int idx );
DiskLoc _alloc(const char *ns, int len); DiskLoc _alloc(const char *ns, int len);
void maybeComplain( const char *ns, int len ) const; void maybeComplain( const char *ns, int len ) const;
DiskLoc __stdAlloc(int len, bool willBeAt); DiskLoc __stdAlloc(int len, bool willBeAt);
void compact(); // combine adjacent deleted records void compact(); // combine adjacent deleted records
friend class NamespaceIndex; friend class NamespaceIndex;
struct ExtraOld { struct ExtraOld {
// note we could use this field for more chaining later, so don 't waste it: // note we could use this field for more chaining later, so don 't waste it:
unsigned long long reserved1; unsigned long long reserved1;
IndexDetails details[NIndexesExtra]; IndexDetails details[NIndexesExtra];
unsigned reserved2; unsigned reserved2;
skipping to change at line 552 skipping to change at line 634
inline NamespaceDetailsTransient& NamespaceDetailsTransient::get_inlock (const string& ns) { inline NamespaceDetailsTransient& NamespaceDetailsTransient::get_inlock (const string& ns) {
CMap& m = get_cmap_inlock(ns); CMap& m = get_cmap_inlock(ns);
CMap::iterator i = m.find( ns ); CMap::iterator i = m.find( ns );
if ( i != m.end() && if ( i != m.end() &&
i->second.get() ) { // could be null ptr from clearForPrefix i->second.get() ) { // could be null ptr from clearForPrefix
return *i->second; return *i->second;
} }
return make_inlock(ns); return make_inlock(ns);
} }
/* NamespaceIndex is the ".ns" file you see in the data directory. It
is the "system catalog"
if you will: at least the core parts. (Additional info in system.*
collections.)
*/
class NamespaceIndex {
public:
NamespaceIndex(const string &dir, const string &database) :
ht( 0 ), dir_( dir ), database_( database ) {}
/* returns true if new db will be created if we init lazily */
bool exists() const;
void init() {
if( !ht )
_init();
}
void add_ns(const char *ns, DiskLoc& loc, bool capped);
void add_ns( const char *ns, const NamespaceDetails &details );
NamespaceDetails* details(const StringData& ns) {
if ( !ht )
return 0;
Namespace n(ns);
NamespaceDetails *d = ht->get(n);
if ( d && d->isCapped() )
d->cappedCheckMigrate();
return d;
}
void kill_ns(const char *ns);
bool find(const char *ns, DiskLoc& loc) {
NamespaceDetails *l = details(ns);
if ( l ) {
loc = l->firstExtent;
return true;
}
return false;
}
bool allocated() const { return ht != 0; }
void getNamespaces( list<string>& tofill , bool onlyCollections = t
rue ) const;
NamespaceDetails::Extra* newExtra(const char *ns, int n, NamespaceD
etails *d);
boost::filesystem::path path() const;
unsigned long long fileLength() const { return f.length(); }
private:
void _init();
void maybeMkdir() const;
MongoMMF f;
HashTable<Namespace,NamespaceDetails> *ht;
string dir_;
string database_;
};
extern string dbpath; // --dbpath parm extern string dbpath; // --dbpath parm
extern bool directoryperdb; extern bool directoryperdb;
// Rename a namespace within current 'client' db. // Rename a namespace within current 'client' db.
// (Arguments should include db name) // (Arguments should include db name)
void renameNamespace( const char *from, const char *to, bool stayTemp); void renameNamespace( const char *from, const char *to, bool stayTemp);
} // namespace mongo } // namespace mongo
 End of changes. 28 change blocks. 
105 lines changed or deleted 131 lines changed or added


 oid.h   oid.h 
skipping to change at line 140 skipping to change at line 140
// TODO: get rid of this eventually // TODO: get rid of this eventually
// this is a hack because of hash_combine with older versions of boost // this is a hack because of hash_combine with older versions of boost
// on 32-bit platforms // on 32-bit platforms
int x; int x;
int y; int y;
int z; int z;
}; };
unsigned char data[kOIDSize]; unsigned char data[kOIDSize];
}; };
static unsigned ourPid();
static void foldInPid(MachineAndPid& x); static void foldInPid(MachineAndPid& x);
static MachineAndPid genMachineAndPid(); static MachineAndPid genMachineAndPid();
}; };
#pragma pack() #pragma pack()
std::ostream& operator<<( std::ostream &s, const OID &o ); std::ostream& operator<<( std::ostream &s, const OID &o );
inline StringBuilder& operator<< (StringBuilder& s, const OID& o) { ret urn (s << o.str()); } inline StringBuilder& operator<< (StringBuilder& s, const OID& o) { ret urn (s << o.str()); }
/** Formatting mode for generating JSON from BSON. /** Formatting mode for generating JSON from BSON.
See <http://dochub.mongodb.org/core/mongodbextendedjson> See <http://dochub.mongodb.org/core/mongodbextendedjson>
 End of changes. 1 change blocks. 
1 lines changed or deleted 0 lines changed or added


 oplogreader.h   oplogreader.h 
skipping to change at line 88 skipping to change at line 88
/* /*
void queryGTE(const char *ns, OpTime t) { void queryGTE(const char *ns, OpTime t) {
BSONObjBuilder q; BSONObjBuilder q;
q.appendDate("$gte", t.asDate()); q.appendDate("$gte", t.asDate());
BSONObjBuilder q2; BSONObjBuilder q2;
q2.append("ts", q.done()); q2.append("ts", q.done());
query(ns, q2.done()); query(ns, q2.done());
} }
*/ */
void query(const char *ns,
Query query,
int nToReturn,
int nToSkip,
const BSONObj* fields=0);
void tailingQuery(const char *ns, const BSONObj& query, const BSONO bj* fields=0); void tailingQuery(const char *ns, const BSONObj& query, const BSONO bj* fields=0);
void tailingQueryGTE(const char *ns, OpTime t, const BSONObj* field s=0); void tailingQueryGTE(const char *ns, OpTime t, const BSONObj* field s=0);
/* Do a tailing query, but only send the ts field back. */ /* Do a tailing query, but only send the ts field back. */
void ghostQueryGTE(const char *ns, OpTime t) { void ghostQueryGTE(const char *ns, OpTime t) {
const BSONObj fields = BSON("ts" << 1 << "_id" << 0); const BSONObj fields = BSON("ts" << 1 << "_id" << 0);
return tailingQueryGTE(ns, t, &fields); return tailingQueryGTE(ns, t, &fields);
} }
 End of changes. 1 change blocks. 
0 lines changed or deleted 6 lines changed or added


 owned_pointer_vector.h   owned_pointer_vector.h 
skipping to change at line 38 skipping to change at line 38
*/ */
template<class T> template<class T>
class OwnedPointerVector { class OwnedPointerVector {
MONGO_DISALLOW_COPYING(OwnedPointerVector); MONGO_DISALLOW_COPYING(OwnedPointerVector);
public: public:
OwnedPointerVector(); OwnedPointerVector();
~OwnedPointerVector(); ~OwnedPointerVector();
/** Access the vector. */ /** Access the vector. */
const std::vector<T*>& vector() { return _vector; } const std::vector<T*>& vector() const { return _vector; }
std::vector<T*>& mutableVector() { return _vector; } std::vector<T*>& mutableVector() { return _vector; }
void clear(); void clear();
private: private:
std::vector<T*> _vector; std::vector<T*> _vector;
}; };
template<class T> template<class T>
OwnedPointerVector<T>::OwnedPointerVector() { OwnedPointerVector<T>::OwnedPointerVector() {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 parallel.h   parallel.h 
skipping to change at line 26 skipping to change at line 26
*/ */
/** /**
tools for working in parallel/sharded/clustered environment tools for working in parallel/sharded/clustered environment
*/ */
#pragma once #pragma once
#include "mongo/db/dbmessage.h" #include "mongo/db/dbmessage.h"
#include "mongo/db/matcher.h" #include "mongo/db/matcher.h"
#include "mongo/db/namespacestring.h" #include "mongo/db/namespace_string.h"
#include "mongo/s/shard.h" #include "mongo/s/shard.h"
#include "mongo/s/stale_exception.h" // for StaleConfigException #include "mongo/s/stale_exception.h" // for StaleConfigException
#include "mongo/util/concurrency/mvar.h" #include "mongo/util/concurrency/mvar.h"
namespace mongo { namespace mongo {
/** /**
* holder for a server address and a query to run * holder for a server address and a query to run
*/ */
class ServerAndQuery { class ServerAndQuery {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 path_support.h   path_support.h 
skipping to change at line 30 skipping to change at line 30
#include "mongo/base/status.h" #include "mongo/base/status.h"
#include "mongo/bson/mutable/element.h" #include "mongo/bson/mutable/element.h"
#include "mongo/db/field_ref.h" #include "mongo/db/field_ref.h"
#include "mongo/platform/cstdint.h" #include "mongo/platform/cstdint.h"
namespace mongo { namespace mongo {
namespace pathsupport { namespace pathsupport {
// Cap on the number of nulls we'll add to an array if we're insert
ing to an index that
// doesn't exist.
static const size_t kMaxPaddingAllowed = 1500000;
/** /**
* Finds the longest portion of 'prefix' that exists in document ro oted at 'root' and is * Finds the longest portion of 'prefix' that exists in document ro oted at 'root' and is
* "viable." A viable path is one that, if fully created on a given doc, would not * "viable." A viable path is one that, if fully created on a given doc, would not
* change the existing types of any fields in that doc. (See exampl es below.) * change the existing types of any fields in that doc. (See exampl es below.)
* *
* If a prefix indeed exists, 'idxFound' is set to indicate how man y parts in common * If a prefix indeed exists, 'idxFound' is set to indicate how man y parts in common
* 'prefix' and 'doc' have. 'elemFound' would point to the Element corresponding to * 'prefix' and 'doc' have. 'elemFound' would point to the Element corresponding to
* prefix[idxFound] in 'doc'. The call would return an OK status in this case. * prefix[idxFound] in 'doc'. The call would return an OK status in this case.
* *
* If a prefix is not viable, returns a status "PathNotViable". 'id xFound' is set to * If a prefix is not viable, returns a status "PathNotViable". 'id xFound' is set to
 End of changes. 1 change blocks. 
0 lines changed or deleted 5 lines changed or added


 pch.h   pch.h 
skipping to change at line 43 skipping to change at line 43
#include <memory> #include <memory>
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <vector> #include <vector>
#include <set> #include <set>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <signal.h> #include <signal.h>
#include "time.h" #include <time.h>
#include "string.h" #include <string.h>
#include "limits.h" #include <limits.h>
#define BOOST_FILESYSTEM_VERSION 3 #define BOOST_FILESYSTEM_VERSION 3
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/smart_ptr.hpp> #include <boost/smart_ptr.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/version.hpp> #include <boost/version.hpp>
#include "mongo/client/redef_macros.h" #include "mongo/client/redef_macros.h"
#include "mongo/util/exit_code.h" #include "mongo/util/exit_code.h"
namespace mongo { namespace mongo {
using namespace std; using namespace std;
 End of changes. 2 change blocks. 
4 lines changed or deleted 3 lines changed or added


 pdfile.h   pdfile.h 
skipping to change at line 33 skipping to change at line 33
... ...
*/ */
#pragma once #pragma once
#include "mongo/db/client.h" #include "mongo/db/client.h"
#include "mongo/db/diskloc.h" #include "mongo/db/diskloc.h"
#include "mongo/db/jsobjmanipulator.h" #include "mongo/db/jsobjmanipulator.h"
#include "mongo/db/memconcept.h" #include "mongo/db/memconcept.h"
#include "mongo/db/mongommf.h" #include "mongo/db/mongommf.h"
#include "mongo/db/namespace-inl.h"
#include "mongo/db/namespace_details-inl.h" #include "mongo/db/namespace_details-inl.h"
#include "mongo/db/namespacestring.h" #include "mongo/db/namespace_string.h"
#include "mongo/db/pdfile_version.h" #include "mongo/db/pdfile_version.h"
#include "mongo/platform/cstdint.h" #include "mongo/platform/cstdint.h"
#include "mongo/util/log.h" #include "mongo/util/log.h"
#include "mongo/util/mmap.h" #include "mongo/util/mmap.h"
namespace mongo { namespace mongo {
class Cursor; class Cursor;
class DataFileHeader; class DataFileHeader;
class Extent; class Extent;
skipping to change at line 263 skipping to change at line 262
int nextOfs() const { _accessing(); return _nextOfs; } int nextOfs() const { _accessing(); return _nextOfs; }
int& nextOfs() { _accessing(); return _nextOfs; } int& nextOfs() { _accessing(); return _nextOfs; }
int prevOfs() const { _accessing(); return _prevOfs; } int prevOfs() const { _accessing(); return _prevOfs; }
int& prevOfs() { _accessing(); return _prevOfs; } int& prevOfs() { _accessing(); return _prevOfs; }
const char * data() const { _accessing(); return _data; } const char * data() const { _accessing(); return _data; }
char * data() { _accessing(); return _data; } char * data() { _accessing(); return _data; }
const char * dataNoThrowing() const { return _data; }
char * dataNoThrowing() { return _data; }
int netLength() const { _accessing(); return _netLength(); } int netLength() const { _accessing(); return _netLength(); }
/* use this when a record is deleted. basically a union with next/p rev fields */ /* use this when a record is deleted. basically a union with next/p rev fields */
DeletedRecord& asDeleted() { return *((DeletedRecord*) this); } DeletedRecord& asDeleted() { return *((DeletedRecord*) this); }
Extent* myExtent(const DiskLoc& myLoc) { return DataFileMgr::getExt ent(DiskLoc(myLoc.a(), extentOfs() ) ); } Extent* myExtent(const DiskLoc& myLoc) { return DataFileMgr::getExt ent(DiskLoc(myLoc.a(), extentOfs() ) ); }
/* get the next record in the namespace, traversing extents as nece ssary */ /* get the next record in the namespace, traversing extents as nece ssary */
DiskLoc getNext(const DiskLoc& myLoc); DiskLoc getNext(const DiskLoc& myLoc);
DiskLoc getPrev(const DiskLoc& myLoc); DiskLoc getPrev(const DiskLoc& myLoc);
skipping to change at line 626 skipping to change at line 628
namespace mongo { namespace mongo {
boost::intmax_t dbSize( const char *database ); boost::intmax_t dbSize( const char *database );
inline NamespaceIndex* nsindex(const StringData& ns) { inline NamespaceIndex* nsindex(const StringData& ns) {
Database *database = cc().database(); Database *database = cc().database();
verify( database ); verify( database );
memconcept::is(database, memconcept::concept::database, ns, sizeof( Database)); memconcept::is(database, memconcept::concept::database, ns, sizeof( Database));
DEV { DEV {
StringData dbname = nsToDatabaseSubstring( ns ); StringData dbname = nsToDatabaseSubstring( ns );
if ( database->name != dbname ) { if ( database->name() != dbname ) {
out() << "ERROR: attempt to write to wrong database\n"; out() << "ERROR: attempt to write to wrong database\n";
out() << " ns:" << ns << '\n'; out() << " ns:" << ns << '\n';
out() << " database->name:" << database->name << endl; out() << " database->name:" << database->name() << endl;
verify( database->name == dbname ); verify( database->name() == dbname );
} }
} }
return &database->namespaceIndex; return &database->namespaceIndex();
} }
inline NamespaceDetails* nsdetails(const StringData& ns) { inline NamespaceDetails* nsdetails(const StringData& ns) {
// if this faults, did you set the current db first? (Client::Cont ext + dblock) // if this faults, did you set the current db first? (Client::Cont ext + dblock)
NamespaceDetails *d = nsindex(ns)->details(ns); NamespaceDetails *d = nsindex(ns)->details(ns);
if( d ) { if( d ) {
memconcept::is(d, memconcept::concept::nsdetails, ns, sizeof(Na mespaceDetails)); memconcept::is(d, memconcept::concept::nsdetails, ns, sizeof(Na mespaceDetails));
} }
return d; return d;
} }
 End of changes. 6 change blocks. 
6 lines changed or deleted 8 lines changed or added


 pipeline.h   pipeline.h 
skipping to change at line 19 skipping to change at line 19
* 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 License * You should have received a copy of the GNU Affero General Public License
* 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 <deque>
#include "mongo/pch.h" #include "mongo/pch.h"
#include "util/intrusive_counter.h" #include "util/intrusive_counter.h"
#include "util/timer.h" #include "util/timer.h"
namespace mongo { namespace mongo {
class BSONObj; class BSONObj;
class BSONObjBuilder; class BSONObjBuilder;
class BSONArrayBuilder; class BSONArrayBuilder;
class DocumentSource; class DocumentSource;
skipping to change at line 95 skipping to change at line 97
This is only intended to be used by the shard command obtained This is only intended to be used by the shard command obtained
from splitForSharded(). Some pipeline operations in the merge from splitForSharded(). Some pipeline operations in the merge
process do not have equivalent command forms, and using this on process do not have equivalent command forms, and using this on
the mongos Pipeline will cause assertions. the mongos Pipeline will cause assertions.
@param the builder to write the command to @param the builder to write the command to
*/ */
void toBson(BSONObjBuilder *pBuilder) const; void toBson(BSONObjBuilder *pBuilder) const;
/** Stitch together the source pointers (by calling setSource) for
each source in sources.
* Must be called after optimize and addInitialSource but before t
rying to get results.
*/
void stitch();
/** /**
Run the Pipeline on the given source. Run the Pipeline on the given source.
@param result builder to write the result to @param result builder to write the result to
@param errmsg place to put error messages, if any
@returns true on success, false if an error occurs
*/ */
bool run(BSONObjBuilder &result, string &errmsg); void run(BSONObjBuilder& result);
/** /**
Debugging: should the processing pipeline be split within Debugging: should the processing pipeline be split within
mongod, simulating the real mongos/mongod split? This is determi ned mongod, simulating the real mongos/mongod split? This is determi ned
by setting the splitMongodPipeline field in an "aggregate" by setting the splitMongodPipeline field in an "aggregate"
command. command.
The split itself is handled by the caller, which is currently The split itself is handled by the caller, which is currently
pipeline_command.cpp. pipeline_command.cpp.
skipping to change at line 127 skipping to change at line 132
/** /**
Ask if this is for an explain request. Ask if this is for an explain request.
@returns true if this is an explain @returns true if this is an explain
*/ */
bool isExplain() const; bool isExplain() const;
/// The initial source is special since it varies between mongos an d mongod. /// The initial source is special since it varies between mongos an d mongod.
void addInitialSource(intrusive_ptr<DocumentSource> source); void addInitialSource(intrusive_ptr<DocumentSource> source);
/// The source that represents the output. Returns a non-owning poi
nter.
DocumentSource* output() { return sources.back().get(); }
/** /**
The aggregation command name. The aggregation command name.
*/ */
static const char commandName[]; static const char commandName[];
/* /*
PipelineD is a "sister" class that has additional functionality PipelineD is a "sister" class that has additional functionality
for the Pipeline. It exists because of linkage requirements. for the Pipeline. It exists because of linkage requirements.
Pipeline needs to function in mongod and mongos. PipelineD Pipeline needs to function in mongod and mongos. PipelineD
contains extra functionality required in mongod, and which can't contains extra functionality required in mongod, and which can't
skipping to change at line 189 skipping to change at line 197
Then this uses writeExplainOps() and adds that array to the resul t Then this uses writeExplainOps() and adds that array to the resul t
with the serverPipelineName. That will be preceded by explain with the serverPipelineName. That will be preceded by explain
information for the input source. information for the input source.
@param result the object to add the explain information to @param result the object to add the explain information to
*/ */
void writeExplainMongos(BSONObjBuilder &result) const; void writeExplainMongos(BSONObjBuilder &result) const;
string collectionName; string collectionName;
typedef deque<intrusive_ptr<DocumentSource> > SourceContainer; typedef std::deque<boost::intrusive_ptr<DocumentSource> > SourceCon tainer;
SourceContainer sources; SourceContainer sources;
bool explain; bool explain;
bool splitMongodPipeline; bool splitMongodPipeline;
intrusive_ptr<ExpressionContext> pCtx; boost::intrusive_ptr<ExpressionContext> pCtx;
}; };
} // namespace mongo } // namespace mongo
/* ======================= INLINED IMPLEMENTATIONS ======================== == */ /* ======================= INLINED IMPLEMENTATIONS ======================== == */
namespace mongo { namespace mongo {
inline string Pipeline::getCollectionName() const { inline string Pipeline::getCollectionName() const {
return collectionName; return collectionName;
 End of changes. 7 change blocks. 
5 lines changed or deleted 16 lines changed or added


 principal.h   principal.h 
skipping to change at line 23 skipping to change at line 23
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>
#include <string> #include <string>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
#include "mongo/base/string_data.h" #include "mongo/base/string_data.h"
#include "mongo/db/auth/principal_name.h" #include "mongo/db/auth/user_name.h"
#include "mongo/util/string_map.h" #include "mongo/util/string_map.h"
namespace mongo { namespace mongo {
/** /**
* Represents an authenticated user. Every principal has a name, a tim e that the user's * Represents an authenticated user. Every principal has a name, a tim e that the user's
* authentication expires, and a flag that describes whether or not pri vileges should be * authentication expires, and a flag that describes whether or not pri vileges should be
* acquired implicitly. * acquired implicitly.
* *
* The implicit privilege acquisition flag defaults to disabled, and th e expiration time * The implicit privilege acquisition flag defaults to disabled, and th e expiration time
* defaults to never. * defaults to never.
* *
* This class does not do any locking/synchronization, the consumer wil l be responsible for * This class does not do any locking/synchronization, the consumer wil l be responsible for
* synchronizing access. * synchronizing access.
*/ */
class Principal { class Principal {
MONGO_DISALLOW_COPYING(Principal); MONGO_DISALLOW_COPYING(Principal);
public: public:
Principal(const PrincipalName& name, Principal(const UserName& name,
const boost::posix_time::ptime& expirationTime); const boost::posix_time::ptime& expirationTime);
explicit Principal(const PrincipalName& name); explicit Principal(const UserName& name);
~Principal(); ~Principal();
const PrincipalName& getName() const { return _name; } const UserName& getName() const { return _name; }
// Returns the expiration time of this principal information. // Returns the expiration time of this principal information.
// No expiration is represented as boost::posix_time::pos_infin // No expiration is represented as boost::posix_time::pos_infin
const boost::posix_time::ptime& getExpirationTime() const { return _expirationTime; } const boost::posix_time::ptime& getExpirationTime() const { return _expirationTime; }
// Returns true if this principal is configured for implicit acquis ition of privileges. // Returns true if this principal is configured for implicit acquis ition of privileges.
bool isImplicitPrivilegeAcquisitionEnabled() const { return _enable ImplicitPrivileges; } bool isImplicitPrivilegeAcquisitionEnabled() const { return _enable ImplicitPrivileges; }
void setExpirationTime(boost::posix_time::ptime& expiration); void setExpirationTime(boost::posix_time::ptime& expiration);
void setImplicitPrivilegeAcquisition(bool enabled); void setImplicitPrivilegeAcquisition(bool enabled);
bool isDatabaseProbed(const StringData& dbname) const; bool isDatabaseProbed(const StringData& dbname) const;
void markDatabaseAsProbed(const StringData& dbname); void markDatabaseAsProbed(const StringData& dbname);
private: private:
PrincipalName _name; UserName _name;
boost::posix_time::ptime _expirationTime; boost::posix_time::ptime _expirationTime;
bool _enableImplicitPrivileges; bool _enableImplicitPrivileges;
StringMap<bool> _probedDatabases; StringMap<bool> _probedDatabases;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 5 change blocks. 
5 lines changed or deleted 5 lines changed or added


 principal_set.h   principal_set.h 
skipping to change at line 24 skipping to change at line 24
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include <vector> #include <vector>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
#include "mongo/base/string_data.h" #include "mongo/base/string_data.h"
#include "mongo/db/auth/principal.h" #include "mongo/db/auth/principal.h"
#include "mongo/db/auth/principal_name.h" #include "mongo/db/auth/user_name.h"
namespace mongo { namespace mongo {
/** /**
* A collection of authenticated principals. * A collection of authenticated principals.
* This class does not do any locking/synchronization, the consumer wil l be responsible for * This class does not do any locking/synchronization, the consumer wil l be responsible for
* synchronizing access. * synchronizing access.
*/ */
class PrincipalSet { class PrincipalSet {
MONGO_DISALLOW_COPYING(PrincipalSet); MONGO_DISALLOW_COPYING(PrincipalSet);
skipping to change at line 56 skipping to change at line 56
class NameIterator { class NameIterator {
public: public:
explicit NameIterator(const std::vector<Principal*>& principals ) : explicit NameIterator(const std::vector<Principal*>& principals ) :
_curr(principals.begin()), _curr(principals.begin()),
_end(principals.end()) { _end(principals.end()) {
} }
NameIterator() {} NameIterator() {}
bool more() { return _curr != _end; } bool more() { return _curr != _end; }
const PrincipalName& next() { const UserName& next() {
const PrincipalName& ret = get(); const UserName& ret = get();
++_curr; ++_curr;
return ret; return ret;
} }
const PrincipalName& get() const { return (*_curr)->getName(); } const UserName& get() const { return (*_curr)->getName(); }
const PrincipalName& operator*() const { return get(); } const UserName& operator*() const { return get(); }
const PrincipalName* operator->() const { return &get(); } const UserName* operator->() const { return &get(); }
private: private:
std::vector<Principal*>::const_iterator _curr; std::vector<Principal*>::const_iterator _curr;
std::vector<Principal*>::const_iterator _end; std::vector<Principal*>::const_iterator _end;
}; };
PrincipalSet(); PrincipalSet();
~PrincipalSet(); ~PrincipalSet();
// If the principal is already present, this will replace the exist ing entry. // If the principal is already present, this will replace the exist ing entry.
skipping to change at line 87 skipping to change at line 87
// deleting it eventually // deleting it eventually
void add(Principal* principal); void add(Principal* principal);
// Removes all principals whose authentication credentials came fro m dbname. // Removes all principals whose authentication credentials came fro m dbname.
void removeByDBName(const StringData& dbname); void removeByDBName(const StringData& dbname);
// Returns the Principal with the given name, or NULL if not found. // Returns the Principal with the given name, or NULL if not found.
// Ownership of the returned Principal remains with the PrincipalSe t. The pointer // Ownership of the returned Principal remains with the PrincipalSe t. The pointer
// returned is only guaranteed to remain valid until the next non-c onst method is called // returned is only guaranteed to remain valid until the next non-c onst method is called
// on the PrincipalSet. // on the PrincipalSet.
Principal* lookup(const PrincipalName& name) const; Principal* lookup(const UserName& name) const;
// Gets the principal whose authentication credentials came from db name, or NULL if none // Gets the principal whose authentication credentials came from db name, or NULL if none
// exist. There should be at most one such principal. // exist. There should be at most one such principal.
Principal* lookupByDBName(const StringData& dbname) const; Principal* lookupByDBName(const StringData& dbname) const;
// Gets an iterator over the names of the principals stored in the set. The iterator is // Gets an iterator over the names of the principals stored in the set. The iterator is
// valid until the next non-const method is called on the Principal Set. // valid until the next non-const method is called on the Principal Set.
NameIterator getNames() const { return NameIterator(_principals); } NameIterator getNames() const { return NameIterator(_principals); }
iterator begin() const { return _principals.begin(); } iterator begin() const { return _principals.begin(); }
 End of changes. 5 change blocks. 
7 lines changed or deleted 7 lines changed or added


 privilege.h   privilege.h 
skipping to change at line 19 skipping to change at line 19
* 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 <string> #include <string>
#include <vector>
#include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h" #include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/principal.h" #include "mongo/db/auth/principal.h"
namespace mongo { namespace mongo {
/** /**
* A representation of the permission to perform a set of actions on a specific resource. * A representation of the permission to perform a set of actions on a specific resource.
*/ */
skipping to change at line 40 skipping to change at line 41
public: public:
Privilege(const std::string& resource, const ActionType& action); Privilege(const std::string& resource, const ActionType& action);
Privilege(const std::string& resource, const ActionSet& actions); Privilege(const std::string& resource, const ActionSet& actions);
~Privilege() {} ~Privilege() {}
const std::string& getResource() const { return _resource; } const std::string& getResource() const { return _resource; }
const ActionSet& getActions() const { return _actions; } const ActionSet& getActions() const { return _actions; }
void addActions(const ActionSet& actionsToAdd);
void removeActions(const ActionSet& actionsToRemove);
// Checks if the given action is present in the Privilege. // Checks if the given action is present in the Privilege.
bool includesAction(const ActionType& action) const; bool includesAction(const ActionType& action) const;
// Checks if the given actions are present in the Privilege. // Checks if the given actions are present in the Privilege.
bool includesActions(const ActionSet& actions) const; bool includesActions(const ActionSet& actions) const;
private: private:
std::string _resource; std::string _resource;
ActionSet _actions; // bitmask of actions this privilege grants ActionSet _actions; // bitmask of actions this privilege grants
}; };
typedef std::vector<Privilege> PrivilegeVector;
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
0 lines changed or deleted 6 lines changed or added


 privilege_set.h   privilege_set.h 
skipping to change at line 24 skipping to change at line 24
*/ */
#pragma once #pragma once
#include <map> #include <map>
#include <string> #include <string>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
#include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h" #include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/privilege.h" #include "mongo/db/auth/privilege.h"
#include "mongo/db/auth/principal_name.h" #include "mongo/db/auth/user_name.h"
#include "mongo/util/string_map.h" #include "mongo/util/string_map.h"
namespace mongo { namespace mongo {
/** /**
* A collection of privileges describing which authenticated principals bestow the client the * A collection of privileges describing which authenticated users best ow the client the
* ability to perform various actions on specific resources. Since eve ry privilege comes from * ability to perform various actions on specific resources. Since eve ry privilege comes from
* an authenticated principal, removing that principal removes all priv * an authenticated user, removing that user removes all privileges gra
ileges granted by that nted by that
* principal. * user.
* *
* Resources are arranged hierarchically, with a wildcard resource, * Resources are arranged hierarchically, with a wildcard resource,
* PrivilegeSet::WILDCARD_RESOURCE, matching any resource. In the curr ent implementation, the * PrivilegeSet::WILDCARD_RESOURCE, matching any resource. In the curr ent implementation, the
* only two levels of the hierarchy are the wildcard and one level belo w, which is analagous to * only two levels of the hierarchy are the wildcard and one level belo w, which is analagous to
* the name of a database. It is future work to support collection or other sub-database * the name of a database. It is future work to support collection or other sub-database
* resources. * resources.
* *
* This class does not do any locking/synchronization, the consumer wil l be responsible for * This class does not do any locking/synchronization, the consumer wil l be responsible for
* synchronizing access. * synchronizing access.
*/ */
class PrivilegeSet { class PrivilegeSet {
MONGO_DISALLOW_COPYING(PrivilegeSet); MONGO_DISALLOW_COPYING(PrivilegeSet);
public: public:
static const std::string WILDCARD_RESOURCE; static const std::string WILDCARD_RESOURCE;
PrivilegeSet(); PrivilegeSet();
~PrivilegeSet(); ~PrivilegeSet();
/** /**
* Adds the specified privilege to the set, associating it with the named principal. * Adds the specified privilege to the set, associating it with the named user.
* *
* The privilege should be on a specific resource, or on the WILDCA RD_RESOURCE. * The privilege should be on a specific resource, or on the WILDCA RD_RESOURCE.
*/ */
void grantPrivilege(const Privilege& privilege, const PrincipalName & authorizingPrincipal); void grantPrivilege(const Privilege& privilege, const UserName& aut horizingUser);
/** /**
* Adds the specified privileges to the set, associating them with the named principal. * Adds the specified privileges to the set, associating them with the named user.
*/ */
void grantPrivileges(const std::vector<Privilege>& privileges, void grantPrivileges(const std::vector<Privilege>& privileges,
const PrincipalName& authorizingPrincipal); const UserName& authorizingUser);
/** /**
* Removes from the set all privileges associated with the given pr incipal. * Removes from the set all privileges associated with the given us er.
* *
* If multiple princpals enable the same privilege, the set will co * If multiple users enable the same privilege, the set will contin
ntinue to ue to
* contain those privileges until all authorizing principals have h * contain those privileges until all authorizing users have had th
ad their eir
* privileges revoked from the set. * privileges revoked from the set.
*/ */
void revokePrivilegesFromPrincipal(const PrincipalName& principal); void revokePrivilegesFromUser(const UserName& user);
/** /**
* Returns true if the set authorizes "desiredPrivilege". * Returns true if the set authorizes "desiredPrivilege".
* *
* The set is considered to authorize "desiredPrivilege" if each ac tion in * The set is considered to authorize "desiredPrivilege" if each ac tion in
* "desiredPrivilege" is satisfied either on the database component of * "desiredPrivilege" is satisfied either on the database component of
* "desiredPrivilege.getResource()" or on WILDCARD_RESOURCE. * "desiredPrivilege.getResource()" or on WILDCARD_RESOURCE.
* *
* TODO: Support checking for the privilege on the full resource na me as well as the * TODO: Support checking for the privilege on the full resource na me as well as the
* database component, to support sub-database granularity privileg e assignment. * database component, to support sub-database granularity privileg e assignment.
skipping to change at line 97 skipping to change at line 97
* Same as hasPrivilege, except checks all the privileges in a vect or. * Same as hasPrivilege, except checks all the privileges in a vect or.
*/ */
bool hasPrivileges(const std::vector<Privilege>& desiredPrivileges) ; bool hasPrivileges(const std::vector<Privilege>& desiredPrivileges) ;
private: private:
/** /**
* Information about privileges held on a resource. * Information about privileges held on a resource.
* *
* Instances are stored in the _byResource map, and accelerate the fast path of * Instances are stored in the _byResource map, and accelerate the fast path of
* hasPrivilege(). Privilege revocations via revokePrivilegesFromP rincipal() can make these * hasPrivilege(). Privilege revocations via revokePrivilegesFromU ser() can make these
* entries invalid, at which point they are marked "dirty". Dirty entries are rebuilt via * entries invalid, at which point they are marked "dirty". Dirty entries are rebuilt via
* _rebuildEntry(), below, during execution of hasPrivilege(). * _rebuildEntry(), below, during execution of hasPrivilege().
*/ */
class ResourcePrivilegeCacheEntry { class ResourcePrivilegeCacheEntry {
public: public:
ResourcePrivilegeCacheEntry() : actions(), dirty(false) {} ResourcePrivilegeCacheEntry() : actions(), dirty(false) {}
// All actions enabled on the associated resource, provided tha t "dirty" is false. // All actions enabled on the associated resource, provided tha t "dirty" is false.
ActionSet actions; ActionSet actions;
// False if this data is consistent with the full privilege inf ormation, stored in the // False if this data is consistent with the full privilege inf ormation, stored in the
// _byPrincipal map. // _byUser map.
bool dirty; bool dirty;
}; };
/** /**
* Type of map from resource names to authorized actions. * Type of map from resource names to authorized actions.
*/ */
typedef StringMap<ResourcePrivilegeCacheEntry> ResourcePrivilegeCac he; typedef StringMap<ResourcePrivilegeCacheEntry> ResourcePrivilegeCac he;
/** /**
* Type of map from principal identity to information about the pri ncipal's privileges. The * Type of map from user identity to information about the user's p rivileges. The
* values in the map are themselves maps from resource names to ass ociated actions. * values in the map are themselves maps from resource names to ass ociated actions.
*/ */
typedef std::map<PrincipalName, StringMap<ActionSet> > PrincipalPri vilegeMap; typedef std::map<UserName, StringMap<ActionSet> > UserPrivilegeMap;
void _rebuildEntry(const StringData& resource, ResourcePrivilegeCac heEntry* summary); void _rebuildEntry(const StringData& resource, ResourcePrivilegeCac heEntry* summary);
ResourcePrivilegeCacheEntry* _lookupEntry(const StringData& resourc e); ResourcePrivilegeCacheEntry* _lookupEntry(const StringData& resourc e);
ResourcePrivilegeCacheEntry* _lookupOrInsertEntry(const StringData& resource); ResourcePrivilegeCacheEntry* _lookupOrInsertEntry(const StringData& resource);
// Information about privileges available on all resources. // Information about privileges available on all resources.
ResourcePrivilegeCacheEntry _globalPrivilegeEntry; ResourcePrivilegeCacheEntry _globalPrivilegeEntry;
// Cache of privilege information, by resource. // Cache of privilege information, by resource.
ResourcePrivilegeCache _byResource; ResourcePrivilegeCache _byResource;
// Directory of privilege information, by principal. // Directory of privilege information, by user.
PrincipalPrivilegeMap _byPrincipal; UserPrivilegeMap _byUser;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 15 change blocks. 
21 lines changed or deleted 21 lines changed or added


 processinfo.h   processinfo.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 <sys/types.h>
#include <string> #include <string>
#ifndef _WIN32 #include "mongo/platform/cstdint.h"
#include <unistd.h> #include "mongo/platform/process_id.h"
#else #include "mongo/db/jsobj.h"
typedef int pid_t;
int getpid();
#endif
#include <db/jsobj.h>
namespace mongo { namespace mongo {
class ProcessInfo { class ProcessInfo {
public: public:
ProcessInfo( pid_t pid = getpid() ); ProcessInfo( ProcessId pid = ProcessId::getCurrent() );
~ProcessInfo(); ~ProcessInfo();
/** /**
* @return mbytes * @return mbytes
*/ */
int getVirtualMemorySize(); int getVirtualMemorySize();
/** /**
* @return mbytes * @return mbytes
*/ */
skipping to change at line 162 skipping to change at line 156
pageSize( 0 ), pageSize( 0 ),
hasNuma( false ) { hasNuma( false ) {
// populate SystemInfo during construction // populate SystemInfo during construction
collectSystemInfo(); collectSystemInfo();
} }
private: private:
/** Collect host system info */ /** Collect host system info */
void collectSystemInfo(); void collectSystemInfo();
}; };
pid_t _pid; ProcessId _pid;
static mongo::mutex _sysInfoLock; static mongo::mutex _sysInfoLock;
static bool checkNumaEnabled(); static bool checkNumaEnabled();
static ProcessInfo::SystemInfo* systemInfo; static ProcessInfo::SystemInfo* systemInfo;
inline const SystemInfo& sysInfo() const { inline const SystemInfo& sysInfo() const {
return *systemInfo; return *systemInfo;
} }
 End of changes. 4 change blocks. 
11 lines changed or deleted 5 lines changed or added


 query.h   query.h 
skipping to change at line 22 skipping to change at line 22
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/pch.h" #include "mongo/pch.h"
#include "../../util/net/message.h"
#include "../dbmessage.h" #include "mongo/db/diskloc.h"
#include "../jsobj.h" #include "mongo/db/dbmessage.h"
#include "../diskloc.h" #include "mongo/db/explain.h"
#include "../explain.h" #include "mongo/db/jsobj.h"
#include "../../s/d_chunk_manager.h" #include "mongo/s/collection_metadata.h"
#include "mongo/util/net/message.h"
// struct QueryOptions, QueryResult, QueryResultFlags in: // struct QueryOptions, QueryResult, QueryResultFlags in:
namespace mongo { namespace mongo {
class ParsedQuery; class ParsedQuery;
class QueryOptimizerCursor; class QueryOptimizerCursor;
struct QueryPlanSummary; struct QueryPlanSummary;
extern const int32_t MaxBytesToReturnToClientAtOnce; extern const int32_t MaxBytesToReturnToClientAtOnce;
skipping to change at line 293 skipping to change at line 294
/** /**
* Callback when enough results have been read for the first batch, with potential handoff * Callback when enough results have been read for the first batch, with potential handoff
* to getMore. * to getMore.
*/ */
void finishedFirstBatch(); void finishedFirstBatch();
/** /**
* Set the data portion of the supplied Message to a buffer contain ing the query results. * Set the data portion of the supplied Message to a buffer contain ing the query results.
* @return the number of results in the buffer. * @return the number of results in the buffer.
*/ */
int handoff( Message &result ); int handoff( Message &result );
/** A chunk manager found at the beginning of the query. */ /** Metadata found at the beginning of the query. */
ShardChunkManagerPtr chunkManager() const { return _chunkManager; } CollectionMetadataPtr collMetadata() const { return _collMetadata;
}
private: private:
QueryResponseBuilder( const ParsedQuery &parsedQuery, const shared_ ptr<Cursor> &cursor ); QueryResponseBuilder( const ParsedQuery &parsedQuery, const shared_ ptr<Cursor> &cursor );
void init( const QueryPlanSummary &queryPlan, const BSONObj &oldPla n ); void init( const QueryPlanSummary &queryPlan, const BSONObj &oldPla n );
ShardChunkManagerPtr newChunkManager() const; CollectionMetadataPtr newCollMetadata() const;
shared_ptr<ExplainRecordingStrategy> newExplainRecordingStrategy shared_ptr<ExplainRecordingStrategy> newExplainRecordingStrategy
( const QueryPlanSummary &queryPlan, const BSONObj &oldPlan ) const ; ( const QueryPlanSummary &queryPlan, const BSONObj &oldPlan ) const ;
shared_ptr<ResponseBuildStrategy> newResponseBuildStrategy shared_ptr<ResponseBuildStrategy> newResponseBuildStrategy
( const QueryPlanSummary &queryPlan ); ( const QueryPlanSummary &queryPlan );
/** /**
* @return true if the cursor's document matches the query. * @return true if the cursor's document matches the query.
* @param resultDetails describes how the document was matched and loaded. * @param resultDetails describes how the document was matched and loaded.
*/ */
bool currentMatches( ResultDetails* resultDetails ); bool currentMatches( ResultDetails* resultDetails );
/** /**
* @return true if the cursor's document is in a valid chunk range. * @return true if the cursor's document is in a valid chunk range.
* @param resultDetails describes how the document was matched and loaded. * @param resultDetails describes how the document was matched and loaded.
*/ */
bool chunkMatches( ResultDetails* resultDetails ); bool chunkMatches( ResultDetails* resultDetails );
const ParsedQuery &_parsedQuery; const ParsedQuery &_parsedQuery;
shared_ptr<Cursor> _cursor; shared_ptr<Cursor> _cursor;
shared_ptr<QueryOptimizerCursor> _queryOptimizerCursor; shared_ptr<QueryOptimizerCursor> _queryOptimizerCursor;
BufBuilder _buf; BufBuilder _buf;
ShardChunkManagerPtr _chunkManager; CollectionMetadataPtr _collMetadata;
shared_ptr<ExplainRecordingStrategy> _explain; shared_ptr<ExplainRecordingStrategy> _explain;
shared_ptr<ResponseBuildStrategy> _builder; shared_ptr<ResponseBuildStrategy> _builder;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 4 change blocks. 
10 lines changed or deleted 12 lines changed or added


 ramlog.h   ramlog.h 
// ramlog.h
/* Copyright 2009 10gen Inc. /* Copyright 2009 10gen Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include "log.h" #include "mongo/logger/ramlog.h"
namespace mongo {
class RamLog : public Tee {
public:
RamLog( const std::string& name );
virtual void write(LogLevel ll, const string& str);
void get( vector<const char*>& v) const;
void toHTML(stringstream& s);
static RamLog* get( const std::string& name );
static void getNames( vector<string>& names );
time_t lastWrite() { return _lastWrite; } // 0 if no writes
long long getTotalLinesWritten() const { return _totalLinesWritten;
}
protected:
static int repeats(const vector<const char *>& v, int i);
static string clean(const vector<const char *>& v, int i, string li
ne="");
static string color(const std::string& line);
/* turn http:... into an anchor */
static string linkify(const char *s);
private:
~RamLog(); // want this private as we want to leak so we can use th
em till the very end
enum {
N = 1024, // number of lines
C = 512 // max size of line
};
char lines[N][C];
unsigned h; // current position
unsigned n; // number of lines stores 0 o N
string _name;
long long _totalLinesWritten;
typedef map<string,RamLog*> RM;
static mongo::mutex* _namedLock;
static RM* _named;
time_t _lastWrite;
};
}
 End of changes. 2 change blocks. 
2 lines changed or deleted 0 lines changed or added


 range_arithmetic.h   range_arithmetic.h 
skipping to change at line 20 skipping to change at line 20
* 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 <string> #include <string>
#include <map>
#include <vector>
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
namespace mongo { namespace mongo {
/** /**
* A KeyRange represents a range over keys of documents in a namespace, qualified by a * A KeyRange represents a range over keys of documents in a namespace, qualified by a
* key pattern which defines the documents that are in the key range. * key pattern which defines the documents that are in the key range.
* *
* There may be many different expressions to generate the same key fie lds from a document - the * There may be many different expressions to generate the same key fie lds from a document - the
skipping to change at line 91 skipping to change at line 93
/** /**
* Returns -1 if first range is less than the second range, 0 if equal and 1 if * Returns -1 if first range is less than the second range, 0 if equal and 1 if
* greater. The ordering is based on comparing both the min first and t hen uses * greater. The ordering is based on comparing both the min first and t hen uses
* the max as the tie breaker. * the max as the tie breaker.
*/ */
int compareRanges( const BSONObj& rangeMin1, int compareRanges( const BSONObj& rangeMin1,
const BSONObj& rangeMax1, const BSONObj& rangeMax1,
const BSONObj& rangeMin2, const BSONObj& rangeMin2,
const BSONObj& rangeMax2 ); const BSONObj& rangeMax2 );
/**
* A RangeMap is a mapping of a BSON range from lower->upper (lower map
s to upper), using
* standard BSON woCompare. Upper bound is exclusive.
*
* NOTE: For overlap testing to work correctly, there may be no overlap
s present in the map
* itself.
*/
typedef map<BSONObj, BSONObj, BSONObjCmp> RangeMap;
/**
* A RangeVector is a list of [lower,upper) ranges.
*/
typedef vector<pair<BSONObj,BSONObj> > RangeVector;
/**
* Returns the overlap of a range [inclusiveLower, exclusiveUpper) with
the provided range map
* as a vector of ranges from the map.
*/
void getRangeMapOverlap( const RangeMap& ranges,
const BSONObj& inclusiveLower,
const BSONObj& exclusiveUpper,
RangeVector* vector );
/**
* Returns true if the provided range map has ranges which overlap the
provided range
* [inclusiveLower, exclusiveUpper).
*/
bool rangeMapOverlaps( const RangeMap& ranges,
const BSONObj& inclusiveLower,
const BSONObj& exclusiveUpper );
/**
* Returns true if the provided range map exactly contains the provided
range
* [inclusiveLower, exclusiveUpper).
*/
bool rangeMapContains( const RangeMap& ranges,
const BSONObj& inclusiveLower,
const BSONObj& exclusiveUpper );
} }
 End of changes. 2 change blocks. 
0 lines changed or deleted 46 lines changed or added


 range_deleter_mock_env.h   range_deleter_mock_env.h 
skipping to change at line 24 skipping to change at line 24
* 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 <map> #include <map>
#include <set> #include <set>
#include <string> #include <string>
#include "mongo/s/range_arithmetic.h" #include "mongo/s/range_arithmetic.h"
#include "mongo/s/range_deleter.h" #include "mongo/db/range_deleter.h"
namespace mongo { namespace mongo {
struct DeletedRange { struct DeletedRange {
std::string ns; std::string ns;
BSONObj min; BSONObj min;
BSONObj max; BSONObj max;
BSONObj shardKeyPattern; BSONObj shardKeyPattern;
}; };
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 range_deleter_stats.h   range_deleter_stats.h 
skipping to change at line 59 skipping to change at line 59
_totalDeletes(0), _totalDeletes(0),
_pendingDeletes(0), _pendingDeletes(0),
_inProgressDeletes(0) { _inProgressDeletes(0) {
} }
/** /**
* Returns the BSON representation of this stat object. * Returns the BSON representation of this stat object.
*/ */
BSONObj toBSON() const; BSONObj toBSON() const;
// Returns the current number of active and pending deletes.
int getCurrentDeletes() const;
// //
// Setters - Should be holding mutex passed to // Setters - Should be holding mutex passed to
// the constructor when calling these methods. // the constructor when calling these methods.
// //
void incTotalDeletes_inlock() { void incTotalDeletes_inlock() {
_totalDeletes++; _totalDeletes++;
} }
void decTotalDeletes_inlock() { void decTotalDeletes_inlock() {
 End of changes. 1 change blocks. 
0 lines changed or deleted 3 lines changed or added


 rs.h   rs.h 
skipping to change at line 337 skipping to change at line 337
PRESTART=0, LOADINGCONFIG=1, BADCONFIG=2, EMPTYCONFIG=3, PRESTART=0, LOADINGCONFIG=1, BADCONFIG=2, EMPTYCONFIG=3,
EMPTYUNREACHABLE=4, STARTED=5, SOON=6 EMPTYUNREACHABLE=4, STARTED=5, SOON=6
}; };
static StartupStatus startupStatus; static StartupStatus startupStatus;
static DiagStr startupStatusMsg; static DiagStr startupStatusMsg;
static string stateAsHtml(MemberState state); static string stateAsHtml(MemberState state);
/* todo thread */ /* todo thread */
void msgUpdateHBInfo(HeartbeatInfo); void msgUpdateHBInfo(HeartbeatInfo);
/**
* Updates the lastHeartbeatRecv of Member with the given id.
*/
void msgUpdateHBRecv(unsigned id, time_t newTime);
StateBox box; StateBox box;
OpTime lastOpTimeWritten; OpTime lastOpTimeWritten;
long long lastH; // hash we use to make sure we are reading the rig ht flow of ops and aren't on an out-of-date "fork" long long lastH; // hash we use to make sure we are reading the rig ht flow of ops and aren't on an out-of-date "fork"
bool forceSyncFrom(const string& host, string& errmsg, BSONObjBuild er& result); bool forceSyncFrom(const string& host, string& errmsg, BSONObjBuild er& result);
// Check if the current sync target is suboptimal. This must be cal led while holding a mutex // Check if the current sync target is suboptimal. This must be cal led while holding a mutex
// that prevents the sync source from changing. // that prevents the sync source from changing.
bool shouldChangeSyncTarget(const OpTime& target) const; bool shouldChangeSyncTarget(const OpTime& target) const;
/** /**
skipping to change at line 435 skipping to change at line 440
* Behavior to note: * Behavior to note:
* - locks this * - locks this
* - intentionally leaks the old _cfg and any old _members (if the * - intentionally leaks the old _cfg and any old _members (if the
* change isn't strictly additive) * change isn't strictly additive)
*/ */
bool initFromConfig(ReplSetConfig& c, bool reconf=false); bool initFromConfig(ReplSetConfig& c, bool reconf=false);
void _fillIsMaster(BSONObjBuilder&); void _fillIsMaster(BSONObjBuilder&);
void _fillIsMasterHost(const Member*, vector<string>&, vector<strin g>&, vector<string>&); void _fillIsMasterHost(const Member*, vector<string>&, vector<strin g>&, vector<string>&);
const ReplSetConfig& config() { return *_cfg; } const ReplSetConfig& config() { return *_cfg; }
string name() const { return _name; } /* @return replica set's logi cal name */ string name() const { return _name; } /* @return replica set's logi cal name */
int version() const { return _cfg->version; } /* @return replica se t's config version */
MemberState state() const { return box.getState(); } MemberState state() const { return box.getState(); }
void _fatal(); void _fatal();
void _getOplogDiagsAsHtml(unsigned server_id, stringstream& ss) con st; void _getOplogDiagsAsHtml(unsigned server_id, stringstream& ss) con st;
void _summarizeAsHtml(stringstream&) const; void _summarizeAsHtml(stringstream&) const;
void _summarizeStatus(BSONObjBuilder&) const; // for replSetGetStat us command void _summarizeStatus(BSONObjBuilder&) const; // for replSetGetStat us command
/* call afer constructing to start - returns fairly quickly after l aunching its threads */ /* call afer constructing to start - returns fairly quickly after l aunching its threads */
void _go(); void _go();
private: private:
 End of changes. 2 change blocks. 
0 lines changed or deleted 6 lines changed or added


 rs_member.h   rs_member.h 
skipping to change at line 103 skipping to change at line 103
bool up() const { return health > 0; } bool up() const { return health > 0; }
/** health is set to -1 on startup. that means we haven't even che cked yet. 0 means we checked and it failed. */ /** health is set to -1 on startup. that means we haven't even che cked yet. 0 means we checked and it failed. */
bool maybeUp() const { return health != 0; } bool maybeUp() const { return health != 0; }
long long timeDown() const; // ms long long timeDown() const; // ms
/* true if changed in a way of interest to the repl set manager. */ /* true if changed in a way of interest to the repl set manager. */
bool changed(const HeartbeatInfo& old) const; bool changed(const HeartbeatInfo& old) const;
void recvHeartbeat(); /**
* Updates this with the info received from the command result we g
ot from
* the last replSetHeartbeat.
*/
void updateFromLastPoll(const HeartbeatInfo& newInfo);
}; };
inline HeartbeatInfo::HeartbeatInfo(unsigned id) : inline HeartbeatInfo::HeartbeatInfo(unsigned id) :
_id(id), _id(id),
lastHeartbeatRecv(0), lastHeartbeatRecv(0),
authIssue(false), authIssue(false),
ping(0) { ping(0) {
hbstate = MemberState::RS_UNKNOWN; hbstate = MemberState::RS_UNKNOWN;
health = -1.0; health = -1.0;
downSince = 0; downSince = 0;
 End of changes. 1 change blocks. 
1 lines changed or deleted 6 lines changed or added


 s2_access_method.h   s2_access_method.h 
skipping to change at line 20 skipping to change at line 20
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/base/status.h" #include "mongo/base/status.h"
#include "mongo/db/geo/s2common.h"
#include "mongo/db/index/btree_access_method_internal.h" #include "mongo/db/index/btree_access_method_internal.h"
#include "mongo/db/index/index_descriptor.h" #include "mongo/db/index/index_descriptor.h"
#include "mongo/db/index/s2_common.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
namespace mongo { namespace mongo {
class IndexCursor; class IndexCursor;
struct S2IndexingParams; struct S2IndexingParams;
class S2AccessMethod : public BtreeBasedAccessMethod { class S2AccessMethod : public BtreeBasedAccessMethod {
public: public:
using BtreeBasedAccessMethod::_descriptor; using BtreeBasedAccessMethod::_descriptor;
 End of changes. 2 change blocks. 
1 lines changed or deleted 1 lines changed or added


 s2_index_cursor.h   s2_index_cursor.h 
skipping to change at line 23 skipping to change at line 23
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <vector> #include <vector>
#include "mongo/db/btreecursor.h" #include "mongo/db/btreecursor.h"
#include "mongo/db/geo/geoquery.h" #include "mongo/db/geo/geoquery.h"
#include "mongo/db/geo/s2common.h"
#include "mongo/db/index/index_cursor.h" #include "mongo/db/index/index_cursor.h"
#include "mongo/db/index/index_descriptor.h" #include "mongo/db/index/index_descriptor.h"
#include "mongo/db/index/s2_common.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/pdfile.h" #include "mongo/db/pdfile.h"
#include "mongo/platform/unordered_set.h" #include "mongo/platform/unordered_set.h"
#include "third_party/s2/s2cap.h" #include "third_party/s2/s2cap.h"
#include "third_party/s2/s2regionintersection.h" #include "third_party/s2/s2regionintersection.h"
namespace mongo { namespace mongo {
/** /**
* This is the cursor that the caller of S2AccessMethod::newCursor actu ally gets. When you call * This is the cursor that the caller of S2AccessMethod::newCursor actu ally gets. When you call
skipping to change at line 49 skipping to change at line 49
*/ */
class S2IndexCursor : public IndexCursor { class S2IndexCursor : public IndexCursor {
public: public:
S2IndexCursor(const S2IndexingParams& params, IndexDescriptor* desc riptor); S2IndexCursor(const S2IndexingParams& params, IndexDescriptor* desc riptor);
virtual ~S2IndexCursor() { } virtual ~S2IndexCursor() { }
// Parse the query, figure out if it's a near or a non-near predica te, and create the // Parse the query, figure out if it's a near or a non-near predica te, and create the
// appropriate sub-cursor. // appropriate sub-cursor.
virtual Status seek(const BSONObj& position); virtual Status seek(const BSONObj& position);
// Not implemented:
virtual Status seek(const vector<const BSONElement*>& position,
const vector<bool>& inclusive);
virtual Status skip(const vector<const BSONElement*>& position,
const vector<bool>& inclusive);
virtual Status setOptions(const CursorOptions& options); virtual Status setOptions(const CursorOptions& options);
// Implemented: // Implemented:
virtual bool isEOF() const; virtual bool isEOF() const;
virtual BSONObj getKey() const; virtual BSONObj getKey() const;
virtual DiskLoc getValue() const; virtual DiskLoc getValue() const;
virtual void next(); virtual void next();
virtual string toString(); virtual string toString();
virtual Status savePosition(); virtual Status savePosition();
virtual Status restorePosition(); virtual Status restorePosition();
virtual void aboutToDeleteBucket(const DiskLoc& bucket);
private: private:
S2IndexingParams _params; S2IndexingParams _params;
IndexDescriptor *_descriptor; IndexDescriptor *_descriptor;
scoped_ptr<IndexCursor> _underlyingCursor; scoped_ptr<IndexCursor> _underlyingCursor;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 4 change blocks. 
8 lines changed or deleted 1 lines changed or added


 s2_near_cursor.h   s2_near_cursor.h 
skipping to change at line 23 skipping to change at line 23
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <queue> #include <queue>
#include "mongo/db/btreecursor.h" #include "mongo/db/btreecursor.h"
#include "mongo/db/geo/geoquery.h" #include "mongo/db/geo/geoquery.h"
#include "mongo/db/geo/s2common.h"
#include "mongo/db/index/index_cursor.h" #include "mongo/db/index/index_cursor.h"
#include "mongo/db/index/index_descriptor.h" #include "mongo/db/index/index_descriptor.h"
#include "mongo/db/index/s2_common.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/pdfile.h" #include "mongo/db/pdfile.h"
#include "mongo/platform/unordered_set.h" #include "mongo/platform/unordered_set.h"
#include "third_party/s2/s2cap.h" #include "third_party/s2/s2cap.h"
#include "third_party/s2/s2regionintersection.h" #include "third_party/s2/s2regionintersection.h"
namespace mongo { namespace mongo {
class S2NearIndexCursor : public IndexCursor { class S2NearIndexCursor : public IndexCursor {
public: public:
S2NearIndexCursor(IndexDescriptor* descriptor, const S2IndexingPara ms& params); S2NearIndexCursor(IndexDescriptor* descriptor, const S2IndexingPara ms& params);
virtual ~S2NearIndexCursor(); virtual ~S2NearIndexCursor();
// Not implemented. // Not implemented.
virtual Status seek(const BSONObj &position); virtual Status seek(const BSONObj &position);
virtual Status seek(const vector<const BSONElement*>& position,
const vector<bool>& inclusive);
virtual Status skip(const vector<const BSONElement*>& position,
const vector<bool>& inclusive);
Status setOptions(const CursorOptions& options); Status setOptions(const CursorOptions& options);
// Implemented: // Implemented:
// This is our very specific seek function. Not part of IndexCurso r. // This is our very specific seek function. Not part of IndexCurso r.
void seek(const BSONObj& query, const NearQuery& nearQuery, void seek(const BSONObj& query, const NearQuery& nearQuery,
const vector<GeoQuery>& regions); const vector<GeoQuery>& regions);
virtual bool isEOF() const; virtual bool isEOF() const;
virtual BSONObj getKey() const; virtual BSONObj getKey() const;
virtual DiskLoc getValue() const; virtual DiskLoc getValue() const;
virtual void next(); virtual void next();
skipping to change at line 123 skipping to change at line 119
// What geo regions are we looking for? // What geo regions are we looking for?
vector<GeoQuery> _indexedGeoFields; vector<GeoQuery> _indexedGeoFields;
// How were the keys created? We need this to search for the right stuff. // How were the keys created? We need this to search for the right stuff.
S2IndexingParams _params; S2IndexingParams _params;
// We also pass this to the FieldRangeVector ctor. // We also pass this to the FieldRangeVector ctor.
BSONObj _specForFRV; BSONObj _specForFRV;
// Geo-related variables. // Geo-related variables.
// At what min distance (arc length) do we start looking for result
s?
double _minDistance;
// What's the max distance (arc length) we're willing to look for r esults? // What's the max distance (arc length) we're willing to look for r esults?
double _maxDistance; double _maxDistance;
// We compute an annulus of results and cache it here. // We compute an annulus of results and cache it here.
priority_queue<Result> _results; priority_queue<Result> _results;
// These radii define the annulus we're currently looking at. // These radii define the annulus we're currently looking at.
double _innerRadius; double _innerRadius;
double _outerRadius; double _outerRadius;
 End of changes. 4 change blocks. 
5 lines changed or deleted 4 lines changed or added


 s2_simple_cursor.h   s2_simple_cursor.h 
skipping to change at line 23 skipping to change at line 23
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <vector> #include <vector>
#include "mongo/db/btreecursor.h" #include "mongo/db/btreecursor.h"
#include "mongo/db/geo/geoquery.h" #include "mongo/db/geo/geoquery.h"
#include "mongo/db/geo/s2common.h"
#include "mongo/db/index/index_cursor.h" #include "mongo/db/index/index_cursor.h"
#include "mongo/db/index/index_descriptor.h" #include "mongo/db/index/index_descriptor.h"
#include "mongo/db/index/s2_common.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/pdfile.h" #include "mongo/db/pdfile.h"
#include "mongo/platform/unordered_set.h" #include "mongo/platform/unordered_set.h"
#include "third_party/s2/s2cap.h" #include "third_party/s2/s2cap.h"
#include "third_party/s2/s2regionintersection.h" #include "third_party/s2/s2regionintersection.h"
namespace mongo { namespace mongo {
class S2SimpleCursor : public IndexCursor { class S2SimpleCursor : public IndexCursor {
public: public:
S2SimpleCursor(IndexDescriptor* descriptor, const S2IndexingParams& params); S2SimpleCursor(IndexDescriptor* descriptor, const S2IndexingParams& params);
virtual ~S2SimpleCursor() { } virtual ~S2SimpleCursor() { }
// Not implemented // Not implemented
virtual Status seek(const BSONObj& position); virtual Status seek(const BSONObj& position);
virtual Status seek(const vector<const BSONElement*>& position,
const vector<bool>& inclusive);
virtual Status skip(const vector<const BSONElement*>& position,
const vector<bool>& inclusive);
Status setOptions(const CursorOptions& options); Status setOptions(const CursorOptions& options);
// Implemented: // Implemented:
// Not part of the IndexCursor spec. // Not part of the IndexCursor spec.
void seek(const BSONObj& query, const vector<GeoQuery>& regions); void seek(const BSONObj& query, const vector<GeoQuery>& regions);
bool isEOF() const; bool isEOF() const;
BSONObj getKey() const; BSONObj getKey() const;
DiskLoc getValue() const; DiskLoc getValue() const;
void next(); void next();
virtual string toString(); virtual string toString();
virtual Status savePosition(); virtual Status savePosition();
virtual Status restorePosition(); virtual Status restorePosition();
virtual void aboutToDeleteBucket(const DiskLoc& bucket);
private: private:
IndexDescriptor* _descriptor; IndexDescriptor* _descriptor;
// The query with the geo stuff taken out. We use this with a matc her. // The query with the geo stuff taken out. We use this with a matc her.
BSONObj _filteredQuery; BSONObj _filteredQuery;
// What geo regions are we looking for? // What geo regions are we looking for?
vector<GeoQuery> _fields; vector<GeoQuery> _fields;
// How were the keys created? We need this to search for the right stuff. // How were the keys created? We need this to search for the right stuff.
 End of changes. 4 change blocks. 
6 lines changed or deleted 1 lines changed or added


 s2common.h   s2common.h 
skipping to change at line 30 skipping to change at line 30
#include "third_party/s2/s2regioncoverer.h" #include "third_party/s2/s2regioncoverer.h"
#include "third_party/s2/s2cell.h" #include "third_party/s2/s2cell.h"
#include "third_party/s2/s2polyline.h" #include "third_party/s2/s2polyline.h"
#include "third_party/s2/s2polygon.h" #include "third_party/s2/s2polygon.h"
#include "third_party/s2/s2regioncoverer.h" #include "third_party/s2/s2regioncoverer.h"
#pragma once #pragma once
namespace mongo { namespace mongo {
struct S2IndexingParams {
static const double kRadiusOfEarthInMeters;
// Since we take the cartesian product when we generate keys for an
insert,
// we need a cap.
size_t maxKeysPerInsert;
// This is really an advisory parameter that we pass to the cover g
enerator. The
// finest/coarsest index level determine the required # of cells.
int maxCellsInCovering;
// What's the finest grained level that we'll index? When we query
for a point
// we start at that -- we index nothing finer than this.
int finestIndexedLevel;
// And, what's the coarsest? When we search in larger coverings we
know we
// can stop here -- we index nothing coarser than this.
int coarsestIndexedLevel;
double radius;
string toString() const {
stringstream ss;
ss << "maxKeysPerInsert: " << maxKeysPerInsert << endl;
ss << "maxCellsInCovering: " << maxCellsInCovering << endl;
ss << "finestIndexedLevel: " << finestIndexedLevel << endl;
ss << "coarsestIndexedLevel: " << coarsestIndexedLevel << endl;
return ss.str();
}
void configureCoverer(S2RegionCoverer *coverer) const {
coverer->set_min_level(coarsestIndexedLevel);
coverer->set_max_level(finestIndexedLevel);
// This is advisory; the two above are strict.
coverer->set_max_cells(maxCellsInCovering);
}
};
class S2SearchUtil { class S2SearchUtil {
public: public:
// Given a coverer, region, and field name, generate a BSONObj that we can pass to a // Given a coverer, region, and field name, generate a BSONObj that we can pass to a
// FieldRangeSet so that we only examine the keys that the provided region may intersect. // FieldRangeSet so that we only examine the keys that the provided region may intersect.
static BSONObj coverAsBSON(const vector<S2CellId> &cover, const str ing& field, static BSONObj coverAsBSON(const vector<S2CellId> &cover, const str ing& field,
const int coarsestIndexedLevel); const int coarsestIndexedLevel);
static void setCoverLimitsBasedOnArea(double area, S2RegionCoverer *coverer, int coarsestIndexedLevel); static void setCoverLimitsBasedOnArea(double area, S2RegionCoverer *coverer, int coarsestIndexedLevel);
static bool getKeysForObject(const BSONObj& obj, const S2IndexingPa
rams& params,
vector<string>* out);
static bool distanceBetween(const S2Point& us, const BSONObj& them,
const S2IndexingParams &params, double
*out);
}; };
} // namespace mongo } // namespace mongo
 End of changes. 2 change blocks. 
0 lines changed or deleted 45 lines changed or added


 s2regionunion.h   s2regionunion.h 
skipping to change at line 26 skipping to change at line 26
class S2LatLngRect; class S2LatLngRect;
// An S2RegionUnion represents a union of possibly overlapping regions. // An S2RegionUnion represents a union of possibly overlapping regions.
// It is convenient for computing a covering of a set of regions. // It is convenient for computing a covering of a set of regions.
class S2RegionUnion : public S2Region { class S2RegionUnion : public S2Region {
public: public:
// Create an empty region. Can be made non-empty by calling Init() or Ad d(). // Create an empty region. Can be made non-empty by calling Init() or Ad d().
S2RegionUnion(); S2RegionUnion();
// Create a region representing the union of the given regions. // Create a region representing the union of the given regions.
// Takes ownership of all regions and clears the given vector. // DOES NOT take ownership of all regions.
// clears the given vector.
S2RegionUnion(vector<S2Region*>* regions); S2RegionUnion(vector<S2Region*>* regions);
virtual ~S2RegionUnion(); virtual ~S2RegionUnion();
// Initialize region by taking ownership of the given regions. // Initialize region by taking ownership of the given regions.
void Init(vector<S2Region*>* regions); void Init(vector<S2Region*>* regions);
// Release ownership of the regions of this union, and appends them to // Release ownership of the regions of this union, and appends them to
// "regions" if non-NULL. Resets the region to be empty. // "regions" if non-NULL. Resets the region to be empty.
void Release(vector<S2Region*>* regions); void Release(vector<S2Region*>* regions);
 End of changes. 1 change blocks. 
1 lines changed or deleted 2 lines changed or added


 sasl_client_authenticate.h   sasl_client_authenticate.h 
skipping to change at line 43 skipping to change at line 43
* ilk to make this functionality available. * ilk to make this functionality available.
* *
* The "saslParameters" BSONObj should be initialized with zero or more of the * The "saslParameters" BSONObj should be initialized with zero or more of the
* fields below. Which fields are required depends on the mechanism. Consult the * fields below. Which fields are required depends on the mechanism. Consult the
* relevant IETF standards. * relevant IETF standards.
* *
* "mechanism": The string name of the sasl mechanism to use. Mand atory. * "mechanism": The string name of the sasl mechanism to use. Mand atory.
* "autoAuthorize": Truthy values tell the server to automatically acquire privileges on * "autoAuthorize": Truthy values tell the server to automatically acquire privileges on
* all resources after successful authentication, which is the default. Falsey values * all resources after successful authentication, which is the default. Falsey values
* instruct the server to await separate privilege-acquisition commands. * instruct the server to await separate privilege-acquisition commands.
* "user": The string name of the principal to authenticate. * "user": The string name of the user to authenticate.
* "userSource": The database target of the auth command, which ide ntifies the location * "userSource": The database target of the auth command, which ide ntifies the location
* of the credential information for the principal. May be "$e xternal" if credential * of the credential information for the user. May be "$extern al" if credential
* information is stored outside of the mongo cluster. * information is stored outside of the mongo cluster.
* "pwd": The password. * "pwd": The password.
* "serviceName": The GSSAPI service name to use. Defaults to "mon godb". * "serviceName": The GSSAPI service name to use. Defaults to "mon godb".
* "serviceHostname": The GSSAPI hostname to use. Defaults to the name of the remote host. * "serviceHostname": The GSSAPI hostname to use. Defaults to the name of the remote host.
* *
* Other fields in saslParameters are silently ignored. * Other fields in saslParameters are silently ignored.
* *
* Returns an OK status on success, and ErrorCodes::AuthenticationFaile d if authentication is * Returns an OK status on success, and ErrorCodes::AuthenticationFaile d if authentication is
* rejected. Other failures, all of which are tantamount to authentica tion failure, may also be * rejected. Other failures, all of which are tantamount to authentica tion failure, may also be
* returned. * returned.
skipping to change at line 80 skipping to change at line 80
// Constants // Constants
/// String name of the saslStart command. /// String name of the saslStart command.
extern const char* const saslStartCommandName; extern const char* const saslStartCommandName;
/// String name of the saslContinue command. /// String name of the saslContinue command.
extern const char* const saslContinueCommandName; extern const char* const saslContinueCommandName;
/// Name of the saslStart parameter indicating that the server should a utomatically grant the /// Name of the saslStart parameter indicating that the server should a utomatically grant the
/// connection all privileges associated with the principal after succe ssful authentication. /// connection all privileges associated with the user after successful authentication.
extern const char* const saslCommandAutoAuthorizeFieldName; extern const char* const saslCommandAutoAuthorizeFieldName;
/// Name of the field contain the status code in responses from the ser ver. /// Name of the field contain the status code in responses from the ser ver.
extern const char* const saslCommandCodeFieldName; extern const char* const saslCommandCodeFieldName;
/// Name of the field containing the conversation identifier in server respones and saslContinue /// Name of the field containing the conversation identifier in server respones and saslContinue
/// commands. /// commands.
extern const char* const saslCommandConversationIdFieldName; extern const char* const saslCommandConversationIdFieldName;
/// Name of the field that indicates whether or not the server believes authentication has /// Name of the field that indicates whether or not the server believes authentication has
skipping to change at line 110 skipping to change at line 110
/// In the event that saslStart supplies an unsupported mechanism, the server responds with a /// In the event that saslStart supplies an unsupported mechanism, the server responds with a
/// field by this name, with a list of supported mechanisms. /// field by this name, with a list of supported mechanisms.
extern const char* const saslCommandMechanismListFieldName; extern const char* const saslCommandMechanismListFieldName;
/// Field containing password information for saslClientAuthenticate(). /// Field containing password information for saslClientAuthenticate().
extern const char* const saslCommandPasswordFieldName; extern const char* const saslCommandPasswordFieldName;
/// Field containing sasl payloads passed to and from the server. /// Field containing sasl payloads passed to and from the server.
extern const char* const saslCommandPayloadFieldName; extern const char* const saslCommandPayloadFieldName;
/// Field containing the string identifier of the principal to authenti cate in /// Field containing the string identifier of the user to authenticate in
/// saslClientAuthenticate(). /// saslClientAuthenticate().
extern const char* const saslCommandPrincipalFieldName; extern const char* const saslCommandUserFieldName;
/// Field containing the string identifier of the database containing c redential information, /// Field containing the string identifier of the database containing c redential information,
/// or "$external" if the credential information is stored outside of t he mongo cluster. /// or "$external" if the credential information is stored outside of t he mongo cluster.
extern const char* const saslCommandPrincipalSourceFieldName; extern const char* const saslCommandUserSourceFieldName;
/// Field overriding the FQDN of the hostname hosting the mongodb srevi ce in /// Field overriding the FQDN of the hostname hosting the mongodb srevi ce in
/// saslClientAuthenticate(). /// saslClientAuthenticate().
extern const char* const saslCommandServiceHostnameFieldName; extern const char* const saslCommandServiceHostnameFieldName;
/// Field overriding the name of the mongodb service saslClientAuthenti cate(). /// Field overriding the name of the mongodb service saslClientAuthenti cate().
extern const char* const saslCommandServiceNameFieldName; extern const char* const saslCommandServiceNameFieldName;
/// Default database against which sasl authentication commands should run. /// Default database against which sasl authentication commands should run.
extern const char* const saslDefaultDBName; extern const char* const saslDefaultDBName;
 End of changes. 6 change blocks. 
6 lines changed or deleted 6 lines changed or added


 security_key.h   security_key.h 
skipping to change at line 21 skipping to change at line 21
* 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
#include <string> #include <string>
#include "mongo/client/dbclientinterface.h"
namespace mongo { namespace mongo {
/**
* @return true if internal authentication parameters has been set up
*/
extern bool isInternalAuthSet();
/**
* This method initializes the internalSecurity object with authenticat
ion
* credentials to be used by authenticateInternalUser. This method shou
ld
* only be called once when setting up authentication method for the sy
stem.
*/
extern bool setInternalUserAuthParams(BSONObj authParams);
/**
* This method authenticates to another cluster member using appropriat
e
* authentication data
* @return true if the authentication was succesful
*/
extern bool authenticateInternalUser(DBClientWithCommands* conn);
/** /**
* This method checks the validity of filename as a security key, hashe s its * This method checks the validity of filename as a security key, hashe s its
* contents, and stores it in the internalSecurity variable. Prints an * contents, and stores it in the internalSecurity variable. Prints an
* error message to the logs if there's an error. * error message to the logs if there's an error.
* @param filename the file containing the key * @param filename the file containing the key
* @return if the key was successfully stored * @return if the key was successfully stored
*/ */
bool setUpSecurityKey(const std::string& filename); bool setUpSecurityKey(const std::string& filename);
 End of changes. 2 change blocks. 
0 lines changed or deleted 24 lines changed or added


 shapes.h   shapes.h 
skipping to change at line 19 skipping to change at line 19
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/pch.h" #include <string>
#include <vector>
#include "mongo/base/owned_pointer_vector.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "third_party/s2/s2.h"
#include "third_party/s2/s2cap.h"
#include "third_party/s2/s2cell.h"
#include "third_party/s2/s2latlng.h"
#include "third_party/s2/s2polygon.h"
#include "third_party/s2/s2polyline.h"
namespace mongo { namespace mongo {
struct Point; struct Point;
double distance(const Point& p1, const Point &p2); double distance(const Point& p1, const Point &p2);
bool distanceWithin(const Point &p1, const Point &p2, double radius); bool distanceWithin(const Point &p1, const Point &p2, double radius);
void checkEarthBounds(const Point &p); void checkEarthBounds(const Point &p);
double spheredist_rad(const Point& p1, const Point& p2); double spheredist_rad(const Point& p1, const Point& p2);
double spheredist_deg(const Point& p1, const Point& p2); double spheredist_deg(const Point& p1, const Point& p2);
struct Point { struct Point {
Point(); Point();
Point(double x, double y); Point(double x, double y);
skipping to change at line 106 skipping to change at line 116
*/ */
Point centroid(); Point centroid();
Box bounds(); Box bounds();
private: private:
bool _centroidCalculated; bool _centroidCalculated;
Point _centroid; Point _centroid;
Box _bounds; Box _bounds;
bool _boundsCalculated; bool _boundsCalculated;
vector<Point> _points; vector<Point> _points;
}; };
// Clearly this isn't right but currently it's sufficient.
enum CRS {
FLAT,
SPHERE
};
struct PointWithCRS {
S2Point point;
S2Cell cell;
Point oldPoint;
CRS crs;
};
struct LineWithCRS {
S2Polyline line;
CRS crs;
};
struct CapWithCRS {
S2Cap cap;
Circle circle;
CRS crs;
};
struct BoxWithCRS {
Box box;
CRS crs;
};
struct PolygonWithCRS {
S2Polygon polygon;
Polygon oldPolygon;
CRS crs;
};
struct MultiPointWithCRS {
vector<S2Point> points;
vector<S2Cell> cells;
CRS crs;
};
struct MultiLineWithCRS {
OwnedPointerVector<S2Polyline> lines;
CRS crs;
};
struct MultiPolygonWithCRS {
OwnedPointerVector<S2Polygon> polygons;
CRS crs;
};
struct GeometryCollection {
vector<PointWithCRS> points;
// The amount of indirection here is painful but we can't operator=
scoped_ptr or
// OwnedPointerVector.
OwnedPointerVector<LineWithCRS> lines;
OwnedPointerVector<PolygonWithCRS> polygons;
OwnedPointerVector<MultiPointWithCRS> multiPoints;
OwnedPointerVector<MultiLineWithCRS> multiLines;
OwnedPointerVector<MultiPolygonWithCRS> multiPolygons;
bool supportsContains() {
// Only polygons (and multiPolygons) support containment.
return (polygons.vector().size() > 0 || multiPolygons.vector().
size() > 0);
}
};
} // namespace mongo } // namespace mongo
 End of changes. 4 change blocks. 
1 lines changed or deleted 82 lines changed or added


 shell_utils_launcher.h   shell_utils_launcher.h 
skipping to change at line 29 skipping to change at line 29
#include <boost/filesystem/convenience.hpp> #include <boost/filesystem/convenience.hpp>
#include <boost/thread/recursive_mutex.hpp> #include <boost/thread/recursive_mutex.hpp>
#include <map> #include <map>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <utility> #include <utility>
#include "mongo/bson/bsonobj.h" #include "mongo/bson/bsonobj.h"
#include "mongo/platform/process_id.h"
#ifdef _WIN32
typedef int pid_t;
#endif
namespace mongo { namespace mongo {
class Scope; class Scope;
namespace shell_utils { namespace shell_utils {
// Scoped management of mongo program instances. Simple implementa tion: // Scoped management of mongo program instances. Simple implementa tion:
// destructor kills all mongod instances created by the shell. // destructor kills all mongod instances created by the shell.
struct MongoProgramScope { struct MongoProgramScope {
skipping to change at line 54 skipping to change at line 51
~MongoProgramScope(); ~MongoProgramScope();
}; };
void KillMongoProgramInstances(); void KillMongoProgramInstances();
void goingAwaySoon(); void goingAwaySoon();
void installShellUtilsLauncher( Scope& scope ); void installShellUtilsLauncher( Scope& scope );
/** Record log lines from concurrent programs. All public members are thread safe. */ /** Record log lines from concurrent programs. All public members are thread safe. */
class ProgramOutputMultiplexer { class ProgramOutputMultiplexer {
public: public:
void appendLine( int port, int pid, const char *line ); void appendLine( int port, ProcessId pid, const char *line );
/** @return up to 100000 characters of the most recent log outp ut. */ /** @return up to 100000 characters of the most recent log outp ut. */
std::string str() const; std::string str() const;
void clear(); void clear();
private: private:
std::stringstream _buffer; std::stringstream _buffer;
}; };
/** /**
* A registry of spawned programs that are identified by a bound po rt or else a system pid. * A registry of spawned programs that are identified by a bound po rt or else a system pid.
* All public member functions are thread safe. * All public member functions are thread safe.
* *
* TODO: Clean this up to make the semantics more consistent betwee n pids and ports * TODO: Clean this up to make the semantics more consistent betwee n pids and ports
*/ */
class ProgramRegistry { class ProgramRegistry {
public: public:
bool isPortRegistered( int port ) const; bool isPortRegistered( int port ) const;
/** @return pid for a registered port. */ /** @return pid for a registered port. */
pid_t pidForPort( int port ) const; ProcessId pidForPort( int port ) const;
/** @return port (-1 if doesn't exist) for a registered pid. */ /** @return port (-1 if doesn't exist) for a registered pid. */
int portForPid( int port ) const; int portForPid( ProcessId pid ) const;
/** Register an unregistered port. */ /** Register an unregistered port. */
void registerPort( int port, pid_t pid, int output ); void registerPort( int port, ProcessId pid, int output );
void deletePort( int port ); void deletePort( int port );
void getRegisteredPorts( std::vector<int> &ports ); void getRegisteredPorts( std::vector<int> &ports );
bool isPidRegistered( pid_t pid ) const; bool isPidRegistered( ProcessId pid ) const;
/** Register an unregistered pid. */ /** Register an unregistered pid. */
void registerPid( pid_t pid, int output ); void registerPid( ProcessId pid, int output );
void deletePid( pid_t pid ); void deletePid( ProcessId pid );
void getRegisteredPids( vector<pid_t> &pids ); void getRegisteredPids( vector<ProcessId> &pids );
private: private:
std::map<int,std::pair<pid_t,int> > _ports; std::map<int,std::pair<ProcessId,int> > _ports;
std::map<pid_t,int> _pids; std::map<ProcessId,int> _pids;
mutable boost::recursive_mutex _mutex; mutable boost::recursive_mutex _mutex;
#ifdef _WIN32 #ifdef _WIN32
public: public:
std::map<pid_t,HANDLE> _handles; std::map<ProcessId,HANDLE> _handles;
#endif #endif
}; };
/** Helper class for launching a program and logging its output. */ /** Helper class for launching a program and logging its output. */
class ProgramRunner { class ProgramRunner {
public: public:
/** @param args The program's arguments, including the program name. */ /** @param args The program's arguments, including the program name. */
ProgramRunner( const BSONObj &args ); ProgramRunner( const BSONObj &args );
/** Launch the program. */ /** Launch the program. */
void start(); void start();
/** Continuously read the program's output, generally from a sp ecial purpose thread. */ /** Continuously read the program's output, generally from a sp ecial purpose thread. */
void operator()(); void operator()();
pid_t pid() const { return _pid; } ProcessId pid() const { return _pid; }
int port() const { return _port; } int port() const { return _port; }
private: private:
boost::filesystem::path findProgram( const string &prog ); boost::filesystem::path findProgram( const string &prog );
void launchProcess( int child_stdout ); void launchProcess( int child_stdout );
std::vector<std::string> _argv; std::vector<std::string> _argv;
int _port; int _port;
int _pipe; int _pipe;
pid_t _pid; ProcessId _pid;
}; };
} }
} }
 End of changes. 11 change blocks. 
17 lines changed or deleted 14 lines changed or added


 sock.h   sock.h 
skipping to change at line 42 skipping to change at line 42
#ifdef __openbsd__ #ifdef __openbsd__
# include <sys/uio.h> # include <sys/uio.h>
#endif #endif
#endif // not _WIN32 #endif // not _WIN32
#ifdef MONGO_SSL #ifdef MONGO_SSL
#include <openssl/ssl.h> #include <openssl/ssl.h>
#endif #endif
#include "mongo/logger/log_severity.h"
#include "mongo/platform/compiler.h" #include "mongo/platform/compiler.h"
namespace mongo { namespace mongo {
class SSLManagerInterface; class SSLManagerInterface;
const int SOCK_FAMILY_UNKNOWN_ERROR=13078; const int SOCK_FAMILY_UNKNOWN_ERROR=13078;
void disableNagle(int sock); void disableNagle(int sock);
skipping to change at line 90 skipping to change at line 91
/** /**
* wrapped around os representation of network address * wrapped around os representation of network address
*/ */
struct SockAddr { struct SockAddr {
SockAddr() { SockAddr() {
addressSize = sizeof(sa); addressSize = sizeof(sa);
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));
sa.ss_family = AF_UNSPEC; sa.ss_family = AF_UNSPEC;
} }
SockAddr(int sourcePort); /* listener side */ explicit SockAddr(int sourcePort); /* listener side */
SockAddr(const char *ip, int port); /* EndPoint (remote) side, or i f you want to specify which interface locally */ SockAddr(const char *ip, int port); /* EndPoint (remote) side, or i f you want to specify which interface locally */
template <typename T> T& as() { return *(T*)(&sa); } template <typename T> T& as() { return *(T*)(&sa); }
template <typename T> const T& as() const { return *(const T*)(&sa) ; } template <typename T> const T& as() const { return *(const T*)(&sa) ; }
string toString(bool includePort=true) const; string toString(bool includePort=true) const;
/** /**
* @return one of AF_INET, AF_INET6, or AF_UNIX * @return one of AF_INET, AF_INET6, or AF_UNIX
*/ */
skipping to change at line 190 skipping to change at line 191
static const int errorPollIntervalSecs; static const int errorPollIntervalSecs;
Socket(int sock, const SockAddr& farEnd); Socket(int sock, const SockAddr& farEnd);
/** In some cases the timeout will actually be 2x this value - eg w e do a partial send, /** In some cases the timeout will actually be 2x this value - eg w e do a partial send,
then the timeout fires, then we try to send again, then the tim eout fires again with then the timeout fires, then we try to send again, then the tim eout fires again with
no data sent, then we detect that the other side is down. no data sent, then we detect that the other side is down.
Generally you don't want a timeout, you should be very prepared for errors if you set one. Generally you don't want a timeout, you should be very prepared for errors if you set one.
*/ */
Socket(double so_timeout = 0, int logLevel = 0 ); Socket(double so_timeout = 0, logger::LogSeverity logLevel = logger ::LogSeverity::Log() );
~Socket(); ~Socket();
bool connect(SockAddr& farEnd); bool connect(SockAddr& farEnd);
void close(); void close();
void send( const char * data , int len, const char *context ); void send( const char * data , int len, const char *context );
void send( const vector< pair< char *, int > > &data, const char *c ontext ); void send( const vector< pair< char *, int > > &data, const char *c ontext );
// recv len or throw SocketException // recv len or throw SocketException
void recv( char * data , int len ); void recv( char * data , int len );
int unsafe_recv( char *buf, int max ); int unsafe_recv( char *buf, int max );
int getLogLevel() const { return _logLevel; } logger::LogSeverity getLogLevel() const { return _logLevel; }
void setLogLevel( int ll ) { _logLevel = ll; } void setLogLevel( logger::LogSeverity ll ) { _logLevel = ll; }
SockAddr remoteAddr() const { return _remote; } SockAddr remoteAddr() const { return _remote; }
string remoteString() const { return _remote.toString(); } string remoteString() const { return _remote.toString(); }
unsigned remotePort() const { return _remote.getPort(); } unsigned remotePort() const { return _remote.getPort(); }
void clearCounters() { _bytesIn = 0; _bytesOut = 0; } void clearCounters() { _bytesIn = 0; _bytesOut = 0; }
long long getBytesIn() const { return _bytesIn; } long long getBytesIn() const { return _bytesIn; }
long long getBytesOut() const { return _bytesOut; } long long getBytesOut() const { return _bytesOut; }
void setTimeout( double secs ); void setTimeout( double secs );
skipping to change at line 228 skipping to change at line 229
#ifdef MONGO_SSL #ifdef MONGO_SSL
/** secures inline */ /** secures inline */
void secure( SSLManagerInterface* ssl ); void secure( SSLManagerInterface* ssl );
void secureAccepted( SSLManagerInterface* ssl ); void secureAccepted( SSLManagerInterface* ssl );
#endif #endif
/** /**
* This function calls SSL_accept() if SSL-encrypted sockets * This function calls SSL_accept() if SSL-encrypted sockets
* are desired. SSL_accept() waits until the remote host calls * are desired. SSL_accept() waits until the remote host calls
* SSL_connect(). * SSL_connect(). The return value is the subject name of any
* client certificate provided during the handshake.
* This function may throw SocketException. * This function may throw SocketException.
*/ */
void doSSLHandshake(); std::string doSSLHandshake();
/** /**
* @return the time when the socket was opened. * @return the time when the socket was opened.
*/ */
uint64_t getSockCreationMicroSec() const { uint64_t getSockCreationMicroSec() const {
return _fdCreationMicroSec; return _fdCreationMicroSec;
} }
private: private:
void _init(); void _init();
skipping to change at line 268 skipping to change at line 270
double _timeout; double _timeout;
long long _bytesIn; long long _bytesIn;
long long _bytesOut; long long _bytesOut;
time_t _lastValidityCheckAtSecs; time_t _lastValidityCheckAtSecs;
#ifdef MONGO_SSL #ifdef MONGO_SSL
SSL* _ssl; SSL* _ssl;
SSLManagerInterface* _sslManager; SSLManagerInterface* _sslManager;
#endif #endif
int _logLevel; // passed to log() when logging errors logger::LogSeverity _logLevel; // passed to log() when logging erro rs
}; };
} // namespace mongo } // namespace mongo
 End of changes. 7 change blocks. 
7 lines changed or deleted 9 lines changed or added


 ssl_manager.h   ssl_manager.h 
skipping to change at line 27 skipping to change at line 27
#pragma once #pragma once
#include <string> #include <string>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
namespace mongo { namespace mongo {
class SSLManagerInterface { class SSLManagerInterface {
public: public:
virtual ~SSLManagerInterface(); virtual ~SSLManagerInterface();
/** /**
* Initiates a TLS connection. * Initiates a TLS connection.
* Throws SocketException on failure. * Throws SocketException on failure.
* @return a pointer to an SSL context; caller must SSL_free it. * @return a pointer to an SSL context; caller must SSL_free it.
*/ */
virtual SSL* connect(int fd) = 0; virtual SSL* connect(int fd) = 0;
skipping to change at line 49 skipping to change at line 48
/** /**
* Waits for the other side to initiate a TLS connection. * Waits for the other side to initiate a TLS connection.
* Throws SocketException on failure. * Throws SocketException on failure.
* @return a pointer to an SSL context; caller must SSL_free it. * @return a pointer to an SSL context; caller must SSL_free it.
*/ */
virtual SSL* accept(int fd) = 0; virtual SSL* accept(int fd) = 0;
/** /**
* Fetches a peer certificate and validates it if it exists * Fetches a peer certificate and validates it if it exists
* Throws SocketException on failure * Throws SocketException on failure
* @return a std::string containing the certificate's subject name.
*/ */
virtual void validatePeerCertificate(const SSL* ssl) = 0; virtual std::string validatePeerCertificate(const SSL* ssl) = 0;
/** /**
* Cleans up SSL thread local memory; use at thread exit * Cleans up SSL thread local memory; use at thread exit
* to avoid memory leaks * to avoid memory leaks
*/ */
virtual void cleanupThreadLocals() = 0; virtual void cleanupThreadLocals() = 0;
/** /**
* Gets the subject name of our own server certificate
* @return the subject name.
*/
virtual std::string getServerSubjectName() = 0;
/**
* Gets the subject name of our own client certificate
* used for cluster authentiation
* @return the subject name.
*/
virtual std::string getClientSubjectName() = 0;
/**
* ssl.h shims * ssl.h shims
*/ */
virtual int SSL_read(SSL* ssl, void* buf, int num) = 0; virtual int SSL_read(SSL* ssl, void* buf, int num) = 0;
virtual int SSL_write(SSL* ssl, const void* buf, int num) = 0; virtual int SSL_write(SSL* ssl, const void* buf, int num) = 0;
virtual unsigned long ERR_get_error() = 0; virtual unsigned long ERR_get_error() = 0;
virtual char* ERR_error_string(unsigned long e, char* buf) = 0; virtual char* ERR_error_string(unsigned long e, char* buf) = 0;
virtual int SSL_get_error(const SSL* ssl, int ret) = 0; virtual int SSL_get_error(const SSL* ssl, int ret) = 0;
virtual int SSL_shutdown(SSL* ssl) = 0; virtual int SSL_shutdown(SSL* ssl) = 0;
virtual void SSL_free(SSL* ssl) = 0; virtual void SSL_free(SSL* ssl) = 0;
}; };
// Access SSL functions through this instance. // Access SSL functions through this instance.
SSLManagerInterface* getSSLManager(); SSLManagerInterface* getSSLManager();
extern bool isSSLServer;
} }
#endif #endif
 End of changes. 5 change blocks. 
2 lines changed or deleted 16 lines changed or added


 stacktrace.h   stacktrace.h 
// Copyright 2009. 10gen, Inc. /* Copyright 2009 10gen Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli
ed.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** /**
* Tools for working with in-process stack traces. * Tools for working with in-process stack traces.
*/ */
#pragma once #pragma once
#include <iostream> #include <iostream>
#include "mongo/platform/basic.h" #include "mongo/util/log.h"
namespace mongo { namespace mongo {
// Print stack trace information to "os", default to std::cout. // Print stack trace information to "os", default to the log stream.
void printStackTrace(std::ostream &os=std::cout); void printStackTrace(std::ostream &os=log().stream());
#if defined(_WIN32) #if defined(_WIN32)
// Print stack trace (using a specified stack context) to "os", default // Print stack trace (using a specified stack context) to "os", default
to std::cout. to the log stream.
void printWindowsStackTrace(CONTEXT &context, std::ostream &os=std::cou void printWindowsStackTrace(CONTEXT &context, std::ostream &os=log().st
t); ream());
// Print error message from C runtime followed by stack trace // Print error message from C runtime followed by stack trace
int crtDebugCallback(int, char* originalMessage, int*); int crtDebugCallback(int, char* originalMessage, int*);
#endif #endif
} // namespace mongo } // namespace mongo
 End of changes. 4 change blocks. 
8 lines changed or deleted 22 lines changed or added


 status.h   status.h 
skipping to change at line 52 skipping to change at line 52
* return Status::OK(); * return Status::OK();
* } * }
* *
* TODO: expand base/error_codes.h to capture common errors in current code * TODO: expand base/error_codes.h to capture common errors in current code
* TODO: generate base/error_codes.h out of a description file * TODO: generate base/error_codes.h out of a description file
* TODO: check 'location' duplicates against assert numbers * TODO: check 'location' duplicates against assert numbers
*/ */
class Status { class Status {
public: public:
// Short-hand for returning an OK status. // Short-hand for returning an OK status.
static Status OK() { return Status(getOKInfo()); } static inline Status OK();
/** /**
* Builds an error status given the error code, a textual descripti on of what * Builds an error status given the error code, a textual descripti on of what
* caused the error, and a unique position in the where the error o ccurred * caused the error, and a unique position in the where the error o ccurred
* (similar to an assert number) * (similar to an assert number)
*/ */
Status(ErrorCodes::Error code, const std::string& reason, int locat ion = 0); Status(ErrorCodes::Error code, const std::string& reason, int locat ion = 0);
Status(ErrorCodes::Error code, const char* reason, int location = 0 ); Status(ErrorCodes::Error code, const char* reason, int location = 0 );
Status(const Status& other);
Status& operator=(const Status& other); inline Status(const Status& other);
~Status(); inline Status& operator=(const Status& other);
inline ~Status();
/** /**
* Returns true if 'other's error code and location are equal/diffe rent to this * Returns true if 'other's error code and location are equal/diffe rent to this
* instance's. Otherwise returns false. * instance's. Otherwise returns false.
*/ */
bool compare(const Status& other) const; bool compare(const Status& other) const;
bool operator==(const Status& other) const; bool operator==(const Status& other) const;
bool operator!=(const Status& other) const; bool operator!=(const Status& other) const;
/** /**
skipping to change at line 85 skipping to change at line 87
* Otherwise returns false. * Otherwise returns false.
*/ */
bool compareCode(const ErrorCodes::Error other) const; bool compareCode(const ErrorCodes::Error other) const;
bool operator==(const ErrorCodes::Error other) const; bool operator==(const ErrorCodes::Error other) const;
bool operator!=(const ErrorCodes::Error other) const; bool operator!=(const ErrorCodes::Error other) const;
// //
// accessors // accessors
// //
bool isOK() const { return code() == ErrorCodes::OK; } inline bool isOK() const;
ErrorCodes::Error code() const { return _error->code; }
const char* codeString() const { return ErrorCodes::errorString(_er inline ErrorCodes::Error code() const;
ror->code); }
const std::string& reason() const { return _error->reason; } inline const char* codeString() const;
int location() const { return _error->location; }
inline std::string reason() const;
inline int location() const;
std::string toString() const; std::string toString() const;
// //
// Below interface used for testing code only. // Below interface used for testing code only.
// //
int refCount() const { return _error->refs.load(); } inline AtomicUInt32::WordType refCount() const;
private: private:
struct ErrorInfo { inline Status();
AtomicUInt32 refs; // reference counter
ErrorCodes::Error code; // error code
std::string reason; // description of error cause
int location; // unique location of the triggering l
ine in the code
ErrorInfo(ErrorCodes::Error aCode, const std::string& aReason, struct ErrorInfo {
int aLocation); AtomicUInt32 refs; // reference counter
}; const ErrorCodes::Error code; // error code
const std::string reason; // description of error cause
const int location; // unique location of the trigge
ring line in the code
static ErrorInfo *getOKInfo(); static ErrorInfo* create(ErrorCodes::Error code,
const StringData& reason, int location
);
explicit Status(ErrorInfo *info); ErrorInfo(ErrorCodes::Error code, const StringData& reason, int
location);
};
ErrorInfo* _error; ErrorInfo* _error;
/** /**
* Increment/Decrement the reference counter inside an ErrorInfo * Increment/Decrement the reference counter inside an ErrorInfo
* *
* @param error ErrorInfo to be incremented * @param error ErrorInfo to be incremented
*/ */
static void ref(ErrorInfo* error); static inline void ref(ErrorInfo* error);
static void unref(ErrorInfo* error); static inline void unref(ErrorInfo* error);
}; };
static inline bool operator==(const ErrorCodes::Error lhs, const Status inline bool operator==(const ErrorCodes::Error lhs, const Status& rhs);
& rhs) {
return rhs == lhs; inline bool operator!=(const ErrorCodes::Error lhs, const Status& rhs);
}
static inline bool operator!=(const ErrorCodes::Error lhs, const Status
& rhs) {
return rhs != lhs;
}
// //
// Convenience method for unittest code. Please use accessors otherwise . // Convenience method for unittest code. Please use accessors otherwise .
// //
std::ostream& operator<<(std::ostream& os, const Status& status); std::ostream& operator<<(std::ostream& os, const Status& status);
std::ostream& operator<<(std::ostream& os, ErrorCodes::Error); std::ostream& operator<<(std::ostream& os, ErrorCodes::Error);
} // namespace mongo } // namespace mongo
#include "mongo/base/status-inl.h"
 End of changes. 11 change blocks. 
33 lines changed or deleted 34 lines changed or added


 status_with.h   status_with.h 
skipping to change at line 18 skipping to change at line 18
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once
#include "mongo/base/status.h" #include "mongo/base/status.h"
namespace mongo { namespace mongo {
/* /*
* StatusWith is used to return an error or a value * StatusWith is used to return an error or a value
* this is designed to make exception code free cleaner by not needing as many out paramters * this is designed to make exception code free cleaner by not needing as many out paramters
* example: * example:
StatusWith<int> fib( int n ) { StatusWith<int> fib( int n ) {
if ( n < 0 ) return StatusWith<int>( ErrorCodes::BadValue, "paramte r to fib has to be >= 0" ); if ( n < 0 ) return StatusWith<int>( ErrorCodes::BadValue, "paramte r to fib has to be >= 0" );
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 thread_pool.h   thread_pool.h 
skipping to change at line 26 skipping to change at line 26
*/ */
#pragma once #pragma once
#include <list> #include <list>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
#include "mongo/util/concurrency/mutex.h"
namespace mongo { namespace mongo {
namespace threadpool { namespace threadpool {
class Worker; class Worker;
typedef boost::function<void(void)> Task; //nullary function or fun ctor typedef boost::function<void(void)> Task; //nullary function or fun ctor
// exported to the mongo namespace // exported to the mongo namespace
class ThreadPool : boost::noncopyable { class ThreadPool : boost::noncopyable {
public: public:
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 time_support.h   time_support.h 
skipping to change at line 23 skipping to change at line 23
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <ctime> #include <ctime>
#include <string> #include <string>
#include <boost/thread/xtime.hpp> #include <boost/thread/xtime.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "mongo/bson/util/misc.h" // Date_t #include "mongo/bson/util/misc.h" // Date_t
namespace mongo { namespace mongo {
void time_t_to_Struct(time_t t, struct tm * buf , bool local = false ); void time_t_to_Struct(time_t t, struct tm * buf , bool local = false );
/** /**
* Gets the current time string (in fixed width) in UTC. Sample format: * Gets the current time string (in fixed width) in UTC. Sample format:
* *
* Wed Oct 31 13:34:47.996 * Wed Oct 31 13:34:47.996
* *
* @param timeStr pointer to the buffer to set the string - should at l * @param timeStr pointer to the buffer to set the string - empirically
east be , 64 bytes is enough for
* 24 bytes big. * the buffer, 26 is not.
*/ */
void curTimeString(char* timeStr); void curTimeString(char* timeStr);
// uses ISO 8601 dates without trailing Z // uses ISO 8601 dates without trailing Z
// colonsOk should be false when creating filenames // colonsOk should be false when creating filenames
std::string terseCurrentTime(bool colonsOk=true); std::string terseCurrentTime(bool colonsOk=true);
std::string timeToISOString(time_t time); std::string timeToISOString(time_t time);
boost::gregorian::date currentDate(); boost::gregorian::date currentDate();
 End of changes. 2 change blocks. 
4 lines changed or deleted 3 lines changed or added


 top.h   top.h 
skipping to change at line 22 skipping to change at line 22
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>
#include "mongo/util/concurrency/mutex.h"
#include "mongo/util/string_map.h" #include "mongo/util/string_map.h"
namespace mongo { namespace mongo {
/** /**
* tracks usage by collection * tracks usage by collection
*/ */
class Top { class Top {
public: public:
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 type_collection.h   type_collection.h 
skipping to change at line 182 skipping to change at line 182
// Calling get*() methods when the member is not set and has no def ault results in undefined // Calling get*() methods when the member is not set and has no def ault results in undefined
// behavior // behavior
std::string getPrimary() const { std::string getPrimary() const {
if (_isPrimarySet) { if (_isPrimarySet) {
return _primary; return _primary;
} else { } else {
dassert(primary.hasDefault()); dassert(primary.hasDefault());
return primary.getDefault(); return primary.getDefault();
} }
} }
void setKeyPattern(BSONObj& keyPattern) { void setKeyPattern(const BSONObj& keyPattern) {
_keyPattern = keyPattern.getOwned(); _keyPattern = keyPattern.getOwned();
_isKeyPatternSet = true; _isKeyPatternSet = true;
} }
void unsetKeyPattern() { _isKeyPatternSet = false; } void unsetKeyPattern() { _isKeyPatternSet = false; }
bool isKeyPatternSet() const { bool isKeyPatternSet() const {
return _isKeyPatternSet || keyPattern.hasDefault(); return _isKeyPatternSet || keyPattern.hasDefault();
} }
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 unittest.h   unittest.h 
skipping to change at line 36 skipping to change at line 36
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include "mongo/logger/logstream_builder.h"
#include "mongo/util/assert_util.h" #include "mongo/util/assert_util.h"
#include "mongo/util/mongoutils/str.h" #include "mongo/util/mongoutils/str.h"
/** /**
* Fail unconditionally, reporting the given message. * Fail unconditionally, reporting the given message.
*/ */
#define FAIL(MESSAGE) ::mongo::unittest::TestAssertion( __FILE__ , __LINE__ ).fail( (MESSAGE) ) #define FAIL(MESSAGE) ::mongo::unittest::TestAssertion( __FILE__ , __LINE__ ).fail( (MESSAGE) )
/** /**
* Fails unless "EXPRESSION" is true. * Fails unless "EXPRESSION" is true.
skipping to change at line 172 skipping to change at line 173
#define _TEST_TYPE_NAME(CASE_NAME, TEST_NAME) \ #define _TEST_TYPE_NAME(CASE_NAME, TEST_NAME) \
UnitTest__##CASE_NAME##__##TEST_NAME UnitTest__##CASE_NAME##__##TEST_NAME
namespace mongo { namespace mongo {
namespace unittest { namespace unittest {
class Result; class Result;
/** /**
* Gets a LogstreamBuilder for logging to the unittest log domain,
which may have
* different target from the global log domain.
*/
mongo::logger::LogstreamBuilder log();
/**
* Type representing the function composing a test. * Type representing the function composing a test.
*/ */
typedef boost::function<void (void)> TestFunction; typedef boost::function<void (void)> TestFunction;
/** /**
* Container holding a test function and its name. Suites * Container holding a test function and its name. Suites
* contain lists of these. * contain lists of these.
*/ */
class TestHolder : private boost::noncopyable { class TestHolder : private boost::noncopyable {
public: public:
 End of changes. 2 change blocks. 
0 lines changed or deleted 8 lines changed or added


 unordered_fast_key_table.h   unordered_fast_key_table.h 
skipping to change at line 65 skipping to change at line 65
size_t curHash; size_t curHash;
value_type data; value_type data;
}; };
struct Area { struct Area {
Area( unsigned capacity, double maxProbeRatio ); Area( unsigned capacity, double maxProbeRatio );
Area( const Area& other ); Area( const Area& other );
int find( const K_L& key, size_t hash, int* firstEmpty, const U norderedFastKeyTable& sm ) const; int find( const K_L& key, size_t hash, int* firstEmpty, const U norderedFastKeyTable& sm ) const;
void transfer( Area* newArea, const UnorderedFastKeyTable& sm ) const; bool transfer( Area* newArea, const UnorderedFastKeyTable& sm ) const;
void swap( Area* other ) { void swap( Area* other ) {
using std::swap; using std::swap;
swap( _capacity, other->_capacity ); swap( _capacity, other->_capacity );
swap( _maxProbe, other->_maxProbe ); swap( _maxProbe, other->_maxProbe );
swap( _entries, other->_entries ); swap( _entries, other->_entries );
} }
unsigned _capacity; unsigned _capacity;
unsigned _maxProbe; unsigned _maxProbe;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 unordered_fast_key_table_internal.h   unordered_fast_key_table_internal.h 
skipping to change at line 79 skipping to change at line 79
} }
// hashes and strings are equal // hashes and strings are equal
// yay! // yay!
return pos; return pos;
} }
return -1; return -1;
} }
template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS > template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
inline void UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::Area::tr ansfer( inline bool UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::Area::tr ansfer(
Area* newArea, Area* newArea,
const UnorderedFastKeyTable& sm) const { const UnorderedFastKeyTable& sm) const {
for ( unsigned i = 0; i < _capacity; i++ ) { for ( unsigned i = 0; i < _capacity; i++ ) {
if ( ! _entries[i].used ) if ( ! _entries[i].used )
continue; continue;
int firstEmpty = -1; int firstEmpty = -1;
int loc = newArea->find( sm._convertor( _entries[i].data.first ), int loc = newArea->find( sm._convertor( _entries[i].data.first ),
_entries[i].curHash, _entries[i].curHash,
&firstEmpty, &firstEmpty,
sm ); sm );
verify( loc == -1 ); verify( loc == -1 );
verify( firstEmpty >= 0 ); if ( firstEmpty < 0 ) {
return false;
}
newArea->_entries[firstEmpty] = _entries[i]; newArea->_entries[firstEmpty] = _entries[i];
} }
return true;
} }
template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS > template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
inline UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::UnorderedFast KeyTable( inline UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::UnorderedFast KeyTable(
unsigned startingCapacity, unsigned startingCapacity,
double maxProbeRatio) double maxProbeRatio)
: _maxProbeRatio( maxProbeRatio ), _area( startingCapacity, maxProb eRatio ) { : _maxProbeRatio( maxProbeRatio ), _area( startingCapacity, maxProb eRatio ) {
_size = 0; _size = 0;
} }
skipping to change at line 132 skipping to change at line 135
out->_maxProbeRatio = _maxProbeRatio; out->_maxProbeRatio = _maxProbeRatio;
Area x( _area ); Area x( _area );
out->_area.swap( &x ); out->_area.swap( &x );
} }
template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS > template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
inline V& UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::get( const K_L& key ) { inline V& UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::get( const K_L& key ) {
const size_t hash = _hash( key ); const size_t hash = _hash( key );
for ( int numGrowTries = 0; numGrowTries < 10; numGrowTries++ ) { for ( int numGrowTries = 0; numGrowTries < 5; numGrowTries++ ) {
int firstEmpty = -1; int firstEmpty = -1;
int pos = _area.find( key, hash, &firstEmpty, *this ); int pos = _area.find( key, hash, &firstEmpty, *this );
if ( pos >= 0 ) if ( pos >= 0 )
return _area._entries[pos].data.second; return _area._entries[pos].data.second;
// key not in map // key not in map
// need to add // need to add
if ( firstEmpty >= 0 ) { if ( firstEmpty >= 0 ) {
_size++; _size++;
_area._entries[firstEmpty].used = true; _area._entries[firstEmpty].used = true;
skipping to change at line 171 skipping to change at line 174
if ( pos < 0 ) if ( pos < 0 )
return 0; return 0;
_area._entries[pos].used = false; _area._entries[pos].used = false;
_area._entries[pos].data.second = V(); _area._entries[pos].data.second = V();
return 1; return 1;
} }
template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS > template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
inline void UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::_grow() { inline void UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::_grow() {
Area newArea( _area._capacity * 2, _maxProbeRatio ); unsigned capacity = _area._capacity;
_area.transfer( &newArea, *this ); for ( int numGrowTries = 0; numGrowTries < 5; numGrowTries++ ) {
_area.swap( &newArea ); capacity *= 2;
Area newArea( capacity, _maxProbeRatio );
bool success = _area.transfer( &newArea, *this );
if ( !success ) {
continue;
}
_area.swap( &newArea );
return;
}
msgasserted( 16845,
"UnorderedFastKeyTable::_grow couldn't add entry after
growing many times" );
} }
template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS > template< typename K_L, typename K_S, typename V, typename H, typename E, typename C, typename C_LS >
inline typename UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::cons t_iterator inline typename UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::cons t_iterator
UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::find( const K_L& key ) const { UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::find( const K_L& key ) const {
if ( _size == 0 ) if ( _size == 0 )
return const_iterator(); return const_iterator();
int pos = _area.find( key, _hash(key), 0, *this ); int pos = _area.find( key, _hash(key), 0, *this );
if ( pos < 0 ) if ( pos < 0 )
return const_iterator(); return const_iterator();
 End of changes. 5 change blocks. 
6 lines changed or deleted 20 lines changed or added


 update.h   update.h 
skipping to change at line 47 skipping to change at line 47
upserted.clear(); upserted.clear();
BSONElement id = upsertedObject["_id"]; BSONElement id = upsertedObject["_id"];
if ( ! e && n == 1 && id.type() == jstOID ) { if ( ! e && n == 1 && id.type() == jstOID ) {
upserted = id.OID(); upserted = id.OID();
} }
} }
}; };
class RemoveSaver; class RemoveSaver;
/** Returns true if updates are supposed to be handle by the new update
framework */
bool isNewUpdateFrameworkEnabled();
/* 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
su - allow access to system namespaces (super user) su - allow access to system namespaces (super user)
*/ */
UpdateResult updateObjects(const char* ns, UpdateResult updateObjects(const char* ns,
const BSONObj& updateobj, const BSONObj& updateobj,
const BSONObj& pattern, const BSONObj& pattern,
bool upsert, bool upsert,
bool multi, bool multi,
bool logop, bool logop,
skipping to change at line 88 skipping to change at line 91
UpdateResult _updateObjects(bool su, UpdateResult _updateObjects(bool su,
const char* ns, const char* ns,
const BSONObj& updateobj, const BSONObj& updateobj,
const BSONObj& pattern, const BSONObj& pattern,
bool upsert, bool upsert,
bool multi, bool multi,
bool logop, bool logop,
OpDebug& debug, OpDebug& debug,
RemoveSaver* rs = 0, RemoveSaver* rs = 0,
bool fromMigrate = false, bool fromMigrate = false,
const QueryPlanSelectionPolicy& planPolicy const QueryPlanSelectionPolicy& planPolicy
= QueryPlanSelectionPolicy::any(), = QueryPlanSelectionPolicy::any(),
bool forReplication = false); bool forReplication = false);
UpdateResult _updateObjectsNEW(bool su,
const char* ns,
const BSONObj& updateobj,
const BSONObj& pattern,
bool upsert,
bool multi,
bool logop,
OpDebug& debug,
RemoveSaver* rs = 0,
bool fromMigrate = false,
const QueryPlanSelectionPolicy& planPoli
cy
= QueryPlanSelectionPolicy::any(),
bool forReplication = false);
/** /**
* takes the from document and returns a new document * takes the from document and returns a new document
* after apply all the operators * after apply all the operators
* e.g. * e.g.
* applyUpdateOperators( BSON( "x" << 1 ) , BSON( "$inc" << BSON( "x" << 1 ) ) ); * applyUpdateOperators( BSON( "x" << 1 ) , BSON( "$inc" << BSON( "x" << 1 ) ) );
* returns: { x : 2 } * returns: { x : 2 }
*/ */
BSONObj applyUpdateOperators( const BSONObj& from, const BSONObj& opera tors ); BSONObj applyUpdateOperators( const BSONObj& from, const BSONObj& opera tors );
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
2 lines changed or deleted 21 lines changed or added


 v8_db.h   v8_db.h 
skipping to change at line 30 skipping to change at line 30
#include <boost/function.hpp> #include <boost/function.hpp>
#include <v8.h> #include <v8.h>
#include "mongo/scripting/engine_v8.h" #include "mongo/scripting/engine_v8.h"
namespace mongo { namespace mongo {
class DBClientBase; class DBClientBase;
/** /**
* install database access functions
*/
void installDBAccess(V8Scope* scope);
/**
* install BSON types and helpers
*/
void installBSONTypes(V8Scope* scope);
/**
* get the DBClientBase connection from JS args * get the DBClientBase connection from JS args
*/ */
mongo::DBClientBase* getConnection(const v8::Arguments& args); mongo::DBClientBase* getConnection(V8Scope* scope, const v8::Arguments&
args);
// Internal Cursor
v8::Handle<v8::FunctionTemplate> getInternalCursorFunctionTemplate(V8Sc
ope* scope);
// Mongo constructors // Mongo constructors
v8::Handle<v8::Value> mongoConsLocal(V8Scope* scope, const v8::Argument s& args); v8::Handle<v8::Value> mongoConsLocal(V8Scope* scope, const v8::Argument s& args);
v8::Handle<v8::Value> mongoConsExternal(V8Scope* scope, const v8::Argum ents& args); v8::Handle<v8::Value> mongoConsExternal(V8Scope* scope, const v8::Argum ents& args);
v8::Handle<v8::FunctionTemplate> getMongoFunctionTemplate(V8Scope* scop e, bool local); v8::Handle<v8::FunctionTemplate> getMongoFunctionTemplate(V8Scope* scop e, bool local);
// Mongo member functions // Mongo member functions
v8::Handle<v8::Value> mongoFind(V8Scope* scope, const v8::Arguments& ar gs); v8::Handle<v8::Value> mongoFind(V8Scope* scope, const v8::Arguments& ar gs);
v8::Handle<v8::Value> mongoInsert(V8Scope* scope, const v8::Arguments& args); v8::Handle<v8::Value> mongoInsert(V8Scope* scope, const v8::Arguments& args);
v8::Handle<v8::Value> mongoRemove(V8Scope* scope, const v8::Arguments& args); v8::Handle<v8::Value> mongoRemove(V8Scope* scope, const v8::Arguments& args);
v8::Handle<v8::Value> mongoUpdate(V8Scope* scope, const v8::Arguments& args); v8::Handle<v8::Value> mongoUpdate(V8Scope* scope, const v8::Arguments& args);
v8::Handle<v8::Value> mongoAuth(V8Scope* scope, const v8::Arguments& ar gs); v8::Handle<v8::Value> mongoAuth(V8Scope* scope, const v8::Arguments& ar gs);
v8::Handle<v8::Value> mongoLogout(V8Scope* scope, const v8::Arguments& args); v8::Handle<v8::Value> mongoLogout(V8Scope* scope, const v8::Arguments& args);
v8::Handle<v8::Value> mongoCursorFromId(V8Scope* scope, const v8::Argum ents& args);
// Cursor object // Cursor object
v8::Handle<v8::Value> internalCursorCons(V8Scope* scope, const v8::Argu ments& args); v8::Handle<v8::Value> internalCursorCons(V8Scope* scope, const v8::Argu ments& args);
v8::Handle<v8::Value> internalCursorNext(V8Scope* scope, const v8::Argu ments& args); v8::Handle<v8::Value> internalCursorNext(V8Scope* scope, const v8::Argu ments& args);
v8::Handle<v8::Value> internalCursorHasNext(V8Scope* scope, const v8::A rguments& args); v8::Handle<v8::Value> internalCursorHasNext(V8Scope* scope, const v8::A rguments& args);
v8::Handle<v8::Value> internalCursorObjsLeftInBatch(V8Scope* scope, con st v8::Arguments& args); v8::Handle<v8::Value> internalCursorObjsLeftInBatch(V8Scope* scope, con st v8::Arguments& args);
v8::Handle<v8::Value> internalCursorReadOnly(V8Scope* scope, const v8:: Arguments& args); v8::Handle<v8::Value> internalCursorReadOnly(V8Scope* scope, const v8:: Arguments& args);
// BinData object // BinData object
v8::Handle<v8::Value> binDataInit(V8Scope* scope, const v8::Arguments& args); v8::Handle<v8::Value> binDataInit(V8Scope* scope, const v8::Arguments& args);
v8::Handle<v8::Value> binDataToString(V8Scope* scope, const v8::Argumen ts& args); v8::Handle<v8::Value> binDataToString(V8Scope* scope, const v8::Argumen ts& args);
v8::Handle<v8::Value> binDataToBase64(V8Scope* scope, const v8::Argumen ts& args); v8::Handle<v8::Value> binDataToBase64(V8Scope* scope, const v8::Argumen ts& args);
v8::Handle<v8::Value> binDataToHex(V8Scope* scope, const v8::Arguments& args); v8::Handle<v8::Value> binDataToHex(V8Scope* scope, const v8::Arguments& args);
// NumberLong object // NumberLong object
long long numberLongVal(V8Scope* scope, const v8::Handle<v8::Object>& i t);
v8::Handle<v8::Value> numberLongInit(V8Scope* scope, const v8::Argument s& args); v8::Handle<v8::Value> numberLongInit(V8Scope* scope, const v8::Argument s& args);
v8::Handle<v8::Value> numberLongToNumber(V8Scope* scope, const v8::Argu ments& args); v8::Handle<v8::Value> numberLongToNumber(V8Scope* scope, const v8::Argu ments& args);
v8::Handle<v8::Value> numberLongValueOf(V8Scope* scope, const v8::Argum ents& args); v8::Handle<v8::Value> numberLongValueOf(V8Scope* scope, const v8::Argum ents& args);
v8::Handle<v8::Value> numberLongToString(V8Scope* scope, const v8::Argu ments& args); v8::Handle<v8::Value> numberLongToString(V8Scope* scope, const v8::Argu ments& args);
// Number object // NumberInt object
int numberIntVal(V8Scope* scope, const v8::Handle<v8::Object>& it);
v8::Handle<v8::Value> numberIntInit(V8Scope* scope, const v8::Arguments & args); v8::Handle<v8::Value> numberIntInit(V8Scope* scope, const v8::Arguments & args);
v8::Handle<v8::Value> numberIntToNumber(V8Scope* scope, const v8::Argum ents& args); v8::Handle<v8::Value> numberIntToNumber(V8Scope* scope, const v8::Argum ents& args);
v8::Handle<v8::Value> numberIntValueOf(V8Scope* scope, const v8::Argume nts& args); v8::Handle<v8::Value> numberIntValueOf(V8Scope* scope, const v8::Argume nts& args);
v8::Handle<v8::Value> numberIntToString(V8Scope* scope, const v8::Argum ents& args); v8::Handle<v8::Value> numberIntToString(V8Scope* scope, const v8::Argum ents& args);
// DBQuery object // DBQuery object
v8::Handle<v8::Value> dbQueryInit(V8Scope* scope, const v8::Arguments& args); v8::Handle<v8::Value> dbQueryInit(V8Scope* scope, const v8::Arguments& args);
v8::Handle<v8::Value> dbQueryIndexAccess(::uint32_t index, const v8::Ac cessorInfo& info); v8::Handle<v8::Value> dbQueryIndexAccess(::uint32_t index, const v8::Ac cessorInfo& info);
// db constructor // db constructor
 End of changes. 5 change blocks. 
12 lines changed or deleted 10 lines changed or added


 value.h   value.h 
/* @file value.h
concurrency helpers DiagStr, Guarded
*/
/** /**
* Copyright (C) 2008 10gen Inc. * Copyright (c) 2011 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3 * it under the terms of the GNU Affero General Public License, version 3,
, * as published by the Free Software Foundation.
* as published by the Free Software Foundation. *
* * This program is distributed in the hope that it will be useful,
* This program is distributed in the hope that it will be useful,b * 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 License
* You should have received a copy of the GNU Affero General Public Licen * along with this program. If not, see <http://www.gnu.org/licenses/>.
se */
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once #pragma once
#include "spin_lock.h" #include "mongo/db/pipeline/value_internal.h"
namespace mongo { namespace mongo {
class BSONElement;
class Builder;
/** declare that a variable that is "guarded" by a mutex. /** A variant type that can hold any type of data representable in BSON
*
The decl documents the rule. For example "counta and countb are gu * Small values are stored inline, but some values, such as large stri
arded by xyzMutex": ngs,
* are heap allocated. It has smart pointer capabilities built-in so i
Guarded<int, xyzMutex> counta; t is
Guarded<int, xyzMutex> countb; * safe and recommended to pass these around and return them by value.
*
Upon use, specify the scoped_lock object. This makes it hard for s * Values are immutable, but can be assigned. This means that once you
omeone have
later to forget to be in the lock. Check is made that it is the ri * a Value, you can be assured that none of the data in that Value wil
ght lock in _DEBUG l
builds at runtime. * change. However if you have a non-const Value you replace it with
*/ * operator=. These rules are the same as BSONObj, and similar to
template <typename T, SimpleMutex& BY> * shared_ptr<const Object> with stronger guarantees of constness. Thi
class Guarded { s is
T _val; * also the same as Java's String type.
*
* Thread-safety: A single Value instance can be safely shared between
* threads as long as there are no writers while other threads are
* accessing the object. Any number of threads can read from a Value
* concurrently. There are no restrictions on how threads access Value
* instances exclusively owned by them, even if they reference the sam
e
* storage as Value in other threads.
*/
class Value {
public: public:
T& ref(const SimpleMutex::scoped_lock& lk) { /** Construct a Value
dassert( &lk.m() == &BY ); *
return _val; * All types not listed will be rejected rather than converted (se
e private for why)
*
* Note: Currently these are all explicit conversions.
* I'm not sure if we want implicit or not.
* //TODO decide
*/
Value(): _storage() {} // "Missing" value
explicit Value(bool value) : _storage(Bool, value) {
}
explicit Value(int value) : _storage(NumberInt, val
ue) {}
explicit Value(long long value) : _storage(NumberLong, va
lue) {}
explicit Value(double value) : _storage(NumberDouble,
value) {}
explicit Value(const OpTime& value) : _storage(Timestamp, val
ue.asDate()) {}
explicit Value(const OID& value) : _storage(jstOID, value)
{}
explicit Value(const StringData& value) : _storage(String, value)
{}
explicit Value(const string& value) : _storage(String, String
Data(value)) {}
explicit Value(const char* value) : _storage(String, String
Data(value)) {}
explicit Value(const Document& doc) : _storage(Object, doc) {
}
explicit Value(const BSONObj& obj);// : _storage(Object, Docume
nt(obj)) {} // in cpp
explicit Value(const vector<Value>& vec) : _storage(Array, new RCV
ector(vec)) {}
explicit Value(const BSONBinData& bd) : _storage(BinData, bd) {
}
explicit Value(const BSONRegEx& re) : _storage(RegEx, re) {}
explicit Value(const BSONCodeWScope& cws) : _storage(CodeWScope, cw
s) {}
explicit Value(const BSONDBRef& dbref) : _storage(DBRef, dbref)
{}
explicit Value(const BSONSymbol& sym) : _storage(Symbol, sym.sy
mbol) {}
explicit Value(const BSONCode& code) : _storage(Code, code.cod
e) {}
explicit Value(const NullLabeler&) : _storage(jstNULL) {}
// BSONNull
explicit Value(const UndefinedLabeler&) : _storage(Undefined) {}
// BSONUndefined
explicit Value(const MinKeyLabeler&) : _storage(MinKey) {}
// MINKEY
explicit Value(const MaxKeyLabeler&) : _storage(MaxKey) {}
// MAXKEY
explicit Value(const Date_t& date)
: _storage(Date, static_cast<long long>(date.millis)) // millis
really signed
{}
/** Creates an empty or zero value of specified type.
* This is currently the only way to create Undefined or Null Valu
es.
*/
explicit Value(BSONType type);
// TODO: add an unsafe version that can share storage with the BSON
Element
/// Deep-convert from BSONElement to Value
explicit Value(const BSONElement& elem);
/** Construct a long or integer-valued Value.
*
* Used when preforming arithmetic operations with int where the
* result may be too large and need to be stored as long. The Valu
e
* will be an int if value fits, otherwise it will be a long.
*/
static Value createIntOrLong(long long value);
/** Construct an Array-typed Value from consumed without copying th
e vector.
* consumed is replaced with an empty vector.
* In C++11 this would be spelled Value(std::move(consumed)).
*/
static Value consume(vector<Value>& consumed) {
RCVector* vec = new RCVector();
std::swap(vec->vec, consumed);
return Value(ValueStorage(Array, vec));
} }
};
// todo: rename this to ThreadSafeString or something /** A "missing" value indicates the lack of a Value.
/** there is now one mutex per DiagStr. If you have hundreds or millio * This is similar to undefined/null but should not appear in outp
ns of ut to BSON.
DiagStrs you'll need to do something different. * Missing Values are returned by Document when accessing non-exis
*/ tent fields.
class DiagStr { */
mutable SpinLock m; bool missing() const { return _storage.type == EOO; }
string _s;
public: /// true if missing() or type is jstNULL or Undefined
DiagStr(const DiagStr& r) : _s(r.get()) { } bool nullish() const {
DiagStr(const string& r) : _s(r) { } return missing()
DiagStr() { } || _storage.type == jstNULL
bool empty() const { || _storage.type == Undefined;
scoped_spinlock lk(m);
return _s.empty();
}
string get() const {
scoped_spinlock lk(m);
return _s;
} }
void set(const char *s) {
scoped_spinlock lk(m); /// true if type represents a number
_s = s; bool numeric() const {
return _storage.type == NumberDouble
|| _storage.type == NumberLong
|| _storage.type == NumberInt;
} }
void set(const string& s) {
scoped_spinlock lk(m); /// Get the BSON type of the field.
_s = s; BSONType getType() const { return _storage.bsonType(); }
/** Exact type getters.
* Asserts if the requested value type is not exactly correct.
* See coerceTo methods below for a more type-flexible alternative
.
*/
double getDouble() const;
string getString() const;
Document getDocument() const;
OID getOid() const;
bool getBool() const;
long long getDate() const; // in milliseconds
OpTime getTimestamp() const;
const char* getRegex() const;
const char* getRegexFlags() const;
string getSymbol() const;
string getCode() const;
int getInt() const;
long long getLong() const;
const vector<Value>& getArray() const { return _storage.getArray();
}
size_t getArrayLength() const;
/// Access an element of a subarray. Returns Value() if missing or
getType() != Array
Value operator[] (size_t index) const;
/// Access a field of a subdocument. Returns Value() if missing or
getType() != Object
Value operator[] (StringData name) const;
/// Add this value to the BSON object under construction.
void addToBsonObj(BSONObjBuilder* pBuilder, StringData fieldName) c
onst;
/// Add this field to the BSON array under construction.
void addToBsonArray(BSONArrayBuilder* pBuilder) const;
// Support BSONObjBuilder and BSONArrayBuilder "stream" API
friend BSONObjBuilder& operator << (BSONObjBuilderValueStream& buil
der, const Value& val);
/** Coerce a value to a bool using BSONElement::trueValue() rules.
* Some types unsupported. SERVER-6120
*/
bool coerceToBool() const;
/** Coercion operators to extract values with fuzzy type logic.
*
* These currently assert if called on an unconvertible type.
* TODO: decided how to handle unsupported types.
*/
string coerceToString() const;
int coerceToInt() const;
long long coerceToLong() const;
double coerceToDouble() const;
OpTime coerceToTimestamp() const;
long long coerceToDate() const;
time_t coerceToTimeT() const;
tm coerceToTm() const; // broken-out time struct (see man gmtime)
/** Compare two Values.
* @returns an integer less than zero, zero, or an integer greater
than
* zero, depending on whether lhs < rhs, lhs == rhs, or l
hs > rhs
* Warning: may return values other than -1, 0, or 1
*/
static int compare(const Value& lhs, const Value& rhs);
friend
bool operator==(const Value& v1, const Value& v2) {
if (v1._storage.identical(v2._storage)) {
// Simple case
return true;
}
return (Value::compare(v1, v2) == 0);
} }
operator string() const { return get(); }
void operator=(const string& s) { set(s); } /// This is for debugging, logging, etc. See getString() for how to
void operator=(const DiagStr& rhs) { extract a string.
set( rhs.get() ); string toString() const;
friend ostream& operator << (ostream& out, const Value& v);
void swap(Value& rhs) {
_storage.swap(rhs._storage);
} }
// == is not defined. use get() == ... instead. done this way so /** Figure out what the widest of two numeric types is.
one thinks about if composing multiple operations *
bool operator==(const string& s) const; * Widest can be thought of as "most capable," or "able to hold th
e
* largest or most precise value." The progression is Int, Long,
Double.
*/
static BSONType getWidestNumeric(BSONType lType, BSONType rType);
/// Get the approximate memory size of the value, in bytes. Include
s sizeof(Value)
size_t getApproximateSize() const;
/** Calculate a hash value.
*
* Meant to be used to create composite hashes suitable for
* hashed container classes such as unordered_map<>.
*/
void hash_combine(size_t& seed) const;
/// struct Hash is defined to enable the use of Values as keys in u
nordered_map.
struct Hash : unary_function<const Value&, size_t> {
size_t operator()(const Value& rV) const;
};
/// Call this after memcpying to update ref counts if needed
void memcpyed() const { _storage.memcpyed(); }
/// members for Sorter
struct SorterDeserializeSettings {}; // unused
void serializeForSorter(BufBuilder& buf) const;
static Value deserializeForSorter(BufReader& buf, const SorterDeser
ializeSettings&);
int memUsageForSorter() const { return getApproximateSize(); }
Value getOwned() const { return *this; }
private:
/** This is a "honeypot" to prevent unexpected implicit conversions
to the accepted argument
* types. bool is especially bad since without this it will accept
any pointer.
*
* Template argument name was chosen to make produced error easier
to read.
*/
template <typename InvalidArgumentType>
explicit Value(const InvalidArgumentType& invalidArgument);
explicit Value(const ValueStorage& storage) :_storage(storage) {}
// does no type checking
StringData getStringData() const; // May contain embedded NUL bytes
ValueStorage _storage;
friend class MutableValue; // gets and sets _storage.genericRCPtr
}; };
BOOST_STATIC_ASSERT(sizeof(Value) == 16);
}
namespace std {
// This is used by std::sort and others
template <>
inline void swap(mongo::Value& lhs, mongo::Value& rhs) { lhs.swap(rhs);
}
} }
/* ======================= INLINED IMPLEMENTATIONS ========================
== */
namespace mongo {
inline size_t Value::getArrayLength() const {
verify(getType() == Array);
return getArray().size();
}
inline size_t Value::Hash::operator()(const Value& v) const {
size_t seed = 0xf0afbeef;
v.hash_combine(seed);
return seed;
}
inline StringData Value::getStringData() const {
return _storage.getString();
}
inline string Value::getString() const {
verify(getType() == String);
return _storage.getString().toString();
}
inline OID Value::getOid() const {
verify(getType() == jstOID);
return OID(_storage.oid);
}
inline bool Value::getBool() const {
verify(getType() == Bool);
return _storage.boolValue;
}
inline long long Value::getDate() const {
verify(getType() == Date);
return _storage.dateValue;
}
inline OpTime Value::getTimestamp() const {
verify(getType() == Timestamp);
return _storage.timestampValue;
}
inline const char* Value::getRegex() const {
verify(getType() == RegEx);
return _storage.getString().rawData(); // this is known to be NUL t
erminated
}
inline const char* Value::getRegexFlags() const {
verify(getType() == RegEx);
const char* pattern = _storage.getString().rawData(); // this is kn
own to be NUL terminated
const char* flags = pattern + strlen(pattern) + 1; // first byte af
ter pattern's NUL
dassert(flags + strlen(flags) == pattern + _storage.getString().siz
e());
return flags;
}
inline string Value::getSymbol() const {
verify(getType() == Symbol);
return _storage.getString().toString();
}
inline string Value::getCode() const {
verify(getType() == Code);
return _storage.getString().toString();
}
inline int Value::getInt() const {
verify(getType() == NumberInt);
return _storage.intValue;
}
inline long long Value::getLong() const {
BSONType type = getType();
if (type == NumberInt)
return _storage.intValue;
verify(type == NumberLong);
return _storage.longValue;
}
};
 End of changes. 15 change blocks. 
74 lines changed or deleted 302 lines changed or added


 windows_basic.h   windows_basic.h 
skipping to change at line 31 skipping to change at line 31
#if !defined(_WIN32) #if !defined(_WIN32)
#error "windows_basic included but _WIN32 is not defined" #error "windows_basic included but _WIN32 is not defined"
#endif #endif
// Ensure that _WIN32_WINNT is set to something before we include windows.h . For server builds // Ensure that _WIN32_WINNT is set to something before we include windows.h . For server builds
// both _WIN32_WINNT and NTDDI_VERSION are set as defines on the command li ne, but we need // both _WIN32_WINNT and NTDDI_VERSION are set as defines on the command li ne, but we need
// these here for things like client driver builds, where they may not alre ady be set. // these here for things like client driver builds, where they may not alre ady be set.
#if !defined(_WIN32_WINNT) #if !defined(_WIN32_WINNT)
// Can't use symbolic versions here, since we may not have seen sdkddkver.h yet. // Can't use symbolic versions here, since we may not have seen sdkddkver.h yet.
#if defined(_WIN64) #if defined(_WIN64)
// 64-bit builds default to Windows Vista support. // 64-bit builds default to Windows Server 2003 support.
#define _WIN32_WINNT 0x0600 #define _WIN32_WINNT 0x0502
#else #else
// 32-bit builds default to Windows XP support. // 32-bit builds default to Windows XP support.
#define _WIN32_WINNT 0x0501 #define _WIN32_WINNT 0x0501
#endif #endif
#endif #endif
// As above, but for NTDDI_VERSION. Otherwise, <windows.h> would set our NT
DDI_VERSION based on
// _WIN32_WINNT, but not select the service pack revision.
#if !defined(NTDDI_VERSION)
// Can't use symbolic versions here, since we may not have seen sdkddkver.h
yet.
#if defined(_WIN64)
// 64-bit builds default to Windows Server 2003 SP 2 support.
#define NTDDI_VERSION 0x05020200
#else
// 32-bit builds default to Windows XP SP 3 support.
#define NTDDI_VERSION 0x05010300
#endif
#endif
// No need to set WINVER, SdkDdkVer.h does that for us, we double check thi s below. // No need to set WINVER, SdkDdkVer.h does that for us, we double check thi s below.
// for rand_s() usage: // for rand_s() usage:
# define _CRT_RAND_S # define _CRT_RAND_S
# ifndef NOMINMAX # ifndef NOMINMAX
# define NOMINMAX # define NOMINMAX
# endif # endif
// Do not complain that about standard library functions that Windows belie
ves should have
// underscores in front of them, such as unlink().
#define _CRT_NONSTDC_NO_DEPRECATE
// tell windows.h not to include a bunch of headers we don't need: // tell windows.h not to include a bunch of headers we don't need:
# define WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN
# 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 <wspiapi.h>
# include <windows.h> # include <windows.h>
// Should come either from the command line, or if not set there, the inclu sion of sdkddkver.h // Should come either from the command line, or if not set there, the inclu sion of sdkddkver.h
// via windows.h above should set it based in _WIN32_WINNT, which is assure dly set by now. // via windows.h above should set it based in _WIN32_WINNT, which is assure dly set by now.
#if !defined(NTDDI_VERSION) #if !defined(NTDDI_VERSION)
#error "NTDDI_VERSION is not defined" #error "NTDDI_VERSION is not defined"
#endif #endif
#if !defined(WINVER) || (WINVER != _WIN32_WINNT) #if !defined(WINVER) || (WINVER != _WIN32_WINNT)
#error "Expected WINVER to have been defined and to equal _WIN32_WINNT" #error "Expected WINVER to have been defined and to equal _WIN32_WINNT"
#endif #endif
#if defined(_WIN64) #if defined(_WIN64)
#if !defined(NTDDI_VISTA) || (NTDDI_VERSION < NTDDI_VISTA) #if !defined(NTDDI_WS03SP2) || (NTDDI_VERSION < NTDDI_WS03SP2)
#error "64 bit mongo does not support Windows versions older than Vista" #error "64 bit mongo does not support Windows versions older than Windows S
erver 2003 SP 2"
#endif #endif
#else #else
#if !defined(NTDDI_WINXPSP3) || (NTDDI_VERSION < NTDDI_WINXPSP3) #if !defined(NTDDI_WINXPSP3) || (NTDDI_VERSION < NTDDI_WINXPSP3)
#error "32 bit mongo does not support Windows versions older than XP Servic e Pack 3" #error "32 bit mongo does not support Windows versions older than XP Servic e Pack 3"
#endif #endif
#endif #endif
 End of changes. 4 change blocks. 
4 lines changed or deleted 26 lines changed or added


 write_concern.h   write_concern.h 
/** /**
* Copyright (C) 2008 10gen Inc. * Copyright (C) 2013 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3 * it under the terms of the GNU Affero General Public License, version
, 3,
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen * You should have received a copy of the GNU Affero General Public Lice
se 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 <vector>
#include "mongo/db/repl/optime.h"
#include "mongo/db/jsobj.h"
/**
local.slaves - current location for all slaves
*/
namespace mongo { namespace mongo {
class CurOp; /**
* Helper method for commands to call. Blocks until write concern (as
void updateSlaveLocation( CurOp& curop, const char * oplog_ns , OpTime specified in "cmdObj")
lastOp ); * is satisfied. "err" should be set to true if the last operation suc
ceeded, otherwise false.
/** @return true if op has made it to w servers */ * "result" will be filled with write concern results. Returns false a
bool opReplicatedEnough( OpTime op , int w ); nd sets "errmsg" on
bool opReplicatedEnough( OpTime op , BSONElement w ); * failure.
*/
bool waitForReplication( OpTime op , int w , int maxSecondsToWait ); bool waitForWriteConcern(const BSONObj& cmdObj,
bool err,
std::vector<BSONObj> getHostsWrittenTo(OpTime& op); BSONObjBuilder* result,
string* errmsg);
void resetSlaveCache(); } // namespace mongo
unsigned getSlaveCount();
}
 End of changes. 4 change blocks. 
37 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/