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 #include <functional>
35 #include <memory>
36 #include <vector>
37 
38 #include "mongo/bson/bsonobj.h"
39 #include "mongo/client/read_preference.h"
40 #include "mongo/db/auth/user_name.h"
41 #include "mongo/db/cursor_id.h"
42 #include "mongo/db/namespace_string.h"
43 #include "mongo/db/pipeline/pipeline.h"
44 #include "mongo/db/query/cursor_response.h"
45 #include "mongo/db/query/tailable_mode.h"
46 #include "mongo/s/client/shard.h"
47 #include "mongo/util/net/hostandport.h"
48 
49 namespace mongo {
50 namespace executor {
51 class TaskExecutor;
52 }
53 
54 class OperationContext;
55 class RouterExecStage;
56 
57 /**
58  * The resulting ClusterClientCursor will take ownership of the existing remote cursor, generating
59  * results based on the cursor's current state.
60  *
61  * Note that any results already generated from this cursor will not be returned by the resulting
62  * ClusterClientCursor. The caller is responsible for ensuring that results previously generated by
63  * this cursor have been processed.
64  */
65 struct ClusterClientCursorParams {
66     // When mongos has to do a merge in order to return results to the client in the correct sort
67     // order, it requests a sortKey meta-projection using this field name.
68     static const char kSortKeyField[];
69 
70     struct RemoteCursor {
RemoteCursorClusterClientCursorParams::RemoteCursor71         RemoteCursor(ShardId shardId, HostAndPort hostAndPort, CursorResponse cursorResponse)
72             : shardId(std::move(shardId)),
73               hostAndPort(std::move(hostAndPort)),
74               cursorResponse(std::move(cursorResponse)) {}
75 
76         // The shardId of the shard on which the cursor resides.
77         ShardId shardId;
78 
79         // The exact host (within the shard) on which the cursor resides.
80         HostAndPort hostAndPort;
81 
82         // Encompasses the state of the established cursor.
83         CursorResponse cursorResponse;
84     };
85 
86     ClusterClientCursorParams(NamespaceString nss,
87                               UserNameIterator authenticatedUsersIter,
88                               boost::optional<ReadPreferenceSetting> readPref = boost::none)
nsStringClusterClientCursorParams89         : nsString(std::move(nss)) {
90         while (authenticatedUsersIter.more()) {
91             authenticatedUsers.emplace_back(authenticatedUsersIter.next());
92         }
93         if (readPref) {
94             readPreference = std::move(readPref.get());
95         }
96     }
97 
98     // Namespace against which the cursors exist.
99     NamespaceString nsString;
100 
101     // The set of authenticated users when this cursor was created.
102     std::vector<UserName> authenticatedUsers;
103 
104     // Per-remote node data.
105     std::vector<RemoteCursor> remotes;
106 
107     // The sort specification. Leave empty if there is no sort.
108     BSONObj sort;
109 
110     // The number of results to skip. Optional. Should not be forwarded to the remote hosts in
111     // 'cmdObj'.
112     boost::optional<long long> skip;
113 
114     // The number of results per batch. Optional. If specified, will be specified as the batch for
115     // each getMore.
116     boost::optional<long long> batchSize;
117 
118     // Limits the number of results returned by the ClusterClientCursor to this many. Optional.
119     // Should be forwarded to the remote hosts in 'cmdObj'.
120     boost::optional<long long> limit;
121 
122     // If set, we use this pipeline to merge the output of aggregations on each remote.
123     std::unique_ptr<Pipeline, Pipeline::Deleter> mergePipeline;
124 
125     // Whether this cursor is tailing a capped collection, and whether it has the awaitData option
126     // set.
127     TailableMode tailableMode = TailableMode::kNormal;
128 
129     // Set if a readPreference must be respected throughout the lifetime of the cursor.
130     boost::optional<ReadPreferenceSetting> readPreference;
131 
132     // If valid, is called to return the RouterExecStage which becomes the initial source in this
133     // cursor's execution plan. Otherwise, a RouterStageMerge is used.
134     stdx::function<std::unique_ptr<RouterExecStage>(
135         OperationContext*, executor::TaskExecutor*, ClusterClientCursorParams*)>
136         createCustomCursorSource;
137 
138     // Whether the client indicated that it is willing to receive partial results in the case of an
139     // unreachable host.
140     bool isAllowPartialResults = false;
141 };
142 
143 }  // mongo
144