accumulator.h   accumulator.h 
skipping to change at line 121 skipping to change at line 121
/* /*
Create the accumulator. Create the accumulator.
@returns the created accumulator @returns the created accumulator
*/ */
static intrusive_ptr<Accumulator> create( static intrusive_ptr<Accumulator> create(
const intrusive_ptr<ExpressionContext> &pCtx); const intrusive_ptr<ExpressionContext> &pCtx);
private: private:
mutable bool _haveFirst;
AccumulatorFirst(); AccumulatorFirst();
}; };
class AccumulatorLast : class AccumulatorLast :
public AccumulatorSingleValue { public AccumulatorSingleValue {
public: public:
// virtuals from Expression // virtuals from Expression
virtual Value evaluate(const Document& pDocument) const; virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const; virtual const char *getOpName() const;
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 action_set.h   action_set.h 
/** /* Copyright 2012 10gen Inc.
* Copyright (C) 2012 10gen Inc. *
* * Licensed under the Apache License, Version 2.0 (the "License");
* This program is free software: you can redistribute it and/or modify * you may not use this file except in compliance with the License.
* it under the terms of the GNU Affero General Public License, version 3 * You may obtain a copy of the License at
, *
* as published by the Free Software Foundation. * http://www.apache.org/licenses/LICENSE-2.0
* *
* This program is distributed in the hope that it will be useful, * Unless required by applicable law or agreed to in writing, software
* but WITHOUT ANY WARRANTY; without even the implied warranty of * distributed under the License is distributed on an "AS IS" BASIS,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli
* GNU Affero General Public License for more details. ed.
* * See the License for the specific language governing permissions and
* You should have received a copy of the GNU Affero General Public Licen * limitations under the License.
se */
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once #pragma once
#include <bitset> #include <bitset>
#include "mongo/base/status.h" #include "mongo/base/status.h"
#include "mongo/db/auth/action_type.h" #include "mongo/db/auth/action_type.h"
namespace mongo { namespace mongo {
skipping to change at line 39 skipping to change at line 38
*/ */
class ActionSet { class ActionSet {
public: public:
ActionSet() : _actions(0) {} ActionSet() : _actions(0) {}
void addAction(const ActionType& action); void addAction(const ActionType& action);
void addAllActionsFromSet(const ActionSet& actionSet); void addAllActionsFromSet(const ActionSet& actionSet);
void addAllActions(); void addAllActions();
void removeAction(const ActionType& action);
void removeAllActionsFromSet(const ActionSet& actionSet);
void removeAllActions();
bool empty() const { return _actions.none(); }
bool contains(const ActionType& action) const; bool contains(const ActionType& action) const;
// Returns true only if this ActionSet contains all the actions pre sent in the 'other' // Returns true only if this ActionSet contains all the actions pre sent in the 'other'
// ActionSet. // ActionSet.
bool isSupersetOf(const ActionSet& other) const; bool isSupersetOf(const ActionSet& other) const;
// Returns the string representation of this ActionSet // Returns the string representation of this ActionSet
std::string toString() const; std::string toString() const;
// Takes a comma-separated string of action type string representat ions and returns // Takes a comma-separated string of action type string representat ions and returns
 End of changes. 2 change blocks. 
17 lines changed or deleted 21 lines changed or added


 action_type.h   action_type.h 
// AUTO-GENERATED FILE DO NOT EDIT // AUTO-GENERATED FILE DO NOT EDIT
// See src/mongo/db/auth/generate_action_types.py // See src/mongo/db/auth/generate_action_types.py
/* /* Copyright 2012 10gen Inc.
* Copyright (C) 2012 10gen Inc. *
* * Licensed under the Apache License, Version 2.0 (the "License");
* This program is free software: you can redistribute it and/or modify * you may not use this file except in compliance with the License.
* it under the terms of the GNU Affero General Public License, version 3 * You may obtain a copy of the License at
, *
* as published by the Free Software Foundation. * http://www.apache.org/licenses/LICENSE-2.0
* *
* This program is distributed in the hope that it will be useful, * Unless required by applicable law or agreed to in writing, software
* but WITHOUT ANY WARRANTY; without even the implied warranty of * distributed under the License is distributed on an "AS IS" BASIS,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli
* GNU Affero General Public License for more details. ed.
* * See the License for the specific language governing permissions and
* You should have received a copy of the GNU Affero General Public Licen * limitations under the License.
se */
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once #pragma once
#include <iosfwd> #include <iosfwd>
#include <map> #include <map>
#include <string> #include <string>
#include "mongo/base/status.h" #include "mongo/base/status.h"
#include "mongo/platform/cstdint.h" #include "mongo/platform/cstdint.h"
skipping to change at line 55 skipping to change at line 54
// ActionType enum. // ActionType enum.
static Status parseActionFromString(const std::string& actionString , ActionType* result); static Status parseActionFromString(const std::string& actionString , ActionType* result);
// Takes an ActionType and returns the string representation // Takes an ActionType and returns the string representation
static std::string actionToString(const ActionType& action); static std::string actionToString(const ActionType& action);
static const ActionType addShard; static const ActionType addShard;
static const ActionType applyOps; static const ActionType applyOps;
static const ActionType captrunc; static const ActionType captrunc;
static const ActionType clean; static const ActionType clean;
static const ActionType clone;
static const ActionType cloneCollectionLocalSource;
static const ActionType cloneCollectionTarget;
static const ActionType closeAllDatabases; static const ActionType closeAllDatabases;
static const ActionType collMod; static const ActionType collMod;
static const ActionType collStats; static const ActionType collStats;
static const ActionType compact; static const ActionType compact;
static const ActionType connPoolStats; static const ActionType connPoolStats;
static const ActionType connPoolSync; static const ActionType connPoolSync;
static const ActionType convertToCapped; static const ActionType convertToCapped;
static const ActionType cpuProfiler; static const ActionType cpuProfiler;
static const ActionType createCollection; static const ActionType createCollection;
static const ActionType cursorInfo; static const ActionType cursorInfo;
skipping to change at line 84 skipping to change at line 86
static const ActionType find; static const ActionType find;
static const ActionType flushRouterConfig; static const ActionType flushRouterConfig;
static const ActionType fsync; static const ActionType fsync;
static const ActionType getCmdLineOpts; static const ActionType getCmdLineOpts;
static const ActionType getLog; static const ActionType getLog;
static const ActionType getParameter; static const ActionType getParameter;
static const ActionType getShardMap; static const ActionType getShardMap;
static const ActionType getShardVersion; static const ActionType getShardVersion;
static const ActionType handshake; static const ActionType handshake;
static const ActionType hostInfo; static const ActionType hostInfo;
static const ActionType indexStats;
static const ActionType inprog;
static const ActionType insert; static const ActionType insert;
static const ActionType killop;
static const ActionType listDatabases; static const ActionType listDatabases;
static const ActionType listShards; static const ActionType listShards;
static const ActionType logRotate; static const ActionType logRotate;
static const ActionType mapReduceShardedFinish;
static const ActionType moveChunk; static const ActionType moveChunk;
static const ActionType movePrimary; static const ActionType movePrimary;
static const ActionType netstat; static const ActionType netstat;
static const ActionType profile; static const ActionType profileEnable;
static const ActionType profileRead;
static const ActionType reIndex; static const ActionType reIndex;
static const ActionType remove; static const ActionType remove;
static const ActionType removeShard; static const ActionType removeShard;
static const ActionType renameCollection; static const ActionType renameCollectionSameDB;
static const ActionType repairDatabase; static const ActionType repairDatabase;
static const ActionType replSetElect; static const ActionType replSetElect;
static const ActionType replSetFreeze; static const ActionType replSetFreeze;
static const ActionType replSetFresh; static const ActionType replSetFresh;
static const ActionType replSetGetRBID; static const ActionType replSetGetRBID;
static const ActionType replSetGetStatus; static const ActionType replSetGetStatus;
static const ActionType replSetHeartbeat; static const ActionType replSetHeartbeat;
static const ActionType replSetInitiate; static const ActionType replSetInitiate;
static const ActionType replSetMaintenance; static const ActionType replSetMaintenance;
static const ActionType replSetReconfig; static const ActionType replSetReconfig;
static const ActionType replSetStepDown; static const ActionType replSetStepDown;
static const ActionType replSetSyncFrom; static const ActionType replSetSyncFrom;
static const ActionType resync; static const ActionType resync;
static const ActionType serverStatus;
static const ActionType setParameter; static const ActionType setParameter;
static const ActionType setShardVersion; static const ActionType setShardVersion;
static const ActionType shardCollection; static const ActionType shardCollection;
static const ActionType shardingState; static const ActionType shardingState;
static const ActionType shutdown; static const ActionType shutdown;
static const ActionType split; static const ActionType split;
static const ActionType splitChunk; static const ActionType splitChunk;
static const ActionType splitVector; static const ActionType splitVector;
static const ActionType storageDetails;
static const ActionType top; static const ActionType top;
static const ActionType touch; static const ActionType touch;
static const ActionType unlock;
static const ActionType unsetSharding; static const ActionType unsetSharding;
static const ActionType update; static const ActionType update;
static const ActionType userAdmin; static const ActionType userAdmin;
static const ActionType validate; static const ActionType validate;
static const ActionType writebacklisten; static const ActionType writebacklisten;
static const ActionType writeBacksQueued; static const ActionType writeBacksQueued;
static const ActionType _migrateClone; static const ActionType _migrateClone;
static const ActionType _recvChunkAbort; static const ActionType _recvChunkAbort;
static const ActionType _recvChunkCommit; static const ActionType _recvChunkCommit;
static const ActionType _recvChunkStart; static const ActionType _recvChunkStart;
static const ActionType _recvChunkStatus; static const ActionType _recvChunkStatus;
static const ActionType _transferMods; static const ActionType _transferMods;
static const ActionType oldRead;
static const ActionType oldWrite;
enum ActionTypeIdentifier { enum ActionTypeIdentifier {
addShardValue, addShardValue,
applyOpsValue, applyOpsValue,
captruncValue, captruncValue,
cleanValue, cleanValue,
cloneValue,
cloneCollectionLocalSourceValue,
cloneCollectionTargetValue,
closeAllDatabasesValue, closeAllDatabasesValue,
collModValue, collModValue,
collStatsValue, collStatsValue,
compactValue, compactValue,
connPoolStatsValue, connPoolStatsValue,
connPoolSyncValue, connPoolSyncValue,
convertToCappedValue, convertToCappedValue,
cpuProfilerValue, cpuProfilerValue,
createCollectionValue, createCollectionValue,
cursorInfoValue, cursorInfoValue,
skipping to change at line 168 skipping to change at line 179
findValue, findValue,
flushRouterConfigValue, flushRouterConfigValue,
fsyncValue, fsyncValue,
getCmdLineOptsValue, getCmdLineOptsValue,
getLogValue, getLogValue,
getParameterValue, getParameterValue,
getShardMapValue, getShardMapValue,
getShardVersionValue, getShardVersionValue,
handshakeValue, handshakeValue,
hostInfoValue, hostInfoValue,
indexStatsValue,
inprogValue,
insertValue, insertValue,
killopValue,
listDatabasesValue, listDatabasesValue,
listShardsValue, listShardsValue,
logRotateValue, logRotateValue,
mapReduceShardedFinishValue,
moveChunkValue, moveChunkValue,
movePrimaryValue, movePrimaryValue,
netstatValue, netstatValue,
profileValue, profileEnableValue,
profileReadValue,
reIndexValue, reIndexValue,
removeValue, removeValue,
removeShardValue, removeShardValue,
renameCollectionValue, renameCollectionSameDBValue,
repairDatabaseValue, repairDatabaseValue,
replSetElectValue, replSetElectValue,
replSetFreezeValue, replSetFreezeValue,
replSetFreshValue, replSetFreshValue,
replSetGetRBIDValue, replSetGetRBIDValue,
replSetGetStatusValue, replSetGetStatusValue,
replSetHeartbeatValue, replSetHeartbeatValue,
replSetInitiateValue, replSetInitiateValue,
replSetMaintenanceValue, replSetMaintenanceValue,
replSetReconfigValue, replSetReconfigValue,
replSetStepDownValue, replSetStepDownValue,
replSetSyncFromValue, replSetSyncFromValue,
resyncValue, resyncValue,
serverStatusValue,
setParameterValue, setParameterValue,
setShardVersionValue, setShardVersionValue,
shardCollectionValue, shardCollectionValue,
shardingStateValue, shardingStateValue,
shutdownValue, shutdownValue,
splitValue, splitValue,
splitChunkValue, splitChunkValue,
splitVectorValue, splitVectorValue,
storageDetailsValue,
topValue, topValue,
touchValue, touchValue,
unlockValue,
unsetShardingValue, unsetShardingValue,
updateValue, updateValue,
userAdminValue, userAdminValue,
validateValue, validateValue,
writebacklistenValue, writebacklistenValue,
writeBacksQueuedValue, writeBacksQueuedValue,
_migrateCloneValue, _migrateCloneValue,
_recvChunkAbortValue, _recvChunkAbortValue,
_recvChunkCommitValue, _recvChunkCommitValue,
_recvChunkStartValue, _recvChunkStartValue,
_recvChunkStatusValue, _recvChunkStatusValue,
_transferModsValue, _transferModsValue,
oldReadValue,
oldWriteValue,
actionTypeEndValue, // Should always be last in this enum actionTypeEndValue, // Should always be last in this enum
}; };
static const int NUM_ACTION_TYPES = actionTypeEndValue; static const int NUM_ACTION_TYPES = actionTypeEndValue;
private: private:
uint32_t _identifier; // unique identifier for this action. uint32_t _identifier; // unique identifier for this action.
}; };
 End of changes. 21 change blocks. 
25 lines changed or deleted 41 lines changed or added


 alignedbuilder.h   alignedbuilder.h 
skipping to change at line 91 skipping to change at line 91
} }
void appendBuf(const void *src, size_t len) { memcpy(grow((unsigned ) len), src, len); } void appendBuf(const void *src, size_t len) { memcpy(grow((unsigned ) len), src, len); }
template<class T> template<class T>
void appendStruct(const T& s) { appendBuf(&s, sizeof(T)); } void appendStruct(const T& s) { appendBuf(&s, sizeof(T)); }
void appendStr(const StringData &str , bool includeEOO = true ) { void appendStr(const StringData &str , bool includeEOO = true ) {
const unsigned len = str.size() + ( includeEOO ? 1 : 0 ); const unsigned len = str.size() + ( includeEOO ? 1 : 0 );
verify( len < (unsigned) BSONObjMaxUserSize ); verify( len < (unsigned) BSONObjMaxUserSize );
memcpy(grow(len), str.data(), len); str.copyTo( grow(len), includeEOO );
} }
/** @return the in-use length */ /** @return the in-use length */
unsigned len() const { return _len; } unsigned len() const { return _len; }
private: private:
static const unsigned Alignment = 8192; static const unsigned Alignment = 8192;
/** returns the pre-grow write position */ /** returns the pre-grow write position */
inline char* grow(unsigned by) { inline char* grow(unsigned by) {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 assert_util.h   assert_util.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 <iostream> #include <iostream>
#include <typeinfo> #include <typeinfo>
#include <string> #include <string>
#include "mongo/base/status.h" // NOTE: This is safe as utils depend on bas e
#include "mongo/bson/inline_decls.h" #include "mongo/bson/inline_decls.h"
#include "mongo/platform/compiler.h" #include "mongo/platform/compiler.h"
namespace mongo { namespace mongo {
enum CommonErrorCodes { enum CommonErrorCodes {
DatabaseDifferCaseCode = 13297 , DatabaseDifferCaseCode = 13297 ,
SendStaleConfigCode = 13388 , SendStaleConfigCode = 13388 ,
RecvStaleConfigCode = 9996 RecvStaleConfigCode = 9996
}; };
skipping to change at line 103 skipping to change at line 104
DBException( const std::string& msg , int code ) : _ei(msg,code) { traceIfNeeded(*this); } DBException( const std::string& msg , int code ) : _ei(msg,code) { traceIfNeeded(*this); }
virtual ~DBException() throw() { } virtual ~DBException() throw() { }
virtual const char* what() const throw() { return _ei.msg.c_str(); } virtual const char* what() const throw() { return _ei.msg.c_str(); }
virtual int getCode() const { return _ei.code; } virtual int getCode() const { return _ei.code; }
virtual void appendPrefix( std::stringstream& ss ) const { } virtual void appendPrefix( std::stringstream& ss ) const { }
virtual void addContext( const std::string& str ) { virtual void addContext( const std::string& str ) {
_ei.msg = str + causedBy( _ei.msg ); _ei.msg = str + causedBy( _ei.msg );
} }
// Utilities for the migration to Status objects
static ErrorCodes::Error convertExceptionCode(int exCode);
Status toStatus(const std::string& context) const {
return Status(convertExceptionCode(getCode()), context + caused
By(*this));
}
Status toStatus() const {
return Status(convertExceptionCode(getCode()), this->toString()
);
}
// context when applicable. otherwise "" // context when applicable. otherwise ""
std::string _shard; std::string _shard;
virtual std::string toString() const; virtual std::string toString() const;
const ExceptionInfo& getInfo() const { return _ei; } const ExceptionInfo& getInfo() const { return _ei; }
private: private:
static void traceIfNeeded( const DBException& e ); static void traceIfNeeded( const DBException& e );
public: public:
static bool traceExceptions; static bool traceExceptions;
skipping to change at line 178 skipping to change at line 189
msgassertedNoTrace( msgid , msg.c_str() ); msgassertedNoTrace( msgid , msg.c_str() );
} }
MONGO_COMPILER_NORETURN void msgasserted(int msgid, const char *msg); MONGO_COMPILER_NORETURN void msgasserted(int msgid, const char *msg);
MONGO_COMPILER_NORETURN void msgasserted(int msgid, const std::string & msg); MONGO_COMPILER_NORETURN void msgasserted(int msgid, const std::string & msg);
/* convert various types of exceptions to strings */ /* convert various types of exceptions to strings */
inline std::string causedBy( const char* e ){ return (std::string)" :: caused by :: " + e; } inline std::string causedBy( const char* e ){ return (std::string)" :: caused by :: " + e; }
inline std::string causedBy( const DBException& e ){ return causedBy( e .toString().c_str() ); } inline std::string causedBy( const DBException& e ){ return causedBy( e .toString().c_str() ); }
inline std::string causedBy( const std::exception& e ){ return causedBy ( e.what() ); } inline std::string causedBy( const std::exception& e ){ return causedBy ( e.what() ); }
inline std::string causedBy( const std::string& e ){ return causedBy( e .c_str() ); } inline std::string causedBy( const std::string& e ){ return causedBy( e .c_str() ); }
inline std::string causedBy( const std::string* e ){
return (e && *e != "") ? causedBy(*e) : "";
}
inline std::string causedBy( const Status& e ){ return causedBy( e.reas
on() ); }
/** aborts on condition failure */ /** aborts on condition failure */
inline void fassert(int msgid, bool testOK) {if (MONGO_unlikely(!testOK )) fassertFailed(msgid);} inline void fassert(int msgid, bool testOK) {if (MONGO_unlikely(!testOK )) fassertFailed(msgid);}
/* "user assert". if asserts, user did something wrong, not our code * / /* "user assert". if asserts, user did something wrong, not our code * /
#define MONGO_uassert(msgid, msg, expr) (void)( MONGO_likely(!!(expr)) || ( mongo::uasserted(msgid, msg), 0) ) #define MONGO_uassert(msgid, msg, expr) (void)( MONGO_likely(!!(expr)) || ( mongo::uasserted(msgid, msg), 0) )
#define MONGO_uassertStatusOK(expr) do { \
Status status = (expr); \
if (!status.isOK()) \
uasserted(status.location() != 0 ? status.location() : status.c
ode(), \
status.reason()); \
} while(0)
/* warning only - keeps going */ /* warning only - keeps going */
#define MONGO_wassert(_Expression) (void)( MONGO_likely(!!(_Expression)) || (mongo::wasserted(#_Expression, __FILE__, __LINE__), 0) ) #define MONGO_wassert(_Expression) (void)( MONGO_likely(!!(_Expression)) || (mongo::wasserted(#_Expression, __FILE__, __LINE__), 0) )
/* display a message, no context, and throw assertionexception /* display a message, no context, and throw assertionexception
easy way to throw an exception and log something without our stack t race easy way to throw an exception and log something without our stack t race
display happening. display happening.
*/ */
#define MONGO_massert(msgid, msg, expr) (void)( MONGO_likely(!!(expr)) || ( mongo::msgasserted(msgid, msg), 0) ) #define MONGO_massert(msgid, msg, expr) (void)( MONGO_likely(!!(expr)) || ( mongo::msgasserted(msgid, msg), 0) )
/* same as massert except no msgid */ /* same as massert except no msgid */
skipping to change at line 206 skipping to change at line 228
/* dassert is 'debug assert' -- might want to turn off for production a s these /* dassert is 'debug assert' -- might want to turn off for production a s these
could be slow. could be slow.
*/ */
#if defined(_DEBUG) #if defined(_DEBUG)
# define MONGO_dassert(x) fassert(16199, (x)) # define MONGO_dassert(x) fassert(16199, (x))
#else #else
# define MONGO_dassert(x) # define MONGO_dassert(x)
#endif #endif
/** Allows to jump code during exeuction. */
inline bool debugCompare(bool inDebug, bool condition) { return inDebug
&& condition; }
#if defined(_DEBUG)
# define MONGO_debug_and(x) debugCompare(true, (x))
#else
# define MONGO_debug_and(x) debugCompare(false, (x))
#endif
#ifdef MONGO_EXPOSE_MACROS #ifdef MONGO_EXPOSE_MACROS
# define dcompare MONGO_debug_and
# define dassert MONGO_dassert # define dassert MONGO_dassert
# define verify MONGO_verify # define verify MONGO_verify
# define uassert MONGO_uassert # define uassert MONGO_uassert
# define uassertStatusOK MONGO_uassertStatusOK
# define wassert MONGO_wassert # define wassert MONGO_wassert
# define massert MONGO_massert # define massert MONGO_massert
#endif #endif
// some special ids that we want to duplicate // some special ids that we want to duplicate
// > 10000 asserts // > 10000 asserts
// < 10000 UserException // < 10000 UserException
enum { ASSERT_ID_DUPKEY = 11000 }; enum { ASSERT_ID_DUPKEY = 11000 };
 End of changes. 7 change blocks. 
0 lines changed or deleted 38 lines changed or added


 auth_external_state.h   auth_external_state.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 <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"
namespace mongo { namespace mongo {
/** /**
* 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:
virtual ~AuthExternalState() {}; virtual ~AuthExternalState();
// Returns true if this connection should be treated as if it has f ull access to do // Returns true if this connection should be treated as if it has f ull access to do
// anything, regardless of the current auth state. Currently the r easons why this could be // anything, regardless of the current auth state. Currently the r easons why this could be
// are that auth isn't enabled, the connection is from localhost an // are that auth isn't enabled, the connection is from localhost an
d there are admin users, d there are no admin
// or the connection is a "god" connection. // users, or the connection is a "god" connection.
// NOTE: _checkShouldAllowLocalhost MUST be called at least once be
fore any call to
// shouldIgnoreAuthChecks or we could ignore auth checks incorrectl
y.
virtual bool shouldIgnoreAuthChecks() const = 0; virtual bool shouldIgnoreAuthChecks() const = 0;
// adminDBConnection is a connection that can be used to access the // Should be called at the beginning of every new request. This pe
admin database. It is rforms the checks
// used to determine if there are any admin users configured for th // necessary to determine if localhost connections should be given
e cluster, and thus if full access.
// localhost connections should be given special admin access. virtual void startRequest() = 0;
// This function *must* be called on any new AuthExternalState, aft
er the constructor but // Gets the privilege information document for "principalName" on "
// before any other methods are called on the AuthExternalState. dbname".
virtual Status initialize(DBClientBase* adminDBConnection) = 0; //
// On success, returns Status::OK() and stores a shared-ownership c
opy of the document into
// "result".
Status getPrivilegeDocument(const std::string& dbname,
const PrincipalName& principalName,
BSONObj* result);
protected: protected:
AuthExternalState() {}; // This class should never be instantiated AuthExternalState(); // This class should never be instantiated dir
directly. ectly.
// 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.
virtual bool _findUser(const std::string& usersNamespace,
const BSONObj& query,
BSONObj* result) const = 0;
// Returns true if there exists at least one privilege document in
the given database.
bool _hasPrivilegeDocument(const std::string& dbname) const;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 6 change blocks. 
15 lines changed or deleted 40 lines changed or added


 auth_external_state_mock.h   auth_external_state_mock.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/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/db/auth/auth_external_state.h" #include "mongo/db/auth/auth_external_state.h"
namespace mongo { namespace mongo {
/** /**
* Mock of the AuthExternalState class used only for testing. * Mock of the AuthExternalState class used only for testing.
*/ */
class AuthExternalStateMock : public AuthExternalState { class AuthExternalStateMock : public AuthExternalState {
MONGO_DISALLOW_COPYING(AuthExternalStateMock); MONGO_DISALLOW_COPYING(AuthExternalStateMock);
skipping to change at line 43 skipping to change at line 42
AuthExternalStateMock() : _returnValue(false) {} AuthExternalStateMock() : _returnValue(false) {}
virtual bool shouldIgnoreAuthChecks() const { virtual bool shouldIgnoreAuthChecks() const {
return _returnValue; return _returnValue;
} }
void setReturnValueForShouldIgnoreAuthChecks(bool returnValue) { void setReturnValueForShouldIgnoreAuthChecks(bool returnValue) {
_returnValue = returnValue; _returnValue = returnValue;
} }
// This is a no-op for the mock virtual bool _findUser(const std::string& usersNamespace,
virtual Status initialize(DBClientBase* adminDBConnection) { return const BSONObj& query,
Status::OK(); } BSONObj* result) const {
return false;
}
virtual void startRequest() {}
private: private:
bool _returnValue; bool _returnValue;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 2 change blocks. 
4 lines changed or deleted 7 lines changed or added


 authentication_session.h   authentication_session.h 
/* /* Copyright 2012 10gen Inc.
* Copyright (C) 2012 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License");
* it under the terms of the GNU Affero General Public License, version * you may not use this file except in compliance with the License.
3, * You may obtain a copy of the License at
* as published by the Free Software Foundation.
* *
* 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
* GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Lice * Unless required by applicable law or agreed to in writing, software
nse * distributed under the License is distributed on an "AS IS" BASIS,
* along with this program. If not, see <http://www.gnu.org/licenses/>. * 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.
*/ */
#pragma once #pragma once
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
namespace mongo { namespace mongo {
/** /**
* Abstract type representing an ongoing authentication session. * Abstract type representing an ongoing authentication session.
 End of changes. 4 change blocks. 
13 lines changed or deleted 11 lines changed or added


 authorization_manager.h   authorization_manager.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 <string> #include <string>
#include <vector>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
#include "mongo/base/status.h" #include "mongo/base/status.h"
#include "mongo/client/dbclientinterface.h"
#include "mongo/db/auth/acquired_privilege.h"
#include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h" #include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/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_set.h" #include "mongo/db/auth/principal_set.h"
#include "mongo/db/auth/privilege.h"
#include "mongo/db/auth/privilege_set.h" #include "mongo/db/auth/privilege_set.h"
namespace mongo { namespace mongo {
// --noauth cmd line option
extern bool noauth;
/**
* Internal secret key info.
*/
struct AuthInfo {
AuthInfo();
string user;
string pwd;
};
extern AuthInfo internalSecurity; // set at startup and not changed aft
er initialization.
/** /**
* Contains all the authorization logic for a single client connection. It contains a set of * Contains all the authorization logic for a single client connection. It contains a set of
* the principals which have been authenticated, as well as a set of pr ivileges that have been * the principals which have been authenticated, as well as a set of pr ivileges that have been
* granted by those principals to perform various actions. * granted by those principals to perform various actions.
* An AuthorizationManager object is present within every mongo::Client object, therefore there * An AuthorizationManager object is present within every mongo::Client object, therefore there
* is one per thread that corresponds to an incoming client connection. * is one per thread that corresponds to an incoming client connection.
*/ */
class AuthorizationManager { class AuthorizationManager {
MONGO_DISALLOW_COPYING(AuthorizationManager); MONGO_DISALLOW_COPYING(AuthorizationManager);
public: public:
static const std::string SERVER_RESOURCE_NAME;
static const std::string CLUSTER_RESOURCE_NAME;
static const std::string USER_NAME_FIELD_NAME;
static const std::string USER_SOURCE_FIELD_NAME;
static const std::string PASSWORD_FIELD_NAME;
static void setSupportOldStylePrivilegeDocuments(bool enabled);
// Checks to see if "doc" is a valid privilege document, assuming i
t is stored in the
// "system.users" collection of database "dbname".
//
// Returns Status::OK() if the document is good, or Status(ErrorCod
es::BadValue), otherwise.
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();
// adminDBConnection is a connection that can be used to access the // Should be called at the beginning of every new request. This pe
admin database. It is rforms the checks
// used to determine if there are any admin users configured for th // necessary to determine if localhost connections should be given
e cluster, and thus if full access.
// localhost connections should be given special admin access. // TODO: try to eliminate the need for this call.
// This function *must* be called on any new AuthorizationManager, void startRequest();
after the constructor but
// before any other methods are called on the AuthorizationManager.
Status initialize(DBClientBase* adminDBConnection);
// Takes ownership of the principal (by putting into _authenticated Principals). // Adds "principal" to the authorization manager, and takes ownersh ip of it.
void addAuthorizedPrincipal(Principal* principal); void addAuthorizedPrincipal(Principal* principal);
// Removes and deletes the given principal from the set of authenti // Returns the authenticated principal with the given name. Return
cated principals. s NULL
// Return an error Status if the given principal isn't a member of // if no such user is found.
the
// _authenticatedPrincipals set.
Status removeAuthorizedPrincipal(const Principal* principal);
// Returns NULL if not found
// Ownership of the returned Principal remains with _authenticatedP rincipals // Ownership of the returned Principal remains with _authenticatedP rincipals
Principal* lookupPrincipal(const std::string& name) const; Principal* lookupPrincipal(const PrincipalName& name);
// Gets an iterator over the names of all authenticated principals
stored in this manager.
PrincipalSet::NameIterator getAuthenticatedPrincipalNames();
// Removes any authenticated principals whose authorization credent
ials came from the given
// database, and revokes any privileges that were granted via that
principal.
void logoutDatabase(const std::string& dbname);
// Grant this connection the given privilege. // Grant this connection the given privilege.
Status acquirePrivilege(const AcquiredPrivilege& privilege); Status acquirePrivilege(const Privilege& privilege,
const PrincipalName& authorizingPrincipal);
// This should be called when the connection gets authenticated as // Adds a new principal with the given principal name and authorize
the internal user. s it with full access.
// This grants a privilege on all the actions for the internal role // Used to grant internal threads full access.
, with the void grantInternalAuthorization(const std::string& principalName);
// internalPrincipal as the principal.
void grantInternalAuthorization(); // Checks if this connection has been authenticated as an internal
user.
bool hasInternalAuthorization();
// Checks if this connection has the privileges required to perform the given action // Checks if this connection has the privileges required to perform the given action
// on the given resource. Contains all the authorization logic inc luding handling things // on the given resource. Contains all the authorization logic inc luding handling things
// like the localhost exception. If it is authorized, returns the // like the localhost exception. Returns true if the action may pr
principal that granted oceed on the resource.
// the needed privilege. Returns NULL if not authorized. If the a bool checkAuthorization(const std::string& resource, ActionType act
ction is authorized but ion);
// not because of a standard user Principal but for a special reaso
n such as the localhost // Same as above but takes an ActionSet instead of a single ActionT
// exception, it returns a pointer to specialAdminPrincipal. ype. Returns true if
const Principal* checkAuthorization(const std::string& resource, Ac // all of the actions may proceed on the resource.
tionType action) const; bool checkAuthorization(const std::string& resource, ActionSet acti
ons);
// Parses the privilege documents and acquires all privileges that
the privilege document
// grants
Status acquirePrivilegesFromPrivilegeDocument(const std::string& db
name,
const PrincipalName&
principal,
const BSONObj& privil
egeDocument);
// Returns the privilege document with the given user name in the g iven database. Currently // Returns the privilege document with the given user name in the g iven database. Currently
// this information comes from the system.users collection in that database. // this information comes from the system.users collection in that database.
static Status getPrivilegeDocument(DBClientBase* conn, Status getPrivilegeDocument(const std::string& dbname,
const std::string& dbname, const PrincipalName& userName,
const std::string& userName, BSONObj* result) {
BSONObj* result); return _externalState->getPrivilegeDocument(dbname, userName, r
esult);
// Returns true if there exists at least one privilege document in }
the given database.
static bool hasPrivilegeDocument(DBClientBase* conn, const std::str // Checks if this connection has the privileges necessary to perfor
ing& dbname); m a query on the given
// namespace.
Status checkAuthForQuery(const std::string& ns);
// Checks if this connection has the privileges necessary to perfor
m an update on the given
// namespace.
Status checkAuthForUpdate(const std::string& ns, bool upsert);
// Checks if this connection has the privileges necessary to perfor
m an insert to the given
// namespace.
Status checkAuthForInsert(const std::string& ns);
// Checks if this connection has the privileges necessary to perfor
m a delete on the given
// namespace.
Status checkAuthForDelete(const std::string& ns);
// Checks if this connection has the privileges necessary to perfor
m a getMore on the given
// namespace.
Status checkAuthForGetMore(const std::string& ns);
// Checks if this connection is authorized for the given Privilege.
Status checkAuthForPrivilege(const Privilege& privilege);
// Checks if this connection is authorized for all the given Privil
eges.
Status checkAuthForPrivileges(const vector<Privilege>& privileges);
// Given a database name and a readOnly flag return an ActionSet de
scribing all the actions
// that an old-style user with those attributes should be given.
static ActionSet getActionsForOldStyleUser(const std::string& dbnam
e, bool readOnly);
// Parses the privilege document and returns a PrivilegeSet of all the Capabilities that // Parses the privilege document and returns a PrivilegeSet of all the Privileges that
// the privilege document grants. // the privilege document grants.
static Status buildPrivilegeSet(const std::string& dbname, static Status buildPrivilegeSet(const std::string& dbname,
Principal* principal, const PrincipalName& principal,
const BSONObj& privilegeDocument, const BSONObj& privilegeDocument,
PrivilegeSet* result); PrivilegeSet* result);
// Returns an ActionSet of all actions that can be be granted to us
ers. This does not
// include internal-only actions.
static ActionSet getAllUserActions();
private: private:
// Finds the set of privileges attributed to "principal" in databas
e "dbname",
// and adds them to the set of acquired privileges.
void _acquirePrivilegesForPrincipalFromDatabase(const std::string&
dbname,
const PrincipalName
& principal);
// Checks to see if the given privilege is allowed, performing impl
icit privilege
// acquisition if enabled and necessary to resolve the privilege.
Status _probeForPrivilege(const Privilege& privilege);
// Parses the old-style (pre 2.4) privilege document and returns a PrivilegeSet of all the // Parses the old-style (pre 2.4) privilege document and returns a PrivilegeSet of all the
// Privileges that the privilege document grants. // Privileges that the privilege document grants.
static Status _buildPrivilegeSetFromOldStylePrivilegeDocument( static Status _buildPrivilegeSetFromOldStylePrivilegeDocument(
const std::string& dbname, const std::string& dbname,
Principal* principal, const PrincipalName& principal,
const BSONObj& privilegeDocument,
PrivilegeSet* result);
// Parses extended-form (2.4+) privilege documents and returns a Pr
ivilegeSet of all the
// privileges that the document grants.
//
// The document, "privilegeDocument", is assumed to describe privil
eges for "principal", and
// to come from database "dbname".
static Status _buildPrivilegeSetFromExtendedPrivilegeDocument(
const std::string& dbname,
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
// certain namespaces like system.users and system.profile.
Privilege _modifyPrivilegeForSpecialCases(const Privilege& privileg
e);
static bool _doesSupportOldStylePrivileges;
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;
bool _initialized;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 21 change blocks. 
50 lines changed or deleted 172 lines changed or added


 balance.h   balance.h 
skipping to change at line 87 skipping to change at line 87
* *
* @param conn is the connection with the config server(s) * @param conn is the connection with the config server(s)
* @param candidateChunks (IN/OUT) filled with candidate chunks, on e per collection, that could possibly be moved * @param candidateChunks (IN/OUT) filled with candidate chunks, on e per collection, that could possibly be moved
*/ */
void _doBalanceRound( DBClientBase& conn, vector<CandidateChunkPtr> * candidateChunks ); void _doBalanceRound( DBClientBase& conn, vector<CandidateChunkPtr> * candidateChunks );
/** /**
* Issues chunk migration request, one at a time. * Issues chunk migration request, one at a time.
* *
* @param candidateChunks possible chunks to move * @param candidateChunks possible chunks to move
* @param secondaryThrottle wait for secondaries to catch up before
pushing more deletes
* @param waitForDelete wait for deletes to complete after each chu
nk move
* @return number of chunks effectively moved * @return number of chunks effectively moved
*/ */
int _moveChunks( const vector<CandidateChunkPtr>* candidateChunks , int _moveChunks(const vector<CandidateChunkPtr>* candidateChunks,
bool secondaryThrottle ); bool secondaryThrottle,
bool waitForDelete);
/** /**
* Marks this balancer as being live on the config server(s). * Marks this balancer as being live on the config server(s).
* *
* @param conn is the connection with the config server(s) * @param conn is the connection with the config server(s)
*/ */
void _ping( DBClientBase& conn, bool waiting = false ); void _ping( DBClientBase& conn, bool waiting = false );
/** /**
* @return true if all the servers listed in configdb as being shar ds are reachable and are distinct processes * @return true if all the servers listed in configdb as being shar ds are reachable and are distinct processes
 End of changes. 2 change blocks. 
2 lines changed or deleted 7 lines changed or added


 balancer_policy.h   balancer_policy.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/>.
*/ */
#ifndef S_BALANCER_POLICY_HEADER #ifndef S_BALANCER_POLICY_HEADER
#define S_BALANCER_POLICY_HEADER #define S_BALANCER_POLICY_HEADER
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/s/cluster_constants.h" #include "mongo/s/type_chunk.h"
namespace mongo { namespace mongo {
struct ChunkInfo { struct ChunkInfo {
const BSONObj min; const BSONObj min;
const BSONObj max; const BSONObj max;
ChunkInfo( const BSONObj& a_min, const BSONObj& a_max ) ChunkInfo( const BSONObj& a_min, const BSONObj& a_max )
: min( a_min.getOwned() ), max( a_max.getOwned() ){} : min( a_min.getOwned() ), max( a_max.getOwned() ){}
ChunkInfo( const BSONObj& chunk ) ChunkInfo( const BSONObj& chunk )
: min(chunk[ChunkFields::min()].Obj().getOwned()), : min(chunk[ChunkType::min()].Obj().getOwned()),
max(chunk[ChunkFields::max()].Obj().getOwned()) { max(chunk[ChunkType::max()].Obj().getOwned()) {
} }
string toString() const; string toString() const;
}; };
struct TagRange { struct TagRange {
BSONObj min; BSONObj min;
BSONObj max; BSONObj max;
string tag; string tag;
skipping to change at line 193 skipping to change at line 193
* @param ns is the collections namepace. * @param ns is the collections namepace.
* @param DistributionStatus holds all the info about the current s tate of the cluster/namespace * @param DistributionStatus holds all the info about the current s tate of the cluster/namespace
* @param balancedLastTime is the number of chunks effectively move d in the last round. * @param balancedLastTime is the number of chunks effectively move d in the last round.
* @returns NULL or MigrateInfo of the best move to make towards ba lacing the collection. * @returns NULL or MigrateInfo of the best move to make towards ba lacing the collection.
* caller owns the MigrateInfo instance * caller owns the MigrateInfo instance
*/ */
static MigrateInfo* balance( const string& ns, static MigrateInfo* balance( const string& ns,
const DistributionStatus& distribution , const DistributionStatus& distribution ,
int balancedLastTime ); int balancedLastTime );
private:
static bool _isJumbo( const BSONObj& chunk );
}; };
} // namespace mongo } // namespace mongo
#endif // S_BALANCER_POLICY_HEADER #endif // S_BALANCER_POLICY_HEADER
 End of changes. 3 change blocks. 
3 lines changed or deleted 5 lines changed or added


 base64.h   base64.h 
skipping to change at line 64 skipping to change at line 64
extern Alphabet alphabet; extern Alphabet alphabet;
void encode( stringstream& ss , const char * data , int size ); void encode( stringstream& ss , const char * data , int size );
string encode( const char * data , int size ); string encode( const char * data , int size );
string encode( const string& s ); string encode( const string& s );
void decode( stringstream& ss , const string& s ); void decode( stringstream& ss , const string& s );
string decode( const string& s ); string decode( const string& s );
extern const char* chars;
void testAlphabet(); void testAlphabet();
} }
} }
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 bgsync.h   bgsync.h 
skipping to change at line 75 skipping to change at line 75
// _mutex protects all of the class variables // _mutex protects all of the class variables
boost::mutex _mutex; boost::mutex _mutex;
// Production thread // Production thread
BlockingQueue<BSONObj> _buffer; BlockingQueue<BSONObj> _buffer;
OpTime _lastOpTimeFetched; OpTime _lastOpTimeFetched;
long long _lastH; long long _lastH;
// if produce thread should be running // if produce thread should be running
bool _pause; bool _pause;
bool _appliedBuffer;
bool _assumingPrimary;
boost::condition _condvar;
const Member* _currentSyncTarget; const Member* _currentSyncTarget;
// Notifier thread // Notifier thread
// used to wait until another op has been replicated // used to wait until another op has been replicated
boost::condition_variable _lastOpCond; boost::condition_variable _lastOpCond;
boost::mutex _lastOpMutex; boost::mutex _lastOpMutex;
const Member* _oplogMarkerTarget; const Member* _oplogMarkerTarget;
skipping to change at line 105 skipping to change at line 108
BackgroundSync(const BackgroundSync& s); BackgroundSync(const BackgroundSync& s);
BackgroundSync operator=(const BackgroundSync& s); BackgroundSync operator=(const BackgroundSync& s);
// Production thread // Production thread
void _producerThread(); void _producerThread();
// Adds elements to the list, up to maxSize. // Adds elements to the list, up to maxSize.
void produce(); void produce();
// Check if rollback is necessary // Check if rollback is necessary
bool isRollbackRequired(OplogReader& r); bool isRollbackRequired(OplogReader& r);
void getOplogReader(OplogReader& r); void getOplogReader(OplogReader& r);
// Evaluate if the current sync target is still good
bool shouldChangeSyncTarget();
// check lastOpTimeWritten against the remote's earliest op, fillin g in remoteOldestOp. // check lastOpTimeWritten against the remote's earliest op, fillin g in remoteOldestOp.
bool isStale(OplogReader& r, BSONObj& remoteOldestOp); bool isStale(OplogReader& r, BSONObj& remoteOldestOp);
// stop syncing when this becomes a primary // stop syncing when this becomes a primary
void stop(); void stop();
// restart syncing // restart syncing
void start(); void start();
// Tracker thread // Tracker thread
// tells the sync target where this member is synced to // tells the sync target where this member is synced to
void markOplog(); void markOplog();
bool hasCursor(); bool hasCursor();
bool isAssumingPrimary();
public: public:
static BackgroundSync* get(); static BackgroundSync* get();
static void shutdown(); static void shutdown();
static void notify(); static void notify();
virtual ~BackgroundSync() {} virtual ~BackgroundSync() {}
// starts the producer thread // starts the producer thread
void producerThread(); void producerThread();
// starts the sync target notifying thread // starts the sync target notifying thread
skipping to change at line 137 skipping to change at line 145
// Interface implementation // Interface implementation
virtual bool peek(BSONObj* op); virtual bool peek(BSONObj* op);
virtual void consume(); virtual void consume();
virtual const Member* getSyncTarget(); virtual const Member* getSyncTarget();
virtual void waitForMore(); virtual void waitForMore();
// For monitoring // For monitoring
BSONObj getCounters(); BSONObj getCounters();
// Wait for replication to finish and buffer to be applied so that
the member can become
// primary.
void stopReplicationAndFlushBuffer();
}; };
} // namespace replset } // namespace replset
} // namespace mongo } // namespace mongo
 End of changes. 4 change blocks. 
0 lines changed or deleted 13 lines changed or added


 bson-inl.h   bson-inl.h 
skipping to change at line 268 skipping to change at line 268
break; break;
} }
} }
} }
} }
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 ( strcmp(e.fieldName(), name.data()) == 0 ) 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 char *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();
} }
skipping to change at line 334 skipping to change at line 334
inline bool BSONObj::getObjectID(BSONElement& e) const { inline bool BSONObj::getObjectID(BSONElement& e) const {
BSONElement f = getField("_id"); BSONElement f = getField("_id");
if( !f.eoo() ) { if( !f.eoo() ) {
e = f; e = f;
return true; return true;
} }
return false; return false;
} }
inline BSONObjBuilderValueStream::BSONObjBuilderValueStream( BSONObjBui lder * builder ) { inline BSONObjBuilderValueStream::BSONObjBuilderValueStream( BSONObjBui lder * builder ) {
_fieldName = 0;
_builder = builder; _builder = builder;
} }
template<class T> template<class T>
inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<( T value ) { inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<( T value ) {
_builder->append(_fieldName, value); _builder->append(_fieldName, value);
_fieldName = 0; _fieldName = StringData();
return *_builder; return *_builder;
} }
inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<( const BSO NElement& e ) { inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<( const BSO NElement& e ) {
_builder->appendAs( e , _fieldName ); _builder->appendAs( e , _fieldName );
_fieldName = 0; _fieldName = StringData();
return *_builder; return *_builder;
} }
inline BufBuilder& BSONObjBuilderValueStream::subobjStart() {
StringData tmp = _fieldName;
_fieldName = StringData();
return _builder->subobjStart(tmp);
}
inline BufBuilder& BSONObjBuilderValueStream::subarrayStart() {
StringData tmp = _fieldName;
_fieldName = StringData();
return _builder->subarrayStart(tmp);
}
inline Labeler BSONObjBuilderValueStream::operator<<( const Labeler::La bel &l ) { inline Labeler BSONObjBuilderValueStream::operator<<( const Labeler::La bel &l ) {
return Labeler( l, this ); return Labeler( l, this );
} }
inline void BSONObjBuilderValueStream::endField( const char *nextFieldN inline void BSONObjBuilderValueStream::endField( const StringData& next
ame ) { FieldName ) {
if ( _fieldName && haveSubobj() ) { if ( haveSubobj() ) {
verify( _fieldName.rawData() );
_builder->append( _fieldName, subobj()->done() ); _builder->append( _fieldName, subobj()->done() );
} }
_subobj.reset(); _subobj.reset();
_fieldName = nextFieldName; _fieldName = nextFieldName;
} }
inline BSONObjBuilder *BSONObjBuilderValueStream::subobj() { inline BSONObjBuilder *BSONObjBuilderValueStream::subobj() {
if ( !haveSubobj() ) if ( !haveSubobj() )
_subobj.reset( new BSONObjBuilder() ); _subobj.reset( new BSONObjBuilder() );
return _subobj.get(); return _subobj.get();
skipping to change at line 406 skipping to change at line 418
inline BSONObjIterator BSONObjBuilder::iterator() const { inline BSONObjIterator BSONObjBuilder::iterator() const {
const char * s = _b.buf() + _offset; const char * s = _b.buf() + _offset;
const char * e = _b.buf() + _b.len(); const char * e = _b.buf() + _b.len();
return BSONObjIterator( s , e ); return BSONObjIterator( s , e );
} }
inline bool BSONObjBuilder::hasField( const StringData& name ) const { inline bool BSONObjBuilder::hasField( const StringData& name ) const {
BSONObjIterator i = iterator(); BSONObjIterator i = iterator();
while ( i.more() ) while ( i.more() )
if ( strcmp( name.data() , i.next().fieldName() ) == 0 ) if ( name == i.next().fieldName() )
return true; return true;
return false; return false;
} }
/* WARNING: nested/dotted conversions are not 100% reversible /* WARNING: nested/dotted conversions are not 100% reversible
* nested2dotted(dotted2nested({a.b: {c:1}})) -> {a.b.c: 1} * nested2dotted(dotted2nested({a.b: {c:1}})) -> {a.b.c: 1}
* also, dotted2nested ignores order * also, dotted2nested ignores order
*/ */
typedef std::map<std::string, BSONElement> BSONMap; typedef std::map<std::string, BSONElement> BSONMap;
skipping to change at line 994 skipping to change at line 1006
verify( ! i.more() ); verify( ! i.more() );
verify( ! j.more() ); verify( ! j.more() );
} }
inline BSONObj BSONObj::removeField(const StringData& name) const { inline BSONObj BSONObj::removeField(const StringData& name) const {
BSONObjBuilder b; BSONObjBuilder b;
BSONObjIterator i(*this); BSONObjIterator i(*this);
while ( i.more() ) { while ( i.more() ) {
BSONElement e = i.next(); BSONElement e = i.next();
const char *fname = e.fieldName(); const char *fname = e.fieldName();
if( strcmp(name.data(), fname) ) if ( name != fname )
b.append(e); b.append(e);
} }
return b.obj(); return b.obj();
} }
template<typename T> bool BSONObj::coerceVector( std::vector<T>* out )
const {
BSONObjIterator i( *this );
while ( i.more() ) {
BSONElement e = i.next();
T t;
if ( ! e.coerce<T>( &t ) )
return false;
out->push_back( t );
}
return true;
}
template<> inline bool BSONElement::coerce<std::string>( std::string* o
ut ) const {
if ( type() != mongo::String )
return false;
*out = String();
return true;
}
template<> inline bool BSONElement::coerce<int>( int* out ) const {
if ( !isNumber() )
return false;
*out = numberInt();
return true;
}
template<> inline bool BSONElement::coerce<double>( double* out ) const
{
if ( !isNumber() )
return false;
*out = numberDouble();
return true;
}
template<> inline bool BSONElement::coerce<bool>( bool* out ) const {
*out = trueValue();
return true;
}
template<> inline bool BSONElement::coerce< std::vector<std::string> >(
std::vector<std::string>* out ) const {
if ( type() != mongo::Array )
return false;
return Obj().coerceVector<std::string>( out );
}
} }
 End of changes. 9 change blocks. 
9 lines changed or deleted 70 lines changed or added


 bson_db.h   bson_db.h 
skipping to change at line 45 skipping to change at line 45
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 ) {
OpTime t( (unsigned) (time / 1000) , inc ); OpTime t( (unsigned) (time / 1000) , inc );
appendTimestamp( fieldName , t.asDate() ); appendTimestamp( fieldName , t.asDate() );
return *this; return *this;
} }
inline BSONObjBuilder& BSONObjBuilder::append(const StringData& fieldNa
me, OpTime optime) {
appendTimestamp(fieldName, optime.asDate());
return *this;
}
inline OpTime BSONElement::_opTime() const { inline OpTime BSONElement::_opTime() const {
if( type() == mongo::Date || type() == Timestamp ) if( type() == mongo::Date || type() == Timestamp )
return OpTime( *reinterpret_cast< const unsigned long long* >( value() ) ); return OpTime( *reinterpret_cast< const unsigned long long* >( value() ) );
return OpTime(); return OpTime();
} }
inline std::string BSONElement::_asCode() const { inline std::string BSONElement::_asCode() const {
switch( type() ) { switch( type() ) {
case mongo::String: case mongo::String:
case Code: case Code:
return std::string(valuestr(), valuestrsize()-1); return std::string(valuestr(), valuestrsize()-1);
case CodeWScope: case CodeWScope:
return std::string(codeWScopeCode(), *(int*)(valuestr())-1); return std::string(codeWScopeCode(), *(int*)(valuestr())-1);
default: default:
log() << "can't convert type: " << (int)(type()) << " to code" << std::endl; log() << "can't convert type: " << (int)(type()) << " to code" << std::endl;
} }
uassert( 10062 , "not code" , 0 ); uassert( 10062 , "not code" , 0 );
return ""; return "";
} }
inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<(DateNowLab eler& id) { inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<(const Date NowLabeler& id) {
_builder->appendDate(_fieldName, jsTime()); _builder->appendDate(_fieldName, jsTime());
_fieldName = 0; _fieldName = StringData();
return *_builder; return *_builder;
} }
inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<(NullLabele r& id) { inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<(const Null Labeler& id) {
_builder->appendNull(_fieldName); _builder->appendNull(_fieldName);
_fieldName = 0; _fieldName = StringData();
return *_builder;
}
inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<(const Unde
finedLabeler& id) {
_builder->appendUndefined(_fieldName);
_fieldName = StringData();
return *_builder; return *_builder;
} }
inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<(MinKeyLabe ler& id) { inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<(const MinK eyLabeler& id) {
_builder->appendMinKey(_fieldName); _builder->appendMinKey(_fieldName);
_fieldName = 0; _fieldName = StringData();
return *_builder; return *_builder;
} }
inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<(MaxKeyLabe ler& id) { inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<(const MaxK eyLabeler& id) {
_builder->appendMaxKey(_fieldName); _builder->appendMaxKey(_fieldName);
_fieldName = 0; _fieldName = StringData();
return *_builder; return *_builder;
} }
} }
 End of changes. 9 change blocks. 
8 lines changed or deleted 21 lines changed or added


 bsonelement.h   bsonelement.h 
skipping to change at line 116 skipping to change at line 116
operator std::string() const { return toString(); } operator std::string() const { return toString(); }
/** Returns the type of the element */ /** Returns the type of the element */
BSONType type() const { return (BSONType) *reinterpret_cast< const signed char * >(data); } BSONType type() const { return (BSONType) *reinterpret_cast< const signed char * >(data); }
/** retrieve a field within this element /** retrieve a field within this element
throws exception if *this is not an embedded object throws exception if *this is not an embedded object
*/ */
BSONElement operator[] (const std::string& field) const; BSONElement operator[] (const std::string& field) const;
/** returns the tyoe of the element fixed for the main type /** See canonicalizeBSONType in bsontypes.h */
the main purpose is numbers. any numeric type will return Numb int canonicalType() const { return canonicalizeBSONType(type()); }
erDouble
Note: if the order changes, indexes have to be re-built or than
can be corruption
*/
int canonicalType() const;
/** Indicates if it is the end-of-object element, which is present at the end of /** Indicates if it is the end-of-object element, which is present at the end of
every BSON object. every BSON object.
*/ */
bool eoo() const { return type() == EOO; } bool eoo() const { return type() == EOO; }
/** Size of the element. /** Size of the element.
@param maxLen If maxLen is specified, don't scan more than maxL en bytes to calculate size. @param maxLen If maxLen is specified, don't scan more than maxL en bytes to calculate size.
*/ */
int size( int maxLen ) const; int size( int maxLen ) const;
skipping to change at line 455 skipping to change at line 452
totalSize = -1; totalSize = -1;
if ( eoo() ) { if ( eoo() ) {
fieldNameSize_ = 0; fieldNameSize_ = 0;
totalSize = 1; totalSize = 1;
} }
} }
std::string _asCode() const; std::string _asCode() const;
OpTime _opTime() const; OpTime _opTime() const;
template<typename T> bool coerce( T* out ) const;
private: private:
const char *data; const char *data;
mutable int fieldNameSize_; // cached value mutable int fieldNameSize_; // cached value
mutable int totalSize; /* caches the computed size */ mutable int totalSize; /* caches the computed size */
friend class BSONObjIterator; friend class BSONObjIterator;
friend class BSONObj; friend class BSONObj;
const BSONElement& chk(int t) const { const BSONElement& chk(int t) const {
if ( t != type() ) { if ( t != type() ) {
skipping to change at line 480 skipping to change at line 479
msgasserted(13111, ss.str() ); msgasserted(13111, ss.str() );
} }
return *this; return *this;
} }
const BSONElement& chk(bool expr) const { const BSONElement& chk(bool expr) const {
massert(13118, "unexpected or missing type value in BSON object ", expr); massert(13118, "unexpected or missing type value in BSON object ", expr);
return *this; return *this;
} }
}; };
inline int BSONElement::canonicalType() const {
BSONType t = type();
switch ( t ) {
case MinKey:
case MaxKey:
return t;
case EOO:
case Undefined:
return 0;
case jstNULL:
return 5;
case NumberDouble:
case NumberInt:
case NumberLong:
return 10;
case mongo::String:
case Symbol:
return 15;
case Object:
return 20;
case mongo::Array:
return 25;
case BinData:
return 30;
case jstOID:
return 35;
case mongo::Bool:
return 40;
case mongo::Date:
case Timestamp:
return 45;
case RegEx:
return 50;
case DBRef:
return 55;
case Code:
return 60;
case CodeWScope:
return 65;
default:
verify(0);
return -1;
}
}
inline bool BSONElement::trueValue() const { inline bool BSONElement::trueValue() const {
// NOTE Behavior changes must be replicated in Value::coerceToBool( ). // NOTE Behavior changes must be replicated in Value::coerceToBool( ).
switch( type() ) { switch( type() ) {
case NumberLong: case NumberLong:
return *reinterpret_cast< const long long* >( value() ) != 0; return *reinterpret_cast< const long long* >( value() ) != 0;
case NumberDouble: case NumberDouble:
return (reinterpret_cast < const PackedDouble* >(value ()))->d != 0; return (reinterpret_cast < const PackedDouble* >(value ()))->d != 0;
case NumberInt: case NumberInt:
return *reinterpret_cast< const int* >( value() ) != 0; return *reinterpret_cast< const int* >( value() ) != 0;
case mongo::Bool: case mongo::Bool:
 End of changes. 3 change blocks. 
52 lines changed or deleted 4 lines changed or added


 bsonmisc.h   bsonmisc.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 <memory>
#include "mongo/bson/bsonelement.h" #include "mongo/bson/bsonelement.h"
namespace mongo { namespace mongo {
int getGtLtOp(const BSONElement& e); int getGtLtOp(const BSONElement& e);
struct BSONElementCmpWithoutField { struct BSONElementCmpWithoutField {
bool operator()( const BSONElement &l, const BSONElement &r ) const { bool operator()( const BSONElement &l, const BSONElement &r ) const {
return l.woCompare( r, false ) < 0; return l.woCompare( r, false ) < 0;
} }
skipping to change at line 97 skipping to change at line 99
std::cout << BSON( "created" << DATENOW ); // { created : "2009-10 -09 11:41:42" } std::cout << BSON( "created" << DATENOW ); // { created : "2009-10 -09 11:41:42" }
*/ */
extern struct DateNowLabeler { } DATENOW; extern struct DateNowLabeler { } DATENOW;
/* Utility class to assign a NULL value to a given attribute /* Utility class to assign a NULL value to a given attribute
Example: Example:
std::cout << BSON( "a" << BSONNULL ); // { a : null } std::cout << BSON( "a" << BSONNULL ); // { a : null }
*/ */
extern struct NullLabeler { } BSONNULL; extern struct NullLabeler { } BSONNULL;
/* Utility class to assign an Undefined value to a given attribute
Example:
std::cout << BSON( "a" << BSONUndefined ); // { a : undefined }
*/
extern struct UndefinedLabeler { } BSONUndefined;
/* Utility class to add the minKey (minus infinity) to a given attribut e /* Utility class to add the minKey (minus infinity) to a given attribut e
Example: Example:
std::cout << BSON( "a" << MINKEY ); // { "a" : { "$minKey" : 1 } } std::cout << BSON( "a" << MINKEY ); // { "a" : { "$minKey" : 1 } }
*/ */
extern struct MinKeyLabeler { } MINKEY; extern struct MinKeyLabeler { } MINKEY;
extern struct MaxKeyLabeler { } MAXKEY; extern struct MaxKeyLabeler { } MAXKEY;
// Utility class to implement GT, GTE, etc as described above. // Utility class to implement GT, GTE, etc as described above.
class Labeler { class Labeler {
public: public:
struct Label { struct Label {
Label( const char *l ) : l_( l ) {} explicit Label( const char *l ) : l_( l ) {}
const char *l_; const char *l_;
}; };
Labeler( const Label &l, BSONObjBuilderValueStream *s ) : l_( l ), s_( s ) {} Labeler( const Label &l, BSONObjBuilderValueStream *s ) : l_( l ), s_( s ) {}
template<class T> template<class T>
BSONObjBuilder& operator<<( T value ); BSONObjBuilder& operator<<( T value );
/* the value of the element e is appended i.e. for /* the value of the element e is appended i.e. for
"age" << GT << someElement "age" << GT << someElement
one gets one gets
{ age : { $gt : someElement's value } } { age : { $gt : someElement's value } }
*/ */
BSONObjBuilder& operator<<( const BSONElement& e ); BSONObjBuilder& operator<<( const BSONElement& e );
private: private:
const Label &l_; const Label &l_;
BSONObjBuilderValueStream *s_; BSONObjBuilderValueStream *s_;
}; };
// Utility class to allow adding a string to BSON as a Symbol
struct BSONSymbol {
explicit BSONSymbol(const StringData& sym) :symbol(sym) {}
StringData symbol;
};
// Utility class to allow adding a string to BSON as Code
struct BSONCode {
explicit BSONCode(const StringData& str) :code(str) {}
StringData code;
};
// Utility class to allow adding CodeWScope to BSON
struct BSONCodeWScope {
explicit BSONCodeWScope(const StringData& str, const BSONObj& obj)
:code(str), scope(obj) {}
StringData code;
BSONObj scope;
};
// Utility class to allow adding a RegEx to BSON
struct BSONRegEx {
explicit BSONRegEx(const StringData& pat, const StringData& f="") :
pattern(pat), flags(f) {}
StringData pattern;
StringData flags;
};
// Utility class to allow adding binary data to BSON
struct BSONBinData {
BSONBinData(const void* d, int l, BinDataType t) :data(d), length(l
), type(t) {}
const void* data;
int length;
BinDataType type;
};
// Utility class to allow adding deprecated DBRef type to BSON
struct BSONDBRef {
BSONDBRef(const StringData& nameSpace, const OID& o) :ns(nameSpace)
, oid(o) {}
StringData ns;
OID oid;
};
extern Labeler::Label GT; extern Labeler::Label GT;
extern Labeler::Label GTE; extern Labeler::Label GTE;
extern Labeler::Label LT; extern Labeler::Label LT;
extern Labeler::Label LTE; extern Labeler::Label LTE;
extern Labeler::Label NE; extern Labeler::Label NE;
extern Labeler::Label NIN; extern Labeler::Label NIN;
extern Labeler::Label BSIZE; extern Labeler::Label BSIZE;
// $or helper: OR(BSON("x" << GT << 7), BSON("y" << LT << 6)); // $or helper: OR(BSON("x" << GT << 7), BSON("y" << LT << 6));
// becomes : {$or: [{x: {$gt: 7}}, {y: {$lt: 6}}]} // becomes : {$or: [{x: {$gt: 7}}, {y: {$lt: 6}}]}
skipping to change at line 154 skipping to change at line 203
class BSONObjBuilderValueStream : public boost::noncopyable { class BSONObjBuilderValueStream : public boost::noncopyable {
public: public:
friend class Labeler; friend class Labeler;
BSONObjBuilderValueStream( BSONObjBuilder * builder ); BSONObjBuilderValueStream( BSONObjBuilder * builder );
BSONObjBuilder& operator<<( const BSONElement& e ); BSONObjBuilder& operator<<( const BSONElement& e );
template<class T> template<class T>
BSONObjBuilder& operator<<( T value ); BSONObjBuilder& operator<<( T value );
BSONObjBuilder& operator<<(DateNowLabeler& id); BSONObjBuilder& operator<<(const DateNowLabeler& id);
BSONObjBuilder& operator<<(NullLabeler& id); BSONObjBuilder& operator<<(const NullLabeler& id);
BSONObjBuilder& operator<<(const UndefinedLabeler& id);
BSONObjBuilder& operator<<(MinKeyLabeler& id); BSONObjBuilder& operator<<(const MinKeyLabeler& id);
BSONObjBuilder& operator<<(MaxKeyLabeler& id); BSONObjBuilder& operator<<(const MaxKeyLabeler& id);
Labeler operator<<( const Labeler::Label &l ); Labeler operator<<( const Labeler::Label &l );
void endField( const char *nextFieldName = 0 ); void endField( const StringData& nextFieldName = StringData() );
bool subobjStarted() const { return _fieldName != 0; } bool subobjStarted() const { return _fieldName != 0; }
// The following methods provide API compatibility with BSONArrayBu
ilder
BufBuilder& subobjStart();
BufBuilder& subarrayStart();
// This method should only be called from inside of implementations
of
// BSONObjBuilder& operator<<(BSONObjBuilderValueStream&, SOME_TYPE
)
// to provide the return value.
BSONObjBuilder& builder() { return *_builder; }
private: private:
const char * _fieldName; StringData _fieldName;
BSONObjBuilder * _builder; BSONObjBuilder * _builder;
bool haveSubobj() const { return _subobj.get() != 0; } bool haveSubobj() const { return _subobj.get() != 0; }
BSONObjBuilder *subobj(); BSONObjBuilder *subobj();
std::auto_ptr< BSONObjBuilder > _subobj; std::auto_ptr< BSONObjBuilder > _subobj;
}; };
/** /**
used in conjuction with BSONObjBuilder, allows for proper buffer siz e to prevent crazy memory usage used in conjuction with BSONObjBuilder, allows for proper buffer siz e to prevent crazy memory usage
*/ */
 End of changes. 10 change blocks. 
7 lines changed or deleted 72 lines changed or added


 bsonobj.h   bsonobj.h 
skipping to change at line 227 skipping to change at line 227
} }
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 char * name ) const { return !getField(name).e oo(); } bool hasField( const StringData& name ) const { return !getField(na me).eoo(); }
/** @return true if field exists */ /** @return true if field exists */
bool hasElement(const char *name) const { return hasField(name); } 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 char *name) const;
/** @return subobject of the given name */ /** @return subobject of the given name */
BSONObj getObjectField(const char *name) const; BSONObj getObjectField(const char *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 char *name) const;
skipping to change at line 424 skipping to change at line 424
NIN = 0x0C, NIN = 0x0C,
opEXISTS = 0x0D, opEXISTS = 0x0D,
opMOD = 0x0E, opMOD = 0x0E,
opTYPE = 0x0F, opTYPE = 0x0F,
opREGEX = 0x10, opREGEX = 0x10,
opOPTIONS = 0x11, opOPTIONS = 0x11,
opELEM_MATCH = 0x12, opELEM_MATCH = 0x12,
opNEAR = 0x13, opNEAR = 0x13,
opWITHIN = 0x14, opWITHIN = 0x14,
opMAX_DISTANCE = 0x15, opMAX_DISTANCE = 0x15,
opINTERSECT = 0x16, opGEO_INTERSECTS = 0x16,
}; };
/** add all elements of the object to the specified vector */ /** add all elements of the object to the specified vector */
void elems(std::vector<BSONElement> &) const; void elems(std::vector<BSONElement> &) const;
/** add all elements of the object to the specified list */ /** add all elements of the object to the specified list */
void elems(std::list<BSONElement> &) const; void elems(std::list<BSONElement> &) const;
/** add all values of the object to the specified vector. If type mismatches, exception. /** add all values of the object to the specified vector. If type mismatches, exception.
this is most useful when the BSONObj is an array, but can be us ed with non-arrays too in theory. this is most useful when the BSONObj is an array, but can be us ed with non-arrays too in theory.
skipping to change at line 469 skipping to change at line 469
... ...
} }
*/ */
BSONObjIterator begin() const; BSONObjIterator begin() const;
void appendSelfToBufBuilder(BufBuilder& b) const { void appendSelfToBufBuilder(BufBuilder& b) const {
verify( objsize() ); verify( objsize() );
b.appendBuf(reinterpret_cast<const void *>( objdata() ), objsiz e()); b.appendBuf(reinterpret_cast<const void *>( objdata() ), objsiz e());
} }
template<typename T> bool coerceVector( std::vector<T>* out ) const
;
#pragma pack(1) #pragma pack(1)
class Holder : boost::noncopyable { class Holder : boost::noncopyable {
private: private:
Holder(); // this class should never be explicitly created Holder(); // this class should never be explicitly created
AtomicUInt refCount; AtomicUInt refCount;
public: public:
char data[4]; // start of object char data[4]; // start of object
void zero() { refCount.zero(); } void zero() { refCount.zero(); }
 End of changes. 4 change blocks. 
3 lines changed or deleted 6 lines changed or added


 bsonobjbuilder.h   bsonobjbuilder.h 
skipping to change at line 26 skipping to change at line 26
* 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/static_assert.hpp> #include <boost/static_assert.hpp>
#include <map>
#include <cmath> #include <cmath>
#include <limits> #include <limits>
#include "mongo/base/parse_number.h"
#include "mongo/bson/bsonelement.h" #include "mongo/bson/bsonelement.h"
#include "mongo/bson/bsonobj.h" #include "mongo/bson/bsonobj.h"
#include "mongo/bson/bsonmisc.h" #include "mongo/bson/bsonmisc.h"
#include "mongo/bson/bson_builder_base.h" #include "mongo/bson/bson_builder_base.h"
#include "mongo/bson/bson_field.h" #include "mongo/bson/bson_field.h"
#if defined(_DEBUG) && defined(MONGO_EXPOSE_MACROS) #if defined(_DEBUG) && defined(MONGO_EXPOSE_MACROS)
#include "mongo/util/log.h" #include "mongo/util/log.h"
#endif #endif
skipping to change at line 340 skipping to change at line 342
@param regex options such as "i" or "g" @param regex options such as "i" or "g"
*/ */
BSONObjBuilder& appendRegex(const StringData& fieldName, const Stri ngData& regex, const StringData& options = "") { BSONObjBuilder& appendRegex(const StringData& fieldName, const Stri ngData& regex, const StringData& options = "") {
_b.appendNum((char) RegEx); _b.appendNum((char) RegEx);
_b.appendStr(fieldName); _b.appendStr(fieldName);
_b.appendStr(regex); _b.appendStr(regex);
_b.appendStr(options); _b.appendStr(options);
return *this; return *this;
} }
BSONObjBuilder& append(const StringData& fieldName, const BSONRegEx
& regex) {
return appendRegex(fieldName, regex.pattern, regex.flags);
}
BSONObjBuilder& appendCode(const StringData& fieldName, const Strin gData& code) { BSONObjBuilder& appendCode(const StringData& fieldName, const Strin gData& code) {
_b.appendNum((char) Code); _b.appendNum((char) Code);
_b.appendStr(fieldName); _b.appendStr(fieldName);
_b.appendNum((int) code.size()+1); _b.appendNum((int) code.size()+1);
_b.appendStr(code); _b.appendStr(code);
return *this; return *this;
} }
BSONObjBuilder& append(const StringData& fieldName, const BSONCode&
code) {
return appendCode(fieldName, code.code);
}
/** Append a string element. /** Append a string element.
@param sz size includes terminating null character */ @param sz size includes terminating null character */
BSONObjBuilder& append(const StringData& fieldName, const char *str , int sz) { BSONObjBuilder& append(const StringData& fieldName, const char *str , int sz) {
_b.appendNum((char) String); _b.appendNum((char) String);
_b.appendStr(fieldName); _b.appendStr(fieldName);
_b.appendNum((int)sz); _b.appendNum((int)sz);
_b.appendBuf(str, sz); _b.appendBuf(str, sz);
return *this; return *this;
} }
/** Append a string element */ /** Append a string element */
BSONObjBuilder& append(const StringData& fieldName, const char *str ) { BSONObjBuilder& append(const StringData& fieldName, const char *str ) {
return append(fieldName, str, (int) strlen(str)+1); return append(fieldName, str, (int) strlen(str)+1);
} }
/** Append a string element */ /** Append a string element */
BSONObjBuilder& append(const StringData& fieldName, const std::stri ng& str) { BSONObjBuilder& append(const StringData& fieldName, const std::stri ng& str) {
return append(fieldName, str.c_str(), (int) str.size()+1); return append(fieldName, str.c_str(), (int) str.size()+1);
} }
/** Append a string element */ /** Append a string element */
BSONObjBuilder& append(const StringData& fieldName, const StringDat a& str) { BSONObjBuilder& append(const StringData& fieldName, const StringDat a& str) {
return append(fieldName, str.data(), (int) str.size()+1); _b.appendNum((char) String);
_b.appendStr(fieldName);
_b.appendNum((int)str.size()+1);
_b.appendStr(str, true);
return *this;
} }
BSONObjBuilder& appendSymbol(const StringData& fieldName, const Str ingData& symbol) { BSONObjBuilder& appendSymbol(const StringData& fieldName, const Str ingData& symbol) {
_b.appendNum((char) Symbol); _b.appendNum((char) Symbol);
_b.appendStr(fieldName); _b.appendStr(fieldName);
_b.appendNum((int) symbol.size()+1); _b.appendNum((int) symbol.size()+1);
_b.appendStr(symbol); _b.appendStr(symbol);
return *this; return *this;
} }
BSONObjBuilder& append(const StringData& fieldName, const BSONSymbo
l& symbol) {
return appendSymbol(fieldName, symbol.symbol);
}
/** Implements builder interface but no-op in ObjBuilder */ /** Implements builder interface but no-op in ObjBuilder */
void appendNull() { void appendNull() {
msgasserted(16234, "Invalid call to appendNull in BSONObj Build er."); msgasserted(16234, "Invalid call to appendNull in BSONObj Build er.");
} }
/** Append a Null element to the object */ /** Append a Null element to the object */
BSONObjBuilder& appendNull( const StringData& fieldName ) { BSONObjBuilder& appendNull( const StringData& fieldName ) {
_b.appendNum( (char) jstNULL ); _b.appendNum( (char) jstNULL );
_b.appendStr( fieldName ); _b.appendStr( fieldName );
return *this; return *this;
skipping to change at line 412 skipping to change at line 430
// Append a Timestamp field -- will be updated to next OpTime on db insert. // Append a Timestamp field -- will be updated to next OpTime on db insert.
BSONObjBuilder& appendTimestamp( const StringData& fieldName ) { BSONObjBuilder& appendTimestamp( const StringData& fieldName ) {
_b.appendNum( (char) Timestamp ); _b.appendNum( (char) Timestamp );
_b.appendStr( fieldName ); _b.appendStr( fieldName );
_b.appendNum( (unsigned long long) 0 ); _b.appendNum( (unsigned long long) 0 );
return *this; return *this;
} }
/** /**
* To store an OpTime in BSON, use this function. Pass the OpTime a * To store an OpTime in BSON, use this function.
s a Date, as follows: * This captures both the secs and inc fields.
*/
BSONObjBuilder& append(const StringData& fieldName, OpTime optime);
/**
* Alternative way to store an OpTime in BSON. Pass the OpTime as a
Date, as follows:
* *
* builder.appendTimestamp("field", optime.asDate()); * builder.appendTimestamp("field", optime.asDate());
* *
* This captures both the secs and inc fields. * This captures both the secs and inc fields.
*/ */
BSONObjBuilder& appendTimestamp( const StringData& fieldName , unsi gned long long val ) { BSONObjBuilder& appendTimestamp( const StringData& fieldName , unsi gned long long val ) {
_b.appendNum( (char) Timestamp ); _b.appendNum( (char) Timestamp );
_b.appendStr( fieldName ); _b.appendStr( fieldName );
_b.appendNum( val ); _b.appendNum( val );
return *this; return *this;
skipping to change at line 445 skipping to change at line 469
*/ */
BSONObjBuilder& appendDBRef( const StringData& fieldName, const Str ingData& ns, const OID &oid ) { BSONObjBuilder& appendDBRef( const StringData& fieldName, const Str ingData& ns, const OID &oid ) {
_b.appendNum( (char) DBRef ); _b.appendNum( (char) DBRef );
_b.appendStr( fieldName ); _b.appendStr( fieldName );
_b.appendNum( (int) ns.size() + 1 ); _b.appendNum( (int) ns.size() + 1 );
_b.appendStr( ns ); _b.appendStr( ns );
_b.appendBuf( (void *) &oid, 12 ); _b.appendBuf( (void *) &oid, 12 );
return *this; return *this;
} }
BSONObjBuilder& append(const StringData& fieldName, const BSONDBRef
& dbref) {
return appendDBRef(fieldName, dbref.ns, dbref.oid);
}
/** Append a binary data element /** Append a binary data element
@param fieldName name of the field @param fieldName name of the field
@param len length of the binary data in bytes @param len length of the binary data in bytes
@param subtype subtype information for the data. @see enum BinD ataType in bsontypes.h. @param subtype subtype information for the data. @see enum BinD ataType in bsontypes.h.
Use BinDataGeneral if you don't care about the type. Use BinDataGeneral if you don't care about the type.
@param data the byte array @param data the byte array
*/ */
BSONObjBuilder& appendBinData( const StringData& fieldName, int len , BinDataType type, const void *data ) { BSONObjBuilder& appendBinData( const StringData& fieldName, int len , BinDataType type, const void *data ) {
_b.appendNum( (char) BinData ); _b.appendNum( (char) BinData );
_b.appendStr( fieldName ); _b.appendStr( fieldName );
_b.appendNum( len ); _b.appendNum( len );
_b.appendNum( (char) type ); _b.appendNum( (char) type );
_b.appendBuf( data, len ); _b.appendBuf( data, len );
return *this; return *this;
} }
BSONObjBuilder& append(const StringData& fieldName, const BSONBinDa
ta& bd) {
return appendBinData(fieldName, bd.length, bd.type, bd.data);
}
/** /**
Subtype 2 is deprecated. Subtype 2 is deprecated.
Append a BSON bindata bytearray element. Append a BSON bindata bytearray element.
@param data a byte array @param data a byte array
@param len the length of data @param len the length of data
*/ */
BSONObjBuilder& appendBinDataArrayDeprecated( const char * fieldNam e , const void * data , int len ) { BSONObjBuilder& appendBinDataArrayDeprecated( const char * fieldNam e , const void * data , int len ) {
_b.appendNum( (char) BinData ); _b.appendNum( (char) BinData );
_b.appendStr( fieldName ); _b.appendStr( fieldName );
_b.appendNum( len + 4 ); _b.appendNum( len + 4 );
skipping to change at line 490 skipping to change at line 522
BSONObjBuilder& appendCodeWScope( const StringData& fieldName, cons t StringData& code, const BSONObj &scope ) { BSONObjBuilder& appendCodeWScope( const StringData& fieldName, cons t StringData& code, const BSONObj &scope ) {
_b.appendNum( (char) CodeWScope ); _b.appendNum( (char) CodeWScope );
_b.appendStr( fieldName ); _b.appendStr( fieldName );
_b.appendNum( ( int )( 4 + 4 + code.size() + 1 + scope.objsize( ) ) ); _b.appendNum( ( int )( 4 + 4 + code.size() + 1 + scope.objsize( ) ) );
_b.appendNum( ( int ) code.size() + 1 ); _b.appendNum( ( int ) code.size() + 1 );
_b.appendStr( code ); _b.appendStr( code );
_b.appendBuf( ( void * )scope.objdata(), scope.objsize() ); _b.appendBuf( ( void * )scope.objdata(), scope.objsize() );
return *this; return *this;
} }
BSONObjBuilder& append(const StringData& fieldName, const BSONCodeW
Scope& cws) {
return appendCodeWScope(fieldName, cws.code, cws.scope);
}
void appendUndefined( const StringData& fieldName ) { void appendUndefined( const StringData& fieldName ) {
_b.appendNum( (char) Undefined ); _b.appendNum( (char) Undefined );
_b.appendStr( fieldName ); _b.appendStr( fieldName );
} }
/* helper function -- see Query::where() for primary way to do this . */ /* helper function -- see Query::where() for primary way to do this . */
void appendWhere( const StringData& code, const BSONObj &scope ) { void appendWhere( const StringData& code, const BSONObj &scope ) {
appendCodeWScope( "$where" , code , scope ); appendCodeWScope( "$where" , code , scope );
} }
skipping to change at line 518 skipping to change at line 554
BSONObjBuilder& append( const StringData& fieldName, const std::vec tor< T >& vals ); BSONObjBuilder& append( const StringData& fieldName, const std::vec tor< T >& vals );
template < class T > template < class T >
BSONObjBuilder& append( const StringData& fieldName, const std::lis t< T >& vals ); BSONObjBuilder& append( const StringData& fieldName, const std::lis t< T >& vals );
/** Append a set of values. */ /** Append a set of values. */
template < class T > template < class T >
BSONObjBuilder& append( const StringData& fieldName, const std::set < T >& vals ); BSONObjBuilder& append( const StringData& fieldName, const std::set < T >& vals );
/** /**
* Append a map of values as a sub-object.
* Note: the keys of the map should be StringData-compatible (i.e.
strings).
*/
template < class K, class T >
BSONObjBuilder& append( const StringData& fieldName, const std::map
< K, T >& vals );
/**
* destructive * destructive
* The returned BSONObj will free the buffer when it is finished. * The returned BSONObj will free the buffer when it is finished.
* @return owned BSONObj * @return owned BSONObj
*/ */
BSONObj obj() { BSONObj obj() {
bool own = owned(); bool own = owned();
massert( 10335 , "builder does not own memory", own ); massert( 10335 , "builder does not own memory", own );
doneFast(); doneFast();
BSONObj::Holder* h = (BSONObj::Holder*)_b.buf(); BSONObj::Holder* h = (BSONObj::Holder*)_b.buf();
decouple(); // sets _b.buf() to NULL decouple(); // sets _b.buf() to NULL
skipping to change at line 556 skipping to change at line 599
The returned object is only valid until the next modification o r destruction of the builder. The returned object is only valid until the next modification o r destruction of the builder.
Intended use case: append a field if not already there. Intended use case: append a field if not already there.
*/ */
BSONObj asTempObj() { BSONObj asTempObj() {
BSONObj temp(_done()); BSONObj temp(_done());
_b.setlen(_b.len()-1); //next append should overwrite the EOO _b.setlen(_b.len()-1); //next append should overwrite the EOO
_doneCalled = false; _doneCalled = false;
return temp; return temp;
} }
/* assume ownership of the buffer - you must then free it (with fre
e()) */
char* decouple(int& l) {
char *x = _done();
verify( x );
l = _b.len();
_b.decouple();
return x;
}
void decouple() { void decouple() {
_b.decouple(); // post done() call version. be sure jsobj f rees... _b.decouple(); // post done() call version. be sure jsobj f rees...
} }
void appendKeys( const BSONObj& keyPattern , const BSONObj& values ); void appendKeys( const BSONObj& keyPattern , const BSONObj& values );
static std::string numStr( int i ) { static std::string numStr( int i ) {
if (i>=0 && i<100 && numStrsReady) if (i>=0 && i<100 && numStrsReady)
return numStrs[i]; return numStrs[i];
StringBuilder o; StringBuilder o;
o << i; o << i;
return o.str(); return o.str();
} }
/** Stream oriented way to add field names and values. */ /** Stream oriented way to add field names and values. */
BSONObjBuilderValueStream &operator<<(const char * name ) { BSONObjBuilderValueStream &operator<<( const StringData& name ) {
_s.endField( name ); _s.endField( name );
return _s; return _s;
} }
/** Stream oriented way to add field names and values. */ /** Stream oriented way to add field names and values. */
BSONObjBuilder& operator<<( GENOIDLabeler ) { return genOID(); } BSONObjBuilder& operator<<( GENOIDLabeler ) { return genOID(); }
// prevent implicit string conversions which would allow bad things
like BSON( BSON( "foo" << 1 ) << 2 )
struct ForceExplicitString {
ForceExplicitString( const std::string &str ) : str_( str ) {}
std::string str_;
};
/** Stream oriented way to add field names and values. */
BSONObjBuilderValueStream &operator<<( const ForceExplicitString& n
ame ) {
return operator<<( name.str_.c_str() );
}
Labeler operator<<( const Labeler::Label &l ) { Labeler operator<<( const Labeler::Label &l ) {
massert( 10336 , "No subobject started", _s.subobjStarted() ); massert( 10336 , "No subobject started", _s.subobjStarted() );
return _s << l; return _s << l;
} }
template<typename T> template<typename T>
BSONObjBuilderValueStream& operator<<( const BSONField<T>& f ) { BSONObjBuilderValueStream& operator<<( const BSONField<T>& f ) {
_s.endField( f.name().c_str() ); _s.endField( f.name() );
return _s; return _s;
} }
template<typename T> template<typename T>
BSONObjBuilder& operator<<( const BSONFieldValue<T>& v ) { BSONObjBuilder& operator<<( const BSONFieldValue<T>& v ) {
append( v.name().c_str() , v.value() ); append( v.name(), v.value() );
return *this; return *this;
} }
BSONObjBuilder& operator<<( const BSONElement& e ){ BSONObjBuilder& operator<<( const BSONElement& e ){
append( e ); append( e );
return *this; return *this;
} }
bool isArray() const { bool isArray() const {
return false; return false;
skipping to change at line 685 skipping to change at line 709
_b.appendAs(e, num()); _b.appendAs(e, num());
return *this; return *this;
} }
BSONArrayBuilder& operator<<(const BSONElement& e) { BSONArrayBuilder& operator<<(const BSONElement& e) {
return append(e); return append(e);
} }
template <typename T> template <typename T>
BSONArrayBuilder& operator<<(const T& x) { BSONArrayBuilder& operator<<(const T& x) {
return append(x); _b << num().c_str() << x;
return *this;
} }
void appendNull() { void appendNull() {
_b.appendNull(num()); _b.appendNull(num());
} }
void appendUndefined() { void appendUndefined() {
_b.appendUndefined(num()); _b.appendUndefined(num());
} }
skipping to change at line 800 skipping to change at line 825
int len() const { return _b.len(); } int len() const { return _b.len(); }
int arrSize() const { return _i; } int arrSize() const { return _i; }
private: private:
// These two are undefined privates to prevent their accidental // These two are undefined privates to prevent their accidental
// use as we don't support unsigned ints in BSON // use as we don't support unsigned ints in BSON
BSONObjBuilder& append(const StringData& fieldName, unsigned int va l); BSONObjBuilder& append(const StringData& fieldName, unsigned int va l);
BSONObjBuilder& append(const StringData& fieldName, unsigned long l ong val); BSONObjBuilder& append(const StringData& fieldName, unsigned long l ong val);
void fill( const StringData& name ) { void fill( const StringData& name ) {
char *r; long int n;
long int n = strtol( name.data(), &r, 10 ); Status status = parseNumberFromStringWithBase( name, 10, &n );
if ( *r ) uassert( 13048,
uasserted( 13048, (std::string)"can't append to array using (string)"can't append to array using string field name
string field name [" + name.data() + "]" ); : " + name.toString(),
status.isOK() );
fill(n); fill(n);
} }
void fill (int upTo){ void fill (int upTo){
// if this is changed make sure to update error message and jst ests/set7.js // if this is changed make sure to update error message and jst ests/set7.js
const int maxElems = 1500000; const int maxElems = 1500000;
BOOST_STATIC_ASSERT(maxElems < (BSONObjMaxUserSize/10)); BOOST_STATIC_ASSERT(maxElems < (BSONObjMaxUserSize/10));
uassert(15891, "can't backfill array to larger than 1,500,000 e lements", upTo <= maxElems); uassert(15891, "can't backfill array to larger than 1,500,000 e lements", upTo <= maxElems);
while( _i < upTo ) while( _i < upTo )
skipping to change at line 851 skipping to change at line 877
template < class T > template < class T >
inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldN ame, const std::list< T >& vals ) { inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldN ame, const std::list< T >& vals ) {
return _appendIt< std::list< T > >( *this, fieldName, vals ); return _appendIt< std::list< T > >( *this, fieldName, vals );
} }
template < class T > template < class T >
inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldN ame, const std::set< T >& vals ) { inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldN ame, const std::set< T >& vals ) {
return _appendIt< std::set< T > >( *this, fieldName, vals ); return _appendIt< std::set< T > >( *this, fieldName, vals );
} }
template < class K, class T >
inline BSONObjBuilder& BSONObjBuilder::append( const StringData& fieldN
ame, const std::map< K, T >& vals ) {
BSONObjBuilder bob;
for( typename std::map<K,T>::const_iterator i = vals.begin(); i !=
vals.end(); ++i ){
bob.append(i->first, i->second);
}
append(fieldName, bob.obj());
return *this;
}
template < class L > template < class L >
inline BSONArrayBuilder& _appendArrayIt( BSONArrayBuilder& _this, const L& vals ) { inline BSONArrayBuilder& _appendArrayIt( BSONArrayBuilder& _this, const L& vals ) {
for( typename L::const_iterator i = vals.begin(); i != vals.end(); i++ ) for( typename L::const_iterator i = vals.begin(); i != vals.end(); i++ )
_this.append( *i ); _this.append( *i );
return _this; return _this;
} }
template < class T > template < class T >
inline BSONArrayBuilder& BSONArrayBuilder::append( const std::list< T > & vals ) { inline BSONArrayBuilder& BSONArrayBuilder::append( const std::list< T > & vals ) {
return _appendArrayIt< std::list< T > >( *this, vals ); return _appendArrayIt< std::list< T > >( *this, vals );
 End of changes. 19 change blocks. 
34 lines changed or deleted 77 lines changed or added


 bsonobjiterator.h   bsonobjiterator.h 
skipping to change at line 143 skipping to change at line 143
/** /**
* Provides iteration of a BSONArray's BSONElements in numeric field or der. * Provides iteration of a BSONArray's BSONElements in numeric field or der.
* The elements of a bson array should always be numerically ordered by field name, but this * The elements of a bson array should always be numerically ordered by field name, but this
* implementation re-sorts them anyway. * implementation re-sorts them anyway.
*/ */
class BSONArrayIteratorSorted : public BSONIteratorSorted { class BSONArrayIteratorSorted : public BSONIteratorSorted {
public: public:
BSONArrayIteratorSorted( const BSONArray &array ); BSONArrayIteratorSorted( const BSONArray &array );
}; };
/** transform a BSON array into a vector of BSONElements.
we match array # positions with their vector position, and ignore
any fields with non-numeric field names.
*/
inline std::vector<BSONElement> BSONElement::Array() const {
chk(mongo::Array);
std::vector<BSONElement> v;
BSONObjIterator i(Obj());
while( i.more() ) {
BSONElement e = i.next();
const char *f = e.fieldName();
try {
unsigned u = stringToNum(f);
verify( u < 1000000 );
if( u >= v.size() )
v.resize(u+1);
v[u] = e;
}
catch(unsigned) { }
}
return v;
}
/** Similar to BOOST_FOREACH /** Similar to BOOST_FOREACH
* *
* because the iterator is defined outside of the for, you must use {} around * because the iterator is defined outside of the for, you must use {} around
* the surrounding scope. Don't do this: * the surrounding scope. Don't do this:
* *
* if (foo) * if (foo)
* BSONForEach(e, obj) * BSONForEach(e, obj)
* doSomething(e); * doSomething(e);
* *
* but this is OK: * but this is OK:
 End of changes. 1 change blocks. 
23 lines changed or deleted 0 lines changed or added


 bsontypes.h   bsontypes.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 "mongo/util/assert_util.h"
namespace bson { } namespace bson { }
namespace mongo { namespace mongo {
class BSONArrayBuilder; class BSONArrayBuilder;
class BSONElement; class BSONElement;
class BSONObj; class BSONObj;
class BSONObjBuilder; class BSONObjBuilder;
class BSONObjBuilderValueStream; class BSONObjBuilderValueStream;
class BSONObjIterator; class BSONObjIterator;
skipping to change at line 109 skipping to change at line 111
enum BinDataType { enum BinDataType {
BinDataGeneral=0, BinDataGeneral=0,
Function=1, Function=1,
ByteArrayDeprecated=2, /* use BinGeneral instead */ ByteArrayDeprecated=2, /* use BinGeneral instead */
bdtUUID = 3, /* deprecated */ bdtUUID = 3, /* deprecated */
newUUID=4, /* language-independent UUID format across all drivers * / newUUID=4, /* language-independent UUID format across all drivers * /
MD5Type=5, MD5Type=5,
bdtCustom=128 bdtCustom=128
}; };
/** Returns a number for where a given type falls in the sort order.
* Elements with the same return value should be compared for value eq
uality.
* The return value is not a BSONType and should not be treated as one
.
* Note: if the order changes, indexes have to be re-built or than can
be corruption
*/
inline int canonicalizeBSONType(BSONType type) {
switch (type) {
case MinKey:
case MaxKey:
return type;
case EOO:
case Undefined:
return 0;
case jstNULL:
return 5;
case NumberDouble:
case NumberInt:
case NumberLong:
return 10;
case mongo::String:
case Symbol:
return 15;
case Object:
return 20;
case mongo::Array:
return 25;
case BinData:
return 30;
case jstOID:
return 35;
case mongo::Bool:
return 40;
case mongo::Date:
case Timestamp:
return 45;
case RegEx:
return 50;
case DBRef:
return 55;
case Code:
return 60;
case CodeWScope:
return 65;
default:
verify(0);
return -1;
}
}
} }
 End of changes. 2 change blocks. 
0 lines changed or deleted 53 lines changed or added


 btree_stats.h   btree_stats.h 
skipping to change at line 34 skipping to change at line 34
#include "mongo/util/processinfo.h" #include "mongo/util/processinfo.h"
namespace mongo { namespace mongo {
class IndexCounters : public ServerStatusSection { class IndexCounters : public ServerStatusSection {
public: public:
IndexCounters(); IndexCounters();
virtual ~IndexCounters(); virtual ~IndexCounters();
virtual bool includeByDefault() const { return true; } virtual bool includeByDefault() const { return true; }
virtual bool adminOnly() const { return false; }
virtual BSONObj generateSection( const BSONElement& configElement, bool userIsAdmin ) const; virtual BSONObj generateSection(const BSONElement& configElement) c onst;
// used without a mutex intentionally (can race) // used without a mutex intentionally (can race)
void btree( char * node ) { void btree( char * node ) {
if ( ! _memSupported ) if ( ! _memSupported )
return; return;
btree( Record::likelyInPhysicalMemory( node ) ); btree( Record::likelyInPhysicalMemory( node ) );
} }
void btree( bool memHit ) { void btree( bool memHit ) {
if ( memHit ) if ( memHit )
 End of changes. 2 change blocks. 
2 lines changed or deleted 1 lines changed or added


 builder.h   builder.h 
skipping to change at line 29 skipping to change at line 29
#include <cfloat> #include <cfloat>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <stdio.h> #include <stdio.h>
#include <string> #include <string>
#include <string.h> #include <string.h>
#include "mongo/bson/inline_decls.h" #include "mongo/bson/inline_decls.h"
#include "mongo/base/string_data.h" #include "mongo/base/string_data.h"
#include "mongo/util/assert_util.h"
namespace mongo { namespace mongo {
/* Accessing unaligned doubles on ARM generates an alignment trap and a borts with SIGBUS on Linux. /* Accessing unaligned doubles on ARM generates an alignment trap and a borts with SIGBUS on Linux.
Wrapping the double in a packed struct forces gcc to generate code t hat works with unaligned values too. Wrapping the double in a packed struct forces gcc to generate code t hat works with unaligned values too.
The generated code for other architectures (which already allow unal igned accesses) is the same as if The generated code for other architectures (which already allow unal igned accesses) is the same as if
there was a direct pointer access. there was a direct pointer access.
*/ */
struct PackedDouble { struct PackedDouble {
double d; double d;
} PACKED_DECL; } PACKED_DECL;
skipping to change at line 191 skipping to change at line 192
memcpy(grow((int) len), src, len); memcpy(grow((int) len), src, len);
} }
template<class T> template<class T>
void appendStruct(const T& s) { void appendStruct(const T& s) {
appendBuf(&s, sizeof(T)); appendBuf(&s, sizeof(T));
} }
void appendStr(const StringData &str , bool includeEndingNull = tru e ) { void appendStr(const StringData &str , bool includeEndingNull = tru e ) {
const int len = str.size() + ( includeEndingNull ? 1 : 0 ); const int len = str.size() + ( includeEndingNull ? 1 : 0 );
memcpy(grow(len), str.data(), len); str.copyTo( grow(len), includeEndingNull );
} }
/** @return length of current string */ /** @return length of current string */
int len() const { return l; } int len() const { return l; }
void setlen( int newLen ) { l = newLen; } void setlen( int newLen ) { l = newLen; }
/** @return size of the buffer */ /** @return size of the buffer */
int getSize() const { return size; } int getSize() const { return size; }
/* returns the pre-grow write position */ /* returns the pre-grow write position */
inline char* grow(int by) { inline char* grow(int by) {
skipping to change at line 311 skipping to change at line 312
verify( z >= 0 ); verify( z >= 0 );
verify( z < maxSize ); verify( z < maxSize );
_buf.l = prev + z; _buf.l = prev + z;
if( strchr(start, '.') == 0 && strchr(start, 'E') == 0 && strch r(start, 'N') == 0 ) { if( strchr(start, '.') == 0 && strchr(start, 'E') == 0 && strch r(start, 'N') == 0 ) {
write( ".0" , 2 ); write( ".0" , 2 );
} }
} }
void write( const char* buf, int len) { memcpy( _buf.grow( len ) , buf , len ); } void write( const char* buf, int len) { memcpy( _buf.grow( len ) , buf , len ); }
void append( const StringData& str ) { memcpy( _buf.grow( str.size( ) ) , str.data() , str.size() ); } void append( const StringData& str ) { str.copyTo( _buf.grow( str.s ize() ), false ); }
StringBuilderImpl& operator<<( const StringData& str ) { StringBuilderImpl& operator<<( const StringData& str ) {
append( str ); append( str );
return *this; return *this;
} }
void reset( int maxSize = 0 ) { _buf.reset( maxSize ); } void reset( int maxSize = 0 ) { _buf.reset( maxSize ); }
std::string str() const { return std::string(_buf.data, _buf.l); } std::string str() const { return std::string(_buf.data, _buf.l); }
/** size of current string */
int len() const { return _buf.l; } int len() const { return _buf.l; }
private: private:
_BufBuilder<Allocator> _buf; _BufBuilder<Allocator> _buf;
// non-copyable, non-assignable // non-copyable, non-assignable
StringBuilderImpl( const StringBuilderImpl& ); StringBuilderImpl( const StringBuilderImpl& );
StringBuilderImpl& operator=( const StringBuilderImpl& ); StringBuilderImpl& operator=( const StringBuilderImpl& );
template <typename T> template <typename T>
 End of changes. 4 change blocks. 
2 lines changed or deleted 4 lines changed or added


 chunk.h   chunk.h 
skipping to change at line 21 skipping to change at line 21
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/pch.h"
#include "mongo/bson/util/atomic_int.h" #include "mongo/bson/util/atomic_int.h"
#include "mongo/client/distlock.h" #include "mongo/client/distlock.h"
#include "mongo/s/cluster_constants.h" #include "mongo/s/chunk_version.h"
#include "mongo/s/shard.h" #include "mongo/s/shard.h"
#include "mongo/s/shardkey.h" #include "mongo/s/shardkey.h"
#include "mongo/s/util.h"
#include "mongo/util/concurrency/ticketholder.h" #include "mongo/util/concurrency/ticketholder.h"
namespace mongo { namespace mongo {
class DBConfig; class DBConfig;
class Chunk; class Chunk;
class ChunkRange; class ChunkRange;
class ChunkManager; class ChunkManager;
class ChunkObjUnitTest; class ChunkObjUnitTest;
skipping to change at line 61 skipping to change at line 58
x is in a shard iff x is in a shard iff
min <= x < max min <= x < max
*/ */
class Chunk : boost::noncopyable { class Chunk : boost::noncopyable {
public: public:
Chunk( const ChunkManager * info , BSONObj from); Chunk( const ChunkManager * info , BSONObj from);
Chunk( const ChunkManager * info , Chunk( const ChunkManager * info ,
const BSONObj& min, const BSONObj& min,
const BSONObj& max, const BSONObj& max,
const Shard& shard, const Shard& shard,
ShardChunkVersion lastmod = ShardChunkVersion() ); ChunkVersion lastmod = ChunkVersion() );
// //
// serialization support // serialization support
// //
void serialize(BSONObjBuilder& to, ShardChunkVersion myLastMod=Shar dChunkVersion(0,OID())); void serialize(BSONObjBuilder& to, ChunkVersion myLastMod=ChunkVers ion(0,OID()));
// //
// chunk boundary support // chunk boundary support
// //
const BSONObj& getMin() const { return _min; } const BSONObj& getMin() const { return _min; }
const BSONObj& getMax() const { return _max; } const BSONObj& getMax() const { return _max; }
// if min/max key is pos/neg infinity // if min/max key is pos/neg infinity
bool minIsInf() const; bool minIsInf() const;
skipping to change at line 96 skipping to change at line 93
string genID() const; string genID() const;
static string genID( const string& ns , const BSONObj& min ); static string genID( const string& ns , const BSONObj& min );
// //
// chunk version support // chunk version support
// //
void appendShortVersion( const char * name , BSONObjBuilder& b ) co nst; void appendShortVersion( const char * name , BSONObjBuilder& b ) co nst;
ShardChunkVersion getLastmod() const { return _lastmod; } ChunkVersion getLastmod() const { return _lastmod; }
void setLastmod( ShardChunkVersion v ) { _lastmod = v; } void setLastmod( ChunkVersion v ) { _lastmod = v; }
// //
// split support // split support
// //
/** /**
* if the amount of data written nears the max size of a shard * if the amount of data written nears the max size of a shard
* then we check the real size, and if its too big, we split * then we check the real size, and if its too big, we split
* @return if something was split * @return if something was split
*/ */
skipping to change at line 154 skipping to change at line 151
// //
// migration support // migration support
// //
/** /**
* Issues a migrate request for this chunk * Issues a migrate request for this chunk
* *
* @param to shard to move this chunk to * @param to shard to move this chunk to
* @param chunSize maximum number of bytes beyond which the migrate should no go trhough * @param chunSize maximum number of bytes beyond which the migrate should no go trhough
* @param secondaryThrottle whether during migrate all writes shoul d block for repl * @param secondaryThrottle whether during migrate all writes shoul d block for repl
* @param waitForDelete whether chunk move should wait for cleanup or return immediately
* @param res the object containing details about the migrate execu tion * @param res the object containing details about the migrate execu tion
* @return true if move was successful * @return true if move was successful
*/ */
bool moveAndCommit( const Shard& to , long long chunkSize , bool se bool moveAndCommit(const Shard& to,
condaryThrottle, BSONObj& res ) const; long long chunkSize,
bool secondaryThrottle,
bool waitForDelete,
BSONObj& res) const;
/** /**
* @return size of shard in bytes * @return size of shard in bytes
* talks to mongod to do this * talks to mongod to do this
*/ */
long getPhysicalSize() const; long getPhysicalSize() const;
/** /**
* marks this chunk as a jumbo chunk * marks this chunk as a jumbo chunk
* that means the chunk will be inelligble for migrates * that means the chunk will be inelligble for migrates
skipping to change at line 211 skipping to change at line 213
private: private:
// main shard info // main shard info
const ChunkManager * _manager; const ChunkManager * _manager;
BSONObj _min; BSONObj _min;
BSONObj _max; BSONObj _max;
Shard _shard; Shard _shard;
ShardChunkVersion _lastmod; ChunkVersion _lastmod;
mutable bool _jumbo; mutable bool _jumbo;
// transient stuff // transient stuff
mutable long _dataWritten; mutable long _dataWritten;
// methods, etc.. // methods, etc..
/** Returns the highest or lowest existing value in the shard-key s pace. /** Returns the highest or lowest existing value in the shard-key s pace.
* Warning: this assumes that the shard key is not "special"- that is, the shardKeyPattern * Warning: this assumes that the shard key is not "special"- that is, the shardKeyPattern
skipping to change at line 318 skipping to change at line 320
}; };
/* config.sharding /* config.sharding
{ ns: 'alleyinsider.fs.chunks' , { ns: 'alleyinsider.fs.chunks' ,
key: { ts : 1 } , key: { ts : 1 } ,
shards: [ { min: 1, max: 100, server: a } , { min: 101, max: 200 , server : b } ] shards: [ { min: 1, max: 100, server: a } , { min: 101, max: 200 , server : b } ]
} }
*/ */
class ChunkManager { class ChunkManager {
public: public:
typedef map<Shard,ShardChunkVersion> ShardVersionMap; typedef map<Shard,ChunkVersion> ShardVersionMap;
// Loads a new chunk manager from a collection document // Loads a new chunk manager from a collection document
ChunkManager( const BSONObj& collDoc ); ChunkManager( const BSONObj& collDoc );
// Creates an empty chunk manager for the namespace // Creates an empty chunk manager for the namespace
ChunkManager( const string& ns, const ShardKeyPattern& pattern, boo l unique ); ChunkManager( const string& ns, const ShardKeyPattern& pattern, boo l unique );
// Updates a chunk manager based on an older manager // Updates a chunk manager based on an older manager
ChunkManager( ChunkManagerPtr oldManager ); ChunkManager( ChunkManagerPtr oldManager );
skipping to change at line 392 skipping to change at line 394
* findChunkForDoc() on {a : "foo" , b : "bar"}, or * findChunkForDoc() on {a : "foo" , b : "bar"}, or
* findIntersectingChunk() on {a : hash("foo") } * findIntersectingChunk() on {a : hash("foo") }
*/ */
ChunkPtr findIntersectingChunk( const BSONObj& point ) const; ChunkPtr findIntersectingChunk( const BSONObj& point ) const;
ChunkPtr findChunkOnServer( const Shard& shard ) const; ChunkPtr findChunkOnServer( const Shard& shard ) const;
void getShardsForQuery( set<Shard>& shards , const BSONObj& query ) const; void getShardsForQuery( set<Shard>& shards , const BSONObj& query ) const;
void getAllShards( set<Shard>& all ) const; void getAllShards( set<Shard>& all ) const;
/** @param shards set to the shards covered by the interval [min, m ax], see SERVER-4791 */ /** @param shards set to the shards covered by the interval [min, m ax], see SERVER-4791 */
void getShardsForRange(set<Shard>& shards, const BSONObj& min, cons t BSONObj& max, bool fullKeyReq = true) const; void getShardsForRange( set<Shard>& shards, const BSONObj& min, con st BSONObj& max ) const;
ChunkMap getChunkMap() const { return _chunkMap; } ChunkMap getChunkMap() const { return _chunkMap; }
/** /**
* Returns true if, for this shard, the chunks are identical in bot h chunk managers * Returns true if, for this shard, the chunks are identical in bot h chunk managers
*/ */
bool compatibleWith( const ChunkManager& other, const Shard& shard ) const; bool compatibleWith( const ChunkManager& other, const Shard& shard ) const;
bool compatibleWith( ChunkManagerPtr other, const Shard& shard ) co nst { if( ! other ) return false; return compatibleWith( *other, shard ); } bool compatibleWith( ChunkManagerPtr other, const Shard& shard ) co nst { if( ! other ) return false; return compatibleWith( *other, shard ); }
bool compatibleWith( const Chunk& other ) const; bool compatibleWith( const Chunk& other ) const;
bool compatibleWith( ChunkPtr other ) const { if( ! other ) return false; return compatibleWith( *other ); } bool compatibleWith( ChunkPtr other ) const { if( ! other ) return false; return compatibleWith( *other ); }
string toString() const; string toString() const;
ShardChunkVersion getVersion( const Shard& shard ) const; ChunkVersion getVersion( const Shard& shard ) const;
ShardChunkVersion getVersion() const; ChunkVersion getVersion() const;
void getInfo( BSONObjBuilder& b ) const { void getInfo( BSONObjBuilder& b ) const;
b.append(CollectionFields::key(), _key.key());
b.appendBool(CollectionFields::unique(), _unique);
_version.addEpochToBSON(b, CollectionFields::lastmod());
}
/** /**
* @param me - so i don't get deleted before i'm done * @param me - so i don't get deleted before i'm done
*/ */
void drop( ChunkManagerPtr me ) const; void drop( ChunkManagerPtr me ) const;
void _printChunks() const; void _printChunks() const;
int getCurrentDesiredChunkSize() const; int getCurrentDesiredChunkSize() const;
ChunkManagerPtr reload(bool force=true) const; // doesn't modify se lf! ChunkManagerPtr reload(bool force=true) const; // doesn't modify se lf!
void markMinorForReload( ShardChunkVersion majorVersion ) const; void markMinorForReload( ChunkVersion majorVersion ) const;
void getMarkedMinorVersions( set<ShardChunkVersion>& minorVersions void getMarkedMinorVersions( set<ChunkVersion>& minorVersions ) con
) const; st;
private: private:
// helpers for loading // helpers for loading
// returns true if load was consistent // returns true if load was consistent
bool _load( const string& config, ChunkMap& chunks, set<Shard>& sha rds, bool _load( const string& config, ChunkMap& chunks, set<Shard>& sha rds,
ShardVersionMap& shardVersions, ChunkMa nagerPtr oldManager); ShardVersionMap& shardVersions, ChunkMa nagerPtr oldManager);
static bool _isValid(const ChunkMap& chunks); static bool _isValid(const ChunkMap& chunks);
skipping to change at line 454 skipping to change at line 452
const bool _unique; const bool _unique;
const ChunkMap _chunkMap; const ChunkMap _chunkMap;
const ChunkRangeManager _chunkRanges; const ChunkRangeManager _chunkRanges;
const set<Shard> _shards; const set<Shard> _shards;
const ShardVersionMap _shardVersions; // max version per shard const ShardVersionMap _shardVersions; // max version per shard
// max version of any chunk // max version of any chunk
ShardChunkVersion _version; ChunkVersion _version;
// the previous manager this was based on // the previous manager this was based on
// cleared after loading chunks // cleared after loading chunks
ChunkManagerPtr _oldManager; ChunkManagerPtr _oldManager;
mutable mutex _mutex; // only used with _nsLock mutable mutex _mutex; // only used with _nsLock
const unsigned long long _sequenceNumber; const unsigned long long _sequenceNumber;
// //
skipping to change at line 476 skipping to change at line 474
// //
class SplitHeuristics { class SplitHeuristics {
public: public:
SplitHeuristics() : SplitHeuristics() :
_splitTickets( maxParallelSplits ), _splitTickets( maxParallelSplits ),
_staleMinorSetMutex( "SplitHeuristics::staleMinorSet" ), _staleMinorSetMutex( "SplitHeuristics::staleMinorSet" ),
_staleMinorCount( 0 ) {} _staleMinorCount( 0 ) {}
void markMinorForReload( const string& ns, ShardChunkVersion ma void markMinorForReload( const string& ns, ChunkVersion majorVe
jorVersion ); rsion );
void getMarkedMinorVersions( set<ShardChunkVersion>& minorVersi void getMarkedMinorVersions( set<ChunkVersion>& minorVersions )
ons ); ;
TicketHolder _splitTickets; TicketHolder _splitTickets;
mutex _staleMinorSetMutex; mutex _staleMinorSetMutex;
// mutex protects below // mutex protects below
int _staleMinorCount; int _staleMinorCount;
set<ShardChunkVersion> _staleMinorSet; set<ChunkVersion> _staleMinorSet;
// Test whether we should split once data * splitTestFactor > c hunkSize (approximately) // Test whether we should split once data * splitTestFactor > c hunkSize (approximately)
static const int splitTestFactor = 5; static const int splitTestFactor = 5;
// Maximum number of parallel threads requesting a split // Maximum number of parallel threads requesting a split
static const int maxParallelSplits = 5; static const int maxParallelSplits = 5;
// The idea here is that we're over-aggressive on split testing by a factor of // The idea here is that we're over-aggressive on split testing by a factor of
// splitTestFactor, so we can safely wait until we get to split TestFactor invalid splits // splitTestFactor, so we can safely wait until we get to split TestFactor invalid splits
// before changing. Unfortunately, we also potentially over-re quest the splits by a // before changing. Unfortunately, we also potentially over-re quest the splits by a
// factor of maxParallelSplits, but since the factors are ident ical it works out // factor of maxParallelSplits, but since the factors are ident ical it works out
skipping to change at line 553 skipping to change at line 551
} }
Chunk _c; Chunk _c;
}; };
*/ */
inline string Chunk::genID() const { return genID(_manager->getns(), _m in); } inline string Chunk::genID() const { return genID(_manager->getns(), _m in); }
bool setShardVersion( DBClientBase & conn, bool setShardVersion( DBClientBase & conn,
const string& ns, const string& ns,
ShardChunkVersion version, ChunkVersion version,
ChunkManagerPtr manager, ChunkManagerPtr manager,
bool authoritative, bool authoritative,
BSONObj& result ); BSONObj& result );
} // namespace mongo } // namespace mongo
 End of changes. 18 change blocks. 
30 lines changed or deleted 27 lines changed or added


 chunk_diff.h   chunk_diff.h 
// @file chunk.h // @file chunk_diff.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 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.h" #include "mongo/bson/bsonobj.h"
#include "../bson/bsonobj.h" #include "mongo/client/dbclientcursor.h"
#include "../client/dbclientcursor.h" #include "mongo/client/connpool.h"
#include "../client/connpool.h" #include "mongo/s/chunk.h"
#include "mongo/s/chunk_version.h"
// TODO: Ideally wouldn't need this, but ShardNS data isn't extracted from
config.h
#include "config.h"
namespace mongo { namespace mongo {
/** /**
* This class manages and applies diffs from partial config server data reloads. Because the * This class manages and applies diffs from partial config server data reloads. Because the
* config data can be large, we want to update it in small parts, not a ll-at-once. Once a * config data can be large, we want to update it in small parts, not a ll-at-once. Once a
* ConfigDiffTracker is created, the current config data is *attached* to it, and it is then * ConfigDiffTracker is created, the current config data is *attached* to it, and it is then
* able to modify the data. * able to modify the data.
* *
* The current form is templated b/c the overall algorithm is identical between mongos and * The current form is templated b/c the overall algorithm is identical between mongos and
skipping to change at line 70 skipping to change at line 68
/** /**
* The tracker attaches to a set of ranges with versions, and uses a config server * The tracker attaches to a set of ranges with versions, and uses a config server
* connection to update these. Because the set of ranges and versio ns may be large, they * connection to update these. Because the set of ranges and versio ns may be large, they
* aren't owned by the tracker, they're just passed in and updated. Therefore they must all * aren't owned by the tracker, they're just passed in and updated. Therefore they must all
* stay in scope while the tracker is working. * stay in scope while the tracker is working.
* *
* TODO: Make a standard VersionedRange to encapsulate this info in both mongod and mongos? * TODO: Make a standard VersionedRange to encapsulate this info in both mongod and mongos?
*/ */
void attach( const string& ns, void attach( const string& ns,
RangeMap& currMap, RangeMap& currMap,
ShardChunkVersion& maxVersion, ChunkVersion& maxVersion,
map<ShardType, ShardChunkVersion>& maxShardVersions ) map<ShardType, ChunkVersion>& maxShardVersions )
{ {
_ns = ns; _ns = ns;
_currMap = &currMap; _currMap = &currMap;
_maxVersion = &maxVersion; _maxVersion = &maxVersion;
_maxShardVersions = &maxShardVersions; _maxShardVersions = &maxShardVersions;
_validDiffs = 0; _validDiffs = 0;
} }
void detach(){ void detach(){
_ns = ""; _ns = "";
skipping to change at line 140 skipping to change at line 138
// Returns a subset of ranges overlapping the region min/max // Returns a subset of ranges overlapping the region min/max
RangeOverlap overlappingRange( const BSONObj& min, const BSONObj& m ax ); RangeOverlap overlappingRange( const BSONObj& min, const BSONObj& m ax );
// Finds and applies the changes to a collection from the config se rver specified // Finds and applies the changes to a collection from the config se rver specified
// Also includes minor version changes for particular major-version chunks if explicitly // Also includes minor version changes for particular major-version chunks if explicitly
// specified. // specified.
// Returns the number of diffs processed, or -1 if the diffs were i nconsistent // Returns the number of diffs processed, or -1 if the diffs were i nconsistent
// Throws a DBException on connection errors // Throws a DBException on connection errors
int calculateConfigDiff( string config, int calculateConfigDiff( string config,
const set<ShardChunkVersion>& extraMinorVe rsions = set<ShardChunkVersion>() ); const set<ChunkVersion>& extraMinorVersion s = set<ChunkVersion>() );
// Applies changes to the config data from a cursor passed in // Applies changes to the config data from a cursor passed in
// Returns the number of diffs processed, or -1 if the diffs were i nconsistent // Returns the number of diffs processed, or -1 if the diffs were i nconsistent
// Throws a DBException on connection errors // Throws a DBException on connection errors
int calculateConfigDiff( DBClientCursorInterface& diffCursor ); int calculateConfigDiff( DBClientCursorInterface& diffCursor );
// Returns the query needed to find new changes to a collection fro m the config server // Returns the query needed to find new changes to a collection fro m the config server
// Needed only if a custom connection is required to the config ser ver // Needed only if a custom connection is required to the config ser ver
Query configDiffQuery( const set<ShardChunkVersion>& extraMinorVers ions = set<ShardChunkVersion>() ) const; Query configDiffQuery( const set<ChunkVersion>& extraMinorVersions = set<ChunkVersion>() ) const;
private: private:
string _ns; string _ns;
RangeMap* _currMap; RangeMap* _currMap;
ShardChunkVersion* _maxVersion; ChunkVersion* _maxVersion;
map<ShardType, ShardChunkVersion>* _maxShardVersions; map<ShardType, ChunkVersion>* _maxShardVersions;
// Store for later use // Store for later use
int _validDiffs; int _validDiffs;
}; };
} // namespace mongo } // namespace mongo
// Include template definition // Include template definition
// TODO: Convert to normal .cpp file when normalized // TODO: Convert to normal .cpp file when normalized
 End of changes. 6 change blocks. 
15 lines changed or deleted 12 lines changed or added


 chunk_diff.hpp   chunk_diff.hpp 
skipping to change at line 22 skipping to change at line 22
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/s/chunk_diff.h" #include "mongo/s/chunk_diff.h"
#include "mongo/s/cluster_constants.h" #include "mongo/s/chunk_version.h"
#include "mongo/s/type_chunk.h"
namespace mongo { namespace mongo {
template < class ValType, class ShardType > template < class ValType, class ShardType >
bool ConfigDiffTracker<ValType,ShardType>:: bool ConfigDiffTracker<ValType,ShardType>::
isOverlapping( const BSONObj& min, const BSONObj& max ) isOverlapping( const BSONObj& min, const BSONObj& max )
{ {
RangeOverlap overlap = overlappingRange( min, max ); RangeOverlap overlap = overlappingRange( min, max );
return overlap.first != overlap.second; return overlap.first != overlap.second;
skipping to change at line 78 skipping to change at line 79
// the next chunk cannot not overlap max // the next chunk cannot not overlap max
high = _currMap->upper_bound( max ); high = _currMap->upper_bound( max );
} }
return RangeOverlap( low, high ); return RangeOverlap( low, high );
} }
template < class ValType, class ShardType > template < class ValType, class ShardType >
int ConfigDiffTracker<ValType,ShardType>:: int ConfigDiffTracker<ValType,ShardType>::
calculateConfigDiff( string config, calculateConfigDiff( string config,
const set<ShardChunkVersion>& extraMinorVersio ns ) const set<ChunkVersion>& extraMinorVersions )
{ {
verifyAttached(); verifyAttached();
// Get the diff query required // Get the diff query required
Query diffQuery = configDiffQuery( extraMinorVersions ); Query diffQuery = configDiffQuery( extraMinorVersions );
scoped_ptr<ScopedDbConnection> conn( scoped_ptr<ScopedDbConnection> conn(
ScopedDbConnection::getInternalScopedDbConnection( config ) ); ScopedDbConnection::getInternalScopedDbConnection( config ) );
try { try {
// Open a cursor for the diff chunks // Open a cursor for the diff chunks
auto_ptr<DBClientCursor> cursor = conn->get()->query( auto_ptr<DBClientCursor> cursor = conn->get()->query(
ConfigNS::chunk, diffQuery, 0, 0, 0, 0, ( DEBUG_BUILD ? 2 : 1000000 ) ); ChunkType::ConfigNS, diffQuery, 0, 0, 0, 0, ( DEBUG_BUI LD ? 2 : 1000000 ) );
verify( cursor.get() ); verify( cursor.get() );
int diff = calculateConfigDiff( *cursor.get() ); int diff = calculateConfigDiff( *cursor.get() );
conn->done(); conn->done();
return diff; return diff;
} }
catch( DBException& e ){ catch( DBException& e ){
// Should only happen on connection errors // Should only happen on connection errors
skipping to change at line 133 skipping to change at line 134
vector<BSONObj> newTracked; vector<BSONObj> newTracked;
// Store epoch now so it doesn't change when we change max // Store epoch now so it doesn't change when we change max
OID currEpoch = _maxVersion->epoch(); OID currEpoch = _maxVersion->epoch();
_validDiffs = 0; _validDiffs = 0;
while( diffCursor.more() ){ while( diffCursor.more() ){
BSONObj diffChunkDoc = diffCursor.next(); BSONObj diffChunkDoc = diffCursor.next();
ShardChunkVersion chunkVersion = ShardChunkVersion::fromBSON(di ffChunkDoc, ChunkFields::lastmod()); ChunkVersion chunkVersion = ChunkVersion::fromBSON(diffChunkDoc , ChunkType::DEPRECATED_lastmod());
if( diffChunkDoc[ChunkFields::min()].type() != Object || if( diffChunkDoc[ChunkType::min()].type() != Object ||
diffChunkDoc[ChunkFields::max()].type() != Object || diffChunkDoc[ChunkType::max()].type() != Object ||
diffChunkDoc[ChunkFields::shard()].type() != String ) diffChunkDoc[ChunkType::shard()].type() != String )
{ {
warning() << "got invalid chunk document " << diffChunkDoc warning() << "got invalid chunk document " << diffChunkDoc
<< " when trying to load differing chunks" << end l; << " when trying to load differing chunks" << end l;
continue; continue;
} }
if( ! chunkVersion.isSet() || ! chunkVersion.hasCompatibleEpoch ( currEpoch ) ){ if( ! chunkVersion.isSet() || ! chunkVersion.hasCompatibleEpoch ( currEpoch ) ){
warning() << "got invalid chunk version " << chunkVersion < < " in document " << diffChunkDoc warning() << "got invalid chunk version " << chunkVersion < < " in document " << diffChunkDoc
<< " when trying to load differing chunks at vers ion " << " when trying to load differing chunks at vers ion "
<< ShardChunkVersion( _maxVersion->toLong(), curr Epoch ) << endl; << ChunkVersion( _maxVersion->toLong(), currEpoch ) << endl;
// Don't keep loading, since we know we'll be broken here // Don't keep loading, since we know we'll be broken here
return -1; return -1;
} }
_validDiffs++; _validDiffs++;
// Get max changed version and chunk version // Get max changed version and chunk version
if( chunkVersion > *_maxVersion ) *_maxVersion = chunkVersion; if( chunkVersion > *_maxVersion ) *_maxVersion = chunkVersion;
// Chunk version changes // Chunk version changes
ShardType shard = shardFor( diffChunkDoc[ChunkFields::shard()]. ShardType shard = shardFor( diffChunkDoc[ChunkType::shard()].St
String() ); ring() );
typename map<ShardType, ShardChunkVersion>::iterator shardVersi typename map<ShardType, ChunkVersion>::iterator shardVersionIt
onIt = _maxShardVersions->find( shard ); = _maxShardVersions->find( shard );
if( shardVersionIt == _maxShardVersions->end() || shardVersionI t->second < chunkVersion ){ if( shardVersionIt == _maxShardVersions->end() || shardVersionI t->second < chunkVersion ){
(*_maxShardVersions)[ shard ] = chunkVersion; (*_maxShardVersions)[ shard ] = chunkVersion;
} }
// See if we need to remove any chunks we are currently trackin g b/c of this chunk's changes // See if we need to remove any chunks we are currently trackin g b/c of this chunk's changes
removeOverlapping(diffChunkDoc[ChunkFields::min()].Obj(), removeOverlapping(diffChunkDoc[ChunkType::min()].Obj(),
diffChunkDoc[ChunkFields::max()].Obj()); diffChunkDoc[ChunkType::max()].Obj());
// Figure out which of the new chunks we need to track // Figure out which of the new chunks we need to track
// Important - we need to actually own this doc, in case the cu rsor decides to getMore or unbuffer // Important - we need to actually own this doc, in case the cu rsor decides to getMore or unbuffer
if( isTracked( diffChunkDoc ) ) newTracked.push_back( diffChunk Doc.getOwned() ); if( isTracked( diffChunkDoc ) ) newTracked.push_back( diffChunk Doc.getOwned() );
} }
LOG(3) << "found " << _validDiffs << " new chunks for collection " << _ns LOG(3) << "found " << _validDiffs << " new chunks for collection " << _ns
<< " (tracking " << newTracked.size() << "), new version is " << _maxVersion << endl; << " (tracking " << newTracked.size() << "), new version is " << _maxVersion << endl;
for( vector<BSONObj>::iterator it = newTracked.begin(); it != newTr acked.end(); it++ ){ for( vector<BSONObj>::iterator it = newTracked.begin(); it != newTr acked.end(); it++ ){
BSONObj chunkDoc = *it; BSONObj chunkDoc = *it;
// Important - we need to make sure we actually own the min and max here // Important - we need to make sure we actually own the min and max here
BSONObj min = chunkDoc[ChunkFields::min()].Obj().getOwned(); BSONObj min = chunkDoc[ChunkType::min()].Obj().getOwned();
BSONObj max = chunkDoc[ChunkFields::max()].Obj().getOwned(); BSONObj max = chunkDoc[ChunkType::max()].Obj().getOwned();
// Invariant enforced by sharding // Invariant enforced by sharding
// It's possible to read inconsistent state b/c of getMore() an d yielding, so we want // It's possible to read inconsistent state b/c of getMore() an d yielding, so we want
// to detect as early as possible. // to detect as early as possible.
// TODO: This checks for overlap, we also should check for hole s here iff we're tracking // TODO: This checks for overlap, we also should check for hole s here iff we're tracking
// all chunks // all chunks
if( isOverlapping( min, max ) ) return -1; if( isOverlapping( min, max ) ) return -1;
_currMap->insert( rangeFor( chunkDoc, min, max ) ); _currMap->insert( rangeFor( chunkDoc, min, max ) );
} }
return _validDiffs; return _validDiffs;
} }
template < class ValType, class ShardType > template < class ValType, class ShardType >
Query ConfigDiffTracker<ValType,ShardType>:: Query ConfigDiffTracker<ValType,ShardType>::
configDiffQuery( const set<ShardChunkVersion>& extraMinorVersions ) const configDiffQuery( const set<ChunkVersion>& extraMinorVersions ) cons t
{ {
verifyAttached(); verifyAttached();
// //
// Basic idea behind the query is to find all the chunks $gt the cu rrent max version, and // Basic idea behind the query is to find all the chunks $gt the cu rrent max version, and
// then also update chunks that we need minor versions - splits and (2.0) max chunks on // then also update chunks that we need minor versions - splits and (2.0) max chunks on
// shards // shards
// //
static const int maxMinorVersionClauses = 50; static const int maxMinorVersionClauses = 50;
BSONObjBuilder queryB; BSONObjBuilder queryB;
int numStaleMinorClauses = extraMinorVersions.size() + _maxShardVer sions->size(); int numStaleMinorClauses = extraMinorVersions.size() + _maxShardVer sions->size();
#ifdef _DEBUG #ifdef _DEBUG
// In debug builds, randomly trigger full reloads to exercise both codepaths // In debug builds, randomly trigger full reloads to exercise both codepaths
if( rand() % 2 ) numStaleMinorClauses = maxMinorVersionClauses; if( rand() % 2 ) numStaleMinorClauses = maxMinorVersionClauses;
#endif #endif
queryB.append(ChunkFields::ns(), _ns); queryB.append(ChunkType::ns(), _ns);
// //
// If we have only a few minor versions to refresh, we can be more selective in our query // If we have only a few minor versions to refresh, we can be more selective in our query
// //
if( numStaleMinorClauses < maxMinorVersionClauses ){ if( numStaleMinorClauses < maxMinorVersionClauses ){
// //
// Get any version changes higher than we know currently // Get any version changes higher than we know currently
// //
BSONArrayBuilder queryOrB( queryB.subarrayStart( "$or" ) ); BSONArrayBuilder queryOrB( queryB.subarrayStart( "$or" ) );
{ {
BSONObjBuilder queryNewB( queryOrB.subobjStart() ); BSONObjBuilder queryNewB( queryOrB.subobjStart() );
{ {
BSONObjBuilder ts(queryNewB.subobjStart(ChunkFields::la stmod())); BSONObjBuilder ts(queryNewB.subobjStart(ChunkType::DEPR ECATED_lastmod()));
// We should *always* pull at least a single chunk back , this lets us quickly // We should *always* pull at least a single chunk back , this lets us quickly
// detect if our collection was unsharded (and most of the time if it was // detect if our collection was unsharded (and most of the time if it was
// resharded) in the meantime // resharded) in the meantime
ts.appendTimestamp( "$gte", _maxVersion->toLong() ); ts.appendTimestamp( "$gte", _maxVersion->toLong() );
ts.done(); ts.done();
} }
queryNewB.done(); queryNewB.done();
} }
// Get any shard version changes higher than we know currently // Get any shard version changes higher than we know currently
// Needed since there could have been a split of the max versio n chunk of any shard // Needed since there could have been a split of the max versio n chunk of any shard
// TODO: Ideally, we shouldn't care about these // TODO: Ideally, we shouldn't care about these
for( typename map<ShardType, ShardChunkVersion>::const_iterator it = _maxShardVersions->begin(); it != _maxShardVersions->end(); it++ ){ for( typename map<ShardType, ChunkVersion>::const_iterator it = _maxShardVersions->begin(); it != _maxShardVersions->end(); it++ ){
BSONObjBuilder queryShardB( queryOrB.subobjStart() ); BSONObjBuilder queryShardB( queryOrB.subobjStart() );
queryShardB.append(ChunkFields::shard(), nameFrom( it->firs t ) ); queryShardB.append(ChunkType::shard(), nameFrom( it->first ) );
{ {
BSONObjBuilder ts(queryShardB.subobjStart(ChunkFields:: lastmod())); BSONObjBuilder ts(queryShardB.subobjStart(ChunkType::DE PRECATED_lastmod()));
ts.appendTimestamp( "$gt", it->second.toLong() ); ts.appendTimestamp( "$gt", it->second.toLong() );
ts.done(); ts.done();
} }
queryShardB.done(); queryShardB.done();
} }
// Get any minor version changes we've marked as interesting // Get any minor version changes we've marked as interesting
// TODO: Ideally we shouldn't care about these // TODO: Ideally we shouldn't care about these
for( set<ShardChunkVersion>::const_iterator it = extraMinorVers ions.begin(); it != extraMinorVersions.end(); it++ ){ for( set<ChunkVersion>::const_iterator it = extraMinorVersions. begin(); it != extraMinorVersions.end(); it++ ){
BSONObjBuilder queryShardB( queryOrB.subobjStart() ); BSONObjBuilder queryShardB( queryOrB.subobjStart() );
{ {
BSONObjBuilder ts(queryShardB.subobjStart(ChunkFields:: lastmod())); BSONObjBuilder ts(queryShardB.subobjStart(ChunkType::DE PRECATED_lastmod()));
ts.appendTimestamp( "$gt", it->toLong() ); ts.appendTimestamp( "$gt", it->toLong() );
ts.appendTimestamp( "$lt", ts.appendTimestamp( "$lt",
ShardChunkVersion( it->majorVersion () + 1, 0, OID() ).toLong() ); ChunkVersion( it->majorVersion() + 1, 0, OID() ).toLong() );
ts.done(); ts.done();
} }
queryShardB.done(); queryShardB.done();
} }
queryOrB.done(); queryOrB.done();
} }
BSONObj query = queryB.obj(); BSONObj query = queryB.obj();
 End of changes. 18 change blocks. 
25 lines changed or deleted 26 lines changed or added


 client.h   client.h 
skipping to change at line 29 skipping to change at line 29
* 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 "mongo/db/client_common.h" #include "mongo/db/client_basic.h"
#include "mongo/db/d_concurrency.h" #include "mongo/db/d_concurrency.h"
#include "mongo/db/lasterror.h" #include "mongo/db/lasterror.h"
#include "mongo/db/lockstate.h" #include "mongo/db/lockstate.h"
#include "mongo/db/namespace-inl.h" #include "mongo/db/namespace-inl.h"
#include "mongo/db/security.h"
#include "mongo/db/stats/top.h" #include "mongo/db/stats/top.h"
#include "mongo/util/concurrency/rwlock.h" #include "mongo/util/concurrency/rwlock.h"
#include "mongo/util/concurrency/threadlocal.h" #include "mongo/util/concurrency/threadlocal.h"
#include "mongo/util/paths.h" #include "mongo/util/paths.h"
namespace mongo { namespace mongo {
extern class ReplSet *theReplSet; extern class ReplSet *theReplSet;
class AuthenticationInfo; class AuthenticationInfo;
class Database; class Database;
skipping to change at line 84 skipping to change at line 83
return; return;
initThread(desc); initThread(desc);
} }
/** 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;
const AuthenticationInfo * getAuthenticationInfo() const { return &
_ai; }
AuthenticationInfo * getAuthenticationInfo() { return &_ai; }
bool isAdmin() { return _ai.isAuthorized( "admin" ); }
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(); }
const std::string desc() const { return _desc; } const std::string desc() const { return _desc; }
void setLastOp( OpTime op ) { _lastOp = op; } void setLastOp( OpTime op ) { _lastOp = op; }
OpTime getLastOp() const { return _lastOp; } OpTime getLastOp() const { return _lastOp; }
/** caution -- use Context class instead */ /** caution -- use Context class instead */
void setContext(Context *c) { _context = c; } void setContext(Context *c) { _context = c; }
skipping to change at line 129 skipping to change at line 125
private: private:
Client(const char *desc, AbstractMessagingPort *p = 0); Client(const char *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;
AuthenticationInfo _ai;
OpTime _lastOp; OpTime _lastOp;
BSONObj _handshake; BSONObj _handshake;
BSONObj _remoteId; BSONObj _remoteId;
bool _hasWrittenThisPass; bool _hasWrittenThisPass;
PageFaultRetryableSection *_pageFaultRetryableSection; PageFaultRetryableSection *_pageFaultRetryableSection;
LockState _ls; LockState _ls;
friend class PageFaultRetryableSection; // TEMP friend class PageFaultRetryableSection; // TEMP
skipping to change at line 158 skipping to change at line 153
~GodScope(); ~GodScope();
}; };
//static void assureDatabaseIsOpen(const string& ns, string path=db path); //static void assureDatabaseIsOpen(const string& ns, string path=db path);
/** "read lock, and set my context, all in one operation" /** "read lock, and set my context, all in one operation"
* This handles (if not recursively locked) opening an unopened da tabase. * This handles (if not recursively locked) opening an unopened da tabase.
*/ */
class ReadContext : boost::noncopyable { class ReadContext : boost::noncopyable {
public: public:
ReadContext(const std::string& ns, const std::string& path=dbpa th, bool doauth=true ); ReadContext(const std::string& ns, const std::string& path=dbpa th);
Context& ctx() { return *c.get(); } Context& ctx() { return *c.get(); }
private: private:
scoped_ptr<Lock::DBRead> lk; scoped_ptr<Lock::DBRead> lk;
scoped_ptr<Context> c; scoped_ptr<Context> c;
}; };
/* Set database we want to use, then, restores when we finish (are out of scope) /* Set database we want to use, then, restores when we finish (are out of scope)
Note this is also helpful if an exception happens as the state i f fixed up. Note this is also helpful if an exception happens as the state i f fixed up.
*/ */
class Context : boost::noncopyable { class Context : boost::noncopyable {
public: public:
/** this is probably what you want */ /** this is probably what you want */
Context(const string& ns, const std::string& path=dbpath, bool doauth=true, bool doVersion=true ); Context(const string& ns, const std::string& path=dbpath, bool doVersion=true);
/** note: this does not call finishInit -- i.e., does not call /** note: this does not call finishInit -- i.e., does not call
shardVersionOk() for example. shardVersionOk() for example.
see also: reset(). see also: reset().
*/ */
Context( const std::string& ns , Database * db, bool doauth=tru e ); Context(const std::string& ns , Database * db);
// used by ReadContext // used by ReadContext
Context(const string& path, const string& ns, Database *db, boo l doauth); Context(const string& path, const string& ns, Database *db);
~Context(); ~Context();
Client* getClient() const { return _client; } Client* getClient() const { return _client; }
Database* db() const { return _db; } Database* db() const { return _db; }
const char * ns() const { return _ns.c_str(); } const char * ns() const { return _ns.c_str(); }
bool equals( const string& ns , const string& path=dbpath ) con st { return _ns == ns && _path == path; } bool equals( const string& ns , const string& path=dbpath ) con st { return _ns == ns && _path == path; }
/** @return if the db was created by this Context */ /** @return if the db was created by this Context */
bool justCreated() const { return _justCreated; } bool justCreated() const { return _justCreated; }
skipping to change at line 209 skipping to change at line 204
/** call before unlocking, so clear any non-thread safe state /** call before unlocking, so clear any non-thread safe state
* _db gets restored on the relock * _db gets restored on the relock
*/ */
void unlocked() { _db = 0; } void unlocked() { _db = 0; }
/** call after going back into the lock, will re-establish non- thread safe stuff */ /** call after going back into the lock, will re-establish non- thread safe stuff */
void relocked() { _finishInit(); } void relocked() { _finishInit(); }
private: private:
friend class CurOp; friend class CurOp;
void _finishInit( bool doauth=true); void _finishInit();
void _auth( int lockState );
void checkNotStale() const; void checkNotStale() const;
void checkNsAccess( bool doauth ); void checkNsAccess( bool doauth );
void checkNsAccess( bool doauth, int lockState ); void checkNsAccess( bool doauth, int lockState );
Client * const _client; Client * const _client;
Context * const _oldContext; Context * const _oldContext;
const string _path; const string _path;
bool _justCreated; bool _justCreated;
bool _doVersion; bool _doVersion;
const string _ns; const string _ns;
Database * _db; Database * _db;
Timer _timer; Timer _timer;
}; // class Client::Context }; // class Client::Context
class WriteContext : boost::noncopyable { class WriteContext : boost::noncopyable {
public: public:
WriteContext(const string& ns, const std::string& path=dbpath, bool doauth=true ); WriteContext(const string& ns, const std::string& path=dbpath);
Context& ctx() { return _c; } Context& ctx() { return _c; }
private: private:
Lock::DBWrite _lk; Lock::DBWrite _lk;
Context _c; Context _c;
}; };
}; // class Client }; // class Client
/** get the Client object for this thread. */ /** get the Client object for this thread. */
inline Client& cc() { inline Client& cc() {
 End of changes. 10 change blocks. 
14 lines changed or deleted 7 lines changed or added


 client_info.h   client_info.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/pch.h" #include "mongo/pch.h"
#include "mongo/db/client_common.h" #include "mongo/db/client_basic.h"
#include "mongo/db/security.h"
#include "mongo/s/chunk.h" #include "mongo/s/chunk.h"
#include "mongo/s/writeback_listener.h" #include "mongo/s/writeback_listener.h"
#include "mongo/util/net/hostandport.h" #include "mongo/util/net/hostandport.h"
namespace mongo { namespace mongo {
class AbstractMessagingPort; class AbstractMessagingPort;
/** /**
* holds information about a client connected to a mongos * holds information about a client connected to a mongos
skipping to change at line 110 skipping to change at line 109
void noAutoSplit() { _autoSplitOk = false; } void noAutoSplit() { _autoSplitOk = false; }
// Returns whether or not a ClientInfo for this thread has already been created and stored // Returns whether or not a ClientInfo for this thread has already been created and stored
// in _tlInfo. // in _tlInfo.
static bool exists(); static bool exists();
// Gets the ClientInfo object for this thread from _tlInfo. If no C lientInfo object exists // Gets the ClientInfo object for this thread from _tlInfo. If no C lientInfo object exists
// yet for this thread, it creates one. // yet for this thread, it creates one.
static ClientInfo * get(AbstractMessagingPort* messagingPort = NULL ); static ClientInfo * get(AbstractMessagingPort* messagingPort = NULL );
// Creates a ClientInfo and stores it in _tlInfo // Creates a ClientInfo and stores it in _tlInfo
static ClientInfo* create(AbstractMessagingPort* messagingPort); static ClientInfo* create(AbstractMessagingPort* messagingPort);
const AuthenticationInfo* getAuthenticationInfo() const { return (A
uthenticationInfo*)&_ai; }
AuthenticationInfo* getAuthenticationInfo() { return (Authenticatio
nInfo*)&_ai; }
bool isAdmin() { return _ai.isAuthorized( "admin" ); }
private: private:
AuthenticationInfo _ai;
struct WBInfo { struct WBInfo {
WBInfo( const WriteBackListener::ConnectionIdent& c , OID o ) : WBInfo( const WriteBackListener::ConnectionIdent& c, OID o, boo
ident( c ) , id( o ) {} l fromLastOperation )
: ident( c ), id( o ), fromLastOperation( fromLastOperation
) {}
WriteBackListener::ConnectionIdent ident; WriteBackListener::ConnectionIdent ident;
OID id; OID id;
bool fromLastOperation;
}; };
// Used to set up this thread's AuthorizationManager. Should be ca
lled during the
// initialization of this ClientInfo.
void _setupAuth();
// for getLastError // for getLastError
void _addWriteBack( vector<WBInfo>& all , const BSONObj& o ); void _addWriteBack( vector<WBInfo>& all , const BSONObj& o, bool fr
vector<BSONObj> _handleWriteBacks( vector<WBInfo>& all , bool fromW omLastOperation );
riteBackListener ); vector<BSONObj> _handleWriteBacks( const vector<WBInfo>& all , bool
fromWriteBackListener );
int _id; // unique client id int _id; // unique client id
HostAndPort _remote; // server:port of remote socket end HostAndPort _remote; // server:port of remote socket end
// we use _a and _b to store shards we've talked to on the current request and the previous // we use _a and _b to store shards we've talked to on the current request and the previous
// we use 2 so we can flip for getLastError type operations // we use 2 so we can flip for getLastError type operations
set<string> _a; // actual set for _cur or _prev set<string> _a; // actual set for _cur or _prev
set<string> _b; // " set<string> _b; // "
 End of changes. 7 change blocks. 
18 lines changed or deleted 10 lines changed or added


 clientcursor.h   clientcursor.h 
skipping to change at line 327 skipping to change at line 327
ClientCursor *c = find_inlock(id, warn); ClientCursor *c = find_inlock(id, warn);
// if this asserts, your code was not thread safe - you either need to set no timeout // if this asserts, your code was not thread safe - you either need to set no timeout
// for the cursor or keep a ClientCursor::Pointer in scope for it. // for the cursor or keep a ClientCursor::Pointer in scope for it.
massert( 12521, "internal error: use of an unlocked ClientCurso r", c == 0 || c->_pinValue ); massert( 12521, "internal error: use of an unlocked ClientCurso r", c == 0 || c->_pinValue );
return c; return c;
} }
/** /**
* Deletes the cursor with the provided @param 'id' if one exists. * Deletes the cursor with the provided @param 'id' if one exists.
* @throw if the cursor with the provided id is pinned. * @throw if the cursor with the provided id is pinned.
* This does not do any auth checking and should be used only when
erasing cursors as part
* of cleaning up internal operations.
*/ */
static bool erase(CursorId id); static bool erase(CursorId id);
// Same as erase but checks to make sure this thread has read permi
ssion on the cursor's
// namespace. This should be called when receiving killCursors fro
m a client.
static bool eraseIfAuthorized(CursorId id);
/** /**
* @return number of cursors found * @return number of cursors found
*/ */
static int erase( int n , long long * ids ); static int erase(int n, long long* ids);
static int eraseIfAuthorized(int n, long long* ids);
void mayUpgradeStorage() { void mayUpgradeStorage() {
/* if ( !ids_.get() ) /* if ( !ids_.get() )
return; return;
stringstream ss; stringstream ss;
ss << ns << "." << cursorid; ss << ns << "." << cursorid;
ids_->mayUpgradeStorage( ss.str() );*/ ids_->mayUpgradeStorage( ss.str() );*/
} }
/** /**
skipping to change at line 379 skipping to change at line 385
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; }
Record* _recordForYield( RecordNeeds need ); Record* _recordForYield( RecordNeeds need );
static bool _erase_inlock(ClientCursor* cursor);
private: private:
CursorId _cursorid; CursorId _cursorid;
const string _ns; const string _ns;
Database * _db; Database * _db;
const shared_ptr<Cursor> _c; const shared_ptr<Cursor> _c;
map<string,int> _indexedFields; // map from indexed field to offse t in key object map<string,int> _indexedFields; // map from indexed field to offse t in key object
 End of changes. 4 change blocks. 
1 lines changed or deleted 11 lines changed or added


 cloner.h   cloner.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 "mongo/db/sort_phase_one.h"
namespace mongo { namespace mongo {
struct CloneOptions;
class IndexSpec;
class DBClientBase;
class DBClientCursor;
class Query;
class Cloner: boost::noncopyable {
public:
Cloner();
/**
* 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
* snapshot - use $snapshot mode for copying collections. note
this should not be used
* when it isn't required, as it will be slower. fo
r example,
* repairDatabase need not use it.
*/
void setConnection( DBClientBase *c ) { _conn.reset( c ); }
/** copy the entire database */
bool go(const char *masterHost, string& errmsg, const string& fromd
b, bool logForRepl,
bool slaveOk, bool useReplAuth, bool snapshot, bool mayYiel
d,
bool mayBeInterrupted, int *errCode = 0);
bool go(const char *masterHost, const CloneOptions& opts, set<strin
g>& clonedColls,
string& errmsg, 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 mayYield, bool mayBeInterrupted, bool copy
Indexes = true,
bool logForRepl = true );
/**
* validate the cloner query was successful
* @param cur Cursor the query was executed on
* @param errCode out Error code encountered during the query
*/
static bool validateQueryResults(const auto_ptr<DBClientCursor>& cu
r, int32_t* errCode);
/**
* @param errmsg out - Error message (if encountered).
* @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
* cloning.
* @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
* repairDatabase need not use it.
* @param errCode out - If provided, this will be set on error to t
he server's error code.
* Currently this will only be set if there is
an error in the initial
* system.namespaces query.
*/
static bool cloneFrom(const char *masterHost, string& errmsg, const
string& fromdb,
bool logForReplication, bool slaveOk, bool us
eReplAuth,
bool snapshot, bool mayYield, bool mayBeInter
rupted,
int *errCode = 0);
static bool cloneFrom(const string& masterHost, const CloneOptions&
options,
string& errmsg, int* errCode = 0,
set<string>* clonedCollections = 0);
/**
* Copy a collection (and indexes) from a remote host
*/
static bool copyCollectionFromRemote(const string& host, const stri
ng& ns, string& errmsg);
private:
void copy(const char *from_ns, const char *to_ns, bool isindex, boo
l logForRepl,
bool masterSameProcess, bool slaveOk, bool mayYield, bool
mayBeInterrupted,
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;
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;
mayBeInterrupted = false; mayBeInterrupted = false;
skipping to change at line 53 skipping to change at line 137
bool slaveOk; bool slaveOk;
bool useReplAuth; bool useReplAuth;
bool snapshot; bool snapshot;
bool mayYield; bool mayYield;
bool mayBeInterrupted; bool mayBeInterrupted;
bool syncData; bool syncData;
bool syncIndexes; bool syncIndexes;
}; };
bool cloneFrom( const string& masterHost ,
const CloneOptions& options ,
string& errmsg /* out */ ,
int* errCode = 0 /* out */ ,
set<string>* clonedCollections = 0 /* out */ );
/**
* @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 replic
ation slave for the cloning
* @param snapshot - use $snapshot mode for copying collections. no
te this should not be used when it isn't required, as it will be slower.
* for example repairDatabase need not use it.
* @param errCode - If provided, this will be set on error to the s
erver's error code. Currently
* this will only be set if there is an error in t
he initial system.namespaces query.
*/
bool cloneFrom(const char *masterHost, string& errmsg, const string& fr
omdb, bool logForReplication,
bool slaveOk, bool useReplAuth, bool snapshot, bool mayY
ield,
bool mayBeInterrupted, int *errCode = 0);
bool copyCollectionFromRemote(const string& host, const string& ns, str
ing& errmsg);
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
29 lines changed or deleted 111 lines changed or added


 cmdline.h   cmdline.h 
skipping to change at line 35 skipping to change at line 35
namespace boost { namespace boost {
namespace program_options { namespace program_options {
class options_description; class options_description;
class positional_options_description; class positional_options_description;
class variables_map; class variables_map;
} }
} }
namespace mongo { namespace mongo {
#ifdef MONGO_SSL
class SSLManager;
#endif
/* command line options /* command line options
*/ */
/* concurrency: OK/READ */ /* concurrency: OK/READ */
struct CmdLine { struct CmdLine {
CmdLine(); CmdLine();
std::string binaryName; // mongod or mongos std::string binaryName; // mongod or mongos
std::string cwd; // cwd of when process started std::string cwd; // cwd of when process started
skipping to change at line 142 skipping to change at line 138
#ifndef _WIN32 #ifndef _WIN32
pid_t parentProc; // --fork pid of initial process pid_t parentProc; // --fork pid of initial process
pid_t leaderProc; // --fork pid of leader process pid_t leaderProc; // --fork pid of leader process
#endif #endif
#ifdef MONGO_SSL #ifdef MONGO_SSL
bool sslOnNormalPorts; // --sslOnNormalPorts bool sslOnNormalPorts; // --sslOnNormalPorts
std::string sslPEMKeyFile; // --sslPEMKeyFile std::string sslPEMKeyFile; // --sslPEMKeyFile
std::string sslPEMKeyPassword; // --sslPEMKeyPassword std::string sslPEMKeyPassword; // --sslPEMKeyPassword
std::string sslCAFile; // --sslCAFile
SSLManager* sslServerManager; // currently leaks on close std::string sslCRLFile; // --sslCRLFile
bool sslForceCertificateValidation;
#endif #endif
/** /**
* Switches to enable experimental (unsupported) features. * Switches to enable experimental (unsupported) features.
*/ */
struct ExperimentalFeatures { struct ExperimentalFeatures {
ExperimentalFeatures() ExperimentalFeatures()
: indexStatsCmdEnabled(false) : indexStatsCmdEnabled(false)
, storageDetailsCmdEnabled(false) , storageDetailsCmdEnabled(false)
{} {}
skipping to change at line 194 skipping to change at line 191
static BSONObj getParsedOpts(); static BSONObj getParsedOpts();
time_t started; time_t started;
}; };
// todo move to cmdline.cpp? // todo move to cmdline.cpp?
inline CmdLine::CmdLine() : inline CmdLine::CmdLine() :
port(DefaultDBPort), rest(false), jsonp(false), indexBuildRetry(tru e), quiet(false), port(DefaultDBPort), rest(false), jsonp(false), indexBuildRetry(tru e), quiet(false),
noTableScan(false), prealloc(true), preallocj(true), smallfiles(siz eof(int*) == 4), noTableScan(false), prealloc(true), preallocj(true), smallfiles(siz eof(int*) == 4),
configsvr(false), quota(false), quotaFiles(8), cpu(false), configsvr(false), quota(false), quotaFiles(8), cpu(false),
durOptions(0), objcheck(false), oplogSize(0), defaultProfile(0), durOptions(0), objcheck(true), oplogSize(0), defaultProfile(0),
slowMS(100), defaultLocalThresholdMillis(15), pretouch(0), movePara slowMS(100), defaultLocalThresholdMillis(15), pretouch(0), movePara
noia( true ), noia( false ),
syncdelay(60), noUnixSocket(false), doFork(0), socket("/tmp"), maxC onns(DEFAULT_MAX_CONN), syncdelay(60), noUnixSocket(false), doFork(0), socket("/tmp"), maxC onns(DEFAULT_MAX_CONN),
logAppend(false), logWithSyslog(false) logAppend(false), logWithSyslog(false)
{ {
started = time(0); started = time(0);
journalCommitInterval = 0; // 0 means use default journalCommitInterval = 0; // 0 means use default
dur = false; dur = false;
#if defined(_DURABLEDEFAULTON) #if defined(_DURABLEDEFAULTON)
dur = true; dur = true;
#endif #endif
if( sizeof(void*) == 8 ) if( sizeof(void*) == 8 )
dur = true; dur = true;
#if defined(_DURABLEDEFAULTOFF) #if defined(_DURABLEDEFAULTOFF)
dur = false; dur = false;
#endif #endif
#ifdef MONGO_SSL #ifdef MONGO_SSL
sslOnNormalPorts = false; sslOnNormalPorts = false;
sslServerManager = 0;
#endif #endif
} }
extern CmdLine cmdLine; extern CmdLine cmdLine;
void printCommandLineOpts(); void printCommandLineOpts();
/**
* used for setParameter command
* so you can write validation code that lives with code using it
* rather than all in the command place
* also lets you have mongos or mongod specific code
* without pulling it all sorts of things
*/
class ParameterValidator {
public:
ParameterValidator( const std::string& name );
virtual ~ParameterValidator() {}
virtual bool isValid( BSONElement e , std::string& errmsg ) const =
0;
static ParameterValidator * get( const std::string& name );
private:
const std::string _name;
};
} }
 End of changes. 5 change blocks. 
32 lines changed or deleted 6 lines changed or added


 commands.h   commands.h 
skipping to change at line 22 skipping to change at line 22
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <vector> #include <vector>
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/privilege.h" #include "mongo/db/auth/privilege.h"
#include "mongo/db/client_basic.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/util/mongoutils/str.h" #include "mongo/util/mongoutils/str.h"
namespace mongo { namespace mongo {
class BSONObj; class BSONObj;
class BSONObjBuilder; class BSONObjBuilder;
class Client; class Client;
class Timer; class Timer;
skipping to change at line 118 skipping to change at line 122
(e.g., getnonce, authenticate) can be done by anyone even unauth orized. (e.g., getnonce, authenticate) can be done by anyone even unauth orized.
*/ */
virtual bool requiresAuth() { return true; } 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); 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.
*/ */
virtual bool maintenanceMode() const { return false; } virtual bool maintenanceMode() const { return false; }
/* Return true if command should be permitted when a replica set se condary is in "recovering" /* Return true if command should be permitted when a replica set se condary is in "recovering"
(unreadable) state. (unreadable) state.
*/ */
virtual bool maintenanceOk() const { return true; /* assumed true p rior to commit */ } virtual bool maintenanceOk() const { return true; /* assumed true p rior to commit */ }
skipping to change at line 155 skipping to change at line 159
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:
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 and executed */ /** @return if command was found */
static bool runAgainstRegistered(const char *ns, BSONObj& jsobj, BS static void runAgainstRegistered(const char *ns,
ONObjBuilder& anObjBuilder, int queryOptions = 0); BSONObj& jsobj,
BSONObjBuilder& anObjBuilder,
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.
static void execCommand(Command* c,
Client& client,
int queryOptions,
const char *ns,
BSONObj& cmdObj,
BSONObjBuilder& result,
bool fromRepl );
// For mongos
static void execCommandClientBasic(Command* c,
ClientBasic& client,
int queryOptions,
const char *ns,
BSONObj& cmdObj,
BSONObjBuilder& result,
bool fromRepl );
// Helper for setting errmsg and ok field in command result object.
static void appendCommandStatus(BSONObjBuilder& result, bool ok, co
nst std::string& errmsg);
// Set by command line. Controls whether or not testing-only comma
nds should be available.
static int testCommandsEnabled;
};
// This will be registered instead of the real implementations of any c
ommands that don't work
// when auth is enabled.
class NotWithAuthCmd : public Command {
public:
NotWithAuthCmd(const char* cmdName) : Command(cmdName) { }
virtual bool slaveOk() const { return true; }
virtual LockType locktype() const { return NONE; }
virtual bool requiresAuth() { return false; }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {}
virtual void help( stringstream &help ) const {
help << name << " is not supported when running with authentica
tion enabled";
}
virtual bool run(const string&,
BSONObj& cmdObj,
int,
string& errmsg,
BSONObjBuilder& result,
bool fromRepl) {
errmsg = name + " is not supported when running with authentica
tion enabled";
log() << errmsg << std::endl;
return false;
}
}; };
class CmdShutdown : public Command { class CmdShutdown : public Command {
public: public:
virtual bool requiresAuth() { return true; } virtual bool requiresAuth() { return true; }
virtual bool adminOnly() const { return true; } virtual bool adminOnly() const { return true; }
virtual bool localHostOnlyIfNoAuth(const BSONObj& cmdObj) { return true; } virtual bool localHostOnlyIfNoAuth(const BSONObj& cmdObj) { return true; }
virtual bool logTheOp() { virtual bool logTheOp() {
return false; return false;
} }
virtual bool slaveOk() const { virtual bool slaveOk() const {
return true; return true;
} }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {
ActionSet actions;
actions.addAction(ActionType::shutdown);
out->push_back(Privilege(AuthorizationManager::SERVER_RESOURCE_
NAME, actions));
}
virtual LockType locktype() const { return NONE; } virtual LockType locktype() const { return NONE; }
virtual void help( stringstream& help ) const; virtual void help( stringstream& help ) const;
CmdShutdown() : Command("shutdown") {} CmdShutdown() : Command("shutdown") {}
bool run(const string& dbname, BSONObj& cmdObj, int options, string & errmsg, BSONObjBuilder& result, bool fromRepl); bool run(const string& dbname, BSONObj& cmdObj, int options, string & errmsg, BSONObjBuilder& result, bool fromRepl);
private: private:
bool shutdownHelper(); bool shutdownHelper();
}; };
bool _runCommands(const char *ns, BSONObj& jsobj, BufBuilder &b, BSONOb jBuilder& anObjBuilder, bool fromRepl, int queryOptions); bool _runCommands(const char *ns, BSONObj& jsobj, BufBuilder &b, BSONOb jBuilder& anObjBuilder, bool fromRepl, int queryOptions);
 End of changes. 6 change blocks. 
4 lines changed or deleted 71 lines changed or added


 config-10gen-linux.h   config-10gen-linux.h 
skipping to change at line 161 skipping to change at line 161
/* <sys/ucontext.h> is broken on redhat 7 */ /* <sys/ucontext.h> is broken on redhat 7 */
/* #undef HAVE_SYS_UCONTEXT_H */ /* #undef HAVE_SYS_UCONTEXT_H */
/* Define to 1 if you have the <sys/wait.h> header file. */ /* Define to 1 if you have the <sys/wait.h> header file. */
#define HAVE_SYS_WAIT_H 1 #define HAVE_SYS_WAIT_H 1
/* Define to 1 if compiler supports __thread */ /* Define to 1 if compiler supports __thread */
#define HAVE_TLS 1 #define HAVE_TLS 1
/* Define to 1 if you have the <ucontext.h> header file. */ /* Define to 1 if you have the <ucontext.h> header file. */
/* #undef HAVE_UCONTEXT_H */ #define HAVE_UCONTEXT_H
/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1 #define HAVE_UNISTD_H 1
/* Define to 1 if you have the <unwind.h> header file. */ /* Define to 1 if you have the <unwind.h> header file. */
#define HAVE_UNWIND_H 1 #define HAVE_UNWIND_H 1
/* Define to 1 if you have the <valgrind.h> header file. */ /* Define to 1 if you have the <valgrind.h> header file. */
/* #undef HAVE_VALGRIND_H */ /* #undef HAVE_VALGRIND_H */
skipping to change at line 216 skipping to change at line 216
/* Define to the one symbol short name of this package. */ /* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "gperftools" #define PACKAGE_TARNAME "gperftools"
/* Define to the home page for this package. */ /* Define to the home page for this package. */
#define PACKAGE_URL "" #define PACKAGE_URL ""
/* Define to the version of this package. */ /* Define to the version of this package. */
#define PACKAGE_VERSION "2.0" #define PACKAGE_VERSION "2.0"
/* How to access the PC from a struct ucontext */ /* How to access the PC from a struct ucontext */
/* #undef PC_FROM_UCONTEXT */ #ifdef __i386
#define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_EIP]
#else
#define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_RIP]
#endif
/* Always the empty-string on non-windows systems. On windows, should be /* Always the empty-string on non-windows systems. On windows, should be
"__declspec(dllexport)". This way, when we compile the dll, we export ou r "__declspec(dllexport)". This way, when we compile the dll, we export ou r
functions/classes. It's safe to define this here because config.h is onl y functions/classes. It's safe to define this here because config.h is onl y
used internally, to compile the DLL, and every DLL source file #includes used internally, to compile the DLL, and every DLL source file #includes
"config.h" before anything else. */ "config.h" before anything else. */
#define PERFTOOLS_DLL_DECL /**/ #define PERFTOOLS_DLL_DECL /**/
/* printf format code for printing a size_t and ssize_t */ /* printf format code for printing a size_t and ssize_t */
#define PRIdS "ld" #define PRIdS "ld"
 End of changes. 2 change blocks. 
2 lines changed or deleted 6 lines changed or added


 config.h   config.h 
skipping to change at line 36 skipping to change at line 36
#include "../db/namespace.h" #include "../db/namespace.h"
#include "../client/model.h" #include "../client/model.h"
#include "mongo/client/dbclient_rs.h" #include "mongo/client/dbclient_rs.h"
#include "chunk.h" #include "chunk.h"
#include "shard.h" #include "shard.h"
#include "shardkey.h" #include "shardkey.h"
namespace mongo { namespace mongo {
struct ShardNS {
static string mongos;
static string settings;
};
class ConfigServer; class ConfigServer;
class DBConfig; class DBConfig;
typedef boost::shared_ptr<DBConfig> DBConfigPtr; typedef boost::shared_ptr<DBConfig> DBConfigPtr;
extern DBConfigPtr configServerPtr; extern DBConfigPtr configServerPtr;
extern ConfigServer& configServer; extern ConfigServer& configServer;
/** /**
* top level configuration for a database * top level configuration for a database
skipping to change at line 236 skipping to change at line 231
bool allUp(); bool allUp();
bool allUp( string& errmsg ); bool allUp( string& errmsg );
int dbConfigVersion(); int dbConfigVersion();
int dbConfigVersion( DBClientBase& conn ); int dbConfigVersion( DBClientBase& conn );
void reloadSettings(); void reloadSettings();
/** /**
* @return 0 = ok, otherwise error #
*/
int checkConfigVersion( bool upgrade );
/**
* Create a metadata change log entry in the config.changelog colle ction. * Create a metadata change log entry in the config.changelog colle ction.
* *
* @param what e.g. "split" , "migrate" * @param what e.g. "split" , "migrate"
* @param ns to which collection the metadata change is being appli ed * @param ns to which collection the metadata change is being appli ed
* @param msg additional info about the metadata change * @param msg additional info about the metadata change
* *
* This call is guaranteed never to throw. * This call is guaranteed never to throw.
*/ */
void logChange( const string& what , const string& ns , const BSONO bj& detail = BSONObj() ); void logChange( const string& what , const string& ns , const BSONO bj& detail = BSONObj() );
 End of changes. 2 change blocks. 
10 lines changed or deleted 0 lines changed or added


 connections.h   connections.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 <map> #include <map>
#include "../security_common.h"
#include "mongo/db/auth/authorization_manager.h"
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 67 skipping to change at line 68
} }
void setTimeout(time_t timeout) { void setTimeout(time_t timeout) {
connInfo->setTimeout(timeout); connInfo->setTimeout(timeout);
} }
/* If we were to run a query and not exhaust the cursor, future use of the connection would be problematic. /* If we were to run a query and not exhaust the cursor, future use of the connection would be problematic.
So here what we do is wrapper known safe methods and not allow c ursor-style queries at all. This makes So here what we do is wrapper known safe methods and not allow c ursor-style queries at all. This makes
ScopedConn limited in functionality but very safe. More non-cur sor wrappers can be added here if needed. ScopedConn limited in functionality but very safe. More non-cur sor wrappers can be added here if needed.
*/ */
bool runCommand(const string &dbname, bool runCommand(const string &dbname, const BSONObj& cmd, BSONObj &
const BSONObj& cmd, info, int options=0) {
BSONObj &info, return conn()->runCommand(dbname, cmd, info, options);
int options=0,
const AuthenticationTable* auth=NULL) {
return conn()->runCommand(dbname, cmd, info, options, noauth ?
NULL : auth);
} }
unsigned long long count(const string &ns) { unsigned long long count(const string &ns) {
return conn()->count(ns); return conn()->count(ns);
} }
BSONObj findOne(const string &ns, const Query& q, const BSONObj *fi eldsToReturn = 0, int queryOptions = 0) { BSONObj findOne(const string &ns, const Query& q, const BSONObj *fi eldsToReturn = 0, int queryOptions = 0) {
return conn()->findOne(ns, q, fieldsToReturn, queryOptions); return conn()->findOne(ns, q, fieldsToReturn, queryOptions);
} }
private: private:
auto_ptr<scoped_lock> connLock; auto_ptr<scoped_lock> connLock;
skipping to change at line 141 skipping to change at line 138
// connection created above will go dead, reconnect, and reauth. // connection created above will go dead, reconnect, and reauth.
if (!noauth) { if (!noauth) {
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;
} }
connInfo->cc->setAuthenticationTable(
AuthenticationTable::getInternalSecurityAuthenticatio
nTable() );
} }
return true; return true;
} }
}; };
inline ScopedConn::ScopedConn(const std::string& hostport) : _hostport( hostport) { inline ScopedConn::ScopedConn(const std::string& hostport) : _hostport( hostport) {
bool first = false; bool first = false;
{ {
scoped_lock lk(mapMutex); scoped_lock lk(mapMutex);
 End of changes. 3 change blocks. 
11 lines changed or deleted 5 lines changed or added


 connpool.h   connpool.h 
skipping to change at line 252 skipping to change at line 252
*/ */
class ScopedDbConnection : public AScopedConnection { class ScopedDbConnection : public AScopedConnection {
private: private:
/** 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 ) {
_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: public:
// Factory functions for getting ScopedDbConnections. The caller o wns the resulting object // 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 // 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 // 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 // authentication. If the command should be run with full permissi ons regardless
// of whether or not the user is authorized, then use getInternalSc opedDbConnection(). // of whether or not the user is authorized, then use getInternalSc opedDbConnection().
static ScopedDbConnection* getScopedDbConnection(const string& host , static ScopedDbConnection* getScopedDbConnection(const string& host ,
double socketTimeo ut = 0); double socketTimeo ut = 0);
static ScopedDbConnection* getScopedDbConnection(const ConnectionSt
ring& host,
double socketTimeo
ut = 0);
static ScopedDbConnection* getScopedDbConnection(); static ScopedDbConnection* getScopedDbConnection();
// Gets a ScopedDbConnection designed to be used for internal commu // DEPRECATED. This is now just a synonym for getScopedDbConnection
nication within a cluster .
// The mongod/mongos implementations of these set the Authenticatio
nTable on the underlying
// connection to the internalSecurity permissions. All commands ru
n on the shard mongods
// using this connection will have full access. If the command sho
uld only be run on the
// shard if the client has permission to do so, then use getScopedD
bConnection().
// These functions should not be called by consumers of the C++ cli
ent library.
static ScopedDbConnection* getInternalScopedDbConnection(const stri ng& host, static ScopedDbConnection* getInternalScopedDbConnection(const stri ng& host,
double soc ketTimeout = 0); double soc ketTimeout = 0);
static ScopedDbConnection* getInternalScopedDbConnection(const Conn
ectionString& host,
double soc
ketTimeout = 0);
static ScopedDbConnection* getInternalScopedDbConnection(); 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;
skipping to change at line 328 skipping to change at line 331
*/ */
void done() { void done() {
if ( ! _conn ) if ( ! _conn )
return; return;
/* we could do this, but instead of assume one is using autorec onnect mode on the connection /* we could do this, but instead of assume one is using autorec onnect mode on the connection
if ( _conn->isFailed() ) if ( _conn->isFailed() )
kill(); kill();
else else
*/ */
_conn->clearAuthenticationTable();
pool.release(_host, _conn); pool.release(_host, _conn);
_conn = 0; _conn = 0;
} }
private: private:
void _setSocketTimeout(); void _setSocketTimeout();
const string _host; const string _host;
DBClientBase *_conn; DBClientBase *_conn;
 End of changes. 5 change blocks. 
13 lines changed or deleted 16 lines changed or added


 counter.h   counter.h 
skipping to change at line 22 skipping to change at line 22
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/platform/atomic_word.h" #include "mongo/platform/atomic_word.h"
#include "mongo/platform/cstdint.h"
namespace mongo { namespace mongo {
class Counter64 { class Counter64 {
public: public:
void increment() { _counter.addAndFetch(1); } void increment( uint64_t n = 1 ) { _counter.addAndFetch(n); }
long long get() const { return _counter.load(); } long long get() const { return _counter.load(); }
operator long long() const { return get(); } operator long long() const { return get(); }
private: private:
AtomicInt64 _counter; AtomicInt64 _counter;
}; };
} }
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 curop.h   curop.h 
skipping to change at line 42 skipping to change at line 42
class CurOp; class CurOp;
/* lifespan is different than CurOp because of recursives with DBDirect Client */ /* lifespan is different than CurOp because of recursives with DBDirect Client */
class OpDebug { class OpDebug {
public: public:
OpDebug() : ns(""){ reset(); } OpDebug() : ns(""){ reset(); }
void reset(); void reset();
void recordStats();
string report( const CurOp& curop ) const; string report( const CurOp& curop ) const;
/** /**
* Appends stored data and information from curop to the builder. * Appends stored data and information from curop to the builder.
* *
* @param curop information about the current operation which will be * @param curop information about the current operation which will be
* use to append data to the builder. * use to append data to the builder.
* @param builder the BSON builder to use for appending data. Data can * @param builder the BSON builder to use for appending data. Data can
* still be appended even if this method returns false. * still be appended even if this method returns false.
* @param maxSize the maximum allowed combined size for the query o bject * @param maxSize the maximum allowed combined size for the query o bject
skipping to change at line 82 skipping to change at line 84
int ntoreturn; int ntoreturn;
int ntoskip; int ntoskip;
bool exhaust; bool exhaust;
// debugging/profile info // debugging/profile info
long long nscanned; long long nscanned;
bool idhack; // indicates short circuited code path on an u pdate to make the update faster bool idhack; // indicates short circuited code path on an u pdate to make the update faster
bool scanAndOrder; // scanandorder query plan aspect was used bool scanAndOrder; // scanandorder query plan aspect was used
long long nupdated; // number of records updated long long nupdated; // number of records updated
long long nmoved; // updates resulted in a move (moves are expen sive) long long nmoved; // updates resulted in a move (moves are expen sive)
long long ninserted;
long long ndeleted;
bool fastmod; bool fastmod;
bool fastmodinsert; // upsert of an $operation. builds a default o bject bool fastmodinsert; // upsert of an $operation. builds a default o bject
bool upsert; // true if the update actually did an insert bool upsert; // true if the update actually did an insert
int keyUpdates; int keyUpdates;
// error handling // error handling
ExceptionInfo exceptionInfo; ExceptionInfo exceptionInfo;
// response info // response info
int executionTime; int executionTime;
skipping to change at line 219 skipping to change at line 223
} }
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();
BSONObj infoNoauth();
string getRemoteString( bool includePort = true ) { return _remote. toString(includePort); } string getRemoteString( bool includePort = true ) { return _remote. toString(includePort); }
ProgressMeter& setMessage( const char * msg , unsigned long long pr ProgressMeter& setMessage(const char * msg,
ogressMeterTotal = 0 , int secondsBetween = 3 ); std::string name = "Progress",
unsigned long long progressMeterTotal = 0
,
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(); }
bool killPending() const { return _killPending.loadRelaxed(); } bool killPending() const { return _killPending.loadRelaxed(); }
void yielded() { _numYields++; } void yielded() { _numYields++; }
int numYields() const { return _numYields; } int numYields() const { return _numYields; }
void suppressFromCurop() { _suppressFromCurop = true; } void suppressFromCurop() { _suppressFromCurop = true; }
 End of changes. 4 change blocks. 
3 lines changed or deleted 9 lines changed or added


 cursors.h   cursors.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/>.
*/ */
#pragma once #pragma once
#include "mongo/pch.h" #include "mongo/pch.h"
#include <string>
#include "mongo/client/parallel.h" #include "mongo/client/parallel.h"
#include "mongo/db/dbmessage.h" #include "mongo/db/dbmessage.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/platform/random.h" #include "mongo/platform/random.h"
#include "mongo/s/request.h" #include "mongo/s/request.h"
namespace mongo { namespace mongo {
class ShardedClientCursor : boost::noncopyable { class ShardedClientCursor : boost::noncopyable {
public: public:
skipping to change at line 67 skipping to change at line 69
* a successful call. * a successful call.
* *
* @return true if this is not the final batch. * @return true if this is not the final batch.
*/ */
bool sendNextBatch( Request& r, int ntoreturn, BufBuilder& buffer, int& docCount ); bool sendNextBatch( Request& r, int ntoreturn, BufBuilder& buffer, int& docCount );
void accessed(); void accessed();
/** @return idle time in ms */ /** @return idle time in ms */
long long idleTime( long long now ); long long idleTime( long long now );
std::string getNS() { return _cursor->getNS(); }
// The default initial buffer size for sending responses. // The default initial buffer size for sending responses.
static const int INIT_REPLY_BUFFER_SIZE; static const int INIT_REPLY_BUFFER_SIZE;
protected: protected:
ClusteredCursor * _cursor; ClusteredCursor * _cursor;
int _skip; int _skip;
int _ntoreturn; int _ntoreturn;
skipping to change at line 102 skipping to change at line 106
typedef map<long long,ShardedClientCursorPtr> MapSharded; typedef map<long long,ShardedClientCursorPtr> MapSharded;
typedef map<long long,string> MapNormal; typedef map<long long,string> MapNormal;
CursorCache(); CursorCache();
~CursorCache(); ~CursorCache();
ShardedClientCursorPtr get( long long id ) const; ShardedClientCursorPtr get( long long id ) const;
void store( ShardedClientCursorPtr cursor ); void store( ShardedClientCursorPtr cursor );
void remove( long long id ); void remove( long long id );
void storeRef( const string& server , long long id ); void storeRef(const std::string& server, long long id, const std::s tring& ns);
/** @return the server for id or "" */ /** @return the server for id or "" */
string getRef( long long id ) const ; string getRef( long long id ) const ;
/** @return the ns for id or "" */
std::string getRefNS(long long id) const ;
void gotKillCursors(Message& m ); void gotKillCursors(Message& m );
void appendInfo( BSONObjBuilder& result ) const ; void appendInfo( BSONObjBuilder& result ) const ;
long long genId(); long long genId();
void doTimeouts(); void doTimeouts();
void startTimeoutThread(); void startTimeoutThread();
private: private:
mutable mongo::mutex _mutex; mutable mongo::mutex _mutex;
PseudoRandom _random; PseudoRandom _random;
MapSharded _cursors; MapSharded _cursors;
MapNormal _refs; MapNormal _refs; // Maps cursor ID to shard name
MapNormal _refsNS; // Maps cursor ID to namespace
long long _shardedTotal; long long _shardedTotal;
static const int _myLogLevel; static const int _myLogLevel;
}; };
extern CursorCache cursorCache; extern CursorCache cursorCache;
} }
 End of changes. 5 change blocks. 
2 lines changed or deleted 9 lines changed or added


 d_chunk_manager.h   d_chunk_manager.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/pch.h" #include "mongo/pch.h"
#include "../db/jsobj.h" #include "mongo/db/jsobj.h"
#include "util.h" #include "mongo/s/chunk_version.h"
namespace mongo { namespace mongo {
class ClientCursor; class ClientCursor;
class DBClientCursorInterface; class DBClientCursorInterface;
class ShardChunkManager; class ShardChunkManager;
typedef shared_ptr<ShardChunkManager> ShardChunkManagerPtr; typedef shared_ptr<ShardChunkManager> ShardChunkManagerPtr;
/** /**
skipping to change at line 80 skipping to change at line 80
~ShardChunkManager() {} ~ShardChunkManager() {}
/** /**
* Generates a new manager based on 'this's state minus a given chu nk. * Generates a new manager based on 'this's state minus a given chu nk.
* *
* @param min max chunk boundaries for the chunk to subtract * @param min max chunk boundaries for the chunk to subtract
* @param version that the resulting manager should be at. The vers ion has to be higher than the current one. * @param version that the resulting manager should be at. The vers ion has to be higher than the current one.
* When cloning away the last chunk, verstion must be 0. * When cloning away the last chunk, verstion must be 0.
* @return a new ShardChunkManager, to be owned by the caller * @return a new ShardChunkManager, to be owned by the caller
*/ */
ShardChunkManager* cloneMinus( const BSONObj& min , const BSONObj& max , const ShardChunkVersion& version ); ShardChunkManager* cloneMinus( const BSONObj& min , const BSONObj& max , const ChunkVersion& version );
/** /**
* Generates a new manager based on 'this's state plus a given chun k. * Generates a new manager based on 'this's state plus a given chun k.
* *
* @param min max chunk boundaries for the chunk to add * @param min max chunk boundaries for the chunk to add
* @param version that the resulting manager should be at. It can n ever be 0, though (see CloneMinus). * @param version that the resulting manager should be at. It can n ever be 0, though (see CloneMinus).
* @return a new ShardChunkManager, to be owned by the caller * @return a new ShardChunkManager, to be owned by the caller
*/ */
ShardChunkManager* clonePlus( const BSONObj& min , const BSONObj& m ax , const ShardChunkVersion& version ); ShardChunkManager* clonePlus( const BSONObj& min , const BSONObj& m ax , const ChunkVersion& version );
/** /**
* Generates a new manager by splitting an existing chunk at one or more points. * Generates a new manager by splitting an existing chunk at one or more points.
* *
* @param min max boundaries of chunk to be split * @param min max boundaries of chunk to be split
* @param splitKeys points to split original chunk at * @param splitKeys points to split original chunk at
* @param version to be used in first chunk. The subsequent chunks would increment the minor version. * @param version to be used in first chunk. The subsequent chunks would increment the minor version.
* @return a new ShardChunkManager with the chunk split, to be owne d by the caller * @return a new ShardChunkManager with the chunk split, to be owne d by the caller
*/ */
ShardChunkManager* cloneSplit( const BSONObj& min , const BSONObj& max , const vector<BSONObj>& splitKeys , ShardChunkManager* cloneSplit( const BSONObj& min , const BSONObj& max , const vector<BSONObj>& splitKeys ,
const ShardChunkVersion& version ); const ChunkVersion& version );
/** /**
* Checks whether a document belongs to this shard. * Checks whether a document belongs to this shard.
* *
* @param obj document containing sharding keys (and, optionally, o ther attributes) * @param obj document containing sharding keys (and, optionally, o ther attributes)
* @return true if shards hold the object * @return true if shards hold the object
*/ */
bool belongsToMe( const BSONObj& doc ) const; bool belongsToMe( const BSONObj& doc ) const;
/** /**
skipping to change at line 131 skipping to change at line 131
* *
* @param lookupKey is the min key for a previously obtained chunk or the empty document * @param lookupKey is the min key for a previously obtained chunk or the empty document
* @param foundMin IN/OUT min for chunk following the one starting at lookupKey * @param foundMin IN/OUT min for chunk following the one starting at lookupKey
* @param foundMax IN/OUT max for the above chunk * @param foundMax IN/OUT max for the above chunk
* @return true if the chunk returned is the last one * @return true if the chunk returned is the last one
*/ */
bool getNextChunk( const BSONObj& lookupKey, BSONObj* foundMin , BS ONObj* foundMax ) const; bool getNextChunk( const BSONObj& lookupKey, BSONObj* foundMin , BS ONObj* foundMax ) const;
// accessors // accessors
ShardChunkVersion getVersion() const { return _version; } ChunkVersion getVersion() const { return _version; }
ShardChunkVersion getCollVersion() const { return _collVersion; } ChunkVersion getCollVersion() const { return _collVersion; }
BSONObj getKey() const { return _key.getOwned(); } BSONObj getKey() const { return _key.getOwned(); }
unsigned getNumChunks() const { return _chunksMap.size(); } unsigned getNumChunks() const { return _chunksMap.size(); }
string toString() const; string toString() const;
private: private:
void _init( const string& configServer , const string& ns , const s tring& shardName, ShardChunkManagerPtr oldManager = ShardChunkManagerPtr() ); void _init( const string& configServer , const string& ns , const s tring& shardName, ShardChunkManagerPtr oldManager = ShardChunkManagerPtr() );
/** /**
* @same as belongsToMe but point is the extracted shard key * @same as belongsToMe but point is the extracted shard key
*/ */
bool _belongsToMe( const BSONObj& point ) const; bool _belongsToMe( const BSONObj& point ) const;
ShardChunkVersion _collVersion; ChunkVersion _collVersion;
// highest ShardChunkVersion for which this ShardChunkManager's inf // highest ChunkVersion for which this ShardChunkManager's informat
ormation is accurate ion is accurate
ShardChunkVersion _version; ChunkVersion _version;
// key pattern for chunks under this range // key pattern for chunks under this range
BSONObj _key; BSONObj _key;
// a map from a min key into the chunk's (or range's) max boundary // a map from a min key into the chunk's (or range's) max boundary
typedef map< BSONObj, BSONObj , BSONObjCmp > RangeMap; typedef map< BSONObj, BSONObj , BSONObjCmp > RangeMap;
RangeMap _chunksMap; RangeMap _chunksMap;
// a map from a min key into a range or continguous chunks // a map from a min key into a range or continguous chunks
// redundant but we expect high chunk continguity, expecially in sm all installations // redundant but we expect high chunk continguity, expecially in sm all installations
 End of changes. 6 change blocks. 
11 lines changed or deleted 11 lines changed or added


 d_concurrency.h   d_concurrency.h 
skipping to change at line 165 skipping to change at line 165
/** /**
* flow * flow
* 1) lockDB * 1) lockDB
* a) lockTop * a) lockTop
* b) lockNestable or lockOther * b) lockNestable or lockOther
* 2) unlockDB * 2) unlockDB
*/ */
void lockTop(LockState&); void lockTop(LockState&);
void lockNestable(Nestable db); void lockNestable(Nestable db);
void lockOther(const string& db); void lockOther(const StringData& db);
void lockDB(const string& ns); void lockDB(const string& ns);
void unlockDB(); void unlockDB();
protected: protected:
void _tempRelease(); void _tempRelease();
void _relock(); void _relock();
public: public:
DBWrite(const StringData& dbOrNs); DBWrite(const StringData& dbOrNs);
virtual ~DBWrite(); virtual ~DBWrite();
skipping to change at line 199 skipping to change at line 199
bool _locked_W; bool _locked_W;
WrapperForRWLock *_weLocked; WrapperForRWLock *_weLocked;
const string _what; const string _what;
bool _nested; bool _nested;
}; };
// lock this database for reading. do not shared_lock globally firs t, that is handledin herein. // lock this database for reading. do not shared_lock globally firs t, that is handledin herein.
class DBRead : public ScopedLock { class DBRead : public ScopedLock {
void lockTop(LockState&); void lockTop(LockState&);
void lockNestable(Nestable db); void lockNestable(Nestable db);
void lockOther(const string& db); void lockOther(const StringData& db);
void lockDB(const string& ns); void lockDB(const string& ns);
void unlockDB(); void unlockDB();
protected: protected:
void _tempRelease(); void _tempRelease();
void _relock(); void _relock();
public: public:
DBRead(const StringData& dbOrNs); DBRead(const StringData& dbOrNs);
virtual ~DBRead(); virtual ~DBRead();
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 d_logic.h   d_logic.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/>.
*/ */
#pragma once #pragma once
#include "mongo/pch.h" #include "mongo/pch.h"
#include "../db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/s/d_chunk_manager.h"
#include "d_chunk_manager.h" #include "mongo/s/chunk_version.h"
#include "util.h"
#include "mongo/util/concurrency/ticketholder.h" #include "mongo/util/concurrency/ticketholder.h"
namespace mongo { namespace mongo {
class Database; class Database;
class DiskLoc; class DiskLoc;
typedef ShardChunkVersion ConfigVersion; typedef ChunkVersion ConfigVersion;
// -------------- // --------------
// --- global state --- // --- global state ---
// -------------- // --------------
class ShardingState { class ShardingState {
public: public:
ShardingState(); ShardingState();
bool enabled() const { return _enabled; } bool enabled() const { return _enabled; }
skipping to change at line 109 skipping to change at line 108
* Creates and installs a new chunk manager for a given collection by "forgetting" about one of its chunks. * Creates and installs a new chunk manager for a given collection by "forgetting" about one of its chunks.
* The new manager uses the provided version, which has to be highe r than the current manager's. * The new manager uses the provided version, which has to be highe r than the current manager's.
* One exception: if the forgotten chunk is the last one in this sh ard for the collection, version has to be 0. * One exception: if the forgotten chunk is the last one in this sh ard for the collection, version has to be 0.
* *
* If it runs successfully, clients need to grab the new version to access the collection. * If it runs successfully, clients need to grab the new version to access the collection.
* *
* @param ns the collection * @param ns the collection
* @param min max the chunk to eliminate from the current manager * @param min max the chunk to eliminate from the current manager
* @param version at which the new manager should be at * @param version at which the new manager should be at
*/ */
void donateChunk( const string& ns , const BSONObj& min , const BSO NObj& max , ShardChunkVersion version ); void donateChunk( const string& ns , const BSONObj& min , const BSO NObj& max , ChunkVersion version );
/** /**
* Creates and installs a new chunk manager for a given collection by reclaiming a previously donated chunk. * Creates and installs a new chunk manager for a given collection by reclaiming a previously donated chunk.
* The previous manager's version has to be provided. * The previous manager's version has to be provided.
* *
* If it runs successfully, clients that became stale by the previo us donateChunk will be able to access the * If it runs successfully, clients that became stale by the previo us donateChunk will be able to access the
* collection again. * collection again.
* *
* @param ns the collection * @param ns the collection
* @param min max the chunk to reclaim and add to the current manag er * @param min max the chunk to reclaim and add to the current manag er
* @param version at which the new manager should be at * @param version at which the new manager should be at
*/ */
void undoDonateChunk( const string& ns , const BSONObj& min , const BSONObj& max , ShardChunkVersion version ); void undoDonateChunk( const string& ns , const BSONObj& min , const BSONObj& max , ChunkVersion version );
/** /**
* Creates and installs a new chunk manager for a given collection by splitting one of its chunks in two or more. * Creates and installs a new chunk manager for a given collection by splitting one of its chunks in two or more.
* The version for the first split chunk should be provided. The su bsequent chunks' version would be the latter with the * The version for the first split chunk should be provided. The su bsequent chunks' version would be the latter with the
* minor portion incremented. * minor portion incremented.
* *
* The effect on clients will depend on the version used. If the ma jor portion is the same as the current shards, * The effect on clients will depend on the version used. If the ma jor portion is the same as the current shards,
* clients shouldn't perceive the split. * clients shouldn't perceive the split.
* *
* @param ns the collection * @param ns the collection
* @param min max the chunk that should be split * @param min max the chunk that should be split
* @param splitKeys point in which to split * @param splitKeys point in which to split
* @param version at which the new manager should be at * @param version at which the new manager should be at
*/ */
void splitChunk( const string& ns , const BSONObj& min , const BSON Obj& max , const vector<BSONObj>& splitKeys , void splitChunk( const string& ns , const BSONObj& min , const BSON Obj& max , const vector<BSONObj>& splitKeys ,
ShardChunkVersion version ); ChunkVersion version );
bool inCriticalMigrateSection(); bool inCriticalMigrateSection();
/** /**
* @return true if we are NOT in the critical section * @return true if we are NOT in the critical section
*/ */
bool waitTillNotInCriticalSection( int maxSecondsToWait ); bool waitTillNotInCriticalSection( int maxSecondsToWait );
private: private:
bool _enabled; bool _enabled;
skipping to change at line 233 skipping to change at line 232
unsigned long long extractVersion( BSONElement e , string& errmsg ); unsigned long long extractVersion( BSONElement e , string& errmsg );
/** /**
* @return true if we have any shard info for the ns * @return true if we have any shard info for the ns
*/ */
bool haveLocalShardingInfo( const string& ns ); bool haveLocalShardingInfo( const string& ns );
/** /**
* @return true if the current threads shard version is ok, or not in s harded version * @return true if the current threads shard version is ok, or not in s harded version
* Also returns an error message and the Config/ShardChunkVersions caus ing conflicts * Also returns an error message and the Config/ChunkVersions causing c onflicts
*/ */
bool shardVersionOk( const string& ns , string& errmsg, ConfigVersion& received, ConfigVersion& wanted ); bool shardVersionOk( const string& ns , string& errmsg, ConfigVersion& received, ConfigVersion& wanted );
/** /**
* @return true if we took care of the message and nothing else should be done * @return true if we took care of the message and nothing else should be done
*/ */
struct DbResponse; struct DbResponse;
bool _handlePossibleShardedMessage( Message &m, DbResponse * dbresponse ); bool _handlePossibleShardedMessage( Message &m, DbResponse * dbresponse );
 End of changes. 6 change blocks. 
9 lines changed or deleted 8 lines changed or added


 database.h   database.h 
skipping to change at line 142 skipping to change at line 142
private: private:
// must be in the dbLock when touching this (and write locked when writing to of course) // must be in the dbLock when touching this (and write locked when writing to of course)
// however during Database object construction we aren't, which is ok as it isn't yet visible // however during Database object construction we aren't, which is ok as it isn't yet visible
// to others and we are in the dbholder lock then. // to others and we are in the dbholder lock then.
vector<MongoDataFile*> _files; vector<MongoDataFile*> _files;
public: // this should be private later public: // this should be private later
NamespaceIndex namespaceIndex; NamespaceIndex namespaceIndex;
int profile; // 0=off.
const string profileName; // "alleyinsider.system.profile" const string profileName; // "alleyinsider.system.profile"
CCByLoc ccByLoc; CCByLoc ccByLoc;
int magic; // used for making sure the object is still loaded in me mory int magic; // used for making sure the object is still loaded in me mory
int getProfilingLevel() const { return _profile; }
private: private:
RecordStats _recordStats; RecordStats _recordStats;
int _profile; // 0=off.
}; };
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
2 lines changed or deleted 3 lines changed or added


 dbclient_rs.h   dbclient_rs.h 
skipping to change at line 46 skipping to change at line 46
/** /**
* manages state about a replica set for client * manages state about a replica set for client
* keeps tabs on whose master and what slaves are up * keeps tabs on whose master and what slaves are up
* can hand a slave to someone for SLAVE_OK * can hand a slave to someone for SLAVE_OK
* one instance per process per replica set * one instance per process per replica set
* TODO: we might be able to use a regular Node * to avoid _lock * TODO: we might be able to use a regular Node * to avoid _lock
*/ */
class ReplicaSetMonitor { class ReplicaSetMonitor {
public: public:
typedef boost::function1<void,const ReplicaSetMonitor*> ConfigChang eHook; typedef boost::function1<void,const ReplicaSetMonitor*> ConfigChang eHook;
/** /**
* Data structure for keeping track of the states of individual rep lica * Data structure for keeping track of the states of individual rep lica
* members. This class is not thread-safe so proper measures should be taken * members. This class is not thread-safe so proper measures should be taken
* when sharing this object across multiple threads. * when sharing this object across multiple threads.
* *
* Note: these get copied around in the nodes vector so be sure to maintain * Note: these get copied around in the nodes vector so be sure to maintain
* copyable semantics here * copyable semantics here
*/ */
skipping to change at line 136 skipping to change at line 135
BSONObj lastIsMaster; BSONObj lastIsMaster;
bool ismaster; bool ismaster;
bool secondary; bool secondary;
bool hidden; bool hidden;
int pingTimeMillis; int pingTimeMillis;
}; };
static const double SOCKET_TIMEOUT_SECS;
/** /**
* Selects the right node given the nodes to pick from and the pref erence. * Selects the right node given the nodes to pick from and the pref erence.
* *
* @param nodes the nodes to select from * @param nodes the nodes to select from
* @param preference the read mode to use * @param preference the read mode to use
* @param tags the tags used for filtering nodes * @param tags the tags used for filtering nodes
* @param localThresholdMillis the exclusive upper bound of ping ti me to be * @param localThresholdMillis the exclusive upper bound of ping ti me to be
* considered as a local node. Local nodes are favored over non -local * considered as a local node. Local nodes are favored over non -local
* nodes if multiple nodes matches the other criteria. * nodes if multiple nodes matches the other criteria.
* @param lastHost the host used in the last successful request. Th is is used for * @param lastHost the host used in the last successful request. Th is is used for
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 dbclientinterface.h   dbclientinterface.h 
skipping to change at line 26 skipping to change at line 26
* 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/client/authlevel.h" #include "mongo/client/authlevel.h"
#include "mongo/client/authentication_table.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/platform/atomic_word.h" #include "mongo/platform/atomic_word.h"
#include "mongo/util/net/message.h" #include "mongo/util/net/message.h"
#include "mongo/util/net/message_port.h" #include "mongo/util/net/message_port.h"
namespace mongo { namespace mongo {
/** the query field 'options' can have these bits set: */ /** the query field 'options' can have these bits set: */
enum QueryOptions { enum QueryOptions {
/** Tailable means cursor is not closed when the last data is retri eved. rather, the cursor marks /** Tailable means cursor is not closed when the last data is retri eved. rather, the cursor marks
skipping to change at line 174 skipping to change at line 173
*/ */
ReadPreference_Nearest, ReadPreference_Nearest,
}; };
/** /**
* @return true if the query object contains a read preference specific ation object. * @return true if the query object contains a read preference specific ation object.
*/ */
bool hasReadPreference(const BSONObj& queryObj); bool hasReadPreference(const BSONObj& queryObj);
class DBClientBase; class DBClientBase;
class DBClientConnection;
/** /**
* ConnectionString handles parsing different ways to connect to mongo and determining method * ConnectionString handles parsing different ways to connect to mongo and determining method
* samples: * samples:
* server * server
* server:port * server:port
* foo/server:port,server:port SET * foo/server:port,server:port SET
* server,server,server SYNC * server,server,server SYNC
* Warning - you usually don't want "SYNC", it's used * Warning - you usually don't want "SYNC", it's used
* for some special things such as s harding config servers. * for some special things such as s harding config servers.
skipping to change at line 291 skipping to change at line 291
virtual DBClientBase* connect( const ConnectionString& c, virtual DBClientBase* connect( const ConnectionString& c,
string& errmsg, string& errmsg,
double socketTimeout ) = 0; double socketTimeout ) = 0;
}; };
static void setConnectionHook( ConnectionHook* hook ){ static void setConnectionHook( ConnectionHook* hook ){
scoped_lock lk( _connectHookMutex ); scoped_lock lk( _connectHookMutex );
_connectHook = hook; _connectHook = hook;
} }
static ConnectionHook* getConnectionHook() {
scoped_lock lk( _connectHookMutex );
return _connectHook;
}
private: private:
void _fillServers( string s ); void _fillServers( string s );
void _finishInit(); void _finishInit();
ConnectionType _type; ConnectionType _type;
vector<HostAndPort> _servers; vector<HostAndPort> _servers;
string _string; string _string;
string _setName; string _setName;
skipping to change at line 564 skipping to change at line 569
Basically just invocations of connection.$cmd.findOne({...}); Basically just invocations of connection.$cmd.findOne({...});
*/ */
class DBClientWithCommands : public DBClientInterface { class DBClientWithCommands : public DBClientInterface {
set<string> _seenIndexes; set<string> _seenIndexes;
public: public:
/** controls how chatty the client is about network errors & such. See log.h */ /** controls how chatty the client is about network errors & such. See log.h */
int _logLevel; int _logLevel;
DBClientWithCommands() : _logLevel(0), DBClientWithCommands() : _logLevel(0),
_cachedAvailableOptions( (enum QueryOptions)0 ), _cachedAvailableOptions( (enum QueryOptions)0 ),
_haveCachedAvailableOptions(false), _haveCachedAvailableOptions(false) { }
_hasAuthentication(false) { }
/** helper function. run a simple command where the command expres sion is simply /** helper function. run a simple command where the command expres sion is simply
{ command : 1 } { command : 1 }
@param info -- where to put result object. may be null if call er doesn't need that info @param info -- where to put result object. may be null if call er doesn't need that info
@param command -- command name @param command -- command name
@return true if the command returned "ok". @return true if the command returned "ok".
*/ */
bool simpleCommand(const string &dbname, BSONObj *info, const strin g &command); bool simpleCommand(const string &dbname, BSONObj *info, const strin g &command);
/** Run a database command. Database commands are represented as B SON objects. Common database /** Run a database command. Database commands are represented as B SON objects. Common database
commands have prebuilt helper functions -- see below. If a hel per is not available you can commands have prebuilt helper functions -- see below. If a hel per is not available you can
directly call runCommand. If _authTable has been set, will app directly call runCommand.
end a BSON representation of
that AuthenticationTable to the command object, unless an Authe
nticationTable object has been
passed to this method directly, in which case it will use that
instead of _authTable.
@param dbname database name. Use "admin" for global administra tive commands. @param dbname database name. Use "admin" for global administra tive commands.
@param cmd the command object to execute. For example, { isma ster : 1 } @param cmd the command object to execute. For example, { isma ster : 1 }
@param info the result object the database returns. Typically h as { ok : ..., errmsg : ... } fields @param info the result object the database returns. Typically h as { ok : ..., errmsg : ... } fields
set. set.
@param options see enum QueryOptions - normally not needed to r un a command @param options see enum QueryOptions - normally not needed to r un a command
@param auth if set, the BSONObj representation will be appended to the command object sent @param auth if set, the BSONObj representation will be appended to the command object sent
@return true if the command returned "ok". @return true if the command returned "ok".
*/ */
virtual bool runCommand(const string &dbname, const BSONObj& cmd, B SONObj &info, virtual bool runCommand(const string &dbname, const BSONObj& cmd, B SONObj &info,
int options=0, const AuthenticationTable* a uth = NULL); int options=0);
/** Authorize access to a particular database. /** Authorize access to a particular database.
Authentication is separate for each database on the server -- y ou may authenticate for any Authentication is separate for each database on the server -- y ou may authenticate for any
number of databases on a single connection. number of databases on a single connection.
The "admin" database is special and once authenticated provides access to all databases on the The "admin" database is special and once authenticated provides access to all databases on the
server. server.
@param digestPassword if password is plain text, set this to true. otherwise assumed to be pre-digested @param digestPassword if password is plain text, set this to true. otherwise assumed to be pre-digested
@param[out] authLevel level of authentication for the giv en user @param[out] authLevel level of authentication for the giv en user
@return true if successful @return true if successful
*/ */
skipping to change at line 859 skipping to change at line 861
*/ */
list<string> getDatabaseNames(); list<string> getDatabaseNames();
/** /**
get a list of all the current collections in db get a list of all the current collections in db
*/ */
list<string> getCollectionNames( const string& db ); list<string> getCollectionNames( const string& db );
bool exists( const string& ns ); bool exists( const string& ns );
virtual void setAuthenticationTable( const AuthenticationTable& aut
h );
virtual void clearAuthenticationTable();
/** Create an index if it does not already exist. /** Create an index if it does not already exist.
ensureIndex calls are remembered so it is safe/fast to call thi s function many ensureIndex calls are remembered so it is safe/fast to call thi s function many
times in your code. times in your code.
@param ns collection to be indexed @param ns collection to be indexed
@param keys the "key pattern" for the index. e.g., { name : 1 } @param keys the "key pattern" for the index. e.g., { name : 1 }
@param unique if true, indicates that key uniqueness should be e nforced for this index @param unique if true, indicates that key uniqueness should be e nforced for this index
@param name if not specified, it will be created from the keys a utomatically (which is recommended) @param name if not specified, it will be created from the keys a utomatically (which is recommended)
@param cache if set to false, the index cache for the connection won't remember this call @param cache if set to false, the index cache for the connection won't remember this call
@param background build index in the background (see mongodb doc s/wiki for details) @param background build index in the background (see mongodb doc s/wiki for details)
@param v index version. leave at default value. (unit tests set this parameter.) @param v index version. leave at default value. (unit tests set this parameter.)
skipping to change at line 929 skipping to change at line 928
BSONObj _countCmd(const string &ns, const BSONObj& query, int optio ns, int limit, int skip ); BSONObj _countCmd(const string &ns, const BSONObj& query, int optio ns, int limit, int skip );
/** /**
* Look up the options available on this client. Caches the answer from * Look up the options available on this client. Caches the answer from
* _lookupAvailableOptions(), below. * _lookupAvailableOptions(), below.
*/ */
QueryOptions availableOptions(); QueryOptions availableOptions();
virtual QueryOptions _lookupAvailableOptions(); virtual QueryOptions _lookupAvailableOptions();
bool hasAuthenticationTable();
AuthenticationTable& getAuthenticationTable();
private: private:
enum QueryOptions _cachedAvailableOptions; enum QueryOptions _cachedAvailableOptions;
bool _haveCachedAvailableOptions; bool _haveCachedAvailableOptions;
AuthenticationTable _authTable;
bool _hasAuthentication;
}; };
/** /**
abstract class that implements the core db operations abstract class that implements the core db operations
*/ */
class DBClientBase : public DBClientWithCommands, public DBConnector { class DBClientBase : public DBClientWithCommands, public DBConnector {
protected: protected:
static AtomicInt64 ConnectionIdSequence; static AtomicInt64 ConnectionIdSequence;
long long _connectionId; // unique connection id for this connectio n long long _connectionId; // unique connection id for this connectio n
WriteConcern _writeConcern; WriteConcern _writeConcern;
skipping to change at line 1138 skipping to change at line 1132
virtual unsigned long long query( boost::function<void(DBClientCurs orBatchIterator &)> f, virtual unsigned long long query( boost::function<void(DBClientCurs orBatchIterator &)> f,
const string& ns, const string& ns,
Query query, Query query,
const BSONObj *fieldsToReturn, const BSONObj *fieldsToReturn,
int queryOptions ); int queryOptions );
virtual bool runCommand(const string &dbname, virtual bool runCommand(const string &dbname,
const BSONObj& cmd, const BSONObj& cmd,
BSONObj &info, BSONObj &info,
int options=0, int options=0);
const AuthenticationTable* auth=NULL);
/** /**
@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; }
MessagingPort& port() { verify(p); return *p; } MessagingPort& port() { verify(p); return *p; }
string toStringLong() const { string toStringLong() const {
skipping to change at line 1177 skipping to change at line 1170
virtual ConnectionString::ConnectionType type() const { return Conn ectionString::MASTER; } virtual ConnectionString::ConnectionType type() const { return Conn ectionString::MASTER; }
void setSoTimeout(double timeout); void setSoTimeout(double timeout);
double getSoTimeout() const { return _so_timeout; } double getSoTimeout() const { return _so_timeout; }
virtual bool lazySupported() const { return true; } virtual bool lazySupported() const { return true; }
static int getNumConnections() { static int getNumConnections() {
return _numConnections; return _numConnections;
} }
/**
* Primarily used for notifying the replica set client that the ser
ver
* it is talking to is not primary anymore.
*
* @param rsClient caller is responsible for managing the life of r
sClient
* and making sure that it lives longer than this object.
*
* Warning: This is only for internal use and will eventually be re
moved in
* the future.
*/
void setReplSetClientCallback(DBClientReplicaSet* rsClient);
static void setLazyKillCursor( bool lazy ) { _lazyKillCursor = lazy ; } static void setLazyKillCursor( bool lazy ) { _lazyKillCursor = lazy ; }
static bool getLazyKillCursor() { return _lazyKillCursor; } static bool getLazyKillCursor() { return _lazyKillCursor; }
uint64_t getSockCreationMicroSec() const; uint64_t getSockCreationMicroSec() const;
protected: protected:
friend class SyncClusterConnection; friend class SyncClusterConnection;
virtual void sayPiggyBack( Message &toSend ); virtual void sayPiggyBack( Message &toSend );
DBClientReplicaSet *clientSet; DBClientReplicaSet *clientSet;
skipping to change at line 1207 skipping to change at line 1212
void checkConnection() { if( _failed ) _checkConnection(); } void checkConnection() { if( _failed ) _checkConnection(); }
map< string, pair<string,string> > authCache; map< string, pair<string,string> > 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
static SSLManager* sslManager(); SSLManager* sslManager();
static SSLManager* _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. 12 change blocks. 
23 lines changed or deleted 26 lines changed or added


 dbhelpers.h   dbhelpers.h 
skipping to change at line 107 skipping to change at line 107
/** /**
* you have to lock * you have to lock
* you do not have to have Context set * you do not have to have Context set
* o has to have an _id field or will assert * o has to have an _id field or will assert
*/ */
static void upsert( const string& ns , const BSONObj& o, bool fromM igrate = false ); static void upsert( const string& ns , const BSONObj& o, bool fromM igrate = false );
/** You do not need to set the database before calling. /** You do not need to set the database before calling.
@return true if collection is empty. @return true if collection is empty.
*/ */
static bool isEmpty(const char *ns, bool doAuth=true); static bool isEmpty(const char *ns);
// TODO: this should be somewhere else probably // TODO: this should be somewhere else probably
/* Takes object o, and returns a new object with the /* Takes object o, and returns a new object with the
* same field elements but the names stripped out. Also, * same field elements but the names stripped out.
* fills in "key" with an ascending keyPattern that matches o
* Example: * Example:
* o = {a : 5 , b : 6} --> * o = {a : 5 , b : 6} --> {"" : 5, "" : 6}
* sets key= {a : 1, b :1}, returns {"" : 5, "" : 6}
*/ */
static BSONObj toKeyFormat( const BSONObj& o , BSONObj& key ); static BSONObj toKeyFormat( const BSONObj& o );
/* Takes a BSONObj indicating the min or max boundary of a range, /* Takes object o, and infers an ascending keyPattern with the same
* and a keyPattern corresponding to an index that is useful fields as o
* for locating items in the range, and returns an "extension" * Example:
* of the bound, modified to fit the given pattern. In other words * o = {a : 5 , b : 6} --> {a : 1 , b : 1 }
,
* it appends MinKey or MaxKey values to the bound, so that the ext
ension
* has the same number of fields as keyPattern.
* minOrMax should be -1/+1 to indicate whether the extension
* corresponds to the min or max bound for the range.
* Also, strips out the field names to put the bound in key format.
* Examples:
* {a : 55}, {a :1}, -1 --> {"" : 55}
* {a : 55}, {a : 1, b : 1}, -1 -> {"" : 55, "" : minKey}
* {a : 55}, {a : 1, b : 1}, 1 -> {"" : 55, "" : maxKey}
* {a : 55}, {a : 1, b : -1}, -1 -> {"" : 55, "" : maxKey}
* {a : 55}, {a : 1, b : -1}, 1 -> {"" : 55, "" : minKey}
*
* This function is useful for modifying chunk ranges in sharding,
* when the shard key is a prefix of the index actually used
* (also useful when the shard key is equal to the index used,
* since it strips out the field names).
*/ */
static BSONObj modifiedRangeBound( const BSONObj& bound , static BSONObj inferKeyPattern( const BSONObj& o );
const BSONObj& keyPattern ,
int minOrMax );
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 ed by * Takes a range, specified by a min and max, and an index, specifi ed by
* keyPattern, and removes all the documents in that range found by iterating * keyPattern, and removes all the documents in that range found by iterating
* over the given index. Caller is responsible for insuring that mi n/max are * over the given index. Caller is responsible for insuring that mi n/max are
* compatible with the given keyPattern (e.g min={a:100} is compati ble with * compatible with the given keyPattern (e.g min={a:100} is compati ble with
* keyPattern={a:1,b:1} since it can be extended to {a:100,b:minKey }, but * keyPattern={a:1,b:1} since it can be extended to {a:100,b:minKey }, but
* min={b:100} is not compatible). * min={b:100} is not compatible).
* *
* Caller must hold a write lock on 'ns' * Caller must hold a write lock on 'ns'
* *
* Does oplog the individual document deletions. * Does oplog the individual document deletions.
* // TODO: Refactor this mechanism, it is growing too large
*/ */
static long long removeRange( const string& ns , static long long removeRange( const string& ns ,
const BSONObj& min , const BSONObj& min ,
const BSONObj& max , const BSONObj& max ,
const BSONObj& keyPattern , const BSONObj& keyPattern ,
bool maxInclusive = false , bool maxInclusive = false ,
bool secondaryThrottle = false , bool secondaryThrottle = false ,
RemoveCallback * callback = 0, RemoveCallback * callback = 0,
bool fromMigrate = false ); bool fromMigrate = false,
bool onlyRemoveOrphanedDocs = false )
;
/** /**
* 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. 
32 lines changed or deleted 13 lines changed or added


 dbmessage.h   dbmessage.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 "jsobj.h" #include "jsobj.h"
#include "namespace-inl.h" #include "namespace-inl.h"
#include "../util/net/message.h" #include "../util/net/message.h"
#include "../client/constants.h" #include "../client/constants.h"
#include "instance.h" #include "instance.h"
#include "mongo/bson/bson_validate.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 198 skipping to change at line 199
/* for insert and update msgs */ /* for insert and update msgs */
bool moreJSObjs() const { bool moreJSObjs() const {
return nextjsobj != 0; return nextjsobj != 0;
} }
BSONObj nextJsObj() { BSONObj nextJsObj() {
if ( nextjsobj == data ) { if ( nextjsobj == data ) {
nextjsobj += strlen(data) + 1; // skip namespace nextjsobj += strlen(data) + 1; // skip namespace
massert( 13066 , "Message contains no documents", theEnd > nextjsobj ); massert( 13066 , "Message contains no documents", theEnd > nextjsobj );
} }
massert( 10304 , "Client Error: Remaining data too small for B massert( 10304,
SON object", theEnd - nextjsobj > 3 ); "Client Error: Remaining data too small for BSON objec
BSONObj js(nextjsobj); t",
massert( 10305 , "Client Error: Invalid object size", js.objsi theEnd - nextjsobj >= 5 );
ze() > 3 );
massert( 10306 , "Client Error: Next object larger than space if ( cmdLine.objcheck ) {
left in message", Status status = validateBSON( nextjsobj, theEnd - nextjsobj
js.objsize() < ( theEnd - data ) ); , NULL );
if ( cmdLine.objcheck && !js.valid() ) { massert( 10307,
massert( 10307 , "Client Error: bad object in message", fal str::stream() << "Client Error: bad object in mess
se); age: " << status.reason(),
status.isOK() );
} }
BSONObj js(nextjsobj);
verify( js.objsize() >= 5 );
verify( js.objsize() < ( theEnd - data ) );
nextjsobj += js.objsize(); nextjsobj += js.objsize();
if ( nextjsobj >= theEnd ) if ( nextjsobj >= theEnd )
nextjsobj = 0; nextjsobj = 0;
return js; return js;
} }
const Message& msg() const { return m; } const Message& msg() const { return m; }
const char * markGet() { const char * markGet() {
return nextjsobj; return nextjsobj;
 End of changes. 3 change blocks. 
11 lines changed or deleted 18 lines changed or added


 diskloc.h   diskloc.h 
skipping to change at line 27 skipping to change at line 27
/* @file diskloc.h /* @file diskloc.h
Storage subsystem management. Storage subsystem management.
Lays out our datafiles on disk, manages disk space. Lays out our datafiles on disk, manages disk space.
*/ */
#pragma once #pragma once
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/platform/cstdint.h" #include "mongo/platform/cstdint.h"
#include "mongo/platform/unordered_set.h"
namespace mongo { namespace mongo {
class Record; class Record;
class DeletedRecord; class DeletedRecord;
class Extent; class Extent;
class MongoDataFile; class MongoDataFile;
class DiskLoc; class DiskLoc;
template< class Version > class BtreeBucket; template< class Version > class BtreeBucket;
skipping to change at line 134 skipping to change at line 135
int compare(const DiskLoc& b) const { int compare(const DiskLoc& b) const {
int x = _a - b._a; int x = _a - b._a;
if ( x ) if ( x )
return x; return x;
return ofs - b.ofs; return ofs - b.ofs;
} }
bool operator<(const DiskLoc& b) const { bool operator<(const DiskLoc& b) const {
return compare(b) < 0; return compare(b) < 0;
} }
uint64_t asUint64() const { return *reinterpret_cast<const uint64_t /**
*>( this ); } * Hash value for this disk location. The hash implementation may
be modified, and its
* behavior may differ across platforms. Hash values should not be
persisted.
*/
struct Hasher {
size_t operator()( DiskLoc loc ) const;
};
/** /**
* Marks this disk loc for writing * Marks this disk loc for writing
* @returns a non const reference to this disk loc * @returns a non const reference to this disk loc
* This function explicitly signals we are writing and casts away c onst * This function explicitly signals we are writing and casts away c onst
*/ */
DiskLoc& writing() const; // see dur.h DiskLoc& writing() const; // see dur.h
/* Get the "thing" associated with this disk location. /* Get the "thing" associated with this disk location.
it is assumed the object is what you say it is -- you must assur e that it is assumed the object is what you say it is -- you must assur e that
skipping to change at line 164 skipping to change at line 171
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;*/
}; };
#pragma pack() #pragma pack()
inline size_t DiskLoc::Hasher::operator()( DiskLoc loc ) const {
// Older tr1 implementations do not support hashing 64 bit integers
. This implementation
// delegates to hashing 32 bit integers.
return
unordered_set<uint32_t>::hasher()( loc.a() ) ^
unordered_set<uint32_t>::hasher()( loc.getOfs() );
}
inline std::ostream& operator<<( std::ostream &stream, const DiskLoc &l oc ) { inline std::ostream& operator<<( std::ostream &stream, const DiskLoc &l oc ) {
return stream << loc.toString(); return stream << loc.toString();
} }
// Minimum allowed DiskLoc. No Record may begin at this location becau se file and extent // Minimum allowed DiskLoc. No Record may begin at this location becau se file and extent
// headers must precede Records in a file. // headers must precede Records in a file.
const DiskLoc minDiskLoc(0, 0); const DiskLoc minDiskLoc(0, 0);
// Maximum allowed DiskLoc. Note that only three bytes are used to rep resent the file number // Maximum allowed DiskLoc. Note that only three bytes are used to rep resent the file number
// for consistency with the v1 index DiskLoc storage format, which uses only 7 bytes total. // for consistency with the v1 index DiskLoc storage format, which uses only 7 bytes total.
 End of changes. 3 change blocks. 
2 lines changed or deleted 19 lines changed or added


 distlock.h   distlock.h 
skipping to change at line 185 skipping to change at line 185
void resetLastPing(){ lastPings.setLastPing( _conn, _name, PingData () ); } void resetLastPing(){ lastPings.setLastPing( _conn, _name, PingData () ); }
void setLastPing( const PingData& pd ){ lastPings.setLastPing( _con n, _name, pd ); } void setLastPing( const PingData& pd ){ lastPings.setLastPing( _con n, _name, pd ); }
PingData getLastPing(){ return lastPings.getLastPing( _conn, _name ); } PingData getLastPing(){ return lastPings.getLastPing( _conn, _name ); }
// May or may not exist, depending on startup // May or may not exist, depending on startup
mongo::mutex _mutex; mongo::mutex _mutex;
string _threadId; string _threadId;
}; };
// Helper functions for tests, allows us to turn the creation of a lock
pinger on and off.
// *NOT* thread-safe
bool isLockPingerEnabled();
void setLockPingerEnabled(bool enabled);
class dist_lock_try { class dist_lock_try {
public: public:
dist_lock_try() : _lock(NULL), _got(false) {} dist_lock_try() : _lock(NULL), _got(false) {}
dist_lock_try( const dist_lock_try& that ) : _lock(that._lock), _got (that._got), _other(that._other) { dist_lock_try( const dist_lock_try& that ) : _lock(that._lock), _got (that._got), _other(that._other) {
_other.getOwned(); _other.getOwned();
// Make sure the lock ownership passes to this object, // Make sure the lock ownership passes to this object,
// so we only unlock once. // so we only unlock once.
skipping to change at line 254 skipping to change at line 259
bool got() const { return _got; } bool got() const { return _got; }
BSONObj other() const { return _other; } BSONObj other() const { return _other; }
private: private:
DistributedLock * _lock; DistributedLock * _lock;
bool _got; bool _got;
BSONObj _other; BSONObj _other;
string _why; string _why;
}; };
/**
* Scoped wrapper for a distributed lock acquisition attempt. One or m
ore attempts to acquire
* the distributed lock are managed by this class, and the distributed
lock is unlocked if
* successfully acquired on object destruction.
*/
class ScopedDistributedLock {
public:
ScopedDistributedLock(const ConnectionString& conn, const string& n
ame);
virtual ~ScopedDistributedLock();
/**
* Tries once to obtain a lock, and can fail with an error message.
*
* Subclasses of this lock can override this method (and are also r
equired to call the base
* in the overridden method).
*
* @return if the lock was successfully acquired
*/
virtual bool tryAcquire(string* errMsg);
/**
* Tries to unlock the lock if acquired. Cannot report an error or
block indefinitely
* (though it may log messages or continue retrying in a non-blocki
ng way).
*
* Subclasses should define their own destructor unlockXXX() method
s.
*/
void unlock();
/**
* Tries multiple times to unlock the lock, using the specified loc
k try interval, until
* a certain amount of time has passed. An error message is immedi
ately returned if the
* lock acquisition attempt fails with an error message.
* waitForMillis = 0 indicates there should only be one attempt to
acquire the lock, and
* no waiting.
* waitForMillis = -1 indicates we should retry indefinitely.
* @return true if the lock was acquired
*/
bool acquire(long long waitForMillis, string* errMsg);
bool isAcquired() const {
return _acquired;
}
ConnectionString getConfigConnectionString() const {
return _lock._conn;
}
void setLockTryIntervalMillis(long long lockTryIntervalMillis) {
_lockTryIntervalMillis = lockTryIntervalMillis;
}
long long getLockTryIntervalMillis() const {
return _lockTryIntervalMillis;
}
void setLockMessage(const string& why) {
_why = why;
}
string getLockMessage() const {
return _why;
}
private:
DistributedLock _lock;
string _why;
long long _lockTryIntervalMillis;
bool _acquired;
BSONObj _other;
};
} }
 End of changes. 2 change blocks. 
0 lines changed or deleted 90 lines changed or added


 document.h   document.h 
skipping to change at line 112 skipping to change at line 112
* the fields in order. The comparison is done in roughly the sam e way * the fields in order. The comparison is done in roughly the sam e way
* as strings are compared, but comparing one field at a time inst ead * as strings are compared, but comparing one field at a time inst ead
* of one character at a time. * of one character at a time.
* *
* @returns an integer less than zero, zero, or an integer greater than * @returns an integer less than zero, zero, or an integer greater than
* zero, depending on whether lhs < rhs, lhs == rhs, or l hs > rhs * zero, depending on whether lhs < rhs, lhs == rhs, or l hs > rhs
* Warning: may return values other than -1, 0, or 1 * Warning: may return values other than -1, 0, or 1
*/ */
static int compare(const Document& lhs, const Document& rhs); static int compare(const Document& lhs, const Document& rhs);
string toString() const; // TODO support streams string toString() const;
friend
ostream& operator << (ostream& out, const Document& doc) { return o
ut << doc.toString(); }
/** Calculate a hash value. /** Calculate a hash value.
* *
* Meant to be used to create composite hashes suitable for * Meant to be used to create composite hashes suitable for
* hashed container classes such as unordered_map. * hashed container classes such as unordered_map.
*/ */
void hash_combine(size_t &seed) const; void hash_combine(size_t &seed) const;
/// Add this document to the BSONObj under construction with the gi ven BSONObjBuilder. /// Add this document to the BSONObj under construction with the gi ven BSONObjBuilder.
void toBson(BSONObjBuilder *pBsonObjBuilder) const; void toBson(BSONObjBuilder *pBsonObjBuilder) const;
// Support BSONObjBuilder and BSONArrayBuilder "stream" API
friend BSONObjBuilder& operator << (BSONObjBuilderValueStream& buil
der, const Document& d);
/** Return the abstract Position of a field, suitable to pass to op erator[] or getField(). /** Return the abstract Position of a field, suitable to pass to op erator[] or getField().
* This can potentially save time if you need to refer to a field multiple times. * This can potentially save time if you need to refer to a field multiple times.
*/ */
Position positionOf(StringData fieldName) const { return storage(). findField(fieldName); } Position positionOf(StringData fieldName) const { return storage(). findField(fieldName); }
/** Clone a document. /** Clone a document.
* *
* This should only be called by MutableDocument and tests * This should only be called by MutableDocument and tests
* *
* The new document shares all the fields' values with the origina l. * The new document shares all the fields' values with the origina l.
skipping to change at line 281 skipping to change at line 287
/// Update field by Position. Must already be a valid Position. /// Update field by Position. Must already be a valid Position.
MutableValue operator[] (Position pos) { return getField(pos); } MutableValue operator[] (Position pos) { return getField(pos); }
void setField(Position pos, const Value& val) { getField(pos) = val ; } void setField(Position pos, const Value& val) { getField(pos) = val ; }
MutableValue getField(Position pos) { MutableValue getField(Position pos) {
return MutableValue(storage().getField(pos).val); return MutableValue(storage().getField(pos).val);
} }
/// Logically remove a field. Note that memory usage does not decre ase. /// Logically remove a field. Note that memory usage does not decre ase.
void remove(StringData key) { getField(key) = Value(); } void remove(StringData key) { getField(key) = Value(); }
/// Takes positions vector from Document::getNestedField. /** Gets/Sets a nested field given a path.
*
* All fields along path are created as empty Documents if they do
n't exist
* or are any other type.
*/
MutableValue getNestedField(const FieldPath& dottedField);
void setNestedField(const FieldPath& dottedField, const Value& val)
{
getNestedField(dottedField) = val;
}
/// Takes positions vector from Document::getNestedField. All field
s in path must exist.
MutableValue getNestedField(const vector<Position>& positions); MutableValue getNestedField(const vector<Position>& positions);
void setNestedField(const vector<Position>& positions, const Value& val) { void setNestedField(const vector<Position>& positions, const Value& val) {
getNestedField(positions) = val; getNestedField(positions) = val;
} }
/** Convert to a read-only document and release reference. /** Convert to a read-only document and release reference.
* *
* Call this to indicate that you are done with this Document and will * Call this to indicate that you are done with this Document and will
* not be making further changes from this MutableDocument. * not be making further changes from this MutableDocument.
* *
* TODO: there are some optimizations that may make sense at freez e time. * TODO: there are some optimizations that may make sense at freez e time.
*/ */
Document freeze() { Document freeze() {
Document ret(storagePtr()); // This essentially moves _storage into a new Document by way o
reset(NULL); f temp.
Document ret;
intrusive_ptr<const DocumentStorage> temp (storagePtr(), /*inc_
ref_count=*/false);
temp.swap(ret._storage);
_storage = NULL;
return ret; return ret;
} }
/** Borrow a readable reference to this Document. /** Borrow a readable reference to this Document.
* *
* Note that unlike freeze(), this indicates intention to continue * Note that unlike freeze(), this indicates intention to continue
* modifying this document. The returned Document will not observe * modifying this document. The returned Document will not observe
* future changes to this MutableDocument. * future changes to this MutableDocument.
*/ */
Document peek() { Document peek() {
skipping to change at line 343 skipping to change at line 362
} }
DocumentStorage& newStorage() { DocumentStorage& newStorage() {
reset(new DocumentStorage); reset(new DocumentStorage);
return const_cast<DocumentStorage&>(*storagePtr()); return const_cast<DocumentStorage&>(*storagePtr());
} }
DocumentStorage& clonedStorage() { DocumentStorage& clonedStorage() {
reset(storagePtr()->clone().get()); reset(storagePtr()->clone().get());
return const_cast<DocumentStorage&>(*storagePtr()); return const_cast<DocumentStorage&>(*storagePtr());
} }
MutableValue getNestedFieldHelper(MutableDocument& md, // recursive helpers for same-named public methods
const vector<Position>& positions MutableValue getNestedFieldHelper(const FieldPath& dottedField, siz
, e_t level);
size_t level); MutableValue getNestedFieldHelper(const vector<Position>& positions
, size_t level);
// this should only be called by storage methods and peek/freeze // this should only be called by storage methods and peek/freeze
const DocumentStorage* storagePtr() const { const DocumentStorage* storagePtr() const {
dassert(!_storage || typeid(*_storage) == typeid(const Document Storage)); dassert(!_storage || typeid(*_storage) == typeid(const Document Storage));
return static_cast<const DocumentStorage*>(_storage); return static_cast<const DocumentStorage*>(_storage);
} }
// These are both const to prevent modifications bypassing storage( ) method. // These are both const to prevent modifications bypassing storage( ) method.
// They always point to NULL or an object with dynamic type Documen tStorage. // They always point to NULL or an object with dynamic type Documen tStorage.
const RefCountable* _storageHolder; // Only used in constructors an d destructor const RefCountable* _storageHolder; // Only used in constructors an d destructor
 End of changes. 5 change blocks. 
8 lines changed or deleted 35 lines changed or added


 document_internal.h   document_internal.h 
skipping to change at line 58 skipping to change at line 58
#pragma pack(1) #pragma pack(1)
/** This is how values are stored in the DocumentStorage buffer /** This is how values are stored in the DocumentStorage buffer
* Internal class. Consumers shouldn't care about this. * Internal class. Consumers shouldn't care about this.
*/ */
class ValueElement : boost::noncopyable { class ValueElement : boost::noncopyable {
public: public:
Value val; Value val;
Position nextCollision; // Position of next field with same hashBuc ket Position nextCollision; // Position of next field with same hashBuc ket
const int nameLen; // doesn't include '\0' const int nameLen; // doesn't include '\0'
const char name[1]; // pointer to start of name const char _name[1]; // pointer to start of name (use nameSD instea d)
ValueElement* next() { ValueElement* next() {
return align(plusBytes(sizeof(ValueElement) + nameLen)); return align(plusBytes(sizeof(ValueElement) + nameLen));
} }
const ValueElement* next() const { const ValueElement* next() const {
return align(plusBytes(sizeof(ValueElement) + nameLen)); return align(plusBytes(sizeof(ValueElement) + nameLen));
} }
StringData nameSD() const { return StringData(name, nameLen); } StringData nameSD() const { return StringData(_name, nameLen); }
// helpers for doing pointer arithmetic with this class // helpers for doing pointer arithmetic with this class
// Note: These don't dereference 'this' so they are safe to use wit h NULL // Note: These don't dereference 'this' so they are safe to use wit h NULL
char* ptr() { return reinterpret_cast<char*>(this); } char* ptr() { return reinterpret_cast<char*>(this); }
const char* ptr() const { return reinterpret_cast<const char*>(this ); } const char* ptr() const { return reinterpret_cast<const char*>(this ); }
const ValueElement* plusBytes(size_t bytes) const { const ValueElement* plusBytes(size_t bytes) const {
return reinterpret_cast<const ValueElement*>(ptr() + bytes); return reinterpret_cast<const ValueElement*>(ptr() + bytes);
} }
ValueElement* plusBytes(size_t bytes) { ValueElement* plusBytes(size_t bytes) {
return reinterpret_cast<ValueElement*>(ptr() + bytes); return reinterpret_cast<ValueElement*>(ptr() + bytes);
skipping to change at line 111 skipping to change at line 111
class DocumentStorageIterator { class DocumentStorageIterator {
public: public:
// DocumentStorage::iterator() and iteratorAll() are easier to use // DocumentStorage::iterator() and iteratorAll() are easier to use
DocumentStorageIterator(const ValueElement* first, DocumentStorageIterator(const ValueElement* first,
const ValueElement* end, const ValueElement* end,
bool includeMissing) bool includeMissing)
: _first(first) : _first(first)
, _it(first) , _it(first)
, _end(end) , _end(end)
, _includeMissing(includeMissing) { , _includeMissing(includeMissing) {
skipMissing(); if (!_includeMissing)
skipMissing();
} }
bool atEnd() const { return _it == _end; } bool atEnd() const { return _it == _end; }
const ValueElement& get() const { return *_it; } const ValueElement& get() const { return *_it; }
Position position() const { return Position(_it->ptr() - _first->pt r()); } Position position() const { return Position(_it->ptr() - _first->pt r()); }
void advance() { void advance() {
advanceOne(); advanceOne();
skipMissing(); if (!_includeMissing)
skipMissing();
} }
const ValueElement* operator-> () { return _it; } const ValueElement* operator-> () { return _it; }
const ValueElement& operator* () { return *_it; } const ValueElement& operator* () { return *_it; }
private: private:
void advanceOne() { void advanceOne() {
_it = _it->next(); _it = _it->next();
} }
void skipMissing() { void skipMissing() {
if (!_includeMissing) { while (!atEnd() && _it->val.missing()) {
while (!atEnd() && _it->val.missing()) { advanceOne();
advanceOne();
}
} }
} }
const ValueElement* _first; const ValueElement* _first;
const ValueElement* _it; const ValueElement* _it;
const ValueElement* _end; const ValueElement* _end;
bool _includeMissing; bool _includeMissing;
}; };
/// Storage class used by both Document and MutableDocument /// Storage class used by both Document and MutableDocument
skipping to change at line 251 skipping to change at line 251
/// rehash on buffer growth if load-factor > .5 (attempt to keep lf < 1 when full) /// rehash on buffer growth if load-factor > .5 (attempt to keep lf < 1 when full)
bool needRehash() const { return _numFields*2 > hashTabBuckets(); } bool needRehash() const { return _numFields*2 > hashTabBuckets(); }
/// Initialize empty hash table /// Initialize empty hash table
void hashTabInit() { memset(_hashTab, -1, hashTabBytes()); } void hashTabInit() { memset(_hashTab, -1, hashTabBytes()); }
static unsigned hashKey(StringData name) { static unsigned hashKey(StringData name) {
// TODO consider FNV-1a once we have a better benchmark corpus // TODO consider FNV-1a once we have a better benchmark corpus
unsigned out; unsigned out;
MurmurHash3_x86_32(name.data(), name.size(), 0, &out); MurmurHash3_x86_32(name.rawData(), name.size(), 0, &out);
return out; return out;
} }
unsigned bucketForKey(StringData name) const { unsigned bucketForKey(StringData name) const {
return hashKey(name) & _hashTabMask; return hashKey(name) & _hashTabMask;
} }
/// Adds all fields to the hash table /// Adds all fields to the hash table
void rehash() { void rehash() {
hashTabInit(); hashTabInit();
 End of changes. 6 change blocks. 
9 lines changed or deleted 9 lines changed or added


 document_source.h   document_source.h 
skipping to change at line 41 skipping to change at line 41
#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 Matcher; 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 182 skipping to change at line 183
*/ */
virtual GetDepsReturn getDependencies(set<string>& deps) const { virtual GetDepsReturn getDependencies(set<string>& deps) const {
return NOT_SUPPORTED; return NOT_SUPPORTED;
} }
/** This takes dependencies from getDependencies and /** This takes dependencies from getDependencies and
* returns a projection that includes all of them * returns a projection that includes all of them
*/ */
static BSONObj depsToProjection(const set<string>& deps); static BSONObj depsToProjection(const set<string>& deps);
/** These functions take the same input as depsToProjection but are
able to
* produce a Document from a BSONObj with the needed fields much f
aster.
*/
typedef Document ParsedDeps; // See implementation for structure
static ParsedDeps parseDeps(const set<string>& deps);
static Document documentFromBsonWithDeps(const BSONObj& object, con
st ParsedDeps& deps);
/** /**
Add the DocumentSource to the array builder. Add the DocumentSource to the array builder.
The default implementation calls sourceToBson() in order to The default implementation calls sourceToBson() in order to
convert the inner part of the object which will be added to the convert the inner part of the object which will be added to the
array being built here. array being built here.
A subclass may choose to overwrite this rather than addToBsonArra
y
if it should output multiple stages.
@param pBuilder the array builder to add the operation to. @param pBuilder the array builder to add the operation to.
@param explain create explain output @param explain create explain output
*/ */
virtual void addToBsonArray(BSONArrayBuilder *pBuilder, virtual void addToBsonArray(BSONArrayBuilder *pBuilder, bool explai
bool explain = false) const; n=false) const;
protected: protected:
/** /**
Base constructor. Base constructor.
*/ */
DocumentSource(const intrusive_ptr<ExpressionContext> &pExpCtx); DocumentSource(const intrusive_ptr<ExpressionContext> &pExpCtx);
/** /**
Create an object that represents the document source. The object Create an object that represents the document source. The object
will have a single field whose name is the source's name. This will have a single field whose name is the source's name. This
skipping to change at line 432 skipping to change at line 442
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 shared_ptr<BSONObj> &pBsonObj);
void setProjection(BSONObj projection); 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);
void findNext(); void findNext();
skipping to change at line 458 skipping to change at line 468
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; shared_ptr<BSONObj> pQuery;
shared_ptr<BSONObj> pSort; shared_ptr<BSONObj> pSort;
shared_ptr<Projection> _projection; // shared with pClientCursor shared_ptr<Projection> _projection; // shared with pClientCursor
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();
/* /*
Yield the cursor sometimes. Yield the cursor sometimes.
skipping to change at line 597 skipping to change at line 608
class DocumentSourceGroup : class DocumentSourceGroup :
public SplittableDocumentSource { public SplittableDocumentSource {
public: public:
// virtuals from DocumentSource // virtuals from DocumentSource
virtual ~DocumentSourceGroup(); virtual ~DocumentSourceGroup();
virtual bool eof(); virtual bool eof();
virtual bool advance(); virtual bool advance();
virtual const char *getSourceName() const; virtual const char *getSourceName() const;
virtual Document getCurrent(); virtual Document getCurrent();
virtual GetDepsReturn getDependencies(set<string>& deps) const; virtual GetDepsReturn getDependencies(set<string>& deps) const;
virtual void dispose();
/** /**
Create a new grouping DocumentSource. Create a new grouping DocumentSource.
@param pExpCtx the expression context for the pipeline @param pExpCtx the expression context for the pipeline
@returns the DocumentSource @returns the DocumentSource
*/ */
static intrusive_ptr<DocumentSourceGroup> create( static intrusive_ptr<DocumentSourceGroup> create(
const intrusive_ptr<ExpressionContext> &pExpCtx); const intrusive_ptr<ExpressionContext> &pExpCtx);
skipping to change at line 698 skipping to change at line 710
These three vectors parallel each other. These three vectors parallel each other.
*/ */
vector<string> vFieldName; vector<string> vFieldName;
vector<intrusive_ptr<Accumulator> (*)( vector<intrusive_ptr<Accumulator> (*)(
const intrusive_ptr<ExpressionContext> &)> vpAccumulatorFactory ; const intrusive_ptr<ExpressionContext> &)> vpAccumulatorFactory ;
vector<intrusive_ptr<Expression> > vpExpression; vector<intrusive_ptr<Expression> > vpExpression;
Document makeDocument(const GroupsType::iterator &rIter); Document makeDocument(const GroupsType::iterator &rIter);
GroupsType::iterator groupsIterator; GroupsType::iterator groupsIterator;
Document pCurrent;
}; };
class DocumentSourceMatch : class DocumentSourceMatch :
public DocumentSourceFilterBase { public DocumentSourceFilterBase {
public: public:
// virtuals from DocumentSource // virtuals from DocumentSource
virtual ~DocumentSourceMatch(); virtual ~DocumentSourceMatch();
virtual const char *getSourceName() const; virtual const char *getSourceName() const;
/** /**
skipping to change at line 840 skipping to change at line 851
class DocumentSourceSort : class DocumentSourceSort :
public SplittableDocumentSource { public SplittableDocumentSource {
public: public:
// virtuals from DocumentSource // virtuals from DocumentSource
virtual ~DocumentSourceSort(); virtual ~DocumentSourceSort();
virtual bool eof(); virtual bool eof();
virtual bool advance(); virtual bool advance();
virtual const char *getSourceName() const; virtual const char *getSourceName() const;
virtual Document getCurrent(); virtual Document getCurrent();
virtual void addToBsonArray(BSONArrayBuilder *pBuilder, bool explai
virtual GetDepsReturn getDependencies(set<string>& deps) const; n=false) const;
/*
TODO
Adjacent sorts should reduce to the last sort.
virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou rce); virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou rce);
*/ virtual void dispose();
/**
Create a new sorting DocumentSource.
@param pExpCtx the expression context for the pipeline virtual GetDepsReturn getDependencies(set<string>& deps) const;
@returns the DocumentSource
*/
static intrusive_ptr<DocumentSourceSort> create(
const intrusive_ptr<ExpressionContext> &pExpCtx);
// Virtuals for SplittableDocumentSource // Virtuals for SplittableDocumentSource
// All work for sort is done in router currently // All work for sort is done in router currently if there is no lim
// TODO: do partial sorts on the shards then merge in the router it.
// Not currently possible due to DocumentSource's cursor-like // If there is a limit, the $sort/$limit combination is performed o
interface n the
virtual intrusive_ptr<DocumentSource> getShardSource() { return NUL // shards, then the results are resorted and limited on mongos
L; } virtual intrusive_ptr<DocumentSource> getShardSource() { return lim
itSrc ? this : NULL; }
virtual intrusive_ptr<DocumentSource> getRouterSource() { return th is; } virtual intrusive_ptr<DocumentSource> getRouterSource() { return th is; }
/** /**
Add sort key field. Add sort key field.
Adds a sort key field to the key being built up. A concatenated Adds a sort key field to the key being built up. A concatenated
key is built up by calling this repeatedly. key is built up by calling this repeatedly.
@param fieldPath the field path to the key component @param fieldPath the field path to the key component
@param ascending if true, use the key for an ascending sort, @param ascending if true, use the key for an ascending sort,
skipping to change at line 900 skipping to change at line 899
element named $group. element named $group.
@param pBsonElement the BSONELement that defines the group @param pBsonElement the BSONELement that defines the group
@param pExpCtx the expression context for the pipeline @param pExpCtx the expression context for the pipeline
@returns the grouping DocumentSource @returns the grouping DocumentSource
*/ */
static intrusive_ptr<DocumentSource> createFromBson( static intrusive_ptr<DocumentSource> createFromBson(
BSONElement *pBsonElement, BSONElement *pBsonElement,
const intrusive_ptr<ExpressionContext> &pExpCtx); const intrusive_ptr<ExpressionContext> &pExpCtx);
static const char sortName[]; /// Create a DocumentSourceSort with a given sort and (optional) li
mit
static intrusive_ptr<DocumentSourceSort> create(
const intrusive_ptr<ExpressionContext> &pExpCtx,
BSONObj sortOrder,
long long limit=-1);
/// returns -1 for no limit
long long getLimit() const;
intrusive_ptr<DocumentSourceLimit> getLimitSrc() const { return lim
itSrc; }
static const char sortName[];
protected: protected:
// virtuals from DocumentSource // virtuals from DocumentSource
virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c
onst; onst {
verify(false); // should call addToBsonArray instead
}
private: private:
DocumentSourceSort(const intrusive_ptr<ExpressionContext> &pExpCtx) ; DocumentSourceSort(const intrusive_ptr<ExpressionContext> &pExpCtx) ;
/* /*
Before returning anything, this source must fetch everything from Before returning anything, this source must fetch everything from
the underlying source and group it. populate() is used to do tha t the underlying source and group it. populate() is used to do tha t
on the first call to any method on this source. The populated on the first call to any method on this source. The populated
boolean indicates that this has been done. boolean indicates that this has been done.
*/ */
void populate(); void populate();
bool populated; bool populated;
// These are called by populate()
void populateAll(); // no limit
void populateOne(); // limit == 1
void populateTopK(); // limit > 1
/* these two parallel each other */ /* these two parallel each other */
typedef vector<intrusive_ptr<ExpressionFieldPath> > SortPaths; typedef vector<intrusive_ptr<ExpressionFieldPath> > SortPaths;
SortPaths vSortKey; SortPaths vSortKey;
vector<bool> vAscending; vector<char> vAscending; // used like vector<bool> but without spec ialization
/* struct KeyAndDoc {
Compare two documents according to the specified sort key. explicit KeyAndDoc(const Document& d, const SortPaths& sp); //
extracts sort key
Value key; // array of keys if vSortKey.size() > 1
Document doc;
};
friend void swap(KeyAndDoc& l, KeyAndDoc& r);
@param rL reference to the left document /// Compare two KeyAndDocs according to the specified sort key.
@param rR reference to the right document int compare(const KeyAndDoc& lhs, const KeyAndDoc& rhs) const;
@returns a number less than, equal to, or greater than zero,
indicating pL < pR, pL == pR, or pL > pR, respectively
*/
int compare(const Document& pL, const Document& pR);
/* /*
This is a utility class just for the STL sort that is done This is a utility class just for the STL sort that is done
inside. inside.
*/ */
class Comparator { class Comparator {
public: public:
bool operator()(const Document& pL, const Document& pR) { explicit Comparator(const DocumentSourceSort& source): _source(
return (pSort->compare(pL, pR) < 0); source) {}
} bool operator()(const KeyAndDoc& lhs, const KeyAndDoc& rhs) con
st {
inline Comparator(DocumentSourceSort *pS): return (_source.compare(lhs, rhs) < 0);
pSort(pS) {
} }
private: private:
DocumentSourceSort *pSort; const DocumentSourceSort& _source;
}; };
typedef vector<Document> VectorType; deque<KeyAndDoc> documents;
VectorType documents;
VectorType::iterator docIterator; intrusive_ptr<DocumentSourceLimit> limitSrc;
Document pCurrent;
}; };
inline void swap(DocumentSourceSort::KeyAndDoc& l, DocumentSourceSort::
KeyAndDoc& r) {
l.key.swap(r.key);
l.doc.swap(r.doc);
}
class DocumentSourceLimit : class DocumentSourceLimit :
public SplittableDocumentSource { public SplittableDocumentSource {
public: public:
// virtuals from DocumentSource // virtuals from DocumentSource
virtual ~DocumentSourceLimit(); virtual ~DocumentSourceLimit();
virtual bool eof(); virtual bool eof();
virtual bool advance(); virtual bool advance();
virtual Document getCurrent(); virtual Document getCurrent();
virtual const char *getSourceName() const; virtual const char *getSourceName() const;
skipping to change at line 980 skipping to change at line 994
return SEE_NEXT; // This doesn't affect needed fields return SEE_NEXT; // This doesn't affect needed fields
} }
/** /**
Create a new limiting DocumentSource. Create a new limiting DocumentSource.
@param pExpCtx the expression context for the pipeline @param pExpCtx the expression context for the pipeline
@returns the DocumentSource @returns the DocumentSource
*/ */
static intrusive_ptr<DocumentSourceLimit> create( static intrusive_ptr<DocumentSourceLimit> create(
const intrusive_ptr<ExpressionContext> &pExpCtx); const intrusive_ptr<ExpressionContext> &pExpCtx,
long long limit);
// Virtuals for SplittableDocumentSource // Virtuals for SplittableDocumentSource
// Need to run on rounter. Running on shard as well is an optimizat ion. // Need to run on rounter. Running on shard as well is an optimizat ion.
virtual intrusive_ptr<DocumentSource> getShardSource() { return thi s; } virtual intrusive_ptr<DocumentSource> getShardSource() { return thi s; }
virtual intrusive_ptr<DocumentSource> getRouterSource() { return th is; } virtual intrusive_ptr<DocumentSource> getRouterSource() { return th is; }
long long getLimit() const { return limit; } long long getLimit() const { return limit; }
void setLimit(long long newLimit) { limit = newLimit; } void setLimit(long long newLimit) { limit = newLimit; }
/** /**
skipping to change at line 1012 skipping to change at line 1027
BSONElement *pBsonElement, BSONElement *pBsonElement,
const intrusive_ptr<ExpressionContext> &pExpCtx); const intrusive_ptr<ExpressionContext> &pExpCtx);
static const char limitName[]; static const char limitName[];
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:
DocumentSourceLimit( DocumentSourceLimit(const intrusive_ptr<ExpressionContext> &pExpCtx
const intrusive_ptr<ExpressionContext> &pExpCtx); ,
long long limit);
long long limit; long long limit;
long long count; long long count;
}; };
class DocumentSourceSkip : class DocumentSourceSkip :
public SplittableDocumentSource { public SplittableDocumentSource {
public: public:
// virtuals from DocumentSource // virtuals from DocumentSource
virtual ~DocumentSourceSkip(); virtual ~DocumentSourceSkip();
skipping to change at line 1143 skipping to change at line 1158
void unwindPath(const FieldPath &fieldPath); void unwindPath(const FieldPath &fieldPath);
// Configuration state. // Configuration state.
scoped_ptr<FieldPath> _unwindPath; scoped_ptr<FieldPath> _unwindPath;
// Iteration state. // Iteration state.
class Unwinder; class Unwinder;
scoped_ptr<Unwinder> _unwinder; scoped_ptr<Unwinder> _unwinder;
}; };
class DocumentSourceGeoNear : public SplittableDocumentSource {
public:
// virtuals from DocumentSource
virtual ~DocumentSourceGeoNear();
virtual bool eof();
virtual bool advance();
virtual Document getCurrent();
virtual const char *getSourceName() const;
virtual void setSource(DocumentSource *pSource); // errors out sinc
e this must be first
virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou
rce);
// Virtuals for SplittableDocumentSource
virtual intrusive_ptr<DocumentSource> getShardSource();
virtual intrusive_ptr<DocumentSource> getRouterSource();
static intrusive_ptr<DocumentSource> createFromBson(
BSONElement *pBsonElement,
const intrusive_ptr<ExpressionContext> &pCtx);
static char geoNearName[];
long long getLimit() { return limit; }
// this should only be used for testing
static intrusive_ptr<DocumentSourceGeoNear> create(
const intrusive_ptr<ExpressionContext> &pCtx);
protected:
// virtuals from DocumentSource
virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c
onst;
private:
DocumentSourceGeoNear(const intrusive_ptr<ExpressionContext> &pExpC
tx);
void parseOptions(BSONObj options);
BSONObj buildGeoNearCmd(const StringData& collection) const;
void runCommand();
// These fields describe the command to run.
// coords and distanceField are required, rest are optional
BSONObj coords; // "near" option, but near is a reserved keyword on
windows
bool coordsIsArray;
scoped_ptr<FieldPath> distanceField; // Using scoped_ptr because Fi
eldPath can't be empty
long long limit;
double maxDistance;
BSONObj query;
bool spherical;
double distanceMultiplier;
scoped_ptr<FieldPath> includeLocs;
bool uniqueDocs;
// These fields are injected by PipelineD. This division of labor a
llows the
// DocumentSourceGeoNear class to be linked into both mongos and mo
ngod while
// allowing it to run a command using DBDirectClient when in mongod
.
string db;
string collection;
boost::scoped_ptr<DBClientWithCommands> client; // either NULL or a
DBDirectClient
friend class PipelineD;
// these fields are used while processing the results
BSONObj cmdOutput;
boost::scoped_ptr<BSONObjIterator> resultsIterator; // iterator ove
r cmdOutput["results"]
Document currentDoc;
bool hasCurrent;
};
} }
/* ======================= INLINED IMPLEMENTATIONS ======================== == */ /* ======================= INLINED IMPLEMENTATIONS ======================== == */
namespace mongo { namespace mongo {
inline void DocumentSource::setPipelineStep(int s) { inline void DocumentSource::setPipelineStep(int s) {
step = s; step = s;
} }
 End of changes. 28 change blocks. 
52 lines changed or deleted 157 lines changed or added


 dur_journalimpl.h   dur_journalimpl.h 
skipping to change at line 76 skipping to change at line 76
* internally called with every commit * internally called with every commit
*/ */
void _rotate(); void _rotate();
void _open(); void _open();
void closeCurrentJournalFile(); void closeCurrentJournalFile();
void removeUnneededJournalFiles(); void removeUnneededJournalFiles();
unsigned long long _written; // bytes written so far to the cur rent journal (log) file unsigned long long _written; // bytes written so far to the cur rent journal (log) file
unsigned _nextFileNumber; unsigned _nextFileNumber;
public:
SimpleMutex _curLogFileMutex; SimpleMutex _curLogFileMutex;
bool _ageOut;
private:
LogFile *_curLogFile; // use _curLogFileMutex LogFile *_curLogFile; // use _curLogFileMutex
unsigned long long _curFileId; // current file id see JHeader:: fileId unsigned long long _curFileId; // current file id see JHeader:: fileId
struct JFile { struct JFile {
string filename; string filename;
unsigned long long lastEventTimeMs; unsigned long long lastEventTimeMs;
}; };
// files which have been closed but not unlinked (rotated out) yet // files which have been closed but not unlinked (rotated out) yet
 End of changes. 2 change blocks. 
3 lines changed or deleted 1 lines changed or added


 engine.h   engine.h 
skipping to change at line 23 skipping to change at line 23
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
namespace mongo { namespace mongo {
typedef unsigned long long ScriptingFunction;
typedef BSONObj (*NativeFunction)(const BSONObj& args, void* data);
class DBClientWithCommands;
static const unsigned kMaxJsFileLength = std::numeric_limits<unsigned>:
:max() - 1;
struct JSFile { struct JSFile {
const char* name; const char* name;
const StringData& source; const StringData& source;
}; };
typedef unsigned long long ScriptingFunction;
typedef BSONObj (*NativeFunction) ( const BSONObj &args, void* data );
class Scope : boost::noncopyable { class Scope : boost::noncopyable {
public: public:
Scope(); Scope();
virtual ~Scope(); virtual ~Scope();
virtual void reset() = 0; virtual void reset() = 0;
virtual void init( const BSONObj * data ) = 0; virtual void init(const BSONObj* data) = 0;
void init( const char * data ) { void init(const char* data) {
BSONObj o( data ); BSONObj o(data);
init( &o ); init(&o);
} }
virtual void localConnect( const char * dbName ) = 0; virtual void localConnect(const char* dbName) = 0;
virtual void externalSetup() = 0; virtual void externalSetup() = 0;
class NoDBAccess { virtual BSONObj getObject(const char* field) = 0;
Scope * _s; virtual string getString(const char* field) = 0;
public: virtual bool getBoolean(const char* field) = 0;
NoDBAccess( Scope * s ) { virtual double getNumber(const char* field) = 0;
_s = s; virtual int getNumberInt(const char* field) { return (int)getNumber
} (field); }
~NoDBAccess() { virtual long long getNumberLongLong(const char* field) {
_s->rename( "____db____" , "db" ); return static_cast<long long>(getNumber(field));
} }
};
NoDBAccess disableDBAccess( const char * why ) { virtual void setElement(const char* field, const BSONElement& e) =
rename( "db" , "____db____" ); 0;
return NoDBAccess( this ); virtual void setNumber(const char* field, double val) = 0;
} virtual void setString(const char* field, const char* val) = 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 setFunction(const char* field, const char* code) = 0;
virtual int type(const char* field) = 0;
virtual double getNumber( const char *field ) = 0; virtual void append(BSONObjBuilder& builder, const char* fieldName,
virtual int getNumberInt( const char *field ) { return (int)getNumb const char* scopeName);
er( field ); }
virtual long long getNumberLongLong( const char *field ) { return (
long long)getNumber( field ); }
virtual string getString( const char *field ) = 0;
virtual bool getBoolean( const char *field ) = 0;
virtual BSONObj getObject( const char *field ) = 0;
virtual int type( const char *field ) = 0; virtual void rename(const char* from, const char* to) = 0;
virtual void append( BSONObjBuilder & builder , const char * fieldN virtual string getError() = 0;
ame , const char * scopeName );
virtual bool hasOutOfMemoryException() = 0;
virtual void setElement( const char *field , const BSONElement& e ) virtual bool isKillPending() const = 0;
= 0;
virtual void setNumber( const char *field , double val ) = 0;
virtual void setString( const char *field , const char * val ) = 0;
virtual void setObject( const char *field , const BSONObj& obj , bo
ol readOnly=true ) = 0;
virtual void setBoolean( const char *field , bool val ) = 0;
virtual void setFunction( const char *field , const char * code ) =
0;
// virtual void setThis( const BSONObj * obj ) = 0;
virtual ScriptingFunction createFunction( const char * code ); virtual void gc() = 0;
virtual ScriptingFunction createFunction(const char* code);
virtual void rename( const char * from , const char * to ) = 0;
/** /**
* @return 0 on success * @return 0 on success
*/ */
virtual int invoke( ScriptingFunction func , const BSONObj* args, c int invoke(const char* code, const BSONObj* args, const BSONObj* re
onst BSONObj* recv, int timeoutMs = 0 , bool ignoreReturn = false, bool rea cv, int timeoutMs = 0);
dOnlyArgs = false, bool readOnlyRecv = false ) = 0;
void invokeSafe( ScriptingFunction func , const BSONObj* args, cons virtual int invoke(ScriptingFunction func, const BSONObj* args, con
t BSONObj* recv, int timeoutMs = 0 , bool ignoreReturn = false, bool readOn st BSONObj* recv,
lyArgs = false, bool readOnlyRecv = false ) { int timeoutMs = 0, bool ignoreReturn = false, bo
int res = invoke( func , args , recv, timeoutMs, ignoreReturn, ol readOnlyArgs = false,
readOnlyArgs, readOnlyRecv ); bool readOnlyRecv = false) = 0;
if ( res == 0 )
void invokeSafe(ScriptingFunction func, const BSONObj* args, const
BSONObj* recv,
int timeoutMs = 0, bool ignoreReturn = false, bool
readOnlyArgs = false,
bool readOnlyRecv = false) {
int res = invoke(func, args, recv, timeoutMs, ignoreReturn,
readOnlyArgs, readOnlyRecv);
if (res == 0)
return; return;
throw UserException( 9004 , (string)"invoke failed: " + getErro r() ); uasserted(9004, string("invoke failed: ") + getError());
} }
virtual string getError() = 0;
virtual bool hasOutOfMemoryException() = 0;
int invoke( const char* code , const BSONObj* args, const BSONObj* void invokeSafe(const char* code, const BSONObj* args, const BSONOb
recv, int timeoutMs = 0 ); j* recv,
void invokeSafe( const char* code , const BSONObj* args, const BSON int timeoutMs = 0) {
Obj* recv, int timeoutMs = 0 ) { if (invoke(code, args, recv, timeoutMs) == 0)
if ( invoke( code , args , recv, timeoutMs ) == 0 )
return; return;
throw UserException( 9005 , (string)"invoke failed: " + getErro r() ); uasserted(9005, string("invoke failed: ") + getError());
} }
virtual bool exec( const StringData& code , const string& name , bo virtual void injectNative(const char* field, NativeFunction func, v
ol printResult , bool reportError , bool assertOnError, int timeoutMs = 0 ) oid* data = 0) = 0;
= 0;
virtual void execSetup( const StringData& code , const string& name virtual bool exec(const StringData& code, const string& name, bool
= "setup" ) { printResult,
exec( code , name , false , true , true , 0 ); bool reportError, bool assertOnError, int timeout
Ms = 0) = 0;
virtual void execSetup(const StringData& code, const string& name =
"setup") {
exec(code, name, false, true, true, 0);
} }
void execSetup( const JSFile& file) { void execSetup(const JSFile& file) {
execSetup(file.source, file.name); execSetup(file.source, file.name);
} }
void execCoreFiles(); virtual bool execFile(const string& filename, bool printResult, boo
l reportError,
int timeoutMs = 0);
virtual bool execFile( const string& filename , bool printResult , void execCoreFiles();
bool reportError , bool assertOnError, int timeoutMs = 0 );
virtual void injectNative( const char *field, NativeFunction func,
void* data = 0 ) = 0;
virtual void gc() = 0;
void loadStored( bool ignoreNotConnected = false ); void loadStored(bool ignoreNotConnected = false);
/** /**
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 simple * right now its just global - slightly inefficient, but a lot simp
r ler
*/ */
static void storedFuncMod(); static void storedFuncMod();
static int getNumScopes() { static void validateObjectIdString(const string& str);
return _numScopes;
}
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 incTimeUsed() { ++_numTimeUsed; } void incTimeUsed() { ++_numTimeUsed; }
/** gets the number of times a scope was used */ /** gets the number of times a scope was used */
int getTimeUsed() { return _numTimeUsed; } int getTimeUsed() { return _numTimeUsed; }
protected: class NoDBAccess {
Scope* _s;
public:
NoDBAccess(Scope* s) : _s(s) {
}
~NoDBAccess() {
_s->rename("____db____", "db");
}
};
NoDBAccess disableDBAccess(const char* why) {
rename("db", "____db____");
return NoDBAccess(this);
}
virtual ScriptingFunction _createFunction( const char * code ) = 0; protected:
virtual ScriptingFunction _createFunction(const char* code) = 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;
map<string,ScriptingFunction> _cachedFunctions; map<string, ScriptingFunction> _cachedFunctions;
int _numTimeUsed; int _numTimeUsed;
static int _numScopes;
}; };
void installGlobalUtils( Scope& scope );
class DBClientWithCommands;
class ScriptEngine : boost::noncopyable { class ScriptEngine : boost::noncopyable {
public: public:
ScriptEngine(); ScriptEngine();
virtual ~ScriptEngine(); virtual ~ScriptEngine();
virtual Scope * newScope() { virtual Scope* newScope() {
Scope *s = createScope(); return createScope();
if ( s && _scopeInitCallback )
_scopeInitCallback( *s );
installGlobalUtils( *s );
return s;
} }
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 pool An identifier for the pool, usually the db name * @param pool An identifier for the pool, usually the db name
* @return the scope */ * @return the scope
auto_ptr<Scope> getPooledScope( const string& pool ); */
auto_ptr<Scope> getPooledScope(const string& pool);
/** call this method to release some JS resources when a thread is /**
done */ * call this method to release some JS resources when a thread is d
one
*/
void threadDone(); void threadDone();
void setScopeInitCallback( void ( *func )( Scope & ) ) { _scopeInit void setScopeInitCallback(void (*func)(Scope&)) { _scopeInitCallbac
Callback = func; } k = func; }
static void setConnectCallback( void ( *func )( DBClientWithCommand static void setConnectCallback(void (*func)(DBClientWithCommands&))
s& ) ) { _connectCallback = func; } {
static void runConnectCallback( DBClientWithCommands &c ) { _connectCallback = func;
if ( _connectCallback ) }
_connectCallback( c ); static void runConnectCallback(DBClientWithCommands& c) {
if (_connectCallback)
_connectCallback(c);
} }
// engine implementation may either respond to interrupt events or // engine implementation may either respond to interrupt events or
// poll for interrupts // poll for interrupts. the interrupt functions must not wait inde
finitely on a lock.
// the interrupt functions must not wait indefinitely on a lock virtual void interrupt(unsigned opId) {}
virtual void interrupt( unsigned opSpec ) {}
virtual void interruptAll() {} virtual void interruptAll() {}
static void setGetCurrentOpIdCallback(unsigned (*func)()) {
static void setGetInterruptSpecCallback( unsigned ( *func )() ) { _ _getCurrentOpIdCallback = func;
getInterruptSpecCallback = func; } }
static bool haveGetInterruptSpecCallback() { return _getInterruptSp static bool haveGetCurrentOpIdCallback() { return _getCurrentOpIdCa
ecCallback; } llback; }
static unsigned getInterruptSpec() { static unsigned getCurrentOpId() {
massert( 13474, "no _getInterruptSpecCallback", _getInterruptSp massert(13474, "no _getCurrentOpIdCallback", _getCurrentOpIdCal
ecCallback ); lback);
return _getInterruptSpecCallback(); return _getCurrentOpIdCallback();
}
static void setCheckInterruptCallback(const char* (*func)()) {
_checkInterruptCallback = func;
} }
static void setCheckInterruptCallback( const char * ( *func )() ) {
_checkInterruptCallback = func; }
static bool haveCheckInterruptCallback() { return _checkInterruptCa llback; } static bool haveCheckInterruptCallback() { return _checkInterruptCa llback; }
static const char * checkInterrupt() { static const char* checkInterrupt() {
return _checkInterruptCallback ? _checkInterruptCallback() : "" ; return _checkInterruptCallback ? _checkInterruptCallback() : "" ;
} }
static bool interrupted() { static bool interrupted() {
const char *r = checkInterrupt(); const char* r = checkInterrupt();
return r && r[ 0 ]; return r && r[0];
} }
static std::string getInterpreterVersionString(); static std::string getInterpreterVersionString();
protected: protected:
virtual Scope * createScope() = 0; virtual Scope* createScope() = 0;
void (*_scopeInitCallback)(Scope&);
private: private:
void ( *_scopeInitCallback )( Scope & ); static void (*_connectCallback)(DBClientWithCommands&);
static void ( *_connectCallback )( DBClientWithCommands & ); static const char* (*_checkInterruptCallback)();
static const char * ( *_checkInterruptCallback )(); static unsigned (*_getCurrentOpIdCallback)();
static unsigned ( *_getInterruptSpecCallback )();
}; };
bool hasJSReturn( const string& s ); void installGlobalUtils(Scope& scope);
bool hasJSReturn(const string& s);
const char * jsSkipWhiteSpace( const char * raw ); const char* jsSkipWhiteSpace(const char* raw);
extern ScriptEngine * globalScriptEngine; extern ScriptEngine* globalScriptEngine;
} }
 End of changes. 43 change blocks. 
142 lines changed or deleted 150 lines changed or added


 engine_spidermonkey_internal.h   engine_spidermonkey_internal.h 
skipping to change at line 202 skipping to change at line 202
~SMScope(); ~SMScope();
void reset(); void reset();
void init( const BSONObj * data ); void init( const BSONObj * data );
bool hasOutOfMemoryException(); bool hasOutOfMemoryException();
void externalSetup(); void externalSetup();
/** check if there is a pending killOp request */
bool isKillPending() const;
void localConnect( const char * dbName ); void localConnect( const char * dbName );
// ----- getters ------ // ----- getters ------
double getNumber( const char *field ); double getNumber( const char *field );
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 );
 End of changes. 1 change blocks. 
0 lines changed or deleted 3 lines changed or added


 engine_v8.h   engine_v8.h 
skipping to change at line 25 skipping to change at line 25
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <v8.h> #include <v8.h>
#include <vector> #include <vector>
#include "mongo/scripting/engine.h" #include "mongo/scripting/engine.h"
using namespace v8; #include "mongo/base/disallow_copying.h"
/**
* 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
* and context). Be sure to close the handle_scope if returning a v8::Hand
le!
*/
#define V8_SIMPLE_HEADER
\
v8::Locker v8lock(_isolate); /* acquire isolate lock */
\
v8::Isolate::Scope iscope(_isolate); /* enter the isolate; exit wh
en out of scope */ \
v8::HandleScope handle_scope; /* make the current scope own
local handles */ \
v8::Context::Scope context_scope(_context); /* enter the context; e
xit when out of scope */
namespace mongo { namespace mongo {
class V8ScriptEngine; class V8ScriptEngine;
class V8Scope; class V8Scope;
typedef Handle< Value > (*v8Function) ( V8Scope* scope, const v8::Argum typedef v8::Handle<v8::Value> (*v8Function)(V8Scope* scope, const v8::A
ents& args ); rguments& args);
// Preemption is going to be allowed for the v8 mutex, and some of our
v8
// usage is not preemption safe. So we are using an additional mutex t
hat
// will not be preempted. The V8Lock should be used in place of v8::Lo
cker
// except in certain special cases involving interrupts.
namespace v8Locks {
struct InterruptLock {
InterruptLock();
~InterruptLock();
};
// the implementations are quite simple - objects must be destroyed
in
// reverse of the order created, and should not be shared between t
hreads
struct RecursiveLock {
RecursiveLock();
~RecursiveLock();
bool _unlock;
};
struct RecursiveUnlock {
RecursiveUnlock();
~RecursiveUnlock();
bool _lock;
};
} // namespace v8Locks
class V8Lock {
public:
V8Lock() : _preemptionLock(Isolate::GetCurrent()){}
private:
v8Locks::RecursiveLock _noPreemptionLock;
v8::Locker _preemptionLock;
};
struct V8Unlock {
public:
V8Unlock() : _preemptionUnlock(Isolate::GetCurrent()){}
private:
v8::Unlocker _preemptionUnlock;
v8Locks::RecursiveUnlock _noPreemptionUnlock;
};
class BSONHolder { class BSONHolder {
public: public:
BSONHolder(BSONObj obj) {
BSONHolder( BSONObj obj ) {
_obj = obj.getOwned(); _obj = obj.getOwned();
_modified = false; _modified = false;
v8::V8::AdjustAmountOfExternalAllocatedMemory(_obj.objsize());
} }
~BSONHolder() { ~BSONHolder() {
v8::V8::AdjustAmountOfExternalAllocatedMemory(-_obj.objsize());
} }
BSONObj _obj; BSONObj _obj;
bool _modified; bool _modified;
list<string> _extra; list<string> _extra;
set<string> _removed; set<string> _removed;
}; };
/**
* A V8Scope represents a unit of javascript execution environment; spe
cifically a single
* isolate and a single context executing in a single mongo thread. A
V8Scope can be reused
* in another thread only after reset() has been called.
*
* NB:
* - v8 objects/handles/etc. cannot be shared between V8Scopes
* - in mongod, each scope is associated with an opId (for KillOp sup
port)
* - any public functions that call the v8 API should use a V8_SIMPLE
_HEADER
* - the caller of any public function that returns a v8 type or has
a v8 handle argument
* must enter the isolate, context, and set up the appropriate
handle scope
*/
class V8Scope : public Scope { class V8Scope : public Scope {
public: public:
V8Scope( V8ScriptEngine * engine ); V8Scope(V8ScriptEngine* engine);
~V8Scope(); ~V8Scope();
virtual void init(const BSONObj* data);
/**
* Reset the state of this scope for use by another thread or opera
tion
*/
virtual void reset(); virtual void reset();
virtual void init( const BSONObj * data );
virtual void localConnect( const char * dbName ); /**
* Terminate this scope
*/
virtual void kill();
/** check if there is a pending killOp request */
bool isKillPending() const;
virtual void localConnect(const char* dbName);
virtual void externalSetup(); virtual void externalSetup();
v8::Handle<v8::Value> get( const char * field ); // caller must cre
ate context and handle scopes
virtual double getNumber( const char *field );
virtual int getNumberInt( const char *field );
virtual long long getNumberLongLong( const char *field );
virtual string getString( const char *field );
virtual bool getBoolean( const char *field );
virtual BSONObj getObject( const char *field );
Handle<v8::Object> getGlobalObject() { return _global; };
virtual int type( const char *field );
virtual void setNumber( const char *field , double val );
virtual void setString( const char *field , const char * val );
virtual void setBoolean( const char *field , bool val );
virtual void setElement( const char *field , const BSONElement& e )
;
virtual void setObject( const char *field , const BSONObj& obj , bo
ol readOnly);
virtual void setFunction( const char *field , const char * code );
// virtual void setThis( const BSONObj * obj );
virtual void rename( const char * from , const char * to );
virtual ScriptingFunction _createFunction( const char * code );
Local< v8::Function > __createFunction( const char * code );
virtual int invoke( ScriptingFunction func , const BSONObj* args, c
onst BSONObj* recv, int timeoutMs = 0 , bool ignoreReturn = false, bool rea
dOnlyArgs = false, bool readOnlyRecv = false );
virtual bool exec( const StringData& code , const string& name , bo
ol printResult , bool reportError , bool assertOnError, int timeoutMs );
virtual string getError() { return _error; } virtual string getError() { return _error; }
virtual bool hasOutOfMemoryException();
virtual void injectNative( const char *field, NativeFunction func, virtual bool hasOutOfMemoryException();
void* data = 0 );
void injectNative( const char *field, NativeFunction func, Handle<v
8::Object>& obj, void* data = 0 );
void injectV8Function( const char *field, v8Function func );
void injectV8Function( const char *field, v8Function func, Handle<v
8::Object>& obj );
void injectV8Function( const char *field, v8Function func, Handle<v
8::Template>& t );
Handle<v8::FunctionTemplate> createV8Function( v8Function func );
/**
* Run the garbage collector on this scope (native function). @see
GCV8 for the
* javascript binding version.
*/
void gc(); void gc();
Handle< Context > context() const { return _context; } /**
* get a global property. caller must set up the v8 state.
v8::Local<v8::Object> mongoToV8( const mongo::BSONObj & m , bool ar */
ray = 0 , bool readOnly = false ); v8::Handle<v8::Value> get(const char* field);
v8::Handle<v8::Object> mongoToLZV8( const mongo::BSONObj & m , bool
array = 0 , bool readOnly = false ); virtual double getNumber(const char* field);
mongo::BSONObj v8ToMongo( v8::Handle<v8::Object> o , int depth = 0 virtual int getNumberInt(const char* field);
); virtual long long getNumberLongLong(const char* field);
virtual string getString(const char* field);
// v8 to mongo/BSON conversion functions virtual bool getBoolean(const char* field);
virtual BSONObj getObject(const char* field);
virtual void setNumber(const char* field, double val);
virtual void setString(const char* field, const char* val);
virtual void setBoolean(const char* field, bool val);
virtual void setElement(const char* field, const BSONElement& e);
virtual void setObject(const char* field, const BSONObj& obj, bool
readOnly);
virtual void setFunction(const char* field, const char* code);
virtual int type(const char* field);
virtual void rename(const char* from, const char* to);
virtual int invoke(ScriptingFunction func, const BSONObj* args, con
st BSONObj* recv,
int timeoutMs = 0, bool ignoreReturn = false,
bool readOnlyArgs = false, bool readOnlyRecv = f
alse);
virtual bool exec(const StringData& code, const string& name, bool
printResult,
bool reportError, bool assertOnError, int timeout
Ms);
// functions to create v8 object and function templates
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* data = 0);
void injectV8Function(const char* field, v8Function func);
void injectV8Function(const char* field, v8Function func, v8::Handl
e<v8::Object>& obj);
void injectV8Function(const char* field, v8Function func, v8::Handl
e<v8::Template>& t);
v8::Handle<v8::FunctionTemplate> createV8Function(v8Function func);
virtual ScriptingFunction _createFunction(const char* code);
v8::Local<v8::Function> __createFunction(const char* code);
/**
* Convert BSON types to v8 Javascript types
*/
v8::Local<v8::Object> mongoToV8(const mongo::BSONObj& m, bool array
= 0,
bool readOnly = 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);
/**
* Convert v8 Javascript types to BSON types
*/
mongo::BSONObj v8ToMongo(v8::Handle<v8::Object> obj, int depth = 0)
;
void v8ToMongoElement(BSONObjBuilder& b, void v8ToMongoElement(BSONObjBuilder& b,
const string& sname, const string& 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 string& sname, const string& sname,
v8::Handle<v8::Value> value, v8::Handle<v8::Value> value,
int depth, int depth,
BSONObj* originalParent); BSONObj* originalParent);
skipping to change at line 183 skipping to change at line 194
void v8ToMongoDBRef(BSONObjBuilder& b, void v8ToMongoDBRef(BSONObjBuilder& b,
const string& elementName, const string& elementName,
v8::Handle<v8::Object> obj); v8::Handle<v8::Object> obj);
void v8ToMongoBinData(BSONObjBuilder& b, void v8ToMongoBinData(BSONObjBuilder& b,
const string& elementName, const string& elementName,
v8::Handle<v8::Object> obj); v8::Handle<v8::Object> obj);
void v8ToMongoObjectID(BSONObjBuilder& b, void v8ToMongoObjectID(BSONObjBuilder& b,
const string& elementName, const string& elementName,
v8::Handle<v8::Object> obj); v8::Handle<v8::Object> obj);
v8::Handle<v8::Value> mongoToV8Element( const BSONElement &f, bool v8::Function* getNamedCons(const char* name);
readOnly = false );
virtual void append( BSONObjBuilder & builder , const char * fieldN
ame , const char * scopeName );
v8::Function * getNamedCons( const char * name ); v8::Function* getObjectIdCons();
v8::Function * getObjectIdCons();
Local< v8::Value > newId( const OID &id );
Persistent<v8::Object> wrapBSONObject(Local<v8::Object> obj, BSONHo v8::Local<v8::Value> newId(const OID& id);
lder* data);
Persistent<v8::Object> wrapArrayObject(Local<v8::Object> obj, char*
data);
/**
* GC callback for weak references to BSON objects (via BSONHolder)
*/
v8::Persistent<v8::Object> wrapBSONObject(v8::Local<v8::Object> obj
, BSONHolder* data);
v8::Persistent<v8::Object> wrapArrayObject(v8::Local<v8::Object> ob
j, char* data);
/**
* Get a V8 string from the scope's cache, creating one if needed (
NOTE: this may be
* dangerous due to use in multiple threads without changing the v8
Locker)
*/
v8::Handle<v8::String> getV8Str(string str); v8::Handle<v8::String> getV8Str(string str);
// inline v8::Handle<v8::String> getV8Str(string str) { return v8::S
tring::New(str.c_str()); }
inline v8::Handle<v8::String> getLocalV8Str(string str) { return v8
::String::New(str.c_str()); }
/**
* Create a V8 string with a local handle
*/
inline v8::Handle<v8::String> getLocalV8Str(string str) {
return v8::String::New(str.c_str());
}
/**
* 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.
*/
v8::Isolate* getIsolate() { return _isolate; } v8::Isolate* getIsolate() { return _isolate; }
Persistent<Context> getContext() { return _context; }
// call with v8 mutex: /**
void enableV8Interrupt(); * Get the JS context this scope executes within.
void disableV8Interrupt(); */
bool pauseV8Interrupt(); v8::Persistent<v8::Context> getContext() { return _context; }
bool resumeV8Interrupt();
/**
Handle<v8::String> V8STR_CONN; * Static v8 strings for various identifiers
Handle<v8::String> V8STR_ID; */
Handle<v8::String> V8STR_LENGTH; v8::Handle<v8::String> V8STR_CONN;
Handle<v8::String> V8STR_LEN; v8::Handle<v8::String> V8STR_ID;
Handle<v8::String> V8STR_TYPE; v8::Handle<v8::String> V8STR_LENGTH;
Handle<v8::String> V8STR_ISOBJECTID; v8::Handle<v8::String> V8STR_LEN;
Handle<v8::String> V8STR_NATIVE_FUNC; v8::Handle<v8::String> V8STR_TYPE;
Handle<v8::String> V8STR_NATIVE_DATA; v8::Handle<v8::String> V8STR_ISOBJECTID;
Handle<v8::String> V8STR_V8_FUNC; v8::Handle<v8::String> V8STR_NATIVE_FUNC;
Handle<v8::String> V8STR_RETURN; v8::Handle<v8::String> V8STR_NATIVE_DATA;
Handle<v8::String> V8STR_ARGS; v8::Handle<v8::String> V8STR_V8_FUNC;
Handle<v8::String> V8STR_T; v8::Handle<v8::String> V8STR_RETURN;
Handle<v8::String> V8STR_I; v8::Handle<v8::String> V8STR_ARGS;
Handle<v8::String> V8STR_EMPTY; v8::Handle<v8::String> V8STR_T;
Handle<v8::String> V8STR_MINKEY; v8::Handle<v8::String> V8STR_I;
Handle<v8::String> V8STR_MAXKEY; v8::Handle<v8::String> V8STR_EMPTY;
Handle<v8::String> V8STR_NUMBERLONG; v8::Handle<v8::String> V8STR_MINKEY;
Handle<v8::String> V8STR_NUMBERINT; v8::Handle<v8::String> V8STR_MAXKEY;
Handle<v8::String> V8STR_DBPTR; v8::Handle<v8::String> V8STR_NUMBERLONG;
Handle<v8::String> V8STR_BINDATA; v8::Handle<v8::String> V8STR_NUMBERINT;
Handle<v8::String> V8STR_WRAPPER; v8::Handle<v8::String> V8STR_DBPTR;
Handle<v8::String> V8STR_RO; v8::Handle<v8::String> V8STR_BINDATA;
Handle<v8::String> V8STR_FULLNAME; v8::Handle<v8::String> V8STR_WRAPPER;
Handle<v8::String> V8STR_BSON; v8::Handle<v8::String> V8STR_RO;
v8::Handle<v8::String> V8STR_FULLNAME;
v8::Handle<v8::String> V8STR_BSON;
private: private:
void _startCall();
static Handle< Value > nativeCallback( V8Scope* scope, const Argume
nts &args );
static v8::Handle< v8::Value > v8Callback( const v8::Arguments &arg
s );
static Handle< Value > load( V8Scope* scope, const Arguments &args
);
static Handle< Value > Print(V8Scope* scope, const v8::Arguments& a
rgs);
static Handle< Value > Version(V8Scope* scope, const v8::Arguments&
args);
static Handle< Value > GCV8(V8Scope* scope, const v8::Arguments& ar
gs);
V8ScriptEngine * _engine; /**
* Trampoline to call a c++ function with a specific signature (V8S
cope*, v8::Arguments&).
* Handles interruption, exceptions, etc.
*/
static v8::Handle<v8::Value> v8Callback(const v8::Arguments& args);
/**
* Interpreter agnostic 'Native Callback' trampoline. Note this is
only called
* from v8Callback().
*/
static v8::Handle<v8::Value> nativeCallback(V8Scope* scope, const v
8::Arguments& args);
/**
* v8-specific implementations of basic global functions
*/
static v8::Handle<v8::Value> load(V8Scope* scope, const v8::Argumen
ts& args);
static v8::Handle<v8::Value> Print(V8Scope* scope, const v8::Argume
nts& args);
static v8::Handle<v8::Value> Version(V8Scope* scope, const v8::Argu
ments& args);
static v8::Handle<v8::Value> GCV8(V8Scope* scope, const v8::Argumen
ts& args);
/** Signal that this scope has entered a native (C++) execution con
text.
* @return false if execution has been interrupted
*/
bool nativePrologue();
/** Signal that this scope has completed native execution and is re
turning to v8.
* @return false if execution has been interrupted
*/
bool nativeEpilogue();
/**
* Register this scope with the mongo op id. If executing outside
the
* context of a mongo operation (e.g. from the shell), killOp will
not
* be supported.
*/
void registerOpId();
/**
* Unregister this scope with the mongo op id.
*/
void unregisterOpId();
/**
* Create a new function; primarily used for BSON/V8 conversion.
*/
v8::Local<v8::Value> newFunction(const char *code);
Persistent<Context> _context; V8ScriptEngine* _engine;
Persistent<v8::Object> _global;
v8::Persistent<v8::Context> _context;
v8::Persistent<v8::Object> _global;
string _error; string _error;
vector< Persistent<Value> > _funcs; vector<v8::Persistent<v8::Value> > _funcs;
v8::Persistent<v8::Object> _emptyObj;
v8::Persistent<v8::Function> _wrapper; enum ConnectState { NOT, LOCAL, EXTERNAL };
enum ConnectState { NOT , LOCAL , EXTERNAL };
ConnectState _connectState; ConnectState _connectState;
std::map <string, v8::Persistent <v8::String> > _strCache; std::map <string, v8::Persistent<v8::String> > _strCache;
v8::Persistent<v8::FunctionTemplate> lzFunctionTemplate;
v8::Persistent<v8::ObjectTemplate> lzObjectTemplate;
v8::Persistent<v8::ObjectTemplate> roObjectTemplate;
v8::Persistent<v8::ObjectTemplate> lzArrayTemplate;
v8::Persistent<v8::ObjectTemplate> internalFieldObjects;
Persistent<v8::FunctionTemplate> lzFunctionTemplate;
Persistent<v8::ObjectTemplate> lzObjectTemplate;
Persistent<v8::ObjectTemplate> roObjectTemplate;
Persistent<v8::ObjectTemplate> lzArrayTemplate;
Persistent<v8::ObjectTemplate> internalFieldObjects;
v8::Isolate* _isolate; v8::Isolate* _isolate;
mongo::mutex _interruptLock; // protects interruption-related flags
bool _inNativeExecution; // protected by _interruptLock
bool _pendingKill; // protected by _interruptLock
int _opId; // op id for this scope
}; };
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; }
virtual void interrupt( unsigned opSpec ); /**
* Interrupt a single active v8 execution context
* NB: To interrupt a context, we must acquire the following locks
(in order):
* - mutex to protect the the map of all scopes (_globalInter
ruptLock)
* - mutex to protect the scope that's being interrupted (_in
terruptLock)
* The scope will be removed from the map upon destruction, and the
op id
* will be updated if the scope is ever reused from a pool.
*/
virtual void interrupt(unsigned opId);
/**
* Interrupt all v8 contexts (and isolates). @see interrupt().
*/
virtual void interruptAll(); virtual void interruptAll();
private: private:
friend class V8Scope; friend class V8Scope;
};
class ExternalString : public v8::String::ExternalAsciiStringResource {
public:
ExternalString(std::string str) : _data(str) {
}
~ExternalString() { std::string printKnownOps_inlock();
}
const char* data () const { return _data.c_str(); } typedef map<unsigned, V8Scope*> OpIdToScopeMap;
size_t length () const { return _data.length(); } mongo::mutex _globalInterruptLock; // protects map of all operatio
private: n ids -> scope
// string _str; OpIdToScopeMap _opToScopeMap; // map of mongo op ids to scope
// const char* _data; s (protected by
std::string _data; // _globalInterruptLock).
// size_t _len;
}; };
extern ScriptEngine * globalScriptEngine; extern ScriptEngine* globalScriptEngine;
} }
 End of changes. 42 change blocks. 
205 lines changed or deleted 292 lines changed or added


 error_codes.h   error_codes.h 
// AUTO-GENERATED FILE DO NOT EDIT // AUTO-GENERATED FILE DO NOT EDIT
// See src/mongo/base/generate_error_codes.py // See src/mongo/base/generate_error_codes.py
/* Copyright 2012 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.
*/
#pragma once #pragma once
#include "mongo/base/string_data.h" #include "mongo/base/string_data.h"
namespace mongo { namespace mongo {
/** /**
* This is a generated class containing a table of error codes and thei r corresponding error * This is a generated class containing a table of error codes and thei r corresponding error
* strings. The class is derived from the definitions in src/mongo/base /error_codes.err file. * strings. The class is derived from the definitions in src/mongo/base /error_codes.err file.
skipping to change at line 42 skipping to change at line 56
UnsupportedFormat = 12, UnsupportedFormat = 12,
Unauthorized = 13, Unauthorized = 13,
TypeMismatch = 14, TypeMismatch = 14,
Overflow = 15, Overflow = 15,
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,
AlreadyInitialized = 23,
LockTimeout = 24,
RemoteValidationError = 25,
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. 2 change blocks. 
0 lines changed or deleted 19 lines changed or added


 expression.h   expression.h 
skipping to change at line 409 skipping to change at line 409
static intrusive_ptr<ExpressionNary> createLt(); static intrusive_ptr<ExpressionNary> createLt();
static intrusive_ptr<ExpressionNary> createLte(); static intrusive_ptr<ExpressionNary> createLte();
private: private:
friend class ExpressionFieldRange; friend class ExpressionFieldRange;
ExpressionCompare(CmpOp cmpOp); ExpressionCompare(CmpOp cmpOp);
CmpOp cmpOp; CmpOp cmpOp;
}; };
class ExpressionCond : class ExpressionConcat : public ExpressionNary {
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: public:
// virtuals from ExpressionNary // virtuals from ExpressionNary
virtual ~ExpressionCond(); virtual ~ExpressionCond();
virtual Value evaluate(const Document& pDocument) const; virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const; virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio n); virtual void addOperand(const intrusive_ptr<Expression> &pExpressio n);
static intrusive_ptr<ExpressionNary> create(); static intrusive_ptr<ExpressionNary> create();
private: private:
skipping to change at line 573 skipping to change at line 582
/* /*
Internal implementation of evaluate(), used recursively. Internal implementation of evaluate(), used recursively.
The internal implementation doesn't just use a loop because of The internal implementation doesn't just use a loop because of
the possibility that we need to skip over an array. If the path 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 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 traverse "b.c" for each element of a:[...]. This requires that
a be an array of objects in order to navigate more deeply. a be an array of objects in order to navigate more deeply.
@param index current path field index to extract @param index current path field index to extract
@param pathLength maximum number of fields on field path @param input current document traversed to (not the top-level one
@param pDocument current document traversed to (not the top-level )
one)
@returns the field found; could be an array @returns the field found; could be an array
*/ */
Value evaluatePath( Value evaluatePath(size_t index, const Document& input) const;
size_t index, const size_t pathLength,
Document pDocument) const; // Helper for evaluatePath to handle Array case
Value evaluatePathArray(size_t index, const Value& input) const;
FieldPath fieldPath; FieldPath fieldPath;
}; };
class ExpressionFieldRange : class ExpressionFieldRange :
public Expression { public Expression {
public: public:
// virtuals from expression // virtuals from expression
virtual ~ExpressionFieldRange(); virtual ~ExpressionFieldRange();
virtual intrusive_ptr<Expression> optimize(); virtual intrusive_ptr<Expression> optimize();
skipping to change at line 705 skipping to change at line 714
virtual Value evaluate(const Document& pDocument) const; virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const; virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio n); virtual void addOperand(const intrusive_ptr<Expression> &pExpressio n);
static intrusive_ptr<ExpressionNary> create(); static intrusive_ptr<ExpressionNary> create();
private: private:
ExpressionIfNull(); 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 : class ExpressionMinute :
public ExpressionNary { public ExpressionNary {
public: public:
// virtuals from ExpressionNary // virtuals from ExpressionNary
virtual ~ExpressionMinute(); virtual ~ExpressionMinute();
virtual Value evaluate(const Document& pDocument) const; virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const; virtual const char *getOpName() const;
virtual void addOperand(const intrusive_ptr<Expression> &pExpressio n); virtual void addOperand(const intrusive_ptr<Expression> &pExpressio n);
static intrusive_ptr<ExpressionNary> create(); static intrusive_ptr<ExpressionNary> create();
skipping to change at line 904 skipping to change at line 928
// mapping from fieldname to Expression to generate the value // mapping from fieldname to Expression to generate the value
// NULL expression means include from source document // NULL expression means include from source document
typedef map<string, intrusive_ptr<Expression> > ExpressionMap; typedef map<string, intrusive_ptr<Expression> > ExpressionMap;
ExpressionMap _expressions; ExpressionMap _expressions;
// this is used to maintain order for generated fields not in the s ource document // this is used to maintain order for generated fields not in the s ource document
vector<string> _order; vector<string> _order;
bool _excludeId; bool _excludeId;
/*
Utility object for collecting emitPaths() results in a BSON
object.
*/
class BuilderPathSink :
public PathSink {
public:
// virtuals from PathSink
virtual void path(const string &path, bool include);
/*
Create a PathSink that writes paths to a BSONObjBuilder,
to create an object in the form of { path:is_included,...}
This object uses a builder pointer that won't guarantee the
lifetime of the builder, so make sure it outlasts the use of
this for an emitPaths() call.
@param pBuilder to the builder to write paths to
*/
BuilderPathSink(BSONObjBuilder *pBuilder);
private:
BSONObjBuilder *pBuilder;
};
/* utility class used by emitPaths() */
class PathPusher :
boost::noncopyable {
public:
PathPusher(vector<string> *pvPath, const string &s);
~PathPusher();
private:
vector<string> *pvPath;
};
}; };
class ExpressionOr : class ExpressionOr :
public ExpressionNary { public ExpressionNary {
public: public:
// virtuals from Expression // virtuals from Expression
virtual ~ExpressionOr(); virtual ~ExpressionOr();
virtual intrusive_ptr<Expression> optimize(); virtual intrusive_ptr<Expression> optimize();
virtual Value evaluate(const Document& pDocument) const; virtual Value evaluate(const Document& pDocument) const;
virtual const char *getOpName() const; virtual const char *getOpName() const;
skipping to change at line 1120 skipping to change at line 1107
} }
inline void ExpressionFieldPath::writeFieldPath( inline void ExpressionFieldPath::writeFieldPath(
ostream &outStream, bool fieldPrefix) const { ostream &outStream, bool fieldPrefix) const {
return fieldPath.writePath(outStream, fieldPrefix); return fieldPath.writePath(outStream, fieldPrefix);
} }
inline size_t ExpressionObject::getFieldCount() const { inline size_t ExpressionObject::getFieldCount() const {
return _expressions.size(); return _expressions.size();
} }
inline ExpressionObject::BuilderPathSink::BuilderPathSink(
BSONObjBuilder *pB):
pBuilder(pB) {
}
inline ExpressionObject::PathPusher::PathPusher(
vector<string> *pTheVPath, const string &s):
pvPath(pTheVPath) {
pvPath->push_back(s);
}
inline ExpressionObject::PathPusher::~PathPusher() {
pvPath->pop_back();
}
} }
 End of changes. 6 change blocks. 
61 lines changed or deleted 33 lines changed or added


 fail_point.h   fail_point.h 
skipping to change at line 88 skipping to change at line 88
} }
/** /**
* Checks whether fail point is active and increments the reference counter without * Checks whether fail point is active and increments the reference counter without
* decrementing it. Must call shouldFailCloseBlock afterwards when the return value * decrementing it. Must call shouldFailCloseBlock afterwards when the return value
* is not fastOff. Otherwise, this will remain read-only forever. * is not fastOff. Otherwise, this will remain read-only forever.
* *
* @return slowOn if fail point is active. * @return slowOn if fail point is active.
*/ */
inline RetCode shouldFailOpenBlock() { inline RetCode shouldFailOpenBlock() {
// TODO: optimization - use unordered load once available if (MONGO_likely((_fpInfo.loadRelaxed() & ACTIVE_BIT) == 0)) {
if (MONGO_likely((_fpInfo.load() & ACTIVE_BIT) == 0)) {
return fastOff; return fastOff;
} }
return slowShouldFailOpenBlock(); return slowShouldFailOpenBlock();
} }
/** /**
* Decrements the reference counter. * Decrements the reference counter.
* @see #shouldFailOpenBlock * @see #shouldFailOpenBlock
*/ */
 End of changes. 1 change blocks. 
2 lines changed or deleted 1 lines changed or added


 field_parser.h   field_parser.h 
skipping to change at line 44 skipping to change at line 44
* *
* NOTE ON BSON OWNERSHIP: * NOTE ON BSON OWNERSHIP:
* *
* The caller must assume that this class will point to data insi de 'doc' without * The caller must assume that this class will point to data insi de 'doc' without
* copying it. In practice this means that 'doc' MUST EXIST for a s long as 'out' * copying it. In practice this means that 'doc' MUST EXIST for a s long as 'out'
* stays in scope. * stays in scope.
*/ */
static bool extract(BSONObj doc, static bool extract(BSONObj doc,
const BSONField<bool>& field, const BSONField<bool>& field,
bool def, bool def,
bool* out); bool* out,
string* errMsg = NULL);
static bool extract(BSONObj doc, static bool extract(BSONObj doc,
const BSONField<BSONArray>& field, const BSONField<BSONArray>& field,
const BSONArray& def, const BSONArray& def,
BSONArray* out); BSONArray* out,
string* errMsg = NULL);
static bool extract(BSONObj doc, static bool extract(BSONObj doc,
const BSONField<BSONObj>& field, const BSONField<BSONObj>& field,
const BSONObj& def, const BSONObj& def,
BSONObj* out); BSONObj* out,
string* errMsg = NULL);
static bool extract(BSONObj doc, static bool extract(BSONObj doc,
const BSONField<Date_t>& field, const BSONField<Date_t>& field,
const Date_t def, const Date_t def,
Date_t* out); Date_t* out,
string* errMsg = NULL);
static bool extract(BSONObj doc, static bool extract(BSONObj doc,
const BSONField<string>& field, const BSONField<string>& field,
const string& def, const string& def,
string* out); string* out,
string* errMsg = NULL);
static bool extract(BSONObj doc, static bool extract(BSONObj doc,
const BSONField<OID>& field, const BSONField<OID>& field,
const OID& def, const OID& def,
OID* out); OID* out,
string* errMsg = NULL);
static bool extract(BSONObj doc,
const BSONField<int>& field,
const int& def,
int* out,
string* errMsg = NULL);
static bool extract(BSONObj doc, static bool extract(BSONObj doc,
const BSONField<long long>& field, const BSONField<long long>& field,
const long long& def, const long long& def,
long long* out); long long* out,
string* errMsg = NULL);
/**
* The following extractNumber methods do implicit conversion betwe
en any numeric type and
* the BSONField type. This can be useful when an exact numeric ty
pe is not needed, for
* example if the field is sometimes modified from the shell which
can change the type.
*/
static bool extractNumber(BSONObj doc,
const BSONField<int>& field,
const int& def,
int* out,
string* errMsg = NULL);
static bool extractNumber(BSONObj doc,
const BSONField<long long>& field,
const long long& def,
long long* out,
string* errMsg = NULL);
/**
* The following extract methods are templatized to handle extracti
on of vectors and
* maps of sub-objects. Keys in the map should be StringData compa
tible.
*
* It's possible to nest extraction of vectors and maps to any dept
h, i.e:
*
* vector<map<string,vector<string> > > val;
* FieldParser::extract(doc, field, val, &val);
*/
template<typename T>
static bool extract(BSONObj doc,
const BSONField<vector<T> >& field,
const vector<T>& def,
vector<T>* out,
string* errMsg = NULL);
template<typename K, typename T>
static bool extract(BSONObj doc,
const BSONField<map<K, T> >& field,
const map<K, T>& def,
map<K, T>* out,
string* errMsg = NULL);
}; };
} // namespace mongo } // namespace mongo
// Inline functions for templating
#include "field_parser-inl.h"
 End of changes. 8 change blocks. 
7 lines changed or deleted 66 lines changed or added


 field_path.h   field_path.h 
skipping to change at line 49 skipping to change at line 49
@returns the number of path elements @returns the number of path elements
*/ */
size_t getPathLength() const; size_t getPathLength() const;
/** /**
Get a particular path element from the path. Get a particular path element from the path.
@param i the zero based index of the path element. @param i the zero based index of the path element.
@returns the path element @returns the path element
*/ */
string getFieldName(size_t i) const; const string& getFieldName(size_t i) const;
/** /**
Get the full path. Get the full path.
@param fieldPrefix whether or not to include the field prefix @param fieldPrefix whether or not to include the field prefix
@returns the complete field path @returns the complete field path
*/ */
string getPath(bool fieldPrefix) const; string getPath(bool fieldPrefix) const;
/** /**
skipping to change at line 104 skipping to change at line 104
} }
/* ======================= INLINED IMPLEMENTATIONS ======================== == */ /* ======================= INLINED IMPLEMENTATIONS ======================== == */
namespace mongo { namespace mongo {
inline size_t FieldPath::getPathLength() const { inline size_t FieldPath::getPathLength() const {
return vFieldName.size(); return vFieldName.size();
} }
inline string FieldPath::getFieldName(size_t i) const { inline const string& FieldPath::getFieldName(size_t i) const {
verify(i < getPathLength()); dassert(i < getPathLength());
return vFieldName[i]; return vFieldName[i];
} }
inline const char *FieldPath::getPrefix() { inline const char *FieldPath::getPrefix() {
return prefix; return prefix;
} }
} }
 End of changes. 2 change blocks. 
3 lines changed or deleted 3 lines changed or added


 file.h   file.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
#if !defined(_WIN32) #include <boost/cstdint.hpp>
#include "errno.h" #include <string>
#include <sys/mman.h>
#include <sys/types.h> #include "mongo/platform/basic.h"
#include <sys/stat.h> #include "mongo/platform/cstdint.h"
#include <fcntl.h>
#include <sys/statvfs.h>
#endif
#include "text.h"
namespace mongo { namespace mongo {
#ifndef __sunos__
typedef uint64_t fileofs; typedef uint64_t fileofs;
#else
typedef boost::uint64_t fileofs;
#endif
/* NOTE: not thread-safe. (at least the windows implementation isn't. * / // NOTE: not thread-safe. (at least the windows implementation isn't)
class FileInterface { class File {
public:
void open(const char *fn) {}
void write(fileofs o, const char *data, unsigned len) {}
void read(fileofs o, char *data, unsigned len) {}
bool bad() {return false;}
bool is_open() {return false;}
fileofs len() { return 0; }
void fsync() { verify(false); }
// shrink file to size bytes. No-op if file already smaller.
void truncate(fileofs size);
/** @return -1 if error or unavailable */
static boost::intmax_t freeSpace(const string &path) { verify(false
); return -1; }
};
#if defined(_WIN32)
#include <io.h>
class File : public FileInterface {
HANDLE fd;
bool _bad;
string _name;
void err(BOOL b=false) { /* false = error happened */
if( !b && !_bad ) {
_bad = true;
log() << "File " << _name << "I/O error " << GetLastError()
<< endl;
}
}
public: public:
File() { File();
fd = INVALID_HANDLE_VALUE; ~File();
_bad = true;
}
~File() {
if( is_open() ) CloseHandle(fd);
fd = INVALID_HANDLE_VALUE;
}
void open(const char *filename, bool readOnly=false , bool direct=f
alse) {
_name = filename;
fd = CreateFile(
toNativeString(filename).c_str(),
( readOnly ? 0 : GENERIC_WRITE ) | GENERIC_READ, FILE_
SHARE_WRITE|FILE_SHARE_READ,
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if( !is_open() ) {
DWORD e = GetLastError();
log() << "Create/Open File failed " << filename << ' ' << e
rrnoWithDescription(e) << endl;
}
else
_bad = false;
}
static boost::intmax_t freeSpace(const string &path) {
ULARGE_INTEGER avail;
if( GetDiskFreeSpaceEx(toNativeString(path.c_str()).c_str(), &a
vail, NULL, NULL) ) {
return avail.QuadPart;
}
DWORD e = GetLastError();
log() << "GetDiskFreeSpaceEx fails errno: " << e << endl;
return -1;
}
void write(fileofs o, const char *data, unsigned len) {
LARGE_INTEGER li;
li.QuadPart = o;
SetFilePointerEx(fd, li, NULL, FILE_BEGIN);
DWORD written;
err( WriteFile(fd, data, len, &written, NULL) );
}
void read(fileofs o, char *data, unsigned len) {
DWORD read;
LARGE_INTEGER li;
li.QuadPart = o;
SetFilePointerEx(fd, li, NULL, FILE_BEGIN);
int ok = ReadFile(fd, data, len, &read, 0);
if( !ok )
err(ok);
else
massert( 10438 , "ReadFile error - truncated file?", read =
= len);
}
bool bad() { return _bad; }
bool is_open() { return fd != INVALID_HANDLE_VALUE; }
fileofs len() {
LARGE_INTEGER li;
li.LowPart = GetFileSize(fd, (DWORD *) &li.HighPart);
if( li.HighPart == 0 && li.LowPart == INVALID_FILE_SIZE ) {
err( false );
return 0;
}
return li.QuadPart;
}
void fsync() { FlushFileBuffers(fd); }
void truncate(fileofs size) {
if (len() <= size)
return;
LARGE_INTEGER li;
li.QuadPart = size;
if (SetFilePointerEx(fd, li, NULL, FILE_BEGIN) == 0){
err(false);
return; //couldn't seek
}
err(SetEndOfFile(fd)); bool bad() const { return _bad; }
} void fsync() const;
}; bool is_open() const;
fileofs len();
void open(const char* filename, bool readOnly = false, bool direct
= false);
void read(fileofs o, char* data, unsigned len);
void truncate(fileofs size);
void write(fileofs o, const char* data, unsigned len);
#else static boost::intmax_t freeSpace(const std::string& path);
class File : public FileInterface {
public:
int fd;
private: private:
bool _bad; bool _bad;
void err(bool ok) { #ifdef _WIN32
if( !ok && !_bad ) { HANDLE _handle;
_bad = true; #else
log() << "File I/O " << errnoWithDescription() << endl; int _fd;
}
}
public:
File() {
fd = -1;
_bad = true;
}
~File() {
if( is_open() ) ::close(fd);
fd = -1;
}
#ifndef O_NOATIME
#define O_NOATIME 0
#endif
void open(const char *filename, bool readOnly=false , bool direct=f
alse) {
fd = ::open(filename,
O_CREAT | ( readOnly ? 0 : ( O_RDWR | O_NOATIME ) )
#if defined(O_DIRECT)
| ( direct ? O_DIRECT : 0 )
#endif #endif
, std::string _name;
S_IRUSR | S_IWUSR);
if ( fd <= 0 ) {
out() << "couldn't open " << filename << ' ' << errnoWithDe
scription() << endl;
return;
}
_bad = false;
}
void write(fileofs o, const char *data, unsigned len) {
err( ::pwrite(fd, data, len, o) == (int) len );
}
void read(fileofs o, char *data, unsigned len) {
ssize_t s = ::pread(fd, data, len, o);
if( s == -1 ) {
err(false);
}
else if( s != (int) len ) {
_bad = true;
log() << "File error read:" << s << " bytes, wanted:" << le
n << " ofs:" << o << endl;
}
}
bool bad() { return _bad; }
bool is_open() { return fd > 0; }
fileofs len() {
off_t o = lseek(fd, 0, SEEK_END);
if( o != (off_t) -1 )
return o;
err(false);
return 0;
}
void fsync() { ::fsync(fd); }
static boost::intmax_t freeSpace ( const string &path ) {
struct statvfs info;
verify( !statvfs( path.c_str() , &info ) );
return boost::intmax_t( info.f_bavail ) * info.f_frsize;
}
void truncate(fileofs size) {
if (len() <= size)
return;
err(ftruncate(fd, size) == 0);
}
}; };
#endif
} }
 End of changes. 14 change blocks. 
200 lines changed or deleted 24 lines changed or added


 gsasl_session.h   gsasl_session.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 <gsasl.h>
#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/base/string_data.h" #include "mongo/base/string_data.h"
#include "mongo/platform/cstdint.h" // Must be included at all because of
SERVER-8086.
#include <gsasl.h> // Must be included here because of SERVER-8086.
namespace mongo { namespace mongo {
/** /**
* C++ wrapper around Gsasl_session. * C++ wrapper around Gsasl_session.
*/ */
class GsaslSession { class GsaslSession {
MONGO_DISALLOW_COPYING(GsaslSession); MONGO_DISALLOW_COPYING(GsaslSession);
public: public:
GsaslSession(); GsaslSession();
 End of changes. 2 change blocks. 
1 lines changed or deleted 4 lines changed or added


 hashindex.h   hashindex.h 
skipping to change at line 77 skipping to change at line 77
* hashed field. Otherwise it's considered USELESS. * hashed field. Otherwise it's considered USELESS.
* Example queries (supposing the indexKey is {a : "hashed"}): * Example queries (supposing the indexKey is {a : "hashed"}):
* {a : 3} HELPFUL * {a : 3} HELPFUL
* {a : 3 , b : 3} HELPFUL * {a : 3 , b : 3} HELPFUL
* {a : {$in : [3,4]}} HELPFUL * {a : {$in : [3,4]}} HELPFUL
* {a : {$gte : 3, $lte : 3}} HELPFUL * {a : {$gte : 3, $lte : 3}} HELPFUL
* {} USELESS * {} USELESS
* {b : 3} USELESS * {b : 3} USELESS
* {a : {$gt : 3}} USELESS * {a : {$gt : 3}} USELESS
*/ */
IndexSuitability suitability( const BSONObj& query , const BSONObj& IndexSuitability suitability( const FieldRangeSet& queryConstraints
order ) const; ,
const BSONObj& order ) const;
/* The input is "obj" which should have a field corresponding to th e hashedfield. /* The input is "obj" which should have a field corresponding to th e hashedfield.
* The output is a BSONObj with a single BSONElement whose value is the hash * The output is a BSONObj with a single BSONElement whose value is the hash
* Eg if this is an index on "a" we have * Eg if this is an index on "a" we have
* obj is {a : 45} --> key becomes {"" : hash(45) } * obj is {a : 45} --> key becomes {"" : hash(45) }
* *
* Limitation: arrays values are not currently supported. This fun ction uasserts * Limitation: arrays values are not currently supported. This fun ction uasserts
* that the value is not an array, and errors out in that case. * that the value is not an array, and errors out in that case.
*/ */
void getKeys( const BSONObj &obj, BSONObjSet &keys ) const; void getKeys( const BSONObj &obj, BSONObjSet &keys ) const;
 End of changes. 1 change blocks. 
2 lines changed or deleted 3 lines changed or added


 health.h   health.h 
skipping to change at line 21 skipping to change at line 21
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/db/jsobj.h"
namespace mongo { namespace mongo {
/* throws */ /* throws */
bool requestHeartbeat(const std::string& setname, bool requestHeartbeat(const std::string& setname,
const std::string& fromHost, const std::string& fromHost,
const std::string& memberFullName, const std::string& memberFullName,
BSONObj& result, BSONObj& result,
int myConfigVersion, int myConfigVersion,
int& theirConfigVersion, int& theirConfigVersion,
bool checkEmpty = false); bool checkEmpty = false);
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 hex.h   hex.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 <string> #include <string>
#include "mongo/base/string_data.h"
#include "mongo/bson/util/builder.h" #include "mongo/bson/util/builder.h"
namespace mongo { namespace mongo {
//can't use hex namespace because it conflicts with hex iostream functi on //can't use hex namespace because it conflicts with hex iostream functi on
inline int fromHex( char c ) { inline int fromHex( char c ) {
if ( '0' <= c && c <= '9' ) if ( '0' <= c && c <= '9' )
return c - '0'; return c - '0';
if ( 'a' <= c && c <= 'f' ) if ( 'a' <= c && c <= 'f' )
return c - 'a' + 10; return c - 'a' + 10;
if ( 'A' <= c && c <= 'F' ) if ( 'A' <= c && c <= 'F' )
return c - 'A' + 10; return c - 'A' + 10;
verify( false ); verify( false );
return 0xff; return 0xff;
} }
inline char fromHex( const char *c ) { inline char fromHex( const char *c ) {
return (char)(( fromHex( c[ 0 ] ) << 4 ) | fromHex( c[ 1 ] )); return (char)(( fromHex( c[ 0 ] ) << 4 ) | fromHex( c[ 1 ] ));
} }
inline char fromHex( const StringData& c ) {
return (char)(( fromHex( c[ 0 ] ) << 4 ) | fromHex( c[ 1 ] ));
}
inline std::string toHex(const void* inRaw, int len) { inline std::string toHex(const void* inRaw, int len) {
static const char hexchars[] = "0123456789ABCDEF"; static const char hexchars[] = "0123456789ABCDEF";
StringBuilder out; StringBuilder out;
const char* in = reinterpret_cast<const char*>(inRaw); const char* in = reinterpret_cast<const char*>(inRaw);
for (int i=0; i<len; ++i) { for (int i=0; i<len; ++i) {
char c = in[i]; char c = in[i];
char hi = hexchars[(c & 0xF0) >> 4]; char hi = hexchars[(c & 0xF0) >> 4];
char lo = hexchars[(c & 0x0F)]; char lo = hexchars[(c & 0x0F)];
 End of changes. 2 change blocks. 
0 lines changed or deleted 4 lines changed or added


 index_rebuilder.h   index_rebuilder.h 
skipping to change at line 39 skipping to change at line 39
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); void checkDB(const std::string& dbname);
/** /**
* Actually retry the 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 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
*/ */
void retryIndexBuild(const std::string& dbName, NamespaceDetails* n sd); void retryIndexBuild(const std::string& dbName, NamespaceDetails* n sd, const int index);
}; };
extern IndexRebuilder indexRebuilder; extern IndexRebuilder indexRebuilder;
} }
 End of changes. 2 change blocks. 
2 lines changed or deleted 8 lines changed or added


 index_update.h   index_update.h 
skipping to change at line 37 skipping to change at line 37
// unindex all keys in index for this record. // unindex all keys in index for this record.
void unindexRecord(NamespaceDetails *d, Record *todelete, const DiskLoc & dl, bool noWarn = false); void unindexRecord(NamespaceDetails *d, Record *todelete, const DiskLoc & 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,
int32_t idxNo,
bool background, 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 rtion in the future // done in two steps/phases to allow potential deferal of write lock po rtion in the future
void indexRecordUsingTwoSteps(const char *ns, NamespaceDetails *d, BSON Obj obj, void indexRecordUsingTwoSteps(const char *ns, NamespaceDetails *d, BSON Obj obj,
DiskLoc loc, bool shouldBeUnlocked ); DiskLoc loc, bool shouldBeUnlocked );
// Given an object, populate "inserter" with information necessary to u pdate indexes. // Given an object, populate "inserter" with information necessary to u pdate indexes.
void fetchIndexInserters(BSONObjSet & /*out*/keys, void fetchIndexInserters(BSONObjSet & /*out*/keys,
 End of changes. 1 change blocks. 
1 lines changed or deleted 0 lines changed or added


 indexkey.h   indexkey.h 
skipping to change at line 37 skipping to change at line 37
extern const int DefaultIndexVersionNumber; extern const int DefaultIndexVersionNumber;
const int ParallelArraysCode = 10088; const int ParallelArraysCode = 10088;
class Cursor; class Cursor;
class IndexSpec; class IndexSpec;
class IndexType; // TODO: this name sucks class IndexType; // TODO: this name sucks
class IndexPlugin; class IndexPlugin;
class IndexDetails; class IndexDetails;
class FieldRangeSet;
enum IndexSuitability { USELESS = 0 , HELPFUL = 1 , OPTIMAL = 2 }; enum IndexSuitability { USELESS = 0 , HELPFUL = 1 , OPTIMAL = 2 };
/** /**
* this represents an instance of a index plugin * this represents an instance of a index plugin
* done this way so parsing, etc... can be cached * done this way so parsing, etc... can be cached
* so if there is a FTS IndexPlugin, for each index using FTS * so if there is a FTS IndexPlugin, for each index using FTS
* there will be 1 of these, and it can have things pre-parsed, etc... * there will be 1 of these, and it can have things pre-parsed, etc...
*/ */
class IndexType : boost::noncopyable { class IndexType : boost::noncopyable {
skipping to change at line 65 skipping to change at line 66
virtual BSONObj fixKey( const BSONObj& in ) { return in; } virtual BSONObj fixKey( const BSONObj& in ) { return in; }
/** optional op : compare 2 objects with regards to this index */ /** optional op : compare 2 objects with regards to this index */
virtual int compare( const BSONObj& l , const BSONObj& r ) const; virtual int compare( const BSONObj& l , const BSONObj& r ) const;
/** @return plugin */ /** @return plugin */
const IndexPlugin * getPlugin() const { return _plugin; } const IndexPlugin * getPlugin() const { return _plugin; }
const BSONObj& keyPattern() const; const BSONObj& keyPattern() const;
virtual IndexSuitability suitability( const BSONObj& query , const /* Determines the suitability level of this index for answering a g
BSONObj& order ) const ; iven query. The query is
* represented as a set of constraints given by a FieldRangeSet, an
d a desired ordering of
* the output.
*
* Note: it is the responsibility of the caller to pass in the corr
ect FieldRangeSet, which
* may depend upon whether this is a single or multi-key index at t
he time of calling.
*/
virtual IndexSuitability suitability( const FieldRangeSet& queryCon
straints ,
const BSONObj& order ) const;
virtual bool scanAndOrderRequired( const BSONObj& query , const BSO NObj& order ) const ; virtual bool scanAndOrderRequired( const BSONObj& query , const BSO NObj& order ) const ;
protected: protected:
const IndexPlugin * _plugin; const IndexPlugin * _plugin;
const IndexSpec * _spec; const IndexSpec * _spec;
}; };
/** /**
* this represents a plugin * this represents a plugin
skipping to change at line 164 skipping to change at line 173
} }
IndexType* getType() const { IndexType* getType() const {
return _indexType.get(); return _indexType.get();
} }
const IndexDetails * getDetails() const { const IndexDetails * getDetails() const {
return _details; return _details;
} }
IndexSuitability suitability( const BSONObj& query , const BSONObj& IndexSuitability suitability( const FieldRangeSet& queryConstraints
order ) const ; ,
const BSONObj& order ) const ;
bool isSparse() const { return _sparse; } bool isSparse() const { return _sparse; }
string toString() const;
protected: protected:
int indexVersion() const; int indexVersion() const;
IndexSuitability _suitability( const BSONObj& query , const BSONObj IndexSuitability _suitability( const FieldRangeSet& queryConstraint
& order ) const ; s ,
const BSONObj& order ) const ;
BSONSizeTracker _sizeTracker; BSONSizeTracker _sizeTracker;
vector<const char*> _fieldNames; vector<const char*> _fieldNames;
vector<BSONElement> _fixed; vector<BSONElement> _fixed;
BSONObj _nullKey; // a full key with all fields null BSONObj _nullKey; // a full key with all fields null
BSONObj _nullObj; // only used for _nullElt BSONObj _nullObj; // only used for _nullElt
BSONElement _nullElt; // jstNull BSONElement _nullElt; // jstNull
BSONObj _undefinedObj; // only used for _undefinedElt BSONObj _undefinedObj; // only used for _undefinedElt
 End of changes. 5 change blocks. 
6 lines changed or deleted 23 lines changed or added


 instance.h   instance.h 
skipping to change at line 23 skipping to change at line 23
* 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 "curop-inl.h"
#include "security.h"
#include "cmdline.h" #include "cmdline.h"
#include "client.h" #include "client.h"
#include "mongo/client/dbclientinterface.h" #include "mongo/client/dbclientinterface.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.
 End of changes. 1 change blocks. 
1 lines changed or deleted 0 lines changed or added


 intervalbtreecursor.h   intervalbtreecursor.h 
skipping to change at line 142 skipping to change at line 142
const bool _upperBoundInclusive; const bool _upperBoundInclusive;
BtreeKeyLocation _curr; // Current position in the btree. BtreeKeyLocation _curr; // Current position in the btree.
LogicalBtreePosition _currRecoverable; // Helper to track the posit ion of _curr if the LogicalBtreePosition _currRecoverable; // Helper to track the posit ion of _curr if the
// btree is modified during a mutex yield. // btree is modified during a mutex yield.
BtreeKeyLocation _end; // Exclusive end location in the btree. BtreeKeyLocation _end; // Exclusive end location in the btree.
int64_t _nscanned; int64_t _nscanned;
shared_ptr<CoveredIndexMatcher> _matcher; shared_ptr<CoveredIndexMatcher> _matcher;
bool _multikeyFlag; bool _multikeyFlag;
set<uint64_t> _dups; unordered_set<DiskLoc,DiskLoc::Hasher> _dups;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 introspect.h   introspect.h 
skipping to change at line 41 skipping to change at line 41
void profile(const Client& c, int op, CurOp& currentOp); void profile(const Client& c, int op, CurOp& currentOp);
/** /**
* Get (or create) the profile collection * Get (or create) the profile collection
* *
* @param db Database in which to create the profile collection * @param db Database in which to create the profile collection
* @param force Always create the collection if it does not exist * @param force Always create the collection if it does not exist
* @return NamespaceDetails for the newly created collection, or NULL on error * @return NamespaceDetails for the newly created collection, or NULL on error
**/ **/
NamespaceDetails* getOrCreateProfileCollection(Database *db, bool force = false); NamespaceDetails* getOrCreateProfileCollection(Database *db, bool force = false, string* errmsg = NULL);
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 isolate.h   isolate.h 
skipping to change at line 1388 skipping to change at line 1388
Isolate* isolate_; Isolate* isolate_;
}; };
// Support for checking for stack-overflows in C++ code. // Support for checking for stack-overflows in C++ code.
class StackLimitCheck BASE_EMBEDDED { class StackLimitCheck BASE_EMBEDDED {
public: public:
explicit StackLimitCheck(Isolate* isolate) : isolate_(isolate) { } explicit StackLimitCheck(Isolate* isolate) : isolate_(isolate) { }
bool HasOverflowed() const { bool HasOverflowed() const {
StackGuard* stack_guard = isolate_->stack_guard(); StackGuard* stack_guard = isolate_->stack_guard();
// Stack has overflowed in C++ code only if stack pointer exceeds the C return (reinterpret_cast<uintptr_t>(this) < stack_guard->real_climit())
++ ;
// stack guard and the limits are not set to interrupt values.
// TODO(214): Stack overflows are ignored if a interrupt is pending. Th
is
// code should probably always use the initial C++ limit.
return (reinterpret_cast<uintptr_t>(this) < stack_guard->climit()) &&
stack_guard->IsStackOverflow();
} }
private: private:
Isolate* isolate_; Isolate* isolate_;
}; };
// Support for temporarily postponing interrupts. When the outermost // Support for temporarily postponing interrupts. When the outermost
// postpone scope is left the interrupts will be re-enabled and any // postpone scope is left the interrupts will be re-enabled and any
// interrupts that occurred while in the scope will be taken into // interrupts that occurred while in the scope will be taken into
// account. // account.
class PostponeInterruptsScope BASE_EMBEDDED { class PostponeInterruptsScope BASE_EMBEDDED {
 End of changes. 1 change blocks. 
8 lines changed or deleted 2 lines changed or added


 json.h   json.h 
/** @file json.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
skipping to change at line 24 skipping to change at line 22
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "mongo/bson/bsonobj.h" #include "mongo/bson/bsonobj.h"
#include "mongo/base/status.h"
namespace mongo { namespace mongo {
/** Create a BSONObj from a JSON <http://www.json.org> string. In addi /**
tion * Create a BSONObj from a JSON <http://www.json.org>,
to the JSON extensions extensions described here * <http://www.ietf.org/rfc/rfc4627.txt> string. In addition to the JS
<http://mongodb.onconfluence.com/display/DOCS/Mongo+Extended+JSON>, ON
this function accepts certain unquoted field names and allows single q * extensions extensions described here
uotes * <http://mongodb.onconfluence.com/display/DOCS/Mongo+Extended+JSON>,
to optionally be used when specifying field names and string values in this
stead * function accepts unquoted field names and allows single quotes to
of double quotes. JSON unicode escape sequences (of the form \uXXXX) * optionally be used when specifying field names and string values ins
are tead
converted to utf8. * of double quotes. JSON unicode escape sequences (of the form \uXXXX
\throws MsgAssertionException if parsing fails. The message included ) are
with * converted to utf8.
this assertion includes a rough indication of where parsing failed. *
*/ * @throws MsgAssertionException if parsing fails. The message include
BSONObj fromjson(const std::string &str); d with
* this assertion includes the character offset where parsing failed.
*/
BSONObj fromjson(const std::string& str);
/** @param len will be size of JSON object in text chars. */
BSONObj fromjson(const char* str, int* len=NULL);
/**
* Parser class. A BSONObj is constructed incrementally by passing a
* BSONObjBuilder to the recursive parsing methods. The grammar for th
e
* element parsed is described before each function.
*/
class JParse {
public:
explicit JParse(const char*);
/*
* Notation: All-uppercase symbols denote non-terminals; all ot
her
* symbols are literals.
*/
/*
* VALUE :
* STRING
* | NUMBER
* | OBJECT
* | ARRAY
*
* | true
* | false
* | null
* | undefined
*
* | NaN
* | Infinity
* | -Infinity
*
* | DATE
* | TIMESTAMP
* | REGEX
* | OBJECTID
* | DBREF
*
* | new CONSTRUCTOR
*/
private:
Status value(const StringData& fieldName, BSONObjBuilder&);
/*
* OBJECT :
* {}
* | { MEMBERS }
* | SPECIALOBJECT
*
* MEMBERS :
* PAIR
* | PAIR , MEMBERS
*
* PAIR :
* FIELD : VALUE
*
* SPECIALOBJECT :
* OIDOBJECT
* | BINARYOBJECT
* | DATEOBJECT
* | TIMESTAMPOBJECT
* | REGEXOBJECT
* | REFOBJECT
* | UNDEFINEDOBJECT
*
*/
public:
Status object(const StringData& fieldName, BSONObjBuilder&, boo
l subObj=true);
private:
/* The following functions are called with the '{' and the firs
t
* field already parsed since they are both implied given the
* context. */
/*
* OIDOBJECT :
* { FIELD("$oid") : <24 character hex string> }
*/
Status objectIdObject(const StringData& fieldName, BSONObjBuild
er&);
/*
* BINARYOBJECT :
* { FIELD("$binary") : <base64 representation of a binary
string>,
* FIELD("$type") : <hexadecimal representation of a s
ingle byte
* indicating the data type> }
*/
Status binaryObject(const StringData& fieldName, BSONObjBuilder
&);
/*
* DATEOBJECT :
* { FIELD("$date") : <64 bit signed integer for millisecon
ds since epoch> }
*/
Status dateObject(const StringData& fieldName, BSONObjBuilder&)
;
/*
* TIMESTAMPOBJECT :
* { FIELD("$timestamp") : {
* FIELD("t") : <32 bit unsigned integer for seconds si
nce epoch>,
* FIELD("i") : <32 bit unsigned integer for the increm
ent> } }
*/
Status timestampObject(const StringData& fieldName, BSONObjBuil
der&);
/*
* NOTE: the rules for the body of the regex are different
here,
* since it is quoted instead of surrounded by slashes.
* REGEXOBJECT :
* { FIELD("$regex") : <string representing body of regex>
}
* | { FIELD("$regex") : <string representing body of regex>,
* FIELD("$options") : <string representing regex opti
ons> }
*/
Status regexObject(const StringData& fieldName, BSONObjBuilder&
);
/*
* REFOBJECT :
* { FIELD("$ref") : <string representing collection name>,
* FIELD("$id") : <24 character hex string> }
* | { FIELD("$ref") : STRING , FIELD("$id") : OBJECTID }
* | { FIELD("$ref") : STRING , FIELD("$id") : OIDOBJECT }
*/
Status dbRefObject(const StringData& fieldName, BSONObjBuilder&
);
/*
* UNDEFINEDOBJECT :
* { FIELD("$undefined") : true }
*/
Status undefinedObject(const StringData& fieldName, BSONObjBuil
der&);
/*
* ARRAY :
* []
* | [ ELEMENTS ]
*
* ELEMENTS :
* VALUE
* | VALUE , ELEMENTS
*/
Status array(const StringData& fieldName, BSONObjBuilder&);
/*
* NOTE: Currently only Date can be preceded by the "new" keywo
rd
* CONSTRUCTOR :
* DATE
*/
Status constructor(const StringData& fieldName, BSONObjBuilder&
);
/* The following functions only parse the body of the construct
or
* between the parentheses, not including the constructor name
*/
/*
* DATE :
* Date( <64 bit signed integer for milliseconds since epoc
h> )
*/
Status date(const StringData& fieldName, BSONObjBuilder&);
/*
* TIMESTAMP :
* Timestamp( <32 bit unsigned integer for seconds since ep
och>,
* <32 bit unsigned integer for the increment> )
*/
Status timestamp(const StringData& fieldName, BSONObjBuilder&);
/*
* OBJECTID :
* ObjectId( <24 character hex string> )
*/
Status objectId(const StringData& fieldName, BSONObjBuilder&);
/*
* DBREF :
* Dbref( <namespace string> , <24 character hex string> )
*/
Status dbRef(const StringData& fieldName, BSONObjBuilder&);
/*
* REGEX :
* / REGEXCHARS / REGEXOPTIONS
*
* REGEXCHARS :
* REGEXCHAR
* | REGEXCHAR REGEXCHARS
*
* REGEXCHAR :
* any-Unicode-character-except-/-or-\-or-CONTROLCHAR
* | \"
* | \'
* | \\
* | \/
* | \b
* | \f
* | \n
* | \r
* | \t
* | \v
* | \u HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT
* | \any-Unicode-character-except-x-or-[0-7]
*
* REGEXOPTIONS :
* REGEXOPTION
* | REGEXOPTION REGEXOPTIONS
*
* REGEXOPTION :
* g | i | m | s
*/
Status regex(const StringData& fieldName, BSONObjBuilder&);
Status regexPat(std::string* result);
Status regexOpt(std::string* result);
Status regexOptCheck(const StringData& opt);
/*
* NUMBER :
*
* NOTE: Number parsing is based on standard library functions,
not
* necessarily on the JSON numeric grammar.
*
* Number as value - strtoll and strtod
* Date - strtoll
* Timestamp - strtoul for both timestamp and increment and '-'
* before a number explicity disallowed
*/
Status number(const StringData& fieldName, BSONObjBuilder&);
/*
* FIELD :
* STRING
* | [a-zA-Z$_] FIELDCHARS
*
* FIELDCHARS :
* [a-zA-Z0-9$_]
* | [a-zA-Z0-9$_] FIELDCHARS
*/
Status field(std::string* result);
/*
* STRING :
* " "
* | ' '
* | " CHARS "
* | ' CHARS '
*/
Status quotedString(std::string* result);
/*
* CHARS :
* CHAR
* | CHAR CHARS
*
* Note: " or ' may be allowed depending on whether the string
is
* double or single quoted
*
* CHAR :
* any-Unicode-character-except-"-or-'-or-\-or-CONTROLCHAR
* | \"
* | \'
* | \\
* | \/
* | \b
* | \f
* | \n
* | \r
* | \t
* | \v
* | \u HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT
* | \any-Unicode-character-except-x-or-[0-9]
*
* HEXDIGIT : [0..9a..fA..F]
*
* per http://www.ietf.org/rfc/rfc4627.txt, control characters
are
* (U+0000 through U+001F). U+007F is not mentioned as a contr
ol
* character.
* CONTROLCHAR : [0x00..0x1F]
*
* If there is not an error, result will contain a null termina
ted
* string, but there is no guarantee that it will not contain o
ther
* null characters.
*/
Status chars(std::string* result, const char* terminalSet, cons
t char* allowedSet=NULL);
/**
* Converts the two byte Unicode code point to its UTF8 charact
er
* encoding representation. This function returns a string bec
ause
* UTF8 encodings for code points from 0x0000 to 0xFFFF can ran
ge
* from one to three characters.
*/
std::string encodeUTF8(unsigned char first, unsigned char secon
d) const;
/**
* @return true if the given token matches the next non whitesp
ace
* sequence in our buffer, and false if the token doesn't match
or
* we reach the end of our buffer. Do not update the pointer t
o our
* buffer if advance is false.
*/
bool accept(const char* token, bool advance=true);
/**
* @return true if the next field in our stream matches field.
* Handles single quoted, double quoted, and unquoted field nam
es
*/
bool acceptField(const StringData& field);
/**
* @return true if matchChar is in matchSet
* @return true if matchSet is NULL and false if it is an empty
string
*/
bool match(char matchChar, const char* matchSet) const;
/**
* @return true if every character in the string is a hex digit
*/
bool isHexString(const StringData&) const;
/**
* @return true if every character in the string is a valid bas
e64
* character
*/
bool isBase64String(const StringData&) const;
/**
* @return FailedToParse status with the given message and some
* additional context information
*/
Status parseError(const StringData& msg);
public:
inline int offset() { return (_input - _buf); }
/** len will be size of JSON object in text chars. */ private:
BSONObj fromjson(const char *str, int* len=NULL); /*
* _buf - start of our input buffer
* _input - cursor we advance in our input buffer
* _input_end - sentinel for the end of our input buffer
*
* _buf is the null terminated buffer containing the JSON strin
g we
* are parsing. _input_end points to the null byte at the end
of
* the buffer. strtoll, strtol, and strtod will access the nul
l
* byte at the end of the buffer because they are assuming a c-
style
* string.
*/
const char* const _buf;
const char* _input;
const char* const _input_end;
};
} // namespace mongo } // namespace mongo
 End of changes. 4 change blocks. 
20 lines changed or deleted 405 lines changed or added


 keypattern.h   keypattern.h 
skipping to change at line 21 skipping to change at line 21
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/base/string_data.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/util/mongoutils/str.h" #include "mongo/util/mongoutils/str.h"
namespace mongo { namespace mongo {
struct FieldInterval; struct FieldInterval;
class FieldRangeSet; class FieldRangeSet;
/** /**
* A BoundList contains intervals specified by inclusive start * A BoundList contains intervals specified by inclusive start
skipping to change at line 60 skipping to change at line 61
/* /*
* Returns a BSON representation of this KeyPattern. * Returns a BSON representation of this KeyPattern.
*/ */
BSONObj toBSON() const { return _pattern; } BSONObj toBSON() const { return _pattern; }
/* /*
* Returns true if the given fieldname is the name of one element o f the (potentially) * Returns true if the given fieldname is the name of one element o f the (potentially)
* compound key described by this KeyPattern. * compound key described by this KeyPattern.
*/ */
bool hasField( const char* fieldname ) const { return _pattern.hasF ield( fieldname ); } bool hasField( const StringData& fieldname ) const { return _patter n.hasField( fieldname ); }
/* /*
* Gets the element of this pattern corresponding to the given fiel dname. * Gets the element of this pattern corresponding to the given fiel dname.
* Returns eoo if none exists. * Returns eoo if none exists.
*/ */
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() );
} }
/* 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
* (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
* shard key, or for calculating index bounds when the shard key is
a prefix of the actual
* index used.
*
* @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
* -1's in the keyPattern will swap MinKey/MaxKey vals. See example
s).
*
* Examples:
* If this keyPattern is {a : 1}
* extendRangeBound( {a : 55}, false) --> {a : 55}
*
* If this keyPattern is {a : 1, b : 1}
* extendRangeBound( {a : 55}, false) --> {a : 55, b : MinKey}
* extendRangeBound( {a : 55}, true ) --> {a : 55, b : MaxKey}
*
* If this keyPattern is {a : 1, b : -1}
* extendRangeBound( {a : 55}, false) --> {a : 55, b : MaxKey}
* extendRangeBound( {a : 55}, true ) --> {a : 55, b : MinKey}
*/
BSONObj extendRangeBound( const BSONObj& bound , bool makeUpperIncl
usive ) const;
/** /**
* Returns true if this KeyPattern contains any computed values, (e .g. {a : "hashed"}), * Returns true if this KeyPattern contains any computed values, (e .g. {a : "hashed"}),
* and false if this KeyPattern consists of only ascending/descendi ng fields * and false if this KeyPattern consists of only ascending/descendi ng fields
* (e.g. {a : 1, b : -1}). With our current index expression langua ge, "special" patterns * (e.g. {a : 1, b : -1}). With our current index expression langua ge, "special" patterns
* are any patterns that are not a simple list of field names and 1 /-1 values. * are any patterns that are not a simple list of field names and 1 /-1 values.
*/ */
bool isSpecial() const; bool isSpecial() const;
/** /**
* Returns true if the quantities stored in this KeyPattern can be used to compute all the * Returns true if the quantities stored in this KeyPattern can be used to compute all the
 End of changes. 3 change blocks. 
1 lines changed or deleted 36 lines changed or added


 kill_current_op.h   kill_current_op.h 
skipping to change at line 81 skipping to change at line 81
void interruptJs( AtomicUInt *op ); void interruptJs( AtomicUInt *op );
volatile bool _globalKill; volatile bool _globalKill;
boost::condition _condvar; boost::condition _condvar;
boost::mutex _mtx; boost::mutex _mtx;
/** /**
* @param i opid of operation to kill * @param i opid of operation to kill
* @param pNotifyFlag optional bool to be set to true when kill act ually happens * @param pNotifyFlag optional bool to be set to true when kill act ually happens
* @return if operation was found * @return if operation was found
**/ **/
bool killImpl(AtomicUInt i, bool* pNotifyFlag = NULL); bool _killImpl_inclientlock(AtomicUInt i, bool* pNotifyFlag = NULL) ;
}; };
extern KillCurrentOp killCurrentOp; extern KillCurrentOp killCurrentOp;
} }
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 lasterror.h   lasterror.h 
skipping to change at line 32 skipping to change at line 32
namespace mongo { namespace mongo {
class BSONObjBuilder; class BSONObjBuilder;
class Message; class Message;
struct LastError { struct LastError {
int code; int code;
string msg; string msg;
enum UpdatedExistingType { NotUpdate, True, False } updatedExisting ; enum UpdatedExistingType { NotUpdate, True, False } updatedExisting ;
OID upsertedId; OID upsertedId;
OID writebackId; // this shouldn't get reset so that old GLE are ha ndled OID writebackId; // this shouldn't get reset so that old GLE are ha ndled
int writebackSince;
long long nObjects; long long nObjects;
int nPrev; int nPrev;
bool valid; bool valid;
bool disabled; bool disabled;
void writeback( OID& oid ) { void writeback( OID& oid ) {
reset( true ); reset( true );
writebackId = oid; writebackId = oid;
writebackSince = 0;
} }
void raiseError(int _code , const char *_msg) { void raiseError(int _code , const char *_msg) {
reset( true ); reset( true );
code = _code; code = _code;
msg = _msg; msg = _msg;
} }
void recordUpdate( bool _updateObjects , long long _nObjects , OID _upsertedId ) { void recordUpdate( bool _updateObjects , long long _nObjects , OID _upsertedId ) {
reset( true ); reset( true );
nObjects = _nObjects; nObjects = _nObjects;
updatedExisting = _updateObjects ? True : False; updatedExisting = _updateObjects ? True : False;
if ( _upsertedId.isSet() ) if ( _upsertedId.isSet() )
upsertedId = _upsertedId; upsertedId = _upsertedId;
} }
void recordDelete( long long nDeleted ) { void recordDelete( long long nDeleted ) {
reset( true ); reset( true );
nObjects = nDeleted; nObjects = nDeleted;
} }
LastError() { LastError() {
reset(); reset();
writebackSince = 0;
} }
void reset( bool _valid = false ) { void reset( bool _valid = false ) {
code = 0; code = 0;
msg.clear(); msg.clear();
updatedExisting = NotUpdate; updatedExisting = NotUpdate;
nObjects = 0; nObjects = 0;
nPrev = 1; nPrev = 1;
valid = _valid; valid = _valid;
disabled = false; disabled = false;
upsertedId.clear(); upsertedId.clear();
 End of changes. 3 change blocks. 
0 lines changed or deleted 3 lines changed or added


 listen.h   listen.h 
skipping to change at line 38 skipping to change at line 38
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();
#ifdef MONGO_SSL
/**
* make this an ssl socket
* ownership of SSLManager remains with the caller
*/
void secure( SSLManager* manager );
void addSecurePort( SSLManager* manager , int additionalPort );
#endif
void initAndListen(); // never returns unless error (start a thread ) void initAndListen(); // never returns unless error (start a thread )
/* spawn a thread, etc., then return */ /* spawn a thread, etc., then return */
virtual void accepted(boost::shared_ptr<Socket> psocket, long long connectionId ); virtual void accepted(boost::shared_ptr<Socket> psocket, long long connectionId );
virtual void acceptedMP(MessagingPort *mp); virtual void acceptedMP(MessagingPort *mp);
const int _port; const int _port;
/** /**
* @return a rough estimate of elapsed time since the server starte d * @return a rough estimate of elapsed time since the server starte d
skipping to change at line 85 skipping to change at line 75
} }
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; SSLManager* _ssl;
int _sslPort;
#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. 2 change blocks. 
11 lines changed or deleted 0 lines changed or added


 lockstate.h   lockstate.h 
skipping to change at line 69 skipping to change at line 69
/** /**
* you have to be locked already to call this * you have to be locked already to call this
* this is mostly for W_to_R or R_to_W * this is mostly for W_to_R or R_to_W
*/ */
void changeLockState( char newstate ); void changeLockState( char newstate );
Lock::Nestable whichNestable() const { return _whichNestable; } Lock::Nestable whichNestable() const { return _whichNestable; }
int nestableCount() const { return _nestableCount; } int nestableCount() const { return _nestableCount; }
int otherCount() const { return _otherCount; } int otherCount() const { return _otherCount; }
string otherName() const { return _otherName; } const string& otherName() const { return _otherName; }
WrapperForRWLock* otherLock() const { return _otherLock; } WrapperForRWLock* otherLock() const { return _otherLock; }
void enterScopedLock( Lock::ScopedLock* lock ); void enterScopedLock( Lock::ScopedLock* lock );
Lock::ScopedLock* leaveScopedLock(); Lock::ScopedLock* leaveScopedLock();
void lockedNestable( Lock::Nestable what , int type ); void lockedNestable( Lock::Nestable what , int type );
void unlockedNestable(); void unlockedNestable();
void lockedOther( const string& db , int type , WrapperForRWLock* l ock ); void lockedOther( const StringData& db , int type , WrapperForRWLoc k* lock );
void lockedOther( int type ); // "same lock as last time" case void lockedOther( int type ); // "same lock as last time" case
void unlockedOther(); void unlockedOther();
bool _batchWriter; bool _batchWriter;
LockStat* getRelevantLockStat(); LockStat* getRelevantLockStat();
void recordLockTime() { _scopedLk->recordTime(); } void recordLockTime() { _scopedLk->recordTime(); }
void resetLockTime() { _scopedLk->resetTime(); } void resetLockTime() { _scopedLk->resetTime(); }
private: private:
unsigned _recursive; // we allow recursively asking for a lock; we track that here unsigned _recursive; // we allow recursively asking for a lock; we track that here
skipping to change at line 117 skipping to change at line 117
friend class Acquiring; friend class Acquiring;
friend class AcquiringParallelWriter; friend class AcquiringParallelWriter;
}; };
class WrapperForRWLock : boost::noncopyable { class WrapperForRWLock : boost::noncopyable {
SimpleRWLock r; SimpleRWLock r;
public: public:
string name() const { return r.name; } string name() const { return r.name; }
LockStat stats; LockStat stats;
WrapperForRWLock(const char *name) : r(name) { } WrapperForRWLock(const StringData& name) : r(name) { }
void lock() { r.lock(); } void lock() { r.lock(); }
void lock_shared() { r.lock_shared(); } void lock_shared() { r.lock_shared(); }
void unlock() { r.unlock(); } void unlock() { r.unlock(); }
void unlock_shared() { r.unlock_shared(); } void unlock_shared() { r.unlock_shared(); }
}; };
class ScopedLock; class ScopedLock;
class Acquiring { class Acquiring {
public: public:
 End of changes. 3 change blocks. 
3 lines changed or deleted 3 lines changed or added


 log.h   log.h 
skipping to change at line 28 skipping to change at line 28
#pragma once #pragma once
#include <string.h> #include <string.h>
#include <sstream> #include <sstream>
#include <errno.h> #include <errno.h>
#include <vector> #include <vector>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
#include <boost/thread/tss.hpp> #include <boost/thread/tss.hpp>
#include "mongo/base/status.h"
#include "mongo/bson/util/builder.h" #include "mongo/bson/util/builder.h"
#include "mongo/util/concurrency/mutex.h" #include "mongo/util/concurrency/mutex.h"
#include "mongo/util/debug_util.h" #include "mongo/util/debug_util.h"
#include "mongo/util/exit_code.h" #include "mongo/util/exit_code.h"
#ifndef _WIN32 #ifndef _WIN32
#include <syslog.h> #include <syslog.h>
#endif #endif
namespace mongo { namespace mongo {
skipping to change at line 250 skipping to change at line 251
static mongo::mutex mutex; static mongo::mutex mutex;
static int doneSetup; static int doneSetup;
std::stringstream ss; std::stringstream ss;
int indent; int indent;
LogLevel logLevel; LogLevel logLevel;
static FILE* logfile; static FILE* logfile;
static boost::scoped_ptr<std::ostream> stream; static boost::scoped_ptr<std::ostream> stream;
static std::vector<Tee*> * globalTees; static std::vector<Tee*> * globalTees;
static bool isSyslog; static bool isSyslog;
public: public:
// Type for optional function for inserting context information in
log messages. See
// registerExtraLogContextFn, below.
typedef void (*ExtraLogContextFn)(BufBuilder& builder);
static void logLockless( const StringData& s ); static void logLockless( const StringData& s );
static void setLogFile(FILE* f); static void setLogFile(FILE* f);
#ifndef _WIN32 #ifndef _WIN32
static void useSyslog(const char * name) { static void useSyslog(const char * name) {
std::cout << "using syslog ident: " << name << std::endl; std::cout << "using syslog ident: " << name << std::endl;
// openlog requires heap allocated non changing pointer // openlog requires heap allocated non changing pointer
// this should only be called once per pragram execution // this should only be called once per pragram execution
skipping to change at line 291 skipping to change at line 296
void flush(Tee *t = 0); void flush(Tee *t = 0);
inline Nullstream& setLogLevel(LogLevel l) { inline Nullstream& setLogLevel(LogLevel l) {
logLevel = l; logLevel = l;
return *this; return *this;
} }
/** note these are virtual */ /** note these are virtual */
Logstream& operator<<(const char *x) { ss << x; return *this; } Logstream& operator<<(const char *x) { ss << x; return *this; }
Logstream& operator<<(const string& x) { ss << x; return *this; } Logstream& operator<<(const string& x) { ss << x; return *this; }
Logstream& operator<<(const StringData& x) { ss << x.data(); return *this; } Logstream& operator<<(const StringData& x) { ss << x; return *this; }
Logstream& operator<<(char *x) { ss << x; return *this; } Logstream& operator<<(char *x) { ss << x; return *this; }
Logstream& operator<<(char x) { ss << x; return *this; } Logstream& operator<<(char x) { ss << x; return *this; }
Logstream& operator<<(int x) { ss << x; return *this; } Logstream& operator<<(int x) { ss << x; return *this; }
Logstream& operator<<(ExitCode x) { ss << x; return *this; } Logstream& operator<<(ExitCode x) { ss << x; return *this; }
Logstream& operator<<(long x) { ss << x; return *this; } Logstream& operator<<(long x) { ss << x; return *this; }
Logstream& operator<<(unsigned long x) { ss << x; return *this; } Logstream& operator<<(unsigned long x) { ss << x; return *this; }
Logstream& operator<<(unsigned x) { ss << x; return *this; } Logstream& operator<<(unsigned x) { ss << x; return *this; }
Logstream& operator<<(unsigned short x){ ss << x; return *this; } Logstream& operator<<(unsigned short x){ ss << x; return *this; }
Logstream& operator<<(double x) { ss << x; return *this; } Logstream& operator<<(double x) { ss << x; return *this; }
Logstream& operator<<(void *x) { ss << x; return *this; } Logstream& operator<<(void *x) { ss << x; return *this; }
skipping to change at line 342 skipping to change at line 347
globalTees = new std::vector<Tee*>(); globalTees = new std::vector<Tee*>();
globalTees->push_back( t ); globalTees->push_back( t );
} }
void removeGlobalTee( Tee * tee ); void removeGlobalTee( Tee * tee );
void indentInc(){ indent++; } void indentInc(){ indent++; }
void indentDec(){ indent--; } void indentDec(){ indent--; }
int getIndent() const { return indent; } int getIndent() const { return indent; }
// Replace any pre-existing function for appending context informat
ion to log lines with
// "contextFn". Returns Status::OK on first call, and ErrorCodes::
AlreadyInitialized if
// called more than once. Returns ErrorCodes::BadValue if contextF
n is NULL.
static Status registerExtraLogContextFn(ExtraLogContextFn contextFn
);
private: private:
static boost::thread_specific_ptr<Logstream> tsp; static boost::thread_specific_ptr<Logstream> tsp;
Logstream() { Logstream() {
indent = 0; indent = 0;
_init(); _init();
} }
void _init() { void _init() {
ss.str(""); ss.str("");
logLevel = LL_INFO; logLevel = LL_INFO;
} }
public: public:
static Logstream& get(); static Logstream& get();
}; };
extern int logLevel; extern int logLevel;
extern int tlogLevel; extern int tlogLevel;
inline Nullstream& out( int level = 0 ) { inline Nullstream& out( int level = 0 ) {
if ( level > logLevel ) if ( level > logLevel )
return nullstream; return nullstream;
 End of changes. 5 change blocks. 
1 lines changed or deleted 17 lines changed or added


 mapsf.h   mapsf.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/>.
*/ */
#include "mongo/platform/unordered_map.h" #include "mongo/platform/unordered_map.h"
namespace mongo { namespace mongo {
/** Thread safe map. /** Thread safe map.
Be careful not to use this too much or it could make things slow; Be careful not to use this too much or it could make things slow;
if not a hot code path no problem. if not a hot code path no problem.
Examples: Examples:
mapsf<int,int> mp; mapsf< map<int,int>, int, int > mp;
int x = mp.get(); int x = mp.get();
map<int,int> two; map< map<int,int>, int, int > two;
mp.swap(two); mp.swap(two);
{ {
mapsf<int,int>::ref r(mp); mapsf< map<int,int>, int, int >::ref r(mp);
r[9] = 1; r[9] = 1;
map<int,int>::iterator i = r.r.begin(); map<int,int>::iterator i = r.r.begin();
} }
*/ */
template< class K, class V > template< class M >
struct mapsf : boost::noncopyable { struct mapsf : boost::noncopyable {
SimpleMutex m; SimpleMutex m;
unordered_map<K,V> val; M val;
friend struct ref; friend struct ref;
public: public:
typedef typename M::const_iterator const_iterator;
typedef typename M::key_type key_type;
typedef typename M::mapped_type mapped_type;
mapsf() : m("mapsf") { } mapsf() : m("mapsf") { }
void swap(unordered_map<K,V>& rhs) { void swap(M& rhs) {
SimpleMutex::scoped_lock lk(m); SimpleMutex::scoped_lock lk(m);
val.swap(rhs); val.swap(rhs);
} }
bool empty() { bool empty() {
SimpleMutex::scoped_lock lk(m); SimpleMutex::scoped_lock lk(m);
return val.empty(); return val.empty();
} }
// safe as we pass by value: // safe as we pass by value:
V get(K k) { mapped_type get(key_type k) {
SimpleMutex::scoped_lock lk(m); SimpleMutex::scoped_lock lk(m);
typename unordered_map<K,V>::iterator i = val.find(k); const_iterator i = val.find(k);
if( i == val.end() ) if( i == val.end() )
return V(); return mapped_type();
return i->second; return i->second;
} }
// think about deadlocks when using ref. the other methods // think about deadlocks when using ref. the other methods
// above will always be safe as they are "leaf" operations. // above will always be safe as they are "leaf" operations.
struct ref { struct ref {
SimpleMutex::scoped_lock lk; SimpleMutex::scoped_lock lk;
public: public:
unordered_map<K,V> &r; M &r;
ref(mapsf<K,V> &m) : lk(m.m), r(m.val) { } ref(mapsf &m) : lk(m.m), r(m.val) { }
V& operator[](const K& k) { return r[k]; } mapped_type& operator[](const key_type& k) { return r[k]; }
}; };
}; };
} }
 End of changes. 13 change blocks. 
14 lines changed or deleted 17 lines changed or added


 matcher.h   matcher.h 
skipping to change at line 25 skipping to change at line 25
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "jsobj.h" #include "jsobj.h"
#include "pcrecpp.h" #include "pcrecpp.h"
#include "mongo/db/geo/geoparser.h"
namespace mongo { namespace mongo {
class Cursor; class Cursor;
class CoveredIndexMatcher; class CoveredIndexMatcher;
class ElementMatcher; class ElementMatcher;
class Matcher; class Matcher;
class FieldRangeVector; class FieldRangeVector;
class RegexMatcher { class RegexMatcher {
skipping to change at line 52 skipping to change at line 53
const char *_fieldName; const char *_fieldName;
const char *_regex; const char *_regex;
const char *_flags; const char *_flags;
string _prefix; string _prefix;
shared_ptr< pcrecpp::RE > _re; shared_ptr< pcrecpp::RE > _re;
bool _isNot; bool _isNot;
RegexMatcher() : _isNot() {} RegexMatcher() : _isNot() {}
}; };
class GeoMatcher {
private:
GeoMatcher(const string& field, bool isNot) : _isBox(false), _isCir
cle(false),
_isPolygon(false), _f
ieldName(field),
_isNot(isNot) {}
bool _isBox;
Box _box;
bool _isCircle;
Point _center;
double _radius;
bool _isPolygon;
Polygon _polygon;
string _fieldName;
bool _isNot;
public:
const string& getFieldName() const { return _fieldName; }
static GeoMatcher makeBoxMatcher(const string& field, const BSONObj
&obj, bool isNot) {
GeoMatcher m(field, isNot);
m._isBox = true;
GeoParser::parseLegacyBox(obj, &m._box);
return m;
}
static GeoMatcher makeCircleMatcher(const string& field, const BSON
Obj &obj, bool isNot) {
GeoMatcher m(field, isNot);
m._isCircle = true;
GeoParser::parseLegacyCenter(obj, &m._center, &m._radius);
return m;
}
static GeoMatcher makePolygonMatcher(const string& field, const BSO
NObj &obj, bool isNot) {
GeoMatcher m(field, isNot);
m._isPolygon = true;
GeoParser::parseLegacyPolygon(obj, &m._polygon);
return m;
}
bool containsPoint(Point p) const {
bool ret;
if (_isBox) {
ret = _box.inside(p, 0);
} else if (_isCircle) {
ret = distance(p, _center) <= _radius;
} else if (_isPolygon) {
ret = _polygon.contains(p);
} else {
ret = false;
}
return _isNot ? !ret : ret;
}
string toString() const {
stringstream ss;
if (_isBox) {
ss << "GeoMatcher Box: " << _box.toString();
} else if (_isCircle) {
ss << "GeoMatcher Circle @ " << _center.toString() << " r =
" << _radius;
} else {
ss << "GeoMatcher UNKNOWN";
}
return ss.str();
}
static bool pointFrom(const BSONObj o, Point *p) {
if (!GeoParser::isLegacyPoint(o)) { return false; }
GeoParser::parseLegacyPoint(o, p);
return true;
}
};
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;
} }
}; };
/** /**
skipping to change at line 225 skipping to change at line 300
return _jsobj.toString(); return _jsobj.toString();
} }
/** /**
* @return true if this key matcher will return the same true/false * @return true if this key matcher will return the same true/false
* value as the provided doc matcher. * value as the provided doc matcher.
*/ */
bool keyMatch( const Matcher &docMatcher ) const; bool keyMatch( const Matcher &docMatcher ) const;
bool singleSimpleCriterion() const { bool singleSimpleCriterion() const {
return false; // TODO SERVER-958 if ( _where ||
// // TODO Really check, especially if all basics are ok. _basics.size() > 1 ||
// // $all, etc _haveNeg ||
// // _orConstraints? _haveSize ||
// return ( ( basics.size() + nRegex ) < 2 ) && !where && !_orMa _regexs.size() > 0 )
tchers.size() && !_norMatchers.size(); 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; }; const BSONObj *getQuery() const { return &_jsobj; };
private: private:
/** /**
* Generate a matcher for the provided index key format using the * Generate a matcher for the provided index key format using the
* provided full doc matcher. * provided full doc matcher.
*/ */
Matcher( const Matcher &docMatcher, const BSONObj &constrainIndexKe y ); Matcher( const Matcher &docMatcher, const BSONObj &constrainIndexKe y );
skipping to change at line 276 skipping to change at line 363
bool _haveNeg; bool _haveNeg;
/* $atomic - if true, a multi document operation (some removes, upd ates) /* $atomic - if true, a multi document operation (some removes, upd ates)
should be done atomically. in that case, we do not yi eld - should be done atomically. in that case, we do not yi eld -
i.e. we stay locked the whole time. i.e. we stay locked the whole time.
http://dochub.mongodb.org/core/remove http://dochub.mongodb.org/core/remove
*/ */
bool _atomic; bool _atomic;
vector<RegexMatcher> _regexs; vector<RegexMatcher> _regexs;
vector<GeoMatcher> _geo;
// so we delete the mem when we're done: // so we delete the mem when we're done:
vector< shared_ptr< BSONObjBuilder > > _builders; vector< shared_ptr< BSONObjBuilder > > _builders;
list< shared_ptr< Matcher > > _andMatchers; list< shared_ptr< Matcher > > _andMatchers;
list< shared_ptr< Matcher > > _orMatchers; list< shared_ptr< Matcher > > _orMatchers;
list< shared_ptr< Matcher > > _norMatchers; list< shared_ptr< Matcher > > _norMatchers;
friend class CoveredIndexMatcher; friend class CoveredIndexMatcher;
}; };
 End of changes. 4 change blocks. 
6 lines changed or deleted 99 lines changed or added


 message.h   message.h 
skipping to change at line 26 skipping to change at line 26
*/ */
#pragma once #pragma once
#include "sock.h" #include "sock.h"
#include "../../bson/util/atomic_int.h" #include "../../bson/util/atomic_int.h"
#include "hostandport.h" #include "hostandport.h"
namespace mongo { namespace mongo {
/**
* Maximum accepted message size on the wire protocol.
*/
const int MaxMessageSizeBytes = 48 * 1000 * 1000;
class Message; class Message;
class MessagingPort; class MessagingPort;
class PiggyBackData; class PiggyBackData;
typedef AtomicUInt MSGID; typedef AtomicUInt MSGID;
enum Operations { enum Operations {
opReply = 1, /* reply. responseTo is set. */ opReply = 1, /* reply. responseTo is set. */
dbMsg = 1000, /* generic msg command followed by a string */ dbMsg = 1000, /* generic msg command followed by a string */
dbUpdate = 2001, /* update object */ dbUpdate = 2001, /* update object */
 End of changes. 1 change blocks. 
0 lines changed or deleted 5 lines changed or added


 message_port.h   message_port.h 
skipping to change at line 108 skipping to change at line 108
void send( const char * data , int len, const char *context ) { void send( const char * data , int len, const char *context ) {
psock->send( data, len, context ); psock->send( data, len, context );
} }
void send( const vector< pair< char *, int > > &data, const char *c ontext ) { void send( const vector< pair< char *, int > > &data, const char *c ontext ) {
psock->send( data, context ); psock->send( data, context );
} }
bool connect(SockAddr& farEnd) { bool connect(SockAddr& farEnd) {
return psock->connect( farEnd ); return psock->connect( farEnd );
} }
#ifdef MONGO_SSL #ifdef MONGO_SSL
/** secures inline */ /**
* Initiates the TLS/SSL handshake on this MessagingPort.
* When this function returns, further communication on this
* MessagingPort will be encrypted.
*/
void secure( SSLManager * ssl ) { void secure( SSLManager * ssl ) {
psock->secure( ssl ); psock->secure( ssl );
} }
#endif #endif
uint64_t getSockCreationMicroSec() const { uint64_t getSockCreationMicroSec() const {
return psock->getSockCreationMicroSec(); return psock->getSockCreationMicroSec();
} }
private: private:
 End of changes. 1 change blocks. 
1 lines changed or deleted 5 lines changed or added


 misc.h   misc.h 
skipping to change at line 111 skipping to change at line 111
// Like strlen, but only scans up to n bytes. // Like strlen, but only scans up to n bytes.
// Returns -1 if no '0' found. // Returns -1 if no '0' found.
inline int strnlen( const char *s, int n ) { inline int strnlen( const char *s, int n ) {
for( int i = 0; i < n; ++i ) for( int i = 0; i < n; ++i )
if ( !s[ i ] ) if ( !s[ i ] )
return i; return i;
return -1; return -1;
} }
inline bool isNumber( char c ) {
return c >= '0' && c <= '9';
}
inline unsigned stringToNum(const char *str) {
unsigned x = 0;
const char *p = str;
while( 1 ) {
if( !isNumber(*p) ) {
if( *p == 0 && p != str )
break;
throw 0;
}
x = x * 10 + *p++ - '0';
}
return x;
}
} }
 End of changes. 1 change blocks. 
18 lines changed or deleted 0 lines changed or added


 mock_dbclient_connection.h   mock_dbclient_connection.h 
skipping to change at line 19 skipping to change at line 19
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include "mongo/client/dbclientinterface.h" #include "mongo/client/dbclientinterface.h"
#include "mongo/dbtests/mock/mock_remote_db_server.h" #include "mongo/dbtests/mock/mock_remote_db_server.h"
namespace mongo_test { namespace mongo {
/** /**
* A simple class for mocking mongo::DBClientConnection. * A simple class for mocking mongo::DBClientConnection.
* *
* Also check out sample usage in dbtests/mock_dbclient_conn_test.cpp * Also check out sample usage in dbtests/mock_dbclient_conn_test.cpp
*/ */
class MockDBClientConnection : public mongo::DBClientConnection { class MockDBClientConnection : public mongo::DBClientConnection {
public: public:
/** /**
* Create a mock connection to a mock server. * Create a mock connection to a mock server.
* *
* @param remoteServer the remote server to connect to. The caller is * @param remoteServer the remote server to connect to. The caller is
* responsible for making sure that the life of remoteServer is * responsible for making sure that the life of remoteServer is
* longer than this connection. * longer than this connection.
* @param autoReconnect will automatically re-establish connection
the
* next time an operation is requested when the last operation
caused
* this connection to fall into a failed state.
*/ */
MockDBClientConnection(MockRemoteDBServer* remoteServer); MockDBClientConnection(MockRemoteDBServer* remoteServer, bool autoR econnect = false);
virtual ~MockDBClientConnection(); virtual ~MockDBClientConnection();
// //
// DBClientBase methods // DBClientBase methods
// //
bool connect(const char* hostName, std::string& errmsg);
inline bool connect(const HostAndPort& host, std::string& errmsg) {
return connect(host.toString().c_str(), errmsg);
}
bool runCommand(const std::string& dbname, const mongo::BSONObj& cm dObj, bool runCommand(const std::string& dbname, const mongo::BSONObj& cm dObj,
mongo::BSONObj &info, int options = 0, mongo::BSONObj &info, int options = 0);
const mongo::AuthenticationTable* auth = NULL);
std::auto_ptr<mongo::DBClientCursor> query(const std::string &ns, std::auto_ptr<mongo::DBClientCursor> query(const std::string &ns,
mongo::Query query = mongo::Query(), mongo::Query query = mongo::Query(),
int nToReturn = 0, int nToReturn = 0,
int nToSkip = 0, int nToSkip = 0,
const mongo::BSONObj* fieldsToReturn = 0, const mongo::BSONObj* fieldsToReturn = 0,
int queryOptions = 0, int queryOptions = 0,
int batchSize = 0); int batchSize = 0);
uint64_t getSockCreationMicroSec() const; uint64_t getSockCreationMicroSec() const;
virtual void insert(const string& ns, BSONObj obj, int flags = 0);
virtual void insert(const string& ns, const vector<BSONObj>& objLis
t, int flags = 0);
virtual void remove(const string& ns, Query query, bool justOne = f
alse);
virtual void remove(const string& ns, Query query, int flags = 0);
// //
// Getters // Getters
// //
mongo::ConnectionString::ConnectionType type() const; mongo::ConnectionString::ConnectionType type() const;
bool isFailed() const; bool isFailed() const;
double getSoTimeout() const; double getSoTimeout() const;
std::string getServerAddress() const; std::string getServerAddress() const;
std::string toString(); std::string toString();
skipping to change at line 97 skipping to change at line 112
void killCursor(long long cursorID); void killCursor(long long cursorID);
bool callRead(mongo::Message& toSend , mongo::Message& response); bool callRead(mongo::Message& toSend , mongo::Message& response);
bool call(mongo::Message& toSend, mongo::Message& response, bool as sertOk = true, bool call(mongo::Message& toSend, mongo::Message& response, bool as sertOk = true,
std::string* actualServer = 0); std::string* actualServer = 0);
void say(mongo::Message& toSend, bool isRetry = false, std::string* actualServer = 0); void say(mongo::Message& toSend, bool isRetry = false, std::string* actualServer = 0);
void sayPiggyBack(mongo::Message& toSend); void sayPiggyBack(mongo::Message& toSend);
bool lazySupported() const; bool lazySupported() const;
private: private:
const MockRemoteDBServer::InstanceID _remoteServerInstanceID; void checkConnection();
MockRemoteDBServer::InstanceID _remoteServerInstanceID;
MockRemoteDBServer* _remoteServer; MockRemoteDBServer* _remoteServer;
bool _isFailed; bool _isFailed;
uint64_t _sockCreationTime; uint64_t _sockCreationTime;
bool _autoReconnect;
}; };
} }
 End of changes. 9 change blocks. 
6 lines changed or deleted 28 lines changed or added


 mock_remote_db_server.h   mock_remote_db_server.h 
skipping to change at line 19 skipping to change at line 19
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/client/dbclientinterface.h" #include "mongo/client/dbclientinterface.h"
#include "mongo/platform/unordered_map.h"
#include "mongo/util/concurrency/spin_lock.h" #include "mongo/util/concurrency/spin_lock.h"
namespace mongo_test { namespace mongo {
/** /**
* A very simple mock that acts like a database server. Every object ke eps track of its own * A very simple mock that acts like a database server. Every object ke eps track of its own
* InstanceID, which initially starts at zero and increments every time it is restarted. * InstanceID, which initially starts at zero and increments every time it is restarted.
* This is primarily used for simulating the state of which old connect ions won't be able * This is primarily used for simulating the state of which old connect ions won't be able
* to talk to the sockets that has already been closed on this server. * to talk to the sockets that has already been closed on this server.
* *
* Note: All operations on this server are protected by a lock. * Note: All operations on this server are protected by a lock.
*/ */
class MockRemoteDBServer { class MockRemoteDBServer {
public: public:
typedef size_t InstanceID; typedef size_t InstanceID;
/** /**
* Creates a new mock server. This also setups a hook to this serve * Creates a new mock server. This can also be setup to work with t
r that can be used he
* to allow clients using the ConnectionString::connect interface t * ConnectionString class by using mongo::MockConnRegistry as follo
o create connections ws:
* to this server. The requirements to make this hook fully functio
nal are:
* *
* 1. hostName of this server should start with $. * ConnectionString::setConnectionHook(MockConnRegistry::get()->get
* 2. No other instance has the same hostName as this. ConnStrHook());
* MockRemoteDBServer server("$a:27017");
* MockConnRegistry::get()->addServer(&server);
* *
* To register the hook, simply call setConnectionHook: * This allows clients using the ConnectionString::connect interfac
e to create
* connections to this server. The requirements to make this hook f
ully functional are:
* *
* MockRemoteDBServer mockServer; * 1. hostAndPort of this server should start with $.
* ConnectionString::setConnectionHook(mockServer.getConnectionHook * 2. No other instance has the same hostAndPort as this.
());
* *
* @param hostName the host name for this server. * @param hostAndPort the host name with port for this server.
*
* @see MockConnRegistry
*/ */
MockRemoteDBServer(const std::string& hostName); MockRemoteDBServer(const std::string& hostAndPort);
virtual ~MockRemoteDBServer(); virtual ~MockRemoteDBServer();
/**
* @return the hook that can be used with ConnectionString.
*/
mongo::ConnectionString::ConnectionHook* getConnectionHook();
// //
// Connectivity methods // Connectivity methods
// //
/** /**
* Set a delay for calls to query and runCommand * Set a delay for calls to query and runCommand
*/ */
void setDelay(long long milliSec); void setDelay(long long milliSec);
/** /**
skipping to change at line 113 skipping to change at line 112
* *
* @param cmdName the name of the command. * @param cmdName the name of the command.
* @param replySequence the sequence of replies to cycle through ev ery time * @param replySequence the sequence of replies to cycle through ev ery time
* the given command is requested. This is useful for setting u p a * the given command is requested. This is useful for setting u p a
* sequence of response when the command can be called more tha n once * sequence of response when the command can be called more tha n once
* that requires different results when calling a method. * that requires different results when calling a method.
*/ */
void setCommandReply(const std::string& cmdName, void setCommandReply(const std::string& cmdName,
const std::vector<mongo::BSONObj>& replySequence); const std::vector<mongo::BSONObj>& replySequence);
/**
* Inserts a single document to this server.
*
* @param ns the namespace to insert the document to.
* @param obj the document to insert.
* @param flags ignored.
*/
void insert(const string& ns, BSONObj obj, int flags = 0);
/**
* Removes documents from this server.
*
* @param ns the namespace to remove documents from.
* @param query ignored.
* @param flags ignored.
*/
void remove(const string& ns, Query query, int flags = 0);
// //
// DBClientBase methods // DBClientBase methods
// //
bool runCommand(InstanceID id, const std::string& dbname, bool runCommand(InstanceID id, const std::string& dbname,
const mongo::BSONObj& cmdObj, const mongo::BSONObj& cmdObj,
mongo::BSONObj &info, int options = 0, mongo::BSONObj &info, int options = 0);
const mongo::AuthenticationTable* auth = NULL);
std::auto_ptr<mongo::DBClientCursor> query(InstanceID id, mongo::BSONArray query(InstanceID id,
const std::string &ns, const std::string &ns,
mongo::Query query = mongo::Query(), mongo::Query query = mongo::Query(),
int nToReturn = 0, int nToReturn = 0,
int nToSkip = 0, int nToSkip = 0,
const mongo::BSONObj* fieldsToReturn = 0, const mongo::BSONObj* fieldsToReturn = 0,
int queryOptions = 0, int queryOptions = 0,
int batchSize = 0); int batchSize = 0);
// //
// Getters // Getters
// //
InstanceID getInstanceID() const; InstanceID getInstanceID() const;
mongo::ConnectionString::ConnectionType type() const; mongo::ConnectionString::ConnectionType type() const;
double getSoTimeout() const; double getSoTimeout() const;
/**
* @return the exact string address passed to hostAndPort parameter
of the
* constructor. In other words, doesn't automatically append a
* 'default' port if none is specified.
*/
std::string getServerAddress() const; std::string getServerAddress() const;
std::string toString(); std::string toString();
// //
// Call counters // Call counters
// //
size_t getCmdCount() const; size_t getCmdCount() const;
size_t getQueryCount() const; size_t getQueryCount() const;
void clearCounters(); void clearCounters();
skipping to change at line 166 skipping to change at line 188
*/ */
CircularBSONIterator(const std::vector<mongo::BSONObj>& replyVe ctor); CircularBSONIterator(const std::vector<mongo::BSONObj>& replyVe ctor);
mongo::BSONObj next(); mongo::BSONObj next();
private: private:
std::vector<mongo::BSONObj>::iterator _iter; std::vector<mongo::BSONObj>::iterator _iter;
std::vector<mongo::BSONObj> _replyObjs; std::vector<mongo::BSONObj> _replyObjs;
}; };
/** /**
* Custom connection hook that can be used with ConnectionString.
*/
class MockDBClientConnStrHook: public mongo::ConnectionString::Conn
ectionHook {
public:
/**
* Creates a new connection hook for the ConnectionString class
that
* can create mock connections to this server.
*
* @param replSet the mock replica set. Caller is responsible f
or managing
* mockServer and making sure that it lives longer than thi
s object.
*/
MockDBClientConnStrHook(MockRemoteDBServer* mockServer);
~MockDBClientConnStrHook();
mongo::DBClientBase* connect(
const mongo::ConnectionString& connString,
std::string& errmsg, double socketTimeout);
private:
MockRemoteDBServer* _mockServer;
};
/**
* Checks whether the instance of the server is still up. * Checks whether the instance of the server is still up.
* *
* @throws mongo::SocketException if this server is down * @throws mongo::SocketException if this server is down
*/ */
void checkIfUp(InstanceID id) const; void checkIfUp(InstanceID id) const;
typedef std::map<std::string, boost::shared_ptr<CircularBSONIterato typedef unordered_map<std::string, boost::shared_ptr<CircularBSONIt
r> > CmdToReplyObj; erator> > CmdToReplyObj;
typedef unordered_map<std::string, mongo::BSONArrayBuilder*> MockDa
taMgr;
bool _isRunning; bool _isRunning;
std::string _hostName; const std::string _hostAndPort;
long long _delayMilliSec; long long _delayMilliSec;
//
// Mock replies
//
CmdToReplyObj _cmdMap; CmdToReplyObj _cmdMap;
MockDataMgr _dataMgr;
// //
// Op Counters // Op Counters
// //
size_t _cmdCount; size_t _cmdCount;
size_t _queryCount; size_t _queryCount;
// Unique id for every restart of this server used for rejecting re quests from // Unique id for every restart of this server used for rejecting re quests from
// connections that are still "connected" to the old instance // connections that are still "connected" to the old instance
InstanceID _instanceID; InstanceID _instanceID;
// protects this entire instance // protects this entire instance
mutable mongo::SpinLock _lock; mutable mongo::SpinLock _lock;
MockDBClientConnStrHook _connStrHook;
}; };
} }
 End of changes. 21 change blocks. 
56 lines changed or deleted 57 lines changed or added


 mock_replica_set.h   mock_replica_set.h 
skipping to change at line 25 skipping to change at line 25
#pragma once #pragma once
#include "mongo/dbtests/mock/mock_remote_db_server.h" #include "mongo/dbtests/mock/mock_remote_db_server.h"
#include "mongo/db/repl/rs_config.h" #include "mongo/db/repl/rs_config.h"
#include <string> #include <string>
#include <map> #include <map>
#include <vector> #include <vector>
namespace mongo_test { namespace mongo {
/** /**
* This is a helper class for managing a replica set consisting of * This is a helper class for managing a replica set consisting of
* MockRemoteDBServer instances. * MockRemoteDBServer instances.
* *
* Note: Be sure to call ScopedDbConnection::clearPool() after every te
st
* when doing tests that involves the ReplicaSetMonitor. This is becaus
e
* it uses ScopedDbConnection which means you can have a residue connec
tions
* that was created from previous tests and can cause a seg fault if th
e
* MockRemoteDBServer instances were already destroyed.
*
* Warning: Not thread-safe * Warning: Not thread-safe
*/ */
class MockReplicaSet { class MockReplicaSet {
public: public:
typedef std::map<std::string, ReplSetConfig::MemberCfg> ReplConfigM
ap;
/** /**
* Creates a mock replica set and automatically mocks the isMaster * Creates a mock replica set and automatically mocks the isMaster
* and replSetGetStatus commands based on the default replica set * and replSetGetStatus commands based on the default replica set
* configuration. * configuration.
* *
* @param setName The name for this replica set * @param setName The name for this replica set
* @param nodes The initial number of nodes for this replica set * @param nodes The initial number of nodes for this replica set
*/ */
MockReplicaSet(const std::string& setName, size_t nodes); MockReplicaSet(const std::string& setName, size_t nodes);
~MockReplicaSet(); ~MockReplicaSet();
// //
// getters // getters
// //
std::string getSetName() const; std::string getSetName() const;
std::string getConnectionString() const; std::string getConnectionString() const;
std::vector<mongo::HostAndPort> getHosts() const; std::vector<HostAndPort> getHosts() const;
mongo::ConnectionString::ConnectionHook* getConnectionHook(); ReplConfigMap getReplConfig() const;
const std::vector<mongo::ReplSetConfig::MemberCfg>& getReplConfig()
const;
std::string getPrimary() const; std::string getPrimary() const;
const std::vector<std::string>&; getSecondaries() const; std::vector<std::string>; getSecondaries() const;
/** /**
* Sets the configuration for this replica sets. This also has a si de effect * Sets the configuration for this replica sets. This also has a si de effect
* of mocking the ismaster and replSetGetStatus command responses b ased on * of mocking the ismaster and replSetGetStatus command responses b ased on
* the new config. * the new config.
*
* Note: does not automatically select a new primary. Can be done m
anually by
* calling setPrimary.
*/ */
void setConfig(const std::vector<mongo::ReplSetConfig::MemberCfg>& void setConfig(const ReplConfigMap& newConfig);
newConfig);
void setPrimary(const std::string& hostAndPort);
/** /**
* @return pointer to the mocked remote server with the given hostN ame. * @return pointer to the mocked remote server with the given hostN ame.
* NULL if host doesn't exists. * NULL if host doesn't exists.
*/ */
MockRemoteDBServer* getNode(const std::string& hostName); MockRemoteDBServer* getNode(const std::string& hostAndPort);
/** /**
* Kills a node. * Kills a node belonging to this set.
* *
* @param hostName the name of the replica node to kill. * @param hostName the name of the replica node to kill.
*/ */
void kill(const std::string& hostName); void kill(const std::string& hostAndPort);
/**
* Kills a set of host belonging to this set.
*
* @param hostList the list of host names of the servers to kill.
*/
void kill(const std::vector<std::string>& hostList);
/** /**
* Reboots a node. * Reboots a node.
* *
* @param hostName the name of the host to reboot. * @param hostName the name of the host to reboot.
*/ */
void restore(const std::string& hostName); void restore(const std::string& hostName);
private: private:
class ReplSetConnHook: public mongo::ConnectionString::ConnectionHo typedef std::map<std::string, MockRemoteDBServer*> ReplNodeMap;
ok {
public:
/**
* Creates a new connection hook for the ConnectionString class
that
* can create mock connections to mock replica set members usin
g their
* pseudo host names.
*
* @param replSet the mock replica set. Caller is responsible f
or managing
* replSet and making sure that it lives longer than this o
bject.
*/
ReplSetConnHook(MockReplicaSet* replSet);
~ReplSetConnHook();
mongo::DBClientBase* connect(
const mongo::ConnectionString& connString,
std::string& errmsg, double socketTimeout);
private:
MockReplicaSet* _replSet;
};
/** /**
* Mocks the ismaster command based on the information on the curre nt * Mocks the ismaster command based on the information on the curre nt
* replica set configuration. * replica set configuration.
*/ */
void mockIsMasterCmd(); void mockIsMasterCmd();
/** /**
* Mocks the replSetGetStatus command based on the current states o f the * Mocks the replSetGetStatus command based on the current states o f the
* mocked servers. * mocked servers.
*/ */
void mockReplSetGetStatusCmd(); void mockReplSetGetStatusCmd();
/** /**
* @return the replica set state of the given host * @return the replica set state of the given host
*/ */
int getState(const std::string& host) const; int getState(const std::string& hostAndPort) const;
const std::string _setName; const std::string _setName;
std::map<std::string, MockRemoteDBServer*> _nodeMap; ReplNodeMap _nodeMap;
ReplSetConnHook _connStringHook; ReplConfigMap _replConfig;
std::vector<mongo::ReplSetConfig::MemberCfg> _replConfig;
std::string _primaryHost; std::string _primaryHost;
std::vector<std::string> _secondaryHosts;
}; };
} }
 End of changes. 14 change blocks. 
41 lines changed or deleted 38 lines changed or added


 mongo_authentication_session.h   mongo_authentication_session.h 
/* /* Copyright 2012 10gen Inc.
* Copyright (C) 2012 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License");
* it under the terms of the GNU Affero General Public License, version * you may not use this file except in compliance with the License.
3, * You may obtain a copy of the License at
* as published by the Free Software Foundation.
* *
* 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
* GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Lice * Unless required by applicable law or agreed to in writing, software
nse * distributed under the License is distributed on an "AS IS" BASIS,
* along with this program. If not, see <http://www.gnu.org/licenses/>. * 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.
*/ */
#pragma once #pragma once
#include "mongo/db/auth/authentication_session.h" #include "mongo/db/auth/authentication_session.h"
namespace mongo { namespace mongo {
typedef unsigned long long nonce64; typedef unsigned long long nonce64;
 End of changes. 4 change blocks. 
13 lines changed or deleted 11 lines changed or added


 mr.h   mr.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 "mongo/pch.h" #include <boost/scoped_ptr.hpp>
#include <string>
#include <vector>
#include "mongo/db/auth/privilege.h"
#include "mongo/db/curop.h"
#include "mongo/db/instance.h"
#include "mongo/db/jsobj.h"
#include "mongo/scripting/engine.h"
namespace mongo { namespace mongo {
namespace mr { namespace mr {
typedef vector<BSONObj> BSONList; typedef vector<BSONObj> BSONList;
class State; class State;
// ------------ function interfaces ----------- // ------------ function interfaces -----------
skipping to change at line 178 skipping to change at line 186
scoped_ptr<Mapper> mapper; scoped_ptr<Mapper> mapper;
scoped_ptr<Reducer> reducer; scoped_ptr<Reducer> reducer;
scoped_ptr<Finalizer> finalizer; scoped_ptr<Finalizer> finalizer;
BSONObj mapParams; BSONObj mapParams;
BSONObj scopeSetup; BSONObj scopeSetup;
// output tables // output tables
string incLong; string incLong;
string tempLong; string tempNamespace;
string finalShort; enum OutputType {
string finalLong; REPLACE , // atomically replace the collection
MERGE , // merge keys, override dups
REDUCE , // merge keys, reduce dups
INMEMORY // only store in memory, limited in size
};
struct OutputOptions {
string outDB;
string collectionName;
string finalNamespace;
// if true, no lock during output operation
bool outNonAtomic;
OutputType outType;
} outputOptions;
string outDB; static OutputOptions parseOutputOptions(const string& dbname, c onst BSONObj& cmdObj);
// max number of keys allowed in JS map before switching mode // max number of keys allowed in JS map before switching mode
long jsMaxKeys; long jsMaxKeys;
// ratio of duplicates vs unique keys before reduce is triggere d in js mode // ratio of duplicates vs unique keys before reduce is triggere d in js mode
float reduceTriggerRatio; float reduceTriggerRatio;
// maximum size of map before it gets dumped to disk // maximum size of map before it gets dumped to disk
long maxInMemSize; long maxInMemSize;
enum { REPLACE , // atomically replace the collection
MERGE , // merge keys, override dups
REDUCE , // merge keys, reduce dups
INMEMORY // only store in memory, limited in size
} outType;
// if true, no lock during output operation
bool outNonAtomic;
// true when called from mongos to do phase-1 of M/R // true when called from mongos to do phase-1 of M/R
bool shardedFirstPass; bool shardedFirstPass;
static AtomicUInt JOB_NUMBER; static AtomicUInt JOB_NUMBER;
}; // end MRsetup }; // end MRsetup
/** /**
* stores information about intermediate map reduce state * stores information about intermediate map reduce state
* controls flow of data from map->reduce->finalize->output * controls flow of data from map->reduce->finalize->output
*/ */
skipping to change at line 320 skipping to change at line 331
bool _jsMode; bool _jsMode;
ScriptingFunction _reduceAll; ScriptingFunction _reduceAll;
ScriptingFunction _reduceAndEmit; ScriptingFunction _reduceAndEmit;
ScriptingFunction _reduceAndFinalize; ScriptingFunction _reduceAndFinalize;
ScriptingFunction _reduceAndFinalizeAndInsert; ScriptingFunction _reduceAndFinalizeAndInsert;
}; };
BSONObj fast_emit( const BSONObj& args, void* data ); BSONObj fast_emit( const BSONObj& args, void* data );
BSONObj _bailFromJS( const BSONObj& args, void* data ); BSONObj _bailFromJS( const BSONObj& args, void* data );
void addPrivilegesRequiredForMapReduce(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out)
;
} // end mr namespace } // end mr namespace
} }
 End of changes. 6 change blocks. 
14 lines changed or deleted 29 lines changed or added


 mutable_bson.h   mutable_bson.h 
skipping to change at line 32 skipping to change at line 32
#include "mongo/base/status.h" #include "mongo/base/status.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/platform/cstdint.h" #include "mongo/platform/cstdint.h"
#include "mongo/util/safe_num.h" #include "mongo/util/safe_num.h"
namespace mongo { namespace mongo {
namespace mutablebson { namespace mutablebson {
class Document; class Document;
class ElementVector; class ElementVector;
class FilterIterator;
class Heap; class Heap;
class SiblingIterator; class SiblingIterator;
struct ElementRep; struct ElementRep;
/* /*
* The Element class represents one node in the document tree. A docume nt is * The Element class represents one node in the document tree. A docume nt is
* identified with its root node. * identified with its root node.
* *
* Elements are created with the help of the Document class. Once creat ed, an * Elements are created with the help of the Document class. Once creat ed, an
* element can be introduced in any position in a document tree with me thods * element can be introduced in any position in a document tree with me thods
skipping to change at line 60 skipping to change at line 59
* // Document is: {} * // Document is: {}
* *
* mutablebson::Element e0 = doc.makeObjElement("e0"); * mutablebson::Element e0 = doc.makeObjElement("e0");
* doc.root().addChild(e0); * doc.root().addChild(e0);
* // Document is: { e0 : {} } * // Document is: { e0 : {} }
* *
* mutablebson::Element e1 = doc.makeObjElement("e1"); * mutablebson::Element e1 = doc.makeObjElement("e1");
* e0.addChild(e1); * e0.addChild(e1);
* // Document is: { e0 : { e1 : {} } } * // Document is: { e0 : { e1 : {} } }
* *
* // traversal * TODO: Add iteration and search examples
* mutablebson::SubtreeIterator it(&doc, e0);
* while (!it.done()) {
* cout << mutablebson::Element(&doc, it.getRep()).fieldName())
<< endl;
* }
* *
* // look up
* mutablebson::FilterIterator it = e0.find("e1");
* if (!it.done()) {
* cout << mongo::mutablebson::Element(&doc, it.getRep()).field
Name( ) << endl;
* }
*/ */
class Element { class Element {
public: public:
Element(Document* doc, uint32_t rep) Element(Document* doc, uint32_t rep)
: _doc(doc) : _doc(doc)
, _rep(rep) {} , _rep(rep) {}
~Element() {} ~Element() {}
// //
// navigation API // navigation API
// //
Element leftChild() const; Element leftChild() const;
Element rightChild() const; Element rightChild() const;
Element leftSibling() const; Element leftSibling() const;
Element rightSibling() const; Element rightSibling() const;
Element parent() const; Element parent() const;
/** Find subtree nodes with a given name */
FilterIterator find(const std::string& fieldName) const;
/** Iterate children of this node */ /** Iterate children of this node */
SiblingIterator children(); SiblingIterator children();
// //
// update API // update API
// //
Status addChild(Element e); Status addChild(Element e);
Status addSiblingBefore(Element e); Status addSiblingBefore(Element e);
Status addSiblingAfter(Element e); Status addSiblingAfter(Element e);
Status remove(); Status remove();
Status rename(const std::string& newName); Status rename(const StringData& newName);
Status move(Element newParent); Status move(Element newParent);
// //
// array API // array API
// //
Status arraySize(uint32_t* size); Status arraySize(uint32_t* size);
Status peekBack(Element* ep); Status peekBack(Element* ep);
Status pushBack(Element e); Status pushBack(Element e);
Status popBack(); Status popBack();
skipping to change at line 160 skipping to change at line 147
void setBoolValue(bool boolVal); void setBoolValue(bool boolVal);
void setIntValue(int32_t intVal); void setIntValue(int32_t intVal);
void setLongValue(int64_t longVal); void setLongValue(int64_t longVal);
void setTSValue(OpTime tsVal); void setTSValue(OpTime tsVal);
void setDateValue(int64_t millis); void setDateValue(int64_t millis);
void setDoubleValue(double doubleVal); void setDoubleValue(double doubleVal);
void setOIDValue(const OID& oid); void setOIDValue(const OID& oid);
void setStringValue(const StringData& stringVal); void setStringValue(const StringData& stringVal);
void setRegexValue(const StringData& re); void setRegexValue(const StringData& re);
void setSafeNumValue(const SafeNum& safeNum); void setSafeNumValue(const SafeNum& safeNum);
void setMinKey();
void setMaxKey();
void setUndefined();
void setNull();
void setSymbol(const StringData& symbolVal);
/** Set the value of this element to equal the value of the
* provided BSONElement 'val'. The name of this Element is
* not modified.
*/
void setValueFromBSONElement(const BSONElement& val);
// additional methods needed for BSON decoding // additional methods needed for BSON decoding
Status prefix(std::string* result, char delim) const; Status prefix(std::string* result, char delim) const;
Status suffix(std::string* result, char delim) const; Status suffix(std::string* result, char delim) const;
Status regex(std::string* result) const; Status regex(std::string* result) const;
Status regexFlags(std::string* result) const; Status regexFlags(std::string* result) const;
Status dbrefNS(std::string* result) const; Status dbrefNS(std::string* result) const;
Status dbrefOID(std::string* result) const; Status dbrefOID(std::string* result) const;
Status codeWScopeCode(std::string* result) const; Status codeWScopeCode(std::string* result) const;
Status codeWScopeScope(std::string* result) const; Status codeWScopeScope(std::string* result) const;
skipping to change at line 208 skipping to change at line 206
Status appendRegex( Status appendRegex(
const StringData& fieldName, const StringData& re, const String Data& flags); const StringData& fieldName, const StringData& re, const String Data& flags);
Status appendCodeWScope( Status appendCodeWScope(
const StringData& fieldName, const StringData& code, const Stri ngData& scope); const StringData& fieldName, const StringData& code, const Stri ngData& scope);
Status appendBinary( Status appendBinary(
const StringData& fieldName, uint32_t len, BinDataType t, const void* bin); const StringData& fieldName, uint32_t len, BinDataType t, const void* bin);
Status appendSafeNum(const StringData& fieldName, const SafeNum num ); Status appendSafeNum(const StringData& fieldName, const SafeNum num );
// //
// operator overloading
//
friend std::ostream& operator<<(std::ostream&, const Element&);
//
// encapsulate state // encapsulate state
// //
uint32_t getRep() const; uint32_t getRep() const { return _rep; };
void setRep(uint32_t rep); Document* getDocument() const { return _doc; }
Document* getDocument() const;
void setDocument(Document* doc);
std::string fieldName() const;
int fieldNameSize() const;
//
// output : mainly for debugging
//
std::ostream& put(std::ostream& os, uint32_t depth) const;
std::ostream& putValue(std::ostream& os) const;
std::string putType() const;
//
// For testing/debugging only: treat as private
//
ElementRep& getElementRep();
ElementRep& getElementRep() const;
// StringData getFieldName() const;
// helper methods
//
Status checkSubtreeIsClean(Element e);
private: private:
inline Status checkSubtreeIsClean(Element e);
// We carry the document in every element. The document determines the element: // We carry the document in every element. The document determines the element:
// '_rep' is resolved through the document ElementVector and Heap // '_rep' is resolved through the document ElementVector and Heap
Document* _doc; Document* _doc;
uint32_t _rep; uint32_t _rep;
}; };
/** /**
* Document contains the root node, and factory methods for * Document contains the root node, and factory methods for
* creating new nodes. Storage is allocated for the nodes within * creating new nodes. Storage is allocated for the nodes within
* the Content heap, and the document tree structure is stored in * the Content heap, and the document tree structure is stored in
skipping to change at line 274 skipping to change at line 244
public: public:
explicit Document(Heap* heap); explicit Document(Heap* heap);
~Document(); ~Document();
// //
// getters, (setters?) // getters, (setters?)
// //
Heap* getHeap() { return _heap; } Heap* getHeap() { return _heap; }
const Heap* getHeap() const { return _heap; } const Heap* getHeap() const { return _heap; }
std::string getString(uint32_t offset) const;
char* getStringBuffer(uint32_t offset) const;
uint32_t elementVectorSize() const;
// //
// The distinguished root Element of the document, which is // The distinguished root Element of the document, which is
// always an Object element. // always an Object element.
// //
Element& root() { return _root; } Element& root() { return _root; }
const Element& root() const { return _root; } const Element& root() const { return _root; }
// //
// factory methods // factory methods
skipping to change at line 317 skipping to change at line 284
const StringData& fieldName, const StringData& regex, const Str ingData& flags); const StringData& fieldName, const StringData& regex, const Str ingData& flags);
Element makeCodeWScopeElement( Element makeCodeWScopeElement(
const StringData& fieldName, const StringData& code, const Stri ngData& scope); const StringData& fieldName, const StringData& code, const Stri ngData& scope);
Element makeDBRefElement( Element makeDBRefElement(
const StringData& fieldName, const StringData& ns, const mongo: :OID& oid); const StringData& fieldName, const StringData& ns, const mongo: :OID& oid);
Element makeBinaryElement( Element makeBinaryElement(
const StringData& fieldName, uint32_t len, BinDataType binType, const void* data); const StringData& fieldName, uint32_t len, BinDataType binType, const void* data);
private: private:
friend class Element; friend class Element;
friend class SubtreeIterator;
friend class SiblingIterator; friend class SiblingIterator;
Heap* const _heap; Heap* const _heap;
boost::scoped_ptr<ElementVector> _elements; boost::scoped_ptr<ElementVector> _elements;
Element _root; Element _root;
}; };
// //
// iteration support // iteration support
// //
class Iterator { class Iterator {
public: public:
virtual ~Iterator() {}
Iterator(); Iterator();
Iterator(Element e);
Iterator(const Iterator& it); explicit Iterator(Element e)
: _doc(e.getDocument())
, _theRep(e.getRep()) {}
virtual ~Iterator() {}
// iterator interface // iterator interface
virtual Iterator& operator++() = 0; virtual Iterator& operator++() = 0;
virtual bool done() const = 0; virtual bool done() const = 0;
Element operator*();
Element operator->(); Element operator*() { return Element(getDocument(), getRep()); }
// acessors // acessors
Document* getDocument() const; Document* getDocument() const { return _doc; }
uint32_t getRep() const; uint32_t getRep() const { return _theRep; }
protected: protected:
Document* _doc; Document* _doc;
uint32_t _theRep; uint32_t _theRep;
}; };
/** implementation: subtree pre-order traversal */
class SubtreeIterator : public Iterator {
public:
virtual ~SubtreeIterator();
SubtreeIterator();
SubtreeIterator(Element e);
SubtreeIterator(const SubtreeIterator& it);
// iterator interface
virtual Iterator& operator++();
virtual bool done() const;
protected:
bool advance();
protected: // state
bool _theDoneBit;
};
/** implementation: sibling iterator */ /** implementation: sibling iterator */
class SiblingIterator : public Iterator { class SiblingIterator : public Iterator {
public: public:
~SiblingIterator(); SiblingIterator()
SiblingIterator(); : Iterator() {}
SiblingIterator(Element e);
SiblingIterator(const SiblingIterator& it);
// iterator interface explicit SiblingIterator(Element e)
Iterator& operator++(); : Iterator(e) {}
bool done() const;
protected: // state
bool advance();
};
/** interface: generic node filter - used by FilterIterator */ virtual ~SiblingIterator() {}
class Filter {
public:
virtual ~Filter() {}
// filter interface virtual SiblingIterator& operator++() {
virtual bool match(Element) const = 0; advance();
}; return *this;
}
/** implementation: field name filter */ virtual bool done() const;
class FieldNameFilter : public Filter {
public:
FieldNameFilter(const std::string& fieldName);
~FieldNameFilter();
// filter interface
bool match(Element e) const;
private:
std::string _fieldName;
};
/** implementation: filtered subtree pre-order traversal */
class FilterIterator : public SubtreeIterator {
public:
~FilterIterator();
FilterIterator();
FilterIterator(Element e, const Filter* filt);
FilterIterator(const FilterIterator& it);
// iterator interface
Iterator& operator++();
bool done() const;
private: private:
const Filter* _filter; bool advance();
}; };
} // namespace mutablebson } // namespace mutablebson
} // namespace mongo } // namespace mongo
 End of changes. 23 change blocks. 
124 lines changed or deleted 39 lines changed or added


 mutable_bson_builder.h   mutable_bson_builder.h 
skipping to change at line 27 skipping to change at line 27
#include "mongo/bson/mutable/mutable_bson.h" #include "mongo/bson/mutable/mutable_bson.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
namespace mongo { namespace mongo {
namespace mutablebson { namespace mutablebson {
/** static method for creating a MutableBSON tree from a BSONObj. */ /** static method for creating a MutableBSON tree from a BSONObj. */
class ElementBuilder { class ElementBuilder {
public: public:
static Status parse(Element* dst, const BSONObj& src); static Status parse(const BSONObj& src, Element* dst);
static Status parse(const BSONObj& src, Document* dst) {
return parse(src, &dst->root());
}
}; };
/** static method for creating BSONObj from MutableBSON */ /** static method for creating BSONObj from MutableBSON */
class BSONBuilder { class BSONBuilder {
public: public:
static void buildFromElement(Element src, BSONObjBuilder* dst); static void buildFromElement(Element src, BSONObjBuilder* dst);
static void build(Element src, BSONObjBuilder* dst); static void build(Element src, BSONObjBuilder* dst);
static void build(const Document& src, BSONObjBuilder* dst) {
return build(src.root(), dst);
}
}; };
} // namespace mutablebson } // namespace mutablebson
} // namespace mongo } // namespace mongo
 End of changes. 2 change blocks. 
1 lines changed or deleted 10 lines changed or added


 mutable_bson_internal.h   mutable_bson_internal.h 
skipping to change at line 100 skipping to change at line 100
* *
* Heap * Heap
* [02|aa|03|bbb|01|c|01|d|01|e|01|f|03|xyz|01|g|01|0|01|1|01|2|.. ] * [02|aa|03|bbb|01|c|01|d|01|e|01|f|03|xyz|01|g|01|0|01|1|01|2|.. ]
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
* 0 6 13 18 23 28 33 40 45 50 55 * 0 6 13 18 23 28 33 40 45 50 55
* *
*/ */
static const uint32_t EMPTY_REP = (uint32_t)-1; static const uint32_t EMPTY_REP = (uint32_t)-1;
static const uint32_t NULL_REF = (uint32_t)-1; static const uint32_t NULL_REF = (uint32_t)-1;
static const uint32_t SHORT_LIMIT = 16;
union ValueType { union ValueType {
bool boolVal; bool boolVal;
int32_t intVal; int32_t intVal;
int64_t longVal; int64_t longVal;
int64_t tsVal; int64_t tsVal;
int64_t dateVal; int64_t dateVal;
double doubleVal; double doubleVal;
char shortStr[16]; /* OID and short strings */ char shortStr[SHORT_LIMIT]; /* OID and short strings */
uint64_t valueRef; /* index to heap (strings, binary, regex) */ uint64_t valueRef; /* index to heap (strings, binary, regex) */
}; };
/** /**
fixed-width node - stored in Document ElementVector fixed-width node - stored in Document ElementVector
"rep" is a name coined by Stroustrup in his original "rep" is a name coined by Stroustrup in his original
std::string implementation. It means "representative". std::string implementation. It means "representative".
Element is the abstraction, ElementRep is the implementation class. Element is the abstraction, ElementRep is the implementation class.
Algorithms manipulate Elements. ElementRep's can be swapped out Algorithms manipulate Elements. ElementRep's can be swapped out
without change upstairs. without change upstairs.
*/ */
struct ElementRep { struct ElementRep {
ElementRep(); ElementRep()
ElementRep(int32_t type); : _type(mongo::Undefined)
ElementRep(int32_t type, uint32_t nameref); , _nameref(NULL_REF)
ElementRep(int32_t type, uint32_t nameref, ValueType value); , _parent(EMPTY_REP) {
ElementRep(int32_t type, uint32_t nameref, ValueType value, uint32_ _child._left = EMPTY_REP;
t parentref); _child._right = EMPTY_REP;
~ElementRep() ; _sibling._left = EMPTY_REP;
_sibling._right = EMPTY_REP;
std::ostream& put(std::ostream&) const; }
void clearSiblings();
void clearParent(); ElementRep(int32_t type)
: _type(type)
, _nameref(NULL_REF)
, _parent(EMPTY_REP) {
_child._left = EMPTY_REP;
_child._right = EMPTY_REP;
_sibling._left = EMPTY_REP;
_sibling._right = EMPTY_REP;
}
ElementRep(int32_t type, uint32_t nameref)
: _type(type)
, _nameref(nameref)
, _parent(EMPTY_REP) {
_child._left = EMPTY_REP;
_child._right = EMPTY_REP;
_sibling._left = EMPTY_REP;
_sibling._right = EMPTY_REP;
}
ElementRep(int32_t type, uint32_t nameref, ValueType value)
: _type(type)
, _nameref(nameref)
, _value(value)
, _parent(EMPTY_REP) {
_sibling._left = EMPTY_REP;
_sibling._right = EMPTY_REP;
}
ElementRep(int32_t type, uint32_t nameref, ValueType value, uint32_
t parentref)
: _type(type)
, _nameref(nameref)
, _value(value)
, _parent(parentref) {
_sibling._left = EMPTY_REP;
_sibling._right = EMPTY_REP;
}
void clearSiblings() {
_sibling._left = EMPTY_REP;
_sibling._right = EMPTY_REP;
}
void clearParent() {
_parent = EMPTY_REP;
}
int32_t _type; int32_t _type;
uint32_t _nameref; uint32_t _nameref;
union { union {
ValueType _value; ValueType _value;
struct { struct {
uint32_t _left; uint32_t _left;
uint32_t _right; uint32_t _right;
} _child; } _child;
skipping to change at line 153 skipping to change at line 200
struct { struct {
uint32_t _left; uint32_t _left;
uint32_t _right; uint32_t _right;
} _sibling; } _sibling;
uint32_t _parent; uint32_t _parent;
}; };
/** node store - as vector of ElementRep's */ /** node store - as vector of ElementRep's */
class ElementVector { class ElementVector {
public: public:
ElementVector();
~ElementVector();
// vector interface // vector interface
void push_back(const ElementRep& elemRep); void push_back(const ElementRep& elemRep) { _vec.push_back(elemRep)
ElementRep& operator[](uint32_t index); ; }
const ElementRep& operator[](uint32_t index) const; ElementRep& operator[](uint32_t index) { return _vec[index]; }
uint32_t size() const; const ElementRep& operator[](uint32_t index) const { return _vec[in
dex]; }
uint32_t size() const { return _vec.size(); }
private: private:
friend class Element; friend class Element;
friend class SubtreeIterator;
friend class SiblingIterator; friend class SiblingIterator;
std::vector<ElementRep> _vec; std::vector<ElementRep> _vec;
}; };
} // namespace mutablebson } // namespace mutablebson
} // namespace mongo } // namespace mongo
 End of changes. 6 change blocks. 
20 lines changed or deleted 65 lines changed or added


 namespace-inl.h   namespace-inl.h 
skipping to change at line 25 skipping to change at line 25
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/db/namespace.h" #include "mongo/db/namespace.h"
namespace mongo { namespace mongo {
inline Namespace& Namespace::operator=(const char *ns) { inline Namespace& Namespace::operator=(const StringData& ns) {
// we fill the remaining space with all zeroes here. as the full N amespace struct is in // we fill the remaining space with all zeroes here. as the full N amespace struct is in
// the datafiles (the .ns files specifically), that is helpful as t hen they are deterministic // the datafiles (the .ns files specifically), that is helpful as t hen they are deterministic
// in the bytes they have for a given sequence of operations. that makes testing and debugging // in the bytes they have for a given sequence of operations. that makes testing and debugging
// the data files easier. // the data files easier.
// //
// if profiling indicates this method is a significant bottleneck, we could have a version we // if profiling indicates this method is a significant bottleneck, we could have a version we
// use for reads which does not fill with zeroes, and keep the zero ing behavior on writes. // use for reads which does not fill with zeroes, and keep the zero ing behavior on writes.
// //
unsigned len = strlen(ns); memset( buf, 0, MaxNsLen );
uassert( 10080 , "ns name too long, max size is 128", len < MaxNsLe uassert( 10080 , "ns name too long, max size is 128", ns.size() < M
n); axNsLen - 1);
memset(buf, 0, MaxNsLen); ns.copyTo( buf, true );
memcpy(buf, ns, len);
return *this; return *this;
} }
inline string Namespace::extraName(int i) const { inline string Namespace::extraName(int i) const {
char ex[] = "$extra"; char ex[] = "$extra";
ex[5] += i; ex[5] += i;
string s = string(buf) + ex; string s = string(buf) + ex;
massert( 10348 , "$extra: ns name too long", s.size() < MaxNsLen); massert( 10348 , "$extra: ns name too long", s.size() < MaxNsLen);
return s; return s;
} }
 End of changes. 2 change blocks. 
6 lines changed or deleted 5 lines changed or added


 namespace.h   namespace.h 
skipping to change at line 31 skipping to change at line 31
#include "mongo/pch.h" #include "mongo/pch.h"
#include <cstring> #include <cstring>
#include <string> #include <string>
namespace mongo { namespace mongo {
#pragma pack(1) #pragma pack(1)
class Namespace { class Namespace {
public: public:
explicit Namespace(const char *ns) { *this = ns; } Namespace(const StringData& ns) { *this = ns; }
Namespace& operator=(const char *ns); Namespace& operator=(const StringData& ns);
bool hasDollarSign() const { return strchr( buf , '$' ) > 0; } bool hasDollarSign() const { return strchr( buf , '$' ) > 0; }
void kill() { buf[0] = 0x7f; } void kill() { buf[0] = 0x7f; }
bool operator==(const char *r) const { return strcmp(buf, r) == 0; } bool operator==(const char *r) const { return strcmp(buf, r) == 0; }
bool operator==(const Namespace& r) const { return strcmp(buf, r.bu f) == 0; } bool operator==(const Namespace& r) const { return strcmp(buf, r.bu f) == 0; }
int hash() const; // value returned is always > 0 int hash() const; // value returned is always > 0
size_t size() const { return strlen( buf ); } size_t size() const { return strlen( buf ); }
string toString() const { return buf; } string toString() const { return buf; }
 End of changes. 1 change blocks. 
2 lines changed or deleted 2 lines changed or added


 namespace_details.h   namespace_details.h 
skipping to change at line 84 skipping to change at line 84
long long nrecords; long long nrecords;
} stats; } stats;
int lastExtentSize; int lastExtentSize;
int nIndexes; int nIndexes;
private: private:
// ofs 192 // ofs 192
IndexDetails _indexes[NIndexesBase]; IndexDetails _indexes[NIndexesBase];
// ofs 352 (16 byte aligned) // ofs 352 (16 byte aligned)
int _isCapped; // there is wasted space her e if I'm right (ERH) int _isCapped; // there is wasted space her e if I'm right (ERH)
int _maxDocsInCapped; // max # of objects for a ca pped table. TODO: should this be 64 bit? int _maxDocsInCapped; // max # of objects for a ca pped table, -1 for inf.
double _paddingFactor; // 1.0 = no padding. double _paddingFactor; // 1.0 = no padding.
// ofs 386 (16) // ofs 386 (16)
int _systemFlags; // things that the system sets/cares about int _systemFlags; // things that the system sets/cares about
public: public:
DiskLoc capExtent; // the "current" extent we're writing too for a capped collection DiskLoc capExtent; // the "current" extent we're writing too for a capped collection
DiskLoc capFirstNewRecord; DiskLoc capFirstNewRecord;
unsigned short dataFileVersion; // NamespaceDetails version. So we can do backward compatibility in the future. See filever.h unsigned short dataFileVersion; // NamespaceDetails version. So we can do backward compatibility in the future. See filever.h
unsigned short indexFileVersion; unsigned short indexFileVersion;
unsigned long long multiKeyIndexBits; unsigned long long multiKeyIndexBits;
private: private:
// ofs 400 (16) // ofs 400 (16)
unsigned long long reservedA; unsigned long long reservedA;
long long extraOffset; // where the $extra info is l ocated (bytes relative to this) long long extraOffset; // where the $extra info is l ocated (bytes relative to this)
public: public:
int indexBuildInProgress; // 1 if in prog int indexBuildsInProgress; // Number of indexes currentl y being built
private: private:
int _userFlags; int _userFlags;
char reserved[72]; char reserved[72];
/*-------- end data 496 bytes */ /*-------- end data 496 bytes */
public: public:
explicit NamespaceDetails( const DiskLoc &loc, bool _capped ); explicit NamespaceDetails( const DiskLoc &loc, bool _capped );
class Extra { class Extra {
long long _next; long long _next;
public: public:
skipping to change at line 158 skipping to change at line 158
Extent *theCapExtent() const { return capExtent.ext(); } Extent *theCapExtent() const { return capExtent.ext(); }
void advanceCapExtent( const char *ns ); void advanceCapExtent( const char *ns );
DiskLoc __capAlloc(int len); DiskLoc __capAlloc(int len);
DiskLoc cappedAlloc(const char *ns, int len); DiskLoc cappedAlloc(const char *ns, int len);
DiskLoc &cappedFirstDeletedInCurExtent(); DiskLoc &cappedFirstDeletedInCurExtent();
bool nextIsInCapExtent( const DiskLoc &dl ) const; bool nextIsInCapExtent( const DiskLoc &dl ) const;
public: public:
bool isCapped() const { return _isCapped; } bool isCapped() const { return _isCapped; }
long long maxCappedDocs() const { verify( isCapped() ); return _max DocsInCapped; } long long maxCappedDocs() const;
void setMaxCappedDocs( long long max ); void setMaxCappedDocs( long long max );
/**
* @param max in and out, will be adjusted
* @return if the value is valid at all
*/
static bool validMaxCappedDocs( long long* max );
DiskLoc& cappedListOfAllDeletedRecords() { return deletedList[0]; } DiskLoc& cappedListOfAllDeletedRecords() { return deletedList[0]; }
DiskLoc& cappedLastDelRecLastExtent() { return deletedList[1]; } DiskLoc& cappedLastDelRecLastExtent() { return deletedList[1]; }
void cappedDumpDelInfo(); void cappedDumpDelInfo();
bool capLooped() const { return _isCapped && capFirstNewRecord.isVa lid(); } bool capLooped() const { return _isCapped && capFirstNewRecord.isVa lid(); }
bool inCapExtent( const DiskLoc &dl ) const; bool inCapExtent( const DiskLoc &dl ) const;
void cappedCheckMigrate(); void cappedCheckMigrate();
/** /**
* Truncate documents newer than the document at 'end' from the cap ped * Truncate documents newer than the document at 'end' from the cap ped
* collection. The collection cannot be completely emptied using t his * collection. The collection cannot be completely emptied using t his
* function. An assertion will be thrown if that is attempted. * function. An assertion will be thrown if that is attempted.
* @param inclusive - Truncate 'end' as well iff true * @param inclusive - Truncate 'end' as well iff true
*/ */
void cappedTruncateAfter(const char *ns, DiskLoc end, bool inclusiv e); void cappedTruncateAfter(const char *ns, DiskLoc end, bool inclusiv e);
/** Remove all documents from the capped collection */ /** Remove all documents from the capped collection */
void emptyCappedCollection(const char *ns); void emptyCappedCollection(const char *ns);
/* when a background index build is in progress, we don't count the index in nIndexes until /* when a background index build is in progress, we don't count the index in nIndexes until
complete, yet need to still use it in _indexRecord() - thus we u se this function for that. complete, yet need to still use it in _indexRecord() - thus we u se this function for that.
*/ */
int nIndexesBeingBuilt() const { return nIndexes + indexBuildInProg ress; } int getTotalIndexCount() const { return nIndexes + indexBuildsInPro gress; }
/* NOTE: be careful with flags. are we manipulating them in read l ocks? if so, /* NOTE: be careful with flags. are we manipulating them in read l ocks? if so,
this isn't thread safe. TODO this isn't thread safe. TODO
*/ */
enum SystemFlags { enum SystemFlags {
Flag_HaveIdIndex = 1 << 0 // set when we have _id index (ONLY i f ensureIdIndex was called -- 0 if that has never been called) Flag_HaveIdIndex = 1 << 0 // set when we have _id index (ONLY i f ensureIdIndex was called -- 0 if that has never been called)
}; };
enum UserFlags { enum UserFlags {
Flag_UsePowerOf2Sizes = 1 << 0 Flag_UsePowerOf2Sizes = 1 << 0
}; };
IndexDetails& idx(int idxNo, bool missingExpected = false ); IndexDetails& idx(int idxNo, bool missingExpected = false );
/** get the IndexDetails for the index currently being built in the
background. (there is at most one) */
IndexDetails& inProgIdx() {
DEV verify(indexBuildInProgress);
return idx(nIndexes);
}
class IndexIterator { class IndexIterator {
public: public:
int pos() { return i; } // note this is the next one to come int pos() { return i; } // note this is the next one to come
bool more() { return i < n; } bool more() { return i < n; }
IndexDetails& next() { return d->idx(i++); } IndexDetails& next() { return d->idx(i++); }
private: private:
friend class NamespaceDetails; friend class NamespaceDetails;
int i, n; int i, n;
NamespaceDetails *d; NamespaceDetails *d;
IndexIterator(NamespaceDetails *_d); IndexIterator(NamespaceDetails *_d);
skipping to change at line 223 skipping to change at line 222
IndexIterator ii() { return IndexIterator(this); } IndexIterator ii() { return IndexIterator(this); }
/* hackish - find our index # in the indexes array */ /* hackish - find our index # in the indexes array */
int idxNo(const IndexDetails& idx); int idxNo(const IndexDetails& idx);
/* multikey indexes are indexes where there are more than one key i n the index /* multikey indexes are indexes where there are more than one key i n the index
for a single document. see multikey in wiki. for a single document. see multikey in wiki.
for these, we have to do some dedup work on queries. for these, we have to do some dedup work on queries.
*/ */
bool isMultikey(int i) const { return (multiKeyIndexBits & (((unsig ned long long) 1) << i)) != 0; } bool isMultikey(int i) const { return (multiKeyIndexBits & (((unsig ned long long) 1) << i)) != 0; }
void setIndexIsMultikey(const char *thisns, int i); void setIndexIsMultikey(const char *thisns, int i, bool multikey = true);
/** /**
* This fetches the IndexDetails for the next empty index slot. The caller must populate * This fetches the IndexDetails for the next empty index slot. The caller must populate
* returned object. This handles allocating extra index space, if necessary. * returned object. This handles allocating extra index space, if necessary.
*/ */
IndexDetails& getNextIndexDetails(const char* thisns); IndexDetails& getNextIndexDetails(const char* thisns);
/** /**
* Add a new index. This does not add it to system.indexes etc. - just to NamespaceDetails. * Add a new index. This does not add it to system.indexes etc. - just to NamespaceDetails.
* This resets the transient namespace details. * This resets the transient namespace details.
skipping to change at line 312 skipping to change at line 311
} }
} }
/* 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 );
/* Updates the expireAfterSeconds field of the given index to the v
alue in newExpireSecs.
* The specified index must already contain an expireAfterSeconds f
ield, and the value in
* that field and newExpireSecs must both be numeric.
*/
void updateTTLIndex( int idxNo , const BSONElement& newExpireSecs )
;
const int systemFlags() const { return _systemFlags; } const int systemFlags() const { return _systemFlags; }
bool isSystemFlagSet( int flag ) const { return _systemFlags & flag ; } bool isSystemFlagSet( int flag ) const { return _systemFlags & flag ; }
void setSystemFlag( int flag ); void setSystemFlag( int flag );
void clearSystemFlag( int flag ); void clearSystemFlag( int flag );
const int userFlags() const { return _userFlags; } const int userFlags() const { return _userFlags; }
bool isUserFlagSet( int flag ) const { return _userFlags & flag; } bool isUserFlagSet( int flag ) const { return _userFlags & flag; }
/** /**
* these methods only modify NamespaceDetails and do not * these methods only modify NamespaceDetails and do not
skipping to change at line 370 skipping to change at line 375
/* @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
*/ */
static int quantizeAllocationSpace(int allocSize); static int quantizeAllocationSpace(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 a new record. lenToAlloc includes headers. */ /** allocate space for a new record from deleted lists.
@param lenToAlloc is WITH header
@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);
/* add a given record to the deleted chains for this NS */ /* add a given record to the deleted chains for this NS */
void addDeletedRec(DeletedRecord *d, DiskLoc dloc); void addDeletedRec(DeletedRecord *d, DiskLoc dloc);
void dumpDeleted(set<DiskLoc> *extents = 0); void dumpDeleted(set<DiskLoc> *extents = 0);
// Start from firstExtent by default. // Start from firstExtent by default.
DiskLoc firstRecord( const DiskLoc &startExtent = DiskLoc() ) const ; DiskLoc firstRecord( const DiskLoc &startExtent = DiskLoc() ) const ;
// Start from lastExtent by default. // Start from lastExtent by default.
DiskLoc lastRecord( const DiskLoc &startExtent = DiskLoc() ) const; DiskLoc lastRecord( const DiskLoc &startExtent = DiskLoc() ) const;
long long storageSize( int * numExtents = 0 , BSONArrayBuilder * ex tentInfo = 0 ) const; long long storageSize( int * numExtents = 0 , BSONArrayBuilder * ex tentInfo = 0 ) const;
skipping to change at line 502 skipping to change at line 510
* The returned cursor may @throw inside of advance() or recoverFro mYield() in certain error * 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 * cases, for example if a capped overrun occurred during a yield. This indicates that the
* cursor was unable to perform a complete scan. * cursor was unable to perform a complete scan.
* *
* This is a work in progress. Partial list of features not yet im plemented through this * This is a work in progress. Partial list of features not yet im plemented through this
* interface: * interface:
* *
* - covered indexes * - covered indexes
* - in memory sorting * - in memory sorting
*/ */
static shared_ptr<Cursor> getCursor( const char* ns, static shared_ptr<Cursor> getCursor( const StringData& ns,
const BSONObj& query, const BSONObj& query,
const BSONObj& order = BSONObj (), const BSONObj& order = BSONObj (),
const QueryPlanSelectionPolicy & planPolicy = const QueryPlanSelectionPolicy & planPolicy =
QueryPlanSelectionPolicy:: any(), QueryPlanSelectionPolicy:: any(),
const shared_ptr<const ParsedQ uery>& parsedQuery = const shared_ptr<const ParsedQ uery>& parsedQuery =
shared_ptr<const ParsedQue ry>(), shared_ptr<const ParsedQue ry>(),
bool requireOrder = true, bool requireOrder = true,
QueryPlanSummary* singlePlanSu mmary = NULL ); QueryPlanSummary* singlePlanSu mmary = NULL );
/** /**
skipping to change at line 628 skipping to change at line 636
bool exists() const; bool exists() const;
void init() { void init() {
if( !ht ) if( !ht )
_init(); _init();
} }
void add_ns(const char *ns, DiskLoc& loc, bool capped); void add_ns(const char *ns, DiskLoc& loc, bool capped);
void add_ns( const char *ns, const NamespaceDetails &details ); void add_ns( const char *ns, const NamespaceDetails &details );
NamespaceDetails* details(const char *ns) { NamespaceDetails* details(const StringData& ns) {
if ( !ht ) if ( !ht )
return 0; return 0;
Namespace n(ns); Namespace n(ns);
NamespaceDetails *d = ht->get(n); NamespaceDetails *d = ht->get(n);
if ( d && d->isCapped() ) if ( d && d->isCapped() )
d->cappedCheckMigrate(); d->cappedCheckMigrate();
return d; return d;
} }
void kill_ns(const char *ns); void kill_ns(const char *ns);
 End of changes. 11 change blocks. 
15 lines changed or deleted 25 lines changed or added


 namespacestring.h   namespacestring.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 "mongo/util/assert_util.h"
namespace mongo { namespace mongo {
using std::string; using std::string;
/* in the mongo source code, "client" means "database". */ /* in the mongo source code, "client" means "database". */
const int MaxDatabaseNameLen = 128; // max str len for the db name, inc luding null char const size_t MaxDatabaseNameLen = 128; // max str len for the db name, including null char
/* e.g. /* e.g.
NamespaceString ns("acme.orders"); NamespaceString ns("acme.orders");
cout << ns.coll; // "orders" cout << ns.coll; // "orders"
*/ */
class NamespaceString { class NamespaceString {
public: public:
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")
skipping to change at line 136 skipping to change at line 138
private: private:
void init(const char *ns) { void init(const char *ns) {
const char *p = strchr(ns, '.'); const char *p = strchr(ns, '.');
if( p == 0 ) return; if( p == 0 ) return;
db = string(ns, p - ns); db = string(ns, p - ns);
coll = p + 1; coll = p + 1;
} }
}; };
// "database.a.b.c" -> "database" // "database.a.b.c" -> "database"
inline void nsToDatabase(const char *ns, char *database) { inline StringData nsToDatabaseSubstring( const StringData& ns ) {
for( int i = 0; i < MaxDatabaseNameLen; i++ ) { size_t i = ns.find( '.' );
database[i] = ns[i]; if ( i == string::npos ) {
if( database[i] == '.' ) { massert(10078, "nsToDatabase: ns too long", ns.size() < MaxData
database[i] = 0; baseNameLen );
return; return ns;
}
if( database[i] == 0 ) {
return;
}
} }
// other checks should have happened already, this is defensive. th massert(10088, "nsToDatabase: ns too long", i < static_cast<size_t>
us massert not uassert (MaxDatabaseNameLen));
massert(10078, "nsToDatabase: ns too long", false); return ns.substr( 0, i );
} }
inline string nsToDatabase(const char *ns) {
char buf[MaxDatabaseNameLen]; // "database.a.b.c" -> "database"
nsToDatabase(ns, buf); inline void nsToDatabase(const StringData& ns, char *database) {
return buf; StringData db = nsToDatabaseSubstring( ns );
db.copyTo( database, true );
} }
inline string nsToDatabase(const string& ns) {
size_t i = ns.find( '.' ); // TODO: make this return a StringData
if ( i == string::npos ) inline string nsToDatabase(const StringData& ns) {
return ns; return nsToDatabaseSubstring( ns ).toString();
massert(10088, "nsToDatabase: ns too long", i < (size_t)MaxDatabase
NameLen);
return ns.substr( 0 , i );
} }
/** /**
* NamespaceDBHash and NamespaceDBEquals allow you to do something like * NamespaceDBHash and NamespaceDBEquals allow you to do something like
* unordered_map<string,int,NamespaceDBHash,NamespaceDBEquals> * unordered_map<string,int,NamespaceDBHash,NamespaceDBEquals>
* and use the full namespace for the string * and use the full namespace for the string
* but comparisons are done only on the db piece * but comparisons are done only on the db piece
*/ */
/** /**
 End of changes. 6 change blocks. 
25 lines changed or deleted 21 lines changed or added


 ntservice.h   ntservice.h 
skipping to change at line 66 skipping to change at line 66
void configureService( void configureService(
ServiceCallback serviceCallback, ServiceCallback serviceCallback,
const boost::program_options::variables_map& params, const boost::program_options::variables_map& params,
const NtServiceDefaultStrings& defaultStrings, const NtServiceDefaultStrings& defaultStrings,
const std::vector<std::string>& disallowedOptions, const std::vector<std::string>& disallowedOptions,
const std::vector<std::string>& argv); const std::vector<std::string>& argv);
bool shouldStartService(); bool shouldStartService();
/** /**
* Construct an argv array that Windows should use to start mongod/mong
os as a service
* if mongo was started with "inputArgv", which is assumed to be an arg
ument vector that
* dictates that Windows should install mongo as a service.
*
* The result is suitable for passing to mongo::constructUtf8WindowsCom
mandLine() to construct
* a properly quoted command line string.
*/
std::vector<std::string> constructServiceArgv(const std::vector<std::st
ring>& inputArgv);
/**
* Start the service. Never returns. * Start the service. Never returns.
*/ */
MONGO_COMPILER_NORETURN void startService(); MONGO_COMPILER_NORETURN void startService();
bool reportStatus(DWORD reportState, DWORD waitHint = 0); bool reportStatus(DWORD reportState, DWORD waitHint = 0);
} // namespace ntservice } // namespace ntservice
} // namespace mongo } // namespace mongo
#endif // defined(_WIN32) #endif // defined(_WIN32)
 End of changes. 1 change blocks. 
0 lines changed or deleted 14 lines changed or added


 oid.h   oid.h 
skipping to change at line 47 skipping to change at line 47
Typical contents of the BSON ObjectID is a 12-byte value consisting of a 4-byte timestamp (seconds since epoch), Typical contents of the BSON ObjectID is a 12-byte value consisting of a 4-byte timestamp (seconds since epoch),
a 3-byte machine id, a 2-byte process id, and a 3-byte counter. Not e that the timestamp and counter fields must a 3-byte machine id, a 2-byte process id, and a 3-byte counter. Not e that the timestamp and counter fields must
be stored big endian unlike the rest of BSON. This is because they are compared byte-by-byte and we want to ensure be stored big endian unlike the rest of BSON. This is because they are compared byte-by-byte and we want to ensure
a mostly increasing order. a mostly increasing order.
*/ */
class OID { class OID {
public: public:
OID() : a(0), b(0) { } OID() : a(0), b(0) { }
enum { enum {
kOIDSize = 12 kOIDSize = 12,
kIncSize = 3
}; };
/** init from a 24 char hex string */ /** init from a 24 char hex string */
explicit OID(const std::string &s) { init(s); } explicit OID(const std::string &s) { init(s); }
/** init from a reference to a 12-byte array */ /** init from a reference to a 12-byte array */
explicit OID(const unsigned char (&arr)[kOIDSize]) { explicit OID(const unsigned char (&arr)[kOIDSize]) {
memcpy(data, arr, sizeof(arr)); memcpy(data, arr, sizeof(arr));
} }
skipping to change at line 72 skipping to change at line 73
bool operator==(const OID& r) const { return a==r.a && b==r.b; } bool operator==(const OID& r) const { return a==r.a && b==r.b; }
bool operator!=(const OID& r) const { return a!=r.a || b!=r.b; } bool operator!=(const OID& r) const { return a!=r.a || b!=r.b; }
int compare( const OID& other ) const { return memcmp( data , other .data , kOIDSize ); } int compare( const OID& other ) const { return memcmp( data , other .data , kOIDSize ); }
bool operator<( const OID& other ) const { return compare( other ) < 0; } bool operator<( const OID& other ) const { return compare( other ) < 0; }
bool operator<=( const OID& other ) const { return compare( other ) <= 0; } bool operator<=( const OID& other ) const { return compare( other ) <= 0; }
/** @return the object ID output as 24 hex digits */ /** @return the object ID output as 24 hex digits */
std::string str() const { return toHexLower(data, kOIDSize); } std::string str() const { return toHexLower(data, kOIDSize); }
std::string toString() const { return str(); } std::string toString() const { return str(); }
/** @return the random/sequential part of the object ID as 6 hex di
gits */
std::string toIncString() const { return toHexLower(_inc, kIncSize)
; }
static OID gen() { OID o; o.init(); return o; } static OID gen() { OID o; o.init(); return o; }
/** sets the contents to a new oid / randomized value */ /** sets the contents to a new oid / randomized value */
void init(); void init();
/** sets the contents to a new oid /** sets the contents to a new oid
* guaranteed to be sequential * guaranteed to be sequential
* NOT guaranteed to be globally unique * NOT guaranteed to be globally unique
* only unique for this process * only unique for this process
 End of changes. 2 change blocks. 
1 lines changed or deleted 6 lines changed or added


 owned_pointer_vector.h   owned_pointer_vector.h 
skipping to change at line 38 skipping to change at line 38
*/ */
template<class T> template<class T>
class OwnedPointerVector { class OwnedPointerVector {
MONGO_DISALLOW_COPYING(OwnedPointerVector); MONGO_DISALLOW_COPYING(OwnedPointerVector);
public: public:
OwnedPointerVector(); OwnedPointerVector();
~OwnedPointerVector(); ~OwnedPointerVector();
/** Access the vector. */ /** Access the vector. */
std::vector<T*>& vector() { return _vector; } const std::vector<T*>& vector() { return _vector; }
std::vector<T*>& mutableVector() { return _vector; }
void clear();
private: private:
std::vector<T*> _vector; std::vector<T*> _vector;
}; };
template<class T> template<class T>
OwnedPointerVector<T>::OwnedPointerVector() { OwnedPointerVector<T>::OwnedPointerVector() {
} }
template<class T> template<class T>
OwnedPointerVector<T>::~OwnedPointerVector() { OwnedPointerVector<T>::~OwnedPointerVector() {
clear();
}
template<class T>
void OwnedPointerVector<T>::clear() {
for( typename std::vector<T*>::iterator i = _vector.begin(); i != _ vector.end(); ++i ) { for( typename std::vector<T*>::iterator i = _vector.begin(); i != _ vector.end(); ++i ) {
delete *i; delete *i;
} }
_vector.clear();
} }
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
1 lines changed or deleted 10 lines changed or added


 parallel.h   parallel.h 
skipping to change at line 28 skipping to change at line 28
/** /**
tools for working in parallel/sharded/clustered environment tools for working in parallel/sharded/clustered environment
*/ */
#pragma once #pragma once
#include "mongo/db/dbmessage.h" #include "mongo/db/dbmessage.h"
#include "mongo/db/matcher.h" #include "mongo/db/matcher.h"
#include "mongo/db/namespacestring.h" #include "mongo/db/namespacestring.h"
#include "mongo/s/shard.h" #include "mongo/s/shard.h"
#include "mongo/s/util.h" #include "mongo/s/stale_exception.h" // for StaleConfigException
#include "mongo/util/concurrency/mvar.h" #include "mongo/util/concurrency/mvar.h"
namespace mongo { namespace mongo {
/** /**
* holder for a server address and a query to run * holder for a server address and a query to run
*/ */
class ServerAndQuery { class ServerAndQuery {
public: public:
ServerAndQuery( const string& server , BSONObj extra = BSONObj() , BSONObj orderObject = BSONObj() ) : ServerAndQuery( const string& server , BSONObj extra = BSONObj() , BSONObj orderObject = BSONObj() ) :
skipping to change at line 82 skipping to change at line 82
class ClusteredCursor { class ClusteredCursor {
public: public:
ClusteredCursor( const QuerySpec& q ); ClusteredCursor( const QuerySpec& q );
ClusteredCursor( QueryMessage& q ); ClusteredCursor( QueryMessage& q );
ClusteredCursor( const string& ns , const BSONObj& q , int options= 0 , const BSONObj& fields=BSONObj() ); ClusteredCursor( const string& ns , const BSONObj& q , int options= 0 , const BSONObj& fields=BSONObj() );
virtual ~ClusteredCursor(); virtual ~ClusteredCursor();
/** call before using */ /** call before using */
void init(); void init();
virtual std::string getNS() { return _ns; }
virtual bool more() = 0; virtual bool more() = 0;
virtual BSONObj next() = 0; virtual BSONObj next() = 0;
static BSONObj concatQuery( const BSONObj& query , const BSONObj& e xtraFilter ); static BSONObj concatQuery( const BSONObj& query , const BSONObj& e xtraFilter );
virtual string type() const = 0; virtual string type() const = 0;
virtual void explain(BSONObjBuilder& b) = 0; virtual void explain(BSONObjBuilder& b) = 0;
protected: protected:
 End of changes. 2 change blocks. 
1 lines changed or deleted 3 lines changed or added


 parse_number.h   parse_number.h 
skipping to change at line 22 skipping to change at line 22
* 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.
*/ */
/** /**
* Utility functions for parsing numbers from strings. * Utility functions for parsing numbers from strings.
*/ */
#pragma once #pragma once
#include <string>
#include "mongo/base/status.h" #include "mongo/base/status.h"
#include "mongo/base/string_data.h"
namespace mongo { namespace mongo {
/** /**
* Parse a number out of a string. * Parses a number out of a StringData.
* *
* Parses "stringValue", interpreting it as a number of the given "base ". On success, stores * Parses "stringValue", interpreting it as a number of the given "base ". On success, stores
* the parsed value into "*result" and returns Status::OK(). * the parsed value into "*result" and returns Status::OK().
* *
* Valid values for "base" are 2-36, with 0 meaning "choose the base by inspecting the prefix * Valid values for "base" are 2-36, with 0 meaning "choose the base by inspecting the prefix
* on the number", as in strtol. Returns Status::BadValue if an illega l value is supplied for * on the number", as in strtol. Returns Status::BadValue if an illega l value is supplied for
* "base". * "base".
* *
* The entirety of the string must consist of digits in the given base, except optionally the * The entirety of the string must consist of digits in the given base, except optionally the
* first character may be "+" or "-", and hexadecimal numbers may begin "0x". Same as strtol, * first character may be "+" or "-", and hexadecimal numbers may begin "0x". Same as strtol,
* without the property of stripping whitespace at the beginning, and f ails to parse if there * without the property of stripping whitespace at the beginning, and f ails to parse if there
* are non-digit characters at the end of the string. * are non-digit characters at the end of the string.
* *
* See parse_number.cpp for the available instantiations, and add any n ew instantiations there. * See parse_number.cpp for the available instantiations, and add any n ew instantiations there.
*/ */
template <typename NumberType> template <typename NumberType>
Status parseNumberFromStringWithBase(const char* stringValue, int base, NumberType* result); Status parseNumberFromStringWithBase(const StringData& stringValue, int base, NumberType* result);
/**
* Equivalent to parseNumberFromStringWithBase(stringValue, 0, result);
*/
template <typename NumberType> template <typename NumberType>
static inline Status parseNumberFromString(const char* stringValue, Num berType* result) { static Status parseNumberFromString(const StringData& stringValue, Numb erType* result) {
return parseNumberFromStringWithBase(stringValue, 0, result); return parseNumberFromStringWithBase(stringValue, 0, result);
} }
/**
* Same as parseNumberFromStringWithBase, above, but taking a std::stri
ng instead of a c-style
* string.
*/
template <typename NumberType>
static inline Status parseNumberFromStringWithBase(
const std::string& stringValue, int base, NumberType* result) {
return parseNumberFromStringWithBase(stringValue.c_str(), base, res
ult);
}
/**
* Same as parseNumberFromString, above, but taking a std::string inste
ad of a c-style string.
*/
template <typename NumberType>
static inline Status parseNumberFromString(const std::string& stringVal
ue, NumberType* result) {
return parseNumberFromString(stringValue.c_str(), result);
}
} // namespace mongo } // namespace mongo
 End of changes. 7 change blocks. 
30 lines changed or deleted 4 lines changed or added


 pdfile.h   pdfile.h 
skipping to change at line 46 skipping to change at line 46
#include "mongo/platform/cstdint.h" #include "mongo/platform/cstdint.h"
#include "mongo/util/log.h" #include "mongo/util/log.h"
#include "mongo/util/mmap.h" #include "mongo/util/mmap.h"
namespace mongo { namespace mongo {
// pdfile versions // pdfile versions
const int PDFILE_VERSION = 4; const int PDFILE_VERSION = 4;
const int PDFILE_VERSION_MINOR = 5; const int PDFILE_VERSION_MINOR = 5;
class Cursor;
class DataFileHeader; class DataFileHeader;
class Extent; class Extent;
class Record;
class Cursor;
class OpDebug; class OpDebug;
class Record;
struct SortPhaseOne;
void dropDatabase(const std::string& db); void dropDatabase(const std::string& db);
bool repairDatabase(string db, string &errmsg, bool preserveClonedFiles OnFailure = false, bool backupOriginalFiles = false); bool repairDatabase(string db, string &errmsg, bool preserveClonedFiles OnFailure = false, bool backupOriginalFiles = false);
/* low level - only drops this ns */ /* low level - only drops this ns */
void dropNS(const string& dropNs); void dropNS(const string& dropNs);
/* deletes this ns, indexes and cursors */ /* deletes this ns, indexes and cursors */
void dropCollection( const string &name, string &errmsg, BSONObjBuilder &result ); void dropCollection( const string &name, string &errmsg, BSONObjBuilder &result );
bool userCreateNS(const char *ns, BSONObj j, string& err, bool logForRe plication, bool *deferIdIndex = 0); bool userCreateNS(const char *ns, BSONObj j, string& err, bool logForRe plication, bool *deferIdIndex = 0);
skipping to change at line 118 skipping to change at line 119
DataFileHeader* header() { return (DataFileHeader*) _mb; } DataFileHeader* header() { return (DataFileHeader*) _mb; }
MongoMMF mmf; MongoMMF mmf;
void *_mb; // the memory mapped view void *_mb; // the memory mapped view
int fileNo; int fileNo;
}; };
class DataFileMgr { class DataFileMgr {
friend class BasicCursor; friend class BasicCursor;
public: public:
DataFileMgr();
void init(const string& path ); void init(const string& path );
/* see if we can find an extent of the right size in the freelist. */ /* see if we can find an extent of the right size in the freelist. */
static Extent* allocFromFreeList(const char *ns, int approxSize, bo ol capped = false); static Extent* allocFromFreeList(const char *ns, int approxSize, bo ol capped = false);
/** @return DiskLoc where item ends up */ /** @return DiskLoc where item ends up */
// changedId should be initialized to false // changedId should be initialized to false
const DiskLoc updateRecord( const DiskLoc updateRecord(
const char *ns, const char *ns,
NamespaceDetails *d, NamespaceDetails *d,
NamespaceDetailsTransient *nsdt, NamespaceDetailsTransient *nsdt,
Record *toupdate, const DiskLoc& dl, Record *toupdate, const DiskLoc& dl,
const char *buf, int len, OpDebug& debug, bool god=false); const char *buf, int len, OpDebug& debug, bool god=false);
// The object o may be updated if modified on insert. // The object o may be updated if modified on insert.
void insertAndLog( const char *ns, const BSONObj &o, bool god = fal se, bool fromMigrate = false ); void insertAndLog( const char *ns, const BSONObj &o, bool god = fal se, bool fromMigrate = false );
/** /**
* insert() will add an _id to the object if not present. If you w ould like to see the * insert() will add an _id to the object if not present. If you w ould like to see the
* final object after such an addition, use this method. * final object after such an addition, use this method.
* note: does NOT put on oplog
* @param o both and in and out param * @param o both and in and out param
* @param mayInterrupt When true, killop may interrupt the function call. * @param mayInterrupt When true, killop may interrupt the function call.
*/ */
DiskLoc insertWithObjMod(const char* ns, DiskLoc insertWithObjMod(const char* ns,
BSONObj& /*out*/o, BSONObj& /*out*/o,
bool mayInterrupt = false, bool mayInterrupt = false,
bool god = false); bool god = false);
/** @param obj in value only for this version. */
void insertNoReturnVal(const char *ns, BSONObj o, bool god = false)
;
/** /**
* Insert the contents of @param buf with length @param len into na mespace @param ns. * Insert the contents of @param buf with length @param len into na mespace @param ns.
* note: does NOT put on oplog
* @param mayInterrupt When true, killop may interrupt the function call. * @param mayInterrupt When true, killop may interrupt the function call.
* @param god if true, you may pass in obuf of NULL and then popula te the returned DiskLoc * @param god if true, you may pass in obuf of NULL and then popula te the returned DiskLoc
* after the call -- that will prevent a double buffer copy in some cases (btree.cpp). * after the call -- that will prevent a double buffer copy in some cases (btree.cpp).
* @param mayAddIndex almost always true, except for invocation fro m rename namespace * @param mayAddIndex almost always true, except for invocation fro m rename namespace
* command. * command.
* @param addedID if not null, set to true if adding _id element. You must assure false * @param addedID if not null, set to true if adding _id element. You must assure false
* before calling if using. * before calling if using.
*/ */
DiskLoc insert(const char* ns, DiskLoc insert(const char* ns,
const void* buf, const void* buf,
int32_t len, int32_t len,
bool mayInterrupt = false, bool mayInterrupt = false,
bool god = false, bool god = false,
bool mayAddIndex = true, bool mayAddIndex = true,
bool* addedID = 0); bool* addedID = 0);
static shared_ptr<Cursor> findAll(const char *ns, const DiskLoc &st artLoc = DiskLoc()); static shared_ptr<Cursor> findAll(const StringData& ns, const DiskL oc &startLoc = DiskLoc());
/* special version of insert for transaction logging -- streamlined a bit. /* special version of insert for transaction logging -- streamlined a bit.
assumes ns is capped and no indexes assumes ns is capped and no indexes
no _id field check no _id field check
*/ */
Record* fast_oplog_insert(NamespaceDetails *d, const char *ns, int len); Record* fast_oplog_insert(NamespaceDetails *d, const char *ns, int len);
static Extent* getExtent(const DiskLoc& dl); static Extent* getExtent(const DiskLoc& dl);
static Record* getRecord(const DiskLoc& dl); static Record* getRecord(const DiskLoc& dl);
static DeletedRecord* getDeletedRecord(const DiskLoc& dl); static DeletedRecord* getDeletedRecord(const DiskLoc& dl);
void deleteRecord(const char *ns, Record *todelete, const DiskLoc& dl, bool cappedOK = false, bool noWarn = false, bool logOp=false); void deleteRecord(const char *ns, Record *todelete, const DiskLoc& dl, bool cappedOK = false, bool noWarn = false, bool logOp=false);
void deleteRecord(NamespaceDetails* d, const char *ns, Record *tode lete, const DiskLoc& dl, bool cappedOK = false, bool noWarn = false, bool l ogOp=false); void deleteRecord(NamespaceDetails* d, const char *ns, Record *tode lete, const DiskLoc& dl, bool cappedOK = false, bool noWarn = false, bool l ogOp=false);
/* does not clean up indexes, etc. : just deletes the record in the pdfile. use deleteRecord() to unindex */ /* does not clean up indexes, etc. : just deletes the record in the pdfile. use deleteRecord() to unindex */
void _deleteRecord(NamespaceDetails *d, const char *ns, Record *tod elete, const DiskLoc& dl); void _deleteRecord(NamespaceDetails *d, const char *ns, Record *tod elete, const DiskLoc& dl);
/**
* accessor/mutator for the 'precalced' keys (that is, sorted index
keys)
*
* NB: 'precalced' is accessed from fastBuildIndex(), which is call
ed from insert-related
* methods like insertWithObjMod(). It is mutated from various cal
lers of the insert
* methods, which assume 'precalced' will not change while in the i
nsert method. This
* should likely be refactored so theDataFileMgr takes full respons
ibility.
*/
SortPhaseOne* getPrecalced() const;
void setPrecalced(SortPhaseOne* precalced);
mongo::mutex _precalcedMutex;
private: private:
vector<MongoDataFile *> files; vector<MongoDataFile *> files;
SortPhaseOne* _precalced;
}; };
extern DataFileMgr theDataFileMgr; extern DataFileMgr theDataFileMgr;
#pragma pack(1) #pragma pack(1)
class DeletedRecord { class DeletedRecord {
public: public:
int lengthWithHeaders() const { _accessing(); return _lengthWithHea ders; } int lengthWithHeaders() const { _accessing(); return _lengthWithHea ders; }
skipping to change at line 546 skipping to change at line 560
while ( 1 ) { while ( 1 ) {
if ( e->xnext.isNull() ) if ( e->xnext.isNull() )
return DiskLoc(); // end of table. return DiskLoc(); // end of table.
e = e->xnext.ext(); e = e->xnext.ext();
if ( !e->firstRecord.isNull() ) if ( !e->firstRecord.isNull() )
break; break;
// entire extent could be empty, keep looking // entire extent could be empty, keep looking
} }
return e->firstRecord; return e->firstRecord;
} }
inline DiskLoc Record::getPrev(const DiskLoc& myLoc) { inline DiskLoc Record::getPrev(const DiskLoc& myLoc) {
_accessing(); _accessing();
if ( _prevOfs != DiskLoc::NullOfs )
// Check if we still have records on our current extent
if ( _prevOfs != DiskLoc::NullOfs ) {
return DiskLoc(myLoc.a(), _prevOfs); return DiskLoc(myLoc.a(), _prevOfs);
}
// Get the current extent
Extent *e = myExtent(myLoc); Extent *e = myExtent(myLoc);
if ( e->xprev.isNull() ) while ( 1 ) {
return DiskLoc(); if ( e->xprev.isNull() ) {
return e->xprev.ext()->lastRecord; // There are no more extents before this one
return DiskLoc();
}
// Move to the extent before this one
e = e->xprev.ext();
if ( !e->lastRecord.isNull() ) {
// We have found a non empty extent
break;
}
}
// Return the last record in our new extent
return e->lastRecord;
} }
inline BSONObj DiskLoc::obj() const { inline BSONObj DiskLoc::obj() const {
return BSONObj::make(rec()->accessed()); return BSONObj::make(rec()->accessed());
} }
inline DeletedRecord* DiskLoc::drec() const { inline DeletedRecord* DiskLoc::drec() const {
verify( _a != -1 ); verify( _a != -1 );
DeletedRecord* dr = (DeletedRecord*) rec(); DeletedRecord* dr = (DeletedRecord*) rec();
memconcept::is(dr, memconcept::concept::deletedrecord); memconcept::is(dr, memconcept::concept::deletedrecord);
return dr; return dr;
skipping to change at line 587 skipping to change at line 621
} // namespace mongo } // namespace mongo
#include "database.h" #include "database.h"
#include "memconcept.h" #include "memconcept.h"
namespace mongo { namespace mongo {
boost::intmax_t dbSize( const char *database ); boost::intmax_t dbSize( const char *database );
inline NamespaceIndex* nsindex(const char *ns) { inline NamespaceIndex* nsindex(const StringData& ns) {
Database *database = cc().database(); Database *database = cc().database();
verify( database ); verify( database );
memconcept::is(database, memconcept::concept::database, ns, sizeof( Database)); memconcept::is(database, memconcept::concept::database, ns, sizeof( Database));
DEV { DEV {
char buf[256]; StringData dbname = nsToDatabaseSubstring( ns );
nsToDatabase(ns, buf); if ( database->name != dbname ) {
if ( database->name != buf ) {
out() << "ERROR: attempt to write to wrong database\n"; out() << "ERROR: attempt to write to wrong database\n";
out() << " ns:" << ns << '\n'; out() << " ns:" << ns << '\n';
out() << " database->name:" << database->name << endl; out() << " database->name:" << database->name << endl;
verify( database->name == buf ); verify( database->name == dbname );
} }
} }
return &database->namespaceIndex; return &database->namespaceIndex;
} }
inline NamespaceDetails* nsdetails(const char *ns) { inline NamespaceDetails* nsdetails(const StringData& ns) {
// if this faults, did you set the current db first? (Client::Cont ext + dblock) // if this faults, did you set the current db first? (Client::Cont ext + dblock)
NamespaceDetails *d = nsindex(ns)->details(ns); NamespaceDetails *d = nsindex(ns)->details(ns);
if( d ) { if( d ) {
memconcept::is(d, memconcept::concept::nsdetails, ns, sizeof(Na mespaceDetails)); memconcept::is(d, memconcept::concept::nsdetails, ns, sizeof(Na mespaceDetails));
} }
return d; return d;
} }
inline Extent* DataFileMgr::getExtent(const DiskLoc& dl) { inline Extent* DataFileMgr::getExtent(const DiskLoc& dl) {
verify( dl.a() != -1 ); verify( dl.a() != -1 );
skipping to change at line 640 skipping to change at line 673
return BSONObj( r->data() ); return BSONObj( r->data() );
} }
DiskLoc allocateSpaceForANewRecord(const char* ns, DiskLoc allocateSpaceForANewRecord(const char* ns,
NamespaceDetails* d, NamespaceDetails* d,
int32_t lenWHdr, int32_t lenWHdr,
bool god); bool god);
void addRecordToRecListInExtent(Record* r, DiskLoc loc); void addRecordToRecListInExtent(Record* r, DiskLoc loc);
/**
* Static helpers to manipulate the list of unfinished index builds.
*/
class IndexBuildsInProgress {
public:
/**
* Find an unfinished index build by name. Does not search finishe
d index builds.
*/
static int get(const char* ns, const std::string& indexName);
/**
* Remove an unfinished index build from the list of index builds a
nd move every subsequent
* unfinished index build back one. E.g., if x, y, z, and w are bu
ilding and someone kills
* y, this method would rearrange the list to be x, z, w, (empty),
etc.
*/
static void remove(const char* ns, int offset);
};
} // namespace mongo } // namespace mongo
 End of changes. 19 change blocks. 
17 lines changed or deleted 76 lines changed or added


 pipeline.h   pipeline.h 
skipping to change at line 100 skipping to change at line 100
@param the builder to write the command to @param the builder to write the command to
*/ */
void toBson(BSONObjBuilder *pBuilder) const; void toBson(BSONObjBuilder *pBuilder) const;
/** /**
Run the Pipeline on the given source. Run the Pipeline on the given source.
@param result builder to write the result to @param result builder to write the result to
@param errmsg place to put error messages, if any @param errmsg place to put error messages, if any
@param pSource the document source to use at the head of the chai n
@returns true on success, false if an error occurs @returns true on success, false if an error occurs
*/ */
bool run(BSONObjBuilder &result, string &errmsg, bool run(BSONObjBuilder &result, string &errmsg);
const intrusive_ptr<DocumentSource> &pSource);
/** /**
Debugging: should the processing pipeline be split within Debugging: should the processing pipeline be split within
mongod, simulating the real mongos/mongod split? This is determi ned mongod, simulating the real mongos/mongod split? This is determi ned
by setting the splitMongodPipeline field in an "aggregate" by setting the splitMongodPipeline field in an "aggregate"
command. command.
The split itself is handled by the caller, which is currently The split itself is handled by the caller, which is currently
pipeline_command.cpp. pipeline_command.cpp.
skipping to change at line 126 skipping to change at line 124
*/ */
bool getSplitMongodPipeline() const; bool getSplitMongodPipeline() const;
/** /**
Ask if this is for an explain request. Ask if this is for an explain request.
@returns true if this is an explain @returns true if this is an explain
*/ */
bool isExplain() const; bool isExplain() const;
/// The initial source is special since it varies between mongos an
d mongod.
void addInitialSource(intrusive_ptr<DocumentSource> source);
/** /**
The aggregation command name. The aggregation command name.
*/ */
static const char commandName[]; static const char commandName[];
/* /*
PipelineD is a "sister" class that has additional functionality PipelineD is a "sister" class that has additional functionality
for the Pipeline. It exists because of linkage requirements. for the Pipeline. It exists because of linkage requirements.
Pipeline needs to function in mongod and mongos. PipelineD Pipeline needs to function in mongod and mongos. PipelineD
contains extra functionality required in mongod, and which can't contains extra functionality required in mongod, and which can't
skipping to change at line 169 skipping to change at line 170
/* /*
Write the pipeline's operators to the given result document, Write the pipeline's operators to the given result document,
for a shard server (or regular server, in an unsharded setup). for a shard server (or regular server, in an unsharded setup).
This uses writeExplainOps() and adds that array to the result This uses writeExplainOps() and adds that array to the result
with the serverPipelineName. That will be preceded by explain with the serverPipelineName. That will be preceded by explain
information for the input source. information for the input source.
@param result the object to add the explain information to @param result the object to add the explain information to
@param pInputSource source for the pipeline
*/ */
void writeExplainShard(BSONObjBuilder &result, void writeExplainShard(BSONObjBuilder &result) const;
const intrusive_ptr<DocumentSource> &pInputSource) const;
/* /*
Write the pipeline's operators to the given result document, Write the pipeline's operators to the given result document,
for a mongos instance. for a mongos instance.
This first adds the serverPipeline obtained from the input This first adds the serverPipeline obtained from the input
source. source.
Then this uses writeExplainOps() and adds that array to the resul t Then this uses writeExplainOps() and adds that array to the resul t
with the serverPipelineName. That will be preceded by explain with the serverPipelineName. That will be preceded by explain
information for the input source. information for the input source.
@param result the object to add the explain information to @param result the object to add the explain information to
@param pInputSource source for the pipeline; expected to be the
output of a shard
*/ */
void writeExplainMongos(BSONObjBuilder &result, void writeExplainMongos(BSONObjBuilder &result) const;
const intrusive_ptr<DocumentSource> &pInputSource) const;
string collectionName; string collectionName;
typedef vector<intrusive_ptr<DocumentSource> > SourceVector; typedef deque<intrusive_ptr<DocumentSource> > SourceContainer;
SourceVector sourceVector; SourceContainer sources;
bool explain; bool explain;
bool splitMongodPipeline; bool splitMongodPipeline;
intrusive_ptr<ExpressionContext> pCtx; intrusive_ptr<ExpressionContext> pCtx;
}; };
} // namespace mongo } // namespace mongo
/* ======================= INLINED IMPLEMENTATIONS ======================== == */ /* ======================= INLINED IMPLEMENTATIONS ======================== == */
 End of changes. 8 change blocks. 
12 lines changed or deleted 9 lines changed or added


 pipeline_d.h   pipeline_d.h 
skipping to change at line 48 skipping to change at line 48
Create a Cursor wrapped in a DocumentSourceCursor, which is suit able Create a Cursor wrapped in a DocumentSourceCursor, which is suit able
to be the first source for a pipeline to begin with. This sourc e to be the first source for a pipeline to begin with. This sourc e
will feed the execution of the pipeline. will feed the execution of the pipeline.
This method looks for early pipeline stages that can be folded i nto This method looks for early pipeline stages that can be folded i nto
the underlying cursor, and when a cursor can absorb those, they the underlying cursor, and when a cursor can absorb those, they
are removed from the head of the pipeline. For example, an are removed from the head of the pipeline. For example, an
early match can be removed and replaced with a Cursor that will early match can be removed and replaced with a Cursor that will
do an index scan. do an index scan.
The cursor is added to the front of the pipeline's sources.
@param pPipeline the logical "this" for this operation @param pPipeline the logical "this" for this operation
@param dbName the name of the database @param dbName the name of the database
@param pExpCtx the expression context for this pipeline @param pExpCtx the expression context for this pipeline
@returns the cursor that was created
*/ */
static intrusive_ptr<DocumentSourceCursor> prepareCursorSource( static void prepareCursorSource(
const intrusive_ptr<Pipeline> &pPipeline, const intrusive_ptr<Pipeline> &pPipeline,
const string &dbName, const string &dbName,
const intrusive_ptr<ExpressionContext> &pExpCtx); const intrusive_ptr<ExpressionContext> &pExpCtx);
private: private:
PipelineD(); // does not exist: prevent instantiation PipelineD(); // does not exist: prevent instantiation
}; };
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
2 lines changed or deleted 3 lines changed or added


 port.h   port.h 
skipping to change at line 680 skipping to change at line 680
#define ATTRIBUTE_SECTION(name) #define ATTRIBUTE_SECTION(name)
#define INIT_ATTRIBUTE_SECTION_VARS(name) #define INIT_ATTRIBUTE_SECTION_VARS(name)
#define DEFINE_ATTRIBUTE_SECTION_VARS(name) #define DEFINE_ATTRIBUTE_SECTION_VARS(name)
#define DECLARE_ATTRIBUTE_SECTION_VARS(name) #define DECLARE_ATTRIBUTE_SECTION_VARS(name)
#define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(0)) #define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(0))
#define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(0)) #define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(0))
#endif // !HAVE_ATTRIBUTE_SECTION #endif // !HAVE_ATTRIBUTE_SECTION
#if defined __sunos__ #if defined __sunos__ || defined _WIN32
#define drem remainder
#endif
// HK's fun windows fixer-upper defines go here! Woo.
#ifdef _WIN32
inline double drem(double x, double y) { inline double drem(double x, double y) {
double quot = x/y; double quot = x/y;
if (quot > 0) { int iquot;
quot = quot + 0.5; // If quot is slightly less than 0.5, we round down explicitly. We hav
e to
// do this explicitly because (0.5 + quot) when quot=(0.5-epsilon) give
s you 1
// and that's rounding the wrong way. Oh, floating point!
if (quot < 0.5 && quot > -0.5) {
iquot = 0;
} else if (quot > 0) {
iquot = quot + 0.5;
} else { } else {
quot = quot - 0.5; iquot = quot - 0.5;
} }
int iquot = quot; double ret = x - iquot * y;
return x - iquot * y; return ret;
} }
#endif
// HK's fun windows fixer-upper defines go here! Woo.
#ifdef _WIN32
#define strtoll _strtoi64 #define strtoll _strtoi64
#define strtoull _strtoui64 #define strtoull _strtoui64
#define safe_vsnprintf _vsnprintf #define safe_vsnprintf _vsnprintf
#define snprintf _snprintf #define snprintf _snprintf
inline void va_copy(va_list& a, va_list& b) { inline void va_copy(va_list& a, va_list& b) {
a = b; a = b;
} }
using namespace std; using namespace std;
#define isnan _isnan #define isnan _isnan
 End of changes. 5 change blocks. 
11 lines changed or deleted 18 lines changed or added


 principal.h   principal.h 
/** /* Copyright 2012 10gen Inc.
* Copyright (C) 2012 10gen Inc. *
* * Licensed under the Apache License, Version 2.0 (the "License");
* This program is free software: you can redistribute it and/or modify * you may not use this file except in compliance with the License.
* it under the terms of the GNU Affero General Public License, version 3 * You may obtain a copy of the License at
, *
* as published by the Free Software Foundation. * http://www.apache.org/licenses/LICENSE-2.0
* *
* This program is distributed in the hope that it will be useful, * Unless required by applicable law or agreed to in writing, software
* but WITHOUT ANY WARRANTY; without even the implied warranty of * distributed under the License is distributed on an "AS IS" BASIS,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli
* GNU Affero General Public License for more details. ed.
* * See the License for the specific language governing permissions and
* You should have received a copy of the GNU Affero General Public Licen * limitations under the License.
se */
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once #pragma once
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>
#include <string> #include <string>
#include "mongo/base/disallow_copying.h"
#include "mongo/base/string_data.h"
#include "mongo/db/auth/principal_name.h"
#include "mongo/util/string_map.h"
namespace mongo { namespace mongo {
/** /**
* Represents an authenticated user. Every principal has a name and a * Represents an authenticated user. Every principal has a name, a tim
time that the user's e that the user's
* authentication expires. * authentication expires, and a flag that describes whether or not pri
vileges should be
* acquired implicitly.
*
* The implicit privilege acquisition flag defaults to disabled, and th
e expiration time
* defaults to never.
*
* This class does not do any locking/synchronization, the consumer wil l be responsible for * This class does not do any locking/synchronization, the consumer wil l be responsible for
* synchronizing access. * synchronizing access.
*/ */
class Principal { class Principal {
MONGO_DISALLOW_COPYING(Principal);
public: public:
Principal(const PrincipalName& name,
const boost::posix_time::ptime& expirationTime);
explicit Principal(const PrincipalName& name);
~Principal();
const PrincipalName& getName() const { return _name; }
// Returns the expiration time of this principal information.
// No expiration is represented as boost::posix_time::pos_infin // No expiration is represented as boost::posix_time::pos_infin
Principal(const std::string& name, const boost::posix_time::ptime& const boost::posix_time::ptime& getExpirationTime() const { return
expirationTime); _expirationTime; }
explicit Principal(const std::string& name);
Principal();
~Principal(){}
const std::string& getName() const; // Returns true if this principal is configured for implicit acquis
const boost::posix_time::ptime& getExpirationTime() const; ition of privileges.
bool isImplicitPrivilegeAcquisitionEnabled() const { return _enable
ImplicitPrivileges; }
void setExpirationTime(boost::posix_time::ptime& expiration); void setExpirationTime(boost::posix_time::ptime& expiration);
void setImplicitPrivilegeAcquisition(bool enabled);
bool isDatabaseProbed(const StringData& dbname) const;
void markDatabaseAsProbed(const StringData& dbname);
private: private:
std::string _name; PrincipalName _name;
boost::posix_time::ptime _expirationTime; boost::posix_time::ptime _expirationTime;
bool _enableImplicitPrivileges;
StringMap<bool> _probedDatabases;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 10 change blocks. 
28 lines changed or deleted 53 lines changed or added


 principal_set.h   principal_set.h 
/** /* Copyright 2012 10gen Inc.
* Copyright (C) 2012 10gen Inc. *
* * Licensed under the Apache License, Version 2.0 (the "License");
* This program is free software: you can redistribute it and/or modify * you may not use this file except in compliance with the License.
* it under the terms of the GNU Affero General Public License, version 3 * You may obtain a copy of the License at
, *
* as published by the Free Software Foundation. * http://www.apache.org/licenses/LICENSE-2.0
* *
* This program is distributed in the hope that it will be useful, * Unless required by applicable law or agreed to in writing, software
* but WITHOUT ANY WARRANTY; without even the implied warranty of * distributed under the License is distributed on an "AS IS" BASIS,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli
* GNU Affero General Public License for more details. ed.
* * See the License for the specific language governing permissions and
* You should have received a copy of the GNU Affero General Public Licen * limitations under the License.
se */
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once #pragma once
#include <string> #include <string>
#include <vector>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
#include "mongo/base/status.h" #include "mongo/base/string_data.h"
#include "mongo/db/auth/principal.h" #include "mongo/db/auth/principal.h"
#include "mongo/platform/unordered_map.h" #include "mongo/db/auth/principal_name.h"
namespace mongo { namespace mongo {
/** /**
* A collection of authenticated principals. * A collection of authenticated principals.
* This class does not do any locking/synchronization, the consumer wil l be responsible for * This class does not do any locking/synchronization, the consumer wil l be responsible for
* synchronizing access. * synchronizing access.
*/ */
class PrincipalSet { class PrincipalSet {
MONGO_DISALLOW_COPYING(PrincipalSet); MONGO_DISALLOW_COPYING(PrincipalSet);
public: public:
typedef std::vector<Principal*>::const_iterator iterator;
/**
* Forward iterator over the names of the principals stored in a Pr
incipalSet.
*
* Instances are valid until the underlying vector<Principal*> is m
odified.
*
* more() must be the first method called after construction, and m
ust be checked
* after each call to next() before calling any other methods.
*/
class NameIterator {
public:
explicit NameIterator(const std::vector<Principal*>& principals
) :
_curr(principals.begin()),
_end(principals.end()) {
}
NameIterator() {}
bool more() { return _curr != _end; }
const PrincipalName& next() {
const PrincipalName& ret = get();
++_curr;
return ret;
}
const PrincipalName& get() const { return (*_curr)->getName();
}
const PrincipalName& operator*() const { return get(); }
const PrincipalName* operator->() const { return &get(); }
private:
std::vector<Principal*>::const_iterator _curr;
std::vector<Principal*>::const_iterator _end;
};
PrincipalSet(); PrincipalSet();
~PrincipalSet(); ~PrincipalSet();
// If the principal is already present, this will replace the exist ing entry. // If the principal is already present, this will replace the exist ing entry.
// The PrincipalSet takes ownership of the passed-in principal and is responsible for // The PrincipalSet takes ownership of the passed-in principal and is responsible for
// deleting it eventually // deleting it eventually
void add(Principal* principal); void add(Principal* principal);
Status removeByName(const std::string& name);
// Returns NULL if not found // Removes all principals whose authentication credentials came fro
m dbname.
void removeByDBName(const StringData& dbname);
// Returns the Principal with the given name, or NULL if not found.
// Ownership of the returned Principal remains with the PrincipalSe t. The pointer // Ownership of the returned Principal remains with the PrincipalSe t. The pointer
// returned is only guaranteed to remain valid until the next non-c onst method is called // returned is only guaranteed to remain valid until the next non-c onst method is called
// on the PrincipalSet. // on the PrincipalSet.
Principal* lookup(const std::string& name) const; Principal* lookup(const PrincipalName& name) const;
// Gets the principal whose authentication credentials came from db
name, or NULL if none
// exist. There should be at most one such principal.
Principal* lookupByDBName(const StringData& dbname) const;
// Gets an iterator over the names of the principals stored in the
set. The iterator is
// valid until the next non-const method is called on the Principal
Set.
NameIterator getNames() const { return NameIterator(_principals); }
iterator begin() const { return _principals.begin(); }
iterator end() const { return _principals.end(); }
private: private:
// Key is principal name.
// The PrincipalSet maintains ownership of the Principals in it, an d is responsible for // The PrincipalSet maintains ownership of the Principals in it, an d is responsible for
// deleting them when done with them. // deleting them when done with them.
unordered_map<std::string, Principal*> _principals; std::vector<Principal*> _principals;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 9 change blocks. 
24 lines changed or deleted 81 lines changed or added


 privilege.h   privilege.h 
/** /* Copyright 2012 10gen Inc.
* Copyright (C) 2012 10gen Inc. *
* * Licensed under the Apache License, Version 2.0 (the "License");
* This program is free software: you can redistribute it and/or modify * you may not use this file except in compliance with the License.
* it under the terms of the GNU Affero General Public License, version 3 * You may obtain a copy of the License at
, *
* as published by the Free Software Foundation. * http://www.apache.org/licenses/LICENSE-2.0
* *
* This program is distributed in the hope that it will be useful, * Unless required by applicable law or agreed to in writing, software
* but WITHOUT ANY WARRANTY; without even the implied warranty of * distributed under the License is distributed on an "AS IS" BASIS,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli
* GNU Affero General Public License for more details. ed.
* * See the License for the specific language governing permissions and
* You should have received a copy of the GNU Affero General Public Licen * limitations under the License.
se */
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once #pragma once
#include <string> #include <string>
#include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h" #include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/principal.h" #include "mongo/db/auth/principal.h"
namespace mongo { namespace mongo {
/** /**
* A representation of the permission to perform a set of actions on a specific resource. * A representation of the permission to perform a set of actions on a specific resource.
*/ */
class Privilege { class Privilege {
public: public:
Privilege(const std::string& resource, ActionSet actions); Privilege(const std::string& resource, const ActionType& action);
Privilege(const std::string& resource, const ActionSet& actions);
~Privilege() {} ~Privilege() {}
const std::string& getResource() const { return _resource; } const std::string& getResource() const { return _resource; }
const ActionSet& getActions() const { return _actions; } const ActionSet& getActions() const { return _actions; }
// Checks if the given action is present in the Privilege. // Checks if the given action is present in the Privilege.
bool includesAction(const ActionType& action) const; bool includesAction(const ActionType& action) const;
// Checks if the given actions are present in the Privilege.
bool includesActions(const ActionSet& actions) const;
private: private:
std::string _resource; std::string _resource;
ActionSet _actions; // bitmask of actions this privilege grants ActionSet _actions; // bitmask of actions this privilege grants
}; };
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
18 lines changed or deleted 19 lines changed or added


 privilege_set.h   privilege_set.h 
/** /* Copyright 2012 10gen Inc.
* Copyright (C) 2012 10gen Inc. *
* * Licensed under the Apache License, Version 2.0 (the "License");
* This program is free software: you can redistribute it and/or modify * you may not use this file except in compliance with the License.
* it under the terms of the GNU Affero General Public License, version 3 * You may obtain a copy of the License at
, *
* as published by the Free Software Foundation. * http://www.apache.org/licenses/LICENSE-2.0
* *
* This program is distributed in the hope that it will be useful, * Unless required by applicable law or agreed to in writing, software
* but WITHOUT ANY WARRANTY; without even the implied warranty of * distributed under the License is distributed on an "AS IS" BASIS,
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli
* GNU Affero General Public License for more details. ed.
* * See the License for the specific language governing permissions and
* You should have received a copy of the GNU Affero General Public Licen * limitations under the License.
se */
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once #pragma once
#include <map> #include <map>
#include <string> #include <string>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
#include "mongo/db/auth/acquired_privilege.h"
#include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h" #include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/privilege.h" #include "mongo/db/auth/privilege.h"
#include "mongo/db/auth/principal.h" #include "mongo/db/auth/principal_name.h"
#include "mongo/util/string_map.h"
namespace mongo { namespace mongo {
/** /**
* A collection of privileges describing which authenticated principals * A collection of privileges describing which authenticated principals
bestow the client bestow the client the
* the ability to perform various actions on specific resources. Since * ability to perform various actions on specific resources. Since eve
every privilege ry privilege comes from
* comes from an authenticated principal, removing that principal can r * an authenticated principal, removing that principal removes all priv
emove all privileges ileges granted by that
* that that principal granted. * principal.
*
* Resources are arranged hierarchically, with a wildcard resource,
* PrivilegeSet::WILDCARD_RESOURCE, matching any resource. In the curr
ent implementation, the
* only two levels of the hierarchy are the wildcard and one level belo
w, which is analagous to
* the name of a database. It is future work to support collection or
other sub-database
* resources.
*
* This class does not do any locking/synchronization, the consumer wil l be responsible for * This class does not do any locking/synchronization, the consumer wil l be responsible for
* synchronizing access. * synchronizing access.
*/ */
class PrivilegeSet { class PrivilegeSet {
MONGO_DISALLOW_COPYING(PrivilegeSet); MONGO_DISALLOW_COPYING(PrivilegeSet);
public: public:
PrivilegeSet(){} static const std::string WILDCARD_RESOURCE;
~PrivilegeSet(){}
void grantPrivilege(const AcquiredPrivilege& privilege); PrivilegeSet();
void revokePrivilegesFromPrincipal(Principal* principal); ~PrivilegeSet();
// Returns the first privilege found that grants the given action o /**
n the given resource. * Adds the specified privilege to the set, associating it with the
// Returns NULL if there is no such privilege. named principal.
// Ownership of the returned Privilege remains with the PrivilegeSe *
t. The pointer * The privilege should be on a specific resource, or on the WILDCA
// returned is only guaranteed to remain valid until the next non-c RD_RESOURCE.
onst method is called */
// on the PrivilegeSet. void grantPrivilege(const Privilege& privilege, const PrincipalName
const AcquiredPrivilege* getPrivilegeForAction(const std::string& r & authorizingPrincipal);
esource,
const ActionType& ac /**
tion) const; * Adds the specified privileges to the set, associating them with
the named principal.
*/
void grantPrivileges(const std::vector<Privilege>& privileges,
const PrincipalName& authorizingPrincipal);
/**
* Removes from the set all privileges associated with the given pr
incipal.
*
* If multiple princpals enable the same privilege, the set will co
ntinue to
* contain those privileges until all authorizing principals have h
ad their
* privileges revoked from the set.
*/
void revokePrivilegesFromPrincipal(const PrincipalName& principal);
/**
* Returns true if the set authorizes "desiredPrivilege".
*
* The set is considered to authorize "desiredPrivilege" if each ac
tion in
* "desiredPrivilege" is satisfied either on the database component
of
* "desiredPrivilege.getResource()" or on WILDCARD_RESOURCE.
*
* TODO: Support checking for the privilege on the full resource na
me as well as the
* database component, to support sub-database granularity privileg
e assignment.
*/
bool hasPrivilege(const Privilege& desiredPrivilege);
/**
* Same as hasPrivilege, except checks all the privileges in a vect
or.
*/
bool hasPrivileges(const std::vector<Privilege>& desiredPrivileges)
;
private: private:
// Key is the resource the privilege is on. /**
typedef std::multimap<const std::string, AcquiredPrivilege> Privile * Information about privileges held on a resource.
geMap; *
typedef PrivilegeMap::iterator PrivilegeRangeIterator; * Instances are stored in the _byResource map, and accelerate the
typedef std::pair<PrivilegeRangeIterator, PrivilegeRangeIterator> P fast path of
rivilegeSetRange; * hasPrivilege(). Privilege revocations via revokePrivilegesFromP
typedef PrivilegeMap::const_iterator PrivilegeRangeConstIterator; rincipal() can make these
typedef std::pair<PrivilegeRangeConstIterator, PrivilegeRangeConstI * entries invalid, at which point they are marked "dirty". Dirty
terator> entries are rebuilt via
PrivilegeSetConstRange; * _rebuildEntry(), below, during execution of hasPrivilege().
*/
class ResourcePrivilegeCacheEntry {
public:
ResourcePrivilegeCacheEntry() : actions(), dirty(false) {}
// All actions enabled on the associated resource, provided tha
t "dirty" is false.
ActionSet actions;
// False if this data is consistent with the full privilege inf
ormation, stored in the
// _byPrincipal map.
bool dirty;
};
/**
* Type of map from resource names to authorized actions.
*/
typedef StringMap<ResourcePrivilegeCacheEntry> ResourcePrivilegeCac
he;
/**
* Type of map from principal identity to information about the pri
ncipal's privileges. The
* values in the map are themselves maps from resource names to ass
ociated actions.
*/
typedef std::map<PrincipalName, StringMap<ActionSet> > PrincipalPri
vilegeMap;
void _rebuildEntry(const StringData& resource, ResourcePrivilegeCac
heEntry* summary);
ResourcePrivilegeCacheEntry* _lookupEntry(const StringData& resourc
e);
ResourcePrivilegeCacheEntry* _lookupOrInsertEntry(const StringData&
resource);
// Information about privileges available on all resources.
ResourcePrivilegeCacheEntry _globalPrivilegeEntry;
// Cache of privilege information, by resource.
ResourcePrivilegeCache _byResource;
// Maps resource to privileges // Directory of privilege information, by principal.
PrivilegeMap _privileges; PrincipalPrivilegeMap _byPrincipal;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 9 change blocks. 
55 lines changed or deleted 143 lines changed or added


 progress_meter.h   progress_meter.h 
skipping to change at line 28 skipping to change at line 28
#pragma once #pragma once
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <string> #include <string>
namespace mongo { namespace mongo {
class ProgressMeter : boost::noncopyable { class ProgressMeter : boost::noncopyable {
public: public:
ProgressMeter( unsigned long long total , int secondsBetween = 3 , ProgressMeter(unsigned long long total,
int checkInterval = 100 , std::string units = "" ) : _units(units) { int secondsBetween = 3,
int checkInterval = 100,
std::string units = "",
std::string name = "Progress")
: _units(units)
, _name(name) {
reset( total , secondsBetween , checkInterval ); reset( total , secondsBetween , checkInterval );
} }
ProgressMeter() { ProgressMeter() : _active(0), _units(""), _name("Progress") {}
_active = 0;
_units = "";
}
// 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
*/ */
bool hit( int n = 1 ); bool hit( int n = 1 );
void setUnits( const std::string& units ) { _units = units; } void setUnits( const std::string& units ) { _units = units; }
std::string getUnit() const { return _units; } std::string getUnit() const { return _units; }
void setName(std::string name) { _name = name; }
std::string getName() const { return _name; }
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; }
skipping to change at line 79 skipping to change at line 85
unsigned long long _total; unsigned long long _total;
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;
}; };
// e.g.: // e.g.:
// CurOp * op = cc().curop(); // CurOp * op = cc().curop();
// ProgressMeterHolder pm( op->setMessage( "index: (1/3) external sort" , d->stats.nrecords , 10 ) ); // ProgressMeterHolder pm(op->setMessage("index: (1/3) external sort", "Index: External Sort Progress", d->stats.nrecords, 10));
// loop { pm.hit(); } // loop { pm.hit(); }
class ProgressMeterHolder : boost::noncopyable { class ProgressMeterHolder : boost::noncopyable {
public: public:
ProgressMeterHolder( ProgressMeter& pm ) ProgressMeterHolder( ProgressMeter& pm )
: _pm( pm ) { : _pm( pm ) {
} }
~ProgressMeterHolder() { ~ProgressMeterHolder() {
_pm.finished(); _pm.finished();
} }
 End of changes. 5 change blocks. 
7 lines changed or deleted 13 lines changed or added


 queryoptimizer.h   queryoptimizer.h 
skipping to change at line 638 skipping to change at line 638
}; };
PriorityQueue<RunnerHolder> _queue; PriorityQueue<RunnerHolder> _queue;
shared_ptr<ExplainClauseInfo> _explainClauseInfo; shared_ptr<ExplainClauseInfo> _explainClauseInfo;
bool _done; bool _done;
}; };
/** Handles $or type queries by generating a QueryPlanSet for each $or clause. */ /** Handles $or type queries by generating a QueryPlanSet for each $or clause. */
class MultiPlanScanner { class MultiPlanScanner {
public: public:
static MultiPlanScanner *make( const char *ns, static MultiPlanScanner *make( const StringData& ns,
const BSONObj &query, const BSONObj &query,
const BSONObj &order, const BSONObj &order,
const shared_ptr<const ParsedQuery> & parsedQuery = const shared_ptr<const ParsedQuery> & parsedQuery =
shared_ptr<const ParsedQuery>( ), shared_ptr<const ParsedQuery>( ),
const BSONObj &hint = BSONObj(), const BSONObj &hint = BSONObj(),
QueryPlanGenerator::RecordedPlanPolic y recordedPlanPolicy = QueryPlanGenerator::RecordedPlanPolic y recordedPlanPolicy =
QueryPlanGenerator::Use, QueryPlanGenerator::Use,
const BSONObj &min = BSONObj(), const BSONObj &min = BSONObj(),
const BSONObj &max = BSONObj() ); const BSONObj &max = BSONObj() );
skipping to change at line 737 skipping to change at line 737
bool possibleInOrderPlan() const; bool possibleInOrderPlan() const;
/** @return true if an active or fallback plan of _currentQps is ou t of order. */ /** @return true if an active or fallback plan of _currentQps is ou t of order. */
bool possibleOutOfOrderPlan() const; bool possibleOutOfOrderPlan() const;
int i() const { return _i; } int i() const { return _i; }
string toString() const; string toString() const;
private: private:
MultiPlanScanner( const char *ns, MultiPlanScanner( const StringData& ns,
const BSONObj &query, const BSONObj &query,
const shared_ptr<const ParsedQuery> &parsedQuery, const shared_ptr<const ParsedQuery> &parsedQuery,
const BSONObj &hint, const BSONObj &hint,
QueryPlanGenerator::RecordedPlanPolicy recordedPla nPolicy ); QueryPlanGenerator::RecordedPlanPolicy recordedPla nPolicy );
void init( const BSONObj &order, void init( const BSONObj &order,
const BSONObj &min, const BSONObj &min,
const BSONObj &max ); const BSONObj &max );
/** Initialize or iterate a runner generated from @param originalOp . */ /** Initialize or iterate a runner generated from @param originalOp . */
shared_ptr<QueryPlanRunner> iterateRunnerQueue( QueryPlanRunner& or iginalRunner, shared_ptr<QueryPlanRunner> iterateRunnerQueue( QueryPlanRunner& or iginalRunner,
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 queryoptimizercursor.h   queryoptimizercursor.h 
skipping to change at line 40 skipping to change at line 40
* An interface for policies overriding the query optimizer's default b ehavior for selecting * An interface for policies overriding the query optimizer's default b ehavior for selecting
* query plans and creating cursors. * query plans and creating cursors.
*/ */
class QueryPlanSelectionPolicy { class QueryPlanSelectionPolicy {
public: public:
virtual ~QueryPlanSelectionPolicy() {} virtual ~QueryPlanSelectionPolicy() {}
virtual string name() const = 0; virtual string name() const = 0;
virtual bool permitOptimalNaturalPlan() const { return true; } virtual bool permitOptimalNaturalPlan() const { return true; }
virtual bool permitOptimalIdPlan() const { return true; } virtual bool permitOptimalIdPlan() const { return true; }
virtual bool permitPlan( const QueryPlan &plan ) const { return tru e; } virtual bool permitPlan( const QueryPlan &plan ) const { return tru e; }
virtual BSONObj planHint( const char *ns ) const { return BSONObj() ; } virtual BSONObj planHint( const StringData& ns ) const { return BSO NObj(); }
/** /**
* @return true to request that a created Cursor provide a matcher( ). If false, the * @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 * 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 * 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 * 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 * 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 * Matcher, but the hint may be ignored. In some cases the Cursor may not provide
* a Matcher even if 'requestMatcher' is true. * a Matcher even if 'requestMatcher' is true.
*/ */
skipping to change at line 99 skipping to change at line 99
public: public:
virtual string name() const { return "indexOnly"; } virtual string name() const { return "indexOnly"; }
virtual bool permitOptimalNaturalPlan() const { return false; } virtual bool permitOptimalNaturalPlan() const { return false; }
virtual bool permitPlan( const QueryPlan &plan ) const; virtual bool permitPlan( const QueryPlan &plan ) const;
}; };
class QueryPlanSelectionPolicy::IdElseNatural : public QueryPlanSelecti onPolicy { class QueryPlanSelectionPolicy::IdElseNatural : public QueryPlanSelecti onPolicy {
public: public:
virtual string name() const { return "idElseNatural"; } virtual string name() const { return "idElseNatural"; }
virtual bool permitPlan( const QueryPlan &plan ) const; virtual bool permitPlan( const QueryPlan &plan ) const;
virtual BSONObj planHint( const char *ns ) const; virtual BSONObj planHint( const StringData& ns ) const;
}; };
class FieldRangeSet; class FieldRangeSet;
class ExplainQueryInfo; class ExplainQueryInfo;
/** /**
* 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 {
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 queryoptimizercursorimpl.h   queryoptimizercursorimpl.h 
skipping to change at line 256 skipping to change at line 256
shared_ptr<ExplainQueryInfo> _explainQueryInfo; shared_ptr<ExplainQueryInfo> _explainQueryInfo;
}; };
/** /**
* Helper class for generating a simple Cursor or QueryOptimizerCursor from a set of query * Helper class for generating a simple Cursor or QueryOptimizerCursor from a set of query
* parameters. This class was refactored from a single function call a nd is not expected to * parameters. This class was refactored from a single function call a nd is not expected to
* outlive its constructor arguments. * outlive its constructor arguments.
*/ */
class CursorGenerator { class CursorGenerator {
public: public:
CursorGenerator( const char *ns, CursorGenerator( const StringData& ns,
const BSONObj &query, const BSONObj &query,
const BSONObj &order, const BSONObj &order,
const QueryPlanSelectionPolicy &planPolicy, const QueryPlanSelectionPolicy &planPolicy,
const shared_ptr<const ParsedQuery> &parsedQuery, const shared_ptr<const ParsedQuery> &parsedQuery,
bool requireOrder, bool requireOrder,
QueryPlanSummary *singlePlanSummary ); QueryPlanSummary *singlePlanSummary );
shared_ptr<Cursor> generate(); shared_ptr<Cursor> generate();
private: private:
skipping to change at line 286 skipping to change at line 286
} }
BSONObj hint() const { BSONObj hint() const {
return _argumentsHint.isEmpty() ? _planPolicy.planHint( _ns ) : _argumentsHint; 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 char *_ns; const StringData _ns;
BSONObj _query; BSONObj _query;
BSONObj _order; BSONObj _order;
const QueryPlanSelectionPolicy &_planPolicy; const QueryPlanSelectionPolicy &_planPolicy;
shared_ptr<const ParsedQuery> _parsedQuery; shared_ptr<const ParsedQuery> _parsedQuery;
bool _requireOrder; bool _requireOrder;
QueryPlanSummary *_singlePlanSummary; QueryPlanSummary *_singlePlanSummary;
BSONObj _argumentsHint; BSONObj _argumentsHint;
auto_ptr<MultiPlanScanner> _mps; auto_ptr<MultiPlanScanner> _mps;
}; };
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 queryutil.h   queryutil.h 
skipping to change at line 261 skipping to change at line 261
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;
} }
void flipInclusive() { _inclusive = !_inclusive; } void flipInclusive() { _inclusive = !_inclusive; }
}; };
// Keep track of what special indices we're using. This can be nontriv
ial
// because an index could be required by one operator but not by anothe
r.
struct SpecialIndices {
// Unlike true/false, this is readable. :)
enum IndexRequired {
INDEX_REQUIRED,
NO_INDEX_REQUIRED,
};
map<string, bool> _indexRequired;
bool has(const string& name) const {
return _indexRequired.end() != _indexRequired.find(name);
}
SpecialIndices combineWith(const SpecialIndices& other) {
SpecialIndices ret = *this;
for (map<string, bool>::const_iterator it = other._indexRequire
d.begin();
it != other._indexRequired.end(); ++it) {
ret._indexRequired[it->first] = ret._indexRequired[it->firs
t] || it->second;
}
return ret;
}
void add(const string& name, IndexRequired req) {
_indexRequired[name] = _indexRequired[name] || (req == INDEX_RE
QUIRED);
}
bool allRequireIndex() const {
for (map<string, bool>::const_iterator it = _indexRequired.begi
n();
it != _indexRequired.end(); ++it) {
if (!it->second) { return false; }
}
return true;
}
bool empty() const { return _indexRequired.empty(); }
string toString() const {
stringstream ss;
for (map<string, bool>::const_iterator it = _indexRequired.begi
n();
it != _indexRequired.end(); ++it) {
ss << it->first;
ss << (it->second ? " (needs index)" : " (no index needed)"
);
ss << ", ";
}
return ss.str();
}
};
/** An interval defined between a lower and an upper FieldBound. */ /** An interval defined between a lower and an upper FieldBound. */
struct FieldInterval { struct FieldInterval {
FieldInterval() : _cachedEquality( -1 ) {} FieldInterval() : _cachedEquality( -1 ) {}
FieldInterval( const BSONElement& e ) : _cachedEquality( -1 ) { FieldInterval( const BSONElement& e ) : _cachedEquality( -1 ) {
_lower._bound = _upper._bound = e; _lower._bound = _upper._bound = e;
_lower._inclusive = _upper._inclusive = true; _lower._inclusive = _upper._inclusive = true;
} }
FieldBound _lower; FieldBound _lower;
FieldBound _upper; FieldBound _upper;
/** /**
skipping to change at line 359 skipping to change at line 407
* FieldRange( { a:{ $in:[ 1, 2 ] } } ), isPointIntervalSet() -> t rue * FieldRange( { a:{ $in:[ 1, 2 ] } } ), isPointIntervalSet() -> t rue
* FieldRange( { a:{ $gt:5 } } ), isPointIntervalSet() -> false * FieldRange( { a:{ $gt:5 } } ), isPointIntervalSet() -> false
* FieldRange( {} ), isPointIntervalSet() -> false * FieldRange( {} ), isPointIntervalSet() -> false
*/ */
bool isPointIntervalSet() const; bool isPointIntervalSet() const;
const BSONElement& elemMatchContext() const { return _elemMatchCont ext; } const BSONElement& elemMatchContext() const { return _elemMatchCont ext; }
/** Empty the range so it includes no BSONElements. */ /** Empty the range so it includes no BSONElements. */
void makeEmpty() { _intervals.clear(); } void makeEmpty() { _intervals.clear(); }
const vector<FieldInterval> &intervals() const { return _intervals; } const vector<FieldInterval> &intervals() const { return _intervals; }
const set<string>& getSpecial() const { return _special; } const SpecialIndices& getSpecial() const { return _special; }
/** Make component intervals noninclusive. */ /** Make component intervals noninclusive. */
void setExclusiveBounds(); void setExclusiveBounds();
/** /**
* Constructs a range where all FieldIntervals and FieldBounds are in * Constructs a range where all FieldIntervals and FieldBounds are in
* the opposite order of the current range. * the opposite order of the current range.
* NOTE the resulting intervals might not be strictValid(). * NOTE the resulting intervals might not be strictValid().
*/ */
void reverse( FieldRange &ret ) const; void reverse( FieldRange &ret ) const;
string toString() const; string toString() const;
private: private:
BSONObj addObj( const BSONObj &o ); BSONObj addObj( const BSONObj &o );
void finishOperation( const vector<FieldInterval> &newIntervals, co nst FieldRange &other, void finishOperation( const vector<FieldInterval> &newIntervals, co nst FieldRange &other,
bool exactMatchRepresentation ); bool exactMatchRepresentation );
vector<FieldInterval> _intervals; vector<FieldInterval> _intervals;
// Owns memory for our BSONElements. // Owns memory for our BSONElements.
vector<BSONObj> _objData; vector<BSONObj> _objData;
set<string> _special; // Index type name of a non standard (eg '2d' ) index required by a SpecialIndices _special; // Index type name of a non standard (eg ' 2d') index required by a
// parsed query operator (eg '$near'). Could be >1. // parsed query operator (eg '$near'). Could be >1.
bool _exactMatchRepresentation; bool _exactMatchRepresentation;
BSONElement _elemMatchContext; // Parent $elemMatch object of the f ield constraint that BSONElement _elemMatchContext; // Parent $elemMatch object of the f ield constraint that
// generated this FieldRange. For e xample if the query is // generated this FieldRange. For e xample if the query is
// { a:{ $elemMatch:{ b:1, c:1 } } } , then the // { a:{ $elemMatch:{ b:1, c:1 } } } , then the
// _elemMatchContext for the FieldRa nge on 'a.b' is the query // _elemMatchContext for the FieldRa nge on 'a.b' is the query
// element having field name '$elemM atch'. // element having field name '$elemM atch'.
}; };
class QueryPattern; class QueryPattern;
skipping to change at line 454 skipping to change at line 502
* *
* Used in determining "suitability" for hashedindexes, and also in * Used in determining "suitability" for hashedindexes, and also in
* sharding for determining the relevant shards for a query. * sharding for determining the relevant shards for a query.
* *
* TODO: move this into FieldRange instead of FieldRangeSet * TODO: move this into FieldRange instead of FieldRangeSet
*/ */
bool isPointIntervalSet( const string& fieldname ) const; bool isPointIntervalSet( const string& fieldname ) const;
const char *ns() const { return _ns.c_str(); } const char *ns() const { return _ns.c_str(); }
/**
* @return a simplified query from the extreme values of the non un
iversal
* fields.
* @param fields If specified, the fields of the returned object ar
e
* ordered to match those of 'fields'.
*/
BSONObj simplifiedQuery( const BSONObj &fields = BSONObj() ) const;
QueryPattern pattern( const BSONObj &sort = BSONObj() ) const; QueryPattern pattern( const BSONObj &sort = BSONObj() ) const;
set<string> getSpecial() const; SpecialIndices getSpecial() const;
/** /**
* @return a FieldRangeSet approximation of the documents in 'this' but * @return a FieldRangeSet approximation of the documents in 'this' but
* not in 'other'. The approximation will be a superset of the doc uments * not in 'other'. The approximation will be a superset of the doc uments
* in 'this' but not 'other'. * in 'this' but not 'other'.
*/ */
const FieldRangeSet &operator-=( const FieldRangeSet &other ); const FieldRangeSet &operator-=( const FieldRangeSet &other );
/** @return intersection of 'this' with 'other'. */ /** @return intersection of 'this' with 'other'. */
const FieldRangeSet &operator&=( const FieldRangeSet &other ); const FieldRangeSet &operator&=( const FieldRangeSet &other );
skipping to change at line 572 skipping to change at line 612
/** @return false if a match is impossible regardless of index. */ /** @return false if a match is impossible regardless of index. */
bool matchPossible() const { return _multiKey.matchPossible(); } bool matchPossible() const { return _multiKey.matchPossible(); }
/** /**
* @return false if a match is impossible on the specified index. * @return false if a match is impossible on the specified index.
* @param idxNo -1 for non index scan. * @param idxNo -1 for non index scan.
*/ */
bool matchPossibleForIndex( NamespaceDetails *d, int idxNo, const B SONObj &keyPattern ) const; bool matchPossibleForIndex( NamespaceDetails *d, int idxNo, const B SONObj &keyPattern ) const;
const char *ns() const { return _singleKey.ns(); } const char *ns() const { return _singleKey.ns(); }
set<string> getSpecial() const { return _singleKey.getSpecial(); } SpecialIndices getSpecial() const { return _singleKey.getSpecial(); }
/** Intersect with another FieldRangeSetPair. */ /** Intersect with another FieldRangeSetPair. */
FieldRangeSetPair &operator&=( const FieldRangeSetPair &other ); FieldRangeSetPair &operator&=( const FieldRangeSetPair &other );
/** /**
* Subtract a FieldRangeSet, generally one expressing a range that has * Subtract a FieldRangeSet, generally one expressing a range that has
* already been scanned. * already been scanned.
*/ */
FieldRangeSetPair &operator-=( const FieldRangeSet &scanned ); FieldRangeSetPair &operator-=( const FieldRangeSet &scanned );
bool matchPossibleForSingleKeyFRS( const BSONObj &keyPattern ) cons t { bool matchPossibleForSingleKeyFRS( const BSONObj &keyPattern ) cons t {
skipping to change at line 598 skipping to change at line 638
const FieldRangeSet getSingleKeyFRS() const { return _singleKey; } const FieldRangeSet getSingleKeyFRS() const { return _singleKey; }
const FieldRangeSet getMultiKeyFRS() const { return _singleKey; } const FieldRangeSet getMultiKeyFRS() const { return _singleKey; }
string toString() const; string toString() const;
private: private:
FieldRangeSetPair( const FieldRangeSet &singleKey, const FieldRange Set &multiKey ) FieldRangeSetPair( const FieldRangeSet &singleKey, const FieldRange Set &multiKey )
:_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. */
BSONObj simplifiedQueryForIndex( NamespaceDetails *d, int idxNo, co nst BSONObj &keyPattern ) const;
FieldRangeSet _singleKey; FieldRangeSet _singleKey;
FieldRangeSet _multiKey; FieldRangeSet _multiKey;
friend class OrRangeGenerator; friend class OrRangeGenerator;
friend struct QueryUtilIndexed; friend struct QueryUtilIndexed;
}; };
class IndexSpec; 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
skipping to change at line 894 skipping to change at line 933
/** @return FieldRangeSetPair for the current $or clause. */ /** @return FieldRangeSetPair for the current $or clause. */
FieldRangeSetPair *topFrsp() const; FieldRangeSetPair *topFrsp() const;
/** /**
* @return original FieldRangeSetPair for the current $or clause. W hile the * @return original FieldRangeSetPair for the current $or clause. W hile the
* original bounds are looser, they are composed of fewer ranges an d it * original bounds are looser, they are composed of fewer ranges an d it
* is faster to do operations with them; when they can be used inst ead of * is faster to do operations with them; when they can be used inst ead of
* more precise bounds, they should. * more precise bounds, they should.
*/ */
FieldRangeSetPair *topFrspOriginal() const; FieldRangeSetPair *topFrspOriginal() const;
set<string> getSpecial() const { return _baseSet.getSpecial(); } SpecialIndices getSpecial() const { return _baseSet.getSpecial(); }
private: private:
void assertMayPopOrClause(); void assertMayPopOrClause();
void _popOrClause( const FieldRangeSet *toDiff, NamespaceDetails *d , int idxNo, const BSONObj &keyPattern ); void _popOrClause( const FieldRangeSet *toDiff, NamespaceDetails *d , int idxNo, const BSONObj &keyPattern );
FieldRangeSetPair _baseSet; FieldRangeSetPair _baseSet;
list<FieldRangeSetPair> _orSets; list<FieldRangeSetPair> _orSets;
list<FieldRangeSetPair> _originalOrSets; list<FieldRangeSetPair> _originalOrSets;
// ensure memory is owned // ensure memory is owned
list<FieldRangeSetPair> _oldOrSets; list<FieldRangeSetPair> _oldOrSets;
bool _orFound; bool _orFound;
friend struct QueryUtilIndexed; friend struct QueryUtilIndexed;
 End of changes. 8 change blocks. 
16 lines changed or deleted 61 lines changed or added


 record.h   record.h 
skipping to change at line 21 skipping to change at line 21
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/platform/atomic_word.h" #include "mongo/platform/atomic_word.h"
namespace mongo { namespace mongo {
struct RecordStats { struct RecordStats {
void record( BSONObjBuilder& b ); void record( BSONObjBuilder& b );
AtomicInt64 accessesNotInMemory; AtomicInt64 accessesNotInMemory;
AtomicInt64 pageFaultExceptionsThrown; AtomicInt64 pageFaultExceptionsThrown;
}; };
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 redef_macros.h   redef_macros.h 
skipping to change at line 51 skipping to change at line 51
#define dassert MONGO_dassert #define dassert MONGO_dassert
#pragma push_macro("wassert") #pragma push_macro("wassert")
#undef wassert #undef wassert
#define wassert MONGO_wassert #define wassert MONGO_wassert
#pragma push_macro("massert") #pragma push_macro("massert")
#undef massert #undef massert
#define massert MONGO_massert #define massert MONGO_massert
#pragma push_macro("uassert") #pragma push_macro("uassert")
#undef uassert #undef uassert
#define uassert MONGO_uassert #define uassert MONGO_uassert
#pragma push_macro("uassertStatusOK")
#undef uassertStatusOK
#define uassertStatusOK MONGO_uassertStatusOK
#pragma push_macro("DESTRUCTOR_GUARD") #pragma push_macro("DESTRUCTOR_GUARD")
#undef DESTRUCTOR_GUARD #undef DESTRUCTOR_GUARD
#define DESTRUCTOR_GUARD MONGO_DESTRUCTOR_GUARD #define DESTRUCTOR_GUARD MONGO_DESTRUCTOR_GUARD
// util/goodies.h // util/goodies.h
#pragma push_macro("PRINT") #pragma push_macro("PRINT")
#undef PRINT #undef PRINT
#define PRINT MONGO_PRINT #define PRINT MONGO_PRINT
#pragma push_macro("PRINTFL") #pragma push_macro("PRINTFL")
#undef PRINTFL #undef PRINTFL
 End of changes. 1 change blocks. 
0 lines changed or deleted 3 lines changed or added


 request.h   request.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 "mongo/pch.h" #include "mongo/pch.h"
#include "../util/net/message.h" #include "../util/net/message.h"
#include "../db/dbmessage.h" #include "../db/dbmessage.h"
#include "config.h" #include "config.h"
#include "util.h"
namespace mongo { namespace mongo {
class OpCounters; class OpCounters;
class ClientInfo; class ClientInfo;
class Request : boost::noncopyable { class Request : boost::noncopyable {
public: public:
Request( Message& m, AbstractMessagingPort* p ); Request( Message& m, AbstractMessagingPort* p );
skipping to change at line 70 skipping to change at line 69
ChunkManagerPtr getChunkManager() const { ChunkManagerPtr getChunkManager() const {
verify( _didInit ); verify( _didInit );
return _chunkManager; return _chunkManager;
} }
ClientInfo * getClientInfo() const { ClientInfo * getClientInfo() const {
return _clientInfo; return _clientInfo;
} }
/**
* @param ns - 0=use ns from message
*/
void checkAuth( Auth::Level levelNeeded , const char * ns=0 ) const
;
// ---- remote location info ----- // ---- remote location info -----
Shard primaryShard() const ; Shard primaryShard() const ;
// ---- low level access ---- // ---- low level access ----
void reply( Message & response , const string& fromServer ); void reply( Message & response , const string& fromServer );
Message& m() { return _m; } Message& m() { return _m; }
DbMessage& d() { return _d; } DbMessage& d() { return _d; }
 End of changes. 2 change blocks. 
7 lines changed or deleted 0 lines changed or added


 rs.h   rs.h 
skipping to change at line 50 skipping to change at line 50
* startReplSets forks off a new thread for replica set activities. It cre ates * startReplSets forks off a new thread for replica set activities. It cre ates
* the global theReplSet variable and calls go() on it. * the global theReplSet variable and calls go() on it.
* *
* 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 {
struct HowToFixUp; class Cloner;
struct Target;
class DBClientConnection; class DBClientConnection;
class ReplSetImpl; struct HowToFixUp;
class OplogReader; class OplogReader;
class ReplSetImpl;
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;
/* 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:
skipping to change at line 79 skipping to change at line 80
ReplSetConfig::MemberCfg& configw() { return _config; } ReplSetConfig::MemberCfg& configw() { return _config; }
const HeartbeatInfo& hbinfo() const { return _hbinfo; } const HeartbeatInfo& hbinfo() const { return _hbinfo; }
HeartbeatInfo& get_hbinfo() { return _hbinfo; } HeartbeatInfo& get_hbinfo() { return _hbinfo; }
string lhb() const { return _hbinfo.lastHeartbeatMsg; } string lhb() const { return _hbinfo.lastHeartbeatMsg; }
MemberState state() const { return _hbinfo.hbstate; } MemberState state() const { return _hbinfo.hbstate; }
const HostAndPort& h() const { return _h; } const HostAndPort& h() const { return _h; }
unsigned id() const { return _hbinfo.id(); } unsigned id() const { return _hbinfo.id(); }
bool potentiallyHot() const { return _config.potentiallyHot(); } // not arbiter, not priority 0 bool potentiallyHot() const { return _config.potentiallyHot(); } // not arbiter, not priority 0
void summarizeMember(stringstream& s) const; void summarizeMember(stringstream& s) const;
// If we could sync from this member. This doesn't tell us anythin
g about the quality of
// this member, just if they are a possible sync target.
bool syncable() const;
private: private:
friend class ReplSetImpl; friend class ReplSetImpl;
ReplSetConfig::MemberCfg _config; ReplSetConfig::MemberCfg _config;
const HostAndPort _h; const HostAndPort _h;
HeartbeatInfo _hbinfo; HeartbeatInfo _hbinfo;
}; };
class Manager : public task::Server { class Manager : public task::Server {
ReplSetImpl *rs; ReplSetImpl *rs;
skipping to change at line 150 skipping to change at line 154
* Say we have an S1--->S2--->P situation and this node is S2. rid * Say we have an S1--->S2--->P situation and this node is S2. rid
* would refer to S1. S2 would create a ghost slave of S1 and conn ect * would refer to S1. S2 would create a ghost slave of S1 and conn ect
* it to P (_currentSyncTarget). Then it would use this connection to * it to P (_currentSyncTarget). Then it would use this connection to
* pretend to be S1, replicating off of P. * pretend to be S1, replicating off of P.
*/ */
void percolate(const BSONObj& rid, const OpTime& last); void percolate(const BSONObj& rid, const OpTime& last);
void associateSlave(const BSONObj& rid, const int memberId); void associateSlave(const BSONObj& rid, const int memberId);
void updateSlave(const mongo::OID& id, const OpTime& last); void updateSlave(const mongo::OID& id, const OpTime& last);
}; };
struct Target;
class Consensus { class Consensus {
ReplSetImpl &rs; ReplSetImpl &rs;
struct LastYea { struct LastYea {
LastYea() : when(0), who(0xffffffff) { } LastYea() : when(0), who(0xffffffff) { }
time_t when; time_t when;
unsigned who; unsigned who;
}; };
static SimpleMutex lyMutex; static SimpleMutex lyMutex;
Guarded<LastYea,lyMutex> ly; Guarded<LastYea,lyMutex> ly;
unsigned yea(unsigned memberId); // throws VoteException unsigned yea(unsigned memberId); // throws VoteException
skipping to change at line 337 skipping to change at line 339
static string stateAsHtml(MemberState state); static string stateAsHtml(MemberState state);
/* todo thread */ /* todo thread */
void msgUpdateHBInfo(HeartbeatInfo); void msgUpdateHBInfo(HeartbeatInfo);
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
// that prevents the sync source from changing.
bool shouldChangeSyncTarget(const OpTime& target) const;
/** /**
* Find the closest member (using ping time) with a higher latest o ptime. * Find the closest member (using ping time) with a higher latest o ptime.
*/ */
const Member* getMemberToSyncTo(); const Member* getMemberToSyncTo();
void veto(const string& host, unsigned secs=10); void veto(const string& host, unsigned secs=10);
bool gotForceSync(); bool gotForceSync();
void goStale(const Member* m, const BSONObj& o); void goStale(const Member* m, const BSONObj& o);
private: private:
set<ReplSetHealthPollTask*> healthTasks; set<ReplSetHealthPollTask*> healthTasks;
skipping to change at line 504 skipping to change at line 509
void getTargets(list<Target>&, int &configVersion); void getTargets(list<Target>&, int &configVersion);
void startThreads(); void startThreads();
friend class FeedbackThread; friend class FeedbackThread;
friend class CmdReplSetElect; friend class CmdReplSetElect;
friend class Member; friend class Member;
friend class Manager; friend class Manager;
friend class GhostSync; friend class GhostSync;
friend class Consensus; friend class Consensus;
private: private:
bool _syncDoInitialSync_clone( const char *master, const list<strin bool _syncDoInitialSync_clone(Cloner &cloner, const char *master,
g>& dbs , bool dataPass ); const list<string>& dbs, bool dataPas
s);
bool _syncDoInitialSync_applyToHead( replset::SyncTail& syncer, Opl ogReader* r , bool _syncDoInitialSync_applyToHead( replset::SyncTail& syncer, Opl ogReader* r ,
const Member* source, const BS ONObj& lastOp, const Member* source, const BS ONObj& lastOp,
BSONObj& minValidOut); BSONObj& minValidOut);
void _syncDoInitialSync(); void _syncDoInitialSync();
void syncDoInitialSync(); void syncDoInitialSync();
void _syncThread(); void _syncThread();
void syncTail(); void syncTail();
unsigned _syncRollback(OplogReader& r); unsigned _syncRollback(OplogReader& r);
void syncFixUp(HowToFixUp& h, OplogReader& r); void syncFixUp(HowToFixUp& h, OplogReader& r);
skipping to change at line 545 skipping to change at line 551
static const int replWriterThreadCount; static const int replWriterThreadCount;
static const int replPrefetcherThreadCount; static const int replPrefetcherThreadCount;
threadpool::ThreadPool& getPrefetchPool() { return _prefetcherPool; } threadpool::ThreadPool& getPrefetchPool() { return _prefetcherPool; }
threadpool::ThreadPool& getWriterPool() { return _writerPool; } threadpool::ThreadPool& getWriterPool() { return _writerPool; }
const ReplSetConfig::MemberCfg& myConfig() const { return _config; } const ReplSetConfig::MemberCfg& myConfig() const { return _config; }
bool tryToGoLiveAsASecondary(OpTime&); // readlocks bool tryToGoLiveAsASecondary(OpTime&); // readlocks
void syncRollback(OplogReader& r); void syncRollback(OplogReader& r);
void syncThread(); void syncThread();
const OpTime lastOtherOpTime() const; const OpTime lastOtherOpTime() const;
/**
* When a member reaches its minValid optime it is in a consistent
state. Thus, minValid is
* set as the last step in initial sync (if no minValid is set, thi
s indicates that initial
* sync is necessary). It is also used during "normal" sync: the la
st op in each batch is
* used to set minValid, to indicate that we are in a consistent st
ate when the batch has
* been fully applied.
*/
static void setMinValid(BSONObj obj); static void setMinValid(BSONObj obj);
static OpTime getMinValid();
int oplogVersion; int oplogVersion;
private: private:
IndexPrefetchConfig _indexPrefetchConfig; IndexPrefetchConfig _indexPrefetchConfig;
}; };
class ReplSet : public ReplSetImpl { class ReplSet : public ReplSetImpl {
public: public:
static ReplSet* make(ReplSetCmdline& replSetCmdline); static ReplSet* make(ReplSetCmdline& replSetCmdline);
virtual ~ReplSet() {} virtual ~ReplSet() {}
skipping to change at line 628 skipping to change at line 643
*/ */
class ReplSetCommand : public Command { class ReplSetCommand : public Command {
protected: protected:
ReplSetCommand(const char * s, bool show=false) : Command(s, show) { } ReplSetCommand(const char * s, bool show=false) : Command(s, show) { }
virtual bool slaveOk() const { return true; } virtual bool slaveOk() const { return true; }
virtual bool adminOnly() const { return true; } virtual bool adminOnly() const { return true; }
virtual bool logTheOp() { return false; } virtual bool logTheOp() { return false; }
virtual LockType locktype() const { return NONE; } virtual LockType locktype() const { return NONE; }
virtual void help( stringstream &help ) const { help << "internal"; } virtual void help( stringstream &help ) const { help << "internal"; }
/**
* Some replica set commands call this and then call check(). This
is
* intentional, as they might do things before theReplSet is initia
lized
* that still need to be checked for auth.
*/
bool checkAuth(string& errmsg, BSONObjBuilder& result) {
if( !noauth ) {
AuthenticationInfo *ai = cc().getAuthenticationInfo();
if (!ai->isAuthorizedForLock("admin", locktype())) {
errmsg = "replSet command unauthorized";
return false;
}
}
return true;
}
bool check(string& errmsg, BSONObjBuilder& result) { bool check(string& errmsg, BSONObjBuilder& result) {
if( !replSet ) { if( !replSet ) {
errmsg = "not running with --replSet"; errmsg = "not running with --replSet";
if( cmdLine.configsvr ) { if( cmdLine.configsvr ) {
result.append("info", "configsvr"); // for shell prompt result.append("info", "configsvr"); // for shell prompt
} }
return false; return false;
} }
if( theReplSet == 0 ) { if( theReplSet == 0 ) {
result.append("startupStatus", ReplSet::startupStatus); result.append("startupStatus", ReplSet::startupStatus);
string s; string s;
errmsg = ReplSet::startupStatusMsg.empty() ? "replset unkno wn error 2" : ReplSet::startupStatusMsg.get(); errmsg = ReplSet::startupStatusMsg.empty() ? "replset unkno wn error 2" : ReplSet::startupStatusMsg.get();
if( ReplSet::startupStatus == 3 ) if( ReplSet::startupStatus == 3 )
result.append("info", "run rs.initiate(...) if not yet done for the set"); result.append("info", "run rs.initiate(...) if not yet done for the set");
return false; return false;
} }
return checkAuth(errmsg, result); return true;
} }
}; };
/** /**
* does local authentication * does local authentication
* directly authorizes against AuthenticationInfo * directly authorizes against AuthenticationInfo
*/ */
void replLocalAuth(); void replLocalAuth();
/** inlines ----------------- */ /** inlines ----------------- */
 End of changes. 11 change blocks. 
26 lines changed or deleted 29 lines changed or added


 s2cellid.h   s2cellid.h 
skipping to change at line 285 skipping to change at line 285
// this cell id. Since cells are represented by the Hilbert curve positi on // this cell id. Since cells are represented by the Hilbert curve positi on
// at the center of the cell, the returned (i,j) for non-leaf cells will be // at the center of the cell, the returned (i,j) for non-leaf cells will be
// a leaf cell adjacent to the cell center. If "orientation" is non-NULL , // a leaf cell adjacent to the cell center. If "orientation" is non-NULL ,
// also return the Hilbert curve orientation for the current cell. // also return the Hilbert curve orientation for the current cell.
int ToFaceIJOrientation(int* pi, int* pj, int* orientation) const; int ToFaceIJOrientation(int* pi, int* pj, int* orientation) const;
// Return the lowest-numbered bit that is on for this cell id, which is // Return the lowest-numbered bit that is on for this cell id, which is
// equal to (uint64(1) << (2 * (kMaxLevel - level))). So for example, // equal to (uint64(1) << (2 * (kMaxLevel - level))). So for example,
// a.lsb() <= b.lsb() if and only if a.level() >= b.level(), but the // a.lsb() <= b.lsb() if and only if a.level() >= b.level(), but the
// first test is more efficient. // first test is more efficient.
#pragma warning(push)
#pragma warning( disable: 4146 )
uint64 lsb() const { return id_ & -id_; } uint64 lsb() const { return id_ & -id_; }
#pragma warning(pop)
// Return the lowest-numbered bit that is on for cells at the given level . // Return the lowest-numbered bit that is on for cells at the given level .
inline static uint64 lsb_for_level(int level) { inline static uint64 lsb_for_level(int level) {
return uint64(1) << (2 * (kMaxLevel - level)); return uint64(1) << (2 * (kMaxLevel - level));
} }
private: private:
// This is the offset required to wrap around from the beginning of the // This is the offset required to wrap around from the beginning of the
// Hilbert curve to the end or vice versa; see next_wrap() and prev_wrap( ). // Hilbert curve to the end or vice versa; see next_wrap() and prev_wrap( ).
static uint64 const kWrapOffset; // = uint64(kNumFaces) << kPosBits; static uint64 const kWrapOffset; // = uint64(kNumFaces) << kPosBits;
skipping to change at line 410 skipping to change at line 413
DCHECK(is_valid()); DCHECK(is_valid());
DCHECK(other.is_valid()); DCHECK(other.is_valid());
return other.range_min() <= range_max() && other.range_max() >= range_min (); return other.range_min() <= range_max() && other.range_max() >= range_min ();
} }
inline S2CellId S2CellId::parent(int level) const { inline S2CellId S2CellId::parent(int level) const {
DCHECK(is_valid()); DCHECK(is_valid());
DCHECK_GE(level, 0); DCHECK_GE(level, 0);
DCHECK_LE(level, this->level()); DCHECK_LE(level, this->level());
uint64 new_lsb = lsb_for_level(level); uint64 new_lsb = lsb_for_level(level);
#pragma warning(push)
#pragma warning( disable: 4146 )
return S2CellId((id_ & -new_lsb) | new_lsb); return S2CellId((id_ & -new_lsb) | new_lsb);
#pragma warning(pop)
} }
inline S2CellId S2CellId::parent() const { inline S2CellId S2CellId::parent() const {
DCHECK(is_valid()); DCHECK(is_valid());
DCHECK(!is_face()); DCHECK(!is_face());
uint64 new_lsb = lsb() << 2; uint64 new_lsb = lsb() << 2;
#pragma warning(push)
#pragma warning( disable: 4146 )
return S2CellId((id_ & -new_lsb) | new_lsb); return S2CellId((id_ & -new_lsb) | new_lsb);
#pragma warning(pop)
} }
inline S2CellId S2CellId::child(int position) const { inline S2CellId S2CellId::child(int position) const {
DCHECK(is_valid()); DCHECK(is_valid());
DCHECK(!is_leaf()); DCHECK(!is_leaf());
// To change the level, we need to move the least-significant bit two // To change the level, we need to move the least-significant bit two
// positions downward. We do this by subtracting (4 * new_lsb) and addin g // positions downward. We do this by subtracting (4 * new_lsb) and addin g
// new_lsb. Then to advance to the given child cell, we add // new_lsb. Then to advance to the given child cell, we add
// (2 * position * new_lsb). // (2 * position * new_lsb).
uint64 new_lsb = lsb() >> 2; uint64 new_lsb = lsb() >> 2;
 End of changes. 6 change blocks. 
0 lines changed or deleted 9 lines changed or added


 s2common.h   s2common.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/>.
*/ */
#include "mongo/db/geo/geojsonparser.h" #include "mongo/db/geo/geoparser.h"
#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. // 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(S2RegionCoverer *coverer, const S2Region static BSONObj coverAsBSON(const vector<S2CellId> &cover, const str
&region, ing& field,
const string& field); const int coarsestIndexedLevel);
}; };
// Used for passing geo data from the newCursor entry point to the S2Cu rsor class. // Used for passing geo data from the newCursor entry point to the S2Cu rsor class.
struct GeoQueryField { struct QueryGeometry {
GeoQueryField(const string& f) : field(f), cell(NULL), line(NULL), QueryGeometry(const string& f) : field(f), predicate(INTERSECT) {}
polygon(NULL) { } enum Predicate {
WITHIN,
INTERSECT,
};
// Name of the field in the query. // Name of the field in the query.
string field; string field;
// Only one of these should be non-NULL. S2Region is a superclass but it only supports // Only one of these should be non-NULL. S2Region is a superclass but it only supports
// testing against S2Cells. We need the most specific class we can get. // testing against S2Cells. We need the most specific class we can get.
// Owned by S2Cursor. // Owned by S2Cursor.
S2Cell *cell; shared_ptr<S2Cell> cell;
S2Polyline *line; shared_ptr<S2Polyline> line;
S2Polygon *polygon; shared_ptr<S2Polygon> polygon;
Predicate predicate;
// Does this GeoQueryField intersect the provided data? Sadly ther string toString() const;
e is no common good way
bool satisfiesPredicate(const BSONObj &obj);
// Does this QueryGeometry intersect the provided data? Sadly ther
e is no common good way
// to check this, so we do different things for all query/data pair s. // to check this, so we do different things for all query/data pair s.
bool intersectsPoint(const S2Cell& otherPoint); bool intersects(const S2Cell& otherPoint);
bool intersectsLine(const S2Polyline& otherLine); bool intersects(const S2Polyline& otherLine);
bool intersectsPolygon(const S2Polygon& otherPolygon); bool intersects(const S2Polygon& otherPolygon);
// And, within.
bool isWithin(const S2Cell& otherPoint);
bool isWithin(const S2Polyline& otherLine);
bool isWithin(const S2Polygon& otherPolygon);
// 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;
// Delete the not NULL region.
void free();
// Get the centroid, boring if we're a point, interesting if we're not. // Get the centroid, boring if we're a point, interesting if we're not.
S2Point getCentroid() const; S2Point getCentroid() const;
// Try to parse the provided object into the right place. // Try to parse the provided object into the right place.
bool parseFrom(BSONObj& obj); bool parseFrom(const BSONObj &obj);
}; };
struct S2IndexingParams { struct S2IndexingParams {
// Since we take the cartesian product when we generate keys for an insert, // Since we take the cartesian product when we generate keys for an insert,
// we need a cap. // we need a cap.
size_t maxKeysPerInsert; size_t maxKeysPerInsert;
// This is really an advisory parameter that we pass to the cover g enerator. The // This is really an advisory parameter that we pass to the cover g enerator. The
// finest/coarsest index level determine the required # of cells. // finest/coarsest index level determine the required # of cells.
int maxCellsInCovering; int maxCellsInCovering;
// What's the finest grained level that we'll index? When we query for a point // 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. // we start at that -- we index nothing finer than this.
int finestIndexedLevel; int finestIndexedLevel;
// And, what's the coarsest? When we search in larger coverings we know we // And, what's the coarsest? When we search in larger coverings we know we
// can stop here -- we index nothing coarser than this. // can stop here -- we index nothing coarser than this.
int coarsestIndexedLevel; int coarsestIndexedLevel;
// What is the radius of the sphere/earth we're using? Not everybo
dy likes giving
// radians or degrees all the time. In meters.
double radius; double radius;
string toString() const { string toString() const {
stringstream ss; stringstream ss;
ss << "maxKeysPerInsert: " << maxKeysPerInsert << endl; ss << "maxKeysPerInsert: " << maxKeysPerInsert << endl;
ss << "maxCellsInCovering: " << maxCellsInCovering << endl; ss << "maxCellsInCovering: " << maxCellsInCovering << endl;
ss << "finestIndexedLevel: " << finestIndexedLevel << endl; ss << "finestIndexedLevel: " << finestIndexedLevel << endl;
ss << "coarsestIndexedLevel: " << coarsestIndexedLevel << endl; ss << "coarsestIndexedLevel: " << coarsestIndexedLevel << endl;
ss << "radius: " << radius << endl;
return ss.str(); return ss.str();
} }
void configureCoverer(S2RegionCoverer *coverer) const { void configureCoverer(S2RegionCoverer *coverer) const {
coverer->set_min_level(coarsestIndexedLevel); coverer->set_min_level(coarsestIndexedLevel);
coverer->set_max_level(finestIndexedLevel); coverer->set_max_level(finestIndexedLevel);
// This is advisory; the two above are strict. // This is advisory; the two above are strict.
coverer->set_max_cells(maxCellsInCovering); coverer->set_max_cells(maxCellsInCovering);
} }
}; };
 End of changes. 10 change blocks. 
22 lines changed or deleted 30 lines changed or added


 s2cursor.h   s2cursor.h 
skipping to change at line 32 skipping to change at line 32
#include "mongo/db/matcher.h" #include "mongo/db/matcher.h"
#include "mongo/db/queryutil.h" #include "mongo/db/queryutil.h"
#include "mongo/db/geo/s2common.h" #include "mongo/db/geo/s2common.h"
namespace mongo { namespace mongo {
class BtreeCursor; class BtreeCursor;
class S2Cursor : public Cursor { class S2Cursor : public Cursor {
public: public:
S2Cursor(const BSONObj &keyPattern, const IndexDetails* details, co nst BSONObj &query, S2Cursor(const BSONObj &keyPattern, const IndexDetails* details, co nst BSONObj &query,
const vector<GeoQueryField> &regions, const S2IndexingPara ms &params, const vector<QueryGeometry> &regions, const S2IndexingPara ms &params,
int numWanted); int numWanted);
virtual ~S2Cursor(); virtual ~S2Cursor();
virtual CoveredIndexMatcher *matcher() const; virtual CoveredIndexMatcher *matcher() const;
virtual bool supportYields() { return true; } virtual bool supportYields() { return true; }
virtual bool supportGetMore() { return true; } virtual bool supportGetMore() { return true; }
virtual bool isMultiKey() const { return true; } virtual bool isMultiKey() const { return true; }
virtual bool autoDedup() const { return false; } virtual bool autoDedup() const { return false; }
virtual bool modifiedKeys() const { return true; } virtual bool modifiedKeys() const { return true; }
virtual bool getsetdup(DiskLoc loc) { return false; } virtual bool getsetdup(DiskLoc loc) { return false; }
skipping to change at line 60 skipping to change at line 60
virtual BSONObj currKey() const; virtual BSONObj currKey() const;
virtual DiskLoc refLoc(); virtual DiskLoc refLoc();
virtual void noteLocation(); virtual void noteLocation();
virtual void checkLocation(); virtual void checkLocation();
virtual long long nscanned(); virtual long long nscanned();
virtual void explainDetails(BSONObjBuilder& b); virtual void explainDetails(BSONObjBuilder& b);
private: private:
// Make an object that describes the restrictions on all possible v alid keys. // Make an object that describes the restrictions on all possible v alid keys.
// It's kind of a monstrous object. Thanks, FieldRangeSet, for doi ng all the work // It's kind of a monstrous object. Thanks, FieldRangeSet, for doi ng all the work
// for us. // for us.
BSONObj makeFRSObject(); // Returns false if the FRS object would be empty.
bool makeFRSObject(BSONObj *out);
// Need this to make a FieldRangeSet. // Need this to make a FieldRangeSet.
const IndexDetails *_details; const IndexDetails *_details;
// The query with the geo stuff taken out. We use this with a matc her. // The query with the geo stuff taken out. We use this with a matc her.
BSONObj _filteredQuery; BSONObj _filteredQuery;
// What geo regions are we looking for? // What geo regions are we looking for?
vector<GeoQueryField> _fields; vector<QueryGeometry> _fields;
// We use this for matching non-GEO stuff. // We use this for matching non-GEO stuff.
shared_ptr<CoveredIndexMatcher> _matcher; shared_ptr<CoveredIndexMatcher> _matcher;
// How were the keys created? We need this to search for the right stuff. // How were the keys created? We need this to search for the right stuff.
S2IndexingParams _params; S2IndexingParams _params;
// How many things did we scan/look at? Not sure exactly how this is defined. // How many things did we scan/look at? Not sure exactly how this is defined.
long long _nscanned; long long _nscanned;
// We have to pass this to the FieldRangeVector ctor (in modified f orm). // We have to pass this to the FieldRangeVector ctor (in modified f orm).
BSONObj _keyPattern; BSONObj _keyPattern;
// How many docs do we want to return? Starts with the # the user requests // How many docs do we want to return? Starts with the # the user requests
// and goes down. // and goes down.
 End of changes. 3 change blocks. 
3 lines changed or deleted 4 lines changed or added


 s2nearcursor.h   s2nearcursor.h 
skipping to change at line 31 skipping to change at line 31
#include "mongo/db/cursor.h" #include "mongo/db/cursor.h"
#include "mongo/db/diskloc.h" #include "mongo/db/diskloc.h"
#include "mongo/db/matcher.h" #include "mongo/db/matcher.h"
#include "mongo/db/queryutil.h" #include "mongo/db/queryutil.h"
#include "mongo/db/geo/s2common.h" #include "mongo/db/geo/s2common.h"
namespace mongo { namespace mongo {
class S2NearCursor : public Cursor { class S2NearCursor : public Cursor {
public: public:
S2NearCursor(const BSONObj &keyPattern, const IndexDetails* details , const BSONObj &query, S2NearCursor(const BSONObj &keyPattern, const IndexDetails* details , const BSONObj &query,
const vector<GeoQueryField> &regions, const S2Indexing Params &params, const vector<QueryGeometry> &regions, const S2Indexing Params &params,
int numWanted, double maxDistance); int numWanted, double maxDistance);
virtual ~S2NearCursor(); virtual ~S2NearCursor();
virtual CoveredIndexMatcher *matcher() const; virtual CoveredIndexMatcher *matcher() const;
virtual bool supportYields() { return true; } virtual bool supportYields() { return true; }
virtual bool supportGetMore() { return true; } virtual bool supportGetMore() { return true; }
virtual bool isMultiKey() const { return true; } virtual bool isMultiKey() const { return true; }
virtual bool autoDedup() const { return false; } virtual bool autoDedup() const { return false; }
virtual bool modifiedKeys() const { return true; } virtual bool modifiedKeys() const { return true; }
virtual bool getsetdup(DiskLoc loc) { return false; } virtual bool getsetdup(DiskLoc loc) { return false; }
skipping to change at line 55 skipping to change at line 55
virtual Record* _current(); virtual Record* _current();
virtual BSONObj current(); virtual BSONObj current();
virtual DiskLoc currLoc(); virtual DiskLoc currLoc();
virtual bool advance(); virtual bool advance();
virtual BSONObj currKey() const; virtual BSONObj currKey() const;
virtual DiskLoc refLoc(); virtual DiskLoc refLoc();
virtual void noteLocation(); virtual void noteLocation();
virtual void checkLocation(); virtual void checkLocation();
virtual long long nscanned(); virtual long long nscanned();
virtual void explainDetails(BSONObjBuilder& b); virtual void explainDetails(BSONObjBuilder& b);
double currentDistance() const;
private: private:
// We use this to cache results of the search. Results are sorted to have decreasing // We use this to cache results of the search. Results are sorted to have decreasing
// distance, and callers are interested in loc and key. // distance, and callers are interested in loc and key.
struct Result { struct Result {
Result(const DiskLoc &dl, const BSONObj &ck, double dist) : loc (dl), key(ck), Result(const DiskLoc &dl, const BSONObj &ck, double dist) : loc (dl), key(ck),
dis tance(dist) { } dis tance(dist) { }
bool operator<(const Result& other) const { bool operator<(const Result& other) const {
// We want increasing distance, not decreasing, so we rever se the <. // We want increasing distance, not decreasing, so we rever se the <.
return distance > other.distance; return distance > other.distance;
} }
skipping to change at line 79 skipping to change at line 81
// Make the object that describes all keys that are within our curr ent search annulus. // Make the object that describes all keys that are within our curr ent search annulus.
BSONObj makeFRSObject(); BSONObj makeFRSObject();
// Fill _results with all of the results in the annulus defined by _innerRadius and // Fill _results with all of the results in the annulus defined by _innerRadius and
// _outerRadius. If no results are found, grow the annulus and rep eat until success (or // _outerRadius. If no results are found, grow the annulus and rep eat until success (or
// until the edge of the world). // until the edge of the world).
void fillResults(); void fillResults();
// Grow _innerRadius and _outerRadius by _radiusIncrement, capping _outerRadius at halfway // Grow _innerRadius and _outerRadius by _radiusIncrement, capping _outerRadius at halfway
// around the world (pi * _params.radius). // around the world (pi * _params.radius).
void nextAnnulus(); void nextAnnulus();
double distanceBetween(const QueryGeometry &field, const BSONObj &o bj);
// Need this to make a FieldRangeSet. // Need this to make a FieldRangeSet.
const IndexDetails *_details; const IndexDetails *_details;
// The query with the geo stuff taken out. We use this with a matc
her. // How we need/use the query:
// Matcher: Can have geo fields in it, but only with $within.
// This only really happens (right now) from geoNear comma
nd.
// We assume the caller takes care of this in the right wa
y.
// FRS: No geo fields allowed!
// So, on that note: the query with the geo stuff taken out, used b
y makeFRSObject().
BSONObj _filteredQuery; BSONObj _filteredQuery;
// What geo regions are we looking for? // What geo regions are we looking for?
vector<GeoQueryField> _fields; vector<QueryGeometry> _fields;
// We use this for matching non-GEO stuff. // We use this for matching non-GEO stuff.
shared_ptr<CoveredIndexMatcher> _matcher; shared_ptr<CoveredIndexMatcher> _matcher;
// How were the keys created? We need this to search for the right stuff. // How were the keys created? We need this to search for the right stuff.
S2IndexingParams _params; S2IndexingParams _params;
// How many things did we scan/look at? Not sure exactly how this is defined. // How many things did we scan/look at? Not sure exactly how this is defined.
long long _nscanned; long long _nscanned;
// We have to pass this to the FieldRangeVector ctor (in modified f orm). // We have to pass this to the FieldRangeVector ctor (in modified f orm).
BSONObj _keyPattern; BSONObj _keyPattern;
// We also pass this to the FieldRangeVector ctor. // We also pass this to the FieldRangeVector ctor.
IndexSpec _specForFRV; IndexSpec _specForFRV;
 End of changes. 5 change blocks. 
4 lines changed or deleted 15 lines changed or added


 s2regioncoverer.h   s2regioncoverer.h 
skipping to change at line 143 skipping to change at line 143
// Given a connected region and a starting point, return a set of cells a t // Given a connected region and a starting point, return a set of cells a t
// the given level that cover the region. // the given level that cover the region.
static void GetSimpleCovering(S2Region const& region, S2Point const& star t, static void GetSimpleCovering(S2Region const& region, S2Point const& star t,
int level, vector<S2CellId>* output); int level, vector<S2CellId>* output);
private: private:
struct Candidate { struct Candidate {
S2Cell cell; S2Cell cell;
bool is_terminal; // Cell should not be expanded further. bool is_terminal; // Cell should not be expanded further.
int num_children; // Number of children that intersect the regio n. int num_children; // Number of children that intersect the regio n.
#pragma warning(push)
#pragma warning( disable: 4200 )
Candidate* children[0]; // Actual size may be 0, 4, 16, or 64 elements . Candidate* children[0]; // Actual size may be 0, 4, 16, or 64 elements .
#pragma warning(pop)
}; };
// If the cell intersects the given region, return a new candidate with n o // If the cell intersects the given region, return a new candidate with n o
// children, otherwise return NULL. Also marks the candidate as "termina l" // children, otherwise return NULL. Also marks the candidate as "termina l"
// if it should not be expanded further. // if it should not be expanded further.
Candidate* NewCandidate(S2Cell const& cell); Candidate* NewCandidate(S2Cell const& cell);
// Return the log base 2 of the maximum number of children of a candidate . // Return the log base 2 of the maximum number of children of a candidate .
inline int max_children_shift() const { return 2 * level_mod_; } inline int max_children_shift() const { return 2 * level_mod_; }
 End of changes. 2 change blocks. 
0 lines changed or deleted 3 lines changed or added


 sasl_client_authenticate.h   sasl_client_authenticate.h 
skipping to change at line 41 skipping to change at line 41
* parameter. * parameter.
* *
* The "saslParameters" BSONObj should be initialized with zero or more of the * The "saslParameters" BSONObj should be initialized with zero or more of the
* fields below. Which fields are required depends on the mechanism. Consult the * fields below. Which fields are required depends on the mechanism. Consult the
* libgsasl documentation. * libgsasl documentation.
* *
* "mechanism": The string name of the sasl mechanism to use. Mand atory. * "mechanism": The string name of the sasl mechanism to use. Mand atory.
* "autoAuthorize": Truthy values tell the server to automatically acquire privileges on * "autoAuthorize": Truthy values tell the server to automatically acquire privileges on
* all resources after successful authentication, which is the default. Falsey values * all resources after successful authentication, which is the default. Falsey values
* instruct the server to await separate privilege-acquisition commands. * instruct the server to await separate privilege-acquisition commands.
* "database": The database target of the auth command. Optional f * "user": The string name of the principal to authenticate, GSASL_
or GSSAPI/Kerberos. AUTHID.
* "principal": The string name of the principal to authenticate, G * "userSource": The database target of the auth command, which ide
SASL_AUTHID. ntifies the location
* "password": The password data, GSASL_PASSWORD. * of the credential information for the principal. May be "$s
asl" if credential
* information is stored outside of the mongo cluster.
* "pwd": The password data, GSASL_PASSWORD.
* "serviceName": The GSSAPI service name to use. Defaults to "mon godb". * "serviceName": The GSSAPI service name to use. Defaults to "mon godb".
* "serviceHostname": The GSSAPI hostname to use. Defaults to the name of the remote host. * "serviceHostname": The GSSAPI hostname to use. Defaults to the name of the remote host.
* *
* Other fields in saslParameters are silently ignored. * Other fields in saslParameters are silently ignored.
* *
* "sessionHook" is a pointer to optional data, which may be used by th e gsasl_callback * "sessionHook" is a pointer to optional data, which may be used by th e gsasl_callback
* previously set on "gsasl". The session hook is set on an underlying Gsasl_session using * previously set on "gsasl". The session hook is set on an underlying Gsasl_session using
* gsasl_session_hook_set, and may be accessed by callbacks using gsasl _session_hook_get. * gsasl_session_hook_set, and may be accessed by callbacks using gsasl _session_hook_get.
* See the gsasl documentation. * See the gsasl documentation.
* *
skipping to change at line 117 skipping to change at line 119
/// Field containing password information for saslClientAuthenticate(). /// Field containing password information for saslClientAuthenticate().
extern const char* const saslCommandPasswordFieldName; extern const char* const saslCommandPasswordFieldName;
/// Field containing sasl payloads passed to and from the server. /// Field containing sasl payloads passed to and from the server.
extern const char* const saslCommandPayloadFieldName; extern const char* const saslCommandPayloadFieldName;
/// Field containing the string identifier of the principal to authenti cate in /// Field containing the string identifier of the principal to authenti cate in
/// saslClientAuthenticate(). /// saslClientAuthenticate().
extern const char* const saslCommandPrincipalFieldName; extern const char* const saslCommandPrincipalFieldName;
/// Field containing the string identifier of the database containing c
redential information,
/// or "$sasl" if the credential information is stored outside of the m
ongo cluster.
extern const char* const saslCommandPrincipalSourceFieldName;
/// Field overriding the FQDN of the hostname hosting the mongodb srevi ce in /// Field overriding the FQDN of the hostname hosting the mongodb srevi ce in
/// saslClientAuthenticate(). /// saslClientAuthenticate().
extern const char* const saslCommandServiceHostnameFieldName; extern const char* const saslCommandServiceHostnameFieldName;
/// Field overriding the name of the mongodb service saslClientAuthenti cate(). /// Field overriding the name of the mongodb service saslClientAuthenti cate().
extern const char* const saslCommandServiceNameFieldName; extern const char* const saslCommandServiceNameFieldName;
/// Default database against which sasl authentication commands should run. /// Default database against which sasl authentication commands should run.
extern const char* const saslDefaultDBName; extern const char* const saslDefaultDBName;
 End of changes. 2 change blocks. 
5 lines changed or deleted 14 lines changed or added


 server_status.h   server_status.h 
skipping to change at line 22 skipping to change at line 22
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "mongo/db/commands.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/db/stats/counters.h" #include "mongo/db/stats/counters.h"
#include "mongo/platform/atomic_word.h" #include "mongo/platform/atomic_word.h"
namespace mongo { namespace mongo {
class ServerStatusSection { class ServerStatusSection {
public: public:
ServerStatusSection( const string& sectionName ); ServerStatusSection( const string& sectionName );
virtual ~ServerStatusSection(){} virtual ~ServerStatusSection(){}
skipping to change at line 54 skipping to change at line 55
* foo : 1 = included * foo : 1 = included
* foo missing = included * foo missing = included
* includeByDefault returning false * includeByDefault returning false
* foo : 0 = not included * foo : 0 = not included
* foo : 1 = included * foo : 1 = included
* foo missing = false * foo missing = false
*/ */
virtual bool includeByDefault() const = 0; virtual bool includeByDefault() const = 0;
/** /**
* if only admins can view this section * Adds the privileges that are required to view this section
* API will change to better auth version * TODO: Remove this empty default implementation and implement for
every section.
*/ */
virtual bool adminOnly() const = 0; virtual void addRequiredPrivileges(std::vector<Privilege>* out) {};
/** /**
* actually generate the result * actually generate the result
* @param configElement the element from the actual command related to this section * @param configElement the element from the actual command related to this section
* so if the section is 'foo', this is cmdObj[ 'foo'] * so if the section is 'foo', this is cmdObj[ 'foo']
*/ */
virtual BSONObj generateSection( const BSONElement& configElement, bool userIsAdmin ) const = 0; virtual BSONObj generateSection(const BSONElement& configElement) c onst = 0;
private: private:
const string _sectionName; const string _sectionName;
}; };
class OpCounterServerStatusSection : public ServerStatusSection { class OpCounterServerStatusSection : public ServerStatusSection {
public: public:
OpCounterServerStatusSection( const string& sectionName, OpCounters * counters ); OpCounterServerStatusSection( const string& sectionName, OpCounters * counters );
virtual bool includeByDefault() const { return true; } virtual bool includeByDefault() const { return true; }
virtual bool adminOnly() const { return false; }
virtual BSONObj generateSection( const BSONElement& configElement, bool userIsAdmin ) const; virtual BSONObj generateSection(const BSONElement& configElement) c onst;
private: private:
const OpCounters* _counters; const OpCounters* _counters;
}; };
class ServerStatusMetric { class ServerStatusMetric {
public: public:
/** /**
* @param name is a dotted path of a counter name * @param name is a dotted path of a counter name
* if name starts with . its treated as a path from the serverStatus root * if name starts with . its treated as a path from the serverStatus root
* otherwise it will live under the "counters" namespac e * otherwise it will live under the "counters" namespac e
* so foo.bar would be serverStatus().counters.foo.bar * so foo.bar would be serverStatus().counters.foo.bar
*/ */
ServerStatusMetric( const string& name, bool adminOnly ); ServerStatusMetric(const string& name);
virtual ~ServerStatusMetric(){} virtual ~ServerStatusMetric(){}
string getMetricName() const { return _name; } string getMetricName() const { return _name; }
virtual bool adminOnly() const { return _adminOnly; }
virtual void appendAtLeaf( BSONObjBuilder& b ) const = 0; virtual void appendAtLeaf( BSONObjBuilder& b ) const = 0;
protected: protected:
static string _parseLeafName( const string& name ); static string _parseLeafName( const string& name );
const string _name; const string _name;
const bool _adminOnly;
const string _leafName; const string _leafName;
}; };
/** /**
* usage * usage
* *
* declared once * declared once
* Counter counter; * Counter counter;
* ServerStatusMetricField myAwesomeCounterDisplay( "path.to.counter ", false, &counter ); * ServerStatusMetricField myAwesomeCounterDisplay( "path.to.counter ", &counter );
* *
* call * call
* counter.hit(); * counter.hit();
* *
* will show up in db.serverStatus().metrics.path.to.counter * will show up in db.serverStatus().metrics.path.to.counter
*/ */
template< typename T > template< typename T >
class ServerStatusMetricField : public ServerStatusMetric { class ServerStatusMetricField : public ServerStatusMetric {
public: public:
ServerStatusMetricField( const string& name, bool adminOnly, const ServerStatusMetricField( const string& name, const T* t )
T* t ) : ServerStatusMetric(name), _t(t) {
: ServerStatusMetric( name, adminOnly ), _t(t) {
} }
const T* get() { return _t; } const T* get() { return _t; }
virtual void appendAtLeaf( BSONObjBuilder& b ) const { virtual void appendAtLeaf( BSONObjBuilder& b ) const {
b.append( _leafName, *_t ); b.append( _leafName, *_t );
} }
private: private:
const T* _t; const T* _t;
 End of changes. 11 change blocks. 
14 lines changed or deleted 11 lines changed or added


 shapes.h   shapes.h 
skipping to change at line 65 skipping to change at line 65
bool mid(double amin, double amax, double bmin, double bmax, bool m in, double* res) const; bool mid(double amin, double amax, double bmin, double bmax, bool m in, double* res) const;
// TODO(hk): What is the return here? comment // TODO(hk): What is the return here? comment
double intersects(const Box& other) const; double intersects(const Box& other) const;
double area() const; double area() const;
double maxDim() const; double maxDim() const;
Point center() const; Point center() const;
void truncate(double min, double max); void truncate(double min, double max);
void fudge(double error); void fudge(double error);
bool onBoundary(Point p, double fudge = 0); bool onBoundary(Point p, double fudge = 0);
bool inside(Point p, double fudge = 0); bool inside(Point p, double fudge = 0) const;
bool inside(double x, double y, double fudge = 0); bool inside(double x, double y, double fudge = 0) const;
bool contains(const Box& other, double fudge = 0); bool contains(const Box& other, double fudge = 0);
// TODO(hk): This could be private and Polygon could be our friend, or we could // TODO(hk): This could be private and Polygon could be our friend, or we could
// have getters/setters (lots of code change). // have getters/setters (lots of code change).
Point _min; Point _min;
Point _max; Point _max;
}; };
class Polygon { class Polygon {
public: public:
Polygon(); Polygon();
 End of changes. 1 change blocks. 
2 lines changed or deleted 2 lines changed or added


 shard.h   shard.h 
skipping to change at line 318 skipping to change at line 318
extern DBConnectionPool shardConnectionPool; extern DBConnectionPool shardConnectionPool;
class ShardingConnectionHook : public DBConnectionHook { class ShardingConnectionHook : public DBConnectionHook {
public: public:
ShardingConnectionHook( bool shardedConnections ) ShardingConnectionHook( bool shardedConnections )
: _shardedConnections( shardedConnections ) { : _shardedConnections( shardedConnections ) {
} }
virtual void onCreate( DBClientBase * conn ); virtual void onCreate( DBClientBase * conn );
virtual void onHandedOut( DBClientBase * conn );
virtual void onDestroy( DBClientBase * conn ); virtual void onDestroy( DBClientBase * conn );
bool _shardedConnections; bool _shardedConnections;
}; };
} }
 End of changes. 1 change blocks. 
1 lines changed or deleted 0 lines changed or added


 shardkey.h   shardkey.h 
skipping to change at line 21 skipping to change at line 21
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/base/string_data.h"
#include "mongo/db/keypattern.h" #include "mongo/db/keypattern.h"
namespace mongo { namespace mongo {
class Chunk; class Chunk;
class FieldRangeSet; class FieldRangeSet;
/* A ShardKeyPattern is a pattern indicating what data to extract from the object to make the shard key from. /* A ShardKeyPattern is a pattern indicating what data to extract from the object to make the shard key from.
Analogous to an index key pattern. Analogous to an index key pattern.
*/ */
skipping to change at line 78 skipping to change at line 79
see unit test for more examples see unit test for more examples
*/ */
bool hasShardKey( const BSONObj& obj ) const; bool hasShardKey( const BSONObj& obj ) const;
BSONObj key() const { return pattern.toBSON(); } BSONObj key() const { return pattern.toBSON(); }
string toString() const; string toString() const;
BSONObj extractKey(const BSONObj& from) const; BSONObj extractKey(const BSONObj& from) const;
bool partOfShardKey(const char* key ) const { bool partOfShardKey(const StringData& key ) const {
return pattern.hasField(key); return pattern.hasField(key);
} }
bool partOfShardKey(const string& key ) const {
return pattern.hasField(key.c_str()); BSONObj extendRangeBound( const BSONObj& bound , bool makeUpperIncl
usive ) const {
return pattern.extendRangeBound( bound , makeUpperInclusive );
} }
/** /**
* @return * @return
* true if 'this' is a prefix (not necessarily contained) of 'other Pattern'. * true if 'this' is a prefix (not necessarily contained) of 'other Pattern'.
*/ */
bool isPrefixOf( const KeyPattern& otherPattern ) const; bool isPrefixOf( const KeyPattern& otherPattern ) const;
/** /**
* @return * @return
 End of changes. 3 change blocks. 
3 lines changed or deleted 6 lines changed or added


 shell_utils_launcher.h   shell_utils_launcher.h 
skipping to change at line 65 skipping to change at line 65
/** @return up to 100000 characters of the most recent log outp ut. */ /** @return up to 100000 characters of the most recent log outp ut. */
std::string str() const; std::string str() const;
void clear(); void clear();
private: private:
std::stringstream _buffer; std::stringstream _buffer;
}; };
/** /**
* A registry of spawned programs that are identified by a bound po rt or else a system pid. * A registry of spawned programs that are identified by a bound po rt or else a system pid.
* All public member functions are thread safe. * All public member functions are thread safe.
*
* TODO: Clean this up to make the semantics more consistent betwee
n pids and ports
*/ */
class ProgramRegistry { class ProgramRegistry {
public: public:
bool isPortRegistered( int port ) const; bool isPortRegistered( int port ) const;
/** @return pid for a registered port. */ /** @return pid for a registered port. */
pid_t pidForPort( int port ) const; pid_t pidForPort( int port ) const;
/** @return port (-1 if doesn't exist) for a registered pid. */
int portForPid( int port ) const;
/** Register an unregistered port. */ /** Register an unregistered port. */
void registerPort( int port, pid_t pid, int output ); void registerPort( int port, pid_t pid, int output );
void deletePort( int port ); void deletePort( int port );
void getRegisteredPorts( std::vector<int> &ports ); void getRegisteredPorts( std::vector<int> &ports );
bool isPidRegistered( pid_t pid ) const; bool isPidRegistered( pid_t pid ) const;
/** Register an unregistered pid. */ /** Register an unregistered pid. */
void registerPid( pid_t pid, int output ); void registerPid( pid_t pid, int output );
void deletePid( pid_t pid ); void deletePid( pid_t pid );
void getRegisteredPids( vector<pid_t> &pids ); void getRegisteredPids( vector<pid_t> &pids );
 End of changes. 2 change blocks. 
0 lines changed or deleted 5 lines changed or added


 simplerwlock.h   simplerwlock.h 
skipping to change at line 19 skipping to change at line 19
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details. * GNU Affero General Public License for more details.
* *
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "mongo/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(_WIN32) && defined(MONGO_USE_SRW_ON_WINDOWS)
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:
const string name; const string name;
SimpleRWLock(const char *name = 0); SimpleRWLock(const StringData& name = "" );
void lock(); void lock();
void unlock(); void unlock();
void lock_shared(); void lock_shared();
void unlock_shared(); void unlock_shared();
class Shared : boost::noncopyable { class Shared : boost::noncopyable {
SimpleRWLock& _r; SimpleRWLock& _r;
public: public:
Shared(SimpleRWLock& rwlock) : _r(rwlock) {_r.lock_shared(); } Shared(SimpleRWLock& rwlock) : _r(rwlock) {_r.lock_shared(); }
~Shared() { _r.unlock_shared(); } ~Shared() { _r.unlock_shared(); }
}; };
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 sock.h   sock.h 
skipping to change at line 36 skipping to change at line 36
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <errno.h> #include <errno.h>
#ifdef __openbsd__ #ifdef __openbsd__
# include <sys/uio.h> # include <sys/uio.h>
#endif #endif
#endif // _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" #include "mongo/util/net/ssl_manager.h"
#endif #endif
#include "mongo/platform/compiler.h"
namespace mongo { namespace mongo {
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;
skipping to change at line 186 skipping to change at line 188
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 );
~Socket() { ~Socket();
close();
}
bool connect(SockAddr& farEnd); bool connect(SockAddr& farEnd);
void close(); void close();
void send( const char * data , int len, const char *context ); void send( const char * data , int len, const char *context );
void send( const vector< pair< char *, int > > &data, const char *c ontext ); void send( const vector< pair< char *, int > > &data, const char *c ontext );
// recv len or throw SocketException // recv len or throw SocketException
void recv( char * data , int len ); void recv( char * data , int len );
int unsafe_recv( char *buf, int max ); int unsafe_recv( char *buf, int max );
skipping to change at line 221 skipping to change at line 221
void setTimeout( double secs ); void setTimeout( double secs );
#ifdef MONGO_SSL #ifdef MONGO_SSL
/** secures inline */ /** secures inline */
void secure( SSLManager * ssl ); void secure( SSLManager * ssl );
void secureAccepted( SSLManager * ssl ); void secureAccepted( SSLManager * ssl );
#endif #endif
/** /**
* call this after a fork for server sockets * This function calls SSL_accept() if SSL-encrypted sockets
* are desired. SSL_accept() waits until the remote host calls
* SSL_connect().
* This function may throw SocketException.
*/ */
void postFork(); void doSSLHandshake();
/** /**
* @return the time when the socket was opened. * @return the time when the socket was opened.
*/ */
uint64_t getSockCreationMicroSec() const { uint64_t getSockCreationMicroSec() const {
return _fdCreationMicroSec; return _fdCreationMicroSec;
} }
private: private:
void _init(); void _init();
/** raw send, same semantics as ::send */
public:
int _send( const char * data , int len );
private:
/** sends dumbly, just each buffer at a time */ /** sends dumbly, just each buffer at a time */
void _send( const vector< pair< char *, int > > &data, const char * context ); void _send( const vector< pair< char *, int > > &data, const char * context );
/** raw send, same semantics as ::send */
int _send( const char * data , int len );
/** raw recv, same semantics as ::recv */ /** raw recv, same semantics as ::recv */
int _recv( char * buf , int max ); int _recv( char * buf , int max );
void _handleRecvError(int ret, int len, int* retries);
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;
#ifdef MONGO_SSL #ifdef MONGO_SSL
SSL* _ssl; SSL* _ssl;
 End of changes. 8 change blocks. 
11 lines changed or deleted 16 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 forceCertificateValidation = false) :
pemfile(pemfile),
pempwd(pempwd),
cafile(cafile),
crlfile(crlfile),
forceCertificateValidation(forceCertificateValidation) {};
std::string pemfile;
std::string pempwd;
std::string cafile;
std::string crlfile;
bool forceCertificateValidation;
};
class SSLManager { class SSLManager {
MONGO_DISALLOW_COPYING(SSLManager); MONGO_DISALLOW_COPYING(SSLManager);
public: public:
SSLManager( bool client ); explicit SSLManager(const SSLParams& params);
/** @return true if was successful, otherwise false */ /**
bool setupPEM( const std::string& keyFile , const std::string& pass * Initiates a TLS connection.
word ); * Throws SocketException on failure.
void setupPubPriv( const std::string& privateKeyFile , const std::s * @return a pointer to an SSL context; caller must SSL_free it.
tring& publicKeyFile ); */
SSL* connect(int fd);
/** /**
* creates an SSL context to be used for this file descriptor * Waits for the other side to initiate a TLS connection.
* caller should delete * Throws SocketException on failure.
* @return a pointer to an SSL context; caller must SSL_free it.
*/ */
SSL * secure( int fd ); SSL* accept(int fd);
/**
* Fetches a peer certificate and validates it if it exists
* Throws SocketException on failure
*/
void validatePeerCertificate(const SSL* ssl);
/**
* Callbacks for SSL functions
*/
static int password_cb( char *buf,int num, int rwflag,void *userdat a ); static int password_cb( char *buf,int num, int rwflag,void *userdat a );
static int verify_cb(int ok, X509_STORE_CTX *ctx);
private: private:
bool _client;
SSL_CTX* _context; SSL_CTX* _context;
std::string _password; std::string _password;
bool _validateCertificates;
bool _forceValidation;
/**
* creates an SSL context to be used for this file descriptor.
* caller must SSL_free it.
*/
SSL* _secure(int fd);
/**
* Fetches the error text for an error code, in a thread-safe manne
r.
*/
std::string _getSSLErrorMessage(int code);
/**
* 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 */
bool _setupPEM( const std::string& keyFile , const std::string& pas
sword );
/*
* Set up SSL for certificate validation by loading a CA
*/
bool _setupCA(const std::string& caFile);
/*
* Import a certificate revocation list into our SSL context
* for use with validating certificates
*/
bool _setupCRL(const std::string& crlFile);
}; };
} }
#endif #endif
 End of changes. 9 change blocks. 
10 lines changed or deleted 75 lines changed or added


 stacktrace.h   stacktrace.h 
skipping to change at line 21 skipping to change at line 21
#include "mongo/platform/basic.h" #include "mongo/platform/basic.h"
namespace mongo { namespace mongo {
// Print stack trace information to "os", default to std::cout. // Print stack trace information to "os", default to std::cout.
void printStackTrace(std::ostream &os=std::cout); void printStackTrace(std::ostream &os=std::cout);
#if defined(_WIN32) #if defined(_WIN32)
// Print stack trace (using a specified stack context) to "os", default to std::cout. // Print stack trace (using a specified stack context) to "os", default to std::cout.
void printWindowsStackTrace(CONTEXT &context, std::ostream &os=std::cou t); void printWindowsStackTrace(CONTEXT &context, std::ostream &os=std::cou t);
// Print error message from C runtime followed by stack trace
int crtDebugCallback(int, char* originalMessage, int*);
#endif #endif
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
0 lines changed or deleted 3 lines changed or added


 status.h   status.h 
skipping to change at line 91 skipping to change at line 91
// //
// accessors // accessors
// //
bool isOK() const { return code() == ErrorCodes::OK; } bool isOK() const { return code() == ErrorCodes::OK; }
ErrorCodes::Error code() const { return _error->code; } ErrorCodes::Error code() const { return _error->code; }
const char* codeString() const { return ErrorCodes::errorString(_er ror->code); } const char* codeString() const { return ErrorCodes::errorString(_er ror->code); }
const std::string& reason() const { return _error->reason; } const std::string& reason() const { return _error->reason; }
int location() const { return _error->location; } int location() const { return _error->location; }
std::string toString() const;
// //
// Below interface used for testing code only. // Below interface used for testing code only.
// //
int refCount() const { return _error->refs.load(); } int refCount() const { return _error->refs.load(); }
private: private:
struct ErrorInfo { struct ErrorInfo {
AtomicUInt32 refs; // reference counter AtomicUInt32 refs; // reference counter
ErrorCodes::Error code; // error code ErrorCodes::Error code; // error code
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 strategy.h   strategy.h 
skipping to change at line 51 skipping to change at line 51
// TODO: Refactor all this. // TODO: Refactor all this.
verify( false ); verify( false );
} }
// These interfaces will merge soon, so make it easy to share logic // These interfaces will merge soon, so make it easy to share logic
friend class ShardStrategy; friend class ShardStrategy;
friend class SingleStrategy; friend class SingleStrategy;
protected: protected:
void doWrite( int op , Request& r , const Shard& shard , bool check Version = true ); void doWrite( int op , Request& r , const Shard& shard , bool check Version = true );
void doQuery( Request& r , const Shard& shard ); void doIndexQuery( Request& r , const Shard& shard );
void broadcastWrite(int op, Request& r); // Sends to all shards in cluster. DOESN'T CHECK VERSION void broadcastWrite(int op, Request& r); // Sends to all shards in cluster. DOESN'T CHECK VERSION
void insert( const Shard& shard , const char * ns , const vector<BS ONObj>& v , int flags=0 , bool safe=false ); void insert( const Shard& shard , const char * ns , const vector<BS ONObj>& v , int flags=0 , bool safe=false );
void update( const Shard& shard , const char * ns , const BSONObj& query , const BSONObj& toupdate , int flags=0, bool safe=false ); void update( const Shard& shard , const char * ns , const BSONObj& query , const BSONObj& toupdate , int flags=0, bool safe=false );
}; };
extern Strategy * SINGLE; extern Strategy * SINGLE;
extern Strategy * SHARDED; extern Strategy * SHARDED;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 string_data.h   string_data.h 
// string_data.h
/* Copyright 2010 10gen Inc. /* Copyright 2010 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 <algorithm> // for min #include <algorithm> // for min
#include <cstring> #include <cstring>
#include <iosfwd>
#include <limits>
#include <string> #include <string>
namespace mongo { namespace mongo {
using std::string; using std::string;
/** /**
* A StringData object wraps a 'const string&' or a 'const char*' witho ut copying its * A StringData object wraps a 'const string&' or a 'const char*' witho ut copying its
* contents. The most common usage is as a function argument that takes any of the two * contents. The most common usage is as a function argument that takes any of the two
* forms of strings above. Fundamentally, this class tries go around th e fact that string * forms of strings above. Fundamentally, this class tries go around th e fact that string
* literals in C++ are char[N]'s. * literals in C++ are char[N]'s.
* *
* Notes: * Notes:
* *
* + The object StringData wraps around must be alive while the String Data is. * + The object StringData wraps around must be alive while the String Data is.
* *
* + Because strings accept null characters, we allow them in StringDa * + Because string data can be used to pass a substring around, one s
ta. But this use is hould never assume a
* *strongly* discouraged. One problem this case may encounter is wh * rawData() terminates with a null.
en asking for data()
* out of a StringData that was feed with, say "a\0b". If interprete
d as a c-string,
* the null character would cut the original string short.
*/ */
class StringData { class StringData {
public: public:
/** Constructs an empty string data */
StringData()
: _data(NULL), _size(0) {}
/** /**
* Constructs a StringData, for the case where the length of string is not known. 'c' * Constructs a StringData, for the case where the length of string is not known. 'c'
* must be a pointer to a null-terminated string. * must be a pointer to a null-terminated string.
*/ */
StringData( const char* c ) StringData( const char* c )
: _data(c), _size(string::npos){} : _data(c), _size((c == NULL) ? 0 : string::npos) {}
/** /**
* Constructs a StringData explicitly, for the case where the lengt h of the string is * Constructs a StringData explicitly, for the case where the lengt h of the string is
* already known. 'c' must be a pointer to a null-terminated string , and strlenOfc must * already known. 'c' must be a pointer to a null-terminated string , and strlenOfc must
* be the length that strlen(c) would return, a.k.a the index of th e terminator in c. * be the length that strlen(c) would return, a.k.a the index of th e terminator in c.
*/ */
StringData( const char* c, size_t len ) StringData( const char* c, size_t len )
: _data(c), _size(len) {} : _data(c), _size(len) {}
/** Constructs a StringData, for the case of a string. */ /** Constructs a StringData, for the case of a string. */
skipping to change at line 76 skipping to change at line 82
*/ */
struct LiteralTag {}; struct LiteralTag {};
template<size_t N> template<size_t N>
StringData( const char (&val)[N], LiteralTag ) StringData( const char (&val)[N], LiteralTag )
: _data(&val[0]), _size(N-1) {} : _data(&val[0]), _size(N-1) {}
/** /**
* Returns -1, 0, or 1 if 'this' is less, equal, or greater than 'o ther' in * Returns -1, 0, or 1 if 'this' is less, equal, or greater than 'o ther' in
* lexicographical order. * lexicographical order.
*/ */
int compare(const StringData& other) const { int compare(const StringData& other) const;
// Sizes might not have been computed yet.
size(); /**
other.size(); * note: this uses tolower, and therefore does not handle
* come languages correctly.
int res = memcmp(_data, other._data, std::min(_size, other._siz * should be use sparingly
e)); */
if (res != 0) { bool equalCaseInsensitive( const StringData& other ) const;
return res > 0 ? 1 : -1;
} void copyTo( char* dest, bool includeEndingNull ) const;
else if (_size == other._size) {
return 0; StringData substr( size_t pos, size_t n = std::numeric_limits<size_
} t>::max() ) const;
else {
return _size > other._size ? 1 : -1; //
} // finders
} //
size_t find( char c ) const;
size_t find( const StringData& needle ) const;
/**
* Returns true if 'prefix' is a substring of this instance, anchor
ed at position 0.
*/
bool startsWith( const StringData& prefix ) const;
/**
* Returns true if 'suffix' is a substring of this instance, anchor
ed at the end.
*/
bool endsWith( const StringData& suffix ) const;
// //
// accessors // accessors
// //
const char* data() const { return _data; } /**
* this is not guaranteed to be null-terminated,
* if you use this without all using size(), you are likely doing s
omething wrong
*/
const char* rawData() const { return _data; }
size_t size() const { fillSize(); return _size; } size_t size() const { fillSize(); return _size; }
bool empty() const { return size() == 0; } bool empty() const { return size() == 0; }
string toString() const { return string(data(), size()); } string toString() const { return string(_data, size()); }
char operator[] ( unsigned pos ) const { return _data[pos]; }
private: private:
const char* const _data; // is always null terminated, but see "no tes" above const char* _data; // is not guaranted to be null terminated (see "notes" above)
mutable size_t _size; // 'size' does not include the null termi nator mutable size_t _size; // 'size' does not include the null termi nator
void fillSize() const { void fillSize() const {
if (_size == string::npos) { if (_size == string::npos) {
_size = strlen(_data); _size = strlen(_data);
} }
} }
}; };
inline bool operator==(const StringData& lhs, const StringData& rhs) { inline bool operator==(const StringData& lhs, const StringData& rhs) {
skipping to change at line 137 skipping to change at line 162
} }
inline bool operator>(const StringData& lhs, const StringData& rhs) { inline bool operator>(const StringData& lhs, const StringData& rhs) {
return lhs.compare(rhs) > 0; return lhs.compare(rhs) > 0;
} }
inline bool operator>=(const StringData& lhs, const StringData& rhs) { inline bool operator>=(const StringData& lhs, const StringData& rhs) {
return lhs.compare(rhs) >= 0; return lhs.compare(rhs) >= 0;
} }
std::ostream& operator<<(std::ostream& stream, const StringData& value)
;
} // namespace mongo } // namespace mongo
#include "string_data-inl.h"
 End of changes. 11 change blocks. 
28 lines changed or deleted 57 lines changed or added


 string_map.h   string_map.h 
skipping to change at line 20 skipping to change at line 20
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <string> #include "mongo/base/string_data.h"
#include "mongo/util/unordered_fast_key_table.h" #include "mongo/util/unordered_fast_key_table.h"
namespace mongo { namespace mongo {
struct StringMapDefaultHash { struct StringMapDefaultHash {
size_t operator()( const char* k ) const; size_t operator()( const StringData& k ) const;
}; };
struct StringMapDefaultEqual { struct StringMapDefaultEqual {
bool operator()( const char* a, const char* b ) const { bool operator()( const StringData& a, const StringData& b ) const {
return strcmp( a,b ) == 0; return a == b;
} }
}; };
struct StringMapDefaultConvertor { struct StringMapDefaultConvertor {
const char* operator()( const std::string& s ) const { StringData operator()( const std::string& s ) const {
return s.c_str(); return StringData( s );
}
};
struct StringMapDefaultConvertorOther {
string operator()( const StringData& s ) const {
return s.toString();
} }
}; };
template< typename V > template< typename V >
class StringMap : public UnorderedFastKeyTable< const char*, // K_L class StringMap : public UnorderedFastKeyTable< StringData, // K_L
std::string, // K_S std::string, // K_S
V, // V V, // V
StringMapDefaultHash, StringMapDefaultHash,
StringMapDefaultEqual, StringMapDefaultEqual,
StringMapDefaultConvertor > { StringMapDefaultConvert
or,
StringMapDefaultConvert
orOther > {
}; };
} }
#include "mongo/util/string_map_internal.h" #include "mongo/util/string_map_internal.h"
 End of changes. 5 change blocks. 
12 lines changed or deleted 21 lines changed or added


 string_map_internal.h   string_map_internal.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.
*/ */
namespace mongo { namespace mongo {
inline size_t StringMapDefaultHash::operator()( const char* origKey ) c inline size_t StringMapDefaultHash::operator()( const StringData& key )
onst { const {
const char* key = origKey; size_t mx = key.size();
size_t hash = 7; size_t hash = 7;
while ( *key ) { for ( size_t i = 0; i < mx; i++ ) {
hash += ( 517 * static_cast<int>(*key) ); hash += ( 517 * static_cast<int>(key[i]) );
hash *= 13; hash *= 13;
key++;
} }
if ( hash == 0 ) if ( hash == 0 )
hash = -1; hash = -1;
return hash; return hash;
} }
template< typename K_L, typename K_S, typename V, typename H, typename
E, typename C >
inline typename UnorderedFastKeyTable<K_L, K_S, V, H, E, C>::const_iter
ator
UnorderedFastKeyTable<K_L, K_S, V, H, E, C>::find( const K_L& key ) con
st {
if ( _size == 0 )
return const_iterator();
int pos = _area.find( key, _hash(key), 0, *this );
if ( pos < 0 )
return const_iterator();
return const_iterator( &_area._entries[pos] );
}
template< typename K_L, typename K_S, typename V, typename H, typename
E, typename C >
inline typename UnorderedFastKeyTable<K_L, K_S, V, H, E, C>::const_iter
ator
UnorderedFastKeyTable<K_L, K_S, V, H, E, C>::end() const {
return const_iterator();
}
} }
 End of changes. 4 change blocks. 
28 lines changed or deleted 5 lines changed or added


 stringutils.h   stringutils.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 <ctype.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include <boost/scoped_array.hpp> #include <boost/scoped_array.hpp>
namespace mongo { namespace mongo {
// see also mongoutils/str.h - perhaps move these there? // see also mongoutils/str.h - perhaps move these there?
// see also text.h // see also text.h
skipping to change at line 59 skipping to change at line 61
class LexNumCmp { class LexNumCmp {
public: public:
/** @param lexOnly - compare all characters lexically, including di gits. */ /** @param lexOnly - compare all characters lexically, including di gits. */
LexNumCmp( bool lexOnly ); LexNumCmp( bool lexOnly );
/** /**
* Non numeric characters are compared lexicographically; numeric s ubstrings * Non numeric characters are compared lexicographically; numeric s ubstrings
* are compared numerically; dots separate ordered comparable subun its. * are compared numerically; dots separate ordered comparable subun its.
* For convenience, character 255 is greater than anything else. * For convenience, character 255 is greater than anything else.
* @param lexOnly - compare all characters lexically, including dig its. * @param lexOnly - compare all characters lexically, including dig its.
*/ */
static int cmp( const char *s1, const char *s2, bool lexOnly ); static int cmp( const StringData& s1, const StringData& s2, bool le
int cmp( const char *s1, const char *s2 ) const; xOnly );
bool operator()( const char *s1, const char *s2 ) const; int cmp( const StringData& s1, const StringData& s2 ) const;
bool operator()( const std::string &s1, const std::string &s2 ) con bool operator()( const StringData& s1, const StringData& s2 ) const
st; ;
private: private:
bool _lexOnly; bool _lexOnly;
}; };
// TODO: Sane-ify core string functionality
// For now, this needs to be near the LexNumCmp or else
int versionCmp(const StringData rhs, const StringData lhs);
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
5 lines changed or deleted 11 lines changed or added


 syncclusterconnection.h   syncclusterconnection.h 
skipping to change at line 112 skipping to change at line 112
virtual bool callRead( Message& toSend , Message& response ); virtual bool callRead( Message& toSend , Message& response );
virtual ConnectionString::ConnectionType type() const { return Conn ectionString::SYNC; } virtual ConnectionString::ConnectionType type() const { return Conn ectionString::SYNC; }
void setAllSoTimeouts( double socketTimeout ); void setAllSoTimeouts( double socketTimeout );
double getSoTimeout() const { return _socketTimeout; } double getSoTimeout() const { return _socketTimeout; }
virtual bool auth(const string &dbname, const string &username, con st string &password_text, string& errmsg, bool digestPassword, Auth::Level* level=NULL); virtual bool auth(const string &dbname, const string &username, con st string &password_text, string& errmsg, bool digestPassword, Auth::Level* level=NULL);
virtual void setAuthenticationTable( const AuthenticationTable& aut
h );
virtual void clearAuthenticationTable();
virtual bool lazySupported() const { return false; } virtual bool lazySupported() const { return false; }
private: private:
SyncClusterConnection( SyncClusterConnection& prev, double socketTi meout = 0 ); SyncClusterConnection( SyncClusterConnection& prev, double socketTi meout = 0 );
string _toString() const; string _toString() const;
bool _commandOnActive(const string &dbname, const BSONObj& cmd, BSO NObj &info, int options=0); bool _commandOnActive(const string &dbname, const BSONObj& cmd, BSO NObj &info, int options=0);
auto_ptr<DBClientCursor> _queryOnActive(const string &ns, Query que ry, int nToReturn, int nToSkip, auto_ptr<DBClientCursor> _queryOnActive(const string &ns, Query que ry, int nToReturn, int nToSkip,
const BSONObj *fieldsToRetu rn, int queryOptions, int batchSize ); const BSONObj *fieldsToRetu rn, int queryOptions, int batchSize );
int _lockType( const string& name ); int _lockType( const string& name );
void _checkLast(); void _checkLast();
void _connect( const std::string& host ); void _connect( const std::string& host );
 End of changes. 1 change blocks. 
4 lines changed or deleted 0 lines changed or added


 systeminfo.h   systeminfo.h 
skipping to change at line 25 skipping to change at line 25
*/ */
#pragma once #pragma once
#include <cstddef> #include <cstddef>
namespace mongo { namespace mongo {
class SystemInfo { class SystemInfo {
public: public:
/* /*
Get the amount of physical memory available on the host. Get the amount of physical memory available on the host.
This should only be used for "advisory" purposes, and not as a har This should only be used for "advisory" purposes, and not as a ha
d rd
value, because this could be deceptive on virtual hosts, and becau value, because this could be deceptive on virtual hosts, and beca
se use
this will return zero on platforms that do not support it. this will return zero on platforms that do not support it.
@returns amount of physical memory, or zero @returns amount of physical memory, or zero
*/ */
static size_t getPhysicalRam(); static size_t getPhysicalRam();
private: private:
// don't instantiate this class // don't instantiate this class
SystemInfo(); // no implementation SystemInfo(); // no implementation
}; };
} }
 End of changes. 3 change blocks. 
13 lines changed or deleted 13 lines changed or added


 text.h   text.h 
skipping to change at line 92 skipping to change at line 92
char** _argv; char** _argv;
public: public:
WindowsCommandLine( int argc, wchar_t* argvW[] ); WindowsCommandLine( int argc, wchar_t* argvW[] );
~WindowsCommandLine(); ~WindowsCommandLine();
char** argv( void ) const { return _argv; }; char** argv( void ) const { return _argv; };
}; };
#endif // #if defined(_WIN32) #endif // #if defined(_WIN32)
/**
* Construct a Windows command line string, UTF-8 encoded, from a vecto
r of
* UTF-8 arguments, "argv".
*
* See "Parsing C++ Command-Line Arguments (C++)"
* http://msdn.microsoft.com/en-us/library/windows/desktop/17w5ykft(v=v
s.85).aspx
*/
std::string constructUtf8WindowsCommandLine(const std::vector<std::stri
ng>& argv);
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
0 lines changed or deleted 12 lines changed or added


 ticketholder.h   ticketholder.h 
skipping to change at line 98 skipping to change at line 98
_num--; _num--;
return true; return true;
} }
int _outof; int _outof;
int _num; int _num;
mongo::mutex _mutex; mongo::mutex _mutex;
boost::condition_variable_any _newTicket; boost::condition_variable_any _newTicket;
}; };
class ScopedTicket {
public:
ScopedTicket(TicketHolder* holder) : _holder(holder) {
_holder->waitForTicket();
}
~ScopedTicket() {
_holder->release();
}
private:
TicketHolder* _holder;
};
class TicketHolderReleaser { class TicketHolderReleaser {
public: public:
TicketHolderReleaser( TicketHolder * holder ) { TicketHolderReleaser( TicketHolder * holder ) {
_holder = holder; _holder = holder;
} }
~TicketHolderReleaser() { ~TicketHolderReleaser() {
_holder->release(); _holder->release();
} }
private: private:
 End of changes. 1 change blocks. 
0 lines changed or deleted 15 lines changed or added


 tool.h   tool.h 
skipping to change at line 31 skipping to change at line 31
#include <string> #include <string>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#if defined(_WIN32) #if defined(_WIN32)
#include <io.h> #include <io.h>
#endif #endif
#include "db/instance.h" #include "db/instance.h"
#include "db/matcher.h" #include "db/matcher.h"
#include "db/security.h"
using std::string; using std::string;
namespace mongo { namespace mongo {
class Tool { class Tool {
public: public:
enum DBAccess { enum DBAccess {
NONE = 0 , NONE = 0 ,
REMOTE_SERVER = 1 << 1 , REMOTE_SERVER = 1 << 1 ,
skipping to change at line 148 skipping to change at line 147
boost::program_options::variables_map _params; boost::program_options::variables_map _params;
}; };
class BSONTool : public Tool { class BSONTool : public Tool {
bool _objcheck; bool _objcheck;
auto_ptr<Matcher> _matcher; auto_ptr<Matcher> _matcher;
public: public:
BSONTool( const char * name , DBAccess access=ALL, bool objcheck = false ); BSONTool( const char * name , DBAccess access=ALL, bool objcheck = true );
virtual int doRun() = 0; virtual int doRun() = 0;
virtual void gotObject( const BSONObj& obj ) = 0; virtual void gotObject( const BSONObj& obj ) = 0;
virtual int run(); virtual int run();
long long processFile( const boost::filesystem::path& file ); long long processFile( const boost::filesystem::path& file );
}; };
 End of changes. 2 change blocks. 
2 lines changed or deleted 1 lines changed or added


 top.h   top.h 
skipping to change at line 22 skipping to change at line 22
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>
#include "mongo/platform/unordered_map.h" #include "mongo/util/string_map.h"
namespace mongo { namespace mongo {
/** /**
* tracks usage by collection * tracks usage by collection
*/ */
class Top { class Top {
public: public:
Top() : _lock("Top") { } Top() : _lock("Top") { }
skipping to change at line 66 skipping to change at line 66
UsageData writeLock; UsageData writeLock;
UsageData queries; UsageData queries;
UsageData getmore; UsageData getmore;
UsageData insert; UsageData insert;
UsageData update; UsageData update;
UsageData remove; UsageData remove;
UsageData commands; UsageData commands;
}; };
typedef unordered_map<string,CollectionData> UsageMap; typedef StringMap<CollectionData> UsageMap;
public: public:
void record( const StringData& ns , int op , int lockType , long lo ng micros , bool command ); void record( const StringData& ns , int op , int lockType , long lo ng micros , bool command );
void append( BSONObjBuilder& b ); void append( BSONObjBuilder& b );
void cloneMap(UsageMap& out) const; void cloneMap(UsageMap& out) const;
CollectionData getGlobalData() const { return _global; } CollectionData getGlobalData() const { return _global; }
void collectionDropped( const string& ns ); void collectionDropped( const string& ns );
public: // static stuff public: // static stuff
static Top global; static Top global;
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 type_chunk.h   type_chunk.h 
skipping to change at line 24 skipping to change at line 24
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <string> #include <string>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
#include "mongo/base/string_data.h" #include "mongo/base/string_data.h"
#include "mongo/db/jsobj.h" #include "mongo/db/jsobj.h"
#include "mongo/s/util.h" // for ShardChunkVersion #include "mongo/s/chunk_version.h"
namespace mongo { namespace mongo {
/** /**
* This class represents the layout and contents of documents contained in the * This class represents the layout and contents of documents contained in the
* config.chunks collection. All manipulation of documents coming from that * config.chunks collection. All manipulation of documents coming from that
* collection should be done with this class. * collection should be done with this class.
* *
* Usage Example: * Usage Example:
* *
skipping to change at line 64 skipping to change at line 64
public: public:
// //
// schema declarations // schema declarations
// //
// Name of the chunk collection in the config server. // Name of the chunk collection in the config server.
static const std::string ConfigNS; static const std::string ConfigNS;
// Field names and types in the chunk collection type. // Field names and types in the chunk collection type.
static BSONField<std::string> name; static BSONField<std::string> name; // chunk's id
static BSONField<std::string> ns; static BSONField<std::string> ns; // namespace this chunk is
static BSONField<BSONObj> min; in
static BSONField<BSONObj> max; static BSONField<BSONObj> min; // first key of the chunk,
static BSONField<BSONArray> version; including
static BSONField<std::string> shard; static BSONField<BSONObj> max; // last key of the chunk, n
static BSONField<bool> jumbo; on-including
static BSONField<BSONArray> version; // [Date_t, OID]
static BSONField<std::string> shard; // home of this chunk
static BSONField<bool> jumbo; // too big to move?
// Transition to new format, 2.2 -> 2.4 // Transition to new format, 2.2 -> 2.4
// 2.2 can read both lastmod + lastmodEpoch format and 2.4 [ lastmo d, OID ] formats. // 2.2 can read both lastmod + lastmodEpoch format and 2.4 [ lastmo d, OID ] formats.
static BSONField<Date_t> DEPRECATED_lastmod; // major | minor vers ions static BSONField<Date_t> DEPRECATED_lastmod; // major | minor vers ions
static BSONField<OID> DEPRECATED_epoch; // disambiguates coll ection incarnations static BSONField<OID> DEPRECATED_epoch; // OID, to disambigua te collection incarnations
// //
// chunk type methods // chunk type methods
// //
ChunkType(); ChunkType();
~ChunkType(); ~ChunkType();
/** /**
* Returns true if all the mandatory fields are present and have va lid * Returns true if all the mandatory fields are present and have va lid
skipping to change at line 97 skipping to change at line 97
*/ */
bool isValid(std::string* errMsg) const; bool isValid(std::string* errMsg) const;
/** /**
* Returns the BSON representation of the entry. * Returns the BSON representation of the entry.
*/ */
BSONObj toBSON() const; BSONObj toBSON() const;
/** /**
* Clears and populates the internal state using the 'source' BSON object if the * Clears and populates the internal state using the 'source' BSON object if the
* latter contains valid values. Otherwise clear the internal state . * latter contains valid values. Otherwise sets errMsg and returns false.
*/ */
void parseBSON(BSONObj source); bool parseBSON(BSONObj source, std::string* errMsg);
/** /**
* Clears the internal state. * Clears the internal state.
*/ */
void clear(); void clear();
/** /**
* Copies all the fields present in 'this' to 'other'. * Copies all the fields present in 'this' to 'other'.
*/ */
void cloneTo(ChunkType* other); void cloneTo(ChunkType* other) const;
/** /**
* Returns a string representation of the current internal state. * Returns a string representation of the current internal state.
*/ */
std::string toString() const; std::string toString() const;
// //
// individual field accessors // individual field accessors
// //
void setName(const StringData& name) { _name = std::string(name.dat void setName(const StringData& name) {
a(), name.size()); } _name = name.toString();
const std::string& getName() const { return _name; } }
void setNS(const StringData& ns) { _ns = std::string(ns.data(), ns. const std::string& getName() const {
size()); } return _name;
const std::string& getNS() const { return _ns; } }
void setMin(const BSONObj& min) { _min = min.getOwned(); } void setNS(const StringData& ns) {
BSONObj getMin() const { return _min; } _ns = ns.toString();
}
void setMax(const BSONObj& max) { _max = max.getOwned(); }
BSONObj getMax() const { return _max; } const std::string& getNS() const {
return _ns;
void setVersion(const ShardChunkVersion& version) { _version = vers }
ion; }
const ShardChunkVersion& getVersion() const { return _version; } void setMin(const BSONObj& min) {
_min = min.getOwned();
void setShard(const StringData& shard) { _shard=std::string(shard. }
data(), shard.size()); }
const std::string& getShard() const { return _shard; } BSONObj getMin() const {
return _min;
void setJumbo(bool jumbo) { _jumbo = jumbo; } }
bool getJumbo() const { return _jumbo; }
void setMax(const BSONObj& max) {
_max = max.getOwned();
}
BSONObj getMax() const {
return _max;
}
void setVersion(const ChunkVersion& version) {
_version = version;
}
const ChunkVersion& getVersion() const {
return _version;
}
void setShard(const StringData& shard) {
_shard = shard.toString();
}
const std::string& getShard() const {
return _shard;
}
void setJumbo(bool jumbo) {
_jumbo = jumbo;
}
bool getJumbo() const {
return _jumbo;
}
private: private:
// Convention: (M)andatory, (O)ptional, (S)pecial rule. // Convention: (M)andatory, (O)ptional, (S)pecial rule.
string _name; // (M) chunk's id string _name; // (M) chunk's id
string _ns; // (M) collection this chunk is in string _ns; // (M) collection this chunk is in
BSONObj _min; // (M) first key of the range, inclusi BSONObj _min; // (M) first key of the range, inclusive
ve BSONObj _max; // (M) last key of the range, non-inclusive
BSONObj _max; // (M) last key of the range, non-incl ChunkVersion _version; // (M) version of this chunk
usive string _shard; // (M) shard this chunk lives in
ShardChunkVersion _version; // (M) version of this chunk bool _jumbo; // (O) too big to move?
string _shard; // (M) shard this chunk lives in
bool _jumbo; // (O) too big to move?
}; };
} // namespace mongo } // namespace mongo
 End of changes. 9 change blocks. 
45 lines changed or deleted 77 lines changed or added


 type_collection.h   type_collection.h 
skipping to change at line 46 skipping to change at line 46
* BSONObj query = QUERY(CollectionType::ns("db.coll") << * BSONObj query = QUERY(CollectionType::ns("db.coll") <<
* CollectionType::unique(true)); * CollectionType::unique(true));
* collDoc = conn->findOne(CollectionType::ConfigNS, query); * collDoc = conn->findOne(CollectionType::ConfigNS, query);
* *
* // Process the response. * // Process the response.
* CollectionType coll; * CollectionType coll;
* coll.fromBSON(collDoc); * coll.fromBSON(collDoc);
* if (! coll.isValid()) { * if (! coll.isValid()) {
* // Can't use 'coll'. Take action. * // Can't use 'coll'. Take action.
* } * }
* if (coll.isDropped()) {
* // Coll doesn't exist, Take action.
* }
*
* // use 'coll' * // use 'coll'
* *
*/ */
class CollectionType { class CollectionType {
MONGO_DISALLOW_COPYING(CollectionType); MONGO_DISALLOW_COPYING(CollectionType);
public: public:
// //
// schema declarations // schema declarations
// //
// Name of the collection in the config server. // Name of the collection in the config server.
static const std::string ConfigNS; static const std::string ConfigNS;
// Field names and types in the collection type. // Field names and types in the collection type.
static BSONField<std::string> ns; // collection's namespace static BSONField<std::string> ns; // collection's namespace
static BSONField<std::string> primary; // primary db when not shard ed static BSONField<std::string> primary; // primary db when not shard ed
static BSONField<BSONObj> keyPattern; // sharding key, if sharded static BSONField<BSONObj> keyPattern; // sharding key, if sharded
static BSONField<bool> unique; // sharding key unique? static BSONField<bool> unique; // sharding key unique?
static BSONField<Date_t> createdAt; // when collection was creat ed static BSONField<Date_t> updatedAt; // when collection was creat ed
static BSONField<bool> noBalance; // true if balancing is disa bled static BSONField<bool> noBalance; // true if balancing is disa bled
static BSONField<OID> epoch; // disambiguate ns (drop/rec reate) static BSONField<OID> epoch; // disambiguate ns (drop/rec reate)
// To-be-deprecated, not yet
static BSONField<bool> dropped; // true if we should ignore
this collection entry
// Deprecated fields should only be used in parseBSON calls. Expose d here for testing only. // Deprecated fields should only be used in parseBSON calls. Expose d here for testing only.
static BSONField<OID> DEPRECATED_lastmodEpoch; static BSONField<OID> DEPRECATED_lastmodEpoch;
static BSONField<Date_t> DEPRECATED_lastmod; static BSONField<Date_t> DEPRECATED_lastmod;
static BSONField<bool> DEPRECATED_dropped;
// //
// collection type methods // collection type methods
// //
CollectionType(); CollectionType();
~CollectionType(); ~CollectionType();
/** /**
* Returns true if all the mandatory fields are present and have va lid * Returns true if all the mandatory fields are present and have va lid
skipping to change at line 94 skipping to change at line 99
*/ */
bool isValid(std::string* errMsg) const; bool isValid(std::string* errMsg) const;
/** /**
* Returns the BSON representation of the entry. * Returns the BSON representation of the entry.
*/ */
BSONObj toBSON() const; BSONObj toBSON() const;
/** /**
* Clears and populates the internal state using the 'source' BSON object if the * Clears and populates the internal state using the 'source' BSON object if the
* latter contains valid values. Otherwise clear the internal state . * latter contains valid values. Otherwise sets errMsg and returns false.
*/ */
void parseBSON(BSONObj source); bool parseBSON(BSONObj source, std::string* errMsg);
/** /**
* Clears the internal state. * Clears the internal state.
*/ */
void clear(); void clear();
/** /**
* Copies all the fields present in 'this' to 'other'. * Copies all the fields present in 'this' to 'other'.
*/ */
void cloneTo(CollectionType* other); void cloneTo(CollectionType* other) const;
/** /**
* Returns a string representation of the current internal state. * Returns a string representation of the current internal state.
*/ */
std::string toString() const; std::string toString() const;
// //
// individual field accessors // individual field accessors
// //
void setNS(const StringData& ns) { _ns = std::string(ns.data(), ns. size()); } void setNS(const StringData& ns) { _ns = ns.toString(); }
const std::string& getNS() const { return _ns; } const std::string& getNS() const { return _ns; }
void setPrimary(const StringData& name) { _primary=std::string(name .data(), name.size()); } void setPrimary(const StringData& name) { _primary = name.toString( ); }
const std::string& getPrimary() const { return _primary; } const std::string& getPrimary() const { return _primary; }
void setKeyPattern(const BSONObj keyPattern) { _keyPattern = keyPat tern.getOwned(); } void setKeyPattern(const BSONObj keyPattern) { _keyPattern = keyPat tern.getOwned(); }
BSONObj getKeyPattern() const { return _keyPattern; } BSONObj getKeyPattern() const { return _keyPattern; }
void setUnique(bool unique) { _unique = unique; } void setUnique(bool unique) { _unique = unique; }
bool getUnique() const { return _unique; } bool isUnique() const { return _unique; }
void setCreatedAt(const Date_t& time) { _createdAt = time; } void setUpdatedAt(const Date_t& time) { _updatedAt = time; }
Date_t getCreatedAt() const { return _createdAt; } Date_t getUpdatedAt() const { return _updatedAt; }
void setNoBalance(bool noBalance) { _noBalance = noBalance; } void setNoBalance(bool noBalance) { _noBalance = noBalance; }
bool getNoBalance() const { return _noBalance; } bool getNoBalance() const { return _noBalance; }
void setEpoch(OID oid) { _epoch = oid; } void setEpoch(OID oid) { _epoch = oid; }
OID getEpoch() const { return _epoch; } OID getEpoch() const { return _epoch; }
void setDropped(bool dropped) { _dropped = dropped; }
bool isDropped() const { return _dropped; }
private: private:
// Convention: (M)andatory, (O)ptional, (S)pecial rule. // Convention: (M)andatory, (O)ptional, (S)pecial rule.
std::string _ns; // (M) namespace std::string _ns; // (M) namespace
std::string _primary; // (S) either/or with _keyPattern std::string _primary; // (S) either/or with _keyPattern
BSONObj _keyPattern; // (S) sharding pattern if sharded BSONObj _keyPattern; // (S) sharding pattern if sharded
bool _unique; // (S) mandatory if sharded, index is unique bool _unique; // (S) mandatory if sharded, index is unique
Date_t _createdAt; // (M) creation time Date_t _updatedAt; // (M) last updated time
bool _noBalance; // (S) optional if sharded, disable balancin g bool _noBalance; // (S) optional if sharded, disable balancin g
OID _epoch; // (M) disambiguates collection incarnations OID _epoch; // (M) disambiguates collection incarnations
bool _dropped; // (O) if true, ignore this entry
}; };
} // namespace mongo } // namespace mongo
 End of changes. 14 change blocks. 
12 lines changed or deleted 21 lines changed or added


 type_database.h   type_database.h 
skipping to change at line 41 skipping to change at line 41
* *
* Usage Example: * Usage Example:
* *
* // Contact the config. 'conn' has been obtained before. * // Contact the config. 'conn' has been obtained before.
* DBClientBase* conn; * DBClientBase* conn;
* BSONObj query = QUERY(DatabaseType::name("mydb")); * BSONObj query = QUERY(DatabaseType::name("mydb"));
* dbDoc = conn->findOne(DatbaseType::ConfigNS, query); * dbDoc = conn->findOne(DatbaseType::ConfigNS, query);
* *
* // Process the response. * // Process the response.
* DatabaseType db; * DatabaseType db;
* db.fromBSON(dbDoc); * string errMsg;
* if (! db.isValid()) { * if (!db.parseBSON(dbDoc, &errMsg) || !db.isValid(&errMsg)) {
* // Can't use 'db'. Take action. * // Can't use 'db'. Take action.
* } * }
* // use 'db' * // use 'db'
* *
*/ */
class DatabaseType { class DatabaseType {
MONGO_DISALLOW_COPYING(DatabaseType); MONGO_DISALLOW_COPYING(DatabaseType);
public: public:
// //
// schema declarations // schema declarations
// //
// Name of the database collection in the config server. // Name of the database collection in the config server.
static const std::string ConfigNS; static const std::string ConfigNS;
// Field names and types in the database collection type. // Field names and types in the database collection type.
static BSONField<std::string> name; static BSONField<std::string> name; // database's name
static BSONField<std::string> primary; static BSONField<std::string> primary; // primary shard for the da
static BSONField<bool> scattered; tabase
static BSONField<bool> draining; static BSONField<bool> draining; // is the database being re
moved?
// This field was last used in 2.2 series (version 3). // This field was last used in 2.2 series (version 3).
static BSONField<bool> DEPRECATED_partitioned; static BSONField<bool> DEPRECATED_partitioned;
// These fields were last used in 1.4 series (version 2). // These fields were last used in 1.4 series (version 2).
static BSONField<std::string> DEPRECATED_name; static BSONField<std::string> DEPRECATED_name;
static BSONField<bool> DEPRECATED_sharded; static BSONField<bool> DEPRECATED_sharded;
// //
// database type methods // database type methods
skipping to change at line 92 skipping to change at line 91
*/ */
bool isValid(std::string* errMsg) const; bool isValid(std::string* errMsg) const;
/** /**
* Returns the BSON representation of the entry. * Returns the BSON representation of the entry.
*/ */
BSONObj toBSON() const; BSONObj toBSON() const;
/** /**
* Clears and populates the internal state using the 'source' BSON object if the * Clears and populates the internal state using the 'source' BSON object if the
* latter contains valid values. Otherwise clear the internal state . * latter contains valid values. Otherwise sets errMsg and returns false.
*/ */
void parseBSON(BSONObj source); bool parseBSON(BSONObj source, std::string* errMsg);
/** /**
* Clears the internal state. * Clears the internal state.
*/ */
void clear(); void clear();
/** /**
* Copies all the fields present in 'this' to 'other'. * Copies all the fields present in 'this' to 'other'.
*/ */
void cloneTo(DatabaseType* other); void cloneTo(DatabaseType* other) const;
/** /**
* Returns a string representation of the current internal state. * Returns a string representation of the current internal state.
*/ */
std::string toString() const; std::string toString() const;
// //
// individual field accessors // individual field accessors
// //
void setName(const StringData& name) { _name = std::string(name.dat a(), name.size()); } void setName(const StringData& name) { _name = name.toString(); }
const std::string& getName() const { return _name; } const std::string& getName() const { return _name; }
void setPrimary(const StringData& shard) {_primary=std::string(shar d.data(), shard.size());} void setPrimary(const StringData& shard) { _primary = shard.toStrin g(); }
const std::string& getPrimary() const { return _primary; } const std::string& getPrimary() const { return _primary; }
void setScattered(bool scattered) { _scattered = scattered; } void setDraining(bool draining) { _draining = draining; }
bool getScattered() { return _scattered; }
void setDrainig(bool draining) { _draining = draining; }
bool getDraining() const { return _draining; } bool getDraining() const { return _draining; }
private: private:
// Convention: (M)andatory, (O)ptional, (S)pecial rule. // Convention: (M)andatory, (O)ptional, (S)pecial rule.
string _name; // (M) database name string _name; // (M) database name
string _primary; // (M) primary shard for the database string _primary; // (M) primary shard for the database
bool _scattered; // (O) can db collections live outside the primar y?
bool _draining; // (O) is this database about to be deleted? bool _draining; // (O) is this database about to be deleted?
}; };
} // namespace mongo } // namespace mongo
 End of changes. 9 change blocks. 
16 lines changed or deleted 13 lines changed or added


 type_shard.h   type_shard.h 
skipping to change at line 59 skipping to change at line 59
public: public:
// //
// schema declarations // schema declarations
// //
// Name of the shard collection in the config server. // Name of the shard collection in the config server.
static const std::string ConfigNS; static const std::string ConfigNS;
// Field names and types in the shard collection type. // Field names and types in the shard collection type.
static BSONField<std::string> name; static BSONField<std::string> name; // shard's id
static BSONField<std::string> host; static BSONField<std::string> host; // connection string for th
static BSONField<bool> draining; e host(s)
static BSONField<long long> maxSize; static BSONField<bool> draining; // is it draining chunks?
static BSONField<long long> maxSize; // max allowed disk space u
sage
static BSONField<BSONArray> tags; // shard tags
// //
// shard type methods // shard type methods
// //
ShardType(); ShardType();
~ShardType(); ~ShardType();
/** /**
* Returns true if all the mandatory fields are present and have va lid * Returns true if all the mandatory fields are present and have va lid
skipping to change at line 84 skipping to change at line 85
*/ */
bool isValid(std::string* errMsg) const; bool isValid(std::string* errMsg) const;
/** /**
* Returns the BSON representation of the entry. * Returns the BSON representation of the entry.
*/ */
BSONObj toBSON() const; BSONObj toBSON() const;
/** /**
* Clears and populates the internal state using the 'source' BSON object if the * Clears and populates the internal state using the 'source' BSON object if the
* latter contains valid values. Otherwise clear the internal state . * latter contains valid values. Otherwise sets errMsg and returns false.
*/ */
void parseBSON(BSONObj source); bool parseBSON(BSONObj source, std::string* errMsg);
/** /**
* Clears the internal state. * Clears the internal state.
*/ */
void clear(); void clear();
/** /**
* Copies all the fields present in 'this' to 'other'. * Copies all the fields present in 'this' to 'other'.
*/ */
void cloneTo(ShardType* other); void cloneTo(ShardType* other) const;
/** /**
* Returns a string representation of the current internal state. * Returns a string representation of the current internal state.
*/ */
std::string toString() const; std::string toString() const;
// //
// individual field accessors // individual field accessors
// //
void setName(const StringData& name) { _name = std::string(name.dat a(), name.size()); } void setName(const StringData& name) { _name = name.toString(); }
const std::string& getName() const { return _name; } const std::string& getName() const { return _name; }
void setHost(const StringData& host) { _host = std::string(host.dat a(), host.size()); } void setHost(const StringData& host) { _host = host.toString(); }
const std::string& getHost() const { return _host; } const std::string& getHost() const { return _host; }
void setDraining(bool draining) { _draining = draining; } void setDraining(bool draining) { _draining = draining; }
bool getDraining() const { return _draining; } bool getDraining() const { return _draining; }
void setMaxSize(uint64_t maxSize) { _maxSize = maxSize; } void setMaxSize(uint64_t maxSize) { _maxSize = maxSize; }
uint64_t getMaxSize() const { return _maxSize; } uint64_t getMaxSize() const { return _maxSize; }
void setTags(const BSONArray& tags) { _tags = tags; }
BSONArray getTags() const { return _tags; }
private: private:
// Convention: (M)andatory, (O)ptional, (S)pecial rule. // Convention: (M)andatory, (O)ptional, (S)pecial rule.
std::string _name; // (M) shard's id std::string _name; // (M) shard's id
std::string _host; // (M) connection string for the host(s) std::string _host; // (M) connection string for the host(s)
bool _draining; // (O) is it draining chunks? bool _draining; // (O) is it draining chunks?
long long _maxSize; // (O) maximum allowed disk space in MB long long _maxSize; // (O) maximum allowed disk space in MB
BSONArray _tags; // (O) shard tags
}; };
} // namespace mongo } // namespace mongo
 End of changes. 8 change blocks. 
9 lines changed or deleted 16 lines changed or added


 undef_macros.h   undef_macros.h 
skipping to change at line 41 skipping to change at line 41
// util/assert_util.h // util/assert_util.h
#undef dassert #undef dassert
#pragma pop_macro("dassert") #pragma pop_macro("dassert")
#undef wassert #undef wassert
#pragma pop_macro("wassert") #pragma pop_macro("wassert")
#undef massert #undef massert
#pragma pop_macro("massert") #pragma pop_macro("massert")
#undef uassert #undef uassert
#pragma pop_macro("uassert") #pragma pop_macro("uassert")
#undef uassertStatusOK
#pragma pop_macro("uassertStatusOK")
#undef verify #undef verify
#pragma pop_macro("verify") #pragma pop_macro("verify")
#undef DESTRUCTOR_GUARD #undef DESTRUCTOR_GUARD
#pragma pop_macro("DESTRUCTOR_GUARD") #pragma pop_macro("DESTRUCTOR_GUARD")
// util/goodies.h // util/goodies.h
#undef PRINT #undef PRINT
#pragma pop_macro("PRINT") #pragma pop_macro("PRINT")
#undef PRINTFL #undef PRINTFL
#pragma pop_macro("PRINTFL") #pragma pop_macro("PRINTFL")
 End of changes. 1 change blocks. 
0 lines changed or deleted 2 lines changed or added


 unittest.h   unittest.h 
skipping to change at line 57 skipping to change at line 57
#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(Status::OK(), (EXPRESSION))
/** /**
* Assert that a status code is anything but OK.
*/
#define ASSERT_NOT_OK(EXPRESSION) ASSERT_NOT_EQUALS(Status::OK(), (EXPRESSI
ON))
/**
* 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.
*/ */
#define ASSERT_EQUALS(a,b) _ASSERT_COMPARISON(Equal, a, b) #define ASSERT_EQUALS(a,b) _ASSERT_COMPARISON(Equal, a, b)
#define ASSERT_NOT_EQUALS(a,b) _ASSERT_COMPARISON(NotEqual, a, b) #define ASSERT_NOT_EQUALS(a,b) _ASSERT_COMPARISON(NotEqual, a, b)
 End of changes. 1 change blocks. 
0 lines changed or deleted 6 lines changed or added


 unordered_fast_key_table.h   unordered_fast_key_table.h 
skipping to change at line 26 skipping to change at line 26
*/ */
#pragma once #pragma once
#include <boost/smart_ptr/scoped_array.hpp> #include <boost/smart_ptr/scoped_array.hpp>
#include "mongo/base/disallow_copying.h" #include "mongo/base/disallow_copying.h"
namespace mongo { namespace mongo {
template<typename K_L, typename K_S>
struct UnorderedFastKeyTable_LS_C {
K_S operator()( const K_L& a ) const {
return K_S(a);
}
};
template< typename K_L, // key lookup template< typename K_L, // key lookup
typename K_S, // key storage typename K_S, // key storage
typename V, // value typename V, // value
typename H , // hash of K_L typename H , // hash of K_L
typename E, // equal of K_L typename E, // equal of K_L
typename C // convertor from K_S -> K_L typename C, // convertor from K_S -> K_L
typename C_LS=UnorderedFastKeyTable_LS_C<K_L,K_S> // converto
r from K_L -> K_S
> >
class UnorderedFastKeyTable { class UnorderedFastKeyTable {
MONGO_DISALLOW_COPYING(UnorderedFastKeyTable);
public: public:
typedef std::pair<K_S, V> value_type; typedef std::pair<K_S, V> value_type;
typedef K_L key_type;
typedef V mapped_type; typedef V mapped_type;
private: private:
struct Entry { struct Entry {
Entry() Entry()
: used( false ), everUsed( false ) { : used( false ), everUsed( false ) {
} }
bool used; bool used;
bool everUsed; bool everUsed;
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 );
int find( const K_L& key, size_t hash, int* firstEmpty, const U norderedFastKeyTable& sm ) const; int find( const K_L& key, size_t hash, int* firstEmpty, const U norderedFastKeyTable& sm ) const;
void transfer( Area* newArea, const UnorderedFastKeyTable& sm ) const; void transfer( Area* newArea, const UnorderedFastKeyTable& sm ) const;
void swap( Area* other ) { void swap( Area* other ) {
std::swap( _capacity, other->_capacity ); using std::swap;
std::swap( _maxProbe, other->_maxProbe ); swap( _capacity, other->_capacity );
_entries.swap( other->_entries ); swap( _maxProbe, other->_maxProbe );
swap( _entries, other->_entries );
} }
unsigned _capacity; unsigned _capacity;
unsigned _maxProbe; unsigned _maxProbe;
boost::scoped_array<Entry> _entries; boost::scoped_array<Entry> _entries;
}; };
public: public:
static const unsigned DEFAULT_STARTING_CAPACITY = 20; static const unsigned DEFAULT_STARTING_CAPACITY = 20;
/** /**
* @param startingCapacity how many buckets should exist on initial creation * @param startingCapacity how many buckets should exist on initial creation
* DEFAULT_STARTING_CAPACITY * DEFAULT_STARTING_CAPACITY
* @param maxProbeRatio the percentage of buckets we're willing to probe * @param maxProbeRatio the percentage of buckets we're willing to probe
* no defined default as you can't have a stat ic const double on windows * no defined default as you can't have a stat ic const double on windows
*/ */
UnorderedFastKeyTable( unsigned startingCapacity = DEFAULT_STARTING _CAPACITY, UnorderedFastKeyTable( unsigned startingCapacity = DEFAULT_STARTING _CAPACITY,
double maxProbeRatio = 0.05 ); double maxProbeRatio = 0.05 );
UnorderedFastKeyTable( const UnorderedFastKeyTable& other );
UnorderedFastKeyTable& operator=( const UnorderedFastKeyTable& othe
r ) {
other.copyTo( this );
return *this;
}
void copyTo( UnorderedFastKeyTable* out ) const;
/** /**
* @return number of elements in map * @return number of elements in map
*/ */
size_t size() const { return _size; } size_t size() const { return _size; }
bool empty() const { return _size == 0; } bool empty() const { return _size == 0; }
/* /*
* @return storage space * @return storage space
*/ */
size_t capacity() const { return _area._capacity; } size_t capacity() const { return _area._capacity; }
V& operator[]( const K_L& key ) { return get( key ); } V& operator[]( const K_L& key ) { return get( key ); }
V& get( const K_L& key ); V& get( const K_L& key );
/**
* @return number of elements removed
*/
size_t erase( const K_L& key );
class const_iterator { class const_iterator {
public: public:
const_iterator() { _theEntry = NULL; } const_iterator() { _position = -1; }
const_iterator( const Entry* entry ) { _theEntry = entry; } const_iterator( const Area* area ) {
_area = area;
_position = 0;
_max = _area->_capacity - 1;
_skip();
}
const_iterator( const Area* area, int pos ) {
_area = area;
_position = pos;
_max = pos;
}
const value_type* operator->() const { return &_theEntry->data; } const value_type* operator->() const { return &_area->_entries[ _position].data; }
const_iterator operator++( int n ) { _theEntry = NULL; return * const_iterator operator++() {
this; } if ( _position < 0 )
return *this;
_position++;
if ( _position > _max )
_position = -1;
else
_skip();
return *this;
}
bool operator==( const const_iterator& other ) const { bool operator==( const const_iterator& other ) const {
return _theEntry == other._theEntry; return _position == other._position;
} }
bool operator!=( const const_iterator& other ) const { bool operator!=( const const_iterator& other ) const {
return _theEntry != other._theEntry; return _position != other._position;
} }
private: private:
const Entry* _theEntry;
void _skip() {
while ( true ) {
if ( _area->_entries[_position].used )
break;
if ( _position >= _max ) {
_position = -1;
break;
}
++_position;
}
}
const Area* _area;
int _position;
int _max; // inclusive
}; };
/**
* @return either a one-shot iterator with the key, or end()
*/
const_iterator find( const K_L& key ) const; const_iterator find( const K_L& key ) const;
const_iterator begin() const;
const_iterator end() const; const_iterator end() const;
private: private:
/* /*
* @param firstEmpty, if we return -1, and firstEmpty != NULL, * @param firstEmpty, if we return -1, and firstEmpty != NULL,
* this will be set to the first empty bucket we found * this will be set to the first empty bucket we found
* @retrun offset into _entries or -1 if not there * @retrun offset into _entries or -1 if not there
*/ */
int _find( const K_L& key, int hash, int* firstEmpty ) const; int _find( const K_L& key, int hash, int* firstEmpty ) const;
void _grow(); void _grow();
// ---- // ----
size_t _size; size_t _size;
const double _maxProbeRatio; double _maxProbeRatio;
Area _area; Area _area;
H _hash; H _hash;
E _equals; E _equals;
C _convertor; C _convertor;
C_LS _convertorOther;
}; };
} }
#include "mongo/util/unordered_fast_key_table_internal.h" #include "mongo/util/unordered_fast_key_table_internal.h"
 End of changes. 18 change blocks. 
14 lines changed or deleted 79 lines changed or added


 unordered_fast_key_table_internal.h   unordered_fast_key_table_internal.h 
skipping to change at line 18 skipping to change at line 18
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include "mongo/util/assert_util.h"
namespace mongo { namespace mongo {
template< typename K_L, typename K_S, typename V, typename H, typename template< typename K_L, typename K_S, typename V, typename H, typename
E, typename C > E, typename C, typename C_LS >
inline UnorderedFastKeyTable<K_L, K_S, V, H, E, C>::Area::Area(unsigned inline UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::Area::Area(un
capacity, signed capacity,
double m axProbeRatio) double m axProbeRatio)
: _capacity( capacity ), : _capacity( capacity ),
_maxProbe( static_cast<unsigned>( capacity * maxProbeRatio ) ), _maxProbe( static_cast<unsigned>( capacity * maxProbeRatio ) ),
_entries( new Entry[_capacity] ) { _entries( new Entry[_capacity] ) {
} }
template< typename K_L, typename K_S, typename V, typename H, typename template< typename K_L, typename K_S, typename V, typename H, typename
E, typename C > E, typename C, typename C_LS >
inline int UnorderedFastKeyTable<K_L, K_S, V, H, E, C>::Area::find( inline UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::Area::Area(co
nst Area& other )
: _capacity( other._capacity ),
_maxProbe( other._maxProbe ),
_entries( new Entry[_capacity] ) {
for ( unsigned i = 0; i < _capacity; i++ ) {
_entries[i] = other._entries[i];
}
}
template< typename K_L, typename K_S, typename V, typename H, typename
E, typename C, typename C_LS >
inline int UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::Area::fin
d(
const K_L& key, const K_L& key,
size_t hash, size_t hash,
int* firstEmpty, int* firstEmpty,
const UnorderedFastKeyTable& sm ) const { const UnorderedFastKeyTable& sm ) const {
if ( firstEmpty ) if ( firstEmpty )
*firstEmpty = -1; *firstEmpty = -1;
for ( unsigned probe = 0; probe < _maxProbe; probe++ ) { for ( unsigned probe = 0; probe < _maxProbe; probe++ ) {
unsigned pos = (hash + probe) % _capacity; unsigned pos = (hash + probe) % _capacity;
skipping to change at line 66 skipping to change at line 78
continue; continue;
} }
// 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 template< typename K_L, typename K_S, typename V, typename H, typename
E, typename C > E, typename C, typename C_LS >
inline void UnorderedFastKeyTable<K_L, K_S, V, H, E, C>::Area::transfer 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 );
verify( firstEmpty >= 0 ); verify( firstEmpty >= 0 );
newArea->_entries[firstEmpty] = _entries[i]; newArea->_entries[firstEmpty] = _entries[i];
} }
} }
template< typename K_L, typename K_S, typename V, typename H, typename template< typename K_L, typename K_S, typename V, typename H, typename
E, typename C > E, typename C, typename C_LS >
inline UnorderedFastKeyTable<K_L, K_S, V, H, E, C>::UnorderedFastKeyTab inline UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::UnorderedFast
le( 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;
} }
template< typename K_L, typename K_S, typename V, typename H, typename template< typename K_L, typename K_S, typename V, typename H, typename
E, typename C > E, typename C, typename C_LS >
inline V& UnorderedFastKeyTable<K_L, K_S, V, H, E, C>::get( const K_L& inline UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::UnorderedFast
key ) { KeyTable(
const UnorderedFastKeyTable& other )
: _size( other._size ),
_maxProbeRatio( other._maxProbeRatio ),
_area( other._area ),
_hash( other._hash ),
_equals( other._equals ),
_convertor( other._convertor ),
_convertorOther( other._convertorOther ) {
}
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>::copyTo(
UnorderedFastKeyTable* out ) const {
out->_size = _size;
out->_maxProbeRatio = _maxProbeRatio;
Area x( _area );
out->_area.swap( &x );
}
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 ) {
const size_t hash = _hash( key ); const size_t hash = _hash( key );
for ( int numGrowTries = 0; numGrowTries < 10; 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;
_area._entries[firstEmpty].everUsed = true; _area._entries[firstEmpty].everUsed = true;
_area._entries[firstEmpty].curHash = hash; _area._entries[firstEmpty].curHash = hash;
_area._entries[firstEmpty].data.first = key; _area._entries[firstEmpty].data.first = _convertorOther(key );
return _area._entries[firstEmpty].data.second; return _area._entries[firstEmpty].data.second;
} }
// no space left in map // no space left in map
_grow(); _grow();
} }
msgasserted( 16471, "UnorderedFastKeyTable couldn't add entry after growing many times" ); msgasserted( 16471, "UnorderedFastKeyTable couldn't add entry after growing many times" );
} }
template< typename K_L, typename K_S, typename V, typename H, typename template< typename K_L, typename K_S, typename V, typename H, typename
E, typename C > E, typename C, typename C_LS >
inline void UnorderedFastKeyTable<K_L, K_S, V, H, E, C>::_grow() { inline size_t UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::erase(
const K_L& key ) {
const size_t hash = _hash( key );
int pos = _area.find( key, hash, NULL, *this );
if ( pos < 0 )
return 0;
_area._entries[pos].used = false;
_area._entries[pos].data.second = V();
return 1;
}
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()
{
Area newArea( _area._capacity * 2, _maxProbeRatio ); Area newArea( _area._capacity * 2, _maxProbeRatio );
_area.transfer( &newArea, *this ); _area.transfer( &newArea, *this );
_area.swap( &newArea ); _area.swap( &newArea );
} }
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
UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::find( const K_L& key
) const {
if ( _size == 0 )
return const_iterator();
int pos = _area.find( key, _hash(key), 0, *this );
if ( pos < 0 )
return const_iterator();
return const_iterator( &_area, pos );
}
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
UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::end() const {
return const_iterator();
}
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
UnorderedFastKeyTable<K_L, K_S, V, H, E, C, C_LS>::begin() const {
return const_iterator( &_area );
}
} }
 End of changes. 9 change blocks. 
23 lines changed or deleted 108 lines changed or added


 update_internal.h   update_internal.h 
skipping to change at line 33 skipping to change at line 33
#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/stringutils.h" #include "mongo/util/stringutils.h"
namespace mongo { namespace mongo {
class ModState; class ModState;
class ModSetState; class ModSetState;
/**
* a.$ -> a
* @return true if out is set and we made a change
*/
bool getCanonicalIndexField( const StringData& fullName, string* out );
/* 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 {
// See opFromStr below // See opFromStr below
// 0 1 2 3 4 5 6 7 8 // 0 1 2 3 4 5 6 7 8
9 10 11 12 13 9 10 11 12 13 14
enum Op { INC, SET, PUSH, PUSH_ALL, PULL, PULL_ALL , POP, UNSET, BI enum Op { INC, SET, PUSH, PUSH_ALL, PULL, PULL_ALL , POP, UNSET, BI
TAND, BITOR , BIT , ADDTOSET, RENAME_FROM, RENAME_TO } op; TAND, BITOR , BIT , ADDTOSET, RENAME_FROM, RENAME_TO, SET_ON_INSERT } op;
static const char* modNames[]; static const char* modNames[];
static unsigned modNamesNum; static unsigned modNamesNum;
const char* fieldName; const char* fieldName;
const char* shortFieldName; const char* shortFieldName;
// Determines if this mod must absoluetly be applied. In some repli cation scenarios, a // Determines if this mod must absoluetly be applied. In some repli cation scenarios, a
// failed apply of a mod does not constitute an error. In those cas es, setting strict // failed apply of a mod does not constitute an error. In those cas es, setting strict
// to off would not throw errors. // to off would not throw errors.
skipping to change at line 146 skipping to change at line 152
static bool isIndexed( const string& fullName , const set<string>& idxKeys ) { static bool isIndexed( const string& fullName , const set<string>& idxKeys ) {
const char * fieldName = fullName.c_str(); const char * fieldName = fullName.c_str();
// check if there is an index key that is a parent of mod // check if there is an index key that is a parent of mod
for( const char* dot = strchr( fieldName, '.' ); dot; dot = str chr( dot + 1, '.' ) ) for( const char* dot = strchr( fieldName, '.' ); dot; dot = str chr( dot + 1, '.' ) )
if ( idxKeys.count( string( fieldName, dot - fieldName ) ) ) if ( idxKeys.count( string( fieldName, dot - fieldName ) ) )
return true; return true;
// check if there is an index key equal to mod // check if there is an index key equal to mod
if ( idxKeys.count(fullName) ) if ( idxKeys.count(fullName) )
return true; return true;
// check if there is an index key that is a child of mod // check if there is an index key that is a child of mod
set< string >::const_iterator j = idxKeys.upper_bound( fullName ); set< string >::const_iterator j = idxKeys.upper_bound( fullName );
if ( j != idxKeys.end() && j->find( fullName ) == 0 && (*j)[ful lName.size()] == '.' ) if ( j != idxKeys.end() && j->find( fullName ) == 0 && (*j)[ful lName.size()] == '.' )
return true; return true;
return false; return false;
} }
/**
* checks if mod is in the index by inspecting fieldName, and remov
ing
* .$ or .### substrings (#=digit) with any number of digits.
*
* @return true iff the mod is indexed
*/
bool isIndexed( const set<string>& idxKeys ) const { bool isIndexed( const set<string>& idxKeys ) const {
string fullName = fieldName;
if ( isIndexed( fullName , idxKeys ) ) // first, check if full name is in idxKeys
if ( isIndexed( fieldName , idxKeys ) )
return true; return true;
if ( strstr( fieldName , "." ) ) { string x;
// check for a.0.1 if ( getCanonicalIndexField( fieldName, &x ) ) {
StringBuilder buf; if ( isIndexed( x, idxKeys ) )
for ( size_t i=0; i<fullName.size(); i++ ) {
char c = fullName[i];
if ( c == '$' &&
i > 0 && fullName[i-1] == '.' &&
i+1<fullName.size() &&
fullName[i+1] == '.' ) {
i++;
continue;
}
buf << c;
if ( c != '.' )
continue;
if ( ! isdigit( fullName[i+1] ) )
continue;
bool possible = true;
size_t j=i+2;
for ( ; j<fullName.size(); j++ ) {
char d = fullName[j];
if ( d == '.' )
break;
if ( isdigit( d ) )
continue;
possible = false;
break;
}
if ( possible )
i = j;
}
string x = buf.str();
if ( isIndexed( x , idxKeys ) )
return true; return true;
} }
return false; return false;
} }
void apply( BSONBuilderBase& b , BSONElement in , ModState& ms ) co nst; void apply( BSONBuilderBase& b , BSONElement in , ModState& ms ) co nst;
/** /**
* @return true iff toMatch should be removed from the array * @return true iff toMatch should be removed from the array
skipping to change at line 242 skipping to change at line 219
return elt.embeddedObjectUserCheck().firstElement().embeddedObj ectUserCheck(); return elt.embeddedObjectUserCheck().firstElement().embeddedObj ectUserCheck();
} }
void parseEach( BSONElementSet& s ) const { void parseEach( BSONElementSet& s ) const {
BSONObjIterator i(getEach()); BSONObjIterator i(getEach());
while ( i.more() ) { while ( i.more() ) {
s.insert( i.next() ); s.insert( i.next() );
} }
} }
bool isSliceOnly() const {
if ( elt.type() != Object )
return false;
BSONObj obj = elt.embeddedObject();
if ( obj.nFields() != 2 )
return false;
BSONObjIterator i( obj );
i.next();
BSONElement elemSlice = i.next();
return strcmp( elemSlice.fieldName(), "$slice" ) == 0;
}
long long getSlice() const {
// The $slice may be the second or the third elemen in the fiel
d object.
// { <field name>: { $each: [<each array>], $slice: -N, $sort:
<pattern> } }
// 'elt' here is the BSONElement above.
BSONObj obj = elt.embeddedObject();
BSONObjIterator i( obj );
i.next();
BSONElement elem = i.next();
if ( ! str::equals( elem.fieldName(), "$slice" ) ) {
elem = i.next();
}
dassert( elem.isNumber() );
// For now, we're only supporting slicing from the back of the
array, i.e.
// negative slice. But the code now is wired in the opposite wa
y: trimming from the
// back of the array is positive.
// TODO: fix this.
return -elem.numberLong();
}
bool isSliceAndSort() const {
if ( elt.type() != Object )
return false;
BSONObj obj = elt.embeddedObject();
if ( obj.nFields() != 3 )
return false;
BSONObjIterator i( obj );
i.next();
// Slice and sort may be switched.
bool seenSlice = false;
bool seenSort = false;
while ( i.more() ) {
BSONElement elem = i.next();
if ( str::equals( elem.fieldName(), "$slice" ) ) {
if ( seenSlice ) return false;
seenSlice = true;
}
else if ( str::equals( elem.fieldName(), "$sort" ) ) {
if ( seenSort ) return false;
seenSort = true;
if ( elem.type() != Object ) return false;
}
else {
return false;
}
}
// If present, the $sort element would have been checked during
ModSet construction.
return seenSlice && seenSort;
}
BSONObj getSort() const {
// The $sort may be the second or the third element in the fiel
d object.
// { <field name>: { $each: [<each array>], $slice: -N, $sort:
<pattern> } }
// 'elt' here is the BSONElement above.
BSONObj obj = elt.embeddedObject();
BSONObjIterator i( obj );
i.next();
BSONElement elem = i.next();
if ( ! str::equals( elem.fieldName(), "$sort" ) ) {
elem = i.next();
}
return elem.embeddedObject();
}
const char* renameFrom() const { const char* renameFrom() const {
massert( 13492, "mod must be RENAME_TO type", op == Mod::RENAME _TO ); massert( 13492, "mod must be RENAME_TO type", op == Mod::RENAME _TO );
return elt.fieldName(); return elt.fieldName();
} }
}; };
/** /**
* stores a set of Mods * stores a set of Mods
* once created, should never be changed * once created, should never be changed
*/ */
skipping to change at line 267 skipping to change at line 322
static Mod::Op opFromStr( const char* fn ) { static Mod::Op opFromStr( const char* fn ) {
verify( fn[0] == '$' ); verify( fn[0] == '$' );
switch( fn[1] ) { switch( fn[1] ) {
case 'i': { case 'i': {
if ( fn[2] == 'n' && fn[3] == 'c' && fn[4] == 0 ) if ( fn[2] == 'n' && fn[3] == 'c' && fn[4] == 0 )
return Mod::INC; return Mod::INC;
break; break;
} }
case 's': { case 's': {
if ( fn[2] == 'e' && fn[3] == 't' && fn[4] == 0 ) if ( fn[2] == 'e' && fn[3] == 't' ) {
return Mod::SET; if ( fn[4] == 0 ) {
return Mod::SET;
}
else if ( fn[4] == 'O' && fn[5] == 'n' && fn[6] == 'I'
&& fn[7] == 'n' &&
fn[8] == 's' && fn[9] == 'e' && fn[10] == 'r'
&& fn[11] == 't' &&
fn[12] == 0 ) {
return Mod::SET_ON_INSERT;
}
}
break; break;
} }
case 'p': { case 'p': {
if ( fn[2] == 'u' ) { if ( fn[2] == 'u' ) {
if ( fn[3] == 's' && fn[4] == 'h' ) { if ( fn[3] == 's' && fn[4] == 'h' ) {
if ( fn[5] == 0 ) if ( fn[5] == 0 )
return Mod::PUSH; return Mod::PUSH;
if ( fn[5] == 'A' && fn[6] == 'l' && fn[7] == 'l' & & fn[8] == 0 ) if ( fn[5] == 'A' && fn[6] == 'l' && fn[7] == 'l' & & fn[8] == 0 )
return Mod::PUSH_ALL; return Mod::PUSH_ALL;
} }
skipping to change at line 396 skipping to change at line 459
case RIGHT_BEFORE: return false; case RIGHT_BEFORE: return false;
case RIGHT_SUBFIELD: return true; case RIGHT_SUBFIELD: return true;
} }
} }
return false; return false;
} }
}; };
/** /**
* Comparator between two BSONObjects that takes in consideration only
the keys and
* direction described in the sort pattern.
*/
struct ProjectKeyCmp {
BSONObj sortPattern;
BSONObj projectionPattern;
ProjectKeyCmp( BSONObj pattern ) : sortPattern( pattern ) {
BSONObjBuilder projectBuilder;
BSONObjIterator i( sortPattern );
while ( i.more() ) {
BSONElement elem = i.next();
uassert( 16645, "sort pattern must be numeric", elem.isNumb
er() );
double val = elem.Number();
uassert( 16646, "sort pattern must contain 1 or -1", val*va
l == 1.0);
//
// If there are dots in the field name, check that they for
m a proper
// field path (e.g., no empty field parts).
//
StringData field( elem.fieldName() );
uassert( 16651, "sort pattern field name cannot be empty" ,
field.size() );
size_t pos = field.find('.');
while ( pos != string::npos ) {
uassert( 16639,
"empty field in dotted sort pattern",
(pos > 0) && (pos != field.size() - 1) );
field = field.substr( pos+1 );
pos = field.find('.');
}
projectBuilder.append( elem.fieldName(), 1 );
}
projectionPattern = projectBuilder.obj();
}
int operator()( const BSONObj& left, const BSONObj& right ) {
BSONObj keyLeft = left.extractFields( projectionPattern, true )
;
BSONObj keyRight = right.extractFields( projectionPattern, true
);
return keyLeft.woCompare( keyRight, sortPattern ) < 0;
}
};
/**
* stores any information about a single Mod operating on a single Obje ct * stores any information about a single Mod operating on a single Obje ct
*/ */
class ModState : boost::noncopyable { class ModState : boost::noncopyable {
public: public:
const Mod* m; const Mod* m;
BSONElement old; BSONElement old;
BSONElement newVal; BSONElement newVal;
BSONObj _objData; BSONObj _objData;
const char* fixedOpName; const char* fixedOpName;
skipping to change at line 535 skipping to change at line 648
//const Mod& m = *(ms.m); // HACK //const Mod& m = *(ms.m); // HACK
Mod& m = *((Mod*)(ms.m)); // HACK Mod& m = *((Mod*)(ms.m)); // HACK
switch ( m.op ) { switch ( m.op ) {
case Mod::PUSH: { case Mod::PUSH: {
ms.fixedOpName = "$set"; ms.fixedOpName = "$set";
if ( m.isEach() ) { if ( m.isEach() ) {
BSONObj arr = m.getEach(); BSONObj arr = m.getEach();
b.appendArray( m.shortFieldName, arr ); if ( !m.isSliceOnly() && !m.isSliceAndSort() ) {
ms.forceEmptyArray = true; b.appendArray( m.shortFieldName, arr );
ms.fixedArray = BSONArray(arr.getOwned());
} else { ms.forceEmptyArray = true;
ms.fixedArray = BSONArray( arr.getOwned() );
}
else if ( m.isSliceOnly() && ( m.getSlice() >= arr.nFie
lds() ) ) {
b.appendArray( m.shortFieldName, arr );
ms.forceEmptyArray = true;
ms.fixedArray = BSONArray( arr.getOwned() );
}
else if ( m.isSliceOnly() ) {
BSONArrayBuilder arrBuilder( b.subarrayStart( m.sho
rtFieldName ) );
long long skip = arr.nFields() - m.getSlice();
BSONObjIterator j( arr );
while ( j.more() ) {
if ( skip-- > 0 ) {
j.next();
continue;
}
arrBuilder.append( j.next() );
}
ms.forceEmptyArray = true;
ms.fixedArray = BSONArray( arrBuilder.done().getOwn
ed() );
}
else if ( m.isSliceAndSort() ) {
long long slice = m.getSlice();
BSONObj sortPattern = m.getSort();
// Sort the $each array over sortPattern.
vector<BSONObj> workArea;
BSONObjIterator j( arr );
while ( j.more() ) {
workArea.push_back( j.next().Obj() );
}
sort( workArea.begin(), workArea.end(), ProjectKeyC
mp( sortPattern) );
// Slice to the appropriate size. If slice is zero,
that's equivalent
// to resetting the array, ie, a no-op.
BSONArrayBuilder arrBuilder( b.subarrayStart( m.sho
rtFieldName ) );
if (slice > 0) {
long long skip = std::max( 0LL,
(long long)workArea.
size() - slice );
for (vector<BSONObj>::iterator it = workArea.be
gin();
it != workArea.end();
++it ) {
if ( skip-- > 0 ) {
continue;
}
arrBuilder.append( *it );
}
}
// Log the full resulting array.
ms.forceEmptyArray = true;
ms.fixedArray = BSONArray( arrBuilder.done().getOwn
ed() );
}
}
else {
BSONObjBuilder arr( b.subarrayStart( m.shortFieldName ) ); BSONObjBuilder arr( b.subarrayStart( m.shortFieldName ) );
arr.appendAs( m.elt, "0" ); arr.appendAs( m.elt, "0" );
ms.forceEmptyArray = true; ms.forceEmptyArray = true;
ms.fixedArray = BSONArray(arr.done().getOwned()); ms.fixedArray = BSONArray(arr.done().getOwned());
} }
break; break;
} }
case Mod::ADDTOSET: { case Mod::ADDTOSET: {
ms.fixedOpName = "$set"; ms.fixedOpName = "$set";
if ( m.isEach() ) { if ( m.isEach() ) {
// Remove any duplicates in given array // Remove any duplicates in given array
skipping to change at line 593 skipping to change at line 764
case Mod::POP: case Mod::POP:
case Mod::PULL: case Mod::PULL:
case Mod::PULL_ALL: case Mod::PULL_ALL:
case Mod::UNSET: case Mod::UNSET:
// No-op b/c unset/pull of nothing does nothing. Still, exp licilty log that // No-op b/c unset/pull of nothing does nothing. Still, exp licilty log that
// the target array was reset. // the target array was reset.
ms.fixedOpName = "$unset"; ms.fixedOpName = "$unset";
break; break;
case Mod::INC: case Mod::INC:
case Mod::SET_ON_INSERT:
ms.fixedOpName = "$set"; ms.fixedOpName = "$set";
case Mod::SET: { case Mod::SET: {
m._checkForAppending( m.elt ); m._checkForAppending( m.elt );
b.appendAs( m.elt, m.shortFieldName ); b.appendAs( m.elt, m.shortFieldName );
break; break;
} }
// shouldn't see RENAME_FROM here // shouldn't see RENAME_FROM here
case Mod::RENAME_TO: case Mod::RENAME_TO:
ms.handleRename( b, m.shortFieldName ); ms.handleRename( b, m.shortFieldName );
 End of changes. 13 change blocks. 
51 lines changed or deleted 249 lines changed or added


 v8_db.h   v8_db.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 <boost/function.hpp> #include <boost/function.hpp>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <v8.h> #include <v8.h>
#include "mongo/scripting/engine_v8.h" #include "mongo/scripting/engine_v8.h"
namespace mongo { namespace mongo {
class DBClientBase;
// These functions may depend on the caller creating a handle scope and
context scope.
v8::Handle<v8::FunctionTemplate> getMongoFunctionTemplate( V8Scope * sc
ope, bool local );
// void installDBTypes( V8Scope * scope, v8::Handle<v8::ObjectTemplate>&
global );
void installDBTypes( V8Scope * scope, v8::Handle<v8::Object>& global );
// the actual globals class DBClientBase;
mongo::DBClientBase * getConnection( const v8::Arguments& args ); /**
* install the db related functions and objects in the given scope
*/
void installDBTypes(V8Scope* scope, v8::Handle<v8::Object>& global);
/**
* get the DBClientBase connection from JS args
*/
mongo::DBClientBase* getConnection(const v8::Arguments& args);
// Mongo members // 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);
// Mongo member functions
v8::Handle<v8::Value> mongoFind(V8Scope* scope, const v8::Arguments& ar gs); v8::Handle<v8::Value> mongoFind(V8Scope* scope, const v8::Arguments& ar gs);
v8::Handle<v8::Value> mongoInsert(V8Scope* scope, const v8::Arguments& args); v8::Handle<v8::Value> mongoInsert(V8Scope* scope, const v8::Arguments& args);
v8::Handle<v8::Value> mongoRemove(V8Scope* scope, const v8::Arguments& args); v8::Handle<v8::Value> mongoRemove(V8Scope* scope, const v8::Arguments& args);
v8::Handle<v8::Value> mongoUpdate(V8Scope* scope, const v8::Arguments& args); v8::Handle<v8::Value> mongoUpdate(V8Scope* scope, const v8::Arguments& args);
v8::Handle<v8::Value> mongoAuth(V8Scope* scope, const v8::Arguments& ar gs); v8::Handle<v8::Value> mongoAuth(V8Scope* scope, const v8::Arguments& ar gs);
v8::Handle<v8::Value> mongoLogout(V8Scope* scope, const v8::Arguments& args); v8::Handle<v8::Value> mongoLogout(V8Scope* scope, const v8::Arguments& args);
// Cursor object
v8::Handle<v8::Value> internalCursorCons(V8Scope* scope, const v8::Argu ments& args); v8::Handle<v8::Value> internalCursorCons(V8Scope* scope, const v8::Argu ments& args);
v8::Handle<v8::Value> internalCursorNext(V8Scope* scope, const v8::Argu ments& args); v8::Handle<v8::Value> internalCursorNext(V8Scope* scope, const v8::Argu ments& args);
v8::Handle<v8::Value> internalCursorHasNext(V8Scope* scope, const v8::A rguments& args); v8::Handle<v8::Value> internalCursorHasNext(V8Scope* scope, const v8::A rguments& args);
v8::Handle<v8::Value> internalCursorObjsLeftInBatch(V8Scope* scope, con st v8::Arguments& args); v8::Handle<v8::Value> internalCursorObjsLeftInBatch(V8Scope* scope, con st v8::Arguments& args);
v8::Handle<v8::Value> internalCursorReadOnly(V8Scope* scope, const v8:: Arguments& args); v8::Handle<v8::Value> internalCursorReadOnly(V8Scope* scope, const v8:: Arguments& args);
// DB members // BinData object
v8::Handle<v8::Value> binDataInit(V8Scope* scope, const v8::Arguments&
v8::Handle<v8::Value> dbInit(V8Scope* scope, const v8::Arguments& args) args);
; v8::Handle<v8::Value> binDataToString(V8Scope* scope, const v8::Argumen
v8::Handle<v8::Value> collectionInit(V8Scope* scope, const v8::Argument ts& args);
s& args ); v8::Handle<v8::Value> binDataToBase64(V8Scope* scope, const v8::Argumen
v8::Handle<v8::Value> objectIdInit( V8Scope* scope, const v8::Arguments ts& args);
& args ); v8::Handle<v8::Value> binDataToHex(V8Scope* scope, const v8::Arguments&
args);
v8::Handle<v8::Value> dbRefInit( V8Scope* scope, const v8::Arguments& a // NumberLong object
rgs ); v8::Handle<v8::Value> numberLongInit(V8Scope* scope, const v8::Argument
v8::Handle<v8::Value> dbPointerInit( V8Scope* scope, const v8::Argument s& args);
s& args );
v8::Handle<v8::Value> dbTimestampInit( V8Scope* scope, const v8::Argume
nts& args );
v8::Handle<v8::Value> binDataInit( V8Scope* scope, const v8::Arguments&
args );
v8::Handle<v8::Value> binDataToString( V8Scope* scope, const v8::Argume
nts& args );
v8::Handle<v8::Value> binDataToBase64( V8Scope* scope, const v8::Argume
nts& args );
v8::Handle<v8::Value> binDataToHex( V8Scope* scope, const v8::Arguments
& args );
v8::Handle<v8::Value> uuidInit( V8Scope* scope, const v8::Arguments& ar
gs );
v8::Handle<v8::Value> md5Init( V8Scope* scope, const v8::Arguments& arg
s );
v8::Handle<v8::Value> hexDataInit( V8Scope* scope, const v8::Arguments&
args );
v8::Handle<v8::Value> numberLongInit( V8Scope* scope, const v8::Argumen
ts& 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);
v8::Handle<v8::Value> numberIntInit( V8Scope* scope, const v8::Argument // Number object
s& 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);
v8::Handle<v8::Value> dbQueryInit( V8Scope* scope, const v8::Arguments& // DBQuery object
args ); v8::Handle<v8::Value> dbQueryInit(V8Scope* scope, const v8::Arguments&
v8::Handle<v8::Value> dbQueryIndexAccess( ::uint32_t index , const v8:: args);
AccessorInfo& info ); v8::Handle<v8::Value> dbQueryIndexAccess(::uint32_t index, const v8::Ac
cessorInfo& info);
// db constructor
v8::Handle<v8::Value> dbInit(V8Scope* scope, const v8::Arguments& args)
;
// collection constructor
v8::Handle<v8::Value> collectionInit(V8Scope* scope, const v8::Argument
s& args);
v8::Handle<v8::Value> collectionGetter( v8::Local<v8::String> name, con // ObjectId constructor
st v8::AccessorInfo &info); v8::Handle<v8::Value> objectIdInit(V8Scope* scope, const v8::Arguments&
v8::Handle<v8::Value> collectionSetter( Local<v8::String> name, Local<V args);
alue> value, const AccessorInfo& info );
v8::Handle<v8::Value> bsonsize( V8Scope* scope, const v8::Arguments& ar // DBRef constructor
gs ); v8::Handle<v8::Value> dbRefInit(V8Scope* scope, const v8::Arguments& ar
gs);
// DBPointer constructor
v8::Handle<v8::Value> dbPointerInit(V8Scope* scope, const v8::Arguments
& args);
// Timestamp constructor
v8::Handle<v8::Value> dbTimestampInit(V8Scope* scope, const v8::Argumen
ts& args);
// UUID constructor
v8::Handle<v8::Value> uuidInit(V8Scope* scope, const v8::Arguments& arg
s);
// MD5 constructor
v8::Handle<v8::Value> md5Init(V8Scope* scope, const v8::Arguments& args
);
// HexData constructor
v8::Handle<v8::Value> hexDataInit(V8Scope* scope, const v8::Arguments&
args);
// Object.bsonsize()
v8::Handle<v8::Value> bsonsize(V8Scope* scope, const v8::Arguments& arg
s);
// 'db.collection' property handlers
v8::Handle<v8::Value> collectionGetter(v8::Local<v8::String> name,
const v8::AccessorInfo& info);
v8::Handle<v8::Value> collectionSetter(v8::Local<v8::String> name, v8::
Local<v8::Value> value,
const v8::AccessorInfo& info);
typedef boost::function<void (V8Scope*, const v8::Handle<v8::FunctionTe mplate>&)> typedef boost::function<void (V8Scope*, const v8::Handle<v8::FunctionTe mplate>&)>
V8FunctionPrototypeManipulatorFn; V8FunctionPrototypeManipulatorFn;
void v8RegisterMongoPrototypeManipulator(const V8FunctionPrototypeManip ulatorFn& manipulator); void v8RegisterMongoPrototypeManipulator(const V8FunctionPrototypeManip ulatorFn& manipulator);
} }
 End of changes. 15 change blocks. 
61 lines changed or deleted 81 lines changed or added


 v8_utils.h   v8_utils.h 
skipping to change at line 30 skipping to change at line 30
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <v8.h> #include <v8.h>
namespace mongo { namespace mongo {
void ReportException(v8::TryCatch* handler); void ReportException(v8::TryCatch* handler);
#define jsassert(x,msg) verify(x) #define jsassert(x,msg) uassert(16664, msg, x)
std::ostream& operator<<( std::ostream &s, const v8::Handle<v8::Value> std::ostream& operator<<(std::ostream& s, const v8::Handle<v8::Value>&
& o ); o);
std::ostream& operator<<( std::ostream &s, const v8::Handle<v8::TryCatc std::ostream& operator<<(std::ostream& s, const v8::Handle<v8::TryCatch
h> * try_catch ); >* try_catch);
std::string toSTLString( const v8::Handle<v8::Value> & o ); std::string toSTLString(const v8::Handle<v8::Value>& o);
std::string toSTLString( const v8::TryCatch * try_catch ); std::string toSTLString(const v8::TryCatch* try_catch);
class V8Scope; class V8Scope;
void installFork( V8Scope* scope, v8::Handle< v8::Object > &global, v8: void installFork(V8Scope* scope,
:Handle< v8::Context > &context ); v8::Handle<v8::Object>& global,
v8::Handle<v8::Context>& context);
} }
 End of changes. 4 change blocks. 
9 lines changed or deleted 10 lines changed or added


 value_internal.h   value_internal.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 License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include <algorithm> #include <algorithm>
#include "bson/bsonobj.h"
#include "bson/bsontypes.h" #include "bson/bsontypes.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 "util/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:
RCVector() {} RCVector() {}
RCVector(const vector<Value>& v) :vec(v) {} RCVector(const vector<Value>& v) :vec(v) {}
vector<Value> vec; vector<Value> vec;
}; };
class RCCodeWScope : public RefCountable {
public:
RCCodeWScope(const string& str, BSONObj obj) :code(str), scope(obj.
getOwned()) {}
const string code;
const BSONObj scope; // Not worth converting to Document for now
};
class RCDBRef : public RefCountable {
public:
RCDBRef(const string& str, const OID& o) :ns(str), oid(o) {}
const string ns;
const OID oid;
};
#pragma pack(1) #pragma pack(1)
class ValueStorage { class ValueStorage {
public: public:
// Note: it is important the memory is zeroed out (by calling zero(
)) at the start of every
// constructor. Much code relies on every byte being predictably in
itialized to zero.
// This is a "missing" Value // This is a "missing" Value
ValueStorage() { zero(); type = EOO; } ValueStorage() { zero(); type = EOO; }
explicit ValueStorage(BSONType t) { zero(); type = t;} explicit ValueStorage(BSONType t) { zero(); type =
ValueStorage(BSONType t, int i) { zero(); type = t; int t; }
Value = i; } ValueStorage(BSONType t, int i) { zero(); type =
ValueStorage(BSONType t, long long l) { zero(); type = t; lon t; intValue = i; }
gValue = l; } ValueStorage(BSONType t, long long l) { zero(); type =
ValueStorage(BSONType t, double d) { zero(); type = t; dou t; longValue = l; }
bleValue = d; } ValueStorage(BSONType t, double d) { zero(); type =
ValueStorage(BSONType t, ReplTime r) { zero(); type = t; tim t; doubleValue = d; }
estampValue = r; } ValueStorage(BSONType t, ReplTime r) { zero(); type =
ValueStorage(BSONType t, bool b) { zero(); type = t; boo t; timestampValue = r; }
lValue = b; } ValueStorage(BSONType t, bool b) { zero(); type =
ValueStorage(BSONType t, const Document& d) { zero(); type = t; put t; boolValue = b; }
Document(d); } ValueStorage(BSONType t, const Document& d) { zero(); type =
ValueStorage(BSONType t, const RCVector* a) { zero(); type = t; put t; putDocument(d); }
Vector(a); } ValueStorage(BSONType t, const RCVector* a) { zero(); type =
ValueStorage(BSONType t, StringData s) { zero(); type = t; put t; putVector(a); }
String(s); } ValueStorage(BSONType t, const StringData& s) { zero(); type =
t; putString(s); }
ValueStorage(BSONType t, const BSONBinData& bd) { zero(); type =
t; putBinData(bd); }
ValueStorage(BSONType t, const BSONRegEx& re) { zero(); type =
t; putRegEx(re); }
ValueStorage(BSONType t, const BSONCodeWScope& cs) { zero(); type =
t; putCodeWScope(cs); }
ValueStorage(BSONType t, const BSONDBRef& dbref) { zero(); type =
t; putDBRef(dbref); }
ValueStorage(BSONType t, OID& o) { ValueStorage(BSONType t, const OID& o) {
zero(); zero();
type = t; type = t;
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();
} }
skipping to change at line 93 skipping to change at line 116
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 {
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(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 putBinData(const BSONBinData& bd) {
putString(StringData(static_cast<const char*>(bd.data), bd.leng
th));
binSubType = bd.type;
}
void putDBRef(const BSONDBRef& dbref) {
putRefCountable(new RCDBRef(dbref.ns.toString(), dbref.oid));
}
void putCodeWScope(const BSONCodeWScope& cws) {
putRefCountable(new RCCodeWScope(cws.code.toString(), cws.scope
));
}
void putRefCountable(intrusive_ptr<const RefCountable> ptr) {
genericRCPtr = ptr.get();
if (genericRCPtr) {
intrusive_ptr_add_ref(genericRCPtr);
refCounter = true;
}
}
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());
} }
} }
const vector<Value>& getArray() const { const vector<Value>& getArray() const {
dassert(typeid(*genericRCPtr) == typeid(const RCVector)); dassert(typeid(*genericRCPtr) == typeid(const RCVector));
const RCVector* arrayPtr = static_cast<const RCVector*>(generic RCPtr); const RCVector* arrayPtr = static_cast<const RCVector*>(generic RCPtr);
return arrayPtr->vec; return arrayPtr->vec;
} }
intrusive_ptr<const RCCodeWScope> getCodeWScope() const {
dassert(typeid(*genericRCPtr) == typeid(const RCCodeWScope));
return static_cast<const RCCodeWScope*>(genericRCPtr);
}
intrusive_ptr<const RCDBRef> getDBRef() const {
dassert(typeid(*genericRCPtr) == typeid(const RCDBRef));
return static_cast<const RCDBRef*>(genericRCPtr);
}
// Document is incomplete here so this can't be inline // Document is incomplete here so this can't be inline
Document getDocument() const; Document getDocument() const;
BSONType bsonType() const { BSONType bsonType() const {
verify(type != EOO);
return BSONType(type); return BSONType(type);
} }
BinDataType binDataType() const {
dassert(type == BinData);
return BinDataType(binSubType);
}
void zero() { void zero() {
// This is important for identical()
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]);
} }
// 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
skipping to change at line 152 skipping to change at line 210
bool shortStr : 1; // true if we are using short string s bool shortStr : 1; // true if we are using short string s
// reservedFlags: 6; // reservedFlags: 6;
}; };
// bytes 3-16; // bytes 3-16;
union { union {
unsigned char oid[12]; unsigned char oid[12];
struct { struct {
char shortStrSize; // TODO Consider moving into fla gs union (4 bits) char shortStrSize; // TODO Consider moving into fla gs union (4 bits)
char shortStrStorage[16 - 3]; // ValueStorage is 16 char shortStrStorage[16/*total bytes*/ - 3/*offset*
bytes, 3 byte offset / - 1/*NUL byte*/];
union {
char nulTerminator;
unsigned char binSubType; // type always goes h
ere even if !shortStr
};
}; };
struct { struct {
union { union {
char pad[6]; char pad[6];
char stringCache[6]; // TODO copy first few byt es of strings in here char stringCache[6]; // TODO copy first few byt es of strings in here
}; };
union { // 8 bytes long and 8-byte aligned union { // 8 bytes long and 8-byte aligned
// There should be no pointers to non-const dat a // There should be no pointers to non-const dat a
const RefCountable* genericRCPtr; const RefCountable* genericRCPtr;
 End of changes. 13 change blocks. 
23 lines changed or deleted 96 lines changed or added


 version.h   version.h 
skipping to change at line 23 skipping to change at line 23
* You should have received a copy of the GNU Affero General Public Licen se * You should have received a copy of the GNU Affero General Public Licen se
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef UTIL_VERSION_HEADER #ifndef UTIL_VERSION_HEADER
#define UTIL_VERSION_HEADER #define UTIL_VERSION_HEADER
#include <string> #include <string>
#include "mongo/base/string_data.h" #include "mongo/base/string_data.h"
#include "mongo/bson/bsonobjbuilder.h"
namespace mongo { namespace mongo {
struct BSONArray; struct BSONArray;
// mongo version // mongo version
extern const char versionString[]; extern const char versionString[];
extern const BSONArray versionArray; extern const BSONArray versionArray;
std::string mongodVersion(); std::string mongodVersion();
int versionCmp(StringData rhs, StringData lhs); // like strcmp
void appendBuildInfo(BSONObjBuilder& result);
const char * gitVersion(); const char * gitVersion();
const char * compiledJSEngine();
const char * allocator();
const char * loaderFlags();
const char * compilerFlags();
void printGitVersion(); void printGitVersion();
std::string sysInfo(); std::string sysInfo();
void printSysInfo(); void printSysInfo();
void printAllocator();
void show_warnings(); void show_warnings();
} // namespace mongo } // namespace mongo
#endif // UTIL_VERSION_HEADER #endif // UTIL_VERSION_HEADER
 End of changes. 4 change blocks. 
1 lines changed or deleted 9 lines changed or added

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