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