Tratamento de falhas do cursor
Existem cursores em um servidor MongoDB . No entanto, a estrutura mongoc_cursor_t fornece ao processo local um identificador para o cursor. É possível que ocorram erros no servidor ao iterar um cursor no cliente. Até mesmo uma partição de rede pode ocorrer. Isso significa que os aplicativos devem ser robustos ao lidar com falhas de cursor.
Ao iterar cursores, você deve verificar se ocorreu um erro. Consulte o exemplo a seguir para saber como verificar se há erros de forma robusta.
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); } 
Destruindo cursores do lado do servidor
O driver MongoDB C destruirá automaticamente um cursor do lado do servidor quando mongoc_cursor_destroy for chamado. Deixar de chamar essa função quando terminar com um cursor vazará a memória do lado do cliente , bem como consumirá memória extra do lado do servidor . Se o cursor foi configurado para nunca atingir o tempo limite, ele se tornará um vazamento de memória no servidor.
Cursores persistentes
Cursores tailable são cursores que permanecem abertos mesmo depois de retornarem um resultado final. Dessa forma, se mais documentos forem adicionados a uma coleção (ou seja, ao conjunto de resultados do cursor), você poderá continuar chamando mongoc_cursor_next para recuperar esses resultados adicionais.
Veja um caso de teste completo que demonstra o uso de cursores tailable.
Observação
Os cursores tailable são apenas para coleções limitadas .
Um exemplo para acompanhar o oplog a partir de um conjunto de réplicas.
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; } 
Vamos compilar e executar este exemplo em um conjunto de réplicas para ver as atualizações conforme elas são feitas.
$ 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 } 
A linha de saída é uma amostra da execução de db.test.insert({}) a partir do shell mongo no conjunto de réplicas.