处理游标故障
游标存在于MongoDB服务器。 但是,  mongoc_cursor_t结构为本地进程提供了游标的处理。 在客户端上迭代游标时,服务器上可能会出现错误。 甚至可能发生网络分区。 这意味着应用程序在处理游标故障方面应该具有稳健性。
迭代游标时,应检查是否发生错误。 有关如何稳健地检查错误,请参阅以下示例。
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 ("%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); } 
销毁服务器端游标
调用 mongoc_cursor_destroy 时, MongoDB C驱动程序将自动销毁服务器端游标。使用游标后未能调用此函数将导致客户端端内存泄漏,并在服务器端消耗额外的内存。如果将游标配置为永不超时,则会导致服务器上的内存泄漏。
可追加游标
可追加游标是即使在返回最终结果后仍保持打开状态的游标。这样,如果有更多文档添加到集合中(即添加到游标的结果设立),则可以继续调用 mongoc_cursor_next 来检索这些附加结果。
下面是一个完整的测试案例,演示了可追加游标的用法。
注意
可追加游标仅适用于固定大小集合。
从副本集中跟踪 oplog 的示例。
mongoc-tail.c
static void print_bson (const bson_t *b) {    char *str;    str = bson_as_canonical_extended_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;    bson_t opts;    BSON_ASSERT (collection);    bson_init (&query);    BSON_APPEND_DOCUMENT_BEGIN (&query, "ts", >);    BSON_APPEND_TIMESTAMP (>, "$gt", last_time, 0);    bson_append_document_end (&query, >);    bson_init (&opts);    BSON_APPEND_BOOL (&opts, "tailable", true);    BSON_APPEND_BOOL (&opts, "awaitData", 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, "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_SERVER) {             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;    mongoc_uri_t *uri;    bson_error_t error;    if (argc != 2) {       fprintf (stderr, "usage: %s MONGO_URI\n", argv[0]);       return EXIT_FAILURE;    }    mongoc_init ();    uri = mongoc_uri_new_with_error (argv[1], &error);    if (!uri) {       fprintf (stderr,                "failed to parse URI: %s\n"                "error message:       %s\n",                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, "local", "oplog.rs");    tail_collection (collection);    mongoc_collection_destroy (collection);    mongoc_uri_destroy (uri);    mongoc_client_destroy (client);    return EXIT_SUCCESS; } 
让我们针对副本集编译并运行此示例,以查看进行的更新。
$ gcc -Wall -o mongoc-tail mongoc-tail.c $(pkg-config --cflags --libs libmongoc-1.0) $ ./mongoc-tail mongodb://example.com/?replicaSet=myReplSet {     "h" : -8458503739429355503,     "ns" : "test.test",     "o" : {         "_id" : {             "$oid" : "5372ab0a25164be923d10d50"         }     },     "op" : "i",     "ts" : {         "$timestamp" : {             "i" : 1,             "t" : 1400023818         }     },     "v" : 2 } 
该输出行是从mongo shell在副本集上执行 db.test.insert({}) 的示例。