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

HANDLING CURSOR FAILURES

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

DESTROYING SERVER-SIDE CURSORS

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

TAILABLE CURSORS

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

AUTHOR

224       MongoDB, Inc
225
227       2017-present, MongoDB, Inc
228
229
230
231
2321.25.1                           Nov 08, 2023                MONGOC_CURSORS(3)
Impressum