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.