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 ¶ms); | ||||
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 ¤tIndex; | return ¤tIndex; | |||
} else { | } else { | |||
bestMultiKeyIndex = ¤tIndex; | bestMultiKeyIndex = ¤tIndex; | |||
} | } | |||
} | } | |||
} | } | |||
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 ¶ms, 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 | |||