action_type.h | action_type.h | |||
---|---|---|---|---|
skipping to change at line 51 | skipping to change at line 51 | |||
std::string toString() const; | std::string toString() const; | |||
// Takes the string representation of a single action type and retu rns the corresponding | // Takes the string representation of a single action type and retu rns the corresponding | |||
// 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 authCheck; | ||||
static const ActionType authenticate; | ||||
static const ActionType captrunc; | static const ActionType captrunc; | |||
static const ActionType clean; | static const ActionType clean; | |||
static const ActionType cleanupOrphaned; | ||||
static const ActionType clone; | static const ActionType clone; | |||
static const ActionType cloneCollectionLocalSource; | static const ActionType cloneCollectionLocalSource; | |||
static const ActionType cloneCollectionTarget; | 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; | |||
skipping to change at line 96 | skipping to change at line 99 | |||
static const ActionType indexRead; | static const ActionType indexRead; | |||
static const ActionType indexStats; | static const ActionType indexStats; | |||
static const ActionType inprog; | static const ActionType inprog; | |||
static const ActionType insert; | static const ActionType insert; | |||
static const ActionType killCursors; | static const ActionType killCursors; | |||
static const ActionType killop; | 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 mapReduceShardedFinish; | |||
static const ActionType mergeChunks; | ||||
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 profileEnable; | static const ActionType profileEnable; | |||
static const ActionType profileRead; | 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 renameCollectionSameDB; | static const ActionType renameCollectionSameDB; | |||
static const ActionType repairDatabase; | static const ActionType repairDatabase; | |||
skipping to change at line 117 | skipping to change at line 121 | |||
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 replSetUpdatePosition; | ||||
static const ActionType resync; | static const ActionType resync; | |||
static const ActionType serverStatus; | 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 storageDetails; | |||
static const ActionType top; | static const ActionType top; | |||
static const ActionType touch; | static const ActionType touch; | |||
static const ActionType unlock; | 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 userAdminV1; | ||||
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; | |||
enum ActionTypeIdentifier { | enum ActionTypeIdentifier { | |||
addShardValue, | addShardValue, | |||
authCheckValue, | ||||
authenticateValue, | ||||
captruncValue, | captruncValue, | |||
cleanValue, | cleanValue, | |||
cleanupOrphanedValue, | ||||
cloneValue, | cloneValue, | |||
cloneCollectionLocalSourceValue, | cloneCollectionLocalSourceValue, | |||
cloneCollectionTargetValue, | cloneCollectionTargetValue, | |||
closeAllDatabasesValue, | closeAllDatabasesValue, | |||
collModValue, | collModValue, | |||
collStatsValue, | collStatsValue, | |||
compactValue, | compactValue, | |||
connPoolStatsValue, | connPoolStatsValue, | |||
connPoolSyncValue, | connPoolSyncValue, | |||
convertToCappedValue, | convertToCappedValue, | |||
skipping to change at line 191 | skipping to change at line 200 | |||
indexReadValue, | indexReadValue, | |||
indexStatsValue, | indexStatsValue, | |||
inprogValue, | inprogValue, | |||
insertValue, | insertValue, | |||
killCursorsValue, | killCursorsValue, | |||
killopValue, | killopValue, | |||
listDatabasesValue, | listDatabasesValue, | |||
listShardsValue, | listShardsValue, | |||
logRotateValue, | logRotateValue, | |||
mapReduceShardedFinishValue, | mapReduceShardedFinishValue, | |||
mergeChunksValue, | ||||
moveChunkValue, | moveChunkValue, | |||
movePrimaryValue, | movePrimaryValue, | |||
netstatValue, | netstatValue, | |||
profileEnableValue, | profileEnableValue, | |||
profileReadValue, | profileReadValue, | |||
reIndexValue, | reIndexValue, | |||
removeValue, | removeValue, | |||
removeShardValue, | removeShardValue, | |||
renameCollectionSameDBValue, | renameCollectionSameDBValue, | |||
repairDatabaseValue, | repairDatabaseValue, | |||
skipping to change at line 212 | skipping to change at line 222 | |||
replSetFreezeValue, | replSetFreezeValue, | |||
replSetFreshValue, | replSetFreshValue, | |||
replSetGetRBIDValue, | replSetGetRBIDValue, | |||
replSetGetStatusValue, | replSetGetStatusValue, | |||
replSetHeartbeatValue, | replSetHeartbeatValue, | |||
replSetInitiateValue, | replSetInitiateValue, | |||
replSetMaintenanceValue, | replSetMaintenanceValue, | |||
replSetReconfigValue, | replSetReconfigValue, | |||
replSetStepDownValue, | replSetStepDownValue, | |||
replSetSyncFromValue, | replSetSyncFromValue, | |||
replSetUpdatePositionValue, | ||||
resyncValue, | resyncValue, | |||
serverStatusValue, | serverStatusValue, | |||
setParameterValue, | setParameterValue, | |||
setShardVersionValue, | setShardVersionValue, | |||
shardCollectionValue, | shardCollectionValue, | |||
shardingStateValue, | shardingStateValue, | |||
shutdownValue, | shutdownValue, | |||
splitValue, | splitValue, | |||
splitChunkValue, | splitChunkValue, | |||
splitVectorValue, | splitVectorValue, | |||
storageDetailsValue, | storageDetailsValue, | |||
topValue, | topValue, | |||
touchValue, | touchValue, | |||
unlockValue, | unlockValue, | |||
unsetShardingValue, | unsetShardingValue, | |||
updateValue, | updateValue, | |||
userAdminValue, | userAdminValue, | |||
userAdminV1Value, | ||||
validateValue, | validateValue, | |||
writebacklistenValue, | writebacklistenValue, | |||
writeBacksQueuedValue, | writeBacksQueuedValue, | |||
_migrateCloneValue, | _migrateCloneValue, | |||
_recvChunkAbortValue, | _recvChunkAbortValue, | |||
_recvChunkCommitValue, | _recvChunkCommitValue, | |||
_recvChunkStartValue, | _recvChunkStartValue, | |||
_recvChunkStatusValue, | _recvChunkStatusValue, | |||
_transferModsValue, | _transferModsValue, | |||
End of changes. 10 change blocks. | ||||
0 lines changed or deleted | 12 lines changed or added | |||
admin_access.h | admin_access.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 "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/auth/user_name.h" | ||||
namespace mongo { | namespace mongo { | |||
/* | /* | |||
* An AdminAccess is an interface class used to determine if certain us ers have | * An AdminAccess is an interface class used to determine if certain us ers have | |||
* privileges to a given resource. | * privileges to a given resource. | |||
* | * | |||
*/ | */ | |||
class AdminAccess { | class AdminAccess { | |||
public: | public: | |||
virtual ~AdminAccess() { } | virtual ~AdminAccess() { } | |||
/** @return if there are any priviledge users. This should not | /** @return if there are any priviledge users. This should not | |||
* block for long and throw if can't get a lock if needed. | * block for long and throw if can't get a lock if needed. | |||
*/ | */ | |||
virtual bool haveAdminUsers() const = 0; | virtual bool haveAdminUsers() const = 0; | |||
/** @return privileged user with this name. This should not block | /** @return privileged user with this name. This should not block | |||
* for long and throw if can't get a lock if needed | * for long and throw if can't get a lock if needed | |||
*/ | */ | |||
virtual BSONObj getAdminUser( const string& username ) const = 0; | virtual BSONObj getAdminUser(const UserName& username) const = 0; | |||
}; | }; | |||
class NoAdminAccess : public AdminAccess { | class NoAdminAccess : public AdminAccess { | |||
public: | public: | |||
virtual ~NoAdminAccess() { } | virtual ~NoAdminAccess() { } | |||
virtual bool haveAdminUsers() const { return false; } | virtual bool haveAdminUsers() const { return false; } | |||
virtual BSONObj getAdminUser( const string& username ) const { retu rn BSONObj(); } | virtual BSONObj getAdminUser(const UserName& username) const { retu rn BSONObj(); } | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 3 change blocks. | ||||
2 lines changed or deleted | 3 lines changed or added | |||
and_hash.h | and_hash.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 <boost/scoped_ptr.hpp> | #include <boost/scoped_ptr.hpp> | |||
#include <vector> | #include <vector> | |||
#include "mongo/db/diskloc.h" | #include "mongo/db/diskloc.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/matcher.h" | ||||
#include "mongo/db/exec/plan_stage.h" | #include "mongo/db/exec/plan_stage.h" | |||
#include "mongo/db/matcher/expression.h" | ||||
#include "mongo/platform/unordered_set.h" | #include "mongo/platform/unordered_set.h" | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* Reads from N children, each of which must have a valid DiskLoc. Use s a hash table to | * Reads from N children, each of which must have a valid DiskLoc. Use s a hash table to | |||
* intersect the outputs of the N children, and outputs the intersectio n. | * intersect the outputs of the N children, and outputs the intersectio n. | |||
* | * | |||
* Preconditions: Valid DiskLoc. More than one child. | * Preconditions: Valid DiskLoc. More than one child. | |||
* | * | |||
* Any DiskLoc that we keep a reference to that is invalidated before w e are able to return it | * Any DiskLoc that we keep a reference to that is invalidated before w e are able to return it | |||
* is fetched and added to the WorkingSet as "flagged for further revie w." Because this stage | * is fetched and added to the WorkingSet as "flagged for further revie w." Because this stage | |||
* operates with DiskLocs, we are unable to evaluate the AND for the in validated DiskLoc, and it | * operates with DiskLocs, we are unable to evaluate the AND for the in validated DiskLoc, and it | |||
* must be fully matched later. | * must be fully matched later. | |||
*/ | */ | |||
class AndHashStage : public PlanStage { | class AndHashStage : public PlanStage { | |||
public: | public: | |||
AndHashStage(WorkingSet* ws, Matcher* matcher); | AndHashStage(WorkingSet* ws, const MatchExpression* filter); | |||
virtual ~AndHashStage(); | virtual ~AndHashStage(); | |||
void addChild(PlanStage* child); | void addChild(PlanStage* child); | |||
virtual StageState work(WorkingSetID* out); | virtual StageState work(WorkingSetID* out); | |||
virtual bool isEOF(); | virtual bool isEOF(); | |||
virtual void prepareToYield(); | virtual void prepareToYield(); | |||
virtual void recoverFromYield(); | virtual void recoverFromYield(); | |||
virtual void invalidate(const DiskLoc& dl); | virtual void invalidate(const DiskLoc& dl); | |||
virtual PlanStageStats* getStats(); | ||||
private: | private: | |||
StageState readFirstChild(); | StageState readFirstChild(); | |||
StageState hashOtherChildren(); | StageState hashOtherChildren(); | |||
// Not owned by us. | // Not owned by us. | |||
WorkingSet* _ws; | WorkingSet* _ws; | |||
scoped_ptr<Matcher> _matcher; | ||||
// Not owned by us. | ||||
const MatchExpression* _filter; | ||||
// The stages we read from. Owned by us. | // The stages we read from. Owned by us. | |||
vector<PlanStage*> _children; | vector<PlanStage*> _children; | |||
// _dataMap is filled out by the first child and probed by subseque nt children. | // _dataMap is filled out by the first child and probed by subseque nt children. | |||
typedef unordered_map<DiskLoc, WorkingSetID, DiskLoc::Hasher> DataM ap; | typedef unordered_map<DiskLoc, WorkingSetID, DiskLoc::Hasher> DataM ap; | |||
DataMap _dataMap; | DataMap _dataMap; | |||
// Keeps track of what elements from _dataMap subsequent children h ave seen. | // Keeps track of what elements from _dataMap subsequent children h ave seen. | |||
typedef unordered_set<DiskLoc, DiskLoc::Hasher> SeenMap; | typedef unordered_set<DiskLoc, DiskLoc::Hasher> SeenMap; | |||
SeenMap _seenMap; | SeenMap _seenMap; | |||
// Iterator over the members of _dataMap that survive. | // Iterator over the members of _dataMap that survive. | |||
DataMap::iterator _resultIterator; | DataMap::iterator _resultIterator; | |||
// True if we're still scanning _children for results. | // True if we're still scanning _children for results. | |||
bool _shouldScanChildren; | bool _shouldScanChildren; | |||
// Which child are we currently working on? | // Which child are we currently working on? | |||
size_t _currentChild; | size_t _currentChild; | |||
// Stats | ||||
CommonStats _commonStats; | ||||
AndHashStats _specificStats; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 6 change blocks. | ||||
3 lines changed or deleted | 11 lines changed or added | |||
and_sorted.h | and_sorted.h | |||
---|---|---|---|---|
skipping to change at line 23 | skipping to change at line 23 | |||
* You should have received a copy of the GNU Affero General Public Lice nse | * You should have received a copy of the GNU Affero General Public Lice nse | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <queue> | #include <queue> | |||
#include <vector> | #include <vector> | |||
#include "mongo/db/diskloc.h" | #include "mongo/db/diskloc.h" | |||
#include "mongo/db/jsobj.h" | ||||
#include "mongo/db/matcher.h" | ||||
#include "mongo/db/exec/plan_stage.h" | #include "mongo/db/exec/plan_stage.h" | |||
#include "mongo/db/jsobj.h" | ||||
#include "mongo/db/matcher/expression.h" | ||||
#include "mongo/platform/unordered_set.h" | #include "mongo/platform/unordered_set.h" | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* Reads from N children, each of which must have a valid DiskLoc. Ass umes each child produces | * Reads from N children, each of which must have a valid DiskLoc. Ass umes each child produces | |||
* DiskLocs in sorted order. Outputs the intersection of the DiskLocs outputted by the | * DiskLocs in sorted order. Outputs the intersection of the DiskLocs outputted by the | |||
* children. | * children. | |||
* | * | |||
* Preconditions: Valid DiskLoc. More than one child. | * Preconditions: Valid DiskLoc. More than one child. | |||
* | * | |||
* Any DiskLoc that we keep a reference to that is invalidated before w e are able to return it | * Any DiskLoc that we keep a reference to that is invalidated before w e are able to return it | |||
* is fetched and added to the WorkingSet as "flagged for further revie w." Because this stage | * is fetched and added to the WorkingSet as "flagged for further revie w." Because this stage | |||
* operates with DiskLocs, we are unable to evaluate the AND for the in validated DiskLoc, and it | * operates with DiskLocs, we are unable to evaluate the AND for the in validated DiskLoc, and it | |||
* must be fully matched later. | * must be fully matched later. | |||
*/ | */ | |||
class AndSortedStage : public PlanStage { | class AndSortedStage : public PlanStage { | |||
public: | public: | |||
AndSortedStage(WorkingSet* ws, Matcher* matcher); | AndSortedStage(WorkingSet* ws, const MatchExpression* filter); | |||
virtual ~AndSortedStage(); | virtual ~AndSortedStage(); | |||
void addChild(PlanStage* child); | void addChild(PlanStage* child); | |||
virtual StageState work(WorkingSetID* out); | virtual StageState work(WorkingSetID* out); | |||
virtual bool isEOF(); | virtual bool isEOF(); | |||
virtual void prepareToYield(); | virtual void prepareToYield(); | |||
virtual void recoverFromYield(); | virtual void recoverFromYield(); | |||
virtual void invalidate(const DiskLoc& dl); | virtual void invalidate(const DiskLoc& dl); | |||
virtual PlanStageStats* getStats(); | ||||
private: | private: | |||
// Find a node to AND against. | // Find a node to AND against. | |||
PlanStage::StageState getTargetLoc(); | PlanStage::StageState getTargetLoc(); | |||
// Move a child which hasn't advanced to the target node forward. | // Move a child which hasn't advanced to the target node forward. | |||
// Returns the target node in 'out' if all children successfully ad vance to it. | // Returns the target node in 'out' if all children successfully ad vance to it. | |||
PlanStage::StageState moveTowardTargetLoc(WorkingSetID* out); | PlanStage::StageState moveTowardTargetLoc(WorkingSetID* out); | |||
// Not owned by us. | // Not owned by us. | |||
WorkingSet* _ws; | WorkingSet* _ws; | |||
scoped_ptr<Matcher> _matcher; | ||||
// Not owned by us. | ||||
const MatchExpression* _filter; | ||||
// Owned by us. | // Owned by us. | |||
vector<PlanStage*> _children; | vector<PlanStage*> _children; | |||
// The current node we're AND-ing against. | // The current node we're AND-ing against. | |||
PlanStage* _targetNode; | size_t _targetNode; | |||
DiskLoc _targetLoc; | DiskLoc _targetLoc; | |||
WorkingSetID _targetId; | WorkingSetID _targetId; | |||
// Nodes we're moving forward until they hit the element we're AND- ing. | // Nodes we're moving forward until they hit the element we're AND- ing. | |||
// Everything in here has not advanced to _targetLoc yet. | // Everything in here has not advanced to _targetLoc yet. | |||
std::queue<PlanStage*> _workingTowardRep; | // These are indices into _children. | |||
std::queue<size_t> _workingTowardRep; | ||||
// If any child hits EOF or if we have any errors, we're EOF. | // If any child hits EOF or if we have any errors, we're EOF. | |||
bool _isEOF; | bool _isEOF; | |||
// Stats | ||||
CommonStats _commonStats; | ||||
AndSortedStats _specificStats; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 8 change blocks. | ||||
6 lines changed or deleted | 15 lines changed or added | |||
assert_util.h | assert_util.h | |||
---|---|---|---|---|
skipping to change at line 203 | skipping to change at line 203 | |||
return (e && *e != "") ? causedBy(*e) : ""; | return (e && *e != "") ? causedBy(*e) : ""; | |||
} | } | |||
inline std::string causedBy( const Status& e ){ return causedBy( e.reas on() ); } | 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 { \ | inline void uassertStatusOK(const Status& status) { | |||
Status status = (expr); \ | if (MONGO_unlikely(!status.isOK())) { | |||
if (!status.isOK()) \ | uasserted((status.location() != 0 ? status.location() : status. | |||
uasserted(status.location() != 0 ? status.location() : status.c | code()), | |||
ode(), \ | status.reason()); | |||
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) ) | |||
skipping to change at line 245 | skipping to change at line 245 | |||
# define MONGO_debug_and(x) debugCompare(true, (x)) | # define MONGO_debug_and(x) debugCompare(true, (x)) | |||
#else | #else | |||
# define MONGO_debug_and(x) debugCompare(false, (x)) | # define MONGO_debug_and(x) debugCompare(false, (x)) | |||
#endif | #endif | |||
#ifdef MONGO_EXPOSE_MACROS | #ifdef MONGO_EXPOSE_MACROS | |||
# define dcompare MONGO_debug_and | # 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. 2 change blocks. | ||||
8 lines changed or deleted | 7 lines changed or added | |||
authentication_commands.h | authentication_commands.h | |||
---|---|---|---|---|
skipping to change at line 19 | skipping to change at line 19 | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Lice nse | * You should have received a copy of the GNU Affero General Public Lice nse | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <string> | ||||
#include "mongo/base/status.h" | ||||
#include "mongo/db/auth/user_name.h" | ||||
#include "mongo/db/commands.h" | #include "mongo/db/commands.h" | |||
namespace mongo { | namespace mongo { | |||
class CmdAuthenticate : public Command { | class CmdAuthenticate : public Command { | |||
public: | public: | |||
static void disableCommand(); | static void disableCommand(); | |||
virtual bool logTheOp() { | virtual bool logTheOp() { | |||
return false; | return false; | |||
} | } | |||
virtual bool slaveOk() const { | virtual bool slaveOk() const { | |||
return true; | return true; | |||
} | } | |||
virtual LockType locktype() const { return NONE; } | virtual LockType locktype() const { return NONE; } | |||
virtual void help(stringstream& ss) const { ss << "internal"; } | virtual void help(stringstream& ss) const { ss << "internal"; } | |||
virtual void addRequiredPrivileges(const std::string& dbname, | virtual void addRequiredPrivileges(const std::string& dbname, | |||
const BSONObj& cmdObj, | const BSONObj& cmdObj, | |||
std::vector<Privilege>* out) {} // No auth required | std::vector<Privilege>* out) {} // No auth required | |||
CmdAuthenticate() : Command("authenticate") {} | CmdAuthenticate() : Command("authenticate") {} | |||
bool run(const string& dbname , BSONObj& cmdObj, int options, strin | bool run(const string& dbname, | |||
g& errmsg, BSONObjBuilder& result, bool fromRepl); | BSONObj& cmdObj, | |||
int options, | ||||
string& errmsg, | ||||
BSONObjBuilder& result, | ||||
bool fromRepl); | ||||
private: | private: | |||
bool authenticateCR(const string& dbname, | /** | |||
BSONObj& cmdObj, | * Completes the authentication of "user" using "mechanism" and par | |||
string& errmsg, | ameters from "cmdObj". | |||
BSONObjBuilder& result); | * | |||
bool authenticateX509(const string& dbname, | * Returns Status::OK() on success. All other statuses indicate fa | |||
BSONObj& cmdObj, | iled authentication. The | |||
string& errmsg, | * entire status returned here may always be used for logging. How | |||
BSONObjBuilder& result); | ever, if the code is | |||
* AuthenticationFailed, the "reason" field of the return status ma | ||||
y contain information | ||||
* that should not be revealed to the connected client. | ||||
* | ||||
* Other than AuthenticationFailed, common returns are BadValue, in | ||||
dicating unsupported | ||||
* mechanism, and ProtocolError, indicating an error in the use of | ||||
the authentication | ||||
* protocol. | ||||
*/ | ||||
Status _authenticate(const std::string& mechanism, | ||||
const UserName& user, | ||||
const BSONObj& cmdObj); | ||||
Status _authenticateCR(const UserName& user, const BSONObj& cmdObj) | ||||
; | ||||
Status _authenticateX509(const UserName& user, const BSONObj& cmdOb | ||||
j); | ||||
}; | }; | |||
extern CmdAuthenticate cmdAuthenticate; | extern CmdAuthenticate cmdAuthenticate; | |||
} | } | |||
End of changes. 3 change blocks. | ||||
10 lines changed or deleted | 35 lines changed or added | |||
authorization_manager.h | authorization_manager.h | |||
---|---|---|---|---|
skipping to change at line 27 | skipping to change at line 27 | |||
#pragma once | #pragma once | |||
#include <boost/scoped_ptr.hpp> | #include <boost/scoped_ptr.hpp> | |||
#include <boost/thread/mutex.hpp> | #include <boost/thread/mutex.hpp> | |||
#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/db/auth/action_set.h" | #include "mongo/db/auth/action_set.h" | |||
#include "mongo/db/auth/authz_manager_external_state.h" | #include "mongo/db/auth/authz_manager_external_state.h" | |||
#include "mongo/db/auth/privilege_set.h" | ||||
#include "mongo/db/auth/user.h" | #include "mongo/db/auth/user.h" | |||
#include "mongo/db/auth/user_name.h" | #include "mongo/db/auth/user_name.h" | |||
#include "mongo/db/auth/user_name_hash.h" | #include "mongo/db/auth/user_name_hash.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/platform/unordered_map.h" | #include "mongo/platform/unordered_map.h" | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* Internal secret key info. | * Internal secret key info. | |||
*/ | */ | |||
struct AuthInfo { | struct AuthInfo { | |||
AuthInfo(); | User* user; | |||
std::string user; | ||||
std::string pwd; | ||||
BSONObj authParams; | BSONObj authParams; | |||
}; | }; | |||
extern AuthInfo internalSecurity; // set at startup and not changed aft er initialization. | extern AuthInfo internalSecurity; // set at startup and not changed aft er initialization. | |||
/** | /** | |||
* Contains server/cluster-wide information about Authorization. | * Contains server/cluster-wide information about Authorization. | |||
*/ | */ | |||
class AuthorizationManager { | class AuthorizationManager { | |||
MONGO_DISALLOW_COPYING(AuthorizationManager); | MONGO_DISALLOW_COPYING(AuthorizationManager); | |||
public: | public: | |||
// The newly constructed AuthorizationManager takes ownership of "e xternalState" | // The newly constructed AuthorizationManager takes ownership of "e xternalState" | |||
explicit AuthorizationManager(AuthzManagerExternalState* externalSt ate); | explicit AuthorizationManager(AuthzManagerExternalState* externalSt ate); | |||
~AuthorizationManager(); | ~AuthorizationManager(); | |||
static const std::string SERVER_RESOURCE_NAME; | static const std::string SERVER_RESOURCE_NAME; | |||
static const std::string CLUSTER_RESOURCE_NAME; | static const std::string CLUSTER_RESOURCE_NAME; | |||
static const std::string WILDCARD_RESOURCE_NAME; | ||||
static const std::string USER_NAME_FIELD_NAME; | static const std::string USER_NAME_FIELD_NAME; | |||
static const std::string USER_SOURCE_FIELD_NAME; | static const std::string USER_SOURCE_FIELD_NAME; | |||
static const std::string PASSWORD_FIELD_NAME; | static const std::string PASSWORD_FIELD_NAME; | |||
// TODO: Make the following functions no longer static. | // TODO: Make the following functions no longer static. | |||
/** | /** | |||
* Sets whether or not we allow old style (pre v2.4) privilege docu ments for this whole | * Sets whether or not we allow old style (pre v2.4) privilege docu ments for this whole | |||
* server. | * server. | |||
skipping to change at line 108 | skipping to change at line 106 | |||
// Returns true if there exists at least one privilege document in the given database. | // Returns true if there exists at least one privilege document in the given database. | |||
bool hasPrivilegeDocument(const std::string& dbname) const; | bool hasPrivilegeDocument(const std::string& dbname) const; | |||
// Creates the given user object in the given database. | // Creates the given user object in the given database. | |||
Status insertPrivilegeDocument(const std::string& dbname, const BSO NObj& userObj) const; | Status insertPrivilegeDocument(const std::string& dbname, const BSO NObj& userObj) const; | |||
// Updates the given user object with the given update modifier. | // Updates the given user object with the given update modifier. | |||
Status updatePrivilegeDocument(const UserName& user, const BSONObj& updateObj) const; | Status updatePrivilegeDocument(const UserName& user, const BSONObj& updateObj) const; | |||
// Removes users for the given database matching the given query. | ||||
Status removePrivilegeDocuments(const std::string& dbname, const BS | ||||
ONObj& query) const; | ||||
// Checks to see if "doc" is a valid privilege document, assuming i t is stored in the | // Checks to see if "doc" is a valid privilege document, assuming i t is stored in the | |||
// "system.users" collection of database "dbname". | // "system.users" collection of database "dbname". | |||
// | // | |||
// Returns Status::OK() if the document is good, or Status(ErrorCod es::BadValue), otherwise. | // Returns Status::OK() if the document is good, or Status(ErrorCod es::BadValue), otherwise. | |||
Status checkValidPrivilegeDocument(const StringData& dbname, const BSONObj& doc); | Status checkValidPrivilegeDocument(const StringData& dbname, const BSONObj& doc); | |||
// Parses the privilege document and returns a PrivilegeSet of all | ||||
the Privileges that | ||||
// the privilege document grants. | ||||
Status buildPrivilegeSet(const std::string& dbname, | ||||
const UserName& user, | ||||
const BSONObj& privilegeDocument, | ||||
PrivilegeSet* result) const; | ||||
// Given a database name and a readOnly flag return an ActionSet de scribing all the actions | // Given a database name and a readOnly flag return an ActionSet de scribing all the actions | |||
// that an old-style user with those attributes should be given. | // that an old-style user with those attributes should be given. | |||
ActionSet getActionsForOldStyleUser(const std::string& dbname, bool readOnly) const; | ActionSet getActionsForOldStyleUser(const std::string& dbname, bool readOnly) const; | |||
// Returns an ActionSet of all actions that can be be granted to us ers. This does not | // Returns an ActionSet of all actions that can be be granted to us ers. This does not | |||
// include internal-only actions. | // include internal-only actions. | |||
ActionSet getAllUserActions() const; | ActionSet getAllUserActions() const; | |||
/** | /** | |||
* Returns the User object for the given userName in the out param "acquiredUser". | * Returns the User object for the given userName in the out param eter "acquiredUser". | |||
* If the user cache already has a user object for this user, it i ncrements the refcount | * If the user cache already has a user object for this user, it i ncrements the refcount | |||
* on that object and gives out a pointer to it. If no user objec t for this user name | * on that object and gives out a pointer to it. If no user objec t for this user name | |||
* exists yet in the cache, reads the user's privilege document fr om disk, builds up | * exists yet in the cache, reads the user's privilege document fr om disk, builds up | |||
* a User object, sets the refcount to 1, and gives that out. | * a User object, sets the refcount to 1, and gives that out. The | |||
returned user may | ||||
* be invalid by the time the caller gets access to it. | ||||
* The AuthorizationManager retains ownership of the returned User object. | * The AuthorizationManager retains ownership of the returned User object. | |||
* On non-OK Status return values, acquiredUser will not be modifi ed. | * On non-OK Status return values, acquiredUser will not be modifi ed. | |||
*/ | */ | |||
Status acquireUser(const UserName& userName, User** acquiredUser); | Status acquireUser(const UserName& userName, User** acquiredUser); | |||
/** | /** | |||
* Decrements the refcount of the given User object. If the refcou nt has gone to zero, | * Decrements the refcount of the given User object. If the refcou nt has gone to zero, | |||
* deletes the User. Caller must stop using its pointer to "user" after calling this. | * deletes the User. Caller must stop using its pointer to "user" after calling this. | |||
*/ | */ | |||
void releaseUser(User* user); | void releaseUser(User* user); | |||
private: | /** | |||
* Marks the given user as invalid and removes it from the user cac | ||||
he. | ||||
*/ | ||||
void invalidateUser(User* user); | ||||
// Parses the old-style (pre 2.4) privilege document and returns a | /** | |||
PrivilegeSet of all the | * Inserts the given user directly into the _userCache. Used to ad | |||
// Privileges that the privilege document grants. | d the internalSecurity | |||
Status _buildPrivilegeSetFromOldStylePrivilegeDocument( | * user into the cache at process startup. | |||
const std::string& dbname, | */ | |||
const UserName& user, | void addInternalUser(User* user); | |||
const BSONObj& privilegeDocument, | ||||
PrivilegeSet* result) const ; | ||||
// Parses extended-form (2.4+) privilege documents and returns a Pr | /** | |||
ivilegeSet of all the | * Initializes the user cache with User objects for every v0 and v1 | |||
// privileges that the document grants. | user document in the | |||
// | * system, by reading the system.users collection of every database | |||
// The document, "privilegeDocument", is assumed to describe privil | . If this function | |||
eges for "principal", and | * returns a non-ok Status, the _userCache should be considered cor | |||
// to come from database "dbname". | rupt and must be | |||
Status _buildPrivilegeSetFromExtendedPrivilegeDocument( | * discarded. This function should be called once at startup (only | |||
const std::string& dbname, | if the system hasn't yet | |||
const UserName& user, | * been upgraded to V2 user data format) and never again after that | |||
const BSONObj& privilegeDocument, | . | |||
PrivilegeSet* result) const; | * TODO(spencer): This function will temporarily be called every ti | |||
me user data is changed | ||||
* as part of the transition period to the new User data structures | ||||
. This should be changed | ||||
* once we have all the code necessary to upgrade to the V2 user da | ||||
ta format, as at that | ||||
* point we'll only be able to user V1 user data as read-only. | ||||
*/ | ||||
Status initializeAllV1UserData(); | ||||
/** | /** | |||
* Parses privDoc and initializes the user object with the informat ion extracted from the | * Parses privDoc and initializes the user object with the informat ion extracted from the | |||
* privilege document. | * privilege document. | |||
* This should never be called from outside the AuthorizationManage | ||||
r - the only reason it's | ||||
* public instead of private is so it can be unit tested. | ||||
*/ | */ | |||
Status _initializeUserFromPrivilegeDocument(User* user, | Status _initializeUserFromPrivilegeDocument(User* user, | |||
const BSONObj& privDoc) const; | const BSONObj& privDoc) const; | |||
private: | ||||
/** | ||||
* Invalidates all User objects in the cache and removes them from | ||||
the cache. | ||||
* Should only be called when already holding _lock. | ||||
* TODO(spencer): This only exists because we're currently calling | ||||
initializeAllV1UserData | ||||
* every time user data is changed. Once we only call that once at | ||||
startup, this function | ||||
* should be removed. | ||||
*/ | ||||
void _invalidateUserCache_inlock(); | ||||
static bool _doesSupportOldStylePrivileges; | static bool _doesSupportOldStylePrivileges; | |||
// True if access control enforcement is enabled on this node (ie i t was started with | // True if access control enforcement is enabled on this node (ie i t was started with | |||
// --auth or --keyFile). | // --auth or --keyFile). | |||
// This is a config setting, set at startup and not changing after initialization. | // This is a config setting, set at startup and not changing after initialization. | |||
static bool _authEnabled; | static bool _authEnabled; | |||
// Integer that represents what format version the privilege docume nts in the system are. | // Integer that represents what format version the privilege docume nts in the system are. | |||
// The current version is 2. When upgrading to v2.6 or later from v2.4 or prior, the | // The current version is 2. When upgrading to v2.6 or later from v2.4 or prior, the | |||
// version is 1. After running the upgrade process to upgrade to t he new privilege document | // version is 1. After running the upgrade process to upgrade to t he new privilege document | |||
End of changes. 12 change blocks. | ||||
35 lines changed or deleted | 58 lines changed or added | |||
authorization_session.h | authorization_session.h | |||
---|---|---|---|---|
skipping to change at line 28 | skipping to change at line 28 | |||
#include <string> | #include <string> | |||
#include <vector> | #include <vector> | |||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/base/status.h" | #include "mongo/base/status.h" | |||
#include "mongo/db/auth/action_set.h" | #include "mongo/db/auth/action_set.h" | |||
#include "mongo/db/auth/action_type.h" | #include "mongo/db/auth/action_type.h" | |||
#include "mongo/db/auth/authorization_manager.h" | #include "mongo/db/auth/authorization_manager.h" | |||
#include "mongo/db/auth/authz_session_external_state.h" | #include "mongo/db/auth/authz_session_external_state.h" | |||
#include "mongo/db/auth/principal.h" | ||||
#include "mongo/db/auth/principal_set.h" | ||||
#include "mongo/db/auth/privilege.h" | #include "mongo/db/auth/privilege.h" | |||
#include "mongo/db/auth/privilege_set.h" | ||||
#include "mongo/db/auth/user_name.h" | #include "mongo/db/auth/user_name.h" | |||
#include "mongo/db/auth/user_set.h" | ||||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* 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 AuthorizationSession object is present within every mongo::Client object, therefore there | * An AuthorizationSession 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 AuthorizationSession { | class AuthorizationSession { | |||
MONGO_DISALLOW_COPYING(AuthorizationSession); | MONGO_DISALLOW_COPYING(AuthorizationSession); | |||
public: | public: | |||
// Takes ownership of the externalState. | // Takes ownership of the externalState. | |||
explicit AuthorizationSession(AuthzSessionExternalState* externalSt ate); | explicit AuthorizationSession(AuthzSessionExternalState* externalSt ate); | |||
~AuthorizationSession(); | ~AuthorizationSession(); | |||
const AuthorizationManager& getAuthorizationManager() const; | AuthorizationManager& getAuthorizationManager(); | |||
// Should be called at the beginning of every new request. This pe rforms the checks | // Should be called at the beginning of every new request. This pe rforms the checks | |||
// necessary to determine if localhost connections should be given full access. | // necessary to determine if localhost connections should be given full access. | |||
// TODO: try to eliminate the need for this call. | // TODO: try to eliminate the need for this call. | |||
void startRequest(); | void startRequest(); | |||
// Adds "principal" to the authorization manager, and takes ownersh | /** | |||
ip of it. | * Adds the User identified by "UserName" to the authorization sess | |||
void addAuthorizedPrincipal(Principal* principal); | ion, acquiring privileges | |||
* for it in the process. | ||||
*/ | ||||
Status addAndAuthorizeUser(const UserName& userName); | ||||
// Returns the authenticated principal with the given name. Return s NULL | // Returns the authenticated user with the given name. Returns NUL L | |||
// if no such user is found. | // if no such user is found. | |||
// Ownership of the returned Principal remains with _authenticatedP | // The user remains in the _authenticatedUsers set for this Authori | |||
rincipals | zationSession, | |||
Principal* lookupPrincipal(const UserName& name); | // and ownership of the user stays with the AuthorizationManager | |||
User* lookupUser(const UserName& name); | ||||
// Gets an iterator over the names of all authenticated principals | // Gets an iterator over the names of all authenticated users store | |||
stored in this manager. | d in this manager. | |||
PrincipalSet::NameIterator getAuthenticatedPrincipalNames(); | UserSet::NameIterator getAuthenticatedUserNames(); | |||
// Removes any authenticated principals whose authorization credent ials came from the given | // Removes any authenticated principals whose authorization credent ials came from the given | |||
// database, and revokes any privileges that were granted via that principal. | // database, and revokes any privileges that were granted via that principal. | |||
void logoutDatabase(const std::string& dbname); | void logoutDatabase(const std::string& dbname); | |||
// Grant this connection the given privilege. | // Adds the internalSecurity user to the set of authenticated users | |||
Status acquirePrivilege(const Privilege& privilege, | . | |||
const UserName& authorizingUser); | ||||
// Adds a new principal with the given username and authorizes it w | ||||
ith full access. | ||||
// Used to grant internal threads full access. | // Used to grant internal threads full access. | |||
void grantInternalAuthorization(const UserName& userName); | void grantInternalAuthorization(); | |||
// Checks if this connection has been authenticated as an internal user. | // Checks if this connection has been authenticated as an internal user. | |||
bool hasInternalAuthorization(); | 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. Returns true if the action may pr oceed on the resource. | // like the localhost exception. Returns true if the action may pr oceed on the resource. | |||
// Note: this may acquire a database read lock (for automatic privi lege acquisition). | // Note: this may acquire a database read lock (for automatic privi lege acquisition). | |||
bool checkAuthorization(const std::string& resource, ActionType act ion); | bool checkAuthorization(const std::string& resource, ActionType act ion); | |||
// Same as above but takes an ActionSet instead of a single ActionT ype. Returns true if | // Same as above but takes an ActionSet instead of a single ActionT ype. Returns true if | |||
// all of the actions may proceed on the resource. | // all of the actions may proceed on the resource. | |||
bool checkAuthorization(const std::string& resource, ActionSet acti ons); | 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 UserName& user, | ||||
const BSONObj& privil | ||||
egeDocument); | ||||
// Checks if this connection has the privileges necessary to perfor m the given query on the | // Checks if this connection has the privileges necessary to perfor m the given query on the | |||
// given namespace. | // given namespace. | |||
Status checkAuthForQuery(const std::string& ns, const BSONObj& quer y); | Status checkAuthForQuery(const std::string& ns, const BSONObj& quer y); | |||
// Checks if this connection has the privileges necessary to perfor m a getMore on the given | // Checks if this connection has the privileges necessary to perfor m a getMore on the given | |||
// cursor in the given namespace. | // cursor in the given namespace. | |||
Status checkAuthForGetMore(const std::string& ns, long long cursorI D); | Status checkAuthForGetMore(const std::string& ns, long long cursorI D); | |||
// Checks if this connection has the privileges necessary to perfor m the given update on the | // Checks if this connection has the privileges necessary to perfor m the given update on the | |||
// given namespace. | // given namespace. | |||
skipping to change at line 131 | skipping to change at line 123 | |||
// namespace. | // namespace. | |||
Status checkAuthForDelete(const std::string& ns, const BSONObj& que ry); | Status checkAuthForDelete(const std::string& ns, const BSONObj& que ry); | |||
// Checks if this connection is authorized for the given Privilege. | // Checks if this connection is authorized for the given Privilege. | |||
Status checkAuthForPrivilege(const Privilege& privilege); | Status checkAuthForPrivilege(const Privilege& privilege); | |||
// Checks if this connection is authorized for all the given Privil eges. | // Checks if this connection is authorized for all the given Privil eges. | |||
Status checkAuthForPrivileges(const vector<Privilege>& privileges); | Status checkAuthForPrivileges(const vector<Privilege>& privileges); | |||
private: | private: | |||
// Finds the set of privileges attributed to "principal" in databas | ||||
e "dbname", | // Checks if this connection is authorized for the given Privilege, | |||
// and adds them to the set of acquired privileges. | ignoring whether or not | |||
void _acquirePrivilegesForPrincipalFromDatabase(const std::string& | // we should even be doing authorization checks in general. | |||
dbname, | Status _checkAuthForPrivilegeHelper(const Privilege& privilege); | |||
const UserName& use | ||||
r); | ||||
// 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); | ||||
// Returns a new privilege that has replaced the actions needed to handle special casing | // Returns a new privilege that has replaced the actions needed to handle special casing | |||
// certain namespaces like system.users and system.profile. Note t hat the special handling | // certain namespaces like system.users and system.profile. Note t hat the special handling | |||
// of system.indexes takes place in checkAuthForInsert, not here. | // of system.indexes takes place in checkAuthForInsert, not here. | |||
Privilege _modifyPrivilegeForSpecialCases(const Privilege& privileg e); | Privilege _modifyPrivilegeForSpecialCases(const Privilege& privileg e); | |||
scoped_ptr<AuthzSessionExternalState> _externalState; | scoped_ptr<AuthzSessionExternalState> _externalState; | |||
// All the privileges that have been acquired by the authenticated | // All Users who have been authenticated on this connection | |||
principals. | UserSet _authenticatedUsers; | |||
PrivilegeSet _acquiredPrivileges; | ||||
// All principals who have been authenticated on this connection | ||||
PrincipalSet _authenticatedPrincipals; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 13 change blocks. | ||||
47 lines changed or deleted | 26 lines changed or added | |||
authz_manager_external_state.h | authz_manager_external_state.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/db/auth/user_name.h" | #include "mongo/db/auth/user_name.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* Public interface for a class that encapsulates all the information r elated to system | * Public interface for a class that encapsulates all the information r elated to system | |||
skipping to change at line 59 | skipping to change at line 60 | |||
bool hasPrivilegeDocument(const std::string& dbname) const; | bool hasPrivilegeDocument(const std::string& dbname) const; | |||
// Creates the given user object in the given database. | // Creates the given user object in the given database. | |||
virtual Status insertPrivilegeDocument(const std::string& dbname, | virtual Status insertPrivilegeDocument(const std::string& dbname, | |||
const BSONObj& userObj) cons t = 0; | const BSONObj& userObj) cons t = 0; | |||
// Updates the given user object with the given update modifier. | // Updates the given user object with the given update modifier. | |||
virtual Status updatePrivilegeDocument(const UserName& user, | virtual Status updatePrivilegeDocument(const UserName& user, | |||
const BSONObj& updateObj) co nst = 0; | const BSONObj& updateObj) co nst = 0; | |||
// Removes users for the given database matching the given query. | ||||
virtual Status removePrivilegeDocuments(const std::string& dbname, | ||||
const BSONObj& query) const | ||||
= 0; | ||||
/** | ||||
* Puts into the *dbnames vector the name of every database in the | ||||
cluster. | ||||
*/ | ||||
virtual Status getAllDatabaseNames(std::vector<std::string>* dbname | ||||
s) const = 0; | ||||
/** | ||||
* Puts into the *privDocs vector every privilege document from the | ||||
given database's | ||||
* system.users collection. | ||||
*/ | ||||
virtual Status getAllV1PrivilegeDocsForDB(const std::string& dbname | ||||
, | ||||
std::vector<BSONObj>* pri | ||||
vDocs) const = 0; | ||||
protected: | protected: | |||
AuthzManagerExternalState(); // This class should never be instanti ated directly. | AuthzManagerExternalState(); // This class should never be instanti ated directly. | |||
// Queries the userNamespace with the given query and returns the p rivilegeDocument found | // Queries the userNamespace with the given query and returns the p rivilegeDocument found | |||
// in *result. Returns true if it finds a document matching the qu | // in *result. Returns Status::OK if it finds a document matching | |||
ery, or false if not. | the query. If it doesn't | |||
virtual bool _findUser(const std::string& usersNamespace, | // find a document matching the query, returns a Status with code U | |||
const BSONObj& query, | serNotFound. Other | |||
BSONObj* result) const = 0; | // errors may return other Status codes. | |||
virtual Status _findUser(const std::string& usersNamespace, | ||||
const BSONObj& query, | ||||
BSONObj* result) const = 0; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 3 change blocks. | ||||
5 lines changed or deleted | 31 lines changed or added | |||
authz_manager_external_state_d.h | authz_manager_external_state_d.h | |||
---|---|---|---|---|
skipping to change at line 44 | skipping to change at line 44 | |||
public: | public: | |||
AuthzManagerExternalStateMongod(); | AuthzManagerExternalStateMongod(); | |||
virtual ~AuthzManagerExternalStateMongod(); | virtual ~AuthzManagerExternalStateMongod(); | |||
virtual Status insertPrivilegeDocument(const std::string& dbname, | virtual Status insertPrivilegeDocument(const std::string& dbname, | |||
const BSONObj& userObj) cons t; | const BSONObj& userObj) cons t; | |||
virtual Status updatePrivilegeDocument(const UserName& user, | virtual Status updatePrivilegeDocument(const UserName& user, | |||
const BSONObj& updateObj) co nst; | const BSONObj& updateObj) co nst; | |||
virtual Status removePrivilegeDocuments(const std::string& dbname, | ||||
const BSONObj& query) const | ||||
; | ||||
virtual Status getAllDatabaseNames(std::vector<std::string>* dbname | ||||
s) const; | ||||
virtual Status getAllV1PrivilegeDocsForDB(const std::string& dbname | ||||
, | ||||
std::vector<BSONObj>* pri | ||||
vDocs) const; | ||||
protected: | protected: | |||
virtual bool _findUser(const string& usersNamespace, | virtual Status _findUser(const string& usersNamespace, | |||
const BSONObj& query, | const BSONObj& query, | |||
BSONObj* result) const; | BSONObj* result) const; | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 2 change blocks. | ||||
3 lines changed or deleted | 15 lines changed or added | |||
authz_manager_external_state_mock.h | authz_manager_external_state_mock.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/db/auth/authz_manager_external_state.h" | #include "mongo/db/auth/authz_manager_external_state.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/platform/unordered_map.h" | #include "mongo/platform/unordered_map.h" | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
skipping to change at line 47 | skipping to change at line 48 | |||
AuthzManagerExternalStateMock() {}; | AuthzManagerExternalStateMock() {}; | |||
// no-op for the mock | // no-op for the mock | |||
virtual Status insertPrivilegeDocument(const std::string& dbname, | virtual Status insertPrivilegeDocument(const std::string& dbname, | |||
const BSONObj& userObj) cons t; | const BSONObj& userObj) cons t; | |||
// no-op for the mock | // no-op for the mock | |||
virtual Status updatePrivilegeDocument(const UserName& user, | virtual Status updatePrivilegeDocument(const UserName& user, | |||
const BSONObj& updateObj) co nst; | const BSONObj& updateObj) co nst; | |||
// no-op for the mock | ||||
virtual Status removePrivilegeDocuments(const std::string& dbname, | ||||
const BSONObj& query) const | ||||
; | ||||
// Non-const version that puts document into a vector that can be a ccessed later | // Non-const version that puts document into a vector that can be a ccessed later | |||
Status insertPrivilegeDocument(const std::string& dbname, const BSO NObj& userObj); | Status insertPrivilegeDocument(const std::string& dbname, const BSO NObj& userObj); | |||
void clearPrivilegeDocuments(); | void clearPrivilegeDocuments(); | |||
virtual bool _findUser(const std::string& usersNamespace, | virtual Status getAllDatabaseNames(std::vector<std::string>* dbname | |||
const BSONObj& query, | s) const; | |||
BSONObj* result) const; | ||||
virtual Status getAllV1PrivilegeDocsForDB(const std::string& dbname | ||||
, | ||||
std::vector<BSONObj>* pri | ||||
vDocs) const; | ||||
virtual Status _findUser(const std::string& usersNamespace, | ||||
const BSONObj& query, | ||||
BSONObj* result) const; | ||||
private: | private: | |||
unordered_map<std::string, BSONObj> _userDocuments; // dbname to us er document | unordered_map<std::string, std::vector<BSONObj> > _userDocuments; / / dbname to user docs | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 4 change blocks. | ||||
4 lines changed or deleted | 18 lines changed or added | |||
authz_manager_external_state_s.h | authz_manager_external_state_s.h | |||
---|---|---|---|---|
skipping to change at line 44 | skipping to change at line 44 | |||
public: | public: | |||
AuthzManagerExternalStateMongos(); | AuthzManagerExternalStateMongos(); | |||
virtual ~AuthzManagerExternalStateMongos(); | virtual ~AuthzManagerExternalStateMongos(); | |||
virtual Status insertPrivilegeDocument(const std::string& dbname, | virtual Status insertPrivilegeDocument(const std::string& dbname, | |||
const BSONObj& userObj) cons t; | const BSONObj& userObj) cons t; | |||
virtual Status updatePrivilegeDocument(const UserName& user, | virtual Status updatePrivilegeDocument(const UserName& user, | |||
const BSONObj& updateObj) co nst; | const BSONObj& updateObj) co nst; | |||
virtual Status removePrivilegeDocuments(const std::string& dbname, | ||||
const BSONObj& query) const | ||||
; | ||||
virtual Status getAllDatabaseNames(std::vector<std::string>* dbname | ||||
s) const; | ||||
virtual Status getAllV1PrivilegeDocsForDB(const std::string& dbname | ||||
, | ||||
std::vector<BSONObj>* pri | ||||
vDocs) const; | ||||
protected: | protected: | |||
virtual bool _findUser(const string& usersNamespace, | virtual Status _findUser(const string& usersNamespace, | |||
const BSONObj& query, | const BSONObj& query, | |||
BSONObj* result) const; | BSONObj* result) const; | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 2 change blocks. | ||||
3 lines changed or deleted | 15 lines changed or added | |||
authz_session_external_state.h | authz_session_external_state.h | |||
---|---|---|---|---|
skipping to change at line 43 | skipping to change at line 43 | |||
* state not stored in AuthorizationSession. This is primarily to make AuthorizationSession | * state not stored in AuthorizationSession. This is primarily to make AuthorizationSession | |||
* easier to test as well as to allow different implementations in mong os and mongod. | * easier to test as well as to allow different implementations in mong os and mongod. | |||
*/ | */ | |||
class AuthzSessionExternalState { | class AuthzSessionExternalState { | |||
MONGO_DISALLOW_COPYING(AuthzSessionExternalState); | MONGO_DISALLOW_COPYING(AuthzSessionExternalState); | |||
public: | public: | |||
virtual ~AuthzSessionExternalState(); | virtual ~AuthzSessionExternalState(); | |||
const AuthorizationManager& getAuthorizationManager() const; | AuthorizationManager& getAuthorizationManager(); | |||
// 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 d there are no admin | // are that auth isn't enabled, the connection is from localhost an d there are no admin | |||
// users, 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 | // NOTE: _checkShouldAllowLocalhost MUST be called at least once be fore any call to | |||
// shouldIgnoreAuthChecks or we could ignore auth checks incorrectl y. | // shouldIgnoreAuthChecks or we could ignore auth checks incorrectl y. | |||
virtual bool shouldIgnoreAuthChecks() const = 0; | virtual bool shouldIgnoreAuthChecks() const = 0; | |||
// Should be called at the beginning of every new request. This pe rforms the checks | // Should be called at the beginning of every new request. This pe rforms the checks | |||
// necessary to determine if localhost connections should be given full access. | // necessary to determine if localhost connections should be given full access. | |||
virtual void startRequest() = 0; | virtual void startRequest() = 0; | |||
// Authorization event hooks | // Authorization event hooks | |||
// Handle any global state which needs to be updated when a new use r has been authorized | // Handle any global state which needs to be updated when a new use r has been authorized | |||
virtual void onAddAuthorizedPrincipal(Principal*) = 0; | virtual void onAddAuthorizedUser() = 0; | |||
// Handle any global state which needs to be updated when a user lo gs out | // Handle any global state which needs to be updated when a user lo gs out | |||
virtual void onLogoutDatabase(const std::string& dbname) = 0; | virtual void onLogoutDatabase(const std::string& dbname) = 0; | |||
protected: | protected: | |||
// This class should never be instantiated directly. | // This class should never be instantiated directly. | |||
AuthzSessionExternalState(AuthorizationManager* authzManager); | AuthzSessionExternalState(AuthorizationManager* authzManager); | |||
AuthorizationManager* _authzManager; | AuthorizationManager* _authzManager; | |||
}; | }; | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
authz_session_external_state_d.h | authz_session_external_state_d.h | |||
---|---|---|---|---|
skipping to change at line 40 | skipping to change at line 40 | |||
MONGO_DISALLOW_COPYING(AuthzSessionExternalStateMongod); | MONGO_DISALLOW_COPYING(AuthzSessionExternalStateMongod); | |||
public: | public: | |||
AuthzSessionExternalStateMongod(AuthorizationManager* authzManager) ; | AuthzSessionExternalStateMongod(AuthorizationManager* authzManager) ; | |||
virtual ~AuthzSessionExternalStateMongod(); | virtual ~AuthzSessionExternalStateMongod(); | |||
virtual bool shouldIgnoreAuthChecks() const; | virtual bool shouldIgnoreAuthChecks() const; | |||
virtual void startRequest(); | virtual void startRequest(); | |||
virtual void onAddAuthorizedPrincipal(Principal*); | virtual void onAddAuthorizedUser(); | |||
virtual void onLogoutDatabase(const std::string&); | virtual void onLogoutDatabase(const std::string&); | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
authz_session_external_state_mock.h | authz_session_external_state_mock.h | |||
---|---|---|---|---|
skipping to change at line 44 | skipping to change at line 44 | |||
AuthzSessionExternalState(authzManager), _returnValue(false) {} | AuthzSessionExternalState(authzManager), _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; | |||
} | } | |||
virtual bool _findUser(const std::string& usersNamespace, | virtual Status _findUser(const std::string& usersNamespace, | |||
const BSONObj& query, | const BSONObj& query, | |||
BSONObj* result) const { | BSONObj* result) const { | |||
return false; | return Status(ErrorCodes::UserNotFound, "User not found"); | |||
} | } | |||
virtual void startRequest() {} | virtual void startRequest() {} | |||
virtual void onAddAuthorizedPrincipal(Principal*) {} | virtual void onAddAuthorizedUser() {} | |||
virtual void onLogoutDatabase(const std::string& dbname) {} | virtual void onLogoutDatabase(const std::string& dbname) {} | |||
private: | private: | |||
bool _returnValue; | bool _returnValue; | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 2 change blocks. | ||||
5 lines changed or deleted | 5 lines changed or added | |||
authz_session_external_state_s.h | authz_session_external_state_s.h | |||
---|---|---|---|---|
skipping to change at line 38 | skipping to change at line 38 | |||
*/ | */ | |||
class AuthzSessionExternalStateMongos : public AuthzSessionExternalStat eServerCommon { | class AuthzSessionExternalStateMongos : public AuthzSessionExternalStat eServerCommon { | |||
MONGO_DISALLOW_COPYING(AuthzSessionExternalStateMongos); | MONGO_DISALLOW_COPYING(AuthzSessionExternalStateMongos); | |||
public: | public: | |||
AuthzSessionExternalStateMongos(AuthorizationManager* authzManager) ; | AuthzSessionExternalStateMongos(AuthorizationManager* authzManager) ; | |||
virtual ~AuthzSessionExternalStateMongos(); | virtual ~AuthzSessionExternalStateMongos(); | |||
virtual void startRequest(); | virtual void startRequest(); | |||
virtual void onAddAuthorizedPrincipal(Principal*); | virtual void onAddAuthorizedUser(); | |||
virtual void onLogoutDatabase(const std::string&); | virtual void onLogoutDatabase(const std::string&); | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
bgsync.h | bgsync.h | |||
---|---|---|---|---|
skipping to change at line 88 | skipping to change at line 88 | |||
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; | |||
OplogReader _oplogMarker; // not locked, only used by notifier thre ad | ||||
OpTime _consumedOpTime; // not locked, only used by notifier thread | OpTime _consumedOpTime; // not locked, only used by notifier thread | |||
BackgroundSync(); | BackgroundSync(); | |||
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(); | |||
skipping to change at line 116 | skipping to change at line 115 | |||
// 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(); | |||
// Sets _oplogMarkerTarget and calls connect(); | ||||
// used for both the notifier command and the older OplogReader sty | ||||
le notifier | ||||
bool connectOplogNotifier(); | ||||
bool isAssumingPrimary(); | 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 | |||
End of changes. 2 change blocks. | ||||
1 lines changed or deleted | 5 lines changed or added | |||
bson_db.h | bson_db.h | |||
---|---|---|---|---|
skipping to change at line 29 | skipping to change at line 29 | |||
This file contains the implementation of BSON-related methods that are required | This file contains the implementation of BSON-related methods that are required | |||
by the MongoDB database server. | by the MongoDB database server. | |||
Normally, for standalone BSON usage, you do not want this file - it wil l tend to | Normally, for standalone BSON usage, you do not want this file - it wil l tend to | |||
pull in some other files from the MongoDB project. Thus, bson.h (the ma in file | pull in some other files from the MongoDB project. Thus, bson.h (the ma in file | |||
one would use) does not include this file. | one would use) does not include this file. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/db/repl/optime.h" | #include "mongo/bson/optime.h" | |||
#include "../util/time_support.h" | #include "mongo/util/time_support.h" | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
Timestamps are a special BSON datatype that is used internally for repl ication. | Timestamps are a special BSON datatype that is used internally for repl ication. | |||
Append a timestamp element to the object being ebuilt. | Append a timestamp element to the object being ebuilt. | |||
@param time - in millis (but stored in seconds) | @param time - in millis (but stored in seconds) | |||
*/ | */ | |||
inline BSONObjBuilder& BSONObjBuilder::appendTimestamp( const StringDat a& fieldName , unsigned long long time , unsigned int inc ) { | inline BSONObjBuilder& BSONObjBuilder::appendTimestamp( const StringDat a& fieldName , unsigned long long time , unsigned int inc ) { | |||
OpTime t( (unsigned) (time / 1000) , inc ); | OpTime t( (unsigned) (time / 1000) , inc ); | |||
End of changes. 1 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
bsonelement.h | bsonelement.h | |||
---|---|---|---|---|
skipping to change at line 67 | skipping to change at line 67 | |||
value() | value() | |||
type() | type() | |||
*/ | */ | |||
class BSONElement { | class BSONElement { | |||
public: | public: | |||
/** These functions, which start with a capital letter, throw a Msg AssertionException if the | /** These functions, which start with a capital letter, throw a Msg AssertionException if the | |||
element is not of the required type. Example: | element is not of the required type. Example: | |||
std::string foo = obj["foo"].String(); // std::exception if not a std::string type or DNE | std::string foo = obj["foo"].String(); // std::exception if not a std::string type or DNE | |||
*/ | */ | |||
std::string String() const { return chk(mongo::String).value str(); } | std::string String() const { return chk(mongo::String).str() ; } | |||
Date_t Date() const { return chk(mongo::Date).date(); } | Date_t Date() const { return chk(mongo::Date).date(); } | |||
double Number() const { return chk(isNumber()).number() ; } | double Number() const { return chk(isNumber()).number() ; } | |||
double Double() const { return chk(NumberDouble)._numbe rDouble(); } | double Double() const { return chk(NumberDouble)._numbe rDouble(); } | |||
long long Long() const { return chk(NumberLong)._numberL ong(); } | long long Long() const { return chk(NumberLong)._numberL ong(); } | |||
int Int() const { return chk(NumberInt)._numberIn t(); } | int Int() const { return chk(NumberInt)._numberIn t(); } | |||
bool Bool() const { return chk(mongo::Bool).boolean (); } | bool Bool() const { return chk(mongo::Bool).boolean (); } | |||
std::vector<BSONElement> Array() const; // see implementation for d etailed comments | std::vector<BSONElement> Array() const; // see implementation for d etailed comments | |||
mongo::OID OID() const { return chk(jstOID).__oid(); } | mongo::OID OID() const { return chk(jstOID).__oid(); } | |||
void Null() const { chk(isNull()); } // throw MsgAs sertionException if not null | void Null() const { chk(isNull()); } // throw MsgAs sertionException if not null | |||
void OK() const { chk(ok()); } // throw MsgAs sertionException if element DNE | void OK() const { chk(ok()); } // throw MsgAs sertionException if element DNE | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
bsonobj.h | bsonobj.h | |||
---|---|---|---|---|
skipping to change at line 276 | skipping to change at line 276 | |||
/** @return the raw data of the object */ | /** @return the raw data of the object */ | |||
const char *objdata() const { | const char *objdata() const { | |||
return _objdata; | return _objdata; | |||
} | } | |||
/** @return total size of the BSON object in bytes */ | /** @return total size of the BSON object in bytes */ | |||
int objsize() const { return *(reinterpret_cast<const int*>(objdata ())); } | int objsize() const { return *(reinterpret_cast<const int*>(objdata ())); } | |||
/** performs a cursory check on the object's size only. */ | /** performs a cursory check on the object's size only. */ | |||
bool isValid() const; | bool isValid() const; | |||
/** @return if the user is a valid user doc | /** @return ok if it can be stored as a valid embedded doc. | |||
criter: isValid() no . or $ field names | * Not valid if any field name: | |||
* - contains a "." | ||||
* - starts with "$" | ||||
* -- unless it is a dbref ($ref/$id/[$db]/...) | ||||
*/ | */ | |||
bool okForStorage() const; | inline bool okForStorage() const { | |||
return _okForStorage(false); | ||||
} | ||||
/** Same as above with the following extra restrictions | ||||
* Not valid if: | ||||
* - "_id" field is a | ||||
* -- Regex | ||||
* -- Array | ||||
*/ | ||||
inline bool okForStorageAsRoot() const { | ||||
return _okForStorage(true); | ||||
} | ||||
/** @return true if object is empty -- i.e., {} */ | /** @return true if object is empty -- i.e., {} */ | |||
bool isEmpty() const { return objsize() <= 5; } | bool isEmpty() const { return objsize() <= 5; } | |||
void dump() const; | void dump() const; | |||
/** Alternative output format */ | /** Alternative output format */ | |||
std::string hexDump() const; | std::string hexDump() const; | |||
/**wo='well ordered'. fields must be in same order in each object. | /**wo='well ordered'. fields must be in same order in each object. | |||
skipping to change at line 530 | skipping to change at line 545 | |||
void init(Holder *holder) { | void init(Holder *holder) { | |||
_holder = holder; // holder is now managed by intrusive_ptr | _holder = holder; // holder is now managed by intrusive_ptr | |||
init(holder->data); | init(holder->data); | |||
} | } | |||
void init(const char *data) { | void init(const char *data) { | |||
_objdata = data; | _objdata = data; | |||
if ( !isValid() ) | if ( !isValid() ) | |||
_assertInvalid(); | _assertInvalid(); | |||
} | } | |||
bool _okForStorage(bool root) const; | ||||
}; | }; | |||
std::ostream& operator<<( std::ostream &s, const BSONObj &o ); | std::ostream& operator<<( std::ostream &s, const BSONObj &o ); | |||
std::ostream& operator<<( std::ostream &s, const BSONElement &e ); | std::ostream& operator<<( std::ostream &s, const BSONElement &e ); | |||
StringBuilder& operator<<( StringBuilder &s, const BSONObj &o ); | StringBuilder& operator<<( StringBuilder &s, const BSONObj &o ); | |||
StringBuilder& operator<<( StringBuilder &s, const BSONElement &e ); | StringBuilder& operator<<( StringBuilder &s, const BSONElement &e ); | |||
struct BSONArray : BSONObj { | struct BSONArray : BSONObj { | |||
// Don't add anything other than forwarding constructors!!! | // Don't add anything other than forwarding constructors!!! | |||
End of changes. 3 change blocks. | ||||
3 lines changed or deleted | 20 lines changed or added | |||
btree.h | btree.h | |||
---|---|---|---|---|
skipping to change at line 194 | skipping to change at line 194 | |||
// A sentinel value sometimes used to identify a deallocated bucket . | // A sentinel value sometimes used to identify a deallocated bucket . | |||
static const int INVALID_N_SENTINEL = -1; | static const int INVALID_N_SENTINEL = -1; | |||
}; | }; | |||
// a a a ofs ofs ofs ofs | // a a a ofs ofs ofs ofs | |||
class DiskLoc56Bit { | class DiskLoc56Bit { | |||
int ofs; | int ofs; | |||
unsigned char _a[3]; | unsigned char _a[3]; | |||
unsigned long long Z() const { | unsigned long long Z() const { | |||
// endian | // endian | |||
return *((unsigned long long*)this) & 0x00ffffffffffffffULL; | unsigned long long result = ofs; | |||
char* cursor = reinterpret_cast<char *>(&result); | ||||
*reinterpret_cast<uint16_t*>(cursor + 4) = *reinterpret_cast<co | ||||
nst uint16_t*>(&_a[0]); | ||||
*reinterpret_cast<uint8_t*>(cursor + 6) = *reinterpret_cast<con | ||||
st uint8_t*>(&_a[2]); | ||||
*reinterpret_cast<uint8_t*>(cursor + 7) = uint8_t(0); | ||||
return result; | ||||
} | } | |||
enum { | enum { | |||
// first bit of offsets used in _KeyNode we don't use -1 here. | // first bit of offsets used in _KeyNode we don't use -1 here. | |||
OurNullOfs = -2 | OurNullOfs = -2 | |||
}; | }; | |||
public: | public: | |||
template< class V > | template< class V > | |||
const BtreeBucket<V> * btree() const { | const BtreeBucket<V> * btree() const { | |||
return DiskLoc(*this).btree<V>(); | return DiskLoc(*this).btree<V>(); | |||
} | } | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 8 lines changed or added | |||
btree_stats.h | btree_stats.h | |||
---|---|---|---|---|
skipping to change at line 23 | skipping to change at line 23 | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Licen se | * You should have received a copy of the GNU Affero General Public Licen se | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/db/commands/server_status.h" | #include "mongo/db/commands/server_status.h" | |||
#include "mongo/db/pdfile.h" | #include "mongo/db/pdfile.h" | |||
#include "mongo/db/record.h" | #include "mongo/db/storage/record.h" | |||
#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; } | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
btreebuilder.h | btreebuilder.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 "btree.h" | #include "mongo/db/btree.h" | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* build btree from the bottom up | * build btree from the bottom up | |||
*/ | */ | |||
template< class V > | template< class V > | |||
class BtreeBuilder { | class BtreeBuilder { | |||
typedef typename V::KeyOwned KeyOwned; | typedef typename V::KeyOwned KeyOwned; | |||
typedef typename V::Key Key; | typedef typename V::Key Key; | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
btreecursor.h | btreecursor.h | |||
---|---|---|---|---|
// DEPRECATED | ||||
/** | /** | |||
* 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 | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
chunk_version.h | chunk_version.h | |||
---|---|---|---|---|
skipping to change at line 271 | skipping to change at line 271 | |||
bool* canParse ) | bool* canParse ) | |||
{ | { | |||
*canParse = false; | *canParse = false; | |||
ChunkVersion version; | ChunkVersion version; | |||
BSONObjIterator it( arr ); | BSONObjIterator it( arr ); | |||
if( ! it.more() ) return version; | if( ! it.more() ) return version; | |||
version = fromBSON( it.next(), "", canParse ); | version = fromBSON( it.next(), "", canParse ); | |||
if( ! canParse ) return version; | if( ! (*canParse) ) return version; | |||
*canParse = true; | *canParse = true; | |||
if( ! it.more() ) return version; | if( ! it.more() ) return version; | |||
BSONElement next = it.next(); | BSONElement next = it.next(); | |||
if( next.type() != jstOID ) return version; | if( next.type() != jstOID ) return version; | |||
version._epoch = next.OID(); | version._epoch = next.OID(); | |||
return version; | return version; | |||
} | } | |||
enum VersionChoice { | ||||
VersionChoice_Local, | ||||
VersionChoice_Remote, | ||||
VersionChoice_Unknown | ||||
}; | ||||
/** | ||||
* Compares a remotely-loaded version 'remoteVersion' to the latest | ||||
local version of a | ||||
* collection, 'localVersion', and returns the newest. | ||||
* | ||||
* Because it isn't clear during epoch changes which epoch is newer | ||||
, the local version | ||||
* before the reload occurred, 'prevLocalVersion', is used to deter | ||||
mine whether the remote | ||||
* epoch is definitely newer, or we're not sure. | ||||
*/ | ||||
static VersionChoice chooseNewestVersion( ChunkVersion prevLocalVer | ||||
sion, | ||||
ChunkVersion localVersion | ||||
, | ||||
ChunkVersion remoteVersio | ||||
n ) | ||||
{ | ||||
OID prevEpoch = prevLocalVersion.epoch(); | ||||
OID localEpoch = localVersion.epoch(); | ||||
OID remoteEpoch = remoteVersion.epoch(); | ||||
// Everything changed in-flight, so we need to try again | ||||
if ( prevEpoch != localEpoch && localEpoch != remoteEpoch ) { | ||||
return VersionChoice_Unknown; | ||||
} | ||||
// We're in the same (zero) epoch as the latest metadata, nothi | ||||
ng to do | ||||
if ( localEpoch == remoteEpoch && !remoteEpoch.isSet() ) { | ||||
return VersionChoice_Local; | ||||
} | ||||
// We're in the same (non-zero) epoch as the latest metadata, s | ||||
o increment the version | ||||
if ( localEpoch == remoteEpoch && remoteEpoch.isSet() ) { | ||||
// Use the newer version if possible | ||||
if ( localVersion < remoteVersion ) { | ||||
return VersionChoice_Remote; | ||||
} | ||||
else { | ||||
return VersionChoice_Local; | ||||
} | ||||
} | ||||
// We're now sure we're installing a new epoch and the epoch di | ||||
dn't change during reload | ||||
dassert( prevEpoch == localEpoch && localEpoch != remoteEpoch ) | ||||
; | ||||
return VersionChoice_Remote; | ||||
} | ||||
// | // | |||
// Currently our BSON output is to two different fields, to cleanly work with older | // Currently our BSON output is to two different fields, to cleanly work with older | |||
// versions that know nothing about epochs. | // versions that know nothing about epochs. | |||
// | // | |||
BSONObj toBSON( const string& prefixIn="" ) const { | BSONObj toBSON( const string& prefixIn="" ) const { | |||
BSONObjBuilder b; | BSONObjBuilder b; | |||
string prefix = prefixIn; | string prefix = prefixIn; | |||
if( prefix == "" ) prefix = "version"; | if( prefix == "" ) prefix = "version"; | |||
End of changes. 2 change blocks. | ||||
1 lines changed or deleted | 60 lines changed or added | |||
clientcursor.h | clientcursor.h | |||
---|---|---|---|---|
/* clientcursor.h */ | ||||
/** | /** | |||
* Copyright (C) 2008 10gen Inc. | * Copyright (C) 2008 10gen Inc. | |||
* | * | |||
* This program is free software: you can redistribute it and/or modify | * This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3 | * it under the terms of the GNU Affero General Public License, version | |||
, | 3, | |||
* as published by the Free Software Foundation. | * as published by the Free Software Foundation. | |||
* | * | |||
* This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Licen | * You should have received a copy of the GNU Affero General Public Lice | |||
se | nse | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
/* Cursor -- and its derived classes -- are our internal cursors. | ||||
ClientCursor is a wrapper that represents a cursorid from our database | ||||
application's perspective. | ||||
*/ | ||||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/pch.h" | |||
#include <boost/thread/recursive_mutex.hpp> | #include <boost/thread/recursive_mutex.hpp> | |||
#include "cursor.h" | #include "mongo/db/cc_by_loc.h" | |||
#include "jsobj.h" | #include "mongo/db/cursor.h" | |||
#include "../util/net/message.h" | #include "mongo/db/diskloc.h" | |||
#include "../util/background.h" | #include "mongo/db/dbhelpers.h" | |||
#include "cc_by_loc.h" | #include "mongo/db/jsobj.h" | |||
#include "diskloc.h" | ||||
#include "dbhelpers.h" | ||||
#include "matcher.h" | ||||
#include "projection.h" | ||||
#include "mongo/db/keypattern.h" | #include "mongo/db/keypattern.h" | |||
#include "mongo/db/matcher.h" | ||||
#include "mongo/db/projection.h" | ||||
#include "mongo/db/query/runner.h" | ||||
#include "mongo/s/collection_metadata.h" | #include "mongo/s/collection_metadata.h" | |||
#include "mongo/util/net/message.h" | ||||
#include "mongo/util/background.h" | ||||
#include "mongo/util/elapsed_tracker.h" | #include "mongo/util/elapsed_tracker.h" | |||
namespace mongo { | namespace mongo { | |||
typedef boost::recursive_mutex::scoped_lock recursive_scoped_lock; | typedef boost::recursive_mutex::scoped_lock recursive_scoped_lock; | |||
class Cursor; /* internal server cursor base class */ | ||||
class ClientCursor; | class ClientCursor; | |||
class ParsedQuery; | class ParsedQuery; | |||
/* todo: make this map be per connection. this will prevent cursor hij | /** | |||
acking security attacks perhaps. | * ClientCursor is a wrapper that represents a cursorid from our databa | |||
* ERH: 9/2010 this may not work since some drivers send getMore | se application's | |||
over a different connection | * perspective. | |||
*/ | */ | |||
typedef map<CursorId, ClientCursor*> CCById; | ||||
extern BSONObj id_obj; | ||||
class ClientCursor : private boost::noncopyable { | class ClientCursor : private boost::noncopyable { | |||
friend class CmdCursorInfo; | ||||
public: | public: | |||
static void assertNoCursors(); | ClientCursor(int qopts, const shared_ptr<Cursor>& c, const string& | |||
ns, | ||||
BSONObj query = BSONObj()); | ||||
/* use this to assure we don't in the background time out cursor wh | ClientCursor(Runner* runner, int qopts = 0, const BSONObj query = B | |||
ile it is under use. | SONObj()); | |||
if you are using noTimeout() already, there is no risk anyway. | ||||
Further, this mechanism guards against two getMore requests on t | ||||
he same cursor executing | ||||
at the same time - which might be bad. That should never happen | ||||
, but if a client driver | ||||
had a bug, it could (or perhaps some sort of attack situation). | ||||
*/ | ||||
class Pin : boost::noncopyable { | ||||
public: | ||||
Pin( long long cursorid ) : | ||||
_cursorid( INVALID_CURSOR_ID ) { | ||||
recursive_scoped_lock lock( ccmutex ); | ||||
ClientCursor *cursor = ClientCursor::find_inlock( cursorid, | ||||
true ); | ||||
if ( cursor ) { | ||||
uassert( 12051, "clientcursor already in use? driver pr | ||||
oblem?", | ||||
cursor->_pinValue < 100 ); | ||||
cursor->_pinValue += 100; | ||||
_cursorid = cursorid; | ||||
} | ||||
} | ||||
void release() { | ||||
if ( _cursorid == INVALID_CURSOR_ID ) { | ||||
return; | ||||
} | ||||
ClientCursor *cursor = c(); | ||||
_cursorid = INVALID_CURSOR_ID; | ||||
if ( cursor ) { | ||||
verify( cursor->_pinValue >= 100 ); | ||||
cursor->_pinValue -= 100; | ||||
} | ||||
} | ||||
~Pin() { DESTRUCTOR_GUARD( release(); ) } | ||||
ClientCursor *c() const { return ClientCursor::find( _cursorid | ||||
); } | ||||
private: | ||||
CursorId _cursorid; | ||||
}; | ||||
/** Assures safe and reliable cleanup of a ClientCursor. */ | ~ClientCursor(); | |||
class Holder : boost::noncopyable { | ||||
public: | ||||
Holder( ClientCursor *c = 0 ) : | ||||
_c( 0 ), | ||||
_id( INVALID_CURSOR_ID ) { | ||||
reset( c ); | ||||
} | ||||
void reset( ClientCursor *c = 0 ) { | ||||
if ( c == _c ) | ||||
return; | ||||
if ( _c ) { | ||||
// be careful in case cursor was deleted by someone els | ||||
e | ||||
ClientCursor::erase( _id ); | ||||
} | ||||
if ( c ) { | ||||
_c = c; | ||||
_id = c->_cursorid; | ||||
} | ||||
else { | ||||
_c = 0; | ||||
_id = INVALID_CURSOR_ID; | ||||
} | ||||
} | ||||
~Holder() { | ||||
DESTRUCTOR_GUARD ( reset(); ); | ||||
} | ||||
ClientCursor* get() { return _c; } | ||||
operator bool() { return _c; } | ||||
ClientCursor * operator-> () { return _c; } | ||||
const ClientCursor * operator-> () const { return _c; } | ||||
/** Release ownership of the ClientCursor. */ | ||||
void release() { | ||||
_c = 0; | ||||
_id = INVALID_CURSOR_ID; | ||||
} | ||||
private: | ||||
ClientCursor *_c; | ||||
CursorId _id; | ||||
}; | ||||
/** | /** | |||
* Iterates through all ClientCursors, under its own ccmutex lock. | * Assert that there are no open cursors. | |||
* Also supports deletion on the fly. | * Called from DatabaseHolder::closeAll. | |||
*/ | */ | |||
class LockedIterator : boost::noncopyable { | static void assertNoCursors(); | |||
public: | ||||
LockedIterator() : _lock( ccmutex ), _i( clientCursorsById.begi | ||||
n() ) {} | ||||
bool ok() const { return _i != clientCursorsById.end(); } | ||||
ClientCursor *current() const { return _i->second; } | ||||
void advance() { ++_i; } | ||||
/** | ||||
* Delete 'current' and advance. Properly handles cascading del | ||||
etions that may occur | ||||
* when one ClientCursor is directly deleted. | ||||
*/ | ||||
void deleteAndAdvance(); | ||||
private: | ||||
recursive_scoped_lock _lock; | ||||
CCById::const_iterator _i; | ||||
}; | ||||
ClientCursor(int queryOptions, const shared_ptr<Cursor>& c, const s | ||||
tring& ns, BSONObj query = BSONObj() ); | ||||
~ClientCursor(); | ||||
// *************** basic accessors ******************* | // | |||
// Basic accessors | ||||
// | ||||
CursorId cursorid() const { return _cursorid; } | CursorId cursorid() const { return _cursorid; } | |||
string ns() const { return _ns; } | string ns() const { return _ns; } | |||
Database * db() const { return _db; } | Database * db() const { return _db; } | |||
const BSONObj& query() const { return _query; } | ||||
int queryOptions() const { return _queryOptions; } | ||||
DiskLoc lastLoc() const { return _lastLoc; } | // | |||
// Invalidation of DiskLocs and dropping of namespaces | ||||
// | ||||
/* Get rid of cursors for namespaces 'ns'. When dropping a db, ns i | /** | |||
s "dbname." | * Get rid of cursors for namespaces 'ns'. When dropping a db, ns i | |||
Used by drop, dropIndexes, dropDatabase. | s "dbname." Used by drop, | |||
*/ | * dropIndexes, dropDatabase. | |||
*/ | ||||
static void invalidate(const char *ns); | static void invalidate(const char *ns); | |||
/** | /** | |||
* Called when the provided DiskLoc is about to change state via a | ||||
deletion or an update. | ||||
* All runners/cursors that might be using that DiskLoc must adapt. | ||||
*/ | ||||
static void aboutToDelete(const StringData& ns, | ||||
const NamespaceDetails* nsd, | ||||
const DiskLoc& dl); | ||||
/** | ||||
* Register a runner so that it can be notified of deletion/invalid | ||||
ation during yields. | ||||
* Must be called before a runner yields. If a runner is cached (i | ||||
nside a ClientCursor) it | ||||
* MUST NOT be registered; the two are mutually exclusive. | ||||
*/ | ||||
static void registerRunner(Runner* runner); | ||||
/** | ||||
* Remove a runner from the runner registry. | ||||
*/ | ||||
static void deregisterRunner(Runner* runner); | ||||
// | ||||
// Yielding. | ||||
// | ||||
static void staticYield(int micros, const StringData& ns, Record* r | ||||
ec); | ||||
// | ||||
// Static methods about all ClientCursors TODO: Document. | ||||
// | ||||
static void appendStats( BSONObjBuilder& result ); | ||||
// | ||||
// ClientCursor creation/deletion. | ||||
// | ||||
static unsigned numCursors() { return clientCursorsById.size(); } | ||||
static void find( const string& ns , set<CursorId>& all ); | ||||
static ClientCursor* find(CursorId id, bool warn = true); | ||||
// 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. This should | ||||
// not be called when ccmutex is held. | ||||
static int eraseIfAuthorized(int n, long long* ids); | ||||
static bool eraseIfAuthorized(CursorId id); | ||||
/** | ||||
* @return number of cursors found | ||||
*/ | ||||
static int erase(int n, long long* ids); | ||||
/** | ||||
* Deletes the cursor with the provided @param 'id' if one exists. | ||||
* @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); | ||||
// | ||||
// Timing and timeouts | ||||
// | ||||
/** | ||||
* called every 4 seconds. millis is amount of idle time passed si | ||||
nce the last call -- | ||||
* could be zero | ||||
*/ | ||||
static void idleTimeReport(unsigned millis); | ||||
/** | ||||
* @param millis amount of idle passed time since last call | ||||
* note called outside of locks (other than ccmutex) so care must b | ||||
e exercised | ||||
*/ | ||||
bool shouldTimeout( unsigned millis ); | ||||
unsigned idleTime() const { return _idleAgeMillis; } | ||||
uint64_t getLeftoverMaxTimeMicros() const { return _leftoverMaxTime | ||||
Micros; } | ||||
void setLeftoverMaxTimeMicros( uint64_t leftoverMaxTimeMicros ) { | ||||
_leftoverMaxTimeMicros = leftoverMaxTimeMicros; | ||||
} | ||||
// | ||||
// Sharding-specific data. TODO: Document. | ||||
// | ||||
// future getMore. | ||||
void setCollMetadata( CollectionMetadataPtr metadata ){ _collMetada | ||||
ta = metadata; } | ||||
CollectionMetadataPtr getCollMetadata(){ return _collMetadata; } | ||||
// | ||||
// Replication-related stuff. TODO: Document and clean. | ||||
// | ||||
void updateSlaveLocation( CurOp& curop ); | ||||
void slaveReadTill( const OpTime& t ) { _slaveReadTill = t; } | ||||
/** Just for testing. */ | ||||
OpTime getSlaveReadTill() const { return _slaveReadTill; } | ||||
// | ||||
// Query-specific functionality that may be adapted for the Runner. | ||||
// | ||||
Runner* getRunner() const { return _runner.get(); } | ||||
int queryOptions() const { return _queryOptions; } | ||||
// Used by ops/query.cpp to stash how many results have been return | ||||
ed by a query. | ||||
int pos() const { return _pos; } | ||||
void incPos(int n) { _pos += n; } | ||||
void setPos(int n) { _pos = n; } | ||||
// | ||||
// Yielding that is DEPRECATED. Will be removed when we use runner | ||||
s and they yield | ||||
// internally. | ||||
// | ||||
/** | ||||
* DEPRECATED | ||||
* @param microsToSleep -1 : ask client | * @param microsToSleep -1 : ask client | |||
* >=0 : sleep for that amount | * 0 : pthread_yield or equivilant | |||
* >0 : sleep for that amount | ||||
* @param recordToLoad after yielding lock, load this record with o nly mmutex | * @param recordToLoad after yielding lock, load this record with o nly mmutex | |||
* do a dbtemprelease | * do a dbtemprelease | |||
* note: caller should check matcher.docMatcher().atomic() first an d not yield if atomic - | * note: caller should check matcher.docMatcher().atomic() first an d not yield if atomic - | |||
* we don't do herein as this->matcher (above) is only initia lized for true queries/getmore. | * we don't do herein as this->matcher (above) is only initia lized for true queries/getmore. | |||
* (ie not set for remote/update) | * (ie not set for remote/update) | |||
* @return if the cursor is still valid. | * @return if the cursor is still valid. | |||
* if false is returned, then this ClientCursor should be c onsidered deleted - | * if false is returned, then this ClientCursor should be c onsidered deleted - | |||
* in fact, the whole database could be gone. | * in fact, the whole database could be gone. | |||
*/ | */ | |||
bool yield( int microsToSleep = -1 , Record * recordToLoad = 0 ); | bool yield( int microsToSleep = -1, Record * recordToLoad = 0 ); | |||
enum RecordNeeds { | enum RecordNeeds { | |||
DontNeed = -1 , MaybeCovered = 0 , WillNeed = 100 | DontNeed = -1 , MaybeCovered = 0 , WillNeed = 100 | |||
}; | }; | |||
/** | /** | |||
* @param needRecord whether or not the next record has to be read from disk for sure | * @param needRecord whether or not the next record has to be read from disk for sure | |||
* if this is true, will yield of next record isn 't in memory | * if this is true, will yield of next record isn 't in memory | |||
* @param yielded true if a yield occurred, and potentially if a yi eld did not occur | * @param yielded true if a yield occurred, and potentially if a yi eld did not occur | |||
* @return same as yield() | * @return same as yield() | |||
*/ | */ | |||
bool yieldSometimes( RecordNeeds need, bool *yielded = 0 ); | bool yieldSometimes( RecordNeeds need, bool *yielded = 0 ); | |||
static int suggestYieldMicros(); | ||||
static void staticYield( int micros , const StringData& ns , Record | ||||
* rec ); | ||||
struct YieldData { CursorId _id; bool _doingDeletes; }; | struct YieldData { CursorId _id; bool _doingDeletes; }; | |||
bool prepareToYield( YieldData &data ); | bool prepareToYield( YieldData &data ); | |||
static bool recoverFromYield( const YieldData &data ); | static bool recoverFromYield( const YieldData &data ); | |||
static int suggestYieldMicros(); | ||||
struct YieldLock : boost::noncopyable { | // | |||
// Cursor-only DEPRECATED methods. | ||||
explicit YieldLock( ptr<ClientCursor> cc ); | // | |||
~YieldLock(); | ||||
/** | ||||
* @return if the cursor is still ok | ||||
* if it is, we also relock | ||||
*/ | ||||
bool stillOk(); | ||||
void relock(); | ||||
private: | void storeOpForSlave( DiskLoc last ); | |||
const bool _canYield; | ||||
YieldData _data; | ||||
scoped_ptr<dbtempreleasecond> _unlock; | ||||
}; | ||||
// --- some pass through helpers for Cursor --- | // Only used by ops/query.cpp, which will stop using them when quer | |||
ies are answered only by | ||||
// a runner. | ||||
const BSONObj& query() const { return _query; } | ||||
shared_ptr<ParsedQuery> pq; | ||||
// This one is used also by pipeline/document_source_cursor.cpp | ||||
shared_ptr<Projection> fields; // which fields query wants returned | ||||
DiskLoc lastLoc() const { return _lastLoc; } | ||||
Cursor* c() const { return _c.get(); } | Cursor* c() const { return _c.get(); } | |||
int pos() const { return _pos; } | ||||
void incPos( int n ) { _pos += n; } // TODO: this is bad | ||||
void setPos( int n ) { _pos = n; } // TODO : this is bad too | ||||
BSONObj indexKeyPattern() { return _c->indexKeyPattern(); } | ||||
bool modifiedKeys() const { return _c->modifiedKeys(); } | ||||
bool isMultiKey() const { return _c->isMultiKey(); } | ||||
bool ok() { return _c->ok(); } | bool ok() { return _c->ok(); } | |||
bool advance() { return _c->advance(); } | bool advance() { return _c->advance(); } | |||
BSONObj current() { return _c->current(); } | BSONObj current() { return _c->current(); } | |||
DiskLoc currLoc() { return _c->currLoc(); } | DiskLoc currLoc() { return _c->currLoc(); } | |||
BSONObj currKey() const { return _c->currKey(); } | BSONObj currKey() const { return _c->currKey(); } | |||
/** | ||||
* same as BSONObj::getFieldsDotted | ||||
* if it can be retrieved from key, it is | ||||
* @param holder keeps the currKey in scope by keeping a reference | ||||
to it here. generally you'll want | ||||
* holder and ret to destruct about the same time. | ||||
* @return if this was retrieved from key | ||||
*/ | ||||
bool getFieldsDotted( const string& name, BSONElementSet &ret, BSON | ||||
Obj& holder ); | ||||
/** | ||||
* same as BSONObj::getFieldDotted | ||||
* if it can be retrieved from key, it is | ||||
* @return if this was retrieved from key | ||||
*/ | ||||
BSONElement getFieldDotted( const string& name , BSONObj& holder , | ||||
bool * fromKey = 0 ) ; | ||||
/** extract items from object which match a pattern object. | ||||
* e.g., if pattern is { x : 1, y : 1 }, builds an object with | ||||
* x and y elements of this object, if they are present. | ||||
* returns elements with original field names | ||||
* NOTE: copied from BSONObj::extractFields | ||||
*/ | ||||
BSONObj extractFields(const BSONObj &pattern , bool fillWithNull = | ||||
false) ; | ||||
/** Extract elements from the object this cursor currently points t | ||||
o, using the expression | ||||
* specified in KeyPattern. Will use a covered index if the one in | ||||
this cursor is usable. | ||||
* TODO: there are some cases where a covered index could be used | ||||
but is not, for instance | ||||
* if both this index and the keyPattern are {a : "hashed"} | ||||
*/ | ||||
BSONObj extractKey( const KeyPattern& usingKeyPattern ) const; | ||||
void fillQueryResultFromObj( BufBuilder &b, const MatchDetails* det | ||||
ails = NULL ) const; | ||||
bool currentIsDup() { return _c->getsetdup( _c->currLoc() ); } | bool currentIsDup() { return _c->getsetdup( _c->currLoc() ); } | |||
bool currentMatches() { | bool currentMatches() { | |||
if ( ! _c->matcher() ) | if ( ! _c->matcher() ) | |||
return true; | return true; | |||
return _c->matcher()->matchesCurrent( _c.get() ); | return _c->matcher()->matchesCurrent( _c.get() ); | |||
} | } | |||
void setCollMetadata( CollectionMetadataPtr metadata ){ _collMetada | void setDoingDeletes( bool doingDeletes ) {_doingDeletes = doingDel | |||
ta = metadata; } | etes; } | |||
CollectionMetadataPtr getCollMetadata(){ return _collMetadata; } | ||||
private: | private: | |||
void setLastLoc_inlock(DiskLoc); | friend class ClientCursorHolder; | |||
friend class ClientCursorPin; | ||||
friend struct ClientCursorYieldLock; | ||||
friend class CmdCursorInfo; | ||||
static ClientCursor* find_inlock(CursorId id, bool warn = true) { | // A map from the CursorId to the ClientCursor behind it. | |||
CCById::iterator it = clientCursorsById.find(id); | // TODO: Consider making this per-connection. | |||
if ( it == clientCursorsById.end() ) { | typedef map<CursorId, ClientCursor*> CCById; | |||
if ( warn ) { | static CCById clientCursorsById; | |||
OCCASIONALLY out() << "ClientCursor::find(): cursor not | ||||
found in map '" << id | ||||
<< "' (ok after a drop)" << endl; | ||||
} | ||||
return 0; | ||||
} | ||||
return it->second; | ||||
} | ||||
/* call when cursor's location changes so that we can update the | // A list of NON-CACHED runners. Any runner that yields must be pu | |||
cursorsbylocation map. if you are locked and internally iterating | t into this map before | |||
, only | // yielding in order to be notified of invalidation and namespace d | |||
need to call when you are ready to "unlock". | eletion. Before the | |||
*/ | // runner is deleted, it must be removed from this map. | |||
void updateLocation(); | // | |||
// TODO: This is temporary and as such is highly NOT optimized. | ||||
static set<Runner*> nonCachedRunners; | ||||
public: | // How many cursors have timed out? | |||
static ClientCursor* find(CursorId id, bool warn = true) { | static long long numberTimedOut; | |||
recursive_scoped_lock lock(ccmutex); | ||||
ClientCursor *c = find_inlock(id, warn); | // This must be held when modifying any static member. | |||
// if this asserts, your code was not thread safe - you either | static boost::recursive_mutex& ccmutex; | |||
need to set no timeout | ||||
// 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 ); | ||||
return c; | ||||
} | ||||
/** | /** | |||
* Deletes the cursor with the provided @param 'id' if one exists. | * Initialization common between Cursor and Runner. | |||
* @throw if the cursor with the provided id is pinned. | * TODO: Remove when we're all-runner. | |||
* 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); | void init(); | |||
// 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. This should | ||||
// not be called when ccmutex is held. | ||||
static bool eraseIfAuthorized(CursorId id); | ||||
/** | /** | |||
* @return number of cursors found | * Allocates a new CursorId. | |||
* Called from init(...). Assumes ccmutex held. | ||||
*/ | */ | |||
static int erase(int n, long long* ids); | static CursorId allocCursorId_inlock(); | |||
static int eraseIfAuthorized(int n, long long* ids); | ||||
void mayUpgradeStorage() { | ||||
/* if ( !ids_.get() ) | ||||
return; | ||||
stringstream ss; | ||||
ss << ns << "." << cursorid; | ||||
ids_->mayUpgradeStorage( ss.str() );*/ | ||||
} | ||||
/** | /** | |||
* @param millis amount of idle passed time since last call | * Find the ClientCursor with the provided ID. Optionally warn if | |||
it's not found. | ||||
* Assumes ccmutex is held. | ||||
*/ | */ | |||
bool shouldTimeout( unsigned millis ); | ||||
void storeOpForSlave( DiskLoc last ); | static ClientCursor* find_inlock(CursorId id, bool warn = true); | |||
void updateSlaveLocation( CurOp& curop ); | ||||
unsigned idleTime() const { return _idleAgeMillis; } | /** | |||
* Delete the ClientCursor with the provided ID. masserts if the c | ||||
ursor is pinned. | ||||
*/ | ||||
static void _erase_inlock(ClientCursor* cursor); | ||||
void setDoingDeletes( bool doingDeletes ) {_doingDeletes = doingDel | // | |||
etes; } | // ClientCursor-specific data, independent of the underlying execut | |||
ion type. | ||||
// | ||||
void slaveReadTill( const OpTime& t ) { _slaveReadTill = t; } | // The ID of the ClientCursor. | |||
CursorId _cursorid; | ||||
/** Just for testing. */ | // A variable indicating the state of the ClientCursor. Possible v | |||
OpTime getSlaveReadTill() const { return _slaveReadTill; } | alues: | |||
// 0: Normal behavior. May time out. | ||||
// 1: No timing out of this ClientCursor. | ||||
// 100: Currently in use (via ClientCursorPin). | ||||
unsigned _pinValue; | ||||
public: // static methods | // The namespace we're operating on. | |||
string _ns; | ||||
static void idleTimeReport(unsigned millis); | // The database we're operating on. | |||
Database* _db; | ||||
static void appendStats( BSONObjBuilder& result ); | // How many objects have been returned by the find() so far? | |||
static unsigned numCursors() { return clientCursorsById.size(); } | int _pos; | |||
static void aboutToDelete( const StringData& ns, | ||||
const NamespaceDetails* nsd, | ||||
const DiskLoc& dl ); | ||||
static void find( const string& ns , set<CursorId>& all ); | ||||
private: // methods | // The query that prompted this ClientCursor. Only used for debugg | |||
ing. | ||||
BSONObj _query; | ||||
// cursors normally timeout after an inactivity period to prevent e | // See the QueryOptions enum in dbclient.h | |||
xcess memory use | int _queryOptions; | |||
// setting this prevents timeout of the cursor in question. | ||||
void noTimeout() { _pinValue++; } | ||||
Record* _recordForYield( RecordNeeds need ); | // TODO: document better. | |||
static bool _erase_inlock(ClientCursor* cursor); | OpTime _slaveReadTill; | |||
private: | // How long has the cursor been idle? | |||
unsigned _idleAgeMillis; | ||||
CursorId _cursorid; | // TODO: Document. | |||
uint64_t _leftoverMaxTimeMicros; | ||||
const string _ns; | // For chunks that are being migrated, there is a period of time wh | |||
Database * _db; | en that chunks data is in | |||
// two shards, the donor and the receiver one. That data is picked | ||||
up by a cursor on the | ||||
// receiver side, even before the migration was decided. The Colle | ||||
ctionMetadata allow one | ||||
// to inquiry if any given document of the collection belongs indee | ||||
d to this shard or if it | ||||
// is coming from (or a vestige of) an ongoing migration. | ||||
CollectionMetadataPtr _collMetadata; | ||||
const shared_ptr<Cursor> _c; | // | |||
map<string,int> _indexedFields; // map from indexed field to offse | // The underlying execution machinery. | |||
t in key object | // | |||
int _pos; // # objects into the cursor so fa | ||||
r | // The new world: a runner. | |||
scoped_ptr<Runner> _runner; | ||||
// | ||||
// Cursor-only private data and methods. DEPRECATED. | ||||
// | ||||
const BSONObj _query; // used for logging diags only; op | // The old world: a cursor. DEPRECATED. | |||
tional in constructor | const shared_ptr<Cursor> _c; | |||
int _queryOptions; // see enum QueryOptions dbclient.h | ||||
OpTime _slaveReadTill; | /** | |||
* call when cursor's location changes so that we can update the cu | ||||
rsorsbylocation map. if | ||||
* you are locked and internally iterating, only need to call when | ||||
you are ready to | ||||
* "unlock". | ||||
*/ | ||||
void updateLocation(); | ||||
void setLastLoc_inlock(DiskLoc); | ||||
Record* _recordForYield( RecordNeeds need ); | ||||
DiskLoc _lastLoc; // use getter and setter n ot this (important) | DiskLoc _lastLoc; // use getter and setter n ot this (important) | |||
unsigned _idleAgeMillis; // how long has the cursor | ||||
been around, relative to server idle time | ||||
/* 0 = normal | ||||
1 = no timeout allowed | ||||
100 = in use (pinned) -- see Pointer class | ||||
*/ | ||||
unsigned _pinValue; | ||||
bool _doingDeletes; // when true we are the delete and aboutToDelet e shouldn't manipulate us | bool _doingDeletes; // when true we are the delete and aboutToDelet e shouldn't manipulate us | |||
ElapsedTracker _yieldSometimesTracker; | ||||
CollectionMetadataPtr _collMetadata; | // TODO: This will be moved into the runner. | |||
ElapsedTracker _yieldSometimesTracker; | ||||
}; | ||||
/** | ||||
* use this to assure we don't in the background time out cursor while | ||||
it is under use. if you | ||||
* are using noTimeout() already, there is no risk anyway. Further, th | ||||
is mechanism guards | ||||
* against two getMore requests on the same cursor executing at the sam | ||||
e time - which might be | ||||
* bad. That should never happen, but if a client driver had a bug, it | ||||
could (or perhaps some | ||||
* sort of attack situation). | ||||
*/ | ||||
class ClientCursorPin : boost::noncopyable { | ||||
public: | public: | |||
shared_ptr<ParsedQuery> pq; | ClientCursorPin( long long cursorid ); | |||
shared_ptr<Projection> fields; // which fields query wants returned | ~ClientCursorPin(); | |||
void release(); | ||||
private: // static members | // Call this to delete the underlying ClientCursor. | |||
void free(); | ||||
static CCById clientCursorsById; | ClientCursor *c() const; | |||
static long long numberTimedOut; | private: | |||
static boost::recursive_mutex& ccmutex; // must use this for all | CursorId _cursorid; | |||
statics above! | }; | |||
static CursorId allocCursorId_inlock(); | ||||
/** Assures safe and reliable cleanup of a ClientCursor. */ | ||||
class ClientCursorHolder : boost::noncopyable { | ||||
public: | ||||
ClientCursorHolder( ClientCursor *c = 0 ); | ||||
~ClientCursorHolder(); | ||||
void reset( ClientCursor *c = 0 ); | ||||
ClientCursor* get(); | ||||
operator bool() { return _c; } | ||||
ClientCursor * operator-> (); | ||||
const ClientCursor * operator-> () const; | ||||
/** Release ownership of the ClientCursor. */ | ||||
void release(); | ||||
private: | ||||
ClientCursor *_c; | ||||
CursorId _id; | ||||
}; | }; | |||
/** thread for timing out old cursors */ | ||||
class ClientCursorMonitor : public BackgroundJob { | class ClientCursorMonitor : public BackgroundJob { | |||
public: | public: | |||
string name() const { return "ClientCursorMonitor"; } | string name() const { return "ClientCursorMonitor"; } | |||
void run(); | void run(); | |||
}; | }; | |||
struct ClientCursorYieldLock : boost::noncopyable { | ||||
explicit ClientCursorYieldLock( ptr<ClientCursor> cc ); | ||||
~ClientCursorYieldLock(); | ||||
/** | ||||
* @return if the cursor is still ok | ||||
* if it is, we also relock | ||||
*/ | ||||
bool stillOk(); | ||||
void relock(); | ||||
private: | ||||
const bool _canYield; | ||||
ClientCursor::YieldData _data; | ||||
scoped_ptr<dbtempreleasecond> _unlock; | ||||
}; | ||||
} // namespace mongo | } // namespace mongo | |||
// ClientCursor should only be used with auto_ptr because it needs to be | // ClientCursor should only be used with auto_ptr because it needs to be | |||
// release()ed after a yield if stillOk() returns false and these pointer t ypes | // release()ed after a yield if stillOk() returns false and these pointer t ypes | |||
// do not support releasing. This will prevent them from being used acciden tally | // do not support releasing. This will prevent them from being used acciden tally | |||
// Instead of auto_ptr<>, which still requires some degree of manual manage ment | // Instead of auto_ptr<>, which still requires some degree of manual manage ment | |||
// of this, consider using ClientCursor::Holder which handles ClientCursor' s | // of this, consider using ClientCursor::Holder which handles ClientCursor' s | |||
// unusual self-deletion mechanics. | // unusual self-deletion mechanics. | |||
namespace boost{ | namespace boost{ | |||
template<> class scoped_ptr<mongo::ClientCursor> {}; | template<> class scoped_ptr<mongo::ClientCursor> {}; | |||
End of changes. 65 change blocks. | ||||
352 lines changed or deleted | 352 lines changed or added | |||
cmdline.h | cmdline.h | |||
---|---|---|---|---|
skipping to change at line 170 | skipping to change at line 170 | |||
static void launchOk(); | static void launchOk(); | |||
static void addGlobalOptions( boost::program_options::options_descr iption& general , | static void addGlobalOptions( boost::program_options::options_descr iption& general , | |||
boost::program_options::options_descr iption& hidden , | boost::program_options::options_descr iption& hidden , | |||
boost::program_options::options_descr iption& ssl_options ); | boost::program_options::options_descr iption& ssl_options ); | |||
static void addWindowsOptions( boost::program_options::options_desc ription& windows , | static void addWindowsOptions( boost::program_options::options_desc ription& windows , | |||
boost::program_options::options_desc ription& hidden ); | boost::program_options::options_desc ription& hidden ); | |||
static void parseConfigFile( istream &f, std::stringstream &ss); | static bool parseConfigFile( istream &f, std::stringstream &ss); | |||
/** | /** | |||
* @return true if should run program, false if should exit | * @return true if should run program, false if should exit | |||
*/ | */ | |||
static bool store( const std::vector<std::string>& argv, | static bool store( const std::vector<std::string>& argv, | |||
boost::program_options::options_description& vis ible, | boost::program_options::options_description& vis ible, | |||
boost::program_options::options_description& hid den, | boost::program_options::options_description& hid den, | |||
boost::program_options::positional_options_descr iption& positional, | boost::program_options::positional_options_descr iption& positional, | |||
boost::program_options::variables_map &output ); | boost::program_options::variables_map &output ); | |||
/** | /** | |||
skipping to change at line 198 | skipping to change at line 198 | |||
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(true), oplogSize(0), defaultProfile(0), | durOptions(0), objcheck(true), oplogSize(0), defaultProfile(0), | |||
slowMS(100), defaultLocalThresholdMillis(15), pretouch(0), movePara noia( false ), | slowMS(100), defaultLocalThresholdMillis(15), pretouch(0), movePara noia( true ), | |||
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), isHttpInterfaceEnabled(fals e) | logAppend(false), logWithSyslog(false), isHttpInterfaceEnabled(fals e) | |||
{ | { | |||
started = time(0); | started = time(0); | |||
journalCommitInterval = 0; // 0 means use default | journalCommitInterval = 0; // 0 means use default | |||
dur = false; | dur = false; | |||
#if defined(_DURABLEDEFAULTON) | #if defined(_DURABLEDEFAULTON) | |||
dur = true; | dur = true; | |||
#endif | #endif | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
collection.h | collection.h | |||
---|---|---|---|---|
// @file collection.h | // collection.h | |||
/** | /** | |||
* Copyright (C) 2012 10gen Inc. | * Copyright (C) 2012 10gen Inc. | |||
* | * | |||
* This program is free software: you can redistribute it and/or modify | * This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License, version 3 , | * it under the terms of the GNU Affero General Public License, version 3 , | |||
* as published by the Free Software Foundation. | * as published by the Free Software Foundation. | |||
* | * | |||
* This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Licen se | * You should have received a copy of the GNU Affero General Public Licen se | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/db/namespace_details.h" | #include <string> | |||
#include "mongo/base/string_data.h" | ||||
#include "mongo/db/diskloc.h" | ||||
#include "mongo/db/exec/collection_scan_common.h" | ||||
namespace mongo { | namespace mongo { | |||
class Collection { | class Database; | |||
class ExtentManager; | ||||
class NamespaceDetails; | ||||
class CollectionIterator; | ||||
class FlatIterator; | ||||
class CappedIterator; | ||||
/** | ||||
* this is NOT safe through a yield right now | ||||
* not sure if it will be, or what yet | ||||
*/ | ||||
class CollectionTemp { | ||||
public: | public: | |||
NamespaceDetails * const d; | CollectionTemp( const StringData& fullNS, | |||
NamespaceDetailsTransient * const nsd; | NamespaceDetails* details, | |||
Database* database ); | ||||
~CollectionTemp(); | ||||
bool ok() const { return _magic == 1357924; } | ||||
StringData ns() const { return _ns; } | ||||
CollectionIterator* getIterator( const DiskLoc& start, bool tailabl | ||||
e, | ||||
const CollectionScanParams::Direct | ||||
ion& dir) const; | ||||
private: | ||||
ExtentManager* getExtentManager(); | ||||
const ExtentManager* getExtentManager() const; | ||||
int _magic; | ||||
std::string _ns; | ||||
NamespaceDetails* _details; | ||||
Database* _database; | ||||
friend class Database; | ||||
friend class FlatIterator; | ||||
friend class CappedIterator; | ||||
}; | }; | |||
} | } | |||
End of changes. 4 change blocks. | ||||
5 lines changed or deleted | 48 lines changed or added | |||
collection_metadata.h | collection_metadata.h | |||
---|---|---|---|---|
skipping to change at line 114 | skipping to change at line 114 | |||
* caller owns the metadata. | * caller owns the metadata. | |||
* | * | |||
* If a new metadata can't be created, returns NULL and fills in 'e rrMsg', if it was | * If a new metadata can't be created, returns NULL and fills in 'e rrMsg', if it was | |||
* provided. | * provided. | |||
*/ | */ | |||
CollectionMetadata* cloneSplit( const ChunkType& chunk, | CollectionMetadata* cloneSplit( const ChunkType& chunk, | |||
const vector<BSONObj>& splitKeys, | const vector<BSONObj>& splitKeys, | |||
const ChunkVersion& newShardVersion , | const ChunkVersion& newShardVersion , | |||
string* errMsg ) const; | string* errMsg ) const; | |||
/** | ||||
* Returns a new metadata instance by merging a key range which sta | ||||
rts and ends at existing | ||||
* chunks into a single chunk. The range may not have holes. The | ||||
resulting metadata will | ||||
* have the 'newShardVersion'. The caller owns the new metadata. | ||||
* | ||||
* If a new metadata can't be created, returns NULL and fills in 'e | ||||
rrMsg', if it was | ||||
* provided. | ||||
*/ | ||||
CollectionMetadata* cloneMerge( const BSONObj& minKey, | ||||
const BSONObj& maxKey, | ||||
const ChunkVersion& newShardVersion | ||||
, | ||||
string* errMsg ) const; | ||||
// | // | |||
// verification logic | // verification logic | |||
// | // | |||
/** | /** | |||
* Returns true if the document key 'key' is a valid instance of a | ||||
shard key for this | ||||
* metadata. The 'key' must contain exactly the same fields as the | ||||
shard key pattern. | ||||
*/ | ||||
bool isValidKey( const BSONObj& key ) const; | ||||
/** | ||||
* Returns true if the document key 'key' belongs to this chunkset. Recall that documents of | * Returns true if the document key 'key' belongs to this chunkset. Recall that documents of | |||
* an in-flight chunk migration may be present and should not be co nsidered part of the | * an in-flight chunk migration may be present and should not be co nsidered part of the | |||
* collection / chunkset yet. Key must be the full shard key. | * collection / chunkset yet. Key must be the full shard key. | |||
*/ | */ | |||
bool keyBelongsToMe( const BSONObj& key ) const; | bool keyBelongsToMe( const BSONObj& key ) const; | |||
/** | /** | |||
* Returns true if the document key 'key' is or has been migrated t o this shard, and may | * Returns true if the document key 'key' is or has been migrated t o this shard, and may | |||
* belong to us after a subsequent config reload. Key must be the full shard key. | * belong to us after a subsequent config reload. Key must be the full shard key. | |||
*/ | */ | |||
bool keyIsPending( const BSONObj& key ) const; | bool keyIsPending( const BSONObj& key ) const; | |||
/** | /** | |||
* Given the chunk's min key (or empty doc) in 'lookupKey', gets th | * Given a key 'lookupKey' in the shard key range, get the next chu | |||
e boundaries of the | nk which overlaps or is | |||
* chunk following that one (the first), and fills in 'foundChunk' | * greater than this key. Returns true if a chunk exists, false ot | |||
with those | herwise. | |||
* boundaries. If the next chunk happens to be the last one, retur | * | |||
ns true otherwise | * Passing a key that is not a valid shard key for this range resul | |||
* false. | ts in undefined behavior. | |||
* | ||||
* @param lookupKey passing a doc that does not belong to this meta | ||||
data is undefined. | ||||
* An empty doc is special and the chunk with the lowest range | ||||
will be set on | ||||
* foundChunk. | ||||
*/ | */ | |||
bool getNextChunk( const BSONObj& lookupKey, ChunkType* foundChunk | bool getNextChunk( const BSONObj& lookupKey, ChunkType* chunk ) con | |||
) const; | st; | |||
/** | ||||
* Given a key in the shard key range, get the next range which ove | ||||
rlaps or is greater than | ||||
* this key. | ||||
* | ||||
* This allows us to do the following to iterate over all orphan ra | ||||
nges: | ||||
* | ||||
* KeyRange range; | ||||
* BSONObj lookupKey = metadata->getMinKey(); | ||||
* while( metadata->getNextOrphanRange( lookupKey, &orphanRange ) ) | ||||
{ | ||||
* // Do stuff with range | ||||
* lookupKey = orphanRange.maxKey; | ||||
* } | ||||
* | ||||
* @param lookupKey passing a key that does not belong to this meta | ||||
data is undefined. | ||||
*/ | ||||
bool getNextOrphanRange( const BSONObj& lookupKey, KeyRange* orphan | ||||
Range ) const; | ||||
// | // | |||
// accessors | // accessors | |||
// | // | |||
ChunkVersion getCollVersion() const { | ChunkVersion getCollVersion() const { | |||
return _collVersion; | return _collVersion; | |||
} | } | |||
ChunkVersion getShardVersion() const { | ChunkVersion getShardVersion() const { | |||
return _shardVersion; | return _shardVersion; | |||
} | } | |||
BSONObj getKeyPattern() const { | BSONObj getKeyPattern() const { | |||
return _keyPattern; | return _keyPattern; | |||
} | } | |||
BSONObj getMinKey() const; | ||||
BSONObj getMaxKey() const; | ||||
std::size_t getNumChunks() const { | std::size_t getNumChunks() const { | |||
return _chunksMap.size(); | return _chunksMap.size(); | |||
} | } | |||
std::size_t getNumPending() const { | std::size_t getNumPending() const { | |||
return _pendingMap.size(); | return _pendingMap.size(); | |||
} | } | |||
// | ||||
// reporting | ||||
// | ||||
/** | ||||
* BSON output of the metadata information. | ||||
*/ | ||||
BSONObj toBSON() const; | ||||
/** | ||||
* BSON output of the metadata information, into a builder. | ||||
*/ | ||||
void toBSON( BSONObjBuilder& bb ) const; | ||||
/** | ||||
* BSON output of the chunks metadata into a BSONArray | ||||
*/ | ||||
void toBSONChunks( BSONArrayBuilder& bb ) const; | ||||
/** | ||||
* BSON output of the pending metadata into a BSONArray | ||||
*/ | ||||
void toBSONPending( BSONArrayBuilder& bb ) const; | ||||
/** | ||||
* String output of the metadata information. | ||||
*/ | ||||
string toString() const; | string toString() const; | |||
/** | /** | |||
* Use the MetadataLoader to fill the empty metadata from the confi g server, or use | * Use the MetadataLoader to fill the empty metadata from the confi g server, or use | |||
* clone*() methods to use existing metadatas to build new ones. | * clone*() methods to use existing metadatas to build new ones. | |||
* | * | |||
* Unless you are the MetadataLoader or a test you should probably not be using this | * Unless you are the MetadataLoader or a test you should probably not be using this | |||
* directly. | * directly. | |||
*/ | */ | |||
CollectionMetadata(); | CollectionMetadata(); | |||
skipping to change at line 223 | skipping to change at line 286 | |||
/** | /** | |||
* Returns true if this metadata was loaded with all necessary info rmation. | * Returns true if this metadata was loaded with all necessary info rmation. | |||
*/ | */ | |||
bool isValid() const; | bool isValid() const; | |||
/** | /** | |||
* Try to find chunks that are adjacent and record these intervals in the _rangesMap | * Try to find chunks that are adjacent and record these intervals in the _rangesMap | |||
*/ | */ | |||
void fillRanges(); | void fillRanges(); | |||
/** | ||||
* String representation of [inclusiveLower, exclusiveUpper) | ||||
*/ | ||||
std::string rangeToString( const BSONObj& inclusiveLower, | ||||
const BSONObj& exclusiveUpper ) const; | ||||
/** | ||||
* String representation of overlapping ranges as a list "[range1), | ||||
[range2),..." | ||||
*/ | ||||
std::string overlapToString( RangeVector overlap ) const; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 7 change blocks. | ||||
27 lines changed or deleted | 87 lines changed or added | |||
commands.h | commands.h | |||
---|---|---|---|---|
skipping to change at line 34 | skipping to change at line 34 | |||
#include "mongo/db/client_basic.h" | #include "mongo/db/client_basic.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
namespace mongo { | namespace mongo { | |||
class BSONObj; | class BSONObj; | |||
class BSONObjBuilder; | class BSONObjBuilder; | |||
class Client; | class Client; | |||
class Timer; | class Timer; | |||
namespace mutablebson { | ||||
class Document; | ||||
} // namespace mutablebson | ||||
/** mongodb "commands" (sent via db.$cmd.findOne(...)) | /** mongodb "commands" (sent via db.$cmd.findOne(...)) | |||
subclass to make a command. define a singleton object for it. | subclass to make a command. define a singleton object for it. | |||
*/ | */ | |||
class Command { | class Command { | |||
protected: | protected: | |||
// The type of the first field in 'cmdObj' must be mongo::String. T | ||||
he first field is | ||||
// interpreted as a collection name. | ||||
string parseNsFullyQualified(const string& dbname, const BSONObj& c mdObj) const; | string parseNsFullyQualified(const string& dbname, const BSONObj& c mdObj) const; | |||
public: | public: | |||
// only makes sense for commands where 1st parm is the collection. | ||||
// Return the namespace for the command. If the first field in 'cmd | ||||
Obj' is of type | ||||
// mongo::String, then that field is interpreted as the collection | ||||
name, and is | ||||
// appended to 'dbname' after a '.' character. If the first field i | ||||
s not of type | ||||
// mongo::String, then 'dbname' is returned unmodified. | ||||
virtual string parseNs(const string& dbname, const BSONObj& cmdObj) const; | virtual string parseNs(const string& dbname, const BSONObj& cmdObj) const; | |||
// warning: isAuthorized uses the lockType() return values, and val ues are being passed | // warning: isAuthorized uses the lockType() return values, and val ues are being passed | |||
// around as ints so be careful as it isn't really typesafe and wil l need cleanup later | // around as ints so be careful as it isn't really typesafe and wil l need cleanup later | |||
enum LockType { READ = -1 , NONE = 0 , WRITE = 1 }; | enum LockType { READ = -1 , NONE = 0 , WRITE = 1 }; | |||
const string name; | const string name; | |||
/* run the given command | /* run the given command | |||
implement this... | implement this... | |||
skipping to change at line 122 | skipping to change at line 132 | |||
virtual void help( stringstream& help ) const; | virtual void help( stringstream& help ) const; | |||
/** | /** | |||
* Checks if the given client is authorized to run this command on database "dbname" | * Checks if the given client is authorized to run this command on database "dbname" | |||
* with the invocation described by "cmdObj". | * with the invocation described by "cmdObj". | |||
*/ | */ | |||
virtual Status checkAuthForCommand(ClientBasic* client, | virtual Status checkAuthForCommand(ClientBasic* client, | |||
const std::string& dbname, | const std::string& dbname, | |||
const BSONObj& cmdObj); | const BSONObj& cmdObj); | |||
/** | ||||
* Redacts "cmdObj" in-place to a form suitable for writing to logs | ||||
. | ||||
* | ||||
* The default implementation does nothing. | ||||
*/ | ||||
virtual void redactForLogging(mutablebson::Document* cmdObj); | ||||
/* Return true if a replica set secondary should go into "recoverin g" | /* Return true if a replica set secondary should go into "recoverin g" | |||
(unreadable) state while running this command. | (unreadable) state while running this command. | |||
*/ | */ | |||
virtual bool maintenanceMode() const { return false; } | virtual bool maintenanceMode() const { return false; } | |||
/* Return true if command should be permitted when a replica set se condary is in "recovering" | /* Return true if command should be permitted when a replica set se condary is in "recovering" | |||
(unreadable) state. | (unreadable) state. | |||
*/ | */ | |||
virtual bool maintenanceOk() const { return true; /* assumed true p rior to commit */ } | virtual bool maintenanceOk() const { return true; /* assumed true p rior to commit */ } | |||
skipping to change at line 200 | skipping to change at line 217 | |||
static void execCommandClientBasic(Command* c, | static void execCommandClientBasic(Command* c, | |||
ClientBasic& client, | ClientBasic& client, | |||
int queryOptions, | int queryOptions, | |||
const char *ns, | const char *ns, | |||
BSONObj& cmdObj, | BSONObj& cmdObj, | |||
BSONObjBuilder& result, | BSONObjBuilder& result, | |||
bool fromRepl ); | bool fromRepl ); | |||
// Helper for setting errmsg and ok field in command result object. | // Helper for setting errmsg and ok field in command result object. | |||
static void appendCommandStatus(BSONObjBuilder& result, bool ok, co nst std::string& errmsg); | static void appendCommandStatus(BSONObjBuilder& result, bool ok, co nst std::string& errmsg); | |||
static void appendCommandStatus(BSONObjBuilder& result, const Statu s& status); | ||||
// Set by command line. Controls whether or not testing-only comma nds should be available. | // Set by command line. Controls whether or not testing-only comma nds should be available. | |||
static int testCommandsEnabled; | static int testCommandsEnabled; | |||
private: | ||||
/** | ||||
* Checks to see if the client is authorized to run the given comma | ||||
nd with the given | ||||
* parameters on the given named database. | ||||
* | ||||
* fromRepl is true if this command is running as part of oplog app | ||||
lication, which for | ||||
* historic reasons has slightly different authorization semantics. | ||||
TODO(schwerin): Check | ||||
* to see if this oddity can now be eliminated. | ||||
* | ||||
* Returns Status::OK() if the command is authorized. Most likely | ||||
returns | ||||
* ErrorCodes::Unauthorized otherwise, but any return other than St | ||||
atus::OK implies not | ||||
* authorized. | ||||
*/ | ||||
static Status _checkAuthorization(Command* c, | ||||
ClientBasic* client, | ||||
const std::string& dbname, | ||||
const BSONObj& cmdObj, | ||||
bool fromRepl); | ||||
}; | }; | |||
bool _runCommands(const char *ns, BSONObj& jsobj, BufBuilder &b, BSONOb jBuilder& anObjBuilder, bool fromRepl, int queryOptions); | bool _runCommands(const char *ns, BSONObj& jsobj, BufBuilder &b, BSONOb jBuilder& anObjBuilder, bool fromRepl, int queryOptions); | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 6 change blocks. | ||||
1 lines changed or deleted | 48 lines changed or added | |||
compiler.h | compiler.h | |||
---|---|---|---|---|
// @file mongo/platform/compiler.h | // Copyright 2012 the V8 project authors. All rights reserved. | |||
// Redistribution and use in source and binary forms, with or without | ||||
// modification, are permitted provided that the following conditions are | ||||
// met: | ||||
// | ||||
// * Redistributions of source code must retain the above copyright | ||||
// notice, this list of conditions and the following disclaimer. | ||||
// * Redistributions in binary form must reproduce the above | ||||
// copyright notice, this list of conditions and the following | ||||
// disclaimer in the documentation and/or other materials provided | ||||
// with the distribution. | ||||
// * Neither the name of Google Inc. nor the names of its | ||||
// contributors may be used to endorse or promote products derived | ||||
// from this software without specific prior written permission. | ||||
// | ||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
/* | #ifndef V8_COMPILER_H_ | |||
* Copyright 2012 10gen Inc. | #define V8_COMPILER_H_ | |||
* | ||||
* Licensed under the Apache License, Version 2.0 (the "License"); | #include "allocation.h" | |||
* you may not use this file except in compliance with the License. | #include "ast.h" | |||
* You may obtain a copy of the License at | #include "zone.h" | |||
* | ||||
* http://www.apache.org/licenses/LICENSE-2.0 | namespace v8 { | |||
* | namespace internal { | |||
* Unless required by applicable law or agreed to in writing, software | ||||
* distributed under the License is distributed on an "AS IS" BASIS, | class ScriptDataImpl; | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
* See the License for the specific language governing permissions and | // CompilationInfo encapsulates some information known at compile time. It | |||
* limitations under the License. | // is constructed based on the resources available at compile-time. | |||
*/ | class CompilationInfo { | |||
public: | ||||
#pragma once | CompilationInfo(Handle<Script> script, Zone* zone); | |||
CompilationInfo(Handle<SharedFunctionInfo> shared_info, Zone* zone); | ||||
/** | CompilationInfo(Handle<JSFunction> closure, Zone* zone); | |||
* Include "mongo/platform/compiler.h" to get compiler-specific macro defin | ||||
itions and utilities. | virtual ~CompilationInfo(); | |||
*/ | ||||
Isolate* isolate() { | ||||
#if defined(_MSC_VER) | ASSERT(Isolate::Current() == isolate_); | |||
#include "mongo/platform/compiler_msvc.h" | return isolate_; | |||
#elif defined(__GNUC__) | } | |||
#include "mongo/platform/compiler_gcc.h" | Zone* zone() { | |||
#else | return zone_; | |||
#error "Unsupported compiler family" | } | |||
bool is_lazy() const { return IsLazy::decode(flags_); } | ||||
bool is_eval() const { return IsEval::decode(flags_); } | ||||
bool is_global() const { return IsGlobal::decode(flags_); } | ||||
bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; } | ||||
bool is_extended_mode() const { return language_mode() == EXTENDED_MODE; | ||||
} | ||||
LanguageMode language_mode() const { | ||||
return LanguageModeField::decode(flags_); | ||||
} | ||||
bool is_in_loop() const { return IsInLoop::decode(flags_); } | ||||
FunctionLiteral* function() const { return function_; } | ||||
Scope* scope() const { return scope_; } | ||||
Scope* global_scope() const { return global_scope_; } | ||||
Handle<Code> code() const { return code_; } | ||||
Handle<JSFunction> closure() const { return closure_; } | ||||
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; } | ||||
Handle<Script> script() const { return script_; } | ||||
v8::Extension* extension() const { return extension_; } | ||||
ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; } | ||||
Handle<Context> calling_context() const { return calling_context_; } | ||||
int osr_ast_id() const { return osr_ast_id_; } | ||||
void MarkAsEval() { | ||||
ASSERT(!is_lazy()); | ||||
flags_ |= IsEval::encode(true); | ||||
} | ||||
void MarkAsGlobal() { | ||||
ASSERT(!is_lazy()); | ||||
flags_ |= IsGlobal::encode(true); | ||||
} | ||||
void SetLanguageMode(LanguageMode language_mode) { | ||||
ASSERT(this->language_mode() == CLASSIC_MODE || | ||||
this->language_mode() == language_mode || | ||||
language_mode == EXTENDED_MODE); | ||||
flags_ = LanguageModeField::update(flags_, language_mode); | ||||
} | ||||
void MarkAsInLoop() { | ||||
ASSERT(is_lazy()); | ||||
flags_ |= IsInLoop::encode(true); | ||||
} | ||||
void MarkAsNative() { | ||||
flags_ |= IsNative::encode(true); | ||||
} | ||||
bool is_native() const { | ||||
return IsNative::decode(flags_); | ||||
} | ||||
void SetFunction(FunctionLiteral* literal) { | ||||
ASSERT(function_ == NULL); | ||||
function_ = literal; | ||||
} | ||||
void SetScope(Scope* scope) { | ||||
ASSERT(scope_ == NULL); | ||||
scope_ = scope; | ||||
} | ||||
void SetGlobalScope(Scope* global_scope) { | ||||
ASSERT(global_scope_ == NULL); | ||||
global_scope_ = global_scope; | ||||
} | ||||
void SetCode(Handle<Code> code) { code_ = code; } | ||||
void SetExtension(v8::Extension* extension) { | ||||
ASSERT(!is_lazy()); | ||||
extension_ = extension; | ||||
} | ||||
void SetPreParseData(ScriptDataImpl* pre_parse_data) { | ||||
ASSERT(!is_lazy()); | ||||
pre_parse_data_ = pre_parse_data; | ||||
} | ||||
void SetCallingContext(Handle<Context> context) { | ||||
ASSERT(is_eval()); | ||||
calling_context_ = context; | ||||
} | ||||
void SetOsrAstId(int osr_ast_id) { | ||||
ASSERT(IsOptimizing()); | ||||
osr_ast_id_ = osr_ast_id; | ||||
} | ||||
void MarkCompilingForDebugging(Handle<Code> current_code) { | ||||
ASSERT(mode_ != OPTIMIZE); | ||||
ASSERT(current_code->kind() == Code::FUNCTION); | ||||
flags_ |= IsCompilingForDebugging::encode(true); | ||||
if (current_code->is_compiled_optimizable()) { | ||||
EnableDeoptimizationSupport(); | ||||
} else { | ||||
mode_ = CompilationInfo::NONOPT; | ||||
} | ||||
} | ||||
bool IsCompilingForDebugging() { | ||||
return IsCompilingForDebugging::decode(flags_); | ||||
} | ||||
bool has_global_object() const { | ||||
return !closure().is_null() && (closure()->context()->global() != NULL) | ||||
; | ||||
} | ||||
GlobalObject* global_object() const { | ||||
return has_global_object() ? closure()->context()->global() : NULL; | ||||
} | ||||
// Accessors for the different compilation modes. | ||||
bool IsOptimizing() const { return mode_ == OPTIMIZE; } | ||||
bool IsOptimizable() const { return mode_ == BASE; } | ||||
void SetOptimizing(int osr_ast_id) { | ||||
SetMode(OPTIMIZE); | ||||
osr_ast_id_ = osr_ast_id; | ||||
} | ||||
void DisableOptimization(); | ||||
// Deoptimization support. | ||||
bool HasDeoptimizationSupport() const { | ||||
return SupportsDeoptimization::decode(flags_); | ||||
} | ||||
void EnableDeoptimizationSupport() { | ||||
ASSERT(IsOptimizable()); | ||||
flags_ |= SupportsDeoptimization::encode(true); | ||||
} | ||||
// Determines whether or not to insert a self-optimization header. | ||||
bool ShouldSelfOptimize(); | ||||
// Disable all optimization attempts of this info for the rest of the | ||||
// current compilation pipeline. | ||||
void AbortOptimization(); | ||||
void set_deferred_handles(DeferredHandles* deferred_handles) { | ||||
ASSERT(deferred_handles_ == NULL); | ||||
deferred_handles_ = deferred_handles; | ||||
} | ||||
void SaveHandles() { | ||||
SaveHandle(&closure_); | ||||
SaveHandle(&shared_info_); | ||||
SaveHandle(&calling_context_); | ||||
SaveHandle(&script_); | ||||
} | ||||
private: | ||||
Isolate* isolate_; | ||||
// Compilation mode. | ||||
// BASE is generated by the full codegen, optionally prepared for bailout | ||||
s. | ||||
// OPTIMIZE is optimized code generated by the Hydrogen-based backend. | ||||
// NONOPT is generated by the full codegen and is not prepared for | ||||
// recompilation/bailouts. These functions are never recompiled. | ||||
enum Mode { | ||||
BASE, | ||||
OPTIMIZE, | ||||
NONOPT | ||||
}; | ||||
void Initialize(Mode mode) { | ||||
mode_ = V8::UseCrankshaft() ? mode : NONOPT; | ||||
ASSERT(!script_.is_null()); | ||||
if (script_->type()->value() == Script::TYPE_NATIVE) { | ||||
MarkAsNative(); | ||||
} | ||||
if (!shared_info_.is_null()) { | ||||
ASSERT(language_mode() == CLASSIC_MODE); | ||||
SetLanguageMode(shared_info_->language_mode()); | ||||
} | ||||
} | ||||
void SetMode(Mode mode) { | ||||
ASSERT(V8::UseCrankshaft()); | ||||
mode_ = mode; | ||||
} | ||||
// Flags using template class BitField<type, start, length>. All are | ||||
// false by default. | ||||
// | ||||
// Compilation is either eager or lazy. | ||||
class IsLazy: public BitField<bool, 0, 1> {}; | ||||
// Flags that can be set for eager compilation. | ||||
class IsEval: public BitField<bool, 1, 1> {}; | ||||
class IsGlobal: public BitField<bool, 2, 1> {}; | ||||
// Flags that can be set for lazy compilation. | ||||
class IsInLoop: public BitField<bool, 3, 1> {}; | ||||
// Strict mode - used in eager compilation. | ||||
class LanguageModeField: public BitField<LanguageMode, 4, 2> {}; | ||||
// Is this a function from our natives. | ||||
class IsNative: public BitField<bool, 6, 1> {}; | ||||
// Is this code being compiled with support for deoptimization.. | ||||
class SupportsDeoptimization: public BitField<bool, 7, 1> {}; | ||||
// If compiling for debugging produce just full code matching the | ||||
// initial mode setting. | ||||
class IsCompilingForDebugging: public BitField<bool, 8, 1> {}; | ||||
unsigned flags_; | ||||
// Fields filled in by the compilation pipeline. | ||||
// AST filled in by the parser. | ||||
FunctionLiteral* function_; | ||||
// The scope of the function literal as a convenience. Set to indicate | ||||
// that scopes have been analyzed. | ||||
Scope* scope_; | ||||
// The global scope provided as a convenience. | ||||
Scope* global_scope_; | ||||
// The compiled code. | ||||
Handle<Code> code_; | ||||
// Possible initial inputs to the compilation process. | ||||
Handle<JSFunction> closure_; | ||||
Handle<SharedFunctionInfo> shared_info_; | ||||
Handle<Script> script_; | ||||
// Fields possibly needed for eager compilation, NULL by default. | ||||
v8::Extension* extension_; | ||||
ScriptDataImpl* pre_parse_data_; | ||||
// The context of the caller is needed for eval code, and will be a null | ||||
// handle otherwise. | ||||
Handle<Context> calling_context_; | ||||
// Compilation mode flag and whether deoptimization is allowed. | ||||
Mode mode_; | ||||
int osr_ast_id_; | ||||
// The zone from which the compilation pipeline working on this | ||||
// CompilationInfo allocates. | ||||
Zone* zone_; | ||||
DeferredHandles* deferred_handles_; | ||||
template<typename T> | ||||
void SaveHandle(Handle<T> *object) { | ||||
if (!object->is_null()) { | ||||
Handle<T> handle(*(*object)); | ||||
*object = handle; | ||||
} | ||||
} | ||||
DISALLOW_COPY_AND_ASSIGN(CompilationInfo); | ||||
}; | ||||
// Exactly like a CompilationInfo, except also creates and enters a | ||||
// Zone on construction and deallocates it on exit. | ||||
class CompilationInfoWithZone: public CompilationInfo { | ||||
public: | ||||
explicit CompilationInfoWithZone(Handle<Script> script) | ||||
: CompilationInfo(script, &zone_), | ||||
zone_(script->GetIsolate()), | ||||
zone_scope_(&zone_, DELETE_ON_EXIT) {} | ||||
explicit CompilationInfoWithZone(Handle<SharedFunctionInfo> shared_info) | ||||
: CompilationInfo(shared_info, &zone_), | ||||
zone_(shared_info->GetIsolate()), | ||||
zone_scope_(&zone_, DELETE_ON_EXIT) {} | ||||
explicit CompilationInfoWithZone(Handle<JSFunction> closure) | ||||
: CompilationInfo(closure, &zone_), | ||||
zone_(closure->GetIsolate()), | ||||
zone_scope_(&zone_, DELETE_ON_EXIT) {} | ||||
private: | ||||
Zone zone_; | ||||
ZoneScope zone_scope_; | ||||
}; | ||||
// A wrapper around a CompilationInfo that detaches the Handles from | ||||
// the underlying DeferredHandleScope and stores them in info_ on | ||||
// destruction. | ||||
class CompilationHandleScope BASE_EMBEDDED { | ||||
public: | ||||
explicit CompilationHandleScope(CompilationInfo* info) | ||||
: deferred_(info->isolate()), info_(info) {} | ||||
~CompilationHandleScope() { | ||||
info_->set_deferred_handles(deferred_.Detach()); | ||||
} | ||||
private: | ||||
DeferredHandleScope deferred_; | ||||
CompilationInfo* info_; | ||||
}; | ||||
class HGraph; | ||||
class HGraphBuilder; | ||||
class LChunk; | ||||
// A helper class that calls the three compilation phases in | ||||
// Crankshaft and keeps track of its state. The three phases | ||||
// CreateGraph, OptimizeGraph and GenerateAndInstallCode can either | ||||
// fail, bail-out to the full code generator or succeed. Apart from | ||||
// their return value, the status of the phase last run can be checked | ||||
// using last_status(). | ||||
class OptimizingCompiler: public ZoneObject { | ||||
public: | ||||
explicit OptimizingCompiler(CompilationInfo* info) | ||||
: info_(info), | ||||
oracle_(NULL), | ||||
graph_builder_(NULL), | ||||
graph_(NULL), | ||||
chunk_(NULL), | ||||
time_taken_to_create_graph_(0), | ||||
time_taken_to_optimize_(0), | ||||
time_taken_to_codegen_(0), | ||||
last_status_(FAILED) { } | ||||
enum Status { | ||||
FAILED, BAILED_OUT, SUCCEEDED | ||||
}; | ||||
MUST_USE_RESULT Status CreateGraph(); | ||||
MUST_USE_RESULT Status OptimizeGraph(); | ||||
MUST_USE_RESULT Status GenerateAndInstallCode(); | ||||
Status last_status() const { return last_status_; } | ||||
CompilationInfo* info() const { return info_; } | ||||
MUST_USE_RESULT Status AbortOptimization() { | ||||
info_->AbortOptimization(); | ||||
info_->shared_info()->DisableOptimization(); | ||||
return SetLastStatus(BAILED_OUT); | ||||
} | ||||
private: | ||||
CompilationInfo* info_; | ||||
TypeFeedbackOracle* oracle_; | ||||
HGraphBuilder* graph_builder_; | ||||
HGraph* graph_; | ||||
LChunk* chunk_; | ||||
int64_t time_taken_to_create_graph_; | ||||
int64_t time_taken_to_optimize_; | ||||
int64_t time_taken_to_codegen_; | ||||
Status last_status_; | ||||
MUST_USE_RESULT Status SetLastStatus(Status status) { | ||||
last_status_ = status; | ||||
return last_status_; | ||||
} | ||||
void RecordOptimizationStats(); | ||||
struct Timer { | ||||
Timer(OptimizingCompiler* compiler, int64_t* location) | ||||
: compiler_(compiler), | ||||
start_(OS::Ticks()), | ||||
location_(location) { } | ||||
~Timer() { | ||||
*location_ += (OS::Ticks() - start_); | ||||
} | ||||
OptimizingCompiler* compiler_; | ||||
int64_t start_; | ||||
int64_t* location_; | ||||
}; | ||||
}; | ||||
// The V8 compiler | ||||
// | ||||
// General strategy: Source code is translated into an anonymous function w | ||||
/o | ||||
// parameters which then can be executed. If the source code contains other | ||||
// functions, they will be compiled and allocated as part of the compilatio | ||||
n | ||||
// of the source code. | ||||
// Please note this interface returns shared function infos. This means yo | ||||
u | ||||
// need to call Factory::NewFunctionFromSharedFunctionInfo before you have | ||||
a | ||||
// real function with a context. | ||||
class Compiler : public AllStatic { | ||||
public: | ||||
// Default maximum number of function optimization attempts before we | ||||
// give up. | ||||
static const int kDefaultMaxOptCount = 10; | ||||
static const int kMaxInliningLevels = 3; | ||||
// Call count before primitive functions trigger their own optimization. | ||||
static const int kCallsUntilPrimitiveOpt = 200; | ||||
// All routines return a SharedFunctionInfo. | ||||
// If an error occurs an exception is raised and the return handle | ||||
// contains NULL. | ||||
// Compile a String source within a context. | ||||
static Handle<SharedFunctionInfo> Compile(Handle<String> source, | ||||
Handle<Object> script_name, | ||||
int line_offset, | ||||
int column_offset, | ||||
v8::Extension* extension, | ||||
ScriptDataImpl* pre_data, | ||||
Handle<Object> script_data, | ||||
NativesFlag is_natives_code); | ||||
// Compile a String source within a context for Eval. | ||||
static Handle<SharedFunctionInfo> CompileEval(Handle<String> source, | ||||
Handle<Context> context, | ||||
bool is_global, | ||||
LanguageMode language_mode, | ||||
int scope_position); | ||||
// Compile from function info (used for lazy compilation). Returns true o | ||||
n | ||||
// success and false if the compilation resulted in a stack overflow. | ||||
static bool CompileLazy(CompilationInfo* info); | ||||
static void RecompileParallel(Handle<JSFunction> function); | ||||
// Compile a shared function info object (the function is possibly lazily | ||||
// compiled). | ||||
static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node | ||||
, | ||||
Handle<Script> script | ||||
); | ||||
// Set the function info for a newly compiled function. | ||||
static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info, | ||||
FunctionLiteral* lit, | ||||
bool is_toplevel, | ||||
Handle<Script> script); | ||||
static void InstallOptimizedCode(OptimizingCompiler* info); | ||||
#ifdef ENABLE_DEBUGGER_SUPPORT | ||||
static bool MakeCodeForLiveEdit(CompilationInfo* info); | ||||
#endif | #endif | |||
static void RecordFunctionCompilation(Logger::LogEventsAndTags tag, | ||||
CompilationInfo* info, | ||||
Handle<SharedFunctionInfo> shared); | ||||
}; | ||||
} } // namespace v8::internal | ||||
#endif // V8_COMPILER_H_ | ||||
End of changes. 3 change blocks. | ||||
30 lines changed or deleted | 471 lines changed or added | |||
count.h | count.h | |||
---|---|---|---|---|
skipping to change at line 19 | skipping to change at line 19 | |||
* | * | |||
* This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Lice nse | * You should have received a copy of the GNU Affero General Public Lice nse | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#include "../jsobj.h" | #include "mongo/db/diskloc.h" | |||
#include "../diskloc.h" | #include "mongo/db/jsobj.h" | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* { count: "collectionname"[, query: <query>] } | * { count: "collectionname"[, query: <query>] } | |||
* @return -1 on ns does not exist error and other errors, 0 on other e rrors, otherwise the match count. | * @return -1 on ns does not exist error and other errors, 0 on other e rrors, otherwise the match count. | |||
*/ | */ | |||
long long runCount(const char *ns, const BSONObj& cmd, string& err, int & errCode ); | long long runCount(const char *ns, const BSONObj& cmd, string& err, int & errCode ); | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 1 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
counters.h | counters.h | |||
---|---|---|---|---|
// Copyright 2012 the V8 project authors. All rights reserved. | // counters.h | |||
// Redistribution and use in source and binary forms, with or without | /* | |||
// modification, are permitted provided that the following conditions are | * Copyright (C) 2010 10gen Inc. | |||
// met: | * | |||
// | * This program is free software: you can redistribute it and/or modify | |||
// * Redistributions of source code must retain the above copyright | * it under the terms of the GNU Affero General Public License, version | |||
// notice, this list of conditions and the following disclaimer. | 3, | |||
// * Redistributions in binary form must reproduce the above | * as published by the Free Software Foundation. | |||
// copyright notice, this list of conditions and the following | * | |||
// disclaimer in the documentation and/or other materials provided | * This program is distributed in the hope that it will be useful, | |||
// with the distribution. | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// * Neither the name of Google Inc. nor the names of its | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// contributors may be used to endorse or promote products derived | * GNU Affero General Public License for more details. | |||
// from this software without specific prior written permission. | * | |||
// | * You should have received a copy of the GNU Affero General Public Lice | |||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | nse | |||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | */ | |||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | #pragma once | |||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | #include "mongo/pch.h" | |||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | #include "../jsobj.h" | |||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | #include "../../util/net/message.h" | |||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | #include "../../util/processinfo.h" | |||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | #include "../../util/concurrency/spin_lock.h" | |||
#include "mongo/db/pdfile.h" | ||||
#ifndef V8_COUNTERS_H_ | ||||
#define V8_COUNTERS_H_ | namespace mongo { | |||
#include "../include/v8.h" | /** | |||
#include "allocation.h" | * for storing operation counters | |||
* note: not thread safe. ok with that for speed | ||||
namespace v8 { | */ | |||
namespace internal { | class OpCounters { | |||
public: | ||||
// StatsCounters is an interface for plugging into external | ||||
// counters for monitoring. Counters can be looked up and | OpCounters(); | |||
// manipulated by name. | void incInsertInWriteLock(int n) { _insert.x += n; } | |||
void gotInsert() { _insert++; } | ||||
class StatsTable { | void gotQuery() { _query++; } | |||
public: | void gotUpdate() { _update++; } | |||
// Register an application-defined function where | void gotDelete() { _delete++; } | |||
// counters can be looked up. | void gotGetMore() { _getmore++; } | |||
void SetCounterFunction(CounterLookupCallback f) { | void gotCommand() { _command++; } | |||
lookup_function_ = f; | ||||
} | void gotOp( int op , bool isCommand ); | |||
// Register an application-defined function to create | BSONObj getObj() const; | |||
// a histogram for passing to the AddHistogramSample function | ||||
void SetCreateHistogramFunction(CreateHistogramCallback f) { | // thse are used by snmp, and other things, do not remove | |||
create_histogram_function_ = f; | const AtomicUInt * getInsert() const { return &_insert; } | |||
} | const AtomicUInt * getQuery() const { return &_query; } | |||
const AtomicUInt * getUpdate() const { return &_update; } | ||||
// Register an application-defined function to add a sample | const AtomicUInt * getDelete() const { return &_delete; } | |||
// to a histogram created with CreateHistogram function | const AtomicUInt * getGetMore() const { return &_getmore; } | |||
void SetAddHistogramSampleFunction(AddHistogramSampleCallback f) { | const AtomicUInt * getCommand() const { return &_command; } | |||
add_histogram_sample_function_ = f; | ||||
} | private: | |||
void _checkWrap(); | ||||
bool HasCounterFunction() const { | ||||
return lookup_function_ != NULL; | // todo: there will be a lot of cache line contention on these. ne | |||
} | ed to do something | |||
// else eventually. | ||||
// Lookup the location of a counter by name. If the lookup | AtomicUInt _insert; | |||
// is successful, returns a non-NULL pointer for writing the | AtomicUInt _query; | |||
// value of the counter. Each thread calling this function | AtomicUInt _update; | |||
// may receive a different location to store it's counter. | AtomicUInt _delete; | |||
// The return value must not be cached and re-used across | AtomicUInt _getmore; | |||
// threads, although a single thread is free to cache it. | AtomicUInt _command; | |||
int* FindLocation(const char* name) { | }; | |||
if (!lookup_function_) return NULL; | ||||
return lookup_function_(name); | extern OpCounters globalOpCounters; | |||
} | extern OpCounters replOpCounters; | |||
// Create a histogram by name. If the create is successful, | class NetworkCounter { | |||
// returns a non-NULL pointer for use with AddHistogramSample | public: | |||
// function. min and max define the expected minimum and maximum | NetworkCounter() : _bytesIn(0), _bytesOut(0), _requests(0), _overfl | |||
// sample values. buckets is the maximum number of buckets | ows(0) {} | |||
// that the samples will be grouped into. | void hit( long long bytesIn , long long bytesOut ); | |||
void* CreateHistogram(const char* name, | void append( BSONObjBuilder& b ); | |||
int min, | private: | |||
int max, | long long _bytesIn; | |||
size_t buckets) { | long long _bytesOut; | |||
if (!create_histogram_function_) return NULL; | long long _requests; | |||
return create_histogram_function_(name, min, max, buckets); | ||||
} | ||||
// Add a sample to a histogram created with the CreateHistogram | ||||
// function. | ||||
void AddHistogramSample(void* histogram, int sample) { | ||||
if (!add_histogram_sample_function_) return; | ||||
return add_histogram_sample_function_(histogram, sample); | ||||
} | ||||
private: | ||||
StatsTable(); | ||||
CounterLookupCallback lookup_function_; | ||||
CreateHistogramCallback create_histogram_function_; | ||||
AddHistogramSampleCallback add_histogram_sample_function_; | ||||
friend class Isolate; | ||||
DISALLOW_COPY_AND_ASSIGN(StatsTable); | ||||
}; | ||||
// StatsCounters are dynamically created values which can be tracked in | ||||
// the StatsTable. They are designed to be lightweight to create and | ||||
// easy to use. | ||||
// | ||||
// Internally, a counter represents a value in a row of a StatsTable. | ||||
// The row has a 32bit value for each process/thread in the table and also | ||||
// a name (stored in the table metadata). Since the storage location can b | ||||
e | ||||
// thread-specific, this class cannot be shared across threads. | ||||
// | ||||
// This class is designed to be POD initialized. It will be registered wit | ||||
h | ||||
// the counter system on first use. For example: | ||||
// StatsCounter c = { "c:myctr", NULL, false }; | ||||
struct StatsCounter { | ||||
const char* name_; | ||||
int* ptr_; | ||||
bool lookup_done_; | ||||
// Sets the counter to a specific value. | ||||
void Set(int value) { | ||||
int* loc = GetPtr(); | ||||
if (loc) *loc = value; | ||||
} | ||||
// Increments the counter. | ||||
void Increment() { | ||||
int* loc = GetPtr(); | ||||
if (loc) (*loc)++; | ||||
} | ||||
void Increment(int value) { | ||||
int* loc = GetPtr(); | ||||
if (loc) | ||||
(*loc) += value; | ||||
} | ||||
// Decrements the counter. | ||||
void Decrement() { | ||||
int* loc = GetPtr(); | ||||
if (loc) (*loc)--; | ||||
} | ||||
void Decrement(int value) { | ||||
int* loc = GetPtr(); | ||||
if (loc) (*loc) -= value; | ||||
} | ||||
// Is this counter enabled? | ||||
// Returns false if table is full. | ||||
bool Enabled() { | ||||
return GetPtr() != NULL; | ||||
} | ||||
// Get the internal pointer to the counter. This is used | ||||
// by the code generator to emit code that manipulates a | ||||
// given counter without calling the runtime system. | ||||
int* GetInternalPointer() { | ||||
int* loc = GetPtr(); | ||||
ASSERT(loc != NULL); | ||||
return loc; | ||||
} | ||||
protected: | ||||
// Returns the cached address of this counter location. | ||||
int* GetPtr() { | ||||
if (lookup_done_) return ptr_; | ||||
lookup_done_ = true; | ||||
ptr_ = FindLocationInStatsTable(); | ||||
return ptr_; | ||||
} | ||||
private: | ||||
int* FindLocationInStatsTable() const; | ||||
}; | ||||
// StatsCounterTimer t = { { L"t:foo", NULL, false }, 0, 0 }; | ||||
struct StatsCounterTimer { | ||||
StatsCounter counter_; | ||||
int64_t start_time_; | ||||
int64_t stop_time_; | ||||
// Start the timer. | ||||
void Start(); | ||||
// Stop the timer and record the results. | ||||
void Stop(); | ||||
// Returns true if the timer is running. | ||||
bool Running() { | ||||
return counter_.Enabled() && start_time_ != 0 && stop_time_ == 0; | ||||
} | ||||
}; | ||||
// A Histogram represents a dynamically created histogram in the StatsTable | ||||
. | ||||
// | ||||
// This class is designed to be POD initialized. It will be registered wit | ||||
h | ||||
// the histogram system on first use. For example: | ||||
// Histogram h = { "myhist", 0, 10000, 50, NULL, false }; | ||||
struct Histogram { | ||||
const char* name_; | ||||
int min_; | ||||
int max_; | ||||
int num_buckets_; | ||||
void* histogram_; | ||||
bool lookup_done_; | ||||
// Add a single sample to this histogram. | ||||
void AddSample(int sample); | ||||
// Returns true if this histogram is enabled. | ||||
bool Enabled() { | ||||
return GetHistogram() != NULL; | ||||
} | ||||
protected: | ||||
// Returns the handle to the histogram. | ||||
void* GetHistogram() { | ||||
if (!lookup_done_) { | ||||
lookup_done_ = true; | ||||
histogram_ = CreateHistogram(); | ||||
} | ||||
return histogram_; | ||||
} | ||||
private: | ||||
void* CreateHistogram() const; | ||||
}; | ||||
// A HistogramTimer allows distributions of results to be created | ||||
// HistogramTimer t = { {L"foo", 0, 10000, 50, NULL, false}, 0, 0 }; | ||||
struct HistogramTimer { | ||||
Histogram histogram_; | ||||
int64_t start_time_; | ||||
int64_t stop_time_; | ||||
// Start the timer. | ||||
void Start(); | ||||
// Stop the timer and record the results. | ||||
void Stop(); | ||||
// Returns true if the timer is running. | ||||
bool Running() { | ||||
return histogram_.Enabled() && (start_time_ != 0) && (stop_time_ == 0); | ||||
} | ||||
}; | ||||
// Helper class for scoping a HistogramTimer. | ||||
class HistogramTimerScope BASE_EMBEDDED { | ||||
public: | ||||
explicit HistogramTimerScope(HistogramTimer* timer) : | ||||
timer_(timer) { | ||||
timer_->Start(); | ||||
} | ||||
~HistogramTimerScope() { | ||||
timer_->Stop(); | ||||
} | ||||
private: | ||||
HistogramTimer* timer_; | ||||
}; | ||||
} } // namespace v8::internal | long long _overflows; | |||
#endif // V8_COUNTERS_H_ | SpinLock _lock; | |||
}; | ||||
extern NetworkCounter networkCounter; | ||||
} | ||||
End of changes. 3 change blocks. | ||||
273 lines changed or deleted | 86 lines changed or added | |||
curop-inl.h | curop-inl.h | |||
---|---|---|---|---|
skipping to change at line 17 | skipping to change at line 17 | |||
* | * | |||
* This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public 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 "curop.h" | #include "mongo/db/curop.h" | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 0 lines changed or added | |||
curop.h | curop.h | |||
---|---|---|---|---|
skipping to change at line 82 | skipping to change at line 82 | |||
// detailed options | // detailed options | |||
long long cursorid; | long long cursorid; | |||
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 (including no-ops | |||
) | ||||
long long nupdateNoops; // number of records updated which were no | ||||
ops | ||||
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 ninserted; | |||
long long ndeleted; | 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; | |||
skipping to change at line 177 | skipping to change at line 178 | |||
*/ | */ | |||
class CurOp : boost::noncopyable { | class CurOp : boost::noncopyable { | |||
public: | public: | |||
CurOp( Client * client , CurOp * wrapped = 0 ); | CurOp( Client * client , CurOp * wrapped = 0 ); | |||
~CurOp(); | ~CurOp(); | |||
bool haveQuery() const { return _query.have(); } | bool haveQuery() const { return _query.have(); } | |||
BSONObj query() const { return _query.get(); } | BSONObj query() const { return _query.get(); } | |||
void appendQuery( BSONObjBuilder& b , const StringData& name ) cons t { _query.append( b , name ); } | void appendQuery( BSONObjBuilder& b , const StringData& name ) cons t { _query.append( b , name ); } | |||
void ensureStarted(); | ||||
bool isStarted() const { return _start > 0; } | ||||
void enter( Client::Context * context ); | void enter( Client::Context * context ); | |||
void leave( Client::Context * context ); | void leave( Client::Context * context ); | |||
void reset(); | void reset(); | |||
void reset( const HostAndPort& remote, int op ); | void reset( const HostAndPort& remote, int op ); | |||
void markCommand() { _command = true; } | void markCommand() { _command = true; } | |||
OpDebug& debug() { return _debug; } | OpDebug& debug() { return _debug; } | |||
int profileLevel() const { return _dbprofile; } | int profileLevel() const { return _dbprofile; } | |||
const char * getNS() const { return _ns; } | const char * getNS() const { return _ns; } | |||
bool shouldDBProfile( int ms ) const { | bool shouldDBProfile( int ms ) const { | |||
skipping to change at line 202 | skipping to change at line 201 | |||
return _dbprofile >= 2 || ms >= cmdLine.slowMS; | return _dbprofile >= 2 || ms >= cmdLine.slowMS; | |||
} | } | |||
AtomicUInt opNum() const { return _opNum; } | AtomicUInt opNum() const { return _opNum; } | |||
/** if this op is running */ | /** if this op is running */ | |||
bool active() const { return _active; } | bool active() const { return _active; } | |||
bool displayInCurop() const { return _active && ! _suppressFromCuro p; } | bool displayInCurop() const { return _active && ! _suppressFromCuro p; } | |||
int getOp() const { return _op; } | int getOp() const { return _op; } | |||
// | ||||
// Methods for controlling CurOp "max time". | ||||
// | ||||
/** | ||||
* Sets the amount of time operation this should be allowed to run, | ||||
units of microseconds. | ||||
* The special value 0 is "allow to run indefinitely". | ||||
*/ | ||||
void setMaxTimeMicros(uint64_t maxTimeMicros); | ||||
/** | ||||
* Checks whether this operation has been running longer than its t | ||||
ime limit. Returns | ||||
* false if not, or if the operation has no time limit. | ||||
* | ||||
* Note that KillCurrentOp objects are responsible for interrupting | ||||
CurOp objects that | ||||
* have exceeded their allotted time; CurOp objects do not interrup | ||||
t themselves. | ||||
*/ | ||||
bool maxTimeHasExpired(); | ||||
/** | ||||
* Returns the number of microseconds remaining for this operation' | ||||
s time limit, or the | ||||
* special value 0 if the operation has no time limit. | ||||
* | ||||
* Calling this method is more expensive than calling its sibling " | ||||
maxTimeHasExpired()", | ||||
* since an accurate measure of remaining time needs to be calculat | ||||
ed. | ||||
*/ | ||||
uint64_t getRemainingMaxTimeMicros() const; | ||||
// | ||||
// Methods for getting/setting elapsed time. | ||||
// | ||||
void ensureStarted(); | ||||
bool isStarted() const { return _start > 0; } | ||||
unsigned long long startTime() { // micros | unsigned long long startTime() { // micros | |||
ensureStarted(); | ensureStarted(); | |||
return _start; | return _start; | |||
} | } | |||
void done() { | void done() { | |||
_active = false; | _active = false; | |||
_end = curTimeMicros64(); | _end = curTimeMicros64(); | |||
} | } | |||
unsigned long long totalTimeMicros() { | unsigned long long totalTimeMicros() { | |||
massert( 12601 , "CurOp not marked done yet" , ! _active ); | massert( 12601 , "CurOp not marked done yet" , ! _active ); | |||
return _end - startTime(); | return _end - startTime(); | |||
} | } | |||
int totalTimeMillis() { return (int) (totalTimeMicros() / 1000); } | int totalTimeMillis() { return (int) (totalTimeMicros() / 1000); } | |||
unsigned long long elapsedMicros() { | ||||
return curTimeMicros64() - startTime(); | ||||
} | ||||
int elapsedMillis() { | int elapsedMillis() { | |||
unsigned long long total = curTimeMicros64() - startTime(); | return (int) (elapsedMicros() / 1000); | |||
return (int) (total / 1000); | ||||
} | } | |||
int elapsedSeconds() { return elapsedMillis() / 1000; } | int elapsedSeconds() { return elapsedMillis() / 1000; } | |||
void setQuery(const BSONObj& query) { _query.set( query ); } | void setQuery(const BSONObj& query) { _query.set( query ); } | |||
Client * getClient() const { return _client; } | Client * getClient() const { return _client; } | |||
BSONObj info(); | BSONObj info(); | |||
// Fetches less information than "info()"; used to search for ops w ith certain criteria | // Fetches less information than "info()"; used to search for ops w ith certain criteria | |||
BSONObj description(); | BSONObj description(); | |||
string getRemoteString( bool includePort = true ) { return _remote. toString(includePort); } | string getRemoteString( bool includePort = true ) { return _remote. toString(includePort); } | |||
ProgressMeter& setMessage(const char * msg, | ProgressMeter& setMessage(const char * msg, | |||
skipping to change at line 292 | skipping to change at line 330 | |||
AtomicInt32 _killPending; | AtomicInt32 _killPending; | |||
int _numYields; | int _numYields; | |||
LockStat _lockStat; | LockStat _lockStat; | |||
// _notifyList is protected by the global killCurrentOp's mtx. | // _notifyList is protected by the global killCurrentOp's mtx. | |||
std::vector<bool*> _notifyList; | std::vector<bool*> _notifyList; | |||
// this is how much "extra" time a query might take | // this is how much "extra" time a query might take | |||
// a writebacklisten for example will block for 30s | // a writebacklisten for example will block for 30s | |||
// so this should be 30000 in that case | // so this should be 30000 in that case | |||
long long _expectedLatencyMs; | long long _expectedLatencyMs; | |||
/** Nested class that implements a time limit ($maxTimeMS) for a Cu | ||||
rOp object. */ | ||||
class MaxTimeTracker { | ||||
MONGO_DISALLOW_COPYING(MaxTimeTracker); | ||||
public: | ||||
/** Newly-constructed MaxTimeTracker objects have the time limi | ||||
t disabled. */ | ||||
MaxTimeTracker(); | ||||
/** Disables the time limit. */ | ||||
void reset(); | ||||
/** | ||||
* Enables the time limit to be "durationMicros" microseconds f | ||||
rom "startEpochMicros" | ||||
* (units of microseconds since the epoch). | ||||
* | ||||
* "durationMicros" must be nonzero. | ||||
*/ | ||||
void setTimeLimit(uint64_t startEpochMicros, uint64_t durationM | ||||
icros); | ||||
/** | ||||
* Checks whether the time limit has been hit. Returns false i | ||||
f not, or if the time | ||||
* limit is disabled. | ||||
*/ | ||||
bool checkTimeLimit(); | ||||
/** | ||||
* Returns the number of microseconds remaining for the time li | ||||
mit, or the special | ||||
* value 0 if the time limit is disabled. | ||||
* | ||||
* Calling this method is more expensive than calling its sibli | ||||
ng "checkInterval()", | ||||
* since an accurate measure of remaining time needs to be calc | ||||
ulated. | ||||
*/ | ||||
uint64_t getRemainingMicros() const; | ||||
private: | ||||
// Whether or not this operation is subject to a time limit. | ||||
bool _enabled; | ||||
// Point in time at which the time limit is hit. Units of micr | ||||
oseconds since the | ||||
// epoch. | ||||
uint64_t _targetEpochMicros; | ||||
// Approximate point in time at which the time limit is hit. | ||||
Units of milliseconds | ||||
// since the server process was started. | ||||
int64_t _approxTargetServerMillis; | ||||
} _maxTimeTracker; | ||||
}; | }; | |||
} | } | |||
End of changes. 8 change blocks. | ||||
5 lines changed or deleted | 108 lines changed or added | |||
d_logic.h | d_logic.h | |||
---|---|---|---|---|
skipping to change at line 26 | skipping to change at line 26 | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/pch.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/s/collection_metadata.h" | #include "mongo/s/collection_metadata.h" | |||
#include "mongo/s/chunk_version.h" | #include "mongo/s/chunk_version.h" | |||
#include "mongo/util/concurrency/ticketholder.h" | #include "mongo/util/concurrency/ticketholder.h" | |||
#include "mongo/util/net/message.h" | ||||
namespace mongo { | namespace mongo { | |||
class Database; | class Database; | |||
class DiskLoc; | class DiskLoc; | |||
// -------------- | // -------------- | |||
// --- global state --- | // --- global state --- | |||
// -------------- | // -------------- | |||
skipping to change at line 65 | skipping to change at line 66 | |||
/** Reverts back to a state where this mongod is not sharded. */ | /** Reverts back to a state where this mongod is not sharded. */ | |||
void resetShardingState(); | void resetShardingState(); | |||
// versioning support | // versioning support | |||
bool hasVersion( const string& ns ); | bool hasVersion( const string& ns ); | |||
bool hasVersion( const string& ns , ChunkVersion& version ); | bool hasVersion( const string& ns , ChunkVersion& version ); | |||
const ChunkVersion getVersion( const string& ns ) const; | const ChunkVersion getVersion( const string& ns ) const; | |||
/** | /** | |||
* Uninstalls the metadata for a given collection. This should be u | * If the metadata for 'ns' at this shard is at or above the reques | |||
sed when the collection | ted version, | |||
* is dropped. | * 'reqShardVersion', returns OK and fills in 'latestShardVersion' | |||
* | with the latest shard | |||
* NOTE: | * version. The latter is always greater or equal than 'reqShardVe | |||
* An existing collection with no chunks on this shard will have | rsion' if in the same | |||
metadata on version 0, | * epoch. | |||
* which is different than a dropped collection, which will not h | * | |||
ave metadata. | * Otherwise, falls back to refreshMetadataNow. | |||
* | * | |||
* TODO: | * This call blocks if there are more than N threads | |||
* All collections should have metadata. (The non-sharded ones ar | * currently refreshing metadata. (N is the number of | |||
e a degenerate case of | * tickets in ShardingState::_configServerTickets, | |||
* one-chunk collections). | * currently 3.) | |||
* | * | |||
* @param ns the collection to be dropped | * Locking Note: | |||
*/ | * + Must NOT be called with the write lock because this call may | |||
void resetVersion( const string& ns ); | go into the network, | |||
* and deadlocks may occur with shard-as-a-config. Therefore, | ||||
/** | nothing here guarantees | |||
* Requests to access a collection at a certain version. If the col | * that 'latestShardVersion' is indeed the current one on retur | |||
lection's metadata is not | n. | |||
* at that version it will try to update itself to the newest versi | */ | |||
on. The request is only | Status refreshMetadataIfNeeded( const string& ns, | |||
* granted if the version is the current or the newest one. | const ChunkVersion& reqShardVersion | |||
* | , | |||
* @param ns collection to be accessed | ChunkVersion* latestShardVersion ); | |||
* @param version (IN) the client believe this collection is on and | ||||
(OUT) the version the | /** | |||
* metadata is actually in | * Refreshes collection metadata by asking the config server for th | |||
* @return true if the access can be allowed at the provided versio | e latest information. | |||
n | * Starts a new config server request. | |||
* | ||||
* Locking Notes: | ||||
* + Must NOT be called with the write lock because this call may | ||||
go into the network, | ||||
* and deadlocks may occur with shard-as-a-config. Therefore, | ||||
nothing here guarantees | ||||
* that 'latestShardVersion' is indeed the current one on retur | ||||
n. | ||||
* | ||||
* + Because this call must not be issued with the DBLock held, b | ||||
y the time the config | ||||
* server sent us back the collection metadata information, som | ||||
eone else may have | ||||
* updated the previously stored collection metadata. There ar | ||||
e cases when one can't | ||||
* tell which of updated or loaded metadata are the freshest. T | ||||
here are also cases where | ||||
* the data coming from configs do not correspond to a consiste | ||||
nt snapshot. | ||||
* In these cases, return RemoteChangeDetected. (This usually m | ||||
eans this call needs to | ||||
* be issued again, at caller discretion) | ||||
* | ||||
* @return OK if remote metadata successfully loaded (may or may no | ||||
t have been installed) | ||||
* @return RemoteChangeDetected if something changed while reloadin | ||||
g and we may retry | ||||
* @return !OK if something else went wrong during reload | ||||
* @return latestShardVersion the version that is now stored for th | ||||
is collection | ||||
*/ | */ | |||
bool trySetVersion( const string& ns , ChunkVersion& version ); | Status refreshMetadataNow( const string& ns, ChunkVersion* latestSh ardVersion ); | |||
void appendInfo( BSONObjBuilder& b ); | void appendInfo( BSONObjBuilder& b ); | |||
// querying support | // querying support | |||
bool needCollectionMetadata( const string& ns ) const; | bool needCollectionMetadata( const string& ns ) const; | |||
CollectionMetadataPtr getCollectionMetadata( const string& ns ); | CollectionMetadataPtr getCollectionMetadata( const string& ns ); | |||
// chunk migrate and split support | // chunk migrate and split support | |||
skipping to change at line 142 | skipping to change at line 161 | |||
* into it. This data can then be protected against cleanup of orp haned data. | * into it. This data can then be protected against cleanup of orp haned data. | |||
* | * | |||
* Overlapping pending ranges will be removed, so it is only safe t o use this when you know | * Overlapping pending ranges will be removed, so it is only safe t o use this when you know | |||
* your metadata view is definitive, such as at the start of a migr ation. | * your metadata view is definitive, such as at the start of a migr ation. | |||
* | * | |||
* @return false with errMsg if the range is owned by this shard | * @return false with errMsg if the range is owned by this shard | |||
*/ | */ | |||
bool notePending( const string& ns, | bool notePending( const string& ns, | |||
const BSONObj& min, | const BSONObj& min, | |||
const BSONObj& max, | const BSONObj& max, | |||
const OID& epoch, | ||||
string* errMsg ); | string* errMsg ); | |||
/** | /** | |||
* Stops tracking a chunk range between 'min' and 'max' that previo usly was having data | * Stops tracking a chunk range between 'min' and 'max' that previo usly was having data | |||
* migrated into it. This data is no longer protected against clea nup of orphaned data. | * migrated into it. This data is no longer protected against clea nup of orphaned data. | |||
* | * | |||
* To avoid removing pending ranges of other operations, ensure tha t this is only used when | * To avoid removing pending ranges of other operations, ensure tha t this is only used when | |||
* a migration is still active. | * a migration is still active. | |||
* TODO: Because migrations may currently be active when a collecti on drops, an epoch is | * TODO: Because migrations may currently be active when a collecti on drops, an epoch is | |||
* necessary to ensure the pending metadata change is still applica ble. | * necessary to ensure the pending metadata change is still applica ble. | |||
skipping to change at line 178 | skipping to change at line 198 | |||
* as the current shards, clients shouldn't perceive the split. | * as the current shards, clients shouldn't perceive the split. | |||
* | * | |||
* @param ns the collection | * @param ns the collection | |||
* @param min max the chunk that should be split | * @param min max the chunk that should be split | |||
* @param splitKeys point in which to split | * @param splitKeys point in which to split | |||
* @param version at which the new metadata should be at | * @param version at which the new metadata should be at | |||
*/ | */ | |||
void splitChunk( const string& ns , const BSONObj& min , const BSON Obj& max , const vector<BSONObj>& splitKeys , | void splitChunk( const string& ns , const BSONObj& min , const BSON Obj& max , const vector<BSONObj>& splitKeys , | |||
ChunkVersion version ); | ChunkVersion version ); | |||
/** | ||||
* Creates and installs a new chunk metadata for a given collection | ||||
by merging a range of | ||||
* chunks ['minKey', 'maxKey') into a single chunk with version 'me | ||||
rgedVersion'. | ||||
* The current metadata must overlap the range completely and minKe | ||||
y and maxKey must not | ||||
* divide an existing chunk. | ||||
* | ||||
* The merged chunk version must have a greater version than the cu | ||||
rrent shard version, | ||||
* and if it has a greater major version clients will need to reloa | ||||
d metadata. | ||||
* | ||||
* @param ns the collection | ||||
* @param minKey maxKey the range which should be merged | ||||
* @param newShardVersion the shard version the newly merged chunk | ||||
should have | ||||
*/ | ||||
void mergeChunks( const string& ns, | ||||
const BSONObj& minKey, | ||||
const BSONObj& maxKey, | ||||
ChunkVersion mergedVersion ); | ||||
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 ); | |||
/** | ||||
* TESTING ONLY | ||||
* Uninstalls the metadata for a given collection. | ||||
*/ | ||||
void resetMetadata( const string& ns ); | ||||
private: | private: | |||
/** | ||||
* Refreshes collection metadata by asking the config server for th | ||||
e latest information. | ||||
* May or may not be based on a requested version. | ||||
*/ | ||||
Status doRefreshMetadata( const string& ns, | ||||
const ChunkVersion& reqShardVersion, | ||||
bool useRequestedVersion, | ||||
ChunkVersion* latestShardVersion ); | ||||
bool _enabled; | bool _enabled; | |||
string _configServer; | string _configServer; | |||
string _shardName; | string _shardName; | |||
string _shardHost; | string _shardHost; | |||
// protects state below | // protects state below | |||
mutable mongo::mutex _mutex; | mutable mongo::mutex _mutex; | |||
// protects accessing the config server | // protects accessing the config server | |||
End of changes. 7 change blocks. | ||||
33 lines changed or deleted | 106 lines changed or added | |||
database.h | database.h | |||
---|---|---|---|---|
skipping to change at line 24 | skipping to change at line 24 | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Licen se | * You should have received a copy of the GNU Affero General Public Licen se | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/db/cc_by_loc.h" | #include "mongo/db/cc_by_loc.h" | |||
#include "mongo/db/cmdline.h" | #include "mongo/db/cmdline.h" | |||
#include "mongo/db/namespace_details.h" | #include "mongo/db/namespace_details.h" | |||
#include "mongo/db/record.h" | #include "mongo/db/storage/record.h" | |||
#include "mongo/db/storage/extent_manager.h" | ||||
#include "mongo/db/structure/collection.h" | ||||
namespace mongo { | namespace mongo { | |||
class Extent; | class Extent; | |||
class MongoDataFile; | class DataFile; | |||
/** | /** | |||
* Database represents a database database | * Database represents a database database | |||
* Each database database has its own set of files -- dbname.ns, dbname .0, dbname.1, ... | * Each database database has its own set of files -- dbname.ns, dbname .0, dbname.1, ... | |||
* NOT memory mapped | * NOT memory mapped | |||
*/ | */ | |||
class Database { | class Database { | |||
public: | public: | |||
// you probably need to be in dbHolderMutex when constructing this | // you probably need to be in dbHolderMutex when constructing this | |||
Database(const char *nm, /*out*/ bool& newDb, const string& path = dbpath); | Database(const char *nm, /*out*/ bool& newDb, const string& path = dbpath); | |||
skipping to change at line 61 | skipping to change at line 63 | |||
/** | /** | |||
* tries to make sure that this hasn't been deleted | * tries to make sure that this hasn't been deleted | |||
*/ | */ | |||
bool isOk() const { return _magic == 781231; } | bool isOk() const { return _magic == 781231; } | |||
bool isEmpty() { return ! _namespaceIndex.allocated(); } | bool isEmpty() { return ! _namespaceIndex.allocated(); } | |||
/** | /** | |||
* total file size of Database in bytes | * total file size of Database in bytes | |||
*/ | */ | |||
long long fileSize() const; | long long fileSize() const { return _extentManager.fileSize(); } | |||
int numFiles() const; | int numFiles() const { return _extentManager.numFiles(); } | |||
/** | ||||
* returns file valid for file number n | ||||
*/ | ||||
boost::filesystem::path fileName( int n ) const; | ||||
/** | /** | |||
* return file n. if it doesn't exist, create it | * return file n. if it doesn't exist, create it | |||
*/ | */ | |||
MongoDataFile* getFile( int n, int sizeNeeded = 0, bool preallocate | DataFile* getFile( int n, int sizeNeeded = 0, bool preallocateOnly | |||
Only = false ); | = false ) { | |||
_namespaceIndex.init(); | ||||
return _extentManager.getFile( n, sizeNeeded, preallocateOnly ) | ||||
; | ||||
} | ||||
MongoDataFile* addAFile( int sizeNeeded, bool preallocateNextFile ) | DataFile* addAFile( int sizeNeeded, bool preallocateNextFile ) { | |||
; | return _extentManager.addAFile( sizeNeeded, preallocateNextFile | |||
); | ||||
} | ||||
/** | /** | |||
* makes sure we have an extra file at the end that is empty | * makes sure we have an extra file at the end that is empty | |||
* safe to call this multiple times - the implementation will only preallocate one file | * safe to call this multiple times - the implementation will only preallocate one file | |||
*/ | */ | |||
void preallocateAFile() { getFile( numFiles() , 0, true ); } | void preallocateAFile() { _extentManager.preallocateAFile(); } | |||
MongoDataFile* suitableFile( const char *ns, int sizeNeeded, bool p | ||||
reallocate, bool enforceQuota ); | ||||
Extent* allocExtent( const char *ns, int size, bool capped, bool en forceQuota ); | Extent* allocExtent( const char *ns, int size, bool capped, bool en forceQuota ); | |||
MongoDataFile* newestFile(); | ||||
/** | /** | |||
* @return true if success. false if bad level or error creating p rofile ns | * @return true if success. false if bad level or error creating p rofile ns | |||
*/ | */ | |||
bool setProfilingLevel( int newLevel , string& errmsg ); | bool setProfilingLevel( int newLevel , string& errmsg ); | |||
void flushFiles( bool sync ); | void flushFiles( bool sync ) { return _extentManager.flushFiles( sy nc ); } | |||
/** | /** | |||
* @return true if ns is part of the database | * @return true if ns is part of the database | |||
* ns=foo.bar, db=foo returns true | * ns=foo.bar, db=foo returns true | |||
*/ | */ | |||
bool ownsNS( const string& ns ) const { | bool ownsNS( const string& ns ) const { | |||
if ( ! startsWith( ns , _name ) ) | if ( ! startsWith( ns , _name ) ) | |||
return false; | return false; | |||
return ns[_name.size()] == '.'; | return ns[_name.size()] == '.'; | |||
} | } | |||
skipping to change at line 117 | skipping to change at line 115 | |||
RecordStats& recordStats() { return _recordStats; } | RecordStats& recordStats() { return _recordStats; } | |||
int getProfilingLevel() const { return _profile; } | int getProfilingLevel() const { return _profile; } | |||
const char* getProfilingNS() const { return _profileName.c_str(); } | const char* getProfilingNS() const { return _profileName.c_str(); } | |||
CCByLoc& ccByLoc() { return _ccByLoc; } | CCByLoc& ccByLoc() { return _ccByLoc; } | |||
const NamespaceIndex& namespaceIndex() const { return _namespaceInd ex; } | const NamespaceIndex& namespaceIndex() const { return _namespaceInd ex; } | |||
NamespaceIndex& namespaceIndex() { return _namespaceIndex; } | NamespaceIndex& namespaceIndex() { return _namespaceIndex; } | |||
// TODO: do not think this method should exist, so should try and e | ||||
ncapsulate better | ||||
ExtentManager& getExtentManager() { return _extentManager; } | ||||
const ExtentManager& getExtentManager() const { return _extentManag | ||||
er; } | ||||
void dropCollection( const StringData& fullns ); | ||||
/** | ||||
* @param ns - this is fully qualified, which is maybe not ideal ?? | ||||
? | ||||
*/ | ||||
CollectionTemp* getCollectionTemp( const StringData& ns ); | ||||
/** | /** | |||
* @return name of an existing database with same text name but dif ferent | * @return name of an existing database with same text name but dif ferent | |||
* casing, if one exists. Otherwise the empty string is returned. If | * casing, if one exists. Otherwise the empty string is returned. If | |||
* 'duplicates' is specified, it is filled with all duplicate names . | * 'duplicates' is specified, it is filled with all duplicate names . | |||
*/ | */ | |||
static string duplicateUncasedName( bool inholderlockalready, const string &name, const string &path, set< string > *duplicates = 0 ); | static string duplicateUncasedName( bool inholderlockalready, const string &name, const string &path, set< string > *duplicates = 0 ); | |||
static Status validateDBName( const StringData& dbname ); | ||||
private: | private: | |||
~Database(); // closes files and other cleanup see below. | ~Database(); // closes files and other cleanup see below. | |||
/** | /** | |||
* @throws DatabaseDifferCaseCode if the name is a duplicate based on | * @throws DatabaseDifferCaseCode if the name is a duplicate based on | |||
* case insensitive matching. | * case insensitive matching. | |||
*/ | */ | |||
void checkDuplicateUncasedNames(bool inholderlockalready) const; | void checkDuplicateUncasedNames(bool inholderlockalready) const; | |||
bool exists(int n) const; | ||||
void openAllFiles(); | void openAllFiles(); | |||
/** | /** | |||
* throws exception if error encounted | * throws exception if error encounted | |||
* @return true if the file was opened | * @return true if the file was opened | |||
* false if no errors, but file doesn't exist | * false if no errors, but file doesn't exist | |||
*/ | */ | |||
bool openExistingFile( int n ); | bool openExistingFile( int n ); | |||
const string _name; // "alleyinsider" | const string _name; // "alleyinsider" | |||
const string _path; // "/data/db" | const string _path; // "/data/db" | |||
// 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 | ||||
// to others and we are in the dbholder lock then. | ||||
vector<MongoDataFile*> _files; | ||||
NamespaceIndex _namespaceIndex; | NamespaceIndex _namespaceIndex; | |||
ExtentManager _extentManager; | ||||
const string _profileName; // "alleyinsider.system.profile" | const string _profileName; // "alleyinsider.system.profile" | |||
CCByLoc _ccByLoc; // use by ClientCursor | CCByLoc _ccByLoc; // use by ClientCursor | |||
RecordStats _recordStats; | RecordStats _recordStats; | |||
int _profile; // 0=off. | int _profile; // 0=off. | |||
int _magic; // used for making sure the object is still loaded in m emory | int _magic; // used for making sure the object is still loaded in m emory | |||
// TODO: probably shouldn't be a std::map | ||||
// TODO: make sure deletes go through | ||||
// this in some ways is a dupe of _namespaceIndex | ||||
// but it points to a much more useful data structure | ||||
typedef std::map< std::string, CollectionTemp* > CollectionMap; | ||||
CollectionMap _collections; | ||||
mutex _collectionLock; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 15 change blocks. | ||||
28 lines changed or deleted | 44 lines changed or added | |||
db.h | db.h | |||
---|---|---|---|---|
skipping to change at line 23 | skipping to change at line 23 | |||
* You should have received a copy of the GNU Affero General Public Licen se | * You should have received a copy of the GNU Affero General Public Licen se | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/pch.h" | |||
#include "mongo/db/client.h" | #include "mongo/db/client.h" | |||
#include "mongo/db/curop.h" | #include "mongo/db/curop.h" | |||
#include "mongo/db/databaseholder.h" | #include "mongo/db/database_holder.h" | |||
#include "mongo/db/pdfile.h" | #include "mongo/db/pdfile.h" | |||
#include "mongo/util/net/message.h" | #include "mongo/util/net/message.h" | |||
namespace mongo { | namespace mongo { | |||
// todo: relocked is being called when there was no unlock below. | // todo: relocked is being called when there was no unlock below. | |||
// that is weird. | // that is weird. | |||
struct dbtemprelease { | struct dbtemprelease { | |||
Client::Context * _context; | Client::Context * _context; | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
dbclient_rs.h | dbclient_rs.h | |||
---|---|---|---|---|
skipping to change at line 209 | skipping to change at line 209 | |||
/** | /** | |||
* checks all sets for current master and new secondaries | * checks all sets for current master and new secondaries | |||
* usually only called from a BackgroundJob | * usually only called from a BackgroundJob | |||
*/ | */ | |||
static void checkAll(); | static void checkAll(); | |||
/** | /** | |||
* Removes the ReplicaSetMonitor for the given set name from _sets, which will delete it. | * Removes the ReplicaSetMonitor for the given set name from _sets, which will delete it. | |||
* If clearSeedCache is true, then the cached seed string for this Replica Set will be removed | * If clearSeedCache is true, then the cached seed string for this Replica Set will be removed | |||
* from _setServers. | * from _seedServers. | |||
*/ | */ | |||
static void remove( const string& name, bool clearSeedCache = false ); | static void remove( const string& name, bool clearSeedCache = false ); | |||
static int getMaxFailedChecks() { return _maxFailedChecks; }; | static int getMaxFailedChecks() { return _maxFailedChecks; }; | |||
static void setMaxFailedChecks(int numChecks) { _maxFailedChecks = numChecks; }; | static void setMaxFailedChecks(int numChecks) { _maxFailedChecks = numChecks; }; | |||
/** | /** | |||
* this is called whenever the config of any replica set changes | * this is called whenever the config of any replica set changes | |||
* currently only 1 globally | * currently only 1 globally | |||
* asserts if one already exists | * asserts if one already exists | |||
* ownership passes to ReplicaSetMonitor and the hook will actually never be deleted | * ownership passes to ReplicaSetMonitor and the hook will actually never be deleted | |||
*/ | */ | |||
static void setConfigChangeHook( ConfigChangeHook hook ); | static void setConfigChangeHook( ConfigChangeHook hook ); | |||
/** | ||||
* Stops all monitoring on replica sets and clears all cached infor | ||||
mation as well. | ||||
* Note that this does not prevent new monitors from being created | ||||
afterwards or even | ||||
* while this is being executed. As a consequence, NEVER call this | ||||
if you have other | ||||
* threads that has a DBClientReplicaSet instance or will create on | ||||
e before this | ||||
* fully terminates as it will cause a deadlock. This is intended f | ||||
or performing cleanups | ||||
* in unit tests. | ||||
* | ||||
* Warning: Make sure that the monitor thread is running, otherwise | ||||
this can hang | ||||
* indefinitely. | ||||
*/ | ||||
static void cleanup(); | ||||
~ReplicaSetMonitor(); | ~ReplicaSetMonitor(); | |||
/** @return HostAndPort or throws an exception */ | /** @return HostAndPort or throws an exception */ | |||
HostAndPort getMaster(); | HostAndPort getMaster(); | |||
/** | /** | |||
* notify the monitor that server has faild | * notify the monitor that server has faild | |||
*/ | */ | |||
void notifyFailure( const HostAndPort& server ); | void notifyFailure( const HostAndPort& server ); | |||
skipping to change at line 327 | skipping to change at line 340 | |||
* @param verbose | * @param verbose | |||
* @param nodesOffset - offset into _nodes array, -1 for not in it | * @param nodesOffset - offset into _nodes array, -1 for not in it | |||
* | * | |||
* @return true if the connection is good or false if invariant | * @return true if the connection is good or false if invariant | |||
* is broken | * is broken | |||
*/ | */ | |||
bool _checkConnection( DBClientConnection* conn, string& maybePrima ry, | bool _checkConnection( DBClientConnection* conn, string& maybePrima ry, | |||
bool verbose, int nodesOffset ); | bool verbose, int nodesOffset ); | |||
/** | /** | |||
* Save the seed list for the current set into the _setServers map | * Save the seed list for the current set into the _seedServers map | |||
* Should only be called if you're already holding _setsLock and th is | * Should only be called if you're already holding _setsLock and th is | |||
* monitor's _lock. | * monitor's _lock. | |||
*/ | */ | |||
void _cacheServerAddresses_inlock(); | void _cacheServerAddresses_inlock(); | |||
string _getServerAddress_inlock() const; | string _getServerAddress_inlock() const; | |||
NodeDiff _getHostDiff_inlock( const BSONObj& hostList ); | NodeDiff _getHostDiff_inlock( const BSONObj& hostList ); | |||
bool _shouldChangeHosts( const BSONObj& hostList, bool inlock ); | bool _shouldChangeHosts( const BSONObj& hostList, bool inlock ); | |||
skipping to change at line 391 | skipping to change at line 404 | |||
std::vector<Node> _nodes; | std::vector<Node> _nodes; | |||
int _master; // which node is the current master. -1 means no mast er is known | int _master; // which node is the current master. -1 means no mast er is known | |||
int _nextSlave; // which node is the current slave, only used by th e deprecated getSlave | int _nextSlave; // which node is the current slave, only used by th e deprecated getSlave | |||
// last host returned by _selectNode, used for round robin selectio n | // last host returned by _selectNode, used for round robin selectio n | |||
HostAndPort _lastReadPrefHost; | HostAndPort _lastReadPrefHost; | |||
// The number of consecutive times the set has been checked and eve ry member in the set was down. | // The number of consecutive times the set has been checked and eve ry member in the set was down. | |||
int _failedChecks; | int _failedChecks; | |||
static mongo::mutex _setsLock; // protects _sets and _setServers | static mongo::mutex _setsLock; // protects _seedServers and _sets | |||
static map<string,ReplicaSetMonitorPtr> _sets; // set name to Monit | ||||
or | // set name to seed list. | |||
static map<string,vector<HostAndPort> > _seedServers; // set name t | // Used to rebuild the monitor if it is cleaned up but then the set | |||
o seed list. Used to rebuild the monitor if it is cleaned up but then the s | is accessed again. | |||
et is accessed again. | static map<string, vector<HostAndPort> > _seedServers; | |||
static map<string, ReplicaSetMonitorPtr> _sets; // set name to Moni | ||||
tor | ||||
static ConfigChangeHook _hook; | static ConfigChangeHook _hook; | |||
int _localThresholdMillis; // local ping latency threshold (protect ed by _lock) | int _localThresholdMillis; // local ping latency threshold (protect ed by _lock) | |||
static int _maxFailedChecks; | static int _maxFailedChecks; | |||
}; | }; | |||
/** Use this class to connect to a replica set of servers. The class w ill manage | /** Use this class to connect to a replica set of servers. The class w ill manage | |||
checking for which server in a replica set is master, and do failove r automatically. | checking for which server in a replica set is master, and do failove r automatically. | |||
End of changes. 4 change blocks. | ||||
8 lines changed or deleted | 29 lines changed or added | |||
dbclientinterface.h | dbclientinterface.h | |||
---|---|---|---|---|
skipping to change at line 701 | skipping to change at line 701 | |||
/** Get error result from the last write operation (insert/update/d elete) on this connection. | /** Get error result from the last write operation (insert/update/d elete) on this connection. | |||
db doesn't change the command's behavior - it is just for auth checks. | db doesn't change the command's behavior - it is just for auth checks. | |||
@return error message text, or empty string if no error. | @return error message text, or empty string if no error. | |||
*/ | */ | |||
string getLastError(const std::string& db, | string getLastError(const std::string& db, | |||
bool fsync = false, | bool fsync = false, | |||
bool j = false, | bool j = false, | |||
int w = 0, | int w = 0, | |||
int wtimeout = 0); | int wtimeout = 0); | |||
// Same as above but defaults to using admin DB | /** | |||
* Same as the form of getLastError that takes a dbname, but just u | ||||
ses the admin DB. | ||||
*/ | ||||
string getLastError(bool fsync = false, bool j = false, int w = 0, int wtimeout = 0); | string getLastError(bool fsync = false, bool j = false, int w = 0, int wtimeout = 0); | |||
/** Get error result from the last write operation (insert/update/d elete) on this connection. | /** Get error result from the last write operation (insert/update/d elete) on this connection. | |||
db doesn't change the command's behavior - it is just for auth checks. | db doesn't change the command's behavior - it is just for auth checks. | |||
@return full error object. | @return full error object. | |||
If "w" is -1, wait for propagation to majority of nodes. | If "w" is -1, wait for propagation to majority of nodes. | |||
If "wtimeout" is 0, the operation will block indefinitely if ne eded. | If "wtimeout" is 0, the operation will block indefinitely if ne eded. | |||
*/ | */ | |||
virtual BSONObj getLastErrorDetailed(const std::string& db, | virtual BSONObj getLastErrorDetailed(const std::string& db, | |||
bool fsync = false, | bool fsync = false, | |||
bool j = false, | bool j = false, | |||
int w = 0, | int w = 0, | |||
int wtimeout = 0); | int wtimeout = 0); | |||
// Same as above but defaults to using admin DB | /** | |||
* Same as the form of getLastErrorDetailed that takes a dbname, bu | ||||
t just uses the admin DB. | ||||
*/ | ||||
virtual BSONObj getLastErrorDetailed(bool fsync = false, bool j = f alse, int w = 0, int wtimeout = 0); | virtual BSONObj getLastErrorDetailed(bool fsync = false, bool j = f alse, int w = 0, int wtimeout = 0); | |||
/** Can be called with the returned value from getLastErrorDetailed to extract an error string. | /** Can be called with the returned value from getLastErrorDetailed to extract an error string. | |||
If all you need is the string, just call getLastError() instead . | If all you need is the string, just call getLastError() instead . | |||
*/ | */ | |||
static string getLastErrorString( const BSONObj& res ); | static string getLastErrorString( const BSONObj& res ); | |||
/** Return the last error which has occurred, even if not the very last operation. | /** Return the last error which has occurred, even if not the very last operation. | |||
@return { err : <error message>, nPrev : <how_many_ops_back_occu rred>, ok : 1 } | @return { err : <error message>, nPrev : <how_many_ops_back_occu rred>, ok : 1 } | |||
skipping to change at line 1134 | skipping to change at line 1138 | |||
public: | public: | |||
using DBClientBase::query; | using DBClientBase::query; | |||
/** | /** | |||
@param _autoReconnect if true, automatically reconnect on a conn ection failure | @param _autoReconnect if true, automatically reconnect on a conn ection failure | |||
@param cp used by DBClientReplicaSet. You do not need to specif y this parameter | @param cp used by DBClientReplicaSet. You do not need to specif y this parameter | |||
@param timeout tcp timeout in seconds - this is for read/write, not connect. | @param timeout tcp timeout in seconds - this is for read/write, not connect. | |||
Connect timeout is fixed, but short, at 5 seconds. | Connect timeout is fixed, but short, at 5 seconds. | |||
*/ | */ | |||
DBClientConnection(bool _autoReconnect=false, DBClientReplicaSet* c p=0, double so_timeout=0) : | DBClientConnection(bool _autoReconnect=false, DBClientReplicaSet* c p=0, double so_timeout=0) : | |||
clientSet(cp), _failed(false), autoReconnect(_autoReconnect), l astReconnectTry(0), _so_timeout(so_timeout) { | clientSet(cp), _failed(false), autoReconnect(_autoReconnect), a utoReconnectBackoff(1000, 2000), _so_timeout(so_timeout) { | |||
_numConnections++; | _numConnections++; | |||
} | } | |||
virtual ~DBClientConnection() { | virtual ~DBClientConnection() { | |||
_numConnections--; | _numConnections--; | |||
} | } | |||
/** Connect to a Mongo database server. | /** Connect to a Mongo database server. | |||
If autoReconnect is true, you can try to use the DBClientConnect ion even when | If autoReconnect is true, you can try to use the DBClientConnect ion even when | |||
skipping to change at line 1275 | skipping to change at line 1279 | |||
protected: | protected: | |||
friend class SyncClusterConnection; | friend class SyncClusterConnection; | |||
virtual void _auth(const BSONObj& params); | virtual void _auth(const BSONObj& params); | |||
virtual void sayPiggyBack( Message &toSend ); | virtual void sayPiggyBack( Message &toSend ); | |||
DBClientReplicaSet *clientSet; | DBClientReplicaSet *clientSet; | |||
boost::scoped_ptr<MessagingPort> p; | boost::scoped_ptr<MessagingPort> p; | |||
boost::scoped_ptr<SockAddr> server; | boost::scoped_ptr<SockAddr> server; | |||
bool _failed; | bool _failed; | |||
const bool autoReconnect; | const bool autoReconnect; | |||
time_t lastReconnectTry; | Backoff autoReconnectBackoff; | |||
HostAndPort _server; // remember for reconnects | HostAndPort _server; // remember for reconnects | |||
string _serverString; | string _serverString; | |||
void _checkConnection(); | void _checkConnection(); | |||
// throws SocketException if in failed state and not reconnecting o r if waiting to reconnect | // throws SocketException if in failed state and not reconnecting o r if waiting to reconnect | |||
void checkConnection() { if( _failed ) _checkConnection(); } | void checkConnection() { if( _failed ) _checkConnection(); } | |||
map<string, BSONObj> authCache; | map<string, BSONObj> authCache; | |||
double _so_timeout; | double _so_timeout; | |||
bool _connect( string& errmsg ); | bool _connect( string& errmsg ); | |||
End of changes. 4 change blocks. | ||||
4 lines changed or deleted | 10 lines changed or added | |||
dbclientmockcursor.h | dbclientmockcursor.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 "dbclientcursor.h" | #include "mongo/client/dbclientcursor.h" | |||
namespace mongo { | namespace mongo { | |||
class DBClientMockCursor : public DBClientCursorInterface { | class DBClientMockCursor : public DBClientCursorInterface { | |||
public: | public: | |||
DBClientMockCursor( const BSONArray& mockCollection ) : _iter( mock Collection ) {} | DBClientMockCursor( const BSONArray& mockCollection ) : _iter( mock Collection ) {} | |||
virtual ~DBClientMockCursor() {} | virtual ~DBClientMockCursor() {} | |||
bool more() { return _iter.more(); } | bool more() { return _iter.more(); } | |||
BSONObj next() { return _iter.next().Obj(); } | BSONObj next() { return _iter.next().Obj(); } | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
dbmessage.h | dbmessage.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/bson/bson_validate.h" | #include "mongo/bson/bson_validate.h" | |||
#include "mongo/client/constants.h" | #include "mongo/client/constants.h" | |||
#include "mongo/db/instance.h" | ||||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/util/net/message.h" | #include "mongo/util/net/message.h" | |||
#include "mongo/util/net/message_port.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 131 | skipping to change at line 131 | |||
/** the 32 bit field before the ns | /** the 32 bit field before the ns | |||
* track all bit usage here as its cross op | * track all bit usage here as its cross op | |||
* 0: InsertOption_ContinueOnError | * 0: InsertOption_ContinueOnError | |||
* 1: fromWriteback | * 1: fromWriteback | |||
*/ | */ | |||
int& reservedField() { return *reserved; } | int& reservedField() { return *reserved; } | |||
const char * getns() const { | const char * getns() const { | |||
return data; | return data; | |||
} | } | |||
void getns(Namespace& ns) const { | ||||
ns = data; | ||||
} | ||||
const char * afterNS() const { | const char * afterNS() const { | |||
return data + strlen( data ) + 1; | return data + strlen( data ) + 1; | |||
} | } | |||
int getInt( int num ) const { | int getInt( int num ) const { | |||
const int * foo = (const int*)afterNS(); | const int * foo = (const int*)afterNS(); | |||
return foo[num]; | return foo[num]; | |||
} | } | |||
skipping to change at line 268 | skipping to change at line 265 | |||
ntoskip = d.pullInt(); | ntoskip = d.pullInt(); | |||
ntoreturn = d.pullInt(); | ntoreturn = d.pullInt(); | |||
query = d.nextJsObj(); | query = d.nextJsObj(); | |||
if ( d.moreJSObjs() ) { | if ( d.moreJSObjs() ) { | |||
fields = d.nextJsObj(); | fields = d.nextJsObj(); | |||
} | } | |||
queryOptions = d.msg().header()->dataAsInt(); | queryOptions = d.msg().header()->dataAsInt(); | |||
} | } | |||
}; | }; | |||
/** | ||||
* A response to a DbMessage. | ||||
*/ | ||||
struct DbResponse { | ||||
Message *response; | ||||
MSGID responseTo; | ||||
string exhaustNS; /* points to ns if exhaust mode. 0=normal mode*/ | ||||
DbResponse(Message *r, MSGID rt) : response(r), responseTo(rt){ } | ||||
DbResponse() { | ||||
response = 0; | ||||
} | ||||
~DbResponse() { delete response; } | ||||
}; | ||||
void replyToQuery(int queryResultFlags, | void replyToQuery(int queryResultFlags, | |||
AbstractMessagingPort* p, Message& requestMsg, | AbstractMessagingPort* p, Message& requestMsg, | |||
void *data, int size, | void *data, int size, | |||
int nReturned, int startingFrom = 0, | int nReturned, int startingFrom = 0, | |||
long long cursorId = 0 | long long cursorId = 0 | |||
); | ); | |||
/* object reply helper. */ | /* object reply helper. */ | |||
void replyToQuery(int queryResultFlags, | void replyToQuery(int queryResultFlags, | |||
AbstractMessagingPort* p, Message& requestMsg, | AbstractMessagingPort* p, Message& requestMsg, | |||
End of changes. 4 change blocks. | ||||
4 lines changed or deleted | 15 lines changed or added | |||
diskloc.h | diskloc.h | |||
---|---|---|---|---|
skipping to change at line 34 | skipping to change at line 34 | |||
#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" | #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 DataFile; | |||
class DiskLoc; | class DiskLoc; | |||
template< class Version > class BtreeBucket; | template< class Version > class BtreeBucket; | |||
#pragma pack(1) | #pragma pack(1) | |||
/** represents a disk location/offset on disk in a database. 64 bits. | /** represents a disk location/offset on disk in a database. 64 bits. | |||
it is assumed these will be passed around by value a lot so don't d o anything to make them large | it is assumed these will be passed around by value a lot so don't d o anything to make them large | |||
(such as adding a virtual function) | (such as adding a virtual function) | |||
*/ | */ | |||
class DiskLoc { | class DiskLoc { | |||
skipping to change at line 78 | skipping to change at line 78 | |||
return ofs < -1 || | return ofs < -1 || | |||
_a < -1 || | _a < -1 || | |||
_a > 524288; | _a > 524288; | |||
} | } | |||
bool isNull() const { return _a == -1; } | bool isNull() const { return _a == -1; } | |||
void Null() { | void Null() { | |||
_a = -1; | _a = -1; | |||
ofs = 0; /* note NullOfs is different. todo clean up. see refs to NullOfs in code - use is valid but outside DiskLoc context so confusing as-is. */ | ofs = 0; /* note NullOfs is different. todo clean up. see refs to NullOfs in code - use is valid but outside DiskLoc context so confusing as-is. */ | |||
} | } | |||
void assertOk() { verify(!isNull()); } | void assertOk() const { verify(!isNull()); } | |||
void setInvalid() { | void setInvalid() { | |||
_a = -2; | _a = -2; | |||
ofs = 0; | ofs = 0; | |||
} | } | |||
bool isValid() const { return _a != -2; } | bool isValid() const { return _a != -2; } | |||
string toString() const { | string toString() const { | |||
if ( isNull() ) | if ( isNull() ) | |||
return "null"; | return "null"; | |||
stringstream ss; | stringstream ss; | |||
skipping to change at line 167 | skipping to change at line 167 | |||
DeletedRecord* drec() const; | DeletedRecord* drec() const; | |||
Extent* ext() const; | Extent* ext() const; | |||
template< class V > | template< class V > | |||
const BtreeBucket<V> * btree() const; | const BtreeBucket<V> * btree() const; | |||
// Explicitly signals we are writing and casts away const | // Explicitly signals we are writing and casts away const | |||
template< class V > | template< class V > | |||
BtreeBucket<V> * btreemod() const; | BtreeBucket<V> * btreemod() const; | |||
/*MongoDataFile& pdf() const;*/ | /*DataFile& pdf() const;*/ | |||
/// members for Sorter | /// members for Sorter | |||
struct SorterDeserializeSettings {}; // unused | struct SorterDeserializeSettings {}; // unused | |||
void serializeForSorter(BufBuilder& buf) const { buf.appendStruct(* this); } | void serializeForSorter(BufBuilder& buf) const { buf.appendStruct(* this); } | |||
static DiskLoc deserializeForSorter(BufReader& buf, const SorterDes erializeSettings&) { | static DiskLoc deserializeForSorter(BufReader& buf, const SorterDes erializeSettings&) { | |||
return buf.read<DiskLoc>(); | return buf.read<DiskLoc>(); | |||
} | } | |||
int memUsageForSorter() const { return sizeof(DiskLoc); } | int memUsageForSorter() const { return sizeof(DiskLoc); } | |||
DiskLoc getOwned() const { return *this; } | DiskLoc getOwned() const { return *this; } | |||
}; | }; | |||
End of changes. 3 change blocks. | ||||
3 lines changed or deleted | 3 lines changed or added | |||
distlock.h | distlock.h | |||
---|---|---|---|---|
skipping to change at line 21 | skipping to change at line 21 | |||
* Unless required by applicable law or agreed to in writing, software | * Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | * distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. | |||
* See the License for the specific language governing permissions and | * See the License for the specific language governing permissions and | |||
* limitations under the License. | * limitations under the License. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/pch.h" | |||
#include "connpool.h" | #include "mongo/client/connpool.h" | |||
#include "syncclusterconnection.h" | #include "mongo/client/syncclusterconnection.h" | |||
#define LOCK_TIMEOUT (15 * 60 * 1000) | #define LOCK_TIMEOUT (15 * 60 * 1000) | |||
#define LOCK_SKEW_FACTOR (30) | #define LOCK_SKEW_FACTOR (30) | |||
#define LOCK_PING (LOCK_TIMEOUT / LOCK_SKEW_FACTOR) | #define LOCK_PING (LOCK_TIMEOUT / LOCK_SKEW_FACTOR) | |||
#define MAX_LOCK_NET_SKEW (LOCK_TIMEOUT / LOCK_SKEW_FACTOR) | #define MAX_LOCK_NET_SKEW (LOCK_TIMEOUT / LOCK_SKEW_FACTOR) | |||
#define MAX_LOCK_CLOCK_SKEW (LOCK_TIMEOUT / LOCK_SKEW_FACTOR) | #define MAX_LOCK_CLOCK_SKEW (LOCK_TIMEOUT / LOCK_SKEW_FACTOR) | |||
#define NUM_LOCK_SKEW_CHECKS (3) | #define NUM_LOCK_SKEW_CHECKS (3) | |||
// The maximum clock skew we need to handle between config servers is | // The maximum clock skew we need to handle between config servers is | |||
// 2 * MAX_LOCK_NET_SKEW + MAX_LOCK_CLOCK_SKEW. | // 2 * MAX_LOCK_NET_SKEW + MAX_LOCK_CLOCK_SKEW. | |||
End of changes. 1 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
document.h | document.h | |||
---|---|---|---|---|
skipping to change at line 126 | skipping to change at line 126 | |||
/** 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; | |||
BSONObj toBson() const; | ||||
// Support BSONObjBuilder and BSONArrayBuilder "stream" API | // Support BSONObjBuilder and BSONArrayBuilder "stream" API | |||
friend BSONObjBuilder& operator << (BSONObjBuilderValueStream& buil der, const Document& d); | 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. | |||
skipping to change at line 152 | skipping to change at line 153 | |||
*/ | */ | |||
Document clone() const { return Document(storage().clone().get()); } | Document clone() const { return Document(storage().clone().get()); } | |||
/// members for Sorter | /// members for Sorter | |||
struct SorterDeserializeSettings {}; // unused | struct SorterDeserializeSettings {}; // unused | |||
void serializeForSorter(BufBuilder& buf) const; | void serializeForSorter(BufBuilder& buf) const; | |||
static Document deserializeForSorter(BufReader& buf, const SorterDe serializeSettings&); | static Document deserializeForSorter(BufReader& buf, const SorterDe serializeSettings&); | |||
int memUsageForSorter() const { return getApproximateSize(); } | int memUsageForSorter() const { return getApproximateSize(); } | |||
Document getOwned() const { return *this; } | Document getOwned() const { return *this; } | |||
// TEMP for compatibility with legacy intrusive_ptr<Document> | /// only for testing | |||
Document& operator*() { return *this; } | ||||
const Document& operator*() const { return *this; } | ||||
Document* operator->() { return this; } | ||||
const Document* operator->() const { return this; } | ||||
const void* getPtr() const { return _storage.get(); } | const void* getPtr() const { return _storage.get(); } | |||
void reset() { return _storage.reset(); } | ||||
static Document createFromBsonObj(BSONObj* pBsonObj) { return Docum | ||||
ent(*pBsonObj); } | ||||
size_t getFieldCount() const { return size(); } | ||||
Value getValue(StringData fieldName) const { return getField(fieldN | ||||
ame); } | ||||
// TODO: replace with logical equality once all current usages are | ||||
fixed | ||||
bool operator== (const Document& lhs) const { return _storage == lh | ||||
s._storage; } | ||||
explicit Document(const DocumentStorage* ptr) : _storage(ptr) {}; | ||||
private: | private: | |||
friend class FieldIterator; | friend class FieldIterator; | |||
friend class ValueStorage; | friend class ValueStorage; | |||
friend class MutableDocument; | friend class MutableDocument; | |||
friend class MutableValue; | ||||
explicit Document(const DocumentStorage* ptr) : _storage(ptr) {}; | ||||
const DocumentStorage& storage() const { | const DocumentStorage& storage() const { | |||
return (_storage ? *_storage : DocumentStorage::emptyDoc()); | return (_storage ? *_storage : DocumentStorage::emptyDoc()); | |||
} | } | |||
intrusive_ptr<const DocumentStorage> _storage; | intrusive_ptr<const DocumentStorage> _storage; | |||
}; | }; | |||
inline bool operator== (const Document& l, const Document& r) { | ||||
return Document::compare(l, r) == 0; | ||||
} | ||||
inline bool operator!= (const Document& l, const Document& r) { | ||||
return Document::compare(l, r) != 0; | ||||
} | ||||
inline bool operator< (const Document& l, const Document& r) { | ||||
return Document::compare(l, r) < 0; | ||||
} | ||||
inline bool operator<= (const Document& l, const Document& r) { | ||||
return Document::compare(l, r) <= 0; | ||||
} | ||||
inline bool operator> (const Document& l, const Document& r) { | ||||
return Document::compare(l, r) > 0; | ||||
} | ||||
inline bool operator>= (const Document& l, const Document& r) { | ||||
return Document::compare(l, r) >= 0; | ||||
} | ||||
/** This class is returned by MutableDocument to allow you to modify it s values. | /** This class is returned by MutableDocument to allow you to modify it s values. | |||
* You are not allowed to hold variables of this type (enforced by the type system). | * You are not allowed to hold variables of this type (enforced by the type system). | |||
*/ | */ | |||
class MutableValue { | class MutableValue { | |||
public: | public: | |||
void operator= (const Value& v) { _val = v; } | void operator= (const Value& v) { _val = v; } | |||
/** These are designed to allow things like mutDoc["a"]["b"]["c"] = Value(10); | /** These are designed to allow things like mutDoc["a"]["b"]["c"] = Value(10); | |||
* It is safe to use even on nonexistent fields. | * It is safe to use even on nonexistent fields. | |||
*/ | */ | |||
skipping to change at line 204 | skipping to change at line 214 | |||
private: | private: | |||
friend class MutableDocument; | friend class MutableDocument; | |||
/// can only be constructed or copied by self and friends | /// can only be constructed or copied by self and friends | |||
MutableValue(const MutableValue& other): _val(other._val) {} | MutableValue(const MutableValue& other): _val(other._val) {} | |||
explicit MutableValue(Value& val): _val(val) {} | explicit MutableValue(Value& val): _val(val) {} | |||
/// Used by MutableDocument(MutableValue) | /// Used by MutableDocument(MutableValue) | |||
const RefCountable*& getDocPtr() { | const RefCountable*& getDocPtr() { | |||
if (_val.getType() != Object) | if (_val.getType() != Object || _val._storage.genericRCPtr == N | |||
*this = Value(Document()); | ULL) { | |||
// If the current value isn't an object we replace it with | ||||
a Object-typed Value. | ||||
// Note that we can't just use Document() here because that | ||||
is a NULL pointer and | ||||
// Value doesn't refcount NULL pointers. This led to a memo | ||||
ry leak (SERVER-10554) | ||||
// because MutableDocument::newStorage() would set a non-NU | ||||
LL pointer into the Value | ||||
// without setting the refCounter bit. While allocating a D | ||||
ocumentStorage here could | ||||
// result in an allocation where none is needed, in practic | ||||
e this is only called | ||||
// when we are about to add a field to the sub-document so | ||||
this just changes where | ||||
// the allocation is done. | ||||
_val = Value(Document(new DocumentStorage())); | ||||
} | ||||
return _val._storage.genericRCPtr; | return _val._storage.genericRCPtr; | |||
} | } | |||
MutableValue& operator= (const MutableValue&); // not assignable wi th another MutableValue | MutableValue& operator= (const MutableValue&); // not assignable wi th another MutableValue | |||
Value& _val; | Value& _val; | |||
}; | }; | |||
/** MutableDocument is a Document builder that supports both adding and updating fields. | /** MutableDocument is a Document builder that supports both adding and updating fields. | |||
End of changes. 6 change blocks. | ||||
20 lines changed or deleted | 43 lines changed or added | |||
document_source.h | document_source.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 License | * You should have received a copy of the GNU Affero General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/pch.h" | |||
#include <boost/optional.hpp> | ||||
#include <boost/unordered_map.hpp> | #include <boost/unordered_map.hpp> | |||
#include <deque> | ||||
#include "mongo/db/clientcursor.h" | #include "mongo/db/clientcursor.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/matcher.h" | #include "mongo/db/matcher.h" | |||
#include "mongo/db/pipeline/document.h" | #include "mongo/db/pipeline/document.h" | |||
#include "mongo/db/pipeline/expression_context.h" | #include "mongo/db/pipeline/expression_context.h" | |||
#include "mongo/db/pipeline/expression.h" | #include "mongo/db/pipeline/expression.h" | |||
#include "mongo/db/pipeline/value.h" | #include "mongo/db/pipeline/value.h" | |||
#include "mongo/db/projection.h" | #include "mongo/db/projection.h" | |||
#include "mongo/db/sorter/sorter.h" | #include "mongo/db/sorter/sorter.h" | |||
#include "mongo/s/shard.h" | #include "mongo/s/shard.h" | |||
#include "mongo/s/strategy.h" | ||||
#include "mongo/util/intrusive_counter.h" | #include "mongo/util/intrusive_counter.h" | |||
namespace mongo { | namespace mongo { | |||
class Accumulator; | class Accumulator; | |||
class Cursor; | class Cursor; | |||
class Document; | class Document; | |||
class Expression; | class Expression; | |||
class ExpressionContext; | ||||
class ExpressionFieldPath; | class ExpressionFieldPath; | |||
class ExpressionObject; | class ExpressionObject; | |||
class DocumentSourceLimit; | class DocumentSourceLimit; | |||
class DocumentSource : public IntrusiveCounterUnsigned { | class DocumentSource : public IntrusiveCounterUnsigned { | |||
public: | public: | |||
virtual ~DocumentSource(); | virtual ~DocumentSource() {} | |||
/** | /** | |||
Set the step for a user-specified pipeline step. | Set the step for a user-specified pipeline step. | |||
The step is used for diagnostics. | The step is used for diagnostics. | |||
@param step step number 0 to n. | @param step step number 0 to n. | |||
*/ | */ | |||
void setPipelineStep(int step); | void setPipelineStep(int step); | |||
/** | /** | |||
Get the user-specified pipeline step. | Get the user-specified pipeline step. | |||
@returns the step number, or -1 if it has never been set | @returns the step number, or -1 if it has never been set | |||
*/ | */ | |||
int getPipelineStep() const; | int getPipelineStep() const; | |||
/** | /** Returns the next Document if there is one or boost::none if at | |||
Is the source at EOF? | EOF. | |||
* Subclasses must call pExpCtx->checkForInterupt(). | ||||
@returns true if the source has no more Documents to return. | ||||
*/ | ||||
virtual bool eof() = 0; | ||||
/** | ||||
Advance the state of the DocumentSource so that it will return th | ||||
e | ||||
next Document. | ||||
The default implementation returns false, after checking for | ||||
interrupts. Derived classes can call the default implementation | ||||
in their own implementations in order to check for interrupts. | ||||
@returns whether there is another document to fetch, i.e., whethe | ||||
r or | ||||
not getCurrent() will succeed. This default implementation alw | ||||
ays | ||||
returns false. | ||||
*/ | ||||
virtual bool advance(); | ||||
/** @returns the current Document without advancing. | ||||
* | ||||
* It is illegal to call this without first checking eof() == fals | ||||
e or advance() == true. | ||||
* | ||||
* While it is legal to call getCurrent() multiple times between c | ||||
alls to advance, and | ||||
* you will get the same Document returned, some DocumentSources d | ||||
o expensive work in | ||||
* getCurrent(). You are advised to cache the result if you plan t | ||||
o access it more than | ||||
* once. | ||||
*/ | */ | |||
virtual Document getCurrent() = 0; | virtual boost::optional<Document> getNext() = 0; | |||
/** | /** | |||
* Inform the source that it is no longer needed and may release it s resources. After | * Inform the source that it is no longer needed and may release it s resources. After | |||
* dispose() is called the source must still be able to handle iter ation requests, but may | * dispose() is called the source must still be able to handle iter ation requests, but may | |||
* become eof(). | * become eof(). | |||
* NOTE: For proper mutex yielding, dispose() must be called on any DocumentSource that will | * NOTE: For proper mutex yielding, dispose() must be called on any DocumentSource that will | |||
* not be advanced until eof(), see SERVER-6123. | * not be advanced until eof(), see SERVER-6123. | |||
*/ | */ | |||
virtual void dispose(); | virtual void dispose(); | |||
skipping to change at line 201 | skipping to change at line 176 | |||
array being built here. | array being built here. | |||
A subclass may choose to overwrite this rather than addToBsonArra y | A subclass may choose to overwrite this rather than addToBsonArra y | |||
if it should output multiple stages. | 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, bool explai n=false) const; | virtual void addToBsonArray(BSONArrayBuilder *pBuilder, bool explai n=false) const; | |||
/// Returns true if doesn't require an input source (most DocumentS | ||||
ources do). | ||||
virtual bool isValidInitialSource() const { return false; } | ||||
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 | |||
will be used by the default implementation of addToBsonArray() | will be used by the default implementation of addToBsonArray() | |||
skipping to change at line 248 | skipping to change at line 226 | |||
/* | /* | |||
for explain: # of rows returned by this source | for explain: # of rows returned by this source | |||
This is *not* unsigned so it can be passed to BSONObjBuilder.appe nd(). | This is *not* unsigned so it can be passed to BSONObjBuilder.appe nd(). | |||
*/ | */ | |||
long long nRowsOut; | long long nRowsOut; | |||
}; | }; | |||
/** This class marks DocumentSources that should be split between the r outer and the shards | /** This class marks DocumentSources that should be split between the r outer and the shards | |||
* See Pipeline::splitForSharded() for details | * See Pipeline::splitForSharded() for details | |||
* | ||||
* TODO inheriting from DocumentSource here was a mistake. It should b | ||||
e separate. | ||||
*/ | */ | |||
class SplittableDocumentSource : public DocumentSource { | class SplittableDocumentSource : public DocumentSource { | |||
public: | public: | |||
/** returns a source to be run on the shards. | /** returns a source to be run on the shards. | |||
* if NULL, don't run on shards | * if NULL, don't run on shards | |||
*/ | */ | |||
virtual intrusive_ptr<DocumentSource> getShardSource() = 0; | virtual intrusive_ptr<DocumentSource> getShardSource() = 0; | |||
/** returns a source that combines results from shards. | /** returns a source that combines results from shards. | |||
* if NULL, don't run on router | * if NULL, don't run on router | |||
*/ | */ | |||
virtual intrusive_ptr<DocumentSource> getRouterSource() = 0; | virtual intrusive_ptr<DocumentSource> getRouterSource() = 0; | |||
protected: | protected: | |||
SplittableDocumentSource(intrusive_ptr<ExpressionContext> ctx) :Doc umentSource(ctx) {} | SplittableDocumentSource(intrusive_ptr<ExpressionContext> ctx) :Doc umentSource(ctx) {} | |||
}; | }; | |||
/** This class marks DocumentSources which need mongod-specific functio | ||||
nality. | ||||
* It causes a MongodInterface to be injected when in a mongod and pre | ||||
vents mongos from | ||||
* merging pipelines containing this stage. | ||||
*/ | ||||
class DocumentSourceNeedsMongod { | ||||
public: | ||||
// Wraps mongod-specific functions to allow linking into mongos. | ||||
class MongodInterface { | ||||
public: | ||||
virtual ~MongodInterface() {}; | ||||
virtual DBClientBase* directClient() = 0; // Always returns a D | ||||
BDirectClient | ||||
// Note that in some rare cases this could return a false negat | ||||
ive but will never return | ||||
// a false positive. This method will be fixed in the future on | ||||
ce it becomes possible to | ||||
// avoid false negatives. | ||||
virtual bool isSharded(const NamespaceString& ns) = 0; | ||||
// Add new methods as needed. | ||||
}; | ||||
void injectMongodInterface(boost::shared_ptr<MongodInterface> mongo | ||||
d) { | ||||
_mongod = mongod; | ||||
} | ||||
protected: | ||||
// It is invalid to delete through a DocumentSourceNeedsMongod-type | ||||
d pointer. | ||||
virtual ~DocumentSourceNeedsMongod() {} | ||||
// Gives subclasses access to a MongodInterface implementation | ||||
shared_ptr<MongodInterface> _mongod; | ||||
}; | ||||
class DocumentSourceBsonArray : | class DocumentSourceBsonArray : | |||
public DocumentSource { | public DocumentSource { | |||
public: | public: | |||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual ~DocumentSourceBsonArray(); | virtual boost::optional<Document> getNext(); | |||
virtual bool eof(); | ||||
virtual bool advance(); | ||||
virtual Document getCurrent(); | ||||
virtual void setSource(DocumentSource *pSource); | virtual void setSource(DocumentSource *pSource); | |||
virtual bool isValidInitialSource() const { return true; } | ||||
/** | /** | |||
Create a document source based on a BSON array. | Create a document source based on a BSON array. | |||
This is usually put at the beginning of a chain of document sourc es | This is usually put at the beginning of a chain of document sourc es | |||
in order to fetch data from the database. | in order to fetch data from the database. | |||
CAUTION: the BSON is not read until the source is used. Any | CAUTION: the BSON is not read until the source is used. Any | |||
elements that appear after these documents must not be read until | elements that appear after these documents must not be read until | |||
this source is exhausted. | this source is exhausted. | |||
skipping to change at line 302 | skipping to change at line 313 | |||
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: | |||
DocumentSourceBsonArray(BSONElement *pBsonElement, | DocumentSourceBsonArray(BSONElement *pBsonElement, | |||
const intrusive_ptr<ExpressionContext> &pExpCtx); | const intrusive_ptr<ExpressionContext> &pExpCtx); | |||
BSONObj embeddedObject; | BSONObj embeddedObject; | |||
BSONObjIterator arrayIterator; | BSONObjIterator arrayIterator; | |||
BSONElement currentElement; | ||||
bool haveCurrent; | ||||
}; | }; | |||
class DocumentSourceCommandShards : | class DocumentSourceCommandShards : | |||
public DocumentSource { | public DocumentSource { | |||
public: | public: | |||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual ~DocumentSourceCommandShards(); | virtual boost::optional<Document> getNext(); | |||
virtual bool eof(); | ||||
virtual bool advance(); | ||||
virtual Document getCurrent(); | ||||
virtual void setSource(DocumentSource *pSource); | virtual void setSource(DocumentSource *pSource); | |||
virtual bool isValidInitialSource() const { return true; } | ||||
/* convenient shorthand for a commonly used type */ | /* convenient shorthand for a commonly used type */ | |||
typedef map<Shard, BSONObj> ShardOutput; | typedef vector<Strategy::CommandResult> ShardOutput; | |||
/** | /** | |||
Create a DocumentSource that wraps the output of many shards | Create a DocumentSource that wraps the output of many shards | |||
@param shardOutput output from the individual shards | @param shardOutput output from the individual shards | |||
@param pExpCtx the expression context for the pipeline | @param pExpCtx the expression context for the pipeline | |||
@returns the newly created DocumentSource | @returns the newly created DocumentSource | |||
*/ | */ | |||
static intrusive_ptr<DocumentSourceCommandShards> create( | static intrusive_ptr<DocumentSourceCommandShards> create( | |||
const ShardOutput& shardOutput, | const ShardOutput& shardOutput, | |||
skipping to change at line 365 | skipping to change at line 372 | |||
/** | /** | |||
* Constructs and returns Documents from the BSONObj objects produced b y a supplied Cursor. | * Constructs and returns Documents from the BSONObj objects produced b y a supplied Cursor. | |||
* An object of this type may only be used by one thread, see SERVER-61 23. | * An object of this type may only be used by one thread, see SERVER-61 23. | |||
*/ | */ | |||
class DocumentSourceCursor : | class DocumentSourceCursor : | |||
public DocumentSource { | public DocumentSource { | |||
public: | public: | |||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual ~DocumentSourceCursor(); | virtual ~DocumentSourceCursor(); | |||
virtual bool eof(); | virtual boost::optional<Document> getNext(); | |||
virtual bool advance(); | ||||
virtual Document getCurrent(); | ||||
virtual void setSource(DocumentSource *pSource); | virtual void setSource(DocumentSource *pSource); | |||
virtual bool coalesce(const intrusive_ptr<DocumentSource>& nextSour | ||||
ce); | ||||
virtual bool isValidInitialSource() const { return true; } | ||||
/** | /** | |||
* Release the Cursor and the read lock it requires, but without ch anging the other data. | * Release the Cursor and the read lock it requires, but without ch anging the other data. | |||
* Releasing the lock is required for proper concurrency, see SERVE R-6123. This | * Releasing the lock is required for proper concurrency, see SERVE R-6123. This | |||
* functionality is also used by the explain version of pipeline ex ecution. | * functionality is also used by the explain version of pipeline ex ecution. | |||
*/ | */ | |||
virtual void dispose(); | virtual void dispose(); | |||
/** | /** | |||
* Create a document source based on a passed-in cursor. | * Create a document source based on a passed-in cursor. | |||
skipping to change at line 429 | skipping to change at line 436 | |||
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 BSONObj& sort) { _sort = sort; } | void setSort(const BSONObj& sort) { _sort = sort; } | |||
void setProjection(const BSONObj& projection, const ParsedDeps& dep s); | void setProjection(const BSONObj& projection, const ParsedDeps& dep s); | |||
/// returns -1 for no limit | ||||
long long getLimit() const; | ||||
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 string& ns, | const string& ns, | |||
CursorId cursorId, | CursorId cursorId, | |||
const intrusive_ptr<ExpressionContext> &pExpCtx); | const intrusive_ptr<ExpressionContext> &pExpCtx); | |||
void findNext(); | void loadBatch(); | |||
bool unstarted; | std::deque<Document> _currentBatch; | |||
bool hasCurrent; | ||||
Document pCurrent; | ||||
// BSONObj members must outlive _projection and cursor. | // BSONObj members must outlive _projection and cursor. | |||
BSONObj _query; | BSONObj _query; | |||
BSONObj _sort; | BSONObj _sort; | |||
shared_ptr<Projection> _projection; // shared with pClientCursor | shared_ptr<Projection> _projection; // shared with pClientCursor | |||
ParsedDeps _dependencies; | ParsedDeps _dependencies; | |||
intrusive_ptr<DocumentSourceLimit> _limit; | ||||
long long _docsAddedToBatches; // for _limit enforcement | ||||
string ns; // namespace | string ns; // namespace | |||
CursorId _cursorId; | CursorId _cursorId; | |||
CollectionMetadataPtr _collMetadata; | CollectionMetadataPtr _collMetadata; | |||
bool canUseCoveredIndex(ClientCursor* cursor); | bool canUseCoveredIndex(ClientCursor* cursor); | |||
/* | /* | |||
Yield the cursor sometimes. | Yield the cursor sometimes. | |||
skipping to change at line 478 | skipping to change at line 488 | |||
/* | /* | |||
This contains all the basic mechanics for filtering a stream of | This contains all the basic mechanics for filtering a stream of | |||
Documents, except for the actual predicate evaluation itself. This w as | Documents, except for the actual predicate evaluation itself. This w as | |||
factored out so we could create DocumentSources that use both Matcher | factored out so we could create DocumentSources that use both Matcher | |||
style predicates as well as full Expressions. | style predicates as well as full Expressions. | |||
*/ | */ | |||
class DocumentSourceFilterBase : | class DocumentSourceFilterBase : | |||
public DocumentSource { | public DocumentSource { | |||
public: | public: | |||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual ~DocumentSourceFilterBase(); | virtual boost::optional<Document> getNext(); | |||
virtual bool eof(); | ||||
virtual bool advance(); | ||||
virtual Document getCurrent(); | ||||
/** | /** | |||
Create a BSONObj suitable for Matcher construction. | Create a BSONObj suitable for Matcher construction. | |||
This is used after filter analysis has moved as many filters to | This is used after filter analysis has moved as many filters to | |||
as early a point as possible in the document processing pipeline. | as early a point as possible in the document processing pipeline. | |||
See db/Matcher.h and the associated documentation for the format. | See db/Matcher.h and the associated documentation for the format. | |||
This conversion is used to move back to the low-level find() | This conversion is used to move back to the low-level find() | |||
Cursor mechanism. | Cursor mechanism. | |||
skipping to change at line 510 | skipping to change at line 517 | |||
/** | /** | |||
Test the given document against the predicate and report if it | Test the given document against the predicate and report if it | |||
should be accepted or not. | should be accepted or not. | |||
@param pDocument the document to test | @param pDocument the document to test | |||
@returns true if the document matches the filter, false otherwise | @returns true if the document matches the filter, false otherwise | |||
*/ | */ | |||
virtual bool accept(const Document& pDocument) const = 0; | virtual bool accept(const Document& pDocument) const = 0; | |||
private: | private: | |||
void findNext(); | ||||
bool unstarted; | bool unstarted; | |||
bool hasCurrent; | ||||
Document pCurrent; | ||||
}; | ||||
class DocumentSourceFilter : | ||||
public DocumentSourceFilterBase { | ||||
public: | ||||
// virtuals from DocumentSource | ||||
virtual ~DocumentSourceFilter(); | ||||
virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou | ||||
rce); | ||||
virtual void optimize(); | ||||
virtual const char *getSourceName() const; | ||||
/** | ||||
Create a filter. | ||||
@param pBsonElement the raw BSON specification for the filter | ||||
@param pExpCtx the expression context for the pipeline | ||||
@returns the filter | ||||
*/ | ||||
static intrusive_ptr<DocumentSource> createFromBson( | ||||
BSONElement *pBsonElement, | ||||
const intrusive_ptr<ExpressionContext> &pExpCtx); | ||||
/** | ||||
Create a filter. | ||||
@param pFilter the expression to use to filter | ||||
@param pExpCtx the expression context for the pipeline | ||||
@returns the filter | ||||
*/ | ||||
static intrusive_ptr<DocumentSourceFilter> create( | ||||
const intrusive_ptr<Expression> &pFilter, | ||||
const intrusive_ptr<ExpressionContext> &pExpCtx); | ||||
/** | ||||
Create a BSONObj suitable for Matcher construction. | ||||
This is used after filter analysis has moved as many filters to | ||||
as early a point as possible in the document processing pipeline. | ||||
See db/Matcher.h and the associated documentation for the format. | ||||
This conversion is used to move back to the low-level find() | ||||
Cursor mechanism. | ||||
@param pBuilder the builder to write to | ||||
*/ | ||||
void toMatcherBson(BSONObjBuilder *pBuilder) const; | ||||
static const char filterName[]; | ||||
protected: | ||||
// virtuals from DocumentSource | ||||
virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c | ||||
onst; | ||||
// virtuals from DocumentSourceFilterBase | ||||
virtual bool accept(const Document& pDocument) const; | ||||
private: | ||||
DocumentSourceFilter(const intrusive_ptr<Expression> &pFilter, | ||||
const intrusive_ptr<ExpressionContext> &pExpCt | ||||
x); | ||||
intrusive_ptr<Expression> pFilter; | ||||
}; | }; | |||
class DocumentSourceGroup : | class DocumentSourceGroup : | |||
public SplittableDocumentSource { | public SplittableDocumentSource { | |||
public: | public: | |||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual ~DocumentSourceGroup(); | virtual boost::optional<Document> getNext(); | |||
virtual bool eof(); | ||||
virtual bool advance(); | ||||
virtual const char *getSourceName() const; | virtual const char *getSourceName() const; | |||
virtual Document getCurrent(); | ||||
virtual GetDepsReturn getDependencies(set<string>& deps) const; | virtual GetDepsReturn getDependencies(set<string>& deps) const; | |||
virtual void dispose(); | 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( | |||
skipping to change at line 626 | skipping to change at line 565 | |||
@param fieldName the name the accumulator result will have in the | @param fieldName the name the accumulator result will have in the | |||
result documents | result documents | |||
@param pAccumulatorFactory used to create the accumulator for the | @param pAccumulatorFactory used to create the accumulator for the | |||
group field | group field | |||
*/ | */ | |||
void addAccumulator(const std::string& fieldName, | void addAccumulator(const std::string& fieldName, | |||
intrusive_ptr<Accumulator> (*pAccumulatorFactor y)(), | intrusive_ptr<Accumulator> (*pAccumulatorFactor y)(), | |||
const intrusive_ptr<Expression> &pExpression); | const intrusive_ptr<Expression> &pExpression); | |||
/// Tell this source if it is doing a merge from shards. Defaults t | ||||
o false. | ||||
void setDoingMerge(bool doingMerge) { _doingMerge = doingMerge; } | ||||
/** | /** | |||
Create a grouping DocumentSource from BSON. | Create a grouping DocumentSource from BSON. | |||
This is a convenience method that uses the above, and operates on | This is a convenience method that uses the above, and operates on | |||
a BSONElement that has been deteremined to be an Object with an | a BSONElement that has been deteremined to be an Object with an | |||
element named $group. | element named $group. | |||
@param pBsonElement the BSONELement that defines the group | @param pBsonElement the BSONELement that defines the group | |||
@param pExpCtx the expression context | @param pExpCtx the expression context | |||
@returns the grouping DocumentSource | @returns the grouping DocumentSource | |||
skipping to change at line 693 | skipping to change at line 635 | |||
accumulators for each new group. | accumulators for each new group. | |||
These three vectors parallel each other. | These three vectors parallel each other. | |||
*/ | */ | |||
vector<string> vFieldName; | vector<string> vFieldName; | |||
vector<intrusive_ptr<Accumulator> (*)()> vpAccumulatorFactory; | vector<intrusive_ptr<Accumulator> (*)()> vpAccumulatorFactory; | |||
vector<intrusive_ptr<Expression> > vpExpression; | vector<intrusive_ptr<Expression> > vpExpression; | |||
Document makeDocument(const Value& id, const Accumulators& accums, bool mergeableOutput); | Document makeDocument(const Value& id, const Accumulators& accums, bool mergeableOutput); | |||
bool _doingMerge; | ||||
bool _spilled; | bool _spilled; | |||
const bool _extSortAllowed; | const bool _extSortAllowed; | |||
const int _maxMemoryUsageBytes; | const int _maxMemoryUsageBytes; | |||
// only used when !_spilled | // only used when !_spilled | |||
GroupsMap::iterator groupsIterator; | GroupsMap::iterator groupsIterator; | |||
// only used when _spilled | // only used when _spilled | |||
scoped_ptr<Sorter<Value, Value>::Iterator> _sorterIterator; | scoped_ptr<Sorter<Value, Value>::Iterator> _sorterIterator; | |||
pair<Value, Value> _firstPartOfNextGroup; | pair<Value, Value> _firstPartOfNextGroup; | |||
Value _currentId; | Value _currentId; | |||
Accumulators _currentAccumulators; | Accumulators _currentAccumulators; | |||
bool _doneAfterNextAdvance; | ||||
bool _done; | ||||
}; | }; | |||
class DocumentSourceMatch : | class DocumentSourceMatch : | |||
public DocumentSourceFilterBase { | public DocumentSourceFilterBase { | |||
public: | public: | |||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual ~DocumentSourceMatch(); | ||||
virtual const char *getSourceName() const; | virtual const char *getSourceName() const; | |||
/** | /** | |||
Create a filter. | Create a filter. | |||
@param pBsonElement the raw BSON specification for the filter | @param pBsonElement the raw BSON specification for the filter | |||
@returns the filter | @returns the filter | |||
*/ | */ | |||
static intrusive_ptr<DocumentSource> createFromBson( | static intrusive_ptr<DocumentSource> createFromBson( | |||
BSONElement *pBsonElement, | BSONElement *pBsonElement, | |||
skipping to change at line 755 | skipping to change at line 695 | |||
// virtuals from DocumentSourceFilterBase | // virtuals from DocumentSourceFilterBase | |||
virtual bool accept(const Document& pDocument) const; | virtual bool accept(const Document& pDocument) const; | |||
private: | private: | |||
DocumentSourceMatch(const BSONObj &query, | DocumentSourceMatch(const BSONObj &query, | |||
const intrusive_ptr<ExpressionContext> &pExpCtx); | const intrusive_ptr<ExpressionContext> &pExpCtx); | |||
Matcher matcher; | Matcher matcher; | |||
}; | }; | |||
class DocumentSourceOut : | class DocumentSourceMergeCursors : | |||
public DocumentSource { | public DocumentSource { | |||
public: | public: | |||
typedef vector<pair<ConnectionString, CursorId> > CursorIds; | ||||
// virtuals from DocumentSource | ||||
boost::optional<Document> getNext(); | ||||
virtual void setSource(DocumentSource *pSource); | ||||
virtual const char *getSourceName() const; | ||||
virtual void dispose(); | ||||
virtual bool isValidInitialSource() const { return true; } | ||||
static intrusive_ptr<DocumentSource> createFromBson( | ||||
BSONElement *pBsonElement, | ||||
const intrusive_ptr<ExpressionContext> &pExpCtx); | ||||
static intrusive_ptr<DocumentSource> create( | ||||
const CursorIds& cursorIds, | ||||
const intrusive_ptr<ExpressionContext> &pExpCtx); | ||||
static const char name[]; | ||||
protected: | ||||
// virtuals from DocumentSource | ||||
virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c | ||||
onst; | ||||
private: | ||||
struct CursorAndConnection { | ||||
CursorAndConnection(ConnectionString host, NamespaceString ns, | ||||
CursorId id); | ||||
ScopedDbConnection connection; | ||||
DBClientCursor cursor; | ||||
}; | ||||
// using list to enable removing arbitrary elements | ||||
typedef list<boost::shared_ptr<CursorAndConnection> > Cursors; | ||||
DocumentSourceMergeCursors( | ||||
const CursorIds& cursorIds, | ||||
const intrusive_ptr<ExpressionContext> &pExpCtx); | ||||
// This is the description of cursors to merge. | ||||
const CursorIds _cursorIds; | ||||
// These are the actual cursors we are merging. Created lazily. | ||||
Cursors _cursors; | ||||
Cursors::iterator _currentCursor; | ||||
bool _unstarted; | ||||
}; | ||||
class DocumentSourceOut : public SplittableDocumentSource | ||||
, public DocumentSourceNeedsMongod { | ||||
public: | ||||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual ~DocumentSourceOut(); | virtual ~DocumentSourceOut(); | |||
virtual bool eof(); | virtual boost::optional<Document> getNext(); | |||
virtual bool advance(); | ||||
virtual const char *getSourceName() const; | virtual const char *getSourceName() const; | |||
virtual Document getCurrent(); | ||||
// Virtuals for SplittableDocumentSource | ||||
virtual intrusive_ptr<DocumentSource> getShardSource() { return NUL | ||||
L; } | ||||
virtual intrusive_ptr<DocumentSource> getRouterSource() { return th | ||||
is; } | ||||
const NamespaceString& getOutputNs() const { return _outputNs; } | ||||
/** | /** | |||
Create a document source for output and pass-through. | Create a document source for output and pass-through. | |||
This can be put anywhere in a pipeline and will store content as | This can be put anywhere in a pipeline and will store content as | |||
well as pass it on. | well as pass it on. | |||
@param pBsonElement the raw BSON specification for the source | @param pBsonElement the raw BSON specification for the source | |||
@param pExpCtx the expression context for the pipeline | @param pExpCtx the expression context for the pipeline | |||
@returns the newly created document source | @returns the newly created document source | |||
*/ | */ | |||
static intrusive_ptr<DocumentSourceOut> createFromBson( | static intrusive_ptr<DocumentSource> createFromBson( | |||
BSONElement *pBsonElement, | BSONElement *pBsonElement, | |||
const intrusive_ptr<ExpressionContext> &pExpCtx); | const intrusive_ptr<ExpressionContext> &pExpCtx); | |||
static const char outName[]; | static const char outName[]; | |||
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: | |||
DocumentSourceOut(BSONElement *pBsonElement, | DocumentSourceOut(const NamespaceString& outputNs, | |||
const intrusive_ptr<ExpressionContext> &pExpCtx); | const intrusive_ptr<ExpressionContext> &pExpCtx); | |||
// Sets _tempsNs and prepares it to receive data. | ||||
void prepTempCollection(); | ||||
void spill(DBClientBase* conn, const vector<BSONObj>& toInsert); | ||||
bool _done; | ||||
NamespaceString _tempNs; // output goes here as it is being process | ||||
ed. | ||||
const NamespaceString _outputNs; // output will go here after all d | ||||
ata is processed. | ||||
}; | }; | |||
class DocumentSourceProject : | class DocumentSourceProject : | |||
public DocumentSource { | public DocumentSource { | |||
public: | public: | |||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual ~DocumentSourceProject(); | virtual boost::optional<Document> getNext(); | |||
virtual bool eof(); | ||||
virtual bool advance(); | ||||
virtual const char *getSourceName() const; | virtual const char *getSourceName() const; | |||
virtual Document getCurrent(); | ||||
virtual void optimize(); | virtual void optimize(); | |||
virtual GetDepsReturn getDependencies(set<string>& deps) const; | virtual GetDepsReturn getDependencies(set<string>& deps) const; | |||
/** | /** | |||
Create a new projection DocumentSource from BSON. | Create a new projection DocumentSource from BSON. | |||
This is a convenience for directly handling BSON, and relies on t he | This is a convenience for directly handling BSON, and relies on t he | |||
above methods. | above methods. | |||
skipping to change at line 840 | skipping to change at line 841 | |||
// configuration state | // configuration state | |||
intrusive_ptr<ExpressionObject> pEO; | intrusive_ptr<ExpressionObject> pEO; | |||
BSONObj _raw; | BSONObj _raw; | |||
#if defined(_DEBUG) | #if defined(_DEBUG) | |||
// this is used in DEBUG builds to ensure we are compatible | // this is used in DEBUG builds to ensure we are compatible | |||
Projection _simpleProjection; | Projection _simpleProjection; | |||
#endif | #endif | |||
}; | }; | |||
class DocumentSourceRedact : | ||||
public DocumentSource { | ||||
public: | ||||
virtual boost::optional<Document> getNext(); | ||||
virtual const char* getSourceName() const; | ||||
virtual void optimize(); | ||||
static const char redactName[]; | ||||
static intrusive_ptr<DocumentSource> createFromBson(BSONElement* bs | ||||
onElement, | ||||
const intrusive_ptr<ExpressionContext>& expCtx); | ||||
protected: | ||||
virtual void sourceToBson(BSONObjBuilder* pBuilder, bool explain) c | ||||
onst; | ||||
private: | ||||
DocumentSourceRedact(const intrusive_ptr<ExpressionContext>& expCtx | ||||
, | ||||
const intrusive_ptr<Expression>& previsit); | ||||
boost::optional<Document> redactObject(const Variables& in); | ||||
Value redactValue(const Variables& vars, const Value& in); | ||||
intrusive_ptr<Expression> _expression; | ||||
}; | ||||
class DocumentSourceSort : | class DocumentSourceSort : | |||
public SplittableDocumentSource { | public SplittableDocumentSource { | |||
public: | public: | |||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual ~DocumentSourceSort(); | virtual boost::optional<Document> getNext(); | |||
virtual bool eof(); | ||||
virtual bool advance(); | ||||
virtual const char *getSourceName() const; | virtual const char *getSourceName() const; | |||
virtual Document getCurrent(); | ||||
virtual void addToBsonArray(BSONArrayBuilder *pBuilder, bool explai n=false) const; | virtual void addToBsonArray(BSONArrayBuilder *pBuilder, bool explai n=false) const; | |||
virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou rce); | virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou rce); | |||
virtual void dispose(); | virtual void dispose(); | |||
virtual GetDepsReturn getDependencies(set<string>& deps) const; | virtual GetDepsReturn getDependencies(set<string>& deps) const; | |||
// Virtuals for SplittableDocumentSource | // Virtuals for SplittableDocumentSource | |||
// All work for sort is done in router currently if there is no lim it. | // All work for sort is done in router currently if there is no lim it. | |||
// If there is a limit, the $sort/$limit combination is performed o n the | // If there is a limit, the $sort/$limit combination is performed o n the | |||
// shards, then the results are resorted and limited on mongos | // shards, then the results are resorted and limited on mongos | |||
skipping to change at line 954 | skipping to change at line 976 | |||
int operator()(const MySorter::Data& lhs, const MySorter::Data& rhs) const { | int operator()(const MySorter::Data& lhs, const MySorter::Data& rhs) const { | |||
return _source.compare(lhs.first, rhs.first); | return _source.compare(lhs.first, rhs.first); | |||
} | } | |||
private: | private: | |||
const DocumentSourceSort& _source; | const DocumentSourceSort& _source; | |||
}; | }; | |||
intrusive_ptr<DocumentSourceLimit> limitSrc; | intrusive_ptr<DocumentSourceLimit> limitSrc; | |||
bool _done; | bool _done; | |||
Document _current; | ||||
scoped_ptr<MySorter::Iterator> _output; | scoped_ptr<MySorter::Iterator> _output; | |||
}; | }; | |||
class DocumentSourceLimit : | class DocumentSourceLimit : | |||
public SplittableDocumentSource { | public SplittableDocumentSource { | |||
public: | public: | |||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual ~DocumentSourceLimit(); | virtual boost::optional<Document> getNext(); | |||
virtual bool eof(); | ||||
virtual bool advance(); | ||||
virtual Document getCurrent(); | ||||
virtual const char *getSourceName() const; | virtual const char *getSourceName() const; | |||
virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou rce); | virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou rce); | |||
virtual GetDepsReturn getDependencies(set<string>& deps) const { | virtual GetDepsReturn getDependencies(set<string>& deps) const { | |||
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. | |||
skipping to change at line 1024 | skipping to change at line 1042 | |||
long long limit); | 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 boost::optional<Document> getNext(); | |||
virtual bool eof(); | ||||
virtual bool advance(); | ||||
virtual Document getCurrent(); | ||||
virtual const char *getSourceName() const; | virtual const char *getSourceName() const; | |||
virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou rce); | virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou rce); | |||
virtual GetDepsReturn getDependencies(set<string>& deps) const { | virtual GetDepsReturn getDependencies(set<string>& deps) const { | |||
return SEE_NEXT; // This doesn't affect needed fields | return SEE_NEXT; // This doesn't affect needed fields | |||
} | } | |||
/** | /** | |||
Create a new skipping DocumentSource. | Create a new skipping DocumentSource. | |||
skipping to change at line 1049 | skipping to change at line 1064 | |||
@returns the DocumentSource | @returns the DocumentSource | |||
*/ | */ | |||
static intrusive_ptr<DocumentSourceSkip> create( | static intrusive_ptr<DocumentSourceSkip> create( | |||
const intrusive_ptr<ExpressionContext> &pExpCtx); | const intrusive_ptr<ExpressionContext> &pExpCtx); | |||
// Virtuals for SplittableDocumentSource | // Virtuals for SplittableDocumentSource | |||
// Need to run on rounter. Can't run on shards. | // Need to run on rounter. Can't run on shards. | |||
virtual intrusive_ptr<DocumentSource> getShardSource() { return NUL L; } | virtual intrusive_ptr<DocumentSource> getShardSource() { return NUL L; } | |||
virtual intrusive_ptr<DocumentSource> getRouterSource() { return th is; } | virtual intrusive_ptr<DocumentSource> getRouterSource() { return th is; } | |||
long long getSkip() const { return skip; } | long long getSkip() const { return _skip; } | |||
void setSkip(long long newSkip) { skip = newSkip; } | void setSkip(long long newSkip) { _skip = newSkip; } | |||
/** | /** | |||
Create a skipping DocumentSource from BSON. | Create a skipping DocumentSource from BSON. | |||
This is a convenience method that uses the above, and operates on | This is a convenience method that uses the above, and operates on | |||
a BSONElement that has been deteremined to be an Object with an | a BSONElement that has been deteremined to be an Object with an | |||
element named $skip. | element named $skip. | |||
@param pBsonElement the BSONELement that defines the skip | @param pBsonElement the BSONELement that defines the skip | |||
@param pExpCtx the expression context | @param pExpCtx the expression context | |||
skipping to change at line 1076 | skipping to change at line 1091 | |||
static const char skipName[]; | static const char skipName[]; | |||
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: | |||
DocumentSourceSkip(const intrusive_ptr<ExpressionContext> &pExpCtx) ; | DocumentSourceSkip(const intrusive_ptr<ExpressionContext> &pExpCtx) ; | |||
/* | long long _skip; | |||
Skips initial documents. | bool _needToSkip; | |||
*/ | ||||
void skipper(); | ||||
long long skip; | ||||
long long count; | ||||
Document pCurrent; | ||||
}; | }; | |||
class DocumentSourceUnwind : | class DocumentSourceUnwind : | |||
public DocumentSource { | public DocumentSource { | |||
public: | public: | |||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual ~DocumentSourceUnwind(); | virtual boost::optional<Document> getNext(); | |||
virtual bool eof(); | ||||
virtual bool advance(); | ||||
virtual const char *getSourceName() const; | virtual const char *getSourceName() const; | |||
virtual Document getCurrent(); | ||||
virtual GetDepsReturn getDependencies(set<string>& deps) const; | virtual GetDepsReturn getDependencies(set<string>& deps) const; | |||
/** | /** | |||
Create a new projection DocumentSource from BSON. | Create a new projection DocumentSource from BSON. | |||
This is a convenience for directly handling BSON, and relies on t he | This is a convenience for directly handling BSON, and relies on t he | |||
above methods. | above methods. | |||
@param pBsonElement the BSONElement with an object named $project | @param pBsonElement the BSONElement with an object named $project | |||
skipping to change at line 1121 | skipping to change at line 1127 | |||
static const char unwindName[]; | static const char unwindName[]; | |||
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: | |||
DocumentSourceUnwind(const intrusive_ptr<ExpressionContext> &pExpCt x); | DocumentSourceUnwind(const intrusive_ptr<ExpressionContext> &pExpCt x); | |||
/** | ||||
* Lazily construct the _unwinder and initialize the iterator state | ||||
of this DocumentSource. | ||||
* To be called by all members that depend on the iterator state. | ||||
*/ | ||||
void lazyInit(); | ||||
/** | ||||
* If the _unwinder is exhausted and the source may be advanced, ad | ||||
vance the pSource and | ||||
* reset the _unwinder's source document. | ||||
*/ | ||||
void mayAdvanceSource(); | ||||
/** Specify the field to unwind. */ | /** Specify the field to unwind. */ | |||
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 { | class DocumentSourceGeoNear : public SplittableDocumentSource | |||
, public DocumentSourceNeedsMongod { | ||||
public: | public: | |||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual ~DocumentSourceGeoNear(); | virtual boost::optional<Document> getNext(); | |||
virtual bool eof(); | ||||
virtual bool advance(); | ||||
virtual Document getCurrent(); | ||||
virtual const char *getSourceName() const; | virtual const char *getSourceName() const; | |||
virtual void setSource(DocumentSource *pSource); // errors out sinc e this must be first | virtual void setSource(DocumentSource *pSource); // errors out sinc e this must be first | |||
virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou rce); | virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou rce); | |||
virtual bool isValidInitialSource() const { return true; } | ||||
// Virtuals for SplittableDocumentSource | // Virtuals for SplittableDocumentSource | |||
virtual intrusive_ptr<DocumentSource> getShardSource(); | virtual intrusive_ptr<DocumentSource> getShardSource(); | |||
virtual intrusive_ptr<DocumentSource> getRouterSource(); | virtual intrusive_ptr<DocumentSource> getRouterSource(); | |||
static intrusive_ptr<DocumentSource> createFromBson( | static intrusive_ptr<DocumentSource> createFromBson( | |||
BSONElement *pBsonElement, | BSONElement *pBsonElement, | |||
const intrusive_ptr<ExpressionContext> &pCtx); | const intrusive_ptr<ExpressionContext> &pCtx); | |||
static char geoNearName[]; | static char geoNearName[]; | |||
skipping to change at line 1179 | skipping to change at line 1172 | |||
const intrusive_ptr<ExpressionContext> &pCtx); | const intrusive_ptr<ExpressionContext> &pCtx); | |||
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: | |||
DocumentSourceGeoNear(const intrusive_ptr<ExpressionContext> &pExpC tx); | DocumentSourceGeoNear(const intrusive_ptr<ExpressionContext> &pExpC tx); | |||
void parseOptions(BSONObj options); | void parseOptions(BSONObj options); | |||
BSONObj buildGeoNearCmd(const StringData& collection) const; | BSONObj buildGeoNearCmd() const; | |||
void runCommand(); | void runCommand(); | |||
// These fields describe the command to run. | // These fields describe the command to run. | |||
// coords and distanceField are required, rest are optional | // coords and distanceField are required, rest are optional | |||
BSONObj coords; // "near" option, but near is a reserved keyword on windows | BSONObj coords; // "near" option, but near is a reserved keyword on windows | |||
bool coordsIsArray; | bool coordsIsArray; | |||
scoped_ptr<FieldPath> distanceField; // Using scoped_ptr because Fi eldPath can't be empty | scoped_ptr<FieldPath> distanceField; // Using scoped_ptr because Fi eldPath can't be empty | |||
long long limit; | long long limit; | |||
double maxDistance; | double maxDistance; | |||
BSONObj query; | BSONObj query; | |||
bool spherical; | bool spherical; | |||
double distanceMultiplier; | double distanceMultiplier; | |||
scoped_ptr<FieldPath> includeLocs; | scoped_ptr<FieldPath> includeLocs; | |||
bool uniqueDocs; | 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 | // these fields are used while processing the results | |||
BSONObj cmdOutput; | BSONObj cmdOutput; | |||
boost::scoped_ptr<BSONObjIterator> resultsIterator; // iterator ove r cmdOutput["results"] | 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. 56 change blocks. | ||||
208 lines changed or deleted | 196 lines changed or added | |||
dur.h | dur.h | |||
---|---|---|---|---|
skipping to change at line 22 | skipping to change at line 22 | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Licen se | * You should have received a copy of the GNU Affero General Public Licen se | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/db/diskloc.h" | #include "mongo/db/diskloc.h" | |||
#include "mongo/db/mongommf.h" | #include "mongo/db/storage/durable_mapped_file.h" | |||
namespace mongo { | namespace mongo { | |||
class NamespaceDetails; | class NamespaceDetails; | |||
void mongoAbort(const char *msg); | void mongoAbort(const char *msg); | |||
void abort(); // not defined -- use mongoAbort() instead | void abort(); // not defined -- use mongoAbort() instead | |||
namespace dur { | namespace dur { | |||
skipping to change at line 138 | skipping to change at line 138 | |||
/** Declare write intent for an int */ | /** Declare write intent for an int */ | |||
inline int& writingInt(int& d) { return *static_cast<int*>(writ ingPtr( &d, sizeof(d))); } | inline int& writingInt(int& d) { return *static_cast<int*>(writ ingPtr( &d, sizeof(d))); } | |||
/** "assume i've already indicated write intent, let me write" | /** "assume i've already indicated write intent, let me write" | |||
redeclaration is fine too, but this is faster. | redeclaration is fine too, but this is faster. | |||
*/ | */ | |||
template <typename T> | template <typename T> | |||
inline | inline | |||
T* alreadyDeclared(T *x) { | T* alreadyDeclared(T *x) { | |||
#if defined(_TESTINTENT) | #if defined(_TESTINTENT) | |||
return (T*) MongoMMF::switchToPrivateView(x); | return (T*) DurableMappedFile::switchToPrivateView(x); | |||
#else | #else | |||
return x; | return x; | |||
#endif | #endif | |||
} | } | |||
/** declare intent to write to x for sizeof(*x) */ | /** declare intent to write to x for sizeof(*x) */ | |||
template <typename T> | template <typename T> | |||
inline | inline | |||
T* writing(T *x) { | T* writing(T *x) { | |||
return (T*) writingPtr(x, sizeof(T)); | return (T*) writingPtr(x, sizeof(T)); | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
dur_recover.h | dur_recover.h | |||
---|---|---|---|---|
skipping to change at line 29 | skipping to change at line 29 | |||
#pragma once | #pragma once | |||
#include <boost/filesystem/operations.hpp> | #include <boost/filesystem/operations.hpp> | |||
#include <list> | #include <list> | |||
#include "mongo/db/dur_journalformat.h" | #include "mongo/db/dur_journalformat.h" | |||
#include "mongo/util/concurrency/mutex.h" | #include "mongo/util/concurrency/mutex.h" | |||
#include "mongo/util/file.h" | #include "mongo/util/file.h" | |||
namespace mongo { | namespace mongo { | |||
class MongoMMF; | class DurableMappedFile; | |||
namespace dur { | namespace dur { | |||
struct ParsedJournalEntry; | struct ParsedJournalEntry; | |||
/** call go() to execute a recovery from existing journal files. | /** call go() to execute a recovery from existing journal files. | |||
*/ | */ | |||
class RecoveryJob : boost::noncopyable { | class RecoveryJob : boost::noncopyable { | |||
static class Last { | static class Last { | |||
public: | public: | |||
Last(); | Last(); | |||
MongoMMF* newEntry(const ParsedJournalEntry&, RecoveryJob&) ; | DurableMappedFile* newEntry(const ParsedJournalEntry&, Reco veryJob&); | |||
private: | private: | |||
MongoMMF *mmf; | DurableMappedFile *mmf; | |||
string dbName; | string dbName; | |||
int fileNo; | int fileNo; | |||
} last; | } last; | |||
public: | public: | |||
RecoveryJob() : _lastDataSyncedFromLastRun(0), | RecoveryJob() : _lastDataSyncedFromLastRun(0), | |||
_mx("recovery"), _recovering(false) { _lastSeqMentionedInCo nsoleLog = 1; } | _mx("recovery"), _recovering(false) { _lastSeqMentionedInCo nsoleLog = 1; } | |||
void go(vector<boost::filesystem::path>& files); | void go(vector<boost::filesystem::path>& files); | |||
~RecoveryJob(); | ~RecoveryJob(); | |||
/** @param data data between header and footer. compressed if r ecovering. */ | /** @param data data between header and footer. compressed if r ecovering. */ | |||
skipping to change at line 65 | skipping to change at line 65 | |||
void close(); // locks and calls _close() | void close(); // locks and calls _close() | |||
static RecoveryJob & get() { return _instance; } | static RecoveryJob & get() { return _instance; } | |||
private: | private: | |||
void write(Last& last, const ParsedJournalEntry& entry); // act ually writes to the file | void write(Last& last, const ParsedJournalEntry& entry); // act ually writes to the file | |||
void applyEntry(Last& last, const ParsedJournalEntry& entry, bo ol apply, bool dump); | void applyEntry(Last& last, const ParsedJournalEntry& entry, bo ol apply, bool dump); | |||
void applyEntries(const vector<ParsedJournalEntry> &entries); | void applyEntries(const vector<ParsedJournalEntry> &entries); | |||
bool processFileBuffer(const void *, unsigned len); | bool processFileBuffer(const void *, unsigned len); | |||
bool processFile(boost::filesystem::path journalfile); | bool processFile(boost::filesystem::path journalfile); | |||
void _close(); // doesn't lock | void _close(); // doesn't lock | |||
MongoMMF* getMongoMMF(const ParsedJournalEntry& entry); | DurableMappedFile* getDurableMappedFile(const ParsedJournalEntr y& entry); | |||
list<boost::shared_ptr<MongoMMF> > _mmfs; | list<boost::shared_ptr<DurableMappedFile> > _mmfs; | |||
unsigned long long _lastDataSyncedFromLastRun; | unsigned long long _lastDataSyncedFromLastRun; | |||
unsigned long long _lastSeqMentionedInConsoleLog; | unsigned long long _lastSeqMentionedInConsoleLog; | |||
public: | public: | |||
mongo::mutex _mx; // protects _mmfs | mongo::mutex _mx; // protects _mmfs | |||
private: | private: | |||
bool _recovering; // are we in recovery or WRITETODATAFILES | bool _recovering; // are we in recovery or WRITETODATAFILES | |||
static RecoveryJob &_instance; | static RecoveryJob &_instance; | |||
}; | }; | |||
End of changes. 5 change blocks. | ||||
5 lines changed or deleted | 5 lines changed or added | |||
element-inl.h | element-inl.h | |||
---|---|---|---|---|
skipping to change at line 92 | skipping to change at line 92 | |||
} | } | |||
inline bool Element::isValueMinKey() const { | inline bool Element::isValueMinKey() const { | |||
return isType(mongo::MinKey); | return isType(mongo::MinKey); | |||
} | } | |||
inline bool Element::isValueMaxKey() const { | inline bool Element::isValueMaxKey() const { | |||
return isType(mongo::MaxKey); | return isType(mongo::MaxKey); | |||
} | } | |||
inline SafeNum Element::getValueSafeNum() const { | ||||
switch (getType()) { | ||||
case mongo::NumberInt: | ||||
return static_cast<int>(getValueInt()); | ||||
case mongo::NumberLong: | ||||
return static_cast<long long int>(getValueLong()); | ||||
case mongo::NumberDouble: | ||||
return getValueDouble(); | ||||
default: | ||||
verify(false); | ||||
} | ||||
} | ||||
inline Document& Element::getDocument() { | inline Document& Element::getDocument() { | |||
return *_doc; | return *_doc; | |||
} | } | |||
inline const Document& Element::getDocument() const { | inline const Document& Element::getDocument() const { | |||
return *_doc; | return *_doc; | |||
} | } | |||
inline bool Element::isType(BSONType type) const { | inline bool Element::isType(BSONType type) const { | |||
return (getType() == type); | return (getType() == type); | |||
End of changes. 1 change blocks. | ||||
13 lines changed or deleted | 0 lines changed or added | |||
element.h | element.h | |||
---|---|---|---|---|
skipping to change at line 284 | skipping to change at line 284 | |||
/** Get the value from a long valued Element. */ | /** Get the value from a long valued Element. */ | |||
inline int64_t getValueLong() const; | inline int64_t getValueLong() const; | |||
/** Returns true if this Element is the min key type. */ | /** Returns true if this Element is the min key type. */ | |||
inline bool isValueMinKey() const; | inline bool isValueMinKey() const; | |||
/** Returns true if this Element is the max key type. */ | /** Returns true if this Element is the max key type. */ | |||
inline bool isValueMaxKey() const; | inline bool isValueMaxKey() const; | |||
/** Returns the numeric value as a SafeNum */ | /** Returns the numeric value as a SafeNum */ | |||
inline SafeNum getValueSafeNum() const; | SafeNum getValueSafeNum() const; | |||
// | // | |||
// Comparision API. | // Comparision API. | |||
// | // | |||
/** Compare this Element with Element 'other'. The two Elements may belong to different | /** Compare this Element with Element 'other'. The two Elements may belong to different | |||
* Documents. You should not call this on the root Element of the Document because the | * Documents. You should not call this on the root Element of the Document because the | |||
* root Element does not have a field name. Use compareWithBSONObj to handle that | * root Element does not have a field name. Use compareWithBSONObj to handle that | |||
* case. | * case. | |||
* | * | |||
skipping to change at line 544 | skipping to change at line 544 | |||
friend class ConstElement; | friend class ConstElement; | |||
friend bool operator==(const Element&, const Element&); | friend bool operator==(const Element&, const Element&); | |||
inline Element(Document* doc, RepIdx repIdx); | inline Element(Document* doc, RepIdx repIdx); | |||
Status addChild(Element e, bool front); | Status addChild(Element e, bool front); | |||
StringData getValueStringOrSymbol() const; | StringData getValueStringOrSymbol() const; | |||
Status setValue(Element* newValue, bool inPlace = false); | Status setValue(Element::RepIdx newValueIdx); | |||
template<typename Builder> | template<typename Builder> | |||
inline void writeElement(Builder* builder, const StringData* fieldN ame = NULL) const; | inline void writeElement(Builder* builder, const StringData* fieldN ame = NULL) const; | |||
template<typename Builder> | template<typename Builder> | |||
inline void writeChildren(Builder* builder) const; | inline void writeChildren(Builder* builder) const; | |||
Document* _doc; | Document* _doc; | |||
RepIdx _repIdx; | RepIdx _repIdx; | |||
}; | }; | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
error_codes.h | error_codes.h | |||
---|---|---|---|---|
skipping to change at line 77 | skipping to change at line 77 | |||
PrivilegeNotFound = 33, | PrivilegeNotFound = 33, | |||
CannotBackfillArray = 34, | CannotBackfillArray = 34, | |||
UserModificationFailed = 35, | UserModificationFailed = 35, | |||
RemoteChangeDetected = 36, | RemoteChangeDetected = 36, | |||
FileRenameFailed = 37, | FileRenameFailed = 37, | |||
FileNotOpen = 38, | FileNotOpen = 38, | |||
FileStreamFailed = 39, | FileStreamFailed = 39, | |||
ConflictingUpdateOperators = 40, | ConflictingUpdateOperators = 40, | |||
FileAlreadyOpen = 41, | FileAlreadyOpen = 41, | |||
LogWriteFailed = 42, | LogWriteFailed = 42, | |||
CursorNotFound = 43, | ||||
KeyNotFound = 44, | ||||
MaxError | MaxError | |||
}; | }; | |||
static const char* errorString(Error err); | static const char* errorString(Error err); | |||
/** | /** | |||
* Parse an Error from its "name". Returns UnknownError if "name" is unrecognized. | * Parse an Error from its "name". Returns UnknownError if "name" is unrecognized. | |||
* | * | |||
* NOTE: Also returns UnknownError for the string "UnknownError". | * NOTE: Also returns UnknownError for the string "UnknownError". | |||
*/ | */ | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 2 lines changed or added | |||
expression.h | expression.h | |||
---|---|---|---|---|
skipping to change at line 48 | skipping to change at line 48 | |||
// array types | // array types | |||
ALL, ELEM_MATCH_OBJECT, ELEM_MATCH_VALUE, SIZE, | ALL, ELEM_MATCH_OBJECT, ELEM_MATCH_VALUE, SIZE, | |||
// leaf types | // leaf types | |||
LTE, LT, EQ, GT, GTE, REGEX, MOD, EXISTS, MATCH_IN, NIN, | LTE, LT, EQ, GT, GTE, REGEX, MOD, EXISTS, MATCH_IN, NIN, | |||
// special types | // special types | |||
TYPE_OPERATOR, GEO, WHERE, | TYPE_OPERATOR, GEO, WHERE, | |||
// things that maybe shouldn't even be nodes | // things that maybe shouldn't even be nodes | |||
ATOMIC, ALWAYS_FALSE | ATOMIC, ALWAYS_FALSE, | |||
// Things that we parse but cannot be answered without an index | ||||
. | ||||
// TODO: Text goes here eventually. | ||||
GEO_NEAR, | ||||
}; | }; | |||
MatchExpression( MatchType type ); | MatchExpression( MatchType type ); | |||
virtual ~MatchExpression(){} | virtual ~MatchExpression(){} | |||
/** | /** | |||
* determins if the doc matches the expression | * determins if the doc matches the expression | |||
* there could be an expression that looks at fields, or the entire doc | * there could be an expression that looks at fields, or the entire doc | |||
*/ | */ | |||
virtual bool matches( const MatchableDocument* doc, MatchDetails* d etails = 0 ) const = 0; | virtual bool matches( const MatchableDocument* doc, MatchDetails* d etails = 0 ) const = 0; | |||
skipping to change at line 127 | skipping to change at line 131 | |||
return false; | return false; | |||
} | } | |||
virtual void debugString( StringBuilder& debug, int level = 0 ) con st; | virtual void debugString( StringBuilder& debug, int level = 0 ) con st; | |||
virtual bool equivalent( const MatchExpression* other ) const { | virtual bool equivalent( const MatchExpression* other ) const { | |||
return other->matchType() == ALWAYS_FALSE; | return other->matchType() == ALWAYS_FALSE; | |||
} | } | |||
}; | }; | |||
} | } | |||
End of changes. 2 change blocks. | ||||
1 lines changed or deleted | 7 lines changed or added | |||
expression_array.h | expression_array.h | |||
---|---|---|---|---|
skipping to change at line 115 | skipping to change at line 115 | |||
/** | /** | |||
* @param e has to be an array | * @param e has to be an array | |||
*/ | */ | |||
virtual bool matchesSingleElement( const BSONElement& e ) const; | virtual bool matchesSingleElement( const BSONElement& e ) const; | |||
virtual void debugString( StringBuilder& debug, int level ) const; | virtual void debugString( StringBuilder& debug, int level ) const; | |||
virtual bool equivalent( const MatchExpression* other ) const; | virtual bool equivalent( const MatchExpression* other ) const; | |||
virtual size_t numChildren() const { return _list.size(); } | ||||
virtual const ArrayMatchingMatchExpression* getChild( size_t i ) co | ||||
nst { return _list[i]; } | ||||
const StringData& path() const { return _path; } | ||||
private: | private: | |||
bool _allMatch( const BSONObj& anArray ) const; | bool _allMatch( const BSONObj& anArray ) const; | |||
StringData _path; | StringData _path; | |||
ElementPath _elementPath; | ElementPath _elementPath; | |||
std::vector< const ArrayMatchingMatchExpression* > _list; | std::vector< const ArrayMatchingMatchExpression* > _list; | |||
}; | }; | |||
class SizeMatchExpression : public ArrayMatchingMatchExpression { | class SizeMatchExpression : public ArrayMatchingMatchExpression { | |||
public: | public: | |||
SizeMatchExpression() : ArrayMatchingMatchExpression( SIZE ){} | SizeMatchExpression() : ArrayMatchingMatchExpression( SIZE ){} | |||
Status init( const StringData& path, int size ); | Status init( const StringData& path, int size ); | |||
virtual bool matchesArray( const BSONObj& anArray, MatchDetails* de tails ) const; | virtual bool matchesArray( const BSONObj& anArray, MatchDetails* de tails ) const; | |||
virtual void debugString( StringBuilder& debug, int level ) const; | virtual void debugString( StringBuilder& debug, int level ) const; | |||
virtual bool equivalent( const MatchExpression* other ) const; | virtual bool equivalent( const MatchExpression* other ) const; | |||
int getData() const { return _size; } | ||||
private: | private: | |||
int _size; // >= 0 real, < 0, nothing will match | int _size; // >= 0 real, < 0, nothing will match | |||
}; | }; | |||
} | } | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 8 lines changed or added | |||
expression_context.h | expression_context.h | |||
---|---|---|---|---|
skipping to change at line 19 | skipping to change at line 19 | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public License | * You should have received a copy of the GNU Affero General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/db/interrupt_status.h" | |||
#include "mongo/db/namespace_string.h" | ||||
#include "util/intrusive_counter.h" | #include "mongo/util/intrusive_counter.h" | |||
namespace mongo { | namespace mongo { | |||
class InterruptStatus; | struct ExpressionContext : public IntrusiveCounterUnsigned { | |||
class ExpressionContext : | ||||
public IntrusiveCounterUnsigned { | ||||
public: | public: | |||
virtual ~ExpressionContext(); | ExpressionContext(const InterruptStatus& status, const NamespaceStr | |||
ing& ns) | ||||
void setDoingMerge(bool b); | : inShard(false) | |||
void setInShard(bool b); | , inRouter(false) | |||
void setInRouter(bool b); | , extSortAllowed(false) | |||
void setExtSortAllowed(bool b) { extSortAllowed = b; } | , interruptStatus(status) | |||
, ns(ns) | ||||
bool getDoingMerge() const; | {} | |||
bool getInShard() const; | /** Used by a pipeline to check for interrupts so that killOp() wor | |||
bool getInRouter() const; | ks. | |||
bool getExtSortAllowed() const { return extSortAllowed; } | * @throws if the operation has been interrupted | |||
/** | ||||
Used by a pipeline to check for interrupts so that killOp() work | ||||
s. | ||||
@throws if the operation has been interrupted | ||||
*/ | */ | |||
void checkForInterrupt(); | void checkForInterrupt() { | |||
// The check could be expensive, at least in relative terms. | ||||
ExpressionContext* clone(); | RARELY interruptStatus.checkForInterrupt(); | |||
} | ||||
static ExpressionContext *create(InterruptStatus *pStatus); | ||||
private: | ||||
ExpressionContext(InterruptStatus *pStatus); | ||||
bool doingMerge; | ||||
bool inShard; | bool inShard; | |||
bool inRouter; | bool inRouter; | |||
bool extSortAllowed; | bool extSortAllowed; | |||
unsigned intCheckCounter; // interrupt check counter | const InterruptStatus& interruptStatus; | |||
InterruptStatus *const pStatus; | NamespaceString ns; | |||
}; | }; | |||
} | } | |||
/* ======================= INLINED IMPLEMENTATIONS ======================== | ||||
== */ | ||||
namespace mongo { | ||||
inline void ExpressionContext::setDoingMerge(bool b) { | ||||
doingMerge = b; | ||||
} | ||||
inline void ExpressionContext::setInShard(bool b) { | ||||
inShard = b; | ||||
} | ||||
inline void ExpressionContext::setInRouter(bool b) { | ||||
inRouter = b; | ||||
} | ||||
inline bool ExpressionContext::getDoingMerge() const { | ||||
return doingMerge; | ||||
} | ||||
inline bool ExpressionContext::getInShard() const { | ||||
return inShard; | ||||
} | ||||
inline bool ExpressionContext::getInRouter() const { | ||||
return inRouter; | ||||
} | ||||
}; | ||||
End of changes. 7 change blocks. | ||||
35 lines changed or deleted | 21 lines changed or added | |||
expression_geo.h | expression_geo.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/db/geo/geonear.h" | ||||
#include "mongo/db/geo/geoquery.h" | #include "mongo/db/geo/geoquery.h" | |||
#include "mongo/db/matcher/expression.h" | #include "mongo/db/matcher/expression.h" | |||
#include "mongo/db/matcher/expression_leaf.h" | #include "mongo/db/matcher/expression_leaf.h" | |||
namespace mongo { | namespace mongo { | |||
class GeoMatchExpression : public LeafMatchExpression { | class GeoMatchExpression : public LeafMatchExpression { | |||
public: | public: | |||
GeoMatchExpression() : LeafMatchExpression( GEO ){} | GeoMatchExpression() : LeafMatchExpression( GEO ){} | |||
virtual ~GeoMatchExpression(){} | virtual ~GeoMatchExpression(){} | |||
skipping to change at line 46 | skipping to change at line 47 | |||
virtual void debugString( StringBuilder& debug, int level = 0 ) con st; | virtual void debugString( StringBuilder& debug, int level = 0 ) con st; | |||
virtual bool equivalent( const MatchExpression* other ) const; | virtual bool equivalent( const MatchExpression* other ) const; | |||
virtual LeafMatchExpression* shallowClone() const; | virtual LeafMatchExpression* shallowClone() const; | |||
private: | private: | |||
GeoQuery _query; | GeoQuery _query; | |||
}; | }; | |||
} | class GeoNearMatchExpression : public LeafMatchExpression { | |||
public: | ||||
GeoNearMatchExpression() : LeafMatchExpression( GEO_NEAR ){} | ||||
virtual ~GeoNearMatchExpression(){} | ||||
Status init( const StringData& path, const NearQuery& query ); | ||||
// This shouldn't be called and as such will crash. GeoNear always | ||||
requires an index. | ||||
virtual bool matchesSingleElement( const BSONElement& e ) const; | ||||
virtual void debugString( StringBuilder& debug, int level = 0 ) con | ||||
st; | ||||
virtual bool equivalent( const MatchExpression* other ) const; | ||||
virtual LeafMatchExpression* shallowClone() const; | ||||
const NearQuery& getData() const { return _query; } | ||||
private: | ||||
NearQuery _query; | ||||
}; | ||||
} // namespace mongo | ||||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
expression_leaf.h | expression_leaf.h | |||
---|---|---|---|---|
skipping to change at line 73 | skipping to change at line 73 | |||
virtual ~ComparisonMatchExpression(){} | virtual ~ComparisonMatchExpression(){} | |||
virtual bool matchesSingleElement( const BSONElement& e ) const; | virtual bool matchesSingleElement( const BSONElement& e ) const; | |||
virtual const BSONElement& getRHS() const { return _rhs; } | virtual const BSONElement& getRHS() const { return _rhs; } | |||
virtual void debugString( StringBuilder& debug, int level = 0 ) con st; | virtual void debugString( StringBuilder& debug, int level = 0 ) con st; | |||
virtual bool equivalent( const MatchExpression* other ) const; | virtual bool equivalent( const MatchExpression* other ) const; | |||
const BSONElement& getData() const { return _rhs; } | ||||
protected: | protected: | |||
BSONElement _rhs; | BSONElement _rhs; | |||
}; | }; | |||
class EqualityMatchExpression : public ComparisonMatchExpression { | class EqualityMatchExpression : public ComparisonMatchExpression { | |||
public: | public: | |||
EqualityMatchExpression() : ComparisonMatchExpression( EQ ){} | EqualityMatchExpression() : ComparisonMatchExpression( EQ ){} | |||
virtual LeafMatchExpression* shallowClone() const { | virtual LeafMatchExpression* shallowClone() const { | |||
ComparisonMatchExpression* e = new EqualityMatchExpression(); | ComparisonMatchExpression* e = new EqualityMatchExpression(); | |||
e->init( path(), _rhs ); | e->init( path(), _rhs ); | |||
skipping to change at line 157 | skipping to change at line 159 | |||
e->init( path(), _regex, _flags ); | e->init( path(), _regex, _flags ); | |||
return e; | return e; | |||
} | } | |||
virtual bool matchesSingleElement( const BSONElement& e ) const; | virtual bool matchesSingleElement( const BSONElement& e ) const; | |||
virtual void debugString( StringBuilder& debug, int level ) const; | virtual void debugString( StringBuilder& debug, int level ) const; | |||
virtual bool equivalent( const MatchExpression* other ) const; | virtual bool equivalent( const MatchExpression* other ) const; | |||
const string& getString() const { return _regex; } | ||||
const string& getFlags() const { return _flags; } | ||||
private: | private: | |||
std::string _regex; | std::string _regex; | |||
std::string _flags; | std::string _flags; | |||
boost::scoped_ptr<pcrecpp::RE> _re; | boost::scoped_ptr<pcrecpp::RE> _re; | |||
}; | }; | |||
class ModMatchExpression : public LeafMatchExpression { | class ModMatchExpression : public LeafMatchExpression { | |||
public: | public: | |||
ModMatchExpression() : LeafMatchExpression( MOD ){} | ModMatchExpression() : LeafMatchExpression( MOD ){} | |||
skipping to change at line 181 | skipping to change at line 186 | |||
m->init( path(), _divisor, _remainder ); | m->init( path(), _divisor, _remainder ); | |||
return m; | return m; | |||
} | } | |||
virtual bool matchesSingleElement( const BSONElement& e ) const; | virtual bool matchesSingleElement( const BSONElement& e ) const; | |||
virtual void debugString( StringBuilder& debug, int level ) const; | virtual void debugString( StringBuilder& debug, int level ) const; | |||
virtual bool equivalent( const MatchExpression* other ) const; | virtual bool equivalent( const MatchExpression* other ) const; | |||
int getDivisor() const { return _divisor; } | ||||
int getRemainder() const { return _remainder; } | ||||
private: | private: | |||
int _divisor; | int _divisor; | |||
int _remainder; | int _remainder; | |||
}; | }; | |||
class ExistsMatchExpression : public LeafMatchExpression { | class ExistsMatchExpression : public LeafMatchExpression { | |||
public: | public: | |||
ExistsMatchExpression() : LeafMatchExpression( EXISTS ){} | ExistsMatchExpression() : LeafMatchExpression( EXISTS ){} | |||
Status init( const StringData& path ); | Status init( const StringData& path ); | |||
skipping to change at line 218 | skipping to change at line 226 | |||
Status init( const StringData& path, int type ); | Status init( const StringData& path, int type ); | |||
virtual bool matchesSingleElement( const BSONElement& e ) const; | virtual bool matchesSingleElement( const BSONElement& e ) const; | |||
virtual bool matches( const MatchableDocument* doc, MatchDetails* d etails = 0 ) const; | virtual bool matches( const MatchableDocument* doc, MatchDetails* d etails = 0 ) const; | |||
virtual void debugString( StringBuilder& debug, int level ) const; | virtual void debugString( StringBuilder& debug, int level ) const; | |||
virtual bool equivalent( const MatchExpression* other ) const; | virtual bool equivalent( const MatchExpression* other ) const; | |||
int getType() const { return _type; } | ||||
private: | private: | |||
bool _matches( const StringData& path, | bool _matches( const StringData& path, | |||
const MatchableDocument* doc, | const MatchableDocument* doc, | |||
MatchDetails* details = 0 ) const; | MatchDetails* details = 0 ) const; | |||
StringData _path; | StringData _path; | |||
ElementPath _elementPath; | ElementPath _elementPath; | |||
int _type; | int _type; | |||
}; | }; | |||
skipping to change at line 257 | skipping to change at line 268 | |||
RegexMatchExpression* regex( int idx ) const { return _regexes[idx] ; } | RegexMatchExpression* regex( int idx ) const { return _regexes[idx] ; } | |||
bool hasNull() const { return _hasNull; } | bool hasNull() const { return _hasNull; } | |||
bool singleNull() const { return size() == 1 && _hasNull; } | bool singleNull() const { return size() == 1 && _hasNull; } | |||
bool hasEmptyArray() const { return _hasEmptyArray; } | bool hasEmptyArray() const { return _hasEmptyArray; } | |||
int size() const { return _equalities.size() + _regexes.size(); } | int size() const { return _equalities.size() + _regexes.size(); } | |||
bool equivalent( const ArrayFilterEntries& other ) const; | bool equivalent( const ArrayFilterEntries& other ) const; | |||
void copyTo( ArrayFilterEntries& toFillIn ) const; | void copyTo( ArrayFilterEntries& toFillIn ) const; | |||
private: | private: | |||
bool _hasNull; // if _equalities has a jstNULL element in it | bool _hasNull; // if _equalities has a jstNULL element in it | |||
bool _hasEmptyArray; | bool _hasEmptyArray; | |||
BSONElementSet _equalities; | BSONElementSet _equalities; | |||
std::vector<RegexMatchExpression*> _regexes; | std::vector<RegexMatchExpression*> _regexes; | |||
}; | }; | |||
/** | /** | |||
* query operator: $in | * query operator: $in | |||
*/ | */ | |||
skipping to change at line 284 | skipping to change at line 296 | |||
ArrayFilterEntries* getArrayFilterEntries() { return &_arrayEntries ; } | ArrayFilterEntries* getArrayFilterEntries() { return &_arrayEntries ; } | |||
virtual bool matchesSingleElement( const BSONElement& e ) const; | virtual bool matchesSingleElement( const BSONElement& e ) const; | |||
virtual void debugString( StringBuilder& debug, int level ) const; | virtual void debugString( StringBuilder& debug, int level ) const; | |||
virtual bool equivalent( const MatchExpression* other ) const; | virtual bool equivalent( const MatchExpression* other ) const; | |||
void copyTo( InMatchExpression* toFillIn ) const; | void copyTo( InMatchExpression* toFillIn ) const; | |||
const ArrayFilterEntries& getData() const { return _arrayEntries; } | ||||
private: | private: | |||
bool _matchesRealElement( const BSONElement& e ) const; | bool _matchesRealElement( const BSONElement& e ) const; | |||
ArrayFilterEntries _arrayEntries; | ArrayFilterEntries _arrayEntries; | |||
}; | }; | |||
} | } | |||
End of changes. 6 change blocks. | ||||
0 lines changed or deleted | 14 lines changed or added | |||
expression_parser.h | expression_parser.h | |||
---|---|---|---|---|
skipping to change at line 35 | skipping to change at line 35 | |||
#include "mongo/db/matcher/expression.h" | #include "mongo/db/matcher/expression.h" | |||
#include "mongo/db/matcher/expression_leaf.h" | #include "mongo/db/matcher/expression_leaf.h" | |||
#include "mongo/db/matcher/expression_tree.h" | #include "mongo/db/matcher/expression_tree.h" | |||
namespace mongo { | namespace mongo { | |||
typedef StatusWith<MatchExpression*> StatusWithMatchExpression; | typedef StatusWith<MatchExpression*> StatusWithMatchExpression; | |||
class MatchExpressionParser { | class MatchExpressionParser { | |||
public: | public: | |||
/** | ||||
* caller has to maintain ownership obj | ||||
* the tree has views (BSONElement) into obj | ||||
*/ | ||||
static StatusWithMatchExpression parse( const BSONObj& obj ) { | static StatusWithMatchExpression parse( const BSONObj& obj ) { | |||
return _parse( obj, true ); | return _parse( obj, true ); | |||
} | } | |||
private: | private: | |||
/** | /** | |||
* 5 = false | * 5 = false | |||
{ a : 5 } = false | { a : 5 } = false | |||
{ $lt : 5 } = true | { $lt : 5 } = true | |||
skipping to change at line 102 | skipping to change at line 107 | |||
const BSONElement& e ); | const BSONElement& e ); | |||
// tree | // tree | |||
static Status _parseTreeList( const BSONObj& arr, ListOfMatchExpres sion* out ); | static Status _parseTreeList( const BSONObj& arr, ListOfMatchExpres sion* out ); | |||
static StatusWithMatchExpression _parseNot( const char* name, const BSONElement& e ); | static StatusWithMatchExpression _parseNot( const char* name, const BSONElement& e ); | |||
}; | }; | |||
typedef boost::function<StatusWithMatchExpression(const char* name, con st BSONObj& section)> MatchExpressionParserGeoCallback; | typedef boost::function<StatusWithMatchExpression(const char* name, int type, const BSONObj& section)> MatchExpressionParserGeoCallback; | |||
extern MatchExpressionParserGeoCallback expressionParserGeoCallback; | extern MatchExpressionParserGeoCallback expressionParserGeoCallback; | |||
typedef boost::function<StatusWithMatchExpression(const BSONElement& wh ere)> MatchExpressionParserWhereCallback; | typedef boost::function<StatusWithMatchExpression(const BSONElement& wh ere)> MatchExpressionParserWhereCallback; | |||
extern MatchExpressionParserWhereCallback expressionParserWhereCallback ; | extern MatchExpressionParserWhereCallback expressionParserWhereCallback ; | |||
} | } | |||
End of changes. 2 change blocks. | ||||
1 lines changed or deleted | 6 lines changed or added | |||
fetch.h | fetch.h | |||
---|---|---|---|---|
skipping to change at line 20 | skipping to change at line 20 | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Lice nse | * You should have received a copy of the GNU Affero General Public Lice nse | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/db/diskloc.h" | #include "mongo/db/diskloc.h" | |||
#include "mongo/db/jsobj.h" | ||||
#include "mongo/db/matcher.h" | ||||
#include "mongo/db/exec/plan_stage.h" | #include "mongo/db/exec/plan_stage.h" | |||
#include "mongo/db/jsobj.h" | ||||
#include "mongo/db/matcher/expression.h" | ||||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* This stage turns a DiskLoc into a BSONObj. | * This stage turns a DiskLoc into a BSONObj. | |||
* | * | |||
* In WorkingSetMember terms, it transitions from LOC_AND_IDX to LOC_AN D_UNOWNED_OBJ by reading | * In WorkingSetMember terms, it transitions from LOC_AND_IDX to LOC_AN D_UNOWNED_OBJ by reading | |||
* the record at the provided loc. Returns verbatim any data that alre ady has an object. | * the record at the provided loc. Returns verbatim any data that alre ady has an object. | |||
* | * | |||
* Preconditions: Valid DiskLoc. | * Preconditions: Valid DiskLoc. | |||
*/ | */ | |||
class FetchStage : public PlanStage { | class FetchStage : public PlanStage { | |||
public: | public: | |||
FetchStage(WorkingSet* ws, PlanStage* child, Matcher* matcher); | FetchStage(WorkingSet* ws, PlanStage* child, const MatchExpression* filter); | |||
virtual ~FetchStage(); | virtual ~FetchStage(); | |||
virtual bool isEOF(); | virtual bool isEOF(); | |||
virtual StageState work(WorkingSetID* out); | virtual StageState work(WorkingSetID* out); | |||
virtual void prepareToYield(); | virtual void prepareToYield(); | |||
virtual void recoverFromYield(); | virtual void recoverFromYield(); | |||
virtual void invalidate(const DiskLoc& dl); | virtual void invalidate(const DiskLoc& dl); | |||
PlanStageStats* getStats(); | ||||
private: | private: | |||
/** | /** | |||
* If the member (with id memberID) passes our filter, set *out to memberID and return that | * If the member (with id memberID) passes our filter, set *out to memberID and return that | |||
* ADVANCED. Otherwise, free memberID and return NEED_TIME. | * ADVANCED. Otherwise, free memberID and return NEED_TIME. | |||
*/ | */ | |||
StageState returnIfMatches(WorkingSetMember* member, WorkingSetID m emberID, | StageState returnIfMatches(WorkingSetMember* member, WorkingSetID m emberID, | |||
WorkingSetID* out); | WorkingSetID* out); | |||
/** | /** | |||
* work(...) delegates to this when we're called after requesting a fetch. | * work(...) delegates to this when we're called after requesting a fetch. | |||
*/ | */ | |||
StageState fetchCompleted(WorkingSetID* out); | StageState fetchCompleted(WorkingSetID* out); | |||
// _ws is not owned by us. | // _ws is not owned by us. | |||
WorkingSet* _ws; | WorkingSet* _ws; | |||
scoped_ptr<PlanStage> _child; | scoped_ptr<PlanStage> _child; | |||
scoped_ptr<Matcher> _matcher; | ||||
// The filter is not owned by us. | ||||
const MatchExpression* _filter; | ||||
// If we're fetching a DiskLoc and it points at something that's no t in memory, we return a | // If we're fetching a DiskLoc and it points at something that's no t in memory, we return a | |||
// a "please page this in" result and hold on to the WSID until the next call to work(...). | // a "please page this in" result and hold on to the WSID until the next call to work(...). | |||
WorkingSetID _idBeingPagedIn; | WorkingSetID _idBeingPagedIn; | |||
// Stats | ||||
CommonStats _commonStats; | ||||
FetchStats _specificStats; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 6 change blocks. | ||||
4 lines changed or deleted | 12 lines changed or added | |||
field_parser.h | field_parser.h | |||
---|---|---|---|---|
skipping to change at line 22 | skipping to change at line 22 | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Lice nse | * You should have received a copy of the GNU Affero General Public Lice nse | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <string> | #include <string> | |||
#include "mongo/bson/bson_field.h" | #include "mongo/bson/bson_field.h" | |||
#include "mongo/bson/util/misc.h" // for Date_t | ||||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/util/time_support.h" | ||||
namespace mongo { | namespace mongo { | |||
class FieldParser { | class FieldParser { | |||
public: | public: | |||
/** | /** | |||
* Returns true and fills in 'out' with the contents of the field d escribed by 'field' | * Returns true and fills in 'out' with the contents of the field d escribed by 'field' | |||
* or with the value in 'def', depending on whether the field is pr esent and has the | * or with the value in 'def', depending on whether the field is pr esent and has the | |||
* correct type in 'doc' or not, respectively. Otherwise, if the fi eld exists but has | * correct type in 'doc' or not, respectively. Otherwise, if the fi eld exists but has | |||
* the wrong type, returns false. | * the wrong type, returns false. | |||
End of changes. 2 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
finding_start_cursor.h | finding_start_cursor.h | |||
---|---|---|---|---|
skipping to change at line 97 | skipping to change at line 97 | |||
private: | private: | |||
FindingStartCursor( const QueryPlan &qp ); | FindingStartCursor( const QueryPlan &qp ); | |||
void init(); | void init(); | |||
enum FindingStartMode { Initial, FindExtent, InExtent }; | enum FindingStartMode { Initial, FindExtent, InExtent }; | |||
const QueryPlan &_qp; | const QueryPlan &_qp; | |||
bool _findingStart; | bool _findingStart; | |||
FindingStartMode _findingStartMode; | FindingStartMode _findingStartMode; | |||
auto_ptr< CoveredIndexMatcher > _matcher; | auto_ptr< CoveredIndexMatcher > _matcher; | |||
Timer _findingStartTimer; | Timer _findingStartTimer; | |||
ClientCursor::Holder _findingStartCursor; | ClientCursorHolder _findingStartCursor; | |||
shared_ptr<Cursor> _c; | shared_ptr<Cursor> _c; | |||
ClientCursor::YieldData _yieldData; | ClientCursor::YieldData _yieldData; | |||
static int _initialTimeout; | static int _initialTimeout; | |||
/** @return the first record of the extent containing @param rec. * / | /** @return the first record of the extent containing @param rec. * / | |||
DiskLoc extentFirstLoc( const DiskLoc &rec ); | DiskLoc extentFirstLoc( const DiskLoc &rec ); | |||
void createClientCursor( const DiskLoc &startLoc = DiskLoc() ); | void createClientCursor( const DiskLoc &startLoc = DiskLoc() ); | |||
void destroyClientCursor() { | void destroyClientCursor() { | |||
_findingStartCursor.reset( 0 ); | _findingStartCursor.reset( 0 ); | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
fts_util.h | fts_util.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 <string> | #include <string> | |||
#include "mongo/db/hasher.h" | #include "mongo/db/hasher.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/record.h" | #include "mongo/db/storage/record.h" | |||
#include "mongo/util/unordered_fast_key_table.h" | #include "mongo/util/unordered_fast_key_table.h" | |||
namespace mongo { | namespace mongo { | |||
namespace fts { | namespace fts { | |||
extern const std::string WILDCARD; | extern const std::string WILDCARD; | |||
extern const std::string INDEX_NAME; | extern const std::string INDEX_NAME; | |||
/** | /** | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
geoquery.h | geoquery.h | |||
---|---|---|---|---|
skipping to change at line 94 | skipping to change at line 94 | |||
shared_ptr<S2RegionUnion> _region; | shared_ptr<S2RegionUnion> _region; | |||
}; | }; | |||
class NearQuery { | class NearQuery { | |||
public: | public: | |||
NearQuery() : minDistance(0), maxDistance(std::numeric_limits<doubl e>::max()), | NearQuery() : minDistance(0), maxDistance(std::numeric_limits<doubl e>::max()), | |||
fromRadians(false) {} | fromRadians(false) {} | |||
NearQuery(const string& f) : field(f), minDistance(0), | NearQuery(const string& f) : field(f), minDistance(0), | |||
maxDistance(std::numeric_limits<double >::max()), | maxDistance(std::numeric_limits<double >::max()), | |||
fromRadians(false) {} | fromRadians(false) {} | |||
bool parseFrom(const BSONObj &obj, double radius); | ||||
/** | ||||
* If fromRadians is true after a parseFrom, minDistance and maxDis | ||||
tance are returned in | ||||
* radians, not meters. The distances must be multiplied by the un | ||||
derlying index's radius | ||||
* to convert them to meters. | ||||
* | ||||
* This is annoying but useful when we don't know what index we're | ||||
using at parse time. | ||||
*/ | ||||
bool parseFrom(const BSONObj &obj); | ||||
bool parseFromGeoNear(const BSONObj &obj, double radius); | bool parseFromGeoNear(const BSONObj &obj, double radius); | |||
string field; | string field; | |||
PointWithCRS centroid; | PointWithCRS centroid; | |||
// Min and max distance IN METERS from centroid that we're willing to search. | // Min and max distance IN METERS from centroid that we're willing to search. | |||
double minDistance; | double minDistance; | |||
double maxDistance; | double maxDistance; | |||
// Did we convert to this distance from radians? (If so, we output distances in radians.) | // Did we convert to this distance from radians? (If so, we output distances in radians.) | |||
bool fromRadians; | bool fromRadians; | |||
}; | }; | |||
// This represents either a $within or a $geoIntersects. | // This represents either a $within or a $geoIntersects. | |||
class GeoQuery { | class GeoQuery { | |||
public: | public: | |||
GeoQuery() : field(""), predicate(INVALID) {} | GeoQuery() : field(""), predicate(INVALID) {} | |||
GeoQuery(const string& f) : field(f), predicate(INVALID) {} | GeoQuery(const string& f) : field(f), predicate(INVALID) {} | |||
End of changes. 4 change blocks. | ||||
1 lines changed or deleted | 15 lines changed or added | |||
grid.h | grid.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 <boost/date_time/posix_time/posix_time.hpp> | #include <boost/date_time/posix_time/posix_time.hpp> | |||
#include "../util/time_support.h" | #include "mongo/util/time_support.h" | |||
#include "../util/concurrency/mutex.h" | #include "mongo/util/concurrency/mutex.h" | |||
#include "config.h" // DBConfigPtr | #include "config.h" // DBConfigPtr | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* stores meta-information about the grid | * stores meta-information about the grid | |||
* TODO: used shard_ptr for DBConfig pointers | * TODO: used shard_ptr for DBConfig pointers | |||
*/ | */ | |||
class Grid { | class Grid { | |||
End of changes. 1 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
index_scan.h | index_scan.h | |||
---|---|---|---|---|
skipping to change at line 19 | skipping to change at line 19 | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Lice nse | * You should have received a copy of the GNU Affero General Public Lice nse | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/db/exec/plan_stage.h" | ||||
#include "mongo/db/diskloc.h" | #include "mongo/db/diskloc.h" | |||
#include "mongo/db/index/btree_index_cursor.h" | ||||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/matcher.h" | #include "mongo/db/matcher/expression.h" | |||
#include "mongo/db/exec/plan_stage.h" | #include "mongo/db/query/index_bounds.h" | |||
#include "mongo/platform/unordered_set.h" | #include "mongo/platform/unordered_set.h" | |||
namespace mongo { | namespace mongo { | |||
class IndexAccessMethod; | class IndexAccessMethod; | |||
class IndexCursor; | class IndexCursor; | |||
class IndexDescriptor; | class IndexDescriptor; | |||
struct IndexScanParams; | ||||
class WorkingSet; | class WorkingSet; | |||
struct IndexScanParams { | ||||
IndexScanParams() : descriptor(NULL), direction(1), limit(0), | ||||
forceBtreeAccessMethod(false) { } | ||||
IndexDescriptor* descriptor; | ||||
IndexBounds bounds; | ||||
int direction; | ||||
// This only matters for 2d indices and will be ignored by every ot | ||||
her index. | ||||
int limit; | ||||
// Special indices internally open an IndexCursor over themselves b | ||||
ut as a straight Btree. | ||||
bool forceBtreeAccessMethod; | ||||
}; | ||||
/** | /** | |||
* Stage scans over an index from startKey to endKey, returning results that pass the provided | * Stage scans over an index from startKey to endKey, returning results that pass the provided | |||
* filter. Internally dedups on DiskLoc. | * filter. Internally dedups on DiskLoc. | |||
* | * | |||
* Sub-stage preconditions: None. Is a leaf and consumes no stage data . | * Sub-stage preconditions: None. Is a leaf and consumes no stage data . | |||
*/ | */ | |||
class IndexScan : public PlanStage { | class IndexScan : public PlanStage { | |||
public: | public: | |||
IndexScan(const IndexScanParams& params, WorkingSet* workingSet, Ma | IndexScan(const IndexScanParams& params, WorkingSet* workingSet, | |||
tcher* matcher); | const MatchExpression* filter); | |||
virtual ~IndexScan() { } | virtual ~IndexScan() { } | |||
virtual StageState work(WorkingSetID* out); | virtual StageState work(WorkingSetID* out); | |||
virtual bool isEOF(); | virtual bool isEOF(); | |||
virtual void prepareToYield(); | virtual void prepareToYield(); | |||
virtual void recoverFromYield(); | virtual void recoverFromYield(); | |||
virtual void invalidate(const DiskLoc& dl); | virtual void invalidate(const DiskLoc& dl); | |||
virtual PlanStageStats* getStats(); | ||||
private: | private: | |||
/** See if the cursor is pointing at or past _endKey, if _endKey is non-empty. */ | /** See if the cursor is pointing at or past _endKey, if _endKey is non-empty. */ | |||
void checkEnd(); | void checkEnd(); | |||
// The WorkingSet we annotate with results. Not owned by us. | // The WorkingSet we annotate with results. Not owned by us. | |||
WorkingSet* _workingSet; | WorkingSet* _workingSet; | |||
// Index access. | // Index access. | |||
scoped_ptr<IndexAccessMethod> _iam; | scoped_ptr<IndexAccessMethod> _iam; | |||
scoped_ptr<IndexCursor> _indexCursor; | scoped_ptr<IndexCursor> _indexCursor; | |||
scoped_ptr<IndexDescriptor> _descriptor; | scoped_ptr<IndexDescriptor> _descriptor; | |||
// Bounds for the cursor. TODO: take a set of bounds. | // Have we hit the end of the index scan? | |||
BSONObj _startKey; | ||||
BSONObj _endKey; | ||||
bool _endKeyInclusive; | ||||
int _direction; | ||||
bool _hitEnd; | bool _hitEnd; | |||
// Contains expressions only over fields in the index key. We assu me this is built | // Contains expressions only over fields in the index key. We assu me this is built | |||
// correctly by whomever creates this class. | // correctly by whomever creates this class. | |||
scoped_ptr<Matcher> _matcher; | // The filter is not owned by us. | |||
const MatchExpression* _filter; | ||||
// Could our index have duplicates? If so, we use _returned to ded up. | // Could our index have duplicates? If so, we use _returned to ded up. | |||
bool _shouldDedup; | bool _shouldDedup; | |||
unordered_set<DiskLoc, DiskLoc::Hasher> _returned; | unordered_set<DiskLoc, DiskLoc::Hasher> _returned; | |||
// For yielding. | // For yielding. | |||
BSONObj _savedKey; | BSONObj _savedKey; | |||
DiskLoc _savedLoc; | DiskLoc _savedLoc; | |||
// True if there was a yield and the yield changed the cursor posit ion. | // True if there was a yield and the yield changed the cursor posit ion. | |||
bool _yieldMovedCursor; | bool _yieldMovedCursor; | |||
// This is IndexScanParams::limit. See comment there. | IndexScanParams _params; | |||
int _numWanted; | ||||
}; | ||||
struct IndexScanParams { | // For our "fast" Btree-only navigation AKA the index bounds optimi | |||
IndexScanParams() : descriptor(NULL), endKeyInclusive(true), direct | zation. | |||
ion(1), limit(0), | scoped_ptr<IndexBoundsChecker> _checker; | |||
forceBtreeAccessMethod(false) { } | BtreeIndexCursor* _btreeCursor; | |||
IndexDescriptor* descriptor; | int _keyEltsToUse; | |||
BSONObj startKey; | bool _movePastKeyElts; | |||
BSONObj endKey; | vector<const BSONElement*> _keyElts; | |||
bool endKeyInclusive; | vector<bool> _keyEltsInc; | |||
int direction; | ||||
// Stats | ||||
// This only matters for 2d indices and will be ignored by every ot | CommonStats _commonStats; | |||
her index. | IndexScanStats _specificStats; | |||
int limit; | ||||
// Special indices internally open an IndexCursor over themselves b | ||||
ut as a straight Btree. | ||||
bool forceBtreeAccessMethod; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 11 change blocks. | ||||
31 lines changed or deleted | 44 lines changed or added | |||
instance.h | instance.h | |||
---|---|---|---|---|
skipping to change at line 26 | skipping to change at line 26 | |||
* 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/client/dbclientinterface.h" | #include "mongo/client/dbclientinterface.h" | |||
#include "mongo/db/client.h" | #include "mongo/db/client.h" | |||
#include "mongo/db/cmdline.h" | #include "mongo/db/cmdline.h" | |||
#include "mongo/db/curop-inl.h" | #include "mongo/db/curop-inl.h" | |||
#include "mongo/db/dbmessage.h" | ||||
namespace mongo { | namespace mongo { | |||
extern string dbExecCommand; | extern string dbExecCommand; | |||
/** a high level recording of operations to the database - sometimes us ed for diagnostics | /** a high level recording of operations to the database - sometimes us ed for diagnostics | |||
and debugging. | and debugging. | |||
*/ | */ | |||
class DiagLog { | class DiagLog { | |||
ofstream *f; // note this is never freed | ofstream *f; // note this is never freed | |||
skipping to change at line 57 | skipping to change at line 58 | |||
* @return old | * @return old | |||
*/ | */ | |||
int setLevel( int newLevel ); | int setLevel( int newLevel ); | |||
void flush(); | void flush(); | |||
void writeop(char *data,int len); | void writeop(char *data,int len); | |||
void readop(char *data, int len); | void readop(char *data, int len); | |||
}; | }; | |||
extern DiagLog _diaglog; | extern DiagLog _diaglog; | |||
/* we defer response until we unlock. don't want a blocked socket to | ||||
keep things locked. | ||||
*/ | ||||
struct DbResponse { | ||||
Message *response; | ||||
MSGID responseTo; | ||||
string exhaustNS; /* points to ns if exhaust mode. 0=normal mode*/ | ||||
DbResponse(Message *r, MSGID rt) : response(r), responseTo(rt){ } | ||||
DbResponse() { | ||||
response = 0; | ||||
} | ||||
~DbResponse() { delete response; } | ||||
}; | ||||
void assembleResponse( Message &m, DbResponse &dbresponse, const HostAn dPort &client ); | void assembleResponse( Message &m, DbResponse &dbresponse, const HostAn dPort &client ); | |||
void getDatabaseNames( vector< string > &names , const string& usePath = dbpath ); | void getDatabaseNames( vector< string > &names , const string& usePath = dbpath ); | |||
/* returns true if there is no data on this server. useful when starti ng replication. | /* returns true if there is no data on this server. useful when starti ng replication. | |||
local database does NOT count. | local database does NOT count. | |||
*/ | */ | |||
bool replHasDatabases(); | bool replHasDatabases(); | |||
/** "embedded" calls to the local server directly. | /** "embedded" calls to the local server directly. | |||
End of changes. 2 change blocks. | ||||
14 lines changed or deleted | 1 lines changed or added | |||
interrupt_status.h | interrupt_status.h | |||
---|---|---|---|---|
skipping to change at line 19 | skipping to change at line 19 | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public License | * You should have received a copy of the GNU Affero General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | ||||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
Abstraction for checking on interrupt status. | Abstraction for checking on interrupt status. | |||
The killCurrentOp object (currently declared in curop.h, and defined | The killCurrentOp object (currently declared in curop.h, and defined | |||
in instance.cpp) can only be referenced within mongod. This abstrac tion | in instance.cpp) can only be referenced within mongod. This abstrac tion | |||
serves to isolate that so that code that runs in both mongod and mon gos | serves to isolate that so that code that runs in both mongod and mon gos | |||
can be linked without unresolved symbols. There is a concrete | can be linked without unresolved symbols. There is a concrete | |||
implementation of this class for mongod which references killCurrent Op, | implementation of this class for mongod which references killCurrent Op, | |||
and another implementation for mongos which does not (currently, it | and another implementation for mongos which does not (currently, it | |||
does nothing, but that should be fixed). | does nothing, but that should be fixed). | |||
*/ | */ | |||
class InterruptStatus { | class InterruptStatus { | |||
public: | public: | |||
/** | /** | |||
Check for interrupt. | Check for interrupt. | |||
@throws a uassert if the process has received an interrupt (SIGI NT) | @throws a uassert if the process has received an interrupt (SIGI NT) | |||
*/ | */ | |||
virtual void checkForInterrupt() = 0; | virtual void checkForInterrupt() const =0; | |||
/** | /** | |||
Check for interrupt. | Check for interrupt. | |||
@returns a pointer to a string with additional information; will be | @returns a pointer to a string with additional information; will be | |||
"" if there hasn't been an interrupt. These strings are stati c | "" if there hasn't been an interrupt. These strings are stati c | |||
and don't need to be freed. | and don't need to be freed. | |||
*/ | */ | |||
virtual const char *checkForInterruptNoAssert() = 0; | virtual const char *checkForInterruptNoAssert() const =0; | |||
protected: | protected: | |||
/** | /** | |||
This interface is meant to be used in the implementation of stat ic | This interface is meant to be used in the implementation of stat ic | |||
objects, so the destructor is made protected so that they can't be | objects, so the destructor is made protected so that they can't be | |||
accidentally deleted. It can't be private, or the compiler | accidentally deleted. It can't be private, or the compiler | |||
generates warnings about being unable to generate the derived | generates warnings about being unable to generate the derived | |||
classes' destructors. | classes' destructors. | |||
*/ | */ | |||
virtual ~InterruptStatus() {}; | virtual ~InterruptStatus() {}; | |||
End of changes. 3 change blocks. | ||||
4 lines changed or deleted | 2 lines changed or added | |||
interrupt_status_mongod.h | interrupt_status_mongod.h | |||
---|---|---|---|---|
skipping to change at line 19 | skipping to change at line 19 | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public License | * You should have received a copy of the GNU Affero General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/db/interrupt_status.h" | |||
#include "db/interrupt_status.h" | ||||
namespace mongo { | namespace mongo { | |||
class InterruptStatusMongod : | class InterruptStatusMongod : | |||
public InterruptStatus, | public InterruptStatus, | |||
boost::noncopyable { | boost::noncopyable { | |||
public: | public: | |||
// virtuals from InterruptStatus | // virtuals from InterruptStatus | |||
virtual void checkForInterrupt(); | virtual void checkForInterrupt() const; | |||
virtual const char *checkForInterruptNoAssert(); | virtual const char *checkForInterruptNoAssert() const; | |||
/* | /* | |||
Static singleton instance. | Static singleton instance. | |||
*/ | */ | |||
static InterruptStatusMongod status; | static const InterruptStatusMongod status; | |||
private: | private: | |||
InterruptStatusMongod(); | InterruptStatusMongod(); | |||
}; | }; | |||
}; | }; | |||
End of changes. 3 change blocks. | ||||
5 lines changed or deleted | 4 lines changed or added | |||
interrupt_status_mongos.h | interrupt_status_mongos.h | |||
---|---|---|---|---|
skipping to change at line 19 | skipping to change at line 19 | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public License | * You should have received a copy of the GNU Affero General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/db/interrupt_status.h" | |||
#include "db/interrupt_status.h" | ||||
namespace mongo { | namespace mongo { | |||
class InterruptStatusMongos : | class InterruptStatusMongos : | |||
public InterruptStatus, | public InterruptStatus, | |||
boost::noncopyable { | boost::noncopyable { | |||
public: | public: | |||
// virtuals from InterruptStatus | // virtuals from InterruptStatus | |||
virtual void checkForInterrupt(); | virtual void checkForInterrupt() const; | |||
virtual const char *checkForInterruptNoAssert(); | virtual const char *checkForInterruptNoAssert() const; | |||
/* | /* | |||
Static singleton instance. | Static singleton instance. | |||
*/ | */ | |||
static InterruptStatusMongos status; | static const InterruptStatusMongos status; | |||
private: | private: | |||
InterruptStatusMongos(); | InterruptStatusMongos(); | |||
}; | }; | |||
}; | }; | |||
End of changes. 3 change blocks. | ||||
5 lines changed or deleted | 4 lines changed or added | |||
introspect.h | introspect.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 "mongo/pch.h" | #include "mongo/pch.h" | |||
#include "jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "pdfile.h" | #include "mongo/db/pdfile.h" | |||
namespace mongo { | namespace mongo { | |||
/* --- profiling -------------------------------------------- | /* --- profiling -------------------------------------------- | |||
do when database->profile is set | do when database->profile is set | |||
*/ | */ | |||
void profile(const Client& c, int op, CurOp& currentOp); | void profile(const Client& c, int op, CurOp& currentOp); | |||
/** | /** | |||
End of changes. 1 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
jsobj.h | jsobj.h | |||
---|---|---|---|---|
skipping to change at line 34 | skipping to change at line 34 | |||
represented in JSON (plus a few extensions useful for databases & other languages). | represented in JSON (plus a few extensions useful for databases & other languages). | |||
http://www.bsonspec.org/ | http://www.bsonspec.org/ | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/pch.h" | |||
#include "mongo/bson/util/builder.h" | #include "mongo/bson/util/builder.h" | |||
#include "mongo/db/repl/optime.h" | #include "mongo/bson/optime.h" | |||
#include "mongo/bson/bsontypes.h" | #include "mongo/bson/bsontypes.h" | |||
#include "mongo/bson/oid.h" | #include "mongo/bson/oid.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/bsonobjbuilder.h" | #include "mongo/bson/bsonobjbuilder.h" | |||
#include "mongo/bson/bsonobjiterator.h" | #include "mongo/bson/bsonobjiterator.h" | |||
#include "mongo/bson/bson-inl.h" | #include "mongo/bson/bson-inl.h" | |||
#include "mongo/bson/ordering.h" | #include "mongo/bson/ordering.h" | |||
#include "mongo/base/string_data.h" | #include "mongo/base/string_data.h" | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
limit.h | limit.h | |||
---|---|---|---|---|
skipping to change at line 44 | skipping to change at line 44 | |||
LimitStage(int limit, WorkingSet* ws, PlanStage* child); | LimitStage(int limit, WorkingSet* ws, PlanStage* child); | |||
virtual ~LimitStage(); | virtual ~LimitStage(); | |||
virtual bool isEOF(); | virtual bool isEOF(); | |||
virtual StageState work(WorkingSetID* out); | virtual StageState work(WorkingSetID* out); | |||
virtual void prepareToYield(); | virtual void prepareToYield(); | |||
virtual void recoverFromYield(); | virtual void recoverFromYield(); | |||
virtual void invalidate(const DiskLoc& dl); | virtual void invalidate(const DiskLoc& dl); | |||
virtual PlanStageStats* getStats(); | ||||
private: | private: | |||
WorkingSet* _ws; | WorkingSet* _ws; | |||
scoped_ptr<PlanStage> _child; | scoped_ptr<PlanStage> _child; | |||
// We only return this many results. | // We only return this many results. | |||
int _numToReturn; | int _numToReturn; | |||
// Stats | ||||
CommonStats _commonStats; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 5 lines changed or added | |||
listen.h | listen.h | |||
---|---|---|---|---|
skipping to change at line 20 | skipping to change at line 20 | |||
* | * | |||
* Unless required by applicable law or agreed to in writing, software | * Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | * distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. | |||
* See the License for the specific language governing permissions and | * See the License for the specific language governing permissions and | |||
* limitations under the License. | * limitations under the License. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <set> | ||||
#include <string> | ||||
#include <vector> | ||||
#include "mongo/platform/atomic_word.h" | #include "mongo/platform/atomic_word.h" | |||
#include "mongo/util/concurrency/ticketholder.h" | #include "mongo/util/concurrency/ticketholder.h" | |||
#include "mongo/util/log.h" | ||||
#include "mongo/util/net/sock.h" | #include "mongo/util/net/sock.h" | |||
namespace mongo { | namespace mongo { | |||
const int DEFAULT_MAX_CONN = 20000; | const int DEFAULT_MAX_CONN = 20000; | |||
class MessagingPort; | class MessagingPort; | |||
class Listener : boost::noncopyable { | class Listener : boost::noncopyable { | |||
public: | public: | |||
Listener(const string& name, const string &ip, int port, bool logCo nnect=true ); | Listener(const std::string& name, const std::string &ip, int port, bool logConnect=true ); | |||
virtual ~Listener(); | virtual ~Listener(); | |||
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; | |||
skipping to change at line 67 | skipping to change at line 72 | |||
static long long getElapsedTimeMillis() { | static long long getElapsedTimeMillis() { | |||
if ( _timeTracker ) | if ( _timeTracker ) | |||
return _timeTracker->getMyElapsedTimeMillis(); | return _timeTracker->getMyElapsedTimeMillis(); | |||
// should this assert or throw? seems like callers may not exp ect to get zero back, certainly not forever. | // should this assert or throw? seems like callers may not exp ect to get zero back, certainly not forever. | |||
return 0; | return 0; | |||
} | } | |||
private: | private: | |||
string _name; | std::string _name; | |||
string _ip; | std::string _ip; | |||
bool _logConnect; | bool _logConnect; | |||
long long _elapsedTime; | long long _elapsedTime; | |||
#ifdef MONGO_SSL | #ifdef MONGO_SSL | |||
SSLManagerInterface* _ssl; | SSLManagerInterface* _ssl; | |||
#endif | #endif | |||
/** | /** | |||
* @return true iff everything went ok | * @return true iff everything went ok | |||
*/ | */ | |||
bool _setupSockets( const vector<SockAddr>& mine , vector<SOCKET>& socks ); | bool _setupSockets( const std::vector<SockAddr>& mine , std::vector <SOCKET>& socks ); | |||
void _logListen( int port , bool ssl ); | void _logListen( int port , bool ssl ); | |||
static const Listener* _timeTracker; | static const Listener* _timeTracker; | |||
virtual bool useUnixSockets() const { return false; } | virtual bool useUnixSockets() const { return false; } | |||
public: | public: | |||
/** the "next" connection number. every connection to this process has a unique number */ | /** the "next" connection number. every connection to this process has a unique number */ | |||
static AtomicInt64 globalConnectionNumber; | static AtomicInt64 globalConnectionNumber; | |||
skipping to change at line 102 | skipping to change at line 107 | |||
static TicketHolder globalTicketHolder; | static TicketHolder globalTicketHolder; | |||
/** makes sure user input is sane */ | /** makes sure user input is sane */ | |||
static void checkTicketNumbers(); | static void checkTicketNumbers(); | |||
}; | }; | |||
class ListeningSockets { | class ListeningSockets { | |||
public: | public: | |||
ListeningSockets() | ListeningSockets() | |||
: _mutex("ListeningSockets") | : _mutex("ListeningSockets") | |||
, _sockets( new set<int>() ) | , _sockets( new std::set<int>() ) | |||
, _socketPaths( new set<string>() ) | , _socketPaths( new std::set<std::string>() ) | |||
{ } | { } | |||
void add( int sock ) { | void add( int sock ) { | |||
scoped_lock lk( _mutex ); | scoped_lock lk( _mutex ); | |||
_sockets->insert( sock ); | _sockets->insert( sock ); | |||
} | } | |||
void addPath( const std::string& path ) { | void addPath( const std::string& path ) { | |||
scoped_lock lk( _mutex ); | scoped_lock lk( _mutex ); | |||
_socketPaths->insert( path ); | _socketPaths->insert( path ); | |||
} | } | |||
void remove( int sock ) { | void remove( int sock ) { | |||
scoped_lock lk( _mutex ); | scoped_lock lk( _mutex ); | |||
_sockets->erase( sock ); | _sockets->erase( sock ); | |||
} | } | |||
void closeAll() { | void closeAll() { | |||
set<int>* sockets; | std::set<int>* sockets; | |||
set<string>* paths; | std::set<std::string>* paths; | |||
{ | { | |||
scoped_lock lk( _mutex ); | scoped_lock lk( _mutex ); | |||
sockets = _sockets; | sockets = _sockets; | |||
_sockets = new set<int>(); | _sockets = new std::set<int>(); | |||
paths = _socketPaths; | paths = _socketPaths; | |||
_socketPaths = new set<string>(); | _socketPaths = new std::set<std::string>(); | |||
} | } | |||
for ( set<int>::iterator i=sockets->begin(); i!=sockets->end(); i++ ) { | for ( std::set<int>::iterator i=sockets->begin(); i!=sockets->e nd(); i++ ) { | |||
int sock = *i; | int sock = *i; | |||
log() << "closing listening socket: " << sock << endl; | log() << "closing listening socket: " << sock << std::endl; | |||
closesocket( sock ); | closesocket( sock ); | |||
} | } | |||
for ( set<string>::iterator i=paths->begin(); i!=paths->end(); | for ( std::set<std::string>::iterator i=paths->begin(); i!=path | |||
i++ ) { | s->end(); i++ ) { | |||
string path = *i; | std::string path = *i; | |||
log() << "removing socket file: " << path << endl; | log() << "removing socket file: " << path << std::endl; | |||
::remove( path.c_str() ); | ::remove( path.c_str() ); | |||
} | } | |||
} | } | |||
static ListeningSockets* get(); | static ListeningSockets* get(); | |||
private: | private: | |||
mongo::mutex _mutex; | mongo::mutex _mutex; | |||
set<int>* _sockets; | std::set<int>* _sockets; | |||
set<string>* _socketPaths; // for unix domain sockets | std::set<std::string>* _socketPaths; // for unix domain sockets | |||
static ListeningSockets* _instance; | static ListeningSockets* _instance; | |||
}; | }; | |||
} | } | |||
End of changes. 13 change blocks. | ||||
18 lines changed or deleted | 23 lines changed or added | |||
lruishmap.h | lruishmap.h | |||
---|---|---|---|---|
skipping to change at line 21 | skipping to change at line 21 | |||
* Unless required by applicable law or agreed to in writing, software | * Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | * distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. | |||
* See the License for the specific language governing permissions and | * See the License for the specific language governing permissions and | |||
* limitations under the License. | * limitations under the License. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/pch.h" | |||
#include "../util/goodies.h" | #include "mongo/util/goodies.h" | |||
namespace mongo { | namespace mongo { | |||
/* Your K object must define: | /* Your K object must define: | |||
int hash() - must always return > 0. | int hash() - must always return > 0. | |||
operator== | operator== | |||
*/ | */ | |||
template <class K, class V, int MaxChain> | template <class K, class V, int MaxChain> | |||
class LRUishMap { | class LRUishMap { | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
master_slave.h | master_slave.h | |||
---|---|---|---|---|
skipping to change at line 80 | skipping to change at line 80 | |||
/* we only clone one database per pass, even if a lot need done. T his helps us | /* we only clone one database per pass, even if a lot need done. T his helps us | |||
avoid overflowing the master's transaction log by doing too much work before going | avoid overflowing the master's transaction log by doing too much work before going | |||
back to read more transactions. (Imagine a scenario of slave sta rtup where we try to | back to read more transactions. (Imagine a scenario of slave sta rtup where we try to | |||
clone 100 databases in one pass.) | clone 100 databases in one pass.) | |||
*/ | */ | |||
set<string> addDbNextPass; | set<string> addDbNextPass; | |||
set<string> incompleteCloneDbs; | set<string> incompleteCloneDbs; | |||
BSONObj _me; | ||||
ReplSource(); | ReplSource(); | |||
// returns the dummy ns used to do the drop | // returns the dummy ns used to do the drop | |||
string resyncDrop( const char *db, const char *requester ); | string resyncDrop( const char *db, const char *requester ); | |||
// call without the db mutex | // call without the db mutex | |||
void syncToTailOfRemoteLog(); | void syncToTailOfRemoteLog(); | |||
string ns() const { return string( "local.oplog.$" ) + sourceName() ; } | string ns() const { return string( "local.oplog.$" ) + sourceName() ; } | |||
unsigned _sleepAdviceTime; | unsigned _sleepAdviceTime; | |||
/** | /** | |||
* If 'db' is a new database and its name would conflict with that of | * If 'db' is a new database and its name would conflict with that of | |||
* an existing database, synchronize these database names with the | * an existing database, synchronize these database names with the | |||
* master. | * master. | |||
* @return true iff an op with the specified ns may be applied. | * @return true iff an op with the specified ns may be applied. | |||
*/ | */ | |||
bool handleDuplicateDbName( const BSONObj &op, const char *ns, cons t char *db ); | bool handleDuplicateDbName( const BSONObj &op, const char *ns, cons t char *db ); | |||
// populates _me so that it can be passed to oplogreader for handsh | ||||
akes | ||||
void ensureMe(); | ||||
public: | public: | |||
OplogReader oplogReader; | OplogReader oplogReader; | |||
void applyOperation(const BSONObj& op); | void applyOperation(const BSONObj& op); | |||
string hostName; // ip addr or hostname plus optionally, ":<port >" | string hostName; // ip addr or hostname plus optionally, ":<port >" | |||
string _sourceName; // a logical source name. | string _sourceName; // a logical source name. | |||
string sourceName() const { return _sourceName.empty() ? "main" : _ sourceName; } | string sourceName() const { return _sourceName.empty() ? "main" : _ sourceName; } | |||
string only; // only a certain db. note that in the sources collect ion, this may not be changed once you start replicating. | string only; // only a certain db. note that in the sources collect ion, this may not be changed once you start replicating. | |||
/* the last time point we have already synced up to (in the remote/ master's oplog). */ | /* the last time point we have already synced up to (in the remote/ master's oplog). */ | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 6 lines changed or added | |||
match_details.h | match_details.h | |||
---|---|---|---|---|
skipping to change at line 21 | skipping to change at line 21 | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Licen se | * You should have received a copy of the GNU Affero General Public Licen se | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <boost/scoped_ptr.hpp> | ||||
#include <string> | #include <string> | |||
namespace mongo { | namespace mongo { | |||
/** Reports information about a match request. */ | /** Reports information about a match request. */ | |||
class MatchDetails { | class MatchDetails { | |||
public: | public: | |||
MatchDetails(); | MatchDetails(); | |||
void resetOutput(); | void resetOutput(); | |||
// for debugging only | ||||
std::string toString() const; | std::string toString() const; | |||
/** Request that an elemMatchKey be recorded. */ | // relating to whether or not we had to load the full record | |||
void requestElemMatchKey() { _elemMatchKeyRequested = true; } | ||||
bool needRecord() const { return _elemMatchKeyRequested; } | void setLoadedRecord( bool loadedRecord ) { _loadedRecord = loadedR ecord; } | |||
bool hasLoadedRecord() const { return _loadedRecord; } | bool hasLoadedRecord() const { return _loadedRecord; } | |||
bool hasElemMatchKey() const { return _elemMatchKeyFound; } | ||||
std::string elemMatchKey() const { | ||||
verify( hasElemMatchKey() ); | ||||
return _elemMatchKey; | ||||
} | ||||
void setLoadedRecord( bool loadedRecord ) { _loadedRecord = loadedR | // this name is wrong | |||
ecord; } | ||||
void setElemMatchKey( const std::string &elemMatchKey ) { | bool needRecord() const { return _elemMatchKeyRequested; } | |||
if ( _elemMatchKeyRequested ) { | ||||
_elemMatchKeyFound = true; | // if we need to store the offset into an array where we found the | |||
_elemMatchKey = elemMatchKey; | match | |||
} | ||||
} | /** Request that an elemMatchKey be recorded. */ | |||
void requestElemMatchKey() { _elemMatchKeyRequested = true; } | ||||
bool hasElemMatchKey() const; | ||||
std::string elemMatchKey() const; | ||||
void setElemMatchKey( const std::string &elemMatchKey ); | ||||
private: | private: | |||
bool _loadedRecord; | bool _loadedRecord; | |||
bool _elemMatchKeyRequested; | bool _elemMatchKeyRequested; | |||
bool _elemMatchKeyFound; | boost::scoped_ptr<std::string> _elemMatchKey; | |||
std::string _elemMatchKey; | ||||
}; | }; | |||
} | } | |||
End of changes. 8 change blocks. | ||||
18 lines changed or deleted | 22 lines changed or added | |||
message_event.h | message_event.h | |||
---|---|---|---|---|
skipping to change at line 20 | skipping to change at line 20 | |||
* 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/base/string_data.h" | #include "mongo/base/string_data.h" | |||
#include "mongo/logger/log_severity.h" | #include "mongo/logger/log_severity.h" | |||
#include "mongo/platform/cstdint.h" | ||||
#include "mongo/util/time_support.h" | ||||
namespace mongo { | namespace mongo { | |||
namespace logger { | namespace logger { | |||
/** | /** | |||
* Free form text log message object that does not own the storage behi nd its message and | * Free form text log message object that does not own the storage behi nd its message and | |||
* contextName. | * contextName. | |||
* | * | |||
* Used and owned by one thread. This is the message type used by Mess ageLogDomain. | * Used and owned by one thread. This is the message type used by Mess ageLogDomain. | |||
*/ | */ | |||
class MessageEventEphemeral { | class MessageEventEphemeral { | |||
public: | public: | |||
MessageEventEphemeral(LogSeverity severity, StringData contextName, | MessageEventEphemeral( | |||
StringData message) : | Date_t date, | |||
_severity(severity), _contextName(contextName), _message(messag | LogSeverity severity, | |||
e) {} | StringData contextName, | |||
StringData message) : | ||||
_date(date), | ||||
_severity(severity), | ||||
_contextName(contextName), | ||||
_message(message) {} | ||||
uint64_t getDate() const { return _date; } | ||||
LogSeverity getSeverity() const { return _severity; } | LogSeverity getSeverity() const { return _severity; } | |||
StringData getContextName() const { return _contextName; } | StringData getContextName() const { return _contextName; } | |||
StringData getMessage() const { return _message; } | StringData getMessage() const { return _message; } | |||
private: | private: | |||
Date_t _date; | ||||
LogSeverity _severity; | LogSeverity _severity; | |||
StringData _contextName; | StringData _contextName; | |||
StringData _message; | StringData _message; | |||
}; | }; | |||
} // namespace logger | } // namespace logger | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 4 change blocks. | ||||
4 lines changed or deleted | 13 lines changed or added | |||
message_event_utf8_encoder.h | message_event_utf8_encoder.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 <string> | ||||
#include "mongo/logger/encoder.h" | #include "mongo/logger/encoder.h" | |||
#include "mongo/logger/message_event.h" | #include "mongo/logger/message_event.h" | |||
#include "mongo/util/time_support.h" | ||||
namespace mongo { | namespace mongo { | |||
namespace logger { | namespace logger { | |||
/** | /** | |||
* Encoder that writes log messages of the style that MongoDB writes to console and files. | * Encoder that writes log messages of the style that MongoDB writes to console and files. | |||
*/ | */ | |||
class MessageEventDetailsEncoder : public Encoder<MessageEventEphemeral > { | class MessageEventDetailsEncoder : public Encoder<MessageEventEphemeral > { | |||
public: | public: | |||
typedef std::string (*DateFormatter)(Date_t); | ||||
/** | ||||
* Sets the date formatter function for all instances of MessageEve | ||||
ntDetailsEncoder. | ||||
* | ||||
* Only and always safe to call during single-threaded execution, a | ||||
s in during start-up | ||||
* intiailization. | ||||
*/ | ||||
static void setDateFormatter(DateFormatter dateFormatter); | ||||
/** | ||||
* Gets the date formatter function in use by instances of MessageE | ||||
ventDetailsEncoder. | ||||
* | ||||
* Always safe to call. | ||||
*/ | ||||
static DateFormatter getDateFormatter(); | ||||
virtual ~MessageEventDetailsEncoder(); | virtual ~MessageEventDetailsEncoder(); | |||
virtual std::ostream& encode(const MessageEventEphemeral& event, st d::ostream& os); | virtual std::ostream& encode(const MessageEventEphemeral& event, st d::ostream& os); | |||
}; | }; | |||
/** | /** | |||
* Encoder that generates log messages suitable for syslog. | * Encoder that generates log messages suitable for syslog. | |||
*/ | */ | |||
class MessageEventWithContextEncoder : public Encoder<MessageEventEphem eral> { | class MessageEventWithContextEncoder : public Encoder<MessageEventEphem eral> { | |||
public: | public: | |||
virtual ~MessageEventWithContextEncoder(); | virtual ~MessageEventWithContextEncoder(); | |||
End of changes. 3 change blocks. | ||||
0 lines changed or deleted | 23 lines changed or added | |||
message_port.h | message_port.h | |||
---|---|---|---|---|
skipping to change at line 39 | skipping to change at line 39 | |||
class AbstractMessagingPort : boost::noncopyable { | class AbstractMessagingPort : boost::noncopyable { | |||
public: | public: | |||
AbstractMessagingPort() : tag(0), _connectionId(0) {} | AbstractMessagingPort() : tag(0), _connectionId(0) {} | |||
virtual ~AbstractMessagingPort() { } | virtual ~AbstractMessagingPort() { } | |||
virtual void reply(Message& received, Message& response, MSGID resp onseTo) = 0; // like the reply below, but doesn't rely on received.data sti ll being available | virtual void reply(Message& received, Message& response, MSGID resp onseTo) = 0; // like the reply below, but doesn't rely on received.data sti ll being available | |||
virtual void reply(Message& received, Message& response) = 0; | virtual void reply(Message& received, Message& response) = 0; | |||
virtual HostAndPort remote() const = 0; | virtual HostAndPort remote() const = 0; | |||
virtual unsigned remotePort() const = 0; | virtual unsigned remotePort() const = 0; | |||
virtual SockAddr remoteAddr() const = 0; | ||||
virtual SockAddr localAddr() const = 0; | ||||
long long connectionId() const { return _connectionId; } | long long connectionId() const { return _connectionId; } | |||
void setConnectionId( long long connectionId ); | void setConnectionId( long long connectionId ); | |||
void setX509SubjectName(const std::string& x509SubjectName){ | void setX509SubjectName(const std::string& x509SubjectName){ | |||
_x509SubjectName = x509SubjectName; | _x509SubjectName = x509SubjectName; | |||
} | } | |||
std::string getX509SubjectName(){ | std::string getX509SubjectName(){ | |||
return _x509SubjectName; | return _x509SubjectName; | |||
skipping to change at line 105 | skipping to change at line 107 | |||
* recv( from ) | * recv( from ) | |||
* Note: if you fail to call recv and someone else uses this port, | * Note: if you fail to call recv and someone else uses this port, | |||
* horrible things will happen | * horrible things will happen | |||
*/ | */ | |||
bool recv( const Message& sent , Message& response ); | bool recv( const Message& sent , Message& response ); | |||
void piggyBack( Message& toSend , int responseTo = -1 ); | void piggyBack( Message& toSend , int responseTo = -1 ); | |||
unsigned remotePort() const { return psock->remotePort(); } | unsigned remotePort() const { return psock->remotePort(); } | |||
virtual HostAndPort remote() const; | virtual HostAndPort remote() const; | |||
virtual SockAddr remoteAddr() const; | ||||
virtual SockAddr localAddr() const; | ||||
boost::shared_ptr<Socket> psock; | boost::shared_ptr<Socket> psock; | |||
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) { | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 4 lines changed or added | |||
metadata_loader.h | metadata_loader.h | |||
---|---|---|---|---|
skipping to change at line 32 | skipping to change at line 32 | |||
#include "mongo/client/dbclientinterface.h" | #include "mongo/client/dbclientinterface.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
namespace mongo { | namespace mongo { | |||
class CollectionMetadata; | class CollectionMetadata; | |||
class CollectionType; | class CollectionType; | |||
class DBClientCursor; | class DBClientCursor; | |||
/** | /** | |||
* The MetadataLoader is responsible for interfacing with the config se | * The MetadataLoader is responsible for interfacing with the config se | |||
rvers and obtaining | rvers and previous | |||
* the data that CollectionMetadatas are made of. Effectively, the load | * metadata to build new instances of CollectionMetadata. MetadataLoad | |||
er is the "builder" | er is the "builder" | |||
* class for that metadata. | * class for metadata. | |||
* | ||||
* CollectionMetadata has both persisted and volatile state (for now) - | ||||
the persisted | ||||
* config server chunk state and the volatile pending state which is on | ||||
ly tracked locally | ||||
* while a server is the primary. This requires a two-step loading pro | ||||
cess - the persisted | ||||
* chunk state *cannot* be loaded in a DBWrite lock while the pending c | ||||
hunk state *must* be. | ||||
* | ||||
* Example usage: | ||||
* beforeMetadata = <get latest local metadata>; | ||||
* remoteMetadata = makeCollectionMetadata( beforeMetadata, remoteMetad | ||||
ata ); | ||||
* DBWrite lock( ns ); | ||||
* afterMetadata = <get latest local metadata>; | ||||
* promotePendingChunks( afterMetadata, remoteMetadata ); | ||||
* | * | |||
* The loader will go out of its way to try to fetch the smaller amount possible of data | * The loader will go out of its way to try to fetch the smaller amount possible of data | |||
* from the config server without sacrificing the freshness and accurac y of the metadata it | * from the config server without sacrificing the freshness and accurac y of the metadata it | |||
* builds. (See ConfigDiffTracker class.) | * builds. (See ConfigDiffTracker class.) | |||
* | * | |||
* The class is not thread safe. | * The class is not thread safe. | |||
*/ | */ | |||
class MetadataLoader { | class MetadataLoader { | |||
public: | public: | |||
skipping to change at line 60 | skipping to change at line 72 | |||
explicit MetadataLoader( const ConnectionString& configLoc ); | explicit MetadataLoader( const ConnectionString& configLoc ); | |||
~MetadataLoader(); | ~MetadataLoader(); | |||
/** | /** | |||
* Fills a new metadata instance representing the chunkset of the c ollection 'ns' | * Fills a new metadata instance representing the chunkset of the c ollection 'ns' | |||
* (or its entirety, if not sharded) that lives on 'shard' with dat a from the config server. | * (or its entirety, if not sharded) that lives on 'shard' with dat a from the config server. | |||
* Optionally, uses an 'oldMetadata' for the same 'ns'/'shard'; the contents of | * Optionally, uses an 'oldMetadata' for the same 'ns'/'shard'; the contents of | |||
* 'oldMetadata' can help reducing the amount of data read from the config servers. | * 'oldMetadata' can help reducing the amount of data read from the config servers. | |||
* | * | |||
* Locking note: | ||||
* + Must not be called in a DBLock, since this loads over the n | ||||
etwork | ||||
* | ||||
* OK on success. | * OK on success. | |||
* | * | |||
* Failure return values: | * Failure return values: | |||
* Abnormal: | * Abnormal: | |||
* @return FailedToParse if there was an error parsing the remote c onfig data | * @return FailedToParse if there was an error parsing the remote c onfig data | |||
* Normal: | * Normal: | |||
* @return NamespaceNotFound if the collection no longer exists | * @return NamespaceNotFound if the collection no longer exists | |||
* @return HostUnreachable if there was an error contacting the con fig servers | * @return HostUnreachable if there was an error contacting the con fig servers | |||
* @return RemoteChangeDetected if the data loaded was modified by another operation | * @return RemoteChangeDetected if the data loaded was modified by another operation | |||
*/ | */ | |||
Status makeCollectionMetadata( const string& ns, | Status makeCollectionMetadata( const string& ns, | |||
const string& shard, | const string& shard, | |||
const CollectionMetadata* oldMetadat a, | const CollectionMetadata* oldMetadat a, | |||
CollectionMetadata* metadata ) const ; | CollectionMetadata* metadata ) const ; | |||
/** | ||||
* Replaces the pending chunks of the remote metadata with the more | ||||
up-to-date pending | ||||
* chunks of the 'after' metadata (metadata from after the remote l | ||||
oad), and removes pending | ||||
* chunks which are now regular chunks. | ||||
* | ||||
* Pending chunks should always correspond to one or zero chunks in | ||||
the remoteMetadata | ||||
* if the epochs are the same and the remote version is the same or | ||||
higher, otherwise they | ||||
* are not applicable. | ||||
* | ||||
* Locking note: | ||||
* + Must be called in a DBLock, to ensure validity of afterMeta | ||||
data | ||||
* | ||||
* Returns OK if pending chunks correctly follow the rule above or | ||||
are not applicable | ||||
* Returns RemoteChangeDetected if pending chunks do not follow the | ||||
rule above, indicating | ||||
* either the config server or us has | ||||
changed unexpectedly. | ||||
* This should only occur with manual | ||||
editing of the config | ||||
* server. | ||||
* | ||||
* TODO: This is a bit ugly but necessary for now. If/when pendin | ||||
g chunk info is stored on | ||||
* the config server, this should go away. | ||||
*/ | ||||
Status promotePendingChunks( const CollectionMetadata* afterMetadat | ||||
a, | ||||
CollectionMetadata* remoteMetadata ) c | ||||
onst; | ||||
private: | private: | |||
ConnectionString _configLoc; | ConnectionString _configLoc; | |||
/** | /** | |||
* Returns OK and fills in the internal state of 'metadata' with ge neral collection | * Returns OK and fills in the internal state of 'metadata' with ge neral collection | |||
* information, not including chunks. | * information, not including chunks. | |||
* | * | |||
* If information about the collection can be accessed or is invali d, returns: | * If information about the collection can be accessed or is invali d, returns: | |||
* @return NamespaceNotFound if the collection no longer exists | * @return NamespaceNotFound if the collection no longer exists | |||
* @return FailedToParse if there was an error parsing the remote c onfig data | * @return FailedToParse if there was an error parsing the remote c onfig data | |||
skipping to change at line 101 | skipping to change at line 140 | |||
CollectionMetadata* metadata ) const; | CollectionMetadata* metadata ) const; | |||
/** | /** | |||
* Returns OK and fills in the chunk state of 'metadata' to portray the chunks of the | * Returns OK and fills in the chunk state of 'metadata' to portray the chunks of the | |||
* collection 'ns' that sit in 'shard'. If provided, uses the conte nts of 'oldMetadata' | * collection 'ns' that sit in 'shard'. If provided, uses the conte nts of 'oldMetadata' | |||
* as a base (see description in initCollection above). | * as a base (see description in initCollection above). | |||
* | * | |||
* If information about the chunks can be accessed or is invalid, r eturns: | * If information about the chunks can be accessed or is invalid, r eturns: | |||
* @return HostUnreachable if there was an error contacting the con fig servers | * @return HostUnreachable if there was an error contacting the con fig servers | |||
* @return RemoteChangeDetected if the chunks loaded are unexpected ly different | * @return RemoteChangeDetected if the chunks loaded are unexpected ly different | |||
* | ||||
* For backwards compatibility, | ||||
* @return NamespaceNotFound if there are no chunks loaded and an e | ||||
poch change is detected | ||||
* TODO: @return FailedToParse | * TODO: @return FailedToParse | |||
*/ | */ | |||
Status initChunks( const string& ns, | Status initChunks( const string& ns, | |||
const string& shard, | const string& shard, | |||
const CollectionMetadata* oldMetadata, | const CollectionMetadata* oldMetadata, | |||
CollectionMetadata* metadata ) const; | CollectionMetadata* metadata ) const; | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 4 change blocks. | ||||
5 lines changed or deleted | 66 lines changed or added | |||
misc.h | misc.h | |||
---|---|---|---|---|
skipping to change at line 28 | skipping to change at line 28 | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <ctime> | #include <ctime> | |||
#include <limits> | #include <limits> | |||
#include <string> | #include <string> | |||
#include "mongo/platform/cstdint.h" | #include "mongo/platform/cstdint.h" | |||
#include "mongo/util/assert_util.h" | #include "mongo/util/assert_util.h" | |||
#include "mongo/util/time_support.h" | ||||
namespace mongo { | namespace mongo { | |||
inline void time_t_to_String(time_t t, char *buf) { | ||||
#if defined(_WIN32) | ||||
ctime_s(buf, 32, &t); | ||||
#else | ||||
ctime_r(&t, buf); | ||||
#endif | ||||
buf[24] = 0; // don't want the \n | ||||
} | ||||
inline std::string time_t_to_String(time_t t = time(0) ) { | ||||
char buf[64]; | ||||
#if defined(_WIN32) | ||||
ctime_s(buf, sizeof(buf), &t); | ||||
#else | ||||
ctime_r(&t, buf); | ||||
#endif | ||||
buf[24] = 0; // don't want the \n | ||||
return buf; | ||||
} | ||||
inline std::string time_t_to_String_no_year(time_t t) { | ||||
char buf[64]; | ||||
#if defined(_WIN32) | ||||
ctime_s(buf, sizeof(buf), &t); | ||||
#else | ||||
ctime_r(&t, buf); | ||||
#endif | ||||
buf[19] = 0; | ||||
return buf; | ||||
} | ||||
inline std::string time_t_to_String_short(time_t t) { | ||||
char buf[64]; | ||||
#if defined(_WIN32) | ||||
ctime_s(buf, sizeof(buf), &t); | ||||
#else | ||||
ctime_r(&t, buf); | ||||
#endif | ||||
buf[19] = 0; | ||||
if( buf[0] && buf[1] && buf[2] && buf[3] ) | ||||
return buf + 4; // skip day of week | ||||
return buf; | ||||
} | ||||
struct Date_t { | ||||
// TODO: make signed (and look for related TODO's) | ||||
unsigned long long millis; | ||||
Date_t(): millis(0) {} | ||||
Date_t(unsigned long long m): millis(m) {} | ||||
operator unsigned long long&() { return millis; } | ||||
operator const unsigned long long&() const { return millis; } | ||||
void toTm (tm *buf) { | ||||
time_t dtime = toTimeT(); | ||||
#if defined(_WIN32) | ||||
gmtime_s(buf, &dtime); | ||||
#else | ||||
gmtime_r(&dtime, buf); | ||||
#endif | ||||
} | ||||
std::string toString() const { | ||||
char buf[64]; | ||||
time_t_to_String(toTimeT(), buf); | ||||
return buf; | ||||
} | ||||
time_t toTimeT() const { | ||||
// cant use uassert from bson/util | ||||
verify((long long)millis >= 0); // TODO when millis is signed, | ||||
delete | ||||
verify(((long long)millis/1000) < (std::numeric_limits<time_t>: | ||||
:max)()); | ||||
return millis / 1000; | ||||
} | ||||
int64_t asInt64() { | ||||
return static_cast<int64_t>(millis); | ||||
} | ||||
}; | ||||
// 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; | |||
} | } | |||
} | } | |||
End of changes. 2 change blocks. | ||||
77 lines changed or deleted | 1 lines changed or added | |||
mmap.h | mmap.h | |||
---|---|---|---|---|
skipping to change at line 100 | skipping to change at line 100 | |||
static set<MongoFile*>& getAllFiles(); | static set<MongoFile*>& getAllFiles(); | |||
// callbacks if you need them | // callbacks if you need them | |||
static void (*notifyPreFlush)(); | static void (*notifyPreFlush)(); | |||
static void (*notifyPostFlush)(); | static void (*notifyPostFlush)(); | |||
static int flushAll( bool sync ); // returns n flushed | static int flushAll( bool sync ); // returns n flushed | |||
static long long totalMappedLength(); | static long long totalMappedLength(); | |||
static void closeAllFiles( stringstream &message ); | static void closeAllFiles( stringstream &message ); | |||
virtual bool isMongoMMF() { return false; } | virtual bool isDurableMappedFile() { return false; } | |||
string filename() const { return _filename; } | string filename() const { return _filename; } | |||
void setFilename(const std::string& fn); | void setFilename(const std::string& fn); | |||
private: | private: | |||
string _filename; | string _filename; | |||
static int _flushAll( bool sync ); // returns n flushed | static int _flushAll( bool sync ); // returns n flushed | |||
protected: | protected: | |||
virtual void close() = 0; | virtual void close() = 0; | |||
virtual void flush(bool sync) = 0; | virtual void flush(bool sync) = 0; | |||
skipping to change at line 132 | skipping to change at line 132 | |||
ideal to call close to the close, if the close is well before ob ject destruction | ideal to call close to the close, if the close is well before ob ject destruction | |||
*/ | */ | |||
void destroyed(); | void destroyed(); | |||
virtual unsigned long long length() const = 0; | virtual unsigned long long length() const = 0; | |||
}; | }; | |||
/** look up a MMF by filename. scoped mutex locking convention. | /** look up a MMF by filename. scoped mutex locking convention. | |||
example: | example: | |||
MMFFinderByName finder; | MMFFinderByName finder; | |||
MongoMMF *a = finder.find("file_name_a"); | DurableMappedFile *a = finder.find("file_name_a"); | |||
MongoMMF *b = finder.find("file_name_b"); | DurableMappedFile *b = finder.find("file_name_b"); | |||
*/ | */ | |||
class MongoFileFinder : boost::noncopyable { | class MongoFileFinder : boost::noncopyable { | |||
public: | public: | |||
/** @return The MongoFile object associated with the specified file name. If no file is open | /** @return The MongoFile object associated with the specified file name. If no file is open | |||
with the specified name, returns null. | with the specified name, returns null. | |||
*/ | */ | |||
MongoFile* findByPath(const std::string& path) const; | MongoFile* findByPath(const std::string& path) const; | |||
private: | private: | |||
LockMongoFilesShared _lk; | LockMongoFilesShared _lk; | |||
skipping to change at line 226 | skipping to change at line 226 | |||
#else | #else | |||
void clearWritableBits(void *privateView) { } | void clearWritableBits(void *privateView) { } | |||
#endif | #endif | |||
protected: | protected: | |||
/** close the current private view and open a new replacement */ | /** close the current private view and open a new replacement */ | |||
void* remapPrivateView(void *oldPrivateAddr); | void* remapPrivateView(void *oldPrivateAddr); | |||
}; | }; | |||
typedef MemoryMappedFile MMF; | ||||
/** p is called from within a mutex that MongoFile uses. so be careful not to deadlock. */ | /** p is called from within a mutex that MongoFile uses. so be careful not to deadlock. */ | |||
template < class F > | template < class F > | |||
inline void MongoFile::forEach( F p ) { | inline void MongoFile::forEach( F p ) { | |||
LockMongoFilesShared lklk; | LockMongoFilesShared lklk; | |||
const set<MongoFile*>& mmfiles = MongoFile::getAllFiles(); | const set<MongoFile*>& mmfiles = MongoFile::getAllFiles(); | |||
for ( set<MongoFile*>::const_iterator i = mmfiles.begin(); i != mmf iles.end(); i++ ) | for ( set<MongoFile*>::const_iterator i = mmfiles.begin(); i != mmf iles.end(); i++ ) | |||
p(*i); | p(*i); | |||
} | } | |||
#if defined(_WIN32) | #if defined(_WIN32) | |||
End of changes. 3 change blocks. | ||||
5 lines changed or deleted | 3 lines changed or added | |||
mock_stage.h | mock_stage.h | |||
---|---|---|---|---|
skipping to change at line 52 | skipping to change at line 52 | |||
virtual StageState work(WorkingSetID* out); | virtual StageState work(WorkingSetID* out); | |||
virtual bool isEOF(); | virtual bool isEOF(); | |||
// These don't really mean anything here. | // These don't really mean anything here. | |||
// Some day we could count the # of calls to the yield functions to check that other stages | // Some day we could count the # of calls to the yield functions to check that other stages | |||
// have correct yielding behavior. | // have correct yielding behavior. | |||
virtual void prepareToYield() { } | virtual void prepareToYield() { } | |||
virtual void recoverFromYield() { } | virtual void recoverFromYield() { } | |||
virtual void invalidate(const DiskLoc& dl) { } | virtual void invalidate(const DiskLoc& dl) { } | |||
virtual PlanStageStats* getStats() { return NULL; } | ||||
/** | /** | |||
* Add a result to the back of the queue. work() goes through the queue. | * Add a result to the back of the queue. work() goes through the queue. | |||
* Either no data is returned (just a state), or... | * Either no data is returned (just a state), or... | |||
*/ | */ | |||
void pushBack(const PlanStage::StageState state); | void pushBack(const PlanStage::StageState state); | |||
/** | /** | |||
* ...data is returned (and we ADVANCED) | * ...data is returned (and we ADVANCED) | |||
*/ | */ | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
modifier_add_to_set.h | modifier_add_to_set.h | |||
---|---|---|---|---|
skipping to change at line 28 | skipping to change at line 28 | |||
#include <boost/scoped_ptr.hpp> | #include <boost/scoped_ptr.hpp> | |||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/bson/mutable/document.h" | #include "mongo/bson/mutable/document.h" | |||
#include "mongo/db/field_ref.h" | #include "mongo/db/field_ref.h" | |||
#include "mongo/db/ops/modifier_interface.h" | #include "mongo/db/ops/modifier_interface.h" | |||
namespace mongo { | namespace mongo { | |||
class LogBuilder; | ||||
class ModifierAddToSet : public ModifierInterface { | class ModifierAddToSet : public ModifierInterface { | |||
MONGO_DISALLOW_COPYING(ModifierAddToSet); | MONGO_DISALLOW_COPYING(ModifierAddToSet); | |||
public: | public: | |||
ModifierAddToSet(); | ModifierAddToSet(); | |||
virtual ~ModifierAddToSet(); | virtual ~ModifierAddToSet(); | |||
/** Goes over the array item(s) that are going to be set- unioned a nd converts them | /** Goes over the array item(s) that are going to be set- unioned a nd converts them | |||
* internally to a mutable bson. Both single and $each forms are s upported. Returns OK | * internally to a mutable bson. Both single and $each forms are s upported. Returns OK | |||
* if the item(s) are valid otherwise returns a status describing the error. | * if the item(s) are valid otherwise returns a status describing the error. | |||
*/ | */ | |||
virtual Status init(const BSONElement& modExpr); | virtual Status init(const BSONElement& modExpr, const Options& opts ); | |||
/** Decides which portion of the array items that are going to be s et-unioned to root's | /** Decides which portion of the array items that are going to be s et-unioned to root's | |||
* document and fills in 'execInfo' accordingly. Returns OK if the document has a | * document and fills in 'execInfo' accordingly. Returns OK if the document has a | |||
* valid array to set-union to, othwise returns a status describin g the error. | * valid array to set-union to, othwise returns a status describin g the error. | |||
*/ | */ | |||
virtual Status prepare(mutablebson::Element root, | virtual Status prepare(mutablebson::Element root, | |||
const StringData& matchedField, | const StringData& matchedField, | |||
ExecInfo* execInfo); | ExecInfo* execInfo); | |||
/** Updates the Element used in prepare with the effects of the $ad dToSet operation. */ | /** Updates the Element used in prepare with the effects of the $ad dToSet operation. */ | |||
virtual Status apply() const; | virtual Status apply() const; | |||
/** Converts the effects of this $addToSet into one or more equival ent $set operations. */ | /** Converts the effects of this $addToSet into one or more equival ent $set operations. */ | |||
virtual Status log(mutablebson::Element logRoot) const; | virtual Status log(LogBuilder* logBuilder) const; | |||
private: | private: | |||
// Access to each component of fieldName that's the target of this mod. | // Access to each component of fieldName that's the target of this mod. | |||
FieldRef _fieldRef; | FieldRef _fieldRef; | |||
// 0 or index for $-positional in _fieldRef. | // 0 or index for $-positional in _fieldRef. | |||
size_t _posDollar; | size_t _posDollar; | |||
// Array of values to be set-union'ed onto target. | // Array of values to be set-union'ed onto target. | |||
mutablebson::Document _valDoc; | mutablebson::Document _valDoc; | |||
End of changes. 3 change blocks. | ||||
2 lines changed or deleted | 4 lines changed or added | |||
modifier_bit.h | modifier_bit.h | |||
---|---|---|---|---|
skipping to change at line 21 | skipping to change at line 21 | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Lice nse | * You should have received a copy of the GNU Affero General Public Lice nse | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <boost/scoped_ptr.hpp> | #include <boost/scoped_ptr.hpp> | |||
#include <string> | #include <string> | |||
#include <vector> | ||||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/bson/mutable/element.h" | #include "mongo/bson/mutable/element.h" | |||
#include "mongo/db/field_ref.h" | #include "mongo/db/field_ref.h" | |||
#include "mongo/db/ops/modifier_interface.h" | #include "mongo/db/ops/modifier_interface.h" | |||
#include "mongo/util/safe_num.h" | #include "mongo/util/safe_num.h" | |||
namespace mongo { | namespace mongo { | |||
class LogBuilder; | ||||
class ModifierBit : public ModifierInterface { | class ModifierBit : public ModifierInterface { | |||
MONGO_DISALLOW_COPYING(ModifierBit); | MONGO_DISALLOW_COPYING(ModifierBit); | |||
public: | public: | |||
ModifierBit(); | ModifierBit(); | |||
virtual ~ModifierBit(); | virtual ~ModifierBit(); | |||
/** | /** | |||
* A 'modExpr' is a BSONElement {<fieldname>: <value>} coming from a $bit mod such as | * A 'modExpr' is a BSONElement {<fieldname>: <value>} coming from a $bit mod such as | |||
* {$bit: {<field: { [and|or] : <value>}}. init() extracts the fiel d name, the | * {$bit: {<field: { [and|or] : <value>}}. init() extracts the fiel d name, the | |||
* operation subtype, and the value to be assigned to it from 'modE xpr'. It returns OK | * operation subtype, and the value to be assigned to it from 'modE xpr'. It returns OK | |||
* if successful or a status describing the error. | * if successful or a status describing the error. | |||
*/ | */ | |||
virtual Status init(const BSONElement& modExpr); | virtual Status init(const BSONElement& modExpr, const Options& opts ); | |||
/** Validates the potential application of the init'ed mod to the g iven Element and | /** Validates the potential application of the init'ed mod to the g iven Element and | |||
* configures the internal state of the mod as necessary. | * configures the internal state of the mod as necessary. | |||
*/ | */ | |||
virtual Status prepare(mutablebson::Element root, | virtual Status prepare(mutablebson::Element root, | |||
const StringData& matchedField, | const StringData& matchedField, | |||
ExecInfo* execInfo); | ExecInfo* execInfo); | |||
/** Updates the Element used in prepare with the effects of the $bi t operation */ | /** Updates the Element used in prepare with the effects of the $bi t operation */ | |||
virtual Status apply() const; | virtual Status apply() const; | |||
/** Converts the effects of this $bit into an equivalent $set */ | /** Converts the effects of this $bit into an equivalent $set */ | |||
virtual Status log(mutablebson::Element logRoot) const; | virtual Status log(LogBuilder* logBuilder) const; | |||
private: | private: | |||
SafeNum apply(SafeNum value) const; | ||||
// Access to each component of fieldName that's the target of this mod. | // Access to each component of fieldName that's the target of this mod. | |||
FieldRef _fieldRef; | FieldRef _fieldRef; | |||
// 0 or index for $-positional in _fieldRef. | // 0 or index for $-positional in _fieldRef. | |||
size_t _posDollar; | size_t _posDollar; | |||
// Value to be $bit'ed onto target | ||||
SafeNum _val; | ||||
// The operator on SafeNum that we will invoke. | // The operator on SafeNum that we will invoke. | |||
SafeNum (SafeNum::* _op)(const SafeNum&) const; | typedef SafeNum (SafeNum::* SafeNumOp)(const SafeNum&) const; | |||
struct OpEntry { | ||||
SafeNum val; | ||||
SafeNumOp op; | ||||
}; | ||||
typedef std::vector<OpEntry> OpEntries; | ||||
OpEntries _ops; | ||||
struct PreparedState; | struct PreparedState; | |||
scoped_ptr<PreparedState> _preparedState; | scoped_ptr<PreparedState> _preparedState; | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 7 change blocks. | ||||
6 lines changed or deleted | 17 lines changed or added | |||
modifier_inc.h | modifier_inc.h | |||
---|---|---|---|---|
skipping to change at line 29 | skipping to change at line 29 | |||
#include <boost/scoped_ptr.hpp> | #include <boost/scoped_ptr.hpp> | |||
#include <string> | #include <string> | |||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/bson/mutable/element.h" | #include "mongo/bson/mutable/element.h" | |||
#include "mongo/db/field_ref.h" | #include "mongo/db/field_ref.h" | |||
#include "mongo/db/ops/modifier_interface.h" | #include "mongo/db/ops/modifier_interface.h" | |||
namespace mongo { | namespace mongo { | |||
class LogBuilder; | ||||
class ModifierInc : public ModifierInterface { | class ModifierInc : public ModifierInterface { | |||
MONGO_DISALLOW_COPYING(ModifierInc); | MONGO_DISALLOW_COPYING(ModifierInc); | |||
public: | public: | |||
ModifierInc(); | // TODO: This is a shortcut to implementing $mul by hijacking $inc. | |||
In the near future, | ||||
// we should consider either pulling $mul into its own operator, or | ||||
creating a general | ||||
// purpose "numeric binary op" operator. Potentially, that operator | ||||
could also subsume | ||||
// $bit (thought there are some subtleties, like that $bit can have | ||||
multiple | ||||
// operations, and doing so with arbirary math operations introduce | ||||
s potential | ||||
// associativity difficulties). At the very least, if this mechanis | ||||
m is retained, then | ||||
// this class should be renamed at some point away from ModifierInc | ||||
. | ||||
enum ModifierIncMode { | ||||
MODE_INC, | ||||
MODE_MUL | ||||
}; | ||||
ModifierInc(ModifierIncMode mode = MODE_INC); | ||||
virtual ~ModifierInc(); | virtual ~ModifierInc(); | |||
/** | /** | |||
* A 'modExpr' is a BSONElement {<fieldname>: <value>} coming from a $inc mod such as | * A 'modExpr' is a BSONElement {<fieldname>: <value>} coming from a $inc mod such as | |||
* {$inc: {<fieldname: <value>}}. init() extracts the field name an d the value to be | * {$inc: {<fieldname: <value>}}. init() extracts the field name an d the value to be | |||
* assigned to it from 'modExpr'. It returns OK if successful or a status describing | * assigned to it from 'modExpr'. It returns OK if successful or a status describing | |||
* the error. | * the error. | |||
*/ | */ | |||
virtual Status init(const BSONElement& modExpr); | virtual Status init(const BSONElement& modExpr, const Options& opts ); | |||
/** Evaluates the validity of applying $inc to the identified node, and computes | /** Evaluates the validity of applying $inc to the identified node, and computes | |||
* effects, handling upcasting and overflow as necessary. | * effects, handling upcasting and overflow as necessary. | |||
*/ | */ | |||
virtual Status prepare(mutablebson::Element root, | virtual Status prepare(mutablebson::Element root, | |||
const StringData& matchedField, | const StringData& matchedField, | |||
ExecInfo* execInfo); | ExecInfo* execInfo); | |||
/** Updates the node passed in prepare with the results of the $inc */ | /** Updates the node passed in prepare with the results of the $inc */ | |||
virtual Status apply() const; | virtual Status apply() const; | |||
/** Converts the result of the $inc into an equivalent $set under l ogRoot */ | /** Converts the result of the $inc into an equivalent $set under l ogRoot */ | |||
virtual Status log(mutablebson::Element logRoot) const; | virtual Status log(LogBuilder* logBuilder) const; | |||
private: | private: | |||
const ModifierIncMode _mode; | ||||
// Access to each component of fieldName that's the target of this mod. | // Access to each component of fieldName that's the target of this mod. | |||
FieldRef _fieldRef; | FieldRef _fieldRef; | |||
// 0 or index for $-positional in _fieldRef. | // 0 or index for $-positional in _fieldRef. | |||
size_t _posDollar; | size_t _posDollar; | |||
// Element of the $set expression. | // Element of the $set expression. | |||
SafeNum _val; | SafeNum _val; | |||
End of changes. 5 change blocks. | ||||
3 lines changed or deleted | 25 lines changed or added | |||
modifier_interface.h | modifier_interface.h | |||
---|---|---|---|---|
skipping to change at line 27 | skipping to change at line 27 | |||
#pragma once | #pragma once | |||
#include "mongo/base/status.h" | #include "mongo/base/status.h" | |||
#include "mongo/base/string_data.h" | #include "mongo/base/string_data.h" | |||
#include "mongo/bson/mutable/element.h" | #include "mongo/bson/mutable/element.h" | |||
#include "mongo/db/field_ref.h" | #include "mongo/db/field_ref.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
namespace mongo { | namespace mongo { | |||
class LogBuilder; | ||||
/** | /** | |||
* Abstract base class for update "modifiers" (a.k.a "$ operators"). To create a new | * Abstract base class for update "modifiers" (a.k.a "$ operators"). To create a new | |||
* operator, implement a new derived class. | * operator, implement a new derived class. | |||
* | * | |||
* A typical call sequence for the class is: | * A typical call sequence for the class is: | |||
* | * | |||
* + init() with the mod arguments | * + init() with the mod arguments | |||
* | * | |||
* + For each document that is being touched on that update, the foll owing methods are | * + For each document that is being touched on that update, the foll owing methods are | |||
* going to be called once for that document and in the order the c alls appear here. | * going to be called once for that document and in the order the c alls appear here. | |||
skipping to change at line 55 | skipping to change at line 57 | |||
* that particular order and therefore can keep and reuse state between these calls, when | * that particular order and therefore can keep and reuse state between these calls, when | |||
* appropriate. | * appropriate. | |||
* | * | |||
* TODO: | * TODO: | |||
* For a reference implementation, see modifier_identity.{h,cpp} used i n tests. | * For a reference implementation, see modifier_identity.{h,cpp} used i n tests. | |||
*/ | */ | |||
class ModifierInterface { | class ModifierInterface { | |||
public: | public: | |||
virtual ~ModifierInterface() { } | virtual ~ModifierInterface() { } | |||
struct Options; | ||||
/** | /** | |||
* Returns OK and extracts the parameters for this given mod from ' modExpr'. For | * Returns OK and extracts the parameters for this given mod from ' modExpr'. For | |||
* instance, for a $inc, extracts the increment value. The init() m ethod would be | * instance, for a $inc, extracts the increment value. The init() m ethod would be | |||
* called only once per operand, that is, if a { $inc: { a: 1, b: 1 } } is issued, | * called only once per operand, that is, if a { $inc: { a: 1, b: 1 } } is issued, | |||
* there would be one instance of the operator working on 'a' and o ne on 'b'. In each | * there would be one instance of the operator working on 'a' and o ne on 'b'. In each | |||
* case, init() would be called once with the respective bson eleme nt. | * case, init() would be called once with the respective bson eleme nt. | |||
* | * | |||
* If 'modExpr' is invalid, returns an error status with a reason d escription. | * If 'modExpr' is invalid, returns an error status with a reason d escription. | |||
* | * | |||
* Note: | * Note: | |||
* | * | |||
* + An operator may assume the modExpr passed here will be uncha nged throughout all | * + An operator may assume the modExpr passed here will be uncha nged throughout all | |||
* the mod object lifetime and also that the modExrp's lifetime exceeds the life | * the mod object lifetime and also that the modExrp's lifetime exceeds the life | |||
* time of this mod. Therefore, taking references to elements i nside modExpr is | * time of this mod. Therefore, taking references to elements i nside modExpr is | |||
* valid. | * valid. | |||
*/ | */ | |||
virtual Status init(const BSONElement& modExpr) = 0; | virtual Status init(const BSONElement& modExpr, const Options& opts ) = 0; | |||
/** | /** | |||
* Returns OK if it would be correct to apply this mod over the doc ument 'root' (e.g, if | * Returns OK if it would be correct to apply this mod over the doc ument 'root' (e.g, if | |||
* we're $inc-ing a field, is that field numeric in the current doc ?). | * we're $inc-ing a field, is that field numeric in the current doc ?). | |||
* | * | |||
* If the field this mod is targeted to contains a $-positional par ameter, that value | * If the field this mod is targeted to contains a $-positional par ameter, that value | |||
* can be bound with 'matchedField', passed by the caller. | * can be bound with 'matchedField', passed by the caller. | |||
* | * | |||
* In addition, the call also identifies which fields(s) of 'root' the mod is interested | * In addition, the call also identifies which fields(s) of 'root' the mod is interested | |||
* in changing (note that the modifier may want to add a field that 's not present in | * in changing (note that the modifier may want to add a field that 's not present in | |||
skipping to change at line 107 | skipping to change at line 110 | |||
* per operator. | * per operator. | |||
* | * | |||
* For this call to be issued, the call to 'prepareElem' must have necessarily turned | * For this call to be issued, the call to 'prepareElem' must have necessarily turned | |||
* off 'ExecInfo.noOp', ie this mod over this document is not a no- op. | * off 'ExecInfo.noOp', ie this mod over this document is not a no- op. | |||
* | * | |||
* If the mod could not be applied, returns an error status with a reason description. | * If the mod could not be applied, returns an error status with a reason description. | |||
*/ | */ | |||
virtual Status apply() const = 0 ; | virtual Status apply() const = 0 ; | |||
/** | /** | |||
* Returns OK and registers the result of this mod in 'logRoot', th | * Returns OK and records the result of this mod in the provided Lo | |||
e document that | gBuilder. The mod | |||
* would eventually become a log entry. The mod must have kept enou | * must have kept enough state to be able to produce the log record | |||
gh state to | (see idempotency | |||
* be able to produce the log record (see idempotency note below). | * note below). This call may be issued even if apply() was not. | |||
This call may be | ||||
* issued even if apply() was not. | ||||
* | * | |||
* If the mod could not be logged, returns an error status with a r eason description. | * If the mod could not be logged, returns an error status with a r eason description. | |||
* | * | |||
* Idempotency Note: | * Idempotency Note: | |||
* | * | |||
* + The modifier must log a mod that is idempotent, ie, applying it more than once | * + The modifier must log a mod that is idempotent, ie, applying it more than once | |||
* to a base collection would produce the same result as applyi ng it only once. For | * to a base collection would produce the same result as applyi ng it only once. For | |||
* example, a $inc can be switched to a $set for the resulting incremented value, | * example, a $inc can be switched to a $set for the resulting incremented value, | |||
* for logging purposes. An array based operator may check the contents of the | * for logging purposes. An array based operator may check the contents of the | |||
* array before operating on it. | * array before operating on it. | |||
*/ | */ | |||
virtual Status log(mutablebson::Element logRoot) const = 0; | virtual Status log(LogBuilder* logBuilder) const = 0; | |||
}; | ||||
/** | ||||
* Options used to control Modifier behavior | ||||
*/ | ||||
struct ModifierInterface::Options { | ||||
Options() : fromReplication(false), enforceOkForStorage(true) {} | ||||
Options(bool repl, bool ofs) : fromReplication(repl), enforceOkForS | ||||
torage(ofs) {} | ||||
static Options normal() { return Options(false, true); } | ||||
static Options fromRepl() { return Options(true, false); } | ||||
static Options unchecked() { return Options(false, false); } | ||||
bool fromReplication; | ||||
bool enforceOkForStorage; | ||||
}; | }; | |||
struct ModifierInterface::ExecInfo { | struct ModifierInterface::ExecInfo { | |||
static const int MAX_NUM_FIELDS = 2; | static const int MAX_NUM_FIELDS = 2; | |||
/** | /** | |||
* An update mod may specify that it wishes to the applied only if the context | * An update mod may specify that it wishes to the applied only if the context | |||
* of the update turns out a certain way. | * of the update turns out a certain way. | |||
*/ | */ | |||
enum UpdateContext { | enum UpdateContext { | |||
// This mod wants to be applied only if the update turns out to be an insert. | // This mod wants to be applied only if the update turns out to be an insert. | |||
INSERT_CONTEXT, | INSERT_CONTEXT, | |||
// This mod wants to be applied only if the update is not an in sert. | // This mod wants to be applied only if the update is not an in sert. | |||
UPDATE_CONTEXT, | UPDATE_CONTEXT, | |||
// This mod doesn't care if the update will be an update or an upsert. | // This mod doesn't care if the update will be an update or an upsert. | |||
ANY_CONTEXT | ANY_CONTEXT | |||
}; | }; | |||
ExecInfo() : inPlace(false), noOp(false), context(ANY_CONTEXT) { | ExecInfo() : noOp(false), context(ANY_CONTEXT) { | |||
for (int i = 0; i < MAX_NUM_FIELDS; i++) { | for (int i = 0; i < MAX_NUM_FIELDS; i++) { | |||
fieldRef[i] = NULL; | fieldRef[i] = NULL; | |||
} | } | |||
} | } | |||
// The fields of concern to the driver: no other op may modify the fields listed here. | // The fields of concern to the driver: no other op may modify the fields listed here. | |||
FieldRef* fieldRef[MAX_NUM_FIELDS]; // not owned here | FieldRef* fieldRef[MAX_NUM_FIELDS]; // not owned here | |||
bool inPlace; | ||||
bool noOp; | bool noOp; | |||
UpdateContext context; | UpdateContext context; | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 8 change blocks. | ||||
11 lines changed or deleted | 26 lines changed or added | |||
modifier_object_replace.h | modifier_object_replace.h | |||
---|---|---|---|---|
skipping to change at line 27 | skipping to change at line 27 | |||
#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/bson/mutable/element.h" | #include "mongo/bson/mutable/element.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/ops/modifier_interface.h" | #include "mongo/db/ops/modifier_interface.h" | |||
namespace mongo { | namespace mongo { | |||
class LogBuilder; | ||||
class ModifierObjectReplace : public ModifierInterface { | class ModifierObjectReplace : public ModifierInterface { | |||
MONGO_DISALLOW_COPYING(ModifierObjectReplace); | MONGO_DISALLOW_COPYING(ModifierObjectReplace); | |||
public: | public: | |||
ModifierObjectReplace(); | ModifierObjectReplace(); | |||
// | // | |||
// Modifier interface implementation | // Modifier interface implementation | |||
// | // | |||
virtual ~ModifierObjectReplace(); | virtual ~ModifierObjectReplace(); | |||
/** | /** | |||
* Returns true and takes the embedded object contained in 'modExpr ' to be the object | * Returns true and takes the embedded object contained in 'modExpr ' to be the object | |||
* we're replacing for. The field name of 'modExpr' is ignored. If 'modExpr' is in an | * we're replacing for. The field name of 'modExpr' is ignored. If 'modExpr' is in an | |||
* unexpected format or if it can't be parsed for some reason, retu rns an error status | * unexpected format or if it can't be parsed for some reason, retu rns an error status | |||
* describing the error. | * describing the error. | |||
*/ | */ | |||
virtual Status init(const BSONElement& modExpr); | virtual Status init(const BSONElement& modExpr, const Options& opts ); | |||
/** | /** | |||
* Registers the that 'root' is in the document that we want to ful ly replace. | * Registers the that 'root' is in the document that we want to ful ly replace. | |||
* prepare() returns OK and always fills 'execInfo' with false for inPlace and true for | * prepare() returns OK and always fills 'execInfo' with true for | |||
* noOp. | * noOp. | |||
*/ | */ | |||
virtual Status prepare(mutablebson::Element root, | virtual Status prepare(mutablebson::Element root, | |||
const StringData& matchedField, | const StringData& matchedField, | |||
ExecInfo* execInfo); | ExecInfo* execInfo); | |||
/** | /** | |||
* Replaces the document passed in prepare() for the object passed in init(). Returns | * Replaces the document passed in prepare() for the object passed in init(). Returns | |||
* OK if successful or a status describing the error. | * OK if successful or a status describing the error. | |||
*/ | */ | |||
virtual Status apply() const; | virtual Status apply() const; | |||
/** | /** | |||
* Adds a log entry to logRoot corresponding to full object replace ment. Returns OK if | * Adds a log entry to logRoot corresponding to full object replace ment. Returns OK if | |||
* successful or a status describing the error. | * successful or a status describing the error. | |||
*/ | */ | |||
virtual Status log(mutablebson::Element logRoot) const; | virtual Status log(LogBuilder* logBuilder) const; | |||
private: | private: | |||
// Object to replace with. | // Object to replace with. | |||
BSONObj _val; | BSONObj _val; | |||
// The document whose value needs to be replaced. This state is val id after a prepare() | // The document whose value needs to be replaced. This state is val id after a prepare() | |||
// was issued and until a log() is issued. The document this mod is being prepared | // was issued and until a log() is issued. The document this mod is being prepared | |||
// against must e live throughout all the calls. | // against must e live throughout all the calls. | |||
struct PreparedState; | struct PreparedState; | |||
End of changes. 4 change blocks. | ||||
3 lines changed or deleted | 5 lines changed or added | |||
modifier_pop.h | modifier_pop.h | |||
---|---|---|---|---|
skipping to change at line 30 | skipping to change at line 30 | |||
#include <string> | #include <string> | |||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/bson/mutable/element.h" | #include "mongo/bson/mutable/element.h" | |||
#include "mongo/db/field_ref.h" | #include "mongo/db/field_ref.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/ops/modifier_interface.h" | #include "mongo/db/ops/modifier_interface.h" | |||
namespace mongo { | namespace mongo { | |||
class LogBuilder; | ||||
class ModifierPop : public ModifierInterface { | class ModifierPop : public ModifierInterface { | |||
MONGO_DISALLOW_COPYING(ModifierPop); | MONGO_DISALLOW_COPYING(ModifierPop); | |||
public: | public: | |||
ModifierPop(); | ModifierPop(); | |||
virtual ~ModifierPop(); | virtual ~ModifierPop(); | |||
/** | /** | |||
* The format of this modifier ($pop) is {<fieldname>: <value>}. | * The format of this modifier ($pop) is {<fieldname>: <value>}. | |||
* If the value is number and greater than -1 then an element is re moved from the bottom, | * If the value is number and greater than -1 then an element is re moved from the bottom, | |||
* otherwise the top. Currently the value can be any anything but w e document | * otherwise the top. Currently the value can be any anything but w e document | |||
* the use of the numbers "1, -1" only. | * the use of the numbers "1, -1" only. | |||
* | * | |||
* Ex. $pop: {'a':1} will remove the last item from this array: [1, 2,3] -> [1,2] | * Ex. $pop: {'a':1} will remove the last item from this array: [1, 2,3] -> [1,2] | |||
*/ | */ | |||
virtual Status init(const BSONElement& modExpr); | virtual Status init(const BSONElement& modExpr, const Options& opts ); | |||
virtual Status prepare(mutablebson::Element root, | virtual Status prepare(mutablebson::Element root, | |||
const StringData& matchedField, | const StringData& matchedField, | |||
ExecInfo* execInfo); | ExecInfo* execInfo); | |||
virtual Status apply() const; | virtual Status apply() const; | |||
virtual Status log(mutablebson::Element logRoot) const; | virtual Status log(LogBuilder* logBuilder) const; | |||
private: | private: | |||
// Access to each component of fieldName that's the target of this mod. | // Access to each component of fieldName that's the target of this mod. | |||
FieldRef _fieldRef; | FieldRef _fieldRef; | |||
// 0 or index for $-positional in _fieldRef. | // 0 or index for $-positional in _fieldRef. | |||
size_t _positionalPathIndex; | size_t _positionalPathIndex; | |||
// element position to remove from | // element position to remove from | |||
End of changes. 3 change blocks. | ||||
2 lines changed or deleted | 4 lines changed or added | |||
modifier_pull.h | modifier_pull.h | |||
---|---|---|---|---|
skipping to change at line 38 | skipping to change at line 38 | |||
class MatchExpression; | class MatchExpression; | |||
class ModifierPull : public ModifierInterface { | class ModifierPull : public ModifierInterface { | |||
MONGO_DISALLOW_COPYING(ModifierPull); | MONGO_DISALLOW_COPYING(ModifierPull); | |||
public: | public: | |||
ModifierPull(); | ModifierPull(); | |||
virtual ~ModifierPull(); | virtual ~ModifierPull(); | |||
/** Evaluates the array items to be removed and the match expressio n. */ | /** Evaluates the array items to be removed and the match expressio n. */ | |||
virtual Status init(const BSONElement& modExpr); | virtual Status init(const BSONElement& modExpr, const Options& opts ); | |||
/** Decides which portion of the array items will be removed from t he provided element */ | /** Decides which portion of the array items will be removed from t he provided element */ | |||
virtual Status prepare(mutablebson::Element root, | virtual Status prepare(mutablebson::Element root, | |||
const StringData& matchedField, | const StringData& matchedField, | |||
ExecInfo* execInfo); | ExecInfo* execInfo); | |||
/** Updates the Element used in prepare with the effects of the $pu ll operation. */ | /** Updates the Element used in prepare with the effects of the $pu ll operation. */ | |||
virtual Status apply() const; | virtual Status apply() const; | |||
/** Converts the effects of this $pull into one or more equivalent $unset operations. */ | /** Converts the effects of this $pull into one or more equivalent $unset operations. */ | |||
virtual Status log(mutablebson::Element logRoot) const; | virtual Status log(LogBuilder* logBuilder) const; | |||
private: | private: | |||
bool isMatch(mutablebson::ConstElement element); | ||||
// Access to each component of fieldName that's the target of this mod. | // Access to each component of fieldName that's the target of this mod. | |||
FieldRef _fieldRef; | FieldRef _fieldRef; | |||
// 0 or index for $-positional in _fieldRef. | // 0 or index for $-positional in _fieldRef. | |||
size_t _posDollar; | size_t _posDollar; | |||
// A matcher built from the modExpr that we use to identify element | // If we aren't using a matcher, we just keep modExpr as _exprElt a | |||
s to remove. | nd use that to match | |||
// with woCompare. | ||||
BSONElement _exprElt; | ||||
// If we are using a matcher, we need to keep around a BSONObj for | ||||
it. | ||||
BSONObj _exprObj; | BSONObj _exprObj; | |||
scoped_ptr<MatchExpression> _matchExpression; | ||||
// If we are using the matcher, this is the match expression we bui | ||||
lt around _exprObj. | ||||
scoped_ptr<MatchExpression> _matchExpr; | ||||
bool _matcherOnPrimitive; | ||||
struct PreparedState; | struct PreparedState; | |||
scoped_ptr<PreparedState> _preparedState; | scoped_ptr<PreparedState> _preparedState; | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 5 change blocks. | ||||
5 lines changed or deleted | 16 lines changed or added | |||
modifier_pull_all.h | modifier_pull_all.h | |||
---|---|---|---|---|
skipping to change at line 30 | skipping to change at line 30 | |||
#include <string> | #include <string> | |||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/bson/mutable/element.h" | #include "mongo/bson/mutable/element.h" | |||
#include "mongo/db/field_ref.h" | #include "mongo/db/field_ref.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/ops/modifier_interface.h" | #include "mongo/db/ops/modifier_interface.h" | |||
namespace mongo { | namespace mongo { | |||
class LogBuilder; | ||||
class ModifierPullAll : public ModifierInterface { | class ModifierPullAll : public ModifierInterface { | |||
MONGO_DISALLOW_COPYING(ModifierPullAll); | MONGO_DISALLOW_COPYING(ModifierPullAll); | |||
public: | public: | |||
ModifierPullAll(); | ModifierPullAll(); | |||
virtual ~ModifierPullAll(); | virtual ~ModifierPullAll(); | |||
/** | /** | |||
* The modifier $pullAll takes an array of values to match literall y, and remove | * The modifier $pullAll takes an array of values to match literall y, and remove | |||
* | * | |||
* Ex. {$pullAll : {<field> : [<values>]}} | * Ex. {$pullAll : {<field> : [<values>]}} | |||
* {$pullAll :{ array : [1,2] } } will transform {array: [1,2,3]} - > {array: [3]} | * {$pullAll :{ array : [1,2] } } will transform {array: [1,2,3]} - > {array: [3]} | |||
*/ | */ | |||
virtual Status init(const BSONElement& modExpr); | virtual Status init(const BSONElement& modExpr, const Options& opts ); | |||
virtual Status prepare(mutablebson::Element root, | virtual Status prepare(mutablebson::Element root, | |||
const StringData& matchedField, | const StringData& matchedField, | |||
ExecInfo* execInfo); | ExecInfo* execInfo); | |||
virtual Status apply() const; | virtual Status apply() const; | |||
virtual Status log(mutablebson::Element logRoot) const; | virtual Status log(LogBuilder* logBuilder) const; | |||
private: | private: | |||
// Access to each component of fieldName that's the target of this mod. | // Access to each component of fieldName that's the target of this mod. | |||
FieldRef _fieldRef; | FieldRef _fieldRef; | |||
// 0 or index for $-positional in _fieldRef. | // 0 or index for $-positional in _fieldRef. | |||
size_t _positionalPathIndex; | size_t _positionalPathIndex; | |||
// The instance of the field in the provided doc. | // The instance of the field in the provided doc. | |||
End of changes. 3 change blocks. | ||||
2 lines changed or deleted | 4 lines changed or added | |||
modifier_push.h | modifier_push.h | |||
---|---|---|---|---|
skipping to change at line 31 | skipping to change at line 31 | |||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/bson/mutable/element.h" | #include "mongo/bson/mutable/element.h" | |||
#include "mongo/db/field_ref.h" | #include "mongo/db/field_ref.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/ops/modifier_interface.h" | #include "mongo/db/ops/modifier_interface.h" | |||
#include "mongo/db/ops/modifier_push_sorter.h" | #include "mongo/db/ops/modifier_push_sorter.h" | |||
namespace mongo { | namespace mongo { | |||
class LogBuilder; | ||||
class ModifierPush : public ModifierInterface { | class ModifierPush : public ModifierInterface { | |||
MONGO_DISALLOW_COPYING(ModifierPush); | MONGO_DISALLOW_COPYING(ModifierPush); | |||
public: | public: | |||
enum ModifierPushMode { PUSH_NORMAL, PUSH_ALL }; | enum ModifierPushMode { PUSH_NORMAL, PUSH_ALL }; | |||
explicit ModifierPush(ModifierPushMode mode= PUSH_NORMAL); | explicit ModifierPush(ModifierPushMode mode= PUSH_NORMAL); | |||
// | // | |||
// Modifier interface implementation | // Modifier interface implementation | |||
skipping to change at line 60 | skipping to change at line 62 | |||
* | * | |||
* There are currently a few restrictions concerning the clauses (b ut all can be | * There are currently a few restrictions concerning the clauses (b ut all can be | |||
* lifted): | * lifted): | |||
* + $slice can be negative only (ie, slicing from the recent end ) | * + $slice can be negative only (ie, slicing from the recent end ) | |||
* + $sort requires $slice to be present | * + $sort requires $slice to be present | |||
* + $sort can only sort objects (as opposed to basic types), so it only takes | * + $sort can only sort objects (as opposed to basic types), so it only takes | |||
* object as patterns | * object as patterns | |||
* + Because of the previous, $sort requires that the array being pushed to be made | * + Because of the previous, $sort requires that the array being pushed to be made | |||
* of objects | * of objects | |||
*/ | */ | |||
virtual Status init(const BSONElement& modExpr); | virtual Status init(const BSONElement& modExpr, const Options& opts ); | |||
/** | /** | |||
* Locates the array to be pushed into in the 'root', if it exists, and fills in | * Locates the array to be pushed into in the 'root', if it exists, and fills in | |||
* execInfo accordingly. Returns true if $push would succeed in 'ro ot', otherwise | * execInfo accordingly. Returns true if $push would succeed in 'ro ot', otherwise | |||
* return a status describing the error. | * return a status describing the error. | |||
* | * | |||
* Note that a $push is never in-place. The cost of checking if it is a no-op makes it | * Note that a $push is never in-place. The cost of checking if it is a no-op makes it | |||
* so that we don't do such check either. As such, execInfo is alwa ys filled with | * so that we don't do such check either. As such, execInfo is alwa ys filled with | |||
* 'false' for those two options. | * 'false' for those two options. | |||
*/ | */ | |||
skipping to change at line 86 | skipping to change at line 88 | |||
* Pushes the array into the prepared position and "sort/slice"s th e resulting array | * Pushes the array into the prepared position and "sort/slice"s th e resulting array | |||
* according to that call's instructions. | * according to that call's instructions. | |||
*/ | */ | |||
virtual Status apply() const; | virtual Status apply() const; | |||
/** | /** | |||
* $push currently logs the entire resulting array as a $set. | * $push currently logs the entire resulting array as a $set. | |||
* | * | |||
* TODO Log a positional $set in the array, whenever possible. | * TODO Log a positional $set in the array, whenever possible. | |||
*/ | */ | |||
virtual Status log(mutablebson::Element logRoot) const; | virtual Status log(LogBuilder* logBuilder) const; | |||
private: | private: | |||
// Access to each component of fieldName that's the target of this mod. | // Access to each component of fieldName that's the target of this mod. | |||
FieldRef _fieldRef; | FieldRef _fieldRef; | |||
// 0 or index for $-positional in _fieldRef. | // 0 or index for $-positional in _fieldRef. | |||
size_t _posDollar; | size_t _posDollar; | |||
// Clauses for the $push that are filled when the $each variation o f the command is used. | // Clauses for the $push that are filled when the $each variation o f the command is used. | |||
End of changes. 3 change blocks. | ||||
2 lines changed or deleted | 4 lines changed or added | |||
modifier_rename.h | modifier_rename.h | |||
---|---|---|---|---|
skipping to change at line 30 | skipping to change at line 30 | |||
#include <string> | #include <string> | |||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/bson/mutable/element.h" | #include "mongo/bson/mutable/element.h" | |||
#include "mongo/db/field_ref.h" | #include "mongo/db/field_ref.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/ops/modifier_interface.h" | #include "mongo/db/ops/modifier_interface.h" | |||
namespace mongo { | namespace mongo { | |||
class LogBuilder; | ||||
/** | /** | |||
* The $rename modifier moves the field from source to the destination t o perform | * The $rename modifier moves the field from source to the destination t o perform | |||
* the rename. | * the rename. | |||
* | * | |||
* Example: {$rename: {<source>:<dest>}} where both <source/dest> are fi eld names | * Example: {$rename: {<source>:<dest>}} where both <source/dest> are fi eld names | |||
* Start with {a:1} and applying a {$rename: {"a":"b"} } produces {b:1} | * Start with {a:1} and applying a {$rename: {"a":"b"} } produces {b:1} | |||
**/ | **/ | |||
class ModifierRename : public ModifierInterface { | class ModifierRename : public ModifierInterface { | |||
MONGO_DISALLOW_COPYING(ModifierRename); | MONGO_DISALLOW_COPYING(ModifierRename); | |||
public: | public: | |||
ModifierRename(); | ModifierRename(); | |||
virtual ~ModifierRename(); | virtual ~ModifierRename(); | |||
/** | /** | |||
* We will check that the to/from are valid paths; in prepare more validation is done | * We will check that the to/from are valid paths; in prepare more validation is done | |||
*/ | */ | |||
virtual Status init(const BSONElement& modExpr); | virtual Status init(const BSONElement& modExpr, const Options& opts ); | |||
/** | /** | |||
* In prepare we will ensure that all restrictions are met: | * In prepare we will ensure that all restrictions are met: | |||
* -- The 'from' field exists, and is valid, else it is a no-op | * -- The 'from' field exists, and is valid, else it is a no-op | |||
* -- The 'to' field is valid as a destination | * -- The 'to' field is valid as a destination | |||
* -- The 'to' field is not on the path (or the same path) as the 'from' field | * -- The 'to' field is not on the path (or the same path) as the 'from' field | |||
* -- Neither 'to' nor 'from' have an array ancestor | * -- Neither 'to' nor 'from' have an array ancestor | |||
*/ | */ | |||
virtual Status prepare(mutablebson::Element root, | virtual Status prepare(mutablebson::Element root, | |||
const StringData& matchedField, | const StringData& matchedField, | |||
skipping to change at line 71 | skipping to change at line 73 | |||
/** | /** | |||
* We will transform the document by first making sure that the 'to ' element | * We will transform the document by first making sure that the 'to ' element | |||
* is empty before moving the 'from' element there. | * is empty before moving the 'from' element there. | |||
*/ | */ | |||
virtual Status apply() const; | virtual Status apply() const; | |||
/** | /** | |||
* For the oplog entry we will generate an $unset on the 'from' fie ld, and $set for | * For the oplog entry we will generate an $unset on the 'from' fie ld, and $set for | |||
* the 'to' field. If no 'from' element is found then function will return immediately. | * the 'to' field. If no 'from' element is found then function will return immediately. | |||
*/ | */ | |||
virtual Status log(mutablebson::Element logRoot) const; | virtual Status log(LogBuilder* logBuilder) const; | |||
private: | private: | |||
// The source and destination fields | // The source and destination fields | |||
FieldRef _fromFieldRef; | FieldRef _fromFieldRef; | |||
FieldRef _toFieldRef; | FieldRef _toFieldRef; | |||
// The state carried over from prepare for apply/log | // The state carried over from prepare for apply/log | |||
struct PreparedState; | struct PreparedState; | |||
scoped_ptr<PreparedState> _preparedState; | scoped_ptr<PreparedState> _preparedState; | |||
End of changes. 3 change blocks. | ||||
2 lines changed or deleted | 4 lines changed or added | |||
modifier_set.h | modifier_set.h | |||
---|---|---|---|---|
skipping to change at line 30 | skipping to change at line 30 | |||
#include <string> | #include <string> | |||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/bson/mutable/element.h" | #include "mongo/bson/mutable/element.h" | |||
#include "mongo/db/field_ref.h" | #include "mongo/db/field_ref.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/ops/modifier_interface.h" | #include "mongo/db/ops/modifier_interface.h" | |||
namespace mongo { | namespace mongo { | |||
class LogBuilder; | ||||
class ModifierSet : public ModifierInterface { | class ModifierSet : public ModifierInterface { | |||
MONGO_DISALLOW_COPYING(ModifierSet); | MONGO_DISALLOW_COPYING(ModifierSet); | |||
public: | public: | |||
enum ModifierSetMode { SET_NORMAL, SET_ON_INSERT }; | enum ModifierSetMode { SET_NORMAL, SET_ON_INSERT }; | |||
explicit ModifierSet(ModifierSetMode mode = SET_NORMAL); | explicit ModifierSet(ModifierSetMode mode = SET_NORMAL); | |||
// | // | |||
// Modifier interface implementation | // Modifier interface implementation | |||
// | // | |||
virtual ~ModifierSet(); | virtual ~ModifierSet(); | |||
/** | /** | |||
* A 'modExpr' is a BSONElement {<fieldname>: <value>} coming from a $set mod such as | * A 'modExpr' is a BSONElement {<fieldname>: <value>} coming from a $set mod such as | |||
* {$set: {<fieldname: <value>}}. init() extracts the field name an d the value to be | * {$set: {<fieldname: <value>}}. init() extracts the field name an d the value to be | |||
* assigned to it from 'modExpr'. It returns OK if successful or a status describing | * assigned to it from 'modExpr'. It returns OK if successful or a status describing | |||
* the error. | * the error. | |||
*/ | */ | |||
virtual Status init(const BSONElement& modExpr); | virtual Status init(const BSONElement& modExpr, const Options& opts ); | |||
/** | /** | |||
* Looks up the field name in the sub-tree rooted at 'root', and bi nds, if necessary, | * Looks up the field name in the sub-tree rooted at 'root', and bi nds, if necessary, | |||
* the '$' field part using the 'matchedfield' number. prepare() re turns OK and | * the '$' field part using the 'matchedfield' number. prepare() re turns OK and | |||
* fills in 'execInfo' with information of whether this mod is a no -op on 'root' and | * fills in 'execInfo' with information of whether this mod is a no -op on 'root' and | |||
* whether it is an in-place candidate. Otherwise, returns a status describing the | * whether it is an in-place candidate. Otherwise, returns a status describing the | |||
* error. | * error. | |||
*/ | */ | |||
virtual Status prepare(mutablebson::Element root, | virtual Status prepare(mutablebson::Element root, | |||
const StringData& matchedField, | const StringData& matchedField, | |||
skipping to change at line 73 | skipping to change at line 75 | |||
/** | /** | |||
* Applies the prepared mod over the element 'root' specified in th e prepare() | * Applies the prepared mod over the element 'root' specified in th e prepare() | |||
* call. Returns OK if successful or a status describing the error. | * call. Returns OK if successful or a status describing the error. | |||
*/ | */ | |||
virtual Status apply() const; | virtual Status apply() const; | |||
/** | /** | |||
* Adds a log entry to logRoot corresponding to the operation appli ed here. Returns OK | * Adds a log entry to logRoot corresponding to the operation appli ed here. Returns OK | |||
* if successful or a status describing the error. | * if successful or a status describing the error. | |||
*/ | */ | |||
virtual Status log(mutablebson::Element logRoot) const; | virtual Status log(LogBuilder* logBuilder) const; | |||
private: | private: | |||
// Access to each component of fieldName that's the target of this mod. | // Access to each component of fieldName that's the target of this mod. | |||
FieldRef _fieldRef; | FieldRef _fieldRef; | |||
// 0 or index for $-positional in _fieldRef. | // 0 or index for $-positional in _fieldRef. | |||
size_t _posDollar; | size_t _posDollar; | |||
// If on 'on insert' mode, We'd like to apply this mod only if we'r e in a upsert. | // If on 'on insert' mode, We'd like to apply this mod only if we'r e in a upsert. | |||
const ModifierSetMode _setMode; | const ModifierSetMode _setMode; | |||
// Element of the $set expression. | // Element of the $set expression. | |||
BSONElement _val; | BSONElement _val; | |||
// See the class comments in modifier_interface.h | ||||
ModifierInterface::Options _modOptions; | ||||
// The instance of the field in the provided doc. This state is val id after a | // The instance of the field in the provided doc. This state is val id after a | |||
// prepare() was issued and until a log() is issued. The document t his mod is | // prepare() was issued and until a log() is issued. The document t his mod is | |||
// being prepared against must be live throughout all the calls. | // being prepared against must be live throughout all the calls. | |||
struct PreparedState; | struct PreparedState; | |||
scoped_ptr<PreparedState> _preparedState; | scoped_ptr<PreparedState> _preparedState; | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 4 change blocks. | ||||
2 lines changed or deleted | 7 lines changed or added | |||
modifier_table.h | modifier_table.h | |||
---|---|---|---|---|
skipping to change at line 28 | skipping to change at line 28 | |||
#include "mongo/db/ops/modifier_interface.h" | #include "mongo/db/ops/modifier_interface.h" | |||
namespace mongo { | namespace mongo { | |||
namespace modifiertable { | namespace modifiertable { | |||
enum ModifierType { | enum ModifierType { | |||
MOD_ADD_TO_SET, | MOD_ADD_TO_SET, | |||
MOD_BIT, | MOD_BIT, | |||
MOD_INC, | MOD_INC, | |||
MOD_MUL, | ||||
MOD_POP, | MOD_POP, | |||
MOD_PULL, | MOD_PULL, | |||
MOD_PULL_ALL, | MOD_PULL_ALL, | |||
MOD_PUSH, | MOD_PUSH, | |||
MOD_PUSH_ALL, | MOD_PUSH_ALL, | |||
MOD_SET, | MOD_SET, | |||
MOD_SET_ON_INSERT, | MOD_SET_ON_INSERT, | |||
MOD_RENAME, | MOD_RENAME, | |||
MOD_UNSET, | MOD_UNSET, | |||
MOD_UNKNOWN | MOD_UNKNOWN | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
modifier_unset.h | modifier_unset.h | |||
---|---|---|---|---|
skipping to change at line 30 | skipping to change at line 30 | |||
#include <string> | #include <string> | |||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/bson/mutable/element.h" | #include "mongo/bson/mutable/element.h" | |||
#include "mongo/db/field_ref.h" | #include "mongo/db/field_ref.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/ops/modifier_interface.h" | #include "mongo/db/ops/modifier_interface.h" | |||
namespace mongo { | namespace mongo { | |||
class LogBuilder; | ||||
class ModifierUnset : public ModifierInterface { | class ModifierUnset : public ModifierInterface { | |||
MONGO_DISALLOW_COPYING(ModifierUnset); | MONGO_DISALLOW_COPYING(ModifierUnset); | |||
public: | public: | |||
ModifierUnset(); | ModifierUnset(); | |||
// | // | |||
// Modifier interface implementation | // Modifier interface implementation | |||
// | // | |||
virtual ~ModifierUnset(); | virtual ~ModifierUnset(); | |||
/** | /** | |||
* A 'modExpr' is a BSONElement {<fieldname>: <value>} coming from a $set mod such as | * A 'modExpr' is a BSONElement {<fieldname>: <value>} coming from a $set mod such as | |||
* {$unset: {<fieldname: <value>}}. init() extracts the field name and the value to be | * {$unset: {<fieldname: <value>}}. init() extracts the field name and the value to be | |||
* assigned to it from 'modExpr'. It returns OK if successful or a status describing | * assigned to it from 'modExpr'. It returns OK if successful or a status describing | |||
* the error. | * the error. | |||
*/ | */ | |||
virtual Status init(const BSONElement& modExpr); | virtual Status init(const BSONElement& modExpr, const Options& opts ); | |||
/** | /** | |||
* Locates the field to be removed under the 'root' element, if it exist, and fills in | * Locates the field to be removed under the 'root' element, if it exist, and fills in | |||
* 'execInfo' accordingly. Return OK if successful or a status desc ribing the error. | * 'execInfo' accordingly. Return OK if successful or a status desc ribing the error. | |||
*/ | */ | |||
virtual Status prepare(mutablebson::Element root, | virtual Status prepare(mutablebson::Element root, | |||
const StringData& matchedField, | const StringData& matchedField, | |||
ExecInfo* execInfo); | ExecInfo* execInfo); | |||
/** | /** | |||
* Removes the found element from the document. If such element was inside an array, | * Removes the found element from the document. If such element was inside an array, | |||
* removal means setting that array position to 'null'. | * removal means setting that array position to 'null'. | |||
*/ | */ | |||
virtual Status apply() const; | virtual Status apply() const; | |||
/** | /** | |||
* Adds the exact $unset mod to the log. | * Adds the exact $unset mod to the log. | |||
*/ | */ | |||
virtual Status log(mutablebson::Element logRoot) const; | virtual Status log(LogBuilder* logBuilder) const; | |||
private: | private: | |||
// Access to each component of fieldName that's the target of this mod. | // Access to each component of fieldName that's the target of this mod. | |||
FieldRef _fieldRef; | FieldRef _fieldRef; | |||
// 0 or index for $-positional in _fieldRef. | // 0 or index for $-positional in _fieldRef. | |||
size_t _posDollar; | size_t _posDollar; | |||
// Element of the $set expression. | // Element of the $set expression. | |||
End of changes. 3 change blocks. | ||||
2 lines changed or deleted | 4 lines changed or added | |||
mutable_bson_test_utils.h | mutable_bson_test_utils.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 implied. | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* 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 <iosfwd> | #include <iosfwd> | |||
#include "mongo/bson/mutable/document.h" | ||||
namespace mongo { | namespace mongo { | |||
class BSONObj; | class BSONObj; | |||
namespace mutablebson { | namespace mutablebson { | |||
class ConstElement; | ||||
class Document; | ||||
// | // | |||
// Utilities for mutable BSON unit tests. | // Utilities for mutable BSON unit tests. | |||
// | // | |||
/** | /** | |||
* Catch all comparator between a mutable 'doc' and the expected BSON ' exp'. It compares | * Catch all comparator between a mutable 'doc' and the expected BSON ' exp'. It compares | |||
* (a) 'doc's generated object, (b) 'exp', the expected object, and (c) 'doc(exp)', a | * (a) 'doc's generated object, (b) 'exp', the expected object, and (c) 'doc(exp)', a | |||
* document created from 'exp'. Returns true if all three are equal, ot herwise false. | * document created from 'exp'. Returns true if all three are equal, ot herwise false. | |||
*/ | */ | |||
bool checkDoc(const Document& lhs, const BSONObj& rhs); | bool checkDoc(const Document& lhs, const BSONObj& rhs); | |||
skipping to change at line 57 | skipping to change at line 56 | |||
inline bool operator==(const Document& lhs, const BSONObj& rhs) { | inline bool operator==(const Document& lhs, const BSONObj& rhs) { | |||
return checkDoc(lhs, rhs); | return checkDoc(lhs, rhs); | |||
} | } | |||
/** Stream out a document; useful within ASSERT calls */ | /** Stream out a document; useful within ASSERT calls */ | |||
std::ostream& operator<<(std::ostream& stream, const Document& doc); | std::ostream& operator<<(std::ostream& stream, const Document& doc); | |||
/** Stream out an element; useful within ASSERT calls */ | /** Stream out an element; useful within ASSERT calls */ | |||
std::ostream& operator<<(std::ostream& stream, const ConstElement& elt) ; | std::ostream& operator<<(std::ostream& stream, const ConstElement& elt) ; | |||
/** Check that the two provided Documents are equivalent modulo field o | ||||
rdering in Object | ||||
* Elements. Leaf values are considered equal via woCompare. | ||||
*/ | ||||
bool checkEqualNoOrdering(const Document& lhs, const Document& rhs); | ||||
struct UnorderedWrapper_Obj { | ||||
inline explicit UnorderedWrapper_Obj(const BSONObj& o) | ||||
: obj(o) {} | ||||
const BSONObj& obj; | ||||
}; | ||||
struct UnorderedWrapper_Doc { | ||||
inline explicit UnorderedWrapper_Doc(const Document& d) | ||||
: doc(d) {} | ||||
const Document& doc; | ||||
}; | ||||
inline UnorderedWrapper_Doc unordered(const Document& d) { | ||||
return UnorderedWrapper_Doc(d); | ||||
} | ||||
inline UnorderedWrapper_Obj unordered(const BSONObj& o) { | ||||
return UnorderedWrapper_Obj(o); | ||||
} | ||||
inline bool operator==(const UnorderedWrapper_Doc& lhs, const Unordered | ||||
Wrapper_Doc& rhs) { | ||||
return checkEqualNoOrdering(lhs.doc, rhs.doc); | ||||
} | ||||
inline bool operator!=(const UnorderedWrapper_Doc& lhs, const Unordered | ||||
Wrapper_Doc& rhs) { | ||||
return !(lhs == rhs); | ||||
} | ||||
inline bool operator==(const UnorderedWrapper_Obj& lhs, const Unordered | ||||
Wrapper_Obj& rhs) { | ||||
const Document dlhs(lhs.obj); | ||||
const Document drhs(rhs.obj); | ||||
return checkEqualNoOrdering(dlhs, drhs); | ||||
} | ||||
inline bool operator!=(const UnorderedWrapper_Obj& lhs, const Unordered | ||||
Wrapper_Obj& rhs) { | ||||
return !(lhs == rhs); | ||||
} | ||||
inline bool operator==(const UnorderedWrapper_Doc& lhs, const Unordered | ||||
Wrapper_Obj& rhs) { | ||||
const Document drhs(rhs.obj); | ||||
return checkEqualNoOrdering(lhs.doc, drhs); | ||||
} | ||||
inline bool operator!=(const UnorderedWrapper_Doc& lhs, const Unordered | ||||
Wrapper_Obj& rhs) { | ||||
return !(lhs == rhs); | ||||
} | ||||
inline bool operator==(const UnorderedWrapper_Obj& lhs, const Unordered | ||||
Wrapper_Doc& rhs) { | ||||
const Document dlhs(lhs.obj); | ||||
return checkEqualNoOrdering(dlhs, rhs.doc); | ||||
} | ||||
inline bool operator!=(const UnorderedWrapper_Obj& lhs, const Unordered | ||||
Wrapper_Doc& rhs) { | ||||
return !(lhs == rhs); | ||||
} | ||||
std::ostream& operator<<(std::ostream& stream, const UnorderedWrapper_D | ||||
oc& uw_d); | ||||
std::ostream& operator<<(std::ostream& stream, const UnorderedWrapper_O | ||||
bj& uw_o); | ||||
} // namespace mutablebson | } // namespace mutablebson | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 3 change blocks. | ||||
3 lines changed or deleted | 77 lines changed or added | |||
namespace_details.h | namespace_details.h | |||
---|---|---|---|---|
skipping to change at line 26 | skipping to change at line 26 | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/pch.h" | |||
#include "mongo/db/d_concurrency.h" | #include "mongo/db/d_concurrency.h" | |||
#include "mongo/db/diskloc.h" | #include "mongo/db/diskloc.h" | |||
#include "mongo/db/index.h" | #include "mongo/db/index.h" | |||
#include "mongo/db/index_names.h" | #include "mongo/db/index_names.h" | |||
#include "mongo/db/index_set.h" | #include "mongo/db/index_set.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/mongommf.h" | #include "mongo/db/storage/durable_mapped_file.h" | |||
#include "mongo/db/namespace_string.h" | #include "mongo/db/namespace_string.h" | |||
#include "mongo/db/querypattern.h" | #include "mongo/db/querypattern.h" | |||
#include "mongo/db/storage/namespace.h" | #include "mongo/db/storage/namespace.h" | |||
#include "mongo/db/storage/namespace_index.h" | #include "mongo/db/storage/namespace_index.h" | |||
#include "mongo/platform/unordered_map.h" | #include "mongo/platform/unordered_map.h" | |||
namespace mongo { | namespace mongo { | |||
class Database; | class Database; | |||
/** @return true if a client can modify this namespace even though it i s under ".system." | /** @return true if a client can modify this namespace even though it i s under ".system." | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
namespace_index.h | namespace_index.h | |||
---|---|---|---|---|
skipping to change at line 69 | skipping to change at line 69 | |||
void getNamespaces( std::list<std::string>& tofill , bool onlyColle ctions = true ) const; | void getNamespaces( std::list<std::string>& tofill , bool onlyColle ctions = true ) const; | |||
boost::filesystem::path path() const; | boost::filesystem::path path() const; | |||
unsigned long long fileLength() const { return _f.length(); } | unsigned long long fileLength() const { return _f.length(); } | |||
private: | private: | |||
void _init(); | void _init(); | |||
void maybeMkdir() const; | void maybeMkdir() const; | |||
MongoMMF _f; | DurableMappedFile _f; | |||
HashTable<Namespace,NamespaceDetails> *_ht; | HashTable<Namespace,NamespaceDetails> *_ht; | |||
std::string _dir; | std::string _dir; | |||
std::string _database; | std::string _database; | |||
}; | }; | |||
} | } | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
namespace_string.h | namespace_string.h | |||
---|---|---|---|---|
skipping to change at line 53 | skipping to change at line 53 | |||
StringData coll() const; | StringData coll() const; | |||
const string& ns() const { return _ns; } | const string& ns() const { return _ns; } | |||
operator string() const { return _ns; } | operator string() const { return _ns; } | |||
string toString() const { return _ns; } | string toString() const { return _ns; } | |||
size_t size() const { return _ns.size(); } | size_t size() const { return _ns.size(); } | |||
bool isSystem() const { return coll().startsWith( "system." ); } | bool isSystem() const { return coll().startsWith( "system." ); } | |||
bool isConfigDB() const { return db() == "config"; } | ||||
bool isCommand() const { return coll() == "$cmd"; } | bool isCommand() const { return coll() == "$cmd"; } | |||
bool isSpecialCommand() const { return coll().startsWith("$cmd.sys" ); } | ||||
/** | /** | |||
* @return true if the namespace is valid. Special namespaces for i nternal use are considered as valid. | * @return true if the namespace is valid. Special namespaces for i nternal use are considered as valid. | |||
*/ | */ | |||
bool isValid() const { return validDBName( db() ) && !coll().empty( ); } | bool isValid() const { return validDBName( db() ) && !coll().empty( ); } | |||
bool operator==( const string& nsIn ) const { return nsIn == _ns; } | bool operator==( const string& nsIn ) const { return nsIn == _ns; } | |||
bool operator==( const NamespaceString& nsIn ) const { return nsIn. _ns == _ns; } | bool operator==( const NamespaceString& nsIn ) const { return nsIn. _ns == _ns; } | |||
bool operator!=( const string& nsIn ) const { return nsIn != _ns; } | bool operator!=( const string& nsIn ) const { return nsIn != _ns; } | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 2 lines changed or added | |||
oplogreader.h | oplogreader.h | |||
---|---|---|---|---|
skipping to change at line 34 | skipping to change at line 34 | |||
namespace mongo { | namespace mongo { | |||
/* started abstracting out the querying of the primary/master's oplog | /* started abstracting out the querying of the primary/master's oplog | |||
still fairly awkward but a start. | still fairly awkward but a start. | |||
*/ | */ | |||
class OplogReader { | class OplogReader { | |||
shared_ptr<DBClientConnection> _conn; | shared_ptr<DBClientConnection> _conn; | |||
shared_ptr<DBClientCursor> cursor; | shared_ptr<DBClientCursor> cursor; | |||
bool _doHandshake; | ||||
int _tailingQueryOptions; | int _tailingQueryOptions; | |||
public: | public: | |||
OplogReader( bool doHandshake = true ); | OplogReader(); | |||
~OplogReader() { } | ~OplogReader() { } | |||
void resetCursor() { cursor.reset(); } | void resetCursor() { cursor.reset(); } | |||
void resetConnection() { | void resetConnection() { | |||
cursor.reset(); | cursor.reset(); | |||
_conn.reset(); | _conn.reset(); | |||
} | } | |||
DBClientConnection* conn() { return _conn.get(); } | DBClientConnection* conn() { return _conn.get(); } | |||
BSONObj findOne(const char *ns, const Query& q) { | BSONObj findOne(const char *ns, const Query& q) { | |||
return conn()->findOne(ns, q, 0, QueryOption_SlaveOk); | return conn()->findOne(ns, q, 0, QueryOption_SlaveOk); | |||
} | } | |||
BSONObj getLastOp(const char *ns) { | BSONObj getLastOp(const char *ns) { | |||
return findOne(ns, Query().sort(reverseNaturalObj)); | return findOne(ns, Query().sort(reverseNaturalObj)); | |||
} | } | |||
/* SO_TIMEOUT (send/recv time out) for our DBClientConnections */ | ||||
static const int tcp_timeout = 30; | ||||
/* ok to call if already connected */ | /* ok to call if already connected */ | |||
bool connect(const std::string& hostname); | bool connect(const std::string& hostname); | |||
bool connect(const BSONObj& rid, const int from, const string& to); | bool connect(const std::string& hostname, const BSONObj& me); | |||
bool connect(const mongo::OID& rid, const int from, const string& t | ||||
o); | ||||
void tailCheck() { | void tailCheck() { | |||
if( cursor.get() && cursor->isDead() ) { | if( cursor.get() && cursor->isDead() ) { | |||
log() << "repl: old cursor isDead, will initiate a new one" << endl; | log() << "repl: old cursor isDead, will initiate a new one" << endl; | |||
resetCursor(); | resetCursor(); | |||
} | } | |||
} | } | |||
bool haveCursor() { return cursor.get() != 0; } | bool haveCursor() { return cursor.get() != 0; } | |||
skipping to change at line 139 | skipping to change at line 143 | |||
if( cursor.get() ) | if( cursor.get() ) | |||
cursor->peek(v,n); | cursor->peek(v,n); | |||
} | } | |||
BSONObj nextSafe() { return cursor->nextSafe(); } | BSONObj nextSafe() { return cursor->nextSafe(); } | |||
BSONObj next() { return cursor->next(); } | BSONObj next() { return cursor->next(); } | |||
void putBack(BSONObj op) { cursor->putBack(op); } | void putBack(BSONObj op) { cursor->putBack(op); } | |||
private: | private: | |||
/** @return true iff connection was successful */ | /** @return true iff connection was successful */ | |||
bool commonConnect(const string& hostName); | bool commonConnect(const string& hostName); | |||
bool passthroughHandshake(const BSONObj& rid, const int f); | bool passthroughHandshake(const mongo::OID& rid, const int f); | |||
}; | }; | |||
} | } | |||
End of changes. 5 change blocks. | ||||
4 lines changed or deleted | 9 lines changed or added | |||
optime.h | optime.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. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <boost/thread/condition.hpp> | #include <boost/thread/condition.hpp> | |||
#include <iostream> | #include <iostream> | |||
#include <sstream> | #include <sstream> | |||
#include "mongo/bson/util/misc.h" // time_t_to_String | ||||
#include "mongo/util/assert_util.h" | #include "mongo/util/assert_util.h" | |||
#include "mongo/util/concurrency/mutex.h" | #include "mongo/util/concurrency/mutex.h" | |||
#include "mongo/util/time_support.h" | ||||
namespace mongo { | namespace mongo { | |||
struct ClockSkewException : public DBException { | struct ClockSkewException : public DBException { | |||
ClockSkewException() : DBException( "clock skew exception" , 20001 ) {} | ClockSkewException() : DBException( "clock skew exception" , 20001 ) {} | |||
}; | }; | |||
/* replsets used to use RSOpTime. | /* replsets used to use RSOpTime. | |||
M/S uses OpTime. | M/S uses OpTime. | |||
But this is useable from both. | But this is useable from both. | |||
skipping to change at line 114 | skipping to change at line 114 | |||
unsigned long long asDate() const { | unsigned long long asDate() const { | |||
return reinterpret_cast<const unsigned long long*>(&i)[0]; | return reinterpret_cast<const unsigned long long*>(&i)[0]; | |||
} | } | |||
long long asLL() const { | long long asLL() const { | |||
return reinterpret_cast<const long long*>(&i)[0]; | return reinterpret_cast<const long long*>(&i)[0]; | |||
} | } | |||
bool isNull() const { return secs == 0; } | bool isNull() const { return secs == 0; } | |||
string toStringLong() const { | string toStringLong() const { | |||
char buf[64]; | ||||
time_t_to_String(secs, buf); | ||||
std::stringstream ss; | std::stringstream ss; | |||
ss << time_t_to_String_short(secs) << ' '; | ss << time_t_to_String_short(secs) << ' '; | |||
ss << std::hex << secs << ':' << i; | ss << std::hex << secs << ':' << i; | |||
return ss.str(); | return ss.str(); | |||
} | } | |||
string toStringPretty() const { | string toStringPretty() const { | |||
std::stringstream ss; | std::stringstream ss; | |||
ss << time_t_to_String_short(secs) << ':' << std::hex << i; | ss << time_t_to_String_short(secs) << ':' << std::hex << i; | |||
return ss.str(); | return ss.str(); | |||
End of changes. 3 change blocks. | ||||
3 lines changed or deleted | 1 lines changed or added | |||
or.h | or.h | |||
---|---|---|---|---|
skipping to change at line 20 | skipping to change at line 20 | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Lice nse | * You should have received a copy of the GNU Affero General Public Lice nse | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/db/diskloc.h" | #include "mongo/db/diskloc.h" | |||
#include "mongo/db/jsobj.h" | ||||
#include "mongo/db/matcher.h" | ||||
#include "mongo/db/exec/plan_stage.h" | #include "mongo/db/exec/plan_stage.h" | |||
#include "mongo/db/jsobj.h" | ||||
#include "mongo/db/matcher/expression.h" | ||||
#include "mongo/platform/unordered_set.h" | #include "mongo/platform/unordered_set.h" | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* This stage outputs the union of its children. It optionally dedupli cates on DiskLoc. | * This stage outputs the union of its children. It optionally dedupli cates on DiskLoc. | |||
* | * | |||
* Preconditions: Valid DiskLoc. | * Preconditions: Valid DiskLoc. | |||
* | * | |||
* If we're deduping, we may fail to dedup any invalidated DiskLoc prop erly. | * If we're deduping, we may fail to dedup any invalidated DiskLoc prop erly. | |||
*/ | */ | |||
class OrStage : public PlanStage { | class OrStage : public PlanStage { | |||
public: | public: | |||
OrStage(WorkingSet* ws, bool dedup, Matcher* matcher); | OrStage(WorkingSet* ws, bool dedup, const MatchExpression* filter); | |||
virtual ~OrStage(); | virtual ~OrStage(); | |||
void addChild(PlanStage* child); | void addChild(PlanStage* child); | |||
virtual bool isEOF(); | virtual bool isEOF(); | |||
virtual StageState work(WorkingSetID* out); | virtual StageState work(WorkingSetID* out); | |||
virtual void prepareToYield(); | virtual void prepareToYield(); | |||
virtual void recoverFromYield(); | virtual void recoverFromYield(); | |||
virtual void invalidate(const DiskLoc& dl); | virtual void invalidate(const DiskLoc& dl); | |||
virtual PlanStageStats* getStats(); | ||||
private: | private: | |||
// Not owned by us. | // Not owned by us. | |||
WorkingSet* _ws; | WorkingSet* _ws; | |||
scoped_ptr<Matcher> _matcher; | // The filter is not owned by us. | |||
const MatchExpression* _filter; | ||||
// Owned by us. | // Owned by us. | |||
vector<PlanStage*> _children; | vector<PlanStage*> _children; | |||
// Which of _children are we calling work(...) on now? | // Which of _children are we calling work(...) on now? | |||
size_t _currentChild; | size_t _currentChild; | |||
// True if we dedup on DiskLoc, false otherwise. | // True if we dedup on DiskLoc, false otherwise. | |||
bool _dedup; | bool _dedup; | |||
// Which DiskLocs have we returned? | // Which DiskLocs have we returned? | |||
unordered_set<DiskLoc, DiskLoc::Hasher> _seen; | unordered_set<DiskLoc, DiskLoc::Hasher> _seen; | |||
// Stats | ||||
CommonStats _commonStats; | ||||
OrStats _specificStats; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 6 change blocks. | ||||
4 lines changed or deleted | 11 lines changed or added | |||
owned_pointer_vector.h | owned_pointer_vector.h | |||
---|---|---|---|---|
skipping to change at line 37 | skipping to change at line 37 | |||
* NOTE that an OwnedPointerVector<T> wraps an std::vector<T*>. | * NOTE that an OwnedPointerVector<T> wraps an std::vector<T*>. | |||
*/ | */ | |||
template<class T> | template<class T> | |||
class OwnedPointerVector { | class OwnedPointerVector { | |||
MONGO_DISALLOW_COPYING(OwnedPointerVector); | MONGO_DISALLOW_COPYING(OwnedPointerVector); | |||
public: | public: | |||
OwnedPointerVector(); | OwnedPointerVector(); | |||
~OwnedPointerVector(); | ~OwnedPointerVector(); | |||
typedef typename std::vector<T*>::const_iterator const_iterator; | ||||
typedef typename std::vector<T*>::const_reverse_iterator const_reve | ||||
rse_iterator; | ||||
/** Access the vector. */ | /** Access the vector. */ | |||
const std::vector<T*>& vector() const { return _vector; } | const std::vector<T*>& vector() const { return _vector; } | |||
std::vector<T*>& mutableVector() { return _vector; } | std::vector<T*>& mutableVector() { return _vector; } | |||
std::size_t size() const { return _vector.size(); } | ||||
bool empty() const { return _vector.empty(); } | ||||
const_iterator begin() const { return _vector.begin(); } | ||||
const_reverse_iterator rbegin() const { return _vector.rbegin(); } | ||||
const_iterator end() const { return _vector.end(); } | ||||
const_reverse_iterator rend() const { return _vector.rend(); } | ||||
void clear(); | void clear(); | |||
private: | private: | |||
std::vector<T*> _vector; | std::vector<T*> _vector; | |||
}; | }; | |||
template<class T> | template<class T> | |||
OwnedPointerVector<T>::OwnedPointerVector() { | OwnedPointerVector<T>::OwnedPointerVector() { | |||
} | } | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 12 lines changed or added | |||
parsed_query.h | parsed_query.h | |||
---|---|---|---|---|
// DEPRECATED | ||||
/* Copyright 2009 10gen Inc. | /* Copyright 2009 10gen Inc. | |||
* | * | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | * You may obtain a copy of the License at | |||
* | * | |||
* http://www.apache.org/licenses/LICENSE-2.0 | * http://www.apache.org/licenses/LICENSE-2.0 | |||
* | * | |||
* Unless required by applicable law or agreed to in writing, software | * Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | * distributed under the License is distributed on an "AS IS" BASIS, | |||
skipping to change at line 68 | skipping to change at line 69 | |||
bool isExplain() const { return _explain; } | bool isExplain() const { return _explain; } | |||
bool isSnapshot() const { return _snapshot; } | bool isSnapshot() const { return _snapshot; } | |||
bool returnKey() const { return _returnKey; } | bool returnKey() const { return _returnKey; } | |||
bool showDiskLoc() const { return _showDiskLoc; } | bool showDiskLoc() const { return _showDiskLoc; } | |||
const BSONObj& getMin() const { return _min; } | const BSONObj& getMin() const { return _min; } | |||
const BSONObj& getMax() const { return _max; } | const BSONObj& getMax() const { return _max; } | |||
const BSONObj& getOrder() const { return _order; } | const BSONObj& getOrder() const { return _order; } | |||
const BSONObj& getHint() const { return _hint; } | const BSONObj& getHint() const { return _hint; } | |||
int getMaxScan() const { return _maxScan; } | int getMaxScan() const { return _maxScan; } | |||
int getMaxTimeMS() const { return _maxTimeMS; } | ||||
bool couldBeCommand() const; | ||||
bool hasIndexSpecifier() const; | bool hasIndexSpecifier() const; | |||
/* if ntoreturn is zero, we return up to 101 objects. on the subse quent getmore, there | /* if ntoreturn is zero, we return up to 101 objects. on the subse quent getmore, there | |||
is only a size limit. The idea is that on a find() where one does n't use much results, | is only a size limit. The idea is that on a find() where one does n't use much results, | |||
we don't return much, but once getmore kicks in, we start pushing significant quantities. | we don't return much, but once getmore kicks in, we start pushing significant quantities. | |||
The n limit (vs. size) is important when someone fetches only one small field from big | The n limit (vs. size) is important when someone fetches only one small field from big | |||
objects, which causes massive scanning server-side. | objects, which causes massive scanning server-side. | |||
*/ | */ | |||
skipping to change at line 112 | skipping to change at line 112 | |||
bool _wantMore; | bool _wantMore; | |||
bool _explain; | bool _explain; | |||
bool _snapshot; | bool _snapshot; | |||
bool _returnKey; | bool _returnKey; | |||
bool _showDiskLoc; | bool _showDiskLoc; | |||
bool _hasReadPref; | bool _hasReadPref; | |||
BSONObj _min; | BSONObj _min; | |||
BSONObj _max; | BSONObj _max; | |||
BSONObj _hint; | BSONObj _hint; | |||
int _maxScan; | int _maxScan; | |||
int _maxTimeMS; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 3 change blocks. | ||||
2 lines changed or deleted | 3 lines changed or added | |||
path_support.h | path_support.h | |||
---|---|---|---|---|
skipping to change at line 67 | skipping to change at line 67 | |||
* 'a.b.c' is a viable path in {a: {b: {c: 1}}} | * 'a.b.c' is a viable path in {a: {b: {c: 1}}} | |||
* 'a.b.c' is a viable path in {a: {b: {c: {d: 1}}}} | * 'a.b.c' is a viable path in {a: {b: {c: {d: 1}}}} | |||
* 'a.b.c' is NOT a viable path in {a: {b: 1}}, because b would h ave changed types | * 'a.b.c' is NOT a viable path in {a: {b: 1}}, because b would h ave changed types | |||
* 'a.0.b' is a viable path in {a: [{b: 1}, {c: 1}]} | * 'a.0.b' is a viable path in {a: [{b: 1}, {c: 1}]} | |||
* 'a.0.b' is a viable path in {a: {"0": {b: 1}}} | * 'a.0.b' is a viable path in {a: {"0": {b: 1}}} | |||
* 'a.0.b' is NOT a viable path in {a: 1}, because a would have c hanged types | * 'a.0.b' is NOT a viable path in {a: 1}, because a would have c hanged types | |||
* 'a.5.b' is a viable path in in {a: []} (padding would occur) | * 'a.5.b' is a viable path in in {a: []} (padding would occur) | |||
*/ | */ | |||
Status findLongestPrefix(const FieldRef& prefix, | Status findLongestPrefix(const FieldRef& prefix, | |||
mutablebson::Element root, | mutablebson::Element root, | |||
int32_t* idxFound, | size_t* idxFound, | |||
mutablebson::Element* elemFound); | mutablebson::Element* elemFound); | |||
/** | /** | |||
* Creates the parts 'prefix[idxRoot]', 'prefix[idxRoot+1]', ..., | * Creates the parts 'prefix[idxRoot]', 'prefix[idxRoot+1]', ..., | |||
* 'prefix[<numParts>-1]' under 'elemFound' and adds 'newElem' as a child of that | * 'prefix[<numParts>-1]' under 'elemFound' and adds 'newElem' as a child of that | |||
* path. Returns OK, if successful, or an error code describing why not, otherwise. | * path. Returns OK, if successful, or an error code describing why not, otherwise. | |||
* | * | |||
* createPathAt is designed to work with 'findLongestPrefix' in tha t it can create the | * createPathAt is designed to work with 'findLongestPrefix' in tha t it can create the | |||
* field parts in 'prefix' that are missing from a given document. 'elemFound' points | * field parts in 'prefix' that are missing from a given document. 'elemFound' points | |||
* to the element in the doc that is the parent of prefix[idxRoot]. | * to the element in the doc that is the parent of prefix[idxRoot]. | |||
*/ | */ | |||
Status createPathAt(const FieldRef& prefix, | Status createPathAt(const FieldRef& prefix, | |||
int32_t idxRoot, | size_t idxRoot, | |||
mutablebson::Element elemFound, | mutablebson::Element elemFound, | |||
mutablebson::Element newElem); | mutablebson::Element newElem); | |||
} // namespace pathsupport | } // namespace pathsupport | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
pdfile.h | pdfile.h | |||
---|---|---|---|---|
skipping to change at line 29 | skipping to change at line 29 | |||
Files: | Files: | |||
database.ns - namespace index | database.ns - namespace index | |||
database.1 - data files | database.1 - data files | |||
database.2 | database.2 | |||
... | ... | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/db/client.h" | #include "mongo/db/client.h" | |||
#include "mongo/db/cursor.h" | ||||
#include "mongo/db/database.h" | ||||
#include "mongo/db/diskloc.h" | #include "mongo/db/diskloc.h" | |||
#include "mongo/db/jsobjmanipulator.h" | #include "mongo/db/jsobjmanipulator.h" | |||
#include "mongo/db/memconcept.h" | #include "mongo/db/memconcept.h" | |||
#include "mongo/db/mongommf.h" | #include "mongo/db/storage/data_file.h" | |||
#include "mongo/db/storage/durable_mapped_file.h" | ||||
#include "mongo/db/storage/extent.h" | ||||
#include "mongo/db/namespace_details-inl.h" | #include "mongo/db/namespace_details-inl.h" | |||
#include "mongo/db/namespace_string.h" | #include "mongo/db/namespace_string.h" | |||
#include "mongo/db/pdfile_version.h" | #include "mongo/db/pdfile_version.h" | |||
#include "mongo/platform/cstdint.h" | #include "mongo/platform/cstdint.h" | |||
#include "mongo/util/log.h" | #include "mongo/util/log.h" | |||
#include "mongo/util/mmap.h" | #include "mongo/util/mmap.h" | |||
namespace mongo { | namespace mongo { | |||
class Cursor; | class Cursor; | |||
skipping to change at line 64 | skipping to change at line 68 | |||
/* 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); | |||
shared_ptr<Cursor> findTableScan(const char *ns, const BSONObj& order, const DiskLoc &startLoc=DiskLoc()); | shared_ptr<Cursor> findTableScan(const char *ns, const BSONObj& order, const DiskLoc &startLoc=DiskLoc()); | |||
bool isValidNS( const StringData& ns ); | bool isValidNS( const StringData& ns ); | |||
/*--------------------------------------------------------------------- */ | /*--------------------------------------------------------------------- */ | |||
class MongoDataFile { | ||||
friend class DataFileMgr; | ||||
friend class BasicCursor; | ||||
public: | ||||
MongoDataFile(int fn) : _mb(0), fileNo(fn) { } | ||||
/** @return true if found and opened. if uninitialized (prealloc on | ||||
ly) does not open. */ | ||||
bool openExisting( const char *filename ); | ||||
/** creates if DNE */ | ||||
void open(const char *filename, int requestedDataSize = 0, bool pre | ||||
allocateOnly = false); | ||||
/* allocate a new extent from this datafile. | ||||
@param capped - true if capped collection | ||||
@param loops is our recursion check variable - you want to pass | ||||
in zero | ||||
*/ | ||||
Extent* createExtent(const char *ns, int approxSize, bool capped = | ||||
false, int loops = 0); | ||||
DataFileHeader *getHeader() { return header(); } | ||||
HANDLE getFd() { return mmf.getFd(); } | ||||
unsigned long long length() const { return mmf.length(); } | ||||
/* return max size an extent may be */ | ||||
static int maxSize(); | ||||
/** fsync */ | ||||
void flush( bool sync ); | ||||
/** only use fore debugging */ | ||||
Extent* debug_getExtent(DiskLoc loc) { return _getExtent( loc ); } | ||||
private: | ||||
void badOfs(int) const; | ||||
void badOfs2(int) const; | ||||
int defaultSize( const char *filename ) const; | ||||
Extent* getExtent(DiskLoc loc) const; | ||||
Extent* _getExtent(DiskLoc loc) const; | ||||
Record* recordAt(DiskLoc dl) const; | ||||
void grow(DiskLoc dl, int size); | ||||
char* p() const { return (char *) _mb; } | ||||
DataFileHeader* header() { return (DataFileHeader*) _mb; } | ||||
MongoMMF mmf; | ||||
void *_mb; // the memory mapped view | ||||
int fileNo; | ||||
}; | ||||
class DataFileMgr { | class DataFileMgr { | |||
friend class BasicCursor; | friend class BasicCursor; | |||
public: | public: | |||
DataFileMgr(); | 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 */ | |||
skipping to change at line 195 | skipping to change at line 151 | |||
* NB: 'precalced' is accessed from fastBuildIndex(), which is call ed from insert-related | * 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 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 | * methods, which assume 'precalced' will not change while in the i nsert method. This | |||
* should likely be refactored so theDataFileMgr takes full respons ibility. | * should likely be refactored so theDataFileMgr takes full respons ibility. | |||
*/ | */ | |||
SortPhaseOne* getPrecalced() const; | SortPhaseOne* getPrecalced() const; | |||
void setPrecalced(SortPhaseOne* precalced); | void setPrecalced(SortPhaseOne* precalced); | |||
mongo::mutex _precalcedMutex; | mongo::mutex _precalcedMutex; | |||
private: | private: | |||
vector<MongoDataFile *> files; | vector<DataFile *> files; | |||
SortPhaseOne* _precalced; | SortPhaseOne* _precalced; | |||
}; | }; | |||
extern DataFileMgr theDataFileMgr; | extern DataFileMgr theDataFileMgr; | |||
#pragma pack(1) | #pragma pack(1) | |||
class DeletedRecord { | class DeletedRecord { | |||
public: | public: | |||
skipping to change at line 276 | skipping to change at line 232 | |||
/* use this when a record is deleted. basically a union with next/p rev fields */ | /* use this when a record is deleted. basically a union with next/p rev fields */ | |||
DeletedRecord& asDeleted() { return *((DeletedRecord*) this); } | DeletedRecord& asDeleted() { return *((DeletedRecord*) this); } | |||
Extent* myExtent(const DiskLoc& myLoc) { return DataFileMgr::getExt ent(DiskLoc(myLoc.a(), extentOfs() ) ); } | Extent* myExtent(const DiskLoc& myLoc) { return DataFileMgr::getExt ent(DiskLoc(myLoc.a(), extentOfs() ) ); } | |||
/* get the next record in the namespace, traversing extents as nece ssary */ | /* get the next record in the namespace, traversing extents as nece ssary */ | |||
DiskLoc getNext(const DiskLoc& myLoc); | DiskLoc getNext(const DiskLoc& myLoc); | |||
DiskLoc getPrev(const DiskLoc& myLoc); | DiskLoc getPrev(const DiskLoc& myLoc); | |||
DiskLoc nextInExtent(const DiskLoc& myLoc) { | ||||
_accessing(); | ||||
if ( _nextOfs == DiskLoc::NullOfs ) | ||||
return DiskLoc(); | ||||
verify( _nextOfs ); | ||||
return DiskLoc(myLoc.a(), _nextOfs); | ||||
} | ||||
struct NP { | struct NP { | |||
int nextOfs; | int nextOfs; | |||
int prevOfs; | int prevOfs; | |||
}; | }; | |||
NP* np() { return (NP*) &_nextOfs; } | NP* np() { return (NP*) &_nextOfs; } | |||
// --------------------- | // --------------------- | |||
// memory cache | // memory cache | |||
// --------------------- | // --------------------- | |||
skipping to change at line 344 | skipping to change at line 292 | |||
int _nextOfs; | int _nextOfs; | |||
int _prevOfs; | int _prevOfs; | |||
/** be careful when referencing this that your write intent was cor rect */ | /** be careful when referencing this that your write intent was cor rect */ | |||
char _data[4]; | char _data[4]; | |||
public: | public: | |||
static bool MemoryTrackingEnabled; | static bool MemoryTrackingEnabled; | |||
}; | }; | |||
/* extents are datafile regions where all the records within the region | ||||
belong to the same namespace. | ||||
(11:12:35 AM) dm10gen: when the extent is allocated, all its empty spac | ||||
e is stuck into one big DeletedRecord | ||||
(11:12:55 AM) dm10gen: and that is placed on the free list | ||||
*/ | ||||
class Extent { | ||||
public: | ||||
enum { extentSignature = 0x41424344 }; | ||||
unsigned magic; | ||||
DiskLoc myLoc; | ||||
DiskLoc xnext, xprev; /* next/prev extent for this namespace */ | ||||
/* which namespace this extent is for. this is just for troublesho | ||||
oting really | ||||
and won't even be correct if the collection were renamed! | ||||
*/ | ||||
Namespace nsDiagnostic; | ||||
int length; /* size of the extent, including these fields */ | ||||
DiskLoc firstRecord; | ||||
DiskLoc lastRecord; | ||||
char _extentData[4]; | ||||
static int HeaderSize() { return sizeof(Extent)-4; } | ||||
bool validates(const DiskLoc diskLoc, BSONArrayBuilder* errors = NU | ||||
LL); | ||||
BSONObj dump() { | ||||
return BSON( "loc" << myLoc.toString() << "xnext" << xnext.toSt | ||||
ring() << "xprev" << xprev.toString() | ||||
<< "nsdiag" << nsDiagnostic.toString() | ||||
<< "size" << length << "firstRecord" << firstRecord.t | ||||
oString() << "lastRecord" << lastRecord.toString()); | ||||
} | ||||
void dump(iostream& s) { | ||||
s << " loc:" << myLoc.toString() << " xnext:" << xnext.toStr | ||||
ing() << " xprev:" << xprev.toString() << '\n'; | ||||
s << " nsdiag:" << nsDiagnostic.toString() << '\n'; | ||||
s << " size:" << length << " firstRecord:" << firstRecord.to | ||||
String() << " lastRecord:" << lastRecord.toString() << '\n'; | ||||
} | ||||
/* assumes already zeroed -- insufficient for block 'reuse' perhaps | ||||
Returns a DeletedRecord location which is the data in the extent re | ||||
ady for us. | ||||
Caller will need to add that to the freelist structure in namespace | ||||
detail. | ||||
*/ | ||||
DiskLoc init(const char *nsname, int _length, int _fileNo, int _off | ||||
set, bool capped); | ||||
/* like init(), but for a reuse case */ | ||||
DiskLoc reuse(const char *nsname, bool newUseIsAsCapped); | ||||
bool isOk() const { return magic == extentSignature; } | ||||
void assertOk() const { verify(isOk()); } | ||||
Record* newRecord(int len); | ||||
Record* getRecord(DiskLoc dl) { | ||||
verify( !dl.isNull() ); | ||||
verify( dl.sameFile(myLoc) ); | ||||
int x = dl.getOfs() - myLoc.getOfs(); | ||||
verify( x > 0 ); | ||||
return (Record *) (((char *) this) + x); | ||||
} | ||||
Extent* getNextExtent() { return xnext.isNull() ? 0 : DataFileMgr:: | ||||
getExtent(xnext); } | ||||
Extent* getPrevExtent() { return xprev.isNull() ? 0 : DataFileMgr:: | ||||
getExtent(xprev); } | ||||
static int maxSize(); | ||||
static int minSize() { return 0x1000; } | ||||
/** | ||||
* @param len lengt of record we need | ||||
* @param lastRecord size of last extent which is a factor in next | ||||
extent size | ||||
*/ | ||||
static int followupSize(int len, int lastExtentLen); | ||||
/** get a suggested size for the first extent in a namespace | ||||
* @param len length of record we need to insert | ||||
*/ | ||||
static int initialSize(int len); | ||||
struct FL { | ||||
DiskLoc firstRecord; | ||||
DiskLoc lastRecord; | ||||
}; | ||||
/** often we want to update just the firstRecord and lastRecord fie | ||||
lds. | ||||
this helper is for that -- for use with getDur().writing() meth | ||||
od | ||||
*/ | ||||
FL* fl() { return (FL*) &firstRecord; } | ||||
/** caller must declare write intent first */ | ||||
void markEmpty(); | ||||
private: | ||||
DiskLoc _reuse(const char *nsname, bool newUseIsAsCapped); // recyc | ||||
le an extent and reuse it for a different ns | ||||
}; | ||||
/* a datafile - i.e. the "dbname.<#>" files : | ||||
---------------------- | ||||
DataFileHeader | ||||
---------------------- | ||||
Extent (for a particular namespace) | ||||
Record | ||||
... | ||||
Record (some chained for unused space) | ||||
---------------------- | ||||
more Extents... | ||||
---------------------- | ||||
*/ | ||||
class DataFileHeader { | ||||
public: | ||||
int version; | ||||
int versionMinor; | ||||
int fileLength; | ||||
DiskLoc unused; /* unused is the portion of the file that doesn't b | ||||
elong to any allocated extents. -1 = no more */ | ||||
int unusedLength; | ||||
char reserved[8192 - 4*4 - 8]; | ||||
char data[4]; // first extent starts here | ||||
enum { HeaderSize = 8192 }; | ||||
bool isCurrentVersion() const { | ||||
return version == PDFILE_VERSION && ( versionMinor == PDFILE_VE | ||||
RSION_MINOR_22_AND_OLDER | ||||
|| versionMinor == PDFILE_VE | ||||
RSION_MINOR_24_AND_NEWER | ||||
); | ||||
} | ||||
bool uninitialized() const { return version == 0; } | ||||
void init(int fileno, int filelength, const char* filename) { | ||||
if ( uninitialized() ) { | ||||
DEV log() << "datafileheader::init initializing " << filena | ||||
me << " n:" << fileno << endl; | ||||
if( !(filelength > 32768 ) ) { | ||||
massert(13640, str::stream() << "DataFileHeader looks c | ||||
orrupt at file open filelength:" << filelength << " fileno:" << fileno, fal | ||||
se); | ||||
} | ||||
{ | ||||
// "something" is too vague, but we checked for the rig | ||||
ht db to be locked higher up the call stack | ||||
if( !Lock::somethingWriteLocked() ) { | ||||
LockState::Dump(); | ||||
log() << "*** TEMP NOT INITIALIZING FILE " << filen | ||||
ame << ", not in a write lock." << endl; | ||||
log() << "temp bypass until more elaborate change - | ||||
case that is manifesting is benign anyway" << endl; | ||||
return; | ||||
/** | ||||
log() << "ERROR can't create outside a write lock" | ||||
<< endl; | ||||
printStackTrace(); | ||||
::abort(); | ||||
**/ | ||||
} | ||||
} | ||||
getDur().createdFile(filename, filelength); | ||||
verify( HeaderSize == 8192 ); | ||||
DataFileHeader *h = getDur().writing(this); | ||||
h->fileLength = filelength; | ||||
h->version = PDFILE_VERSION; | ||||
h->versionMinor = PDFILE_VERSION_MINOR_22_AND_OLDER; // All | ||||
dbs start like this | ||||
h->unused.set( fileno, HeaderSize ); | ||||
verify( (data-(char*)this) == HeaderSize ); | ||||
h->unusedLength = fileLength - HeaderSize - 16; | ||||
} | ||||
} | ||||
bool isEmpty() const { | ||||
return uninitialized() || ( unusedLength == fileLength - Header | ||||
Size - 16 ); | ||||
} | ||||
}; | ||||
#pragma pack() | #pragma pack() | |||
inline Extent* MongoDataFile::_getExtent(DiskLoc loc) const { | // XXX-ERH | |||
loc.assertOk(); | ||||
Extent *e = (Extent *) (p()+loc.getOfs()); | ||||
return e; | ||||
} | ||||
inline Extent* MongoDataFile::getExtent(DiskLoc loc) const { | inline Extent* Extent::getNextExtent() { | |||
Extent *e = _getExtent(loc); | return xnext.isNull() ? 0 : DataFileMgr::getExtent(xnext); | |||
e->assertOk(); | ||||
memconcept::is(e, memconcept::concept::extent); | ||||
return e; | ||||
} | } | |||
} // namespace mongo | inline Extent* Extent::getPrevExtent() { | |||
return xprev.isNull() ? 0 : DataFileMgr::getExtent(xprev); | ||||
#include "cursor.h" | ||||
namespace mongo { | ||||
inline Record* MongoDataFile::recordAt(DiskLoc dl) const { | ||||
int ofs = dl.getOfs(); | ||||
if (ofs < DataFileHeader::HeaderSize) { | ||||
badOfs(ofs); // will uassert - external call to keep out of the | ||||
normal code path | ||||
} | ||||
return reinterpret_cast<Record*>(p() + ofs); | ||||
} | } | |||
inline DiskLoc Record::getNext(const DiskLoc& myLoc) { | inline DiskLoc Record::getNext(const DiskLoc& myLoc) { | |||
_accessing(); | _accessing(); | |||
if ( _nextOfs != DiskLoc::NullOfs ) { | if ( _nextOfs != DiskLoc::NullOfs ) { | |||
/* defensive */ | /* defensive */ | |||
if ( _nextOfs >= 0 && _nextOfs < 10 ) { | if ( _nextOfs >= 0 && _nextOfs < 10 ) { | |||
logContext("Assertion failure - Record::getNext() referenci ng a deleted record?"); | logContext("Assertion failure - Record::getNext() referenci ng a deleted record?"); | |||
return DiskLoc(); | return DiskLoc(); | |||
} | } | |||
skipping to change at line 613 | skipping to change at line 378 | |||
template< class V > | template< class V > | |||
inline | inline | |||
const BtreeBucket<V> * DiskLoc::btree() const { | const BtreeBucket<V> * DiskLoc::btree() const { | |||
verify( _a != -1 ); | verify( _a != -1 ); | |||
Record *r = rec(); | Record *r = rec(); | |||
memconcept::is(r, memconcept::concept::btreebucket, "", 8192); | memconcept::is(r, memconcept::concept::btreebucket, "", 8192); | |||
return (const BtreeBucket<V> *) r->data(); | return (const BtreeBucket<V> *) r->data(); | |||
} | } | |||
} // namespace mongo | ||||
#include "database.h" | ||||
#include "memconcept.h" | ||||
namespace mongo { | ||||
boost::intmax_t dbSize( const char *database ); | boost::intmax_t dbSize( const char *database ); | |||
inline NamespaceIndex* nsindex(const StringData& ns) { | inline NamespaceIndex* nsindex(const StringData& ns) { | |||
Database *database = cc().database(); | Database *database = cc().database(); | |||
verify( database ); | verify( database ); | |||
memconcept::is(database, memconcept::concept::database, ns, sizeof( Database)); | memconcept::is(database, memconcept::concept::database, ns, sizeof( Database)); | |||
DEV { | DEV { | |||
StringData dbname = nsToDatabaseSubstring( ns ); | StringData dbname = nsToDatabaseSubstring( ns ); | |||
if ( database->name() != dbname ) { | if ( database->name() != dbname ) { | |||
out() << "ERROR: attempt to write to wrong database\n"; | out() << "ERROR: attempt to write to wrong database\n"; | |||
skipping to change at line 649 | skipping to change at line 407 | |||
// 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 ); | |||
return cc().database()->getFile(dl.a())->getExtent(dl); | return cc().database()->getExtentManager().getExtent(dl); | |||
} | } | |||
inline Record* DataFileMgr::getRecord(const DiskLoc& dl) { | inline Record* DataFileMgr::getRecord(const DiskLoc& dl) { | |||
verify(dl.a() != -1); | verify(dl.a() != -1); | |||
return cc().database()->getFile(dl.a())->recordAt(dl); | return cc().database()->getExtentManager().recordFor( dl ); | |||
} | } | |||
BOOST_STATIC_ASSERT( 16 == sizeof(DeletedRecord) ); | BOOST_STATIC_ASSERT( 16 == sizeof(DeletedRecord) ); | |||
inline DeletedRecord* DataFileMgr::getDeletedRecord(const DiskLoc& dl) { | inline DeletedRecord* DataFileMgr::getDeletedRecord(const DiskLoc& dl) { | |||
return reinterpret_cast<DeletedRecord*>(getRecord(dl)); | return reinterpret_cast<DeletedRecord*>(getRecord(dl)); | |||
} | } | |||
inline BSONObj BSONObj::make(const Record* r ) { | inline BSONObj BSONObj::make(const Record* r ) { | |||
return BSONObj( r->data() ); | return BSONObj( r->data() ); | |||
End of changes. 12 change blocks. | ||||
288 lines changed or deleted | 13 lines changed or added | |||
pipeline.h | pipeline.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 License | * You should have received a copy of the GNU Affero General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <deque> | #include <deque> | |||
#include "mongo/pch.h" | #include "mongo/pch.h" | |||
#include "util/intrusive_counter.h" | #include "mongo/util/intrusive_counter.h" | |||
#include "util/timer.h" | #include "mongo/util/timer.h" | |||
namespace mongo { | namespace mongo { | |||
class BSONObj; | class BSONObj; | |||
class BSONObjBuilder; | class BSONObjBuilder; | |||
class BSONArrayBuilder; | class BSONArrayBuilder; | |||
class DocumentSource; | class DocumentSource; | |||
class DocumentSourceProject; | class DocumentSourceProject; | |||
class Expression; | class Expression; | |||
class ExpressionContext; | struct ExpressionContext; | |||
class ExpressionNary; | class ExpressionNary; | |||
struct OpDesc; // local private struct | struct OpDesc; // local private struct | |||
class Privilege; | ||||
/** mongodb "commands" (sent via db.$cmd.findOne(...)) | /** mongodb "commands" (sent via db.$cmd.findOne(...)) | |||
subclass to make a command. define a singleton object for it. | subclass to make a command. define a singleton object for it. | |||
*/ | */ | |||
class Pipeline : | class Pipeline : | |||
public IntrusiveCounterUnsigned { | public IntrusiveCounterUnsigned { | |||
public: | public: | |||
virtual ~Pipeline(); | ||||
/** | /** | |||
Create a pipeline from the command. | Create a pipeline from the command. | |||
@param errmsg where to write errors, if there are any | @param errmsg where to write errors, if there are any | |||
@param cmdObj the command object sent from the client | @param cmdObj the command object sent from the client | |||
@returns the pipeline, if created, otherwise a NULL reference | @returns the pipeline, if created, otherwise a NULL reference | |||
*/ | */ | |||
static intrusive_ptr<Pipeline> parseCommand( | static intrusive_ptr<Pipeline> parseCommand( | |||
string &errmsg, BSONObj &cmdObj, | string &errmsg, BSONObj &cmdObj, | |||
const intrusive_ptr<ExpressionContext> &pCtx); | const intrusive_ptr<ExpressionContext> &pCtx); | |||
/// Helper to implement Command::addRequiredPrivileges | ||||
static void addRequiredPrivileges(const string& inputNs, | ||||
BSONObj cmdObj, | ||||
vector<Privilege>* out); | ||||
/** | /** | |||
Get the collection name from the command. | Get the collection name from the command. | |||
@returns the collection name | @returns the collection name | |||
*/ | */ | |||
string getCollectionName() const; | string getCollectionName() const; | |||
intrusive_ptr<ExpressionContext> getContext() const { return pCtx; | ||||
} | ||||
/** | /** | |||
Split the current Pipeline into a Pipeline for each shard, and | Split the current Pipeline into a Pipeline for each shard, and | |||
a Pipeline that combines the results within mongos. | a Pipeline that combines the results within mongos. | |||
This permanently alters this pipeline for the merging operation. | This permanently alters this pipeline for the merging operation. | |||
@returns the Spec for the pipeline command that should be sent | @returns the Spec for the pipeline command that should be sent | |||
to the shards | to the shards | |||
*/ | */ | |||
intrusive_ptr<Pipeline> splitForSharded(); | intrusive_ptr<Pipeline> splitForSharded(); | |||
skipping to change at line 135 | skipping to change at line 141 | |||
@returns true if this is an explain | @returns true if this is an explain | |||
*/ | */ | |||
bool isExplain() const; | bool isExplain() const; | |||
/// The initial source is special since it varies between mongos an d mongod. | /// The initial source is special since it varies between mongos an d mongod. | |||
void addInitialSource(intrusive_ptr<DocumentSource> source); | void addInitialSource(intrusive_ptr<DocumentSource> source); | |||
/// The source that represents the output. Returns a non-owning poi nter. | /// The source that represents the output. Returns a non-owning poi nter. | |||
DocumentSource* output() { return sources.back().get(); } | DocumentSource* output() { return sources.back().get(); } | |||
/// Returns true if this pipeline only uses features that work in m | ||||
ongos. | ||||
bool canRunInMongos() const; | ||||
/** | /** | |||
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 | |||
End of changes. 7 change blocks. | ||||
5 lines changed or deleted | 16 lines changed or added | |||
pipeline_d.h | pipeline_d.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 License | * You should have received a copy of the GNU Affero General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/pch.h" | |||
namespace mongo { | namespace mongo { | |||
class DocumentSourceCursor; | class DocumentSourceCursor; | |||
struct ExpressionContext; | ||||
class Pipeline; | class Pipeline; | |||
/* | /* | |||
PipelineD is an extension of the Pipeline class, but with additional | PipelineD is an extension of the Pipeline class, but with additional | |||
material that references symbols that are not available in mongos, | material that references symbols that are not available in mongos, | |||
where the remainder of the Pipeline class also functions. PipelineD | where the remainder of the Pipeline class also functions. PipelineD | |||
is a friend of Pipeline so that it can have equal access to Pipeline' s | is a friend of Pipeline so that it can have equal access to Pipeline' s | |||
members. | members. | |||
See the friend declaration in Pipeline. | See the friend declaration in Pipeline. | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
plan_stage.h | plan_stage.h | |||
---|---|---|---|---|
skipping to change at line 19 | skipping to change at line 19 | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Lice nse | * You should have received a copy of the GNU Affero General Public Lice nse | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/db/exec/plan_stats.h" | ||||
#include "mongo/db/exec/working_set.h" | #include "mongo/db/exec/working_set.h" | |||
namespace mongo { | namespace mongo { | |||
class DiskLoc; | class DiskLoc; | |||
/** | /** | |||
* A PlanStage ("stage") is the basic building block of a "Query Execut ion Plan." A stage is | * A PlanStage ("stage") is the basic building block of a "Query Execut ion Plan." A stage is | |||
* the smallest piece of machinery used in executing a compiled query. Stages either access | * the smallest piece of machinery used in executing a compiled query. Stages either access | |||
* data (from a collection or an index) to create a stream of results, or transform a stream of | * data (from a collection or an index) to create a stream of results, or transform a stream of | |||
skipping to change at line 174 | skipping to change at line 175 | |||
virtual void recoverFromYield() = 0; | virtual void recoverFromYield() = 0; | |||
/** | /** | |||
* Notifies a stage that a DiskLoc is going to be deleted (or in-pl ace updated) so that the | * Notifies a stage that a DiskLoc is going to be deleted (or in-pl ace updated) so that the | |||
* stage can invalidate or modify any state required to continue pr ocessing without this | * stage can invalidate or modify any state required to continue pr ocessing without this | |||
* DiskLoc. | * DiskLoc. | |||
* | * | |||
* Can only be called after a prepareToYield but before a recoverFr omYield. | * Can only be called after a prepareToYield but before a recoverFr omYield. | |||
*/ | */ | |||
virtual void invalidate(const DiskLoc& dl) = 0; | virtual void invalidate(const DiskLoc& dl) = 0; | |||
/** | ||||
* Returns a tree of stats. See plan_stats.h for the details of th | ||||
is structure. If the | ||||
* stage has any children it must propagate the request for stats t | ||||
o them. | ||||
* | ||||
* Caller owns returned pointer. | ||||
*/ | ||||
virtual PlanStageStats* getStats() = 0; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 11 lines changed or added | |||
privilege.h | privilege.h | |||
---|---|---|---|---|
skipping to change at line 23 | skipping to change at line 23 | |||
* limitations under the License. | * limitations under the License. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <string> | #include <string> | |||
#include <vector> | #include <vector> | |||
#include "mongo/db/auth/action_set.h" | #include "mongo/db/auth/action_set.h" | |||
#include "mongo/db/auth/action_type.h" | #include "mongo/db/auth/action_type.h" | |||
#include "mongo/db/auth/principal.h" | ||||
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, const ActionType& action); | Privilege(const std::string& resource, const ActionType& action); | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 0 lines changed or added | |||
progress_meter.h | progress_meter.h | |||
---|---|---|---|---|
skipping to change at line 33 | skipping to change at line 33 | |||
namespace mongo { | namespace mongo { | |||
class ProgressMeter : boost::noncopyable { | class ProgressMeter : boost::noncopyable { | |||
public: | public: | |||
ProgressMeter(unsigned long long total, | ProgressMeter(unsigned long long total, | |||
int secondsBetween = 3, | int secondsBetween = 3, | |||
int checkInterval = 100, | int checkInterval = 100, | |||
std::string units = "", | std::string units = "", | |||
std::string name = "Progress") | std::string name = "Progress") | |||
: _units(units) | : _showTotal(true), | |||
, _name(name) { | _units(units), | |||
_name(name) { | ||||
reset( total , secondsBetween , checkInterval ); | reset( total , secondsBetween , checkInterval ); | |||
} | } | |||
ProgressMeter() : _active(0), _units(""), _name("Progress") {} | ProgressMeter() : _active(0), _showTotal(true), _units(""), _name(" Progress") {} | |||
// typically you do ProgressMeterHolder | // typically you do ProgressMeterHolder | |||
void reset( unsigned long long total , int secondsBetween = 3 , int checkInterval = 100 ); | void reset( unsigned long long total , int secondsBetween = 3 , int checkInterval = 100 ); | |||
void finished() { _active = 0; } | void finished() { _active = 0; } | |||
bool isActive() const { return _active; } | bool isActive() const { return _active; } | |||
/** | /** | |||
* @param n how far along we are relative to the total # we set in CurOp::setMessage | * @param n how far along we are relative to the total # we set in CurOp::setMessage | |||
* @return if row was printed | * @return if row was printed | |||
skipping to change at line 68 | skipping to change at line 69 | |||
void setTotalWhileRunning( unsigned long long total ) { | void setTotalWhileRunning( unsigned long long total ) { | |||
_total = total; | _total = total; | |||
} | } | |||
unsigned long long done() const { return _done; } | unsigned long long done() const { return _done; } | |||
unsigned long long hits() const { return _hits; } | unsigned long long hits() const { return _hits; } | |||
unsigned long long total() const { return _total; } | unsigned long long total() const { return _total; } | |||
void showTotal(bool doShow) { | ||||
_showTotal = doShow; | ||||
} | ||||
std::string toString() const; | std::string toString() const; | |||
bool operator==( const ProgressMeter& other ) const { return this = = &other; } | bool operator==( const ProgressMeter& other ) const { return this = = &other; } | |||
private: | private: | |||
bool _active; | bool _active; | |||
unsigned long long _total; | unsigned long long _total; | |||
bool _showTotal; | ||||
int _secondsBetween; | int _secondsBetween; | |||
int _checkInterval; | int _checkInterval; | |||
unsigned long long _done; | unsigned long long _done; | |||
unsigned long long _hits; | unsigned long long _hits; | |||
int _lastTime; | int _lastTime; | |||
std::string _units; | std::string _units; | |||
std::string _name; | std::string _name; | |||
}; | }; | |||
End of changes. 4 change blocks. | ||||
3 lines changed or deleted | 9 lines changed or added | |||
query.h | query.h | |||
---|---|---|---|---|
skipping to change at line 34 | skipping to change at line 34 | |||
#include "mongo/db/dbmessage.h" | #include "mongo/db/dbmessage.h" | |||
#include "mongo/db/explain.h" | #include "mongo/db/explain.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/s/collection_metadata.h" | #include "mongo/s/collection_metadata.h" | |||
#include "mongo/util/net/message.h" | #include "mongo/util/net/message.h" | |||
// struct QueryOptions, QueryResult, QueryResultFlags in: | // struct QueryOptions, QueryResult, QueryResultFlags in: | |||
namespace mongo { | namespace mongo { | |||
class CurOp; | ||||
class ParsedQuery; | class ParsedQuery; | |||
class QueryOptimizerCursor; | class QueryOptimizerCursor; | |||
struct QueryPlanSummary; | struct QueryPlanSummary; | |||
extern const int32_t MaxBytesToReturnToClientAtOnce; | extern const int32_t MaxBytesToReturnToClientAtOnce; | |||
/** | /** | |||
* Return a batch of results from a client OP_GET_MORE request. | * Return a batch of results from a client OP_GET_MORE request. | |||
* 'cursorid' - The id of the cursor producing results. | * 'cursorid' - The id of the cursor producing results. | |||
* 'isCursorAuthorized' - Set to true after a cursor with id 'cursorid' is authorized for use. | * 'isCursorAuthorized' - Set to true after a cursor with id 'cursorid' is authorized for use. | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
query_optimizer_internal.h | query_optimizer_internal.h | |||
---|---|---|---|---|
skipping to change at line 245 | skipping to change at line 245 | |||
bool _complete; | bool _complete; | |||
bool _stopRequested; | bool _stopRequested; | |||
ExceptionInfo _exception; | ExceptionInfo _exception; | |||
const QueryPlan* _queryPlan; | const QueryPlan* _queryPlan; | |||
bool _error; | bool _error; | |||
CachedMatchCounter _matchCounter; | CachedMatchCounter _matchCounter; | |||
bool _countingMatches; | bool _countingMatches; | |||
bool _mustAdvance; | bool _mustAdvance; | |||
bool _capped; | bool _capped; | |||
shared_ptr<Cursor> _c; | shared_ptr<Cursor> _c; | |||
ClientCursor::Holder _cc; | ClientCursorHolder _cc; | |||
DiskLoc _posBeforeYield; | DiskLoc _posBeforeYield; | |||
ClientCursor::YieldData _yieldData; | ClientCursor::YieldData _yieldData; | |||
const QueryPlanSelectionPolicy& _selectionPolicy; | const QueryPlanSelectionPolicy& _selectionPolicy; | |||
const bool& _requireOrder; // TODO don't use a ref for this, but si gnal change explicitly | const bool& _requireOrder; // TODO don't use a ref for this, but si gnal change explicitly | |||
shared_ptr<ExplainPlanInfo> _explainPlanInfo; | shared_ptr<ExplainPlanInfo> _explainPlanInfo; | |||
bool _alwaysCountMatches; | bool _alwaysCountMatches; | |||
}; | }; | |||
/** | /** | |||
* This class works if T::operator< is variant unlike a regular stl pri ority queue, but it's | * This class works if T::operator< is variant unlike a regular stl pri ority queue, but it's | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
range_arithmetic.h | range_arithmetic.h | |||
---|---|---|---|---|
skipping to change at line 53 | skipping to change at line 53 | |||
* contains Id(DocB) | * contains Id(DocB) | |||
* | * | |||
* keyPattern : { field : "numberofletters" } | * keyPattern : { field : "numberofletters" } | |||
* minKey : { field : 4 } : numberofletters(DocA) | * minKey : { field : 4 } : numberofletters(DocA) | |||
* maxKey : { field : 5 } : numberofletters(DocC) | * maxKey : { field : 5 } : numberofletters(DocC) | |||
* | * | |||
* does not contain numberofletters(DocB) | * does not contain numberofletters(DocB) | |||
*/ | */ | |||
struct KeyRange { | struct KeyRange { | |||
KeyRange( const std::string& ns_, | KeyRange( const std::string& ns, | |||
const BSONObj& minKey_, | const BSONObj& minKey, | |||
const BSONObj& maxKey_, | const BSONObj& maxKey, | |||
const BSONObj& keyPattern_ ) : | const BSONObj& keyPattern ) : | |||
ns( ns_ ), minKey( minKey_ ), maxKey( maxKey_ ), keyPattern | ns( ns ), minKey( minKey ), maxKey( maxKey ), keyPattern( k | |||
( keyPattern_ ) | eyPattern ) | |||
{ | { | |||
} | } | |||
KeyRange() {} | ||||
std::string ns; | std::string ns; | |||
BSONObj minKey; | BSONObj minKey; | |||
BSONObj maxKey; | BSONObj maxKey; | |||
BSONObj keyPattern; | BSONObj keyPattern; | |||
}; | }; | |||
/** | /** | |||
* Returns true if the point is within the range [inclusiveLower, exclu siveUpper). | * Returns true if the point is within the range [inclusiveLower, exclu siveUpper). | |||
*/ | */ | |||
bool rangeContains( const BSONObj& inclusiveLower, | bool rangeContains( const BSONObj& inclusiveLower, | |||
skipping to change at line 132 | skipping to change at line 134 | |||
const BSONObj& exclusiveUpper ); | const BSONObj& exclusiveUpper ); | |||
/** | /** | |||
* Returns true if the provided range map exactly contains the provided range | * Returns true if the provided range map exactly contains the provided range | |||
* [inclusiveLower, exclusiveUpper). | * [inclusiveLower, exclusiveUpper). | |||
*/ | */ | |||
bool rangeMapContains( const RangeMap& ranges, | bool rangeMapContains( const RangeMap& ranges, | |||
const BSONObj& inclusiveLower, | const BSONObj& inclusiveLower, | |||
const BSONObj& exclusiveUpper ); | const BSONObj& exclusiveUpper ); | |||
/** | ||||
* String representation of [inclusiveLower, exclusiveUpper) | ||||
*/ | ||||
std::string rangeToString( const BSONObj& inclusiveLower, | ||||
const BSONObj& exclusiveUpper ); | ||||
/** | ||||
* String representation of overlapping ranges as a list "[range1),[ran | ||||
ge2),..." | ||||
*/ | ||||
std::string overlapToString( RangeVector overlap ); | ||||
} | } | |||
End of changes. 3 change blocks. | ||||
6 lines changed or deleted | 20 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. | ||||
3 lines changed or deleted | 0 lines changed or added | |||
request.h | request.h | |||
---|---|---|---|---|
skipping to change at line 21 | skipping to change at line 21 | |||
* 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 "../util/net/message.h" | ||||
#include "../db/dbmessage.h" | #include "mongo/db/dbmessage.h" | |||
#include "config.h" | #include "mongo/s/config.h" | |||
#include "mongo/util/net/message.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 ); | |||
End of changes. 1 change blocks. | ||||
3 lines changed or deleted | 4 lines changed or added | |||
restapi.h | restapi.h | |||
---|---|---|---|---|
skipping to change at line 24 | skipping to change at line 24 | |||
* 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/auth/user_name.h" | ||||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/util/admin_access.h" | #include "mongo/util/admin_access.h" | |||
namespace mongo { | namespace mongo { | |||
class RestAdminAccess : public AdminAccess { | class RestAdminAccess : public AdminAccess { | |||
public: | public: | |||
virtual ~RestAdminAccess() { } | virtual ~RestAdminAccess() { } | |||
virtual bool haveAdminUsers() const; | virtual bool haveAdminUsers() const; | |||
virtual BSONObj getAdminUser( const std::string& username ) const; | virtual BSONObj getAdminUser(const UserName& username) const; | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 2 change blocks. | ||||
1 lines changed or deleted | 2 lines changed or added | |||
rs.h | rs.h | |||
---|---|---|---|---|
skipping to change at line 24 | skipping to change at line 24 | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Licen se | * You should have received a copy of the GNU Affero General Public Licen se | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/db/commands.h" | #include "mongo/db/commands.h" | |||
#include "mongo/db/index.h" | #include "mongo/db/index.h" | |||
#include "mongo/db/repl/oplogreader.h" | #include "mongo/db/repl/oplogreader.h" | |||
#include "mongo/db/repl/optime.h" | #include "mongo/bson/optime.h" | |||
#include "mongo/db/repl/rs_config.h" | #include "mongo/db/repl/rs_config.h" | |||
#include "mongo/db/repl/rs_exception.h" | #include "mongo/db/repl/rs_exception.h" | |||
#include "mongo/db/repl/rs_member.h" | #include "mongo/db/repl/rs_member.h" | |||
#include "mongo/db/repl/rs_sync.h" | #include "mongo/db/repl/rs_sync.h" | |||
#include "mongo/db/repl/sync_source_feedback.h" | ||||
#include "mongo/util/concurrency/list.h" | #include "mongo/util/concurrency/list.h" | |||
#include "mongo/util/concurrency/msg.h" | #include "mongo/util/concurrency/msg.h" | |||
#include "mongo/util/concurrency/thread_pool.h" | #include "mongo/util/concurrency/thread_pool.h" | |||
#include "mongo/util/concurrency/value.h" | #include "mongo/util/concurrency/value.h" | |||
#include "mongo/util/net/hostandport.h" | #include "mongo/util/net/hostandport.h" | |||
/** | /** | |||
* Order of Events | * Order of Events | |||
* | * | |||
* On startup, if the --replSet option is present, startReplSets is called. | * On startup, if the --replSet option is present, startReplSets is called. | |||
skipping to change at line 151 | skipping to change at line 152 | |||
* | * | |||
* We can't just directly sync to the primary because it could be | * We can't just directly sync to the primary because it could be | |||
* unreachable, e.g., S1--->S2--->S3--->P. S2 should ghost sync fr om S3 | * unreachable, e.g., S1--->S2--->S3--->P. S2 should ghost sync fr om S3 | |||
* and S3 can ghost sync from the primary. | * and S3 can ghost sync from the primary. | |||
* | * | |||
* 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 mongo::OID& 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); | |||
void clearCache(); | void clearCache(); | |||
}; | }; | |||
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; | |||
skipping to change at line 344 | skipping to change at line 345 | |||
/* todo thread */ | /* todo thread */ | |||
void msgUpdateHBInfo(HeartbeatInfo); | void msgUpdateHBInfo(HeartbeatInfo); | |||
/** | /** | |||
* Updates the lastHeartbeatRecv of Member with the given id. | * Updates the lastHeartbeatRecv of Member with the given id. | |||
*/ | */ | |||
void msgUpdateHBRecv(unsigned id, time_t newTime); | void msgUpdateHBRecv(unsigned id, time_t newTime); | |||
StateBox box; | StateBox box; | |||
SyncSourceFeedback syncSourceFeedback; | ||||
OpTime lastOpTimeWritten; | OpTime lastOpTimeWritten; | |||
long long lastH; // hash we use to make sure we are reading the rig ht flow of ops and aren't on an out-of-date "fork" | long long lastH; // hash we use to make sure we are reading the rig ht flow of ops and aren't on an out-of-date "fork" | |||
bool forceSyncFrom(const string& host, string& errmsg, BSONObjBuild er& result); | bool forceSyncFrom(const string& host, string& errmsg, BSONObjBuild er& result); | |||
// Check if the current sync target is suboptimal. This must be cal led while holding a mutex | // Check if the current sync target is suboptimal. This must be cal led while holding a mutex | |||
// that prevents the sync source from changing. | // that prevents the sync source from changing. | |||
bool shouldChangeSyncTarget(const OpTime& target) const; | bool shouldChangeSyncTarget(const OpTime& target) const; | |||
/** | /** | |||
* 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. | |||
*/ | */ | |||
skipping to change at line 508 | skipping to change at line 511 | |||
* have called it again, passing in false. | * have called it again, passing in false. | |||
*/ | */ | |||
bool setMaintenanceMode(const bool inc); | bool setMaintenanceMode(const bool inc); | |||
// Records a new slave's id in the GhostSlave map, at handshake tim e. | // Records a new slave's id in the GhostSlave map, at handshake tim e. | |||
void registerSlave(const BSONObj& rid, const int memberId); | void registerSlave(const BSONObj& rid, const int memberId); | |||
private: | private: | |||
Member* head() const { return _members.head(); } | Member* head() const { return _members.head(); } | |||
public: | public: | |||
const Member* findById(unsigned id) const; | const Member* findById(unsigned id) const; | |||
Member* getMutableMember(unsigned id); | ||||
Member* findByName(const std::string& hostname) const; | Member* findByName(const std::string& hostname) const; | |||
private: | private: | |||
void _getTargets(list<Target>&, int &configVersion); | void _getTargets(list<Target>&, int &configVersion); | |||
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; | |||
skipping to change at line 565 | skipping to change at line 569 | |||
threadpool::ThreadPool& getPrefetchPool() { return _prefetcherPool; } | threadpool::ThreadPool& getPrefetchPool() { return _prefetcherPool; } | |||
threadpool::ThreadPool& getWriterPool() { return _writerPool; } | threadpool::ThreadPool& getWriterPool() { return _writerPool; } | |||
static const int maxSyncSourceLagSecs; | static const int maxSyncSourceLagSecs; | |||
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; | |||
/** | ||||
* The most up to date electable replica | ||||
*/ | ||||
const OpTime lastOtherElectableOpTime() const; | ||||
/** | /** | |||
* When a member reaches its minValid optime it is in a consistent state. Thus, minValid is | * When a member reaches its minValid optime it is in a consistent state. Thus, minValid is | |||
* set as the last step in initial sync. At the beginning of initi al sync, _initialSyncFlag | * set as the last step in initial sync. At the beginning of initi al sync, _initialSyncFlag | |||
* is appended onto minValid to indicate that initial sync was star ted but has not yet | * is appended onto minValid to indicate that initial sync was star ted but has not yet | |||
* completed. | * completed. | |||
* minValid is also used during "normal" sync: the last op in each batch is used to set | * minValid is also used during "normal" sync: the last op in each batch is used to set | |||
* minValid, to indicate that we are in a consistent state when the batch has been fully | * minValid, to indicate that we are in a consistent state when the batch has been fully | |||
* applied. | * applied. | |||
*/ | */ | |||
End of changes. 6 change blocks. | ||||
2 lines changed or deleted | 10 lines changed or added | |||
safe_num-inl.h | safe_num-inl.h | |||
---|---|---|---|---|
skipping to change at line 63 | skipping to change at line 63 | |||
} | } | |||
inline SafeNum SafeNum::operator+(const SafeNum& rhs) const { | inline SafeNum SafeNum::operator+(const SafeNum& rhs) const { | |||
return addInternal(*this, rhs); | return addInternal(*this, rhs); | |||
} | } | |||
inline SafeNum& SafeNum::operator+=(const SafeNum& rhs) { | inline SafeNum& SafeNum::operator+=(const SafeNum& rhs) { | |||
return *this = addInternal(*this, rhs); | return *this = addInternal(*this, rhs); | |||
} | } | |||
inline SafeNum SafeNum::operator*(const SafeNum& rhs) const { | ||||
return mulInternal(*this, rhs); | ||||
} | ||||
inline SafeNum& SafeNum::operator*=(const SafeNum& rhs) { | ||||
return *this = mulInternal(*this, rhs); | ||||
} | ||||
inline SafeNum SafeNum::bitAnd(const SafeNum& rhs) const { | inline SafeNum SafeNum::bitAnd(const SafeNum& rhs) const { | |||
return andInternal(*this, rhs); | return andInternal(*this, rhs); | |||
} | } | |||
inline SafeNum SafeNum::operator&(const SafeNum& rhs) const { | inline SafeNum SafeNum::operator&(const SafeNum& rhs) const { | |||
return bitAnd(rhs); | return bitAnd(rhs); | |||
} | } | |||
inline SafeNum& SafeNum::operator&=(const SafeNum& rhs) { | inline SafeNum& SafeNum::operator&=(const SafeNum& rhs) { | |||
return *this = bitAnd(rhs); | return *this = bitAnd(rhs); | |||
skipping to change at line 87 | skipping to change at line 95 | |||
} | } | |||
inline SafeNum SafeNum::operator|(const SafeNum& rhs) const { | inline SafeNum SafeNum::operator|(const SafeNum& rhs) const { | |||
return bitOr(rhs); | return bitOr(rhs); | |||
} | } | |||
inline SafeNum& SafeNum::operator|=(const SafeNum& rhs) { | inline SafeNum& SafeNum::operator|=(const SafeNum& rhs) { | |||
return *this = bitOr(rhs); | return *this = bitOr(rhs); | |||
} | } | |||
inline SafeNum SafeNum::bitXor(const SafeNum& rhs) const { | ||||
return xorInternal(*this, rhs); | ||||
} | ||||
inline SafeNum SafeNum::operator^(const SafeNum& rhs) const { | ||||
return bitXor(rhs); | ||||
} | ||||
inline SafeNum& SafeNum::operator^=(const SafeNum& rhs) { | ||||
return *this = bitXor(rhs); | ||||
} | ||||
inline bool SafeNum::isValid() const { | inline bool SafeNum::isValid() const { | |||
return _type != EOO; | return _type != EOO; | |||
} | } | |||
inline BSONType SafeNum::type() const { | inline BSONType SafeNum::type() const { | |||
return _type; | return _type; | |||
} | } | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 20 lines changed or added | |||
safe_num.h | safe_num.h | |||
---|---|---|---|---|
skipping to change at line 102 | skipping to change at line 102 | |||
* anything else, even another EOO-typed instance. Otherwise, retur ns false. | * anything else, even another EOO-typed instance. Otherwise, retur ns false. | |||
*/ | */ | |||
bool isIdentical(const SafeNum& rhs) const; | bool isIdentical(const SafeNum& rhs) const; | |||
// | // | |||
// arithmetic support | // arithmetic support | |||
// | // | |||
/** | /** | |||
* Sums the 'rhs' -- right-hand side -- safe num with this, taking care of | * Sums the 'rhs' -- right-hand side -- safe num with this, taking care of | |||
* upconvertions and overflow (see class header). | * upconversions and overflow (see class header). | |||
*/ | */ | |||
SafeNum operator+(const SafeNum& rhs) const; | SafeNum operator+(const SafeNum& rhs) const; | |||
SafeNum& operator+=(const SafeNum& rhs); | SafeNum& operator+=(const SafeNum& rhs); | |||
// TODO other operations than sum | ||||
/** | ||||
* Multiplies the 'rhs' -- right-hand side -- safe num with this, t | ||||
aking care of | ||||
* upconversions and overflow (see class header). | ||||
*/ | ||||
SafeNum operator*(const SafeNum& rhs) const; | ||||
SafeNum& operator*=(const SafeNum& rhs); | ||||
// | // | |||
// logical operation support. Note that these operations are only s upported for | // logical operation support. Note that these operations are only s upported for | |||
// integral types. Attempts to apply with either side holding a dou ble value | // integral types. Attempts to apply with either side holding a dou ble value | |||
// will result in an EOO typed safenum. | // will result in an EOO typed safenum. | |||
// | // | |||
// Bitwise 'and' support | // Bitwise 'and' support | |||
SafeNum bitAnd(const SafeNum& rhs) const; | SafeNum bitAnd(const SafeNum& rhs) const; | |||
SafeNum operator&(const SafeNum& rhs) const; | SafeNum operator&(const SafeNum& rhs) const; | |||
SafeNum& operator&=(const SafeNum& rhs); | SafeNum& operator&=(const SafeNum& rhs); | |||
// Bitwise 'or' support | // Bitwise 'or' support | |||
SafeNum bitOr(const SafeNum& rhs) const; | SafeNum bitOr(const SafeNum& rhs) const; | |||
SafeNum operator|(const SafeNum& rhs) const; | SafeNum operator|(const SafeNum& rhs) const; | |||
SafeNum& operator|=(const SafeNum& rhs); | SafeNum& operator|=(const SafeNum& rhs); | |||
// Bitwise 'xor' support | ||||
SafeNum bitXor(const SafeNum& rhs) const; | ||||
SafeNum operator^(const SafeNum& rhs) const; | ||||
SafeNum& operator^=(const SafeNum& rhs); | ||||
// | // | |||
// output support | // output support | |||
// | // | |||
friend class mutablebson::Element; | friend class mutablebson::Element; | |||
friend class mutablebson::Document; | friend class mutablebson::Document; | |||
// TODO: output to builder | // TODO: output to builder | |||
// | // | |||
skipping to change at line 167 | skipping to change at line 178 | |||
double doubleVal; | double doubleVal; | |||
} _value; | } _value; | |||
/** | /** | |||
* Returns the sum of 'lhs' and 'rhs', taking into consideration th eir types. The | * Returns the sum of 'lhs' and 'rhs', taking into consideration th eir types. The | |||
* type of the result would upcast, if necessary and permitted. Oth erwise, returns | * type of the result would upcast, if necessary and permitted. Oth erwise, returns | |||
* an EOO-type instance. | * an EOO-type instance. | |||
*/ | */ | |||
static SafeNum addInternal(const SafeNum& lhs, const SafeNum& rhs); | static SafeNum addInternal(const SafeNum& lhs, const SafeNum& rhs); | |||
/** | ||||
* Returns the product of 'lhs' and 'rhs', taking into consideratio | ||||
n their types. The | ||||
* type of the result would upcast, if necessary and permitted. Oth | ||||
erwise, returns an | ||||
* EOO-type instance. | ||||
*/ | ||||
static SafeNum mulInternal(const SafeNum& lhs, const SafeNum& rhs); | ||||
/** Returns the bitwise 'and' of lhs and rhs, taking into considera tion their types. If | /** Returns the bitwise 'and' of lhs and rhs, taking into considera tion their types. If | |||
* the operation is invalid for the underlying types, returns an E OO instance. | * the operation is invalid for the underlying types, returns an E OO instance. | |||
*/ | */ | |||
static SafeNum andInternal(const SafeNum& lhs, const SafeNum& rhs); | static SafeNum andInternal(const SafeNum& lhs, const SafeNum& rhs); | |||
/** Returns the bitwise 'or' of lhs and rhs, taking into considerat ion their types. If | /** Returns the bitwise 'or' of lhs and rhs, taking into considerat ion their types. If | |||
* the operation is invalid for the underlying types, returns an E OO instance. | * the operation is invalid for the underlying types, returns an E OO instance. | |||
*/ | */ | |||
static SafeNum orInternal(const SafeNum& lhs, const SafeNum& rhs); | static SafeNum orInternal(const SafeNum& lhs, const SafeNum& rhs); | |||
/** Returns the bitwise 'xor' of lhs and rhs, taking into considera | ||||
tion their types. If | ||||
* the operation is invalid for the underlying types, returns an E | ||||
OO instance. | ||||
*/ | ||||
static SafeNum xorInternal(const SafeNum& lhs, const SafeNum& rhs); | ||||
/** | /** | |||
* Extracts the value of 'snum' in a long format. It assumes 'snum' is an NumberInt | * Extracts the value of 'snum' in a long format. It assumes 'snum' is an NumberInt | |||
* or a NumberDouble. | * or a NumberDouble. | |||
*/ | */ | |||
static long long getLongLong(const SafeNum& snum); | static long long getLongLong(const SafeNum& snum); | |||
/** | /** | |||
* Extracts the value of 'snum' in a double format. It assumes 'snu m' is a valid | * Extracts the value of 'snum' in a double format. It assumes 'snu m' is a valid | |||
* SafeNum, i.e., that _type is not EOO. | * SafeNum, i.e., that _type is not EOO. | |||
*/ | */ | |||
End of changes. 5 change blocks. | ||||
2 lines changed or deleted | 30 lines changed or added | |||
shard.h | shard.h | |||
---|---|---|---|---|
skipping to change at line 310 | skipping to change at line 310 | |||
* Note: This is *dangerous* if we have GLE state. | * Note: This is *dangerous* if we have GLE state. | |||
*/ | */ | |||
static void releaseMyConnections(); | static void releaseMyConnections(); | |||
/** | /** | |||
* Clears all connections in the sharded pool, including connection s in the | * Clears all connections in the sharded pool, including connection s in the | |||
* thread local storage pool of the current thread. | * thread local storage pool of the current thread. | |||
*/ | */ | |||
static void clearPool(); | static void clearPool(); | |||
/** | ||||
* Forgets a namespace to prevent future versioning. | ||||
*/ | ||||
static void forgetNS( const string& ns ); | ||||
private: | private: | |||
void _init(); | void _init(); | |||
void _finishInit(); | void _finishInit(); | |||
bool _finishedInit; | bool _finishedInit; | |||
string _addr; | string _addr; | |||
string _ns; | string _ns; | |||
ChunkManagerPtr _manager; | ChunkManagerPtr _manager; | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 5 lines changed or added | |||
skip.h | skip.h | |||
---|---|---|---|---|
skipping to change at line 43 | skipping to change at line 43 | |||
SkipStage(int toSkip, WorkingSet* ws, PlanStage* child); | SkipStage(int toSkip, WorkingSet* ws, PlanStage* child); | |||
virtual ~SkipStage(); | virtual ~SkipStage(); | |||
virtual bool isEOF(); | virtual bool isEOF(); | |||
virtual StageState work(WorkingSetID* out); | virtual StageState work(WorkingSetID* out); | |||
virtual void prepareToYield(); | virtual void prepareToYield(); | |||
virtual void recoverFromYield(); | virtual void recoverFromYield(); | |||
virtual void invalidate(const DiskLoc& dl); | virtual void invalidate(const DiskLoc& dl); | |||
virtual PlanStageStats* getStats(); | ||||
private: | private: | |||
WorkingSet* _ws; | WorkingSet* _ws; | |||
scoped_ptr<PlanStage> _child; | scoped_ptr<PlanStage> _child; | |||
// We drop the first _toSkip results that we would have returned. | // We drop the first _toSkip results that we would have returned. | |||
int _toSkip; | int _toSkip; | |||
// Stats | ||||
CommonStats _commonStats; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 5 lines changed or added | |||
sock.h | sock.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/pch.h" | ||||
#include <stdio.h> | #include <stdio.h> | |||
#ifndef _WIN32 | #ifndef _WIN32 | |||
#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 // not _WIN32 | #endif // not _WIN32 | |||
#ifdef MONGO_SSL | #ifdef MONGO_SSL | |||
#include <openssl/ssl.h> | #include <openssl/ssl.h> | |||
#endif | #endif | |||
#include <string> | ||||
#include <utility> | ||||
#include <vector> | ||||
#include "mongo/base/disallow_copying.h" | ||||
#include "mongo/logger/log_severity.h" | #include "mongo/logger/log_severity.h" | |||
#include "mongo/platform/compiler.h" | #include "mongo/platform/compiler.h" | |||
#include "mongo/platform/cstdint.h" | ||||
#include "mongo/util/assert_util.h" | ||||
namespace mongo { | namespace mongo { | |||
class SSLManagerInterface; | class SSLManagerInterface; | |||
const int SOCK_FAMILY_UNKNOWN_ERROR=13078; | const int SOCK_FAMILY_UNKNOWN_ERROR=13078; | |||
void disableNagle(int sock); | void disableNagle(int sock); | |||
#if defined(_WIN32) | #if defined(_WIN32) | |||
skipping to change at line 72 | skipping to change at line 77 | |||
}; | }; | |||
#else // _WIN32 | #else // _WIN32 | |||
inline void closesocket(int s) { close(s); } | inline void closesocket(int s) { close(s); } | |||
const int INVALID_SOCKET = -1; | const int INVALID_SOCKET = -1; | |||
typedef int SOCKET; | typedef int SOCKET; | |||
#endif // _WIN32 | #endif // _WIN32 | |||
string makeUnixSockPath(int port); | std::string makeUnixSockPath(int port); | |||
// If an ip address is passed in, just return that. If a hostname is p assed | // If an ip address is passed in, just return that. If a hostname is p assed | |||
// in, look up its ip and return that. Returns "" on failure. | // in, look up its ip and return that. Returns "" on failure. | |||
string hostbyname(const char *hostname); | std::string hostbyname(const char *hostname); | |||
void enableIPv6(bool state=true); | void enableIPv6(bool state=true); | |||
bool IPv6Enabled(); | bool IPv6Enabled(); | |||
void setSockTimeouts(int sock, double secs); | void setSockTimeouts(int sock, double secs); | |||
/** | /** | |||
* wrapped around os representation of network address | * wrapped around os representation of network address | |||
*/ | */ | |||
struct SockAddr { | struct SockAddr { | |||
SockAddr() { | SockAddr() { | |||
addressSize = sizeof(sa); | addressSize = sizeof(sa); | |||
memset(&sa, 0, sizeof(sa)); | memset(&sa, 0, sizeof(sa)); | |||
sa.ss_family = AF_UNSPEC; | sa.ss_family = AF_UNSPEC; | |||
} | } | |||
explicit SockAddr(int sourcePort); /* listener side */ | explicit SockAddr(int sourcePort); /* listener side */ | |||
SockAddr(const char *ip, int port); /* EndPoint (remote) side, or i f you want to specify which interface locally */ | SockAddr(const char *ip, int port); /* EndPoint (remote) side, or i f you want to specify which interface locally */ | |||
template <typename T> T& as() { return *(T*)(&sa); } | template <typename T> T& as() { return *(T*)(&sa); } | |||
template <typename T> const T& as() const { return *(const T*)(&sa) ; } | template <typename T> const T& as() const { return *(const T*)(&sa) ; } | |||
string toString(bool includePort=true) const; | std::string toString(bool includePort=true) const; | |||
/** | /** | |||
* @return one of AF_INET, AF_INET6, or AF_UNIX | * @return one of AF_INET, AF_INET6, or AF_UNIX | |||
*/ | */ | |||
sa_family_t getType() const; | sa_family_t getType() const; | |||
unsigned getPort() const; | unsigned getPort() const; | |||
string getAddr() const; | std::string getAddr() const; | |||
bool isLocalHost() const; | bool isLocalHost() const; | |||
bool operator==(const SockAddr& r) const; | bool operator==(const SockAddr& r) const; | |||
bool operator!=(const SockAddr& r) const; | bool operator!=(const SockAddr& r) const; | |||
bool operator<(const SockAddr& r) const; | bool operator<(const SockAddr& r) const; | |||
const sockaddr* raw() const {return (sockaddr*)&sa;} | const sockaddr* raw() const {return (sockaddr*)&sa;} | |||
sockaddr* raw() {return (sockaddr*)&sa;} | sockaddr* raw() {return (sockaddr*)&sa;} | |||
socklen_t addressSize; | socklen_t addressSize; | |||
private: | private: | |||
struct sockaddr_storage sa; | struct sockaddr_storage sa; | |||
}; | }; | |||
extern SockAddr unknownAddress; // ( "0.0.0.0", 0 ) | extern SockAddr unknownAddress; // ( "0.0.0.0", 0 ) | |||
/** this is not cache and does a syscall */ | /** this is not cache and does a syscall */ | |||
string getHostName(); | std::string getHostName(); | |||
/** this is cached, so if changes during the process lifetime | /** this is cached, so if changes during the process lifetime | |||
* will be stale */ | * will be stale */ | |||
string getHostNameCached(); | std::string getHostNameCached(); | |||
string prettyHostName(); | std::string prettyHostName(); | |||
/** | /** | |||
* thrown by Socket and SockAddr | * thrown by Socket and SockAddr | |||
*/ | */ | |||
class SocketException : public DBException { | class SocketException : public DBException { | |||
public: | public: | |||
const enum Type { CLOSED , RECV_ERROR , SEND_ERROR, RECV_TIMEOUT, S END_TIMEOUT, FAILED_STATE, CONNECT_ERROR } _type; | const enum Type { CLOSED , RECV_ERROR , SEND_ERROR, RECV_TIMEOUT, S END_TIMEOUT, FAILED_STATE, CONNECT_ERROR } _type; | |||
SocketException( Type t , const std::string& server , int code = 90 01 , const std::string& extra="" ) | SocketException( Type t , const std::string& server , int code = 90 01 , const std::string& extra="" ) | |||
: DBException( (string)"socket exception [" + _getStringType( t ) + "] for " + server, code ), | : DBException( std::string("socket exception [") + _getStringT ype( t ) + "] for " + server, code ), | |||
_type(t), | _type(t), | |||
_server(server), | _server(server), | |||
_extra(extra) | _extra(extra) | |||
{} | {} | |||
virtual ~SocketException() throw() {} | virtual ~SocketException() throw() {} | |||
bool shouldPrint() const { return _type != CLOSED; } | bool shouldPrint() const { return _type != CLOSED; } | |||
virtual string toString() const; | virtual std::string toString() const; | |||
virtual const std::string* server() const { return &_server; } | virtual const std::string* server() const { return &_server; } | |||
private: | private: | |||
// TODO: Allow exceptions better control over their messages | // TODO: Allow exceptions better control over their messages | |||
static string _getStringType( Type t ){ | static std::string _getStringType( Type t ){ | |||
switch (t) { | switch (t) { | |||
case CLOSED: return "CLOSED"; | case CLOSED: return "CLOSED"; | |||
case RECV_ERROR: return "RECV_ERROR"; | case RECV_ERROR: return "RECV_ERROR"; | |||
case SEND_ERROR: return "SEND_ERROR"; | case SEND_ERROR: return "SEND_ERROR"; | |||
case RECV_TIMEOUT: return "RECV_TIMEOUT"; | case RECV_TIMEOUT: return "RECV_TIMEOUT"; | |||
case SEND_TIMEOUT: return "SEND_TIMEOUT"; | case SEND_TIMEOUT: return "SEND_TIMEOUT"; | |||
case FAILED_STATE: return "FAILED_STATE"; | case FAILED_STATE: return "FAILED_STATE"; | |||
case CONNECT_ERROR: return "CONNECT_ERROR"; | case CONNECT_ERROR: return "CONNECT_ERROR"; | |||
default: return "UNKNOWN"; // should never happe n | default: return "UNKNOWN"; // should never happe n | |||
} | } | |||
} | } | |||
string _server; | std::string _server; | |||
string _extra; | std::string _extra; | |||
}; | }; | |||
/** | /** | |||
* thin wrapped around file descriptor and system calls | * thin wrapped around file descriptor and system calls | |||
* todo: ssl | * todo: ssl | |||
*/ | */ | |||
class Socket : boost::noncopyable { | class Socket { | |||
MONGO_DISALLOW_COPYING(Socket); | ||||
public: | public: | |||
static const int errorPollIntervalSecs; | static const int errorPollIntervalSecs; | |||
Socket(int sock, const SockAddr& farEnd); | Socket(int sock, const SockAddr& farEnd); | |||
/** In some cases the timeout will actually be 2x this value - eg w e do a partial send, | /** In some cases the timeout will actually be 2x this value - eg w e do a partial send, | |||
then the timeout fires, then we try to send again, then the tim eout fires again with | then the timeout fires, then we try to send again, then the tim eout fires again with | |||
no data sent, then we detect that the other side is down. | no data sent, then we detect that the other side is down. | |||
Generally you don't want a timeout, you should be very prepared for errors if you set one. | Generally you don't want a timeout, you should be very prepared for errors if you set one. | |||
*/ | */ | |||
Socket(double so_timeout = 0, logger::LogSeverity logLevel = logger ::LogSeverity::Log() ); | Socket(double so_timeout = 0, logger::LogSeverity logLevel = logger ::LogSeverity::Log() ); | |||
~Socket(); | ~Socket(); | |||
bool connect(SockAddr& farEnd); | bool connect(SockAddr& farEnd); | |||
void close(); | void close(); | |||
void send( const char * data , int len, const char *context ); | void send( const char * data , int len, const char *context ); | |||
void send( const vector< pair< char *, int > > &data, const char *c ontext ); | void send( const std::vector< std::pair< char *, int > > &data, con st char *context ); | |||
// 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 ); | |||
logger::LogSeverity getLogLevel() const { return _logLevel; } | logger::LogSeverity getLogLevel() const { return _logLevel; } | |||
void setLogLevel( logger::LogSeverity ll ) { _logLevel = ll; } | void setLogLevel( logger::LogSeverity ll ) { _logLevel = ll; } | |||
SockAddr remoteAddr() const { return _remote; } | SockAddr remoteAddr() const { return _remote; } | |||
string remoteString() const { return _remote.toString(); } | std::string remoteString() const { return _remote.toString(); } | |||
unsigned remotePort() const { return _remote.getPort(); } | unsigned remotePort() const { return _remote.getPort(); } | |||
SockAddr localAddr() const { return _local; } | ||||
void clearCounters() { _bytesIn = 0; _bytesOut = 0; } | void clearCounters() { _bytesIn = 0; _bytesOut = 0; } | |||
long long getBytesIn() const { return _bytesIn; } | long long getBytesIn() const { return _bytesIn; } | |||
long long getBytesOut() const { return _bytesOut; } | long long getBytesOut() const { return _bytesOut; } | |||
void setTimeout( double secs ); | void setTimeout( double secs ); | |||
bool isStillConnected(); | bool isStillConnected(); | |||
#ifdef MONGO_SSL | #ifdef MONGO_SSL | |||
/** secures inline */ | /** secures inline */ | |||
void secure( SSLManagerInterface* ssl ); | void secure( SSLManagerInterface* ssl ); | |||
skipping to change at line 246 | skipping to change at line 254 | |||
* @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(); | |||
/** 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 std::vector< std::pair< char *, int > > &data, co nst char *context ); | |||
/** raw send, same semantics as ::send */ | /** raw send, same semantics as ::send */ | |||
int _send( const char * data , int len ); | 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); | void _handleRecvError(int ret, int len, int* retries); | |||
MONGO_COMPILER_NORETURN void _handleSendError(int ret, const char* context); | MONGO_COMPILER_NORETURN void _handleSendError(int ret, const char* context); | |||
int _fd; | int _fd; | |||
uint64_t _fdCreationMicroSec; | uint64_t _fdCreationMicroSec; | |||
SockAddr _local; | ||||
SockAddr _remote; | SockAddr _remote; | |||
double _timeout; | double _timeout; | |||
long long _bytesIn; | long long _bytesIn; | |||
long long _bytesOut; | long long _bytesOut; | |||
time_t _lastValidityCheckAtSecs; | time_t _lastValidityCheckAtSecs; | |||
#ifdef MONGO_SSL | #ifdef MONGO_SSL | |||
SSL* _ssl; | SSL* _ssl; | |||
SSLManagerInterface* _sslManager; | SSLManagerInterface* _sslManager; | |||
End of changes. 20 change blocks. | ||||
18 lines changed or deleted | 27 lines changed or added | |||
strategy.h | strategy.h | |||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
class Strategy { | class Strategy { | |||
public: | public: | |||
Strategy() {} | Strategy() {} | |||
virtual ~Strategy() {} | virtual ~Strategy() {} | |||
virtual void queryOp( Request& r ) = 0; | virtual void queryOp( Request& r ) = 0; | |||
virtual void getMore( Request& r ) = 0; | virtual void getMore( Request& r ) = 0; | |||
virtual void writeOp( int op , Request& r ) = 0; | virtual void writeOp( int op , Request& r ) = 0; | |||
void insert( const Shard& shard , const char * ns , const BSONObj& obj , int flags=0 , bool safe=false ); | void insert( const Shard& shard , const char * ns , const BSONObj& obj , int flags=0 , bool safe=false ); | |||
virtual void commandOp( const string& db, const BSONObj& command, i | struct CommandResult { | |||
nt options, | Shard shardTarget; | |||
const string& versionedNS, const BSONObj& f | ConnectionString target; | |||
ilter, | BSONObj result; | |||
map<Shard,BSONObj>& results ) | }; | |||
virtual void commandOp( const string& db, | ||||
const BSONObj& command, | ||||
int options, | ||||
const string& versionedNS, | ||||
const BSONObj& targetingQuery, | ||||
vector<CommandResult>* results ) | ||||
{ | { | |||
// Only call this from sharded, for now. | // Only call this from sharded, for now. | |||
// 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; | |||
End of changes. 1 change blocks. | ||||
5 lines changed or deleted | 12 lines changed or added | |||
string_data.h | string_data.h | |||
---|---|---|---|---|
skipping to change at line 138 | skipping to change at line 138 | |||
/** | /** | |||
* Functor compatible with std::hash for std::unordered_{map,set} | * Functor compatible with std::hash for std::unordered_{map,set} | |||
* Warning: The hash function is subject to change. Do not use in c ases where hashes need | * Warning: The hash function is subject to change. Do not use in c ases where hashes need | |||
* to be consistent across versions. | * to be consistent across versions. | |||
*/ | */ | |||
struct Hasher { | struct Hasher { | |||
size_t operator() (const StringData& str) const; | size_t operator() (const StringData& str) const; | |||
}; | }; | |||
// | ||||
// iterators | ||||
// | ||||
typedef const char* const_iterator; | ||||
const_iterator begin() const { return rawData(); } | ||||
const_iterator end() const { return rawData() + size(); } | ||||
private: | private: | |||
const char* _data; // is not guaranted to be null terminated (see "notes" 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); | |||
} | } | |||
} | } | |||
}; | }; | |||
skipping to change at line 177 | skipping to change at line 186 | |||
} | } | |||
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) ; | std::ostream& operator<<(std::ostream& stream, const StringData& value) ; | |||
} // namespace mongo | } // namespace mongo | |||
#include "string_data-inl.h" | #include "mongo/base/string_data-inl.h" | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 9 lines changed or added | |||
synchronization.h | synchronization.h | |||
---|---|---|---|---|
skipping to change at line 41 | skipping to change at line 41 | |||
class Notification : boost::noncopyable { | class Notification : boost::noncopyable { | |||
public: | public: | |||
Notification(); | Notification(); | |||
/* | /* | |||
* Blocks until the method 'notifyOne()' is called. | * Blocks until the method 'notifyOne()' is called. | |||
*/ | */ | |||
void waitToBeNotified(); | void waitToBeNotified(); | |||
/* | /* | |||
* Blocks until the method 'notifyOne()' is called or the time inte | ||||
rval elapses. | ||||
* Returns true if notified, false if timeout. | ||||
*/ | ||||
bool timedWaitToBeNotified( int millis ); | ||||
/* | ||||
* Notifies the waiter of '*this' that it can proceed. Can only be called once. | * Notifies the waiter of '*this' that it can proceed. Can only be called once. | |||
*/ | */ | |||
void notifyOne(); | void notifyOne(); | |||
private: | private: | |||
mongo::mutex _mutex; // protects state below | mongo::mutex _mutex; // protects state below | |||
unsigned long long lookFor; | unsigned long long lookFor; | |||
unsigned long long cur; | unsigned long long cur; | |||
boost::condition _condition; // cond over _notified being true | boost::condition _condition; // cond over _notified being true | |||
}; | }; | |||
End of changes. 1 change blocks. | ||||
7 lines changed or deleted | 0 lines changed or added | |||
time_support.h | time_support.h | |||
---|---|---|---|---|
skipping to change at line 23 | skipping to change at line 23 | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. | |||
* See the License for the specific language governing permissions and | * See the License for the specific language governing permissions and | |||
* limitations under the License. | * limitations under the License. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <ctime> | #include <ctime> | |||
#include <string> | #include <string> | |||
#include <boost/thread/xtime.hpp> | #include <boost/thread/xtime.hpp> | |||
#include <boost/version.hpp> | ||||
#include "mongo/bson/util/misc.h" // Date_t | ||||
namespace mongo { | namespace mongo { | |||
void time_t_to_Struct(time_t t, struct tm * buf , bool local = false ); | void time_t_to_Struct(time_t t, struct tm * buf , bool local = false ); | |||
std::string time_t_to_String(time_t t); | ||||
std::string time_t_to_String_short(time_t t); | ||||
/** | struct Date_t { | |||
* Gets the current time string (in fixed width) in UTC. Sample format: | // TODO: make signed (and look for related TODO's) | |||
* | unsigned long long millis; | |||
* Wed Oct 31 13:34:47.996 | Date_t(): millis(0) {} | |||
* | Date_t(unsigned long long m): millis(m) {} | |||
* @param timeStr pointer to the buffer to set the string - empirically | operator unsigned long long&() { return millis; } | |||
, 64 bytes is enough for | operator const unsigned long long&() const { return millis; } | |||
* the buffer, 26 is not. | void toTm (tm *buf); | |||
*/ | std::string toString() const; | |||
void curTimeString(char* timeStr); | time_t toTimeT() const; | |||
int64_t asInt64() const { | ||||
return static_cast<int64_t>(millis); | ||||
} | ||||
}; | ||||
// uses ISO 8601 dates without trailing Z | // uses ISO 8601 dates without trailing Z | |||
// colonsOk should be false when creating filenames | // colonsOk should be false when creating filenames | |||
std::string terseCurrentTime(bool colonsOk=true); | std::string terseCurrentTime(bool colonsOk=true); | |||
/** | ||||
* Formats "time" according to the ISO 8601 extended form standard, inc | ||||
luding date, | ||||
* and time, in the UTC timezone. | ||||
* | ||||
* Sample format: "2013-07-23T18:42:14Z" | ||||
*/ | ||||
std::string timeToISOString(time_t time); | std::string timeToISOString(time_t time); | |||
/** | ||||
* Formats "date" according to the ISO 8601 extended form standard, inc | ||||
luding date, | ||||
* and time with milliseconds decimal component, in the UTC timezone. | ||||
* | ||||
* Sample format: "2013-07-23T18:42:14.072Z" | ||||
*/ | ||||
std::string dateToISOStringUTC(Date_t date); | ||||
/** | ||||
* Formats "date" according to the ISO 8601 extended form standard, inc | ||||
luding date, | ||||
* and time with milliseconds decimal component, in the local timezone. | ||||
* | ||||
* Sample format: "2013-07-23T18:42:14.072-05:00" | ||||
*/ | ||||
std::string dateToISOStringLocal(Date_t date); | ||||
/** | ||||
* Formats "date" in fixed width in the local time zone. | ||||
* | ||||
* Sample format: "Wed Oct 31 13:34:47.996" | ||||
*/ | ||||
std::string dateToCtimeString(Date_t date); | ||||
boost::gregorian::date currentDate(); | boost::gregorian::date currentDate(); | |||
// parses time of day in "hh:mm" format assuming 'hh' is 00-23 | // parses time of day in "hh:mm" format assuming 'hh' is 00-23 | |||
bool toPointInTime( const std::string& str , boost::posix_time::ptime* timeOfDay ); | bool toPointInTime( const std::string& str , boost::posix_time::ptime* timeOfDay ); | |||
void sleepsecs(int s); | void sleepsecs(int s); | |||
void sleepmillis(long long ms); | void sleepmillis(long long ms); | |||
void sleepmicros(long long micros); | void sleepmicros(long long micros); | |||
class Backoff { | class Backoff { | |||
End of changes. 5 change blocks. | ||||
12 lines changed or deleted | 49 lines changed or added | |||
tool.h | tool.h | |||
---|---|---|---|---|
skipping to change at line 21 | skipping to change at line 21 | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Lice nse | * You should have received a copy of the GNU Affero General Public Lice nse | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
// Tool.h | // Tool.h | |||
#pragma once | #pragma once | |||
#include <string> | ||||
#include <boost/program_options.hpp> | #include <boost/program_options.hpp> | |||
#include <string> | ||||
#if defined(_WIN32) | #if defined(_WIN32) | |||
#include <io.h> | #include <io.h> | |||
#endif | #endif | |||
#include "db/instance.h" | #include "mongo/db/instance.h" | |||
#include "db/matcher.h" | #include "mongo/db/matcher.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 , | |||
LOCAL_SERVER = 1 << 2 , | LOCAL_SERVER = 1 << 2 , | |||
SPECIFY_DBCOL = 1 << 3 , | SPECIFY_DBCOL = 1 << 3 , | |||
ALL = REMOTE_SERVER | LOCAL_SERVER | SPECIFY_DBCOL | ALL = REMOTE_SERVER | LOCAL_SERVER | SPECIFY_DBCOL | |||
}; | }; | |||
Tool( string name , DBAccess access=ALL, string defaultDB="test" , | Tool( string name , DBAccess access=ALL, string defaultDB="test" , | |||
string defaultCollection="", bool usesstdout=true, bool quiet =false); | string defaultCollection="", bool usesstdout=true, bool quiet =false); | |||
virtual ~Tool(); | virtual ~Tool(); | |||
int main( int argc , char ** argv ); | static auto_ptr<Tool> (*createInstance)(); | |||
int main( int argc , char ** argv, char ** envp ); | ||||
boost::program_options::options_description_easy_init add_options() { | boost::program_options::options_description_easy_init add_options() { | |||
return _options->add_options(); | return _options->add_options(); | |||
} | } | |||
boost::program_options::options_description_easy_init add_hidden_op tions() { | boost::program_options::options_description_easy_init add_hidden_op tions() { | |||
return _hidden_options->add_options(); | return _hidden_options->add_options(); | |||
} | } | |||
void addPositionArg( const char * name , int pos ) { | void addPositionArg( const char * name , int pos ) { | |||
_positonalOptions.add( name , pos ); | _positonalOptions.add( name , pos ); | |||
} | } | |||
skipping to change at line 165 | skipping to change at line 166 | |||
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 ); | |||
}; | }; | |||
} | } | |||
#define REGISTER_MONGO_TOOL(TYPENAME) \ | ||||
auto_ptr<Tool> createInstanceOfThisTool() {return auto_ptr<Tool>(new TY | ||||
PENAME());} \ | ||||
auto_ptr<Tool> (*Tool::createInstance)() = createInstanceOfThisTool; | ||||
End of changes. 5 change blocks. | ||||
5 lines changed or deleted | 6 lines changed or added | |||
trace.h | trace.h | |||
---|---|---|---|---|
skipping to change at line 22 | skipping to change at line 22 | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public License | * You should have received a copy of the GNU Affero General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/pch.h" | |||
#include <boost/unordered_map.hpp> | #include <boost/unordered_map.hpp> | |||
#include "util/concurrency/rwlock.h" | #include "mongo/util/concurrency/rwlock.h" | |||
namespace mongo { | namespace mongo { | |||
class Trace : | class Trace : | |||
public boost::noncopyable { | public boost::noncopyable { | |||
public: | public: | |||
#ifdef LATER | #ifdef LATER | |||
/** | /** | |||
Set the traces with the given names. | Set the traces with the given names. | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
type_config_version.h | type_config_version.h | |||
---|---|---|---|---|
skipping to change at line 122 | skipping to change at line 122 | |||
void setMinCompatibleVersion(const int minCompatibleVersion) { | void setMinCompatibleVersion(const int minCompatibleVersion) { | |||
_minCompatibleVersion = minCompatibleVersion; | _minCompatibleVersion = minCompatibleVersion; | |||
_isMinCompatibleVersionSet = true; | _isMinCompatibleVersionSet = true; | |||
} | } | |||
void unsetMinCompatibleVersion() { _isMinCompatibleVersionSet = fal se; } | void unsetMinCompatibleVersion() { _isMinCompatibleVersionSet = fal se; } | |||
bool isMinCompatibleVersionSet() const { return _isMinCompatibleVer sionSet; } | bool isMinCompatibleVersionSet() const { return _isMinCompatibleVer sionSet; } | |||
// Calling get*() methods when the member is not set results in und efined behavior | // Calling get*() methods when the member is not set results in und efined behavior | |||
const int getMinCompatibleVersion() const { | int getMinCompatibleVersion() const { | |||
dassert(_isMinCompatibleVersionSet); | dassert(_isMinCompatibleVersionSet); | |||
return _minCompatibleVersion; | return _minCompatibleVersion; | |||
} | } | |||
void setCurrentVersion(const int currentVersion) { | void setCurrentVersion(const int currentVersion) { | |||
_currentVersion = currentVersion; | _currentVersion = currentVersion; | |||
_isCurrentVersionSet = true; | _isCurrentVersionSet = true; | |||
} | } | |||
void unsetCurrentVersion() { _isCurrentVersionSet = false; } | void unsetCurrentVersion() { _isCurrentVersionSet = false; } | |||
bool isCurrentVersionSet() const { return _isCurrentVersionSet; } | bool isCurrentVersionSet() const { return _isCurrentVersionSet; } | |||
// Calling get*() methods when the member is not set results in und efined behavior | // Calling get*() methods when the member is not set results in und efined behavior | |||
const int getCurrentVersion() const { | int getCurrentVersion() const { | |||
dassert(_isCurrentVersionSet); | dassert(_isCurrentVersionSet); | |||
return _currentVersion; | return _currentVersion; | |||
} | } | |||
void setExcludingMongoVersions(const BSONArray& excludingMongoVersi ons) { | void setExcludingMongoVersions(const BSONArray& excludingMongoVersi ons) { | |||
_excludingMongoVersions = excludingMongoVersions; | _excludingMongoVersions = excludingMongoVersions; | |||
_isExcludingMongoVersionsSet = true; | _isExcludingMongoVersionsSet = true; | |||
} | } | |||
void unsetExcludingMongoVersions() { _isExcludingMongoVersionsSet = false; } | void unsetExcludingMongoVersions() { _isExcludingMongoVersionsSet = false; } | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
type_locks.h | type_locks.h | |||
---|---|---|---|---|
skipping to change at line 136 | skipping to change at line 136 | |||
void setState(const int state) { | void setState(const int state) { | |||
_state = state; | _state = state; | |||
_isStateSet = true; | _isStateSet = true; | |||
} | } | |||
void unsetState() { _isStateSet = false; } | void unsetState() { _isStateSet = false; } | |||
bool isStateSet() const { return _isStateSet; } | bool isStateSet() const { return _isStateSet; } | |||
// Calling get*() methods when the member is not set results in und efined behavior | // Calling get*() methods when the member is not set results in und efined behavior | |||
const int getState() const { | int getState() const { | |||
dassert(_isStateSet); | dassert(_isStateSet); | |||
return _state; | return _state; | |||
} | } | |||
// Optional Fields | // Optional Fields | |||
void setProcess(StringData& process) { | void setProcess(StringData& process) { | |||
_process = process.toString(); | _process = process.toString(); | |||
_isProcessSet = true; | _isProcessSet = true; | |||
} | } | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
type_mongos.h | type_mongos.h | |||
---|---|---|---|---|
skipping to change at line 151 | skipping to change at line 151 | |||
void setUp(const int up) { | void setUp(const int up) { | |||
_up = up; | _up = up; | |||
_isUpSet = true; | _isUpSet = true; | |||
} | } | |||
void unsetUp() { _isUpSet = false; } | void unsetUp() { _isUpSet = false; } | |||
bool isUpSet() const { return _isUpSet; } | bool isUpSet() const { return _isUpSet; } | |||
// Calling get*() methods when the member is not set results in und efined behavior | // Calling get*() methods when the member is not set results in und efined behavior | |||
const int getUp() const { | int getUp() const { | |||
dassert(_isUpSet); | dassert(_isUpSet); | |||
return _up; | return _up; | |||
} | } | |||
void setWaiting(const bool waiting) { | void setWaiting(const bool waiting) { | |||
_waiting = waiting; | _waiting = waiting; | |||
_isWaitingSet = true; | _isWaitingSet = true; | |||
} | } | |||
void unsetWaiting() { _isWaitingSet = false; } | void unsetWaiting() { _isWaitingSet = false; } | |||
bool isWaitingSet() const { return _isWaitingSet; } | bool isWaitingSet() const { return _isWaitingSet; } | |||
// Calling get*() methods when the member is not set results in und efined behavior | // Calling get*() methods when the member is not set results in und efined behavior | |||
const bool getWaiting() const { | bool getWaiting() const { | |||
dassert(_isWaitingSet); | dassert(_isWaitingSet); | |||
return _waiting; | return _waiting; | |||
} | } | |||
// Optional Fields | // Optional Fields | |||
void setMongoVersion(const StringData& mongoVersion) { | void setMongoVersion(const StringData& mongoVersion) { | |||
_mongoVersion = mongoVersion.toString(); | _mongoVersion = mongoVersion.toString(); | |||
_isMongoVersionSet = true; | _isMongoVersionSet = true; | |||
} | } | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 2 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. | ||||
2 lines changed or deleted | 0 lines changed or added | |||
update.h | update.h | |||
---|---|---|---|---|
skipping to change at line 19 | skipping to change at line 19 | |||
* | * | |||
* This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Lice nse | * You should have received a copy of the GNU Affero General Public Lice nse | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#include "mongo/pch.h" | #pragma once | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/curop.h" | #include "mongo/db/curop.h" | |||
#include "mongo/db/ops/update_request.h" | ||||
#include "mongo/db/ops/update_result.h" | ||||
#include "mongo/db/query_plan_selection_policy.h" | #include "mongo/db/query_plan_selection_policy.h" | |||
namespace mongo { | namespace mongo { | |||
// ---------- public ------------- | class UpdateDriver; | |||
struct UpdateResult { | UpdateResult update(const UpdateRequest& request, OpDebug* opDebug); | |||
const bool existing; // if existing objects were modified | ||||
const bool mod; // was this a $ mod | UpdateResult update(const UpdateRequest& request, OpDebug* opDebug, Upd | |||
const long long num; // how many objects touched | ateDriver* driver); | |||
OID upserted; // if something was upserted, the new _id of the obj | ||||
ect | ||||
UpdateResult( bool e, bool m, unsigned long long n , const BSONObj& | ||||
upsertedObject ) | ||||
: existing(e) , mod(m), num(n) { | ||||
upserted.clear(); | ||||
BSONElement id = upsertedObject["_id"]; | ||||
if ( ! e && n == 1 && id.type() == jstOID ) { | ||||
upserted = id.OID(); | ||||
} | ||||
} | ||||
}; | ||||
class RemoveSaver; | ||||
/** Returns true if updates are supposed to be handle by the new update | ||||
framework */ | ||||
bool isNewUpdateFrameworkEnabled(); | ||||
/* returns true if an existing object was updated, false if no existing | ||||
object was found. | ||||
multi - update multiple objects - mostly useful with things like $se | ||||
t | ||||
su - allow access to system namespaces (super user) | ||||
*/ | ||||
UpdateResult updateObjects(const char* ns, | ||||
const BSONObj& updateobj, | ||||
const BSONObj& pattern, | ||||
bool upsert, | ||||
bool multi, | ||||
bool logop, | ||||
OpDebug& debug, | ||||
bool fromMigrate = false, | ||||
const QueryPlanSelectionPolicy& planPolicy = | ||||
QueryPlanSelectionPolicy::any()); | ||||
/* | ||||
* Similar to updateObjects but not strict about applying mods that can | ||||
fail during initial | ||||
* replication. | ||||
* | ||||
* Reference ticket: SERVER-4781 | ||||
*/ | ||||
UpdateResult updateObjectsForReplication(const char* ns, | ||||
const BSONObj& updateobj, | ||||
const BSONObj& pattern, | ||||
bool upsert, | ||||
bool multi, | ||||
bool logop, | ||||
OpDebug& debug, | ||||
bool fromMigrate = false, | ||||
const QueryPlanSelectionPolicy | ||||
& planPolicy = | ||||
QueryPlanSelectionPolicy:: | ||||
any()); | ||||
UpdateResult _updateObjects(bool su, | ||||
const char* ns, | ||||
const BSONObj& updateobj, | ||||
const BSONObj& pattern, | ||||
bool upsert, | ||||
bool multi, | ||||
bool logop, | ||||
OpDebug& debug, | ||||
RemoveSaver* rs = 0, | ||||
bool fromMigrate = false, | ||||
const QueryPlanSelectionPolicy& planPolicy | ||||
= QueryPlanSelectionPolicy::any(), | ||||
bool forReplication = false); | ||||
UpdateResult _updateObjectsNEW(bool su, | ||||
const char* ns, | ||||
const BSONObj& updateobj, | ||||
const BSONObj& pattern, | ||||
bool upsert, | ||||
bool multi, | ||||
bool logop, | ||||
OpDebug& debug, | ||||
RemoveSaver* rs = 0, | ||||
bool fromMigrate = false, | ||||
const QueryPlanSelectionPolicy& planPoli | ||||
cy | ||||
= QueryPlanSelectionPolicy::any(), | ||||
bool forReplication = false); | ||||
/** | /** | |||
* takes the from document and returns a new document | * takes the from document and returns a new document | |||
* after apply all the operators | * after apply all the operators | |||
* e.g. | * e.g. | |||
* applyUpdateOperators( BSON( "x" << 1 ) , BSON( "$inc" << BSON( "x" << 1 ) ) ); | * applyUpdateOperators( BSON( "x" << 1 ) , BSON( "$inc" << BSON( "x" << 1 ) ) ); | |||
* returns: { x : 2 } | * returns: { x : 2 } | |||
*/ | */ | |||
BSONObj applyUpdateOperators( const BSONObj& from, const BSONObj& opera tors ); | BSONObj applyUpdateOperators( const BSONObj& from, const BSONObj& opera tors ); | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 5 change blocks. | ||||
92 lines changed or deleted | 8 lines changed or added | |||
update_driver.h | update_driver.h | |||
---|---|---|---|---|
skipping to change at line 23 | skipping to change at line 23 | |||
* You should have received a copy of the GNU Affero General Public Lice nse | * You should have received a copy of the GNU Affero General Public Lice nse | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <string> | #include <string> | |||
#include <vector> | #include <vector> | |||
#include "mongo/base/status.h" | #include "mongo/base/status.h" | |||
#include "mongo/bson/mutable/document.h" | ||||
#include "mongo/db/index_set.h" | #include "mongo/db/index_set.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/ops/modifier_interface.h" | #include "mongo/db/ops/modifier_interface.h" | |||
namespace mongo { | namespace mongo { | |||
class UpdateDriver { | class UpdateDriver { | |||
public: | public: | |||
struct Options; | struct Options; | |||
UpdateDriver(const Options& opts); | UpdateDriver(const Options& opts); | |||
~UpdateDriver(); | ~UpdateDriver(); | |||
/** | /** | |||
* Returns OK and fills in '_mods' if 'updateExpr' is correct. In t | * Returns OK and fills in '_mods' if 'updateExpr' is correct. Othe | |||
hat case, take note | rwise returns an | |||
* that the collection that 'updateExpr' is built against have indi | * error status with a corresponding description. | |||
ces that encompass | ||||
* all fields present in 'indexedFields'. Otherwise returns an erro | ||||
r status with a | ||||
* corresponding description. | ||||
*/ | */ | |||
Status parse(const IndexPathSet& indexedFields, const BSONObj& upda teExpr); | Status parse(const BSONObj& updateExpr); | |||
/** | /** | |||
* Returns true and derives a BSONObj, 'newObj', from 'query'. | * Fills in document with any fields in the query which are valid. | |||
* | * | |||
* TODO: Elaborate on the logic used here. | * Valid fields include equality matches like "a":1, or "a.b":false | |||
* | ||||
* Each valid field will be expanded (from dot notation) and confli | ||||
cts will be | ||||
* checked for all fields added to the underlying document. | ||||
* | ||||
* Returns Status::OK() if the document can be used. If there are a | ||||
ny error or | ||||
* conflicts along the way then those errors will be returned. | ||||
*/ | ||||
static Status createFromQuery(const BSONObj& query, mutablebson::Do | ||||
cument& doc); | ||||
/** | ||||
* return a BSONObj with the _id field of the doc passed in, or the | ||||
doc itself. | ||||
* If no _id and multi, error. | ||||
*/ | */ | |||
bool createFromQuery(const BSONObj query, BSONObj* newObj) const; | BSONObj makeOplogEntryQuery(const BSONObj doc, bool multi) const; | |||
/** | /** | |||
* Returns OK and executes '_mods' over 'doc', generating 'newObj'. If any mod is | * Returns OK and executes '_mods' over 'doc', generating 'newObj'. If any mod is | |||
* positional, use 'matchedField' (index of the array item matched) . If doc allows | * positional, use 'matchedField' (index of the array item matched) . If doc allows | |||
* mods to be applied in place and no index updating is involved, t hen the mods may | * mods to be applied in place and no index updating is involved, t hen the mods may | |||
* be applied "in place" over 'doc'. | * be applied "in place" over 'doc'. | |||
* | * | |||
* If the driver's '_logOp' mode is turned on, and if 'logOpRec' is not NULL, fills in | * If the driver's '_logOp' mode is turned on, and if 'logOpRec' is not NULL, fills in | |||
* the latter with the oplog entry corresponding to the update. If '_mods' can't be | * the latter with the oplog entry corresponding to the update. If '_mods' can't be | |||
* applied, returns an error status with a corresponding descriptio n. | * applied, returns an error status with a corresponding descriptio n. | |||
skipping to change at line 72 | skipping to change at line 83 | |||
Status update(const StringData& matchedField, | Status update(const StringData& matchedField, | |||
mutablebson::Document* doc, | mutablebson::Document* doc, | |||
BSONObj* logOpRec); | BSONObj* logOpRec); | |||
// | // | |||
// Accessors | // Accessors | |||
// | // | |||
size_t numMods() const; | size_t numMods() const; | |||
bool dollarModMode() const; | bool isDocReplacement() const; | |||
bool modsAffectIndices() const; | bool modsAffectIndices() const; | |||
void refreshIndexKeys(const IndexPathSet& indexedFields); | ||||
bool multi() const; | bool multi() const; | |||
void setMulti(bool multi); | void setMulti(bool multi); | |||
bool upsert() const; | bool upsert() const; | |||
void setUpsert(bool upsert); | void setUpsert(bool upsert); | |||
bool logOp() const; | bool logOp() const; | |||
void setLogOp(bool logOp); | void setLogOp(bool logOp); | |||
ModifierInterface::Options modOptions() const; | ||||
void setModOptions(ModifierInterface::Options modOpts); | ||||
ModifierInterface::ExecInfo::UpdateContext context() const; | ModifierInterface::ExecInfo::UpdateContext context() const; | |||
void setContext(ModifierInterface::ExecInfo::UpdateContext context) ; | void setContext(ModifierInterface::ExecInfo::UpdateContext context) ; | |||
private: | private: | |||
/** Resets the state of the class associated with mods (not the err or state) */ | /** Resets the state of the class associated with mods (not the err or state) */ | |||
void clear(); | void clear(); | |||
// | // | |||
// immutable properties after parsing | // immutable properties after parsing | |||
// | // | |||
// Is there a list of $mod's on '_mods' or is it just full object r | // Is there a list of $mod's on '_mods' or is it just full object r | |||
eplacment? | eplacement? | |||
bool _dollarModMode; | bool _replacementMode; | |||
// Collection of update mod instances. Owned here. | // Collection of update mod instances. Owned here. | |||
vector<ModifierInterface*> _mods; | vector<ModifierInterface*> _mods; | |||
// What are the list of fields in the collection over which the upd ate is going to be | // What are the list of fields in the collection over which the upd ate is going to be | |||
// applied that participate in indices? | // applied that participate in indices? | |||
// | ||||
// TODO: Do we actually need to keep a copy of this? | ||||
IndexPathSet _indexedFields; | IndexPathSet _indexedFields; | |||
// | // | |||
// mutable properties after parsing | // mutable properties after parsing | |||
// | // | |||
// May this driver apply updates to several documents? | // May this driver apply updates to several documents? | |||
bool _multi; | bool _multi; | |||
// May this driver construct a new object if an update for a non-ex isting one is sent? | // May this driver construct a new object if an update for a non-ex isting one is sent? | |||
bool _upsert; | bool _upsert; | |||
// Should this driver generate an oplog record when it applies the update? | // Should this driver generate an oplog record when it applies the update? | |||
bool _logOp; | bool _logOp; | |||
// The options to initiate the mods with | ||||
ModifierInterface::Options _modOptions; | ||||
// Are any of the fields mentioned in the mods participating in any index? Is set anew | // Are any of the fields mentioned in the mods participating in any index? Is set anew | |||
// at each call to update. | // at each call to update. | |||
bool _affectIndices; | bool _affectIndices; | |||
// Is this update going to be an upsert? | // Is this update going to be an upsert? | |||
ModifierInterface::ExecInfo::UpdateContext _context; | ModifierInterface::ExecInfo::UpdateContext _context; | |||
mutablebson::Document _logDoc; | ||||
}; | }; | |||
struct UpdateDriver::Options { | struct UpdateDriver::Options { | |||
bool multi; | bool multi; | |||
bool upsert; | bool upsert; | |||
bool logOp; | bool logOp; | |||
ModifierInterface::Options modOptions; | ||||
Options() : multi(false), upsert(false), logOp(false) {} | Options() : multi(false), upsert(false), logOp(false), modOptions() {} | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 15 change blocks. | ||||
16 lines changed or deleted | 41 lines changed or added | |||
user.h | user.h | |||
---|---|---|---|---|
skipping to change at line 66 | skipping to change at line 66 | |||
* Returns the user name for this user. | * Returns the user name for this user. | |||
*/ | */ | |||
const UserName& getName() const; | const UserName& getName() const; | |||
/** | /** | |||
* Returns an iterator that can be used to get the list of roles th is user belongs to. | * Returns an iterator that can be used to get the list of roles th is user belongs to. | |||
*/ | */ | |||
const RoleNameIterator getRoles() const; | const RoleNameIterator getRoles() const; | |||
/** | /** | |||
* Returns the CredentialData for this user. | ||||
*/ | ||||
const CredentialData& getCredentials() const; | ||||
/** | ||||
* Gets the set of actions this user is allowed to perform on the g iven resource. | * Gets the set of actions this user is allowed to perform on the g iven resource. | |||
*/ | */ | |||
const ActionSet getActionsForResource(const std::string& resource) const; | const ActionSet getActionsForResource(const std::string& resource) const; | |||
/** | /** | |||
* Returns true if this copy of information about this user is stil l valid. If this returns | * Returns true if this copy of information about this user is stil l valid. If this returns | |||
* false, this object should no longer be used and should be return ed to the | * false, this object should no longer be used and should be return ed to the | |||
* AuthorizationManager and a new User object for this user should be requested. | * AuthorizationManager and a new User object for this user should be requested. | |||
*/ | */ | |||
bool isValid() const; | bool isValid() const; | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 5 lines changed or added | |||
value.h | value.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 "mongo/db/pipeline/value_internal.h" | #include "mongo/db/pipeline/value_internal.h" | |||
#include "mongo/platform/unordered_set.h" | ||||
namespace mongo { | namespace mongo { | |||
class BSONElement; | class BSONElement; | |||
class Builder; | ||||
/** A variant type that can hold any type of data representable in BSON | /** A variant type that can hold any type of data representable in BSON | |||
* | * | |||
* Small values are stored inline, but some values, such as large stri ngs, | * Small values are stored inline, but some values, such as large stri ngs, | |||
* are heap allocated. It has smart pointer capabilities built-in so i t is | * are heap allocated. It has smart pointer capabilities built-in so i t is | |||
* safe and recommended to pass these around and return them by value. | * safe and recommended to pass these around and return them by value. | |||
* | * | |||
* Values are immutable, but can be assigned. This means that once you have | * Values are immutable, but can be assigned. This means that once you have | |||
* a Value, you can be assured that none of the data in that Value wil l | * a Value, you can be assured that none of the data in that Value wil l | |||
* change. However if you have a non-const Value you replace it with | * change. However if you have a non-const Value you replace it with | |||
skipping to change at line 83 | skipping to change at line 83 | |||
explicit Value(const BSONSymbol& sym) : _storage(Symbol, sym.sy mbol) {} | explicit Value(const BSONSymbol& sym) : _storage(Symbol, sym.sy mbol) {} | |||
explicit Value(const BSONCode& code) : _storage(Code, code.cod e) {} | explicit Value(const BSONCode& code) : _storage(Code, code.cod e) {} | |||
explicit Value(const NullLabeler&) : _storage(jstNULL) {} // BSONNull | explicit Value(const NullLabeler&) : _storage(jstNULL) {} // BSONNull | |||
explicit Value(const UndefinedLabeler&) : _storage(Undefined) {} // BSONUndefined | explicit Value(const UndefinedLabeler&) : _storage(Undefined) {} // BSONUndefined | |||
explicit Value(const MinKeyLabeler&) : _storage(MinKey) {} // MINKEY | explicit Value(const MinKeyLabeler&) : _storage(MinKey) {} // MINKEY | |||
explicit Value(const MaxKeyLabeler&) : _storage(MaxKey) {} // MAXKEY | explicit Value(const MaxKeyLabeler&) : _storage(MaxKey) {} // MAXKEY | |||
explicit Value(const Date_t& date) | explicit Value(const Date_t& date) | |||
: _storage(Date, static_cast<long long>(date.millis)) // millis really signed | : _storage(Date, static_cast<long long>(date.millis)) // millis really signed | |||
{} | {} | |||
/** Creates an empty or zero value of specified type. | ||||
* This is currently the only way to create Undefined or Null Valu | ||||
es. | ||||
*/ | ||||
explicit Value(BSONType type); | ||||
// TODO: add an unsafe version that can share storage with the BSON Element | // TODO: add an unsafe version that can share storage with the BSON Element | |||
/// Deep-convert from BSONElement to Value | /// Deep-convert from BSONElement to Value | |||
explicit Value(const BSONElement& elem); | explicit Value(const BSONElement& elem); | |||
/** Construct a long or integer-valued Value. | /** Construct a long or integer-valued Value. | |||
* | * | |||
* Used when preforming arithmetic operations with int where the | * Used when preforming arithmetic operations with int where the | |||
* result may be too large and need to be stored as long. The Valu e | * result may be too large and need to be stored as long. The Valu e | |||
* will be an int if value fits, otherwise it will be a long. | * will be an int if value fits, otherwise it will be a long. | |||
*/ | */ | |||
skipping to change at line 203 | skipping to change at line 198 | |||
friend | friend | |||
bool operator==(const Value& v1, const Value& v2) { | bool operator==(const Value& v1, const Value& v2) { | |||
if (v1._storage.identical(v2._storage)) { | if (v1._storage.identical(v2._storage)) { | |||
// Simple case | // Simple case | |||
return true; | return true; | |||
} | } | |||
return (Value::compare(v1, v2) == 0); | return (Value::compare(v1, v2) == 0); | |||
} | } | |||
friend bool operator!=(const Value& v1, const Value& v2) { | ||||
return !(v1 == v2); | ||||
} | ||||
friend bool operator<(const Value& lhs, const Value& rhs) { | ||||
return (Value::compare(lhs, rhs) < 0); | ||||
} | ||||
/// This is for debugging, logging, etc. See getString() for how to extract a string. | /// This is for debugging, logging, etc. See getString() for how to extract a string. | |||
string toString() const; | string toString() const; | |||
friend ostream& operator << (ostream& out, const Value& v); | friend ostream& operator << (ostream& out, const Value& v); | |||
void swap(Value& rhs) { | void swap(Value& rhs) { | |||
_storage.swap(rhs._storage); | _storage.swap(rhs._storage); | |||
} | } | |||
/** Figure out what the widest of two numeric types is. | /** Figure out what the widest of two numeric types is. | |||
* | * | |||
skipping to change at line 261 | skipping to change at line 264 | |||
explicit Value(const ValueStorage& storage) :_storage(storage) {} | explicit Value(const ValueStorage& storage) :_storage(storage) {} | |||
// does no type checking | // does no type checking | |||
StringData getStringData() const; // May contain embedded NUL bytes | StringData getStringData() const; // May contain embedded NUL bytes | |||
ValueStorage _storage; | ValueStorage _storage; | |||
friend class MutableValue; // gets and sets _storage.genericRCPtr | friend class MutableValue; // gets and sets _storage.genericRCPtr | |||
}; | }; | |||
BOOST_STATIC_ASSERT(sizeof(Value) == 16); | BOOST_STATIC_ASSERT(sizeof(Value) == 16); | |||
typedef unordered_set<Value, Value::Hash> ValueSet; | ||||
} | } | |||
namespace std { | namespace std { | |||
// This is used by std::sort and others | // This is used by std::sort and others | |||
template <> | template <> | |||
inline void swap(mongo::Value& lhs, mongo::Value& rhs) { lhs.swap(rhs); } | inline void swap(mongo::Value& lhs, mongo::Value& rhs) { lhs.swap(rhs); } | |||
} | } | |||
/* ======================= INLINED IMPLEMENTATIONS ======================== == */ | /* ======================= INLINED IMPLEMENTATIONS ======================== == */ | |||
End of changes. 5 change blocks. | ||||
7 lines changed or deleted | 11 lines changed or added | |||
value_internal.h | value_internal.h | |||
---|---|---|---|---|
skipping to change at line 25 | skipping to change at line 25 | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <algorithm> | #include <algorithm> | |||
#include "bson/bsonobj.h" | #include "bson/bsonobj.h" | |||
#include "bson/bsontypes.h" | #include "bson/bsontypes.h" | |||
#include "bson/bsonmisc.h" | #include "bson/bsonmisc.h" | |||
#include "bson/oid.h" | #include "bson/oid.h" | |||
#include "util/intrusive_counter.h" | #include "util/intrusive_counter.h" | |||
#include "mongo/db/repl/optime.h" | #include "mongo/bson/optime.h" | |||
namespace mongo { | namespace mongo { | |||
class Document; | class Document; | |||
class DocumentStorage; | class DocumentStorage; | |||
class Value; | class Value; | |||
//TODO: a MutableVector, similar to MutableDocument | //TODO: a MutableVector, similar to MutableDocument | |||
/// A heap-allocated reference-counted std::vector | /// A heap-allocated reference-counted std::vector | |||
class RCVector : public RefCountable { | class RCVector : public RefCountable { | |||
public: | public: | |||
skipping to change at line 91 | skipping to change at line 91 | |||
memcpy(&oid, &o, sizeof(OID)); | memcpy(&oid, &o, sizeof(OID)); | |||
BOOST_STATIC_ASSERT(sizeof(OID) == sizeof(oid)); | BOOST_STATIC_ASSERT(sizeof(OID) == sizeof(oid)); | |||
} | } | |||
ValueStorage(const ValueStorage& rhs) { | ValueStorage(const ValueStorage& rhs) { | |||
memcpy(this, &rhs, sizeof(*this)); | memcpy(this, &rhs, sizeof(*this)); | |||
memcpyed(); | memcpyed(); | |||
} | } | |||
~ValueStorage() { | ~ValueStorage() { | |||
DEV verifyRefCountingIfShould(); | ||||
if (refCounter) | if (refCounter) | |||
intrusive_ptr_release(genericRCPtr); | intrusive_ptr_release(genericRCPtr); | |||
DEV memset(this, 0xee, sizeof(*this)); | DEV memset(this, 0xee, sizeof(*this)); | |||
} | } | |||
ValueStorage& operator= (ValueStorage rhsCopy) { | ValueStorage& operator= (ValueStorage rhsCopy) { | |||
this->swap(rhsCopy); | this->swap(rhsCopy); | |||
return *this; | return *this; | |||
} | } | |||
void swap(ValueStorage& rhs) { | void swap(ValueStorage& rhs) { | |||
// Don't need to update ref-counts because they will be the sam e in the end | // Don't need to update ref-counts because they will be the sam e in the end | |||
char temp[sizeof(ValueStorage)]; | char temp[sizeof(ValueStorage)]; | |||
memcpy(temp, this, sizeof(*this)); | memcpy(temp, this, sizeof(*this)); | |||
memcpy(this, &rhs, sizeof(*this)); | memcpy(this, &rhs, sizeof(*this)); | |||
memcpy(&rhs, temp, sizeof(*this)); | memcpy(&rhs, temp, sizeof(*this)); | |||
} | } | |||
/// Call this after memcpying to update ref counts if needed | /// Call this after memcpying to update ref counts if needed | |||
void memcpyed() const { | void memcpyed() const { | |||
DEV verifyRefCountingIfShould(); | ||||
if (refCounter) | if (refCounter) | |||
intrusive_ptr_add_ref(genericRCPtr); | intrusive_ptr_add_ref(genericRCPtr); | |||
} | } | |||
/// These are only to be called during Value construction on an emp ty Value | /// These are only to be called during Value construction on an emp ty Value | |||
void putString(const StringData& s); | void putString(const StringData& s); | |||
void putVector(const RCVector* v); | void putVector(const RCVector* v); | |||
void putDocument(const Document& d); | void putDocument(const Document& d); | |||
void putRegEx(const BSONRegEx& re); | void putRegEx(const BSONRegEx& re); | |||
void putBinData(const BSONBinData& bd) { | void putBinData(const BSONBinData& bd) { | |||
skipping to change at line 142 | skipping to change at line 144 | |||
putRefCountable(new RCCodeWScope(cws.code.toString(), cws.scope )); | putRefCountable(new RCCodeWScope(cws.code.toString(), cws.scope )); | |||
} | } | |||
void putRefCountable(intrusive_ptr<const RefCountable> ptr) { | void putRefCountable(intrusive_ptr<const RefCountable> ptr) { | |||
genericRCPtr = ptr.get(); | genericRCPtr = ptr.get(); | |||
if (genericRCPtr) { | if (genericRCPtr) { | |||
intrusive_ptr_add_ref(genericRCPtr); | intrusive_ptr_add_ref(genericRCPtr); | |||
refCounter = true; | refCounter = true; | |||
} | } | |||
DEV verifyRefCountingIfShould(); | ||||
} | } | |||
StringData getString() const { | StringData getString() const { | |||
if (shortStr) { | if (shortStr) { | |||
return StringData(shortStrStorage, shortStrSize); | return StringData(shortStrStorage, shortStrSize); | |||
} | } | |||
else { | else { | |||
dassert(typeid(*genericRCPtr) == typeid(const RCString)); | dassert(typeid(*genericRCPtr) == typeid(const RCString)); | |||
const RCString* stringPtr = static_cast<const RCString*>(ge nericRCPtr); | const RCString* stringPtr = static_cast<const RCString*>(ge nericRCPtr); | |||
return StringData(stringPtr->c_str(), stringPtr->size()); | return StringData(stringPtr->c_str(), stringPtr->size()); | |||
skipping to change at line 193 | skipping to change at line 196 | |||
void zero() { | void zero() { | |||
memset(this, 0, sizeof(*this)); | memset(this, 0, sizeof(*this)); | |||
} | } | |||
// Byte-for-byte identical | // Byte-for-byte identical | |||
bool identical(const ValueStorage& other) const { | bool identical(const ValueStorage& other) const { | |||
return (i64[0] == other.i64[0] | return (i64[0] == other.i64[0] | |||
&& i64[1] == other.i64[1]); | && i64[1] == other.i64[1]); | |||
} | } | |||
void verifyRefCountingIfShould() const; | ||||
// This data is public because this should only be used by Value wh ich would be a friend | // This data is public because this should only be used by Value wh ich would be a friend | |||
union { | union { | |||
struct { | struct { | |||
// byte 1 | // byte 1 | |||
signed char type; | signed char type; | |||
// byte 2 | // byte 2 | |||
struct { | struct { | |||
bool refCounter : 1; // true if we need to refCount | bool refCounter : 1; // true if we need to refCount | |||
bool shortStr : 1; // true if we are using short string s | bool shortStr : 1; // true if we are using short string s | |||
End of changes. 5 change blocks. | ||||
1 lines changed or deleted | 6 lines changed or added | |||
version.h | version.h | |||
---|---|---|---|---|
skipping to change at line 49 | skipping to change at line 49 | |||
void appendBuildInfo(BSONObjBuilder& result); | void appendBuildInfo(BSONObjBuilder& result); | |||
const char * gitVersion(); | const char * gitVersion(); | |||
const char * compiledJSEngine(); | const char * compiledJSEngine(); | |||
const char * allocator(); | const char * allocator(); | |||
const char * loaderFlags(); | const char * loaderFlags(); | |||
const char * compilerFlags(); | const char * compilerFlags(); | |||
void printGitVersion(); | void printGitVersion(); | |||
const std::string openSSLVersion(const std::string &prefix = "", const | ||||
std::string &suffix = ""); | ||||
void printOpenSSLVersion(); | ||||
std::string sysInfo(); | std::string sysInfo(); | |||
void printSysInfo(); | void printSysInfo(); | |||
void printAllocator(); | void printAllocator(); | |||
void show_warnings(); | void show_warnings(); | |||
} // namespace mongo | } // namespace mongo | |||
#endif // UTIL_VERSION_HEADER | #endif // UTIL_VERSION_HEADER | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 4 lines changed or added | |||
winutil.h | winutil.h | |||
---|---|---|---|---|
skipping to change at line 19 | skipping to change at line 19 | |||
// * | // * | |||
// * This program is distributed in the hope that it will be useful, | // * This program is distributed in the hope that it will be useful, | |||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of | // * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
// * GNU Affero General Public License for more details. | // * GNU Affero General Public License for more details. | |||
// * | // * | |||
// * You should have received a copy of the GNU Affero General Public Li cense | // * You should have received a copy of the GNU Affero General Public Li cense | |||
// * 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 "pch.h" | // #include "mongo/pch.h" | |||
#pragma once | #pragma once | |||
#if defined(_WIN32) | #if defined(_WIN32) | |||
#include <windows.h> | #include <windows.h> | |||
#include "text.h" | #include "text.h" | |||
namespace mongo { | namespace mongo { | |||
inline string GetWinErrMsg(DWORD err) { | inline string GetWinErrMsg(DWORD err) { | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
working_set.h | working_set.h | |||
---|---|---|---|---|
skipping to change at line 120 | skipping to change at line 120 | |||
struct WorkingSetMember { | struct WorkingSetMember { | |||
WorkingSetMember(); | WorkingSetMember(); | |||
enum MemberState { | enum MemberState { | |||
// Initial state. | // Initial state. | |||
INVALID, | INVALID, | |||
// Data is from 1 or more indices. | // Data is from 1 or more indices. | |||
LOC_AND_IDX, | LOC_AND_IDX, | |||
// Data is from a collection scan. | // Data is from a collection scan, or data is from an index sca n and was fetched. | |||
LOC_AND_UNOWNED_OBJ, | LOC_AND_UNOWNED_OBJ, | |||
// Data is from a fetch. | ||||
LOC_AND_OWNED_OBJ, | ||||
// DiskLoc has been invalidated, or the obj doesn't correspond to an on-disk document | // DiskLoc has been invalidated, or the obj doesn't correspond to an on-disk document | |||
// anymore (e.g. is a computed expression). | // anymore (e.g. is a computed expression). | |||
OWNED_OBJ, | OWNED_OBJ, | |||
}; | }; | |||
DiskLoc loc; | DiskLoc loc; | |||
BSONObj obj; | BSONObj obj; | |||
vector<IndexKeyDatum> keyData; | vector<IndexKeyDatum> keyData; | |||
MemberState state; | MemberState state; | |||
skipping to change at line 150 | skipping to change at line 147 | |||
/** | /** | |||
* getFieldDotted uses its state (obj or index data) to produce the field with the provided | * getFieldDotted uses its state (obj or index data) to produce the field with the provided | |||
* name. | * name. | |||
* | * | |||
* Returns true if there is the element is in an index key or in an (owned or unowned) | * Returns true if there is the element is in an index key or in an (owned or unowned) | |||
* object. *out is set to the element if so. | * object. *out is set to the element if so. | |||
* | * | |||
* Returns false otherwise. Returning false indicates a query plan ning error. | * Returns false otherwise. Returning false indicates a query plan ning error. | |||
*/ | */ | |||
bool getFieldDotted(const string& field, BSONElement* out); | bool getFieldDotted(const string& field, BSONElement* out) const; | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 3 change blocks. | ||||
5 lines changed or deleted | 2 lines changed or added | |||
working_set_common.h | working_set_common.h | |||
---|---|---|---|---|
skipping to change at line 26 | skipping to change at line 26 | |||
#pragma once | #pragma once | |||
namespace mongo { | namespace mongo { | |||
struct WorkingSetMember; | struct WorkingSetMember; | |||
class WorkingSetCommon { | class WorkingSetCommon { | |||
public: | public: | |||
/** | /** | |||
* Fetch an unowned copy of the BSONObj that the provided WSM refer | ||||
s to. Updates | ||||
* member->obj to refer to that unowned BSONObj. Requires a valid | ||||
DiskLoc. Does nothing if | ||||
* WSM has a valid obj already. | ||||
* | ||||
* Returns true if the fetch succeeded, false otherwise. | ||||
* | ||||
* Used in SORT and FETCH. | ||||
*/ | ||||
static bool fetch(WorkingSetMember* member); | ||||
/** | ||||
* Get an owned copy of the BSONObj the WSM refers to. | * Get an owned copy of the BSONObj the WSM refers to. | |||
* Requires either a valid BSONObj or valid DiskLoc. | * Requires either a valid BSONObj or valid DiskLoc. | |||
* Returns true if the fetch and invalidate succeeded, false otherw ise. | * Returns true if the fetch and invalidate succeeded, false otherw ise. | |||
*/ | */ | |||
static bool fetchAndInvalidateLoc(WorkingSetMember* member); | static bool fetchAndInvalidateLoc(WorkingSetMember* member); | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 1 change blocks. | ||||
13 lines changed or deleted | 0 lines changed or added | |||
writeback_listener.h | writeback_listener.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 "mongo/client/connpool.h" | ||||
#include "mongo/db/client.h" | ||||
#include "mongo/platform/unordered_map.h" | #include "mongo/platform/unordered_map.h" | |||
#include "mongo/platform/unordered_set.h" | #include "mongo/platform/unordered_set.h" | |||
#include "../client/connpool.h" | #include "mongo/util/background.h" | |||
#include "../util/background.h" | ||||
#include "../db/client.h" | ||||
namespace mongo { | namespace mongo { | |||
/* | /* | |||
* The writeback listener takes back write attempts that were made agai nst a wrong shard. | * The writeback listener takes back write attempts that were made agai nst a wrong shard. | |||
* (Wrong here in the sense that the target chunk moved before this mon gos had a chance to | * (Wrong here in the sense that the target chunk moved before this mon gos had a chance to | |||
* learn so.) It is responsible for reapplying these writes to the corr ect shard. | * learn so.) It is responsible for reapplying these writes to the corr ect shard. | |||
* | * | |||
* Runs (instantiated) on mongos. | * Runs (instantiated) on mongos. | |||
* Currently, there is one writebacklistener per shard. | * Currently, there is one writebacklistener per shard. | |||
End of changes. 2 change blocks. | ||||
3 lines changed or deleted | 3 lines changed or added | |||