summaryrefslogtreecommitdiff
path: root/src/mongo/client/dbclient_cursor.h
diff options
context:
space:
mode:
authorHenrik Edin <henrik.edin@mongodb.com>2018-06-19 15:09:01 -0400
committerHenrik Edin <henrik.edin@mongodb.com>2018-06-29 11:57:55 -0400
commitcfa96795eefed2061628891c43ccdc2c256bb40a (patch)
tree110d230d14a7a60fa8b7ce937a77def7af98f1ef /src/mongo/client/dbclient_cursor.h
parent40ad396238fdfb87a7a86e26020db2d293d23f40 (diff)
downloadmongo-cfa96795eefed2061628891c43ccdc2c256bb40a.tar.gz
SERVER-35115 Separate dbclientinterface.h into several parts, one per class.
Diffstat (limited to 'src/mongo/client/dbclient_cursor.h')
-rw-r--r--src/mongo/client/dbclient_cursor.h310
1 files changed, 310 insertions, 0 deletions
diff --git a/src/mongo/client/dbclient_cursor.h b/src/mongo/client/dbclient_cursor.h
new file mode 100644
index 00000000000..36f5c20452a
--- /dev/null
+++ b/src/mongo/client/dbclient_cursor.h
@@ -0,0 +1,310 @@
+// file dbclientcursor.h
+
+/* Copyright 2009 10gen Inc.
+ *
+ * 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,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects
+ * for all of the code used other than as permitted herein. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you do not
+ * wish to do so, delete this exception statement from your version. If you
+ * delete this exception statement from all source files in the program,
+ * then also delete it in the license file.
+ */
+
+#pragma once
+
+#include <stack>
+
+#include "mongo/base/disallow_copying.h"
+#include "mongo/db/dbmessage.h"
+#include "mongo/db/jsobj.h"
+#include "mongo/db/json.h"
+#include "mongo/db/namespace_string.h"
+#include "mongo/rpc/message.h"
+
+namespace mongo {
+
+class AScopedConnection;
+class DBClientBase;
+
+/** Queries return a cursor object */
+class DBClientCursor {
+ MONGO_DISALLOW_COPYING(DBClientCursor);
+
+public:
+ /** If true, safe to call next(). Requests more from server if necessary. */
+ virtual bool more();
+
+ /** If true, there is more in our local buffers to be fetched via next(). Returns
+ false when a getMore request back to server would be required. You can use this
+ if you want to exhaust whatever data has been fetched to the client already but
+ then perhaps stop.
+ */
+ int objsLeftInBatch() const {
+ return _putBack.size() + batch.objs.size() - batch.pos;
+ }
+ bool moreInCurrentBatch() {
+ return objsLeftInBatch() > 0;
+ }
+
+ /** next
+ @return next object in the result cursor.
+ on an error at the remote server, you will get back:
+ { $err: <std::string> }
+ if you do not want to handle that yourself, call nextSafe().
+ */
+ virtual BSONObj next();
+
+ /**
+ restore an object previously returned by next() to the cursor
+ */
+ void putBack(const BSONObj& o) {
+ _putBack.push(o.getOwned());
+ }
+
+ /** throws AssertionException if get back { $err : ... } */
+ BSONObj nextSafe();
+
+ /** peek ahead at items buffered for future next() calls.
+ never requests new data from the server. so peek only effective
+ with what is already buffered.
+ WARNING: no support for _putBack yet!
+ */
+ void peek(std::vector<BSONObj>&, int atMost);
+
+ // Peeks at first element, if exists
+ BSONObj peekFirst();
+
+ /**
+ * peek ahead and see if an error occurred, and get the error if so.
+ */
+ bool peekError(BSONObj* error = NULL);
+
+ /**
+ iterate the rest of the cursor and return the number if items
+ */
+ int itcount() {
+ int c = 0;
+ while (more()) {
+ next();
+ c++;
+ }
+ return c;
+ }
+
+ /** cursor no longer valid -- use with tailable cursors.
+ note you should only rely on this once more() returns false;
+ 'dead' may be preset yet some data still queued and locally
+ available from the dbclientcursor.
+ */
+ bool isDead() const {
+ return cursorId == 0;
+ }
+
+ bool tailable() const {
+ return (opts & QueryOption_CursorTailable) != 0;
+ }
+
+ /** see ResultFlagType (constants.h) for flag values
+ mostly these flags are for internal purposes -
+ ResultFlag_ErrSet is the possible exception to that
+ */
+ bool hasResultFlag(int flag) {
+ return (resultFlags & flag) != 0;
+ }
+
+ /// Change batchSize after construction. Can change after requesting first batch.
+ void setBatchSize(int newBatchSize) {
+ batchSize = newBatchSize;
+ }
+
+
+ /**
+ * Fold this in with queryOptions to force the use of legacy query operations.
+ * This flag is never sent over the wire and is only used locally.
+ */
+ enum { QueryOptionLocal_forceOpQuery = 1 << 30 };
+
+ DBClientCursor(DBClientBase* client,
+ const std::string& ns,
+ const BSONObj& query,
+ int nToReturn,
+ int nToSkip,
+ const BSONObj* fieldsToReturn,
+ int queryOptions,
+ int bs);
+
+ DBClientCursor(DBClientBase* client,
+ const std::string& ns,
+ long long cursorId,
+ int nToReturn,
+ int options,
+ std::vector<BSONObj> initialBatch = {});
+
+ virtual ~DBClientCursor();
+
+ long long getCursorId() const {
+ return cursorId;
+ }
+
+ /** by default we "own" the cursor and will send the server a KillCursor
+ message when ~DBClientCursor() is called. This function overrides that.
+ */
+ void decouple() {
+ _ownCursor = false;
+ }
+
+ void attach(AScopedConnection* conn);
+
+ std::string originalHost() const {
+ return _originalHost;
+ }
+
+ std::string getns() const {
+ return ns.ns();
+ }
+
+ /**
+ * actually does the query
+ */
+ bool init();
+
+ void initLazy(bool isRetry = false);
+ bool initLazyFinish(bool& retry);
+
+ /**
+ * For exhaust. Used in DBClientConnection.
+ */
+ void exhaustReceiveMore();
+
+ /**
+ * Marks this object as dead and sends the KillCursors message to the server.
+ *
+ * Any errors that result from this are swallowed since this is typically performed as part of
+ * cleanup and a failure to kill the cursor should not result in a failure of the operation
+ * using the cursor.
+ *
+ * Killing an already killed or exhausted cursor does nothing, so it is safe to always call this
+ * if you want to ensure that a cursor is killed.
+ */
+ void kill();
+
+ /**
+ * Returns true if the connection this cursor is using has pending replies.
+ *
+ * If true, you should not try to use the connection for any other purpose or return it to a
+ * pool.
+ *
+ * This can happen if either initLazy() was called without initLazyFinish() or an exhaust query
+ * was started but not completed.
+ */
+ bool connectionHasPendingReplies() const {
+ return _connectionHasPendingReplies;
+ }
+
+private:
+ DBClientCursor(DBClientBase* client,
+ const std::string& ns,
+ const BSONObj& query,
+ long long cursorId,
+ int nToReturn,
+ int nToSkip,
+ const BSONObj* fieldsToReturn,
+ int queryOptions,
+ int bs,
+ std::vector<BSONObj> initialBatch);
+
+ int nextBatchSize();
+
+ struct Batch {
+ // TODO remove constructors after c++17 toolchain upgrade
+ Batch() = default;
+ Batch(std::vector<BSONObj> initial, size_t initialPos = 0)
+ : objs(std::move(initial)), pos(initialPos) {}
+ std::vector<BSONObj> objs;
+ size_t pos = 0;
+ };
+
+ Batch batch;
+ DBClientBase* _client;
+ std::string _originalHost;
+ NamespaceString ns;
+ const bool _isCommand;
+ BSONObj query;
+ int nToReturn;
+ bool haveLimit;
+ int nToSkip;
+ const BSONObj* fieldsToReturn;
+ int opts;
+ int batchSize;
+ std::stack<BSONObj> _putBack;
+ int resultFlags;
+ long long cursorId;
+ bool _ownCursor; // see decouple()
+ std::string _scopedHost;
+ std::string _lazyHost;
+ bool wasError;
+ BSONVersion _enabledBSONVersion;
+ bool _useFindCommand = true;
+ bool _connectionHasPendingReplies = false;
+ int _lastRequestId = 0;
+
+ void dataReceived(const Message& reply) {
+ bool retry;
+ std::string lazyHost;
+ dataReceived(reply, retry, lazyHost);
+ }
+ void dataReceived(const Message& reply, bool& retry, std::string& lazyHost);
+
+ /**
+ * Parses and returns command replies regardless of which command protocol was used.
+ * Does *not* parse replies from non-command OP_QUERY finds.
+ */
+ BSONObj commandDataReceived(const Message& reply);
+
+ void requestMore();
+
+ // init pieces
+ Message _assembleInit();
+ Message _assembleGetMore();
+};
+
+/** iterate over objects in current batch only - will not cause a network call
+ */
+class DBClientCursorBatchIterator {
+public:
+ DBClientCursorBatchIterator(DBClientCursor& c) : _c(c), _n() {}
+ bool moreInCurrentBatch() {
+ return _c.moreInCurrentBatch();
+ }
+ BSONObj nextSafe() {
+ massert(13383, "BatchIterator empty", moreInCurrentBatch());
+ ++_n;
+ return _c.nextSafe();
+ }
+ int n() const {
+ return _n;
+ }
+
+private:
+ DBClientCursor& _c;
+ int _n;
+};
+
+} // namespace mongo