1 
2 /**
3  *    Copyright (C) 2018-present MongoDB, Inc.
4  *
5  *    This program is free software: you can redistribute it and/or modify
6  *    it under the terms of the Server Side Public License, version 1,
7  *    as published by MongoDB, Inc.
8  *
9  *    This program is distributed in the hope that it will be useful,
10  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *    Server Side Public License for more details.
13  *
14  *    You should have received a copy of the Server Side Public License
15  *    along with this program. If not, see
16  *    <http://www.mongodb.com/licensing/server-side-public-license>.
17  *
18  *    As a special exception, the copyright holders give permission to link the
19  *    code of portions of this program with the OpenSSL library under certain
20  *    conditions as described in each individual source file and distribute
21  *    linked combinations including the program with the OpenSSL library. You
22  *    must comply with the Server Side Public License in all respects for
23  *    all of the code used other than as permitted herein. If you modify file(s)
24  *    with this exception, you may extend this exception to your version of the
25  *    file(s), but you are not obligated to do so. If you do not wish to do so,
26  *    delete this exception statement from your version. If you delete this
27  *    exception statement from all source files in the program, then also delete
28  *    it in the license file.
29  */
30 
31 #pragma once
32 
33 #include <boost/optional.hpp>
34 
35 #include "mongo/client/dbclientinterface.h"
36 #include "mongo/db/auth/user_name.h"
37 #include "mongo/db/cursor_id.h"
38 #include "mongo/db/jsobj.h"
39 #include "mongo/db/logical_session_id.h"
40 #include "mongo/db/query/plan_executor.h"
41 #include "mongo/db/record_id.h"
42 #include "mongo/stdx/functional.h"
43 #include "mongo/util/net/message.h"
44 
45 namespace mongo {
46 
47 class Collection;
48 class CursorManager;
49 class RecoveryUnit;
50 
51 /**
52  * Parameters used for constructing a ClientCursor. Makes an owned copy of 'originatingCommandObj'
53  * to be used across getMores.
54  *
55  * ClientCursors cannot be constructed in isolation, but rather must be
56  * constructed and managed using a CursorManager. See cursor_manager.h for more details.
57  */
58 struct ClientCursorParams {
ClientCursorParamsClientCursorParams59     ClientCursorParams(std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> planExecutor,
60                        NamespaceString nss,
61                        UserNameIterator authenticatedUsersIter,
62                        bool isReadCommitted,
63                        BSONObj originatingCommandObj)
64         : exec(std::move(planExecutor)),
65           nss(std::move(nss)),
66           isReadCommitted(isReadCommitted),
67           queryOptions(exec->getCanonicalQuery()
68                            ? exec->getCanonicalQuery()->getQueryRequest().getOptions()
69                            : 0),
70           originatingCommandObj(originatingCommandObj.getOwned()) {
71         while (authenticatedUsersIter.more()) {
72             authenticatedUsers.emplace_back(authenticatedUsersIter.next());
73         }
74     }
75 
setTailableClientCursorParams76     void setTailable(bool tailable) {
77         if (tailable)
78             queryOptions |= QueryOption_CursorTailable;
79         else
80             queryOptions &= ~QueryOption_CursorTailable;
81     }
82 
setAwaitDataClientCursorParams83     void setAwaitData(bool awaitData) {
84         if (awaitData)
85             queryOptions |= QueryOption_AwaitData;
86         else
87             queryOptions &= ~QueryOption_AwaitData;
88     }
89 
90     std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> exec;
91     const NamespaceString nss;
92     std::vector<UserName> authenticatedUsers;
93     bool isReadCommitted = false;
94     int queryOptions = 0;
95     BSONObj originatingCommandObj;
96 };
97 
98 /**
99  * A ClientCursor is the server-side state associated with a particular cursor id. A cursor id is a
100  * handle that we return to the client for queries which require results to be returned in multiple
101  * batches. The client can manage the server-side cursor state by passing the cursor id back to the
102  * server for certain supported operations.
103  *
104  * For instance, a client can retrieve the next batch of results from the cursor by issuing a
105  * getMore on this cursor id. It can also request that server-side resources be freed by issuing a
106  * killCursors on a particular cursor id. This is useful if the client wishes to abandon the cursor
107  * without retrieving all results.
108  *
109  * ClientCursors cannot exist in isolation and must be created, accessed, and destroyed via a
110  * CursorManager. See cursor_manager.h for more details. Unless the ClientCursor is marked by the
111  * caller as "no timeout", it will be automatically destroyed by its cursor manager after a period
112  * of inactivity.
113  */
114 class ClientCursor {
115     MONGO_DISALLOW_COPYING(ClientCursor);
116 
117 public:
cursorid()118     CursorId cursorid() const {
119         return _cursorid;
120     }
121 
nss()122     const NamespaceString& nss() const {
123         return _nss;
124     }
125 
getAuthenticatedUsers()126     UserNameIterator getAuthenticatedUsers() const {
127         return makeUserNameIterator(_authenticatedUsers.begin(), _authenticatedUsers.end());
128     }
129 
getSessionId()130     boost::optional<LogicalSessionId> getSessionId() const {
131         return _lsid;
132     }
133 
isReadCommitted()134     bool isReadCommitted() const {
135         return _isReadCommitted;
136     }
137 
138     /**
139      * Returns a pointer to the underlying query plan executor. All cursors manage a PlanExecutor,
140      * so this method never returns a null pointer.
141      */
getExecutor()142     PlanExecutor* getExecutor() const {
143         return _exec.get();
144     }
145 
146     /**
147      * Returns the query options bitmask.  If you'd like to know if the cursor is tailable or
148      * awaitData, prefer using the specific methods isTailable() and isAwaitData() over using this
149      * method.
150      */
queryOptions()151     int queryOptions() const {
152         return _queryOptions;
153     }
154 
isTailable()155     bool isTailable() const {
156         return _queryOptions & QueryOption_CursorTailable;
157     }
158 
isAwaitData()159     bool isAwaitData() const {
160         return _queryOptions & QueryOption_AwaitData;
161     }
162 
getOriginatingCommandObj()163     const BSONObj& getOriginatingCommandObj() const {
164         return _originatingCommand;
165     }
166 
167     /**
168      * Returns the total number of query results returned by the cursor so far.
169      */
pos()170     long long pos() const {
171         return _pos;
172     }
173 
174     /**
175      * Increments the cursor's tracked number of query results returned so far by 'n'.
176      */
incPos(long long n)177     void incPos(long long n) {
178         _pos += n;
179     }
180 
181     /**
182      * Sets the cursor's tracked number of query results returned so far to 'n'.
183      */
setPos(long long n)184     void setPos(long long n) {
185         _pos = n;
186     }
187 
188     //
189     // Timing.
190     //
191 
192     /**
193      * Returns the amount of time execution time available to this cursor. Only valid at the
194      * beginning of a getMore request, and only really for use by the maxTime tracking code.
195      *
196      * Microseconds::max() == infinity, values less than 1 mean no time left.
197      */
getLeftoverMaxTimeMicros()198     Microseconds getLeftoverMaxTimeMicros() const {
199         return _leftoverMaxTimeMicros;
200     }
201 
202     /**
203      * Sets the amount of execution time available to this cursor. This is only called when an
204      * operation that uses a cursor is finishing, to update its remaining time.
205      *
206      * Microseconds::max() == infinity, values less than 1 mean no time left.
207      */
setLeftoverMaxTimeMicros(Microseconds leftoverMaxTimeMicros)208     void setLeftoverMaxTimeMicros(Microseconds leftoverMaxTimeMicros) {
209         _leftoverMaxTimeMicros = leftoverMaxTimeMicros;
210     }
211 
212     //
213     // Replication-related methods.
214     //
215 
216     // Used to report replication position only in master-slave, so we keep them as TimeStamp rather
217     // than OpTime.
218     void updateSlaveLocation(OperationContext* opCtx);
219 
slaveReadTill(const Timestamp & t)220     void slaveReadTill(const Timestamp& t) {
221         _slaveReadTill = t;
222     }
223 
224     /** Just for testing. */
getSlaveReadTill()225     Timestamp getSlaveReadTill() const {
226         return _slaveReadTill;
227     }
228 
229     /**
230      * Returns the server-wide the count of living cursors. Such a cursor is called an "open
231      * cursor".
232      */
233     static long long totalOpen();
234 
partitionOf(const ClientCursor * cursor)235     friend std::size_t partitionOf(const ClientCursor* cursor) {
236         return cursor->cursorid();
237     }
238 
getLastUseDate()239     Date_t getLastUseDate() const {
240         return _lastUseDate;
241     }
242 
243 private:
244     friend class CursorManager;
245     friend class ClientCursorPin;
246 
247     /**
248      * Since the client cursor destructor is private, this is needed for using client cursors with
249      * smart pointers.
250      */
251     struct Deleter {
operatorDeleter252         void operator()(ClientCursor* cursor) {
253             delete cursor;
254         }
255     };
256 
257     /**
258      * Constructs a ClientCursor. Since cursors must come into being registered and pinned, this is
259      * private. See cursor_manager.h for more details.
260      */
261     ClientCursor(ClientCursorParams params,
262                  CursorManager* cursorManager,
263                  CursorId cursorId,
264                  boost::optional<LogicalSessionId> lsid,
265                  Date_t now);
266 
267     /**
268      * Destroys a ClientCursor. This is private, since only the CursorManager or the ClientCursorPin
269      * is allowed to destroy a cursor.
270      *
271      * Cursors must be unpinned and deregistered from the CursorManager before they can be
272      * destroyed.
273      */
274     ~ClientCursor();
275 
276     /**
277      * Marks this cursor as killed, so any future uses will return an error status including
278      * 'reason'.
279      */
280     void markAsKilled(const std::string& reason);
281 
282     /**
283      * Disposes this ClientCursor's PlanExecutor. Must be called before deleting a ClientCursor to
284      * ensure it has a chance to clean up any resources it is using. Can be called multiple times.
285      * It is an error to call any other method after calling dispose().
286      */
287     void dispose(OperationContext* opCtx);
288 
isNoTimeout()289     bool isNoTimeout() const {
290         return (_queryOptions & QueryOption_NoCursorTimeout);
291     }
292 
293     // The ID of the ClientCursor. A value of 0 is used to mean that no cursor id has been assigned.
294     CursorId _cursorid = 0;
295 
296     const NamespaceString _nss;
297 
298     // The set of authenticated users when this cursor was created.
299     std::vector<UserName> _authenticatedUsers;
300 
301     // A logical session id for this cursor, if it is running inside of a session.
302     const boost::optional<LogicalSessionId> _lsid;
303 
304     const bool _isReadCommitted = false;
305 
306     CursorManager* _cursorManager;
307 
308     // Tracks whether dispose() has been called, to make sure it happens before destruction. It is
309     // an error to use a ClientCursor once it has been disposed.
310     bool _disposed = false;
311 
312     // Tracks the number of results returned by this cursor so far.
313     long long _pos = 0;
314 
315     // Holds an owned copy of the command specification received from the client.
316     const BSONObj _originatingCommand;
317 
318     // See the QueryOptions enum in dbclientinterface.h.
319     const int _queryOptions = 0;
320 
321     // The replication position only used in master-slave.
322     Timestamp _slaveReadTill;
323 
324     // Unused maxTime budget for this cursor.
325     Microseconds _leftoverMaxTimeMicros = Microseconds::max();
326 
327     // The underlying query execution machinery. Must be non-null.
328     std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> _exec;
329 
330     //
331     // The following fields are used by the CursorManager and the ClientCursorPin. In most
332     // conditions, they can only be used while holding the CursorManager's mutex. Exceptions
333     // include:
334     //   - If the ClientCursor is pinned, the CursorManager will never change '_isPinned' until
335     //     asked to by the ClientCursorPin.
336     //   - It is safe to read '_killed' while holding a collection lock, which must be held when
337     //     interacting with a ClientCursorPin.
338     //   - A ClientCursorPin can access these members after deregistering the cursor from the
339     //     CursorManager, at which point it has sole ownership of the ClientCursor.
340     //
341 
342     // TODO SERVER-28309 Remove this field and instead use _exec->markedAsKilled().
343     bool _killed = false;
344 
345     // While a cursor is being used by a client, it is marked as "pinned". See ClientCursorPin
346     // below.
347     //
348     // Cursors always come into existence in a pinned state.
349     bool _isPinned = true;
350 
351     Date_t _lastUseDate;
352 };
353 
354 /**
355  * ClientCursorPin is an RAII class which must be used in order to access a cursor. On construction,
356  * the ClientCursorPin marks its cursor as in use, which is called "pinning" the cursor. On
357  * destructrution, the ClientCursorPin marks its cursor as no longer in use, which is called
358  * "unpinning" the cursor. Pinning is used to prevent multiple concurrent uses of the same cursor---
359  * pinned cursors cannot be killed or timed out and cannot be used concurrently by other operations
360  * such as getMore or killCursors. A pin is obtained using the CursorManager. See cursor_manager.h
361  * for more details.
362  *
363  * A pin extends the lifetime of a ClientCursor object until the pin's release.  Pinned
364  * ClientCursor objects cannot not be killed due to inactivity, and cannot be killed by user
365  * kill requests.  When a CursorManager is destroyed (e.g. by a collection drop), ownership of
366  * any still-pinned ClientCursor objects is transferred to their managing ClientCursorPin
367  * objects.
368  *
369  * Example usage:
370  * {
371  *     StatusWith<ClientCursorPin> pin = cursorManager->pinCursor(opCtx, cursorid);
372  *     if (!pin.isOK()) {
373  *         // No cursor with id 'cursorid' exists, or it was killed while inactive. Handle the error
374  *         here.
375  *         return pin.getStatus();
376  *     }
377  *
378  *     ClientCursor* cursor = pin.getValue().getCursor();
379  *     // Use cursor. Pin automatically released on block exit.
380  * }
381  *
382  * Clients that wish to access ClientCursor objects owned by collection cursor managers must hold
383  * the collection lock while calling any pin method, including pin acquisition by the RAII
384  * constructor and pin release by the RAII destructor.  This guards from a collection drop (which
385  * requires an exclusive lock on the collection) occurring concurrently with the pin request or
386  * unpin request.
387  *
388  * Clients that wish to access ClientCursor objects owned by the global cursor manager need not
389  * hold any locks; the global cursor manager can only be destroyed by a process exit.
390  */
391 class ClientCursorPin {
392     MONGO_DISALLOW_COPYING(ClientCursorPin);
393 
394 public:
395     /**
396      * Moves 'other' into 'this'. The 'other' pin must have a pinned cursor. Moving an empty pin
397      * into 'this' is illegal.
398      */
399     ClientCursorPin(ClientCursorPin&& other);
400 
401     /**
402      * Moves 'other' into 'this'. 'other' must have a pinned cursor and 'this' must have no pinned
403      * cursor.
404      */
405     ClientCursorPin& operator=(ClientCursorPin&& other);
406 
407     /**
408      * Calls release().
409      */
410     ~ClientCursorPin();
411 
412     /**
413      * Releases the pin.  It does not delete the underlying cursor unless ownership has passed
414      * to us after kill.  Turns into a no-op if release() or deleteUnderlying() have already
415      * been called on this pin.
416      */
417     void release();
418 
419     /**
420      * Deletes the underlying cursor.  Cannot be called if release() or deleteUnderlying() have
421      * already been called on this pin.
422      */
423     void deleteUnderlying();
424 
425     /**
426      * Returns a pointer to the pinned cursor.
427      */
428     ClientCursor* getCursor() const;
429 
430 private:
431     friend class CursorManager;
432 
433     ClientCursorPin(OperationContext* opCtx, ClientCursor* cursor);
434 
435     OperationContext* _opCtx = nullptr;
436     ClientCursor* _cursor = nullptr;
437 };
438 
439 void startClientCursorMonitor();
440 
441 }  // namespace mongo
442