.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "MONGOC_CURSORS" "3" "May 07, 2024" "1.27.1" "libmongoc" .SH HANDLING CURSOR FAILURES .sp Cursors exist on a MongoDB server. However, the \fBmongoc_cursor_t\fP structure gives the local process a handle to the cursor. It is possible for errors to occur on the server while iterating a cursor on the client. Even a network partition may occur. This means that applications should be robust in handling cursor failures. .sp While iterating cursors, you should check to see if an error has occurred. See the following example for how to robustly check for errors. .INDENT 0.0 .INDENT 3.5 .sp .EX static void print_all_documents (mongoc_collection_t *collection) { mongoc_cursor_t *cursor; const bson_t *doc; bson_error_t error; bson_t query = BSON_INITIALIZER; char *str; cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL); while (mongoc_cursor_next (cursor, &doc)) { str = bson_as_canonical_extended_json (doc, NULL); printf (\(dq%s\en\(dq, str); bson_free (str); } if (mongoc_cursor_error (cursor, &error)) { fprintf (stderr, \(dqFailed to iterate all documents: %s\en\(dq, error.message); } mongoc_cursor_destroy (cursor); } .EE .UNINDENT .UNINDENT .SH DESTROYING SERVER-SIDE CURSORS .sp The MongoDB C driver will automatically destroy a server\-side cursor when \fI\%mongoc_cursor_destroy()\fP is called. Failure to call this function when done with a cursor will leak memory client side as well as consume extra memory server side. If the cursor was configured to never timeout, it will become a memory leak on the server. .SH TAILABLE CURSORS .sp Tailable cursors are cursors that remain open even after they\(aqve returned a final result. This way, if more documents are added to a collection (i.e., to the cursor\(aqs result set), then you can continue to call \fI\%mongoc_cursor_next()\fP to retrieve those additional results. .sp Here\(aqs a complete test case that demonstrates the use of tailable cursors. .sp \fBNOTE:\fP .INDENT 0.0 .INDENT 3.5 Tailable cursors are for capped collections only. .UNINDENT .UNINDENT .sp An example to tail the oplog from a replica set. .sp mongoc\-tail.c .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include #include #include #ifdef _WIN32 #define sleep(_n) Sleep ((_n) * 1000) #endif static void print_bson (const bson_t *b) { char *str; str = bson_as_canonical_extended_json (b, NULL); fprintf (stdout, \(dq%s\en\(dq, str); bson_free (str); } static mongoc_cursor_t * query_collection (mongoc_collection_t *collection, uint32_t last_time) { mongoc_cursor_t *cursor; bson_t query; bson_t gt; bson_t opts; BSON_ASSERT (collection); bson_init (&query); BSON_APPEND_DOCUMENT_BEGIN (&query, \(dqts\(dq, >); BSON_APPEND_TIMESTAMP (>, \(dq$gt\(dq, last_time, 0); bson_append_document_end (&query, >); bson_init (&opts); BSON_APPEND_BOOL (&opts, \(dqtailable\(dq, true); BSON_APPEND_BOOL (&opts, \(dqawaitData\(dq, true); cursor = mongoc_collection_find_with_opts (collection, &query, &opts, NULL); bson_destroy (&query); bson_destroy (&opts); return cursor; } static void tail_collection (mongoc_collection_t *collection) { mongoc_cursor_t *cursor; uint32_t last_time; const bson_t *doc; bson_error_t error; bson_iter_t iter; BSON_ASSERT (collection); last_time = (uint32_t) time (NULL); while (true) { cursor = query_collection (collection, last_time); while (!mongoc_cursor_error (cursor, &error) && mongoc_cursor_more (cursor)) { if (mongoc_cursor_next (cursor, &doc)) { if (bson_iter_init_find (&iter, doc, \(dqts\(dq) && BSON_ITER_HOLDS_TIMESTAMP (&iter)) { bson_iter_timestamp (&iter, &last_time, NULL); } print_bson (doc); } } if (mongoc_cursor_error (cursor, &error)) { if (error.domain == MONGOC_ERROR_SERVER) { fprintf (stderr, \(dq%s\en\(dq, error.message); exit (1); } } mongoc_cursor_destroy (cursor); sleep (1); } } int main (int argc, char *argv[]) { mongoc_collection_t *collection; mongoc_client_t *client; mongoc_uri_t *uri; bson_error_t error; if (argc != 2) { fprintf (stderr, \(dqusage: %s MONGO_URI\en\(dq, argv[0]); return EXIT_FAILURE; } mongoc_init (); uri = mongoc_uri_new_with_error (argv[1], &error); if (!uri) { fprintf (stderr, \(dqfailed to parse URI: %s\en\(dq \(dqerror message: %s\en\(dq, argv[1], error.message); return EXIT_FAILURE; } client = mongoc_client_new_from_uri (uri); if (!client) { return EXIT_FAILURE; } mongoc_client_set_error_api (client, 2); collection = mongoc_client_get_collection (client, \(dqlocal\(dq, \(dqoplog.rs\(dq); tail_collection (collection); mongoc_collection_destroy (collection); mongoc_uri_destroy (uri); mongoc_client_destroy (client); return EXIT_SUCCESS; } .EE .UNINDENT .UNINDENT .sp Let\(aqs compile and run this example against a replica set to see updates as they are made. .INDENT 0.0 .INDENT 3.5 .sp .EX $ gcc \-Wall \-o mongoc\-tail mongoc\-tail.c $(pkg\-config \-\-cflags \-\-libs libmongoc\-1.0) $ ./mongoc\-tail mongodb://example.com/?replicaSet=myReplSet { \(dqh\(dq : \-8458503739429355503, \(dqns\(dq : \(dqtest.test\(dq, \(dqo\(dq : { \(dq_id\(dq : { \(dq$oid\(dq : \(dq5372ab0a25164be923d10d50\(dq } }, \(dqop\(dq : \(dqi\(dq, \(dqts\(dq : { \(dq$timestamp\(dq : { \(dqi\(dq : 1, \(dqt\(dq : 1400023818 } }, \(dqv\(dq : 2 } .EE .UNINDENT .UNINDENT .sp The line of output is a sample from performing \fBdb.test.insert({})\fP from the mongo shell on the replica set. .sp \fBSEE ALSO:\fP .INDENT 0.0 .INDENT 3.5 .nf \fI\%mongoc_cursor_set_max_await_time_ms()\fP\&. .fi .sp .UNINDENT .UNINDENT .SH AUTHOR MongoDB, Inc .SH COPYRIGHT 2017-present, MongoDB, Inc .\" Generated by docutils manpage writer. .