<page xmlns="http://projectmallard.org/1.0/"
      type="topic"
      id="cursors">

  <title>Cursors</title>

  <section id="cursor-errors">
    <title>Handling Cursor Failures</title>
    <info><link type="guide" xref="index#cursors"/></info>
    <p>Cursors exist on a MongoDB server. However, the <code>mongoc_cursor_t</code> 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.</p>
    <p>While iterating cursors, you should check to see if an error has occurred. See the following example for how to robustly check for errors.</p>
    <screen><code mime="text/x-csrc"><![CDATA[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);
}
]]></code></screen>
  </section>

  <section id="killing-cursors">
    <info><link type="guide" xref="index#cursors"/></info>
    <title>Destroying Server-Side Cursors</title>
    <p>The MongoDB C driver will automatically destroy a server-side cursor when <code xref="mongoc_cursor_destroy">mongoc_cursor_destroy()</code> 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.</p>
  </section>

  <section id="tailable">
    <title>Tailable Cursors</title>
    <info><link type="guide" xref="index#cursors"/></info>

    <p>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 <code xref="mongoc_cursor_next">mongoc_cursor_next()</code> to retrieve those additional results.</p>
    <p>Here's a complete test case that demonstrates the use of tailable cursors.</p>

    <note style="info"><p>Note that tailable cursors are for capped collections only.</p></note>

    <listing>
      <title><file>mongoc-tail.c</file></title>
      <desc>An example to tail the oplog from a replicaSet.</desc>
      <code mime="text/x-csrc"><include parse="text" href="../examples/mongoc-tail.c" xmlns="http://www.w3.org/2001/XInclude" /></code>
    </listing>

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

    <screen><output style="prompt">$ </output><input>gcc -Wall -o mongoc-tail mongoc-tail.c $(pkg-config --cflags --libs libmongoc-1.0)</input>
<output style="prompt">$ </output><input>./mongoc-tail mongodb://example.com/?replicaSet=myReplSet</input>
<output>{ "ts" : { "$timestamp" : { "t" : 1400023818, "i" : 1 } }, "h" : -8458503739429355503, "v" : 2, "op" : "i", "ns" : "test.test", "o" : { "_id" : { "$oid" : "5372ab0a25164be923d10d50" } } }</output></screen>

    <note style="tip"><p>The line of output is a sample from performing <code>db.test.insert({})</code> from the mongo shell on the given replicaSet.</p></note>
    <p>See also <code xref="mongoc_cursor_set_max_await_time_ms">mongoc_cursor_set_max_await_time_ms</code>.</p>

  </section>

</page>
