From fd841e416881cc0392e61ec312c1870f3a0004bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Tue, 2 Dec 2014 10:06:21 +0100 Subject: Initial import of libmongo-client version 0.1.8-2 --- docs/tutorial/Makefile.am | 13 + docs/tutorial/examples/GNUmakefile | 36 +++ docs/tutorial/examples/tut_bson_build.c | 81 ++++++ docs/tutorial/examples/tut_bson_build.json | 16 ++ docs/tutorial/examples/tut_bson_traverse.c | 123 ++++++++++ docs/tutorial/examples/tut_hl_client.c | 107 ++++++++ docs/tutorial/examples/tut_json2bson.c | 132 ++++++++++ docs/tutorial/examples/tut_mongo_sync.c | 273 +++++++++++++++++++++ docs/tutorial/examples/tut_mongo_sync_cmd_create.c | 82 +++++++ docs/tutorial/examples/tut_mongo_sync_cmd_custom.c | 81 ++++++ .../examples/tut_mongo_sync_cmd_index_create.c | 54 ++++ docs/tutorial/tut_bson.h | 10 + docs/tutorial/tut_bson_build.h | 62 +++++ docs/tutorial/tut_bson_traverse.h | 135 ++++++++++ docs/tutorial/tut_hl_client.h | 86 +++++++ docs/tutorial/tut_json2bson.h | 97 ++++++++ docs/tutorial/tut_mongo_sync.h | 16 ++ docs/tutorial/tut_mongo_sync_cmd_create.h | 53 ++++ docs/tutorial/tut_mongo_sync_cmd_custom.h | 64 +++++ docs/tutorial/tut_mongo_sync_cmd_index_create.h | 66 +++++ docs/tutorial/tut_mongo_sync_connect.h | 49 ++++ docs/tutorial/tut_mongo_sync_insert.h | 46 ++++ docs/tutorial/tut_mongo_sync_query.h | 67 +++++ docs/tutorial/tut_mongo_sync_query_complex.h | 43 ++++ docs/tutorial/tutorial.h | 34 +++ 25 files changed, 1826 insertions(+) create mode 100644 docs/tutorial/Makefile.am create mode 100644 docs/tutorial/examples/GNUmakefile create mode 100644 docs/tutorial/examples/tut_bson_build.c create mode 100644 docs/tutorial/examples/tut_bson_build.json create mode 100644 docs/tutorial/examples/tut_bson_traverse.c create mode 100644 docs/tutorial/examples/tut_hl_client.c create mode 100644 docs/tutorial/examples/tut_json2bson.c create mode 100644 docs/tutorial/examples/tut_mongo_sync.c create mode 100644 docs/tutorial/examples/tut_mongo_sync_cmd_create.c create mode 100644 docs/tutorial/examples/tut_mongo_sync_cmd_custom.c create mode 100644 docs/tutorial/examples/tut_mongo_sync_cmd_index_create.c create mode 100644 docs/tutorial/tut_bson.h create mode 100644 docs/tutorial/tut_bson_build.h create mode 100644 docs/tutorial/tut_bson_traverse.h create mode 100644 docs/tutorial/tut_hl_client.h create mode 100644 docs/tutorial/tut_json2bson.h create mode 100644 docs/tutorial/tut_mongo_sync.h create mode 100644 docs/tutorial/tut_mongo_sync_cmd_create.h create mode 100644 docs/tutorial/tut_mongo_sync_cmd_custom.h create mode 100644 docs/tutorial/tut_mongo_sync_cmd_index_create.h create mode 100644 docs/tutorial/tut_mongo_sync_connect.h create mode 100644 docs/tutorial/tut_mongo_sync_insert.h create mode 100644 docs/tutorial/tut_mongo_sync_query.h create mode 100644 docs/tutorial/tut_mongo_sync_query_complex.h create mode 100644 docs/tutorial/tutorial.h (limited to 'docs/tutorial') diff --git a/docs/tutorial/Makefile.am b/docs/tutorial/Makefile.am new file mode 100644 index 0000000..4ebd301 --- /dev/null +++ b/docs/tutorial/Makefile.am @@ -0,0 +1,13 @@ +EXTRA_DIST = tutorial.h \ + examples/GNUmakefile \ + tut_bson.h \ + tut_bson_build.h examples/tut_bson_build.c examples/tut_bson_build.json \ + tut_bson_traverse.h examples/tut_bson_traverse.c \ + tut_mongo_sync.h \ + tut_mongo_sync_connect.h tut_mongo_sync_insert.h \ + tut_mongo_sync_query.h tut_mongo_sync_query_complex.h \ + examples/tut_mongo_sync.c \ + tut_mongo_sync_cmd_create.h \ + examples/tut_mongo_sync_cmd_create.c \ + tut_hl_client.h examples/tut_hl_client.c \ + tut_json2bson.h examples/tut_json2bson.c diff --git a/docs/tutorial/examples/GNUmakefile b/docs/tutorial/examples/GNUmakefile new file mode 100644 index 0000000..01b5363 --- /dev/null +++ b/docs/tutorial/examples/GNUmakefile @@ -0,0 +1,36 @@ +# NOTE: This Makefile assumes that a recent enough version of +# libmongo-client is installed! +# +# It will NOT work in the build directory, without an installed +# libmongo-client library. + +TUTORIAL_PROGRAMS = tut/bson_build \ + tut/bson_traverse \ + tut/mongo_sync \ + tut/mongo_sync_cmd_create \ + tut/mongo_sync_cmd_custom \ + tut/mongo_sync_cmd_index_create \ + tut/hl_client \ + tut/json2bson + +LMC_CFLAGS = $(shell pkg-config --cflags libmongo-client) +LMC_LIBS = $(shell pkg-config --libs libmongo-client) + +JSON_C_CFLAGS = $(shell pkg-config --cflags json) +JSON_C_LIBS = $(shell pkg-config --libs json) + +TUT_CFLAGS = ${LMC_CFLAGS} +TUT_LIBS = ${LMC_LIBS} + +all: ${TUTORIAL_PROGRAMS} +clean: + rm -f ${TUTORIAL_PROGRAMS} + -rmdir tut/ + +tut/json2bson: TUT_CFLAGS += ${JSON_C_CFLAGS} +tut/json2bson: TUT_LIBS += ${JSON_C_LIBS} +${TUTORIAL_PROGRAMS}: tut/%: tut_%.c + @install -d tut + ${CC} ${TUT_CFLAGS} ${CFLAGS} $< ${TUT_LIBS} ${LDFLAGS} -o $@ + +.PHONY: all clean diff --git a/docs/tutorial/examples/tut_bson_build.c b/docs/tutorial/examples/tut_bson_build.c new file mode 100644 index 0000000..2624310 --- /dev/null +++ b/docs/tutorial/examples/tut_bson_build.c @@ -0,0 +1,81 @@ +#include + +#include +#include + +int +main (void) +{ + bson *b_new, *b_builder, *b_builder_full; + bson *page1, *page2, *pages; + + page1 = bson_new (); + bson_append_string (page1, "title", "BSON tutorial", -1); + bson_append_string (page1, "content", "...", -1); + bson_append_int32 (page1, "importance", 1); + bson_finish (page1); + + page2 = bson_new (); + bson_append_string (page2, "title", "Some other thing", -1); + bson_append_string (page2, "content", "...", -1); + bson_append_int32 (page2, "importance", 0); + bson_finish (page2); + + pages = bson_new (); + bson_append_document (pages, "1", page1); + bson_append_document (pages, "2", page2); + bson_finish (pages); + + b_new = bson_new (); + bson_append_string (b_new, "author", "Gergely Nagy", -1); + bson_append_array (b_new, "pages", pages); + bson_append_boolean (b_new, "inline", TRUE); + bson_finish (b_new); + + b_builder = bson_build (BSON_TYPE_STRING, "author", "Gergely Nagy", -1, + BSON_TYPE_ARRAY, "pages", pages, + BSON_TYPE_BOOLEAN, "inline", TRUE, + BSON_TYPE_NONE); + bson_finish (b_builder); + + b_builder_full = bson_build_full + (BSON_TYPE_STRING, "author", FALSE, "Gergely Nagy", -1, + BSON_TYPE_ARRAY, "pages", TRUE, + bson_build_full (BSON_TYPE_DOCUMENT, "1", TRUE, + bson_build (BSON_TYPE_STRING, "title", "BSON tutorial", -1, + BSON_TYPE_STRING, "content", "...", -1, + BSON_TYPE_INT32, "importance", 1, + BSON_TYPE_NONE), + BSON_TYPE_DOCUMENT, "2", TRUE, + bson_build (BSON_TYPE_STRING, "title", "Some other thing", -1, + BSON_TYPE_STRING, "content", "...", -1, + BSON_TYPE_INT32, "importance", 0, + BSON_TYPE_NONE), + BSON_TYPE_NONE), + BSON_TYPE_BOOLEAN, "inline", FALSE, TRUE, + BSON_TYPE_NONE); + bson_finish (b_builder_full); + + if (bson_size (b_new) != bson_size (b_builder) || + bson_size (b_new) != bson_size (b_builder_full)) + { + fprintf (stderr, "There's something fishy: the three BSON objects have different sizes"); + return 1; + } + + if (memcmp (bson_data (b_new), bson_data (b_builder), bson_size (b_new)) != 0 || + memcmp (bson_data (b_new), bson_data (b_builder_full), bson_size (b_new)) != 0) + { + fprintf (stderr, "The BSON objects do not match. Something smells."); + return 1; + } + + bson_free (b_builder_full); + bson_free (b_builder); + bson_free (b_new); + bson_free (pages); + bson_free (page2); + bson_free (page1); + + return 0; +} diff --git a/docs/tutorial/examples/tut_bson_build.json b/docs/tutorial/examples/tut_bson_build.json new file mode 100644 index 0000000..078cf53 --- /dev/null +++ b/docs/tutorial/examples/tut_bson_build.json @@ -0,0 +1,16 @@ +{ + author: "Gergely Nagy", + pages: [ + { + title: "BSON tutorial", + content: "...", + importance: 1 + }, + { + title: "Some other thing", + content: "...", + importance: 0 + } + ], + inline: true +} diff --git a/docs/tutorial/examples/tut_bson_traverse.c b/docs/tutorial/examples/tut_bson_traverse.c new file mode 100644 index 0000000..4be7b1d --- /dev/null +++ b/docs/tutorial/examples/tut_bson_traverse.c @@ -0,0 +1,123 @@ +#include + +#include +#include + +bson * +tut_bson (void) +{ + bson *b; + + b = bson_build_full + (BSON_TYPE_STRING, "author", FALSE, "Gergely Nagy", -1, + BSON_TYPE_ARRAY, "pages", TRUE, + bson_build_full (BSON_TYPE_DOCUMENT, "1", TRUE, + bson_build (BSON_TYPE_STRING, "title", "BSON tutorial", -1, + BSON_TYPE_STRING, "content", "...", -1, + BSON_TYPE_INT32, "importance", 1, + BSON_TYPE_NONE), + BSON_TYPE_DOCUMENT, "2", TRUE, + bson_build (BSON_TYPE_STRING, "title", "Some other thing", -1, + BSON_TYPE_STRING, "content", "...", -1, + BSON_TYPE_INT32, "importance", 0, + BSON_TYPE_NONE), + BSON_TYPE_NONE), + BSON_TYPE_BOOLEAN, "inline", FALSE, TRUE, + BSON_TYPE_NONE); + bson_finish (b); + + return b; +} + +int +main (void) +{ + bson *doc; + bson_cursor *c, *c_arr, *c_page; + + bson *v_doc, *v_array; + gboolean v_bool; + const gchar *v_str; + + doc = tut_bson (); + + c = bson_find (doc, "author"); + bson_cursor_get_string (c, &v_str); + printf ("Author: %s\n", v_str); + + bson_cursor_next (c); + bson_cursor_next (c); + + bson_cursor_get_boolean (c, &v_bool); + printf ("inline: %s\n", (v_bool) ? "TRUE" : "FALSE"); + + bson_cursor_free (c); + + c = bson_find (doc, "author"); + bson_cursor_get_string (c, &v_str); + bson_cursor_free (c); + c = bson_find (doc, "inline"); + bson_cursor_get_boolean (c, &v_bool); + bson_cursor_free (c); + + printf ("Author: %s; inline: %s; (bson_find)\n", + v_str, (v_bool) ? "TRUE" : "FALSE"); + + c = bson_find (doc, "author"); + bson_cursor_get_string (c, &v_str); + while (bson_cursor_next (c)) + { + if (strcmp (bson_cursor_key (c), "inline") == 0) + { + bson_cursor_get_boolean (c, &v_bool); + break; + } + } + bson_cursor_free (c); + + printf ("Author: %s; inline: %s; (bson_cursor_next)\n", + v_str, (v_bool) ? "TRUE" : "FALSE"); + + c = bson_find (doc, "author"); + bson_cursor_get_string (c, &v_str); + bson_cursor_find_next (c, "inline"); + bson_cursor_get_boolean (c, &v_bool); + bson_cursor_free (c); + + printf ("Author: %s; inline: %s; (bson_cursor_find_next)\n", + v_str, (v_bool) ? "TRUE" : "FALSE"); + + c = bson_find (doc, "pages"); + bson_cursor_find (c, "inline"); + bson_cursor_get_boolean (c, &v_bool); + bson_cursor_find (c, "author"); + bson_cursor_get_string (c, &v_str); + bson_cursor_free (c); + + printf ("Author: %s; inline: %s; (bson_cursor_find)\n", + v_str, (v_bool) ? "TRUE" : "FALSE"); + + c = bson_cursor_new (doc); + while (bson_cursor_next (c)) + { + printf ("Key: %s; type=%s\n", bson_cursor_key (c), + bson_cursor_type_as_string (c)); + } + bson_cursor_free (c); + + c = bson_find (doc, "pages"); + bson_cursor_get_array (c, &v_array); + c_arr = bson_find (v_array, "2"); + bson_cursor_get_document (c_arr, &v_doc); + c_page = bson_find (v_doc, "title"); + bson_cursor_get_string (c_page, &v_str); + + bson_cursor_free (c_page); + bson_cursor_free (c_arr); + bson_cursor_free (c); + + printf ("Title of the 2nd page in the pages array: %s\n", v_str); + + bson_free (doc); + return 0; +} diff --git a/docs/tutorial/examples/tut_hl_client.c b/docs/tutorial/examples/tut_hl_client.c new file mode 100644 index 0000000..68ceb8f --- /dev/null +++ b/docs/tutorial/examples/tut_hl_client.c @@ -0,0 +1,107 @@ +#include + +#include +#include +#include +#include + +static void +do_inserts (mongo_sync_connection *conn) +{ + bson *base; + gint i; + + base = bson_build + (BSON_TYPE_STRING, "tutorial-program", "tut_hl_client.c", -1, + BSON_TYPE_INT32, "the answer to life, the universe and everything", 42, + BSON_TYPE_NONE); + bson_finish (base); + + for (i = 0; i < 1000; i++) + { + bson *n; + + n = bson_new_from_data (bson_data (base), bson_size (base) - 1); + bson_append_int32 (n, "counter", i); + bson_finish (n); + + if (!mongo_sync_cmd_insert (conn, "lmc.tutorial", n, NULL)) + { + fprintf (stderr, "Error inserting document %d: %s\n", i, + strerror (errno)); + exit (1); + } + bson_free (n); + } + bson_free (base); +} + +static void +do_query (mongo_sync_connection *conn) +{ + mongo_sync_cursor *c; + bson *query; + gchar *error = NULL; + + query = bson_build + (BSON_TYPE_STRING, "tutorial-program", "tut_hl_client.c", -1, + BSON_TYPE_NONE); + bson_finish (query); + + c = mongo_sync_cursor_new (conn, "lmc.tutorial", + mongo_sync_cmd_query (conn, "lmc.tutorial", 0, + 0, 10, query, NULL)); + if (!c) + { + fprintf (stderr, "Error creating the query cursor: %s\n", + strerror (errno)); + exit (1); + } + bson_free (query); + + while (mongo_sync_cursor_next (c)) + { + bson *b = mongo_sync_cursor_get_data (c); + bson_cursor *bc; + gint32 cnt; + + if (!b) + { + int e = errno; + + mongo_sync_cmd_get_last_error (conn, "lmc", &error); + fprintf (stderr, "Error retrieving cursor data: %s\n", + (error) ? error : strerror (e)); + exit (1); + } + + bc = bson_find (b, "counter"); + bson_cursor_get_int32 (bc, &cnt); + printf ("\rCounter: %d", cnt); + + bson_cursor_free (bc); + bson_free (b); + } + printf ("\n"); + + mongo_sync_cursor_free (c); +} + +int +main (void) +{ + mongo_sync_connection *conn; + + conn = mongo_sync_connect ("localhost", 27017, FALSE); + if (!conn) + { + fprintf (stderr, "Connection failed: %s\n", strerror (errno)); + return 1; + } + + do_inserts (conn); + do_query (conn); + + mongo_sync_disconnect (conn); + return 0; +} diff --git a/docs/tutorial/examples/tut_json2bson.c b/docs/tutorial/examples/tut_json2bson.c new file mode 100644 index 0000000..3ad5b9a --- /dev/null +++ b/docs/tutorial/examples/tut_json2bson.c @@ -0,0 +1,132 @@ +#define __STRICT_ANSI__ 1 + +#include +#include + +#include +#include +#include + +static bson *json_to_bson (struct json_object *json); + +static void +json_key_to_bson_key (bson *b, void *val, + const gchar *key) +{ + switch (json_object_get_type (val)) + { + case json_type_boolean: + bson_append_boolean (b, key, json_object_get_boolean (val)); + break; + case json_type_double: + bson_append_double (b, key, json_object_get_double (val)); + break; + case json_type_int: + bson_append_int32 (b, key, json_object_get_int (val)); + break; + case json_type_string: + bson_append_string (b, key, json_object_get_string (val), -1); + break; + case json_type_object: + { + bson *sub; + + sub = json_to_bson (val); + bson_append_document (b, key, sub); + bson_free (sub); + break; + } + case json_type_array: + { + gint pos; + bson *sub; + + sub = bson_new (); + + for (pos = 0; pos < json_object_array_length (val); pos++) + { + gchar *nk = g_strdup_printf ("%d", pos); + + json_key_to_bson_key (sub, json_object_array_get_idx (val, pos), + nk); + g_free (nk); + } + bson_finish (sub); + + bson_append_array (b, key, sub); + bson_free (sub); + break; + } + default: + break; + } +} + +static void +json_to_bson_foreach (bson *b, struct json_object *json) +{ + json_object_object_foreach (json, key, val) + { + json_key_to_bson_key (b, val, key); + } +} + +static bson * +json_to_bson (struct json_object *json) +{ + bson *b; + + b = bson_new (); + json_to_bson_foreach (b, json); + bson_finish (b); + + return b; +} + +int +main (int argc, char **argv) +{ + GIOChannel *input; + GString *json_str; + GError *error = NULL; + struct json_tokener *tokener; + + input = g_io_channel_unix_new (0); + + json_str = g_string_new (NULL); + tokener = json_tokener_new (); + + while (g_io_channel_read_line_string (input, json_str, + NULL, &error) == G_IO_STATUS_NORMAL) + { + struct json_object *json; + bson *bson; + + json_tokener_reset (tokener); + + json = json_tokener_parse_ex (tokener, json_str->str, json_str->len); + if (!json) + { + fprintf (stderr, "Error parsing json: %s\n", json_str->str); + break; + } + + if (json_object_get_type (json) != json_type_object) + { + fprintf (stderr, + "Error: json's top-level object is not object: %s\n", + json_str->str); + json_object_put (json); + break; + } + + bson = json_to_bson (json); + json_object_put (json); + + write (1, bson_data (bson), bson_size (bson)); + + bson_free (bson); + } + + return 0; +} diff --git a/docs/tutorial/examples/tut_mongo_sync.c b/docs/tutorial/examples/tut_mongo_sync.c new file mode 100644 index 0000000..ff27560 --- /dev/null +++ b/docs/tutorial/examples/tut_mongo_sync.c @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include + +void +tut_sync_connect (void) +{ + mongo_sync_connection *conn; + + conn = mongo_sync_connect ("localhost", 27017, TRUE); + if (!conn) + { + perror ("mongo_sync_connect()"); + exit (1); + } + mongo_sync_disconnect (conn); +} + +void +tut_sync_connect_replica (void) +{ + mongo_sync_connection *conn; + + conn = mongo_sync_connect ("mongo-master", 27017, TRUE); + if (!conn) + { + perror ("mongo_sync_connect()"); + return; + } + + if (!mongo_sync_conn_set_auto_reconnect (conn, TRUE)) + { + perror ("mongo_sync_conn_set_auto_reconnect()"); + return; + } + + if (!mongo_sync_conn_seed_add (conn, "mongo-replica", 27017)) + { + perror ("mongo_sync_conn_seed_add()"); + return; + } + if (!mongo_sync_conn_seed_add (conn, "mongo-replica-2", 27017)) + { + perror ("mongo_sync_conn_seed_add()"); + return; + } + + mongo_sync_disconnect (conn); +} + +void +tut_sync_insert (void) +{ + mongo_sync_connection *conn; + bson *doc1, *doc2, *doc3; + + conn = mongo_sync_connect ("localhost", 27017, FALSE); + if (!conn) + { + perror ("mongo_sync_connect()"); + exit (1); + } + + doc1 = bson_build (BSON_TYPE_STRING, "hello", "world", -1, + BSON_TYPE_INT32, "the_final_answer", 42, + BSON_TYPE_BOOLEAN, "yes?", FALSE, + BSON_TYPE_INT32, "n", 1, + BSON_TYPE_NONE); + bson_finish (doc1); + + if (!mongo_sync_cmd_insert (conn, "tutorial.docs", doc1, NULL)) + { + perror ("mongo_sync_cmd_insert()"); + exit (1); + } + + doc2 = bson_build (BSON_TYPE_INT32, "n", 2, + BSON_TYPE_BOOLEAN, "yes?", FALSE, + BSON_TYPE_STRING, "hello", "dolly", -1, + BSON_TYPE_NONE); + bson_finish (doc2); + + doc3 = bson_build (BSON_TYPE_INT32, "n", 3, + BSON_TYPE_STRING, "hello", "nurse", -1, + BSON_TYPE_BOOLEAN, "yes?", TRUE, + BSON_TYPE_NONE); + bson_finish (doc3); + + if (!mongo_sync_cmd_insert (conn, "tutorial.docs", doc2, doc3, NULL)) + { + perror ("mongo_sync_cmd_insert()"); + exit (1); + } + + bson_free (doc3); + bson_free (doc2); + bson_free (doc1); + + mongo_sync_disconnect (conn); +} + +void +tut_sync_query_simple (void) +{ + mongo_sync_connection *conn; + mongo_packet *p; + mongo_sync_cursor *cursor; + bson *query; + gint i = 0; + + conn = mongo_sync_connect ("localhost", 27017, FALSE); + if (!conn) + { + perror ("mongo_sync_connect()"); + exit (1); + } + + query = bson_new (); + bson_finish (query); + + p = mongo_sync_cmd_query (conn, "tutorial.docs", 0, + 0, 10, query, NULL); + if (!p) + { + perror ("mongo_sync_cmd_query()"); + exit (1); + } + bson_free (query); + + cursor = mongo_sync_cursor_new (conn, "tutorial.docs", p); + if (!cursor) + { + perror ("mongo_sync_cursor_new()"); + exit (1); + } + + while (mongo_sync_cursor_next (cursor)) + { + bson *result = mongo_sync_cursor_get_data (cursor); + bson_cursor *c; + + if (!result) + { + perror ("mongo_sync_cursor_get_data()"); + exit (1); + } + + printf ("Keys in document #%d:\n", i); + c = bson_cursor_new (result); + while (bson_cursor_next (c)) + printf ("\t%s\n", bson_cursor_key (c)); + + i++; + bson_cursor_free (c); + bson_free (result); + } + + mongo_sync_cursor_free (cursor); + mongo_sync_disconnect (conn); +} + +void +tut_sync_query_complex (void) +{ + mongo_sync_connection *conn; + mongo_packet *p; + mongo_sync_cursor *cursor; + bson *query, *select; + gint i = 0; + + conn = mongo_sync_connect ("localhost", 27017, FALSE); + if (!conn) + { + perror ("mongo_sync_connect()"); + exit (1); + } + + query = bson_build_full (BSON_TYPE_DOCUMENT, "$query", TRUE, + bson_build (BSON_TYPE_BOOLEAN, "yes?", FALSE, + BSON_TYPE_NONE), + BSON_TYPE_DOCUMENT, "$orderby", TRUE, + bson_build (BSON_TYPE_INT32, "n", 1, + BSON_TYPE_NONE), + BSON_TYPE_NONE); + bson_finish (query); + + select = bson_build (BSON_TYPE_INT32, "hello", 1, + BSON_TYPE_INT32, "n", 1, + BSON_TYPE_INT32, "yes?", 1, + BSON_TYPE_NONE); + bson_finish (select); + + p = mongo_sync_cmd_query (conn, "tutorial.docs", 0, + 0, 10, query, select); + if (!p) + { + perror ("mongo_sync_cmd_query()"); + exit (1); + } + bson_free (query); + bson_free (select); + + cursor = mongo_sync_cursor_new (conn, "tutorial.docs", p); + if (!cursor) + { + perror ("mongo_sync_cursor_new()"); + exit (1); + } + + while (mongo_sync_cursor_next (cursor)) + { + const char *hello; + gint32 n; + gboolean yes; + + bson *result; + bson_cursor *c; + + result = mongo_sync_cursor_get_data (cursor); + if (!result) + { + perror ("mongo_sync_cursor_get_data()"); + exit (1); + } + + c = bson_find (result, "hello"); + if (!bson_cursor_get_string (c, &hello)) + { + perror ("bson_cursor_get_string()"); + exit (1); + } + bson_cursor_free (c); + + c = bson_find (result, "n"); + if (!bson_cursor_get_int32 (c, &n)) + { + perror ("bson_cursor_get_int32()"); + exit (1); + } + bson_cursor_free (c); + + c = bson_find (result, "yes?"); + if (!bson_cursor_get_boolean (c, &yes)) + { + perror ("bson_cursor_get_boolean()"); + exit (1); + } + bson_cursor_free (c); + + printf ("Document #%d: hello=%s; n=%d; yes?=%s\n", + i, hello, n, (yes) ? "TRUE" : "FALSE"); + + bson_free (result); + i++; + } + + mongo_sync_cursor_free (cursor); + mongo_sync_disconnect (conn); +} + +int +main (int argc, char *argv[]) +{ + tut_sync_connect (); + tut_sync_connect_replica (); + tut_sync_insert (); + tut_sync_query_simple (); + tut_sync_query_complex (); + + return 0; +} diff --git a/docs/tutorial/examples/tut_mongo_sync_cmd_create.c b/docs/tutorial/examples/tut_mongo_sync_cmd_create.c new file mode 100644 index 0000000..9b31c91 --- /dev/null +++ b/docs/tutorial/examples/tut_mongo_sync_cmd_create.c @@ -0,0 +1,82 @@ +#include + +#include +#include + +static void +print_coll_info (bson *info) +{ + bson_cursor *c = NULL; + bson *options = NULL; + + const gchar *name; + gboolean capped = FALSE; + gint64 size = -1; + gint64 max = -1; + + c = bson_find (info, "name"); + bson_cursor_get_string (c, &name); + bson_cursor_find (c, "options"); + + bson_cursor_get_document (c, &options); + + printf ("Options for %s:\n", name); + + bson_cursor_free (c); + bson_free (info); + + c = bson_find (options, "capped"); + bson_cursor_get_boolean (c, &capped); + bson_cursor_free (c); + + c = bson_find (options, "size"); + bson_cursor_get_int64 (c, &size); + bson_cursor_free (c); + + c = bson_find (options, "max"); + bson_cursor_get_int64 (c, &max); + bson_cursor_free (c); + + bson_free (options); + + printf ("\tCapped: %s\n", (capped) ? "yes" : "no"); + if (size > 0) + printf ("\tSize : %lu\n", size); + if (max > 0) + printf ("\tMax : %lu\n", max); + printf ("\n"); +} + +int +main (void) +{ + mongo_sync_connection *conn; + + conn = mongo_sync_connect ("localhost", 27017, FALSE); + if (!conn) + { + fprintf (stderr, "Connection failed: %s\n", strerror (errno)); + return 1; + } + + mongo_sync_cmd_create (conn, "lmc", "cmd_create", MONGO_COLLECTION_DEFAULTS); + print_coll_info (mongo_sync_cmd_exists (conn, "lmc", "cmd_create")); + + mongo_sync_cmd_create (conn, "lmc", "cmd_create_capped", + MONGO_COLLECTION_CAPPED, 655360); + print_coll_info (mongo_sync_cmd_exists (conn, "lmc", "cmd_create_capped")); + + mongo_sync_cmd_create (conn, "lmc", "cmd_create_capped_max", + MONGO_COLLECTION_CAPPED | MONGO_COLLECTION_CAPPED_MAX, + 655360, 100); + print_coll_info (mongo_sync_cmd_exists (conn, "lmc", + "cmd_create_capped_max")); + + mongo_sync_cmd_create (conn, "lmc", "cmd_create_sized", + MONGO_COLLECTION_SIZED, 655360); + print_coll_info (mongo_sync_cmd_exists (conn, "lmc", "cmd_create_sized")); + + mongo_sync_disconnect (conn); + + return 0; +} diff --git a/docs/tutorial/examples/tut_mongo_sync_cmd_custom.c b/docs/tutorial/examples/tut_mongo_sync_cmd_custom.c new file mode 100644 index 0000000..4e48b18 --- /dev/null +++ b/docs/tutorial/examples/tut_mongo_sync_cmd_custom.c @@ -0,0 +1,81 @@ +#include + +#include +#include +#include +#include + +int +main (void) +{ + mongo_sync_connection *conn; + mongo_packet *p; + mongo_sync_cursor *cursor; + bson *eval; + + conn = mongo_sync_connect ("localhost", 27017, FALSE); + if (!conn) + { + perror ("mongo_sync_connect()"); + exit (1); + } + + eval = bson_build_full (BSON_TYPE_JS_CODE, "$eval", FALSE, + "function(x){return x + 4.2;}", -1, + BSON_TYPE_ARRAY, "args", TRUE, + bson_build (BSON_TYPE_INT32, "0", 1, + BSON_TYPE_NONE), + BSON_TYPE_NONE); + bson_finish (eval); + + p = mongo_sync_cmd_custom (conn, "test", eval); + + if (!p) + { + gchar *error = NULL; + + mongo_sync_cmd_get_last_error (conn, "test", &error); + fprintf (stderr, "Can't run db.eval: %s\n", error); + g_free (error); + + exit (1); + } + + cursor = mongo_sync_cursor_new (conn, "test", p); + + if (!cursor) + { + perror ("mongo_sync_cursor_new()"); + exit (1); + } + + while (mongo_sync_cursor_next (cursor)) + { + bson *result; + bson_cursor *c; + gdouble r; + + result = mongo_sync_cursor_get_data (cursor); + if (!result) + { + perror ("mongo_sync_cursor_get_data()"); + exit (1); + } + + c = bson_find (result, "retval"); + if (!bson_cursor_get_double (c, &r)) + { + perror ("bson_cursor_get_double()"); + exit (1); + } + bson_cursor_free (c); + bson_free (result); + + printf ("Result: %2.1f\n", r); + } + + mongo_sync_cursor_free (cursor); + mongo_sync_disconnect (conn); + + return 0; +} diff --git a/docs/tutorial/examples/tut_mongo_sync_cmd_index_create.c b/docs/tutorial/examples/tut_mongo_sync_cmd_index_create.c new file mode 100644 index 0000000..0e2f0b5 --- /dev/null +++ b/docs/tutorial/examples/tut_mongo_sync_cmd_index_create.c @@ -0,0 +1,54 @@ +#include + +#include +#include + +static void +create_and_verify_index(mongo_sync_connection *conn, + bson *index) +{ + if (!mongo_sync_cmd_index_create (conn, "lmc.indexed", index, + MONGO_INDEX_UNIQUE | MONGO_INDEX_DROP_DUPS | + MONGO_INDEX_SPARSE)) + { + gchar *error = NULL; + int e = errno; + + mongo_sync_cmd_get_last_error (conn, "lmc.indexed", &error); + fprintf (stderr, "Can't create indexes: %s\n", error ? error : strerror (e)); + g_free (error); + } + else + printf ("Index successfully created!\n"); +} + +int +main (void) +{ + mongo_sync_connection *conn; + bson *invalid_index, *index; + + invalid_index = bson_build (BSON_TYPE_STRING, "name", "", -1, + BSON_TYPE_NONE); + bson_finish (invalid_index); + + index = bson_build (BSON_TYPE_INT32, "name", 1, + BSON_TYPE_NONE); + bson_finish (index); + + conn = mongo_sync_connect ("localhost", 27017, FALSE); + if (!conn) + { + fprintf (stderr, "Connection failed: %s\n", strerror (errno)); + return 1; + } + + create_and_verify_index (conn, invalid_index); + create_and_verify_index (conn, index); + + bson_free (invalid_index); + bson_free (index); + mongo_sync_disconnect (conn); + + return 0; +} diff --git a/docs/tutorial/tut_bson.h b/docs/tutorial/tut_bson.h new file mode 100644 index 0000000..973f12d --- /dev/null +++ b/docs/tutorial/tut_bson.h @@ -0,0 +1,10 @@ +/** @page tut_bson Working with BSON objects + * + * In this section, we'll cover the basics of working with BSON + * objects in a few big steps. Working with BSON is fairly + * straightforward, so we will not be going into much details here. + * + * Contents: + * - @subpage tut_bson_build + * - @subpage tut_bson_traverse + */ diff --git a/docs/tutorial/tut_bson_build.h b/docs/tutorial/tut_bson_build.h new file mode 100644 index 0000000..5c5eb54 --- /dev/null +++ b/docs/tutorial/tut_bson_build.h @@ -0,0 +1,62 @@ +/** @page tut_bson_build Building BSON objects + * + * Our first task will be to build a BSON document, which we can later + * insert into MongoDB. For this example, we want something more + * complex than a simple "Hello World"-style object, so we can + * showcase all the interesting functions of the BSON API. + * + * Lets build a document that would look like this, if we were writing + * JSON: + * @verbinclude tut_bson_build.json + * + * @dontinclude tut_bson_build.c + * + * First we start by including the main libmongo-client header. It's + * convenient to include the whole lot instead of including the used + * headers one by one, unless one's embedding only parts of the + * library. + * @until mongo.h + * + * @until { + * + * We'll be building the same BSON object in various different ways, + * so we declare a few more variables than we'd normally need. + * @until pages + * + * Next, we create the two pages: + * @until bson_finish (page2) + * + * Then we construct the "pages" array. Do note how we set the key to + * "1" and "2", and how pages is just a document! This is because in + * BSON, an array is a document that has a special type, and where + * keys are numbers. + * @until bson_finish (pages) + * + * Finally, now that we have all the subdocuments ready, we build up + * our main object: + * @until bson_finish (b_new) + * + * And that's about it! But surely, there is an easier way to do + * this... And indeed, there is, using bson_build(): + * @until bson_finish (b_builder) + * + * Much cleaner, but still, we had to create the pages array in three + * steps beforehand. Couldn't we do it in one gigantic function call + * instead? + * @until bson_finish (b_builder_full) + * + * Wonderful! We have three BSON objects created now, in three + * different ways! But are they the same? That's really easy to figure + * out. As a quick check, we can compare their sizes: if they do not + * match, we can bail out fast: + * @until } + * + * Or, we can do a more expensive comparsion, and compare the data: + * @until } + * + * And now that we are done, we free up the resources we allocated. + * @until bson_free (page1) + * + * + * @until } + */ diff --git a/docs/tutorial/tut_bson_traverse.h b/docs/tutorial/tut_bson_traverse.h new file mode 100644 index 0000000..712ff71 --- /dev/null +++ b/docs/tutorial/tut_bson_traverse.h @@ -0,0 +1,135 @@ +/** @page tut_bson_traverse Traversing BSON objects + * + * Now that we can build BSON objects (see the @ref tut_bson_build + * "previous section"), it is time that we learn how to find things in + * them! + * + * We will use the same JSON structure as in the previous example. + * + * @dontinclude tut_bson_traverse.c + * First, we include our stuff, and create a function that gives us a + * BSON object to work with: + * @until return b + * @line } + * + * @until { + * First, we need a variable to hold our BSON object, and a cursor, + * with which we can find the keys we're looking for. + * @until bson_cursor + * + * Then we need a few variables to store the retrieved information + * in. Extracting data out of a BSON object involves storing them in a + * variable of our own. + * @until v_str + * + * @until doc = tut_bson + * + * In order to find something in a BSON object, we must know the keys + * name. There's two ways to find information within a BSON object: + * bson_find() and bson_cursor_next() and its friends. + * + * The first takes a BSON object, and returns a cursor that points to + * the key we wanted to find (or to NULL, if it was not found, of + * course). We can then extract that value, and either close the + * cursor, or use bson_cursor_next() to iterate over the rest of the + * keys. + * + * The advantage of bson_find() is that we can jump to a specific key + * easily, but at the cost of having to use a new cursor every time, + * which in turn will start searching from the beginning of a BSON + * document. + * + * On the other hand, bson_cursor_next() remembers its position, and + * jumping to the next key is straightforward. It can also be used in + * conjunction with bson_find() to locate the first key we're + * interested in, and move on to the next until we're done. + * + * For our first traversal example, lets say we want to see who the + * author of our BSON object is! We can extract that information by + * locating the "author" key, and retrieving the string contents: + * @until printf + * + * Now, if we also want to know whether the 'inline' key is set to + * true or false, we have two options: if we know the exact order of + * keys, we can use the appropriate amount of bson_cursor_next() + * calls: + * @until printf + * + * But this is not only ugly, it's very sensitive to the order of the + * keys, and it's hard to understand aswell, without being familiar + * with the document's structure. + * + * So, while it is a little more inconvenient, it's better to find the + * key in some other way. But first, let's close our cursor, as we'll + * need to start again anyway... + * @until bson_cursor_free + * + * First, we'll go the easy route, and use bson_find(): + * @until printf + * + * Now, the downside of this, is that we ran through the BSON object + * twice. Well, once and a little, since the "author" key was the + * first. But using bson_find() this way has the potential of + * traversing through a document multiple times. + * + * Now, if we know the one key always comes after another, then we can + * use bson_cursor_next() to help us find it, without having to + * restart from the beginning. We do this by extracting the key name + * from the cursor, and comparing it to whatever we're searching for: + * @until printf + * + * Now the above is still picky about key order, but it's at least + * more flexible: we can put any number of keys between author and + * inline, and it will work. In most cases, that's good enough. In + * every other case, where we have no idea about key ordering, + * bson_find() is still there for us. + * + * Even better, the library itself provides a function that does + * something similar: it takes a cursor and a key name, and attempts + * to find the key past the cursor's current position. So if we + * already have the author, we can use this function to find the next + * inline key aswell: + * @until printf + * + * However, if we suspect that a key might come after the current + * position, but we're not sure, and still want to find the key with + * as little code as possible, we shall not despair! The + * bson_cursor_find() function does just that: it will try to find the + * key starting from the current position, and wrap over once if it + * can't. + * + * Lets see how it works! First, we find a key in the middle: + * @until bson_find + * + * Now that we have a key in the middle, lets find a key after it: + * @until get_boolean + * + * And once we have that - and we're at the end of our BSON object -, + * lets try finding the author key aswell: + * @until get_string + * + * That works, just like that! To verify, we go ahead and print the + * results, which should be the same as it was in the previous + * examples: + * + * @until cursor_free + * + * @until printf + * + * One thing we did not explore yet, is bson_cursor_new(): this will + * create a new cursor, and point to to the very beginning of our BSON + * object, just before the first key. Thus, the first + * bson_cursor_next() done afterwards will yield the first key. + * @until bson_cursor_free + * + * Very well! But what if we want to see the title of the second page + * within the pages array? Unfortunately, that is a bit more work to + * accomplish: we'll need to extract the pages array from our + * document, and then extract its second element, and then we can find + * stuff in that: + * @until printf + * + * And that concludes our BSON traversing tutorial! + * + * @until } + */ diff --git a/docs/tutorial/tut_hl_client.h b/docs/tutorial/tut_hl_client.h new file mode 100644 index 0000000..8b8e806 --- /dev/null +++ b/docs/tutorial/tut_hl_client.h @@ -0,0 +1,86 @@ +/** @page tut_hl_client A full-blown application + * + * As the next step of our tutorial, we will write a full blown + * application. While it does not solve any real-life problems, and + * what it does is entirely pointless, it nevertheless is a good + * example to showcase certain patterns one is likely to run into + * while developing with libmongo-client. + * + * @dontinclude tut_hl_client.c + * @until string.h + * + * Our first task is to add a handful of items to our test + * collection. We'll have two static keys, and one that's different + * for each key. + * @until gint i + * + * First, we'll build a base BSON object: + * @until bson_finish + * + * Then, we create a copy, append a counter element to the object, + * insert it, and do this a thousand times over. + * @until bson_free + * @until } + * + * This was pretty simple, wasn't it? And we even have error handling! + * Lets finish this function up, and move on. + * + * @until } + * + * Next up comes the interesting part: doing queries. We will use the + * @ref mongo_sync_cursor "cursor API" to iterate over all our + * results, hiding the gory details of database access behind its + * convenience layer. + * + * @until { + * + * We'll need a couple of things: a cursor, a query, and a string to + * store error messages in, if any. + * + * @until error + * + * Before we can query the database, we must build a query object: + * @until bson_finish + * + * Once that is done, we create a cursor, cleverly embedding the + * mongo_sync_cmd_query() call into the constructor: + * @until bson_free + * + * Again, we properly handle errors. It is very important to not just + * blindly assume things will work. While the library tries its best + * to handle invalid data gracefully, it's easy to get lost between + * the layers when one forgets to handle error cases at the + * appropriate level. + * + * But I digress, lets get back to our program! + * + * We have a nice little query cursor, it's time to loop through the + * database, extract the counter from the current BSON object, and + * move on: + * @until } + * + * At this point, we have the current document in the @a b variable, + * handled the error case, and as such, we're ready to dig deep into + * the BSON object! + * @until printf + * + * And once we're done working with the BSON object, we free the + * cursor, and the object, and continue the loop. + * @until } + * + * And in the end, we emit a newline, and free the cursor to wrap up + * our query routine. + * @until } + * + * All that is left now, is the glue that holds this together, and + * connects to MongoDB: + * @until } + * @until } + * + * I believe that does not need any further explanation. + * + * As an exercise, one can add another feature: dropping the temporary + * collection on error. Or perhaps, count the number of documents + * returned, and see if and how the count changes between subsequent + * runs of the test program. + */ diff --git a/docs/tutorial/tut_json2bson.h b/docs/tutorial/tut_json2bson.h new file mode 100644 index 0000000..f263234 --- /dev/null +++ b/docs/tutorial/tut_json2bson.h @@ -0,0 +1,97 @@ +/** @page tut_json2bson JSON to BSON converter + * + * Now that we have a basic grasp of the library, we'll write a + * solution to a real life problem: converting JSON to BSON. + * + * Our program will expect correctly formatted JSON, in condensed + * one-line format, and will output a BSON document for each line of + * JSON received. + * + * @dontinclude tut_json2bson.c + * @until glib.h + * + * First, we forward declare the json_to_bson() function, because + * we'll recursively use it later on: + * @until json_to_bson + * + * Next, we create the heart of the program, a function that takes a + * BSON object, a value and a key, and appends the key-value pair to + * the bson object, with the correct type. + * @until { + * + * We do this by checking the JSON object's type, and acting up on it: + * @until switch + * @until { + * + * The boolean, double, integer and string types are easy: we just use + * the appropriate bson_append_*() function: + * @until break + * @until break + * @until break + * @until break + * + * Converting a JSON object to BSON is a bit more complicated, yet, + * straightforward nevertheless: + * @until } + * + * This is one of the reasons we needed to forward-declare + * json_to_bson(): we're using it to turn the JSON value into BSON, + * and append it as a subdocument. + * + * Next up: arrays! This is even trickier than sub-documents, as we + * need to iterate over the elements, and append each + * individually. But, trickier as it may be, it's still + * straightforward; + * @until } + * @until } + * + * Anything else, we ignore: + * @until break + * + * @until } + * + * @until } + * + * And to bind this together with JSON-C's API, we need two more + * functions. The first one will simply iterate over a JSON object, + * and call the function we wrote above: + * @until } + * @until } + * + * The next one is another wrapper around this former: it creates a + * BSON document, calls the foreach method, then finishes the BSON + * object and we're done: + * @until } + * + * We're almost done! All that is left is writing our program's entry + * point: something that will read the input, turn it into BSON, and + * write it out: + * + * @until json_tokener + * + * We do some setting up, creating a new IO channel, and a JSON + * tokenizer: + * @until tokener = + * + * Then, until we have something to read... + * @until { + * @until bson + * + * We reset the tokenizer before parsing another line, then parse the + * JSON we received: + * @until } + * + * If we received something other than a JSON object, we can't turn + * that into BSON, so we write an error to STDERR, and skip this line: + * @until } + * + * Otherwise, we turn it into BSON, and write it to STDOUT: + * @until bson_free + * + * @until } + * + * And that was our program, a very simple application that turns each + * line of JSON into BSON. + * + * @until } + */ diff --git a/docs/tutorial/tut_mongo_sync.h b/docs/tutorial/tut_mongo_sync.h new file mode 100644 index 0000000..bc86a7e --- /dev/null +++ b/docs/tutorial/tut_mongo_sync.h @@ -0,0 +1,16 @@ +/** @page tut_mongo_sync Working with the Mongo Sync API + * + * In this section we'll be going over various parts of the + * synchronous API provided by libmongo-client. From connecting to a + * single host, through replica sets to performing various more + * complex operations. + * + * Contents: + * - @subpage tut_mongo_sync_connect + * - @subpage tut_mongo_sync_insert + * - @subpage tut_mongo_sync_query + * - @subpage tut_mongo_sync_query_complex + * - @subpage tut_mongo_sync_cmd_create + * - @subpage tut_mongo_sync_cmd_index_create + * - @subpage tut_mongo_sync_cmd_custom + */ diff --git a/docs/tutorial/tut_mongo_sync_cmd_create.h b/docs/tutorial/tut_mongo_sync_cmd_create.h new file mode 100644 index 0000000..f05940d --- /dev/null +++ b/docs/tutorial/tut_mongo_sync_cmd_create.h @@ -0,0 +1,53 @@ +/** @page tut_mongo_sync_cmd_create Creating collections + * + * In this simple example we'll learn how to explicitly create + * collections with the library, be those normal collections, capped + * ones or simply preallocated. + * + * Our application will attempt to create a normal collection, a + * capped one, a capped one that's also capped on the number of + * entries, and a pre-allocated (but uncapped) collection. + * + * It will print these properties of the collections aswell, so that + * we can verify that the creation did indeed work. + * + * @dontinclude tut_mongo_sync_cmd_create.c + * @until stdio.h + * + * First of all, we need a function that prints the collection + * properties. Because we're lazy, it will take a BSON object, as + * returned by mongo_sync_cmd_exists(). + * + * The output of said command is a BSON object that has a @a name + * field, which is the full name of the collection, the database part + * included; and an @a options subdocument, which lists various + * options specified during creating, such as cappedness, size and + * maximum number of elements. + * + * Our very simple function will extract all these and print what's + * appropriate. It will also free the BSON object it was given, so + * that we don't leak memory. + * @until printf ("\n") + * @until } + * + * With that done, lets get down to business, and create the + * collections, after connecting to the server, of course. + * @until } + * + * First we create a completely normal collection, with the default + * settings: + * @until print_coll_info + * + * Then a capped collection: + * @until print_coll_info + * + * Followed by another capped collection, one that is also capped by + * the number of elements, not only by size: + * @until print_coll_info + * + * And finally, we create a pre-allocated collection: + * @until print_coll_info + * + * And that's about it, really. + * @until } + */ diff --git a/docs/tutorial/tut_mongo_sync_cmd_custom.h b/docs/tutorial/tut_mongo_sync_cmd_custom.h new file mode 100644 index 0000000..0b224b2 --- /dev/null +++ b/docs/tutorial/tut_mongo_sync_cmd_custom.h @@ -0,0 +1,64 @@ +/** @page tut_mongo_sync_cmd_custom Running custom commands + * + * Sometimes it is necessary to run custom commands against a + * database, commands for which the library does not provide a + * convenience wrapper for. In this tutorial, we will explore how to + * run server-side evaluations, using the @a $eval command. + * + * @dontinclude tut_mongo_sync_cmd_custom.c + * @until stdlib.h + * + * @until eval + * + * First, we connect to the database, and create a BSON object that + * will hold our command, one that creates a function server side, + * that takes one argument, and returns the argument plus 4.2. The + * BSON object will also set up the arguments passed to this function, + * which, in our case, will be the number @a 1. + * + * @line conn = + * @until } + * + * @line eval = + * @until bson_finish + * + * Once we have the connection and the query established, it is time + * to send the command: + * + * @line p = + * @until } + * + * We then create a cursor from the returned packet, and iterate over + * it (in case there are multiple documents returned - which will not + * be the case here): + * + * @line cursor = + * @until } + * + * @until gdouble + * + * We want to retrieve each document, and find the @a retval key in + * them, because that's where @a $eval returns the results to us. + * + * @line result = + * @until } + * @until } + * + * At this point, we have successfully extracted the data, so we can + * free up the BSON and cursor objects. + * + * @line bson_cursor_free + * @until bson_free + * + * And finally, print the result: + * + * @until printf + * + * @until } + * + * And that's it! We clean up, disconnect, and that's all there is to + * running custom commands! + * + * @line mongo_sync_cursor_free + * @until } + */ diff --git a/docs/tutorial/tut_mongo_sync_cmd_index_create.h b/docs/tutorial/tut_mongo_sync_cmd_index_create.h new file mode 100644 index 0000000..22842e0 --- /dev/null +++ b/docs/tutorial/tut_mongo_sync_cmd_index_create.h @@ -0,0 +1,66 @@ +/** @page tut_mongo_sync_cmd_index_create Creating indexes + * + * This example will show how to properly create indexes, how to + * verify its success, and will also give hints on how to prepare the + * BSON used to create the index. + * + * @dontinclude tut_mongo_sync_cmd_index_create.c + * @until stdio.h + * + * We will be creating and verifying multiple indexes, so lets create + * a function that takes a connection, a prepared index, and does the + * create and verify magic. + * + * @line static void + * @until } + * @until } + * + * This will create the index, and if it succeeds, write that to + * stdout. If it fails, it will try to query the last error, and print + * that to stderr. + * + * All we have to do past this point, is to build a few index + * specifications in BSON, and see what happens: + * + * @line int + * @until bson + * + * @line invalid + * @until bson_finish + * + * The first index spec we create will have a single index field, @a + * name, where we set the value to an empty string. However - as we + * will soon see - this is not a valid specification, as MongoDB does + * not accept string-typed fields in the index spec. + * + * @line index + * @until bson_finish + * + * Armed with the knowledge that strings are not going to work, we + * turn to our trusty old integers. Integers (32-bit integers at that, + * there really is no need to use a 64-bit value here) are the best + * fit for the type of an index field, because one can tell MongoDB + * the sort order (with negative or positive numbers) with them easily. + * + * @line conn = + * @until } + * + * We now have two index specs in BSON, and an established connection, + * lets see what happens! + * + * @line create_and_verify + * @until conn, index + * + * The first will - as explained above - fail, the second will + * succeed. + * + * And that is all it takes to create simple indexes! We now free up + * our BSON objects and disconnect, and the tutorial program is all + * done and finished. + * + * @line bson_free + * @until disconnect + * + * @line return + * @until } + */ diff --git a/docs/tutorial/tut_mongo_sync_connect.h b/docs/tutorial/tut_mongo_sync_connect.h new file mode 100644 index 0000000..1fb8b4a --- /dev/null +++ b/docs/tutorial/tut_mongo_sync_connect.h @@ -0,0 +1,49 @@ +/** @page tut_mongo_sync_connect Connecting to MongoDB + * + * The next step in our journey is to connect to MongoDB: to a single + * server and to a replicaset alike. + * + * Our first task is to connect to a MongoDB server, listening + * on localhost's 27017 port. And we don't care whether it is a master + * or a secondary, so we set the slave_ok argument to TRUE: + * + * @dontinclude tut_mongo_sync.c + * @skip void + * @until mongo_sync_disconnect + * @until } + * + * It's fairly straightforward: error handling is done using errno + * values, because that saves us from inventing our own statuses: + * POSIX provides us with plenty, and the C library uses errno + * extensively well. So does libmongo-client! + * + * Next up, is connecting to a replicaset: + * + * @until return; + * @until } + * + * Wait a minute! Does this look familiar? Isn't it @b exactly the + * same as in the former example (apart from the host name)? It sure + * is! There really is no difference between connecting to a single + * server and to a replica set when using the Sync API. It hides all + * the boring things from the user. + * + * However, if the server is a replicaset, we can add seeds: seeds are + * hosts that are not listed in the replicaset's public config + * (meaning they're hidden), but we still want to be able to use them, + * if so need be. + * + * It's not neccessary to add seeds, if the replica set itself + * advertises secondaries: the library will discover those, and + * reconnect to them, if automatic reconnection is turned on. Lets + * just do that! + * + * @until } + * + * Then we can add the seeds: + * @until } + * @until } + * + * And that's about it! We wrap up our function, and we're done! + * @until } + */ diff --git a/docs/tutorial/tut_mongo_sync_insert.h b/docs/tutorial/tut_mongo_sync_insert.h new file mode 100644 index 0000000..aaf0754 --- /dev/null +++ b/docs/tutorial/tut_mongo_sync_insert.h @@ -0,0 +1,46 @@ +/** @page tut_mongo_sync_insert Inserting documents into MongoDB + * + * Now that we know how to connect, it is time to take another step + * forward, and put something into our database. We already learned + * how to build BSON objects in @ref tut_bson_build, so lets put that + * knowledge together, and insert a document! + * + * @dontinclude tut_mongo_sync.c + * @skip tut_sync_connect_replica + * @skip } + * @skip void + * @until { + * + * First, we define a couple of variables, a connection, and three documents: + * + * @until bson + * + * Then we do our routine connect: + * @until } + * + * And then build a BSON object, as we've learned earlier: + * @until bson_finish + * + * Now we have a connection, and we have a document, it's time to get + * dirty, and insert: + * + * @until } + * + * One might wonder what that @c NULL is at the end of + * mongo_sync_cmd_insert()'s argument list: it's the @a sentinel. The + * value that marks the end of the documents we want to insert. It is + * needed, because the insert command can take any number of + * documents, and it will try to insert them in bulk. + * + * Lets try that, and build two more documents: + * @until bson_finish (doc3) + * + * Then we insert the two new documents into the same collection, at + * the same time: + * @until } + * + * And we're done! It's that straightforward. All we have left is + * cleaning up! + * + * @until } + */ diff --git a/docs/tutorial/tut_mongo_sync_query.h b/docs/tutorial/tut_mongo_sync_query.h new file mode 100644 index 0000000..ebed5a1 --- /dev/null +++ b/docs/tutorial/tut_mongo_sync_query.h @@ -0,0 +1,67 @@ +/** @page tut_mongo_sync_query Querying documents + * + * We can connect, insert, and we still vaguely remember how to build + * BSON objects: how about we go out and query the database this time? + * + * @dontinclude tut_mongo_sync.c + * @skip tut_sync_insert + * @skip } + * @skip void + * @until { + * + * First, we define a couple of variables: a connection, a packet, a + * cursor, a BSON object and a counter: + * + * @until gint i + * + * We'll use the packet as an intermediate step between querying and + * making a cursor. We'll see why later. The query will be used to + * limit the documents queried, and the counter is just for pretty + * printing. + * + * Then we do our routine connect: + * @until } + * + * And then build a BSON object, an empty one, because an empty query + * means we're interested in all of the documents! + * @until bson_finish + * + * Now we have a connection, and we have a query, lets tell MongoDB + * what we want: + * + * @until bson_free + * + * The first two parameters are obvious. The third is a set of flags - + * but we don't use any right now. Then comes the number of documents + * to skip, and the number of documents to return, followed by a + * query, and an optional field selector, which we just left empty + * (meaning we want all fields returned). + * + * There's more than one way to figure out the data returned by a + * query: we can either use the returned packet as-is, and extract + * data from it using the low-level mongo_wire family of functions. Or + * we can make a cursor out of this packet, and iterate over the + * elements: + * + * @until } + * + * @until } + * + * The first thing we do inside of the loop is to get the data from + * the cursor - or bail out with an error if we can't. + * + * @until printf + * + * Then we proceed to make a BSON cursor, and print all the keys that + * belong to the document. + * + * Once that's done, we free the resources we used, and continue along + * the loop, until our cursor signals the end of the query. + * + * @until printf + * + * @until } + * + * Then we clean up and go home: + * @until } + */ diff --git a/docs/tutorial/tut_mongo_sync_query_complex.h b/docs/tutorial/tut_mongo_sync_query_complex.h new file mode 100644 index 0000000..145ab0e --- /dev/null +++ b/docs/tutorial/tut_mongo_sync_query_complex.h @@ -0,0 +1,43 @@ +/** @page tut_mongo_sync_query_complex Querying documents, part two + * + * We learned how to make simple queries in the previous section, + * we'll be brave and do something much more advanced this time: we'll + * limit the query to documents that have their @c "yes?" field set to + * @a FALSE, and sort the results by the @c "n" field, in ascending + * order. + * + * @dontinclude tut_mongo_sync.c + * @skip tut_sync_query_simple + * @skip } + * @skip void + * @until { + * + * @until gint i + * + * @until } + * + * After our routine connect, we build the query and select BSON + * objects: + * + * @until bson_finish (select) + * + * Then we launch the query: + * @until bson_free (select) + * + * And make a cursor, just like last time: + * @until } + * + * And that's pretty much the bulk of what we wanted to do: we just + * constructed our query and select BSON objects appropriately, and + * mongo_sync_cmd_query() does the rest. + * + * But just to make sure our results are sane, we iterate over the + * returned documents, and print the fields we're interested in: + * + * @until i++ + * @until } + * + * And when that is done, all that is left, is to clean up after + * ourselves: + * @until } + */ diff --git a/docs/tutorial/tutorial.h b/docs/tutorial/tutorial.h new file mode 100644 index 0000000..e136071 --- /dev/null +++ b/docs/tutorial/tutorial.h @@ -0,0 +1,34 @@ +/** @page tutorial Tutorial + * + * These pages will attempt to guide one through the libmongo-client + * library, starting from the basic BSON building blocks, through the + * low level wire protocol API, until the highest level synchronous + * API. + * + * The documentation assumes a reasonable amount of C knowledge, and + * basic familiarity with MongoDB concepts. + * + * The example programs can be found in the @c docs/tut/examples + * directory in the source tree, along with a Makefile. Would one want + * to compile the examples, or modified versions of them by hand, then + * the following command should work: + * + * @verbatim +$ cc $(pkg-config --cflags libmongo-client) tut_bson_build.c $(pkg-config --libs libmongo-client) -o tut_bson_build +@endverbatim + * + * Contents: + * - @subpage tut_bson + * - @ref tut_bson_build + * - @ref tut_bson_traverse + * - @subpage tut_mongo_sync + * - @ref tut_mongo_sync_connect + * - @ref tut_mongo_sync_insert + * - @ref tut_mongo_sync_query + * - @ref tut_mongo_sync_query_complex + * - @ref tut_mongo_sync_cmd_create + * - @ref tut_mongo_sync_cmd_index_create + * - @ref tut_mongo_sync_cmd_custom + * - @subpage tut_hl_client + * - @subpage tut_json2bson + */ -- cgit v1.2.3