admin_access.h   admin_access.h 
skipping to change at line 22 skipping to change at line 22
* 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"
namespace mongo { namespace mongo {
/* /*
* An AdminAccess is an interface class used to determine if certain us ers have * An AdminAccess is an interface class used to determine if certain us ers have
* privileges to a given resource. * privileges to a given resource.
* *
*/ */
class AdminAccess { class AdminAccess {
public: public:
virtual ~AdminAccess() { } virtual ~AdminAccess() { }
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 assert_util.h   assert_util.h 
skipping to change at line 169 skipping to change at line 169
public: public:
MsgAssertionException( const ExceptionInfo& ei ) : AssertionExcepti on( ei ) {} MsgAssertionException( const ExceptionInfo& ei ) : AssertionExcepti on( ei ) {}
MsgAssertionException(int c, const std::string& m) : AssertionExcep tion( m , c ) {} MsgAssertionException(int c, const std::string& m) : AssertionExcep tion( m , c ) {}
virtual bool severe() { return false; } virtual bool severe() { return false; }
virtual void appendPrefix( std::stringstream& ss ) const; virtual void appendPrefix( std::stringstream& ss ) const;
}; };
MONGO_COMPILER_NORETURN void verifyFailed(const char *msg, const char * file, unsigned line); MONGO_COMPILER_NORETURN void verifyFailed(const char *msg, const char * file, unsigned line);
void wasserted(const char *msg, const char *file, unsigned line); void wasserted(const char *msg, const char *file, unsigned line);
MONGO_COMPILER_NORETURN void fassertFailed( int msgid ); MONGO_COMPILER_NORETURN void fassertFailed( int msgid );
MONGO_COMPILER_NORETURN void fassertFailedNoTrace( int msgid );
/** a "user assertion". throws UserAssertion. logs. typically used f or errors that a user /** a "user assertion". throws UserAssertion. logs. typically used f or errors that a user
could cause, such as duplicate key, disk full, etc. could cause, such as duplicate key, disk full, etc.
*/ */
MONGO_COMPILER_NORETURN void uasserted(int msgid, const char *msg); MONGO_COMPILER_NORETURN void uasserted(int msgid, const char *msg);
MONGO_COMPILER_NORETURN void uasserted(int msgid , const std::string &m sg); MONGO_COMPILER_NORETURN void uasserted(int msgid , const std::string &m sg);
/** msgassert and massert are for errors that are internal but have a w ell defined error text std::string. /** msgassert and massert are for errors that are internal but have a w ell defined error text std::string.
a stack trace is logged. a stack trace is logged.
*/ */
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 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(_WIN32_WINNT_VISTA) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA) #if defined(NTDDI_VERSION) && defined(NTDDI_VISTA) && (NTDDI_VERSION >= NTD DI_VISTA)
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_external_state.h   auth_external_state.h 
skipping to change at line 28 skipping to change at line 28
#include <string> #include <string>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
#include "mongo/base/status.h" #include "mongo/base/status.h"
#include "mongo/client/dbclientinterface.h" #include "mongo/client/dbclientinterface.h"
#include "mongo/db/auth/principal_name.h" #include "mongo/db/auth/principal_name.h"
namespace mongo { namespace mongo {
class Principal;
/** /**
* Public interface for a class that encapsulates all the information r elated to system state * Public interface for a class that encapsulates all the information r elated to system state
* not stored in AuthorizationManager. This is primarily to make Autho rizationManager easier * not stored in AuthorizationManager. This is primarily to make Autho rizationManager easier
* to test. There are two classes that implement this interface, AuthE xternalStateImpl, which * to test. There are two classes that implement this interface, AuthE xternalStateImpl, which
* is what's used for the actual system, and AuthExternalStateMock, whi ch is used in the tests. * is what's used for the actual system, and AuthExternalStateMock, whi ch is used in the tests.
*/ */
class AuthExternalState { class AuthExternalState {
MONGO_DISALLOW_COPYING(AuthExternalState); MONGO_DISALLOW_COPYING(AuthExternalState);
public: public:
skipping to change at line 61 skipping to change at line 63
virtual void startRequest() = 0; virtual void startRequest() = 0;
// Gets the privilege information document for "principalName" on " dbname". // Gets the privilege information document for "principalName" on " dbname".
// //
// On success, returns Status::OK() and stores a shared-ownership c opy of the document into // On success, returns Status::OK() and stores a shared-ownership c opy of the document into
// "result". // "result".
Status getPrivilegeDocument(const std::string& dbname, Status getPrivilegeDocument(const std::string& dbname,
const PrincipalName& principalName, const PrincipalName& principalName,
BSONObj* result); BSONObj* result);
// Authorization event hooks
// Handle any global state which needs to be updated when a new use
r has been authorized
virtual void onAddAuthorizedPrincipal(Principal*) = 0;
// Handle any global state which needs to be updated when a user lo
gs out
virtual void onLogoutDatabase(const std::string& dbname) = 0;
protected: protected:
AuthExternalState(); // This class should never be instantiated dir ectly. AuthExternalState(); // This class should never be instantiated dir ectly.
// Queries the userNamespace with the given query and returns the p rivilegeDocument found // Queries the userNamespace with the given query and returns the p rivilegeDocument found
// in *result. Returns true if it finds a document matching the qu ery, or false if not. // in *result. Returns true if it finds a document matching the qu ery, or false if not.
virtual bool _findUser(const std::string& usersNamespace, virtual bool _findUser(const std::string& usersNamespace,
const BSONObj& query, const BSONObj& query,
BSONObj* result) const = 0; BSONObj* result) const = 0;
// Returns true if there exists at least one privilege document in the given database. // Returns true if there exists at least one privilege document in the given database.
 End of changes. 2 change blocks. 
0 lines changed or deleted 12 lines changed or added


 auth_external_state_d.h   auth_external_state_d.h 
skipping to change at line 39 skipping to change at line 39
MONGO_DISALLOW_COPYING(AuthExternalStateMongod); MONGO_DISALLOW_COPYING(AuthExternalStateMongod);
public: public:
AuthExternalStateMongod(); AuthExternalStateMongod();
virtual ~AuthExternalStateMongod(); virtual ~AuthExternalStateMongod();
virtual bool shouldIgnoreAuthChecks() const; virtual bool shouldIgnoreAuthChecks() const;
virtual void startRequest(); virtual void startRequest();
virtual void onAddAuthorizedPrincipal(Principal*);
virtual void onLogoutDatabase(const std::string&);
protected: protected:
virtual bool _findUser(const string& usersNamespace, virtual bool _findUser(const string& usersNamespace,
const BSONObj& query, const BSONObj& query,
BSONObj* result) const; BSONObj* result) const;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
0 lines changed or deleted 4 lines changed or added


 auth_external_state_mock.h   auth_external_state_mock.h 
skipping to change at line 50 skipping to change at line 50
} }
virtual bool _findUser(const std::string& usersNamespace, virtual bool _findUser(const std::string& usersNamespace,
const BSONObj& query, const BSONObj& query,
BSONObj* result) const { BSONObj* result) const {
return false; return false;
} }
virtual void startRequest() {} virtual void startRequest() {}
virtual void onAddAuthorizedPrincipal(Principal*) {}
virtual void onLogoutDatabase(const std::string& dbname) {}
private: private:
bool _returnValue; bool _returnValue;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
0 lines changed or deleted 4 lines changed or added


 auth_external_state_s.h   auth_external_state_s.h 
skipping to change at line 37 skipping to change at line 37
*/ */
class AuthExternalStateMongos : public AuthExternalStateServerCommon { class AuthExternalStateMongos : public AuthExternalStateServerCommon {
MONGO_DISALLOW_COPYING(AuthExternalStateMongos); MONGO_DISALLOW_COPYING(AuthExternalStateMongos);
public: public:
AuthExternalStateMongos(); AuthExternalStateMongos();
virtual ~AuthExternalStateMongos(); virtual ~AuthExternalStateMongos();
virtual void startRequest(); virtual void startRequest();
virtual void onAddAuthorizedPrincipal(Principal*);
virtual void onLogoutDatabase(const std::string&);
protected: protected:
virtual bool _findUser(const string& usersNamespace, virtual bool _findUser(const string& usersNamespace,
const BSONObj& query, const BSONObj& query,
BSONObj* result) const; BSONObj* result) const;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
0 lines changed or deleted 4 lines changed or added


 authentication_commands.h   authentication_commands.h 
skipping to change at line 27 skipping to change at line 27
#pragma once #pragma once
#include "mongo/db/commands.h" #include "mongo/db/commands.h"
namespace mongo { namespace mongo {
class CmdAuthenticate : public Command { class CmdAuthenticate : public Command {
public: public:
static void disableCommand(); static void disableCommand();
virtual bool requiresAuth() { return false; }
virtual bool logTheOp() { virtual bool logTheOp() {
return false; return false;
} }
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,
 End of changes. 1 change blocks. 
1 lines changed or deleted 0 lines changed or added


 authorization_manager.h   authorization_manager.h 
skipping to change at line 35 skipping to change at line 35
#include "mongo/db/auth/action_type.h" #include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/auth_external_state.h" #include "mongo/db/auth/auth_external_state.h"
#include "mongo/db/auth/principal.h" #include "mongo/db/auth/principal.h"
#include "mongo/db/auth/principal_name.h" #include "mongo/db/auth/principal_name.h"
#include "mongo/db/auth/principal_set.h" #include "mongo/db/auth/principal_set.h"
#include "mongo/db/auth/privilege.h" #include "mongo/db/auth/privilege.h"
#include "mongo/db/auth/privilege_set.h" #include "mongo/db/auth/privilege_set.h"
namespace mongo { namespace mongo {
// --noauth cmd line option
extern bool noauth;
/** /**
* Internal secret key info. * Internal secret key info.
*/ */
struct AuthInfo { struct AuthInfo {
AuthInfo(); AuthInfo();
string user; string user;
string pwd; string pwd;
}; };
extern AuthInfo internalSecurity; // set at startup and not changed aft er initialization. extern AuthInfo internalSecurity; // set at startup and not changed aft er initialization.
skipping to change at line 68 skipping to change at line 65
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;
static void setSupportOldStylePrivilegeDocuments(bool enabled); static void setSupportOldStylePrivilegeDocuments(bool enabled);
// Sets whether or not access control enforcement is enabled for th
is whole server..
static void setAuthEnabled(bool enabled);
// Returns true if access control is enabled on this server.
static bool isAuthEnabled();
// Checks to see if "doc" is a valid privilege document, assuming i t is stored in the // Checks to see if "doc" is a valid privilege document, assuming i t is stored in the
// "system.users" collection of database "dbname". // "system.users" collection of database "dbname".
// //
// Returns Status::OK() if the document is good, or Status(ErrorCod es::BadValue), otherwise. // Returns Status::OK() if the document is good, or Status(ErrorCod es::BadValue), otherwise.
static Status checkValidPrivilegeDocument(const StringData& dbname, const BSONObj& doc); static Status checkValidPrivilegeDocument(const StringData& dbname, const BSONObj& doc);
// Takes ownership of the externalState. // Takes ownership of the externalState.
explicit AuthorizationManager(AuthExternalState* externalState); explicit AuthorizationManager(AuthExternalState* externalState);
~AuthorizationManager(); ~AuthorizationManager();
skipping to change at line 94 skipping to change at line 97
void addAuthorizedPrincipal(Principal* principal); void addAuthorizedPrincipal(Principal* principal);
// Returns the authenticated principal with the given name. Return s NULL // Returns the authenticated principal with the given name. Return s NULL
// if no such user is found. // if no such user is found.
// Ownership of the returned Principal remains with _authenticatedP rincipals // Ownership of the returned Principal remains with _authenticatedP rincipals
Principal* lookupPrincipal(const PrincipalName& name); Principal* lookupPrincipal(const PrincipalName& name);
// Gets an iterator over the names of all authenticated principals stored in this manager. // Gets an iterator over the names of all authenticated principals stored in this manager.
PrincipalSet::NameIterator getAuthenticatedPrincipalNames(); PrincipalSet::NameIterator getAuthenticatedPrincipalNames();
// Returns a string representing all logged-in principals on the cu
rrent session.
// WARNING: this string will contain NUL bytes so don't call c_str(
)!
std::string getAuthenticatedPrincipalNamesToken();
// Removes any authenticated principals whose authorization credent ials came from the given // Removes any authenticated principals whose authorization credent ials came from the given
// database, and revokes any privileges that were granted via that principal. // database, and revokes any privileges that were granted via that principal.
void logoutDatabase(const std::string& dbname); void logoutDatabase(const std::string& dbname);
// Grant this connection the given privilege. // Grant this connection the given privilege.
Status acquirePrivilege(const Privilege& privilege, Status acquirePrivilege(const Privilege& privilege,
const PrincipalName& authorizingPrincipal); const PrincipalName& authorizingPrincipal);
// Adds a new principal with the given principal name and authorize s it with full access. // Adds a new principal with the given principal name and authorize s it with full access.
// Used to grant internal threads full access. // Used to grant internal threads full access.
skipping to change at line 213 skipping to change at line 212
const PrincipalName& principal, const PrincipalName& principal,
const BSONObj& privilegeDocument, const BSONObj& privilegeDocument,
PrivilegeSet* result); PrivilegeSet* result);
// Returns a new privilege that has replaced the actions needed to handle special casing // Returns a new privilege that has replaced the actions needed to handle special casing
// certain namespaces like system.users and system.profile. // certain namespaces like system.users and system.profile.
Privilege _modifyPrivilegeForSpecialCases(const Privilege& privileg e); Privilege _modifyPrivilegeForSpecialCases(const Privilege& privileg e);
static bool _doesSupportOldStylePrivileges; static bool _doesSupportOldStylePrivileges;
// True if access control enforcement is enabled on this node (ie i
t was started with
// --auth or --keyFile).
// This is a config setting, set at startup and not changing after
initialization.
static bool _authEnabled;
scoped_ptr<AuthExternalState> _externalState; scoped_ptr<AuthExternalState> _externalState;
// All the privileges that have been acquired by the authenticated principals. // All the privileges that have been acquired by the authenticated principals.
PrivilegeSet _acquiredPrivileges; PrivilegeSet _acquiredPrivileges;
// All principals who have been authenticated on this connection // All principals who have been authenticated on this connection
PrincipalSet _authenticatedPrincipals; PrincipalSet _authenticatedPrincipals;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 4 change blocks. 
9 lines changed or deleted 14 lines changed or added


 bgsync.h   bgsync.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 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/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include "mongo/util/queue.h" #include "mongo/util/queue.h"
#include "mongo/db/oplogreader.h" #include "mongo/db/repl/oplogreader.h"
#include "mongo/db/repl/rs.h" #include "mongo/db/repl/rs.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
namespace mongo { namespace mongo {
namespace replset { namespace replset {
// This interface exists to facilitate easier testing; // This interface exists to facilitate easier testing;
// the test infrastructure implements these functions with stubs. // the test infrastructure implements these functions with stubs.
class BackgroundSyncInterface { class BackgroundSyncInterface {
public: public:
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 bson-inl.h   bson-inl.h 
skipping to change at line 274 skipping to change at line 274
inline BSONElement BSONObj::getField(const StringData& name) const { inline BSONElement BSONObj::getField(const StringData& name) const {
BSONObjIterator i(*this); BSONObjIterator i(*this);
while ( i.more() ) { while ( i.more() ) {
BSONElement e = i.next(); BSONElement e = i.next();
if ( name == e.fieldName() ) if ( name == e.fieldName() )
return e; return e;
} }
return BSONElement(); return BSONElement();
} }
inline int BSONObj::getIntField(const char *name) const { inline int BSONObj::getIntField(const StringData& name) const {
BSONElement e = getField(name); BSONElement e = getField(name);
return e.isNumber() ? (int) e.number() : std::numeric_limits< int > ::min(); return e.isNumber() ? (int) e.number() : std::numeric_limits< int > ::min();
} }
inline bool BSONObj::getBoolField(const char *name) const { inline bool BSONObj::getBoolField(const StringData& name) const {
BSONElement e = getField(name); BSONElement e = getField(name);
return e.type() == Bool ? e.boolean() : false; return e.type() == Bool ? e.boolean() : false;
} }
inline const char * BSONObj::getStringField(const char *name) const { inline const char * BSONObj::getStringField(const StringData& name) con st {
BSONElement e = getField(name); BSONElement e = getField(name);
return e.type() == String ? e.valuestr() : ""; return e.type() == String ? e.valuestr() : "";
} }
/* add all the fields from the object specified to this object */ /* add all the fields from the object specified to this object */
inline BSONObjBuilder& BSONObjBuilder::appendElements(BSONObj x) { inline BSONObjBuilder& BSONObjBuilder::appendElements(BSONObj x) {
BSONObjIterator it(x); if (!x.isEmpty())
while ( it.moreWithEOO() ) { _b.appendBuf(
BSONElement e = it.next(); x.objdata() + 4, // skip over leading length
if ( e.eoo() ) break; x.objsize() - 5); // ignore leading length and trailing \0
append(e);
}
return *this; return *this;
} }
/* add all the fields from the object specified to this object if they don't exist */ /* add all the fields from the object specified to this object if they don't exist */
inline BSONObjBuilder& BSONObjBuilder::appendElementsUnique(BSONObj x) { inline BSONObjBuilder& BSONObjBuilder::appendElementsUnique(BSONObj x) {
std::set<std::string> have; std::set<std::string> have;
{ {
BSONObjIterator i = iterator(); BSONObjIterator i = iterator();
while ( i.more() ) while ( i.more() )
have.insert( i.next().fieldName() ); have.insert( i.next().fieldName() );
skipping to change at line 799 skipping to change at line 797
break; break;
default: default:
s << "?type=" << type(); s << "?type=" << type();
break; break;
} }
} }
/* return has eoo() true if no match /* return has eoo() true if no match
supports "." notation to reach into embedded objects supports "." notation to reach into embedded objects
*/ */
inline BSONElement BSONObj::getFieldDotted(const char *name) const { inline BSONElement BSONObj::getFieldDotted(const StringData& name) cons
BSONElement e = getField( name ); t {
if ( e.eoo() ) { BSONElement e = getField(name);
const char *p = strchr(name, '.'); if (e.eoo()) {
if ( p ) { size_t dot_offset = name.find('.');
std::string left(name, p-name); if (dot_offset != string::npos) {
BSONObj sub = getObjectField(left.c_str()); StringData left = name.substr(0, dot_offset);
return sub.isEmpty() ? BSONElement() : sub.getFieldDotted(p StringData right = name.substr(dot_offset + 1);
+1); BSONObj sub = getObjectField(left);
return sub.isEmpty() ? BSONElement() : sub.getFieldDotted(r
ight);
} }
} }
return e; return e;
} }
inline BSONObj BSONObj::getObjectField(const char *name) const { inline BSONObj BSONObj::getObjectField(const StringData& name) const {
BSONElement e = getField(name); BSONElement e = getField(name);
BSONType t = e.type(); BSONType t = e.type();
return t == Object || t == Array ? e.embeddedObject() : BSONObj(); return t == Object || t == Array ? e.embeddedObject() : BSONObj();
} }
inline int BSONObj::nFields() const { inline int BSONObj::nFields() const {
int n = 0; int n = 0;
BSONObjIterator i(*this); BSONObjIterator i(*this);
while ( i.moreWithEOO() ) { while ( i.moreWithEOO() ) {
BSONElement e = i.next(); BSONElement e = i.next();
 End of changes. 6 change blocks. 
19 lines changed or deleted 19 lines changed or added


 bson_db.h   bson_db.h 
skipping to change at line 29 skipping to change at line 29
This file contains the implementation of BSON-related methods that are required This file contains the implementation of BSON-related methods that are required
by the MongoDB database server. by the MongoDB database server.
Normally, for standalone BSON usage, you do not want this file - it wil l tend to Normally, for standalone BSON usage, you do not want this file - it wil l tend to
pull in some other files from the MongoDB project. Thus, bson.h (the ma in file pull in some other files from the MongoDB project. Thus, bson.h (the ma in file
one would use) does not include this file. one would use) does not include this file.
*/ */
#pragma once #pragma once
#include "../util/optime.h" #include "mongo/db/repl/optime.h"
#include "../util/time_support.h" #include "../util/time_support.h"
namespace mongo { namespace mongo {
/** /**
Timestamps are a special BSON datatype that is used internally for repl ication. Timestamps are a special BSON datatype that is used internally for repl ication.
Append a timestamp element to the object being ebuilt. Append a timestamp element to the object being ebuilt.
@param time - in millis (but stored in seconds) @param time - in millis (but stored in seconds)
*/ */
inline BSONObjBuilder& BSONObjBuilder::appendTimestamp( const StringDat a& fieldName , unsigned long long time , unsigned int inc ) { inline BSONObjBuilder& BSONObjBuilder::appendTimestamp( const StringDat a& fieldName , unsigned long long time , unsigned int inc ) {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 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 239 skipping to change at line 238
/** 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
size_t objsize() const { int objsize() const {
return static_cast< const size_t >( *reinterpret_cast< const ui return *reinterpret_cast< const int* >( value() );
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. 2 change blocks. 
4 lines changed or deleted 2 lines changed or added


 bsonobj.h   bsonobj.h 
skipping to change at line 31 skipping to change at line 31
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <set> #include <set>
#include <list> #include <list>
#include <string> #include <string>
#include <vector> #include <vector>
#include "mongo/bson/bsonelement.h" #include "mongo/bson/bsonelement.h"
#include "mongo/base/string_data.h" #include "mongo/base/string_data.h"
#include "mongo/bson/util/atomic_int.h" #include "mongo/bson/util/atomic_int.h"
#include "mongo/bson/util/builder.h" #include "mongo/bson/util/builder.h"
#include "mongo/util/bufreader.h"
namespace mongo { namespace mongo {
typedef std::set< BSONElement, BSONElementCmpWithoutField > BSONElement Set; typedef std::set< BSONElement, BSONElementCmpWithoutField > BSONElement Set;
typedef std::multiset< BSONElement, BSONElementCmpWithoutField > BSONEl ementMSet; typedef std::multiset< BSONElement, BSONElementCmpWithoutField > BSONEl ementMSet;
/** /**
C++ representation of a "BSON" object -- that is, an extended JSON-s tyle C++ representation of a "BSON" object -- that is, an extended JSON-s tyle
object in a binary representation. object in a binary representation.
skipping to change at line 174 skipping to change at line 175
*/ */
int nFields() const; int nFields() const;
/** adds the field names to the fields set. does NOT clear it (app ends). */ /** adds the field names to the fields set. does NOT clear it (app ends). */
int getFieldNames(std::set<std::string>& fields) const; int getFieldNames(std::set<std::string>& fields) const;
/** @return the specified element. element.eoo() will be true if n ot found. /** @return the specified element. element.eoo() will be true if n ot found.
@param name field to find. supports dot (".") notation to reach into embedded objects. @param name field to find. supports dot (".") notation to reach into embedded objects.
for example "x.y" means "in the nested object in field x, retr ieve field y" for example "x.y" means "in the nested object in field x, retr ieve field y"
*/ */
BSONElement getFieldDotted(const char *name) const; BSONElement getFieldDotted(const StringData &name) const;
/** @return the specified element. element.eoo() will be true if n
ot found.
@param name field to find. supports dot (".") notation to reach
into embedded objects.
for example "x.y" means "in the nested object in field x, retr
ieve field y"
*/
BSONElement getFieldDotted(const std::string& name) const {
return getFieldDotted( name.c_str() );
}
/** Like getFieldDotted(), but expands arrays and returns all match ing objects. /** Like getFieldDotted(), but expands arrays and returns all match ing objects.
* Turning off expandLastArray allows you to retrieve nested array objects instead of * Turning off expandLastArray allows you to retrieve nested array objects instead of
* their contents. * their contents.
*/ */
void getFieldsDotted(const StringData& name, BSONElementSet &ret, b ool expandLastArray = true ) const; void getFieldsDotted(const StringData& name, BSONElementSet &ret, b ool expandLastArray = true ) const;
void getFieldsDotted(const StringData& name, BSONElementMSet &ret, bool expandLastArray = true ) const; void getFieldsDotted(const StringData& name, BSONElementMSet &ret, bool expandLastArray = true ) const;
/** Like getFieldDotted(), but returns first array encountered whil e traversing the /** Like getFieldDotted(), but returns first array encountered whil e traversing the
dotted fields of name. The name variable is updated to represe nt field dotted fields of name. The name variable is updated to represe nt field
skipping to change at line 211 skipping to change at line 205
elements iterated can then be calculated only once each. elements iterated can then be calculated only once each.
@param n number of fieldNames, and number of elements in the fi elds array @param n number of fieldNames, and number of elements in the fi elds array
@param fields if a field is found its element is stored in its corresponding position in this array. @param fields if a field is found its element is stored in its corresponding position in this array.
if not found the array element is unchanged. if not found the array element is unchanged.
*/ */
void getFields(unsigned n, const char **fieldNames, BSONElement *fi elds) const; void getFields(unsigned n, const char **fieldNames, BSONElement *fi elds) const;
/** Get the field of the specified name. eoo() is true on the retur ned /** Get the field of the specified name. eoo() is true on the retur ned
element if not found. element if not found.
*/ */
BSONElement operator[] (const char *field) const { BSONElement operator[] (const StringData& field) const {
return getField(field);
}
BSONElement operator[] (const std::string& field) const {
return getField(field); return getField(field);
} }
BSONElement operator[] (int field) const { BSONElement operator[] (int field) const {
StringBuilder ss; StringBuilder ss;
ss << field; ss << field;
std::string s = ss.str(); std::string s = ss.str();
return getField(s.c_str()); return getField(s.c_str());
} }
/** @return true if field exists */ /** @return true if field exists */
bool hasField( const StringData& name ) const { return !getField(na me).eoo(); } bool hasField( const StringData& name ) const { return !getField(na me).eoo(); }
/** @return true if field exists */ /** @return true if field exists */
bool hasElement(const StringData& name) const { return hasField(nam e); } bool hasElement(const StringData& name) const { return hasField(nam e); }
/** @return "" if DNE or wrong type */ /** @return "" if DNE or wrong type */
const char * getStringField(const char *name) const; const char * getStringField(const StringData& name) const;
/** @return subobject of the given name */ /** @return subobject of the given name */
BSONObj getObjectField(const char *name) const; BSONObj getObjectField(const StringData& name) const;
/** @return INT_MIN if not present - does some type conversions */ /** @return INT_MIN if not present - does some type conversions */
int getIntField(const char *name) const; int getIntField(const StringData& name) const;
/** @return false if not present /** @return false if not present
@see BSONElement::trueValue() @see BSONElement::trueValue()
*/ */
bool getBoolField(const char *name) const; bool getBoolField(const StringData& name) const;
/** @param pattern a BSON obj indicating a set of (un-dotted) field /** @param pattern a BSON obj indicating a set of (un-dotted) field
* names. Element values are ignored. * names. Element values are ignored.
* @return a BSON obj constructed by taking the elements of this o bj * @return a BSON obj constructed by taking the elements of this o bj
* that correspond to the fields in pattern. Field names of the * that correspond to the fields in pattern. Field names of the
* returned object are replaced with the empty string. If field in * returned object are replaced with the empty string. If field in
* pattern is missing, it is omitted from the returned object. * pattern is missing, it is omitted from the returned object.
* *
* Example: if this = {a : 4 , b : 5 , c : 6}) * Example: if this = {a : 4 , b : 5 , c : 6})
* this.extractFieldsUnDotted({a : 1 , c : 1}) -> {"" : 4 , "" : 6 } * this.extractFieldsUnDotted({a : 1 , c : 1}) -> {"" : 4 , "" : 6 }
skipping to change at line 268 skipping to change at line 258
/** extract items from object which match a pattern object. /** extract items from object which match a pattern object.
e.g., if pattern is { x : 1, y : 1 }, builds an object with e.g., if pattern is { x : 1, y : 1 }, builds an object with
x and y elements of this object, if they are present. x and y elements of this object, if they are present.
returns elements with original field names returns elements with original field names
*/ */
BSONObj extractFields(const BSONObj &pattern , bool fillWithNull=fa lse) const; BSONObj extractFields(const BSONObj &pattern , bool fillWithNull=fa lse) const;
BSONObj filterFieldsUndotted(const BSONObj &filter, bool inFilter) const; BSONObj filterFieldsUndotted(const BSONObj &filter, bool inFilter) const;
BSONElement getFieldUsingIndexNames(const char *fieldName, const BS BSONElement getFieldUsingIndexNames(const StringData& fieldName,
ONObj &indexKey) const; const BSONObj &indexKey) const;
/** arrays are bson objects with numeric and increasing field names /** arrays are bson objects with numeric and increasing field names
@return true if field names are numeric and increasing @return true if field names are numeric and increasing
*/ */
bool couldBeArray() const; bool couldBeArray() const;
/** @return the raw data of the object */ /** @return the raw data of the object */
const char *objdata() const { const char *objdata() const {
return _objdata; return _objdata;
} }
skipping to change at line 511 skipping to change at line 502
} }
BSONObj &operator=(const BSONObj &rRHS) { BSONObj &operator=(const BSONObj &rRHS) {
if (this != &rRHS) { if (this != &rRHS) {
_objdata = rRHS._objdata; _objdata = rRHS._objdata;
_holder = rRHS._holder; _holder = rRHS._holder;
} }
return *this; return *this;
} }
/// members for Sorter
struct SorterDeserializeSettings {}; // unused
void serializeForSorter(BufBuilder& buf) const { buf.appendBuf(objdata(
), objsize()); }
static BSONObj deserializeForSorter(BufReader& buf, const SorterDeseria
lizeSettings&) {
const int size = buf.peek<int>();
const void* ptr = buf.skip(size);
return BSONObj(static_cast<const char*>(ptr));
}
int memUsageForSorter() const {
// TODO consider ownedness?
return sizeof(BSONObj) + objsize();
}
private: private:
const char *_objdata; const char *_objdata;
boost::intrusive_ptr< Holder > _holder; boost::intrusive_ptr< Holder > _holder;
void _assertInvalid() const; void _assertInvalid() const;
void init(Holder *holder) { void init(Holder *holder) {
_holder = holder; // holder is now managed by intrusive_ptr _holder = holder; // holder is now managed by intrusive_ptr
init(holder->data); init(holder->data);
} }
 End of changes. 9 change blocks. 
22 lines changed or deleted 24 lines changed or added


 btree.h   btree.h 
skipping to change at line 591 skipping to change at line 591
* - If 'key' and 'prevChildBucket' are set at index i, the btree * - If 'key' and 'prevChildBucket' are set at index i, the btree
* ordering properties will be maintained. * ordering properties will be maintained.
* Postconditions: * Postconditions:
* - The specified key is set at index i, replacing the existing * - The specified key is set at index i, replacing the existing
* _KeyNode data and without shifting any other _KeyNode objects . * _KeyNode data and without shifting any other _KeyNode objects .
*/ */
void setKey( int i, const DiskLoc recordLoc, const Key& key, const DiskLoc prevChildBucket ); void setKey( int i, const DiskLoc recordLoc, const Key& key, const DiskLoc prevChildBucket );
}; };
class IndexDetails; class IndexDetails;
class IndexInsertionContinuation;
template< class V>
struct IndexInsertionContinuationImpl;
/** /**
* This class adds functionality for manipulating buckets that are asse mbled * This class adds functionality for manipulating buckets that are asse mbled
* in a tree. The requirements for const and non const functions and * in a tree. The requirements for const and non const functions and
* arguments are generally the same as in BtreeBucket. Because this cl ass * arguments are generally the same as in BtreeBucket. Because this cl ass
* deals with tree structure, some functions that are marked const may * deals with tree structure, some functions that are marked const may
* trigger modification of another node in the btree or potentially of the * trigger modification of another node in the btree or potentially of the
* current node. In such cases, the function's implementation explicit ly * current node. In such cases, the function's implementation explicit ly
* casts away const when indicating an intent to write to the durabilit y * casts away const when indicating an intent to write to the durabilit y
* layer. The DiskLocs provided to such functions should be passed by * layer. The DiskLocs provided to such functions should be passed by
skipping to change at line 626 skipping to change at line 623
* *
* TODO There are several cases in which the 'this' pointer is invalida ted * TODO There are several cases in which the 'this' pointer is invalida ted
* as a result of deallocation. A separate class representing a btree would * as a result of deallocation. A separate class representing a btree would
* alleviate some fragile cases where the implementation must currently * alleviate some fragile cases where the implementation must currently
* behave correctly if the 'this' pointer is suddenly invalidated by a * behave correctly if the 'this' pointer is suddenly invalidated by a
* callee. * callee.
*/ */
template< class V > template< class V >
class BtreeBucket : public BucketBasics<V> { class BtreeBucket : public BucketBasics<V> {
friend class BtreeCursor; friend class BtreeCursor;
friend struct IndexInsertionContinuationImpl<V>;
public: public:
// make compiler happy: // make compiler happy:
typedef typename V::Key Key; typedef typename V::Key Key;
typedef typename V::KeyOwned KeyOwned; typedef typename V::KeyOwned KeyOwned;
typedef typename BucketBasics<V>::KeyNode KeyNode; typedef typename BucketBasics<V>::KeyNode KeyNode;
typedef typename BucketBasics<V>::_KeyNode _KeyNode; typedef typename BucketBasics<V>::_KeyNode _KeyNode;
typedef typename BucketBasics<V>::Loc Loc; typedef typename BucketBasics<V>::Loc Loc;
const _KeyNode& k(int i) const { return static_cast< const Buck etBasics<V> * >(this)->k(i); } const _KeyNode& k(int i) const { return static_cast< const Buck etBasics<V> * >(this)->k(i); }
protected: protected:
_KeyNode& k(int i) { return static_cast< BucketBasi cs<V> * >(this)->_k(i); } _KeyNode& k(int i) { return static_cast< BucketBasi cs<V> * >(this)->_k(i); }
skipping to change at line 703 skipping to change at line 699
* - If key / recordLoc exist in the btree as a used key, @throw * - If key / recordLoc exist in the btree as a used key, @throw
* exception 10287 and no change. * exception 10287 and no change.
* - If key / recordLoc do not exist in the btree, they are insert ed * - If key / recordLoc do not exist in the btree, they are insert ed
* and @return 0. The root of the btree may be changed, so * and @return 0. The root of the btree may be changed, so
* 'this'/thisLoc may no longer be the root upon return. * 'this'/thisLoc may no longer be the root upon return.
*/ */
int bt_insert(const DiskLoc thisLoc, const DiskLoc recordLoc, int bt_insert(const DiskLoc thisLoc, const DiskLoc recordLoc,
const BSONObj& key, const Ordering &order, bool dupsA llowed, const BSONObj& key, const Ordering &order, bool dupsA llowed,
IndexDetails& idx, bool toplevel = true) const; IndexDetails& idx, bool toplevel = true) const;
/** does the insert in two steps - can then use an upgradable lock
for step 1, which
is the part which may have page faults. also that step is most
of the computational work.
*/
void twoStepInsert(DiskLoc thisLoc, IndexInsertionContinuationImpl<
V> &c, bool dupsAllowed) const;
/** /**
* Preconditions: * Preconditions:
* - 'key' has a valid schema for this index, and may have objsize () > KeyMax. * - 'key' has a valid schema for this index, and may have objsize () > KeyMax.
* Postconditions: * Postconditions:
* - If key / recordLoc are in the btree, they are removed (possib ly * - If key / recordLoc are in the btree, they are removed (possib ly
* by being marked as an unused key), @return true, and potentia lly * by being marked as an unused key), @return true, and potentia lly
* invalidate 'this' / thisLoc and change the head. * invalidate 'this' / thisLoc and change the head.
* - If key / recordLoc are not in the btree, @return false and do nothing. * - If key / recordLoc are not in the btree, @return false and do nothing.
*/ */
bool unindex(const DiskLoc thisLoc, IndexDetails& id, const BSONObj & key, const DiskLoc recordLoc) const; bool unindex(const DiskLoc thisLoc, IndexDetails& id, const BSONObj & key, const DiskLoc recordLoc) const;
skipping to change at line 960 skipping to change at line 951
*/ */
void insertHere(const DiskLoc thisLoc, int keypos, void insertHere(const DiskLoc thisLoc, int keypos,
const DiskLoc recordLoc, const Key& key, const Orde ring &order, const DiskLoc recordLoc, const Key& key, const Orde ring &order,
const DiskLoc lchild, const DiskLoc rchild, IndexDe tails &idx) const; const DiskLoc lchild, const DiskLoc rchild, IndexDe tails &idx) const;
/** bt_insert() is basically just a wrapper around this. */ /** bt_insert() is basically just a wrapper around this. */
int _insert(const DiskLoc thisLoc, const DiskLoc recordLoc, int _insert(const DiskLoc thisLoc, const DiskLoc recordLoc,
const Key& key, const Ordering &order, bool dupsAllowed , const Key& key, const Ordering &order, bool dupsAllowed ,
const DiskLoc lChild, const DiskLoc rChild, IndexDetail s &idx) const; const DiskLoc lChild, const DiskLoc rChild, IndexDetail s &idx) const;
void insertStepOne(
DiskLoc thisLoc, IndexInsertionContinuationImpl<V>& c, bool
dupsAllowed) const;
bool find(const IndexDetails& idx, const Key& key, const DiskLoc &r ecordLoc, const Ordering &order, int& pos, bool assertIfDup) const; bool find(const IndexDetails& idx, const Key& key, const DiskLoc &r ecordLoc, const Ordering &order, int& pos, bool assertIfDup) const;
static bool customFind( int l, int h, const BSONObj &keyBegin, int keyBeginLen, bool afterKey, const vector< const BSONElement * > &keyEnd, co nst vector< bool > &keyEndInclusive, const Ordering &order, int direction, DiskLoc &thisLoc, int &keyOfs, pair< DiskLoc, int > &bestParent ) ; static bool customFind( int l, int h, const BSONObj &keyBegin, int keyBeginLen, bool afterKey, const vector< const BSONElement * > &keyEnd, co nst vector< bool > &keyEndInclusive, const Ordering &order, int direction, DiskLoc &thisLoc, int &keyOfs, pair< DiskLoc, int > &bestParent ) ;
static void findLargestKey(const DiskLoc& thisLoc, DiskLoc& largest Loc, int& largestKey); static void findLargestKey(const DiskLoc& thisLoc, DiskLoc& largest Loc, int& largestKey);
static int customBSONCmp( const BSONObj &l, const BSONObj &rBegin, int rBeginLen, bool rSup, const vector< const BSONElement * > &rEnd, const vector< bool > &rEndInclusive, const Ordering &o, int direction ); static int customBSONCmp( const BSONObj &l, const BSONObj &rBegin, int rBeginLen, bool rSup, const vector< const BSONElement * > &rEnd, const vector< bool > &rEndInclusive, const Ordering &o, int direction );
/** If child is non null, set its parent to thisLoc */ /** If child is non null, set its parent to thisLoc */
static void fix(const DiskLoc thisLoc, const DiskLoc child); static void fix(const DiskLoc thisLoc, const DiskLoc child);
/** /**
* Preconditions: * Preconditions:
 End of changes. 4 change blocks. 
16 lines changed or deleted 0 lines changed or added


 btreecursor.h   btreecursor.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 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 <set>
#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/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.
* *
* A BtreeCursor iterates over all keys of a specified btree that are w ithin the provided * A BtreeCursor iterates over all keys of a specified btree that are w ithin the provided
* btree bounds, using the specified direction of traversal. * btree bounds, using the specified direction of traversal.
* *
* Notes on specifying btree bounds: * Notes on specifying btree bounds:
* *
* A BtreeCursor may be initialized with the 'startKey' and 'endKey' bo unds of an interval of * A BtreeCursor may be initialized with the 'startKey' and 'endKey' bo unds of an interval of
* keys within a btree. A BtreeCursor may alternatively be initialized with a FieldRangeVector * keys within a btree. A BtreeCursor may alternatively be initialized with a FieldRangeVector
* describing a list of intervals for every field of the btree index. * describing a list of intervals for every field of the btree index.
* *
* Notes on inheritance:
*
* BtreeCursor is an abstract class. Btrees come in different versions
, with different storage
* formats. The versions are v0 and v1 as of this writing. Member fun
ctions implemented in
* BtreeCursor are storage format agnostic. Classes derived from Btree
Cursor implement the
* format specific bits.
*
* Notes on the yielding implementation: * Notes on the yielding implementation:
* *
* When an operation using a BtreeCursor yields the database mutex that locks the btree data * When an operation using a BtreeCursor yields the database mutex that locks the btree data
* structure, the btree may be modified. When the operation regains th e database mutex, the * structure, the btree may be modified. When the operation regains th e database mutex, the
* BtreeCursor can relocate its position in the modified btree and cont inue iteration from that * BtreeCursor can relocate its position in the modified btree and cont inue iteration from that
* point. * point.
* *
* Before the database mutex is yielded, a BtreeCursor records its posi tion (noteLoc()). A * Before the database mutex is yielded, a BtreeCursor records its posi tion (noteLoc()). A
* recorded btree position consists of a btree bucket, bucket key offse t, and unique btree key. * recorded btree position consists of a btree bucket, bucket key offse t, and unique btree key.
* *
skipping to change at line 84 skipping to change at line 81
const BSONObj& endKey, const BSONObj& endKey,
bool endKeyInclusive, bool endKeyInclusive,
int direction ); int direction );
static BtreeCursor* make( NamespaceDetails* namespaceDetails, static BtreeCursor* make( NamespaceDetails* namespaceDetails,
const IndexDetails& id, const IndexDetails& id,
const shared_ptr<FieldRangeVector>& bound s, const shared_ptr<FieldRangeVector>& bound s,
int singleIntervalLimit, int singleIntervalLimit,
int direction ); int direction );
virtual bool ok() { return !bucket.isNull(); } virtual bool ok();
virtual bool advance(); virtual bool advance();
virtual void noteLocation(); // updates keyAtKeyOfs... virtual void noteLocation();
virtual void checkLocation() = 0; virtual void checkLocation();
virtual bool supportGetMore() { return true; } virtual bool supportGetMore() { return true; }
virtual bool supportYields() { return true; } virtual bool supportYields() { return true; }
/** /**
* used for multikey index traversal to avoid sending back dups. se e Matcher::matches(). * used for multikey index traversal to avoid sending back dups. se e Matcher::matches().
* if a multikey index traversal: * if a multikey index traversal:
* if loc has already been sent, returns true. * if loc has already been sent, returns true.
* otherwise, marks loc as sent. * otherwise, marks loc as sent.
* @return false if the loc has not been seen * @return false if the loc has not been seen
*/ */
skipping to change at line 109 skipping to change at line 106
if( _multikey ) { if( _multikey ) {
pair<set<DiskLoc>::iterator, bool> p = _dups.insert(loc); pair<set<DiskLoc>::iterator, bool> p = _dups.insert(loc);
return !p.second; return !p.second;
} }
return false; return false;
} }
virtual bool modifiedKeys() const { return _multikey; } virtual bool modifiedKeys() const { return _multikey; }
virtual bool isMultiKey() const { return _multikey; } virtual bool isMultiKey() const { return _multikey; }
/** returns BSONObj() if ofs is out of range */ virtual BSONObj currKey() const;
virtual BSONObj keyAt(int ofs) const = 0;
virtual BSONObj currKey() const = 0;
virtual BSONObj indexKeyPattern() { return _order; } virtual BSONObj indexKeyPattern() { return _order; }
virtual void aboutToDeleteBucket(const DiskLoc& b) { virtual DiskLoc currLoc();
if ( bucket == b )
keyOfs = -1;
}
virtual DiskLoc currLoc() = 0;
virtual DiskLoc refLoc() { return currLoc(); } virtual DiskLoc refLoc() { return currLoc(); }
virtual Record* _current() { return currLoc().rec(); } virtual Record* _current() { return currLoc().rec(); }
virtual BSONObj current() { return BSONObj::make(_current()); } virtual BSONObj current() { return BSONObj::make(_current()); }
virtual string toString(); virtual string toString();
BSONObj prettyKey( const BSONObj& key ) const { BSONObj prettyKey( const BSONObj& key ) const {
return key.replaceFieldNames( indexDetails.keyPattern() ).clien tReadable(); return key.replaceFieldNames( indexDetails.keyPattern() ).clien tReadable();
} }
virtual BSONObj prettyIndexBounds() const; virtual BSONObj prettyIndexBounds() const;
skipping to change at line 146 skipping to change at line 135
virtual void setMatcher( shared_ptr<CoveredIndexMatcher> matcher ) { _matcher = matcher; } virtual void setMatcher( shared_ptr<CoveredIndexMatcher> matcher ) { _matcher = matcher; }
virtual const Projection::KeyOnly* keyFieldsOnly() const { return _ keyFieldsOnly.get(); } virtual const Projection::KeyOnly* keyFieldsOnly() const { return _ keyFieldsOnly.get(); }
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; }
/** for debugging only */ // XXX(hk): geo uses this for restoring state...for now.
const DiskLoc getBucket() const { return bucket; } virtual const DiskLoc getBucket() const;
int getKeyOfs() const { return keyOfs; } // XXX(hk): geo uses this too. :(
virtual int getKeyOfs() const;
// just for unit tests // XXX(hk): deletions go through a lengthy, scary path (btree.cpp -
virtual bool curKeyHasChild() = 0; > clientcursor.cpp ->
// cursor.cpp -> btreecursor.cpp) and this is part of it...for now.
virtual void aboutToDeleteBucket(const DiskLoc& b);
protected: 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,
int singleIntervalLimit, int singleIntervalLimit,
int direction ); int direction );
/**
* Our btrees may (rarely) have "unused" keys when items are delete
d.
* Skip past them.
*/
virtual bool skipUnusedKeys() = 0;
bool skipOutOfRangeKeysAndCheckEnd(); bool skipOutOfRangeKeysAndCheckEnd();
/** /**
* Attempt to locate the next btree key matching _bounds. This may mean advancing to the * Attempt to locate the next btree key matching _bounds. This may mean advancing to the
* next successive key in the btree, or skipping to a new position in the btree. If an * next successive key in the btree, or skipping to a new position in the btree. If an
* internal iteration cutoff is reached before a matching key is fo und, then the search for * internal iteration cutoff is reached before a matching key is fo und, then the search for
* a matching key will be aborted, leaving the cursor pointing at a key that is not within * a matching key will be aborted, leaving the cursor pointing at a key that is not within
* bounds. * bounds.
*/ */
void skipAndCheck(); void skipAndCheck();
void checkEnd(); void checkEnd();
/** selective audits on construction */
void audit();
virtual void _audit() = 0;
virtual DiskLoc _locate(const BSONObj& key, const DiskLoc& loc) = 0
;
virtual DiskLoc _advance(const DiskLoc& thisLoc,
int& keyOfs,
int direction,
const char* caller) = 0;
virtual void _advanceTo(DiskLoc& thisLoc,
int& keyOfs,
const BSONObj& keyBegin,
int keyBeginLen,
bool afterKey,
const vector<const BSONElement*>& keyEnd,
const vector<bool>& keyEndInclusive,
const Ordering& order,
int direction ) = 0;
/** set initial bucket */ /** set initial bucket */
void initWithoutIndependentFieldRanges(); void initWithoutIndependentFieldRanges();
/** if afterKey is true, we want the first key with values of the k eyBegin fields greater than keyBegin */ /** if afterKey is true, we want the first key with values of the k eyBegin fields greater than keyBegin */
void advanceTo( const BSONObj& keyBegin, void advanceTo( const BSONObj& keyBegin,
int keyBeginLen, int keyBeginLen,
bool afterKey, bool afterKey,
const vector<const BSONElement*>& keyEnd, const vector<const BSONElement*>& keyEnd,
const vector<bool>& keyEndInclusive ); const vector<bool>& keyEndInclusive );
void _finishConstructorInit();
static BtreeCursor* make( NamespaceDetails* nsd,
int idxNo,
const IndexDetails& indexDetails );
// these are set in the construtor // these are set in the construtor
NamespaceDetails* const d; NamespaceDetails* const d;
const int idxNo; const int idxNo;
const IndexDetails& indexDetails; const IndexDetails& indexDetails;
// These variables are for query-level index scanning.
// these are all set in init() // these are all set in init()
set<DiskLoc> _dups; set<DiskLoc> _dups;
BSONObj startKey; BSONObj startKey;
BSONObj endKey; BSONObj endKey;
bool _endKeyInclusive; bool _endKeyInclusive;
bool _multikey; // this must be updated every getmore batch in case someone added a multikey bool _multikey; // this must be updated every getmore batch in case someone added a multikey
BSONObj _order; // this is the same as indexDetails.keyPattern() BSONObj _order; // this is the same as indexDetails.keyPattern()
Ordering _ordering; int _direction;
DiskLoc bucket;
int keyOfs;
int _direction; // 1=fwd,-1=reverse
BSONObj keyAtKeyOfs; // so we can tell if things moved around on us
between the query and the getMore call
DiskLoc locAtKeyOfs;
shared_ptr<FieldRangeVector> _bounds; shared_ptr<FieldRangeVector> _bounds;
auto_ptr<FieldRangeVectorIterator> _boundsIterator; auto_ptr<FieldRangeVectorIterator> _boundsIterator;
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;
private: // These variables are for index traversal.
void _finishConstructorInit(); scoped_ptr<IndexCursor> _indexCursor;
static BtreeCursor* make( NamespaceDetails* nsd, scoped_ptr<IndexAccessMethod> _indexAM;
int idxNo, scoped_ptr<IndexDescriptor> _indexDescriptor;
const IndexDetails& indexDetails ); bool _hitEnd;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 15 change blocks. 
72 lines changed or deleted 30 lines changed or added


 bufreader.h   bufreader.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 <boost/noncopyable.hpp>
#include "mongo/bson/util/builder.h"
#include "mongo/util/assert_util.h"
namespace mongo { namespace mongo {
/** helper to read and parse a block of memory /** helper to read and parse a block of memory
methods throw the eof exception if the operation would pass the end of the methods throw the eof exception if the operation would pass the end of the
buffer with which we are working. buffer with which we are working.
*/ */
class BufReader : boost::noncopyable { class BufReader : boost::noncopyable {
public: public:
class eof : public std::exception { class eof : public std::exception {
public: public:
skipping to change at line 49 skipping to change at line 54
/** read in the object specified, and advance buffer pointer */ /** read in the object specified, and advance buffer pointer */
template <typename T> template <typename T>
void read(T &t) { void read(T &t) {
T* cur = (T*) _pos; T* cur = (T*) _pos;
T *next = cur + 1; T *next = cur + 1;
if( _end < next ) throw eof(); if( _end < next ) throw eof();
t = *cur; t = *cur;
_pos = next; _pos = next;
} }
/** verify we can look at t, but do not advance */ /** read in and return an object of the specified type, and advance
buffer pointer */
template <typename T>
T read() {
T out;
read(out);
return out;
}
/** read in the object specified, but do not advance buffer pointer
*/
template <typename T> template <typename T>
void peek(T &t) { void peek(T &t) const {
T* cur = (T*) _pos; T* cur = (T*) _pos;
T *next = cur + 1; T *next = cur + 1;
if( _end < next ) throw eof(); if( _end < next ) throw eof();
t = *cur; t = *cur;
} }
/** read in and return an object of the specified type, but do not
advance buffer pointer */
template <typename T>
T peek() const {
T out;
peek(out);
return out;
}
/** return current offset into buffer */ /** return current offset into buffer */
unsigned offset() const { return (char*)_pos - (char*)_start; } unsigned offset() const { return (char*)_pos - (char*)_start; }
/** return remaining bytes */ /** return remaining bytes */
unsigned remaining() const { return (char*)_end -(char*)_pos; } unsigned remaining() const { return (char*)_end -(char*)_pos; }
/** back up by nbytes */ /** back up by nbytes */
void rewind(unsigned nbytes) { void rewind(unsigned nbytes) {
_pos = ((char *) _pos) - nbytes; _pos = ((char *) _pos) - nbytes;
verify( _pos >= _start ); verify( _pos >= _start );
 End of changes. 4 change blocks. 
2 lines changed or deleted 26 lines changed or added


 client.h   client.h 
skipping to change at line 77 skipping to change at line 77
* call this when your thread starts. * call this when your thread starts.
*/ */
static Client& initThread(const char *desc, AbstractMessagingPort * mp = 0); static Client& initThread(const char *desc, AbstractMessagingPort * mp = 0);
static void initThreadIfNotAlready(const char *desc) { static void initThreadIfNotAlready(const char *desc) {
if( currentClient.get() ) if( currentClient.get() )
return; return;
initThread(desc); initThread(desc);
} }
/**
* Allows detaching a thread from a Client object. Use for testing
and for the creation
* of non-connection clients.
*/
static void resetThread( const StringData& origThreadName );
/** this has to be called as the client goes away, but before threa d termination /** this has to be called as the client goes away, but before threa d termination
* @return true if anything was done * @return true if anything was done
*/ */
bool shutdown(); bool shutdown();
string clientAddress(bool includePort=false) const; string clientAddress(bool includePort=false) const;
CurOp* curop() const { return _curOp; } CurOp* curop() const { return _curOp; }
Context* getContext() const { return _context; } Context* getContext() const { return _context; }
Database* database() const { return _context ? _context->db() : 0; } Database* database() const { return _context ? _context->db() : 0; }
const char *ns() const { return _context->ns(); } const char *ns() const { return _context->ns(); }
skipping to change at line 116 skipping to change at line 122
bool hasWrittenThisPass() const { return _hasWrittenThisPass; } bool hasWrittenThisPass() const { return _hasWrittenThisPass; }
void writeHappened() { _hasWrittenThisPass = true; } void writeHappened() { _hasWrittenThisPass = true; }
void newTopLevelRequest() { _hasWrittenThisPass = false; } void newTopLevelRequest() { _hasWrittenThisPass = false; }
bool allowedToThrowPageFaultException() const; bool allowedToThrowPageFaultException() const;
LockState& lockState() { return _ls; } LockState& lockState() { return _ls; }
private: private:
Client(const char *desc, AbstractMessagingPort *p = 0); Client(const std::string& desc, AbstractMessagingPort *p = 0);
friend class CurOp; friend class CurOp;
ConnectionId _connectionId; // > 0 for things "conn", 0 otherwise ConnectionId _connectionId; // > 0 for things "conn", 0 otherwise
string _threadId; // "" on non support systems string _threadId; // "" on non support systems
CurOp * _curOp; CurOp * _curOp;
Context * _context; Context * _context;
bool _shutdown; // to track if Client::shutdown() gets called bool _shutdown; // to track if Client::shutdown() gets called
std::string _desc; std::string _desc;
bool _god; bool _god;
OpTime _lastOp; OpTime _lastOp;
BSONObj _handshake; BSONObj _handshake;
 End of changes. 2 change blocks. 
1 lines changed or deleted 8 lines changed or added


 clientcursor.h   clientcursor.h 
skipping to change at line 181 skipping to change at line 181
DiskLoc lastLoc() const { return _lastLoc; } DiskLoc lastLoc() const { return _lastLoc; }
/* Get rid of cursors for namespaces 'ns'. When dropping a db, ns i s "dbname." /* Get rid of cursors for namespaces 'ns'. When dropping a db, ns i s "dbname."
Used by drop, dropIndexes, dropDatabase. Used by drop, dropIndexes, dropDatabase.
*/ */
static void invalidate(const char *ns); static void invalidate(const char *ns);
/** /**
* @param microsToSleep -1 : ask client * @param microsToSleep -1 : ask client
* 0 : pthread_yield or equivilant * >=0 : sleep for that amount
* >0 : sleep for that amount
* @param recordToLoad after yielding lock, load this record with o nly mmutex * @param recordToLoad after yielding lock, load this record with o nly mmutex
* do a dbtemprelease * do a dbtemprelease
* note: caller should check matcher.docMatcher().atomic() first an d not yield if atomic - * note: caller should check matcher.docMatcher().atomic() first an d not yield if atomic -
* we don't do herein as this->matcher (above) is only initia lized for true queries/getmore. * we don't do herein as this->matcher (above) is only initia lized for true queries/getmore.
* (ie not set for remote/update) * (ie not set for remote/update)
* @return if the cursor is still valid. * @return if the cursor is still valid.
* if false is returned, then this ClientCursor should be c onsidered deleted - * if false is returned, then this ClientCursor should be c onsidered deleted -
* in fact, the whole database could be gone. * in fact, the whole database could be gone.
*/ */
bool yield( int microsToSleep = -1, Record * recordToLoad = 0 ); bool yield( int microsToSleep = -1 , Record * recordToLoad = 0 );
enum RecordNeeds { enum RecordNeeds {
DontNeed = -1 , MaybeCovered = 0 , WillNeed = 100 DontNeed = -1 , MaybeCovered = 0 , WillNeed = 100
}; };
/** /**
* @param needRecord whether or not the next record has to be read from disk for sure * @param needRecord whether or not the next record has to be read from disk for sure
* if this is true, will yield of next record isn 't in memory * if this is true, will yield of next record isn 't in memory
* @param yielded true if a yield occurred, and potentially if a yi eld did not occur * @param yielded true if a yield occurred, and potentially if a yi eld did not occur
* @return same as yield() * @return same as yield()
skipping to change at line 376 skipping to change at line 375
/** 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 informAboutToDeleteBucket(const DiskLoc& b);
static void aboutToDelete(const NamespaceDetails* nsd, const DiskLo static void aboutToDelete( const StringData& ns,
c& dl); const NamespaceDetails* nsd,
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; } CCByLoc& byLoc() { return _db->ccByLoc; }
 End of changes. 3 change blocks. 
5 lines changed or deleted 5 lines changed or added


 cloner.h   cloner.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 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/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/sort_phase_one.h"
namespace mongo { namespace mongo {
struct CloneOptions; struct CloneOptions;
class IndexSpec;
class DBClientBase; class DBClientBase;
class DBClientCursor; class DBClientCursor;
class Query; class Query;
class Cloner: boost::noncopyable { class Cloner: boost::noncopyable {
public: public:
Cloner(); Cloner();
/** /**
* slaveOk - if true it is ok if the source of the data is !is master. * slaveOk - if true it is ok if the source of the data is !is master.
* useReplAuth - use the credentials we normally use as a replicat ion slave for the cloning * useReplAuth - use the credentials we normally use as a replicat ion slave for the cloning
skipping to change at line 61 skipping to change at line 59
bool go(const char *masterHost, const CloneOptions& opts, string& e rrmsg, int *errCode = 0); bool go(const char *masterHost, const CloneOptions& opts, string& e rrmsg, int *errCode = 0);
bool copyCollection(const string& ns, const BSONObj& query, string& errmsg, bool copyCollection(const string& ns, const BSONObj& query, string& errmsg,
bool mayYield, bool mayBeInterrupted, bool copy Indexes = true, bool mayYield, bool mayBeInterrupted, bool copy Indexes = true,
bool logForRepl = true ); bool logForRepl = true );
/** /**
* validate the cloner query was successful * validate the cloner query was successful
* @param cur Cursor the query was executed on * @param cur Cursor the query was executed on
* @param errCode out Error code encountered during the query * @param errCode out Error code encountered during the query
* @param errmsg out Error message encountered during the query
*/ */
static bool validateQueryResults(const auto_ptr<DBClientCursor>& cu static bool validateQueryResults(const auto_ptr<DBClientCursor>& cu
r, int32_t* errCode); r, int32_t* errCode,
string& errmsg);
/** /**
* @param errmsg out - Error message (if encountered). * @param errmsg out - Error message (if encountered).
* @param slaveOk - if true it is ok if the source of the data is !ismaster. * @param slaveOk - if true it is ok if the source of the data is !ismaster.
* @param useReplAuth - use the credentials we normally use as a re plication slave for the * @param useReplAuth - use the credentials we normally use as a re plication slave for the
* cloning. * cloning.
* @param snapshot - use $snapshot mode for copying collections. note this should not be * @param snapshot - use $snapshot mode for copying collections. note this should not be
* used when it isn't required, as it will be slower. for example * used when it isn't required, as it will be slower. for example
* repairDatabase need not use it. * repairDatabase need not use it.
* @param errCode out - If provided, this will be set on error to t he server's error code. * @param errCode out - If provided, this will be set on error to t he server's error code.
skipping to change at line 95 skipping to change at line 95
/** /**
* Copy a collection (and indexes) from a remote host * Copy a collection (and indexes) from a remote host
*/ */
static bool copyCollectionFromRemote(const string& host, const stri ng& ns, string& errmsg); static bool copyCollectionFromRemote(const string& host, const stri ng& ns, string& errmsg);
private: private:
void copy(const char *from_ns, const char *to_ns, bool isindex, boo l logForRepl, void copy(const char *from_ns, const char *to_ns, bool isindex, boo l logForRepl,
bool masterSameProcess, bool slaveOk, bool mayYield, bool mayBeInterrupted, bool masterSameProcess, bool slaveOk, bool mayYield, bool mayBeInterrupted,
Query q); Query q);
// index presort info
typedef struct {
IndexSpec spec;
SortPhaseOne preSortPhase;
} PreSortDetails;
typedef map<string, PreSortDetails> SortersForIndex; // map from in
dex name to presorter
typedef map<string, SortersForIndex> SortersForNS; // map from ns
to indices/sorters
struct Fun; struct Fun;
auto_ptr<DBClientBase> _conn; auto_ptr<DBClientBase> _conn;
SortersForNS _sortersForNS;
}; };
struct CloneOptions { struct CloneOptions {
CloneOptions() { CloneOptions() {
logForRepl = true; logForRepl = true;
slaveOk = false; slaveOk = false;
useReplAuth = false; useReplAuth = false;
snapshot = true; snapshot = true;
mayYield = true; mayYield = true;
 End of changes. 6 change blocks. 
16 lines changed or deleted 4 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 "namespace.h" #include "mongo/db/namespace.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 111 skipping to change at line 111
/* 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; }
virtual void help( stringstream& help ) const; virtual void help( stringstream& help ) const;
/* Return true if authentication and security applies to the comman
ds. Some commands
(e.g., getnonce, authenticate) can be done by anyone even unauth
orized.
*/
virtual bool requiresAuth() { return true; }
/** /**
* Appends to "*out" the privileges required to run this command on database "dbname" with * Appends to "*out" the privileges required to run this command on database "dbname" with
* the invocation described by "cmdObj". * the invocation described by "cmdObj".
*/ */
virtual void addRequiredPrivileges(const std::string& dbname, virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj, const BSONObj& cmdObj,
std::vector<Privilege>* out) = 0 ; std::vector<Privilege>* out) = 0 ;
/* 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.
skipping to change at line 157 skipping to change at line 152
return BSONObj(); return BSONObj();
} }
static void logIfSlow( const Timer& cmdTimer, const string& msg); static void logIfSlow( const Timer& cmdTimer, const string& msg);
static map<string,Command*> * _commands; static map<string,Command*> * _commands;
static map<string,Command*> * _commandsByBestName; static map<string,Command*> * _commandsByBestName;
static map<string,Command*> * _webCommands; static map<string,Command*> * _webCommands;
public: public:
// Stop all index builds required to run this command and return in
dex builds killed.
virtual std::vector<BSONObj> stopIndexBuilds(const std::string& dbn
ame,
const BSONObj& cmdObj)
;
static const map<string,Command*>* commandsByBestName() { return _c ommandsByBestName; } static const map<string,Command*>* commandsByBestName() { return _c ommandsByBestName; }
static const map<string,Command*>* webCommands() { return _webComma nds; } static const map<string,Command*>* webCommands() { return _webComma nds; }
/** @return if command was found */ /** @return if command was found */
static void runAgainstRegistered(const char *ns, static void runAgainstRegistered(const char *ns,
BSONObj& jsobj, BSONObj& jsobj,
BSONObjBuilder& anObjBuilder, BSONObjBuilder& anObjBuilder,
int queryOptions = 0); int queryOptions = 0);
static LockType locktype( const string& name ); static LockType locktype( const string& name );
static Command * findCommand( const string& name ); static Command * findCommand( const string& name );
// For mongod and webserver. // For mongod and webserver.
 End of changes. 2 change blocks. 
7 lines changed or deleted 7 lines changed or added


 compiler.h   compiler.h 
// Copyright 2012 the V8 project authors. All rights reserved. // @file mongo/platform/compiler.h
// 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_COMPILER_H_ /*
#define V8_COMPILER_H_ * Copyright 2012 10gen Inc.
*
#include "allocation.h" * Licensed under the Apache License, Version 2.0 (the "License");
#include "ast.h" * you may not use this file except in compliance with the License.
#include "zone.h" * You may obtain a copy of the License at
*
namespace v8 { * http://www.apache.org/licenses/LICENSE-2.0
namespace internal { *
* Unless required by applicable law or agreed to in writing, software
class ScriptDataImpl; * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// CompilationInfo encapsulates some information known at compile time. It * See the License for the specific language governing permissions and
// is constructed based on the resources available at compile-time. * limitations under the License.
class CompilationInfo { */
public:
CompilationInfo(Handle<Script> script, Zone* zone); #pragma once
CompilationInfo(Handle<SharedFunctionInfo> shared_info, Zone* zone);
CompilationInfo(Handle<JSFunction> closure, Zone* zone); /**
* Include "mongo/platform/compiler.h" to get compiler-specific macro defin
virtual ~CompilationInfo(); itions and utilities.
*/
Isolate* isolate() {
ASSERT(Isolate::Current() == isolate_); #if defined(_MSC_VER)
return isolate_; #include "mongo/platform/compiler_msvc.h"
} #elif defined(__GNUC__)
Zone* zone() { #include "mongo/platform/compiler_gcc.h"
return zone_; #else
} #error "Unsupported compiler family"
bool is_lazy() const { return IsLazy::decode(flags_); }
bool is_eval() const { return IsEval::decode(flags_); }
bool is_global() const { return IsGlobal::decode(flags_); }
bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; }
bool is_extended_mode() const { return language_mode() == EXTENDED_MODE;
}
LanguageMode language_mode() const {
return LanguageModeField::decode(flags_);
}
bool is_in_loop() const { return IsInLoop::decode(flags_); }
FunctionLiteral* function() const { return function_; }
Scope* scope() const { return scope_; }
Scope* global_scope() const { return global_scope_; }
Handle<Code> code() const { return code_; }
Handle<JSFunction> closure() const { return closure_; }
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
Handle<Script> script() const { return script_; }
v8::Extension* extension() const { return extension_; }
ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
Handle<Context> calling_context() const { return calling_context_; }
int osr_ast_id() const { return osr_ast_id_; }
void MarkAsEval() {
ASSERT(!is_lazy());
flags_ |= IsEval::encode(true);
}
void MarkAsGlobal() {
ASSERT(!is_lazy());
flags_ |= IsGlobal::encode(true);
}
void SetLanguageMode(LanguageMode language_mode) {
ASSERT(this->language_mode() == CLASSIC_MODE ||
this->language_mode() == language_mode ||
language_mode == EXTENDED_MODE);
flags_ = LanguageModeField::update(flags_, language_mode);
}
void MarkAsInLoop() {
ASSERT(is_lazy());
flags_ |= IsInLoop::encode(true);
}
void MarkAsNative() {
flags_ |= IsNative::encode(true);
}
bool is_native() const {
return IsNative::decode(flags_);
}
void SetFunction(FunctionLiteral* literal) {
ASSERT(function_ == NULL);
function_ = literal;
}
void SetScope(Scope* scope) {
ASSERT(scope_ == NULL);
scope_ = scope;
}
void SetGlobalScope(Scope* global_scope) {
ASSERT(global_scope_ == NULL);
global_scope_ = global_scope;
}
void SetCode(Handle<Code> code) { code_ = code; }
void SetExtension(v8::Extension* extension) {
ASSERT(!is_lazy());
extension_ = extension;
}
void SetPreParseData(ScriptDataImpl* pre_parse_data) {
ASSERT(!is_lazy());
pre_parse_data_ = pre_parse_data;
}
void SetCallingContext(Handle<Context> context) {
ASSERT(is_eval());
calling_context_ = context;
}
void SetOsrAstId(int osr_ast_id) {
ASSERT(IsOptimizing());
osr_ast_id_ = osr_ast_id;
}
void MarkCompilingForDebugging(Handle<Code> current_code) {
ASSERT(mode_ != OPTIMIZE);
ASSERT(current_code->kind() == Code::FUNCTION);
flags_ |= IsCompilingForDebugging::encode(true);
if (current_code->is_compiled_optimizable()) {
EnableDeoptimizationSupport();
} else {
mode_ = CompilationInfo::NONOPT;
}
}
bool IsCompilingForDebugging() {
return IsCompilingForDebugging::decode(flags_);
}
bool has_global_object() const {
return !closure().is_null() && (closure()->context()->global() != NULL)
;
}
GlobalObject* global_object() const {
return has_global_object() ? closure()->context()->global() : NULL;
}
// Accessors for the different compilation modes.
bool IsOptimizing() const { return mode_ == OPTIMIZE; }
bool IsOptimizable() const { return mode_ == BASE; }
void SetOptimizing(int osr_ast_id) {
SetMode(OPTIMIZE);
osr_ast_id_ = osr_ast_id;
}
void DisableOptimization();
// Deoptimization support.
bool HasDeoptimizationSupport() const {
return SupportsDeoptimization::decode(flags_);
}
void EnableDeoptimizationSupport() {
ASSERT(IsOptimizable());
flags_ |= SupportsDeoptimization::encode(true);
}
// Determines whether or not to insert a self-optimization header.
bool ShouldSelfOptimize();
// Disable all optimization attempts of this info for the rest of the
// current compilation pipeline.
void AbortOptimization();
void set_deferred_handles(DeferredHandles* deferred_handles) {
ASSERT(deferred_handles_ == NULL);
deferred_handles_ = deferred_handles;
}
void SaveHandles() {
SaveHandle(&closure_);
SaveHandle(&shared_info_);
SaveHandle(&calling_context_);
SaveHandle(&script_);
}
private:
Isolate* isolate_;
// Compilation mode.
// BASE is generated by the full codegen, optionally prepared for bailout
s.
// OPTIMIZE is optimized code generated by the Hydrogen-based backend.
// NONOPT is generated by the full codegen and is not prepared for
// recompilation/bailouts. These functions are never recompiled.
enum Mode {
BASE,
OPTIMIZE,
NONOPT
};
void Initialize(Mode mode) {
mode_ = V8::UseCrankshaft() ? mode : NONOPT;
ASSERT(!script_.is_null());
if (script_->type()->value() == Script::TYPE_NATIVE) {
MarkAsNative();
}
if (!shared_info_.is_null()) {
ASSERT(language_mode() == CLASSIC_MODE);
SetLanguageMode(shared_info_->language_mode());
}
}
void SetMode(Mode mode) {
ASSERT(V8::UseCrankshaft());
mode_ = mode;
}
// Flags using template class BitField<type, start, length>. All are
// false by default.
//
// Compilation is either eager or lazy.
class IsLazy: public BitField<bool, 0, 1> {};
// Flags that can be set for eager compilation.
class IsEval: public BitField<bool, 1, 1> {};
class IsGlobal: public BitField<bool, 2, 1> {};
// Flags that can be set for lazy compilation.
class IsInLoop: public BitField<bool, 3, 1> {};
// Strict mode - used in eager compilation.
class LanguageModeField: public BitField<LanguageMode, 4, 2> {};
// Is this a function from our natives.
class IsNative: public BitField<bool, 6, 1> {};
// Is this code being compiled with support for deoptimization..
class SupportsDeoptimization: public BitField<bool, 7, 1> {};
// If compiling for debugging produce just full code matching the
// initial mode setting.
class IsCompilingForDebugging: public BitField<bool, 8, 1> {};
unsigned flags_;
// Fields filled in by the compilation pipeline.
// AST filled in by the parser.
FunctionLiteral* function_;
// The scope of the function literal as a convenience. Set to indicate
// that scopes have been analyzed.
Scope* scope_;
// The global scope provided as a convenience.
Scope* global_scope_;
// The compiled code.
Handle<Code> code_;
// Possible initial inputs to the compilation process.
Handle<JSFunction> closure_;
Handle<SharedFunctionInfo> shared_info_;
Handle<Script> script_;
// Fields possibly needed for eager compilation, NULL by default.
v8::Extension* extension_;
ScriptDataImpl* pre_parse_data_;
// The context of the caller is needed for eval code, and will be a null
// handle otherwise.
Handle<Context> calling_context_;
// Compilation mode flag and whether deoptimization is allowed.
Mode mode_;
int osr_ast_id_;
// The zone from which the compilation pipeline working on this
// CompilationInfo allocates.
Zone* zone_;
DeferredHandles* deferred_handles_;
template<typename T>
void SaveHandle(Handle<T> *object) {
if (!object->is_null()) {
Handle<T> handle(*(*object));
*object = handle;
}
}
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
};
// Exactly like a CompilationInfo, except also creates and enters a
// Zone on construction and deallocates it on exit.
class CompilationInfoWithZone: public CompilationInfo {
public:
explicit CompilationInfoWithZone(Handle<Script> script)
: CompilationInfo(script, &zone_),
zone_(script->GetIsolate()),
zone_scope_(&zone_, DELETE_ON_EXIT) {}
explicit CompilationInfoWithZone(Handle<SharedFunctionInfo> shared_info)
: CompilationInfo(shared_info, &zone_),
zone_(shared_info->GetIsolate()),
zone_scope_(&zone_, DELETE_ON_EXIT) {}
explicit CompilationInfoWithZone(Handle<JSFunction> closure)
: CompilationInfo(closure, &zone_),
zone_(closure->GetIsolate()),
zone_scope_(&zone_, DELETE_ON_EXIT) {}
private:
Zone zone_;
ZoneScope zone_scope_;
};
// A wrapper around a CompilationInfo that detaches the Handles from
// the underlying DeferredHandleScope and stores them in info_ on
// destruction.
class CompilationHandleScope BASE_EMBEDDED {
public:
explicit CompilationHandleScope(CompilationInfo* info)
: deferred_(info->isolate()), info_(info) {}
~CompilationHandleScope() {
info_->set_deferred_handles(deferred_.Detach());
}
private:
DeferredHandleScope deferred_;
CompilationInfo* info_;
};
class HGraph;
class HGraphBuilder;
class LChunk;
// A helper class that calls the three compilation phases in
// Crankshaft and keeps track of its state. The three phases
// CreateGraph, OptimizeGraph and GenerateAndInstallCode can either
// fail, bail-out to the full code generator or succeed. Apart from
// their return value, the status of the phase last run can be checked
// using last_status().
class OptimizingCompiler: public ZoneObject {
public:
explicit OptimizingCompiler(CompilationInfo* info)
: info_(info),
oracle_(NULL),
graph_builder_(NULL),
graph_(NULL),
chunk_(NULL),
time_taken_to_create_graph_(0),
time_taken_to_optimize_(0),
time_taken_to_codegen_(0),
last_status_(FAILED) { }
enum Status {
FAILED, BAILED_OUT, SUCCEEDED
};
MUST_USE_RESULT Status CreateGraph();
MUST_USE_RESULT Status OptimizeGraph();
MUST_USE_RESULT Status GenerateAndInstallCode();
Status last_status() const { return last_status_; }
CompilationInfo* info() const { return info_; }
MUST_USE_RESULT Status AbortOptimization() {
info_->AbortOptimization();
info_->shared_info()->DisableOptimization();
return SetLastStatus(BAILED_OUT);
}
private:
CompilationInfo* info_;
TypeFeedbackOracle* oracle_;
HGraphBuilder* graph_builder_;
HGraph* graph_;
LChunk* chunk_;
int64_t time_taken_to_create_graph_;
int64_t time_taken_to_optimize_;
int64_t time_taken_to_codegen_;
Status last_status_;
MUST_USE_RESULT Status SetLastStatus(Status status) {
last_status_ = status;
return last_status_;
}
void RecordOptimizationStats();
struct Timer {
Timer(OptimizingCompiler* compiler, int64_t* location)
: compiler_(compiler),
start_(OS::Ticks()),
location_(location) { }
~Timer() {
*location_ += (OS::Ticks() - start_);
}
OptimizingCompiler* compiler_;
int64_t start_;
int64_t* location_;
};
};
// The V8 compiler
//
// General strategy: Source code is translated into an anonymous function w
/o
// parameters which then can be executed. If the source code contains other
// functions, they will be compiled and allocated as part of the compilatio
n
// of the source code.
// Please note this interface returns shared function infos. This means yo
u
// need to call Factory::NewFunctionFromSharedFunctionInfo before you have
a
// real function with a context.
class Compiler : public AllStatic {
public:
// Default maximum number of function optimization attempts before we
// give up.
static const int kDefaultMaxOptCount = 10;
static const int kMaxInliningLevels = 3;
// Call count before primitive functions trigger their own optimization.
static const int kCallsUntilPrimitiveOpt = 200;
// All routines return a SharedFunctionInfo.
// If an error occurs an exception is raised and the return handle
// contains NULL.
// Compile a String source within a context.
static Handle<SharedFunctionInfo> Compile(Handle<String> source,
Handle<Object> script_name,
int line_offset,
int column_offset,
v8::Extension* extension,
ScriptDataImpl* pre_data,
Handle<Object> script_data,
NativesFlag is_natives_code);
// Compile a String source within a context for Eval.
static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
Handle<Context> context,
bool is_global,
LanguageMode language_mode,
int scope_position);
// Compile from function info (used for lazy compilation). Returns true o
n
// success and false if the compilation resulted in a stack overflow.
static bool CompileLazy(CompilationInfo* info);
static void RecompileParallel(Handle<JSFunction> function);
// Compile a shared function info object (the function is possibly lazily
// compiled).
static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node
,
Handle<Script> script
);
// Set the function info for a newly compiled function.
static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
FunctionLiteral* lit,
bool is_toplevel,
Handle<Script> script);
static void InstallOptimizedCode(OptimizingCompiler* info);
#ifdef ENABLE_DEBUGGER_SUPPORT
static bool MakeCodeForLiveEdit(CompilationInfo* info);
#endif #endif
static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
CompilationInfo* info,
Handle<SharedFunctionInfo> shared);
};
} } // namespace v8::internal
#endif // V8_COMPILER_H_
 End of changes. 3 change blocks. 
471 lines changed or deleted 30 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/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 129 skipping to change at line 130
log() << "couldn't connect to " << _hostport << ": " << err << rsLog; log() << "couldn't connect to " << _hostport << ": " << err << rsLog;
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 (!noauth) { if (AuthorizationManager::isAuthEnabled()) {
if (!connInfo->cc->auth("local", if (!connInfo->cc->auth("local",
internalSecurity.user, internalSecurity.user,
internalSecurity.pwd, internalSecurity.pwd,
err, err,
false)) { false)) {
log() << "could not authenticate against " << _hostport < < ", " << err << rsLog; log() << "could not authenticate against " << _hostport < < ", " << err << rsLog;
return false; return false;
} }
} }
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 connpool.h   connpool.h 
skipping to change at line 244 skipping to change at line 244
private: private:
static AtomicUInt _numConnections; static AtomicUInt _numConnections;
}; };
/** Use to get a connection from the pool. On exceptions things /** Use to get a connection from the pool. On exceptions things
clean up nicely (i.e. the socket gets closed automatically when the clean up nicely (i.e. the socket gets closed automatically when the
scopeddbconnection goes out of scope). scopeddbconnection goes out of scope).
*/ */
class ScopedDbConnection : public AScopedConnection { class ScopedDbConnection : public AScopedConnection {
private: public:
/** the main constructor you want to use /** the main constructor you want to use
throws UserException if can't connect throws UserException if can't connect
*/ */
explicit ScopedDbConnection(const string& host, double socketTimeou t = 0) : _host(host), _conn( pool.get(host, socketTimeout) ), _socketTimeou t( socketTimeout ) { explicit ScopedDbConnection(const string& host, double socketTimeou t = 0) : _host(host), _conn( pool.get(host, socketTimeout) ), _socketTimeou t( socketTimeout ) {
_setSocketTimeout(); _setSocketTimeout();
} }
explicit ScopedDbConnection(const ConnectionString& host, double so cketTimeout = 0) : _host(host.toString()), _conn( pool.get(host, socketTime out) ), _socketTimeout( socketTimeout ) { explicit ScopedDbConnection(const ConnectionString& host, double so cketTimeout = 0) : _host(host.toString()), _conn( pool.get(host, socketTime out) ), _socketTimeout( socketTimeout ) {
_setSocketTimeout(); _setSocketTimeout();
} }
ScopedDbConnection() : _host( "" ) , _conn(0), _socketTimeout( 0 ) {} ScopedDbConnection() : _host( "" ) , _conn(0), _socketTimeout( 0 ) {}
/* @param conn - bind to an existing connection */ /* @param conn - bind to an existing connection */
ScopedDbConnection(const string& host, DBClientBase* conn, double s ocketTimeout = 0 ) : _host( host ) , _conn( conn ), _socketTimeout( socketT imeout ) { ScopedDbConnection(const string& host, DBClientBase* conn, double s ocketTimeout = 0 ) : _host( host ) , _conn( conn ), _socketTimeout( socketT imeout ) {
_setSocketTimeout(); _setSocketTimeout();
} }
public:
// Factory functions for getting ScopedDbConnections. The caller o
wns the resulting object
// and is responsible for deleting it when finished. This should be
used when running a
// command on a shard from the mongos and the command should run wi
th the client's
// authentication. If the command should be run with full permissi
ons regardless
// of whether or not the user is authorized, then use getInternalSc
opedDbConnection().
static ScopedDbConnection* getScopedDbConnection(const string& host
,
double socketTimeo
ut = 0);
static ScopedDbConnection* getScopedDbConnection(const ConnectionSt
ring& host,
double socketTimeo
ut = 0);
static ScopedDbConnection* getScopedDbConnection();
// DEPRECATED. This is now just a synonym for getScopedDbConnection
.
static ScopedDbConnection* getInternalScopedDbConnection(const stri
ng& host,
double soc
ketTimeout = 0);
static ScopedDbConnection* getInternalScopedDbConnection(const Conn
ectionString& host,
double soc
ketTimeout = 0);
static ScopedDbConnection* getInternalScopedDbConnection();
static void clearPool(); static void clearPool();
~ScopedDbConnection(); ~ScopedDbConnection();
/** get the associated connection object */ /** get the associated connection object */
DBClientBase* operator->() { DBClientBase* operator->() {
uassert( 11004 , "connection was returned to the pool already" , _conn ); uassert( 11004 , "connection was returned to the pool already" , _conn );
return _conn; return _conn;
} }
 End of changes. 2 change blocks. 
34 lines changed or deleted 1 lines changed or added


 counters.h   counters.h 
// Copyright 2012 the V8 project authors. All rights reserved. // counters.h
// Redistribution and use in source and binary forms, with or without /*
// modification, are permitted provided that the following conditions are * Copyright (C) 2010 10gen Inc.
// met: *
// * This program is free software: you can redistribute it and/or modify
// * Redistributions of source code must retain the above copyright * it under the terms of the GNU Affero General Public License, version
// notice, this list of conditions and the following disclaimer. 3,
// * Redistributions in binary form must reproduce the above * as published by the Free Software Foundation.
// copyright notice, this list of conditions and the following *
// disclaimer in the documentation and/or other materials provided * This program is distributed in the hope that it will be useful,
// with the distribution. * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * Neither the name of Google Inc. nor the names of its * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// contributors may be used to endorse or promote products derived * GNU Affero General Public License for more details.
// from this software without specific prior written permission. *
// * You should have received a copy of the GNU Affero General Public Lice
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nse
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * along with this program. If not, see <http://www.gnu.org/licenses/>.
// 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, #pragma once
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, #include "mongo/pch.h"
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY #include "../jsobj.h"
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT #include "../../util/net/message.h"
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE #include "../../util/processinfo.h"
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../util/concurrency/spin_lock.h"
#include "mongo/db/pdfile.h"
#ifndef V8_COUNTERS_H_
#define V8_COUNTERS_H_ namespace mongo {
#include "../include/v8.h" /**
#include "allocation.h" * for storing operation counters
* note: not thread safe. ok with that for speed
namespace v8 { */
namespace internal { class OpCounters {
public:
// StatsCounters is an interface for plugging into external
// counters for monitoring. Counters can be looked up and OpCounters();
// manipulated by name. void incInsertInWriteLock(int n) { _insert.x += n; }
void gotInsert() { _insert++; }
class StatsTable { void gotQuery() { _query++; }
public: void gotUpdate() { _update++; }
// Register an application-defined function where void gotDelete() { _delete++; }
// counters can be looked up. void gotGetMore() { _getmore++; }
void SetCounterFunction(CounterLookupCallback f) { void gotCommand() { _command++; }
lookup_function_ = f;
} void gotOp( int op , bool isCommand );
// Register an application-defined function to create BSONObj getObj() const;
// a histogram for passing to the AddHistogramSample function
void SetCreateHistogramFunction(CreateHistogramCallback f) { // thse are used by snmp, and other things, do not remove
create_histogram_function_ = f; const AtomicUInt * getInsert() const { return &_insert; }
} const AtomicUInt * getQuery() const { return &_query; }
const AtomicUInt * getUpdate() const { return &_update; }
// Register an application-defined function to add a sample const AtomicUInt * getDelete() const { return &_delete; }
// to a histogram created with CreateHistogram function const AtomicUInt * getGetMore() const { return &_getmore; }
void SetAddHistogramSampleFunction(AddHistogramSampleCallback f) { const AtomicUInt * getCommand() const { return &_command; }
add_histogram_sample_function_ = f;
} private:
void _checkWrap();
bool HasCounterFunction() const {
return lookup_function_ != NULL; // todo: there will be a lot of cache line contention on these. ne
} ed to do something
// else eventually.
// Lookup the location of a counter by name. If the lookup AtomicUInt _insert;
// is successful, returns a non-NULL pointer for writing the AtomicUInt _query;
// value of the counter. Each thread calling this function AtomicUInt _update;
// may receive a different location to store it's counter. AtomicUInt _delete;
// The return value must not be cached and re-used across AtomicUInt _getmore;
// threads, although a single thread is free to cache it. AtomicUInt _command;
int* FindLocation(const char* name) { };
if (!lookup_function_) return NULL;
return lookup_function_(name); extern OpCounters globalOpCounters;
} extern OpCounters replOpCounters;
// Create a histogram by name. If the create is successful, class NetworkCounter {
// returns a non-NULL pointer for use with AddHistogramSample public:
// function. min and max define the expected minimum and maximum NetworkCounter() : _bytesIn(0), _bytesOut(0), _requests(0), _overfl
// sample values. buckets is the maximum number of buckets ows(0) {}
// that the samples will be grouped into. void hit( long long bytesIn , long long bytesOut );
void* CreateHistogram(const char* name, void append( BSONObjBuilder& b );
int min, private:
int max, long long _bytesIn;
size_t buckets) { long long _bytesOut;
if (!create_histogram_function_) return NULL; long long _requests;
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_;
};
} } // namespace v8::internal long long _overflows;
#endif // V8_COUNTERS_H_ SpinLock _lock;
};
extern NetworkCounter networkCounter;
}
 End of changes. 3 change blocks. 
273 lines changed or deleted 86 lines changed or added


 curop.h   curop.h 
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);
size_t sz = o.objsize(); int sz = o.objsize();
if ( sz > sizeof(_buf) ) { if ( sz > (int) 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; }
skipping to change at line 222 skipping to change at line 222
return _end - startTime(); return _end - startTime();
} }
int totalTimeMillis() { return (int) (totalTimeMicros() / 1000); } int totalTimeMillis() { return (int) (totalTimeMicros() / 1000); }
int elapsedMillis() { int elapsedMillis() {
unsigned long long total = curTimeMicros64() - startTime(); unsigned long long total = curTimeMicros64() - startTime();
return (int) (total / 1000); return (int) (total / 1000);
} }
int elapsedSeconds() { return elapsedMillis() / 1000; } int elapsedSeconds() { return elapsedMillis() / 1000; }
void setQuery(const BSONObj& query) { _query.set( query ); } void setQuery(const BSONObj& query) { _query.set( query ); }
Client * getClient() const { return _client; } Client * getClient() const { return _client; }
BSONObj info(); BSONObj info();
// Fetches less information than "info()"; used to search for ops w
ith certain criteria
BSONObj description();
string getRemoteString( bool includePort = true ) { return _remote. toString(includePort); } string getRemoteString( bool includePort = true ) { return _remote. toString(includePort); }
ProgressMeter& setMessage(const char * msg, ProgressMeter& setMessage(const char * msg,
std::string name = "Progress", std::string name = "Progress",
unsigned long long progressMeterTotal = 0 , unsigned long long progressMeterTotal = 0 ,
int secondsBetween = 3); int secondsBetween = 3);
string getMessage() const { return _message.toString(); } string getMessage() const { return _message.toString(); }
ProgressMeter& getProgressMeter() { return _progressMeter; } ProgressMeter& getProgressMeter() { return _progressMeter; }
CurOp *parent() const { return _wrapped; } CurOp *parent() const { return _wrapped; }
void kill(bool* pNotifyFlag = NULL); void kill(bool* pNotifyFlag = NULL);
bool killPendingStrict() const { return _killPending.load(); } bool killPendingStrict() const { return _killPending.load(); }
skipping to change at line 247 skipping to change at line 252
long long getExpectedLatencyMs() const { return _expectedLatencyMs; } long long getExpectedLatencyMs() const { return _expectedLatencyMs; }
void setExpectedLatencyMs( long long latency ) { _expectedLatencyMs = latency; } void setExpectedLatencyMs( long long latency ) { _expectedLatencyMs = latency; }
void recordGlobalTime( long long micros ) const; void recordGlobalTime( long long micros ) const;
const LockStat& lockStat() const { return _lockStat; } const LockStat& lockStat() const { return _lockStat; }
LockStat& lockStat() { return _lockStat; } LockStat& lockStat() { return _lockStat; }
void setKillWaiterFlags(); void setKillWaiterFlags();
/**
* Find a currently running operation matching the given criteria.
This assumes that you're
* going to kill the operation, so it must be called multiple times
to get multiple matching
* operations.
* @param criteria the search to do against the infoNoauth() BSONOb
j
* @return a pointer to a matching op or NULL if no ops match
*/
static CurOp* getOp(const BSONObj& criteria);
private: private:
friend class Client; friend class Client;
void _reset(); void _reset();
static AtomicUInt _nextOpNum; static AtomicUInt _nextOpNum;
Client * _client; Client * _client;
CurOp * _wrapped; CurOp * _wrapped;
unsigned long long _start; unsigned long long _start;
unsigned long long _end; unsigned long long _end;
bool _active; bool _active;
 End of changes. 4 change blocks. 
2 lines changed or deleted 20 lines changed or added


 cursor.h   cursor.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 "mongo/pch.h" #include "mongo/pch.h"
#include "jsobj.h" #include "mongo/db/diskloc.h"
#include "diskloc.h" #include "mongo/db/jsobj.h"
#include "matcher.h" #include "mongo/db/matcher.h"
#include "mongo/db/matcher_covered.h"
#include "mongo/db/projection.h" #include "mongo/db/projection.h"
namespace mongo { namespace mongo {
class NamespaceDetails; class NamespaceDetails;
class Record; class Record;
class CoveredIndexMatcher; class CoveredIndexMatcher;
/** /**
* Query cursors, base class. This is for our internal cursors. "Clie ntCursor" is a separate * Query cursors, base class. This is for our internal cursors. "Clie ntCursor" is a separate
 End of changes. 1 change blocks. 
3 lines changed or deleted 4 lines changed or added


 d_logic.h   d_logic.h 
skipping to change at line 255 skipping to change at line 255
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 ) {
if( !shardingState.enabled() ) if( !shardingState.enabled() )
return false; return false;
return _handlePossibleShardedMessage(m, dbresponse); return _handlePossibleShardedMessage(m, dbresponse);
} }
void logOpForSharding( const char * opstr , const char * ns , const BSO /**
NObj& obj , BSONObj * patt ); * If a migration for the chunk in 'ns' where 'obj' lives is occurring,
void aboutToDeleteForSharding( const Database* db , const DiskLoc& dl ) save this log entry
; * 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.
*/
void logOpForSharding( const char * opstr,
const char * ns,
const BSONObj& obj,
BSONObj * patt,
const BSONObj* fullObj );
void aboutToDeleteForSharding( const StringData& ns, const Database* db
, const DiskLoc& dl );
} }
 End of changes. 1 change blocks. 
4 lines changed or deleted 16 lines changed or added


 db.h   db.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/pch.h" #include "mongo/pch.h"
#include "../util/net/message.h"
#include "pdfile.h" #include "mongo/db/client.h"
#include "curop.h" #include "mongo/db/curop.h"
#include "client.h" #include "mongo/db/databaseholder.h"
#include "databaseholder.h" #include "mongo/db/pdfile.h"
#include "mongo/util/net/message.h"
namespace mongo { namespace mongo {
// todo: relocked is being called when there was no unlock below. // todo: relocked is being called when there was no unlock below.
// that is weird. // that is weird.
struct dbtemprelease { struct dbtemprelease {
Client::Context * _context; Client::Context * _context;
scoped_ptr<Lock::TempRelease> tr; scoped_ptr<Lock::TempRelease> tr;
dbtemprelease() { dbtemprelease() {
const Client& c = cc(); const Client& c = cc();
_context = c.getContext(); _context = c.getContext();
verify( Lock::isLocked() ); verify( Lock::isLocked() );
if( Lock::nested() ) { if( Lock::nested() ) {
Lock::nested();
massert(10298 , "can't temprelease nested lock", false); massert(10298 , "can't temprelease nested lock", false);
} }
if ( _context ) { if ( _context ) {
_context->unlocked(); _context->unlocked();
} }
tr.reset(new Lock::TempRelease); tr.reset(new Lock::TempRelease);
verify( c.curop() ); verify( c.curop() );
c.curop()->yielded(); c.curop()->yielded();
} }
~dbtemprelease() { ~dbtemprelease() {
 End of changes. 2 change blocks. 
6 lines changed or deleted 6 lines changed or added


 dbclient_rs.h   dbclient_rs.h 
skipping to change at line 204 skipping to change at line 204
/** /**
* Populates activeSets with all the currently tracked replica set names. * Populates activeSets with all the currently tracked replica set names.
*/ */
static void getAllTrackedSets(set<string>* activeSets); static void getAllTrackedSets(set<string>* activeSets);
/** /**
* checks all sets for current master and new secondaries * checks all sets for current master and new secondaries
* usually only called from a BackgroundJob * usually only called from a BackgroundJob
*/ */
static void checkAll( bool checkAllSecondaries ); static void checkAll();
/** /**
* Removes the ReplicaSetMonitor for the given set name from _sets, which will delete it. * Removes the ReplicaSetMonitor for the given set name from _sets, which will delete it.
* If clearSeedCache is true, then the cached seed string for this Replica Set will be removed * If clearSeedCache is true, then the cached seed string for this Replica Set will be removed
* from _seedServers. * from _setServers.
*/ */
static void remove( const string& name, bool clearSeedCache = false ); static void remove( const string& name, bool clearSeedCache = false );
static int getMaxFailedChecks() { return _maxFailedChecks; }; static int getMaxFailedChecks() { return _maxFailedChecks; };
static void setMaxFailedChecks(int numChecks) { _maxFailedChecks = numChecks; }; static void setMaxFailedChecks(int numChecks) { _maxFailedChecks = numChecks; };
/** /**
* this is called whenever the config of any replica set changes * this is called whenever the config of any replica set changes
* currently only 1 globally * currently only 1 globally
* asserts if one already exists * asserts if one already exists
skipping to change at line 255 skipping to change at line 255
HostAndPort getSlave( bool preferLocal = true ); HostAndPort getSlave( bool preferLocal = true );
/** /**
* notify the monitor that server has faild * notify the monitor that server has faild
*/ */
void notifySlaveFailure( const HostAndPort& server ); void notifySlaveFailure( const HostAndPort& server );
/** /**
* checks for current master and new secondaries * checks for current master and new secondaries
*/ */
void check( bool checkAllSecondaries ); void check();
string getName() const { return _name; } string getName() const { return _name; }
string getServerAddress() const; string getServerAddress() const;
bool contains( const string& server ) const; bool contains( const string& server ) const;
void appendInfo( BSONObjBuilder& b ) const; void appendInfo( BSONObjBuilder& b ) const;
/** /**
skipping to change at line 299 skipping to change at line 299
* @param name set name * @param name set name
* @param servers seeds * @param servers seeds
*/ */
ReplicaSetMonitor( const string& name , const vector<HostAndPort>& servers ); ReplicaSetMonitor( const string& name , const vector<HostAndPort>& servers );
static void _remove_inlock( const string& name, bool clearSeedCache = false ); static void _remove_inlock( const string& name, bool clearSeedCache = false );
/** /**
* Checks all connections from the host list and sets the current * Checks all connections from the host list and sets the current
* master. * master.
*
* @param checkAllSecondaries if set to false, stop immediately whe
n
* the master is found or when _master is not -1.
*/
void _check( bool checkAllSecondaries );
/**
* Use replSetGetStatus command to make sure hosts in host list are
up
* and readable. Sets Node::ok appropriately.
*/ */
void _checkStatus( const string& hostAddr ); void _check();
/** /**
* Add array of hosts to host list. Doesn't do anything if hosts ar e * Add array of hosts to host list. Doesn't do anything if hosts ar e
* already in host list. * already in host list.
* @param hostList the list of hosts to add * @param hostList the list of hosts to add
* @param changed if new hosts were added * @param changed if new hosts were added
*/ */
void _checkHosts(const BSONObj& hostList, bool& changed); void _checkHosts(const BSONObj& hostList, bool& changed);
/** /**
skipping to change at line 336 skipping to change at line 327
* @param verbose * @param verbose
* @param nodesOffset - offset into _nodes array, -1 for not in it * @param nodesOffset - offset into _nodes array, -1 for not in it
* *
* @return true if the connection is good or false if invariant * @return true if the connection is good or false if invariant
* is broken * is broken
*/ */
bool _checkConnection( DBClientConnection* conn, string& maybePrima ry, bool _checkConnection( DBClientConnection* conn, string& maybePrima ry,
bool verbose, int nodesOffset ); bool verbose, int nodesOffset );
/** /**
* Save the seed list for the current set into the _seedServers map * Save the seed list for the current set into the _setServers map
* Should only be called if you're already holding _setsLock and th is * Should only be called if you're already holding _setsLock and th is
* monitor's _lock. * monitor's _lock.
*/ */
void _cacheServerAddresses_inlock(); void _cacheServerAddresses_inlock();
string _getServerAddress_inlock() const; string _getServerAddress_inlock() const;
NodeDiff _getHostDiff_inlock( const BSONObj& hostList ); NodeDiff _getHostDiff_inlock( const BSONObj& hostList );
bool _shouldChangeHosts( const BSONObj& hostList, bool inlock ); bool _shouldChangeHosts( const BSONObj& hostList, bool inlock );
skipping to change at line 400 skipping to change at line 391
std::vector<Node> _nodes; std::vector<Node> _nodes;
int _master; // which node is the current master. -1 means no mast er is known int _master; // which node is the current master. -1 means no mast er is known
int _nextSlave; // which node is the current slave, only used by th e deprecated getSlave int _nextSlave; // which node is the current slave, only used by th e deprecated getSlave
// last host returned by _selectNode, used for round robin selectio n // last host returned by _selectNode, used for round robin selectio n
HostAndPort _lastReadPrefHost; HostAndPort _lastReadPrefHost;
// The number of consecutive times the set has been checked and eve ry member in the set was down. // The number of consecutive times the set has been checked and eve ry member in the set was down.
int _failedChecks; int _failedChecks;
static mongo::mutex _setsLock; // protects _seedServers and _sets static mongo::mutex _setsLock; // protects _sets and _setServers
static map<string,ReplicaSetMonitorPtr> _sets; // set name to Monit
// set name to seed list. or
// Used to rebuild the monitor if it is cleaned up but then the set static map<string,vector<HostAndPort> > _seedServers; // set name t
is accessed again. o seed list. Used to rebuild the monitor if it is cleaned up but then the s
static map<string, vector<HostAndPort> > _seedServers; et is accessed again.
static map<string, ReplicaSetMonitorPtr> _sets; // set name to Moni
tor
static ConfigChangeHook _hook; static ConfigChangeHook _hook;
int _localThresholdMillis; // local ping latency threshold (protect ed by _lock) int _localThresholdMillis; // local ping latency threshold (protect ed by _lock)
static int _maxFailedChecks; static int _maxFailedChecks;
}; };
/** Use this class to connect to a replica set of servers. The class w ill manage /** Use this class to connect to a replica set of servers. The class w ill manage
checking for which server in a replica set is master, and do failove r automatically. checking for which server in a replica set is master, and do failove r automatically.
skipping to change at line 504 skipping to change at line 492
*/ */
void isntMaster(); void isntMaster();
/* this is used to indicate we got a "not master or secondary" erro r from a secondary. /* this is used to indicate we got a "not master or secondary" erro r from a secondary.
*/ */
void isntSecondary(); void isntSecondary();
// ----- status ------ // ----- status ------
virtual bool isFailed() const { return ! _master || _master->isFail ed(); } virtual bool isFailed() const { return ! _master || _master->isFail ed(); }
bool isStillConnected();
// ----- informational ---- // ----- informational ----
double getSoTimeout() const { return _so_timeout; } double getSoTimeout() const { return _so_timeout; }
string toString() { return getServerAddress(); } string toString() { return getServerAddress(); }
string getServerAddress() const; string getServerAddress() const;
virtual ConnectionString::ConnectionType type() const { return Conn ectionString::SET; } virtual ConnectionString::ConnectionType type() const { return Conn ectionString::SET; }
virtual bool lazySupported() const { return true; } virtual bool lazySupported() const { return true; }
// ---- low level ------ // ---- low level ------
virtual bool call( Message &toSend, Message &response, bool assertO k=true , string * actualServer = 0 ); virtual bool call( Message &toSend, Message &response, bool assertO k=true , string * actualServer = 0 );
virtual bool callRead( Message& toSend , Message& response ) { retu rn checkMaster()->callRead( toSend , response ); } virtual bool callRead( Message& toSend , Message& response ) { retu rn checkMaster()->callRead( toSend , response ); }
/**
* Authenticate using supplied credentials. Authenticates against
the primary node, fails
* if node is down.
* Credentials are cached for future connections.
*
* See DBClientWithCommands::auth() for more details.
*
* This is the default authentication mode for DBClientReplicaSet
connections.
*/
void authPrimary(const BSONObj& params);
/**
* Same as above, but authorizes access to a particular database.
*
* See DBClientWithCommands::auth() for more details.
*/
bool authPrimary(const string &dbname,
const string &username,
const string &password_text,
string& errmsg,
bool digestPassword);
/**
* Authenticate using supplied credentials. Prefers authentication
against the primary
* node, will fall back to a secondary and retry if the primary nod
e is down but
* secondaries are still available.
* Credentials are cached for future connections.
*
* See DBClientWithCommands::auth() for more details.
*/
void authAny(const BSONObj& params);
/**
* Same as above, but authorizes access to a particular database.
*
* See DBClientWithCommands::auth() for more details.
*/
bool authAny( const string &dbname,
const string &username,
const string &password_text,
string& errmsg,
bool digestPassword );
/*
* Returns whether a query or command can be sent to secondaries ba
sed on the query object
* and options.
*
* @param ns the namespace of the query.
* @param queryObj the query object to check.
* @param queryOptions the query options
*
* @return true if the query/cmd could potentially be sent to a sec
ondary, false otherwise
*/
static bool isSecondaryQuery( const string& ns,
const BSONObj& queryObj,
int queryOptions );
protected: protected:
/** Authorize. Authorizes all nodes as needed
*/
virtual void _auth(const BSONObj& params); virtual void _auth(const BSONObj& params);
virtual void sayPiggyBack( Message &toSend ) { checkMaster()->say( toSend ); } virtual void sayPiggyBack( Message &toSend ) { checkMaster()->say( toSend ); }
private: private:
/** /**
* Used to simplify slave-handling logic on errors * Used to simplify slave-handling logic on errors
* *
* @return back the passed cursor * @return back the passed cursor
* @throws DBException if the directed node cannot accept the query because it * @throws DBException if the directed node cannot accept the query because it
skipping to change at line 664 skipping to change at line 597
// not sure if/how we should handle // not sure if/how we should handle
std::map<string, BSONObj> _auths; // dbName -> auth parameters std::map<string, BSONObj> _auths; // dbName -> auth parameters
protected: protected:
/** /**
* for storing (non-threadsafe) information between lazy calls * for storing (non-threadsafe) information between lazy calls
*/ */
class LazyState { class LazyState {
public: public:
LazyState() : LazyState() : _lastClient( NULL ), _lastOp( -1 ), _slaveOk( fal
_lastClient( NULL ), _lastOp( -1 ), _isSecondaryQuery( fals se ), _retries( 0 ) {}
e ), _retries( 0 ) {
}
DBClientConnection* _lastClient; DBClientConnection* _lastClient;
int _lastOp; int _lastOp;
bool _isSecondaryQuery; bool _slaveOk;
int _retries; int _retries;
} _lazyState; } _lazyState;
}; };
/** /**
* A simple object for representing the list of tags. The initial state will * A simple object for representing the list of tags. The initial state will
* have a valid current tag as long as the list is not empty. * have a valid current tag as long as the list is not empty.
*/ */
skipping to change at line 735 skipping to change at line 666
* 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;
skipping to change at line 768 skipping to change at line 697
* 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. 14 change blocks. 
97 lines changed or deleted 17 lines changed or added


 dbclientinterface.h   dbclientinterface.h 
skipping to change at line 194 skipping to change at line 194
* DBClientBase * conn = cs.connect( errmsg ); * DBClientBase * conn = cs.connect( errmsg );
*/ */
class ConnectionString { class ConnectionString {
public: public:
enum ConnectionType { INVALID , MASTER , PAIR , SET , SYNC, CUSTOM }; enum ConnectionType { INVALID , MASTER , PAIR , SET , SYNC, CUSTOM };
ConnectionString() { ConnectionString() {
_type = INVALID; _type = INVALID;
} }
// Note: This should only be used for direct connections to a singl
e server. For replica
// set and SyncClusterConnections, use ConnectionString::parse.
ConnectionString( const HostAndPort& server ) { ConnectionString( const HostAndPort& server ) {
_type = MASTER; _type = MASTER;
_servers.push_back( server ); _servers.push_back( server );
_finishInit(); _finishInit();
} }
ConnectionString( ConnectionType type , const string& s , const str ing& setName = "" ) { ConnectionString( ConnectionType type , const string& s , const str ing& setName = "" ) {
_type = type; _type = type;
_setName = setName; _setName = setName;
_fillServers( s ); _fillServers( s );
skipping to change at line 1078 skipping to change at line 1080
/** /**
remove matching objects from the database remove matching objects from the database
@param justOne if this true, then once a single match is found w ill stop @param justOne if this true, then once a single match is found w ill stop
*/ */
virtual void remove( const string &ns , Query q , bool justOne = 0 ); virtual void remove( const string &ns , Query q , bool justOne = 0 );
virtual void remove( const string &ns , Query query, int flags ); virtual void remove( const string &ns , Query query, int flags );
virtual bool isFailed() const = 0; virtual bool isFailed() const = 0;
/**
* if not checked recently, checks whether the underlying socket/so
ckets are still valid
*/
virtual bool isStillConnected() = 0;
virtual void killCursor( long long cursorID ) = 0; virtual void killCursor( long long cursorID ) = 0;
virtual bool callRead( Message& toSend , Message& response ) = 0; virtual bool callRead( Message& toSend , Message& response ) = 0;
// virtual bool callWrite( Message& toSend , Message& response ) = 0; // TODO: add this if needed // virtual bool callWrite( Message& toSend , Message& response ) = 0; // TODO: add this if needed
virtual ConnectionString::ConnectionType type() const = 0; virtual ConnectionString::ConnectionType type() const = 0;
virtual double getSoTimeout() const = 0; virtual double getSoTimeout() const = 0;
virtual uint64_t getSockCreationMicroSec() const { virtual uint64_t getSockCreationMicroSec() const {
skipping to change at line 1188 skipping to change at line 1195
const BSONObj& cmd, const BSONObj& cmd,
BSONObj &info, BSONObj &info,
int options=0); int options=0);
/** /**
@return true if this connection is currently in a failed state. When autoreconnect is on, @return true if this connection is currently in a failed state. When autoreconnect is on,
a connection will transition back to an ok state after r econnecting. a connection will transition back to an ok state after r econnecting.
*/ */
bool isFailed() const { return _failed; } bool isFailed() const { return _failed; }
bool isStillConnected() { return p ? p->isStillConnected() : true;
}
MessagingPort& port() { verify(p); return *p; } MessagingPort& port() { verify(p); return *p; }
string toStringLong() const { string toStringLong() const {
stringstream ss; stringstream ss;
ss << _serverString; ss << _serverString;
if ( _failed ) ss << " failed"; if ( _failed ) ss << " failed";
return ss.str(); return ss.str();
} }
/** Returns the address of the server */ /** Returns the address of the server */
skipping to change at line 1261 skipping to change at line 1270
void checkConnection() { if( _failed ) _checkConnection(); } void checkConnection() { if( _failed ) _checkConnection(); }
map<string, BSONObj> authCache; map<string, BSONObj> authCache;
double _so_timeout; double _so_timeout;
bool _connect( string& errmsg ); bool _connect( string& errmsg );
static AtomicUInt _numConnections; static AtomicUInt _numConnections;
static bool _lazyKillCursor; // lazy means we piggy back kill curso rs on next op static bool _lazyKillCursor; // lazy means we piggy back kill curso rs on next op
#ifdef MONGO_SSL #ifdef MONGO_SSL
SSLManager* sslManager(); SSLManagerInterface* sslManager();
#endif #endif
}; };
/** pings server to check if it's up /** pings server to check if it's up
*/ */
bool serverAlive( const string &uri ); bool serverAlive( const string &uri );
DBClientBase * createDirectClient(); DBClientBase * createDirectClient();
BSONElement getErrField( const BSONObj& result ); BSONElement getErrField( const BSONObj& result );
 End of changes. 4 change blocks. 
1 lines changed or deleted 13 lines changed or added


 dbhelpers.h   dbhelpers.h 
/* @file dbhelpers.h
db helpers are helper functions and classes that let us easily manipulat
e the local
database instance in-proc.
*/
/** /**
* Copyright (C) 2008 10gen Inc. * Copyright (C) 2008 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3 * it under the terms of the GNU Affero General Public License, version
, 3,
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen * 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
// TODO: Remove
#include "mongo/pch.h" #include "mongo/pch.h"
#include "client.h"
#include "db.h" #include "mongo/db/client.h"
#include "mongo/db/db.h"
#include "mongo/db/keypattern.h"
#include "mongo/s/range_arithmetic.h"
namespace mongo { namespace mongo {
extern const BSONObj reverseNaturalObj; // {"$natural": -1 } extern const BSONObj reverseNaturalObj; // {"$natural": -1 }
class Cursor; class Cursor;
class CoveredIndexMatcher; class CoveredIndexMatcher;
/** /**
all helpers assume locking is handled above them * db helpers are helper functions and classes that let us easily manip
ulate the local
* database instance in-proc.
*
* all helpers assume locking is handled above them
*/ */
struct Helpers { struct Helpers {
/* ensure the specified index exists. /* ensure the specified index exists.
@param keyPattern key pattern, e.g., { ts : 1 } @param keyPattern key pattern, e.g., { ts : 1 }
@param name index name, e.g., "name_1" @param name index name, e.g., "name_1"
This method can be a little (not much) cpu-slow, so you may wish to use This method can be a little (not much) cpu-slow, so you may wish to use
OCCASIONALLY ensureIndex(...); OCCASIONALLY ensureIndex(...);
skipping to change at line 130 skipping to change at line 131
*/ */
static BSONObj inferKeyPattern( const BSONObj& o ); static BSONObj inferKeyPattern( const BSONObj& o );
class RemoveCallback { class RemoveCallback {
public: public:
virtual ~RemoveCallback() {} virtual ~RemoveCallback() {}
virtual void goingToDelete( const BSONObj& o ) = 0; virtual void goingToDelete( const BSONObj& o ) = 0;
}; };
/** /**
* Takes a range, specified by a min and max, and an index, specifi * Takes a namespace range, specified by a min and max and qualifie
ed by d by an index pattern,
* keyPattern, and removes all the documents in that range found by * and removes all the documents in that range found by iterating
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'
* *
* 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 string& ns , static long long removeRange( const KeyRange& range,
const BSONObj& min , bool maxInclusive = false,
const BSONObj& max , bool secondaryThrottle = false,
const BSONObj& keyPattern ,
bool maxInclusive = false ,
bool secondaryThrottle = false ,
RemoveCallback * callback = 0, RemoveCallback * callback = 0,
bool fromMigrate = false, bool fromMigrate = false,
bool onlyRemoveOrphanedDocs = false ) ; bool onlyRemoveOrphanedDocs = false ) ;
// TODO: This will supersede Chunk::MaxObjectsPerChunk
static const long long kMaxDocsPerChunk;
/**
* Get sorted disklocs that belong to a range of a namespace define
d over an index
* key pattern (KeyRange).
*
* @param chunk range of a namespace over an index key pattern.
* @param maxChunkSizeBytes max number of bytes that we will retrie
ve locs for, if the
* range is estimated larger (from avg doc stats) we will stop reco
rding locs.
* @param locs set to record locs in
* @param estChunkSizeBytes chunk size estimated from doc count and
avg doc size
* @param chunkTooBig whether the chunk was estimated larger than o
ur maxChunkSizeBytes
* @param errmsg filled with textual description of error if this c
all return false
*
* @return NamespaceNotFound if the namespace doesn't exist
* @return IndexNotFound if the index pattern doesn't match any ind
exes
* @return InvalidLength if the estimated size exceeds maxChunkSize
Bytes
*/
static Status getLocsInRange( const KeyRange& range,
long long maxChunkSizeBytes,
set<DiskLoc>* locs,
long long* numDocs,
long long* estChunkSizeBytes );
/** /**
* Remove all documents from a collection. * Remove all documents from a collection.
* You do not need to set the database before calling. * You do not need to set the database before calling.
* Does not oplog the operation. * Does not oplog the operation.
*/ */
static void emptyCollection(const char *ns); static void emptyCollection(const char *ns);
}; };
/** /**
 End of changes. 8 change blocks. 
36 lines changed or deleted 66 lines changed or added


 dbmessage.h   dbmessage.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 "jsobj.h"
#include "namespace-inl.h"
#include "../util/net/message.h"
#include "../client/constants.h"
#include "instance.h"
#include "mongo/bson/bson_validate.h" #include "mongo/bson/bson_validate.h"
#include "mongo/client/constants.h"
#include "mongo/db/instance.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/namespace-inl.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;
int nReturned; int nReturned;
skipping to change at line 112 skipping to change at line 112
}; };
#pragma pack() #pragma pack()
/* For the database/server protocol, these objects and functions encaps ulate /* For the database/server protocol, these objects and functions encaps ulate
the various messages transmitted over the connection. the various messages transmitted over the connection.
See http://dochub.mongodb.org/core/mongowireprotocol See http://dochub.mongodb.org/core/mongowireprotocol
*/ */
class DbMessage { class DbMessage {
// Assume sizeof(int) == 4 bytes
BOOST_STATIC_ASSERT(sizeof(int) == 4);
public: public:
// Note: DbMessage constructor reads the first 4 bytes and stores i DbMessage(const Message& _m) : m(_m) , mark(0) {
t in reserved // for received messages, Message has only one buffer
DbMessage(const Message& msg); theEnd = _m.singleData()->_data + _m.header()->dataLen();
char *r = _m.singleData()->_data;
// Indicates whether this message is expected to have a ns reserved = (int *) r;
// or in the case of dbMsg, a string in the same place as ns data = r + 4;
bool messageShouldHaveNs() const { nextjsobj = data;
return (_msg.operation() >= dbMsg) && (_msg.operation() <= dbDe
lete);
} }
/** the 32 bit field before the ns /** the 32 bit field before the ns
* track all bit usage here as its cross op * track all bit usage here as its cross op
* 0: InsertOption_ContinueOnError * 0: InsertOption_ContinueOnError
* 1: fromWriteback * 1: fromWriteback
*/ */
int reservedField() const { return _reserved; } int& reservedField() { return *reserved; }
void setReservedField(int value) { _reserved = value; }
const char * getns() const {
return data;
}
void getns(Namespace& ns) const {
ns = data;
}
const char * getns() const; const char * afterNS() const {
int getQueryNToReturn() const; return data + strlen( data ) + 1;
}
int getFlags() const; int getInt( int num ) const {
void setFlags(int value); const int * foo = (const int*)afterNS();
return foo[num];
}
long long getInt64(int offsetBytes) const; int getQueryNToReturn() const {
return getInt( 1 );
}
int pullInt(); /**
long long pullInt64(); * get an int64 at specified offsetBytes after ns
const long long* getArray(size_t count) const; */
long long getInt64( int offsetBytes ) const {
const char * x = afterNS();
x += offsetBytes;
const long long * ll = (const long long*)x;
return ll[0];
}
void resetPull() { nextjsobj = data; }
int pullInt() const { return pullInt(); }
int& pullInt() {
if ( nextjsobj == data )
nextjsobj += strlen(data) + 1; // skip namespace
int& i = *((int *)nextjsobj);
nextjsobj += 4;
return i;
}
long long pullInt64() const {
return pullInt64();
}
long long &pullInt64() {
if ( nextjsobj == data )
nextjsobj += strlen(data) + 1; // skip namespace
long long &i = *((long long *)nextjsobj);
nextjsobj += 8;
return i;
}
OID* getOID() const {
return (OID *) (data + strlen(data) + 1); // skip namespace
}
void getQueryStuff(const char *&query, int& ntoreturn) {
int *i = (int *) (data + strlen(data) + 1);
ntoreturn = *i;
i++;
query = (const char *) i;
}
/* for insert and update msgs */ /* for insert and update msgs */
bool moreJSObjs() const { bool moreJSObjs() const {
return _nextjsobj != 0; return nextjsobj != 0;
}
BSONObj nextJsObj() {
if ( nextjsobj == data ) {
nextjsobj += strlen(data) + 1; // skip namespace
massert( 13066 , "Message contains no documents", theEnd >
nextjsobj );
}
massert( 10304,
"Client Error: Remaining data too small for BSON objec
t",
theEnd - nextjsobj >= 5 );
if ( cmdLine.objcheck ) {
Status status = validateBSON( nextjsobj, theEnd - nextjsobj
);
massert( 10307,
str::stream() << "Client Error: bad object in mess
age: " << status.reason(),
status.isOK() );
}
BSONObj js(nextjsobj);
verify( js.objsize() >= 5 );
verify( js.objsize() < ( theEnd - data ) );
nextjsobj += js.objsize();
if ( nextjsobj >= theEnd )
nextjsobj = 0;
return js;
} }
BSONObj nextJsObj(); const Message& msg() const { return m; }
const Message& msg() const { return _msg; }
const char * markGet() const { const char * markGet() {
return _nextjsobj; return nextjsobj;
} }
void markSet() { void markSet() {
_mark = _nextjsobj; mark = nextjsobj;
} }
void markReset(const char * toMark = NULL); void markReset( const char * toMark = 0) {
if( toMark == 0 ) toMark = mark;
verify( toMark );
nextjsobj = toMark;
}
private: private:
// Check if we have enough data to read const Message& m;
template<typename T> int* reserved;
void checkRead(const char* start, size_t count = 0) const; const char *data;
const char *nextjsobj;
template<typename T> const char *theEnd;
void checkReadOffset(const char* start, size_t offset) const;
// Read some type without advancing our position
template<typename T>
T read() const;
// Read some type, and advance our position
template<typename T> T readAndAdvance();
const Message& _msg;
int _reserved; // flags or zero depending on packet, starts the pac
ket
const char* _nsStart; // start of namespace string, +4 from message
start
const char* _nextjsobj; // current position reading packet
const char* _theEnd; // end of packet
const char* _mark;
unsigned int _nsLen; const char * mark;
}; };
/* a request to run a query, received from the database */ /* a request to run a query, received from the database */
class QueryMessage { class QueryMessage {
public: public:
const char *ns; const char *ns;
int ntoskip; int ntoskip;
int ntoreturn; int ntoreturn;
int queryOptions; int queryOptions;
BSONObj query; BSONObj query;
 End of changes. 16 change blocks. 
60 lines changed or deleted 115 lines changed or added


 dbwebserver.h   dbwebserver.h 
skipping to change at line 20 skipping to change at line 20
* *
* 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/>.
*/ */
#include "../util/admin_access.h" #include <string>
#include <vector>
#include "mongo/util/admin_access.h"
#include "mongo/util/net/sock.h"
namespace mongo { namespace mongo {
class Prioritizable { class Prioritizable {
public: public:
Prioritizable( double p ) : _priority(p) {} Prioritizable( double p ) : _priority(p) {}
double priority() const { return _priority; } double priority() const { return _priority; }
private: private:
double _priority; double _priority;
}; };
 End of changes. 1 change blocks. 
1 lines changed or deleted 5 lines changed or added


 diskloc.h   diskloc.h 
skipping to change at line 168 skipping to change at line 168
Extent* ext() const; Extent* ext() const;
template< class V > template< class V >
const BtreeBucket<V> * btree() const; const BtreeBucket<V> * btree() const;
// Explicitly signals we are writing and casts away const // Explicitly signals we are writing and casts away const
template< class V > template< class V >
BtreeBucket<V> * btreemod() const; BtreeBucket<V> * btreemod() const;
/*MongoDataFile& pdf() const;*/ /*MongoDataFile& pdf() const;*/
/// members for Sorter
struct SorterDeserializeSettings {}; // unused
void serializeForSorter(BufBuilder& buf) const { buf.appendStruct(*
this); }
static DiskLoc deserializeForSorter(BufReader& buf, const SorterDes
erializeSettings&) {
return buf.read<DiskLoc>();
}
int memUsageForSorter() const { return sizeof(DiskLoc); }
DiskLoc getOwned() const { return *this; }
}; };
#pragma pack() #pragma pack()
inline size_t DiskLoc::Hasher::operator()( DiskLoc loc ) const { inline size_t DiskLoc::Hasher::operator()( DiskLoc loc ) const {
// Older tr1 implementations do not support hashing 64 bit integers . This implementation // Older tr1 implementations do not support hashing 64 bit integers . This implementation
// delegates to hashing 32 bit integers. // delegates to hashing 32 bit integers.
return return
unordered_set<uint32_t>::hasher()( loc.a() ) ^ unordered_set<uint32_t>::hasher()( loc.a() ) ^
unordered_set<uint32_t>::hasher()( loc.getOfs() ); unordered_set<uint32_t>::hasher()( loc.getOfs() );
} }
 End of changes. 1 change blocks. 
0 lines changed or deleted 11 lines changed or added


 distlock.h   distlock.h 
skipping to change at line 60 skipping to change at line 60
* Indicates an error in retrieving time values from remote servers. * Indicates an error in retrieving time values from remote servers.
*/ */
class TimeNotFoundException : public LockException { class TimeNotFoundException : public LockException {
public: public:
TimeNotFoundException( const char * msg , int code ) : LockExceptio n( msg, code ) {} TimeNotFoundException( const char * msg , int code ) : LockExceptio n( msg, code ) {}
TimeNotFoundException( const string& msg, int code ) : LockExceptio n( msg, code ) {} TimeNotFoundException( const string& msg, int code ) : LockExceptio n( msg, code ) {}
virtual ~TimeNotFoundException() throw() { } virtual ~TimeNotFoundException() throw() { }
}; };
/** /**
* The distributed lock is a configdb backed way of synchronizing syste * The distributed lock is a configdb backed way of synchronizing syste
m-wide tasks. A task m-wide tasks. A task must be identified by a
* must be identified by a unique name across the system (e.g., "balanc * unique name across the system (e.g., "balancer"). A lock is taken by
er"). A lock is taken writing a document in the configdb's locks
* by writing a document in the configdb's locks collection with that n * collection with that name.
ame.
* *
* To be maintained, each taken lock needs to be revalidated ("pinged") * To be maintained, each taken lock needs to be revalidated ("pinged")
within a within a pre-established amount of time. This
* pre-established amount of time. This class does this maintenance aut * class does this maintenance automatically once a DistributedLock obj
omatically once a ect was constructed.
* DistributedLock object was constructed. The ping procedure records t
he local time to
* the ping document, but that time is untrusted and is only used as a
point of reference
* of whether the ping was refreshed or not. Ultimately, the clock a co
nfigdb is the source
* of truth when determining whether a ping is still fresh or not. This
is achieved by
* (1) remembering the ping document time along with config server time
when unable to
* take a lock, and (2) ensuring all config servers report similar time
s and have similar
* time rates (the difference in times must start and stay small).
*/ */
class DistributedLock { class DistributedLock {
public: public:
static LabeledLevel logLvl; static LabeledLevel logLvl;
struct PingData { struct PingData {
PingData( const string& _id , Date_t _lastPing , Date_t _remote , OID _ts ) PingData( const string& _id , Date_t _lastPing , Date_t _remote , OID _ts )
: id(_id), lastPing(_lastPing), remote(_remote), ts(_ts){ : id(_id), lastPing(_lastPing), remote(_remote), ts(_ts){
skipping to change at line 157 skipping to change at line 150
Date_t getRemoteTime(); Date_t getRemoteTime();
bool isRemoteTimeSkewed(); bool isRemoteTimeSkewed();
const string& getProcessId(); const string& getProcessId();
const ConnectionString& getRemoteConnection(); const ConnectionString& getRemoteConnection();
/** /**
* Checks the skew among a cluster of servers and returns true if t * Check the skew between a cluster of servers
he min and max clock
* times among the servers are within maxClockSkew.
*/ */
static bool checkSkew( const ConnectionString& cluster, static bool checkSkew( const ConnectionString& cluster, unsigned sk
unsigned skewChecks = NUM_LOCK_SKEW_CHECKS, ewChecks = NUM_LOCK_SKEW_CHECKS, unsigned long long maxClockSkew = MAX_LOCK
unsigned long long maxClockSkew = MAX_LOCK_C _CLOCK_SKEW, unsigned long long maxNetSkew = MAX_LOCK_NET_SKEW );
LOCK_SKEW,
unsigned long long maxNetSkew = MAX_LOCK_NET
_SKEW );
/** /**
* Get the remote time from a server or cluster * Get the remote time from a server or cluster
*/ */
static Date_t remoteTime( const ConnectionString& cluster, unsigned long long maxNetSkew = MAX_LOCK_NET_SKEW ); static Date_t remoteTime( const ConnectionString& cluster, unsigned long long maxNetSkew = MAX_LOCK_NET_SKEW );
static bool killPinger( DistributedLock& lock ); static bool killPinger( DistributedLock& lock );
/** /**
* Namespace for lock pings * Namespace for lock pings
 End of changes. 4 change blocks. 
32 lines changed or deleted 13 lines changed or added


 document.h   document.h 
skipping to change at line 165 skipping to change at line 165
// TODO: replace with logical equality once all current usages are fixed // TODO: replace with logical equality once all current usages are fixed
bool operator== (const Document& lhs) const { return _storage == lh s._storage; } bool operator== (const Document& lhs) const { return _storage == lh s._storage; }
explicit Document(const DocumentStorage* ptr) : _storage(ptr) {}; explicit Document(const DocumentStorage* ptr) : _storage(ptr) {};
private: private:
friend class FieldIterator; friend class FieldIterator;
friend class ValueStorage; friend class ValueStorage;
friend class MutableDocument; friend class MutableDocument;
friend class MutableValue;
const DocumentStorage& storage() const { const DocumentStorage& storage() const {
return (_storage ? *_storage : DocumentStorage::emptyDoc()); return (_storage ? *_storage : DocumentStorage::emptyDoc());
} }
intrusive_ptr<const DocumentStorage> _storage; intrusive_ptr<const DocumentStorage> _storage;
}; };
/** This class is returned by MutableDocument to allow you to modify it s values. /** This class is returned by MutableDocument to allow you to modify it s values.
* You are not allowed to hold variables of this type (enforced by the type system). * You are not allowed to hold variables of this type (enforced by the type system).
*/ */
skipping to change at line 198 skipping to change at line 197
private: private:
friend class MutableDocument; friend class MutableDocument;
/// can only be constructed or copied by self and friends /// can only be constructed or copied by self and friends
MutableValue(const MutableValue& other): _val(other._val) {} MutableValue(const MutableValue& other): _val(other._val) {}
explicit MutableValue(Value& val): _val(val) {} explicit MutableValue(Value& val): _val(val) {}
/// Used by MutableDocument(MutableValue) /// Used by MutableDocument(MutableValue)
const RefCountable*& getDocPtr() { const RefCountable*& getDocPtr() {
if (_val.getType() != Object || _val._storage.genericRCPtr == N if (_val.getType() != Object)
ULL) { *this = Value(Document());
// If the current value isn't an object we replace it with
a Object-typed Value.
// Note that we can't just use Document() here because that
is a NULL pointer and
// Value doesn't refcount NULL pointers. This led to a memo
ry leak (SERVER-10554)
// because MutableDocument::newStorage() would set a non-NU
LL pointer into the Value
// without setting the refCounter bit. While allocating a D
ocumentStorage here could
// result in an allocation where none is needed, in practic
e this is only called
// when we are about to add a field to the sub-document so
this just changes where
// the allocation is done.
_val = Value(Document(new DocumentStorage()));
}
return _val._storage.genericRCPtr; return _val._storage.genericRCPtr;
} }
MutableValue& operator= (const MutableValue&); // not assignable wi th another MutableValue MutableValue& operator= (const MutableValue&); // not assignable wi th another MutableValue
Value& _val; Value& _val;
}; };
/** MutableDocument is a Document builder that supports both adding and updating fields. /** MutableDocument is a Document builder that supports both adding and updating fields.
 End of changes. 2 change blocks. 
20 lines changed or deleted 2 lines changed or added


 document_source.h   document_source.h 
skipping to change at line 25 skipping to change at line 25
*/ */
#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 "util/intrusive_counter.h"
#include "db/clientcursor.h" #include "db/clientcursor.h"
#include "db/jsobj.h" #include "db/jsobj.h"
#include "db/matcher.h"
#include "db/pipeline/document.h" #include "db/pipeline/document.h"
#include "db/pipeline/expression.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 "db/pipeline/value.h"
#include "util/string_writer.h" #include "util/string_writer.h"
#include "mongo/db/projection.h" #include "mongo/db/projection.h"
#include "mongo/s/shard.h" #include "mongo/s/shard.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 Matcher;
class DocumentSource : class DocumentSource :
public IntrusiveCounterUnsigned, public IntrusiveCounterUnsigned,
public StringWriter { public StringWriter {
public: public:
virtual ~DocumentSource(); virtual ~DocumentSource();
// virtuals from StringWriter // virtuals from StringWriter
virtual void writeString(stringstream &ss) const; virtual void writeString(stringstream &ss) const;
skipping to change at line 427 skipping to change at line 427
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.
@param pBsonObj the query to record @param pBsonObj the query to record
*/ */
void setQuery(const shared_ptr<BSONObj> &pBsonObj); void setQuery(const BSONObj& query) { _query = query; }
/* /*
Record the sort that was specified for the cursor this wraps, if Record the sort 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.
@param pBsonObj the sort to record @param pBsonObj the sort to record
*/ */
void setSort(const shared_ptr<BSONObj> &pBsonObj); 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 shared_ptr<CursorWithContext>& cursorWithContext,
const intrusive_ptr<ExpressionContext> &pExpCtx); const intrusive_ptr<ExpressionContext> &pExpCtx);
skipping to change at line 465 skipping to change at line 465
bool hasCurrent; bool hasCurrent;
Document pCurrent; Document pCurrent;
string ns; // namespace string ns; // namespace
/* /*
The bson dependencies must outlive the Cursor wrapped by this The bson dependencies must outlive the Cursor wrapped by this
source. Therefore, bson dependencies must appear before pCursor source. Therefore, bson dependencies must appear before pCursor
in order cause its destructor to be called *after* pCursor's. in order cause its destructor to be called *after* pCursor's.
*/ */
shared_ptr<BSONObj> pQuery; BSONObj _query;
shared_ptr<BSONObj> pSort; BSONObj _sort;
shared_ptr<Projection> _projection; // shared with pClientCursor shared_ptr<Projection> _projection; // shared with pClientCursor
ParsedDeps _dependencies; ParsedDeps _dependencies;
shared_ptr<CursorWithContext> _cursorWithContext; shared_ptr<CursorWithContext> _cursorWithContext;
ClientCursor::Holder& cursor(); ClientCursor::Holder& cursor();
const ShardChunkManager* chunkMgr() { return _cursorWithContext->_c hunkMgr.get(); } const ShardChunkManager* chunkMgr() { return _cursorWithContext->_c hunkMgr.get(); }
bool canUseCoveredIndex(); bool canUseCoveredIndex();
 End of changes. 5 change blocks. 
5 lines changed or deleted 5 lines changed or added


 dur.h   dur.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 "diskloc.h" #include "mongo/db/diskloc.h"
#include "mongommf.h" #include "mongo/db/mongommf.h"
namespace mongo { namespace mongo {
class NamespaceDetails; class NamespaceDetails;
void mongoAbort(const char *msg); void mongoAbort(const char *msg);
void abort(); // not defined -- use mongoAbort() instead void abort(); // not defined -- use mongoAbort() instead
namespace dur { namespace dur {
 End of changes. 1 change blocks. 
2 lines changed or deleted 2 lines changed or added


 dur_commitjob.h   dur_commitjob.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 "../util/alignedbuilder.h" #include "mongo/db/cmdline.h"
#include "../util/mongoutils/hash.h" #include "mongo/db/d_concurrency.h"
#include "../util/concurrency/synchronization.h" #include "mongo/db/dur.h"
#include "cmdline.h" #include "mongo/db/durop.h"
#include "durop.h" #include "mongo/db/taskqueue.h"
#include "dur.h" #include "mongo/util/alignedbuilder.h"
#include "taskqueue.h" #include "mongo/util/concurrency/synchronization.h"
#include "d_concurrency.h" #include "mongo/util/mongoutils/hash.h"
namespace mongo { namespace mongo {
namespace dur { namespace dur {
void assertLockedForCommitting(); void assertLockedForCommitting();
/** Declaration of an intent to write to a region of a memory mappe d view /** Declaration of an intent to write to a region of a memory mappe d view
* We store the end rather than the start pointer to make operator < faster * We store the end rather than the start pointer to make operator < faster
* since that is heavily used in set lookup. * since that is heavily used in set lookup.
*/ */
 End of changes. 1 change blocks. 
8 lines changed or deleted 8 lines changed or added


 dur_journalimpl.h   dur_journalimpl.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 "dur_journalformat.h" #include "mongo/db/dur_journalformat.h"
#include "../util/logfile.h" #include "mongo/util/logfile.h"
namespace mongo { namespace mongo {
namespace dur { namespace dur {
/** the writeahead journal for durability */ /** the writeahead journal for durability */
class Journal { class Journal {
public: public:
string dir; // set by journalMakeDir() during initialization string dir; // set by journalMakeDir() during initialization
Journal(); Journal();
 End of changes. 1 change blocks. 
2 lines changed or deleted 2 lines changed or added


 durop.h   durop.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 "dur_journalformat.h" #include "mongo/db/dur_journalformat.h"
#include "../util/bufreader.h" #include "mongo/util/bufreader.h"
#include "../util/paths.h" #include "mongo/util/paths.h"
namespace mongo { namespace mongo {
class AlignedBuilder; class AlignedBuilder;
namespace dur { namespace dur {
/** DurOp - Operations we journal that aren't just basic writes. /** DurOp - Operations we journal that aren't just basic writes.
* *
* Basic writes are logged as JEntry's, and indicated in ram tempo rarily as struct dur::WriteIntent. * Basic writes are logged as JEntry's, and indicated in ram tempo rarily as struct dur::WriteIntent.
 End of changes. 1 change blocks. 
3 lines changed or deleted 3 lines changed or added


 engine.h   engine.h 
skipping to change at line 60 skipping to change at line 60
virtual string getString(const char* field) = 0; virtual string getString(const char* field) = 0;
virtual bool getBoolean(const char* field) = 0; virtual bool getBoolean(const char* field) = 0;
virtual double getNumber(const char* field) = 0; virtual double getNumber(const char* field) = 0;
virtual int getNumberInt(const char* field) { return (int)getNumber (field); } virtual int getNumberInt(const char* field) { return (int)getNumber (field); }
virtual long long getNumberLongLong(const char* field) { virtual long long getNumberLongLong(const char* field) {
return static_cast<long long>(getNumber(field)); return static_cast<long long>(getNumber(field));
} }
virtual void setElement(const char* field, const BSONElement& e) = 0; virtual void setElement(const char* field, const BSONElement& e) = 0;
virtual void setNumber(const char* field, double val) = 0; virtual void setNumber(const char* field, double val) = 0;
virtual void setString(const char* field, const char* val) = 0; virtual void setString(const char* field, const StringData& val) = 0;
virtual void setObject(const char* field, const BSONObj& obj, bool readOnly=true) = 0; virtual void setObject(const char* field, const BSONObj& obj, bool readOnly=true) = 0;
virtual void setBoolean(const char* field, bool val) = 0; virtual void setBoolean(const char* field, bool val) = 0;
virtual void setFunction(const char* field, const char* code) = 0; virtual void setFunction(const char* field, const char* code) = 0;
virtual int type(const char* field) = 0; virtual int type(const char* field) = 0;
virtual void append(BSONObjBuilder& builder, const char* fieldName, const char* scopeName); virtual void append(BSONObjBuilder& builder, const char* fieldName, const char* scopeName);
virtual void rename(const char* from, const char* to) = 0; virtual void rename(const char* from, const char* to) = 0;
skipping to change at line 138 skipping to change at line 138
/** /**
* if any changes are made to .system.js, call this * if any changes are made to .system.js, call this
* right now its just global - slightly inefficient, but a lot simp ler * right now its just global - slightly inefficient, but a lot simp ler
*/ */
static void storedFuncMod(); static void storedFuncMod();
static void validateObjectIdString(const string& str); static void validateObjectIdString(const string& str);
/** increments the number of times a scope was used */ /** increments the number of times a scope was used */
void incTimesUsed() { ++_numTimesUsed; } void incTimeUsed() { ++_numTimeUsed; }
/** gets the number of times a scope was used */ /** gets the number of times a scope was used */
int getTimesUsed() { return _numTimesUsed; } int getTimeUsed() { return _numTimeUsed; }
/** return true if last invoke() return'd native code */ /** return true if last invoke() return'd native code */
virtual bool isLastRetNativeCode() { return _lastRetIsNativeCode; } virtual bool isLastRetNativeCode() { return _lastRetIsNativeCode; }
class NoDBAccess { class NoDBAccess {
Scope* _s; Scope* _s;
public: public:
NoDBAccess(Scope* s) : _s(s) { NoDBAccess(Scope* s) : _s(s) {
} }
~NoDBAccess() { ~NoDBAccess() {
skipping to change at line 171 skipping to change at line 171
friend class PooledScope; friend class PooledScope;
virtual FunctionCacheMap& getFunctionCache() { return _cachedFuncti ons; } virtual FunctionCacheMap& getFunctionCache() { return _cachedFuncti ons; }
virtual ScriptingFunction _createFunction(const char* code, virtual ScriptingFunction _createFunction(const char* code,
ScriptingFunction functio nNumber = 0) = 0; ScriptingFunction functio nNumber = 0) = 0;
string _localDBName; string _localDBName;
long long _loadedVersion; long long _loadedVersion;
set<string> _storedNames; set<string> _storedNames;
static long long _lastVersion; static long long _lastVersion;
FunctionCacheMap _cachedFunctions; FunctionCacheMap _cachedFunctions;
int _numTimesUsed; int _numTimeUsed;
bool _lastRetIsNativeCode; // v8 only: set to true if eval'd script returns a native func bool _lastRetIsNativeCode; // v8 only: set to true if eval'd script returns a native func
}; };
class ScriptEngine : boost::noncopyable { class ScriptEngine : boost::noncopyable {
public: public:
ScriptEngine(); ScriptEngine();
virtual ~ScriptEngine(); virtual ~ScriptEngine();
virtual Scope* newScope() { virtual Scope* newScope() {
return createScope(); return createScope();
} }
virtual void runTest() = 0; virtual void runTest() = 0;
virtual bool utf8Ok() const = 0; virtual bool utf8Ok() const = 0;
static void setup(); static void setup();
/** gets a scope from the pool or a new one if pool is empty /** gets a scope from the pool or a new one if pool is empty
* @param db The db name * @param pool An identifier for the pool, usually the db name
* @param scopeType A unique id to limit scope sharing.
* This must include authenticated users.
* @return the scope * @return the scope
*/ */
auto_ptr<Scope> getPooledScope(const string& db, const string& scop auto_ptr<Scope> getPooledScope(const string& pool, const string& sc
eType); opeType);
/**
* call this method to release some JS resources when a thread is d
one
*/
void threadDone();
void setScopeInitCallback(void (*func)(Scope&)) { _scopeInitCallbac k = func; } void setScopeInitCallback(void (*func)(Scope&)) { _scopeInitCallbac k = func; }
static void setConnectCallback(void (*func)(DBClientWithCommands&)) { static void setConnectCallback(void (*func)(DBClientWithCommands&)) {
_connectCallback = func; _connectCallback = func;
} }
static void runConnectCallback(DBClientWithCommands& c) { static void runConnectCallback(DBClientWithCommands& c) {
if (_connectCallback) if (_connectCallback)
_connectCallback(c); _connectCallback(c);
} }
 End of changes. 6 change blocks. 
9 lines changed or deleted 13 lines changed or added


 engine_spidermonkey_internal.h   engine_spidermonkey_internal.h 
skipping to change at line 222 skipping to change at line 222
string getString( const char *field ); string getString( const char *field );
bool getBoolean( const char *field ); bool getBoolean( const char *field );
BSONObj getObject( const char *field ); BSONObj getObject( const char *field );
JSObject * getJSObject( const char * field ); JSObject * getJSObject( const char * field );
int type( const char *field ); int type( const char *field );
// ----- setters ------ // ----- setters ------
void setElement( const char *field , const BSONElement& val ); void setElement( const char *field , const BSONElement& val );
void setNumber( const char *field , double val ); void setNumber( const char *field , double val );
void setString( const char *field , const char * val ); void setString( const char *field , const StringData& val );
void setObject( const char *field , const BSONObj& obj , bool readO nly ); void setObject( const char *field , const BSONObj& obj , bool readO nly );
void setBoolean( const char *field , bool val ); void setBoolean( const char *field , bool val );
void setThis( const BSONObj * obj ); void setThis( const BSONObj * obj );
void setFunction( const char *field , const char * code ); void setFunction( const char *field , const char * code );
void rename( const char * from , const char * to ); void rename( const char * from , const char * to );
// ---- functions ----- // ---- functions -----
ScriptingFunction _createFunction(const char* code, ScriptingFuncti on functionNumber); ScriptingFunction _createFunction(const char* code, ScriptingFuncti on functionNumber);
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 engine_v8.h   engine_v8.h 
skipping to change at line 24 skipping to change at line 24
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <v8.h> #include <v8.h>
#include <vector> #include <vector>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
#include "mongo/base/string_data.h"
#include "mongo/client/dbclientinterface.h" #include "mongo/client/dbclientinterface.h"
#include "mongo/client/dbclientcursor.h" #include "mongo/client/dbclientcursor.h"
#include "mongo/platform/unordered_map.h" #include "mongo/platform/unordered_map.h"
#include "mongo/scripting/engine.h" #include "mongo/scripting/engine.h"
#include "mongo/scripting/v8_deadline_monitor.h" #include "mongo/scripting/v8_deadline_monitor.h"
#include "mongo/scripting/v8_profiler.h" #include "mongo/scripting/v8_profiler.h"
/** /**
* V8_SIMPLE_HEADER must be placed in any function called from a public API * V8_SIMPLE_HEADER must be placed in any function called from a public API
* that work with v8 handles (and/or must be within the V8Scope's isolate * that work with v8 handles (and/or must be within the V8Scope's isolate
skipping to change at line 184 skipping to change at line 185
v8::Handle<v8::Value> get(const char* field); v8::Handle<v8::Value> get(const char* field);
virtual double getNumber(const char* field); virtual double getNumber(const char* field);
virtual int getNumberInt(const char* field); virtual int getNumberInt(const char* field);
virtual long long getNumberLongLong(const char* field); virtual long long getNumberLongLong(const char* field);
virtual string getString(const char* field); virtual string getString(const char* field);
virtual bool getBoolean(const char* field); virtual bool getBoolean(const char* field);
virtual BSONObj getObject(const char* field); virtual BSONObj getObject(const char* field);
virtual void setNumber(const char* field, double val); virtual void setNumber(const char* field, double val);
virtual void setString(const char* field, const char* val); virtual void setString(const char* field, const StringData& val);
virtual void setBoolean(const char* field, bool val); virtual void setBoolean(const char* field, bool val);
virtual void setElement(const char* field, const BSONElement& e); virtual void setElement(const char* field, const BSONElement& e);
virtual void setObject(const char* field, const BSONObj& obj, bool readOnly); virtual void setObject(const char* field, const BSONObj& obj, bool readOnly);
virtual void setFunction(const char* field, const char* code); virtual void setFunction(const char* field, const char* code);
virtual int type(const char* field); virtual int type(const char* field);
virtual void rename(const char* from, const char* to); virtual void rename(const char* from, const char* to);
virtual int invoke(ScriptingFunction func, const BSONObj* args, con st BSONObj* recv, virtual int invoke(ScriptingFunction func, const BSONObj* args, con st BSONObj* recv,
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);
// These functions inject a function (either an unwrapped function void injectV8Function(const char* name, v8Function func, v8::Handle
pointer or a pre-wrapped <v8::Object>& obj);
// FunctionTemplate) into the provided object. If no object is prov void injectV8Function(const char* name, v8Function func, v8::Handle
ided, the function will <v8::Template>& t);
// 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::Handle<v8::Object> mongoToLZV8(const mongo::BSONObj& m, bool re adOnly = false); v8::Persistent<v8::Object> mongoToLZV8(const mongo::BSONObj& m, boo l readOnly = 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::Number> value, v8::Handle<v8::Value> 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::RegExp> v8Regex); v8::Handle<v8::Object> 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);
OID v8ToMongoObjectID(v8::Handle<v8::Object> obj); void v8ToMongoObjectID(BSONObjBuilder& b,
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()); 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 393 skipping to change at line 347
* 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 char *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;
// These are all named after the JS constructor name + FT v8::Persistent<v8::FunctionTemplate> lzFunctionTemplate;
v8::Persistent<v8::FunctionTemplate> _ObjectIdFT; v8::Persistent<v8::ObjectTemplate> lzObjectTemplate;
v8::Persistent<v8::FunctionTemplate> _DBRefFT; v8::Persistent<v8::ObjectTemplate> roObjectTemplate;
v8::Persistent<v8::FunctionTemplate> _DBPointerFT; v8::Persistent<v8::ObjectTemplate> lzArrayTemplate;
v8::Persistent<v8::FunctionTemplate> _BinDataFT; v8::Persistent<v8::ObjectTemplate> internalFieldObjects;
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 533 skipping to change at line 499
*/ */
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 = v8ExceptionToSTLString(&try_catch); _error = string("JavaScript execution failed: ") + v8ExceptionT oSTLString(&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. 19 change blocks. 
127 lines changed or deleted 70 lines changed or added


 error_codes.h   error_codes.h 
skipping to change at line 60 skipping to change at line 60
InvalidLength = 16, InvalidLength = 16,
ProtocolError = 17, ProtocolError = 17,
AuthenticationFailed = 18, AuthenticationFailed = 18,
CannotReuseObject = 19, CannotReuseObject = 19,
IllegalOperation = 20, IllegalOperation = 20,
EmptyArrayOperation = 21, EmptyArrayOperation = 21,
InvalidBSON = 22, InvalidBSON = 22,
AlreadyInitialized = 23, AlreadyInitialized = 23,
LockTimeout = 24, LockTimeout = 24,
RemoteValidationError = 25, RemoteValidationError = 25,
NodeNotFound = 74, NamespaceNotFound = 26,
IndexNotFound = 27,
PathNotViable = 28,
NonExistentPath = 29,
InvalidPath = 30,
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. 
1 lines changed or deleted 5 lines changed or added


 explain.h   explain.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 "cursor.h" #include "mongo/db/cursor.h"
#include "../util/timer.h" #include "mongo/util/timer.h"
namespace mongo { namespace mongo {
/** /**
* Note: by default we filter out allPlans and oldPlan in the shell's * Note: by default we filter out allPlans and oldPlan in the shell's
* explain() function. If you add any recursive structures, make sure t o * explain() function. If you add any recursive structures, make sure t o
* edit the JS to make sure everything gets filtered. * edit the JS to make sure everything gets filtered.
*/ */
/** The timer starts on construction and provides the duration since th en or until stopped. */ /** The timer starts on construction and provides the duration since th en or until stopped. */
 End of changes. 1 change blocks. 
2 lines changed or deleted 2 lines changed or added


 expression.h   expression.h 
// expression.h
/** /**
* Copyright (c) 2011 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
* as published by the Free Software Foundation. 3,
* 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 License * You should have received a copy of the GNU Affero General Public Lice
* along with this program. If not, see <http://www.gnu.org/licenses/>. nse
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/pch.h" #include "mongo/base/disallow_copying.h"
#include "mongo/base/status.h"
#include "db/pipeline/field_path.h" #include "mongo/bson/bsonobj.h"
#include "db/pipeline/value.h" #include "mongo/db/matcher/matchable.h"
#include "util/intrusive_counter.h" #include "mongo/db/matcher/match_details.h"
namespace mongo { namespace mongo {
class BSONArrayBuilder; class TreeMatchExpression;
class BSONElement;
class BSONObjBuilder;
class Builder;
class Document;
class MutableDocument;
class DocumentSource;
class ExpressionContext;
class Value;
class Expression : class MatchExpression {
public IntrusiveCounterUnsigned { MONGO_DISALLOW_COPYING( MatchExpression );
public: public:
virtual ~Expression() {}; enum MatchType {
// tree types
/* AND, OR, NOR, NOT,
Optimize the Expression.
This provides an opportunity to do constant folding, or to
collapse nested operators that have the same precedence, such as
$add, $and, or $or.
The Expression should be replaced with the return value, which ma
y
or may not be the same object. In the case of constant folding,
a computed expression may be replaced by a constant.
@returns the optimized Expression
*/
virtual intrusive_ptr<Expression> optimize() = 0;
/**
Add this expression's field dependencies to the set
Expressions are trees, so this is often recursive. // array types
ALL, ELEM_MATCH_OBJECT, ELEM_MATCH_VALUE, SIZE,
@param deps output parameter // leaf types
@param path path to self if all ancestors are ExpressionObjects. LTE, LT, EQ, GT, GTE, REGEX, MOD, EXISTS, MATCH_IN, NIN,
Top-level ExpressionObject gets pointer to empty vec
tor.
If any other Expression is an ancestor, or in other
cases
where {a:1} inclusion objects aren't allowed, they g
et
NULL.
*/
virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const = 0;
/** simple expressions are just inclusion exclusion as supported by
ExpressionObject */
virtual bool isSimple() { return false; }
/*
Evaluate the Expression using the given document as input.
@returns the computed value
*/
virtual Value evaluate(const Document& pDocument) const = 0;
/*
Add the Expression (and any descendant Expressions) into a BSON
object that is under construction.
Unevaluated Expressions always materialize as objects. Evaluatio
n
may produce a scalar or another object, either of which will be
substituted inline.
@param pBuilder the builder to add the expression to
@param fieldName the name the object should be given
@param requireExpression specify true if the value must appear
as an expression; this is used by DocumentSources like
$project which distinguish between field inclusion and virtual
field specification; See ExpressionConstant.
*/
virtual void addToBsonObj(BSONObjBuilder *pBuilder,
StringData fieldName,
bool requireExpression) const = 0;
/*
Add the Expression (and any descendant Expressions) into a BSON
array that is under construction.
Unevaluated Expressions always materialize as objects. Evaluatio
n
may produce a scalar or another object, either of which will be
substituted inline.
@param pBuilder the builder to add the expression to // special types
*/ TYPE_OPERATOR, GEO, WHERE,
virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const = 0;
/*
Convert the expression into a BSONObj that corresponds to the
db.collection.find() predicate language. This is intended for
use by DocumentSourceFilter.
This is more limited than the full expression language supported
by all available expressions in a DocumentSource processing
pipeline, and will fail with an assertion if an attempt is made
to go outside the bounds of the recognized patterns, which don't
include full computed expressions. There are other methods avail
able
on DocumentSourceFilter which can be used to analyze a filter
predicate and break it up into appropriate expressions which can
be translated within these constraints. As a result, the default
implementation is to fail with an assertion; only a subset of
operators will be able to fulfill this request.
@param pBuilder the builder to add the expression to.
*/
virtual void toMatcherBson(BSONObjBuilder *pBuilder) const;
/* // things that maybe shouldn't even be nodes
Utility class for parseObject() below. ATOMIC
DOCUMENT_OK indicates that it is OK to use a Document in the curr
ent
context.
*/
class ObjectCtx {
public:
ObjectCtx(int options);
static const int DOCUMENT_OK = 0x0001;
static const int TOP_LEVEL = 0x0002;
static const int INCLUSION_OK = 0x0004;
bool documentOk() const;
bool topLevel() const;
bool inclusionOk() const;
private:
int options;
}; };
/* MatchExpression( MatchType type );
Parse a BSONElement Object. The object could represent a functio virtual ~MatchExpression(){}
nal
expression or a Document expression.
@param pBsonElement the element representing the object
@param pCtx a MiniCtx representing the options above
@returns the parsed Expression
*/
static intrusive_ptr<Expression> parseObject(
BSONElement *pBsonElement, ObjectCtx *pCtx);
/*
Parse a BSONElement Object which has already been determined to b
e
functional expression.
@param pOpName the name of the (prefix) operator
@param pBsonElement the BSONElement to parse
@returns the parsed Expression
*/
static intrusive_ptr<Expression> parseExpression(
const char *pOpName, BSONElement *pBsonElement);
/* /**
Parse a BSONElement which is an operand in an Expression. * determins if the doc matches the expression
* there could be an expression that looks at fields, or the entire
@param pBsonElement the expected operand's BSONElement doc
@returns the parsed operand, as an Expression
*/ */
static intrusive_ptr<Expression> parseOperand( virtual bool matches( const MatchableDocument* doc, MatchDetails* d
BSONElement *pBsonElement); etails = 0 ) const = 0;
/* virtual bool matchesBSON( const BSONObj& doc, MatchDetails* details
Produce a field path string with the field prefix removed. = 0 ) const;
Throws an error if the field prefix is not present. /**
* does the element match the expression
@param prefixedField the prefixed field * not valid for all expressions ($where) where this will immediate
@returns the field path with the prefix removed ly return false
*/ */
static string removeFieldPrefix(const string &prefixedField); virtual bool matchesSingleElement( const BSONElement& e ) const = 0 ;
/* virtual size_t numChildren() const { return 0; }
Enumeration of comparison operators. These are shared between a virtual const MatchExpression* getChild( size_t i ) const { return
few expression implementations, so they are factored out here. NULL; }
Any changes to these values require adjustment of the lookup
table in the implementation.
*/
enum CmpOp {
EQ = 0, // return true for a == b, false otherwise
NE = 1, // return true for a != b, false otherwise
GT = 2, // return true for a > b, false otherwise
GTE = 3, // return true for a >= b, false otherwise
LT = 4, // return true for a < b, false otherwise
LTE = 5, // return true for a <= b, false otherwise
CMP = 6, // return -1, 0, 1 for a < b, a == b, a > b
};
static int signum(int i);
protected:
typedef vector<intrusive_ptr<Expression> > ExpressionVector;
}; MatchType matchType() const { return _matchType; }
class ExpressionNary :
public Expression {
public:
// virtuals from Expression
virtual intrusive_ptr<Expression> optimize();
virtual void addToBsonObj(BSONObjBuilder *pBuilder,
StringData fieldName,
bool requireExpression) const;
virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const;
virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const;
/*
Add an operand to the n-ary expression.
@param pExpression the expression to add
*/
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
/*
Return a factory function that will make Expression nodes of
the same type as this. This will be used to create constant
expressions for constant folding for optimize(). Only return
a factory function if this operator is both associative and
commutative. The default implementation returns NULL; optimize()
will recognize that and stop.
Note that ExpressionNary::optimize() promises that if it uses thi
s
to fold constants, then if optimize() returns an ExpressionNary,
any remaining constant will be the last one in vpOperand. Derive
d
classes may take advantage of this to do further optimizations in
their optimize().
@returns pointer to a factory function or NULL virtual string toString() const;
*/ virtual void debugString( StringBuilder& debug, int level = 0 ) con
virtual intrusive_ptr<ExpressionNary> (*getFactory() const)(); st = 0;
/*
Get the name of the operator.
@returns the name of the operator; this string belongs to the cla
ss
implementation, and should not be deleted
and should not
*/
virtual const char *getOpName() const = 0;
virtual bool equivalent( const MatchExpression* other ) const = 0;
protected: protected:
ExpressionNary(); void _debugAddSpace( StringBuilder& debug, int level ) const;
ExpressionVector vpOperand;
/*
Add the expression to the builder.
If there is only one operand (a unary operator), then the operand
is added directly, without an array. For more than one operand,
a named array is created. In both cases, the result is an object
.
@param pBuilder the (blank) builder to add the expression to
@param pOpName the name of the operator
*/
virtual void toBson(BSONObjBuilder *pBuilder,
const char *pOpName) const;
/*
Checks the current size of vpOperand; if the size equal to or
greater than maxArgs, fires a user assertion indicating that this
operator cannot have this many arguments.
The equal is there because this is intended to be used in
addOperand() to check for the limit *before* adding the requested
argument.
@param maxArgs the maximum number of arguments the operator accep
ts
*/
void checkArgLimit(unsigned maxArgs) const;
/*
Checks the current size of vpOperand; if the size is not equal to
reqArgs, fires a user assertion indicating that this must have
exactly reqArgs arguments.
This is meant to be used in evaluate(), *before* the evaluation
takes place.
@param reqArgs the number of arguments this operator requires
*/
void checkArgCount(unsigned reqArgs) const;
};
class ExpressionAdd :
public ExpressionNary {
public:
// virtuals from Expression
virtual ~ExpressionAdd();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
// virtuals from ExpressionNary
virtual intrusive_ptr<ExpressionNary> (*getFactory() const)();
/*
Create an expression that finds the sum of n operands.
@returns addition expression
*/
static intrusive_ptr<ExpressionNary> create();
};
class ExpressionAnd :
public ExpressionNary {
public:
// virtuals from Expression
virtual ~ExpressionAnd();
virtual intrusive_ptr<Expression> optimize();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void toMatcherBson(BSONObjBuilder *pBuilder) const;
// virtuals from ExpressionNary
virtual intrusive_ptr<ExpressionNary> (*getFactory() const)();
/*
Create an expression that finds the conjunction of n operands.
The conjunction uses short-circuit logic; the expressions are
evaluated in the order they were added to the conjunction, and
the evaluation stops and returns false on the first operand that
evaluates to false.
@returns conjunction expression
*/
static intrusive_ptr<ExpressionNary> create();
private: private:
ExpressionAnd(); MatchType _matchType;
}; };
class ExpressionCoerceToBool : /**
public Expression { * this isn't really an expression, but a hint to other things
* not sure where to put it in the end
*/
class AtomicMatchExpression : public MatchExpression {
public: public:
// virtuals from ExpressionNary AtomicMatchExpression() : MatchExpression( ATOMIC ){}
virtual ~ExpressionCoerceToBool();
virtual intrusive_ptr<Expression> optimize();
virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const;
virtual Value evaluate(const Document& pDocument) const;
virtual void addToBsonObj(BSONObjBuilder *pBuilder,
StringData fieldName,
bool requireExpression) const;
virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const;
static intrusive_ptr<ExpressionCoerceToBool> create( virtual bool matches( const MatchableDocument* doc, MatchDetails* d
const intrusive_ptr<Expression> &pExpression); etails = 0 ) const {
return true;
}
private: virtual bool matchesSingleElement( const BSONElement& e ) const {
ExpressionCoerceToBool(const intrusive_ptr<Expression> &pExpression return true;
); }
intrusive_ptr<Expression> pExpression; virtual void debugString( StringBuilder& debug, int level = 0 ) con
}; st;
class ExpressionCompare : virtual bool equivalent( const MatchExpression* other ) const {
public ExpressionNary { return other->matchType() == ATOMIC;
public: }
// virtuals from ExpressionNary
virtual ~ExpressionCompare();
virtual intrusive_ptr<Expression> optimize();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
/*
Shorthands for creating various comparisons expressions.
Provide for conformance with the uniform function pointer signatu
re
required for parsing.
These create a particular comparison operand, without any
operands. Those must be added via ExpressionNary::addOperand().
*/
static intrusive_ptr<ExpressionNary> createCmp();
static intrusive_ptr<ExpressionNary> createEq();
static intrusive_ptr<ExpressionNary> createNe();
static intrusive_ptr<ExpressionNary> createGt();
static intrusive_ptr<ExpressionNary> createGte();
static intrusive_ptr<ExpressionNary> createLt();
static intrusive_ptr<ExpressionNary> createLte();
private:
friend class ExpressionFieldRange;
ExpressionCompare(CmpOp cmpOp);
CmpOp cmpOp;
}; };
class ExpressionConcat : public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionConcat();
virtual Value evaluate(const Document& input) const;
virtual const char *getOpName() const;
static intrusive_ptr<ExpressionNary> create();
};
class ExpressionCond : public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionCond();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionCond();
};
class ExpressionConstant :
public Expression {
public:
// virtuals from Expression
virtual ~ExpressionConstant();
virtual intrusive_ptr<Expression> optimize();
virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const;
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addToBsonObj(BSONObjBuilder *pBuilder,
StringData fieldName,
bool requireExpression) const;
virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const;
static intrusive_ptr<ExpressionConstant> createFromBsonElement(
BSONElement *pBsonElement);
static intrusive_ptr<ExpressionConstant> create(const Value& pValue
);
/*
Get the constant value represented by this Expression.
@returns the value
*/
Value getValue() const;
private:
ExpressionConstant(BSONElement *pBsonElement);
ExpressionConstant(const Value& pValue);
Value pValue;
};
class ExpressionDayOfMonth :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionDayOfMonth();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionDayOfMonth();
};
class ExpressionDayOfWeek :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionDayOfWeek();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionDayOfWeek();
};
class ExpressionDayOfYear :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionDayOfYear();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionDayOfYear();
};
class ExpressionDivide :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionDivide();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionDivide();
};
class ExpressionFieldPath :
public Expression {
public:
// virtuals from Expression
virtual ~ExpressionFieldPath();
virtual intrusive_ptr<Expression> optimize();
virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const;
virtual Value evaluate(const Document& pDocument) const;
virtual void addToBsonObj(BSONObjBuilder *pBuilder,
StringData fieldName,
bool requireExpression) const;
virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const;
/*
Create a field path expression.
Evaluation will extract the value associated with the given field
path from the source document.
@param fieldPath the field path string, without any leading docum
ent
indicator
@returns the newly created field path expression
*/
static intrusive_ptr<ExpressionFieldPath> create(
const string &fieldPath);
/*
Return a string representation of the field path.
@param fieldPrefix whether or not to include the document field
indicator prefix
@returns the dot-delimited field path
*/
string getFieldPath(bool fieldPrefix) const;
/*
Write a string representation of the field path to a stream.
@param the stream to write to
@param fieldPrefix whether or not to include the document field
indicator prefix
*/
void writeFieldPath(ostream &outStream, bool fieldPrefix) const;
private:
ExpressionFieldPath(const string &fieldPath);
/*
Internal implementation of evaluate(), used recursively.
The internal implementation doesn't just use a loop because of
the possibility that we need to skip over an array. If the path
is "a.b.c", and a is an array, then we fan out from there, and
traverse "b.c" for each element of a:[...]. This requires that
a be an array of objects in order to navigate more deeply.
@param index current path field index to extract
@param input current document traversed to (not the top-level one
)
@returns the field found; could be an array
*/
Value evaluatePath(size_t index, const Document& input) const;
// Helper for evaluatePath to handle Array case
Value evaluatePathArray(size_t index, const Value& input) const;
FieldPath fieldPath;
};
class ExpressionFieldRange :
public Expression {
public:
// virtuals from expression
virtual ~ExpressionFieldRange();
virtual intrusive_ptr<Expression> optimize();
virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const;
virtual Value evaluate(const Document& pDocument) const;
virtual void addToBsonObj(BSONObjBuilder *pBuilder,
StringData fieldName,
bool requireExpression) const;
virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const;
virtual void toMatcherBson(BSONObjBuilder *pBuilder) const;
/*
Create a field range expression.
Field ranges are meant to match up with classic Matcher semantics
,
and therefore are conjunctions. For example, these appear in
mongo shell predicates in one of these forms:
{ a : C } -> (a == C) // degenerate "point" range
{ a : { $lt : C } } -> (a < C) // open range
{ a : { $gt : C1, $lte : C2 } } -> ((a > C1) && (a <= C2)) // clo
sed
When initially created, a field range only includes one end of
the range. Additional points may be added via intersect().
Note that NE and CMP are not supported.
@param pFieldPath the field path for extracting the field value
@param cmpOp the comparison operator
@param pValue the value to compare against
@returns the newly created field range expression
*/
static intrusive_ptr<ExpressionFieldRange> create(
const intrusive_ptr<ExpressionFieldPath> &pFieldPath,
CmpOp cmpOp, const Value& pValue);
/*
Add an intersecting range.
This can be done any number of times after creation. The
range is internally optimized for each new addition. If the new
intersection extends or reduces the values within the range, the
internal representation is adjusted to reflect that.
Note that NE and CMP are not supported.
@param cmpOp the comparison operator
@param pValue the value to compare against
*/
void intersect(CmpOp cmpOp, const Value& pValue);
private:
ExpressionFieldRange(const intrusive_ptr<ExpressionFieldPath> &pFie
ldPath,
CmpOp cmpOp,
const Value& pValue);
intrusive_ptr<ExpressionFieldPath> pFieldPath;
class Range {
public:
Range(CmpOp cmpOp, const Value& pValue);
Range(const Range &rRange);
Range *intersect(const Range *pRange) const;
bool contains(const Value& pValue) const;
Range(const Value& pBottom, bool bottomOpen,
const Value& pTop, bool topOpen);
bool bottomOpen;
bool topOpen;
Value pBottom;
Value pTop;
};
scoped_ptr<Range> pRange;
/*
Add to a generic Builder.
The methods to append items to an object and an array differ by
their inclusion of a field name. For more complicated objects,
it makes sense to abstract that out and use a generic builder tha
t
always looks the same, and then implement addToBsonObj() and
addToBsonArray() by using the common method.
*/
void addToBson(Builder *pBuilder) const;
};
class ExpressionHour :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionHour();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionHour();
};
class ExpressionIfNull :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionIfNull();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionIfNull();
};
class ExpressionMillisecond :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionMillisecond();
virtual Value evaluate(const Document& document) const;
virtual const char* getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression>& pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionMillisecond();
};
class ExpressionMinute :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionMinute();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionMinute();
};
class ExpressionMod :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionMod();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionMod();
};
class ExpressionMultiply :
public ExpressionNary {
public:
// virtuals from Expression
virtual ~ExpressionMultiply();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
// virtuals from ExpressionNary
virtual intrusive_ptr<ExpressionNary> (*getFactory() const)();
/*
Create an expression that finds the product of n operands.
@returns multiplication expression
*/
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionMultiply();
};
class ExpressionMonth :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionMonth();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionMonth();
};
class ExpressionNot :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionNot();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionNot();
};
class ExpressionObject :
public Expression {
public:
// virtuals from Expression
virtual ~ExpressionObject();
virtual intrusive_ptr<Expression> optimize();
virtual bool isSimple();
virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const;
/** Only evaluates non inclusion expressions. For inclusions, use
addToDocument(). */
virtual Value evaluate(const Document& pDocument) const;
virtual void addToBsonObj(BSONObjBuilder *pBuilder,
StringData fieldName,
bool requireExpression) const;
virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const;
/*
evaluate(), but return a Document instead of a Value-wrapped
Document.
@param pDocument the input Document
@returns the result document
*/
Document evaluateDocument(const Document& pDocument) const;
/*
evaluate(), but add the evaluated fields to a given document
instead of creating a new one.
@param pResult the Document to add the evaluated expressions to
@param pDocument the input Document for this level
@param rootDoc the root of the whole input document
*/
void addToDocument(MutableDocument& pResult,
const Document& pDocument,
const Document& rootDoc
) const;
// estimated number of fields that will be output
size_t getSizeHint() const;
/*
Create an empty expression. Until fields are added, this
will evaluate to an empty document (object).
*/
static intrusive_ptr<ExpressionObject> create();
/*
Add a field to the document expression.
@param fieldPath the path the evaluated expression will have in t
he
result Document
@param pExpression the expression to evaluate obtain this field's
Value in the result Document
*/
void addField(const FieldPath &fieldPath,
const intrusive_ptr<Expression> &pExpression);
/*
Add a field path to the set of those to be included.
Note that including a nested field implies including everything o
n
the path leading down to it.
@param fieldPath the name of the field to be included
*/
void includePath(const string &fieldPath);
/*
Get a count of the added fields.
@returns how many fields have been added
*/
size_t getFieldCount() const;
/*
Specialized BSON conversion that allows for writing out a
$project specification. This creates a standalone object, which
must
be added to a containing object with a name
@param pBuilder where to write the object to
@param requireExpression see Expression::addToBsonObj
*/
void documentToBson(BSONObjBuilder *pBuilder,
bool requireExpression) const;
/*
Visitor abstraction used by emitPaths(). Each path is recorded b
y
calling path().
*/
class PathSink {
public:
virtual ~PathSink() {};
/**
Record a path.
@param path the dotted path string
@param include if true, the path is included; if false, the
path
is excluded
*/
virtual void path(const string &path, bool include) = 0;
};
void excludeId(bool b) { _excludeId = b; }
private:
ExpressionObject();
// mapping from fieldname to Expression to generate the value
// NULL expression means include from source document
typedef map<string, intrusive_ptr<Expression> > ExpressionMap;
ExpressionMap _expressions;
// this is used to maintain order for generated fields not in the s
ource document
vector<string> _order;
bool _excludeId;
};
class ExpressionOr :
public ExpressionNary {
public:
// virtuals from Expression
virtual ~ExpressionOr();
virtual intrusive_ptr<Expression> optimize();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void toMatcherBson(BSONObjBuilder *pBuilder) const;
// virtuals from ExpressionNary
virtual intrusive_ptr<ExpressionNary> (*getFactory() const)();
/*
Create an expression that finds the conjunction of n operands.
The conjunction uses short-circuit logic; the expressions are
evaluated in the order they were added to the conjunction, and
the evaluation stops and returns false on the first operand that
evaluates to false.
@returns conjunction expression
*/
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionOr();
};
class ExpressionSecond :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionSecond();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionSecond();
};
class ExpressionStrcasecmp :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionStrcasecmp();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionStrcasecmp();
};
class ExpressionSubstr :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionSubstr();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionSubstr();
};
class ExpressionSubtract :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionSubtract();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionSubtract();
};
class ExpressionToLower :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionToLower();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionToLower();
};
class ExpressionToUpper :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionToUpper();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionToUpper();
};
class ExpressionWeek :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionWeek();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionWeek();
};
class ExpressionYear :
public ExpressionNary {
public:
// virtuals from ExpressionNary
virtual ~ExpressionYear();
virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n);
static intrusive_ptr<ExpressionNary> create();
private:
ExpressionYear();
};
}
/* ======================= INLINED IMPLEMENTATIONS ========================
== */
namespace mongo {
inline int Expression::signum(int i) {
if (i < 0)
return -1;
if (i > 0)
return 1;
return 0;
}
inline Value ExpressionConstant::getValue() const {
return pValue;
}
inline string ExpressionFieldPath::getFieldPath(bool fieldPrefix) const
{
return fieldPath.getPath(fieldPrefix);
}
inline void ExpressionFieldPath::writeFieldPath(
ostream &outStream, bool fieldPrefix) const {
return fieldPath.writePath(outStream, fieldPrefix);
}
inline size_t ExpressionObject::getFieldCount() const {
return _expressions.size();
}
} }
 End of changes. 33 change blocks. 
1129 lines changed or deleted 76 lines changed or added


 extsort.h   extsort.h 
skipping to change at line 29 skipping to change at line 29
#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/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
#if MONGO_USE_NEW_SORTER
# include "mongo/db/sorter/sorter.h"
#endif
namespace mongo { namespace mongo {
typedef pair<BSONObj, DiskLoc> ExternalSortDatum;
/**
* To external sort, you provide a pointer to an implementation of this
class.
* The compare function follows the usual -1, 0, 1 semantics.
*/
class ExternalSortComparison {
public:
virtual ~ExternalSortComparison() { }
virtual int compare(const ExternalSortDatum& l, const ExternalSortD
atum& r) const = 0;
};
#if MONGO_USE_NEW_SORTER
// TODO This class will probably disappear in the future or be replaced
with a typedef
class BSONObjExternalSorter : boost::noncopyable {
public:
typedef pair<BSONObj, DiskLoc> Data;
typedef SortIteratorInterface<BSONObj, DiskLoc> Iterator;
BSONObjExternalSorter(const ExternalSortComparison* comp, long maxF
ileSize=100*1024*1024);
void add( const BSONObj& o, const DiskLoc& loc, bool mayInterrupt )
{
*_mayInterrupt = mayInterrupt;
_sorter->add(o.getOwned(), loc);
}
auto_ptr<Iterator> iterator() { return auto_ptr<Iterator>(_sorter->
done()); }
void sort( bool mayInterrupt ) { *_mayInterrupt = mayInterrupt; }
int numFiles() { return _sorter->numFiles(); }
long getCurSizeSoFar() { return _sorter->memUsed(); }
void hintNumObjects(long long) {} // unused
private:
shared_ptr<bool> _mayInterrupt;
scoped_ptr<Sorter<BSONObj, DiskLoc> > _sorter;
};
#else
/** /**
for external (disk) sorting by BSONObj and attaching a value for external (disk) sorting by BSONObj and attaching a value
*/ */
class BSONObjExternalSorter : boost::noncopyable { class BSONObjExternalSorter : boost::noncopyable {
public: public:
BSONObjExternalSorter( IndexInterface &i, const BSONObj & order = B BSONObjExternalSorter(const ExternalSortComparison* cmp,
SONObj() , long maxFileSize = 1024 * 1024 * 100 ); long maxFileSize = 1024 * 1024 * 100 );
~BSONObjExternalSorter(); ~BSONObjExternalSorter();
typedef pair<BSONObj,DiskLoc> Data;
/** @return the IndexInterface used to perform key comparisons. */
const IndexInterface& getIndexInterface() const { return _idxi; }
private: private:
static HLMutex _extSortMutex; static HLMutex _extSortMutex;
IndexInterface& _idxi;
static int _compare(IndexInterface& i, const Data& l, const Data& r static int _compare(const ExternalSortComparison* cmp, const Extern
, const Ordering& order); alSortDatum& l,
const ExternalSortDatum& r);
class MyCmp { class MyCmp {
public: public:
MyCmp( IndexInterface& i, BSONObj order = BSONObj() ) : _i(i), MyCmp(const ExternalSortComparison* cmp) : _cmp(cmp) { }
_order( Ordering::make(order) ) {} bool operator()( const ExternalSortDatum &l, const ExternalSort
bool operator()( const Data &l, const Data &r ) const { Datum &r ) const {
return _compare(_i, l, r, _order) < 0; return _cmp->compare(l, r) < 0;
}; };
private: private:
IndexInterface& _i; const ExternalSortComparison* _cmp;
const Ordering _order;
}; };
static IndexInterface *extSortIdxInterface;
static Ordering extSortOrder;
static bool extSortMayInterrupt; static bool extSortMayInterrupt;
static int extSortComp( const void *lv, const void *rv ); static int extSortComp( const void *lv, const void *rv );
static const ExternalSortComparison* staticExtSortCmp;
class FileIterator : boost::noncopyable { class FileIterator : boost::noncopyable {
public: public:
FileIterator( const std::string& file ); FileIterator( const std::string& file );
~FileIterator(); ~FileIterator();
bool more(); bool more();
Data next(); ExternalSortDatum next();
private: private:
bool _read( char* buf, long long count ); bool _read( char* buf, long long count );
int _file; int _file;
unsigned long long _length; unsigned long long _length;
unsigned long long _readSoFar; unsigned long long _readSoFar;
}; };
public: public:
typedef FastArray<Data> InMemory; typedef FastArray<ExternalSortDatum> InMemory;
class Iterator : boost::noncopyable { class Iterator : boost::noncopyable {
public: public:
Iterator( BSONObjExternalSorter * sorter ); Iterator( BSONObjExternalSorter * sorter );
~Iterator(); ~Iterator();
bool more(); bool more();
Data next(); ExternalSortDatum next();
private: private:
MyCmp _cmp; MyCmp _cmp;
vector<FileIterator*> _files; vector<FileIterator*> _files;
vector< pair<Data,bool> > _stash; vector< pair<ExternalSortDatum,bool> > _stash;
InMemory * _in; InMemory * _in;
InMemory::iterator _it; InMemory::iterator _it;
}; };
void add( const BSONObj& o, const DiskLoc& loc, bool mayInterrupt ) ; void add( const BSONObj& o, const DiskLoc& loc, bool mayInterrupt ) ;
/* call after adding values, and before fetching the iterator */ /* call after adding values, and before fetching the iterator */
void sort( bool mayInterrupt ); void sort( bool mayInterrupt );
skipping to change at line 128 skipping to change at line 168
_arraySize = (int)(numObjects + 100); _arraySize = (int)(numObjects + 100);
} }
private: private:
void _sortInMem( bool mayInterrupt ); void _sortInMem( bool mayInterrupt );
void sort( const std::string& file ); void sort( const std::string& file );
void finishMap( bool mayInterrupt ); void finishMap( bool mayInterrupt );
BSONObj _order; const ExternalSortComparison* _cmp;
long _maxFilesize; long _maxFilesize;
boost::filesystem::path _root; boost::filesystem::path _root;
int _arraySize; int _arraySize;
InMemory * _cur; InMemory * _cur;
long _curSizeSoFar; long _curSizeSoFar;
list<string> _files; list<string> _files;
bool _sorted; bool _sorted;
static unsigned long long _compares; static unsigned long long _compares;
static unsigned long long _uniqueNumber; static unsigned long long _uniqueNumber;
}; };
#endif
} }
 End of changes. 16 change blocks. 
21 lines changed or deleted 67 lines changed or added


 field_ref.h   field_ref.h 
skipping to change at line 69 skipping to change at line 69
/** /**
* 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 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() const; std::string dottedField( size_t offset = 0 ) 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
// //
skipping to change at line 91 skipping to change at line 91
* 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 three 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 size_t _size; // # of field parts st ored
StringData _fixed[kReserveAhead]; // first kResevedAhead field components StringData _fixed[kReserveAhead]; // first kResevedAhead field components
std::vector<StringData> _variable; // remaining field com ponents std::vector<StringData> _variable; // remaining field com ponents
 End of changes. 2 change blocks. 
1 lines changed or deleted 7 lines changed or added


 fts_search.h   fts_search.h 
skipping to change at line 27 skipping to change at line 27
*/ */
#pragma once #pragma once
#include <map> #include <map>
#include <set> #include <set>
#include <vector> #include <vector>
#include <queue> #include <queue>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
#include "mongo/db/fts/fts_index.h"
#include "mongo/db/fts/fts_matcher.h" #include "mongo/db/fts/fts_matcher.h"
#include "mongo/db/fts/fts_query.h" #include "mongo/db/fts/fts_query.h"
#include "mongo/db/fts/fts_util.h" #include "mongo/db/fts/fts_util.h"
#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/matcher.h" #include "mongo/db/matcher.h"
namespace mongo { namespace mongo {
class BtreeCursor; class BtreeCursor;
namespace fts { namespace fts {
// priority queue template, for use when we're populating results // priority queue template, for use when we're populating results
// vector returned to the user. extends the default priority_queue // vector returned to the user. extends the default priority_queue
skipping to change at line 60 skipping to change at line 60
}; };
typedef a_priority_queue<ScoredLocation, vector<ScoredLocation>, Sc oredLocationComp> Results; typedef a_priority_queue<ScoredLocation, vector<ScoredLocation>, Sc oredLocationComp> Results;
class FTSSearch { class FTSSearch {
MONGO_DISALLOW_COPYING(FTSSearch); MONGO_DISALLOW_COPYING(FTSSearch);
public: public:
typedef std::map<Record*,double> Scores; typedef std::map<Record*,double> Scores;
FTSSearch( NamespaceDetails* ns, FTSSearch( IndexDescriptor* descriptor,
const IndexDetails& id, const FTSSpec& ftsSpec,
const BSONObj& indexPrefix, const BSONObj& indexPrefix,
const FTSQuery& query, const FTSQuery& query,
const BSONObj& filter ); const BSONObj& filter );
void go(Results* results, unsigned limit ); void go(Results* results, unsigned limit );
const FTSIndex * getIndex() const { return _fts; }
long long getKeysLookedAt() const { return _keysLookedAt; } long long getKeysLookedAt() const { return _keysLookedAt; }
long long getObjLookedAt() const { return _objectsLookedAt; } long long getObjLookedAt() const { return _objectsLookedAt; }
private: private:
void _process( BtreeCursor* cursor ); void _process( BtreeCursor* cursor );
/** /**
* checks not index pieces * checks not index pieces
* i.e. prhases & negated terms * i.e. prhases & negated terms
*/ */
bool _ok( Record* record ) const; bool _ok( Record* record ) const;
NamespaceDetails* _ns; IndexDescriptor* _descriptor;
const IndexDetails& _id; const FTSSpec& _ftsSpec;
FTSIndex* _fts;
BSONObj _indexPrefix; BSONObj _indexPrefix;
FTSQuery _query; FTSQuery _query;
FTSMatcher _ftsMatcher; FTSMatcher _ftsMatcher;
scoped_ptr<CoveredIndexMatcher> _matcher; scoped_ptr<CoveredIndexMatcher> _matcher;
long long _keysLookedAt; long long _keysLookedAt;
long long _objectsLookedAt; long long _objectsLookedAt;
Scores _scores; Scores _scores;
 End of changes. 5 change blocks. 
8 lines changed or deleted 5 lines changed or added


 geonear.h   geonear.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/jsobj.h" #include "mongo/db/jsobj.h"
namespace mongo { namespace mongo {
// Arguments in common between 2d and 2dsphere geoNear. // Arguments in common between 2d and 2dsphere geoNear.
class GeoNearArguments { class GeoNearArguments {
public: public:
GeoNearArguments(const BSONObj& cmdObj); GeoNearArguments(const BSONObj& cmdObj);
int numWanted; int numWanted;
bool uniqueDocs; bool uniqueDocs;
bool includeLocs; bool includeLocs;
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


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


 httpclient.h   httpclient.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 "mongo/pch.h" #include "mongo/pch.h"
#include "sock.h"
namespace mongo { namespace mongo {
class HttpClient : boost::noncopyable { class HttpClient : boost::noncopyable {
public: public:
typedef map<string,string> Headers; typedef map<string,string> Headers;
class Result { class Result {
public: public:
skipping to change at line 71 skipping to change at line 70
*/ */
int get( const std::string& url , Result * result = 0 ); int get( const std::string& url , Result * result = 0 );
/** /**
* @return response code * @return response code
*/ */
int post( const std::string& url , const std::string& body , Result * result = 0 ); int post( const std::string& url , const std::string& body , Result * result = 0 );
private: private:
int _go( const char * command , string url , const char * body , Re sult * result ); int _go( const char * command , string url , const char * body , Re sult * result );
#ifdef MONGO_SSL
void _checkSSLManager();
scoped_ptr<SSLManager> _sslManager;
#endif
}; };
} }
 End of changes. 2 change blocks. 
7 lines changed or deleted 0 lines changed or added


 index.h   index.h 
skipping to change at line 26 skipping to change at line 26
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/pch.h" #include "mongo/pch.h"
#include <vector> #include <vector>
#include "mongo/db/diskloc.h" #include "mongo/db/diskloc.h"
#include "mongo/db/index_insertion_continuation.h"
#include "mongo/db/indexkey.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/namespace.h"
namespace mongo { namespace mongo {
class IndexInterface {
protected:
virtual ~IndexInterface() { }
public:
class IndexInserter : private boost::noncopyable {
public:
IndexInserter();
~IndexInserter();
void addInsertionContinuation(IndexInsertionContinuation *c);
void finishAllInsertions();
private:
std::vector<IndexInsertionContinuation *> _continuations;
};
virtual IndexInsertionContinuation *beginInsertIntoIndex(
int idxNo,
IndexDetails &_idx, DiskLoc _recordLoc, const BSONObj &_key,
const Ordering& _order, bool dupsAllowed) = 0;
virtual int keyCompare(const BSONObj& l,const BSONObj& r, const Ord
ering &ordering) = 0;
virtual long long fullValidate(const DiskLoc& thisLoc, const BSONOb
j &order) = 0;
virtual DiskLoc findSingle(const IndexDetails &indexdetails , const
DiskLoc& thisLoc, const BSONObj& key) const = 0;
virtual bool unindex(const DiskLoc thisLoc, IndexDetails& id, const
BSONObj& key, const DiskLoc recordLoc) const = 0;
virtual int bt_insert(const DiskLoc thisLoc, const DiskLoc recordLo
c,
const BSONObj& key, const Ordering &order, bool dupsAllowed,
IndexDetails& idx, bool toplevel = true) const = 0;
virtual DiskLoc addBucket(const IndexDetails&) = 0;
virtual void uassertIfDups(IndexDetails& idx, vector<BSONObj*>& add
edKeys, DiskLoc head,
DiskLoc self, const Ordering& ordering) = 0;
// these are for geo
virtual bool isUsed(DiskLoc thisLoc, int pos) = 0;
virtual void keyAt(DiskLoc thisLoc, int pos, BSONObj&, DiskLoc& rec
ordLoc) = 0;
virtual BSONObj keyAt(DiskLoc thisLoc, int pos) = 0;
virtual DiskLoc locate(const IndexDetails &idx , const DiskLoc& thi
sLoc, const BSONObj& key, const Ordering &order,
int& pos, bool& found, const DiskLoc &record
Loc, int direction=1) = 0;
virtual DiskLoc advance(const DiskLoc& thisLoc, int& keyOfs, int di
rection, const char *caller) = 0;
/**
* @return a static IndexInterface consistent with index version De
faultIndexVersionNumber.
* An IndexInterface should generally not be retrieved via this fun
ction, but from the
* IndexDetails for an existing index.
*/
static IndexInterface& defaultVersion();
};
/* 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 {
public: public:
/** /**
* btree head disk location * btree head disk location
skipping to change at line 120 skipping to change at line 70
/* extract key value from the query object /* extract key value from the query object
e.g., if key() == { x : 1 }, e.g., if key() == { x : 1 },
{ x : 70, y : 3 } -> { x : 70 } { x : 70, y : 3 } -> { x : 70 }
*/ */
BSONObj getKeyFromQuery(const BSONObj& query) const { BSONObj getKeyFromQuery(const BSONObj& query) const {
BSONObj k = keyPattern(); BSONObj k = keyPattern();
BSONObj res = query.extractFieldsUnDotted(k); BSONObj res = query.extractFieldsUnDotted(k);
return res; return res;
} }
/* pull out the relevant key objects from obj, so we
can index them. Note that the set is multiple elements
only when it's a "multikey" array.
keys will be left empty if key not found in the object.
*/
void getKeysFromObject( const BSONObj& obj, BSONObjSet& keys) const
;
/* get the key pattern for this object. /* get the key pattern for this object.
e.g., { lastname:1, firstname:1 } e.g., { lastname:1, firstname:1 }
*/ */
BSONObj keyPattern() const { BSONObj keyPattern() const {
return info.obj().getObjectField("key"); return info.obj().getObjectField("key");
} }
/** /**
* @return offset into keyPattern for key * @return offset into keyPattern for key
-1 if doesn't exist -1 if doesn't exist
skipping to change at line 219 skipping to change at line 162
/** return true if dropDups was set when building index (if any dup licates, dropdups drops the duplicating objects) */ /** return true if dropDups was set when building index (if any dup licates, dropdups drops the duplicating objects) */
bool dropDups() const { bool dropDups() const {
return info.obj().getBoolField( "dropDups" ); return info.obj().getBoolField( "dropDups" );
} }
/** delete this index. does NOT clean up the system catalog /** delete this index. does NOT clean up the system catalog
(system.indexes or system.namespaces) -- only NamespaceIndex. (system.indexes or system.namespaces) -- only NamespaceIndex.
*/ */
void kill_idx(); void kill_idx();
const IndexSpec& getSpec() const;
string toString() const { string toString() const {
return info.obj().toString(); return info.obj().toString();
} }
/** @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
/** @return the interface for this interface, which varies with the
index version.
used for backward compatibility of index versions/formats.
*/
IndexInterface& idxInterface() const {
int v = version();
dassert( isASupportedIndexVersionNumber(v) );
return *iis[v&1];
}
static IndexInterface *iis[];
};
struct IndexChanges { /*on an update*/
BSONObjSet oldkeys;
BSONObjSet newkeys;
vector<BSONObj*> removed; // these keys were removed as part of the
change
vector<BSONObj*> added; // these keys were added as part of the c
hange
/** @curObjLoc - the object we want to add's location. if it is al
ready in the
index, that is allowed here (for bg indexing case)
.
*/
void dupCheck(IndexDetails& idx, DiskLoc curObjLoc);
}; };
class NamespaceDetails; class NamespaceDetails;
// changedId should be initialized to false // changedId should be initialized to false
void getIndexChanges(vector<IndexChanges>& v, const char *ns, Namespace
Details& d,
BSONObj newObj, BSONObj oldObj, bool &cangedId);
void dupCheck(vector<IndexChanges>& v, NamespaceDetails& d, DiskLoc cur
ObjLoc);
void assureSysIndexesEmptied(const char *ns, IndexDetails *exceptForIdI ndex); void assureSysIndexesEmptied(const char *ns, IndexDetails *exceptForIdI ndex);
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':
 End of changes. 6 change blocks. 
106 lines changed or deleted 0 lines changed or added


 index_rebuilder.h   index_rebuilder.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 "mongo/db/namespace_details.h" #include "mongo/db/namespace_details.h"
#include "mongo/util/background.h"
namespace mongo { namespace mongo {
class IndexRebuilder { // This is a job that's only run at startup. It finds all incomplete in
dices and
// finishes rebuilding them. After they complete rebuilding, the thread
terminates.
class IndexRebuilder : public BackgroundJob {
public: public:
IndexRebuilder(); IndexRebuilder();
std::string name() const; std::string name() const;
void run(); void run();
private: private:
/** /**
* Check each collection in a database to see if it has any in-prog ress index builds that * Check each collection in a database to see if it has any in-prog ress index builds that
* need to be retried. If so, calls retryIndexBuild. * need to be retried. If so, calls retryIndexBuild.
*/ */
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, NamespaceDetails* n void retryIndexBuild(const std::string& dbName,
sd, const int index); NamespaceDetails* nsd,
const int index);
}; };
extern IndexRebuilder indexRebuilder; extern IndexRebuilder indexRebuilder;
} }
 End of changes. 3 change blocks. 
3 lines changed or deleted 9 lines changed or added


 index_set.h   index_set.h 
skipping to change at line 35 skipping to change at line 35
namespace mongo { namespace mongo {
/** /**
* a.$ -> a * a.$ -> a
* @return true if out is set and we made a change * @return true if out is set and we made a change
*/ */
bool getCanonicalIndexField( const StringData& fullName, std::string* o ut ); bool getCanonicalIndexField( const StringData& fullName, std::string* o ut );
class IndexPathSet { class IndexPathSet {
public: public:
IndexPathSet();
void addPath( const StringData& path ); void addPath( const StringData& path );
void allPathsIndexed();
void clear(); void clear();
bool mightBeIndexed( const StringData& path ) const; bool mightBeIndexed( const StringData& path ) const;
private: private:
bool _startsWith( const StringData& a, const StringData& b ) const; bool _startsWith( const StringData& a, const StringData& b ) const;
std::set<std::string> _canonical; std::set<std::string> _canonical;
bool _allPathsIndexed;
}; };
} }
 End of changes. 3 change blocks. 
6 lines changed or deleted 0 lines changed or added


 index_update.h   index_update.h 
skipping to change at line 29 skipping to change at line 29
#include "mongo/db/diskloc.h" #include "mongo/db/diskloc.h"
#include "mongo/db/index.h" #include "mongo/db/index.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/platform/cstdint.h" #include "mongo/platform/cstdint.h"
namespace mongo { namespace mongo {
class NamespaceDetails; class NamespaceDetails;
class Record; class Record;
// unindex all keys in index for this record. // unindex all keys in index for this record.
void unindexRecord(NamespaceDetails *d, Record *todelete, const DiskLoc void unindexRecord(NamespaceDetails *d, Record *todelete, const DiskLoc
& dl, bool noWarn = false); & dl,
bool noWarn = false);
// Build an index in the foreground // Build an index in the foreground
// If background is false, uses fast index builder // If background is false, uses fast index builder
// If background is true, uses background index builder; blocks until d one. // If background is true, uses background index builder; blocks until d one.
void buildAnIndex(const std::string& ns, void buildAnIndex(const std::string& ns,
NamespaceDetails *d, NamespaceDetails *d,
IndexDetails& idx, IndexDetails& idx,
bool background,
bool mayInterrupt); bool mayInterrupt);
// add index keys for a newly inserted record // add index keys for a newly inserted record
// done in two steps/phases to allow potential deferal of write lock po void indexRecord(const char *ns, NamespaceDetails *d, const BSONObj& ob
rtion in the future j, const DiskLoc &loc);
void indexRecordUsingTwoSteps(const char *ns, NamespaceDetails *d, BSON
Obj obj,
DiskLoc loc, bool shouldBeUnlocked
);
// Given an object, populate "inserter" with information necessary to u
pdate indexes.
void fetchIndexInserters(BSONObjSet & /*out*/keys,
IndexInterface::IndexInserter &inserter,
NamespaceDetails *d,
int idxNo,
const BSONObj& obj,
DiskLoc recordLoc,
const bool allowDups = false);
bool dropIndexes( NamespaceDetails *d, const char *ns, const char *name bool dropIndexes(NamespaceDetails *d, const char *ns, const char *name,
, string &errmsg, BSONObjBuilder &anObjBuilder, bool maydeleteIdIndex ); string &errmsg,
BSONObjBuilder &anObjBuilder, bool maydeleteIdIndex );
/** /**
* Add an _id index to namespace @param 'ns' if not already present. * Add an _id index to namespace @param 'ns' if not already present.
* @param mayInterrupt When true, killop may interrupt the function cal l. * @param mayInterrupt When true, killop may interrupt the function cal l.
*/ */
void ensureHaveIdIndex(const char* ns, bool mayInterrupt); void ensureHaveIdIndex(const char* ns, bool mayInterrupt);
////// The remaining functions are only included in this header file fo
r unit testing.
class BSONObjExternalSorter;
class CurOp;
class ProgressMeter;
class ProgressMeterHolder;
struct SortPhaseOne;
class Timer;
/** Extract index keys from the @param 'ns' to the external sorter in @
param 'phaseOne'. */
void addKeysToPhaseOne( const char* ns,
const IndexDetails& idx,
const BSONObj& order,
SortPhaseOne* phaseOne,
int64_t nrecords,
ProgressMeter* progressMeter,
bool mayInterrupt );
/** Popuate the index @param 'idx' using the keys contained in @param '
sorter'. */
template< class V >
void buildBottomUpPhases2And3( bool dupsAllowed,
IndexDetails& idx,
BSONObjExternalSorter& sorter,
bool dropDups,
set<DiskLoc>& dupsToDrop,
CurOp* op,
SortPhaseOne* phase1,
ProgressMeterHolder& pm,
Timer& t,
bool mayInterrupt );
/** Drop duplicate documents from the set @param 'dupsToDrop'. */
void doDropDups( const char* ns,
NamespaceDetails* d,
const set<DiskLoc>& dupsToDrop,
bool mayInterrupt );
} // namespace mongo } // namespace mongo
 End of changes. 5 change blocks. 
61 lines changed or deleted 8 lines changed or added


 init.h   init.h 
skipping to change at line 65 skipping to change at line 65
#include "mongo/base/initializer_context.h" #include "mongo/base/initializer_context.h"
#include "mongo/base/initializer_function.h" #include "mongo/base/initializer_function.h"
#include "mongo/base/global_initializer.h" #include "mongo/base/global_initializer.h"
#include "mongo/base/global_initializer_registerer.h" #include "mongo/base/global_initializer_registerer.h"
#include "mongo/base/make_string_vector.h" #include "mongo/base/make_string_vector.h"
#include "mongo/base/status.h" #include "mongo/base/status.h"
/** /**
* Convenience parameter representing an empty set of prerequisites for an initializer function. * Convenience parameter representing an empty set of prerequisites for an initializer function.
*/ */
#define MONGO_NO_PREREQUISITES () #define MONGO_NO_PREREQUISITES (NULL)
/** /**
* Convenience parameter representing an empty set of dependents of an init ializer function. * Convenience parameter representing an empty set of dependents of an init ializer function.
*/ */
#define MONGO_NO_DEPENDENTS () #define MONGO_NO_DEPENDENTS (NULL)
/** /**
* Convenience parameter representing the default set of dependents for ini tializer functions. * Convenience parameter representing the default set of dependents for ini tializer functions.
*/ */
#define MONGO_DEFAULT_PREREQUISITES ("default") #define MONGO_DEFAULT_PREREQUISITES ("default")
/** /**
* Macro to define an initializer function named "NAME" with the default pr erequisites, and * Macro to define an initializer function named "NAME" with the default pr erequisites, and
* no explicit dependents. * no explicit dependents.
* *
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 instance.h   instance.h 
skipping to change at line 22 skipping to change at line 22
* 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 "curop-inl.h"
#include "cmdline.h"
#include "client.h"
#include "mongo/client/dbclientinterface.h" #include "mongo/client/dbclientinterface.h"
#include "mongo/db/client.h"
#include "mongo/db/cmdline.h"
#include "mongo/db/curop-inl.h"
namespace mongo { namespace mongo {
extern string dbExecCommand; extern string dbExecCommand;
/** a high level recording of operations to the database - sometimes us ed for diagnostics /** a high level recording of operations to the database - sometimes us ed for diagnostics
and debugging. and debugging.
*/ */
class DiagLog { class DiagLog {
ofstream *f; // note this is never freed ofstream *f; // note this is never freed
skipping to change at line 93 skipping to change at line 93
class DBDirectClient : public DBClientBase { class DBDirectClient : public DBClientBase {
public: public:
using DBClientBase::query; using DBClientBase::query;
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0, virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0,
const BSONObj *fieldsToRetur n = 0, int queryOptions = 0, int batchSize = 0); const BSONObj *fieldsToRetur n = 0, int queryOptions = 0, int batchSize = 0);
virtual bool isFailed() const { virtual bool isFailed() const {
return false; return false;
} }
virtual bool isStillConnected() {
return true;
}
virtual string toString() { virtual string toString() {
return "DBDirectClient"; return "DBDirectClient";
} }
virtual string getServerAddress() const { virtual string getServerAddress() const {
return "localhost"; // TODO: should this have the port? return "localhost"; // TODO: should this have the port?
} }
virtual bool call( Message &toSend, Message &response, bool assertO k=true , string * actualServer = 0 ); virtual bool call( Message &toSend, Message &response, bool assertO k=true , string * actualServer = 0 );
virtual void say( Message &toSend, bool isRetry = false , string * actualServer = 0 ); virtual void say( Message &toSend, bool isRetry = false , string * actualServer = 0 );
virtual void sayPiggyBack( Message &toSend ) { virtual void sayPiggyBack( Message &toSend ) {
// don't need to piggy back when connected locally // don't need to piggy back when connected locally
 End of changes. 3 change blocks. 
3 lines changed or deleted 8 lines changed or added


 jsobj.h   jsobj.h 
skipping to change at line 32 skipping to change at line 32
"BSON" stands for "binary JSON" -- ie a binary way to represent objects that would be "BSON" stands for "binary JSON" -- ie a binary way to represent objects that would be
represented in JSON (plus a few extensions useful for databases & other languages). represented in JSON (plus a few extensions useful for databases & other languages).
http://www.bsonspec.org/ http://www.bsonspec.org/
*/ */
#pragma once #pragma once
#include "mongo/pch.h" #include "mongo/pch.h"
#include "../bson/util/builder.h"
#include "../util/optime.h" #include "mongo/bson/util/builder.h"
#include "../bson/bsontypes.h" #include "mongo/db/repl/optime.h"
#include "../bson/oid.h" #include "mongo/bson/bsontypes.h"
#include "../bson/bsonelement.h" #include "mongo/bson/oid.h"
#include "../bson/bsonobj.h" #include "mongo/bson/bsonelement.h"
#include "../bson/bsonmisc.h" #include "mongo/bson/bsonobj.h"
#include "../bson/bsonobjbuilder.h" #include "mongo/bson/bsonmisc.h"
#include "../bson/bsonobjiterator.h" #include "mongo/bson/bsonobjbuilder.h"
#include "../bson/bson-inl.h" #include "mongo/bson/bsonobjiterator.h"
#include "../bson/ordering.h" #include "mongo/bson/bson-inl.h"
#include "mongo/bson/ordering.h"
#include "mongo/base/string_data.h" #include "mongo/base/string_data.h"
#include "../bson/bson_db.h" #include "mongo/bson/bson_db.h"
 End of changes. 2 change blocks. 
11 lines changed or deleted 12 lines changed or added


 jsobjmanipulator.h   jsobjmanipulator.h 
skipping to change at line 21 skipping to change at line 21
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Lice nse * You should have received a copy of the GNU Affero General Public Lice nse
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "jsobj.h" #include "mongo/db/jsobj.h"
//#include "dur.h"
namespace mongo { namespace mongo {
/** Manipulate the binary representation of a BSONElement in-place. /** Manipulate the binary representation of a BSONElement in-place.
Careful, this casts away const. Careful, this casts away const.
*/ */
class BSONElementManipulator { class BSONElementManipulator {
public: public:
BSONElementManipulator( const BSONElement &element ) : BSONElementManipulator( const BSONElement &element ) :
_element( element ) { _element( element ) {
 End of changes. 1 change blocks. 
2 lines changed or deleted 1 lines changed or added


 jsregexp.h   jsregexp.h 
// Copyright 2012 the V8 project authors. All rights reserved. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// Redistribution and use in source and binary forms, with or without *
// modification, are permitted provided that the following conditions are * ***** BEGIN LICENSE BLOCK *****
// met: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
// *
// * Redistributions of source code must retain the above copyright * The contents of this file are subject to the Mozilla Public License Vers
// notice, this list of conditions and the following disclaimer. ion
// * Redistributions in binary form must reproduce the above * 1.1 (the "License"); you may not use this file except in compliance with
// copyright notice, this list of conditions and the following * the License. You may obtain a copy of the License at
// disclaimer in the documentation and/or other materials provided * http://www.mozilla.org/MPL/
// with the distribution. *
// * Neither the name of Google Inc. nor the names of its * Software distributed under the License is distributed on an "AS IS" basi
// contributors may be used to endorse or promote products derived s,
// from this software without specific prior written permission. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// * for the specific language governing rights and limitations under the
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * License.
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * The Original Code is Mozilla Communicator client code, released
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * March 31, 1998.
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * The Initial Developer of the Original Code is
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * Netscape Communications Corporation.
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * Portions created by the Initial Developer are Copyright (C) 1998
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * the Initial Developer. All Rights Reserved.
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * Contributor(s):
*
#ifndef V8_JSREGEXP_H_ * Alternatively, the contents of this file may be used under the terms of
#define V8_JSREGEXP_H_ * either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL
#include "allocation.h" "),
#include "assembler.h" * in which case the provisions of the GPL or the LGPL are applicable inste
#include "zone-inl.h" ad
* of those above. If you wish to allow use of your version of this file on
namespace v8 { ly
namespace internal { * under the terms of either the GPL or the LGPL, and not to allow others t
o
class NodeVisitor; * use your version of this file under the terms of the MPL, indicate your
class RegExpCompiler; * decision by deleting the provisions above and replace them with the noti
class RegExpMacroAssembler; ce
class RegExpNode; * and other provisions required by the GPL or the LGPL. If you do not dele
class RegExpTree; te
class BoyerMooreLookahead; * the provisions above, a recipient may use your version of this file unde
r
class RegExpImpl { * the terms of any one of the MPL, the GPL or the LGPL.
public: *
// Whether V8 is compiled with native regexp support or not. * ***** END LICENSE BLOCK ***** */
static bool UsesNativeRegExp() {
#ifdef V8_INTERPRETED_REGEXP #ifndef jsregexp_h___
return false; #define jsregexp_h___
#else /*
return true; * JS regular expression interface.
#endif */
} #include <stddef.h>
#include "jspubtd.h"
// Creates a regular expression literal in the old space. #include "jsstr.h"
// 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;
class RegExpNode: public ZoneObject { #ifdef JS_THREADSAFE
public: #include "jsdhash.h"
explicit RegExpNode(Zone* zone) #endif
: replacement_(NULL), trace_count_(0), zone_(zone) {
bm_info_[0] = bm_info_[1] = NULL;
}
virtual ~RegExpNode();
virtual void Accept(NodeVisitor* visitor) = 0;
// Generates a goto to this node or actually generates the code at this p
oint.
virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0;
// How many characters must this node consume at a minimum in order to
// succeed. If we have found at least 'still_to_find' characters that
// must be consumed there is no need to ask any following nodes whether
// they are sure to eat any more characters. The not_at_start argument i
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.
virtual int EatsAtLeast(int still_to_find,
int recursion_depth,
bool not_at_start) = 0;
// Emits some quick code that checks whether the preloaded characters mat
ch.
// 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
e.
bool EmitQuickCheck(RegExpCompiler* compiler,
Trace* trace,
bool preload_has_checked_bounds,
Label* on_possible_success,
QuickCheckDetails* details_return,
bool fall_through_on_failure);
// For a given number of characters this returns a mask and a value. The
// next n characters are anded with the mask and compared with the value.
// A comparison failure indicates the node cannot match the next n charac
ters.
// A comparison success indicates the node may match.
virtual void GetQuickCheckDetails(QuickCheckDetails* details,
RegExpCompiler* compiler,
int characters_filled_in,
bool not_at_start) = 0;
static const int kNodeIsTooComplexForGreedyLoops = -1;
virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoo
ps; }
// Only returns the successor for a text node of length 1 that matches an
y
// character and that has no guards on it.
virtual RegExpNode* GetSuccessorOfOmnivorousTextNode(
RegExpCompiler* compiler) {
return NULL;
}
// Collects information on the possible code units (mod 128) that can mat
ch if
// we look forward. This is used for a Boyer-Moore-like string searching
// implementation. TODO(erikcorry): This should share more code with
// EatsAtLeast, GetQuickCheckDetails. The budget argument is used to lim
it
// the number of nodes we are willing to look at in order to create this
data.
static const int kFillInBMBudget = 200;
virtual void FillInBMInfo(int offset,
int recursion_depth,
int budget,
BoyerMooreLookahead* bm,
bool not_at_start) {
UNREACHABLE();
}
// If we know that the input is ASCII then there are some nodes that can
// never match. This method returns a node that can be substituted for
// itself, or NULL if the node can never match.
virtual RegExpNode* FilterASCII(int depth) { return this; }
// Helper for FilterASCII.
RegExpNode* replacement() {
ASSERT(info()->replacement_calculated);
return replacement_;
}
RegExpNode* set_replacement(RegExpNode* replacement) {
info()->replacement_calculated = true;
replacement_ = replacement;
return replacement; // For convenience.
}
// We want to avoid recalculating the lookahead info, so we store it on t
he
// node. Only info that is for this node is stored. We can tell that th
e
// info is for this node when offset == 0, so the information is calculat
ed
// relative to this node.
void SaveBMInfo(BoyerMooreLookahead* bm, bool not_at_start, int offset) {
if (offset == 0) set_bm_info(not_at_start, bm);
}
Label* label() { return &label_; }
// If non-generic code is generated for a node (i.e. the node is not at t
he
// start of the trace) then it cannot be reused. This variable sets a li
mit
// on how often we allow that to happen before we insist on starting a ne
w
// trace and generating generic code for a node that can be reused by flu
shing
// the deferred actions in the current trace and generating a goto.
static const int kMaxCopiesCodeGenerated = 10;
NodeInfo* info() { return &info_; }
BoyerMooreLookahead* bm_info(bool not_at_start) {
return bm_info_[not_at_start ? 1 : 0];
}
Zone* zone() const { return zone_; }
protected:
enum LimitResult { DONE, CONTINUE };
RegExpNode* replacement_;
LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace);
void set_bm_info(bool not_at_start, BoyerMooreLookahead* bm) {
bm_info_[not_at_start ? 1 : 0] = bm;
}
private:
static const int kFirstCharBudget = 10;
Label label_;
NodeInfo info_;
// This variable keeps track of how many times code has been generated fo
r
// this node (in different traces). We don't keep track of where the
// 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.
int trace_count_;
BoyerMooreLookahead* bm_info_[2];
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; struct JSRegExpStatics {
}; JSString *input; /* input string to match (perl $_, GC root)
*/
JSBool multiline; /* whether input contains newlines (perl $*
) */
uint16 parenCount; /* number of valid elements in parens[] */
uint16 moreLength; /* number of allocated elements in morePare
ns */
JSSubString parens[9]; /* last set of parens matched (perl $1, $2)
*/
JSSubString *moreParens; /* null or realloc'd vector for $10, etc. *
/
JSSubString lastMatch; /* last string matched (perl $&) */
JSSubString lastParen; /* last paren matched (perl $+) */
JSSubString leftContext; /* input to left of last match (perl $`) */
JSSubString rightContext; /* input to right of last match (perl $') *
/
};
/*
* This struct holds a bitmap representation of a class from a regexp.
* There's a list of these referenced by the classList field in the JSRegEx
p
* struct below. The initial state has startIndex set to the offset in the
* original regexp source of the beginning of the class contents. The first
* use of the class converts the source representation into a bitmap.
*
*/
typedef struct RECharSet {
JSPackedBool converted;
JSPackedBool sense;
uint16 length;
union {
uint8 *bits;
struct {
size_t startIndex;
size_t length;
} src;
} u;
} RECharSet;
/*
* This macro is safe because moreParens is guaranteed to be allocated and
big
* enough to hold parenCount, or else be null when parenCount is 0.
*/
#define REGEXP_PAREN_SUBSTRING(res, num)
\
(((jsuint)(num) < (jsuint)(res)->parenCount)
\
? ((jsuint)(num) < 9)
\
? &(res)->parens[num]
\
: &(res)->moreParens[(num) - 9]
\
: &js_EmptySubString)
typedef struct RENode RENode;
struct JSRegExp {
jsrefcount nrefs; /* reference count */
uint16 flags; /* flags, see jsapi.h's JSREG_* defines */
uint16 cloneIndex; /* index in fp->vars or funobj->slots of
cloned regexp object */
size_t parenCount; /* number of parenthesized submatches */
size_t classCount; /* count [...] bitmaps */
RECharSet *classList; /* list of [...] bitmaps */
JSString *source; /* locked source string, sans // */
jsbytecode program[1]; /* regular expression bytecode */
};
extern JSRegExp *
js_NewRegExp(JSContext *cx, JSTokenStream *ts,
JSString *str, uintN flags, JSBool flat);
extern JSRegExp *
js_NewRegExpOpt(JSContext *cx, JSTokenStream *ts,
JSString *str, JSString *opt, JSBool flat);
#define HOLD_REGEXP(cx, re) JS_ATOMIC_INCREMENT(&(re)->nrefs)
#define DROP_REGEXP(cx, re) js_DestroyRegExp(cx, re)
extern void
js_DestroyRegExp(JSContext *cx, JSRegExp *re);
/*
* Execute re on input str at *indexp, returning null in *rval on mismatch.
* On match, return true if test is true, otherwise return an array object.
* Update *indexp and cx->regExpStatics always on match.
*/
extern JSBool
js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp
,
JSBool test, jsval *rval);
/*
* These two add and remove GC roots, respectively, so their calls must be
* well-ordered.
*/
extern JSBool
js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res);
extern void
js_FreeRegExpStatics(JSContext *cx, JSRegExpStatics *res);
#define JSVAL_IS_REGEXP(cx, v)
\
(JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) &&
\
OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_RegExpClass)
extern JSClass js_RegExpClass;
extern JSObject *
js_InitRegExpClass(JSContext *cx, JSObject *obj);
/*
* Export js_regexp_toString to the decompiler.
*/
extern JSBool
js_regexp_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval);
/*
* Create, serialize/deserialize, or clone a RegExp object.
*/
extern JSObject *
js_NewRegExpObject(JSContext *cx, JSTokenStream *ts,
jschar *chars, size_t length, uintN flags);
extern JSBool
js_XDRRegExp(JSXDRState *xdr, JSObject **objp);
extern JSObject *
js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent);
/*
* Get and set the per-object (clone or clone-parent) lastIndex slot.
*/
extern JSBool
js_GetLastIndex(JSContext *cx, JSObject *obj, jsdouble *lastIndex);
} } // namespace v8::internal extern JSBool
js_SetLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex);
#endif // V8_JSREGEXP_H_ #endif /* jsregexp_h___ */
 End of changes. 5 change blocks. 
1694 lines changed or deleted 203 lines changed or added


 keypattern.h   keypattern.h 
skipping to change at line 83 skipping to change at line 83
BSONElement getField( const char* fieldname ) const { return _patte rn[ fieldname ]; } BSONElement getField( const char* fieldname ) const { return _patte rn[ fieldname ]; }
/* /*
* Returns true if the key described by this KeyPattern is a prefix of * Returns true if the key described by this KeyPattern is a prefix of
* the (potentially) compound key described by 'other' * the (potentially) compound key described by 'other'
*/ */
bool isPrefixOf( const KeyPattern& other ) const { bool isPrefixOf( const KeyPattern& other ) const {
return _pattern.isPrefixOf( other.toBSON() ); return _pattern.isPrefixOf( other.toBSON() );
} }
/**
* Is the provided key pattern the index over the ID field?
* The always required ID index is always {_id: 1} or {_id: -1}.
*/
static bool isIdKeyPattern(const BSONObj& pattern);
/* Takes a BSONObj whose field names are a prefix of the fields in this keyPattern, and /* Takes a BSONObj whose field names are a prefix of the fields in this keyPattern, and
* outputs a new bound with MinKey values appended to match the fie lds in this keyPattern * outputs a new bound with MinKey values appended to match the fie lds in this keyPattern
* (or MaxKey values for descending -1 fields). This is useful in s harding for * (or MaxKey values for descending -1 fields). This is useful in s harding for
* calculating chunk boundaries when tag ranges are specified on a prefix of the actual * calculating chunk boundaries when tag ranges are specified on a prefix of the actual
* shard key, or for calculating index bounds when the shard key is a prefix of the actual * shard key, or for calculating index bounds when the shard key is a prefix of the actual
* index used. * index used.
* *
* @param makeUpperInclusive If true, then MaxKeys instead of MinKe ys will be appended, so * @param makeUpperInclusive If true, then MaxKeys instead of MinKe ys will be appended, so
* that the output bound will compare *greater* than the bound bein g extended (note that * that the output bound will compare *greater* than the bound bein g extended (note that
* -1's in the keyPattern will swap MinKey/MaxKey vals. See example s). * -1's in the keyPattern will swap MinKey/MaxKey vals. See example s).
 End of changes. 1 change blocks. 
0 lines changed or deleted 6 lines changed or added


 list.h   list.h 
// Copyright 2011 the V8 project authors. All rights reserved. // list.h
// 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. /**
void Resize(int new_capacity, AllocationPolicy allocator); * Copyright (C) 2008 10gen Inc.
*
* 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. 
194 lines changed or deleted 98 lines changed or added


 listen.h   listen.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 "sock.h"
#include "mongo/platform/atomic_word.h" #include "mongo/platform/atomic_word.h"
#include "mongo/util/concurrency/ticketholder.h" #include "mongo/util/concurrency/ticketholder.h"
#include "mongo/util/net/sock.h"
namespace mongo { namespace mongo {
const int DEFAULT_MAX_CONN = 20000; const int DEFAULT_MAX_CONN = 20000;
const int MAX_MAX_CONN = 20000;
class MessagingPort; class MessagingPort;
class Listener : boost::noncopyable { class Listener : boost::noncopyable {
public: public:
Listener(const string& name, const string &ip, int port, bool logCo nnect=true ); Listener(const string& name, const string &ip, int port, bool logCo nnect=true );
virtual ~Listener(); virtual ~Listener();
skipping to change at line 74 skipping to change at line 73
return 0; return 0;
} }
private: private:
string _name; string _name;
string _ip; string _ip;
bool _logConnect; bool _logConnect;
long long _elapsedTime; long long _elapsedTime;
#ifdef MONGO_SSL #ifdef MONGO_SSL
SSLManager* _ssl; SSLManagerInterface* _ssl;
#endif #endif
/** /**
* @return true iff everything went ok * @return true iff everything went ok
*/ */
bool _setupSockets( const vector<SockAddr>& mine , vector<SOCKET>& socks ); bool _setupSockets( const vector<SockAddr>& mine , vector<SOCKET>& socks );
void _logListen( int port , bool ssl ); void _logListen( int port , bool ssl );
static const Listener* _timeTracker; static const Listener* _timeTracker;
 End of changes. 4 change blocks. 
3 lines changed or deleted 2 lines changed or added


 lockstat.h   lockstat.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 "util/timer.h"
#include "mongo/platform/atomic_word.h" #include "mongo/platform/atomic_word.h"
#include "mongo/util/timer.h"
namespace mongo { namespace mongo {
class BSONObj; class BSONObj;
class LockStat { class LockStat {
enum { N = 4 }; enum { N = 4 };
public: public:
void recordAcquireTimeMicros( char type , long long micros ); void recordAcquireTimeMicros( char type , long long micros );
void recordLockTimeMicros( char type , long long micros ); void recordLockTimeMicros( char type , long long micros );
 End of changes. 2 change blocks. 
1 lines changed or deleted 1 lines changed or added


 make_string_vector.h   make_string_vector.h 
skipping to change at line 28 skipping to change at line 28
#include <string> #include <string>
#include <vector> #include <vector>
/** /**
* Utility macro to construct a std::vector<std::string> from a sequence of C-style * Utility macro to construct a std::vector<std::string> from a sequence of C-style
* strings. * strings.
* *
* Usage: MONGO_MAKE_STRING_VECTOR("a", "b", "c") returns a vector contain ing * Usage: MONGO_MAKE_STRING_VECTOR("a", "b", "c") returns a vector contain ing
* std::strings "a", "b", "c", in that order. * std::strings "a", "b", "c", in that order.
*/ */
#define MONGO_MAKE_STRING_VECTOR(...) ::mongo::_makeStringVector(0, NULL, # #__VA_ARGS__, NULL) #define MONGO_MAKE_STRING_VECTOR(...) ::mongo::_makeStringVector(0, __VA_AR GS__, NULL)
namespace mongo { namespace mongo {
/** /**
* Create a vector of strings from varargs of C-style strings. * Create a vector of strings from varargs of C-style strings.
* *
* WARNING: Only intended for use by MONGO_MAKE_STRING_VECTOR macro, de fined above. Aborts * WARNING: Only intended for use by MONGO_MAKE_STRING_VECTOR macro, de fined above. Aborts
* ungracefully if you misuse it, so stick to the macro. * ungracefully if you misuse it, so stick to the macro.
* *
* The first parameter is ignored in all circumstances. The second par * The first parameter is ignored in all circumstances. The subsequent
ameter must be NULL, as parameters must be
* must be the last parameter. The third through penultimate parameter * const char* C-style strings, or NULL. Of these parameters, at least
s should be const char* one must be
* C-style strings. * NULL. Parameters at and beyond the NULL are not inserted. Typically,
the NULL will be
* the last parameter. The MONGO_MAKE_STRING_VECTOR macro enforces this
.
* *
* Returns a vector of std::strings. * Returns a vector of std::strings.
*/ */
std::vector<std::string> _makeStringVector(int ignored, ...); std::vector<std::string> _makeStringVector(int ignored, ...);
} // namespace mongo } // namespace mongo
 End of changes. 2 change blocks. 
6 lines changed or deleted 9 lines changed or added


 matcher.h   matcher.h 
skipping to change at line 23 skipping to change at line 23
* 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 "jsobj.h" #include "mongo/db/jsobj.h"
#include "pcrecpp.h"
#include "mongo/db/geo/geoquery.h"
namespace mongo { namespace mongo {
class Cursor; class Cursor;
class CoveredIndexMatcher; class CoveredIndexMatcher;
class ElementMatcher;
class Matcher;
class FieldRangeVector; class FieldRangeVector;
class RegexMatcher {
public:
/**
* Maximum pattern size which pcre v8.3 can do matches correctly wi
th
* LINK_SIZE define macro set to 2 @ pcre's config.h (based on
* experiments)
*/
static const size_t MaxPatternSize = 32764;
const char *_fieldName;
const char *_regex;
const char *_flags;
string _prefix;
shared_ptr< pcrecpp::RE > _re;
bool _isNot;
RegexMatcher() : _isNot() {}
};
struct GeoMatcher {
public:
GeoMatcher(GeoQuery query, bool negated) : geoQuery(query), isNot(n
egated) {}
string getField() const { return geoQuery.getField(); }
bool matches(const GeometryContainer &container) const {
bool satisfied = geoQuery.satisfiesPredicate(container);
if (isNot) { return !satisfied; }
else { return satisfied; }
}
GeoQuery geoQuery;
bool isNot;
};
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"
* An interface for visiting a Matcher and all of its nested Matchers a #include "mongo/db/matcher/matcher.h"
nd ElementMatchers.
* RegexMatchers are not visited.
*/
class MatcherVisitor {
public:
virtual ~MatcherVisitor() {}
virtual void visitMatcher( const Matcher& matcher ) {}
virtual void visitElementMatcher( const ElementMatcher& elementMatc
her ) {}
};
class ElementMatcher {
public:
ElementMatcher() {
}
ElementMatcher( BSONElement e , int op, bool isNot );
ElementMatcher( BSONElement e , int op , const BSONObj& array, bool
isNot );
~ElementMatcher() { }
bool negativeCompareOp() const { return _compareOp == BSONObj::NE |
| _compareOp == BSONObj::NIN; }
int inverseOfNegativeCompareOp() const;
bool negativeCompareOpContainsNull() const;
void visit( MatcherVisitor& visitor ) const;
BSONElement _toMatch;
int _compareOp;
bool _isNot;
shared_ptr< set<BSONElement,element_lt> > _myset;
shared_ptr< vector<RegexMatcher> > _myregex;
// these are for specific operators
int _mod;
int _modm;
BSONType _type;
shared_ptr<Matcher> _subMatcher;
bool _subMatcherOnPrimitives ;
vector< shared_ptr<Matcher> > _allMatchers;
};
class Where; // used for $where javascript eval
class DiskLoc;
/** Reports information about a match request. */
class MatchDetails {
public:
MatchDetails();
void resetOutput();
string toString() const;
/** Request that an elemMatchKey be recorded. */
void requestElemMatchKey() { _elemMatchKeyRequested = true; }
bool needRecord() const { return _elemMatchKeyRequested; }
bool hasLoadedRecord() const { return _loadedRecord; }
bool hasElemMatchKey() const { return _elemMatchKeyFound; }
string elemMatchKey() const {
verify( hasElemMatchKey() );
return _elemMatchKey;
}
void setLoadedRecord( bool loadedRecord ) { _loadedRecord = loadedR
ecord; }
void setElemMatchKey( const string &elemMatchKey ) {
if ( _elemMatchKeyRequested ) {
_elemMatchKeyFound = true;
_elemMatchKey = elemMatchKey;
}
}
private:
bool _loadedRecord;
bool _elemMatchKeyRequested;
bool _elemMatchKeyFound;
string _elemMatchKey;
};
/* Match BSON objects against a query pattern.
e.g.
db.foo.find( { a : 3 } );
{ a : 3 } is the pattern object. See manual for full info.
GT/LT:
{ a : { $gt : 3 } }
Not equal:
{ a : { $ne : 3 } }
TODO: we should rewrite the matcher to be more an AST style.
*/
class Matcher : boost::noncopyable {
int matchesDotted(
const char *fieldName,
const BSONElement& toMatch, const BSONObj& obj,
int compareOp, const ElementMatcher& bm, bool isArr , MatchDeta
ils * details ) const;
/**
* Perform a NE or NIN match by returning the inverse of the opposi
te matching operation.
* Missing values are considered matches unless the match must not
equal null.
*/
int inverseMatch(
const char *fieldName,
const BSONElement &toMatch, const BSONObj &obj,
const ElementMatcher&bm, MatchDetails * details ) const;
public:
static int opDirection(int op) {
return op <= BSONObj::LTE ? -1 : 1;
}
Matcher(const BSONObj &pattern, bool nested=false);
~Matcher(); namespace mongo {
bool matches(const BSONObj& j, MatchDetails * details = 0 ) const;
#ifdef MONGO_LATER_SERVER_4644
class FieldSink {
public:
virtual ~FieldSink() {};
virtual void referenceField(const string &fieldPath) = 0;
};
/**
Visit all of the fields that are referenced by this Matcher
(and any descendants).
This can be used to gather a list of all the references made by
this matcher. The implementation of this parallels that of
matches() above.
@param pSink a FieldSink that the caller will use to gather or
process the references
*/
void visitReferences(FieldSink *pSink) const;
#endif /* MONGO_LATER_SERVER_4644 */
/**
* Visit this Matcher and all of its nested Matchers and ElementMat
chers. All top level
* ElementMatchers of a Matcher are visited immediately after the M
atcher itself (before any
* other Matcher is visited).
*/
void visit( MatcherVisitor& visitor ) const;
bool atomic() const { return _atomic; }
string toString() const {
return _jsobj.toString();
}
/**
* @return true if this key matcher will return the same true/false
* value as the provided doc matcher.
*/
bool keyMatch( const Matcher &docMatcher ) const;
bool singleSimpleCriterion() const {
if ( _where ||
_basics.size() > 1 ||
_haveNeg ||
_haveSize ||
_regexs.size() > 0 )
return false;
if ( _jsobj.nFields() > 1 )
return false;
if ( _basics.size() != 1 )
return false;
if ( strchr( _jsobj.firstElement().fieldName(), '.' ) )
return false;
return _basics[0]._compareOp == BSONObj::Equality;
}
const BSONObj *getQuery() const { return &_jsobj; };
private:
/**
* Generate a matcher for the provided index key format using the
* provided full doc matcher.
*/
Matcher( const Matcher &docMatcher, const BSONObj &constrainIndexKe
y );
void addBasic(const BSONElement &e, int c, bool isNot) {
// TODO May want to selectively ignore these element types base
d on op type.
if ( e.type() == MinKey || e.type() == MaxKey )
return;
_basics.push_back( ElementMatcher( e , c, isNot ) );
}
void addRegex(const char *fieldName, const char *regex, const char
*flags, bool isNot = false);
bool addOp( const BSONElement &e, const BSONElement &fe, bool isNot
, const char *& regex, const char *&flags );
int valuesMatch(const BSONElement& l, const BSONElement& r, int op,
const ElementMatcher& bm) const;
bool parseClause( const BSONElement &e );
void parseExtractedClause( const BSONElement &e, list< shared_ptr<
Matcher > > &matchers );
void parseWhere( const BSONElement &e );
void parseMatchExpressionElement( const BSONElement &e, bool nested
);
Where *_where; // set if query uses $where
BSONObj _jsobj; // the query pattern. e.g., { nam
e: "joe" }
BSONObj _constrainIndexKey;
vector<ElementMatcher> _basics;
bool _haveSize;
bool _all;
bool _hasArray;
bool _haveNeg;
/* $atomic - if true, a multi document operation (some removes, upd
ates)
should be done atomically. in that case, we do not yi
eld -
i.e. we stay locked the whole time.
http://dochub.mongodb.org/core/remove
*/
bool _atomic;
vector<RegexMatcher> _regexs;
vector<GeoMatcher> _geo;
// so we delete the mem when we're done:
vector< shared_ptr< BSONObjBuilder > > _builders;
list< shared_ptr< Matcher > > _andMatchers;
list< shared_ptr< Matcher > > _orMatchers;
list< shared_ptr< Matcher > > _norMatchers;
friend class CoveredIndexMatcher;
};
// If match succeeds on index key, then attempt to match full document.
class CoveredIndexMatcher : boost::noncopyable {
public:
CoveredIndexMatcher(const BSONObj &pattern, const BSONObj &indexKey
Pattern);
bool matchesWithSingleKeyIndex( const BSONObj& key, const DiskLoc&
recLoc,
MatchDetails* details = 0 ) const {
return matches( key, recLoc, details, true );
}
/**
* This is the preferred method for matching against a cursor, as i
t
* can handle both multi and single key cursors.
*/
bool matchesCurrent( Cursor * cursor , MatchDetails * details = 0 )
const;
bool needRecord() const { return _needRecord; }
const Matcher &docMatcher() const { return *_docMatcher; }
/**
* @return a matcher for a following $or clause.
* @param prevClauseFrs The index range scanned by the previous $or
clause. May be empty.
* @param nextClauseIndexKeyPattern The index key of the following
$or clause.
*/
CoveredIndexMatcher *nextClauseMatcher( const shared_ptr<FieldRange
Vector>& prevClauseFrv,
const BSONObj& nextClauseIn
dexKeyPattern ) const {
return new CoveredIndexMatcher( *this, prevClauseFrv, nextClaus
eIndexKeyPattern );
}
string toString() const;
private:
bool matches( const BSONObj& key, const DiskLoc& recLoc, MatchDetai
ls* details = 0,
bool keyUsable = true ) const;
bool isOrClauseDup( const BSONObj &obj ) const;
CoveredIndexMatcher( const CoveredIndexMatcher &prevClauseMatcher,
const shared_ptr<FieldRangeVector> &prevClauseF
rv,
const BSONObj &nextClauseIndexKeyPattern );
void init();
shared_ptr< Matcher > _docMatcher;
Matcher _keyMatcher;
vector<shared_ptr<FieldRangeVector> > _orDedupConstraints;
bool _needRecord; // if the key itself isn't good enough to determi
ne a positive match
};
} // namespace mongo //typedef MatcherOld Matcher;
typedef Matcher2 Matcher;
}
 End of changes. 7 change blocks. 
352 lines changed or deleted 5 lines changed or added


 message.h   message.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 "sock.h" #include "mongo/bson/util/atomic_int.h"
#include "../../bson/util/atomic_int.h" #include "mongo/util/net/hostandport.h"
#include "hostandport.h" #include "mongo/util/net/sock.h"
namespace mongo { namespace mongo {
/** /**
* Maximum accepted message size on the wire protocol. * Maximum accepted message size on the wire protocol.
*/ */
const int MaxMessageSizeBytes = 48 * 1000 * 1000; const int MaxMessageSizeBytes = 48 * 1000 * 1000;
class Message; class Message;
class MessagingPort; class MessagingPort;
skipping to change at line 106 skipping to change at line 106
int messageLength; // total message size, including this int messageLength; // total message size, including this
int requestID; // identifier for this message int requestID; // identifier for this message
int responseTo; // requestID from the original request int responseTo; // requestID from the original request
// (used in responses from db) // (used in responses from db)
int opCode; int opCode;
}; };
#pragma pack() #pragma pack()
#pragma pack(1) #pragma pack(1)
/* todo merge this with MSGHEADER (or inherit from it). */ /* todo merge this with MSGHEADER (or inherit from it). */
class MsgData { struct MsgData {
friend class Message;
friend class DbMessage;
friend class MessagingPort;
public:
int len; /* len of the msg, including this field */ int len; /* len of the msg, including this field */
MSGID id; /* request/reply id's match... */ MSGID id; /* request/reply id's match... */
MSGID responseTo; /* id of the message we are responding to */ MSGID responseTo; /* id of the message we are responding to */
short _operation; short _operation;
char _flags; char _flags;
char _version; char _version;
int operation() const { int operation() const {
return _operation; return _operation;
} }
void setOperation(int o) { void setOperation(int o) {
_flags = 0; _flags = 0;
_version = 0; _version = 0;
_operation = o; _operation = o;
} }
char _data[4];
int& dataAsInt() { int& dataAsInt() {
return *((int *) _data); return *((int *) _data);
} }
bool valid() { bool valid() {
if ( len <= 0 || len > ( 4 * BSONObjMaxInternalSize ) ) if ( len <= 0 || len > ( 4 * BSONObjMaxInternalSize ) )
return false; return false;
if ( _operation < 0 || _operation > 30000 ) if ( _operation < 0 || _operation > 30000 )
return false; return false;
skipping to change at line 147 skipping to change at line 143
} }
long long getCursor() { long long getCursor() {
verify( responseTo > 0 ); verify( responseTo > 0 );
verify( _operation == opReply ); verify( _operation == opReply );
long long * l = (long long *)(_data + 4); long long * l = (long long *)(_data + 4);
return l[0]; return l[0];
} }
int dataLen(); // len without header int dataLen(); // len without header
private:
char _data[4]; //must be last member
}; };
const int MsgDataHeaderSize = sizeof(MsgData) - 4; const int MsgDataHeaderSize = sizeof(MsgData) - 4;
inline int MsgData::dataLen() { inline int MsgData::dataLen() {
return len - MsgDataHeaderSize; return len - MsgDataHeaderSize;
} }
#pragma pack() #pragma pack()
class Message { class Message {
public: public:
// we assume here that a vector with initial size 0 does no allocat ion (0 is the default, but wanted to make it explicit). // we assume here that a vector with initial size 0 does no allocat ion (0 is the default, but wanted to make it explicit).
 End of changes. 5 change blocks. 
11 lines changed or deleted 5 lines changed or added


 message_port.h   message_port.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 "sock.h" #include "mongo/util/net/message.h"
#include "message.h" #include "mongo/util/net/sock.h"
namespace mongo { namespace mongo {
class MessagingPort; class MessagingPort;
class PiggyBackData; class PiggyBackData;
typedef AtomicUInt MSGID; typedef AtomicUInt MSGID;
class AbstractMessagingPort : boost::noncopyable { class AbstractMessagingPort : boost::noncopyable {
public: public:
skipping to change at line 113 skipping to change at line 113
} }
bool connect(SockAddr& farEnd) { bool connect(SockAddr& farEnd) {
return psock->connect( farEnd ); return psock->connect( farEnd );
} }
#ifdef MONGO_SSL #ifdef MONGO_SSL
/** /**
* Initiates the TLS/SSL handshake on this MessagingPort. * Initiates the TLS/SSL handshake on this MessagingPort.
* When this function returns, further communication on this * When this function returns, further communication on this
* MessagingPort will be encrypted. * MessagingPort will be encrypted.
*/ */
void secure( SSLManager * ssl ) { void secure( SSLManagerInterface* ssl ) {
psock->secure( ssl ); psock->secure( ssl );
} }
#endif #endif
bool isStillConnected() {
return psock->isStillConnected();
}
uint64_t getSockCreationMicroSec() const { uint64_t getSockCreationMicroSec() const {
return psock->getSockCreationMicroSec(); return psock->getSockCreationMicroSec();
} }
private: private:
PiggyBackData * piggyBackData; PiggyBackData * piggyBackData;
// this is the parsed version of remote // this is the parsed version of remote
// mutable because its initialized only on call to remote() // mutable because its initialized only on call to remote()
 End of changes. 3 change blocks. 
3 lines changed or deleted 7 lines changed or added


 miniwebserver.h   miniwebserver.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 "mongo/pch.h" #include "mongo/pch.h"
#include "message.h"
#include "message_port.h" #include "mongo/db/jsobj.h"
#include "listen.h" #include "mongo/util/net/listen.h"
#include "../../db/jsobj.h" #include "mongo/util/net/message.h"
#include "mongo/util/net/message_port.h"
namespace mongo { namespace mongo {
class MiniWebServer : public Listener { class MiniWebServer : public Listener {
public: public:
MiniWebServer(const string& name, const string &ip, int _port); MiniWebServer(const string& name, const string &ip, int _port);
virtual ~MiniWebServer() {} virtual ~MiniWebServer() {}
virtual void doRequest( virtual void doRequest(
const char *rq, // the full request const char *rq, // the full request
 End of changes. 1 change blocks. 
4 lines changed or deleted 5 lines changed or added


 mongommf.h   mongommf.h 
skipping to change at line 20 skipping to change at line 20
* 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 "../util/mmap.h" #include "mongo/util/mmap.h"
#include "../util/paths.h" #include "mongo/util/paths.h"
namespace mongo { namespace mongo {
/** MongoMMF adds some layers atop memory mapped files - specifically o ur handling of private views & such. /** MongoMMF adds some layers atop memory mapped files - specifically o ur handling of private views & such.
if you don't care about journaling/durability (temp sort files & su ch) use MemoryMappedFile class, if you don't care about journaling/durability (temp sort files & su ch) use MemoryMappedFile class,
not this. not this.
*/ */
class MongoMMF : private MemoryMappedFile { class MongoMMF : private MemoryMappedFile {
protected: protected:
virtual void* viewForFlushing() { return _view_write; } virtual void* viewForFlushing() { return _view_write; }
 End of changes. 1 change blocks. 
2 lines changed or deleted 2 lines changed or added


 multicmd.h   multicmd.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 "../../util/background.h" #include "mongo/db/repl/connections.h"
#include "connections.h" #include "mongo/util/background.h"
namespace mongo { namespace mongo {
struct Target { struct Target {
Target(string hostport) : toHost(hostport), ok(false) { } Target(string hostport) : toHost(hostport), ok(false) { }
//Target() : ok(false) { } //Target() : ok(false) { }
const string toHost; const string toHost;
bool ok; bool ok;
BSONObj result; BSONObj result;
}; };
 End of changes. 1 change blocks. 
2 lines changed or deleted 2 lines changed or added


 mutex.h   mutex.h 
skipping to change at line 37 skipping to change at line 37
#include "mongo/util/assert_util.h" #include "mongo/util/assert_util.h"
#include "mongo/util/heapcheck.h" #include "mongo/util/heapcheck.h"
#include "mongo/util/concurrency/threadlocal.h" #include "mongo/util/concurrency/threadlocal.h"
#include "mongo/util/time_support.h" #include "mongo/util/time_support.h"
#if defined(_DEBUG) #if defined(_DEBUG)
#include "mongo/util/concurrency/mutexdebugger.h" #include "mongo/util/concurrency/mutexdebugger.h"
#endif #endif
// Macro to get line as a string constant
#define MONGO_STRINGIFY(X) #X
// Double-expansion trick to get preproc to actually substitute __LINE__
#define _MONGO_LINE_STRING(LINE) MONGO_STRINGIFY( LINE )
#define MONGO_LINE_STRING _MONGO_LINE_STRING( __LINE__ )
// Mutex names should be as <file>::<line> string
#define MONGO_FILE_LINE __FILE__ "::" MONGO_LINE_STRING
namespace mongo { namespace mongo {
inline boost::xtime incxtimemillis( long long s ) { inline boost::xtime incxtimemillis( long long s ) {
boost::xtime xt; boost::xtime xt;
boost::xtime_get(&xt, MONGO_BOOST_TIME_UTC); boost::xtime_get(&xt, MONGO_BOOST_TIME_UTC);
xt.sec += (int)( s / 1000 ); xt.sec += (int)( s / 1000 );
xt.nsec += (int)(( s % 1000 ) * 1000000); xt.nsec += (int)(( s % 1000 ) * 1000000);
if ( xt.nsec >= 1000000000 ) { if ( xt.nsec >= 1000000000 ) {
xt.nsec -= 1000000000; xt.nsec -= 1000000000;
xt.sec++; xt.sec++;
 End of changes. 1 change blocks. 
0 lines changed or deleted 9 lines changed or added


 namespace_details-inl.h   namespace_details-inl.h 
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) {
bool includeBackgrou IndexIterator i = ii();
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 87 skipping to change at line 86
return &currentIndex; return &currentIndex;
} else { } else {
bestMultiKeyIndex = &currentIndex; bestMultiKeyIndex = &currentIndex;
} }
} }
} }
return requireSingleKey ? NULL : bestMultiKeyIndex; return requireSingleKey ? NULL : bestMultiKeyIndex;
} }
// @return offset in indexes[] // @return offset in indexes[]
inline int NamespaceDetails::findIndexByName(const char *name, inline int NamespaceDetails::findIndexByName(const char *name) {
bool includeBackgroundInPr IndexIterator i = ii();
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;
 End of changes. 2 change blocks. 
9 lines changed or deleted 5 lines changed or added


 namespace_details.h   namespace_details.h 
// namespace_details.h
/** /**
* Copyright (C) 2008 10gen Inc. * Copyright (C) 2008 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3 * it under the terms of the GNU Affero General Public License, version
, 3,
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen * 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 "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_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.h"
#include "mongo/db/namespacestring.h" #include "mongo/db/namespacestring.h"
#include "mongo/db/queryoptimizercursor.h"
#include "mongo/db/querypattern.h" #include "mongo/db/querypattern.h"
#include "mongo/platform/unordered_map.h" #include "mongo/platform/unordered_map.h"
#include "mongo/util/hashtab.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
skipping to change at line 294 skipping to change at line 292
*/ */
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, bool includeBackgroundInProgr ess = false); int findIndexByName(const char *name);
// @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 ( i.next().getSpec().getTypeName() == name ) 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 );
skipping to change at line 362 skipping to change at line 359
return i.pos()-1; return i.pos()-1;
} }
return -1; return -1;
} }
bool haveIdIndex() { bool haveIdIndex() {
return isSystemFlagSet( NamespaceDetails::Flag_HaveIdIndex ) || findIdIndex() >= 0; return isSystemFlagSet( NamespaceDetails::Flag_HaveIdIndex ) || findIdIndex() >= 0;
} }
/* return which "deleted bucket" for this size object */ /* return which "deleted bucket" for this size object */
static int bucket(int n) { static int bucket(int size) {
for ( int i = 0; i < Buckets; i++ ) for ( int i = 0; i < Buckets; i++ ) {
if ( bucketSizes[i] > n ) if ( bucketSizes[i] > size ) {
// Return the first bucket sized _larger_ than the requ
ested size.
return i; return i;
return Buckets-1; }
}
return MaxBucket;
} }
/* @return the size for an allocated record quantized to 1/16th of the BucketSize /* @return the size for an allocated record quantized to 1/16th of the BucketSize.
@param allocSize requested size to allocate @param allocSize requested size to allocate
The returned size will be greater than or equal to 'allocSize'.
*/ */
static int quantizeAllocationSpace(int allocSize); static int quantizeAllocationSpace(int allocSize);
/**
* Quantize 'allocSize' to the nearest bucketSize (or nearest 1mb b
oundary for large sizes).
*/
static int quantizePowerOf2AllocationSpace(int allocSize);
/* predetermine location of the next alloc without actually doing i t. /* predetermine location of the next alloc without actually doing i t.
if cannot predetermine returns null (so still call alloc() then) if cannot predetermine returns null (so still call alloc() then)
*/ */
DiskLoc allocWillBeAt(const char *ns, int lenToAlloc); DiskLoc allocWillBeAt(const char *ns, int lenToAlloc);
/** allocate space for a new record from deleted lists. /** allocate space for a new record from deleted lists.
@param lenToAlloc is WITH header @param lenToAlloc is WITH header
@return null diskloc if no room - allocate a new extent then @return null diskloc if no room - allocate a new extent then
*/ */
DiskLoc alloc(const char* ns, int lenToAlloc); DiskLoc alloc(const char* ns, int lenToAlloc);
skipping to change at line 406 skipping to change at line 412
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();
void onLoad( const Namespace& k );
private: private:
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];
skipping to change at line 429 skipping to change at line 434
}; };
/** Update cappedLastDelRecLastExtent() after capExtent changed in cappedTruncateAfter() */ /** Update cappedLastDelRecLastExtent() after capExtent changed in cappedTruncateAfter() */
void cappedTruncateLastDelUpdate(); void cappedTruncateLastDelUpdate();
BOOST_STATIC_ASSERT( NIndexesMax <= NIndexesBase + NIndexesExtra*2 ); BOOST_STATIC_ASSERT( NIndexesMax <= NIndexesBase + NIndexesExtra*2 );
BOOST_STATIC_ASSERT( NIndexesMax <= 64 ); // multiKey bits BOOST_STATIC_ASSERT( NIndexesMax <= 64 ); // multiKey bits
BOOST_STATIC_ASSERT( sizeof(NamespaceDetails::ExtraOld) == 496 ); BOOST_STATIC_ASSERT( sizeof(NamespaceDetails::ExtraOld) == 496 );
BOOST_STATIC_ASSERT( sizeof(NamespaceDetails::Extra) == 496 ); BOOST_STATIC_ASSERT( sizeof(NamespaceDetails::Extra) == 496 );
}; // NamespaceDetails }; // NamespaceDetails
#pragma pack() #pragma pack()
class ParsedQuery;
class QueryPlanSummary;
/* NamespaceDetailsTransient /* NamespaceDetailsTransient
these are things we know / compute about a namespace that are transi ent -- things these are things we know / compute about a namespace that are transi ent -- things
we don't actually store in the .ns file. so mainly caching of frequ ently used we don't actually store in the .ns file. so mainly caching of frequ ently used
information. information.
CAUTION: Are you maintaining this properly on a collection drop()? A dropdatabase()? Be careful. CAUTION: Are you maintaining this properly on a collection drop()? A dropdatabase()? Be careful.
The current field "allIndexKeys" may have too many keys in it on such an occurrence; The current field "allIndexKeys" may have too many keys in it on such an occurrence;
as currently used that does not cause anything terrible to happen. as currently used that does not cause anything terrible to happen.
skipping to change at line 479 skipping to change at line 481
/** /**
* remove entry for a collection * remove entry for a collection
*/ */
static void eraseCollection(const string& ns); static void eraseCollection(const string& ns);
/** /**
* remove all entries for db * remove all entries for db
*/ */
static void eraseDB(const string& db); static void eraseDB(const string& db);
/**
* @return a cursor interface to the query optimizer. The implemen
tation may utilize a
* single query plan or interleave results from multiple query plan
s before settling on a
* single query plan. Note that the schema of currKey() documents,
indexKeyPattern(), the
* matcher(), and the isMultiKey() nature of the cursor may change
over the course of
* iteration.
*
* @param query - Query used to select indexes and populate matcher
s; not copied if unowned
* (see bsonobj.h).
*
* @param order - Required ordering spec for documents produced by
this cursor, empty object
* default indicates no order requirement. If no index exists that
satisfies the required
* sort order, an empty shared_ptr is returned unless parsedQuery i
s also provided. This is
* not copied if unowned.
*
* @param planPolicy - A policy for selecting query plans - see que
ryoptimizercursor.h
*
* @param parsedQuery - Additional query parameters, as from a clie
nt query request.
*
* @param requireOrder - If false, the resulting cursor may return
results in an order
* inconsistent with the @param order spec. See queryoptimizercurs
or.h for information on
* handling these results properly.
*
* @param singlePlanSummary - Query plan summary information that m
ay be provided when a
* cursor running a single plan is returned.
*
* The returned cursor may @throw inside of advance() or recoverFro
mYield() in certain error
* cases, for example if a capped overrun occurred during a yield.
This indicates that the
* cursor was unable to perform a complete scan.
*
* This is a work in progress. Partial list of features not yet im
plemented through this
* interface:
*
* - covered indexes
* - in memory sorting
*/
static shared_ptr<Cursor> getCursor( const StringData& ns,
const BSONObj& query,
const BSONObj& order = BSONObj
(),
const QueryPlanSelectionPolicy
& planPolicy =
QueryPlanSelectionPolicy::
any(),
const shared_ptr<const ParsedQ
uery>& parsedQuery =
shared_ptr<const ParsedQue
ry>(),
bool requireOrder = true,
QueryPlanSummary* singlePlanSu
mmary = NULL );
/**
* @return a single cursor that may work well for the given query.
A $or style query will
* produce a single cursor, not a MultiCursor.
* It is possible no cursor is returned if the sort is not supporte
d by an index. Clients are responsible
* for checking this if they are not sure an index for a sort exist
s, and defaulting to a non-sort if
* no suitable indices exist.
*/
static shared_ptr<Cursor> bestGuessCursor( const char *ns, const BS
ONObj &query, const BSONObj &sort );
/* indexKeys() cache ---------------------------------------------- ------ */ /* indexKeys() cache ---------------------------------------------- ------ */
/* assumed to be in write lock for this */ /* assumed to be in write lock for this */
private: private:
bool _keysComputed; bool _keysComputed;
IndexPathSet _indexedPaths; IndexPathSet _indexedPaths;
void computeIndexKeys(); void computeIndexKeys();
public: public:
/* get set of index keys for this namespace. handy to quickly chec k if a given /* get set of index keys for this namespace. handy to quickly chec k if a given
field is indexed (Note it might be a secondary component of a co mpound index.) field is indexed (Note it might be a secondary component of a co mpound index.)
*/ */
const IndexPathSet& indexKeys() { const IndexPathSet& indexKeys() {
DEV Lock::assertWriteLocked(_ns); DEV Lock::assertWriteLocked(_ns);
if ( !_keysComputed ) if ( !_keysComputed )
computeIndexKeys(); computeIndexKeys();
return _indexedPaths; return _indexedPaths;
} }
/* IndexSpec caching */
private:
map<const IndexDetails*,IndexSpec> _indexSpecs;
static SimpleMutex _isMutex;
public:
const IndexSpec& getIndexSpec( const IndexDetails * details ) {
IndexSpec& spec = _indexSpecs[details];
if ( ! spec._finishedInit ) {
SimpleMutex::scoped_lock lk(_isMutex);
if ( ! spec._finishedInit ) {
spec.reset( details );
verify( spec._finishedInit );
}
}
return spec;
}
/* query cache (for query optimizer) ------------------------------ ------- */ /* query cache (for query optimizer) ------------------------------ ------- */
private: private:
int _qcWriteCount; int _qcWriteCount;
map<QueryPattern,CachedQueryPlan> _qcCache; map<QueryPattern,CachedQueryPlan> _qcCache;
static NamespaceDetailsTransient& make_inlock(const string& ns); static NamespaceDetailsTransient& make_inlock(const string& ns);
static CMap& get_cmap_inlock(const string& ns); static CMap& get_cmap_inlock(const string& ns);
public: public:
static SimpleMutex _qcMutex; static SimpleMutex _qcMutex;
/* you must be in the qcMutex when calling this. /* you must be in the qcMutex when calling this.
 End of changes. 16 change blocks. 
131 lines changed or deleted 36 lines changed or added


 namespacestring.h   namespacestring.h 
skipping to change at line 49 skipping to change at line 49
string db; string db;
string coll; // note collection names can have periods in them for organizing purposes (e.g. "system.indexes") string coll; // note collection names can have periods in them for organizing purposes (e.g. "system.indexes")
NamespaceString( const char * ns ) { init(ns); } NamespaceString( const char * ns ) { init(ns); }
NamespaceString( const string& ns ) { init(ns.c_str()); } NamespaceString( const string& ns ) { init(ns.c_str()); }
string ns() const { return db + '.' + coll; } string ns() const { return db + '.' + coll; }
bool isSystem() const { return strncmp(coll.c_str(), "system.", 7) == 0; } bool isSystem() const { return strncmp(coll.c_str(), "system.", 7) == 0; }
bool isCommand() const { return coll == "$cmd"; } bool isCommand() const { return coll == "$cmd"; }
bool isSystemDotIndexes() const { return strncmp(coll.c_str(), "sys tem.indexes", 14) == 0; }
/** /**
* @return true if the namespace is valid. Special namespaces for i nternal use are considered as valid. * @return true if the namespace is valid. Special namespaces for i nternal use are considered as valid.
*/ */
bool isValid() const { bool isValid() const {
return validDBName( db ) && !coll.empty(); return validDBName( db ) && !coll.empty();
} }
operator string() const { return ns(); } operator string() const { return ns(); }
 End of changes. 1 change blocks. 
1 lines changed or deleted 0 lines changed or added


 oplog.h   oplog.h 
// oplog.h - writing to and reading from oplog
/** /**
* Copyright (C) 2008 10gen Inc. * Copyright (C) 2008 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3 , * it under the terms of the GNU Affero General Public License, version 3 ,
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/*
local.oplog.$main is the default
*/
#pragma once #pragma once
#include "pdfile.h"
#include "db.h"
#include "dbhelpers.h"
#include "clientcursor.h"
#include "../util/optime.h"
#include "../util/timer.h"
namespace mongo { namespace mongo {
class BSONObj;
class Database;
// These functions redefine the function for logOp(),
// for either master/slave or replica sets.
void oldRepl(); // master-slave
void newRepl(); // replica set starting up
void newReplUp();// replica set after startup
// Create a new capped collection for the oplog if it doesn't yet exist
.
// This will be either local.oplog.rs (replica sets) or local.oplog.$ma
in (master/slave)
// If the collection already exists, set the 'last' OpTime if master/sl
ave (side effect!)
void createOplog(); void createOplog();
// This poorly-named function writes an op into the replica-set oplog;
// used internally by replication secondaries after they have applied a
n op
void _logOpObjRS(const BSONObj& op); void _logOpObjRS(const BSONObj& op);
/** Write operation to the log (local.oplog.$main) const char rsoplog[] = "local.oplog.rs";
/** Log an operation to the local oplog
@param opstr @param opstr
"i" insert "i" insert
"u" update "u" update
"d" delete "d" delete
"c" db cmd "c" db cmd
"n" no-op "n" no-op
"db" declares presence of a database (ns is set to the db name + '. ') "db" declares presence of a database (ns is set to the db name + '. ')
For 'u' records, 'obj' captures the mutation made to the object but
not
the object itself. In that case, we provide also 'fullObj' which is
the
image of the object _after_ the mutation logged here was applied.
See _logOp() in oplog.cpp for more details. See _logOp() in oplog.cpp for more details.
*/ */
void logOp( const char *opstr, const char *ns, const BSONObj& obj, BSON void logOp( const char *opstr, const char *ns, const BSONObj& obj,
Obj *patt = 0, bool *b = 0, bool fromMigrate = false ); BSONObj *patt = NULL, bool *b = NULL, bool fromMigrate = fa
lse,
const BSONObj* fullObj = NULL );
// Log an empty no-op operation to the local oplog
void logKeepalive(); void logKeepalive();
/** puts obj in the oplog as a comment (a no-op). Just for diags. /** puts obj in the oplog as a comment (a no-op). Just for diags.
convention is convention is
{ msg : "text", ... } { msg : "text", ... }
*/ */
void logOpComment(const BSONObj& obj); void logOpComment(const BSONObj& obj);
// Flush out the cached pointers to the local database and oplog.
// Used by the closeDatabase command to ensure we don't cache closed th
ings.
void oplogCheckCloseDatabase( Database * db ); void oplogCheckCloseDatabase( Database * db );
class QueryPlan;
/** Implements an optimized procedure for finding the first op in the o
plog. */
class FindingStartCursor {
public:
/**
* The cursor will attempt to find the first op in the oplog matchi
ng the
* 'ts' field of the qp's query.
*/
static FindingStartCursor *make( const QueryPlan &qp );
/** @return true if the first matching op in the oplog has been fou
nd. */
bool done() const { return !_findingStart; }
/** @return cursor pointing to the first matching op, if done(). */
shared_ptr<Cursor> cursor() { verify( done() ); return _c; }
/** Iterate the cursor, to continue trying to find matching op. */
void next();
/** Yield cursor, if not done(). */
bool prepareToYield() {
if ( _findingStartCursor ) {
return _findingStartCursor->prepareToYield( _yieldData );
}
return false;
}
/** Recover from cursor yield. */
void recoverFromYield() {
if ( _findingStartCursor ) {
if ( !ClientCursor::recoverFromYield( _yieldData ) ) {
_findingStartCursor.reset( 0 );
msgassertedNoTrace( 15889, "FindingStartCursor::recover
FromYield() failed to recover" );
}
}
}
/**
* @return a BasicCursor constructed using a FindingStartCursor wit
h the provided query and
* order parameters.
* @yields the db lock.
* @asserts on yield recovery failure.
*/
static shared_ptr<Cursor> getCursor( const char *ns, const BSONObj
&query, const BSONObj &order );
/**
* @return the first record of the first nonempty extent preceding
the extent containing
* @param rec, or DiskLoc() if there is no such record or the b
eginning of the
* collection is reached.
* public for testing
*/
DiskLoc prevExtentFirstLoc( const DiskLoc& rec ) const;
/** For testing only. */
static int getInitialTimeout() { return _initialTimeout; }
static void setInitialTimeout( int timeout ) { _initialTimeout = ti
meout; }
private:
FindingStartCursor( const QueryPlan &qp );
void init();
enum FindingStartMode { Initial, FindExtent, InExtent };
const QueryPlan &_qp;
bool _findingStart;
FindingStartMode _findingStartMode;
auto_ptr< CoveredIndexMatcher > _matcher;
Timer _findingStartTimer;
ClientCursor::Holder _findingStartCursor;
shared_ptr<Cursor> _c;
ClientCursor::YieldData _yieldData;
static int _initialTimeout;
/** @return the first record of the extent containing @param rec. *
/
DiskLoc extentFirstLoc( const DiskLoc &rec );
void createClientCursor( const DiskLoc &startLoc = DiskLoc() );
void destroyClientCursor() {
_findingStartCursor.reset( 0 );
}
bool firstDocMatchesOrEmpty() const;
};
class Sync {
protected:
string hn;
public:
Sync(const string& hostname) : hn(hostname) {}
virtual ~Sync() {}
virtual BSONObj getMissingDoc(const BSONObj& o);
/**
* If applyOperation_inlock should be called again after an update
fails.
*/
virtual bool shouldRetry(const BSONObj& o);
void setHostname(const string& hostname);
};
void pretouchOperation(const BSONObj& op);
void pretouchN(vector<BSONObj>&, unsigned a, unsigned b);
/** /**
* take an op and apply locally * take an op and apply locally
* used for applying from an oplog * used for applying from an oplog
* @param fromRepl really from replication or for testing/internal/comm and/etc... * @param fromRepl really from replication or for testing/internal/comm and/etc...
* @param convertUpdateToUpsert convert some updates to upserts for ide mpotency reasons
* Returns if the op was an update that could not be applied (true on f ailure) * Returns if the op was an update that could not be applied (true on f ailure)
*/ */
bool applyOperation_inlock(const BSONObj& op, bool fromRepl = true, boo bool applyOperation_inlock(const BSONObj& op,
l convertUpdateToUpsert = false); bool fromRepl = true,
bool convertUpdateToUpsert = false);
} }
 End of changes. 13 change blocks. 
133 lines changed or deleted 39 lines changed or added


 oplogreader.h   oplogreader.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 "../client/constants.h" #include "mongo/client/constants.h"
#include "dbhelpers.h"
#include "mongo/client/dbclientcursor.h" #include "mongo/client/dbclientcursor.h"
#include "mongo/db/dbhelpers.h"
namespace mongo { namespace mongo {
/* started abstracting out the querying of the primary/master's oplog /* started abstracting out the querying of the primary/master's oplog
still fairly awkward but a start. still fairly awkward but a start.
*/ */
class OplogReader { class OplogReader {
shared_ptr<DBClientConnection> _conn; shared_ptr<DBClientConnection> _conn;
shared_ptr<DBClientCursor> cursor; shared_ptr<DBClientCursor> cursor;
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 optime.h   optime.h 
// optime.h - OpTime class
/* 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 <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
#include <iostream>
#include <sstream>
#include "mongo/bson/util/misc.h" // time_t_to_String
#include "mongo/util/assert_util.h"
#include "mongo/util/concurrency/mutex.h"
namespace mongo { namespace mongo {
struct ClockSkewException : public DBException { struct ClockSkewException : public DBException {
ClockSkewException() : DBException( "clock skew exception" , 20001 ) {} ClockSkewException() : DBException( "clock skew exception" , 20001 ) {}
}; };
/* replsets used to use RSOpTime. /* replsets used to use RSOpTime.
M/S uses OpTime. M/S uses OpTime.
But this is useable from both. But this is useable from both.
skipping to change at line 112 skipping to change at line 116
} }
long long asLL() const { long long asLL() const {
return reinterpret_cast<const long long*>(&i)[0]; return reinterpret_cast<const long long*>(&i)[0];
} }
bool isNull() const { return secs == 0; } bool isNull() const { return secs == 0; }
string toStringLong() const { string toStringLong() const {
char buf[64]; char buf[64];
time_t_to_String(secs, buf); time_t_to_String(secs, buf);
stringstream ss; std::stringstream ss;
ss << time_t_to_String_short(secs) << ' '; ss << time_t_to_String_short(secs) << ' ';
ss << hex << secs << ':' << i; ss << std::hex << secs << ':' << i;
return ss.str(); return ss.str();
} }
string toStringPretty() const { string toStringPretty() const {
stringstream ss; std::stringstream ss;
ss << time_t_to_String_short(secs) << ':' << hex << i; ss << time_t_to_String_short(secs) << ':' << std::hex << i;
return ss.str(); return ss.str();
} }
string toString() const { string toString() const {
stringstream ss; std::stringstream ss;
ss << hex << secs << ':' << i; ss << std::hex << secs << ':' << i;
return ss.str(); return ss.str();
} }
bool operator==(const OpTime& r) const { bool operator==(const OpTime& r) const {
return i == r.i && secs == r.secs; return i == r.i && secs == r.secs;
} }
bool operator!=(const OpTime& r) const { bool operator!=(const OpTime& r) const {
return !(*this == r); return !(*this == r);
} }
bool operator<(const OpTime& r) const { bool operator<(const OpTime& r) const {
 End of changes. 6 change blocks. 
8 lines changed or deleted 12 lines changed or added


 parallel.h   parallel.h 
skipping to change at line 266 skipping to change at line 266
class DBClientCursor; class DBClientCursor;
typedef shared_ptr<DBClientCursor> DBClientCursorPtr; typedef shared_ptr<DBClientCursor> DBClientCursorPtr;
class ParallelConnectionState { class ParallelConnectionState {
public: public:
ParallelConnectionState() : ParallelConnectionState() :
count( 0 ), done( false ) { } count( 0 ), done( false ) { }
// Please do not reorder. cursor destructor can use conn.
// On a related note, never attempt to cleanup these pointers manua
lly.
ShardConnectionPtr conn; ShardConnectionPtr conn;
DBClientCursorPtr cursor; DBClientCursorPtr cursor;
// Version information // Version information
ChunkManagerPtr manager; ChunkManagerPtr manager;
ShardPtr primary; ShardPtr primary;
// Cursor status information // Cursor status information
long long count; long long count;
bool done; bool done;
 End of changes. 1 change blocks. 
3 lines changed or deleted 0 lines changed or added


 pcre.h   pcre.h 
/************************************************* /*************************************************
* Perl-Compatible Regular Expressions * * Perl-Compatible Regular Expressions *
*************************************************/ *************************************************/
/* This is the public header file for the PCRE library, to be #included by /* This is the public header file for the PCRE library, to be #included by
applications that call the PCRE functions. applications that call the PCRE functions.
Copyright (c) 1997-2014 University of Cambridge Copyright (c) 1997-2012 University of Cambridge
--------------------------------------------------------------------------- -- --------------------------------------------------------------------------- --
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice , * Redistributions of source code must retain the above copyright notice ,
this list of conditions and the following disclaimer. this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
skipping to change at line 45 skipping to change at line 45
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- -- --------------------------------------------------------------------------- --
*/ */
#ifndef _PCRE_H #ifndef _PCRE_H
#define _PCRE_H #define _PCRE_H
/* The current PCRE version information. */ /* The current PCRE version information. */
#define PCRE_MAJOR 8 #define PCRE_MAJOR 8
#define PCRE_MINOR 36 #define PCRE_MINOR 30
#define PCRE_PRERELEASE #define PCRE_PRERELEASE
#define PCRE_DATE 2014-09-26 #define PCRE_DATE 2012-02-04
/* When an application links to a PCRE DLL in Windows, the symbols that are /* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate imported have to be identified as such. When building PCRE, the appropriate
export setting is defined in pcre_internal.h, which includes this file. So we export setting is defined in pcre_internal.h, which includes this file. So we
don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */ don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */
#if defined(_WIN32) && !defined(PCRE_STATIC) #if defined(_WIN32) && !defined(PCRE_STATIC)
# ifndef PCRE_EXP_DECL # ifndef PCRE_EXP_DECL
# define PCRE_EXP_DECL extern __declspec(dllimport) # define PCRE_EXP_DECL extern
# endif # endif
# ifdef __cplusplus # ifdef __cplusplus
# ifndef PCRECPP_EXP_DECL # ifndef PCRECPP_EXP_DECL
# define PCRECPP_EXP_DECL extern __declspec(dllimport) # define PCRECPP_EXP_DECL extern
# endif # endif
# ifndef PCRECPP_EXP_DEFN # ifndef PCRECPP_EXP_DEFN
# define PCRECPP_EXP_DEFN __declspec(dllimport) # define PCRECPP_EXP_DEFN
# endif # endif
# endif # endif
#endif #endif
/* By default, we use the standard "extern" declarations. */ /* By default, we use the standard "extern" declarations. */
#ifndef PCRE_EXP_DECL #ifndef PCRE_EXP_DECL
# ifdef __cplusplus # ifdef __cplusplus
# define PCRE_EXP_DECL extern "C" # define PCRE_EXP_DECL extern "C"
# else # else
skipping to change at line 98 skipping to change at line 98
it is needed here for malloc. */ it is needed here for malloc. */
#include <stdlib.h> #include <stdlib.h>
/* Allow for C++ users */ /* Allow for C++ users */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Public options. Some are compile-time only, some are run-time only, and /* Options. Some are compile-time only, some are run-time only, and some ar
some e
are both. Most of the compile-time options are saved with the compiled rege both, so we keep them all distinct. However, almost all the bits in the opt
x so ions
that they can be inspected during studying (and therefore JIT compiling). N word are now used. In the long run, we may have to re-use some of the
ote compile-time only bits for runtime options, or vice versa. In the comments
that pcre_study() has its own set of options. Originally, all the options below, "compile", "exec", and "DFA exec" mean that the option is permitted
defined here used distinct bits. However, almost all the bits in a 32-bit w to
ord be set for those functions; "used in" means that an option may be set only
are now used, so in order to conserve them, option bits that were previousl for
y compile, but is subsequently referenced in exec and/or DFA exec. Any of the
only recognized at matching time (i.e. by pcre_exec() or pcre_dfa_exec()) m compile-time options may be inspected during studying (and therefore JIT
ay compiling). */
also be used for compile-time options that affect only compiling and are no
t #define PCRE_CASELESS 0x00000001 /* Compile */
relevant for studying or JIT compiling. #define PCRE_MULTILINE 0x00000002 /* Compile */
#define PCRE_DOTALL 0x00000004 /* Compile */
Some options for pcre_compile() change its behaviour but do not affect the #define PCRE_EXTENDED 0x00000008 /* Compile */
behaviour of the execution functions. Other options are passed through to t #define PCRE_ANCHORED 0x00000010 /* Compile, exec, DFA exec */
he #define PCRE_DOLLAR_ENDONLY 0x00000020 /* Compile, used in exec, DFA e
execution functions and affect their behaviour, with or without affecting t xec */
he #define PCRE_EXTRA 0x00000040 /* Compile */
behaviour of pcre_compile(). #define PCRE_NOTBOL 0x00000080 /* Exec, DFA exec */
#define PCRE_NOTEOL 0x00000100 /* Exec, DFA exec */
Options that can be passed to pcre_compile() are tagged Cx below, with thes #define PCRE_UNGREEDY 0x00000200 /* Compile */
e #define PCRE_NOTEMPTY 0x00000400 /* Exec, DFA exec */
variants: /* The next two are also used in exec and DFA exec */
#define PCRE_UTF8 0x00000800 /* Compile (same as PCRE_UTF16)
C1 Affects compile only */
C2 Does not affect compile; affects exec, dfa_exec #define PCRE_UTF16 0x00000800 /* Compile (same as PCRE_UTF8)
C3 Affects compile, exec, dfa_exec */
C4 Affects compile, exec, dfa_exec, study #define PCRE_NO_AUTO_CAPTURE 0x00001000 /* Compile */
C5 Affects compile, exec, study /* The next two are also used in exec and DFA exec */
#define PCRE_NO_UTF8_CHECK 0x00002000 /* Compile (same as PCRE_NO_UTF
Options that can be set for pcre_exec() and/or pcre_dfa_exec() are flagged 16_CHECK) */
with #define PCRE_NO_UTF16_CHECK 0x00002000 /* Compile (same as PCRE_NO_UTF
E and D, respectively. They take precedence over C3, C4, and C5 settings pa 8_CHECK) */
ssed #define PCRE_AUTO_CALLOUT 0x00004000 /* Compile */
from pcre_compile(). Those that are compatible with JIT execution are flagg #define PCRE_PARTIAL_SOFT 0x00008000 /* Exec, DFA exec */
ed #define PCRE_PARTIAL 0x00008000 /* Backwards compatible synonym
with J. */ */
#define PCRE_DFA_SHORTEST 0x00010000 /* DFA exec */
#define PCRE_CASELESS 0x00000001 /* C1 */ #define PCRE_DFA_RESTART 0x00020000 /* DFA exec */
#define PCRE_MULTILINE 0x00000002 /* C1 */ #define PCRE_FIRSTLINE 0x00040000 /* Compile, used in exec, DFA e
#define PCRE_DOTALL 0x00000004 /* C1 */ xec */
#define PCRE_EXTENDED 0x00000008 /* C1 */ #define PCRE_DUPNAMES 0x00080000 /* Compile */
#define PCRE_ANCHORED 0x00000010 /* C4 E D */ #define PCRE_NEWLINE_CR 0x00100000 /* Compile, exec, DFA exec */
#define PCRE_DOLLAR_ENDONLY 0x00000020 /* C2 */ #define PCRE_NEWLINE_LF 0x00200000 /* Compile, exec, DFA exec */
#define PCRE_EXTRA 0x00000040 /* C1 */ #define PCRE_NEWLINE_CRLF 0x00300000 /* Compile, exec, DFA exec */
#define PCRE_NOTBOL 0x00000080 /* E D J */ #define PCRE_NEWLINE_ANY 0x00400000 /* Compile, exec, DFA exec */
#define PCRE_NOTEOL 0x00000100 /* E D J */ #define PCRE_NEWLINE_ANYCRLF 0x00500000 /* Compile, exec, DFA exec */
#define PCRE_UNGREEDY 0x00000200 /* C1 */ #define PCRE_BSR_ANYCRLF 0x00800000 /* Compile, exec, DFA exec */
#define PCRE_NOTEMPTY 0x00000400 /* E D J */ #define PCRE_BSR_UNICODE 0x01000000 /* Compile, exec, DFA exec */
#define PCRE_UTF8 0x00000800 /* C4 ) */ #define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* Compile, used in exec */
#define PCRE_UTF16 0x00000800 /* C4 ) Synonyms */ #define PCRE_NO_START_OPTIMIZE 0x04000000 /* Compile, exec, DFA exec */
#define PCRE_UTF32 0x00000800 /* C4 ) */ #define PCRE_NO_START_OPTIMISE 0x04000000 /* Synonym */
#define PCRE_NO_AUTO_CAPTURE 0x00001000 /* C1 */ #define PCRE_PARTIAL_HARD 0x08000000 /* Exec, DFA exec */
#define PCRE_NO_UTF8_CHECK 0x00002000 /* C1 E D J ) */ #define PCRE_NOTEMPTY_ATSTART 0x10000000 /* Exec, DFA exec */
#define PCRE_NO_UTF16_CHECK 0x00002000 /* C1 E D J ) Synonyms */ #define PCRE_UCP 0x20000000 /* Compile, used in exec, DFA e
#define PCRE_NO_UTF32_CHECK 0x00002000 /* C1 E D J ) */ xec */
#define PCRE_AUTO_CALLOUT 0x00004000 /* C1 */
#define PCRE_PARTIAL_SOFT 0x00008000 /* E D J ) Synonyms */
#define PCRE_PARTIAL 0x00008000 /* E D J ) */
/* This pair use the same bit. */
#define PCRE_NEVER_UTF 0x00010000 /* C1 ) Overlaid */
#define PCRE_DFA_SHORTEST 0x00010000 /* D ) Overlaid */
/* This pair use the same bit. */
#define PCRE_NO_AUTO_POSSESS 0x00020000 /* C1 ) Overlaid */
#define PCRE_DFA_RESTART 0x00020000 /* D ) Overlaid */
#define PCRE_FIRSTLINE 0x00040000 /* C3 */
#define PCRE_DUPNAMES 0x00080000 /* C1 */
#define PCRE_NEWLINE_CR 0x00100000 /* C3 E D */
#define PCRE_NEWLINE_LF 0x00200000 /* C3 E D */
#define PCRE_NEWLINE_CRLF 0x00300000 /* C3 E D */
#define PCRE_NEWLINE_ANY 0x00400000 /* C3 E D */
#define PCRE_NEWLINE_ANYCRLF 0x00500000 /* C3 E D */
#define PCRE_BSR_ANYCRLF 0x00800000 /* C3 E D */
#define PCRE_BSR_UNICODE 0x01000000 /* C3 E D */
#define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* C5 */
#define PCRE_NO_START_OPTIMIZE 0x04000000 /* C2 E D ) Synonyms */
#define PCRE_NO_START_OPTIMISE 0x04000000 /* C2 E D ) */
#define PCRE_PARTIAL_HARD 0x08000000 /* E D J */
#define PCRE_NOTEMPTY_ATSTART 0x10000000 /* E D J */
#define PCRE_UCP 0x20000000 /* C3 */
/* Exec-time and get/set-time error codes */ /* Exec-time and get/set-time error codes */
#define PCRE_ERROR_NOMATCH (-1) #define PCRE_ERROR_NOMATCH (-1)
#define PCRE_ERROR_NULL (-2) #define PCRE_ERROR_NULL (-2)
#define PCRE_ERROR_BADOPTION (-3) #define PCRE_ERROR_BADOPTION (-3)
#define PCRE_ERROR_BADMAGIC (-4) #define PCRE_ERROR_BADMAGIC (-4)
#define PCRE_ERROR_UNKNOWN_OPCODE (-5) #define PCRE_ERROR_UNKNOWN_OPCODE (-5)
#define PCRE_ERROR_UNKNOWN_NODE (-5) /* For backward compatibility */ #define PCRE_ERROR_UNKNOWN_NODE (-5) /* For backward compatibility */
#define PCRE_ERROR_NOMEMORY (-6) #define PCRE_ERROR_NOMEMORY (-6)
#define PCRE_ERROR_NOSUBSTRING (-7) #define PCRE_ERROR_NOSUBSTRING (-7)
#define PCRE_ERROR_MATCHLIMIT (-8) #define PCRE_ERROR_MATCHLIMIT (-8)
#define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */ #define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */
#define PCRE_ERROR_BADUTF8 (-10) /* Same for 8/16/32 */ #define PCRE_ERROR_BADUTF8 (-10) /* Same for 8/16 */
#define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16/32 */ #define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16 */
#define PCRE_ERROR_BADUTF32 (-10) /* Same for 8/16/32 */
#define PCRE_ERROR_BADUTF8_OFFSET (-11) /* Same for 8/16 */ #define PCRE_ERROR_BADUTF8_OFFSET (-11) /* Same for 8/16 */
#define PCRE_ERROR_BADUTF16_OFFSET (-11) /* Same for 8/16 */ #define PCRE_ERROR_BADUTF16_OFFSET (-11) /* Same for 8/16 */
#define PCRE_ERROR_PARTIAL (-12) #define PCRE_ERROR_PARTIAL (-12)
#define PCRE_ERROR_BADPARTIAL (-13) #define PCRE_ERROR_BADPARTIAL (-13)
#define PCRE_ERROR_INTERNAL (-14) #define PCRE_ERROR_INTERNAL (-14)
#define PCRE_ERROR_BADCOUNT (-15) #define PCRE_ERROR_BADCOUNT (-15)
#define PCRE_ERROR_DFA_UITEM (-16) #define PCRE_ERROR_DFA_UITEM (-16)
#define PCRE_ERROR_DFA_UCOND (-17) #define PCRE_ERROR_DFA_UCOND (-17)
#define PCRE_ERROR_DFA_UMLIMIT (-18) #define PCRE_ERROR_DFA_UMLIMIT (-18)
#define PCRE_ERROR_DFA_WSSIZE (-19) #define PCRE_ERROR_DFA_WSSIZE (-19)
skipping to change at line 209 skipping to change at line 182
#define PCRE_ERROR_RECURSIONLIMIT (-21) #define PCRE_ERROR_RECURSIONLIMIT (-21)
#define PCRE_ERROR_NULLWSLIMIT (-22) /* No longer actually used */ #define PCRE_ERROR_NULLWSLIMIT (-22) /* No longer actually used */
#define PCRE_ERROR_BADNEWLINE (-23) #define PCRE_ERROR_BADNEWLINE (-23)
#define PCRE_ERROR_BADOFFSET (-24) #define PCRE_ERROR_BADOFFSET (-24)
#define PCRE_ERROR_SHORTUTF8 (-25) #define PCRE_ERROR_SHORTUTF8 (-25)
#define PCRE_ERROR_SHORTUTF16 (-25) /* Same for 8/16 */ #define PCRE_ERROR_SHORTUTF16 (-25) /* Same for 8/16 */
#define PCRE_ERROR_RECURSELOOP (-26) #define PCRE_ERROR_RECURSELOOP (-26)
#define PCRE_ERROR_JIT_STACKLIMIT (-27) #define PCRE_ERROR_JIT_STACKLIMIT (-27)
#define PCRE_ERROR_BADMODE (-28) #define PCRE_ERROR_BADMODE (-28)
#define PCRE_ERROR_BADENDIANNESS (-29) #define PCRE_ERROR_BADENDIANNESS (-29)
#define PCRE_ERROR_DFA_BADRESTART (-30)
#define PCRE_ERROR_JIT_BADOPTION (-31)
#define PCRE_ERROR_BADLENGTH (-32)
#define PCRE_ERROR_UNSET (-33)
/* Specific error codes for UTF-8 validity checks */ /* Specific error codes for UTF-8 validity checks */
#define PCRE_UTF8_ERR0 0 #define PCRE_UTF8_ERR0 0
#define PCRE_UTF8_ERR1 1 #define PCRE_UTF8_ERR1 1
#define PCRE_UTF8_ERR2 2 #define PCRE_UTF8_ERR2 2
#define PCRE_UTF8_ERR3 3 #define PCRE_UTF8_ERR3 3
#define PCRE_UTF8_ERR4 4 #define PCRE_UTF8_ERR4 4
#define PCRE_UTF8_ERR5 5 #define PCRE_UTF8_ERR5 5
#define PCRE_UTF8_ERR6 6 #define PCRE_UTF8_ERR6 6
skipping to change at line 238 skipping to change at line 207
#define PCRE_UTF8_ERR12 12 #define PCRE_UTF8_ERR12 12
#define PCRE_UTF8_ERR13 13 #define PCRE_UTF8_ERR13 13
#define PCRE_UTF8_ERR14 14 #define PCRE_UTF8_ERR14 14
#define PCRE_UTF8_ERR15 15 #define PCRE_UTF8_ERR15 15
#define PCRE_UTF8_ERR16 16 #define PCRE_UTF8_ERR16 16
#define PCRE_UTF8_ERR17 17 #define PCRE_UTF8_ERR17 17
#define PCRE_UTF8_ERR18 18 #define PCRE_UTF8_ERR18 18
#define PCRE_UTF8_ERR19 19 #define PCRE_UTF8_ERR19 19
#define PCRE_UTF8_ERR20 20 #define PCRE_UTF8_ERR20 20
#define PCRE_UTF8_ERR21 21 #define PCRE_UTF8_ERR21 21
#define PCRE_UTF8_ERR22 22 /* Unused (was non-character) */
/* Specific error codes for UTF-16 validity checks */ /* Specific error codes for UTF-16 validity checks */
#define PCRE_UTF16_ERR0 0 #define PCRE_UTF16_ERR0 0
#define PCRE_UTF16_ERR1 1 #define PCRE_UTF16_ERR1 1
#define PCRE_UTF16_ERR2 2 #define PCRE_UTF16_ERR2 2
#define PCRE_UTF16_ERR3 3 #define PCRE_UTF16_ERR3 3
#define PCRE_UTF16_ERR4 4 /* Unused (was non-character) */ #define PCRE_UTF16_ERR4 4
/* Specific error codes for UTF-32 validity checks */
#define PCRE_UTF32_ERR0 0
#define PCRE_UTF32_ERR1 1
#define PCRE_UTF32_ERR2 2 /* Unused (was non-character) */
#define PCRE_UTF32_ERR3 3
/* Request types for pcre_fullinfo() */ /* Request types for pcre_fullinfo() */
#define PCRE_INFO_OPTIONS 0 #define PCRE_INFO_OPTIONS 0
#define PCRE_INFO_SIZE 1 #define PCRE_INFO_SIZE 1
#define PCRE_INFO_CAPTURECOUNT 2 #define PCRE_INFO_CAPTURECOUNT 2
#define PCRE_INFO_BACKREFMAX 3 #define PCRE_INFO_BACKREFMAX 3
#define PCRE_INFO_FIRSTBYTE 4 #define PCRE_INFO_FIRSTBYTE 4
#define PCRE_INFO_FIRSTCHAR 4 /* For backwards compatibility */ #define PCRE_INFO_FIRSTCHAR 4 /* For backwards compatibility */
#define PCRE_INFO_FIRSTTABLE 5 #define PCRE_INFO_FIRSTTABLE 5
skipping to change at line 276 skipping to change at line 237
#define PCRE_INFO_NAMECOUNT 8 #define PCRE_INFO_NAMECOUNT 8
#define PCRE_INFO_NAMETABLE 9 #define PCRE_INFO_NAMETABLE 9
#define PCRE_INFO_STUDYSIZE 10 #define PCRE_INFO_STUDYSIZE 10
#define PCRE_INFO_DEFAULT_TABLES 11 #define PCRE_INFO_DEFAULT_TABLES 11
#define PCRE_INFO_OKPARTIAL 12 #define PCRE_INFO_OKPARTIAL 12
#define PCRE_INFO_JCHANGED 13 #define PCRE_INFO_JCHANGED 13
#define PCRE_INFO_HASCRORLF 14 #define PCRE_INFO_HASCRORLF 14
#define PCRE_INFO_MINLENGTH 15 #define PCRE_INFO_MINLENGTH 15
#define PCRE_INFO_JIT 16 #define PCRE_INFO_JIT 16
#define PCRE_INFO_JITSIZE 17 #define PCRE_INFO_JITSIZE 17
#define PCRE_INFO_MAXLOOKBEHIND 18
#define PCRE_INFO_FIRSTCHARACTER 19
#define PCRE_INFO_FIRSTCHARACTERFLAGS 20
#define PCRE_INFO_REQUIREDCHAR 21
#define PCRE_INFO_REQUIREDCHARFLAGS 22
#define PCRE_INFO_MATCHLIMIT 23
#define PCRE_INFO_RECURSIONLIMIT 24
#define PCRE_INFO_MATCH_EMPTY 25
/* Request types for pcre_config(). Do not re-arrange, in order to remain /* Request types for pcre_config(). Do not re-arrange, in order to remain
compatible. */ compatible. */
#define PCRE_CONFIG_UTF8 0 #define PCRE_CONFIG_UTF8 0
#define PCRE_CONFIG_NEWLINE 1 #define PCRE_CONFIG_NEWLINE 1
#define PCRE_CONFIG_LINK_SIZE 2 #define PCRE_CONFIG_LINK_SIZE 2
#define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD 3 #define PCRE_CONFIG_POSIX_MALLOC_THRESHOLD 3
#define PCRE_CONFIG_MATCH_LIMIT 4 #define PCRE_CONFIG_MATCH_LIMIT 4
#define PCRE_CONFIG_STACKRECURSE 5 #define PCRE_CONFIG_STACKRECURSE 5
#define PCRE_CONFIG_UNICODE_PROPERTIES 6 #define PCRE_CONFIG_UNICODE_PROPERTIES 6
#define PCRE_CONFIG_MATCH_LIMIT_RECURSION 7 #define PCRE_CONFIG_MATCH_LIMIT_RECURSION 7
#define PCRE_CONFIG_BSR 8 #define PCRE_CONFIG_BSR 8
#define PCRE_CONFIG_JIT 9 #define PCRE_CONFIG_JIT 9
#define PCRE_CONFIG_UTF16 10 #define PCRE_CONFIG_UTF16 10
#define PCRE_CONFIG_JITTARGET 11 #define PCRE_CONFIG_JITTARGET 11
#define PCRE_CONFIG_UTF32 12
#define PCRE_CONFIG_PARENS_LIMIT 13
/* Request types for pcre_study(). Do not re-arrange, in order to remain /* Request types for pcre_study(). Do not re-arrange, in order to remain
compatible. */ compatible. */
#define PCRE_STUDY_JIT_COMPILE 0x0001 #define PCRE_STUDY_JIT_COMPILE 0x0001
#define PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE 0x0002
#define PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE 0x0004
#define PCRE_STUDY_EXTRA_NEEDED 0x0008
/* Bit flags for the pcre[16|32]_extra structure. Do not re-arrange or rede fine /* Bit flags for the pcre[16]_extra structure. Do not re-arrange or redefin e
these bits, just add new ones on the end, in order to remain compatible. */ these bits, just add new ones on the end, in order to remain compatible. */
#define PCRE_EXTRA_STUDY_DATA 0x0001 #define PCRE_EXTRA_STUDY_DATA 0x0001
#define PCRE_EXTRA_MATCH_LIMIT 0x0002 #define PCRE_EXTRA_MATCH_LIMIT 0x0002
#define PCRE_EXTRA_CALLOUT_DATA 0x0004 #define PCRE_EXTRA_CALLOUT_DATA 0x0004
#define PCRE_EXTRA_TABLES 0x0008 #define PCRE_EXTRA_TABLES 0x0008
#define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0x0010 #define PCRE_EXTRA_MATCH_LIMIT_RECURSION 0x0010
#define PCRE_EXTRA_MARK 0x0020 #define PCRE_EXTRA_MARK 0x0020
#define PCRE_EXTRA_EXECUTABLE_JIT 0x0040 #define PCRE_EXTRA_EXECUTABLE_JIT 0x0040
/* Types */ /* Types */
struct real_pcre; /* declaration; the definition is private */ struct real_pcre; /* declaration; the definition is private */
typedef struct real_pcre pcre; typedef struct real_pcre pcre;
struct real_pcre16; /* declaration; the definition is private */ struct real_pcre16; /* declaration; the definition is private */
typedef struct real_pcre16 pcre16; typedef struct real_pcre16 pcre16;
struct real_pcre32; /* declaration; the definition is private
*/
typedef struct real_pcre32 pcre32;
struct real_pcre_jit_stack; /* declaration; the definition is private */ struct real_pcre_jit_stack; /* declaration; the definition is private */
typedef struct real_pcre_jit_stack pcre_jit_stack; typedef struct real_pcre_jit_stack pcre_jit_stack;
struct real_pcre16_jit_stack; /* declaration; the definition is private */ struct real_pcre16_jit_stack; /* declaration; the definition is private */
typedef struct real_pcre16_jit_stack pcre16_jit_stack; typedef struct real_pcre16_jit_stack pcre16_jit_stack;
struct real_pcre32_jit_stack; /* declaration; the definition is private
*/
typedef struct real_pcre32_jit_stack pcre32_jit_stack;
/* If PCRE is compiled with 16 bit character support, PCRE_UCHAR16 must con tain /* If PCRE is compiled with 16 bit character support, PCRE_UCHAR16 must con tain
a 16 bit wide signed data type. Otherwise it can be a dummy data type since a 16 bit wide signed data type. Otherwise it can be a dummy data type since
pcre16 functions are not implemented. There is a check for this in pcre_int ernal.h. */ pcre16 functions are not implemented. There is a check for this in pcre_int ernal.h. */
#ifndef PCRE_UCHAR16 #ifndef PCRE_UCHAR16
#define PCRE_UCHAR16 unsigned short #define PCRE_UCHAR16 unsigned short
#endif #endif
#ifndef PCRE_SPTR16 #ifndef PCRE_SPTR16
#define PCRE_SPTR16 const PCRE_UCHAR16 * #define PCRE_SPTR16 const PCRE_UCHAR16 *
#endif #endif
/* If PCRE is compiled with 32 bit character support, PCRE_UCHAR32 must con
tain
a 32 bit wide signed data type. Otherwise it can be a dummy data type since
pcre32 functions are not implemented. There is a check for this in pcre_int
ernal.h. */
#ifndef PCRE_UCHAR32
#define PCRE_UCHAR32 unsigned int
#endif
#ifndef PCRE_SPTR32
#define PCRE_SPTR32 const PCRE_UCHAR32 *
#endif
/* When PCRE is compiled as a C++ library, the subject pointer type can be /* When PCRE is compiled as a C++ library, the subject pointer type can be
replaced with a custom type. For conventional use, the public interface is a replaced with a custom type. For conventional use, the public interface is a
const char *. */ const char *. */
#ifndef PCRE_SPTR #ifndef PCRE_SPTR
#define PCRE_SPTR const char * #define PCRE_SPTR const char *
#endif #endif
/* The structure for passing additional data to pcre_exec(). This is define d in /* The structure for passing additional data to pcre_exec(). This is define d in
such as way as to be extensible. Always add new fields at the end, in order to such as way as to be extensible. Always add new fields at the end, in order to
skipping to change at line 400 skipping to change at line 331
unsigned long int flags; /* Bits for which fields are set */ unsigned long int flags; /* Bits for which fields are set */
void *study_data; /* Opaque data from pcre_study() */ void *study_data; /* Opaque data from pcre_study() */
unsigned long int match_limit; /* Maximum number of calls to match() */ unsigned long int match_limit; /* Maximum number of calls to match() */
void *callout_data; /* Data passed back in callouts */ void *callout_data; /* Data passed back in callouts */
const unsigned char *tables; /* Pointer to character tables */ const unsigned char *tables; /* Pointer to character tables */
unsigned long int match_limit_recursion; /* Max recursive calls to match( ) */ unsigned long int match_limit_recursion; /* Max recursive calls to match( ) */
PCRE_UCHAR16 **mark; /* For passing back a mark pointer */ PCRE_UCHAR16 **mark; /* For passing back a mark pointer */
void *executable_jit; /* Contains a pointer to a compiled jit c ode */ void *executable_jit; /* Contains a pointer to a compiled jit c ode */
} pcre16_extra; } pcre16_extra;
/* Same structure as above, but with 32 bit char pointers. */
typedef struct pcre32_extra {
unsigned long int flags; /* Bits for which fields are set */
void *study_data; /* Opaque data from pcre_study() */
unsigned long int match_limit; /* Maximum number of calls to match() */
void *callout_data; /* Data passed back in callouts */
const unsigned char *tables; /* Pointer to character tables */
unsigned long int match_limit_recursion; /* Max recursive calls to match(
) */
PCRE_UCHAR32 **mark; /* For passing back a mark pointer */
void *executable_jit; /* Contains a pointer to a compiled jit c
ode */
} pcre32_extra;
/* The structure for passing out data via the pcre_callout_function. We use a /* The structure for passing out data via the pcre_callout_function. We use a
structure so that new fields can be added on the end in future versions, structure so that new fields can be added on the end in future versions,
without changing the API of the function, thereby allowing old clients to w ork without changing the API of the function, thereby allowing old clients to w ork
without modification. */ without modification. */
typedef struct pcre_callout_block { typedef struct pcre_callout_block {
int version; /* Identifies version of block */ int version; /* Identifies version of block */
/* ------------------------ Version 0 ------------------------------- */ /* ------------------------ Version 0 ------------------------------- */
int callout_number; /* Number compiled into pattern */ int callout_number; /* Number compiled into pattern */
int *offset_vector; /* The offset vector */ int *offset_vector; /* The offset vector */
skipping to change at line 460 skipping to change at line 378
int capture_last; /* Most recently closed capture */ int capture_last; /* Most recently closed capture */
void *callout_data; /* Data passed in with the call */ void *callout_data; /* Data passed in with the call */
/* ------------------- Added for Version 1 -------------------------- */ /* ------------------- Added for Version 1 -------------------------- */
int pattern_position; /* Offset to next item in the pattern */ int pattern_position; /* Offset to next item in the pattern */
int next_item_length; /* Length of next item in the pattern */ int next_item_length; /* Length of next item in the pattern */
/* ------------------- Added for Version 2 -------------------------- */ /* ------------------- Added for Version 2 -------------------------- */
const PCRE_UCHAR16 *mark; /* Pointer to current mark or NULL */ const PCRE_UCHAR16 *mark; /* Pointer to current mark or NULL */
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
} pcre16_callout_block; } pcre16_callout_block;
/* Same structure as above, but with 32 bit char pointers. */
typedef struct pcre32_callout_block {
int version; /* Identifies version of block */
/* ------------------------ Version 0 ------------------------------- */
int callout_number; /* Number compiled into pattern */
int *offset_vector; /* The offset vector */
PCRE_SPTR32 subject; /* The subject being matched */
int subject_length; /* The length of the subject */
int start_match; /* Offset to start of this match attempt
*/
int current_position; /* Where we currently are in the subject
*/
int capture_top; /* Max current capture */
int capture_last; /* Most recently closed capture */
void *callout_data; /* Data passed in with the call */
/* ------------------- Added for Version 1 -------------------------- */
int pattern_position; /* Offset to next item in the pattern */
int next_item_length; /* Length of next item in the pattern */
/* ------------------- Added for Version 2 -------------------------- */
const PCRE_UCHAR32 *mark; /* Pointer to current mark or NULL */
/* ------------------------------------------------------------------ */
} pcre32_callout_block;
/* Indirection for store get and free functions. These can be set to /* Indirection for store get and free functions. These can be set to
alternative malloc/free functions if required. Special ones are used in the alternative malloc/free functions if required. Special ones are used in the
non-recursive case for "frames". There is also an optional callout function non-recursive case for "frames". There is also an optional callout function
that is triggered by the (?) regex item. For Virtual Pascal, these definiti ons that is triggered by the (?) regex item. For Virtual Pascal, these definiti ons
have to take another form. */ have to take another form. */
#ifndef VPCOMPAT #ifndef VPCOMPAT
PCRE_EXP_DECL void *(*pcre_malloc)(size_t); PCRE_EXP_DECL void *(*pcre_malloc)(size_t);
PCRE_EXP_DECL void (*pcre_free)(void *); PCRE_EXP_DECL void (*pcre_free)(void *);
PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t); PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t);
PCRE_EXP_DECL void (*pcre_stack_free)(void *); PCRE_EXP_DECL void (*pcre_stack_free)(void *);
PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *); PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *);
PCRE_EXP_DECL int (*pcre_stack_guard)(void);
PCRE_EXP_DECL void *(*pcre16_malloc)(size_t); PCRE_EXP_DECL void *(*pcre16_malloc)(size_t);
PCRE_EXP_DECL void (*pcre16_free)(void *); PCRE_EXP_DECL void (*pcre16_free)(void *);
PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t); PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t);
PCRE_EXP_DECL void (*pcre16_stack_free)(void *); PCRE_EXP_DECL void (*pcre16_stack_free)(void *);
PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *); PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *);
PCRE_EXP_DECL int (*pcre16_stack_guard)(void);
PCRE_EXP_DECL void *(*pcre32_malloc)(size_t);
PCRE_EXP_DECL void (*pcre32_free)(void *);
PCRE_EXP_DECL void *(*pcre32_stack_malloc)(size_t);
PCRE_EXP_DECL void (*pcre32_stack_free)(void *);
PCRE_EXP_DECL int (*pcre32_callout)(pcre32_callout_block *);
PCRE_EXP_DECL int (*pcre32_stack_guard)(void);
#else /* VPCOMPAT */ #else /* VPCOMPAT */
PCRE_EXP_DECL void *pcre_malloc(size_t); PCRE_EXP_DECL void *pcre_malloc(size_t);
PCRE_EXP_DECL void pcre_free(void *); PCRE_EXP_DECL void pcre_free(void *);
PCRE_EXP_DECL void *pcre_stack_malloc(size_t); PCRE_EXP_DECL void *pcre_stack_malloc(size_t);
PCRE_EXP_DECL void pcre_stack_free(void *); PCRE_EXP_DECL void pcre_stack_free(void *);
PCRE_EXP_DECL int pcre_callout(pcre_callout_block *); PCRE_EXP_DECL int pcre_callout(pcre_callout_block *);
PCRE_EXP_DECL int pcre_stack_guard(void);
PCRE_EXP_DECL void *pcre16_malloc(size_t); PCRE_EXP_DECL void *pcre16_malloc(size_t);
PCRE_EXP_DECL void pcre16_free(void *); PCRE_EXP_DECL void pcre16_free(void *);
PCRE_EXP_DECL void *pcre16_stack_malloc(size_t); PCRE_EXP_DECL void *pcre16_stack_malloc(size_t);
PCRE_EXP_DECL void pcre16_stack_free(void *); PCRE_EXP_DECL void pcre16_stack_free(void *);
PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *); PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *);
PCRE_EXP_DECL int pcre16_stack_guard(void);
PCRE_EXP_DECL void *pcre32_malloc(size_t);
PCRE_EXP_DECL void pcre32_free(void *);
PCRE_EXP_DECL void *pcre32_stack_malloc(size_t);
PCRE_EXP_DECL void pcre32_stack_free(void *);
PCRE_EXP_DECL int pcre32_callout(pcre32_callout_block *);
PCRE_EXP_DECL int pcre32_stack_guard(void);
#endif /* VPCOMPAT */ #endif /* VPCOMPAT */
/* User defined callback which provides a stack just before the match start s. */ /* User defined callback which provides a stack just before the match start s. */
typedef pcre_jit_stack *(*pcre_jit_callback)(void *); typedef pcre_jit_stack *(*pcre_jit_callback)(void *);
typedef pcre16_jit_stack *(*pcre16_jit_callback)(void *); typedef pcre16_jit_stack *(*pcre16_jit_callback)(void *);
typedef pcre32_jit_stack *(*pcre32_jit_callback)(void *);
/* Exported PCRE functions */ /* Exported PCRE functions */
PCRE_EXP_DECL pcre *pcre_compile(const char *, int, const char **, int *, PCRE_EXP_DECL pcre *pcre_compile(const char *, int, const char **, int *,
const unsigned char *); const unsigned char *);
PCRE_EXP_DECL pcre16 *pcre16_compile(PCRE_SPTR16, int, const char **, int * , PCRE_EXP_DECL pcre16 *pcre16_compile(PCRE_SPTR16, int, const char **, int * ,
const unsigned char *); const unsigned char *);
PCRE_EXP_DECL pcre32 *pcre32_compile(PCRE_SPTR32, int, const char **, int *
,
const unsigned char *);
PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **, PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **,
int *, const unsigned char *); int *, const unsigned char *);
PCRE_EXP_DECL pcre16 *pcre16_compile2(PCRE_SPTR16, int, int *, const char * *, PCRE_EXP_DECL pcre16 *pcre16_compile2(PCRE_SPTR16, int, int *, const char * *,
int *, const unsigned char *); int *, const unsigned char *);
PCRE_EXP_DECL pcre32 *pcre32_compile2(PCRE_SPTR32, int, int *, const char *
*,
int *, const unsigned char *);
PCRE_EXP_DECL int pcre_config(int, void *); PCRE_EXP_DECL int pcre_config(int, void *);
PCRE_EXP_DECL int pcre16_config(int, void *); PCRE_EXP_DECL int pcre16_config(int, void *);
PCRE_EXP_DECL int pcre32_config(int, void *);
PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *, PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *,
int *, int, const char *, char *, int); int *, int, const char *, char *, int);
PCRE_EXP_DECL int pcre16_copy_named_substring(const pcre16 *, PCRE_SPTR16, PCRE_EXP_DECL int pcre16_copy_named_substring(const pcre16 *, PCRE_SPTR16,
int *, int, PCRE_SPTR16, PCRE_UCHAR16 *, int); int *, int, PCRE_SPTR16, PCRE_UCHAR16 *, int);
PCRE_EXP_DECL int pcre32_copy_named_substring(const pcre32 *, PCRE_SPTR32,
int *, int, PCRE_SPTR32, PCRE_UCHAR32 *, int);
PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int, PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int,
char *, int); char *, int);
PCRE_EXP_DECL int pcre16_copy_substring(PCRE_SPTR16, int *, int, int, PCRE_EXP_DECL int pcre16_copy_substring(PCRE_SPTR16, int *, int, int,
PCRE_UCHAR16 *, int); PCRE_UCHAR16 *, int);
PCRE_EXP_DECL int pcre32_copy_substring(PCRE_SPTR32, int *, int, int,
PCRE_UCHAR32 *, int);
PCRE_EXP_DECL int pcre_dfa_exec(const pcre *, const pcre_extra *, PCRE_EXP_DECL int pcre_dfa_exec(const pcre *, const pcre_extra *,
const char *, int, int, int, int *, int , int *, int); const char *, int, int, int, int *, int , int *, int);
PCRE_EXP_DECL int pcre16_dfa_exec(const pcre16 *, const pcre16_extra *, PCRE_EXP_DECL int pcre16_dfa_exec(const pcre16 *, const pcre16_extra *,
PCRE_SPTR16, int, int, int, int *, int , int *, int); PCRE_SPTR16, int, int, int, int *, int , int *, int);
PCRE_EXP_DECL int pcre32_dfa_exec(const pcre32 *, const pcre32_extra *,
PCRE_SPTR32, int, int, int, int *, int , int *, int);
PCRE_EXP_DECL int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR, PCRE_EXP_DECL int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR,
int, int, int, int *, int); int, int, int, int *, int);
PCRE_EXP_DECL int pcre16_exec(const pcre16 *, const pcre16_extra *, PCRE_EXP_DECL int pcre16_exec(const pcre16 *, const pcre16_extra *,
PCRE_SPTR16, int, int, int, int *, int); PCRE_SPTR16, int, int, int, int *, int);
PCRE_EXP_DECL int pcre32_exec(const pcre32 *, const pcre32_extra *,
PCRE_SPTR32, int, int, int, int *, int);
PCRE_EXP_DECL int pcre_jit_exec(const pcre *, const pcre_extra *,
PCRE_SPTR, int, int, int, int *, int,
pcre_jit_stack *);
PCRE_EXP_DECL int pcre16_jit_exec(const pcre16 *, const pcre16_extra *,
PCRE_SPTR16, int, int, int, int *, int,
pcre16_jit_stack *);
PCRE_EXP_DECL int pcre32_jit_exec(const pcre32 *, const pcre32_extra *,
PCRE_SPTR32, int, int, int, int *, int,
pcre32_jit_stack *);
PCRE_EXP_DECL void pcre_free_substring(const char *); PCRE_EXP_DECL void pcre_free_substring(const char *);
PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16); PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16);
PCRE_EXP_DECL void pcre32_free_substring(PCRE_SPTR32);
PCRE_EXP_DECL void pcre_free_substring_list(const char **); PCRE_EXP_DECL void pcre_free_substring_list(const char **);
PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *); PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *);
PCRE_EXP_DECL void pcre32_free_substring_list(PCRE_SPTR32 *);
PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_extra *, int, PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_extra *, int,
void *); void *);
PCRE_EXP_DECL int pcre16_fullinfo(const pcre16 *, const pcre16_extra *, in t, PCRE_EXP_DECL int pcre16_fullinfo(const pcre16 *, const pcre16_extra *, in t,
void *); void *);
PCRE_EXP_DECL int pcre32_fullinfo(const pcre32 *, const pcre32_extra *, in
t,
void *);
PCRE_EXP_DECL int pcre_get_named_substring(const pcre *, const char *, PCRE_EXP_DECL int pcre_get_named_substring(const pcre *, const char *,
int *, int, const char *, const char **); int *, int, const char *, const char **);
PCRE_EXP_DECL int pcre16_get_named_substring(const pcre16 *, PCRE_SPTR16, PCRE_EXP_DECL int pcre16_get_named_substring(const pcre16 *, PCRE_SPTR16,
int *, int, PCRE_SPTR16, PCRE_SPTR16 *); int *, int, PCRE_SPTR16, PCRE_SPTR16 *);
PCRE_EXP_DECL int pcre32_get_named_substring(const pcre32 *, PCRE_SPTR32,
int *, int, PCRE_SPTR32, PCRE_SPTR32 *);
PCRE_EXP_DECL int pcre_get_stringnumber(const pcre *, const char *); PCRE_EXP_DECL int pcre_get_stringnumber(const pcre *, const char *);
PCRE_EXP_DECL int pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16); PCRE_EXP_DECL int pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16);
PCRE_EXP_DECL int pcre32_get_stringnumber(const pcre32 *, PCRE_SPTR32);
PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *, PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *,
char **, char **); char **, char **);
PCRE_EXP_DECL int pcre16_get_stringtable_entries(const pcre16 *, PCRE_SPTR 16, PCRE_EXP_DECL int pcre16_get_stringtable_entries(const pcre16 *, PCRE_SPTR 16,
PCRE_UCHAR16 **, PCRE_UCHAR16 **); PCRE_UCHAR16 **, PCRE_UCHAR16 **);
PCRE_EXP_DECL int pcre32_get_stringtable_entries(const pcre32 *, PCRE_SPTR
32,
PCRE_UCHAR32 **, PCRE_UCHAR32 **);
PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int, PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int,
const char **); const char **);
PCRE_EXP_DECL int pcre16_get_substring(PCRE_SPTR16, int *, int, int, PCRE_EXP_DECL int pcre16_get_substring(PCRE_SPTR16, int *, int, int,
PCRE_SPTR16 *); PCRE_SPTR16 *);
PCRE_EXP_DECL int pcre32_get_substring(PCRE_SPTR32, int *, int, int,
PCRE_SPTR32 *);
PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int, PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int,
const char ***); const char ***);
PCRE_EXP_DECL int pcre16_get_substring_list(PCRE_SPTR16, int *, int, PCRE_EXP_DECL int pcre16_get_substring_list(PCRE_SPTR16, int *, int,
PCRE_SPTR16 **); PCRE_SPTR16 **);
PCRE_EXP_DECL int pcre32_get_substring_list(PCRE_SPTR32, int *, int,
PCRE_SPTR32 **);
PCRE_EXP_DECL const unsigned char *pcre_maketables(void); PCRE_EXP_DECL const unsigned char *pcre_maketables(void);
PCRE_EXP_DECL const unsigned char *pcre16_maketables(void); PCRE_EXP_DECL const unsigned char *pcre16_maketables(void);
PCRE_EXP_DECL const unsigned char *pcre32_maketables(void);
PCRE_EXP_DECL int pcre_refcount(pcre *, int); PCRE_EXP_DECL int pcre_refcount(pcre *, int);
PCRE_EXP_DECL int pcre16_refcount(pcre16 *, int); PCRE_EXP_DECL int pcre16_refcount(pcre16 *, int);
PCRE_EXP_DECL int pcre32_refcount(pcre32 *, int);
PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **); PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **);
PCRE_EXP_DECL pcre16_extra *pcre16_study(const pcre16 *, int, const char ** ); PCRE_EXP_DECL pcre16_extra *pcre16_study(const pcre16 *, int, const char ** );
PCRE_EXP_DECL pcre32_extra *pcre32_study(const pcre32 *, int, const char ** );
PCRE_EXP_DECL void pcre_free_study(pcre_extra *); PCRE_EXP_DECL void pcre_free_study(pcre_extra *);
PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *); PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *);
PCRE_EXP_DECL void pcre32_free_study(pcre32_extra *);
PCRE_EXP_DECL const char *pcre_version(void); PCRE_EXP_DECL const char *pcre_version(void);
PCRE_EXP_DECL const char *pcre16_version(void); PCRE_EXP_DECL const char *pcre16_version(void);
PCRE_EXP_DECL const char *pcre32_version(void);
/* Utility functions for byte order swaps. */ /* Utility functions for byte order swaps. */
PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *, pcre_extra *, PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *, pcre_extra *,
const unsigned char *); const unsigned char *);
PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *, pcre16_extra *, PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *, pcre16_extra *,
const unsigned char *); const unsigned char *);
PCRE_EXP_DECL int pcre32_pattern_to_host_byte_order(pcre32 *, pcre32_extra
*,
const unsigned char *);
PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *, PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *,
PCRE_SPTR16, int, int *, int); PCRE_SPTR16, int, int *, int);
PCRE_EXP_DECL int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *,
PCRE_SPTR32, int, int *, int);
/* JIT compiler related functions. */ /* JIT compiler related functions. */
PCRE_EXP_DECL pcre_jit_stack *pcre_jit_stack_alloc(int, int); PCRE_EXP_DECL pcre_jit_stack *pcre_jit_stack_alloc(int, int);
PCRE_EXP_DECL pcre16_jit_stack *pcre16_jit_stack_alloc(int, int); PCRE_EXP_DECL pcre16_jit_stack *pcre16_jit_stack_alloc(int, int);
PCRE_EXP_DECL pcre32_jit_stack *pcre32_jit_stack_alloc(int, int);
PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *); PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *);
PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *); PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *);
PCRE_EXP_DECL void pcre32_jit_stack_free(pcre32_jit_stack *);
PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *, PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *,
pcre_jit_callback, void *); pcre_jit_callback, void *);
PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *, PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *,
pcre16_jit_callback, void *); pcre16_jit_callback, void *);
PCRE_EXP_DECL void pcre32_assign_jit_stack(pcre32_extra *,
pcre32_jit_callback, void *);
PCRE_EXP_DECL void pcre_jit_free_unused_memory(void);
PCRE_EXP_DECL void pcre16_jit_free_unused_memory(void);
PCRE_EXP_DECL void pcre32_jit_free_unused_memory(void);
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif #endif
#endif /* End of pcre.h */ #endif /* End of pcre.h */
 End of changes. 50 change blocks. 
259 lines changed or deleted 71 lines changed or added


 principal_name.h   principal_name.h 
skipping to change at line 32 skipping to change at line 32
namespace mongo { namespace mongo {
/** /**
* Representation of a name of a principal (authenticatable user) in a MongoDB system. * Representation of a name of a principal (authenticatable user) in a MongoDB system.
* *
* Consists of a "user name" part, and a "database name" part. * Consists of a "user name" part, and a "database name" part.
*/ */
class PrincipalName { class PrincipalName {
public: public:
PrincipalName() : _splitPoint(0) {} PrincipalName() : _splitPoint(0) {}
PrincipalName(const StringData& user, const StringData& dbname) : PrincipalName(const StringData& user, const StringData& dbname);
_fullName(user.toString() + "@" + dbname.toString()),
_splitPoint(user.size()) {
}
/** /**
* Gets the user-name part of a principal name. * Gets the user-name part of a principal name.
*/ */
StringData getUser() const { return StringData(_fullName).substr(0, _splitPoint); } StringData getUser() const { return StringData(_fullName).substr(0, _splitPoint); }
/** /**
* Gets the database name part of a principal name. * Gets the database name part of a principal name.
*/ */
StringData getDB() const { return StringData(_fullName).substr(_spl itPoint + 1); } StringData getDB() const { return StringData(_fullName).substr(_spl itPoint + 1); }
 End of changes. 1 change blocks. 
5 lines changed or deleted 1 lines changed or added


 processinfo.h   processinfo.h 
skipping to change at line 95 skipping to change at line 95
* Get the CPU architecture (e.g. x86, x86_64) * Get the CPU architecture (e.g. x86, x86_64)
*/ */
const string& getArch() const { return sysInfo().cpuArch; } const string& getArch() const { return sysInfo().cpuArch; }
/** /**
* Determine if NUMA is enabled (interleaved) for this process * Determine if NUMA is enabled (interleaved) for this process
*/ */
bool hasNumaEnabled() const { return sysInfo().hasNuma; } bool hasNumaEnabled() const { return sysInfo().hasNuma; }
/** /**
* Determine if file zeroing is necessary for newly allocated data
files.
*/
static bool isDataFileZeroingNeeded() { return systemInfo->fileZero
Needed; }
/**
* Get extra system stats * Get extra system stats
*/ */
void appendSystemDetails( BSONObjBuilder& details ) const { void appendSystemDetails( BSONObjBuilder& details ) const {
details.append( StringData("extra"), sysInfo()._extraStats.copy () ); details.append( StringData("extra"), sysInfo()._extraStats.copy () );
} }
/** /**
* Append platform-specific data to obj * Append platform-specific data to obj
*/ */
void getExtraInfo( BSONObjBuilder& info ); void getExtraInfo( BSONObjBuilder& info );
skipping to change at line 153 skipping to change at line 148
string osType; string osType;
string osName; string osName;
string osVersion; string osVersion;
unsigned addrSize; unsigned addrSize;
unsigned long long memSize; unsigned long long memSize;
unsigned numCores; unsigned numCores;
unsigned long long pageSize; unsigned long long pageSize;
string cpuArch; string cpuArch;
bool hasNuma; bool hasNuma;
BSONObj _extraStats; BSONObj _extraStats;
// This is an OS specific value, which determines whether files
should be zero-filled
// at allocation time in order to avoid Microsoft KB 2731284.
//
bool fileZeroNeeded;
SystemInfo() : SystemInfo() :
addrSize( 0 ), addrSize( 0 ),
memSize( 0 ), memSize( 0 ),
numCores( 0 ), numCores( 0 ),
pageSize( 0 ), pageSize( 0 ),
hasNuma( false ), hasNuma( false ) {
fileZeroNeeded (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; pid_t _pid;
static mongo::mutex _sysInfoLock; static mongo::mutex _sysInfoLock;
 End of changes. 3 change blocks. 
16 lines changed or deleted 1 lines changed or added


 progress_meter.h   progress_meter.h 
skipping to change at line 33 skipping to change at line 33
namespace mongo { namespace mongo {
class ProgressMeter : boost::noncopyable { class ProgressMeter : boost::noncopyable {
public: public:
ProgressMeter(unsigned long long total, ProgressMeter(unsigned long long total,
int secondsBetween = 3, int secondsBetween = 3,
int checkInterval = 100, int checkInterval = 100,
std::string units = "", std::string units = "",
std::string name = "Progress") std::string name = "Progress")
: _showTotal(true), : _units(units)
_units(units), , _name(name) {
_name(name) {
reset( total , secondsBetween , checkInterval ); reset( total , secondsBetween , checkInterval );
} }
ProgressMeter() : _active(0), _showTotal(true), _units(""), _name(" Progress") {} ProgressMeter() : _active(0), _units(""), _name("Progress") {}
// typically you do ProgressMeterHolder // typically you do ProgressMeterHolder
void reset( unsigned long long total , int secondsBetween = 3 , int checkInterval = 100 ); void reset( unsigned long long total , int secondsBetween = 3 , int checkInterval = 100 );
void finished() { _active = 0; } void finished() { _active = 0; }
bool isActive() const { return _active; } bool isActive() const { return _active; }
/** /**
* @param n how far along we are relative to the total # we set in CurOp::setMessage * @param n how far along we are relative to the total # we set in CurOp::setMessage
* @return if row was printed * @return if row was printed
skipping to change at line 69 skipping to change at line 68
void setTotalWhileRunning( unsigned long long total ) { void setTotalWhileRunning( unsigned long long total ) {
_total = total; _total = total;
} }
unsigned long long done() const { return _done; } unsigned long long done() const { return _done; }
unsigned long long hits() const { return _hits; } unsigned long long hits() const { return _hits; }
unsigned long long total() const { return _total; } unsigned long long total() const { return _total; }
void showTotal(bool doShow) {
_showTotal = doShow;
}
std::string toString() const; std::string toString() const;
bool operator==( const ProgressMeter& other ) const { return this = = &other; } bool operator==( const ProgressMeter& other ) const { return this = = &other; }
private: private:
bool _active; bool _active;
unsigned long long _total; unsigned long long _total;
bool _showTotal;
int _secondsBetween; int _secondsBetween;
int _checkInterval; int _checkInterval;
unsigned long long _done; unsigned long long _done;
unsigned long long _hits; unsigned long long _hits;
int _lastTime; int _lastTime;
std::string _units; std::string _units;
std::string _name; std::string _name;
}; };
 End of changes. 4 change blocks. 
9 lines changed or deleted 3 lines changed or added


 projection.h   projection.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 "mongo/pch.h" #include "mongo/pch.h"
#include "mongo/util/string_map.h" #include "mongo/util/string_map.h"
#include "jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/matcher.h"
namespace mongo { namespace mongo {
// fwd decls
class Matcher;
class MatchDetails;
/** /**
* given a document and a projection specification * given a document and a projection specification
* can transform the document * can transform the document
* currently supports specifying which fields and $slice * currently supports specifying which fields and $slice
*/ */
class Projection { class Projection {
public: public:
class KeyOnly { class KeyOnly {
public: public:
 End of changes. 2 change blocks. 
5 lines changed or deleted 2 lines changed or added


 query.h   query.h 
skipping to change at line 35 skipping to change at line 35
#include "../diskloc.h" #include "../diskloc.h"
#include "../explain.h" #include "../explain.h"
#include "../../s/d_chunk_manager.h" #include "../../s/d_chunk_manager.h"
// struct QueryOptions, QueryResult, QueryResultFlags in: // struct QueryOptions, QueryResult, QueryResultFlags in:
namespace mongo { namespace mongo {
class ParsedQuery; class ParsedQuery;
class QueryOptimizerCursor; class QueryOptimizerCursor;
class QueryPlanSummary; struct QueryPlanSummary;
extern const int32_t MaxBytesToReturnToClientAtOnce;
/** /**
* Return a batch of results from a client OP_GET_MORE request. * Return a batch of results from a client OP_GET_MORE request.
* 'cursorid' - The id of the cursor producing results. * 'cursorid' - The id of the cursor producing results.
* 'isCursorAuthorized' - Set to true after a cursor with id 'cursorid' is authorized for use. * 'isCursorAuthorized' - Set to true after a cursor with id 'cursorid' is authorized for use.
*/ */
QueryResult* processGetMore(const char* ns, QueryResult* processGetMore(const char* ns,
int ntoreturn, int ntoreturn,
long long cursorid, long long cursorid,
CurOp& op, CurOp& op,
 End of changes. 1 change blocks. 
1 lines changed or deleted 3 lines changed or added


 queryoptimizercursor.h   queryoptimizercursor.h 
// @file queryoptimizercursor.h - Interface for a cursor interleaving multi
ple candidate cursors.
/** /**
* Copyright (C) 2011 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,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Lice nse * You should have received a copy of the GNU Affero General Public Lice nse
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "cursor.h" #include "cursor.h"
#include "diskloc.h"
namespace mongo { namespace mongo {
class QueryPlan;
class CandidatePlanCharacter; class CandidatePlanCharacter;
/**
* An interface for policies overriding the query optimizer's default b
ehavior for selecting
* query plans and creating cursors.
*/
class QueryPlanSelectionPolicy {
public:
virtual ~QueryPlanSelectionPolicy() {}
virtual string name() const = 0;
virtual bool permitOptimalNaturalPlan() const { return true; }
virtual bool permitOptimalIdPlan() const { return true; }
virtual bool permitPlan( const QueryPlan &plan ) const { return tru
e; }
virtual BSONObj planHint( const StringData& ns ) const { return BSO
NObj(); }
/**
* @return true to request that a created Cursor provide a matcher(
). If false, the
* Cursor's matcher() may be NULL if the Cursor can perform accurat
e query matching
* internally using a non Matcher mechanism. One case where a Matc
her might be requested
* even though not strictly necessary to select matching documents
is if metadata about
* matches may be requested using MatchDetails. NOTE This is a hin
t that the Cursor use a
* Matcher, but the hint may be ignored. In some cases the Cursor
may not provide
* a Matcher even if 'requestMatcher' is true.
*/
virtual bool requestMatcher() const { return true; }
/**
* @return true to request creating an IntervalBtreeCursor rather t
han a BtreeCursor when
* possible. An IntervalBtreeCursor is optimized for counting the
number of documents
* between two endpoints in a btree. NOTE This is a hint to create
an interval cursor, but
* the hint may be ignored. In some cases a different cursor type
may be created even if
* 'requestIntervalCursor' is true.
*/
virtual bool requestIntervalCursor() const { return false; }
/** Allow any query plan selection, permitting the query optimizer'
s default behavior. */
static const QueryPlanSelectionPolicy &any();
/** Prevent unindexed collection scans. */
static const QueryPlanSelectionPolicy &indexOnly();
/**
* Generally hints to use the _id plan, falling back to the $natura
l plan. However, the
* $natural plan will always be used if optimal for the query.
*/
static const QueryPlanSelectionPolicy &idElseNatural();
private:
class Any;
static Any __any;
class IndexOnly;
static IndexOnly __indexOnly;
class IdElseNatural;
static IdElseNatural __idElseNatural;
};
class QueryPlanSelectionPolicy::Any : public QueryPlanSelectionPolicy {
public:
virtual string name() const { return "any"; }
};
class QueryPlanSelectionPolicy::IndexOnly : public QueryPlanSelectionPo
licy {
public:
virtual string name() const { return "indexOnly"; }
virtual bool permitOptimalNaturalPlan() const { return false; }
virtual bool permitPlan( const QueryPlan &plan ) const;
};
class QueryPlanSelectionPolicy::IdElseNatural : public QueryPlanSelecti
onPolicy {
public:
virtual string name() const { return "idElseNatural"; }
virtual bool permitPlan( const QueryPlan &plan ) const;
virtual BSONObj planHint( const StringData& ns ) const;
};
class FieldRangeSet;
class ExplainQueryInfo; class ExplainQueryInfo;
class FieldRangeSet;
/** /**
* Adds functionality to Cursor for running multiple plans, running out of order plans, * Adds functionality to Cursor for running multiple plans, running out of order plans,
* utilizing covered indexes, and generating explain output. * utilizing covered indexes, and generating explain output.
*/ */
class QueryOptimizerCursor : public Cursor { class QueryOptimizerCursor : public Cursor {
public: public:
/** Candidate plans for the query before it begins running. */ /** Candidate plans for the query before it begins running. */
virtual CandidatePlanCharacter initialCandidatePlans() const = 0; virtual CandidatePlanCharacter initialCandidatePlans() const = 0;
 End of changes. 5 change blocks. 
97 lines changed or deleted 1 lines changed or added


 queryoptimizercursorimpl.h   queryoptimizercursorimpl.h 
// @file queryoptimizercursorimpl.h - A cursor interleaving multiple candid
ate cursors.
/** /**
* Copyright (C) 2011 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,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Lice nse * You should have received a copy of the GNU Affero General Public Lice nse
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/db/queryutil.h" #include "mongo/db/parsed_query.h"
#include "mongo/db/queryoptimizercursor.h" #include "mongo/db/queryoptimizercursor.h"
#include "mongo/db/querypattern.h" #include "mongo/db/querypattern.h"
namespace mongo { namespace mongo {
class MultiCursor; class MultiCursor;
class MultiPlanScanner; class MultiPlanScanner;
class QueryPlanRunner; class QueryPlanRunner;
class QueryPlanSummary; class QueryPlanSelectionPolicy;
struct QueryPlanSummary;
/** Dup tracking class, optimizing one common case with small set and f ew initial reads. */ /** Dup tracking class, optimizing one common case with small set and f ew initial reads. */
class SmallDupSet { class SmallDupSet {
public: public:
SmallDupSet() : _accesses() { SmallDupSet() : _accesses() {
_vec.reserve( 250 ); _vec.reserve( 250 );
} }
/** @return true if @param 'loc' already added to the set, false if adding to the set in this call. */ /** @return true if @param 'loc' already added to the set, false if adding to the set in this call. */
bool getsetdup( const DiskLoc &loc ) { bool getsetdup( const DiskLoc &loc ) {
access(); access();
skipping to change at line 277 skipping to change at line 276
bool snapshot() const { return _parsedQuery && _parsedQuery->isSnap shot(); } bool snapshot() const { return _parsedQuery && _parsedQuery->isSnap shot(); }
bool explain() const { return _parsedQuery && _parsedQuery->isExpla in(); } bool explain() const { return _parsedQuery && _parsedQuery->isExpla in(); }
BSONObj min() const { return _parsedQuery ? _parsedQuery->getMin() : BSONObj(); } BSONObj min() const { return _parsedQuery ? _parsedQuery->getMin() : BSONObj(); }
BSONObj max() const { return _parsedQuery ? _parsedQuery->getMax() : BSONObj(); } BSONObj max() const { return _parsedQuery ? _parsedQuery->getMax() : BSONObj(); }
bool hasFields() const { return _parsedQuery && _parsedQuery->getFi eldPtr(); } bool hasFields() const { return _parsedQuery && _parsedQuery->getFi eldPtr(); }
bool isOrderRequired() const { return _requireOrder; } bool isOrderRequired() const { return _requireOrder; }
bool mayShortcutQueryOptimizer() const { bool mayShortcutQueryOptimizer() const {
return min().isEmpty() && max().isEmpty() && !hasFields() && _a rgumentsHint.isEmpty(); return min().isEmpty() && max().isEmpty() && !hasFields() && _a rgumentsHint.isEmpty();
} }
BSONObj hint() const { BSONObj hint() const;
return _argumentsHint.isEmpty() ? _planPolicy.planHint( _ns ) :
_argumentsHint;
}
void setArgumentsHint(); void setArgumentsHint();
shared_ptr<Cursor> shortcutCursor() const; shared_ptr<Cursor> shortcutCursor() const;
void setMultiPlanScanner(); void setMultiPlanScanner();
shared_ptr<Cursor> singlePlanCursor(); shared_ptr<Cursor> singlePlanCursor();
const StringData _ns; const StringData _ns;
BSONObj _query; BSONObj _query;
BSONObj _order; BSONObj _order;
const QueryPlanSelectionPolicy &_planPolicy; const QueryPlanSelectionPolicy &_planPolicy;
 End of changes. 4 change blocks. 
9 lines changed or deleted 4 lines changed or added


 queryutil.h   queryutil.h 
// @file queryutil.h - Utility classes representing ranges of valid BSONEle
ment values for a query.
/* 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 "jsobj.h" #include "jsobj.h"
#include "indexkey.h" #include "mongo/db/index/btree_key_generator.h"
#include "projection.h"
#include "mongo/client/dbclientinterface.h"
namespace mongo { namespace mongo {
extern const int MaxBytesToReturnToClientAtOnce;
//maximum number of intervals produced by $in queries. //maximum number of intervals produced by $in queries.
static const unsigned MAX_IN_COMBINATIONS = 4000000; static const unsigned MAX_IN_COMBINATIONS = 4000000;
/* This is for languages whose "objects" are not well ordered (JSON is
well ordered).
[ { a : ... } , { b : ... } ] -> { a : ..., b : ... }
*/
inline BSONObj transformOrderFromArrayFormat(BSONObj order) {
/* note: this is slow, but that is ok as order will have very few p
ieces */
BSONObjBuilder b;
char p[2] = "0";
while ( 1 ) {
BSONObj j = order.getObjectField(p);
if ( j.isEmpty() )
break;
BSONElement e = j.firstElement();
uassert( 10102 , "bad order array", !e.eoo());
uassert( 10103 , "bad order array [2]", e.isNumber());
b.append(e);
(*p)++;
uassert( 10104 , "too many ordering elements", *p <= '9');
}
return b.obj();
}
class QueryMessage;
/**
* this represents a total user query
* includes fields from the query message, both possible query levels
* parses everything up front
*/
class ParsedQuery : boost::noncopyable {
public:
ParsedQuery( QueryMessage& qm );
ParsedQuery( const char* ns , int ntoskip , int ntoreturn , int que
ryoptions , const BSONObj& query , const BSONObj& fields )
: _ns( ns ) , _ntoskip( ntoskip ) , _ntoreturn( ntoreturn ) , _opti
ons( queryoptions ) {
init( query );
initFields( fields );
}
const char * ns() const { return _ns; }
bool isLocalDB() const { return strncmp(_ns, "local.", 6) == 0; }
const BSONObj& getFilter() const { return _filter; }
Projection* getFields() const { return _fields.get(); }
shared_ptr<Projection> getFieldPtr() const { return _fields; }
int getSkip() const { return _ntoskip; }
int getNumToReturn() const { return _ntoreturn; }
bool wantMore() const { return _wantMore; }
int getOptions() const { return _options; }
bool hasOption( int x ) const { return ( x & _options ) != 0; }
bool hasReadPref() const { return _hasReadPref; }
bool isExplain() const { return _explain; }
bool isSnapshot() const { return _snapshot; }
bool returnKey() const { return _returnKey; }
bool showDiskLoc() const { return _showDiskLoc; }
const BSONObj& getMin() const { return _min; }
const BSONObj& getMax() const { return _max; }
const BSONObj& getOrder() const { return _order; }
const BSONObj& getHint() const { return _hint; }
int getMaxScan() const { return _maxScan; }
bool couldBeCommand() const {
/* we assume you are using findOne() for running a cmd... */
return _ntoreturn == 1 && strstr( _ns , ".$cmd" );
}
bool hasIndexSpecifier() const {
return ! _hint.isEmpty() || ! _min.isEmpty() || ! _max.isEmpty(
);
}
/* if ntoreturn is zero, we return up to 101 objects. on the subse
quent getmore, there
is only a size limit. The idea is that on a find() where one does
n't use much results,
we don't return much, but once getmore kicks in, we start pushing
significant quantities.
The n limit (vs. size) is important when someone fetches only one
small field from big
objects, which causes massive scanning server-side.
*/
bool enoughForFirstBatch( int n , int len ) const {
if ( _ntoreturn == 0 )
return ( len > 1024 * 1024 ) || n >= 101;
return n >= _ntoreturn || len > MaxBytesToReturnToClientAtOnce;
}
bool enough( int n ) const {
if ( _ntoreturn == 0 )
return false;
return n >= _ntoreturn;
}
bool enoughForExplain( long long n ) const {
if ( _wantMore || _ntoreturn == 0 ) {
return false;
}
return n >= _ntoreturn;
}
private:
void init( const BSONObj& q ) {
_reset();
uassert( 10105 , "bad skip value in query", _ntoskip >= 0);
if ( _ntoreturn < 0 ) {
/* _ntoreturn greater than zero is simply a hint on how man
y objects to send back per
"cursor batch".
A negative number indicates a hard limit.
*/
_wantMore = false;
_ntoreturn = -_ntoreturn;
}
BSONElement e = q["query"];
if ( ! e.isABSONObj() )
e = q["$query"];
if ( e.isABSONObj() ) {
_filter = e.embeddedObject();
_initTop( q );
}
else {
_filter = q;
}
_filter = _filter.getOwned();
_hasReadPref = q.hasField(Query::ReadPrefField.name());
}
void _reset() {
_wantMore = true;
_explain = false;
_snapshot = false;
_returnKey = false;
_showDiskLoc = false;
_maxScan = 0;
}
void _initTop( const BSONObj& top ) {
BSONObjIterator i( top );
while ( i.more() ) {
BSONElement e = i.next();
const char * name = e.fieldName();
if ( strcmp( "$orderby" , name ) == 0 ||
strcmp( "orderby" , name ) == 0 ) {
if ( e.type() == Object ) {
_order = e.embeddedObject();
}
else if ( e.type() == Array ) {
_order = transformOrderFromArrayFormat( _order );
}
else {
uasserted(13513, "sort must be an object or array")
;
}
continue;
}
if( *name == '$' ) {
name++;
if ( strcmp( "explain" , name ) == 0 )
_explain = e.trueValue();
else if ( strcmp( "snapshot" , name ) == 0 )
_snapshot = e.trueValue();
else if ( strcmp( "min" , name ) == 0 )
_min = e.embeddedObject();
else if ( strcmp( "max" , name ) == 0 )
_max = e.embeddedObject();
else if ( strcmp( "hint" , name ) == 0 )
_hint = e.wrap();
else if ( strcmp( "returnKey" , name ) == 0 )
_returnKey = e.trueValue();
else if ( strcmp( "maxScan" , name ) == 0 )
_maxScan = e.numberInt();
else if ( strcmp( "showDiskLoc" , name ) == 0 )
_showDiskLoc = e.trueValue();
else if ( strcmp( "comment" , name ) == 0 ) {
; // no-op
}
}
}
if ( _snapshot ) {
uassert( 12001 , "E12001 can't sort with $snapshot", _order
.isEmpty() );
uassert( 12002 , "E12002 can't use hint with $snapshot", _h
int.isEmpty() );
}
}
void initFields( const BSONObj& fields ) {
if ( fields.isEmpty() )
return;
_fields.reset( new Projection() );
_fields->init( fields.getOwned() );
}
const char * const _ns;
const int _ntoskip;
int _ntoreturn;
BSONObj _filter;
BSONObj _order;
const int _options;
shared_ptr< Projection > _fields;
bool _wantMore;
bool _explain;
bool _snapshot;
bool _returnKey;
bool _showDiskLoc;
bool _hasReadPref;
BSONObj _min;
BSONObj _max;
BSONObj _hint;
int _maxScan;
};
/** /**
* One side of an interval of BSONElements, defined by a value and a bo olean indicating if the * One side of an interval of BSONElements, defined by a value and a bo olean indicating if the
* interval includes the value. * interval includes the value.
*/ */
struct FieldBound { struct FieldBound {
BSONElement _bound; BSONElement _bound;
bool _inclusive; bool _inclusive;
bool operator==( const FieldBound &other ) const { bool operator==( const FieldBound &other ) const {
return _bound.woCompare( other._bound ) == 0 && return _bound.woCompare( other._bound ) == 0 &&
_inclusive == other._inclusive; _inclusive == other._inclusive;
skipping to change at line 645 skipping to change at line 423
:_singleKey( singleKey ), _multiKey( multiKey ) {} :_singleKey( singleKey ), _multiKey( multiKey ) {}
void assertValidIndex( const NamespaceDetails *d, int idxNo ) const ; void assertValidIndex( const NamespaceDetails *d, int idxNo ) const ;
void assertValidIndexOrNoIndex( const NamespaceDetails *d, int idxN o ) const; void assertValidIndexOrNoIndex( const NamespaceDetails *d, int idxN o ) const;
/** matchPossibleForIndex() must be true. */ /** matchPossibleForIndex() must be true. */
FieldRangeSet _singleKey; FieldRangeSet _singleKey;
FieldRangeSet _multiKey; FieldRangeSet _multiKey;
friend class OrRangeGenerator; friend class OrRangeGenerator;
friend struct QueryUtilIndexed; friend struct QueryUtilIndexed;
}; };
class IndexSpec;
/** /**
* An ordered list of fields and their FieldRanges, corresponding to va lid * An ordered list of fields and their FieldRanges, corresponding to va lid
* index keys for a given index spec. * index keys for a given index spec.
*/ */
class FieldRangeVector { class FieldRangeVector {
public: public:
/** /**
* @param frs The valid ranges for all fields, as defined by the qu ery spec. None of the * @param frs The valid ranges for all fields, as defined by the qu ery spec. None of the
* fields in indexSpec may be empty() ranges of frs. * fields in indexSpec may be empty() ranges of frs.
* @param indexSpec The index spec (key pattern and info) * @param indexSpec The index spec (key pattern and info)
* @param direction The direction of index traversal * @param direction The direction of index traversal
*/ */
FieldRangeVector( const FieldRangeSet &frs, const IndexSpec &indexS pec, int direction ); FieldRangeVector( const FieldRangeSet &frs, BSONObj keyPattern, int direction );
/** /**
* Methods for identifying compound start and end btree bounds desc ribing this field range * Methods for identifying compound start and end btree bounds desc ribing this field range
* vector. * vector.
* *
* A FieldRangeVector contains the FieldRange bounds for every fiel d of an index. A * A FieldRangeVector contains the FieldRange bounds for every fiel d of an index. A
* FieldRangeVectorIterator may be used to efficiently search for b tree keys within these * FieldRangeVectorIterator may be used to efficiently search for b tree keys within these
* bounds. Alternatively, a single compound field interval of the btree may be scanned, * bounds. Alternatively, a single compound field interval of the btree may be scanned,
* between a compound field start point and end point. If isSingle Interval() is true then * between a compound field start point and end point. If isSingle Interval() is true then
* the interval between the start and end points will be an exact d escription of this * the interval between the start and end points will be an exact d escription of this
skipping to change at line 725 skipping to change at line 501
/** @return true if the endKey() bound is inclusive. */ /** @return true if the endKey() bound is inclusive. */
bool endKeyInclusive() const; bool endKeyInclusive() const;
/** @return the number of index ranges represented by 'this' */ /** @return the number of index ranges represented by 'this' */
unsigned size() const; unsigned size() const;
/** @return a client readable representation of 'this' */ /** @return a client readable representation of 'this' */
BSONObj obj() const; BSONObj obj() const;
const IndexSpec& getSpec(){ return _indexSpec; }
/** /**
* @return true iff the provided document matches valid ranges on a ll * @return true iff the provided document matches valid ranges on a ll
* of this FieldRangeVector's fields, which is the case iff this do cument * of this FieldRangeVector's fields, which is the case iff this do cument
* would be returned while scanning the index corresponding to this * would be returned while scanning the index corresponding to this
* FieldRangeVector. This function is used for $or clause deduping . * FieldRangeVector. This function is used for $or clause deduping .
*/ */
bool matches( const BSONObj &obj ) const; bool matches( const BSONObj &obj ) const;
/** /**
* @return true if all values in the provided index key are contain ed within the field * @return true if all values in the provided index key are contain ed within the field
skipping to change at line 767 skipping to change at line 541
* FieldRangeVector(). * FieldRangeVector().
*/ */
bool hasAllIndexedRanges() const { return _hasAllIndexedRanges; } bool hasAllIndexedRanges() const { return _hasAllIndexedRanges; }
string toString() const; string toString() const;
private: private:
int matchingLowElement( const BSONElement &e, int i, bool direction , bool &lowEquality ) const; int matchingLowElement( const BSONElement &e, int i, bool direction , bool &lowEquality ) const;
bool matchesElement( const BSONElement &e, int i, bool direction ) const; bool matchesElement( const BSONElement &e, int i, bool direction ) const;
vector<FieldRange> _ranges; vector<FieldRange> _ranges;
const IndexSpec _indexSpec; BSONObj _keyPattern;
int _direction; int _direction;
vector<BSONObj> _queries; // make sure mem owned vector<BSONObj> _queries; // make sure mem owned
bool _hasAllIndexedRanges; bool _hasAllIndexedRanges;
friend class FieldRangeVectorIterator; friend class FieldRangeVectorIterator;
vector<const char*> _fieldNames;
vector<BSONElement> _fixed;
// See FieldRangeVector::matches for comment on key generation.
scoped_ptr<BtreeKeyGenerator> _keyGenerator;
}; };
/** /**
* Helper class for iterating through an ordered representation of keys * Helper class for iterating through an ordered representation of keys
* to find those keys that match a specified FieldRangeVector. * to find those keys that match a specified FieldRangeVector.
*/ */
class FieldRangeVectorIterator { class FieldRangeVectorIterator {
public: public:
/** /**
* @param v - a FieldRangeVector representing matching keys. * @param v - a FieldRangeVector representing matching keys.
 End of changes. 9 change blocks. 
243 lines changed or deleted 8 lines changed or added


 race.h   race.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 "../goodies.h" // printStackTrace #include "mongo/util/concurrency/mutexdebugger.h"
#include "mutexdebugger.h" #include "mongo/util/goodies.h" // printStackTrace
#include "mongo/util/stacktrace.h" #include "mongo/util/stacktrace.h"
namespace mongo { namespace mongo {
namespace race { namespace race {
#ifdef _WIN32 #ifdef _WIN32
typedef unsigned threadId_t; typedef unsigned threadId_t;
#else #else
typedef pthread_t threadId_t; typedef pthread_t threadId_t;
 End of changes. 1 change blocks. 
2 lines changed or deleted 2 lines changed or added


 restapi.h   restapi.h 
skipping to change at line 22 skipping to change at line 22
* 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 "../util/admin_access.h" #include <string>
#include "mongo/db/jsobj.h"
#include "mongo/util/admin_access.h"
namespace mongo { namespace mongo {
class RestAdminAccess : public AdminAccess { class RestAdminAccess : public AdminAccess {
public: public:
virtual ~RestAdminAccess() { } virtual ~RestAdminAccess() { }
virtual bool haveAdminUsers() const; virtual bool haveAdminUsers() const;
virtual BSONObj getAdminUser( const string& username ) const; virtual BSONObj getAdminUser( const std::string& username ) const;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 2 change blocks. 
2 lines changed or deleted 5 lines changed or added


 rs.h   rs.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 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/commands.h" #include "mongo/db/commands.h"
#include "mongo/db/index.h" #include "mongo/db/index.h"
#include "mongo/db/oplog.h" #include "mongo/db/repl/oplogreader.h"
#include "mongo/db/oplogreader.h" #include "mongo/db/repl/optime.h"
#include "mongo/db/repl/rs_config.h" #include "mongo/db/repl/rs_config.h"
#include "mongo/db/repl/rs_exception.h" #include "mongo/db/repl/rs_exception.h"
#include "mongo/db/repl/rs_member.h" #include "mongo/db/repl/rs_member.h"
#include "mongo/db/repl/rs_optime.h"
#include "mongo/db/repl/rs_sync.h" #include "mongo/db/repl/rs_sync.h"
#include "mongo/util/concurrency/list.h" #include "mongo/util/concurrency/list.h"
#include "mongo/util/concurrency/msg.h" #include "mongo/util/concurrency/msg.h"
#include "mongo/util/concurrency/thread_pool.h" #include "mongo/util/concurrency/thread_pool.h"
#include "mongo/util/concurrency/value.h" #include "mongo/util/concurrency/value.h"
#include "mongo/util/net/hostandport.h" #include "mongo/util/net/hostandport.h"
/** /**
* Order of Events * Order of Events
* *
skipping to change at line 53 skipping to change at line 52
* theReplSet's constructor changes the replica set's state to RS_STARTUP, * theReplSet's constructor changes the replica set's state to RS_STARTUP,
* starts the replica set manager, and loads the config (if the replica set * starts the replica set manager, and loads the config (if the replica set
* has been initialized). * has been initialized).
*/ */
namespace mongo { namespace mongo {
class Cloner; class Cloner;
class DBClientConnection; class DBClientConnection;
struct HowToFixUp; struct HowToFixUp;
class OplogReader;
class ReplSetImpl; class ReplSetImpl;
struct Target; struct Target;
extern bool replSet; // true if using repl sets extern bool replSet; // true if using repl sets
extern class ReplSet *theReplSet; // null until initialized extern class ReplSet *theReplSet; // null until initialized
extern Tee *rsLog; extern Tee *rsLog;
class ReplSetCmdline;
// Main entry point for replica sets
void startReplSets(ReplSetCmdline *replSetCmdline);
/* member of a replica set */ /* member of a replica set */
class Member : public List1<Member>::Base { class Member : public List1<Member>::Base {
private: private:
~Member(); // intentionally unimplemented as should never be called -- see List1<>::Base. ~Member(); // intentionally unimplemented as should never be called -- see List1<>::Base.
Member(const Member&); Member(const Member&);
public: public:
Member(HostAndPort h, unsigned ord, const ReplSetConfig::MemberCfg *c, bool self); Member(HostAndPort h, unsigned ord, const ReplSetConfig::MemberCfg *c, bool self);
string fullName() const { return h().toString(); } string fullName() const { return h().toString(); }
skipping to change at line 335 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;
/** /**
 End of changes. 5 change blocks. 
9 lines changed or deleted 6 lines changed or added


 rs_member.h   rs_member.h 
skipping to change at line 22 skipping to change at line 22
* 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/>.
*/ */
/** replica set member */ /** replica set member */
#pragma once #pragma once
#include "../../util/concurrency/value.h" #include "mongo/util/concurrency/value.h"
namespace mongo { namespace mongo {
/* /*
RS_STARTUP serving still starting up, or still trying to initiat e the set RS_STARTUP serving still starting up, or still trying to initiat e the set
RS_PRIMARY this server thinks it is primary RS_PRIMARY this server thinks it is primary
RS_SECONDARY this server thinks it is a secondary (slave mode) RS_SECONDARY this server thinks it is a secondary (slave mode)
RS_RECOVERING recovering/resyncing; after recovery usually auto-tra nsitions to secondary RS_RECOVERING recovering/resyncing; after recovery usually auto-tra nsitions to secondary
RS_FATAL something bad has occurred and server is not complete ly offline with regard to the replica set. fatal error. RS_FATAL something bad has occurred and server is not complete ly offline with regard to the replica set. fatal error.
RS_STARTUP2 loaded config, still determining who is primary RS_STARTUP2 loaded config, still determining who is primary
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. 2 change blocks. 
7 lines changed or deleted 2 lines changed or added


 rs_sync.h   rs_sync.h 
skipping to change at line 25 skipping to change at line 25
*/ */
#pragma once #pragma once
#include <deque> #include <deque>
#include <vector> #include <vector>
#include "mongo/db/client.h" #include "mongo/db/client.h"
#include "mongo/db/dur.h" #include "mongo/db/dur.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/oplog.h" #include "mongo/db/repl/sync.h"
#include "mongo/util/concurrency/thread_pool.h" #include "mongo/util/concurrency/thread_pool.h"
namespace mongo { namespace mongo {
namespace replset { namespace replset {
class BackgroundSyncInterface; class BackgroundSyncInterface;
/** /**
* "Normal" replica set syncing * "Normal" replica set syncing
*/ */
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 rwlockimpl.h   rwlockimpl.h 
skipping to change at line 27 skipping to change at line 27
*/ */
#pragma once #pragma once
#include "mutex.h" #include "mutex.h"
#if defined(RWLOCK_TEST) #if defined(RWLOCK_TEST)
namespace mongo { namespace mongo {
typedef RWLockBase1 RWLockBase; typedef RWLockBase1 RWLockBase;
} }
#elif defined(MONGO_USE_SRW_ON_WINDOWS) && defined(_WIN32) #elif defined(NTDDI_VERSION) && defined(NTDDI_WIN7) && (NTDDI_VERSION >= NT DDI_WIN7)
// windows slimreaderwriter version. newer windows versions only // windows slimreaderwriter version. newer windows versions only
namespace mongo { namespace mongo {
unsigned long long curTimeMicros64(); unsigned long long curTimeMicros64();
class RWLockBase : boost::noncopyable { class RWLockBase : boost::noncopyable {
friend class SimpleRWLock; friend class SimpleRWLock;
SRWLOCK _lock; SRWLOCK _lock;
protected: protected:
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 s2common.h   s2common.h 
skipping to change at line 29 skipping to change at line 29
#include "third_party/s2/s2.h" #include "third_party/s2/s2.h"
#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 {
// This is used by both s2cursor and s2nearcursor.
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);
}; };
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);
}
};
} // namespace mongo } // namespace mongo
 End of changes. 2 change blocks. 
39 lines changed or deleted 1 lines changed or added


 safe_num.h   safe_num.h 
skipping to change at line 59 skipping to change at line 59
* if (newValue.type() == EOO) { * if (newValue.type() == EOO) {
* return; * return;
* } * }
* // append SafeNum to a BSONObj * // append SafeNum to a BSONObj
* bsonObjBuilder.append(newValue); * bsonObjBuilder.append(newValue);
* *
*/ */
class SafeNum { class SafeNum {
public: public:
SafeNum(); SafeNum();
~SafeNum() { } ~SafeNum();
// //
// construction support // construction support
// //
// Copy ctor and assignment are allowed. // Copy ctor and assignment are allowed.
SafeNum(const SafeNum& rhs); SafeNum(const SafeNum& rhs);
SafeNum& operator=(const SafeNum& rhs); SafeNum& operator=(const SafeNum& rhs);
// Implicit conversions are allowed. // Implicit conversions are allowed.
skipping to change at line 109 skipping to change at line 109
/** /**
* Sums the 'rhs' -- right-hand side -- safe num with this, taking care of * Sums the 'rhs' -- right-hand side -- safe num with this, taking care of
* upconvertions and overflow (see class header). * upconvertions and overflow (see class header).
*/ */
SafeNum operator+(const SafeNum& rhs) const; SafeNum operator+(const SafeNum& rhs) const;
SafeNum& operator+=(const SafeNum& rhs); SafeNum& operator+=(const SafeNum& rhs);
// TODO other operations than sum // TODO other operations than sum
// //
// logical operation support. Note that these operations are only s
upported for
// integral types. Attempts to apply with either side holding a dou
ble value
// will result in an EOO typed safenum.
//
// Bitwise 'and' support
SafeNum bitAnd(const SafeNum& rhs) const;
SafeNum operator&(const SafeNum& rhs) const;
SafeNum& operator&=(const SafeNum& rhs);
// Bitwise 'or' support
SafeNum bitOr(const SafeNum& rhs) const;
SafeNum operator|(const SafeNum& rhs) const;
SafeNum& operator|=(const SafeNum& rhs);
//
// output support // output support
// //
friend class mutablebson::Element; friend class mutablebson::Element;
friend class mutablebson::Document; friend class mutablebson::Document;
// TODO: output to builder // TODO: output to builder
// //
// accessors // accessors
// //
bool isValid() const { return _type != EOO; } bool isValid() const;
BSONType type() const { return _type; } BSONType type() const;
std::string debugString() const; std::string debugString() const;
// //
// Below exposed for testing purposes. Treat as private. // Below exposed for testing purposes. Treat as private.
// //
// Maximum integer that can be converted accuratelly into a double, assuming a // Maximum integer that can be converted accuratelly into a double, assuming a
// double precission IEEE 754 representation. // double precission IEEE 754 representation.
// TODO use numeric_limits to make this portable // TODO use numeric_limits to make this portable
static const long long maxIntInDouble = 9007199254740992LL; // 2^53 static const long long maxIntInDouble = 9007199254740992LL; // 2^53
skipping to change at line 151 skipping to change at line 167
double doubleVal; double doubleVal;
} _value; } _value;
/** /**
* Returns the sum of 'lhs' and 'rhs', taking into consideration th eir types. The * Returns the sum of 'lhs' and 'rhs', taking into consideration th eir types. The
* type of the result would upcast, if necessary and permitted. Oth erwise, returns * type of the result would upcast, if necessary and permitted. Oth erwise, returns
* an EOO-type instance. * an EOO-type instance.
*/ */
static SafeNum addInternal(const SafeNum& lhs, const SafeNum& rhs); static SafeNum addInternal(const SafeNum& lhs, const SafeNum& rhs);
/** Returns the bitwise 'and' of lhs and rhs, taking into considera
tion their types. If
* the operation is invalid for the underlying types, returns an E
OO instance.
*/
static SafeNum andInternal(const SafeNum& lhs, const SafeNum& rhs);
/** Returns the bitwise 'or' of lhs and rhs, taking into considerat
ion their types. If
* the operation is invalid for the underlying types, returns an E
OO instance.
*/
static SafeNum orInternal(const SafeNum& lhs, const SafeNum& rhs);
/** /**
* Extracts the value of 'snum' in a long format. It assumes 'snum' is an NumberInt * Extracts the value of 'snum' in a long format. It assumes 'snum' is an NumberInt
* or a NumberDouble. * or a NumberDouble.
*/ */
static long long getLongLong(const SafeNum& snum); static long long getLongLong(const SafeNum& snum);
/** /**
* Extracts the value of 'snum' in a double format. It assumes 'snu m' is a valid * Extracts the value of 'snum' in a double format. It assumes 'snu m' is a valid
* SafeNum, i.e., that _type is not EOO. * SafeNum, i.e., that _type is not EOO.
*/ */
static double getDouble(const SafeNum& snum); static double getDouble(const SafeNum& snum);
}; };
// 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 SafeNum& snum); std::ostream& operator<<(std::ostream& os, const SafeNum& snum);
} // namespace mongo } // namespace mongo
#include "mongo/util/safe_num-inl.h"
 End of changes. 5 change blocks. 
3 lines changed or deleted 35 lines changed or added


 scanandorder.h   scanandorder.h 
skipping to change at line 23 skipping to change at line 23
* 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 "indexkey.h" #include "mongo/db/diskloc.h"
#include "queryutil.h" #include "mongo/db/projection.h"
#include "projection.h" #include "mongo/db/queryutil.h"
namespace mongo { namespace mongo {
class ParsedQuery;
static const int ScanAndOrderMemoryLimitExceededAssertionCode = 10128; static const int ScanAndOrderMemoryLimitExceededAssertionCode = 10128;
class KeyType : boost::noncopyable { class KeyType : boost::noncopyable {
public: public:
IndexSpec _spec; BSONObj _keyPattern;
FieldRangeVector _keyCutter; FieldRangeVector _keyCutter;
public: public:
KeyType(const BSONObj &pattern, const FieldRangeSet &frs): KeyType(const BSONObj &pattern, const FieldRangeSet &frs)
_spec(pattern, BSONObj(), IndexSpec::NoPlugins), : _keyPattern(pattern), _keyCutter(frs, pattern, 1) {
_keyCutter(frs, _spec, 1) {
verify(!pattern.isEmpty()); verify(!pattern.isEmpty());
} }
/** /**
* @return first key of the object that would be encountered while * @return first key of the object that would be encountered while
* scanning an index with keySpec 'pattern' using constraints 'frs' , or * scanning an index with keySpec 'pattern' using constraints 'frs' , or
* BSONObj() if no such key. * BSONObj() if no such key.
*/ */
BSONObj getKeyFromObject(const BSONObj &o) const { BSONObj getKeyFromObject(const BSONObj &o) const {
return _keyCutter.firstMatch(o); return _keyCutter.firstMatch(o);
 End of changes. 4 change blocks. 
7 lines changed or deleted 8 lines changed or added


 server.h   server.h 
skipping to change at line 36 skipping to change at line 36
#pragma once #pragma once
#if !defined(MONGO_EXPOSE_MACROS) #if !defined(MONGO_EXPOSE_MACROS)
# error this file is for mongo server programs not client lib # error this file is for mongo server programs not client lib
#endif #endif
#include <map> #include <map>
#include <vector> #include <vector>
#include <set> #include <set>
#include "bson/inline_decls.h" #include "mongo/bson/inline_decls.h"
//using namespace std; //using namespace std;
//using namespace bson; //using namespace bson;
/* Note: do not clutter code with these -- ONLY use in hot spots / signific ant loops. */ /* Note: do not clutter code with these -- ONLY use in hot spots / signific ant loops. */
// branch prediction. indicate we expect to be true // branch prediction. indicate we expect to be true
#define likely MONGO_likely #define likely MONGO_likely
// branch prediction. indicate we expect to be false // branch prediction. indicate we expect to be false
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 server_parameters_inline.h   server_parameters_inline.h 
skipping to change at line 44 skipping to change at line 44
inline Status ExportedServerParameter<T>::set( const T& newValue ) { inline Status ExportedServerParameter<T>::set( const T& newValue ) {
Status v = validate( newValue ); Status v = validate( newValue );
if ( !v.isOK() ) if ( !v.isOK() )
return v; return v;
*_value = newValue; *_value = newValue;
return Status::OK(); return Status::OK();
} }
template<> } // namespace mongo
inline Status ExportedServerParameter<int>::setFromString( const string
& str ) {
return set( atoi(str.c_str() ) );
}
template<>
inline Status ExportedServerParameter<double>::setFromString( const str
ing& str ) {
const char* start = str.c_str();
char* end;
double d = strtod( str.c_str(), &end );
if ( start == end )
return Status( ErrorCodes::BadValue, "not a double" );
return set( d );
}
template<>
inline Status ExportedServerParameter<string>::setFromString( const str
ing& str ) {
return set( str );
}
template<>
inline Status ExportedServerParameter<bool>::setFromString( const strin
g& str ) {
if ( str == "true" ||
str == "1" )
return set(true);
if ( str == "false" ||
str == "0" )
return set(false);
return Status( ErrorCodes::BadValue, "can't convert string to bool"
);
}
template<>
inline Status ExportedServerParameter< vector<string> >::setFromString(
const string& str ) {
vector<string> v;
splitStringDelim( str, &v, ',' );
return set( v );
}
}
 End of changes. 1 change blocks. 
0 lines changed or deleted 0 lines changed or added


 shard.h   shard.h 
skipping to change at line 126 skipping to change at line 126
return _name != s && _addr != s; return _name != s && _addr != s;
} }
bool operator<(const Shard& o) const { bool operator<(const Shard& o) const {
return _name < o._name; return _name < o._name;
} }
bool ok() const { return _addr.size() > 0; } bool ok() const { return _addr.size() > 0; }
// Set internal to true to run the command with internal authentica tion privileges. // Set internal to true to run the command with internal authentica tion privileges.
BSONObj runCommand( const string& db , const string& simple , bool BSONObj runCommand( const string& db , const string& simple ) const
internal = false ) const { {
return runCommand( db , BSON( simple << 1 ) , internal ); return runCommand( db , BSON( simple << 1 ) );
} }
BSONObj runCommand( const string& db , const BSONObj& cmd , bool in ternal = false) const ; BSONObj runCommand( const string& db , const BSONObj& cmd ) const ;
ShardStatus getStatus() const ; ShardStatus getStatus() const ;
/** /**
* mostly for replica set * mostly for replica set
* retursn true if node is the shard * retursn true if node is the shard
* of if the replica set contains node * of if the replica set contains node
*/ */
bool containsNode( const string& node ) const; bool containsNode( const string& node ) const;
skipping to change at line 293 skipping to change at line 293
_finishedInit = true; _finishedInit = true;
} }
bool ok() const { return _conn > 0; } bool ok() const { return _conn > 0; }
/** /**
this just passes through excpet it checks for stale configs this just passes through excpet it checks for stale configs
*/ */
bool runCommand( const string& db , const BSONObj& cmd , BSONObj& r es ); bool runCommand( const string& db , const BSONObj& cmd , BSONObj& r es );
// Whether or not we release connections from the thread-local cach e after a read
static bool releaseConnectionsAfterResponse; static bool releaseConnectionsAfterResponse;
// Controls whether we throw on initially failing to set a version
static bool ignoreInitialVersionFailure;
/** checks all of my thread local connections for the version of th is ns */ /** checks all of my thread local connections for the version of th is ns */
static void checkMyConnectionVersions( const string & ns ); static void checkMyConnectionVersions( const string & ns );
/** /**
* Returns all the current sharded connections to the pool. * Returns all the current sharded connections to the pool.
* Note: This is *dangerous* if we have GLE state. * Note: This is *dangerous* if we have GLE state.
*/ */
static void releaseMyConnections(); static void releaseMyConnections();
/** /**
* Clears all connections in the sharded pool, including connection s in the * Clears all connections in the sharded pool, including connection s in the
* thread local storage pool of the current thread. * thread local storage pool of the current thread.
*/ */
static void clearPool(); static void clearPool();
/**
* Forgets a namespace to prevent future versioning.
*/
static void forgetNS( const string& ns );
private: private:
void _init(); void _init();
void _finishInit(); void _finishInit();
bool _finishedInit; bool _finishedInit;
string _addr; string _addr;
string _ns; string _ns;
ChunkManagerPtr _manager; ChunkManagerPtr _manager;
 End of changes. 5 change blocks. 
13 lines changed or deleted 4 lines changed or added


 simplerwlock.h   simplerwlock.h 
skipping to change at line 28 skipping to change at line 28
#include "mongo/base/string_data.h" #include "mongo/base/string_data.h"
#include "mongo/bson/util/atomic_int.h" #include "mongo/bson/util/atomic_int.h"
namespace mongo { namespace mongo {
/** separated out as later the implementation of this may be different than RWLock, /** separated out as later the implementation of this may be different than RWLock,
depending on OS, as there is no upgrade etc. facility herein. depending on OS, as there is no upgrade etc. facility herein.
*/ */
class SimpleRWLock : boost::noncopyable { class SimpleRWLock : boost::noncopyable {
#if defined(_WIN32) && defined(MONGO_USE_SRW_ON_WINDOWS) #if defined(NTDDI_VERSION) && defined(NTDDI_WIN7) && (NTDDI_VERSION >= NTDD I_WIN7)
SRWLOCK _lock; SRWLOCK _lock;
#else #else
RWLockBase m; RWLockBase m;
#endif #endif
#if defined(_WIN32) && defined(_DEBUG) #if defined(_WIN32) && defined(_DEBUG)
AtomicUInt shares; AtomicUInt shares;
ThreadLocalValue<int> s; ThreadLocalValue<int> s;
unsigned tid; unsigned tid;
#endif #endif
public: public:
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 sock.h   sock.h 
skipping to change at line 40 skipping to change at line 40
#include <errno.h> #include <errno.h>
#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>
#include "mongo/util/net/ssl_manager.h"
#endif #endif
#include "mongo/platform/compiler.h" #include "mongo/platform/compiler.h"
namespace mongo { namespace mongo {
class SSLManagerInterface;
const int SOCK_FAMILY_UNKNOWN_ERROR=13078; const int SOCK_FAMILY_UNKNOWN_ERROR=13078;
void disableNagle(int sock); void disableNagle(int sock);
#if defined(_WIN32) #if defined(_WIN32)
typedef short sa_family_t; typedef short sa_family_t;
typedef int socklen_t; typedef int socklen_t;
// This won't actually be used on windows // This won't actually be used on windows
skipping to change at line 178 skipping to change at line 179
string _server; string _server;
string _extra; string _extra;
}; };
/** /**
* thin wrapped around file descriptor and system calls * thin wrapped around file descriptor and system calls
* todo: ssl * todo: ssl
*/ */
class Socket : boost::noncopyable { class Socket : boost::noncopyable {
public: public:
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, int logLevel = 0 );
skipping to change at line 212 skipping to change at line 216
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 );
bool isStillConnected();
#ifdef MONGO_SSL #ifdef MONGO_SSL
/** secures inline */ /** secures inline */
void secure( SSLManager * ssl ); void secure( SSLManagerInterface* ssl );
void secureAccepted( SSLManager * 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().
* This function may throw SocketException. * This function may throw SocketException.
*/ */
void doSSLHandshake(); void doSSLHandshake();
skipping to change at line 257 skipping to change at line 262
void _handleRecvError(int ret, int len, int* retries); void _handleRecvError(int ret, int len, int* retries);
MONGO_COMPILER_NORETURN void _handleSendError(int ret, const char* context); MONGO_COMPILER_NORETURN void _handleSendError(int ret, const char* context);
int _fd; int _fd;
uint64_t _fdCreationMicroSec; uint64_t _fdCreationMicroSec;
SockAddr _remote; SockAddr _remote;
double _timeout; double _timeout;
long long _bytesIn; long long _bytesIn;
long long _bytesOut; long long _bytesOut;
time_t _lastValidityCheckAtSecs;
#ifdef MONGO_SSL #ifdef MONGO_SSL
SSL* _ssl; SSL* _ssl;
SSLManager * _sslAccepted; SSLManagerInterface* _sslManager;
#endif #endif
int _logLevel; // passed to log() when logging errors int _logLevel; // passed to log() when logging errors
}; };
} // namespace mongo } // namespace mongo
 End of changes. 8 change blocks. 
4 lines changed or deleted 10 lines changed or added


 sort_phase_one.h   sort_phase_one.h 
skipping to change at line 31 skipping to change at line 31
namespace mongo { namespace mongo {
/** for bottom up fastbuildindex (where we presort keys) */ /** for bottom up fastbuildindex (where we presort keys) */
struct SortPhaseOne { struct SortPhaseOne {
SortPhaseOne() { SortPhaseOne() {
n = 0; n = 0;
nkeys = 0; nkeys = 0;
multi = false; multi = false;
} }
shared_ptr<BSONObjExternalSorter> sorter; shared_ptr<BSONObjExternalSorter> sorter;
shared_ptr<ExternalSortComparison> sortCmp;
unsigned long long n; // # of records unsigned long long n; // # of records
unsigned long long nkeys; unsigned long long nkeys;
bool multi; // multikey index bool multi; // multikey index
void addKeys(const IndexSpec& spec, const BSONObj& o, DiskLoc loc, void addKeys(const BSONObjSet& keys, const DiskLoc& loc, bool mayIn
bool mayInterrupt) { terrupt) {
BSONObjSet keys; multi = multi || (keys.size() > 1);
spec.getKeys(o, keys); for (BSONObjSet::iterator it = keys.begin(); it != keys.end();
int k = 0; ++it) {
for ( BSONObjSet::iterator i=keys.begin(); i != keys.end(); i++ sorter->add(*it, loc, mayInterrupt);
) { ++nkeys;
if( ++k == 2 ) {
multi = true;
}
sorter->add(*i, loc, mayInterrupt);
nkeys++;
} }
n++; ++n;
} }
}; };
} } // namespace mongo
 End of changes. 4 change blocks. 
13 lines changed or deleted 10 lines changed or added


 spaces-inl.h   spaces-inl.h 
skipping to change at line 152 skipping to change at line 152
#endif #endif
// ------------------------------------------------------------------------ -- // ------------------------------------------------------------------------ --
// PagedSpace // PagedSpace
Page* Page::Initialize(Heap* heap, Page* Page::Initialize(Heap* heap,
MemoryChunk* chunk, MemoryChunk* chunk,
Executability executable, Executability executable,
PagedSpace* owner) { PagedSpace* owner) {
Page* page = reinterpret_cast<Page*>(chunk); Page* page = reinterpret_cast<Page*>(chunk);
ASSERT(page->area_size() <= kNonCodeObjectAreaSize); ASSERT(chunk->size() <= static_cast<size_t>(kPageSize));
ASSERT(chunk->owner() == owner); ASSERT(chunk->owner() == owner);
owner->IncreaseCapacity(page->area_size()); owner->IncreaseCapacity(page->area_size());
owner->Free(page->area_start(), page->area_size()); owner->Free(page->area_start(), page->area_size());
heap->incremental_marking()->SetOldSpacePageFlags(chunk); heap->incremental_marking()->SetOldSpacePageFlags(chunk);
return page; return page;
} }
bool PagedSpace::Contains(Address addr) { bool PagedSpace::Contains(Address addr) {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 spaces.h   spaces.h 
skipping to change at line 320 skipping to change at line 320
MemoryChunk* next_chunk() const { return next_chunk_; } MemoryChunk* next_chunk() const { return next_chunk_; }
MemoryChunk* prev_chunk() const { return prev_chunk_; } MemoryChunk* prev_chunk() const { return prev_chunk_; }
void set_next_chunk(MemoryChunk* next) { next_chunk_ = next; } void set_next_chunk(MemoryChunk* next) { next_chunk_ = next; }
void set_prev_chunk(MemoryChunk* prev) { prev_chunk_ = prev; } void set_prev_chunk(MemoryChunk* prev) { prev_chunk_ = prev; }
Space* owner() const { Space* owner() const {
if ((reinterpret_cast<intptr_t>(owner_) & kFailureTagMask) == if ((reinterpret_cast<intptr_t>(owner_) & kFailureTagMask) ==
kFailureTag) { kFailureTag) {
return reinterpret_cast<Space*>(reinterpret_cast<intptr_t>(owner_) - return reinterpret_cast<Space*>(owner_ - kFailureTag);
kFailureTag);
} else { } else {
return NULL; return NULL;
} }
} }
void set_owner(Space* space) { void set_owner(Space* space) {
ASSERT((reinterpret_cast<intptr_t>(space) & kFailureTagMask) == 0); ASSERT((reinterpret_cast<intptr_t>(space) & kFailureTagMask) == 0);
owner_ = reinterpret_cast<Address>(space) + kFailureTag; owner_ = reinterpret_cast<Address>(space) + kFailureTag;
ASSERT((reinterpret_cast<intptr_t>(owner_) & kFailureTagMask) == ASSERT((reinterpret_cast<intptr_t>(owner_) & kFailureTagMask) ==
kFailureTag); kFailureTag);
 End of changes. 1 change blocks. 
2 lines changed or deleted 1 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 SSLParams {
public:
SSLParams(const std::string& pemfile,
const std::string& pempwd,
const std::string& cafile = "",
const std::string& crlfile = "",
bool weakCertificateValidation = false,
bool fipsMode = false) :
pemfile(pemfile),
pempwd(pempwd),
cafile(cafile),
crlfile(crlfile),
weakCertificateValidation(weakCertificateValidation),
fipsMode(fipsMode) {};
std::string pemfile;
std::string pempwd;
std::string cafile;
std::string crlfile;
bool weakCertificateValidation;
bool fipsMode;
};
class SSLManager { class SSLManagerInterface {
MONGO_DISALLOW_COPYING(SSLManager);
public: public:
explicit SSLManager(const SSLParams& params); 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.
*/ */
SSL* connect(int fd); virtual SSL* connect(int fd) = 0;
/** /**
* 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.
*/ */
SSL* accept(int fd); 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
*/ */
void validatePeerCertificate(const SSL* ssl); virtual void 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
*/ */
static void cleanupThreadLocals(); virtual void cleanupThreadLocals() = 0;
/**
* Callbacks for SSL functions
*/
static int password_cb( char *buf,int num, int rwflag,void *userdat
a );
static int verify_cb(int ok, X509_STORE_CTX *ctx);
private:
SSL_CTX* _context;
std::string _password;
bool _validateCertificates;
bool _weakValidation;
/** /**
* creates an SSL context to be used for this file descriptor. * ssl.h shims
* caller must SSL_free it.
*/ */
SSL* _secure(int fd); virtual int SSL_read(SSL* ssl, void* buf, int num) = 0;
/** virtual int SSL_write(SSL* ssl, const void* buf, int num) = 0;
* Fetches the error text for an error code, in a thread-safe manne
r.
*/
std::string _getSSLErrorMessage(int code);
/** virtual unsigned long ERR_get_error() = 0;
* Given an error code from an SSL-type IO function, logs an
* appropriate message and throws a SocketException
*/
void _handleSSLError(int code);
/** @return true if was successful, otherwise false */ virtual char* ERR_error_string(unsigned long e, char* buf) = 0;
bool _setupPEM( const std::string& keyFile , const std::string& pas
sword );
/* virtual int SSL_get_error(const SSL* ssl, int ret) = 0;
* Set up SSL for certificate validation by loading a CA
*/
bool _setupCA(const std::string& caFile);
/* virtual int SSL_shutdown(SSL* ssl) = 0;
* Import a certificate revocation list into our SSL context
* for use with validating certificates
*/
bool _setupCRL(const std::string& crlFile);
/* virtual void SSL_free(SSL* ssl) = 0;
* Activate FIPS 140-2 mode, if the server started with a command l };
ine
* parameter.
*/
void _setupFIPS();
/* // Access SSL functions through this instance.
* Wrapper for SSL_Connect() that handles SSL_ERROR_WANT_READ, SSLManagerInterface* getSSLManager();
* see SERVER-7940
*/
int _ssl_connect(SSL* ssl);
/*
* Initialize the SSL Library.
* This function can be called multiple times; it ensures it only
* does the SSL initialization once per process.
*/
void _initializeSSL(const SSLParams& params);
};
} }
#endif #endif
 End of changes. 18 change blocks. 
84 lines changed or deleted 17 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/platform/basic.h"
 End of changes. 1 change blocks. 
15 lines changed or deleted 1 lines changed or added


 stemmer.h   stemmer.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 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 "libstemmer.h"
#include "mongo/base/string_data.h" #include "mongo/base/string_data.h"
#include "third_party/libstemmer_c/include/libstemmer.h"
namespace mongo { namespace mongo {
namespace fts { namespace fts {
/** /**
* maintains case * maintains case
* but works * but works
* running/Running -> run/Run * running/Running -> run/Run
*/ */
 End of changes. 2 change blocks. 
2 lines changed or deleted 1 lines changed or added


 syncclusterconnection.h   syncclusterconnection.h 
skipping to change at line 94 skipping to change at line 94
virtual void update( const string &ns , Query query , BSONObj obj , int flags ); virtual void update( const string &ns , Query query , BSONObj obj , int flags );
virtual bool call( Message &toSend, Message &response, bool assertO k , string * actualServer ); virtual bool call( Message &toSend, Message &response, bool assertO k , string * actualServer );
virtual void say( Message &toSend, bool isRetry = false , string * actualServer = 0 ); virtual void say( Message &toSend, bool isRetry = false , string * actualServer = 0 );
virtual void sayPiggyBack( Message &toSend ); virtual void sayPiggyBack( Message &toSend );
virtual void killCursor( long long cursorID ); virtual void killCursor( long long cursorID );
virtual string getServerAddress() const { return _address; } virtual string getServerAddress() const { return _address; }
virtual bool isFailed() const { return false; } virtual bool isFailed() const { return false; }
virtual bool isStillConnected();
virtual string toString() { return _toString(); } virtual string toString() { return _toString(); }
virtual BSONObj getLastErrorDetailed(const std::string& db, virtual BSONObj getLastErrorDetailed(const std::string& db,
bool fsync=false, bool fsync=false,
bool j=false, bool j=false,
int w=0, int w=0,
int wtimeout=0); int wtimeout=0);
virtual BSONObj getLastErrorDetailed(bool fsync=false, bool j=false , int w=0, int wtimeout=0); virtual BSONObj getLastErrorDetailed(bool fsync=false, bool j=false , int w=0, int wtimeout=0);
virtual bool callRead( Message& toSend , Message& response ); virtual bool callRead( Message& toSend , Message& response );
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 synchronization.h   synchronization.h 
skipping to change at line 41 skipping to change at line 41
class Notification : boost::noncopyable { class Notification : boost::noncopyable {
public: public:
Notification(); Notification();
/* /*
* Blocks until the method 'notifyOne()' is called. * Blocks until the method 'notifyOne()' is called.
*/ */
void waitToBeNotified(); void waitToBeNotified();
/* /*
* Blocks until the method 'notifyOne()' is called or the time inte
rval elapses.
* Returns true if notified, false if timeout.
*/
bool timedWaitToBeNotified( int millis );
/*
* Notifies the waiter of '*this' that it can proceed. Can only be called once. * Notifies the waiter of '*this' that it can proceed. Can only be called once.
*/ */
void notifyOne(); void notifyOne();
private: private:
mongo::mutex _mutex; // protects state below mongo::mutex _mutex; // protects state below
unsigned long long lookFor; unsigned long long lookFor;
unsigned long long cur; unsigned long long cur;
boost::condition _condition; // cond over _notified being true boost::condition _condition; // cond over _notified being true
}; };
 End of changes. 1 change blocks. 
0 lines changed or deleted 7 lines changed or added


 task.h   task.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 "../background.h" #include "mongo/util/background.h"
namespace mongo { namespace mongo {
namespace task { namespace task {
/** abstraction around threads. simpler than BackgroundJob which i s used behind the scenes. /** abstraction around threads. simpler than BackgroundJob which i s used behind the scenes.
allocate the Task dynamically. when the thread terminates, the Task object will delete itself. allocate the Task dynamically. when the thread terminates, the Task object will delete itself.
*/ */
class Task : private BackgroundJob { class Task : private BackgroundJob {
protected: protected:
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 text.h   text.h 
skipping to change at line 24 skipping to change at line 24
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <vector> #include <vector>
#include <string> #include <string>
#include "mongo/base/disallow_copying.h"
namespace mongo { namespace mongo {
class StringSplitter { class StringSplitter {
public: public:
/** @param big the string to be split /** @param big the string to be split
@param splitter the delimiter @param splitter the delimiter
*/ */
StringSplitter( const char * big , const char * splitter ) StringSplitter( const char * big , const char * splitter )
: _big( big ) , _splitter( splitter ) { : _big( big ) , _splitter( splitter ) {
} }
skipping to change at line 82 skipping to change at line 84
/* like toWideString but UNICODE macro sensitive */ /* like toWideString but UNICODE macro sensitive */
# if !defined(_UNICODE) # if !defined(_UNICODE)
#error temp error #error temp error
inline std::string toNativeString(const char *s) { return s; } inline std::string toNativeString(const char *s) { return s; }
# else # else
inline std::wstring toNativeString(const char *s) { return toWideString (s); } inline std::wstring toNativeString(const char *s) { return toWideString (s); }
# endif # endif
class WindowsCommandLine { class WindowsCommandLine {
MONGO_DISALLOW_COPYING(WindowsCommandLine);
char** _argv; char** _argv;
char** _envp;
public: public:
WindowsCommandLine( int argc, wchar_t* argvW[] ); WindowsCommandLine(int argc, wchar_t* argvW[], wchar_t* envpW[]);
~WindowsCommandLine(); ~WindowsCommandLine();
char** argv( void ) const { return _argv; }; char** argv(void) const { return _argv; };
char** envp(void) const { return _envp; };
}; };
#endif // #if defined(_WIN32) #endif // #if defined(_WIN32)
/** /**
* Construct a Windows command line string, UTF-8 encoded, from a vecto r of * Construct a Windows command line string, UTF-8 encoded, from a vecto r of
* UTF-8 arguments, "argv". * UTF-8 arguments, "argv".
* *
* See "Parsing C++ Command-Line Arguments (C++)" * See "Parsing C++ Command-Line Arguments (C++)"
* http://msdn.microsoft.com/en-us/library/windows/desktop/17w5ykft(v=v s.85).aspx * http://msdn.microsoft.com/en-us/library/windows/desktop/17w5ykft(v=v s.85).aspx
 End of changes. 5 change blocks. 
2 lines changed or deleted 7 lines changed or added


 ticketholder.h   ticketholder.h 
skipping to change at line 18 skipping to change at line 18
* *
* 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/condition_variable.hpp> #include <boost/thread/condition_variable.hpp>
#include <iostream>
#include "mongo/util/concurrency/mutex.h" #include "mongo/util/concurrency/mutex.h"
namespace mongo { namespace mongo {
class TicketHolder { class TicketHolder {
public: public:
TicketHolder( int num ) : _mutex("TicketHolder") { TicketHolder( int num ) : _mutex("TicketHolder") {
_outof = num; _outof = num;
_num = num; _num = num;
skipping to change at line 57 skipping to change at line 58
} }
_newTicket.notify_one(); _newTicket.notify_one();
} }
void resize( int newSize ) { void resize( int newSize ) {
{ {
scoped_lock lk( _mutex ); scoped_lock lk( _mutex );
int used = _outof - _num; int used = _outof - _num;
if ( used > newSize ) { if ( used > newSize ) {
cout << "ERROR: can't resize since we're using (" << us ed << ") more than newSize(" << newSize << ")" << endl; std::cout << "can't resize since we're using (" << used << ") more than newSize(" << newSize << ")" << std::endl;
return; return;
} }
_outof = newSize; _outof = newSize;
_num = _outof - used; _num = _outof - used;
} }
// Potentially wasteful, but easier to see is correct // Potentially wasteful, but easier to see is correct
_newTicket.notify_all(); _newTicket.notify_all();
} }
skipping to change at line 84 skipping to change at line 85
return _outof - _num; return _outof - _num;
} }
int outof() const { return _outof; } int outof() const { return _outof; }
private: private:
bool _tryAcquire(){ bool _tryAcquire(){
if ( _num <= 0 ) { if ( _num <= 0 ) {
if ( _num < 0 ) { if ( _num < 0 ) {
cerr << "DISASTER! in TicketHolder" << endl; std::cerr << "DISASTER! in TicketHolder" << std::endl;
} }
return false; return false;
} }
_num--; _num--;
return true; return true;
} }
int _outof; int _outof;
int _num; int _num;
mongo::mutex _mutex; mongo::mutex _mutex;
 End of changes. 3 change blocks. 
2 lines changed or deleted 3 lines changed or added


 tool.h   tool.h 
skipping to change at line 47 skipping to change at line 47
public: public:
enum DBAccess { enum DBAccess {
NONE = 0 , NONE = 0 ,
REMOTE_SERVER = 1 << 1 , REMOTE_SERVER = 1 << 1 ,
LOCAL_SERVER = 1 << 2 , LOCAL_SERVER = 1 << 2 ,
SPECIFY_DBCOL = 1 << 3 , SPECIFY_DBCOL = 1 << 3 ,
ALL = REMOTE_SERVER | LOCAL_SERVER | SPECIFY_DBCOL ALL = REMOTE_SERVER | LOCAL_SERVER | SPECIFY_DBCOL
}; };
Tool( string name , DBAccess access=ALL, string defaultDB="test" , Tool( string name , DBAccess access=ALL, string defaultDB="test" ,
string defaultCollection="", bool usesstdout=true); string defaultCollection="", bool usesstdout=true, bool quiet =false);
virtual ~Tool(); virtual ~Tool();
int main( int argc , char ** argv ); int main( int argc , char ** argv );
boost::program_options::options_description_easy_init add_options() { boost::program_options::options_description_easy_init add_options() {
return _options->add_options(); return _options->add_options();
} }
boost::program_options::options_description_easy_init add_hidden_op tions() { boost::program_options::options_description_easy_init add_hidden_op tions() {
return _hidden_options->add_options(); return _hidden_options->add_options();
} }
skipping to change at line 120 skipping to change at line 120
string _db; string _db;
string _coll; string _coll;
string _fileName; string _fileName;
string _username; string _username;
string _password; string _password;
string _authenticationDatabase; string _authenticationDatabase;
string _authenticationMechanism; string _authenticationMechanism;
bool _usesstdout; bool _usesstdout;
bool _quiet;
bool _noconnection; bool _noconnection;
bool _autoreconnect; bool _autoreconnect;
void addFieldOptions(); void addFieldOptions();
void needFields(); void needFields();
vector<string> _fields; vector<string> _fields;
BSONObj _fieldsObj; BSONObj _fieldsObj;
string _host; string _host;
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 unittest.h   unittest.h 
skipping to change at line 54 skipping to change at line 54
/** /**
* Fails unless "EXPRESSION" is true. * Fails unless "EXPRESSION" is true.
*/ */
#define ASSERT_TRUE(EXPRESSION) ::mongo::unittest::TestAssertion( __FILE__, __LINE__ ).failIf( \ #define ASSERT_TRUE(EXPRESSION) ::mongo::unittest::TestAssertion( __FILE__, __LINE__ ).failIf( \
!(EXPRESSION), "Expected: " #EXPRESSION ) !(EXPRESSION), "Expected: " #EXPRESSION )
#define ASSERT(EXPRESSION) ASSERT_TRUE(EXPRESSION) #define ASSERT(EXPRESSION) ASSERT_TRUE(EXPRESSION)
/** /**
* Assert that a Status code is OK. * Assert that a Status code is OK.
*/ */
#define ASSERT_OK(EXPRESSION) ASSERT_EQUALS(Status::OK(), (EXPRESSION)) #define ASSERT_OK(EXPRESSION) ASSERT_EQUALS(::mongo::Status::OK(), (EXPRESS ION))
/** /**
* Assert that a status code is anything but OK. * Assert that a status code is anything but OK.
*/ */
#define ASSERT_NOT_OK(EXPRESSION) ASSERT_NOT_EQUALS(Status::OK(), (EXPRESSI ON)) #define ASSERT_NOT_OK(EXPRESSION) ASSERT_NOT_EQUALS(::mongo::Status::OK(), (EXPRESSION))
/** /**
* Fails if "EXPRESSION" is true. * Fails if "EXPRESSION" is true.
*/ */
#define ASSERT_FALSE(EXPRESSION) ::mongo::unittest::TestAssertion( __FILE__ , __LINE__ ).failIf( \ #define ASSERT_FALSE(EXPRESSION) ::mongo::unittest::TestAssertion( __FILE__ , __LINE__ ).failIf( \
(EXPRESSION), "Expected: !(" #EXPRESSION ")" ) (EXPRESSION), "Expected: !(" #EXPRESSION ")" )
/* /*
* Binary comparison assertions. * Binary comparison assertions.
*/ */
skipping to change at line 82 skipping to change at line 82
#define ASSERT_LESS_THAN(a, b) _ASSERT_COMPARISON(LessThan, a, b) #define ASSERT_LESS_THAN(a, b) _ASSERT_COMPARISON(LessThan, a, b)
#define ASSERT_NOT_LESS_THAN(a, b) _ASSERT_COMPARISON(NotLessThan, a, b) #define ASSERT_NOT_LESS_THAN(a, b) _ASSERT_COMPARISON(NotLessThan, a, b)
#define ASSERT_GREATER_THAN(a, b) _ASSERT_COMPARISON(GreaterThan, a, b) #define ASSERT_GREATER_THAN(a, b) _ASSERT_COMPARISON(GreaterThan, a, b)
#define ASSERT_NOT_GREATER_THAN(a, b) _ASSERT_COMPARISON(NotGreaterThan, a, b) #define ASSERT_NOT_GREATER_THAN(a, b) _ASSERT_COMPARISON(NotGreaterThan, a, b)
#define ASSERT_LESS_THAN_OR_EQUALS(a, b) ASSERT_NOT_GREATER_THAN(a, b) #define ASSERT_LESS_THAN_OR_EQUALS(a, b) ASSERT_NOT_GREATER_THAN(a, b)
#define ASSERT_GREATER_THAN_OR_EQUALS(a, b) ASSERT_NOT_LESS_THAN(a, b) #define ASSERT_GREATER_THAN_OR_EQUALS(a, b) ASSERT_NOT_LESS_THAN(a, b)
/** /**
* Binary comparison utility macro. Do not use directly. * Binary comparison utility macro. Do not use directly.
*/ */
#define _ASSERT_COMPARISON(COMPARISON, a, b) mongo::unittest::ComparisonAss ertion( \ #define _ASSERT_COMPARISON(COMPARISON, a, b) ::mongo::unittest::ComparisonA ssertion( \
#a, #b , __FILE__ , __LINE__ ).assert##COMPARISON( (a), (b) ) #a, #b , __FILE__ , __LINE__ ).assert##COMPARISON( (a), (b) )
/** /**
* Approximate equality assertion. Useful for comparisons on limited precis ion floating point * Approximate equality assertion. Useful for comparisons on limited precis ion floating point
* values. * values.
*/ */
#define ASSERT_APPROX_EQUAL(a,b,ABSOLUTE_ERR) ::mongo::unittest::assertAppr oxEqual( \ #define ASSERT_APPROX_EQUAL(a,b,ABSOLUTE_ERR) ::mongo::unittest::assertAppr oxEqual( \
#a, #b, a, b, ABSOLUTE_ERR, __FILE__, __LINE__) #a, #b, a, b, ABSOLUTE_ERR, __FILE__, __LINE__)
/** /**
skipping to change at line 350 skipping to change at line 350
private: private:
boost::shared_ptr<TestAssertionFailureDetails> _details; boost::shared_ptr<TestAssertionFailureDetails> _details;
}; };
/** /**
* Object representing an assertion about some condition. * Object representing an assertion about some condition.
*/ */
class TestAssertion : private boost::noncopyable { class TestAssertion : private boost::noncopyable {
public: public:
TestAssertion( const std::string& file, unsigned line ); /**
* file string must stay in scope and remain unchanged for the
lifetime
* of the TestAssertion object.
*/
TestAssertion( const char* file, unsigned line );
~TestAssertion(); ~TestAssertion();
void fail( const std::string& message) const; MONGO_COMPILER_NORETURN void fail( const std::string& message) const;
void failIf( bool flag, const std::string &message ) const { void failIf( bool flag, const std::string &message ) const {
if ( flag ) fail( message ); if ( flag ) fail( message );
} }
private: private:
const std::string _file; const char* _file;
const unsigned _line; const unsigned _line;
}; };
/** /**
* Specialization of TestAssertion for binary comparisons. * Specialization of TestAssertion for binary comparisons.
*/ */
class ComparisonAssertion : private TestAssertion { class ComparisonAssertion : private TestAssertion {
public: public:
ComparisonAssertion( const std::string& aexp , const std::strin /**
g& bexp , * All char* arguments must stay in scope and remain unchanged
const std::string& file , unsigned line ); for the lifetime
* of the ComparisonAssertion object.
*/
ComparisonAssertion( const char* aexp , const char* bexp ,
const char* file , unsigned line );
template<typename A,typename B> template<typename A,typename B>
void assertEqual( const A& a , const B& b ) { void assertEqual( const A& a , const B& b ) {
if ( a == b ) if ( a == b )
return; return;
fail(getComparisonFailureMessage("==", a, b)); fail(getComparisonFailureMessage("==", a, b));
} }
template<typename A,typename B> template<typename A,typename B>
void assertNotEqual( const A& a , const B& b ) { void assertNotEqual( const A& a , const B& b ) {
skipping to change at line 418 skipping to change at line 426
if ( a <= b ) if ( a <= b )
return; return;
fail(getComparisonFailureMessage("<=", a, b)); fail(getComparisonFailureMessage("<=", a, b));
} }
private: private:
template< typename A, typename B> template< typename A, typename B>
std::string getComparisonFailureMessage(const std::string &theO perator, std::string getComparisonFailureMessage(const std::string &theO perator,
const A& a, const B& b) ; const A& a, const B& b) ;
std::string _aexp; const char* _aexp;
std::string _bexp; const char* _bexp;
}; };
/** /**
* Helper for ASSERT_APPROX_EQUAL to ensure that the arguments are evaluated only once. * Helper for ASSERT_APPROX_EQUAL to ensure that the arguments are evaluated only once.
*/ */
template < typename A, typename B, typename ABSOLUTE_ERR > template < typename A, typename B, typename ABSOLUTE_ERR >
inline void assertApproxEqual(const std::string& aexp, const std::s tring& bexp, inline void assertApproxEqual(const char* aexp, const char* bexp,
const A& a, const B& b, const ABSOLUT E_ERR& absoluteErr, const A& a, const B& b, const ABSOLUT E_ERR& absoluteErr,
const std::string& file , unsigned li ne) { const char* file , unsigned line) {
if (std::abs(a - b) <= absoluteErr) if (std::abs(a - b) <= absoluteErr)
return; return;
TestAssertion(file, line).fail(mongoutils::str::stream() TestAssertion(file, line).fail(mongoutils::str::stream()
<< "Expected " << aexp << " and " << bexp << " to be wi thin " << absoluteErr << "Expected " << aexp << " and " << bexp << " to be wi thin " << absoluteErr
<< " of each other ((" << a << ") - (" << b << ") = " < < (a - b) << ")"); << " of each other ((" << a << ") - (" << b << ") = " < < (a - b) << ")");
} }
/** /**
* Hack to support the runaway test observer in dbtests. This is a hook that * Hack to support the runaway test observer in dbtests. This is a hook that
* unit test running harnesses (unittest_main and dbtests) must imp lement. * unit test running harnesses (unittest_main and dbtests) must imp lement.
 End of changes. 10 change blocks. 
13 lines changed or deleted 22 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;
bool transfer( Area* newArea, const UnorderedFastKeyTable& sm ) const; void 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 bool UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::Area::tr ansfer( inline void 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 );
if ( firstEmpty < 0 ) { verify( 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 135 skipping to change at line 132
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 < 5; numGrowTries++ ) { for ( int numGrowTries = 0; numGrowTries < 10; 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 174 skipping to change at line 171
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() {
unsigned capacity = _area._capacity; Area newArea( _area._capacity * 2, _maxProbeRatio );
for ( int numGrowTries = 0; numGrowTries < 5; numGrowTries++ ) { _area.transfer( &newArea, *this );
capacity *= 2; _area.swap( &newArea );
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. 
20 lines changed or deleted 6 lines changed or added


 update.h   update.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/>.
*/ */
#include "mongo/pch.h" #include "mongo/pch.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/curop.h" #include "mongo/db/curop.h"
#include "mongo/db/queryoptimizercursor.h" #include "mongo/db/query_plan_selection_policy.h"
namespace mongo { namespace mongo {
// ---------- public ------------- // ---------- public -------------
struct UpdateResult { struct UpdateResult {
const bool existing; // if existing objects were modified const bool existing; // if existing objects were modified
const bool mod; // was this a $ mod const bool mod; // was this a $ mod
const long long num; // how many objects touched const long long num; // how many objects touched
OID upserted; // if something was upserted, the new _id of the obj ect OID upserted; // if something was upserted, the new _id of the obj ect
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 update_internal.h   update_internal.h 
skipping to change at line 19 skipping to change at line 19
* *
* 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/pch.h" #include "mongo/db/index_set.h"
#include "mongo/bson/bson_builder_base.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/jsobjmanipulator.h" #include "mongo/db/jsobjmanipulator.h"
#include "mongo/db/matcher.h" #include "mongo/db/matcher.h"
#include "mongo/util/embedded_builder.h" #include "mongo/util/embedded_builder.h"
#include "mongo/util/mongoutils/str.h"
#include "mongo/util/stringutils.h" #include "mongo/util/stringutils.h"
using namespace mongoutils;
namespace mongo { namespace mongo {
class ModState; class ModState;
class ModSetState; class ModSetState;
/* Used for modifiers such as $inc, $set, $push, ... /* Used for modifiers such as $inc, $set, $push, ...
* stores the info about a single operation * stores the info about a single operation
* once created should never be modified * once created should never be modified
*/ */
struct Mod { struct Mod {
 End of changes. 3 change blocks. 
3 lines changed or deleted 4 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;
/** /**
* get the DBClientBase connection from JS args * install database access functions
*/
void installDBAccess(V8Scope* scope);
/**
* install BSON types and helpers
*/ */
mongo::DBClientBase* getConnection(V8Scope* scope, const v8::Arguments& args); void installBSONTypes(V8Scope* scope);
// Internal Cursor /**
v8::Handle<v8::FunctionTemplate> getInternalCursorFunctionTemplate(V8Sc * get the DBClientBase connection from JS args
ope* scope); */
mongo::DBClientBase* getConnection(const v8::Arguments& args);
// 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);
skipping to change at line 64 skipping to change at line 71
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);
// NumberInt object // Number 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. 
8 lines changed or deleted 12 lines changed or added


 value.h   value.h 
/* @file value.h
concurrency helpers DiagStr, Guarded
*/
/** /**
* Copyright (c) 2011 10gen Inc. * Copyright (C) 2008 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3, * it under the terms of the GNU Affero General Public License, version 3
* as published by the Free Software Foundation. ,
* * as published by the Free Software Foundation.
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of * This program is distributed in the hope that it will be useful,b
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU Affero General Public License for more details. * 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 License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. * 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 #pragma once
#include "mongo/db/pipeline/value_internal.h" #include "spin_lock.h"
namespace mongo { namespace mongo {
class BSONElement;
class Builder;
/** A variant type that can hold any type of data representable in BSON /** declare that a variable that is "guarded" by a mutex.
*
* Small values are stored inline, but some values, such as large stri
ngs,
* are heap allocated. It has smart pointer capabilities built-in so i
t is
* safe and recommended to pass these around and return them by value.
*
* Values are immutable, but can be assigned. This means that once you
have
* a Value, you can be assured that none of the data in that Value wil
l
* change. However if you have a non-const Value you replace it with
* operator=. These rules are the same as BSONObj, and similar to
* shared_ptr<const Object> with stronger guarantees of constness. Thi
s is
* 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:
/** Construct a Value
*
* 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);
/** A "missing" value indicates the lack of a Value.
* This is similar to undefined/null but should not appear in outp
ut to BSON.
* Missing Values are returned by Document when accessing non-exis
tent fields.
*/
bool missing() const { return _storage.type == EOO; }
/// true if missing() or type is jstNULL or Undefined
bool nullish() const {
return missing()
|| _storage.type == jstNULL
|| _storage.type == Undefined;
}
/// true if type represents a number The decl documents the rule. For example "counta and countb are gu
bool numeric() const { arded by xyzMutex":
return _storage.type == NumberDouble
|| _storage.type == NumberLong
|| _storage.type == NumberInt;
}
/// Get the BSON type of the field. Guarded<int, xyzMutex> counta;
BSONType getType() const { return _storage.bsonType(); } Guarded<int, xyzMutex> countb;
/** Exact type getters. Upon use, specify the scoped_lock object. This makes it hard for s
* Asserts if the requested value type is not exactly correct. omeone
* See coerceTo methods below for a more type-flexible alternative later to forget to be in the lock. Check is made that it is the ri
. ght lock in _DEBUG
*/ builds at runtime.
double getDouble() const; */
string getString() const; template <typename T, SimpleMutex& BY>
Document getDocument() const; class Guarded {
OID getOid() const; T _val;
bool getBool() const; public:
long long getDate() const; // in milliseconds T& ref(const SimpleMutex::scoped_lock& lk) {
OpTime getTimestamp() const; dassert( &lk.m() == &BY );
const char* getRegex() const; return _val;
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);
} }
};
/// This is for debugging, logging, etc. See getString() for how to // todo: rename this to ThreadSafeString or something
extract a string. /** there is now one mutex per DiagStr. If you have hundreds or millio
string toString() const; ns of
friend ostream& operator << (ostream& out, const Value& v); DiagStrs you'll need to do something different.
*/
void swap(Value& rhs) { class DiagStr {
_storage.swap(rhs._storage); mutable SpinLock m;
string _s;
public:
DiagStr(const DiagStr& r) : _s(r.get()) { }
DiagStr(const string& r) : _s(r) { }
DiagStr() { }
bool empty() const {
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);
_s = s;
}
void set(const string& s) {
scoped_spinlock lk(m);
_s = s;
}
operator string() const { return get(); }
void operator=(const string& s) { set(s); }
void operator=(const DiagStr& rhs) {
set( rhs.get() );
} }
/** Figure out what the widest of two numeric types is. // == is not defined. use get() == ... instead. done this way so
* one thinks about if composing multiple operations
* Widest can be thought of as "most capable," or "able to hold th bool operator==(const string& s) const;
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(); }
// LEGACY creation functions
static Value createFromBsonElement(const BSONElement* pBsonElement)
;
static Value createInt(int value) { return Value(value); }
static Value createLong(long long value) { return Value(value); }
static Value createDouble(double value) { return Value(value); }
static Value createTimestamp(const OpTime& value) { return Value(va
lue); }
static Value createString(const string& value) { return Value(value
); }
static Value createDocument(const Document& doc) { return Value(doc
); }
static Value createArray(const vector<Value>& vec) { return Value(v
ec); }
static Value createDate(const long long value);
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);
// 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. 14 change blocks. 
298 lines changed or deleted 75 lines changed or added


 value_internal.h   value_internal.h 
skipping to change at line 25 skipping to change at line 25
*/ */
#pragma once #pragma once
#include <algorithm> #include <algorithm>
#include "bson/bsonobj.h" #include "bson/bsonobj.h"
#include "bson/bsontypes.h" #include "bson/bsontypes.h"
#include "bson/bsonmisc.h" #include "bson/bsonmisc.h"
#include "bson/oid.h" #include "bson/oid.h"
#include "util/intrusive_counter.h" #include "util/intrusive_counter.h"
#include "util/optime.h" #include "mongo/db/repl/optime.h"
namespace mongo { namespace mongo {
class Document; class Document;
class DocumentStorage; class DocumentStorage;
class Value; class Value;
//TODO: a MutableVector, similar to MutableDocument //TODO: a MutableVector, similar to MutableDocument
/// A heap-allocated reference-counted std::vector /// A heap-allocated reference-counted std::vector
class RCVector : public RefCountable { class RCVector : public RefCountable {
public: public:
skipping to change at line 91 skipping to change at line 91
memcpy(&oid, &o, sizeof(OID)); memcpy(&oid, &o, sizeof(OID));
BOOST_STATIC_ASSERT(sizeof(OID) == sizeof(oid)); BOOST_STATIC_ASSERT(sizeof(OID) == sizeof(oid));
} }
ValueStorage(const ValueStorage& rhs) { ValueStorage(const ValueStorage& rhs) {
memcpy(this, &rhs, sizeof(*this)); memcpy(this, &rhs, sizeof(*this));
memcpyed(); memcpyed();
} }
~ValueStorage() { ~ValueStorage() {
DEV verifyRefCountingIfShould();
if (refCounter) if (refCounter)
intrusive_ptr_release(genericRCPtr); intrusive_ptr_release(genericRCPtr);
DEV memset(this, 0xee, sizeof(*this)); DEV memset(this, 0xee, sizeof(*this));
} }
ValueStorage& operator= (ValueStorage rhsCopy) { ValueStorage& operator= (ValueStorage rhsCopy) {
this->swap(rhsCopy); this->swap(rhsCopy);
return *this; return *this;
} }
void swap(ValueStorage& rhs) { void swap(ValueStorage& rhs) {
// Don't need to update ref-counts because they will be the sam e in the end // Don't need to update ref-counts because they will be the sam e in the end
char temp[sizeof(ValueStorage)]; char temp[sizeof(ValueStorage)];
memcpy(temp, this, sizeof(*this)); memcpy(temp, this, sizeof(*this));
memcpy(this, &rhs, sizeof(*this)); memcpy(this, &rhs, sizeof(*this));
memcpy(&rhs, temp, sizeof(*this)); memcpy(&rhs, temp, sizeof(*this));
} }
/// Call this after memcpying to update ref counts if needed /// Call this after memcpying to update ref counts if needed
void memcpyed() const { void memcpyed() const {
DEV verifyRefCountingIfShould();
if (refCounter) if (refCounter)
intrusive_ptr_add_ref(genericRCPtr); intrusive_ptr_add_ref(genericRCPtr);
} }
/// These are only to be called during Value construction on an emp ty Value /// These are only to be called during Value construction on an emp ty Value
void putString(const StringData& s); void putString(const StringData& s);
void putVector(const RCVector* v); void putVector(const RCVector* v);
void putDocument(const Document& d); void putDocument(const Document& d);
void putRegEx(const BSONRegEx& re); void putRegEx(const BSONRegEx& re);
void putBinData(const BSONBinData& bd) { void putBinData(const BSONBinData& bd) {
skipping to change at line 144 skipping to change at line 142
putRefCountable(new RCCodeWScope(cws.code.toString(), cws.scope )); putRefCountable(new RCCodeWScope(cws.code.toString(), cws.scope ));
} }
void putRefCountable(intrusive_ptr<const RefCountable> ptr) { void putRefCountable(intrusive_ptr<const RefCountable> ptr) {
genericRCPtr = ptr.get(); genericRCPtr = ptr.get();
if (genericRCPtr) { if (genericRCPtr) {
intrusive_ptr_add_ref(genericRCPtr); intrusive_ptr_add_ref(genericRCPtr);
refCounter = true; refCounter = true;
} }
DEV verifyRefCountingIfShould();
} }
StringData getString() const { StringData getString() const {
if (shortStr) { if (shortStr) {
return StringData(shortStrStorage, shortStrSize); return StringData(shortStrStorage, shortStrSize);
} }
else { else {
dassert(typeid(*genericRCPtr) == typeid(const RCString)); dassert(typeid(*genericRCPtr) == typeid(const RCString));
const RCString* stringPtr = static_cast<const RCString*>(ge nericRCPtr); const RCString* stringPtr = static_cast<const RCString*>(ge nericRCPtr);
return StringData(stringPtr->c_str(), stringPtr->size()); return StringData(stringPtr->c_str(), stringPtr->size());
skipping to change at line 196 skipping to change at line 193
void zero() { void zero() {
memset(this, 0, sizeof(*this)); memset(this, 0, sizeof(*this));
} }
// Byte-for-byte identical // Byte-for-byte identical
bool identical(const ValueStorage& other) const { bool identical(const ValueStorage& other) const {
return (i64[0] == other.i64[0] return (i64[0] == other.i64[0]
&& i64[1] == other.i64[1]); && i64[1] == other.i64[1]);
} }
void verifyRefCountingIfShould() const;
// This data is public because this should only be used by Value wh ich would be a friend // This data is public because this should only be used by Value wh ich would be a friend
union { union {
struct { struct {
// byte 1 // byte 1
signed char type; signed char type;
// byte 2 // byte 2
struct { struct {
bool refCounter : 1; // true if we need to refCount bool refCounter : 1; // true if we need to refCount
bool shortStr : 1; // true if we are using short string s bool shortStr : 1; // true if we are using short string s
 End of changes. 5 change blocks. 
6 lines changed or deleted 1 lines changed or added


 windows_basic.h   windows_basic.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
#if defined(_WIN32) #if !defined(_WIN32)
#error "windows_basic included but _WIN32 is not defined"
#endif
// 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
// these here for things like client driver builds, where they may not alre
ady be set.
#if !defined(_WIN32_WINNT)
// Can't use symbolic versions here, since we may not have seen sdkddkver.h
yet.
#if defined(_WIN64)
// 64-bit builds default to Windows Vista support.
#define _WIN32_WINNT 0x0600
#else
// 32-bit builds default to Windows XP support.
#define _WIN32_WINNT 0x0501
#endif
#endif
// 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
// 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 "mongo/targetver.h"
# 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
// via windows.h above should set it based in _WIN32_WINNT, which is assure
dly set by now.
#if !defined(NTDDI_VERSION)
#error "NTDDI_VERSION is not defined"
#endif
#if !defined(WINVER) || (WINVER != _WIN32_WINNT)
#error "Expected WINVER to have been defined and to equal _WIN32_WINNT"
#endif
#if defined(_WIN64)
#if !defined(NTDDI_VISTA) || (NTDDI_VERSION < NTDDI_VISTA)
#error "64 bit mongo does not support Windows versions older than Vista"
#endif
#else
#if !defined(NTDDI_WINXPSP3) || (NTDDI_VERSION < NTDDI_WINXPSP3)
#error "32 bit mongo does not support Windows versions older than XP Servic
e Pack 3"
#endif
#endif #endif
 End of changes. 3 change blocks. 
2 lines changed or deleted 47 lines changed or added

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