1MONGOC_CURSORS(3)                  libmongoc                 MONGOC_CURSORS(3)
2
3
4

NAME

6       mongoc_cursors - Cursors
7

HANDLING CURSOR FAILURES

9       Cursors  exist on a MongoDB server. However, the mongoc_cursor_t struc‐
10       ture gives the local process a handle to the cursor. It is possible for
11       errors  to  occur on the server while iterating a cursor on the client.
12       Even a network partition may occur. This means that applications should
13       be robust in handling cursor failures.
14
15       While  iterating  cursors,  you should check to see if an error has oc‐
16       curred. See the following example for how to robustly check for errors.
17
18          static void
19          print_all_documents (mongoc_collection_t *collection)
20          {
21             mongoc_cursor_t *cursor;
22             const bson_t *doc;
23             bson_error_t error;
24             bson_t query = BSON_INITIALIZER;
25             char *str;
26
27             cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
28
29             while (mongoc_cursor_next (cursor, &doc)) {
30                str = bson_as_canonical_extended_json (doc, NULL);
31                printf ("%s\n", str);
32                bson_free (str);
33             }
34
35             if (mongoc_cursor_error (cursor, &error)) {
36                fprintf (stderr, "Failed to iterate all documents: %s\n", error.message);
37             }
38
39             mongoc_cursor_destroy (cursor);
40          }
41

DESTROYING SERVER-SIDE CURSORS

43       The MongoDB C driver will automatically destroy  a  server-side  cursor
44       when  mongoc_cursor_destroy()  is called. Failure to call this function
45       when done with a cursor will leak memory client side as well as consume
46       extra  memory  server side. If the cursor was configured to never time‐
47       out, it will become a memory leak on the server.
48

TAILABLE CURSORS

50       Tailable cursors are cursors that remain open even  after  they've  re‐
51       turned  a final result. This way, if more documents are added to a col‐
52       lection (i.e., to the cursor's result set), then you  can  continue  to
53       call mongoc_cursor_next() to retrieve those additional results.
54
55       Here's  a complete test case that demonstrates the use of tailable cur‐
56       sors.
57
58       NOTE:
59          Tailable cursors are for capped collections only.
60
61       An example to tail the oplog from a replica set.
62
63       mongoc-tail.c
64
65          #include <bson/bson.h>
66          #include <mongoc/mongoc.h>
67          #include <stdio.h>
68          #include <stdlib.h>
69
70          #ifdef _WIN32
71          #define sleep(_n) Sleep ((_n) *1000)
72          #endif
73
74
75          static void
76          print_bson (const bson_t *b)
77          {
78             char *str;
79
80             str = bson_as_canonical_extended_json (b, NULL);
81             fprintf (stdout, "%s\n", str);
82             bson_free (str);
83          }
84
85
86          static mongoc_cursor_t *
87          query_collection (mongoc_collection_t *collection, uint32_t last_time)
88          {
89             mongoc_cursor_t *cursor;
90             bson_t query;
91             bson_t gt;
92             bson_t opts;
93
94             BSON_ASSERT (collection);
95
96             bson_init (&query);
97             BSON_APPEND_DOCUMENT_BEGIN (&query, "ts", &gt);
98             BSON_APPEND_TIMESTAMP (&gt, "$gt", last_time, 0);
99             bson_append_document_end (&query, &gt);
100
101             bson_init (&opts);
102             BSON_APPEND_BOOL (&opts, "tailable", true);
103             BSON_APPEND_BOOL (&opts, "awaitData", true);
104
105             cursor = mongoc_collection_find_with_opts (collection, &query, &opts, NULL);
106
107             bson_destroy (&query);
108             bson_destroy (&opts);
109
110             return cursor;
111          }
112
113
114          static void
115          tail_collection (mongoc_collection_t *collection)
116          {
117             mongoc_cursor_t *cursor;
118             uint32_t last_time;
119             const bson_t *doc;
120             bson_error_t error;
121             bson_iter_t iter;
122
123             BSON_ASSERT (collection);
124
125             last_time = (uint32_t) time (NULL);
126
127             while (true) {
128                cursor = query_collection (collection, last_time);
129                while (!mongoc_cursor_error (cursor, &error) &&
130                       mongoc_cursor_more (cursor)) {
131                   if (mongoc_cursor_next (cursor, &doc)) {
132                      if (bson_iter_init_find (&iter, doc, "ts") &&
133                          BSON_ITER_HOLDS_TIMESTAMP (&iter)) {
134                         bson_iter_timestamp (&iter, &last_time, NULL);
135                      }
136                      print_bson (doc);
137                   }
138                }
139                if (mongoc_cursor_error (cursor, &error)) {
140                   if (error.domain == MONGOC_ERROR_SERVER) {
141                      fprintf (stderr, "%s\n", error.message);
142                      exit (1);
143                   }
144                }
145
146                mongoc_cursor_destroy (cursor);
147                sleep (1);
148             }
149          }
150
151
152          int
153          main (int argc, char *argv[])
154          {
155             mongoc_collection_t *collection;
156             mongoc_client_t *client;
157             mongoc_uri_t *uri;
158             bson_error_t error;
159
160             if (argc != 2) {
161                fprintf (stderr, "usage: %s MONGO_URI\n", argv[0]);
162                return EXIT_FAILURE;
163             }
164
165             mongoc_init ();
166
167             uri = mongoc_uri_new_with_error (argv[1], &error);
168             if (!uri) {
169                fprintf (stderr,
170                         "failed to parse URI: %s\n"
171                         "error message:       %s\n",
172                         argv[1],
173                         error.message);
174                return EXIT_FAILURE;
175             }
176
177             client = mongoc_client_new_from_uri (uri);
178             if (!client) {
179                return EXIT_FAILURE;
180             }
181
182             mongoc_client_set_error_api (client, 2);
183
184             collection = mongoc_client_get_collection (client, "local", "oplog.rs");
185
186             tail_collection (collection);
187
188             mongoc_collection_destroy (collection);
189             mongoc_uri_destroy (uri);
190             mongoc_client_destroy (client);
191
192             return EXIT_SUCCESS;
193          }
194
195
196       Let's compile and run this example against a replica set to see updates
197       as they are made.
198
199          $ gcc -Wall -o mongoc-tail mongoc-tail.c $(pkg-config --cflags --libs libmongoc-1.0)
200          $ ./mongoc-tail mongodb://example.com/?replicaSet=myReplSet
201          {
202              "h" : -8458503739429355503,
203              "ns" : "test.test",
204              "o" : {
205                  "_id" : {
206                      "$oid" : "5372ab0a25164be923d10d50"
207                  }
208              },
209              "op" : "i",
210              "ts" : {
211                  "$timestamp" : {
212                      "i" : 1,
213                      "t" : 1400023818
214                  }
215              },
216              "v" : 2
217          }
218
219       The  line of output is a sample from performing db.test.insert({}) from
220       the mongo shell on the replica set.
221
222       SEE ALSO:
223          mongoc_cursor_set_max_await_time_ms().
224
225

AUTHOR

227       MongoDB, Inc
228
230       2017-present, MongoDB, Inc
231
232
233
234
2351.24.3                           Aug 17, 2023                MONGOC_CURSORS(3)
Impressum