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.  mongoc-tail.c.INDENT
63       0.0
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
196Let's compile and run this example against a replica set  to  see  updates  as
197they 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 mongoc_cursor_set_max_await_time_ms.
223

AUTHOR

225       MongoDB, Inc
226
228       2017-present, MongoDB, Inc
229
230
231
232
2331.16.2                           Feb 25, 2020                MONGOC_CURSORS(3)
Impressum