Manejo de fallos del cursor
Los cursores existen en un servidor MongoDB. Sin embargo, mongoc_cursor_t La estructura proporciona al proceso local un identificador del cursor. Es posible que se produzcan errores en el servidor al iterar un cursor en el cliente. Incluso puede producirse una partición de red. Esto significa que las aplicaciones deben ser robustas en la gestión de fallos del cursor.
Al iterar los cursores, debe comprobar si se ha producido algún error. Consulte el siguiente ejemplo para saber cómo realizar una comprobación robusta de errores.
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); }
Destrucción de cursores del lado del servidor
El controlador C de MongoDB destruirá automáticamente un cursor del lado del servidor cuando Se llama amongoc_cursor_destroy. Si no se llama a esta función al usar un cursor, se perderá memoria del lado del cliente y se consumirá memoria adicional del lado del servidor. Si el cursor se configuró para que nunca expire, se producirá una pérdida de memoria en el servidor.
Cursores con seguimiento
Los cursores adaptables permanecen abiertos incluso después de devolver un resultado final. De esta forma, si se añaden más documentos a una colección (es decir, al conjunto de resultados del cursor), se puede seguir llamando a mongoc_cursor_next para recuperar esos resultados adicionales.
A continuación se muestra un caso de prueba completo que demuestra el uso de cursores adaptables.
Nota
Los cursores adaptables son solo para colecciones limitadas.
Un ejemplo para seguir el registro de operaciones desde un 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; }
Compile y ejecutemos este ejemplo contra un conjunto de réplicas para ver las actualizaciones a medida que se realizan.
$ 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 }
La línea de salida es una muestra de la ejecución de db.test.insert({}) desde el shell mongo en el conjunto de réplicas.