summaryrefslogtreecommitdiff
path: root/src/mongo/db/clientcursor.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/clientcursor.h')
-rw-r--r--src/mongo/db/clientcursor.h624
1 files changed, 331 insertions, 293 deletions
diff --git a/src/mongo/db/clientcursor.h b/src/mongo/db/clientcursor.h
index d2482ffbfa9..a145802e985 100644
--- a/src/mongo/db/clientcursor.h
+++ b/src/mongo/db/clientcursor.h
@@ -36,306 +36,344 @@
namespace mongo {
- class ClientCursor;
- class Collection;
- class CursorManager;
- class RecoveryUnit;
+class ClientCursor;
+class Collection;
+class CursorManager;
+class RecoveryUnit;
- typedef long long CursorId; /* passed to the client so it can send back on getMore */
- static const CursorId INVALID_CURSOR_ID = -1; // But see SERVER-5726.
+typedef long long CursorId; /* passed to the client so it can send back on getMore */
+static const CursorId INVALID_CURSOR_ID = -1; // But see SERVER-5726.
+/**
+ * ClientCursor is a wrapper that represents a cursorid from our database application's
+ * perspective.
+ */
+class ClientCursor {
+ MONGO_DISALLOW_COPYING(ClientCursor);
+
+public:
/**
- * ClientCursor is a wrapper that represents a cursorid from our database application's
- * perspective.
+ * This ClientCursor constructor creates a cursorid that can be used with getMore and
+ * killCursors. "cursorManager" is the object that will manage the lifetime of this
+ * cursor, and "ns" is the namespace string that should be associated with this cursor (e.g.
+ * "test.foo", "test.$cmd.listCollections", etc).
*/
- class ClientCursor {
- MONGO_DISALLOW_COPYING(ClientCursor);
- public:
- /**
- * This ClientCursor constructor creates a cursorid that can be used with getMore and
- * killCursors. "cursorManager" is the object that will manage the lifetime of this
- * cursor, and "ns" is the namespace string that should be associated with this cursor (e.g.
- * "test.foo", "test.$cmd.listCollections", etc).
- */
- ClientCursor(CursorManager* cursorManager,
- PlanExecutor* exec,
- const std::string& ns,
- int qopts = 0,
- const BSONObj query = BSONObj(),
- bool isAggCursor = false);
-
- /**
- * This ClientCursor is used to track sharding state for the given collection.
- */
- explicit ClientCursor(const Collection* collection);
-
- //
- // Basic accessors
- //
-
- CursorId cursorid() const { return _cursorid; }
- std::string ns() const { return _ns; }
- CursorManager* cursorManager() const { return _cursorManager; }
- bool isAggCursor() const { return _isAggCursor; }
-
- //
- // Pinning functionality.
- //
-
- /**
- * Marks this ClientCursor as in use. unsetPinned() must be called before the destructor of
- * this ClientCursor is invoked.
- */
- void setPinned() { _isPinned = true; }
-
- /**
- * Marks this ClientCursor as no longer in use.
- */
- void unsetPinned() { _isPinned = false; }
-
- bool isPinned() const { return _isPinned; }
-
- /**
- * This is called when someone is dropping a collection or something else that
- * goes through killing cursors.
- * It removes the responsiilibty of de-registering from ClientCursor.
- * Responsibility for deleting the ClientCursor doesn't change from this call
- * see PlanExecutor::kill.
- */
- void kill();
-
- //
- // Timing and timeouts
- //
-
- /**
- * @param millis amount of idle passed time since last call
- * note called outside of locks (other than ccmutex) so care must be exercised
- */
- bool shouldTimeout( int millis );
- void setIdleTime( int millis );
- int idleTime() const { return _idleAgeMillis; }
-
- uint64_t getLeftoverMaxTimeMicros() const { return _leftoverMaxTimeMicros; }
- void setLeftoverMaxTimeMicros( uint64_t leftoverMaxTimeMicros ) {
- _leftoverMaxTimeMicros = leftoverMaxTimeMicros;
- }
-
- //
- // Replication-related stuff. TODO: Document and clean.
- //
-
- // Used to report replication position only in master-slave,
- // so we keep them as TimeStamp rather than OpTime.
- void updateSlaveLocation(OperationContext* txn);
- void slaveReadTill( const Timestamp& t ) { _slaveReadTill = t; }
- /** Just for testing. */
- Timestamp getSlaveReadTill() const { return _slaveReadTill; }
-
- //
- // Query-specific functionality that may be adapted for the PlanExecutor.
- //
-
- PlanExecutor* getExecutor() const { return _exec.get(); }
- int queryOptions() const { return _queryOptions; }
- const BSONObj& getQuery() const { return _query; }
-
- // Used by ops/query.cpp to stash how many results have been returned by a query.
- int pos() const { return _pos; }
- void incPos(int n) { _pos += n; }
- void setPos(int n) { _pos = n; }
-
- static long long totalOpen();
-
- //
- // Storage engine state for getMore.
- //
-
- bool hasRecoveryUnit() const { return _ownedRU.get() || _unownedRU; }
-
- /**
- *
- * If a ClientCursor is created via DBDirectClient, it uses the same storage engine
- * context as the DBDirectClient caller. We store this context in _unownedRU. We use
- * this to verify that all further callers use the same RecoveryUnit.
- *
- * Once a ClientCursor has an unowned RecoveryUnit, it will always have one.
- *
- * Sets the unowned RecoveryUnit to 'ru'. Does NOT take ownership of the pointer.
- */
- void setUnownedRecoveryUnit(RecoveryUnit* ru);
-
- /**
- * Return the unowned RecoveryUnit. 'this' does not own pointer and therefore cannot
- * transfer ownership.
- */
- RecoveryUnit* getUnownedRecoveryUnit() const;
-
- /**
- * If a ClientCursor is created via a client request, we bind its lifetime to the
- * ClientCursor's by storing it un _ownedRU. In order to execute the query over repeated
- * network requests, we have to keep the execution state around.
- */
-
- /**
- * Set the owned recovery unit to 'ru'. Takes ownership of it. If there is a previous
- * owned recovery unit, it is deleted.
- */
- void setOwnedRecoveryUnit(RecoveryUnit* ru);
-
- /**
- * Returns the owned recovery unit. Ownership is transferred to the caller.
- */
- RecoveryUnit* releaseOwnedRecoveryUnit();
-
- private:
- friend class CursorManager;
- friend class ClientCursorPin;
-
- /**
- * Only friends are allowed to destroy ClientCursor objects.
- */
- ~ClientCursor();
-
- /**
- * Initialization common between both constructors for the ClientCursor. The database must
- * be stable when this is called, because cursors hang off the collection.
- */
- void init();
-
- //
- // ClientCursor-specific data, independent of the underlying execution type.
- //
-
- // The ID of the ClientCursor.
- CursorId _cursorid;
-
- // The namespace we're operating on.
- std::string _ns;
-
- CursorManager* _cursorManager;
-
- // if we've added it to the total open counter yet
- bool _countedYet;
-
- // How many objects have been returned by the find() so far?
- int _pos;
-
- // If this cursor was created by a find operation, '_query' holds the query predicate for
- // the find. If this cursor was created by a command (e.g. the aggregate command), then
- // '_query' holds the command specification received from the client.
- BSONObj _query;
-
- // See the QueryOptions enum in dbclient.h
- int _queryOptions;
-
- // Is this ClientCursor backed by an aggregation pipeline? Defaults to false.
- //
- // Agg executors differ from others in that they manage their own locking internally and
- // should not be killed or destroyed when the underlying collection is deleted.
- //
- // Note: This should *not* be set for the internal cursor used as input to an aggregation.
- bool _isAggCursor;
-
- // Is this cursor in use? Defaults to false.
- bool _isPinned;
-
- // Is the "no timeout" flag set on this cursor? If false, this cursor may be targeted for
- // deletion after an interval of inactivity. Defaults to false.
- bool _isNoTimeout;
-
- // The replication position only used in master-slave.
- Timestamp _slaveReadTill;
-
- // How long has the cursor been idle?
- int _idleAgeMillis;
-
- // TODO: Document.
- uint64_t _leftoverMaxTimeMicros;
-
- // For chunks that are being migrated, there is a period of time when 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 CollectionMetadata allow one
- // to inquiry if any given document of the collection belongs indeed to this shard or if it
- // is coming from (or a vestige of) an ongoing migration.
- CollectionMetadataPtr _collMetadata;
-
- // Only one of these is not-NULL.
- RecoveryUnit* _unownedRU;
- std::unique_ptr<RecoveryUnit> _ownedRU;
- // NOTE: _ownedRU must come before _exec, because _ownedRU must outlive _exec.
- // The storage engine can have resources in the PlanExecutor that rely on
- // the RecoveryUnit being alive.
-
- //
- // The underlying execution machinery.
- //
- std::unique_ptr<PlanExecutor> _exec;
- };
+ ClientCursor(CursorManager* cursorManager,
+ PlanExecutor* exec,
+ const std::string& ns,
+ int qopts = 0,
+ const BSONObj query = BSONObj(),
+ bool isAggCursor = false);
+
+ /**
+ * This ClientCursor is used to track sharding state for the given collection.
+ */
+ explicit ClientCursor(const Collection* collection);
+
+ //
+ // Basic accessors
+ //
+
+ CursorId cursorid() const {
+ return _cursorid;
+ }
+ std::string ns() const {
+ return _ns;
+ }
+ CursorManager* cursorManager() const {
+ return _cursorManager;
+ }
+ bool isAggCursor() const {
+ return _isAggCursor;
+ }
+
+ //
+ // Pinning functionality.
+ //
+
+ /**
+ * Marks this ClientCursor as in use. unsetPinned() must be called before the destructor of
+ * this ClientCursor is invoked.
+ */
+ void setPinned() {
+ _isPinned = true;
+ }
+
+ /**
+ * Marks this ClientCursor as no longer in use.
+ */
+ void unsetPinned() {
+ _isPinned = false;
+ }
+
+ bool isPinned() const {
+ return _isPinned;
+ }
+
+ /**
+ * This is called when someone is dropping a collection or something else that
+ * goes through killing cursors.
+ * It removes the responsiilibty of de-registering from ClientCursor.
+ * Responsibility for deleting the ClientCursor doesn't change from this call
+ * see PlanExecutor::kill.
+ */
+ void kill();
+
+ //
+ // Timing and timeouts
+ //
+
+ /**
+ * @param millis amount of idle passed time since last call
+ * note called outside of locks (other than ccmutex) so care must be exercised
+ */
+ bool shouldTimeout(int millis);
+ void setIdleTime(int millis);
+ int idleTime() const {
+ return _idleAgeMillis;
+ }
+
+ uint64_t getLeftoverMaxTimeMicros() const {
+ return _leftoverMaxTimeMicros;
+ }
+ void setLeftoverMaxTimeMicros(uint64_t leftoverMaxTimeMicros) {
+ _leftoverMaxTimeMicros = leftoverMaxTimeMicros;
+ }
+
+ //
+ // Replication-related stuff. TODO: Document and clean.
+ //
+
+ // Used to report replication position only in master-slave,
+ // so we keep them as TimeStamp rather than OpTime.
+ void updateSlaveLocation(OperationContext* txn);
+ void slaveReadTill(const Timestamp& t) {
+ _slaveReadTill = t;
+ }
+ /** Just for testing. */
+ Timestamp getSlaveReadTill() const {
+ return _slaveReadTill;
+ }
+
+ //
+ // Query-specific functionality that may be adapted for the PlanExecutor.
+ //
+
+ PlanExecutor* getExecutor() const {
+ return _exec.get();
+ }
+ int queryOptions() const {
+ return _queryOptions;
+ }
+ const BSONObj& getQuery() const {
+ return _query;
+ }
+
+ // Used by ops/query.cpp to stash how many results have been returned by a query.
+ int pos() const {
+ return _pos;
+ }
+ void incPos(int n) {
+ _pos += n;
+ }
+ void setPos(int n) {
+ _pos = n;
+ }
+
+ static long long totalOpen();
+
+ //
+ // Storage engine state for getMore.
+ //
+
+ bool hasRecoveryUnit() const {
+ return _ownedRU.get() || _unownedRU;
+ }
/**
- * ClientCursorPin is an RAII class that manages the pinned state of a ClientCursor.
- * ClientCursorPin objects pin the given cursor upon construction, and release the pin upon
- * destruction.
- *
- * A pin extends the lifetime of a ClientCursor object until the pin's release. Pinned
- * ClientCursor objects cannot not be killed due to inactivity, and cannot be killed by user
- * kill requests. When a CursorManager is destroyed (e.g. by a collection drop), ownership of
- * any still-pinned ClientCursor objects is transferred to their managing ClientCursorPin
- * objects.
*
- * Example usage:
- * {
- * ClientCursorPin pin(cursorManager, cursorid);
- * ClientCursor* cursor = pin.c();
- * if (cursor) {
- * // Use cursor.
- * }
- * // Pin automatically released on block exit.
- * }
+ * If a ClientCursor is created via DBDirectClient, it uses the same storage engine
+ * context as the DBDirectClient caller. We store this context in _unownedRU. We use
+ * this to verify that all further callers use the same RecoveryUnit.
*
- * Clients that wish to access ClientCursor objects owned by collection cursor managers must
- * hold the collection lock during pin acquisition and pin release. This guards from a
- * collection drop (which requires an exclusive lock on the collection) occurring concurrently
- * with the pin request or unpin request.
+ * Once a ClientCursor has an unowned RecoveryUnit, it will always have one.
*
- * Clients that wish to access ClientCursor objects owned by the global cursor manager need not
- * hold any locks; the global cursor manager can only be destroyed by a process exit.
+ * Sets the unowned RecoveryUnit to 'ru'. Does NOT take ownership of the pointer.
+ */
+ void setUnownedRecoveryUnit(RecoveryUnit* ru);
+
+ /**
+ * Return the unowned RecoveryUnit. 'this' does not own pointer and therefore cannot
+ * transfer ownership.
+ */
+ RecoveryUnit* getUnownedRecoveryUnit() const;
+
+ /**
+ * If a ClientCursor is created via a client request, we bind its lifetime to the
+ * ClientCursor's by storing it un _ownedRU. In order to execute the query over repeated
+ * network requests, we have to keep the execution state around.
+ */
+
+ /**
+ * Set the owned recovery unit to 'ru'. Takes ownership of it. If there is a previous
+ * owned recovery unit, it is deleted.
+ */
+ void setOwnedRecoveryUnit(RecoveryUnit* ru);
+
+ /**
+ * Returns the owned recovery unit. Ownership is transferred to the caller.
+ */
+ RecoveryUnit* releaseOwnedRecoveryUnit();
+
+private:
+ friend class CursorManager;
+ friend class ClientCursorPin;
+
+ /**
+ * Only friends are allowed to destroy ClientCursor objects.
+ */
+ ~ClientCursor();
+
+ /**
+ * Initialization common between both constructors for the ClientCursor. The database must
+ * be stable when this is called, because cursors hang off the collection.
*/
- class ClientCursorPin {
- MONGO_DISALLOW_COPYING(ClientCursorPin);
- public:
- /**
- * Asks "cursorManager" to set a pin on the ClientCursor associated with "cursorid". If no
- * such cursor exists, does nothing. If the cursor is already pinned, throws a
- * UserException.
- */
- ClientCursorPin( CursorManager* cursorManager, long long cursorid );
-
- /**
- * Calls release().
- */
- ~ClientCursorPin();
-
- /**
- * Releases the pin. It does not delete the underlying cursor unless ownership has passed
- * to us after kill. Turns into a no-op if release() or deleteUnderlying() have already
- * been called on this pin.
- */
- void release();
-
- /**
- * Deletes the underlying cursor. Cannot be called if release() or deleteUnderlying() have
- * already been called on this pin.
- */
- void deleteUnderlying();
-
- ClientCursor *c() const;
-
- private:
- ClientCursor* _cursor;
- };
-
- void startClientCursorMonitor();
-
-} // namespace mongo
+ void init();
+
+ //
+ // ClientCursor-specific data, independent of the underlying execution type.
+ //
+
+ // The ID of the ClientCursor.
+ CursorId _cursorid;
+
+ // The namespace we're operating on.
+ std::string _ns;
+
+ CursorManager* _cursorManager;
+
+ // if we've added it to the total open counter yet
+ bool _countedYet;
+
+ // How many objects have been returned by the find() so far?
+ int _pos;
+
+ // If this cursor was created by a find operation, '_query' holds the query predicate for
+ // the find. If this cursor was created by a command (e.g. the aggregate command), then
+ // '_query' holds the command specification received from the client.
+ BSONObj _query;
+
+ // See the QueryOptions enum in dbclient.h
+ int _queryOptions;
+
+ // Is this ClientCursor backed by an aggregation pipeline? Defaults to false.
+ //
+ // Agg executors differ from others in that they manage their own locking internally and
+ // should not be killed or destroyed when the underlying collection is deleted.
+ //
+ // Note: This should *not* be set for the internal cursor used as input to an aggregation.
+ bool _isAggCursor;
+
+ // Is this cursor in use? Defaults to false.
+ bool _isPinned;
+
+ // Is the "no timeout" flag set on this cursor? If false, this cursor may be targeted for
+ // deletion after an interval of inactivity. Defaults to false.
+ bool _isNoTimeout;
+
+ // The replication position only used in master-slave.
+ Timestamp _slaveReadTill;
+
+ // How long has the cursor been idle?
+ int _idleAgeMillis;
+
+ // TODO: Document.
+ uint64_t _leftoverMaxTimeMicros;
+
+ // For chunks that are being migrated, there is a period of time when 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 CollectionMetadata allow one
+ // to inquiry if any given document of the collection belongs indeed to this shard or if it
+ // is coming from (or a vestige of) an ongoing migration.
+ CollectionMetadataPtr _collMetadata;
+
+ // Only one of these is not-NULL.
+ RecoveryUnit* _unownedRU;
+ std::unique_ptr<RecoveryUnit> _ownedRU;
+ // NOTE: _ownedRU must come before _exec, because _ownedRU must outlive _exec.
+ // The storage engine can have resources in the PlanExecutor that rely on
+ // the RecoveryUnit being alive.
+
+ //
+ // The underlying execution machinery.
+ //
+ std::unique_ptr<PlanExecutor> _exec;
+};
+
+/**
+ * ClientCursorPin is an RAII class that manages the pinned state of a ClientCursor.
+ * ClientCursorPin objects pin the given cursor upon construction, and release the pin upon
+ * destruction.
+ *
+ * A pin extends the lifetime of a ClientCursor object until the pin's release. Pinned
+ * ClientCursor objects cannot not be killed due to inactivity, and cannot be killed by user
+ * kill requests. When a CursorManager is destroyed (e.g. by a collection drop), ownership of
+ * any still-pinned ClientCursor objects is transferred to their managing ClientCursorPin
+ * objects.
+ *
+ * Example usage:
+ * {
+ * ClientCursorPin pin(cursorManager, cursorid);
+ * ClientCursor* cursor = pin.c();
+ * if (cursor) {
+ * // Use cursor.
+ * }
+ * // Pin automatically released on block exit.
+ * }
+ *
+ * Clients that wish to access ClientCursor objects owned by collection cursor managers must
+ * hold the collection lock during pin acquisition and pin release. This guards from a
+ * collection drop (which requires an exclusive lock on the collection) occurring concurrently
+ * with the pin request or unpin request.
+ *
+ * Clients that wish to access ClientCursor objects owned by the global cursor manager need not
+ * hold any locks; the global cursor manager can only be destroyed by a process exit.
+ */
+class ClientCursorPin {
+ MONGO_DISALLOW_COPYING(ClientCursorPin);
+
+public:
+ /**
+ * Asks "cursorManager" to set a pin on the ClientCursor associated with "cursorid". If no
+ * such cursor exists, does nothing. If the cursor is already pinned, throws a
+ * UserException.
+ */
+ ClientCursorPin(CursorManager* cursorManager, long long cursorid);
+
+ /**
+ * Calls release().
+ */
+ ~ClientCursorPin();
+
+ /**
+ * Releases the pin. It does not delete the underlying cursor unless ownership has passed
+ * to us after kill. Turns into a no-op if release() or deleteUnderlying() have already
+ * been called on this pin.
+ */
+ void release();
+
+ /**
+ * Deletes the underlying cursor. Cannot be called if release() or deleteUnderlying() have
+ * already been called on this pin.
+ */
+ void deleteUnderlying();
+
+ ClientCursor* c() const;
+
+private:
+ ClientCursor* _cursor;
+};
+
+void startClientCursorMonitor();
+
+} // namespace mongo