Provided by: libmongoc-doc_1.3.1-1_all bug

NAME

       Cursors - None

HANDLING CURSOR FAILURES

       Cursors  exist  on  a  MongoDB  server.  However, the mongoc_cursor_t 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.

       While iterating cursors, you should check to see if an error has occurred. See the following example  for
       how to robustly check for errors.

       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 (collection, MONGOC_QUERY_NONE, 0, 0, 0,
                                           query, NULL, NULL);

          while (mongoc_cursor_more (cursor) && mongoc_cursor_next (cursor, &doc)) {
             str = bson_as_json (doc, NULL);
             printf ("%s\n", str);
             bson_free (str);
          }

          if (mongoc_cursor_error (cursor, &error)) {
             fprintf (stderr, "Failed to iterate all documents: %s\n", error.message);
          }

          mongoc_cursor_destroy (cursor);
       }

DESTROYING SERVER‐SIDE CURSORS

       The  MongoDB  C  driver  will automatically destroy a server‐side cursor when mongoc_cursor_destroy(3) 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.

TAILABLE CURSORS

       Tailable cursors are cursors that remain open even after they've returned a final result.  This  way,  if
       more  documents  are  added  to a collection (i.e., to the cursor's result set), then you can continue to
       call mongoc_cursor_next(3) to retrieve those additional results.

       Here's a complete test case that demonstrates the use of tailable cursors.

       NOTE
              Note that tailable cursors are for capped collections only.

       #include <bson.h>
       #include <mongoc.h>
       #include <stdio.h>
       #include <stdlib.h>

       #ifdef _WIN32
       #define sleep(_n) Sleep((_n) * 1000)
       #endif

       static void
       print_bson (const bson_t *b)
       {
          char *str;

          str = bson_as_json(b, NULL);
          fprintf(stdout, "%s\n", 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;
          int fflags = (MONGOC_QUERY_TAILABLE_CURSOR
                | MONGOC_QUERY_AWAIT_DATA
                | MONGOC_QUERY_SLAVE_OK);

          BSON_ASSERT(collection);

          bson_init(&query);
          bson_append_document_begin(&query, "ts", 2, &gt);
          bson_append_timestamp(&gt, "$gt", 3, last_time, 0);
          bson_append_document_end(&query, &gt);

          cursor = mongoc_collection_find(collection,
                                          (mongoc_query_flags_t)fflags,
                                          0,
                                          0,
                                          0,
                                          &query,
                                          NULL,
                                          NULL);

          bson_destroy(&query);

          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, "ts") &&
                       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_QUERY) &&
                    (error.code == MONGOC_ERROR_QUERY_NOT_TAILABLE)) {
                   fprintf(stderr, "%s\n", error.message);
                   exit(1);
                }
             }
             mongoc_cursor_destroy(cursor);
             sleep(1);
          }
       }

       int
       main (int   argc,
             char *argv[])
       {
          mongoc_collection_t *collection;
          mongoc_client_t *client;

          if (argc != 2) {
             fprintf(stderr, "usage: %s MONGO_URI\n", argv[0]);
             return EXIT_FAILURE;
          }

          mongoc_init();

          client = mongoc_client_new(argv[1]);
          if (!client) {
             fprintf(stderr, "Invalid URI: \"%s\"\n", argv[1]);
             return EXIT_FAILURE;
          }

          collection = mongoc_client_get_collection(client, "local", "oplog.rs");

          tail_collection(collection);

          mongoc_collection_destroy(collection);
          mongoc_client_destroy(client);

          return 0;
       }

       Let's compile and run this example against a replica set to see updates as they are made.

       $ $ { ts : { $timestamp : { t : 1400023818, i : 1 } }, h : ‐8458503739429355503, v : 2, op :  i  ,  ns  :
       test.test , o : { _id : { $oid : 5372ab0a25164be923d10d50 } } }

       NOTE
              The  line  of  output  is  a sample from performing db.test.insert({}) from the mongo shell on the
              given replicaSet.

       See also mongoc_cursor_set_max_await_time_ms \&.

COLOPHON

       This    page    is    part    of    MongoDB    C    Driver.     Please     report     any     bugs     at
       https://jira.mongodb.org/browse/CDRIVER.

MongoDB C Driver                                   2016‐01‐18                                         CURSORS(3)