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
16       occurred. See the following example  for  how  to  robustly  check  for
17       errors.
18
19          static void
20          print_all_documents (mongoc_collection_t *collection)
21          {
22             mongoc_cursor_t *cursor;
23             const bson_t *doc;
24             bson_error_t error;
25             bson_t query = BSON_INITIALIZER;
26             char *str;
27
28             cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
29
30             while (mongoc_cursor_next (cursor, &doc)) {
31                str = bson_as_canonical_extended_json (doc, NULL);
32                printf ("%s\n", str);
33                bson_free (str);
34             }
35
36             if (mongoc_cursor_error (cursor, &error)) {
37                fprintf (stderr, "Failed to iterate all documents: %s\n", error.message);
38             }
39
40             mongoc_cursor_destroy (cursor);
41          }
42

DESTROYING SERVER-SIDE CURSORS

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

TAILABLE CURSORS

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

AUTHOR

226       MongoDB, Inc
227
229       2017-present, MongoDB, Inc
230
231
232
233
2341.17.4                           Feb 04, 2021                MONGOC_CURSORS(3)
Impressum