Docs Menu
Docs Home
/ / /
C ドライバー
/ /

Cursors

項目一覧

  • カーソルの障害の処理
  • サーバーサイド カーソルの破棄
  • テール可能カーソル

カーソルは 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);
}

MongoDB C ドライバーは、 mongoc_cursor_destructor の場合にサーバー側カーソルを自動的に破棄します は呼び出されます。カーソルを使用して実行するときにこの関数を呼び出されない場合、クライアント側でメモリがリークされるだけでなく、サーバー側で余計なメモリが消費されます。 カーソルがタイムアウトしないように設定されている場合、サーバー上のメモリリークになります。

追尾可能 (tailable) カーソルは、最終結果を返した後も開いたままであるカーソルです。 この方法では、コレクション(カーソルの結果セット)にさらにドキュメントが追加された場合でも、引き続き mongoc_cursor_next を呼び出すことができます。 これらの追加の結果を検索するには、を参照してください。

以下は、追尾可能 (tailable) カーソルの使用を示す完全なテストケースです。

注意

追尾可能(tailable)なカーソルは、Cappedコレクションのみに適用されます。

レプリカセットから oplog を追跡する例。

mongoc-tail.c
#include <bson/bson.h>
#include <mongoc/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_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", &gt);
BSON_APPEND_TIMESTAMP (&gt, "$gt", last_time, 0);
bson_append_document_end (&query, &gt);
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({})を実行する場合のサンプルです。

Tip

以下も参照してください。

戻る

データ圧縮