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 ¶ms); | ||||
int getBits() const { return _params.bits; } | ||||
double getError() const { return _error; } | ||||
double getErrorSphere() const { return _errorSphere ;} | ||||
double getMin() const { return _params.min; } | ||||
double getMax() const { return _params.max; } | ||||
double distanceBetweenHashes(const GeoHash& a, const GeoHash& b) co | ||||
nst; | ||||
/** | ||||
* Hashing functions. Convert the following types to a GeoHash: | ||||
* BSONElement | ||||
* BSONObj | ||||
* Point | ||||
* double, double | ||||
*/ | ||||
GeoHash hash(const Point &p) const; | ||||
GeoHash hash(const BSONElement& e) const; | ||||
GeoHash hash(const BSONObj& o) const; | ||||
// src is printed out as debugging information. I'm not sure if it | ||||
's actually | ||||
// somehow the 'source' of o? Anyway, this is nasty, very nasty. | ||||
XXX | ||||
GeoHash hash(const BSONObj& o, const BSONObj* src) const; | ||||
GeoHash hash(double x, double y) const; | ||||
/** Unhashing functions. | ||||
* Convert from a hash to the following types: | ||||
* double, double | ||||
* Point | ||||
* BSONObj | ||||
*/ | ||||
// XXX: these should have consistent naming | ||||
Point unhashToPoint(const GeoHash &h) const; | ||||
Point unhashToPoint(const BSONElement &e) const; | ||||
BSONObj unhashToBSONObj(const GeoHash& h) const; | ||||
void unhash(const GeoHash &h, double *x, double *y) const; | ||||
double sizeOfDiag(const GeoHash& a) const; | ||||
// XXX: understand/clean this. | ||||
double sizeEdge(const GeoHash& a) const; | ||||
private: | ||||
// Convert from an unsigned in [0, (max-min)*scaling] to [min, max] | ||||
double convertFromHashScale(unsigned in) const; | ||||
// Convert from a double that is [min, max] to an unsigned in [0, ( | ||||
max-min)*scaling] | ||||
unsigned convertToHashScale(double in) const; | ||||
Parameters _params; | ||||
// We compute these based on the _params: | ||||
double _error; | ||||
double _errorSphere; | ||||
}; | ||||
} // namespace mongo | ||||
End of changes. 2 change blocks. | ||||
17 lines changed or deleted | 17 lines changed or added | |||
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 ¤tIndex; | return ¤tIndex; | |||
} else { | } else { | |||
bestMultiKeyIndex = ¤tIndex; | bestMultiKeyIndex = ¤tIndex; | |||
} | } | |||
} | } | |||
} | } | |||
return requireSingleKey ? NULL : bestMultiKeyIndex; | return requireSingleKey ? NULL : bestMultiKeyIndex; | |||
} | } | |||
// @return offset in indexes[] | // @return offset in indexes[] | |||
inline int NamespaceDetails::findIndexByName(const char *name, | inline int NamespaceDetails::findIndexByName(const char *name) { | |||
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 | |||