bionic (3) mongoc_reference.3.gz

Provided by: libmongoc-doc_1.9.2+dfsg-1build1_all bug

NAME

       mongoc_reference - Index

MONGODB C DRIVER

       A Cross Platform MongoDB Client Library for C

   Introduction
       The  MongoDB C Driver, also known as "libmongoc", is a library for using MongoDB from C applications, and
       for writing MongoDB drivers in higher-level languages.

       It depends on libbson to generate and parse BSON documents, the native data format of MongoDB.

   Installing the MongoDB C Driver
       The following guide will step you through the  process  of  downloading,  building,  and  installing  the
       current release of the MongoDB C Driver.

   Supported Platforms
       The MongoDB C Driver is continuously tested on variety of platforms including:

       • Archlinux

       • Debian 8.1

       • macOS 10.10

       • Microsoft Windows Server 2008

       • RHEL 7.0, 7.1, 7.2

       • SUSE 12

       • Ubuntu 12.04, 14.04, 16.04

       • Clang 3.4, 3.5, 3.7, 3.8

       • GCC 4.6, 4.8, 4.9, 5.3

       • MinGW-W64

       • Visual Studio 2010, 2013, 2015

       • x86, x86_64, ARM (aarch64), Power8 (ppc64le), zSeries (s390x)

   Install with a Package Manager
       The libmongoc package is available on recent versions of Debian and Ubuntu.

          $ apt-get install libmongoc-1.0-0

       On Fedora, a mongo-c-driver package is available in the default repositories and can be installed with:

          $ dnf install mongo-c-driver

       On  recent  Red Hat systems, such as CentOS and RHEL 7, a mongo-c-driver package is available in the EPEL
       repository. To check version available, see  https://apps.fedoraproject.org/packages/mongo-c-driver.  The
       package can be installed with:

          $ yum install mongo-c-driver

   Building on Unix
   Prerequisites
       OpenSSL  is  required  for  authentication  or  for  SSL connections to MongoDB. Kerberos or LDAP support
       requires Cyrus SASL.

       To install all optional dependencies on RedHat / Fedora:

          $ sudo yum install pkg-config openssl-devel cyrus-sasl-devel

       On Debian / Ubuntu:

          $ sudo apt-get install pkg-config libssl-dev libsasl2-dev

       On FreeBSD:

          $ su -c 'pkg install pkgconf openssl cyrus-sasl'

   Building from a release tarball
       Unless you intend on contributing to the mongo-c-driver, you will want to build from a release tarball.

       The most recent release of libmongoc is 1.9.2 and can be downloaded  here.  The  following  snippet  will
       download and extract the driver, and configure it:

          $ wget https://github.com/mongodb/mongo-c-driver/releases/download/1.9.2/mongo-c-driver-1.9.2.tar.gz
          $ tar xzf mongo-c-driver-1.9.2.tar.gz
          $ cd mongo-c-driver-1.9.2
          $ ./configure --disable-automatic-init-and-cleanup

       The  --disable-automatic-init-and-cleanup  option  is  recommended,  see  init-cleanup. For a list of all
       configure options, run ./configure --help.

       If configure completed successfully, you'll see  something  like  the  following  describing  your  build
       configuration.

          libmongoc 1.9.2 was configured with the following options:

          Build configuration:
            Enable debugging (slow)                          : no
            Compile with debug symbols (slow)                : no
            Enable GCC build optimization                    : yes
            Enable automatic init and cleanup                : no
            Enable maintainer flags                          : no
            Code coverage support                            : no
            Cross Compiling                                  : no
            Fast counters                                    : no
            Shared memory performance counters               : yes
            SASL                                             : sasl2
            SSL                                              : openssl
            Snappy Compression                               : no
            Zlib Compression                                 : bundled
            Libbson                                          : bundled

          Documentation:
            man                                              : no
            HTML                                             : no

       mongo-c-driver  contains  a copy of libbson, in case your system does not already have libbson installed.
       The configure script will detect if libbson is not installed and use the bundled libbson.

          $ make
          $ sudo make install

   Building from git
       To build an unreleased version of the driver from git requires additional dependencies.

       RedHat / Fedora:

          $ sudo yum install git gcc automake autoconf libtool

       Debian / Ubuntu:

          $ sudo apt-get install git gcc automake autoconf libtool

       FreeBSD:

          $ su -c 'pkg install git gcc automake autoconf libtool'

       Once you have the dependencies installed, clone  the  repository  and  build  the  current  master  or  a
       particular release tag:

          $ git clone https://github.com/mongodb/mongo-c-driver.git
          $ cd mongo-c-driver
          $ git checkout x.y.z  # To build a particular release
          $ ./autogen.sh --with-libbson=bundled
          $ make
          $ sudo make install

   Generating the documentation
       Install Sphinx, then:

          $ ./configure --enable-html-docs --enable-man-pages
          $ make man html

   Building on Mac OS X
       Install the XCode Command Line Tools:

          $ xcode-select --install

       The pkg-config utility is also required. First install Homebrew according to its instructions, then:

          $ brew install pkgconfig

       Download the latest release tarball:

          $ curl -LO https://github.com/mongodb/mongo-c-driver/releases/download/1.9.2/mongo-c-driver-1.9.2.tar.gz
          $ tar xzf mongo-c-driver-1.9.2.tar.gz
          $ cd mongo-c-driver-1.9.2

       Build and install the driver:

          $ ./configure
          $ make
          $ sudo make install

   Native TLS Support on Mac OS X / Darwin (Secure Transport)
       The  MongoDB  C  Driver  supports the Darwin native TLS and crypto libraries.  Using the native libraries
       there is no need to install OpenSSL. By default however, the driver will compile against  OpenSSL  if  it
       detects it being available. If OpenSSL is not available, it will fallback on the native libraries.

       To  compile against the Darwin native TLS and crypto libraries, even when OpenSSL is available, configure
       the driver like so:

          $ ./configure --enable-ssl=darwin

   OpenSSL support on El Capitan
       Beginning in OS X 10.11 El Capitan, OS X no longer includes the OpenSSL headers. To build the driver with
       SSL on El Capitan and later:

          $ brew install openssl
          $ export LDFLAGS="-L/usr/local/opt/openssl/lib"
          $ export CPPFLAGS="-I/usr/local/opt/openssl/include"

   Building on Windows
       Building  on Windows requires Windows Vista or newer and Visual Studio 2010 or newer. Additionally, cmake
       is required to generate Visual Studio project files.

       Let's start by generating Visual Studio project files for libbson, a dependency  of  the  C  driver.  The
       following  assumes  we  are  compiling  for 64-bit Windows using Visual Studio 2015 Express, which can be
       freely downloaded from Microsoft.

          cd mongo-c-driver-1.9.2\src\libbson
          cmake -G "Visual Studio 14 2015 Win64" \
            "-DCMAKE_INSTALL_PREFIX=C:\mongo-c-driver" \
            "-DCMAKE_BUILD_TYPE=Release" # Defaults to debug builds

       (Run cmake -LH . for a list of other options.)

       Now that we have project files generated, we can either open the project in Visual Studio or compile from
       the command line. Let's build using the command line program msbuild.exe

          msbuild.exe /p:Configuration=Release ALL_BUILD.vcxproj

       Now  that libbson is compiled, let's install it using msbuild. It will be installed to the path specified
       by CMAKE_INSTALL_PREFIX.

          msbuild.exe /p:Configuration=Release INSTALL.vcxproj

       You should now see libbson installed in C:\mongo-c-driver

       Now let's do the same for the MongoDB C driver.

          cd mongo-c-driver-1.9.2
          cmake -G "Visual Studio 14 2015 Win64" \
            "-DENABLE_SSL=WINDOWS" \
            "-DENABLE_SASL=SSPI" \
            "-DCMAKE_INSTALL_PREFIX=C:\mongo-c-driver" \
            "-DCMAKE_PREFIX_PATH=C:\mongo-c-driver" \
            "-DCMAKE_BUILD_TYPE=Release" # Defaults to debug builds

          msbuild.exe /p:Configuration=Release ALL_BUILD.vcxproj
          msbuild.exe /p:Configuration=Release INSTALL.vcxproj

       All of the MongoDB C Driver's components will now have been build in release mode and  can  be  found  in
       C:\mongo-c-driver.  To build and install debug binaries, remove the "-DCMAKE_BUILD_TYPE=Release" argument
       to cmake and /p:Configuration=Release to msbuild.exe.

       To use the driver libraries in your program, see visual-studio-guide.

   Native TLS Support on Windows (Secure Channel)
       The MongoDB C Driver supports the Windows native TLS and crypto libraries.  Using  the  native  libraries
       there  is  no  need to install OpenSSL. By default however, the driver will compile against OpenSSL if it
       detects it being available. If OpenSSL is not available, it will fallback on the native libraries.

       To compile against the Windows native TLS and crypto libraries, even when OpenSSL is available, configure
       the driver like so:

          cmake -G "Visual Studio 14 2015 Win64" \
            "-DENABLE_SSL=WINDOWS" \
            "-DCMAKE_INSTALL_PREFIX=C:\\mongo-c-driver" \
            "-DCMAKE_PREFIX_PATH=C:\\mongo-c-driver"

   Native SASL Support on Windows (SSPI)
       The MongoDB C Driver supports the Windows native Kerberos and Active Directory interface, SSPI. Using the
       native libraries there is no need to install any dependencies, such as cyrus-sasl.  By  default  however,
       the driver will compile against cyrus-sasl.

       To compile against the Windows native SSPI, configure the driver like so:

          cmake -G "Visual Studio 14 2015 Win64" \
            "-DENABLE_SASL=SSPI" \
            "-DCMAKE_INSTALL_PREFIX=C:\\mongo-c-driver" \
            "-DCMAKE_PREFIX_PATH=C:\\mongo-c-driver"

   OpenSSL support on Windows
       For  backwards  compatibility  CMake  will default to OpenSSL support.  If not found, it will fallback to
       native TLS support provided by the platform.

       OpenSSL 1.1.0 support requires CMake 3.7 or later on Windows.

   Tutorial
       This guide offers a brief introduction to the MongoDB C Driver.

       For more information on the C API, please refer to the api.

   ContentsTutorialInstallingStarting MongoDBInclude and link libmongoc in your C programUse libmongoc in a Microsoft Visual Studio ProjectMaking a ConnectionCreating BSON DocumentsBasic CRUD OperationsExecuting CommandsThreadingNext Steps

   Installing
       For detailed instructions on installing the MongoDB C Driver on a particular  platform,  please  see  the
       installation guide.

   Starting MongoDB
       To  run  the examples in this tutorial, MongoDB must be installed and running on localhost on the default
       port, 27017. To check if it is up and running, connect to it with the MongoDB shell.

          $ mongo --host localhost --port 27017
          MongoDB shell version: 3.0.6
          connecting to: localhost:27017/test
          >

   Include and link libmongoc in your C program
   Include mongoc.h
       All libmongoc's functions and types are available in one header file. Simply include mongoc.h:

          #include <mongoc.h>

   CMake
       The libmongoc installation includes a CMake config-file package, so  you  can  use  CMake's  find_package
       command to find libmongoc's header and library paths and link to libmongoc: CMakeLists.txt.INDENT 0.0

          # Specify the minimum version you require.
          find_package (libmongoc-1.0 1.7 REQUIRED)

          message ("--   mongoc found version \"${MONGOC_VERSION}\"")
          message ("--   mongoc include path \"${MONGOC_INCLUDE_DIRS}\"")
          message ("--   mongoc libraries \"${MONGOC_LIBRARIES}\"")

          # The "hello_mongoc.c" sample program is shared among four tests.
          add_executable (hello_mongoc ../../hello_mongoc.c)
          target_include_directories (hello_mongoc PRIVATE "${MONGOC_INCLUDE_DIRS}")
          target_link_libraries (hello_mongoc PRIVATE "${MONGOC_LIBRARIES}")
          target_compile_definitions (hello_mongoc PRIVATE "${MONGOC_DEFINITIONS}")
libmongoc-static-1.0 config-file package:

          # Specify the minimum version you require.
          find_package (libmongoc-static-1.0 1.7 REQUIRED)

          message ("--   mongoc found version \"${MONGOC_STATIC_VERSION}\"")
          message ("--   mongoc include path \"${MONGOC_STATIC_INCLUDE_DIRS}\"")
          message ("--   mongoc libraries \"${MONGOC_STATIC_LIBRARIES}\"")

          # The "hello_mongoc.c" sample program is shared among four tests.
          add_executable (hello_mongoc ../../hello_mongoc.c)
          target_include_directories (hello_mongoc PRIVATE "${MONGOC_STATIC_INCLUDE_DIRS}")
          target_link_libraries (hello_mongoc PRIVATE "${MONGOC_STATIC_LIBRARIES}")
          target_compile_definitions (hello_mongoc PRIVATE "${MONGOC_STATIC_DEFINITIONS}")

   pkg-config
       If you're not using CMake, use pkg-config on the command line to set header and library paths:

          gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-1.0)

       Or to statically link to libmongoc:

          gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-static-1.0)

   Specifying header and include paths manually
       If you aren't using CMake or pkg-config, paths and libraries can be managed manually.

          $ gcc -o hello_mongoc hello_mongoc.c \
              -I/usr/local/include/libbson-1.0 -I/usr/local/include/libmongoc-1.0 \
              -lmongoc-1.0 -lbson-1.0
          $ ./hello_mongoc
          { "ok" : 1.000000 }

       For Windows users, the code can be compiled and run with the following commands. (This assumes  that  the
       MongoDB C Driver has been installed to C:\mongo-c-driver; change the include directory as needed.)

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 hello_mongoc.c
          C:\> hello_mongoc
          { "ok" : 1.000000 }

   Use libmongoc in a Microsoft Visual Studio Project
       See the libmongoc and Visual Studio guide.

   Making a Connection
       Access  MongoDB with a mongoc_client_t. It transparently connects to standalone servers, replica sets and
       sharded clusters on demand. To perform operations on a database or collection, create a mongoc_database_t
       or mongoc_collection_t struct from the mongoc_client_t.

       At  the  start of an application, call mongoc_init before any other libmongoc functions. At the end, call
       the appropriate destroy function for each collection, database, or client handle, in reverse  order  from
       how they were constructed. Call mongoc_cleanup before exiting.

       The  example  below  establishes  a  connection to a standalone server on localhost, registers the client
       application as "connect-example," and performs a simple command.

       More information about database operations can be found in the CRUD  Operations  and  Executing  Commands
       sections.  Examples  of  connecting  to  replica  sets  and sharded clusters can be found on the Advanced
       Connections page.  hello_mongoc.c.INDENT 0.0

          #include <mongoc.h>

          int
          main (int argc, char *argv[])
          {
             const char *uri_str = "mongodb://localhost:27017";
             mongoc_client_t *client;
             mongoc_database_t *database;
             mongoc_collection_t *collection;
             bson_t *command, reply, *insert;
             bson_error_t error;
             char *str;
             bool retval;

             /*
              * Required to initialize libmongoc's internals
              */
             mongoc_init ();

             /*
              * Optionally get MongoDB URI from command line
              */
             if (argc > 1) {
                uri_str = argv[1];
             }

             /*
              * Create a new client instance
              */
             client = mongoc_client_new (uri_str);

             /*
              * Register the application name so we can track it in the profile logs
              * on the server. This can also be done from the URI (see other examples).
              */
             mongoc_client_set_appname (client, "connect-example");

             /*
              * Get a handle on the database "db_name" and collection "coll_name"
              */
             database = mongoc_client_get_database (client, "db_name");
             collection = mongoc_client_get_collection (client, "db_name", "coll_name");

             /*
              * Do work. This example pings the database, prints the result as JSON and
              * performs an insert
              */
             command = BCON_NEW ("ping", BCON_INT32 (1));

             retval = mongoc_client_command_simple (
                client, "admin", command, NULL, &reply, &error);

             if (!retval) {
                fprintf (stderr, "%s\n", error.message);
                return EXIT_FAILURE;
             }

             str = bson_as_json (&reply, NULL);
             printf ("%s\n", str);

             insert = BCON_NEW ("hello", BCON_UTF8 ("world"));

             if (!mongoc_collection_insert_one (collection, insert, NULL, NULL, &error)) {
                fprintf (stderr, "%s\n", error.message);
             }

             bson_destroy (insert);
             bson_destroy (&reply);
             bson_destroy (command);
             bson_free (str);

             /*
              * Release our handles and clean up libmongoc
              */
             mongoc_collection_destroy (collection);
             mongoc_database_destroy (database);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

   Creating BSON Documents
       Documents are stored in MongoDB's data format, BSON. The C driver uses libbson to create BSON  documents.
       There are several ways to construct them: appending key-value pairs, using BCON, or parsing JSON.

   Appending BSON
       A  BSON document, represented as a bson_t in code, can be constructed one field at a time using libbson's
       append functions.

       For example, to create a document like this:

          {
             born : ISODate("1906-12-09"),
             died : ISODate("1992-01-01"),
             name : {
                first : "Grace",
                last : "Hopper"
             },
             languages : [ "MATH-MATIC", "FLOW-MATIC", "COBOL" ],
             degrees: [ { degree: "BA", school: "Vassar" }, { degree: "PhD", school: "Yale" } ]
          }

       Use the following code:

          #include <bson.h>

          int
          main (int   argc,
                char *argv[])
          {
             struct tm   born = { 0 };
             struct tm   died = { 0 };
             const char *lang_names[] = {"MATH-MATIC", "FLOW-MATIC", "COBOL"};
             const char *schools[] = {"Vassar", "Yale"};
             const char *degrees[] = {"BA", "PhD"};
             uint32_t    i;
             char        buf[16];
             const       char *key;
             size_t      keylen;
             bson_t     *document;
             bson_t      child;
             bson_t      child2;
             char       *str;

             document = bson_new ();

             /*
              * Append { "born" : ISODate("1906-12-09") } to the document.
              * Passing -1 for the length argument tells libbson to calculate the string length.
              */
             born.tm_year = 6;  /* years are 1900-based */
             born.tm_mon = 11;  /* months are 0-based */
             born.tm_mday = 9;
             bson_append_date_time (document, "born", -1, mktime (&born) * 1000);

             /*
              * Append { "died" : ISODate("1992-01-01") } to the document.
              */
             died.tm_year = 92;
             died.tm_mon = 0;
             died.tm_mday = 1;

             /*
              * For convenience, this macro passes length -1 by default.
              */
             BSON_APPEND_DATE_TIME (document, "died", mktime (&died) * 1000);

             /*
              * Append a subdocument.
              */
             BSON_APPEND_DOCUMENT_BEGIN (document, "name", &child);
             BSON_APPEND_UTF8 (&child, "first", "Grace");
             BSON_APPEND_UTF8 (&child, "last", "Hopper");
             bson_append_document_end (document, &child);

             /*
              * Append array of strings. Generate keys "0", "1", "2".
              */
             BSON_APPEND_ARRAY_BEGIN (document, "languages", &child);
             for (i = 0; i < sizeof lang_names / sizeof (char *); ++i) {
                keylen = bson_uint32_to_string (i, &key, buf, sizeof buf);
                bson_append_utf8 (&child, key, (int) keylen, lang_names[i], -1);
             }
             bson_append_array_end (document, &child);

             /*
              * Array of subdocuments:
              *    degrees: [ { degree: "BA", school: "Vassar" }, ... ]
              */
             BSON_APPEND_ARRAY_BEGIN (document, "degrees", &child);
             for (i = 0; i < sizeof degrees / sizeof (char *); ++i) {
                keylen = bson_uint32_to_string (i, &key, buf, sizeof buf);
                bson_append_document_begin (&child, key, (int) keylen, &child2);
                BSON_APPEND_UTF8 (&child2, "degree", degrees[i]);
                BSON_APPEND_UTF8 (&child2, "school", schools[i]);
                bson_append_document_end (&child, &child2);
             }
             bson_append_array_end (document, &child);

             /*
              * Print the document as a JSON string.
              */
             str = bson_as_canonical_extended_json (document, NULL);
             printf ("%s\n", str);
             bson_free (str);

             /*
              * Clean up allocated bson documents.
              */
             bson_destroy (document);
             return 0;
          }

       See the libbson documentation for all of the types that can be appended to a bson_t.

   Using BCON
       BSON C Object Notation, BCON for short, is an alternative way of constructing BSON documents in a  manner
       closer  to  the intended format. It has less type-safety than BSON's append functions but results in less
       code.

          #include <bson.h>

          int
          main (int   argc,
                char *argv[])
          {
             struct tm born = { 0 };
             struct tm died = { 0 };
             bson_t   *document;
             char     *str;

             born.tm_year = 6;
             born.tm_mon = 11;
             born.tm_mday = 9;

             died.tm_year = 92;
             died.tm_mon = 0;
             died.tm_mday = 1;

             document = BCON_NEW (
                "born", BCON_DATE_TIME (mktime (&born) * 1000),
                "died", BCON_DATE_TIME (mktime (&died) * 1000),
                "name", "{",
                "first", BCON_UTF8 ("Grace"),
                "last", BCON_UTF8 ("Hopper"),
                "}",
                "languages", "[",
                BCON_UTF8 ("MATH-MATIC"),
                BCON_UTF8 ("FLOW-MATIC"),
                BCON_UTF8 ("COBOL"),
                "]",
                "degrees", "[",
                "{", "degree", BCON_UTF8 ("BA"), "school", BCON_UTF8 ("Vassar"), "}",
                "{", "degree", BCON_UTF8 ("PhD"), "school", BCON_UTF8 ("Yale"), "}",
                "]");

             /*
              * Print the document as a JSON string.
              */
             str = bson_as_canonical_extended_json (document, NULL);
             printf ("%s\n", str);
             bson_free (str);

             /*
              * Clean up allocated bson documents.
              */
             bson_destroy (document);
             return 0;
          }

       Notice that BCON can create arrays, subdocuments and arbitrary fields.

   Creating BSON from JSON
       For single documents, BSON can be created from JSON strings via bson_new_from_json.

          #include <bson.h>

          int
          main (int   argc,
                char *argv[])
          {
             bson_error_t error;
             bson_t      *bson;
             char        *string;

             const char *json = "{\"name\": {\"first\":\"Grace\", \"last\":\"Hopper\"}}";
             bson = bson_new_from_json ((const uint8_t *)json, -1, &error);

             if (!bson) {
                fprintf (stderr, "%s\n", error.message);
                return EXIT_FAILURE;
             }

             string = bson_as_canonical_extended_json (bson, NULL);
             printf ("%s\n", string);
             bson_free (string);

             return 0;
          }

       To initialize BSON from a sequence of JSON documents, use bson_json_reader_t.

   Basic CRUD Operations
       This section demonstrates the basics of using the C Driver to interact with MongoDB.

   Inserting a Document
       To  insert  documents  into  a  collection,  first  obtain  a  handle  to  a  mongoc_collection_t  via  a
       mongoc_client_t.  Then,  use  mongoc_collection_insert_one  to add BSON documents to the collection. This
       example inserts into the database "mydb" and collection "mycoll".

       When finished, ensure that allocated structures are freed by using their respective destroy functions.

          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int   argc,
                char *argv[])
          {
              mongoc_client_t *client;
              mongoc_collection_t *collection;
              bson_error_t error;
              bson_oid_t oid;
              bson_t *doc;

              mongoc_init ();

              client = mongoc_client_new ("mongodb://localhost:27017/?appname=insert-example");
              collection = mongoc_client_get_collection (client, "mydb", "mycoll");

              doc = bson_new ();
              bson_oid_init (&oid, NULL);
              BSON_APPEND_OID (doc, "_id", &oid);
              BSON_APPEND_UTF8 (doc, "hello", "world");

              if (!mongoc_collection_insert_one (
                     collection, doc, NULL, NULL, &error)) {
                  fprintf (stderr, "%s\n", error.message);
              }

              bson_destroy (doc);
              mongoc_collection_destroy (collection);
              mongoc_client_destroy (client);
              mongoc_cleanup ();

              return 0;
          }

       Compile the code and run it:

          $ gcc -o insert insert.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./insert

       On Windows:

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 insert.c
          C:\> insert

       To verify that the insert succeeded, connect with the MongoDB shell.

          $ mongo
          MongoDB shell version: 3.0.6
          connecting to: test
          > use mydb
          switched to db mydb
          > db.mycoll.find()
          { "_id" : ObjectId("55ef43766cb5f36a3bae6ee4"), "hello" : "world" }
          >

   Finding a Document
       To query a MongoDB collection with the C driver,  use  the  function  mongoc_collection_find_with_opts().
       This  returns  a  cursor  to  the  matching  documents. The following examples iterate through the result
       cursors and print the matches to stdout as JSON strings.

       Use a document as a query specifier; for example,

          { "color" : "red" }

       will match any document with a field named "color" with value "red". An empty document {} can be used  to
       match all documents.

       This  first  example  uses  an  empty  query  specifier  to find all documents in the database "mydb" and
       collection "mycoll".

          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             mongoc_cursor_t *cursor;
             const bson_t *doc;
             bson_t *query;
             char *str;

             mongoc_init ();

             client =
                mongoc_client_new ("mongodb://localhost:27017/?appname=find-example");
             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
             query = bson_new ();
             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);
             }

             bson_destroy (query);
             mongoc_cursor_destroy (cursor);
             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

       Compile the code and run it:

          $ gcc -o find find.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./find
          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }

       On Windows:

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find.c
          C:\> find
          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }

       To look for a specific document, add a specifier to query. This example adds a call to BSON_APPEND_UTF8()
       to look for all documents matching {"hello" : "world"}.

          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             mongoc_cursor_t *cursor;
             const bson_t *doc;
             bson_t *query;
             char *str;

             mongoc_init ();

             client = mongoc_client_new (
                "mongodb://localhost:27017/?appname=find-specific-example");
             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
             query = bson_new ();
             BSON_APPEND_UTF8 (query, "hello", "world");

             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);
             }

             bson_destroy (query);
             mongoc_cursor_destroy (cursor);
             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

          $ gcc -o find-specific find-specific.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./find-specific
          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find-specific.c
          C:\> find-specific
          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }

   Updating a Document
       This  code  snippet  gives  an  example of using mongoc_collection_update_one() to update the fields of a
       document.

       Using the "mydb"  database,  the  following  example  inserts  an  example  document  into  the  "mycoll"
       collection. Then, using its _id field, the document is updated with different values and a new field.

          #include <bcon.h>
          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_collection_t *collection;
             mongoc_client_t *client;
             bson_error_t error;
             bson_oid_t oid;
             bson_t *doc = NULL;
             bson_t *update = NULL;
             bson_t *query = NULL;

             mongoc_init ();

             client =
                mongoc_client_new ("mongodb://localhost:27017/?appname=update-example");
             collection = mongoc_client_get_collection (client, "mydb", "mycoll");

             bson_oid_init (&oid, NULL);
             doc = BCON_NEW ("_id", BCON_OID (&oid), "key", BCON_UTF8 ("old_value"));

             if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) {
                fprintf (stderr, "%s\n", error.message);
                goto fail;
             }

             query = BCON_NEW ("_id", BCON_OID (&oid));
             update = BCON_NEW ("$set",
                                "{",
                                "key",
                                BCON_UTF8 ("new_value"),
                                "updated",
                                BCON_BOOL (true),
                                "}");

             if (!mongoc_collection_update_one (
                    collection, query, update, NULL, NULL, &error)) {
                fprintf (stderr, "%s\n", error.message);
                goto fail;
             }

          fail:
             if (doc)
                bson_destroy (doc);
             if (query)
                bson_destroy (query);
             if (update)
                bson_destroy (update);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

       Compile the code and run it:

          $ gcc -o update update.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./update

       On Windows:

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 update.c
          C:\> update
          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }

       To verify that the update succeeded, connect with the MongoDB shell.

          $ mongo
          MongoDB shell version: 3.0.6
          connecting to: test
          > use mydb
          switched to db mydb
          > db.mycoll.find({"updated" : true})
          { "_id" : ObjectId("55ef549236fe322f9490e17b"), "updated" : true, "key" : "new_value" }
          >

   Deleting a Document
       This example illustrates the use of mongoc_collection_delete_one() to delete a document.

       The  following  code inserts a sample document into the database "mydb" and collection "mycoll". Then, it
       deletes all documents matching {"hello" : "world"}.

          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             bson_error_t error;
             bson_oid_t oid;
             bson_t *doc;

             mongoc_init ();

             client =
                mongoc_client_new ("mongodb://localhost:27017/?appname=delete-example");
             collection = mongoc_client_get_collection (client, "test", "test");

             doc = bson_new ();
             bson_oid_init (&oid, NULL);
             BSON_APPEND_OID (doc, "_id", &oid);
             BSON_APPEND_UTF8 (doc, "hello", "world");

             if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) {
                fprintf (stderr, "Insert failed: %s\n", error.message);
             }

             bson_destroy (doc);

             doc = bson_new ();
             BSON_APPEND_OID (doc, "_id", &oid);

             if (!mongoc_collection_delete_one (
                    collection, doc, NULL, NULL, &error)) {
                fprintf (stderr, "Delete failed: %s\n", error.message);
             }

             bson_destroy (doc);
             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

       Compile the code and run it:

          $ gcc -o delete delete.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./delete

       On Windows:

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 delete.c
          C:\> delete

       Use the MongoDB shell to prove that the documents have been removed successfully.

          $ mongo
          MongoDB shell version: 3.0.6
          connecting to: test
          > use mydb
          switched to db mydb
          > db.mycoll.count({"hello" : "world"})
          0
          >

   Counting Documents
       Counting the number of documents in a MongoDB collection is similar to performing a find operation.  This
       example counts the number of documents matching {"hello" : "world"} in the database "mydb" and collection
       "mycoll".

          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             bson_error_t error;
             bson_t *doc;
             int64_t count;

             mongoc_init ();

             client =
                mongoc_client_new ("mongodb://localhost:27017/?appname=count-example");
             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
             doc = bson_new_from_json (
                (const uint8_t *) "{\"hello\" : \"world\"}", -1, &error);

             count = mongoc_collection_count (
                collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error);

             if (count < 0) {
                fprintf (stderr, "%s\n", error.message);
             } else {
                printf ("%" PRId64 "\n", count);
             }

             bson_destroy (doc);
             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

       Compile the code and run it:

          $ gcc -o count count.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./count
          1

       On Windows:

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 count.c
          C:\> count
          1

   Executing Commands
       The driver provides helper functions for executing MongoDB commands on client,  database  and  collection
       structures.  These  functions  return cursors; the _simple variants return booleans indicating success or
       failure.

       This example executes the collStats command against the collection "mycoll" in database "mydb".

          #include <bson.h>
          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             bson_error_t error;
             bson_t *command;
             bson_t reply;
             char *str;

             mongoc_init ();

             client = mongoc_client_new (
                "mongodb://localhost:27017/?appname=executing-example");
             collection = mongoc_client_get_collection (client, "mydb", "mycoll");

             command = BCON_NEW ("collStats", BCON_UTF8 ("mycoll"));
             if (mongoc_collection_command_simple (
                    collection, command, NULL, &reply, &error)) {
                str = bson_as_canonical_extended_json (&reply, NULL);
                printf ("%s\n", str);
                bson_free (str);
             } else {
                fprintf (stderr, "Failed to run command: %s\n", error.message);
             }

             bson_destroy (command);
             bson_destroy (&reply);
             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

       Compile the code and run it:

          $ gcc -o executing executing.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./executing
          { "ns" : "mydb.mycoll", "count" : 1, "size" : 48, "avgObjSize" : 48, "numExtents" : 1, "storageSize" : 8192,
          "lastExtentSize" : 8192.000000, "paddingFactor" : 1.000000, "userFlags" : 1, "capped" : false, "nindexes" : 1,
          "indexDetails" : {  }, "totalIndexSize" : 8176, "indexSizes" : { "_id_" : 8176 }, "ok" : 1.000000 }

       On Windows:

          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 executing.c
          C:\> executing
          { "ns" : "mydb.mycoll", "count" : 1, "size" : 48, "avgObjSize" : 48, "numExtents" : 1, "storageSize" : 8192,
          "lastExtentSize" : 8192.000000, "paddingFactor" : 1.000000, "userFlags" : 1, "capped" : false, "nindexes" : 1,
          "indexDetails" : {  }, "totalIndexSize" : 8176, "indexSizes" : { "_id_" : 8176 }, "ok" : 1.000000 }

   Threading
       The MongoDB C Driver is thread-unaware in the vast majority of its operations. This means it is up to the
       programmer to guarantee thread-safety.

       However,  mongoc_client_pool_t  is  thread-safe  and  is used to fetch a mongoc_client_t in a thread-safe
       manner. After retrieving a client from the pool, the client structure should be considered owned  by  the
       calling  thread.  When  the  thread  is  finished,  the  client  should  be  placed  back  into the pool.
       example-pool.c.INDENT 0.0

          /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs
           * libmongoc-1.0) */

          /* ./example-pool [CONNECTION_STRING] */

          #include <mongoc.h>
          #include <pthread.h>
          #include <stdio.h>

          static pthread_mutex_t mutex;
          static bool in_shutdown = false;

          static void *
          worker (void *data)
          {
             mongoc_client_pool_t *pool = data;
             mongoc_client_t *client;
             bson_t ping = BSON_INITIALIZER;
             bson_error_t error;
             bool r;

             BSON_APPEND_INT32 (&ping, "ping", 1);

             while (true) {
                client = mongoc_client_pool_pop (pool);
                /* Do something with client. If you are writing an HTTP server, you
                 * probably only want to hold onto the client for the portion of the
                 * request performing database queries.
                 */
                r = mongoc_client_command_simple (
                   client, "admin", &ping, NULL, NULL, &error);

                if (!r) {
                   fprintf (stderr, "%s\n", error.message);
                }

                mongoc_client_pool_push (pool, client);

                pthread_mutex_lock (&mutex);
                if (in_shutdown || !r) {
                   pthread_mutex_unlock (&mutex);
                   break;
                }

                pthread_mutex_unlock (&mutex);
             }

             bson_destroy (&ping);
             return NULL;
          }

          int
          main (int argc, char *argv[])
          {
             const char *uristr = "mongodb://127.0.0.1/?appname=pool-example";
             mongoc_uri_t *uri;
             mongoc_client_pool_t *pool;
             pthread_t threads[10];
             unsigned i;
             void *ret;

             pthread_mutex_init (&mutex, NULL);
             mongoc_init ();

             if (argc > 1) {
                uristr = argv[1];
             }

             uri = mongoc_uri_new (uristr);
             if (!uri) {
                fprintf (stderr, "Failed to parse URI: \"%s\".\n", uristr);
                return EXIT_FAILURE;
             }

             pool = mongoc_client_pool_new (uri);
             mongoc_client_pool_set_error_api (pool, 2);

             for (i = 0; i < 10; i++) {
                pthread_create (&threads[i], NULL, worker, pool);
             }

             sleep (10);
             pthread_mutex_lock (&mutex);
             in_shutdown = true;
             pthread_mutex_unlock (&mutex);

             for (i = 0; i < 10; i++) {
                pthread_join (threads[i], &ret);
             }

             mongoc_client_pool_destroy (pool);
             mongoc_uri_destroy (uri);

             mongoc_cleanup ();

             return 0;
          }

   Next Steps
       To find information on advanced topics, browse the rest of the C driver guide  or  the  official  MongoDB
       documentation.

       For  help with common issues, consult the Troubleshooting page. To report a bug or request a new feature,
       follow these instructions.

   Authentication
       This guide covers the use of authentication options with the MongoDB C Driver. Ensure  that  the  MongoDB
       server  is  also properly configured for authentication before making a connection. For more information,
       see the MongoDB security documentation.

       The MongoDB C driver supports several authentication mechanisms through the  use  of  MongoDB  connection
       URIs.

       By  default,  if  a  username and password are provided as part of the connection string (and an optional
       authentication database), they are used to connect  via  the  default  authentication  mechanism  of  the
       server.

       To select a specific authentication mechanism other than the default, see the list of supported mechanism
       below.

          mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authSource=mydb");

       Currently supported values for the authMechanism connection string option are:

       • SCRAM-SHA-1MONGODB-CRGSSAPIPLAINX509

   Basic Authentication (SCRAM-SHA-1)
       The default authentication mechanism when talking to MongoDB 3.0 and later  is  SCRAM-SHA-1  (RFC  5802).
       Using  this  authentication  mechanism  means that the password is never actually sent over the wire when
       authenticating, but rather a computed proof that the client password is the  same  as  the  password  the
       server knows.

          mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-1&authSource=mydb");

       NOTE:
          SCRAM-SHA-1  authenticates  against  the  admin database by default. If the user is created in another
          database, then specifying the authSource is required.

   Legacy Authentication (MONGODB-CR)
       The MONGODB-CR authMechanism is a  challenge  response  authentication  mechanism.  It  was  the  default
       mechanism  until  MongoDB  3.0  and  is  being phased out. It is strongly suggested that users upgrade to
       SCRAM-SHA-1.

       NOTE:
          MONGODB-CR authenticates against the admin database by default. If the  user  is  created  in  another
          database, then specifying the authSource is required.

   GSSAPI (Kerberos) Authentication
       NOTE:
          Kerberos  support  requires  compiling  the  driver  against  cyrus-sasl on UNIX-like environments. On
          Windows, configure the driver to build against the Windows Native SSPI.

       GSSAPI (Kerberos) authentication is available in the Enterprise Edition of MongoDB. To authenticate using
       GSSAPI, the MongoDB C driver must be installed with SASL support.

       On UNIX-like environments, run the kinit command before using the following authentication methods:

          $ kinit mongodbuser@EXAMPLE.COM
          mongodbuser@EXAMPLE.COM's Password:
          $ klistCredentials cache: FILE:/tmp/krb5cc_1000
                  Principal: mongodbuser@EXAMPLE.COM

            Issued                Expires               Principal
          Feb  9 13:48:51 2013  Feb  9 23:48:51 2013  krbtgt/EXAMPLE.COM@EXAMPLE.COM

       Now authenticate using the MongoDB URI. GSSAPI authenticates against the $external virtual database, so a
       database does not need to be specified in the URI. Note that the Kerberos principal must be URL-encoded:

          mongoc_client_t *client;

          client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI");

       NOTE:
          GSSAPI authenticates against the $external database, so specifying  the  authSource  database  is  not
          required.

       The driver supports these GSSAPI properties:

       • CANONICALIZE_HOST_NAME:  This  might  be  required  with  Cyrus-SASL  when  the  hosts report different
         hostnames than what is used in the Kerberos database. The default is "false".

       • SERVICE_NAME: Use a different service name than the default, "mongodb".

       Set properties in the URL:

          mongoc_client_t *client;

          client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI&"
                                      "authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true");

       If you encounter errors such as Invalid net address, check if the application is behind  a  NAT  (Network
       Address  Translation)  firewall.  If  so,  create a ticket that uses forwardable and addressless Kerberos
       tickets. This can be done by passing -f -A to kinit.

          $ kinit -f -A mongodbuser@EXAMPLE.COM

   SASL Plain Authentication
       NOTE:
          The MongoDB C Driver must be compiled with SASL support in order to use SASL PLAIN authentication.

       MongoDB Enterprise Edition supports the SASL  PLAIN  authentication  mechanism,  initially  intended  for
       delegating  authentication  to  an  LDAP  server.  Using  the SASL PLAIN mechanism is very similar to the
       challenge response mechanism with  usernames  and  passwords.  This  authentication  mechanism  uses  the
       $external virtual database for LDAP support:

       NOTE:
          SASL  PLAIN is a clear-text authentication mechanism. It is strongly recommended to connect to MongoDB
          using SSL with certificate validation when using the PLAIN mechanism.

          mongoc_client_t *client;

          client = mongoc_client_new ("mongodb://user:password@example.com/?authMechanism=PLAIN");

       PLAIN authenticates against the  $external  database,  so  specifying  the  authSource  database  is  not
       required.

   X.509 Certificate Authentication
       NOTE:
          The  MongoDB C Driver must be compiled with SSL support for X.509 authentication support. Once this is
          done, start a server with the following options:

              $ mongod --sslMode requireSSL --sslPEMKeyFile server.pem --sslCAFile ca.pem

       The MONGODB-X509 mechanism authenticates a username derived from the distinguished subject  name  of  the
       X.509 certificate presented by the driver during SSL negotiation. This authentication method requires the
       use of SSL connections with certificate validation.

          mongoc_client_t *client;
          mongoc_ssl_opt_t ssl_opts = { 0 };

          ssl_opts.pem_file = "mycert.pem";
          ssl_opts.pem_pwd = "mycertpassword";
          ssl_opts.ca_file = "myca.pem";
          ssl_opts.ca_dir = "trust_dir";
          ssl_opts.weak_cert_validation = false;

          client = mongoc_client_new ("mongodb://x509_derived_username@localhost/?authMechanism=MONGODB-X509");
          mongoc_client_set_ssl_opts (client, &ssl_opts);

       MONGODB-X509 authenticates against the $external database, so specifying the authSource database  is  not
       required. For more information on the x509_derived_username, see the MongoDB server x.509 tutorial.

       NOTE:
          The MongoDB C Driver will attempt to determine the x509 derived username when none is provided, and as
          of MongoDB 3.4 providing the username is not required at all.

   Basic Troubleshooting
   Troubleshooting Checklist
       The following is a short list of things to check when you have a problem.

       • Did you call mongoc_init() in main()? If not, you will likely see a segfault.

       • Have you leaked any clients or cursors as can be found with mongoc-stat <PID>?

       • Have packets been delivered to the server? See egress bytes from mongoc-stat <PID>.

       • Does valgrind show any leaks? Ensure you call mongoc_cleanup() at the end of your  process  to  cleanup
         lingering allocations from the MongoDB C driver.

       • If  compiling  your  own copy of MongoDB C driver, consider configuring with --enable-tracing to enable
         function tracing and hex dumps of network packets to STDERR and STDOUT.

   Performance Counters
       The MongoDB C driver comes with a unique feature to help developers and sysadmins  troubleshoot  problems
       in  production.   Performance counters are available for each process using the driver.  The counters can
       be accessed outside of the application process via a shared memory segment.   This  means  that  you  can
       graph  statistics  about  your  application  process easily from tools like Munin or Nagios.  Your author
       often uses watch --interval=0.5 -d mongoc-stat $PID to monitor an application.

       Counters are currently available on UNIX-like platforms that support shared memory segments.

       • Active and Disposed Cursors

       • Active and Disposed Clients, Client Pools, and Socket Streams.

       • Number of operations sent and received, by type.

       • Bytes transferred and received.

       • Authentication successes and failures.

       • Number of wire protocol errors.

       To access counters for a given process,  simply  provide  the  process  id  to  the  mongoc-stat  program
       installed with the MongoDB C Driver.

          $ mongoc-stat 22203
             Operations : Egress Total        : The number of sent operations.                    : 13247
             Operations : Ingress Total       : The number of received operations.                : 13246
             Operations : Egress Queries      : The number of sent Query operations.              : 13247
             Operations : Ingress Queries     : The number of received Query operations.          : 0
             Operations : Egress GetMore      : The number of sent GetMore operations.            : 0
             Operations : Ingress GetMore     : The number of received GetMore operations.        : 0
             Operations : Egress Insert       : The number of sent Insert operations.             : 0
             Operations : Ingress Insert      : The number of received Insert operations.         : 0
             Operations : Egress Delete       : The number of sent Delete operations.             : 0
             Operations : Ingress Delete      : The number of received Delete operations.         : 0
             Operations : Egress Update       : The number of sent Update operations.             : 0
             Operations : Ingress Update      : The number of received Update operations.         : 0
             Operations : Egress KillCursors  : The number of sent KillCursors operations.        : 0
             Operations : Ingress KillCursors : The number of received KillCursors operations.    : 0
             Operations : Egress Msg          : The number of sent Msg operations.                : 0
             Operations : Ingress Msg         : The number of received Msg operations.            : 0
             Operations : Egress Reply        : The number of sent Reply operations.              : 0
             Operations : Ingress Reply       : The number of received Reply operations.          : 13246
                Cursors : Active              : The number of active cursors.                     : 1
                Cursors : Disposed            : The number of disposed cursors.                   : 13246
                Clients : Active              : The number of active clients.                     : 1
                Clients : Disposed            : The number of disposed clients.                   : 0
                Streams : Active              : The number of active streams.                     : 1
                Streams : Disposed            : The number of disposed streams.                   : 0
                Streams : Egress Bytes        : The number of bytes sent.                         : 794931
                Streams : Ingress Bytes       : The number of bytes received.                     : 589694
                Streams : N Socket Timeouts   : The number of socket timeouts.                    : 0
           Client Pools : Active              : The number of active client pools.                : 1
           Client Pools : Disposed            : The number of disposed client pools.              : 0
               Protocol : Ingress Errors      : The number of protocol errors on ingress.         : 0
                   Auth : Failures            : The number of failed authentication requests.     : 0
                   Auth : Success             : The number of successful authentication requests. : 0

   Submitting a Bug Report
       Think  you've  found  a bug? Want to see a new feature in the MongoDB C driver? Please open a case in our
       issue management tool, JIRA:

       • Create an account and login.

       • Navigate to the CDRIVER project.

       • Click Create Issue - Please provide as much information as possible about the issue  type  and  how  to
         reproduce it.

       Bug  reports  in  JIRA  for  all  driver  projects (i.e. CDRIVER, CSHARP, JAVA) and the Core Server (i.e.
       SERVER) project are public.

   Guides
   Common Tasks
       Drivers for some other languages provide helper functions to perform  certain  common  tasks.  In  the  C
       Driver we must explicitly build commands to send to the server.

       This snippet contains example code for the explain, copydb and cloneCollection commands.

   Setup
       First we'll write some code to insert sample data: doc-common-insert.c.INDENT 0.0

          /* Don't try to compile this file on its own. It's meant to be #included
             by example code */

          /* Insert some sample data */
          bool
          insert_data (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             enum N { ndocs = 4 };
             bson_t *docs[ndocs];
             bson_error_t error;
             int i = 0;
             bool ret;

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

             docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
             docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
             docs[2] = BCON_NEW (
                "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
             docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");

             for (i = 0; i < ndocs; i++) {
                mongoc_bulk_operation_insert (bulk, docs[i]);
                bson_destroy (docs[i]);
                docs[i] = NULL;
             }

             ret = mongoc_bulk_operation_execute (bulk, NULL, &error);

             if (!ret) {
                fprintf (stderr, "Error inserting data: %s\n", error.message);
             }

             mongoc_bulk_operation_destroy (bulk);
             return ret;
          }

          /* A helper which we'll use a lot later on */
          void
          print_res (const bson_t *reply)
          {
             BSON_ASSERT (reply);
             char *str = bson_as_canonical_extended_json (reply, NULL);
             printf ("%s\n", str);
             bson_free (str);
          }

   explain Command
       This is how to use the explain command in MongoDB 3.2+: explain.c.INDENT 0.0

          bool
          explain (mongoc_collection_t *collection)
          {
             bson_t *command;
             bson_t reply;
             bson_error_t error;
             bool res;

             command = BCON_NEW ("explain",
                                 "{",
                                 "find",
                                 BCON_UTF8 (COLLECTION_NAME),
                                 "filter",
                                 "{",
                                 "x",
                                 BCON_INT32 (1),
                                 "}",
                                 "}");
             res = mongoc_collection_command_simple (
                collection, command, NULL, &reply, &error);
             if (!res) {
                fprintf (stderr, "Error with explain: %s\n", error.message);
                goto cleanup;
             }

             /* Do something with the reply */
             print_res (&reply);

          cleanup:
             bson_destroy (&reply);
             bson_destroy (command);
             return res;
          }

   copydb Command
       This example requires two instances of mongo to be running.

       Here's how to use the copydb command to copy a database from another instance of MongoDB: copydb.c.INDENT
       0.0

          bool
          copydb (mongoc_client_t *client, const char *other_host_and_port)
          {
             mongoc_database_t *admindb;
             bson_t *command;
             bson_t reply;
             bson_error_t error;
             bool res;

             BSON_ASSERT (other_host_and_port);
             /* Must do this from the admin db */
             admindb = mongoc_client_get_database (client, "admin");

             command = BCON_NEW ("copydb",
                                 BCON_INT32 (1),
                                 "fromdb",
                                 BCON_UTF8 ("test"),
                                 "todb",
                                 BCON_UTF8 ("test2"),

                                 /* If you want from a different host */
                                 "fromhost",
                                 BCON_UTF8 (other_host_and_port));
             res =
                mongoc_database_command_simple (admindb, command, NULL, &reply, &error);
             if (!res) {
                fprintf (stderr, "Error with copydb: %s\n", error.message);
                goto cleanup;
             }

             /* Do something with the reply */
             print_res (&reply);

          cleanup:
             bson_destroy (&reply);
             bson_destroy (command);
             mongoc_database_destroy (admindb);

             return res;
          }

   cloneCollection Command
       This example requires two instances of mongo to be running.

       Here's an example of the cloneCollection command to clone a collection from another instance of  MongoDB:
       clone-collection.c.INDENT 0.0

          bool
          clone_collection (mongoc_database_t *database, const char *other_host_and_port)
          {
             bson_t *command;
             bson_t reply;
             bson_error_t error;
             bool res;

             BSON_ASSERT (other_host_and_port);
             command = BCON_NEW ("cloneCollection",
                                 BCON_UTF8 ("test.remoteThings"),
                                 "from",
                                 BCON_UTF8 (other_host_and_port),
                                 "query",
                                 "{",
                                 "x",
                                 BCON_INT32 (1),
                                 "}");
             res =
                mongoc_database_command_simple (database, command, NULL, &reply, &error);
             if (!res) {
                fprintf (stderr, "Error with clone: %s\n", error.message);
                goto cleanup;
             }

             /* Do something with the reply */
             print_res (&reply);

          cleanup:
             bson_destroy (&reply);
             bson_destroy (command);

             return res;
          }

   Running the Examples
       common-operations.c.INDENT 0.0

          /*
           * Copyright 2016 MongoDB, Inc.
           *
           * Licensed under the Apache License, Version 2.0 (the "License");
           * you may not use this file except in compliance with the License.
           * You may obtain a copy of the License at
           *
           *   http://www.apache.org/licenses/LICENSE-2.0
           *
           * Unless required by applicable law or agreed to in writing, software
           * distributed under the License is distributed on an "AS IS" BASIS,
           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
           * See the License for the specific language governing permissions and
           * limitations under the License.
           */

          #include <mongoc.h>
          #include <stdio.h>

          const char *COLLECTION_NAME = "things";

          #include "../doc-common-insert.c"
          #include "explain.c"
          #include "copydb.c"
          #include "clone-collection.c"

          int
          main (int argc, char *argv[])
          {
             mongoc_database_t *database = NULL;
             mongoc_client_t *client = NULL;
             mongoc_collection_t *collection = NULL;
             char *host_and_port;
             int res = 0;
             char *other_host_and_port = NULL;

             if (argc < 2 || argc > 3) {
                fprintf (stderr,
                         "usage: %s MONGOD-1-CONNECTION-STRING "
                         "[MONGOD-2-HOST-NAME:MONGOD-2-PORT]\n",
                         argv[0]);
                fprintf (stderr,
                         "MONGOD-1-CONNECTION-STRING can be "
                         "of the following forms:\n");
                fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
                fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
                fprintf (stderr,
                         "mongodb://user:pass@localhost:27017\t"
                         "local machine on port 27017, and authenticate with username "
                         "user and password pass\n");
                return 1;
             }

             mongoc_init ();

             if (strncmp (argv[1], "mongodb://", 10) == 0) {
                host_and_port = bson_strdup (argv[1]);
             } else {
                host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
             }
             other_host_and_port = argc > 2 ? argv[2] : NULL;

             client = mongoc_client_new (host_and_port);

             if (!client) {
                fprintf (stderr, "Invalid hostname or port: %s\n", host_and_port);
                res = 2;
                goto cleanup;
             }

             mongoc_client_set_error_api (client, 2);
             database = mongoc_client_get_database (client, "test");
             collection = mongoc_database_get_collection (database, COLLECTION_NAME);

             printf ("Inserting data\n");
             if (!insert_data (collection)) {
                res = 3;
                goto cleanup;
             }

             printf ("explain\n");
             if (!explain (collection)) {
                res = 4;
                goto cleanup;
             }

             if (other_host_and_port) {
                printf ("copydb\n");
                if (!copydb (client, other_host_and_port)) {
                   res = 5;
                   goto cleanup;
                }

                printf ("clone collection\n");
                if (!clone_collection (database, other_host_and_port)) {
                   res = 6;
                   goto cleanup;
                }
             }

          cleanup:
             if (collection) {
                mongoc_collection_destroy (collection);
             }

             if (database) {
                mongoc_database_destroy (database);
             }

             if (client) {
                mongoc_client_destroy (client);
             }

             bson_free (host_and_port);
             mongoc_cleanup ();
             return res;
          }
          $ mongod

          $ mkdir /tmp/db2$ mongod --dbpath /tmp/db2 --port 27018 # second instance

       Now compile and run the example program:

          $ cd examples/common_operations/$ gcc -Wall -o example common-operations.c $(pkg-config --cflags --libs libmongoc-1.0)$ ./example localhost:27017 localhost:27018
          Inserting data
          explain
          {
             "executionStats" : {
                "allPlansExecution" : [],
                "executionStages" : {
                   "advanced" : 19,
                   "direction" : "forward" ,
                   "docsExamined" : 76,
                   "executionTimeMillisEstimate" : 0,
                   "filter" : {
                      "x" : {
                         "$eq" : 1
                      }
                   },
                   "invalidates" : 0,
                   "isEOF" : 1,
                   "nReturned" : 19,
                   "needTime" : 58,
                   "needYield" : 0,
                   "restoreState" : 0,
                   "saveState" : 0,
                   "stage" : "COLLSCAN" ,
                   "works" : 78
                },
                "executionSuccess" : true,
                "executionTimeMillis" : 0,
                "nReturned" : 19,
                "totalDocsExamined" : 76,
                "totalKeysExamined" : 0
             },
             "ok" : 1,
             "queryPlanner" : {
                "indexFilterSet" : false,
                "namespace" : "test.things",
                "parsedQuery" : {
                   "x" : {
                      "$eq" : 1
                   }
                },
                "plannerVersion" : 1,
                "rejectedPlans" : [],
                "winningPlan" : {
                   "direction" : "forward" ,
                   "filter" : {
                      "x" : {
                         "$eq" : 1
                      }
                   },
                   "stage" : "COLLSCAN"
                }
             },
             "serverInfo" : {
                "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25" ,
                "host" : "MacBook-Pro-57.local",
                "port" : 27017,
                "version" : "3.2.6"
             }
          }
          copydb
          { "ok" : 1 }
          clone collection
          { "ok" : 1 }

   Advanced Connections
       The following guide contains information specific to certain types of MongoDB configurations.

       For  an  example of connecting to a simple standalone server, see the Tutorial. To establish a connection
       with authentication options enabled, see the Authentication page.

   Connecting to a Replica Set
       Connecting to a replica set is much like connecting to a standalone MongoDB server.  Simply  specify  the
       replica set name using the ?replicaSet=myreplset URI option.

          #include <bson.h>
          #include <mongoc.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;

             mongoc_init ();

             /* Create our MongoDB Client */
             client = mongoc_client_new (
                "mongodb://host01:27017,host02:27017,host03:27017/?replicaSet=myreplset");

             /* Do some work */
             /* TODO */

             /* Clean up */
             mongoc_client_destroy (client);
             mongoc_cleanup ();

             return 0;
          }

       TIP:
          Multiple  hostnames  can  be  specified  in the MongoDB connection string URI, with a comma separating
          hosts in the seed list.

          It is recommended to use a seed list of members of the replica set to allow the driver to  connect  to
          any node.

   Connecting to a Sharded Cluster
       To connect to a sharded cluster, specify the mongos nodes the client should connect to. The C Driver will
       automatically detect that it has connected to a mongos sharding server.

       If more than one hostname is specified, a seed list will be  created  to  attempt  failover  between  the
       mongos instances.

       WARNING:
          Specifying the replicaSet parameter when connecting to a mongos sharding server is invalid.

          #include <bson.h>
          #include <mongoc.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;

             mongoc_init ();

             /* Create our MongoDB Client */
             client = mongoc_client_new ("mongodb://myshard01:27017/");

             /* Do something with client ... */

             /* Free the client */
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

   Connecting to an IPv6 Address
       The  MongoDB  C  Driver will automatically resolve IPv6 addresses from host names. However, to specify an
       IPv6 address directly, wrap the address in [].

          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://[::1]:27017");

   Connecting to a UNIX Domain Socket
       On UNIX-like systems, the C Driver can connect directly to a MongoDB server using a UNIX  domain  socket.
       Pass  the URL-encoded path to the socket, which must be suffixed with .sock. For example, to connect to a
       domain socket at /tmp/mongodb-27017.sock:

          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://%2Ftmp%2Fmongodb-27017.sock");

       Include username and password like so:

          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://user:pass@%2Ftmp%2Fmongodb-27017.sock");

   Connecting to a server over SSL
       These are instructions for configuring TLS/SSL connections.

       To run a server locally (on port 27017, for example):

          $ mongod --port 27017 --sslMode requireSSL --sslPEMKeyFile server.pem --sslCAFile ca.pem

       Add /?ssl=true to the end of a client URI.

          mongoc_client_t *client = NULL;
          client = mongoc_client_new ("mongodb://localhost:27017/?ssl=true");

       MongoDB requires client certificates by default, unless the  --sslAllowConnectionsWithoutCertificates  is
       provided. The C Driver can be configured to present a client certificate using a mongoc_ssl_opt_t:

          const mongoc_ssl_opt_t *ssl_default = mongoc_ssl_opt_get_default ();
          mongoc_ssl_opt_t ssl_opts = { 0 };

          /* optionally copy in a custom trust directory or file; otherwise the default is used. */
          memcpy (&ssl_opts, ssl_default, sizeof ssl_opts);
          ssl_opts.pem_file = "client.pem"

          mongoc_client_set_ssl_opts (client, &ssl_opts);

       The  client  certificate  provided  by  pem_file  must be issued by one of the server trusted Certificate
       Authorities listed in --sslCAFile, or issued by a CA in the native certificate store on the  server  when
       omitted.

       To verify the server certificate against a specific CA, provide a PEM armored file with a CA certificate,
       or concatenated list of CA certificates using the ca_file option, or c_rehash directory structure of CAs,
       pointed  to  using  the  ca_dir  option.  When  no ca_file or ca_dir is provided, the driver will use CAs
       provided by the native platform certificate store.

       See mongoc_ssl_opt_t for more information on the various SSL related options.

   Compressing data to and from MongoDB
       MongoDB 3.4 added Snappy compression support, and zlib compression in 3.6.  To enable compression support
       the client must be configured with which compressors to use:

          mongoc_client_t *client = NULL;
          client = mongoc_client_new ("mongodb://localhost:27017/?compressors=snappy,zlib");

       The  compressors option specifies the priority order of compressors the client wants to use. Messages are
       compressed if the client and server share any compressors in common.

       Note that the compressor used by the server might not be the same compressor as  the  client  used.   For
       example,  if  the  client  uses  the  connection  string compressors=zlib,snappy the client will use zlib
       compression to send data (if possible), but the server might still reply using snappy, depending  on  how
       the server was configured.

       The  driver  must be built with zlib and/or snappy support to enable compression support, any unknown (or
       not compiled in) compressor value will be ignored.

   Additional Connection Options
       The full list of connection options can be found in the mongoc_uri_t docs.

       Certain socket/connection related options are not configurable:

                        ┌──────────────┬──────────────────────────────┬────────────────────────┐
                        │Option        │ Description                  │ Value                  │
                        ├──────────────┼──────────────────────────────┼────────────────────────┤
                        │SO_KEEPALIVE  │ TCP Keep Alive               │ Enabled                │
                        ├──────────────┼──────────────────────────────┼────────────────────────┤
                        │TCP_KEEPIDLE  │ How long a connection  needs │ 300 seconds            │
                        │              │ to  remain  idle  before TCP │                        │
                        │              │ starts   sending   keepalive │                        │
                        │              │ probes                       │                        │
                        ├──────────────┼──────────────────────────────┼────────────────────────┤
                        │TCP_KEEPINTVL │ The  time in seconds between │ 10 seconds             │
                        │              │ TCP probes                   │                        │
                        ├──────────────┼──────────────────────────────┼────────────────────────┤
                        │TCP_KEEPCNT   │ How  many  probes  to  send, │ 9 probes               │
                        │              │ without     acknowledgement, │                        │
                        │              │ before     dropping      the │                        │
                        │              │ connection                   │                        │
                        ├──────────────┼──────────────────────────────┼────────────────────────┤
                        │TCP_NODELAY   │ Send   packets  as  soon  as │ Enabled (no buffering) │
                        │              │ possible  or  buffer   small │                        │
                        │              │ packets (Nagle algorithm)    │                        │
                        └──────────────┴──────────────────────────────┴────────────────────────┘

   Connection Pooling
       The  MongoDB  C  driver  has  two  connection  modes: single-threaded and pooled. Single-threaded mode is
       optimized for embedding the driver within languages like PHP. Multi-threaded programs should  use  pooled
       mode: this mode minimizes the total connection count, and in pooled mode a background thread monitors the
       MongoDB server topology, so the program need not block to scan it.

   Single Mode
       In single mode, your program creates a mongoc_client_t directly:

          mongoc_client_t *client = mongoc_client_new (
             "mongodb://hostA,hostB/?replicaSet=my_rs");

       The client connects on demand when  your  program  first  uses  it  for  a  MongoDB  operation.  Using  a
       non-blocking  socket per server, it begins a check on each server concurrently, and uses the asynchronous
       poll or select function to receive events from the sockets, until all have responded or  timed  out.  Put
       another way, in single-threaded mode the C Driver fans out to begin all checks concurrently, then fans in
       once all checks have completed or timed out. Once the scan completes, the client executes your  program's
       operation and returns.

       In  single  mode,  the client re-scans the server topology roughly once per minute. If more than a minute
       has elapsed since the previous scan, the next operation  on  the  client  will  block  while  the  client
       completes  its  scan.  This  interval is configurable with heartbeatFrequencyMS in the connection string.
       (See mongoc_uri_t.)

       A single client opens one connection per server in your topology: these connections  are  used  both  for
       scanning the topology and performing normal operations.

   Pooled Mode
       To activate pooled mode, create a mongoc_client_pool_t:

          mongoc_uri_t *uri = mongoc_uri_new (
             "mongodb://hostA,hostB/?replicaSet=my_rs");

          mongoc_client_pool_t *pool = mongoc_client_pool_new (uri);

       When  your  program  first  calls  mongoc_client_pool_pop,  the  pool  launches  a  background thread for
       monitoring. The thread fans out and connects to all servers in the connection string, using  non-blocking
       sockets  and a simple event loop. As it receives ismaster responses from the servers, it updates its view
       of the server topology. Each time the thread discovers a new server it begins connecting to it, and  adds
       the new socket to the list of non-blocking sockets in the event loop.

       Each thread that executes MongoDB operations must check out a client from the pool:

          mongoc_client_t *client = mongoc_client_pool_pop (pool);

          /* use the client for operations ... */

          mongoc_client_pool_push (pool, client);

       The mongoc_client_t object is not thread-safe, only the mongoc_client_pool_t is.

       When  the  driver  is  in  pooled  mode,  your  program's  operations are unblocked as soon as monitoring
       discovers a usable server. For example, if a thread in your program is waiting to execute an "insert"  on
       the  primary,  it  is  unblocked  as  soon  as  the  primary  is  discovered, rather than waiting for all
       secondaries to be checked as well.

       The pool opens one connection per server for monitoring, and each client opens its own connection to each
       server  it  uses  for  application operations. The background thread re-scans the server topology roughly
       every 10 seconds. This interval is configurable with heartbeatFrequencyMS in the connection string.  (See
       mongoc_uri_t.)

       See  connection_pool_options  to  configure  pool  size and behavior, and see mongoc_client_pool_t for an
       extended example of a multi-threaded program that uses the driver in pooled mode.

   Cursors
   Handling Cursor Failures
       Cursors exist on a MongoDB server. However, the mongoc_cursor_t  structure  gives  the  local  process  a
       handle  to  the  cursor. It is possible for errors to occur on the server while iterating a cursor on the
       client. Even a network partition may occur. This means that applications should  be  robust  in  handling
       cursor failures.

       While  iterating cursors, you should check to see if an error has occurred. See the following example for
       how to robustly check for errors.

          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);
          }

   Destroying Server-Side Cursors
       The MongoDB C driver will automatically destroy a  server-side  cursor  when  mongoc_cursor_destroy()  is
       called.  Failure  to  call  this function when done with a cursor will leak memory client side as well as
       consume extra memory server side. If the cursor was configured to never timeout, it will become a  memory
       leak on the server.

   Tailable Cursors
       Tailable  cursors  are  cursors that remain open even after they've returned a final result. This way, if
       more documents are added to a collection (i.e., to the cursor's result set), then  you  can  continue  to
       call mongoc_cursor_next() to retrieve those additional results.

       Here's a complete test case that demonstrates the use of tailable cursors.

       NOTE:
          Tailable cursors are for capped collections only.

       An example to tail the oplog from a replica set.  mongoc-tail.c.INDENT 0.0

          #include <bson.h>
          #include <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;

             if (argc != 2) {
                fprintf (stderr, "usage: %s MONGO_URI\n", argv[0]);
                return EXIT_FAILURE;
             }

             mongoc_init ();

             client = mongoc_client_new (argv[1]);
             if (!client) {
                fprintf (stderr, "Invalid URI: \"%s\"\n", argv[1]);
                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_client_destroy (client);

             return 0;
          }
          $ 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
          }

       The  line  of  output  is a sample from performing db.test.insert({}) from the mongo shell on the replica
       set.

       See also mongoc_cursor_set_max_await_time_ms.

   Bulk Write Operations
       This tutorial explains how to take advantage of MongoDB C driver bulk write operation features. Executing
       write operations in batches reduces the number of network round trips, increasing write throughput.

   Bulk Insert
       First we need to fetch a bulk operation handle from the mongoc_collection_t.

          mongoc_bulk_operation_t *bulk =
             mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

       We  can  now start inserting documents to the bulk operation. These will be buffered until we execute the
       operation.

       The  bulk  operation  will  coalesce  insertions  as  a  single  batch  for  each  consecutive  call   to
       mongoc_bulk_operation_insert(). This creates a pipelined effect when possible.

       To   execute  the  bulk  operation  and  receive  the  result  we  call  mongoc_bulk_operation_execute().
       bulk1.c.INDENT 0.0

          #include <assert.h>
          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk1 (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *doc;
             bson_t reply;
             char *str;
             bool ret;
             int i;

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

             for (i = 0; i < 10000; i++) {
                doc = BCON_NEW ("i", BCON_INT32 (i));
                mongoc_bulk_operation_insert (bulk, doc);
                bson_destroy (doc);
             }

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                fprintf (stderr, "Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk1-example");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "test", "test");

             bulk1 (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

Example reply document:

          {"nInserted"   : 10000,
           "nMatched"    : 0,
           "nModified"   : 0,
           "nRemoved"    : 0,
           "nUpserted"   : 0,
           "writeErrors" : []
           "writeConcernErrors" : [] }

   Mixed Bulk Write Operations
       MongoDB C driver also supports executing mixed bulk write operations. A  batch  of  insert,  update,  and
       remove operations can be executed together using the bulk write operations API.

   Ordered Bulk Write Operations
       Ordered  bulk  write  operations  are  batched  and  sent  to the server in the order provided for serial
       execution. The reply document describes the type and count of operations performed.  bulk2.c.INDENT 0.0

          #include <assert.h>
          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk2 (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *query;
             bson_t *doc;
             bson_t *opts;
             bson_t reply;
             char *str;
             bool ret;
             int i;

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

             /* Remove everything */
             query = bson_new ();
             mongoc_bulk_operation_remove (bulk, query);
             bson_destroy (query);

             /* Add a few documents */
             for (i = 1; i < 4; i++) {
                doc = BCON_NEW ("_id", BCON_INT32 (i));
                mongoc_bulk_operation_insert (bulk, doc);
                bson_destroy (doc);
             }

             /* {_id: 1} => {$set: {foo: "bar"}} */
             query = BCON_NEW ("_id", BCON_INT32 (1));
             doc = BCON_NEW ("$set", "{", "foo", BCON_UTF8 ("bar"), "}");
             mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, NULL, &error);
             bson_destroy (query);
             bson_destroy (doc);

             /* {_id: 4} => {'$inc': {'j': 1}} (upsert) */
             opts = BCON_NEW ("upsert", BCON_BOOL (true));
             query = BCON_NEW ("_id", BCON_INT32 (4));
             doc = BCON_NEW ("$inc", "{", "j", BCON_INT32 (1), "}");
             mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, opts, &error);
             bson_destroy (query);
             bson_destroy (doc);
             bson_destroy (opts);

             /* replace {j:1} with {j:2} */
             query = BCON_NEW ("j", BCON_INT32 (1));
             doc = BCON_NEW ("j", BCON_INT32 (2));
             mongoc_bulk_operation_replace_one_with_opts (bulk, query, doc, NULL, &error);
             bson_destroy (query);
             bson_destroy (doc);

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk2-example");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "test", "test");

             bulk2 (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

Example reply document:

          { "nInserted"   : 3,
            "nMatched"    : 2,
            "nModified"   : 2,
            "nRemoved"    : 10000,
            "nUpserted"   : 1,
            "upserted"    : [{"index" : 5, "_id" : 4}],
            "writeErrors" : []
            "writeConcernErrors" : [] }

       The index field in the upserted array is the 0-based index of the upsert operation; in this example,  the
       sixth operation of the overall bulk operation was an upsert, so its index is 5.

   Unordered Bulk Write Operations
       Unordered  bulk  write operations are batched and sent to the server in arbitrary order where they may be
       executed in parallel. Any errors that occur are reported after all operations are attempted.

       In the next example the first and third operations fail due to the unique constraint on _id. Since we are
       doing unordered execution the second and fourth operations succeed.  bulk3.c.INDENT 0.0

          #include <assert.h>
          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk3 (mongoc_collection_t *collection)
          {
             bson_t opts = BSON_INITIALIZER;
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *query;
             bson_t *doc;
             bson_t reply;
             char *str;
             bool ret;

             /* false indicates unordered */
             BSON_APPEND_BOOL (&opts, "ordered", false);
             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
             bson_destroy (&opts);

             /* Add a document */
             doc = BCON_NEW ("_id", BCON_INT32 (1));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             /* remove {_id: 2} */
             query = BCON_NEW ("_id", BCON_INT32 (2));
             mongoc_bulk_operation_remove_one (bulk, query);
             bson_destroy (query);

             /* insert {_id: 3} */
             doc = BCON_NEW ("_id", BCON_INT32 (3));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             /* replace {_id:4} {'i': 1} */
             query = BCON_NEW ("_id", BCON_INT32 (4));
             doc = BCON_NEW ("i", BCON_INT32 (1));
             mongoc_bulk_operation_replace_one (bulk, query, doc, false);
             bson_destroy (query);
             bson_destroy (doc);

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
             bson_destroy (&opts);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk3-example");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "test", "test");

             bulk3 (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

Example reply document:

          { "nInserted"    : 0,
            "nMatched"     : 1,
            "nModified"    : 1,
            "nRemoved"     : 1,
            "nUpserted"    : 0,
            "writeErrors"  : [
              { "index"  : 0,
                "code"   : 11000,
                "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }" },
              { "index"  : 2,
                "code"   : 11000,
                "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 3 }" } ],
            "writeConcernErrors" : [] }

          Error: E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }

       The bson_error_t domain is MONGOC_ERROR_COMMAND and its code is 11000.

   Bulk Operation Bypassing Document Validation
       This feature is only available when using MongoDB 3.2 and later.

       By  default bulk operations are validated against the schema, if any is defined. In certain cases however
       it may be necessary to bypass the document validation.  bulk5.c.INDENT 0.0

          #include <assert.h>
          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk5_fail (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *doc;
             bson_t reply;
             char *str;
             bool ret;

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

             /* Two inserts */
             doc = BCON_NEW ("_id", BCON_INT32 (31));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             doc = BCON_NEW ("_id", BCON_INT32 (32));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             /* The above documents do not comply to the schema validation rules
              * we created previously, so this will result in an error */
             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
          }

          static void
          bulk5_success (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *doc;
             bson_t reply;
             char *str;
             bool ret;

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

             /* Allow this document to bypass document validation.
              * NOTE: When authentication is enabled, the authenticated user must have
              * either the "dbadmin" or "restore" roles to bypass document validation */
             mongoc_bulk_operation_set_bypass_document_validation (bulk, true);

             /* Two inserts */
             doc = BCON_NEW ("_id", BCON_INT32 (31));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             doc = BCON_NEW ("_id", BCON_INT32 (32));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
          }

          int
          main (int argc, char *argv[])
          {
             bson_t *options;
             bson_error_t error;
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             mongoc_database_t *database;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk5-example");
             mongoc_client_set_error_api (client, 2);
             database = mongoc_client_get_database (client, "testasdf");

             /* Create schema validator */
             options = BCON_NEW (
                "validator", "{", "number", "{", "$gte", BCON_INT32 (5), "}", "}");
             collection =
                mongoc_database_create_collection (database, "collname", options, &error);

             if (collection) {
                bulk5_fail (collection);
                bulk5_success (collection);
                mongoc_collection_destroy (collection);
             } else {
                fprintf (stderr, "Couldn't create collection: '%s'\n", error.message);
             }

             bson_free (options);
             mongoc_database_destroy (database);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }
          { "nInserted" : 0,
            "nMatched" : 0,
            "nModified" : 0,
            "nRemoved" : 0,
            "nUpserted" : 0,
            "writeErrors" : [
              { "index" : 0,
                "code" : 121,
                "errmsg" : "Document failed validation" } ] }

          Error: Document failed validation

          { "nInserted" : 2,
            "nMatched" : 0,
            "nModified" : 0,
            "nRemoved" : 0,
            "nUpserted" : 0,
            "writeErrors" : [] }

       The bson_error_t domain is MONGOC_ERROR_COMMAND.

   Bulk Operation Write Concerns
       By default bulk operations are executed with the  write_concern  of  the  collection  they  are  executed
       against.  A custom write concern can be passed to the mongoc_collection_create_bulk_operation_with_opts()
       method. Write concern errors (e.g. wtimeout)  will  be  reported  after  all  operations  are  attempted,
       regardless of execution order.  bulk4.c.INDENT 0.0

          #include <assert.h>
          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk4 (mongoc_collection_t *collection)
          {
             bson_t opts = BSON_INITIALIZER;
             mongoc_write_concern_t *wc;
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *doc;
             bson_t reply;
             char *str;
             bool ret;

             wc = mongoc_write_concern_new ();
             mongoc_write_concern_set_w (wc, 4);
             mongoc_write_concern_set_wtimeout (wc, 100); /* milliseconds */
             mongoc_write_concern_append (wc, &opts);

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);

             /* Two inserts */
             doc = BCON_NEW ("_id", BCON_INT32 (10));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             doc = BCON_NEW ("_id", BCON_INT32 (11));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
             mongoc_write_concern_destroy (wc);
             bson_destroy (&opts);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk4-example");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "test", "test");

             bulk4 (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

Example reply document and error message:

          { "nInserted"    : 2,
            "nMatched"     : 0,
            "nModified"    : 0,
            "nRemoved"     : 0,
            "nUpserted"    : 0,
            "writeErrors"  : [],
            "writeConcernErrors" : [
              { "code"   : 64,
                "errmsg" : "waiting for replication timed out" }
          ] }

          Error: waiting for replication timed out

       The  bson_error_t  domain  is  MONGOC_ERROR_WRITE_CONCERN  if there are write concern errors and no write
       errors. Write errors indicate failed operations, so they take precedence over write concern errors, which
       mean merely that the write concern is not satisfied yet.

   Setting Collation Order
       This feature is only available when using MongoDB 3.4 and later.  bulk-collation.c.INDENT 0.0

          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk_collation (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             bson_t *opts;
             bson_t *doc;
             bson_t *selector;
             bson_t *update;
             bson_error_t error;
             bson_t reply;
             char *str;
             uint32_t ret;

             /* insert {_id: "one"} and {_id: "One"} */
             bulk = mongoc_collection_create_bulk_operation_with_opts (
                collection, NULL);
             doc = BCON_NEW ("_id", BCON_UTF8 ("one"));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             doc = BCON_NEW ("_id", BCON_UTF8 ("One"));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             /* "One" normally sorts before "one"; make "one" come first */
             opts = BCON_NEW ("collation",
                              "{",
                              "locale",
                              BCON_UTF8 ("en_US"),
                              "caseFirst",
                              BCON_UTF8 ("lower"),
                              "}");

             /* set x=1 on the document with _id "One", which now sorts after "one" */
             update = BCON_NEW ("$set", "{", "x", BCON_INT64 (1), "}");
             selector = BCON_NEW ("_id", "{", "$gt", BCON_UTF8 ("one"), "}");
             mongoc_bulk_operation_update_one_with_opts (
                bulk, selector, update, opts, &error);

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             bson_destroy (update);
             bson_destroy (selector);
             bson_destroy (opts);
             mongoc_bulk_operation_destroy (bulk);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk-collation");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "db", "collection");
             bulk_collation (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }
          { "nInserted" : 2,
             "nMatched" : 1,
             "nModified" : 1,
             "nRemoved" : 0,
             "nUpserted" : 0,
             "writeErrors" : [  ]
          }

   Unacknowledged Bulk Writes
       Set  "w"  to  zero  for  an unacknowledged write. The driver sends unacknowledged writes using the legacy
       opcodes OP_INSERT, OP_UPDATE, and OP_DELETE.  bulk6.c.INDENT 0.0

          #include <bcon.h>
          #include <mongoc.h>
          #include <stdio.h>

          static void
          bulk6 (mongoc_collection_t *collection)
          {
             bson_t opts = BSON_INITIALIZER;
             mongoc_write_concern_t *wc;
             mongoc_bulk_operation_t *bulk;
             bson_error_t error;
             bson_t *doc;
             bson_t *selector;
             bson_t reply;
             char *str;
             bool ret;

             wc = mongoc_write_concern_new ();
             mongoc_write_concern_set_w (wc, 0);
             mongoc_write_concern_append (wc, &opts);

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);

             doc = BCON_NEW ("_id", BCON_INT32 (10));
             mongoc_bulk_operation_insert (bulk, doc);
             bson_destroy (doc);

             selector = BCON_NEW ("_id", BCON_INT32 (11));
             mongoc_bulk_operation_remove_one (bulk, selector);
             bson_destroy (selector);

             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);

             str = bson_as_canonical_extended_json (&reply, NULL);
             printf ("%s\n", str);
             bson_free (str);

             if (!ret) {
                printf ("Error: %s\n", error.message);
             }

             bson_destroy (&reply);
             mongoc_bulk_operation_destroy (bulk);
             mongoc_write_concern_destroy (wc);
             bson_destroy (&opts);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/?appname=bulk6-example");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "test", "test");

             bulk6 (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

The reply document is empty:

          { }

   Further Reading
       See the Driver Bulk API Spec, which describes bulk write operations for all MongoDB drivers.

   Aggregation Framework Examples
       This document provides a number of practical examples that display the capabilities  of  the  aggregation
       framework.

       The Aggregations using the Zip Codes Data Set examples uses a publicly available data set of all zipcodes
       and populations in the United States. These data are available at: zips.json.

   Requirements
       Let's check if everything is installed.

       Use the following command to load zips.json data set into mongod instance:

          $ mongoimport --drop -d test -c zipcodes zips.json

       Let's use the MongoDB shell to verify that everything was imported successfully.

          $ mongo test
          MongoDB shell version: 2.6.1
          connecting to: test
          > db.zipcodes.count()
          29467
          > db.zipcodes.findOne()
          {
                "_id" : "35004",
                "city" : "ACMAR",
                "loc" : [
                        -86.51557,
                        33.584132
                ],
                "pop" : 6055,
                "state" : "AL"
          }

   Aggregations using the Zip Codes Data Set
       Each document in this collection has the following form:

          {
            "_id" : "35004",
            "city" : "Acmar",
            "state" : "AL",
            "pop" : 6055,
            "loc" : [-86.51557, 33.584132]
          }

       In these documents:

       • The _id field holds the zipcode as a string.

       • The city field holds the city name.

       • The state field holds the two letter state abbreviation.

       • The pop field holds the population.

       • The loc field holds the location as a [latitude, longitude] array.

   States with Populations Over 10 Million
       To get all states with a population greater than 10 million,  use  the  following  aggregation  pipeline:
       aggregation1.c.INDENT 0.0

          #include <mongoc.h>
          #include <stdio.h>

          static void
          print_pipeline (mongoc_collection_t *collection)
          {
             mongoc_cursor_t *cursor;
             bson_error_t error;
             const bson_t *doc;
             bson_t *pipeline;
             char *str;

             pipeline = BCON_NEW ("pipeline",
                                  "[",
                                  "{",
                                  "$group",
                                  "{",
                                  "_id",
                                  "$state",
                                  "total_pop",
                                  "{",
                                  "$sum",
                                  "$pop",
                                  "}",
                                  "}",
                                  "}",
                                  "{",
                                  "$match",
                                  "{",
                                  "total_pop",
                                  "{",
                                  "$gte",
                                  BCON_INT32 (10000000),
                                  "}",
                                  "}",
                                  "}",
                                  "]");

             cursor = mongoc_collection_aggregate (
                collection, MONGOC_QUERY_NONE, pipeline, 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, "Cursor Failure: %s\n", error.message);
             }

             mongoc_cursor_destroy (cursor);
             bson_destroy (pipeline);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;

             mongoc_init ();

             client = mongoc_client_new (
                "mongodb://localhost:27017?appname=aggregation-example");
             mongoc_client_set_error_api (client, 2);
             collection = mongoc_client_get_collection (client, "test", "zipcodes");

             print_pipeline (collection);

             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }
          { "_id" : "PA", "total_pop" : 11881643 }
          { "_id" : "OH", "total_pop" : 10847115 }
          { "_id" : "NY", "total_pop" : 17990455 }
          { "_id" : "FL", "total_pop" : 12937284 }
          { "_id" : "TX", "total_pop" : 16986510 }
          { "_id" : "IL", "total_pop" : 11430472 }
          { "_id" : "CA", "total_pop" : 29760021 }

       The above aggregation pipeline is build from two pipeline operators: $group and $match.

       The  $group  pipeline operator requires _id field where we specify grouping; remaining fields specify how
       to generate composite value and must use one of  the  group  aggregation  functions:  $addToSet,  $first,
       $last,  $max,  $min,  $avg,  $push,  $sum.  The  $match  pipeline operator syntax is the same as the read
       operation query syntax.

       The $group process reads all documents and for each state it creates a separate document, for example:

          { "_id" : "WA", "total_pop" : 4866692 }

       The total_pop field uses the $sum aggregation function to sum the values of all pop fields in the  source
       documents.

       Documents  created by $group are piped to the $match pipeline operator. It returns the documents with the
       value of total_pop field greater than or equal to 10 million.

   Average City Population by State
       To get the first three  states  with  the  greatest  average  population  per  city,  use  the  following
       aggregation:

          pipeline = BCON_NEW ("pipeline", "[",
             "{", "$group", "{", "_id", "{", "state", "$state", "city", "$city", "}", "pop", "{", "$sum", "$pop", "}", "}", "}",
             "{", "$group", "{", "_id", "$_id.state", "avg_city_pop", "{", "$avg", "$pop", "}", "}", "}",
             "{", "$sort", "{", "avg_city_pop", BCON_INT32 (-1), "}", "}",
             "{", "$limit", BCON_INT32 (3) "}",
          "]");

       This aggregate pipeline produces:

          { "_id" : "DC", "avg_city_pop" : 303450.0 }
          { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
          { "_id" : "CA", "avg_city_pop" : 27735.341099720412 }

       The above aggregation pipeline is build from three pipeline operators: $group, $sort and $limit.

       The first $group operator creates the following documents:

          { "_id" : { "state" : "WY", "city" : "Smoot" }, "pop" : 414 }

       Note, that the $group operator can't use nested documents except the _id field.

       The second $group uses these documents to create the following documents:

          { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }

       These  documents  are  sorted by the avg_city_pop field in descending order. Finally, the $limit pipeline
       operator returns the first 3 documents from the sorted set.

   distinct and mapReduce
       This document provides some practical,  simple,  examples  to  demonstrate  the  distinct  and  mapReduce
       commands.

   Setup
       First we'll write some code to insert sample data: doc-common-insert.c.INDENT 0.0

          /* Don't try to compile this file on its own. It's meant to be #included
             by example code */

          /* Insert some sample data */
          bool
          insert_data (mongoc_collection_t *collection)
          {
             mongoc_bulk_operation_t *bulk;
             enum N { ndocs = 4 };
             bson_t *docs[ndocs];
             bson_error_t error;
             int i = 0;
             bool ret;

             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);

             docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
             docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
             docs[2] = BCON_NEW (
                "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
             docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");

             for (i = 0; i < ndocs; i++) {
                mongoc_bulk_operation_insert (bulk, docs[i]);
                bson_destroy (docs[i]);
                docs[i] = NULL;
             }

             ret = mongoc_bulk_operation_execute (bulk, NULL, &error);

             if (!ret) {
                fprintf (stderr, "Error inserting data: %s\n", error.message);
             }

             mongoc_bulk_operation_destroy (bulk);
             return ret;
          }

          /* A helper which we'll use a lot later on */
          void
          print_res (const bson_t *reply)
          {
             BSON_ASSERT (reply);
             char *str = bson_as_canonical_extended_json (reply, NULL);
             printf ("%s\n", str);
             bson_free (str);
          }

   distinct command
       This  is  how  to  use  the  distinct  command  to get the distinct values of x which are greater than 1:
       distinct.c.INDENT 0.0

          bool
          distinct (mongoc_database_t *database)
          {
             bson_t *command;
             bson_t reply;
             bson_error_t error;
             bool res;
             bson_iter_t iter;
             bson_iter_t array_iter;
             double val;

             command = BCON_NEW ("distinct",
                                 BCON_UTF8 (COLLECTION_NAME),
                                 "key",
                                 BCON_UTF8 ("x"),
                                 "query",
                                 "{",
                                 "x",
                                 "{",
                                 "$gt",
                                 BCON_DOUBLE (1.0),
                                 "}",
                                 "}");
             res =
                mongoc_database_command_simple (database, command, NULL, &reply, &error);
             if (!res) {
                fprintf (stderr, "Error with distinct: %s\n", error.message);
                goto cleanup;
             }

             /* Do something with reply (in this case iterate through the values) */
             if (!(bson_iter_init_find (&iter, &reply, "values") &&
                   BSON_ITER_HOLDS_ARRAY (&iter) &&
                   bson_iter_recurse (&iter, &array_iter))) {
                fprintf (stderr, "Couldn't extract \"values\" field from response\n");
                goto cleanup;
             }

             while (bson_iter_next (&array_iter)) {
                if (BSON_ITER_HOLDS_DOUBLE (&array_iter)) {
                   val = bson_iter_double (&array_iter);
                   printf ("Next double: %f\n", val);
                }
             }

          cleanup:
             /* cleanup */
             bson_destroy (command);
             bson_destroy (&reply);
             return res;
          }

   mapReduce - basic example
       A simple example using the map reduce framework. It simply adds up the  number  of  occurrences  of  each
       "tag".

       First define the map and reduce functions: constants.c.INDENT 0.0

          const char *const COLLECTION_NAME = "things";

          /* Our map function just emits a single (key, 1) pair for each tag
             in the array: */
          const char *const MAPPER = "function () {"
                                     "this.tags.forEach(function(z) {"
                                     "emit(z, 1);"
                                     "});"
                                     "}";

          /* The reduce function sums over all of the emitted values for a
             given key: */
          const char *const REDUCER = "function (key, values) {"
                                      "var total = 0;"
                                      "for (var i = 0; i < values.length; i++) {"
                                      "total += values[i];"
                                      "}"
                                      "return total;"
                                      "}";
          /* Note We can't just return values.length as the reduce function
             might be called iteratively on the results of other reduce
             steps. */

Run the mapReduce command: map-reduce-basic.c.INDENT 0.0

          bool
          map_reduce_basic (mongoc_database_t *database)
          {
             bson_t reply;
             bson_t *command;
             bool res;
             bson_error_t error;
             mongoc_cursor_t *cursor;
             const bson_t *doc;

             bool map_reduce_done = false;
             bool query_done = false;

             const char *out_collection_name = "outCollection";
             mongoc_collection_t *out_collection;

             /* Empty find query */
             bson_t find_query = BSON_INITIALIZER;

             /* Construct the mapReduce command */

             /* Other arguments can also be specified here, like "query" or
                "limit" and so on */
             command = BCON_NEW ("mapReduce",
                                 BCON_UTF8 (COLLECTION_NAME),
                                 "map",
                                 BCON_CODE (MAPPER),
                                 "reduce",
                                 BCON_CODE (REDUCER),
                                 "out",
                                 BCON_UTF8 (out_collection_name));
             res =
                mongoc_database_command_simple (database, command, NULL, &reply, &error);
             map_reduce_done = true;

             if (!res) {
                fprintf (stderr, "MapReduce failed: %s\n", error.message);
                goto cleanup;
             }

             /* Do something with the reply (it doesn't contain the mapReduce results) */
             print_res (&reply);

             /* Now we'll query outCollection to see what the results are */
             out_collection =
                mongoc_database_get_collection (database, out_collection_name);
             cursor = mongoc_collection_find_with_opts (
                out_collection, &find_query, NULL, NULL);
             query_done = true;

             /* Do something with the results */
             while (mongoc_cursor_next (cursor, &doc)) {
                print_res (doc);
             }

             if (mongoc_cursor_error (cursor, &error)) {
                fprintf (stderr, "ERROR: %s\n", error.message);
                res = false;
                goto cleanup;
             }

          cleanup:
             /* cleanup */
             if (query_done) {
                mongoc_cursor_destroy (cursor);
                mongoc_collection_destroy (out_collection);
             }

             if (map_reduce_done) {
                bson_destroy (&reply);
                bson_destroy (command);
             }

             return res;
          }

   mapReduce - more complicated example
       You must have replica set running for this.

       In  this  example we contact a secondary in the replica set and do an "inline" map reduce, so the results
       are returned immediately: map-reduce-advanced.c.INDENT 0.0

          bool
          map_reduce_advanced (mongoc_database_t *database)
          {
             bson_t *command;
             bson_error_t error;
             bool res = true;
             mongoc_cursor_t *cursor;
             mongoc_read_prefs_t *read_pref;
             const bson_t *doc;

             /* Construct the mapReduce command */
             /* Other arguments can also be specified here, like "query" or "limit"
                and so on */

             /* Read the results inline from a secondary replica */
             command = BCON_NEW ("mapReduce",
                                 BCON_UTF8 (COLLECTION_NAME),
                                 "map",
                                 BCON_CODE (MAPPER),
                                 "reduce",
                                 BCON_CODE (REDUCER),
                                 "out",
                                 "{",
                                 "inline",
                                 "1",
                                 "}");

             read_pref = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
             cursor = mongoc_database_command (
                database, MONGOC_QUERY_NONE, 0, 0, 0, command, NULL, read_pref);

             /* Do something with the results */
             while (mongoc_cursor_next (cursor, &doc)) {
                print_res (doc);
             }

             if (mongoc_cursor_error (cursor, &error)) {
                fprintf (stderr, "ERROR: %s\n", error.message);
                res = false;
             }

             mongoc_cursor_destroy (cursor);
             mongoc_read_prefs_destroy (read_pref);
             bson_destroy (command);

             return res;
          }

   Running the Examples
       Here's how to run the example code basic-aggregation.c.INDENT 0.0

          /*
           * Copyright 2016 MongoDB, Inc.
           *
           * Licensed under the Apache License, Version 2.0 (the "License");
           * you may not use this file except in compliance with the License.
           * You may obtain a copy of the License at
           *
           *   http://www.apache.org/licenses/LICENSE-2.0
           *
           * Unless required by applicable law or agreed to in writing, software
           * distributed under the License is distributed on an "AS IS" BASIS,
           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
           * See the License for the specific language governing permissions and
           * limitations under the License.
           */

          #include <mongoc.h>
          #include <stdio.h>

          #include "constants.c"

          #include "../doc-common-insert.c"
          #include "distinct.c"
          #include "map-reduce-basic.c"
          #include "map-reduce-advanced.c"

          int
          main (int argc, char *argv[])
          {
             mongoc_database_t *database = NULL;
             mongoc_client_t *client = NULL;
             mongoc_collection_t *collection = NULL;
             char *host_and_port = NULL;
             int res = 0;

             if (argc != 2) {
                fprintf (stderr, "usage: %s CONNECTION-STRING\n", argv[0]);
                fprintf (stderr,
                         "the connection string can be of the following forms:\n");
                fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
                fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
                fprintf (stderr,
                         "mongodb://user:pass@localhost:27017\t"
                         "local machine on port 27017, and authenticate with username "
                         "user and password pass\n");
                return 1;
             }

             mongoc_init ();

             if (strncmp (argv[1], "mongodb://", 10) == 0) {
                host_and_port = bson_strdup (argv[1]);
             } else {
                host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
             }

             client = mongoc_client_new (host_and_port);

             if (!client) {
                fprintf (stderr, "Invalid hostname or port: %s\n", host_and_port);
                res = 2;
                goto cleanup;
             }

             mongoc_client_set_error_api (client, 2);
             database = mongoc_client_get_database (client, "test");
             collection = mongoc_database_get_collection (database, COLLECTION_NAME);

             printf ("Inserting data\n");
             if (!insert_data (collection)) {
                res = 3;
                goto cleanup;
             }

             printf ("distinct\n");
             if (!distinct (database)) {
                res = 4;
                goto cleanup;
             }

             printf ("map reduce\n");
             if (!map_reduce_basic (database)) {
                res = 5;
                goto cleanup;
             }

             printf ("more complicated map reduce\n");
             if (!map_reduce_advanced (database)) {
                res = 6;
                goto cleanup;
             }

          cleanup:
             if (collection) {
                mongoc_collection_destroy (collection);
             }

             if (database) {
                mongoc_database_destroy (database);
             }

             if (client) {
                mongoc_client_destroy (client);
             }

             if (host_and_port) {
                bson_free (host_and_port);
             }

             mongoc_cleanup ();
             return res;
          }
to do this can be found here).
          $ mongod

       Now compile and run the example program:

          $ cd examples/basic_aggregation/
          $ gcc -Wall -o agg-example basic-aggregation.c $(pkg-config --cflags --libs libmongoc-1.0)
          $ ./agg-example localhost

          Inserting data
          distinct
          Next double: 2.000000
          Next double: 3.000000
          map reduce
          { "result" : "outCollection", "timeMillis" : 155, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 }
          { "_id" : "cat", "value" : 63 }
          { "_id" : "dog", "value" : 42 }
          { "_id" : "mouse", "value" : 21 }
          more complicated map reduce
          { "results" : [ { "_id" : "cat", "value" : 63 }, { "_id" : "dog", "value" : 42 }, { "_id" : "mouse", "value" : 21 } ], "timeMillis" : 14, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 }

   Using libmongoc in a Microsoft Visual Studio project
       Download and install libmongoc on your system, then open Visual Studio, select "File→New→Project...", and
       create a new Win32 Console Application.  [image]

       Remember to switch the platform from 32-bit to 64-bit: [image]

       Right-click on your console application in the Solution Explorer and select "Properties". Choose to  edit
       properties  for  "All  Configurations",  expand  the  "C/C++"  options  and  choose "General". Add to the
       "Additional Include Directories" these paths:

          C:\mongo-c-driver\include\libbson-1.0
          C:\mongo-c-driver\include\libmongoc-1.0
       [image]

       (If you chose a different CMAKE_INSTALL_PREFIX when you ran CMake, your include paths will be different.)

       Also in the Properties dialog, expand the "Linker" options and choose "Input", and add to the "Additional
       Dependencies" these libraries:

          C:\mongo-c-driver\lib\bson-1.0.lib
          C:\mongo-c-driver\lib\mongoc-1.0.lib
       [image]

       Adding these libraries as dependencies provides linker symbols to build your application, but to actually
       run it, libbson's and libmongoc's DLLs must be  in  your  executable  path.  Select  "Debugging"  in  the
       Properties dialog, and set the "Environment" option to:

          PATH=c:/mongo-c-driver/bin
       [image]

       Finally, include "mongoc.h" in your project's "stdafx.h":

          #include <mongoc.h>

   Static linking
       Following  the  instructions  above,  you  have  dynamically  linked  your application to the libbson and
       libmongoc DLLs. This is usually the right choice. If you want to link  statically  instead,  update  your
       "Additional  Dependencies" list by removing bson-1.0.lib and mongoc-1.0.lib and replacing them with these
       libraries:

          C:\mongo-c-driver\lib\bson-static-1.0.lib
          C:\mongo-c-driver\lib\mongoc-static-1.0.lib
          ws2_32.lib
          Secur32.lib
          Crypt32.lib
          BCrypt.lib
       [image]

       (To explain the purpose  of  each  library:  bson-static-1.0.lib  and  mongoc-static-1.0.lib  are  static
       archives  of  the  driver  code.  The socket library ws2_32 is required by libbson, which uses the socket
       routine gethostname to help guarantee ObjectId uniqueness. The BCrypt library is used  by  libmongoc  for
       SSL  connections  to  MongoDB, and Secur32 and Crypt32 are required for enterprise authentication methods
       like Kerberos.)

       Finally, define two preprocessor symbols before including mongoc.h in your stdafx.h:

          #define BSON_STATIC
          #define MONGOC_STATIC
          #include <mongoc.h>

       Making these changes to your  project  is  only  required  for  static  linking;  for  most  people,  the
       dynamic-linking instructions above are preferred.

   Next Steps
       Now  you  can  build  and  debug applications in Visual Studio that use libbson and libmongoc. Proceed to
       making-a-connection in the tutorial to learn how connect to MongoDB and perform operations.

   Creating Indexes
       To   create   indexes   on   a   MongoDB   collection,   execute   the   createIndexes    command    with
       mongoc_database_write_command_with_opts.  See  the MongoDB Manual entry for the createIndexes command for
       details.

   Example
       example-create-indexes.c.INDENT 0.0

          /* gcc example-create-indexes.c -o example-create-indexes $(pkg-config --cflags
           * --libs libmongoc-1.0) */

          /* ./example-create-indexes [CONNECTION_STRING [COLLECTION_NAME]] */

          #include <mongoc.h>
          #include <stdio.h>
          #include <stdlib.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_database_t *db;
             const char *uristr = "mongodb://127.0.0.1/?appname=create-indexes-example";
             const char *collection_name = "test";
             bson_t keys;
             char *index_name;
             bson_t *create_indexes;
             bson_t reply;
             char *reply_str;
             bson_error_t error;
             bool r;

             mongoc_init ();

             if (argc > 1) {
                uristr = argv[1];
             }

             if (argc > 2) {
                collection_name = argv[2];
             }

             client = mongoc_client_new (uristr);

             if (!client) {
                fprintf (stderr, "Failed to parse URI.\n");
                return EXIT_FAILURE;
             }

             mongoc_client_set_error_api (client, 2);
             db = mongoc_client_get_database (client, "test");

             /* ascending index on field "x" */
             bson_init (&keys);
             BSON_APPEND_INT32 (&keys, "x", 1);
             index_name = mongoc_collection_keys_to_index_string (&keys);
             create_indexes = BCON_NEW ("createIndexes",
                                        BCON_UTF8 (collection_name),
                                        "indexes",
                                        "[",
                                        "{",
                                        "key",
                                        BCON_DOCUMENT (&keys),
                                        "name",
                                        BCON_UTF8 (index_name),
                                        "}",
                                        "]");

             r = mongoc_database_write_command_with_opts (
                db, create_indexes, NULL /* opts */, &reply, &error);

             reply_str = bson_as_json (&reply, NULL);
             printf ("%s\n", reply_str);

             if (!r) {
                fprintf (stderr, "Error in createIndexes: %s\n", error.message);
             }

             bson_free (index_name);
             bson_free (reply_str);
             bson_destroy (&reply);
             bson_destroy (create_indexes);
             mongoc_database_destroy (db);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return r ? EXIT_SUCCESS : EXIT_FAILURE;
          }

   API Reference
   Initialization and cleanup
   Synopsis
       Initialize the MongoDB C Driver by calling mongoc_init exactly once at the beginning of your program.  It
       is responsible for initializing global state such as process counters, SSL, and threading primitives.

       Call  mongoc_cleanup  exactly  once  at the end of your program to release all memory and other resources
       allocated by the driver. You must not call any other MongoDB C  Driver  functions  after  mongoc_cleanup.
       Note that mongoc_init does not reinitialize the driver after mongoc_cleanup.

   Deprecated feature: automatic initialization and cleanup
       On  some  platforms the driver can automatically call mongoc_init before main, and call mongoc_cleanup as
       the process exits. This is problematic in situations where related libraries also execute cleanup code on
       shutdown,  and it creates inconsistent rules across platforms. Therefore the automatic initialization and
       cleanup feature is deprecated, and will be dropped in version 2.0. Meanwhile, for backward compatibility,
       the feature is enabled by default on platforms where it is available.

       For  portable,  future-proof code, always call mongoc_init and mongoc_cleanup yourself, and configure the
       driver like:

          ./configure --disable-automatic-init-and-cleanup

       Or with CMake:

          cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=NO

   Logging
       MongoDB C driver Logging Abstraction

   Synopsis
          typedef enum {
             MONGOC_LOG_LEVEL_ERROR,
             MONGOC_LOG_LEVEL_CRITICAL,
             MONGOC_LOG_LEVEL_WARNING,
             MONGOC_LOG_LEVEL_MESSAGE,
             MONGOC_LOG_LEVEL_INFO,
             MONGOC_LOG_LEVEL_DEBUG,
             MONGOC_LOG_LEVEL_TRACE,
          } mongoc_log_level_t;

          #define MONGOC_ERROR(...)
          #define MONGOC_CRITICAL(...)
          #define MONGOC_WARNING(...)
          #define MONGOC_MESSAGE(...)
          #define MONGOC_INFO(...)
          #define MONGOC_DEBUG(...)

          typedef void (*mongoc_log_func_t) (mongoc_log_level_t log_level,
                                             const char *log_domain,
                                             const char *message,
                                             void *user_data);

          void
          mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data);
          void
          mongoc_log (mongoc_log_level_t log_level,
                      const char *log_domain,
                      const char *format,
                      ...) BSON_GNUC_PRINTF (3, 4);
          const char *
          mongoc_log_level_str (mongoc_log_level_t log_level);
          void
          mongoc_log_default_handler (mongoc_log_level_t log_level,
                                      const char *log_domain,
                                      const char *message,
                                      void *user_data);
          void
          mongoc_log_trace_enable (void);
          void
          mongoc_log_trace_disable (void);

       The MongoDB C driver comes with an abstraction for logging that you  can  use  in  your  application,  or
       integrate with an existing logging system.

   Macros
       To make logging a little less painful, various helper macros are provided. See the following example.

          #undef MONGOC_LOG_DOMAIN
          #define MONGOC_LOG_DOMAIN "my-custom-domain"

          MONGOC_WARNING ("An error occurred: %s", strerror (errno));

   Custom Log Handlers
       The  default  log  handler  prints  a timestamp and the log message to stdout, or to stderr for warnings,
       critical messages, and errors.
              You can override the handler with mongoc_log_set_handler().  Your handler function is called in  a
              mutex for thread safety.

       For example, you could register a custom handler to suppress messages at INFO level and below:

          void
          my_logger (mongoc_log_level_t log_level,
                     const char *log_domain,
                     const char *message,
                     void *user_data)
          {
             /* smaller values are more important */
             if (log_level < MONGOC_LOG_LEVEL_INFO) {
                mongoc_log_default_handler (log_level, log_domain, message, user_data);
             }
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_init ();
             mongoc_log_set_handler (my_logger, NULL);

             /* ... your code ...  */

             mongoc_cleanup ();
             return 0;
          }

       To restore the default handler:

          mongoc_log_set_handler (mongoc_log_default_handler, NULL);

   Disable logging
       To disable all logging, including warnings, critical messages and errors, provide an empty log handler:

          mongoc_log_set_handler (NULL, NULL);

   Tracing
       If  compiling your own copy of the MongoDB C driver, consider configuring with --enable-tracing to enable
       function tracing and hex dumps of network packets to STDERR and STDOUT during development and debugging.

       This is especially useful when debugging what may be going on internally in the driver.

       Trace   messages   can   be   enabled   and   disabled   by   calling    mongoc_log_trace_enable()    and
       mongoc_log_trace_disable()

       NOTE:
          Compiling  the  driver  with  --enable-tracing  will  affect  its  performance. Disabling tracing with
          mongoc_log_trace_disable() significantly reduces the overhead, but cannot remove it completely.
       « index

   Error Reporting
   Description
       Many C Driver functions report errors by returning false or -1 and filling out a  bson_error_t  structure
       with  an  error  domain,  error  code, and message. Use domain to determine which subsystem generated the
       error, and code for the specific error. message is a human-readable error description.

       See also: Handling Errors in libbson.

    ┌──────────────────────────────┬────────────────────────────────────────────┬───────────────────────────────────┐
    │Domain                        │ Code                                       │ Description                       │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_CLIENTMONGOC_ERROR_CLIENT_TOO_BIG                │ You tried to send a  message      │
    │                              │                                            │ larger than the server's max      │
    │                              │                                            │ message size.                     │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │                              │ MONGOC_ERROR_CLIENT_AUTHENTICATE           │ Wrong     credentials,    or      │
    │                              │                                            │ failure sending or receiving      │
    │                              │                                            │ authentication messages.          │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │                              │ MONGOC_ERROR_CLIENT_NO_ACCEPTABLE_PEER     │ You tried an SSL  connection      │
    │                              │                                            │ but the driver was not built      │
    │                              │                                            │ with SSL.                         │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │                              │ MONGOC_ERROR_CLIENT_IN_EXHAUST             │ You   began   iterating   an      │
    │                              │                                            │ exhaust  cursor,  then tried      │
    │                              │                                            │ to begin  another  operation      │
    │                              │                                            │ with         the        same      │
    │                              │                                            │ mongoc_client_t.                  │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │                              │ MONGOC_ERROR_CLIENT_SESSION_FAILURE        │ Failure related to  creating      │
    │                              │                                            │ or using a logical session.       │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_STREAMMONGOC_ERROR_STREAM_NAME_RESOLUTION        │ DNS failure.                      │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │                              │ MONGOC_ERROR_STREAM_SOCKET                 │ Timeout  communicating  with      │
    │                              │                                            │ server,    or     connection      │
    │                              │                                            │ closed.                           │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │                              │ MONGOC_ERROR_STREAM_CONNECT                │ Failed to connect to server.      │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_PROTOCOLMONGOC_ERROR_PROTOCOL_INVALID_REPLY        │ Corrupt     response    from      │
    │                              │                                            │ server.                           │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │                              │ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION     │ The server  version  is  too      │
    │                              │                                            │ old    or    too    new   to      │
    │                              │                                            │ communicate with the driver.      │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_CURSORMONGOC_ERROR_CURSOR_INVALID_CURSOR         │ You passed bad arguments  to      │
    │                              │                                            │ mongoc_collection_find_with_opts, │
    │                              │                                            │ or        you         called      │
    │                              │                                            │ mongoc_cursor_next    on   a      │
    │                              │                                            │ completed or failed  cursor,      │
    │                              │                                            │ or  the  cursor timed out on      │
    │                              │                                            │ the server.                       │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │                              │ MONGOC_ERROR_CHANGE_STREAM_NO_RESUME_TOKEN │ A  resume  token was not returned │
    │                              │                                            │ in   a   document   found    with │
    │                              │                                            │ mongoc_change_stream_next         │
    └──────────────────────────────┴────────────────────────────────────────────┴───────────────────────────────────┘

    │MONGOC_ERROR_QUERYMONGOC_ERROR_QUERY_FAILUREError API Version 1: Server error │
    │                              │                                            │ from command or query. The server │
    │                              │                                            │ error message is in message.      │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_SERVERMONGOC_ERROR_QUERY_FAILUREError API Version 2: Server error │
    │                              │                                            │ from command or query. The server │
    │                              │                                            │ error message is in message.      │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_SASL             │ A SASL error code.                         │ man  sasl_errors  for  a  list of │
    │                              │                                            │ codes.                            │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_BSONMONGOC_ERROR_BSON_INVALID                  │ You   passed   an   invalid    or │
    │                              │                                            │ oversized   BSON  document  as  a │
    │                              │                                            │ parameter,       or        called │
    │                              │                                            │ mongoc_collection_create_index    │
    │                              │                                            │ with invalid keys, or the  server │
    │                              │                                            │ reply was corrupt.                │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_NAMESPACEMONGOC_ERROR_NAMESPACE_INVALID             │ You  tried to create a collection │
    │                              │                                            │ with an invalid name.             │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_COMMANDMONGOC_ERROR_COMMAND_INVALID_ARG           │ Many  functions  set  this  error │
    │                              │                                            │ code  when passed bad parameters. │
    │                              │                                            │ Print  the  error   message   for │
    │                              │                                            │ details.                          │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │                              │ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION     │ You tried to use a command option │
    │                              │                                            │ the server does not support.      │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │                              │ MONGOC_ERROR_DUPLICATE_KEY                 │ An  insert   or   update   failed │
    │                              │                                            │ because  because  of  a duplicate │
    │                              │                                            │ _id   or    other    unique-index │
    │                              │                                            │ violation.                        │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_COMMANDError code from server.                    │ Error API Version 1: Server error │
    │                              │                                            │ from a command. The server  error │
    │                              │                                            │ message is in message.            │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_SERVERError code from server.                    │ Error API Version 2: Server error │
    │                              │                                            │ from a command. The server  error │
    │                              │                                            │ message is in message.            │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_COLLECTIONMONGOC_ERROR_COLLECTION_INSERT_FAILED,     │ Invalid   or   empty   input   to │
    │                              │ MONGOC_ERROR_COLLECTION_UPDATE_FAILED,     │ mongoc_collection_insert_one,     │
    │                              │ MONGOC_ERROR_COLLECTION_DELETE_FAILED.     │ mongoc_collection_insert_bulk,    │
    │                              │                                            │ mongoc_collection_update_one,     │
    │                              │                                            │ mongoc_collection_update_many,    │
    │                              │                                            │ mongoc_collection_replace_one,    │
    │                              │                                            │ mongoc_collection_delete_one,  or │
    │                              │                                            │ mongoc_collection_delete_many.    │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_COLLECTIONError code from server.                    │ Error API Version 1: Server error │
    │                              │                                            │ from                              │
    │                              │                                            │ mongoc_collection_insert_one,     │
    │                              │                                            │ mongoc_collection_insert_bulk,    │
    │                              │                                            │ mongoc_collection_update_one,     │
    │                              │                                            │ mongoc_collection_update_many,    │
    │                              │                                            │ mongoc_collection_replace_one,    │
    │                              │                                            │ mongoc_collection_delete_one,  or │
    │                              │                                            │ mongoc_collection_delete_many.    │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_SERVERError code from server.                    │ Error API Version 2: Server error │
    │                              │                                            │ from                              │
    │                              │                                            │ mongoc_collection_insert_one,     │
    │                              │                                            │ mongoc_collection_insert_bulk,    │
    │                              │                                            │ mongoc_collection_update_one,     │
    │                              │                                            │ mongoc_collection_update_many,    │
    │                              │                                            │ mongoc_collection_replace_one,    │
    │                              │                                            │ mongoc_collection_delete_one,  or │
    │                              │                                            │ mongoc_collection_delete_many.    │
    └──────────────────────────────┴────────────────────────────────────────────┴───────────────────────────────────┘

    │MONGOC_ERROR_GRIDFSMONGOC_ERROR_GRIDFS_CHUNK_MISSING          │ The  GridFS  file  is  missing  a │
    │                              │                                            │ document     in     its    chunks │
    │                              │                                            │ collection.                       │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │                              │ MONGOC_ERROR_GRIDFS_INVALID_FILENAME       │ You passed  a  NULL  filename  to │
    │                              │                                            │ mongoc_gridfs_remove_by_filename. │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │                              │ MONGOC_ERROR_GRIDFS_PROTOCOL_ERROR         │ You                        called │
    │                              │                                            │ mongoc_gridfs_file_set_id   after │
    │                              │                                            │ mongoc_gridfs_file_save.          │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_SCRAMMONGOC_ERROR_SCRAM_PROTOCOL_ERROR          │ Failure       in      SCRAM-SHA-1 │
    │                              │                                            │ authentication.                   │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_SERVER_SELECTIONMONGOC_ERROR_SERVER_SELECTION_FAILURE      │ No  replica  set member or mongos │
    │                              │                                            │ is  available,  or  none  matches │
    │                              │                                            │ your   read  preference,  or  you │
    │                              │                                            │ supplied        an        invalid │
    │                              │                                            │ mongoc_read_prefs_t.              │
    ├──────────────────────────────┼────────────────────────────────────────────┼───────────────────────────────────┤
    │MONGOC_ERROR_WRITE_CONCERNError code from server.                    │ There  was  a write concern error │
    │                              │                                            │ or timeout from the server.       │
    └──────────────────────────────┴────────────────────────────────────────────┴───────────────────────────────────┘

   Setting the Error API Version
       The driver's error reporting began with a design flaw: when the error domain is  MONGOC_ERROR_COLLECTION,
       MONGOC_ERROR_QUERY,  or  MONGOC_ERROR_COMMAND,  the  error  code  might  originate from the server or the
       driver. An application cannot always know where an error originated, and therefore cannot tell  what  the
       code means.

       For  example,  if mongoc_collection_update_one sets the error's domain to MONGOC_ERROR_COLLECTION and its
       code  to  24,  the  application  cannot  know   whether   24   is   the   generic   driver   error   code
       MONGOC_ERROR_COLLECTION_UPDATE_FAILED or the specific server error code "LockTimeout".

       To  fix  this  flaw  while  preserving  backward  compatibility,  the  C Driver 1.4 introduces "Error API
       Versions". Version 1, the default Error API Version, maintains the flawed behavior. Version 2 adds a  new
       error  domain, MONGOC_ERROR_SERVER. In Version 2, error codes originating on the server always have error
       domain MONGOC_ERROR_SERVER or MONGOC_ERROR_WRITE_CONCERN. When the driver uses Version 2 the  application
       can  always  determine  the origin and meaning of error codes. New applications should use Version 2, and
       existing applications should be updated to use Version 2 as well.

        ┌────────────────────────────────────────────┬────────────────────────────┬────────────────────────────┐
        │Error Source                                │ API Version 1              │ API Version 2              │
        ├────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤
        │mongoc_cursor_errorMONGOC_ERROR_QUERYMONGOC_ERROR_SERVER        │
        ├────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤
        │mongoc_client_command_with_opts,            │ MONGOC_ERROR_QUERYMONGOC_ERROR_SERVER        │
        │mongoc_database_command_with_opts,          │                            │                            │
        │and other command functions                 │                            │                            │
        ├────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤
        │mongoc_collection_count_with_optsMONGOC_ERROR_QUERYMONGOC_ERROR_SERVER        │
        │mongoc_client_get_database_names_with_opts, │                            │                            │
        │and other command helper functions          │                            │                            │
        ├────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤
        │mongoc_collection_insert_oneMONGOC_ERROR_COMMANDMONGOC_ERROR_SERVER        │
        │mongoc_collection_insert_bulk               │                            │                            │
        │mongoc_collection_update_one                │                            │                            │
        │mongoc_collection_update_many               │                            │                            │
        │mongoc_collection_replace_one               │                            │                            │
        │mongoc_collection_delete_one                │                            │                            │
        │mongoc_collection_delete_many               │                            │                            │
        ├────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤
        │mongoc_bulk_operation_executeMONGOC_ERROR_COMMANDMONGOC_ERROR_SERVER        │
        ├────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤
        │Write-concern timeout                       │ MONGOC_ERROR_WRITE_CONCERNMONGOC_ERROR_WRITE_CONCERN │
        └────────────────────────────────────────────┴────────────────────────────┴────────────────────────────┘

       The Error API Versions are defined with MONGOC_ERROR_API_VERSION_LEGACY  and  MONGOC_ERROR_API_VERSION_2.
       Set the version with mongoc_client_set_error_api or mongoc_client_pool_set_error_api.

   See Also
       MongoDB Server Error Codes

   Object Lifecycle
       This page documents the order of creation and destruction for libmongoc's main struct types.

   Clients and pools
       Call  mongoc_init()  once,  before  calling any other libmongoc functions, and call mongoc_cleanup() once
       before your program exits.

       A  program  that  uses  libmongoc  from  multiple  threads  should  create  a  mongoc_client_pool_t  with
       mongoc_client_pool_new().    Each    thread    acquires    a   mongoc_client_t   from   the   pool   with
       mongoc_client_pool_pop() and returns it with mongoc_client_pool_push() when the thread is finished  using
       it. To destroy the pool, first return all clients, then call mongoc_client_pool_destroy().

       If   your  program  uses  libmongoc  from  only  one  thread,  create  a  mongoc_client_t  directly  with
       mongoc_client_new() or mongoc_client_new_from_uri(). Destroy it with mongoc_client_destroy().

   Databases, collections, and related objects
       You can  create  a  mongoc_database_t  or  mongoc_collection_t  from  a  mongoc_client_t,  and  create  a
       mongoc_cursor_t or mongoc_bulk_operation_t from a mongoc_collection_t.

       Each of these objects must be destroyed before the client they were created from, but their lifetimes are
       otherwise independent.

   GridFS objects
       You  can  create  a  mongoc_gridfs_t  from  a   mongoc_client_t,   create   a   mongoc_gridfs_file_t   or
       mongoc_gridfs_file_list_t    from    a    mongoc_gridfs_t,   create   a   mongoc_gridfs_file_t   from   a
       mongoc_gridfs_file_list_t, and create a mongoc_stream_t from a mongoc_gridfs_file_t.

       Each of these objects depends on the object it was created from. Always destroy  GridFS  objects  in  the
       reverse  of  the  order  they were created. The sole exception is that a mongoc_gridfs_file_t need not be
       destroyed before the mongoc_gridfs_file_list_t it was created from.

   Sessions
       Start a session with mongoc_client_start_session, use the session for a sequence of operations, then free
       it with mongoc_client_session_destroy(). A session must be freed before the mongoc_client_t it came from.

       By  default,  sessions  are causally consistent. To disable causal consistency, before starting a session
       create       a       mongoc_session_opt_t       with       mongoc_session_opts_new()       and       call
       mongoc_session_opts_set_causal_consistency(), then free the struct with mongoc_session_opts_destroy.

       Unacknowledged   writes   are  not  causally  consistent.  If  you  execute  a  write  operation  with  a
       mongoc_write_concern_t on which you have called mongoc_write_concern_set_w with a value of 0,  the  write
       does not participate in causal consistency.

       A  mongoc_client_session_t  must  be  used  by  only  one  thread  at  a  time.  Due  to session pooling,
       mongoc_client_start_session may return a session that has been idle for some time  and  is  about  to  be
       closed  after  its idle timeout. Use the session within one minute of acquiring it to refresh the session
       and avoid a timeout.

   mongoc_bulk_operation_t
       Bulk Write Operations

   Synopsis
          typedef struct _mongoc_bulk_operation_t mongoc_bulk_operation_t;

       The opaque type mongoc_bulk_operation_t provides an abstraction for submitting multiple write  operations
       as a single batch.

       After    adding    all    of    the    write    operations    to    the   mongoc_bulk_operation_t,   call
       mongoc_bulk_operation_execute() to execute the operation.

       WARNING:
          It is only valid to call mongoc_bulk_operation_execute() once.  The  mongoc_bulk_operation_t  must  be
          destroyed afterwards.

   See Also
       Bulk Write Operations

   mongoc_change_stream_t
   Synopsis
          #include <mongoc.h>

          typedef struct _mongoc_change_stream_t mongoc_change_stream_t;

       mongoc_change_stream_t  is  a handle to a change stream. A collection change stream can be obtained using
       mongoc_collection_watch.

       It is recommended to use a mongoc_change_stream_t and its functions instead of a raw aggregation  with  a
       $changeStream stage. For more information see the MongoDB Manual Entry on Change Streams.

   Example
       example-collection-watch.c.INDENT 0.0

          #include <mongoc.h>

          int
          main ()
          {
             bson_t empty = BSON_INITIALIZER;
             const bson_t *doc;
             bson_t *to_insert = BCON_NEW ("x", BCON_INT32 (1));
             const bson_t *err_doc;
             bson_error_t err;
             mongoc_client_t *client;
             mongoc_collection_t *coll;
             mongoc_change_stream_t *stream;
             mongoc_write_concern_t *wc = mongoc_write_concern_new ();
             bson_t opts = BSON_INITIALIZER;
             bool r;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://"
                                         "localhost:27017,localhost:27018,localhost:"
                                         "27019/db?replicaSet=rs0");
             if (!client) {
                fprintf (stderr, "Could not connect to replica set\n");
                return 1;
             }

             coll = mongoc_client_get_collection (client, "db", "coll");
             stream = mongoc_collection_watch (coll, &empty, NULL);

             mongoc_write_concern_set_wmajority (wc, 10000);
             mongoc_write_concern_append (wc, &opts);
             r = mongoc_collection_insert_one (coll, to_insert, &opts, NULL, &err);
             if (!r) {
                fprintf (stderr, "Error: %s\n", err.message);
                return 1;
             }

             while (mongoc_change_stream_next (stream, &doc)) {
                char *as_json = bson_as_relaxed_extended_json (doc, NULL);
                fprintf (stderr, "Got document: %s\n", as_json);
                bson_free (as_json);
             }

             if (mongoc_change_stream_error_document (stream, &err, &err_doc)) {
                if (!bson_empty (err_doc)) {
                   fprintf (stderr,
                            "Server Error: %s\n",
                            bson_as_relaxed_extended_json (err_doc, NULL));
                } else {
                   fprintf (stderr, "Client Error: %s\n", err.message);
                }
                return 1;
             }

             bson_destroy (to_insert);
             mongoc_write_concern_destroy (wc);
             bson_destroy (&opts);
             mongoc_change_stream_destroy (stream);
             mongoc_collection_destroy (coll);
             mongoc_client_destroy (client);
             mongoc_cleanup ();
          }

   mongoc_client_pool_t
       A connection pool for multi-threaded programs. See connection-pooling.

   Synopsis
          typedef struct _mongoc_client_pool_t mongoc_client_pool_t

       mongoc_client_pool_t  is  the  basis  for  multi-threading in the MongoDB C driver. Since mongoc_client_t
       structures are not thread-safe, this structure is used to retrieve a  new  mongoc_client_t  for  a  given
       thread. This structure is thread-safe.

   Example
       example-pool.c.INDENT 0.0

          /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs
           * libmongoc-1.0) */

          /* ./example-pool [CONNECTION_STRING] */

          #include <mongoc.h>
          #include <pthread.h>
          #include <stdio.h>

          static pthread_mutex_t mutex;
          static bool in_shutdown = false;

          static void *
          worker (void *data)
          {
             mongoc_client_pool_t *pool = data;
             mongoc_client_t *client;
             bson_t ping = BSON_INITIALIZER;
             bson_error_t error;
             bool r;

             BSON_APPEND_INT32 (&ping, "ping", 1);

             while (true) {
                client = mongoc_client_pool_pop (pool);
                /* Do something with client. If you are writing an HTTP server, you
                 * probably only want to hold onto the client for the portion of the
                 * request performing database queries.
                 */
                r = mongoc_client_command_simple (
                   client, "admin", &ping, NULL, NULL, &error);

                if (!r) {
                   fprintf (stderr, "%s\n", error.message);
                }

                mongoc_client_pool_push (pool, client);

                pthread_mutex_lock (&mutex);
                if (in_shutdown || !r) {
                   pthread_mutex_unlock (&mutex);
                   break;
                }

                pthread_mutex_unlock (&mutex);
             }

             bson_destroy (&ping);
             return NULL;
          }

          int
          main (int argc, char *argv[])
          {
             const char *uristr = "mongodb://127.0.0.1/?appname=pool-example";
             mongoc_uri_t *uri;
             mongoc_client_pool_t *pool;
             pthread_t threads[10];
             unsigned i;
             void *ret;

             pthread_mutex_init (&mutex, NULL);
             mongoc_init ();

             if (argc > 1) {
                uristr = argv[1];
             }

             uri = mongoc_uri_new (uristr);
             if (!uri) {
                fprintf (stderr, "Failed to parse URI: \"%s\".\n", uristr);
                return EXIT_FAILURE;
             }

             pool = mongoc_client_pool_new (uri);
             mongoc_client_pool_set_error_api (pool, 2);

             for (i = 0; i < 10; i++) {
                pthread_create (&threads[i], NULL, worker, pool);
             }

             sleep (10);
             pthread_mutex_lock (&mutex);
             in_shutdown = true;
             pthread_mutex_unlock (&mutex);

             for (i = 0; i < 10; i++) {
                pthread_join (threads[i], &ret);
             }

             mongoc_client_pool_destroy (pool);
             mongoc_uri_destroy (uri);

             mongoc_cleanup ();

             return 0;
          }

   mongoc_client_session_t
       Use  a  session  for a sequence of operations, optionally with causal consistency. See the MongoDB Manual
       Entry for Causal Consistency.

   Synopsis
       Start a session with mongoc_client_start_session, use the session for a sequence of operations, then free
       it with mongoc_client_session_destroy(). A session must be freed before the mongoc_client_t it came from.

       By  default,  sessions  are causally consistent. To disable causal consistency, before starting a session
       create       a       mongoc_session_opt_t       with       mongoc_session_opts_new()       and       call
       mongoc_session_opts_set_causal_consistency(), then free the struct with mongoc_session_opts_destroy.

       Unacknowledged   writes   are  not  causally  consistent.  If  you  execute  a  write  operation  with  a
       mongoc_write_concern_t on which you have called mongoc_write_concern_set_w with a value of 0,  the  write
       does not participate in causal consistency.

       A  mongoc_client_session_t  must  be  used  by  only  one  thread  at  a  time.  Due  to session pooling,
       mongoc_client_start_session may return a session that has been idle for some time  and  is  about  to  be
       closed  after  its idle timeout. Use the session within one minute of acquiring it to refresh the session
       and avoid a timeout.

   Example
       example-session.c.INDENT 0.0

          /* gcc example-session.c -o example-session \
           *     $(pkg-config --cflags --libs libmongoc-1.0) */

          /* ./example-session [CONNECTION_STRING] */

          #include <stdio.h>
          #include <mongoc.h>

          int
          main (int argc, char *argv[])
          {
             int exit_code = EXIT_FAILURE;

             mongoc_client_t *client;
             mongoc_client_session_t *client_session = NULL;
             mongoc_collection_t *collection = NULL;
             const char *uristr = "mongodb://127.0.0.1/?appname=session-example";
             bson_error_t error;
             bson_t *selector = NULL;
             bson_t *update = NULL;
             bson_t *update_opts = NULL;
             bson_t *find_opts = NULL;
             mongoc_read_prefs_t *secondary = NULL;
             mongoc_cursor_t *cursor = NULL;
             const bson_t *doc;
             char *str;
             bool r;

             mongoc_init ();

             if (argc > 1) {
                uristr = argv[1];
             }

             client = mongoc_client_new (uristr);

             if (!client) {
                fprintf (stderr, "Failed to parse URI.\n");
                goto done;
             }

             mongoc_client_set_error_api (client, 2);

             /* pass NULL for options - by default the session is causally consistent */
             client_session = mongoc_client_start_session (client, NULL, &error);
             if (!client_session) {
                fprintf (stderr, "Failed to start session: %s\n", error.message);
                goto done;
             }

             collection = mongoc_client_get_collection (client, "test", "collection");
             selector = BCON_NEW ("_id", BCON_INT32 (1));
             update = BCON_NEW ("$inc", "{", "x", BCON_INT32 (1), "}");
             update_opts = bson_new ();
             if (!mongoc_client_session_append (client_session, update_opts, &error)) {
                fprintf (stderr, "Could not add session to opts: %s\n", error.message);
                goto done;
             }

             r = mongoc_collection_update_one (
                collection, selector, update, update_opts, NULL /* reply */, &error);

             if (!r) {
                fprintf (stderr, "Update failed: %s\n", error.message);
                goto done;
             }

             bson_destroy (selector);
             selector = BCON_NEW ("_id", BCON_INT32 (1));
             secondary = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);

             find_opts = BCON_NEW ("maxTimeMS", BCON_INT32 (2000));
             if (!mongoc_client_session_append (client_session, find_opts, &error)) {
                fprintf (stderr, "Could not add session to opts: %s\n", error.message);
                goto done;
             };

             /* read from secondary. since we're in a causally consistent session, the
              * data is guaranteed to reflect the update we did on the primary. the query
              * blocks waiting for the secondary to catch up, if necessary, or times out
              * and fails after 2000 ms.
              */
             cursor = mongoc_collection_find_with_opts (
                collection, selector, find_opts, secondary);

             bson_destroy (selector);
             mongoc_read_prefs_destroy (secondary);
             bson_destroy (find_opts);

             while (mongoc_cursor_next (cursor, &doc)) {
                str = bson_as_json (doc, NULL);
                fprintf (stdout, "%s\n", str);
                bson_free (str);
             }

             if (mongoc_cursor_error (cursor, &error)) {
                fprintf (stderr, "Cursor Failure: %s\n", error.message);
                goto done;
             }

             exit_code = EXIT_SUCCESS;

          done:
             if (find_opts) {
                bson_destroy (find_opts);
             }
             if (update) {
                bson_destroy (update);
             }
             if (selector) {
                bson_destroy (selector);
             }
             if (update_opts) {
                bson_destroy (update_opts);
             }
             if (secondary) {
                mongoc_read_prefs_destroy (secondary);
             }
             /* destroy cursor, collection, session before the client they came from */
             if (cursor) {
                mongoc_cursor_destroy (cursor);
             }
             if (collection) {
                mongoc_collection_destroy (collection);
             }
             if (client_session) {
                mongoc_client_session_destroy (client_session);
             }
             if (client) {
                mongoc_client_destroy (client);
             }

             mongoc_cleanup ();

             return exit_code;
          }

   mongoc_client_t
       A single-threaded MongoDB connection. See connection-pooling.

   Synopsis
          typedef struct _mongoc_client_t mongoc_client_t;

          typedef mongoc_stream_t *(*mongoc_stream_initiator_t) (
             const mongoc_uri_t *uri,
             const mongoc_host_list_t *host,
             void *user_data,
             bson_error_t *error);

       mongoc_client_t is an opaque type that provides access to a  MongoDB  server,  replica  set,  or  sharded
       cluster.  It  maintains  management  of  underlying  sockets  and  routing  to  individual nodes based on
       mongoc_read_prefs_t or mongoc_write_concern_t.

   Streams
       The underlying transport for a given client can be customized, wrapped or replaced by any  implementation
       that fulfills mongoc_stream_t. A custom transport can be set with mongoc_client_set_stream_initiator().

   Thread Safety
       mongoc_client_t  is  NOT  thread-safe  and  should  only  be used from one thread at a time. When used in
       multi-threaded scenarios, it is recommended that you use the thread-safe mongoc_client_pool_t to retrieve
       a mongoc_client_t for your thread.

   Example
       example-client.c.INDENT 0.0

          /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
           * libmongoc-1.0) */

          /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */

          #include <mongoc.h>
          #include <stdio.h>
          #include <stdlib.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             mongoc_cursor_t *cursor;
             bson_error_t error;
             const bson_t *doc;
             const char *uristr = "mongodb://127.0.0.1/?appname=client-example";
             const char *collection_name = "test";
             bson_t query;
             char *str;

             mongoc_init ();

             if (argc > 1) {
                uristr = argv[1];
             }

             if (argc > 2) {
                collection_name = argv[2];
             }

             client = mongoc_client_new (uristr);

             if (!client) {
                fprintf (stderr, "Failed to parse URI.\n");
                return EXIT_FAILURE;
             }

             mongoc_client_set_error_api (client, 2);

             bson_init (&query);

          #if 0
             bson_append_utf8 (&query, "hello", -1, "world", -1);
          #endif

             collection = mongoc_client_get_collection (client, "test", collection_name);
             cursor = mongoc_collection_find_with_opts (
                collection,
                &query,
                NULL,  /* additional options */
                NULL); /* read prefs, NULL for default */

             while (mongoc_cursor_next (cursor, &doc)) {
                str = bson_as_canonical_extended_json (doc, NULL);
                fprintf (stdout, "%s\n", str);
                bson_free (str);
             }

             if (mongoc_cursor_error (cursor, &error)) {
                fprintf (stderr, "Cursor Failure: %s\n", error.message);
                return EXIT_FAILURE;
             }

             bson_destroy (&query);
             mongoc_cursor_destroy (cursor);
             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return EXIT_SUCCESS;
          }

   mongoc_collection_t
   Synopsis
          #include <mongoc.h>

          typedef struct _mongoc_collection_t mongoc_collection_t;

       mongoc_collection_t  provides access to a MongoDB collection.  This handle is useful for actions for most
       CRUD operations, I.e. insert, update, delete, find, etc.

   Read Preferences and Write Concerns
       Read preferences and write concerns are inherited from the parent client. They can be overridden by set_*
       commands if so desired.

   mongoc_cursor_t
       Client-side cursor abstraction

   Synopsis
          typedef struct _mongoc_cursor_t mongoc_cursor_t;

       mongoc_cursor_t  provides  access  to  a MongoDB query cursor.  It wraps up the wire protocol negotiation
       required to initiate a query and retrieve an unknown number of documents.

       Cursors are lazy, meaning that no network traffic occurs until the first call to mongoc_cursor_next().

       At that point we can:

       • Determine which host we've connected to with mongoc_cursor_get_host().

       • Retrieve more records with repeated calls to mongoc_cursor_next().

       • Clone a query to repeat execution at a later point with mongoc_cursor_clone().

       • Test for errors with mongoc_cursor_error().

   Thread Safety
       mongoc_cursor_t is NOT thread safe. It may only be used from the thread it was created from.

   Example
       Query MongoDB and iterate results.INDENT 0.0

          /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
           * libmongoc-1.0) */

          /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */

          #include <mongoc.h>
          #include <stdio.h>
          #include <stdlib.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             mongoc_cursor_t *cursor;
             bson_error_t error;
             const bson_t *doc;
             const char *uristr = "mongodb://127.0.0.1/?appname=client-example";
             const char *collection_name = "test";
             bson_t query;
             char *str;

             mongoc_init ();

             if (argc > 1) {
                uristr = argv[1];
             }

             if (argc > 2) {
                collection_name = argv[2];
             }

             client = mongoc_client_new (uristr);

             if (!client) {
                fprintf (stderr, "Failed to parse URI.\n");
                return EXIT_FAILURE;
             }

             mongoc_client_set_error_api (client, 2);

             bson_init (&query);

          #if 0
             bson_append_utf8 (&query, "hello", -1, "world", -1);
          #endif

             collection = mongoc_client_get_collection (client, "test", collection_name);
             cursor = mongoc_collection_find_with_opts (
                collection,
                &query,
                NULL,  /* additional options */
                NULL); /* read prefs, NULL for default */

             while (mongoc_cursor_next (cursor, &doc)) {
                str = bson_as_canonical_extended_json (doc, NULL);
                fprintf (stdout, "%s\n", str);
                bson_free (str);
             }

             if (mongoc_cursor_error (cursor, &error)) {
                fprintf (stderr, "Cursor Failure: %s\n", error.message);
                return EXIT_FAILURE;
             }

             bson_destroy (&query);
             mongoc_cursor_destroy (cursor);
             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return EXIT_SUCCESS;
          }

   mongoc_database_t
       MongoDB Database Abstraction

   Synopsis
          typedef struct _mongoc_database_t mongoc_database_t;

       mongoc_database_t provides access to a MongoDB database. This handle is useful for actions  a  particular
       database object. It is not a container for mongoc_collection_t structures.

       Read  preferences  and  write  concerns are inherited from the parent client. They can be overridden with
       mongoc_database_set_read_prefs() and mongoc_database_set_write_concern().

   Examples
          #include <mongoc.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_database_t *database;
             mongoc_client_t *client;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/");
             database = mongoc_client_get_database (client, "test");

             mongoc_database_destroy (database);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

   mongoc_delete_flags_t
       Flags for deletion operations

   Synopsis
          typedef enum {
             MONGOC_DELETE_NONE = 0,
             MONGOC_DELETE_SINGLE_REMOVE = 1 << 0,
          } mongoc_delete_flags_t;

   Deprecated
       WARNING:
          These flags are deprecated and should not be used in new code.

       Please use mongoc_collection_delete_one() or mongoc_collection_delete_many() instead.

   mongoc_find_and_modify_opts_t
       find_and_modify abstraction

   Synopsis
       mongoc_find_and_modify_opts_t is a builder interface to construct a find_and_modify command.

       It was created to be able to accommodate new arguments to the MongoDB find_and_modify command.

       As of MongoDB 3.2, the mongoc_write_concern_t specified on the mongoc_collection_t will be used, if any.

   Example
       flags.c.INDENT 0.0

          void
          fam_flags (mongoc_collection_t *collection)
          {
             mongoc_find_and_modify_opts_t *opts;
             bson_t reply;
             bson_error_t error;
             bson_t query = BSON_INITIALIZER;
             bson_t *update;
             bool success;

             /* Find Zlatan Ibrahimovic, the striker */
             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
             BSON_APPEND_UTF8 (&query, "profession", "Football player");
             BSON_APPEND_INT32 (&query, "age", 34);
             BSON_APPEND_INT32 (
                &query, "goals", (16 + 35 + 23 + 57 + 16 + 14 + 28 + 84) + (1 + 6 + 62));

             /* Add his football position */
             update = BCON_NEW ("$set", "{", "position", BCON_UTF8 ("striker"), "}");

             opts = mongoc_find_and_modify_opts_new ();

             mongoc_find_and_modify_opts_set_update (opts, update);

             /* Create the document if it didn't exist, and return the updated document */
             mongoc_find_and_modify_opts_set_flags (
                opts, MONGOC_FIND_AND_MODIFY_UPSERT | MONGOC_FIND_AND_MODIFY_RETURN_NEW);

             success = mongoc_collection_find_and_modify_with_opts (
                collection, &query, opts, &reply, &error);

             if (success) {
                char *str;

                str = bson_as_canonical_extended_json (&reply, NULL);
                printf ("%s\n", str);
                bson_free (str);
             } else {
                fprintf (
                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
             }

             bson_destroy (&reply);
             bson_destroy (update);
             bson_destroy (&query);
             mongoc_find_and_modify_opts_destroy (opts);
          }
          void
          fam_bypass (mongoc_collection_t *collection)
          {
             mongoc_find_and_modify_opts_t *opts;
             bson_t reply;
             bson_t *update;
             bson_error_t error;
             bson_t query = BSON_INITIALIZER;
             bool success;

             /* Find Zlatan Ibrahimovic, the striker */
             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
             BSON_APPEND_UTF8 (&query, "profession", "Football player");

             /* Bump his age */
             update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}");

             opts = mongoc_find_and_modify_opts_new ();
             mongoc_find_and_modify_opts_set_update (opts, update);
             /* He can still play, even though he is pretty old. */
             mongoc_find_and_modify_opts_set_bypass_document_validation (opts, true);

             success = mongoc_collection_find_and_modify_with_opts (
                collection, &query, opts, &reply, &error);

             if (success) {
                char *str;

                str = bson_as_canonical_extended_json (&reply, NULL);
                printf ("%s\n", str);
                bson_free (str);
             } else {
                fprintf (
                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
             }

             bson_destroy (&reply);
             bson_destroy (update);
             bson_destroy (&query);
             mongoc_find_and_modify_opts_destroy (opts);
          }
          void
          fam_update (mongoc_collection_t *collection)
          {
             mongoc_find_and_modify_opts_t *opts;
             bson_t *update;
             bson_t reply;
             bson_error_t error;
             bson_t query = BSON_INITIALIZER;
             bool success;

             /* Find Zlatan Ibrahimovic */
             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");

             /* Make him a book author */
             update = BCON_NEW ("$set", "{", "author", BCON_BOOL (true), "}");

             opts = mongoc_find_and_modify_opts_new ();
             /* Note that the document returned is the _previous_ version of the document
              * To fetch the modified new version, use
              * mongoc_find_and_modify_opts_set_flags (opts,
              * MONGOC_FIND_AND_MODIFY_RETURN_NEW);
              */
             mongoc_find_and_modify_opts_set_update (opts, update);

             success = mongoc_collection_find_and_modify_with_opts (
                collection, &query, opts, &reply, &error);

             if (success) {
                char *str;

                str = bson_as_canonical_extended_json (&reply, NULL);
                printf ("%s\n", str);
                bson_free (str);
             } else {
                fprintf (
                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
             }

             bson_destroy (&reply);
             bson_destroy (update);
             bson_destroy (&query);
             mongoc_find_and_modify_opts_destroy (opts);
          }
          void
          fam_fields (mongoc_collection_t *collection)
          {
             mongoc_find_and_modify_opts_t *opts;
             bson_t fields = BSON_INITIALIZER;
             bson_t *update;
             bson_t reply;
             bson_error_t error;
             bson_t query = BSON_INITIALIZER;
             bool success;

             /* Find Zlatan Ibrahimovic */
             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");

             /* Return his goal tally */
             BSON_APPEND_INT32 (&fields, "goals", 1);

             /* Bump his goal tally */
             update = BCON_NEW ("$inc", "{", "goals", BCON_INT32 (1), "}");

             opts = mongoc_find_and_modify_opts_new ();
             mongoc_find_and_modify_opts_set_update (opts, update);
             mongoc_find_and_modify_opts_set_fields (opts, &fields);
             /* Return the new tally */
             mongoc_find_and_modify_opts_set_flags (opts,
                                                    MONGOC_FIND_AND_MODIFY_RETURN_NEW);

             success = mongoc_collection_find_and_modify_with_opts (
                collection, &query, opts, &reply, &error);

             if (success) {
                char *str;

                str = bson_as_canonical_extended_json (&reply, NULL);
                printf ("%s\n", str);
                bson_free (str);
             } else {
                fprintf (
                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
             }

             bson_destroy (&reply);
             bson_destroy (update);
             bson_destroy (&fields);
             bson_destroy (&query);
             mongoc_find_and_modify_opts_destroy (opts);
          }
          void
          fam_sort (mongoc_collection_t *collection)
          {
             mongoc_find_and_modify_opts_t *opts;
             bson_t *update;
             bson_t sort = BSON_INITIALIZER;
             bson_t reply;
             bson_error_t error;
             bson_t query = BSON_INITIALIZER;
             bool success;

             /* Find all users with the lastname Ibrahimovic */
             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");

             /* Sort by age (descending) */
             BSON_APPEND_INT32 (&sort, "age", -1);

             /* Bump his goal tally */
             update = BCON_NEW ("$set", "{", "oldest", BCON_BOOL (true), "}");

             opts = mongoc_find_and_modify_opts_new ();
             mongoc_find_and_modify_opts_set_update (opts, update);
             mongoc_find_and_modify_opts_set_sort (opts, &sort);

             success = mongoc_collection_find_and_modify_with_opts (
                collection, &query, opts, &reply, &error);

             if (success) {
                char *str;

                str = bson_as_canonical_extended_json (&reply, NULL);
                printf ("%s\n", str);
                bson_free (str);
             } else {
                fprintf (
                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
             }

             bson_destroy (&reply);
             bson_destroy (update);
             bson_destroy (&sort);
             bson_destroy (&query);
             mongoc_find_and_modify_opts_destroy (opts);
          }
          void
          fam_opts (mongoc_collection_t *collection)
          {
             mongoc_find_and_modify_opts_t *opts;
             bson_t reply;
             bson_t *update;
             bson_error_t error;
             bson_t query = BSON_INITIALIZER;
             mongoc_write_concern_t *wc;
             bson_t extra = BSON_INITIALIZER;
             bool success;

             /* Find Zlatan Ibrahimovic, the striker */
             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
             BSON_APPEND_UTF8 (&query, "profession", "Football player");

             /* Bump his age */
             update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}");

             opts = mongoc_find_and_modify_opts_new ();
             mongoc_find_and_modify_opts_set_update (opts, update);

             /* Abort if the operation takes too long. */
             mongoc_find_and_modify_opts_set_max_time_ms (opts, 100);

             /* Set write concern w: 2 */
             wc = mongoc_write_concern_new ();
             mongoc_write_concern_set_w (wc, 2);
             mongoc_write_concern_append (wc, &extra);

             /* Some future findAndModify option the driver doesn't support conveniently
              */
             BSON_APPEND_INT32 (&extra, "futureOption", 42);
             mongoc_find_and_modify_opts_append (opts, &extra);

             success = mongoc_collection_find_and_modify_with_opts (
                collection, &query, opts, &reply, &error);

             if (success) {
                char *str;

                str = bson_as_canonical_extended_json (&reply, NULL);
                printf ("%s\n", str);
                bson_free (str);
             } else {
                fprintf (
                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
             }

             bson_destroy (&reply);
             bson_destroy (&extra);
             bson_destroy (update);
             bson_destroy (&query);
             mongoc_write_concern_destroy (wc);
             mongoc_find_and_modify_opts_destroy (opts);
          }
          int
          main (void)
          {
             mongoc_collection_t *collection;
             mongoc_database_t *database;
             mongoc_client_t *client;
             bson_error_t error;
             bson_t *options;

             mongoc_init ();
             client = mongoc_client_new (
                "mongodb://localhost:27017/admin?appname=find-and-modify-opts-example");
             mongoc_client_set_error_api (client, 2);
             database = mongoc_client_get_database (client, "databaseName");

             options = BCON_NEW ("validator",
                                 "{",
                                 "age",
                                 "{",
                                 "$lte",
                                 BCON_INT32 (34),
                                 "}",
                                 "}",
                                 "validationAction",
                                 BCON_UTF8 ("error"),
                                 "validationLevel",
                                 BCON_UTF8 ("moderate"));

             collection = mongoc_database_create_collection (
                database, "collectionName", options, &error);
             if (!collection) {
                fprintf (
                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
                return 1;
             }

             fam_flags (collection);
             fam_bypass (collection);
             fam_update (collection);
             fam_fields (collection);
             fam_opts (collection);
             fam_sort (collection);

             mongoc_collection_drop (collection, NULL);
             bson_destroy (options);
             mongoc_database_destroy (database);
             mongoc_collection_destroy (collection);
             mongoc_client_destroy (client);

             mongoc_cleanup ();
             return 0;
          }

Outputs:

          {
              "lastErrorObject": {
                  "updatedExisting": false,
                  "n": 1,
                  "upserted": {
                      "$oid": "56562a99d13e6d86239c7b00"
                  }
              },
              "value": {
                  "_id": {
                      "$oid": "56562a99d13e6d86239c7b00"
                  },
                  "age": 34,
                  "firstname": "Zlatan",
                  "goals": 342,
                  "lastname": "Ibrahimovic",
                  "profession": "Football player",
                  "position": "striker"
              },
              "ok": 1
          }
          {
              "lastErrorObject": {
                  "updatedExisting": true,
                  "n": 1
              },
              "value": {
                  "_id": {
                      "$oid": "56562a99d13e6d86239c7b00"
                  },
                  "age": 34,
                  "firstname": "Zlatan",
                  "goals": 342,
                  "lastname": "Ibrahimovic",
                  "profession": "Football player",
                  "position": "striker"
              },
              "ok": 1
          }
          {
              "lastErrorObject": {
                  "updatedExisting": true,
                  "n": 1
              },
              "value": {
                  "_id": {
                      "$oid": "56562a99d13e6d86239c7b00"
                  },
                  "age": 35,
                  "firstname": "Zlatan",
                  "goals": 342,
                  "lastname": "Ibrahimovic",
                  "profession": "Football player",
                  "position": "striker"
              },
              "ok": 1
          }
          {
              "lastErrorObject": {
                  "updatedExisting": true,
                  "n": 1
              },
              "value": {
                  "_id": {
                      "$oid": "56562a99d13e6d86239c7b00"
                  },
                  "goals": 343
              },
              "ok": 1
          }
          {
              "lastErrorObject": {
                  "updatedExisting": true,
                  "n": 1
              },
              "value": {
                  "_id": {
                      "$oid": "56562a99d13e6d86239c7b00"
                  },
                  "age": 35,
                  "firstname": "Zlatan",
                  "goals": 343,
                  "lastname": "Ibrahimovic",
                  "profession": "Football player",
                  "position": "striker",
                  "author": true
              },
              "ok": 1
          }

   mongoc_gridfs_file_list_t
   Synopsis
          #include <mongoc.h>

          typedef struct _mongoc_gridfs_file_list_t mongoc_gridfs_file_list_t;

   Description
       mongoc_gridfs_file_list_t provides a gridfs file list  abstraction.   It  provides  iteration  and  basic
       marshalling on top of a regular mongoc_collection_find_with_opts() style query. In interface, it's styled
       after mongoc_cursor_t.

   Example
          mongoc_gridfs_file_list_t *list;
          mongoc_gridfs_file_t *file;

          list = mongoc_gridfs_find (gridfs, query);

          while ((file = mongoc_gridfs_file_list_next (list))) {
             do_something (file);

             mongoc_gridfs_file_destroy (file);
          }

          mongoc_gridfs_file_list_destroy (list);

   mongoc_gridfs_file_opt_t
   Synopsis
          typedef struct {
             const char *md5;
             const char *filename;
             const char *content_type;
             const bson_t *aliases;
             const bson_t *metadata;
             uint32_t chunk_size;
          } mongoc_gridfs_file_opt_t;

   Description
       This structure contains options that can be set on a mongoc_gridfs_file_t. It  can  be  used  by  various
       functions when creating a new gridfs file.

   mongoc_gridfs_file_t
   Synopsis
          typedef struct _mongoc_gridfs_file_t mongoc_gridfs_file_t;

   Description
       This structure provides a MongoDB GridFS file abstraction. It provides several APIs.

       • readv, writev, seek, and tell.

       • General file metadata such as filename and length.

       • GridFS metadata such as md5, filename, content_type, aliases, metadata, chunk_size, and upload_date.

   Thread Safety
       This structure is NOT thread-safe and should only be used from one thread at a time.

   Relatedmongoc_client_tmongoc_gridfs_tmongoc_gridfs_file_list_tmongoc_gridfs_file_opt_t

   mongoc_gridfs_t
   Synopsis
          #include <mongoc.h>

          typedef struct _mongoc_gridfs_t mongoc_gridfs_t;

   Description
       mongoc_gridfs_t  provides  a  MongoDB  gridfs  implementation. The system as a whole is made up of gridfs
       objects, which contain gridfs_files and gridfs_file_lists.  Essentially, a basic file system API.

       There are extensive caveats about the kind of use cases gridfs  is  practical  for.  In  particular,  any
       writing  after  initial  file  creation  is  likely  to  both  break  any concurrent readers and be quite
       expensive. That said, this implementation does allow for arbitrary writes to existing gridfs object, just
       use them with caution.

       mongoc_gridfs  also  integrates  tightly  with  the  mongoc_stream_t  abstraction,  which  provides  some
       convenient wrapping for file creation and reading/writing.  It can be used without, but its worth looking
       to see if your problem can fit that model.

       WARNING:
          mongoc_gridfs_t  does not support read preferences. In a replica set, GridFS queries are always routed
          to the primary.

   Thread Safety
       mongoc_gridfs_t is  NOT  thread-safe  and  should  only  be  used  in  the  same  thread  as  the  owning
       mongoc_client_t.

   Lifecycle
       It is an error to free a mongoc_gridfs_t before freeing all related instances of mongoc_gridfs_file_t and
       mongoc_gridfs_file_list_t.

   Example
       example-gridfs.c.INDENT 0.0

          #include <assert.h>
          #include <mongoc.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include <fcntl.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_gridfs_t *gridfs;
             mongoc_gridfs_file_t *file;
             mongoc_gridfs_file_list_t *list;
             mongoc_gridfs_file_opt_t opt = {0};
             mongoc_client_t *client;
             mongoc_stream_t *stream;
             bson_t filter;
             bson_t opts;
             bson_t child;
             bson_error_t error;
             ssize_t r;
             char buf[4096];
             mongoc_iovec_t iov;
             const char *filename;
             const char *command;
             bson_value_t id;

             if (argc < 2) {
                fprintf (stderr, "usage - %s command ...\n", argv[0]);
                return 1;
             }

             mongoc_init ();

             iov.iov_base = (void *) buf;
             iov.iov_len = sizeof buf;

             /* connect to localhost client */
             client =
                mongoc_client_new ("mongodb://127.0.0.1:27017/?appname=gridfs-example");
             assert (client);
             mongoc_client_set_error_api (client, 2);

             /* grab a gridfs handle in test prefixed by fs */
             gridfs = mongoc_client_get_gridfs (client, "test", "fs", &error);
             assert (gridfs);

             command = argv[1];
             filename = argv[2];

             if (strcmp (command, "read") == 0) {
                if (argc != 3) {
                   fprintf (stderr, "usage - %s read filename\n", argv[0]);
                   return 1;
                }
                file = mongoc_gridfs_find_one_by_filename (gridfs, filename, &error);
                assert (file);

                stream = mongoc_stream_gridfs_new (file);
                assert (stream);

                for (;;) {
                   r = mongoc_stream_readv (stream, &iov, 1, -1, 0);

                   assert (r >= 0);

                   if (r == 0) {
                      break;
                   }

                   if (fwrite (iov.iov_base, 1, r, stdout) != r) {
                      MONGOC_ERROR ("Failed to write to stdout. Exiting.\n");
                      exit (1);
                   }
                }

                mongoc_stream_destroy (stream);
                mongoc_gridfs_file_destroy (file);
             } else if (strcmp (command, "list") == 0) {
                bson_init (&filter);

                bson_init (&opts);
                bson_append_document_begin (&opts, "sort", -1, &child);
                BSON_APPEND_INT32 (&child, "filename", 1);
                bson_append_document_end (&opts, &child);

                list = mongoc_gridfs_find_with_opts (gridfs, &filter, &opts);

                bson_destroy (&filter);
                bson_destroy (&opts);

                while ((file = mongoc_gridfs_file_list_next (list))) {
                   const char *name = mongoc_gridfs_file_get_filename (file);
                   printf ("%s\n", name ? name : "?");

                   mongoc_gridfs_file_destroy (file);
                }

                mongoc_gridfs_file_list_destroy (list);
             } else if (strcmp (command, "write") == 0) {
                if (argc != 4) {
                   fprintf (stderr, "usage - %s write filename input_file\n", argv[0]);
                   return 1;
                }

                stream = mongoc_stream_file_new_for_path (argv[3], O_RDONLY, 0);
                assert (stream);

                opt.filename = filename;

                /* the driver generates a file_id for you */
                file = mongoc_gridfs_create_file_from_stream (gridfs, stream, &opt);
                assert (file);

                id.value_type = BSON_TYPE_INT32;
                id.value.v_int32 = 1;

                /* optional: the following method specifies a file_id of any
                   BSON type */
                if (!mongoc_gridfs_file_set_id (file, &id, &error)) {
                   fprintf (stderr, "%s\n", error.message);
                   return 1;
                }

                mongoc_gridfs_file_save (file);
                mongoc_gridfs_file_destroy (file);
             } else {
                fprintf (stderr, "Unknown command");
                return 1;
             }

             mongoc_gridfs_destroy (gridfs);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

   mongoc_host_list_t
   Synopsis
          typedef struct {
             mongoc_host_list_t *next;
             char host[BSON_HOST_NAME_MAX + 1];
             char host_and_port[BSON_HOST_NAME_MAX + 7];
             uint16_t port;
             int family;
             void *padding[4];
          } mongoc_host_list_t;

   Description
       The host and port of a MongoDB server. Can be part of a linked list: for  example  the  return  value  of
       mongoc_uri_get_hosts when multiple hosts are provided in the MongoDB URI.

   See Also
       mongoc_uri_get_hosts and mongoc_cursor_get_host.

   mongoc_index_opt_geo_t
   Synopsis
          #include <mongoc.h>

          typedef struct {
             uint8_t twod_sphere_version;
             uint8_t twod_bits_precision;
             double twod_location_min;
             double twod_location_max;
             double haystack_bucket_size;
             uint8_t *padding[32];
          } mongoc_index_opt_geo_t;

   Description
       This structure contains the options that may be used for tuning a GEO index.

   See Also
       mongoc_index_opt_t

       mongoc_index_opt_wt_t

   mongoc_index_opt_t
   Synopsis
          #include <mongoc.h>

          typedef struct {
             bool is_initialized;
             bool background;
             bool unique;
             const char *name;
             bool drop_dups;
             bool sparse;
             int32_t expire_after_seconds;
             int32_t v;
             const bson_t *weights;
             const char *default_language;
             const char *language_override;
             mongoc_index_opt_geo_t *geo_options;
             mongoc_index_opt_storage_t *storage_options;
             const bson_t *partial_filter_expression;
             const bson_t *collation;
             void *padding[4];
          } mongoc_index_opt_t;

   Deprecated
       This structure is deprecated and should not be used in new code. See create-indexes.

   Description
       This structure contains the options that may be used for tuning a specific index.

       See the createIndexes documentations in the MongoDB manual for descriptions of individual options.

       NOTE:
          dropDups is deprecated as of MongoDB version 3.0.0.  This option is silently ignored by the server and
          unique index builds using this option will fail if a duplicate value is detected.

   Example
          {
             bson_t keys;
             bson_error_t error;
             mongoc_index_opt_t opt;
             mongoc_index_opt_geo_t geo_opt;

             mongoc_index_opt_init (&opt);
             mongoc_index_opt_geo_init (&geo_opt);

             bson_init (&keys);
             BSON_APPEND_UTF8 (&keys, "location", "2d");

             geo_opt.twod_location_min = -123;
             geo_opt.twod_location_max = +123;
             geo_opt.twod_bits_precision = 30;
             opt.geo_options = &geo_opt;

             collection = mongoc_client_get_collection (client, "test", "geo_test");
             if (mongoc_collection_create_index (collection, &keys, &opt, &error)) {
                /* Successfully created the geo index */
             }
             bson_destroy (&keys);
             mongoc_collection_destroy (&collection);
          }

   See Also
       mongoc_index_opt_geo_t

       mongoc_index_opt_wt_t

   mongoc_index_opt_wt_t
   Synopsis
          #include <mongoc.h>

          typedef struct {
             mongoc_index_opt_storage_t base;
             const char *config_str;
             void *padding[8];
          } mongoc_index_opt_wt_t;

   Description
       This structure contains the options that may be used for tuning a WiredTiger specific index.

   See Also
       mongoc_index_opt_t

       mongoc_index_opt_geo_t

   mongoc_insert_flags_t
       Flags for insert operations

   Synopsis
          typedef enum {
             MONGOC_INSERT_NONE = 0,
             MONGOC_INSERT_CONTINUE_ON_ERROR = 1 << 0,
          } mongoc_insert_flags_t;

          #define MONGOC_INSERT_NO_VALIDATE (1U << 31)

   Description
       These flags correspond to the MongoDB wire protocol. They may be bitwise or'd together. They  may  modify
       how an insert happens on the MongoDB server.

   Flag Values
                       ┌────────────────────────────────┬───────────────────────────────────────┐
                       │MONGOC_INSERT_NONE              │ Specify no insert flags.              │
                       ├────────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_INSERT_CONTINUE_ON_ERROR │ Continue inserting documents from the │
                       │                                │ insertion  set  even  if  one  insert │
                       │                                │ fails.                                │
                       ├────────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_INSERT_NO_VALIDATE       │ Do  not  validate insertion documents │
                       │                                │ before    performing    an    insert. │
                       │                                │ Validation  can be expensive, so this │
                       │                                │ can save some time if you  know  your │
                       │                                │ documents are already valid.          │
                       └────────────────────────────────┴───────────────────────────────────────┘

   mongoc_iovec_t
   Synopsis
   Synopsis
          #include <mongoc.h>

          #ifdef _WIN32
          typedef struct {
             u_long iov_len;
             char *iov_base;
          } mongoc_iovec_t;
          #else
          typedef struct iovec mongoc_iovec_t;
          #endif

       The  mongoc_iovec_t  structure  is  a  portability  abstraction  for  consumers  of  the  mongoc_stream_t
       interfaces. It allows for scatter/gather I/O through the socket subsystem.

       WARNING:
          When writing portable code, beware of the ordering of iov_len and iov_base as they  are  different  on
          various platforms. Therefore, you should not use C initializers for initialization.

   mongoc_matcher_t
       Client-side document matching abstraction

   Synopsis
          typedef struct _mongoc_matcher_t mongoc_matcher_t;

       mongoc_matcher_t provides a reduced-interface for client-side matching of BSON documents.

       It can perform the basics such as $in, $nin, $eq, $neq, $gt, $gte, $lt, and $lte.

       WARNING:
          mongoc_matcher_t  does  not  currently  support the full spectrum of query operations that the MongoDB
          server supports.

   Deprecated
       WARNING:
          mongoc_matcher_t is deprecated and will be removed in version 2.0.

   Example
       Filter a sequence of BSON documents from STDIN based on a query.INDENT 0.0

          #include <bcon.h>
          #include <bson.h>
          #include <mongoc.h>
          #include <stdio.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_matcher_t *matcher;
             bson_reader_t *reader;
             const bson_t *bson;
             bson_t *spec;
             char *str;
             int fd;

             mongoc_init ();

          #ifdef _WIN32
             fd = fileno (stdin);
          #else
             fd = STDIN_FILENO;
          #endif

             reader = bson_reader_new_from_fd (fd, false);

             spec = BCON_NEW ("hello", "world");
             matcher = mongoc_matcher_new (spec, NULL);

             while ((bson = bson_reader_read (reader, NULL))) {
                if (mongoc_matcher_match (matcher, bson)) {
                   str = bson_as_canonical_extended_json (bson, NULL);
                   printf ("%s\n", str);
                   bson_free (str);
                }
             }

             bson_reader_destroy (reader);
             bson_destroy (spec);

             mongoc_cleanup ();

             return 0;
          }

   mongoc_query_flags_t
       Flags for query operations

   Synopsis
          typedef enum {
             MONGOC_QUERY_NONE = 0,
             MONGOC_QUERY_TAILABLE_CURSOR = 1 << 1,
             MONGOC_QUERY_SLAVE_OK = 1 << 2,
             MONGOC_QUERY_OPLOG_REPLAY = 1 << 3,
             MONGOC_QUERY_NO_CURSOR_TIMEOUT = 1 << 4,
             MONGOC_QUERY_AWAIT_DATA = 1 << 5,
             MONGOC_QUERY_EXHAUST = 1 << 6,
             MONGOC_QUERY_PARTIAL = 1 << 7,
          } mongoc_query_flags_t;

   Description
       These flags correspond to the MongoDB wire protocol. They may be bitwise or'd together. They  may  modify
       how a query is performed in the MongoDB server.

   Flag Values
                       ┌───────────────────────────────┬───────────────────────────────────────┐
                       │MONGOC_QUERY_NONE              │ Specify no query flags.               │
                       ├───────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_QUERY_TAILABLE_CURSOR   │ Cursor  will  not  be closed when the │
                       │                               │ last  data  is  retrieved.  You   can │
                       │                               │ resume this cursor later.             │
                       ├───────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_QUERY_SLAVE_OK          │ Allow    query    of    replica   set │
                       │                               │ secondaries.                          │
                       ├───────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_QUERY_OPLOG_REPLAY      │ Used internally by MongoDB.           │
                       ├───────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_QUERY_NO_CURSOR_TIMEOUT │ The server normally times out an idle │
                       │                               │ cursor after an inactivity period (10 │
                       │                               │ minutes). This prevents that.         │
                       ├───────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_QUERY_AWAIT_DATA        │ Use                              with │
                       │                               │ MONGOC_QUERY_TAILABLE_CURSOR.   Block │
                       │                               │ rather than returning no data.  After │
                       │                               │ a period, time out.                   │
                       └───────────────────────────────┴───────────────────────────────────────┘

                       │MONGOC_QUERY_EXHAUST           │ Stream  the  data  down full blast in │
                       │                               │ multiple "reply" packets. Faster when │
                       │                               │ you  are  pulling  down a lot of data │
                       │                               │ and you know you want to retrieve  it │
                       │                               │ all.                                  │
                       ├───────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_QUERY_PARTIAL           │ Get  partial  results  from mongos if │
                       │                               │ some  shards  are  down  (instead  of │
                       │                               │ throwing an error).                   │
                       └───────────────────────────────┴───────────────────────────────────────┘

   mongoc_rand
       MongoDB Random Number Generator

   Synopsis
          void
          mongoc_rand_add (const void *buf, int num, doubel entropy);

          void
          mongoc_rand_seed (const void *buf, int num);

          int
          mongoc_rand_status (void);

   Description
       The  mongoc_rand  family  of  functions provide access to the low level randomness primitives used by the
       MongoDB C Driver.  In particular, they control the creation  of  cryptographically  strong  pseudo-random
       bytes required by some security mechanisms.

       While  we  can  usually  pull  enough  entropy from the environment, you may be required to seed the PRNG
       manually depending on your OS, hardware and other entropy consumers running on the same system.

   Entropy
       mongoc_rand_add and mongoc_rand_seed allow the user to directly provide entropy.  They differ insofar  as
       mongoc_rand_seed  requires  that  each  bit provided is fully random.  mongoc_rand_add allows the user to
       specify the degree of randomness in the provided bytes as well.

   Status
       The mongoc_rand_status function allows the user to check the status of the mongoc PRNG.  This can be used
       to guarantee sufficient entropy at program startup, rather than waiting for runtime errors to occur.

   mongoc_read_concern_t
       Read Concern abstraction

   Synopsis
       New in MongoDB 3.2.

       The  mongoc_read_concern_t  allows  clients  to choose a level of isolation for their reads. The default,
       MONGOC_READ_CONCERN_LEVEL_LOCAL, is right for the great majority of applications.

       You can specify a read concern on connection objects, database objects, or collection objects.

       See readConcern on the MongoDB website for more information.

       Read Concern is only sent to MongoDB when it has explicitly been set by mongoc_read_concern_set_level  to
       anything other than NULL.

   Read Concern Levels
            ┌───────────────────────────────────────┬─────────────────────────────┬───────────────────────┐
            │Macro                                  │ Description                 │ First MongoDB version │
            ├───────────────────────────────────────┼─────────────────────────────┼───────────────────────┤
            │MONGOC_READ_CONCERN_LEVEL_LOCAL        │ Level "local", the default. │ 3.2                   │
            ├───────────────────────────────────────┼─────────────────────────────┼───────────────────────┤
            │MONGOC_READ_CONCERN_LEVEL_MAJORITY     │ Level "majority".           │ 3.2                   │
            ├───────────────────────────────────────┼─────────────────────────────┼───────────────────────┤
            │MONGOC_READ_CONCERN_LEVEL_LINEARIZABLE │ Level "linearizable".       │ 3.4                   │
            └───────────────────────────────────────┴─────────────────────────────┴───────────────────────┘

       For the sake of compatibility with future versions of MongoDB, mongoc_read_concern_set_level  allows  any
       string, not just this list of known read concern levels.

       See  Read  Concern  Levels  in  the MongoDB manual for more information about the individual read concern
       levels.

   mongoc_read_mode_t
       Read Preference Modes

   Synopsis
          typedef enum {
             MONGOC_READ_PRIMARY = (1 << 0),
             MONGOC_READ_SECONDARY = (1 << 1),
             MONGOC_READ_PRIMARY_PREFERRED = (1 << 2) | MONGOC_READ_PRIMARY,
             MONGOC_READ_SECONDARY_PREFERRED = (1 << 2) | MONGOC_READ_SECONDARY,
             MONGOC_READ_NEAREST = (1 << 3) | MONGOC_READ_SECONDARY,
          } mongoc_read_mode_t;

   Description
       This enum describes how reads should be dispatched. The default is MONGOC_READ_PRIMARY.

       Please see the MongoDB website for a description of Read Preferences.

   mongoc_read_prefs_t
       A read preference abstraction

   Synopsis
       mongoc_read_prefs_t provides an abstraction on top of the MongoDB connection read  prefences.  It  allows
       for hinting to the driver which nodes in a replica set should be accessed first.

       You  can  specify  a read preference mode on connection objects, database objects, collection objects, or
       per-operation.  Generally, it makes the most sense to stick with the global default, MONGOC_READ_PRIMARY.
       All of the other modes come with caveats that won't be covered in great detail here.

   Read Modes
                       ┌────────────────────────────────┬───────────────────────────────────────┐
                       │MONGOC_READ_PRIMARY             │ Default  mode.  All  operations  read │
                       │                                │ from the current replica set primary. │
                       ├────────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_READ_SECONDARY           │ All operations read  from  among  the │
                       │                                │ nearest   secondary  members  of  the │
                       │                                │ replica set.                          │
                       ├────────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_READ_PRIMARY_PREFERRED   │ In most situations,  operations  read │
                       │                                │ from   the   primary  but  if  it  is │
                       │                                │ unavailable,  operations  read   from │
                       │                                │ secondary members.                    │
                       ├────────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_READ_SECONDARY_PREFERRED │ In  most  situations, operations read │
                       │                                │ from  among  the  nearest   secondary │
                       │                                │ members,  but  if  no secondaries are │
                       │                                │ available, operations read  from  the │
                       │                                │ primary.                              │
                       ├────────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_READ_NEAREST             │ Operations   read   from   among  the │
                       │                                │ nearest members of the  replica  set, │
                       │                                │ irrespective of the member's type.    │
                       └────────────────────────────────┴───────────────────────────────────────┘

   Tag Sets
       Tag  sets  allow  you  to specify custom read preferences and write concerns so that your application can
       target operations to specific members.

       Custom read preferences and write concerns  evaluate  tags  sets  in  different  ways:  read  preferences
       consider  the  value of a tag when selecting a member to read from. while write concerns ignore the value
       of a tag to when selecting a member except to consider whether or not the value is unique.

       You can specify tag sets with the following read preference modes:

       • primaryPreferred

       • secondary

       • secondaryPreferred

       • nearest

       Tags are not compatible with MONGOC_READ_PRIMARY and, in general, only apply when selecting  a  secondary
       member  of  a set for a read operation. However, the nearest read mode, when combined with a tag set will
       select the nearest member that matches the specified tag set, which may be a primary or secondary.

       Tag sets are represented as a comma-separated list of colon-separated key-value pairs when provided as  a
       connection string, e.g. dc:ny,rack:1.

       To specify a list of tag sets, using multiple readPreferenceTags, e.g.

          readPreferenceTags=dc:ny,rack:1;readPreferenceTags=dc:ny;readPreferenceTags=

       Note the empty value for the last one, which means match any secondary as a last resort.

       Order matters when using multiple readPreferenceTags.

       Tag Sets can also be configured using mongoc_read_prefs_set_tags.

       All  interfaces  use  the  same  member  selection  logic  to  choose  the member to which to direct read
       operations, basing the choice on read preference mode and tag sets.

   Max Staleness
       When connected to replica set running MongoDB 3.4 or later, the driver estimates the  staleness  of  each
       secondary based on lastWriteDate values provided in server isMaster responses.

       Max Staleness is the maximum replication lag in seconds (wall clock time) that a secondary can suffer and
       still be eligible for reads. The default is MONGOC_NO_MAX_STALENESS,  which  disables  staleness  checks.
       Otherwise, it must be a positive integer at least MONGOC_SMALLEST_MAX_STALENESS_SECONDS (90 seconds).

       Max  Staleness  is  also  supported by sharded clusters of replica sets if all servers run MongoDB 3.4 or
       later.

   mongoc_remove_flags_t
       Flags for deletion operations

   Synopsis
          typedef enum {
             MONGOC_REMOVE_NONE = 0,
             MONGOC_REMOVE_SINGLE_REMOVE = 1 << 0,
          } mongoc_remove_flags_t;

   Description
       These flags correspond to the MongoDB wire protocol. They may be bitwise or'd together. They  may  change
       the number of documents that are removed during a remove command.

   Flag Values
                         ┌────────────────────────────┬───────────────────────────────────────┐
                         │MONGOC_REMOVE_NONE          │ Specify   no   removal   flags.   All │
                         │                            │ matching documents will be removed.   │
                         ├────────────────────────────┼───────────────────────────────────────┤
                         │MONGOC_REMOVE_SINGLE_REMOVE │ Only  remove   the   first   matching │
                         │                            │ document from the selector.           │
                         └────────────────────────────┴───────────────────────────────────────┘

   mongoc_reply_flags_t
       Flags from server replies

   Synopsis
          typedef enum {
             MONGOC_REPLY_NONE = 0,
             MONGOC_REPLY_CURSOR_NOT_FOUND = 1 << 0,
             MONGOC_REPLY_QUERY_FAILURE = 1 << 1,
             MONGOC_REPLY_SHARD_CONFIG_STALE = 1 << 2,
             MONGOC_REPLY_AWAIT_CAPABLE = 1 << 3,
          } mongoc_reply_flags_t;

   Description
       These flags correspond to the wire protocol. They may be bitwise or'd together.

   Flag Values
                       ┌────────────────────────────────┬───────────────────────────────────────┐
                       │MONGOC_REPLY_NONE               │ No flags set.                         │
                       └────────────────────────────────┴───────────────────────────────────────┘

                       │MONGOC_REPLY_CURSOR_NOT_FOUND   │ No  matching  cursor was found on the │
                       │                                │ server.                               │
                       ├────────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_REPLY_QUERY_FAILURE      │ The  query  failed  or  was  invalid. │
                       │                                │ Error document has been provided.     │
                       ├────────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_REPLY_SHARD_CONFIG_STALE │ Shard config is stale.                │
                       ├────────────────────────────────┼───────────────────────────────────────┤
                       │MONGOC_REPLY_AWAIT_CAPABLE      │ If  the returned cursor is capable of │
                       │                                │ MONGOC_QUERY_AWAIT_DATA.              │
                       └────────────────────────────────┴───────────────────────────────────────┘

   mongoc_server_description_t
       Server description

   Synopsis
          #include <mongoc.h>
          typedef struct _mongoc_server_description_t mongoc_server_description_t

       mongoc_server_description_t holds information about a mongod or mongos the driver is connected to.

       See also mongoc_client_get_server_descriptions().

   Lifecycle
       Clean up with mongoc_server_description_destroy().

   mongoc_session_opt_t
          #include <mongoc.h>

          typedef struct _mongoc_session_opt_t mongoc_session_opt_t;

   Synopsis
       Start a session with mongoc_client_start_session, use the session for a sequence of operations, then free
       it with mongoc_client_session_destroy(). A session must be freed before the mongoc_client_t it came from.

       By  default,  sessions  are causally consistent. To disable causal consistency, before starting a session
       create       a       mongoc_session_opt_t       with       mongoc_session_opts_new()       and       call
       mongoc_session_opts_set_causal_consistency(), then free the struct with mongoc_session_opts_destroy.

       Unacknowledged   writes   are  not  causally  consistent.  If  you  execute  a  write  operation  with  a
       mongoc_write_concern_t on which you have called mongoc_write_concern_set_w with a value of 0,  the  write
       does not participate in causal consistency.

       A  mongoc_client_session_t  must  be  used  by  only  one  thread  at  a  time.  Due  to session pooling,
       mongoc_client_start_session may return a session that has been idle for some time  and  is  about  to  be
       closed  after  its idle timeout. Use the session within one minute of acquiring it to refresh the session
       and avoid a timeout.

       See the example code for mongoc_session_opts_set_causal_consistency.

   mongoc_socket_t
       Portable socket abstraction

   Synopsis
          #include <mongoc.h>

          typedef struct _mongoc_socket_t mongoc_socket_t

   Synopsis
       This structure provides a socket  abstraction  that  is  friendlier  for  portability  than  BSD  sockets
       directly. Inconsistencies between Linux, various BSDs, Solaris, and Windows are handled here.

   mongoc_ssl_opt_t
   Synopsis
          typedef struct {
             const char *pem_file;
             const char *pem_pwd;
             const char *ca_file;
             const char *ca_dir;
             const char *crl_file;
             bool weak_cert_validation;
             bool allow_invalid_hostname;
             void *padding[7];
          } mongoc_ssl_opt_t;

   Description
       This structure is used to set the SSL options for a mongoc_client_t or mongoc_client_pool_t.

       Beginning  in version 1.2.0, once a pool or client has any SSL options set, all connections use SSL, even
       if ssl=true is omitted from the MongoDB URI.  Before,  SSL  options  were  ignored  unless  ssl=true  was
       included in the URI.

       As  of  1.4.0,  the  mongoc_client_pool_set_ssl_opts and mongoc_client_set_ssl_opts will not only shallow
       copy the struct, but will also copy the const char*. It is therefore no longer needed to  make  sure  the
       values remain valid after setting them.

   Configuration through URI Options
       Most of the configurable options can be using the Connection URI.

                              ┌───────────────────────┬─────────────────────────────────┐
                              │mongoc_ssl_opt_t keyURI key                         │
                              ├───────────────────────┼─────────────────────────────────┤
                              │pem_file               │ sslClientCertificateKeyFile     │
                              ├───────────────────────┼─────────────────────────────────┤
                              │pem_pwd                │ sslClientCertificateKeyPassword │
                              ├───────────────────────┼─────────────────────────────────┤
                              │ca_file                │ sslCertificateAuthorityFile     │
                              ├───────────────────────┼─────────────────────────────────┤
                              │weak_cert_validation   │ sslAllowInvalidCertificates     │
                              ├───────────────────────┼─────────────────────────────────┤
                              │allow_invalid_hostname │ sslAllowInvalidHostnames        │
                              └───────────────────────┴─────────────────────────────────┘

   Client Authentication
       When  MongoDB  is  started  with  SSL  enabled, it will by default require the client to provide a client
       certificate issued by a certificate authority specified by --sslCAFile, or an authority  trusted  by  the
       native certificate store in use on the server.

       To  provide  the  client  certificate,  the  user  must  configure the pem_file to point at a PEM armored
       certificate.

          mongoc_ssl_opt_t ssl_opts = {0};

          ssl_opts.pem_file = "/path/to/client-certificate.pem"

          /* Then set the client ssl_opts, when using a single client mongoc_client_t */
          mongoc_client_pool_set_ssl_opts (pool, &ssl_opts);

          /* or, set the pool ssl_opts, when using a the thread safe mongoc_client_pool_t */
          mongoc_client_set_ssl_opts (client, &ssl_opts);

   Server Certificate Verification
       The MongoDB C Driver will automatically verify the validity of the server certificate, such as issued  by
       configured Certificate Authority, hostname validation, and expiration.

       To  overwrite  this  behaviour,  it  is  possible  to disable hostname validation, and/or allow otherwise
       invalid   certificates.   This   behaviour   is   controlled   using   the   allow_invalid_hostname   and
       weak_cert_validation  fields.  By  default,  both are set to false. It is not recommended to change these
       defaults as it exposes the client to Man In The Middle attacks (when allow_invalid_hostname is  set)  and
       otherwise invalid certificates when weak_cert_validation is set to true.

   Native TLS Support on Linux (OpenSSL)
       The  MongoDB  C  Driver  supports  the  dominating  TLS library (OpenSSL) and crypto libraries (OpenSSL's
       libcrypto) on Linux and Unix platforms.

       Support for OpenSSL 1.1 and later was added in 1.4.0.

       When compiled against OpenSSL, the driver will attempt to load the system default certificate  store,  as
       configured by the distribution, if the ca_file and ca_dir are not set.

   LibreSSL / libtls
       The MongoDB C Driver supports LibreSSL through the use of OpenSSL compatibility checks when configured to
       compile against openssl. It also supports the  new  libtls  library  when  configured  to  build  against
       libressl.

   Native TLS Support on Windows (Secure Channel)
       The  MongoDB  C  Driver  supports  the  Windows native TLS library (Secure Channel, or SChannel), and its
       native crypto library (Cryptography API: Next Generation, or CNG).

       When compiled against the Windows native libraries, the ca_dir option is not supported, and will issue an
       error if used.

       Encrypted  PEM  files  (e.g.,  requiring  pem_pwd)  are also not supported, and will result in error when
       attempting to load them.

       When ca_file is provided, the driver will only allow server certificates  issued  by  the  authority  (or
       authorities)  provided.  When  no  ca_file is provided, the driver will look up the Certificate Authority
       using the System Local Machine Root certificate store to confirm the provided certificate.

       When crl_file is provided, the driver will import the revocation list to the System  Local  Machine  Root
       certificate store.

   Native TLS Support on Mac OS X / Darwin (Secure Transport)
       The  MongoDB C Driver supports the Darwin (OS X, macOS, iOS, etc.) native TLS library (Secure Transport),
       and its native crypto library (Common Crypto, or CC).

       When compiled against Secure Transport, the ca_dir option is not supported, and will issue  an  error  if
       used.

       When  ca_file  is  provided,  the  driver will only allow server certificates issued by the authority (or
       authorities) provided. When no ca_file is provided, the driver will use the  Certificate  Authorities  in
       the currently unlocked keychains.

   See Also
       • mongoc_client_set_ssl_opts

       • mongoc_client_pool_set_ssl_opts

   mongoc_stream_buffered_t
   Synopsis
          typedef struct _mongoc_stream_buffered_t mongoc_stream_buffered_t;

   Description
       mongoc_stream_buffered_t  should be considered a subclass of mongoc_stream_t. It performs buffering on an
       underlying stream.

   See Also
       mongoc_stream_buffered_new()

       mongoc_stream_destroy()

   mongoc_stream_file_t
   Synopsis
          typedef struct _mongoc_stream_file_t mongoc_stream_file_t

       mongoc_stream_file_t is a mongoc_stream_t subclass for working with standard UNIX style file-descriptors.

   mongoc_stream_socket_t
   Synopsis
          typedef struct _mongoc_stream_socket_t mongoc_stream_socket_t

       mongoc_stream_socket_t should be considered a subclass of mongoc_stream_t that works upon socket streams.

   mongoc_stream_t
   Synopsis
          typedef struct _mongoc_stream_t mongoc_stream_t

       mongoc_stream_t provides a generic streaming IO abstraction based on a struct of pointers interface.  The
       idea  is  to  allow  wrappers,  perhaps  other language drivers, to easily shim their IO system on top of
       mongoc_stream_t.

       The API for the stream abstraction is currently private and non-extensible.

   Stream Types
       There are a number of built in stream types that  come  with  mongoc.  The  default  configuration  is  a
       buffered unix stream.  If SSL is in use, that in turn is wrapped in a tls stream.

   See Also
       mongoc_stream_buffered_t

       mongoc_stream_file_t

       mongoc_stream_socket_t

       mongoc_stream_tls_t

   mongoc_stream_tls_t
   Synopsis
          typedef struct _mongoc_stream_tls_t mongoc_stream_tls_t

       mongoc_stream_tls_t is a mongoc_stream_t subclass for working with OpenSSL TLS streams.

   mongoc_topology_description_t
       Status of MongoDB Servers

   Synopsis
          typedef struct _mongoc_topology_description_t mongoc_topology_description_t;

       mongoc_topology_description_t is an opaque type representing the driver's knowledge of the MongoDB server
       or servers it is connected to.  Its API conforms to the SDAM Monitoring Specification.

       Applications receive a temporary reference to a mongoc_topology_description_t as a parameter to  an  SDAM
       Monitoring callback. See Introduction to Application Performance Monitoring.

   mongoc_update_flags_t
       Flags for update operations

   Synopsis
          typedef enum {
             MONGOC_UPDATE_NONE = 0,
             MONGOC_UPDATE_UPSERT = 1 << 0,
             MONGOC_UPDATE_MULTI_UPDATE = 1 << 1,
          } mongoc_update_flags_t;

          #define MONGOC_UPDATE_NO_VALIDATE (1U << 31)

   Description
       These  flags  correspond  to  the MongoDB wire protocol. They may be bitwise or'd together. The allow for
       modifying the way an update is performed in the MongoDB server.

   Flag Values
                         ┌───────────────────────────┬───────────────────────────────────────┐
                         │MONGOC_UPDATE_NONE         │ No update flags set.                  │
                         ├───────────────────────────┼───────────────────────────────────────┤
                         │MONGOC_UPDATE_UPSERT       │ If an upsert should be performed.     │
                         ├───────────────────────────┼───────────────────────────────────────┤
                         │MONGOC_UPDATE_MULTI_UPDATE │ If  more  than  a   single   matching │
                         │                           │ document   should   be   updated.  By │
                         │                           │ default only the  first  document  is │
                         │                           │ updated.                              │
                         ├───────────────────────────┼───────────────────────────────────────┤
                         │MONGOC_UPDATE_NO_VALIDATE  │ Do   not  perform  client  side  BSON │
                         │                           │ validations   when   performing    an │
                         │                           │ update. This is useful if you already │
                         │                           │ know your BSON documents are valid.   │
                         └───────────────────────────┴───────────────────────────────────────┘

   mongoc_uri_t
   Synopsis
          typedef struct _mongoc_uri_t mongoc_uri_t;

   Description
       mongoc_uri_t provides  an  abstraction  on  top  of  the  MongoDB  connection  URI  format.  It  provides
       standardized  parsing  as  well  as convenience methods for extracting useful information such as replica
       hosts or authorization information.

       See Connection String URI Reference on the MongoDB website for more information.

   Format
          mongodb[+srv]://                             <1>
             [username:password@]                      <2>
             host1                                     <3>
             [:port1]                                  <4>
             [,host2[:port2],...[,hostN[:portN]]]      <5>
             [/[database]                              <6>
             [?options]]                               <7>

       1. "mongodb" is the specifier of the MongoDB protocol. Use "mongodb+srv" with a single  service  name  in
          place of "host1" to specify the initial list of servers with an SRV record.

       2. An optional username and password.

       3. The  only  required  part  of  the  uri.   This specifies either a hostname, IP address or UNIX domain
          socket.

       4. An optional port number.  Defaults to :27017.

       5. Extra optional hosts and ports.  You would specify multiple hosts, for  example,  for  connections  to
          replica sets.

       6. The name of the database to authenticate if the connection string includes authentication credentials.
          If /database is not specified and the connection string includes credentials, defaults to the  'admin'
          database.

       7. Connection specific options.

       NOTE:
          Option names are case-insensitive

       The  MongoDB  C  Driver  exposes  constants for each supported connection option. These constants make it
       easier to discover connection options, but their string values can be used as well.

       For example, the following calls are equal.

          uri = mongoc_uri_new ("mongodb://localhost/?" MONGOC_URI_APPNAME "=applicationName");
          uri = mongoc_uri_new ("mongodb://localhost/?appname=applicationName");
          uri = mongoc_uri_new ("mongodb://localhost/?appName=applicationName");

   Replica Set Example
       To describe a connection to a replica set named 'test' with the following mongod hosts:

       • db1.example.com on port 27017db2.example.com on port 2500

       You would use a connection string that resembles the following.

          mongodb://db1.example.com,db2.example.com:2500/?replicaSet=test

   SRV Example
       If you have configured an SRV record with a name like  "_mongodb._tcp.server.example.com"  whose  records
       are a list of one or more MongoDB server hostnames, use a connection string like this:

          uri = mongoc_uri_new ("mongodb+srv://server.example.com/?replicaSet=rs&appName=applicationName");

       The  driver prefixes the service name with "_mongodb._tcp.", then performs a DNS SRV query to resolve the
       service name to one or more hostnames. If this query succeeds, the driver performs a DNS TXT query on the
       service name (without the "_mongodb._tcp" prefix) for additional URI options configured as TXT records.

       On  Unix,  the  MongoDB  C  Driver  relies  on  libresolv to look up SRV and TXT records. If libresolv is
       unavailable, then using a "mongodb+srv" URI will cause an error. If your libresolv lacks res_nsearch then
       the driver will fall back to res_search, which is not thread-safe.

   Connection Options
             ┌────────────────────────────────┬──────────────────────┬───────────────────────────────────┐
             │Constant                        │ Key                  │ Description                       │
             ├────────────────────────────────┼──────────────────────┼───────────────────────────────────┤
             │MONGOC_URI_RETRYWRITES          │ retrywrites          │ If  "true" and the server is      │
             │                                │                      │ a MongoDB 3.6+  replica  set      │
             │                                │                      │ or   sharded   cluster,  the      │
             │                                │                      │ driver  safely   retries   a      │
             │                                │                      │ write  that  failed due to a      │
             │                                │                      │ network error or replica set      │
             │                                │                      │ failover.    Only   inserts,      │
             │                                │                      │ updates of single documents,      │
             │                                │                      │ or    deletes    of   single      │
             │                                │                      │ documents are retried.            │
             └────────────────────────────────┴──────────────────────┴───────────────────────────────────┘

             │MONGOC_URI_APPNAME              │ appname              │ The client application name.      │
             │                                │                      │ This   value   is   used  by      │
             │                                │                      │ MongoDB   when    it    logs      │
             │                                │                      │ connection  information  and      │
             │                                │                      │ profile information, such as      │
             │                                │                      │ slow queries.                     │
             ├────────────────────────────────┼──────────────────────┼───────────────────────────────────┤
             │MONGOC_URI_SSL                  │ ssl                  │ {true|false},  indicating if      │
             │                                │                      │ SSL must be used. (See  also      │
             │                                │                      │ mongoc_client_set_ssl_opts        │
             │                                │                      │ and                               │
             │                                │                      │ mongoc_client_pool_set_ssl_opts.) │
             ├────────────────────────────────┼──────────────────────┼───────────────────────────────────┤
             │MONGOC_URI_COMPRESSORS          │ compressors          │ Comma    separated    list     of │
             │                                │                      │ compressors,  if  any,  to use to │
             │                                │                      │ compress   the   wire    protocol │
             │                                │                      │ messages.  Snappy  are  Zlib  are │
             │                                │                      │ optional build time dependencies, │
             │                                │                      │ and   enable   the  "snappy"  and │
             │                                │                      │ "zlib"    values    respectively. │
             │                                │                      │ Defaults     to     empty     (no │
             │                                │                      │ compressors).                     │
             ├────────────────────────────────┼──────────────────────┼───────────────────────────────────┤
             │MONGOC_URI_CONNECTTIMEOUTMS     │ connecttimeoutms     │ This  setting  applies   to   new │
             │                                │                      │ server  connections.  It  is also │
             │                                │                      │ used as the  socket  timeout  for │
             │                                │                      │ server  discovery  and monitoring │
             │                                │                      │ operations. The default is 10,000 │
             │                                │                      │ ms (10 seconds).                  │
             ├────────────────────────────────┼──────────────────────┼───────────────────────────────────┤
             │MONGOC_URI_SOCKETTIMEOUTMS      │ sockettimeoutms      │ The   time   in  milliseconds  to │
             │                                │                      │ attempt to send or receive  on  a │
             │                                │                      │ socket  before  the attempt times │
             │                                │                      │ out. The default  is  300,000  (5 │
             │                                │                      │ minutes).                         │
             ├────────────────────────────────┼──────────────────────┼───────────────────────────────────┤
             │MONGOC_URI_REPLICASET           │ replicaset           │ The  name of the Replica Set that │
             │                                │                      │ the driver should connect to.     │
             ├────────────────────────────────┼──────────────────────┼───────────────────────────────────┤
             │MONGOC_URI_ZLIBCOMPRESSIONLEVEL │ zlibcompressionlevel │ When  the  MONGOC_URI_COMPRESSORS │
             │                                │                      │ includes  "zlib"   this   options │
             │                                │                      │ configures  the  zlib compression │
             │                                │                      │ level, when the  zlib  compressor │
             │                                │                      │ is used to compress client data.  │
             └────────────────────────────────┴──────────────────────┴───────────────────────────────────┘

       Setting any of the *timeoutMS options above to 0 will be interpreted as "use the default value".

   Authentication Options
             ┌───────────────────────────────────┬─────────────────────────┬──────────────────────────────┐
             │Constant                           │ Key                     │ Description                  │
             ├───────────────────────────────────┼─────────────────────────┼──────────────────────────────┤
             │MONGOC_URI_AUTHMECHANISM           │ authmechanism           │ Specifies  the  mechanism to │
             │                                   │                         │ use when  authenticating  as │
             │                                   │                         │ the   provided   user.   See │
             │                                   │                         │ Authentication for supported │
             │                                   │                         │ values.                      │
             ├───────────────────────────────────┼─────────────────────────┼──────────────────────────────┤
             │MONGOC_URI_AUTHMECHANISMPROPERTIES │ authmechanismproperties │ Certain       authentication │
             │                                   │                         │ mechanisms  have  additional │
             │                                   │                         │ options    that    can    be │
             │                                   │                         │ configured.   These  options │
             │                                   │                         │ should be provided as  comma │
             │                                   │                         │ separated                    │
             │                                   │                         │ option_key:option_value pair │
             │                                   │                         │ and        provided       as │
             │                                   │                         │ authMechanismProperties.     │
             └───────────────────────────────────┴─────────────────────────┴──────────────────────────────┘

             │MONGOC_URI_AUTHSOURCE              │ authsource              │ The authSource  defines  the │
             │                                   │                         │ database that should be used │
             │                                   │                         │ to authenticate  to.  It  is │
             │                                   │                         │ unnecessary  to provide this │
             │                                   │                         │ option the database name  is │
             │                                   │                         │ the  same  as  the  database │
             │                                   │                         │ used in the URI.             │
             └───────────────────────────────────┴─────────────────────────┴──────────────────────────────┘

   Mechanism Properties
                ┌────────────────────────────────┬──────────────────────┬──────────────────────────────┐
                │Constant                        │ Key                  │ Description                  │
                ├────────────────────────────────┼──────────────────────┼──────────────────────────────┤
                │MONGOC_URI_CANONICALIZEHOSTNAME │ canonicalizehostname │ Use  the  canonical hostname │
                │                                │                      │ of the service, rather  than │
                │                                │                      │ its  configured  alias, when │
                │                                │                      │ authenticating          with │
                │                                │                      │ Cyrus-SASL Kerberos.         │
                ├────────────────────────────────┼──────────────────────┼──────────────────────────────┤
                │MONGOC_URI_GSSAPISERVICENAME    │ gssapiservicename    │ Use    alternative   service │
                │                                │                      │ name.   The    default    is │
                │                                │                      │ mongodb.                     │
                └────────────────────────────────┴──────────────────────┴──────────────────────────────┘

   SSL Options
     ┌───────────────────────────────────────────┬─────────────────────────────────┬──────────────────────────────┐
     │Constant                                   │ Key                             │ Description                  │
     ├───────────────────────────────────────────┼─────────────────────────────────┼──────────────────────────────┤
     │MONGOC_URI_SSLCLIENTCERTIFICATEKEYFILE     │ sslclientcertificatekeyfile     │ Path   to   PEM    formatted │
     │                                           │                                 │ Private Key, with its Public │
     │                                           │                                 │ Certificate concatenated  at │
     │                                           │                                 │ the end.                     │
     ├───────────────────────────────────────────┼─────────────────────────────────┼──────────────────────────────┤
     │MONGOC_URI_SSLCLIENTCERTIFICATEKEYPASSWORD │ sslclientcertificatekeypassword │ The password, if any, to use │
     │                                           │                                 │ to unlock encrypted  Private │
     │                                           │                                 │ Key.                         │
     ├───────────────────────────────────────────┼─────────────────────────────────┼──────────────────────────────┤
     │MONGOC_URI_SSLCERTIFICATEAUTHORITYFILE     │ sslcertificateauthorityfile     │ One,   or   a   bundle   of, │
     │                                           │                                 │ Certificate Authorities whom │
     │                                           │                                 │ should  be  considered to be │
     │                                           │                                 │ trusted.                     │
     ├───────────────────────────────────────────┼─────────────────────────────────┼──────────────────────────────┤
     │MONGOC_URI_SSLALLOWINVALIDCERTIFICATES     │ sslallowinvalidcertificates     │ Accept      and       ignore │
     │                                           │                                 │ certificate     verification │
     │                                           │                                 │ errors    (e.g.    untrusted │
     │                                           │                                 │ issuer, expired, etc etc)    │
     ├───────────────────────────────────────────┼─────────────────────────────────┼──────────────────────────────┤
     │MONGOC_URI_SSLALLOWINVALIDHOSTNAMES        │ sslallowinvalidhostnames        │ Ignore hostname verification │
     │                                           │                                 │ of the certificate (e.g. Man │
     │                                           │                                 │ In  The  Middle, using valid │
     │                                           │                                 │ certificate, but issued  for │
     │                                           │                                 │ another hostname)            │
     └───────────────────────────────────────────┴─────────────────────────────────┴──────────────────────────────┘

   Server Discovery, Monitoring, and Selection Options
       Clients  in  a mongoc_client_pool_t share a topology scanner that runs on a background thread. The thread
       wakes every heartbeatFrequencyMS (default 10 seconds) to scan all MongoDB servers in  parallel.  Whenever
       an  application  operation requires a server that is not known--for example, if there is no known primary
       and your application attempts an insert--the thread  rescans  all  servers  every  half-second.  In  this
       situation  the  pooled client waits up to serverSelectionTimeoutMS (default 30 seconds) for the thread to
       find   a   server   suitable   for   the   operation,    then    returns    an    error    with    domain
       MONGOC_ERROR_SERVER_SELECTION.

       Technically,  the total time an operation may wait while a pooled client scans the topology is controlled
       both by serverSelectionTimeoutMS and connectTimeoutMS. The longest wait occurs if the  last  scan  begins
       just  at the end of the selection timeout, and a slow or down server requires the full connection timeout
       before the client gives up.

       A non-pooled client is single-threaded.  Every  heartbeatFrequencyMS,  it  blocks  the  next  application
       operation  while  it does a parallel scan. This scan takes as long as needed to check the slowest server:
       roughly connectTimeoutMS. Therefore the  default  heartbeatFrequencyMS  for  single-threaded  clients  is
       greater than for pooled clients: 60 seconds.

       By  default, single-threaded (non-pooled) clients scan only once when an operation requires a server that
       is not known. If you attempt an insert and there is no known primary, the client checks all servers  once
       trying  to  find  it, then succeeds or returns an error with domain MONGOC_ERROR_SERVER_SELECTION. But if
       you set serverSelectionTryOnce to "false", the single-threaded client loops, checking all  servers  every
       half-second, until serverSelectionTimeoutMS.

       The  total  time an operation may wait for a single-threaded client to scan the topology is determined by
       connectTimeoutMS  in  the  try-once   case,   or   serverSelectionTimeoutMS   and   connectTimeoutMS   if
       serverSelectionTryOnce is set "false".

            ┌────────────────────────────────────┬──────────────────────────┬──────────────────────────────┐
            │Constant                            │ Key                      │ Description                  │
            ├────────────────────────────────────┼──────────────────────────┼──────────────────────────────┤
            │MONGOC_URI_HEARTBEATFREQUENCYMS     │ heartbeatfrequencyms     │ The interval between  server │
            │                                    │                          │ monitoring  checks. Defaults │
            │                                    │                          │ to 10,000ms (10 seconds)  in │
            │                                    │                          │ pooled      (multi-threaded) │
            │                                    │                          │ mode, 60,000ms (60  seconds) │
            │                                    │                          │ in      non-pooled      mode │
            │                                    │                          │ (single-threaded).           │
            ├────────────────────────────────────┼──────────────────────────┼──────────────────────────────┤
            │MONGOC_URI_SERVERSELECTIONTIMEOUTMS │ serverselectiontimeoutms │ A timeout in milliseconds to │
            │                                    │                          │ block for  server  selection │
            │                                    │                          │ before      throwing      an │
            │                                    │                          │ exception.  The  default  is │
            │                                    │                          │ 30,0000ms (30 seconds).      │
            ├────────────────────────────────────┼──────────────────────────┼──────────────────────────────┤
            │MONGOC_URI_SERVERSELECTIONTRYONCE   │ serverselectiontryonce   │ If  "true", the driver scans │
            │                                    │                          │ the  topology  exactly  once │
            │                                    │                          │ after    server    selection │
            │                                    │                          │ fails, then either selects a │
            │                                    │                          │ server  or returns an error. │
            │                                    │                          │ If it  is  false,  then  the │
            │                                    │                          │ driver  repeatedly  searches │
            │                                    │                          │ for a suitable server for up │
            │                                    │                          │ to  serverSelectionTimeoutMS │
            │                                    │                          │ milliseconds (pausing a half │
            │                                    │                          │ second   between  attempts). │
            │                                    │                          │ The       default        for │
            │                                    │                          │ serverSelectionTryOnce    is │
            │                                    │                          │ "false" for pooled  clients, │
            │                                    │                          │ otherwise   "true".   Pooled │
            │                                    │                          │ clients               ignore │
            │                                    │                          │ serverSelectionTryOnce; they │
            │                                    │                          │ signal the thread to  rescan │
            │                                    │                          │ the      topology      every │
            │                                    │                          │ half-second            until │
            │                                    │                          │ serverSelectionTimeoutMS     │
            │                                    │                          │ expires.                     │
            ├────────────────────────────────────┼──────────────────────────┼──────────────────────────────┤
            │MONGOC_URI_SOCKETCHECKINTERVALMS    │ socketcheckintervalms    │ Only   applies   to   single │
            │                                    │                          │ threaded   clients.   If   a │
            │                                    │                          │ socket  has  not  been  used │
            │                                    │                          │ within    this   time,   its │
            │                                    │                          │ connection is checked with a │
            │                                    │                          │ quick "isMaster" call before │
            │                                    │                          │ it is used  again.  Defaults │
            │                                    │                          │ to 5,000ms (5 seconds).      │
            └────────────────────────────────────┴──────────────────────────┴──────────────────────────────┘

       Setting any of the *TimeoutMS options above to 0 will be interpreted as "use the default value".

   Connection Pool Options
       These  options  govern  the  behavior  of  a  mongoc_client_pool_t.  They  are  ignored  by  a non-pooled
       mongoc_client_t.

                  ┌──────────────────────────────┬────────────────────┬──────────────────────────────┐
                  │Constant                      │ Key                │ Description                  │
                  └──────────────────────────────┴────────────────────┴──────────────────────────────┘

                  │MONGOC_URI_MAXPOOLSIZE        │ maxpoolsize        │ The   maximum   number    of │
                  │                              │                    │ clients    created    by   a │
                  │                              │                    │ mongoc_client_pool_t   total │
                  │                              │                    │ (both   in   the   pool  and │
                  │                              │                    │ checked  out).  The  default │
                  │                              │                    │ value  is  100.  Once  it is │
                  │                              │                    │ reached,                     │
                  │                              │                    │ mongoc_client_pool_pop       │
                  │                              │                    │ blocks until another  thread │
                  │                              │                    │ pushes a client.             │
                  ├──────────────────────────────┼────────────────────┼──────────────────────────────┤
                  │MONGOC_URI_MINPOOLSIZE        │ minpoolsize        │ Deprecated.   This  option's │
                  │                              │                    │ behavior does not match  its │
                  │                              │                    │ name,    and    its   actual │
                  │                              │                    │ behavior  will  likely  hurt │
                  │                              │                    │ performance.                 │
                  ├──────────────────────────────┼────────────────────┼──────────────────────────────┤
                  │MONGOC_URI_MAXIDLETIMEMS      │ maxidletimems      │ Not implemented.             │
                  ├──────────────────────────────┼────────────────────┼──────────────────────────────┤
                  │MONGOC_URI_WAITQUEUEMULTIPLE  │ waitqueuemultiple  │ Not implemented.             │
                  ├──────────────────────────────┼────────────────────┼──────────────────────────────┤
                  │MONGOC_URI_WAITQUEUETIMEOUTMS │ waitqueuetimeoutms │ Not implemented.             │
                  └──────────────────────────────┴────────────────────┴──────────────────────────────┘

   Write Concern Options
                          ┌──────────────────────┬────────────┬──────────────────────────────┐
                          │Constant              │ Key        │ Description                  │
                          └──────────────────────┴────────────┴──────────────────────────────┘

                           MONGOC_URI_W            w            Determines the write concern
                                                                (guarantee). Valid values:

                                                                       • 0 = The driver will
                                                                         not     acknowledge
                                                                         write    operations
                                                                         but  will  pass  or
                                                                         handle  any network
                                                                         and  socket  errors
                                                                         that it receives to
                                                                         the client. If  you
                                                                         disable       write
                                                                         concern but  enable
                                                                         the    getLastError
                                                                         command’s w option,
                                                                         w  overrides  the w
                                                                         option.

                                                                       • 1 = Provides  basic
                                                                         acknowledgment   of
                                                                         write   operations.
                                                                         By   specifying  1,
                                                                         you require that  a
                                                                         standalone   mongod
                                                                         instance,  or   the
                                                                         primary for replica
                                                                         sets,   acknowledge
                                                                         all           write
                                                                         operations.     For
                                                                         drivers    released
                                                                         after  the  default
                                                                         write       concern
                                                                         change, this is the
                                                                         default       write
                                                                         concern setting.

                                                                       • majority   =    For
                                                                         replica   sets,  if
                                                                         you   specify   the
                                                                         special    majority
                                                                         value to w  option,
                                                                         write    operations
                                                                         will  only   return
                                                                         successfully  after
                                                                         a majority  of  the
                                                                         configured  replica
                                                                         set  members   have
                                                                         acknowledged    the
                                                                         write operation.

                                                                       • n  =  For   replica
                                                                         sets,     if    you
                                                                         specify a number  n
                                                                         greater   than   1,
                                                                         operations     with
                                                                         this  write concern
                                                                         return only after n
                                                                         members  of the set
                                                                         have   acknowledged
                                                                         the  write.  If you
                                                                         set n to  a  number
                                                                         that   is   greater
                                                                         than the number  of
                                                                         available       set
                                                                         members or  members
                                                                         that   hold   data,
                                                                         MongoDB will  wait,
                                                                         potentially
                                                                         indefinitely,   for
                                                                         these   members  to
                                                                         become available.

                                                                       • tags = For  replica
                                                                         sets,    you    can
                                                                         specify a  tag  set
                                                                         to require that all
                                                                         members of the  set
                                                                         that   have   these
                                                                         tags     configured
                                                                         return confirmation
                                                                         of    the     write
                                                                         operation.
                          ├──────────────────────┼────────────┼──────────────────────────────┤
                          │MONGOC_URI_WTIMEOUTMS │ wtimeoutms │ The  time in milliseconds to │
                          │                      │            │ wait  for   replication   to │
                          │                      │            │ succeed, as specified in the │
                          │                      │            │ w option, before timing out. │
                          │                      │            │ When  wtimeoutMS is 0, write │
                          │                      │            │ operations will  never  time │
                          │                      │            │ out.                         │
                          ├──────────────────────┼────────────┼──────────────────────────────┤
                          │MONGOC_URI_JOURNAL    │ journal    │ Controls    whether    write │
                          │                      │            │ operations will  wait  until │
                          │                      │            │ the  mongod acknowledges the │
                          │                      │            │ write operations and commits │
                          │                      │            │ the  data  to  the  on  disk │
                          │                      │            │ journal.                     │
                          │                      │            │                              │
                          │                      │            │        • true    =   Enables │
                          │                      │            │          journal      commit │
                          │                      │            │          acknowledgment      │
                          │                      │            │          write      concern. │
                          │                      │            │          Equivalent       to │
                          │                      │            │          specifying      the │
                          │                      │            │          getLastError        │
                          │                      │            │          command  with the j │
                          │                      │            │          option enabled.     │
                          │                      │            │                              │
                          │                      │            │        • false  =  Does  not │
                          │                      │            │          require that mongod │
                          │                      │            │          commit        write │
                          │                      │            │          operations  to  the │
                          │                      │            │          journal      before │
                          │                      │            │          acknowledging   the │
                          │                      │            │          write    operation. │
                          │                      │            │          This is the default │
                          │                      │            │          option   for    the │
                          │                      │            │          journal parameter.  │
                          └──────────────────────┴────────────┴──────────────────────────────┘

   Read Concern Options
                    ┌────────────────────────────┬──────────────────┬──────────────────────────────┐
                    │Constant                    │ Key              │ Description                  │
                    ├────────────────────────────┼──────────────────┼──────────────────────────────┤
                    │MONGOC_URI_READCONCERNLEVEL │ readconcernlevel │ The  level  of isolation for │
                    │                            │                  │ read  operations.   If   the │
                    │                            │                  │ level  is  left unspecified, │
                    │                            │                  │ the server default  will  be │
                    │                            │                  │ used. See readConcern in the │
                    │                            │                  │ MongoDB Manual for details.  │
                    └────────────────────────────┴──────────────────┴──────────────────────────────┘

   Read Preference Options
       When connected to a replica set, the driver chooses which member to query using the read preference:

       1. Choose members whose type matches "readPreference".

       2. From these, if there are any tags sets configured, choose members matching the first tag set. If there
          are  none,  fall back to the next tag set and so on, until some members are chosen or the tag sets are
          exhausted.

       3. From the chosen servers, distribute queries randomly among the  server  with  the  fastest  round-trip
          times.  These  include  the server with the fastest time and any whose round-trip time is no more than
          "localThresholdMS" slower.

                 ┌───────────────────────────────┬─────────────────────┬──────────────────────────────┐
                 │Constant                       │ Key                 │ Description                  │
                 └───────────────────────────────┴─────────────────────┴──────────────────────────────┘

                 │MONGOC_URI_READPREFERENCE      │ readpreference      │ Specifies  the  replica  set │
                 │                               │                     │ read   preference  for  this │
                 │                               │                     │ connection.   This   setting │
                 │                               │                     │ overrides any slaveOk value. │
                 │                               │                     │ The read  preference  values │
                 │                               │                     │ are the following:           │
                 │                               │                     │                              │
                 │                               │                     │        • primary (default)   │
                 │                               │                     │                              │
                 │                               │                     │        • primaryPreferred    │
                 │                               │                     │                              │
                 │                               │                     │        • secondary           │
                 │                               │                     │                              │
                 │                               │                     │        • secondaryPreferred  │
                 │                               │                     │                              │
                 │                               │                     │        • nearest             │
                 ├───────────────────────────────┼─────────────────────┼──────────────────────────────┤
                 │MONGOC_URI_READPREFERENCETAGS  │ readpreferencetags  │ A representation  of  a  tag │
                 │                               │                     │ set.         See        also │
                 │                               │                     │ mongoc-read-prefs-tag-sets.  │
                 ├───────────────────────────────┼─────────────────────┼──────────────────────────────┤
                 │MONGOC_URI_LOCALTHRESHOLDMS    │ localthresholdms    │ How   far   to    distribute │
                 │                               │                     │ queries,  beyond  the server │
                 │                               │                     │ with the fastest  round-trip │
                 │                               │                     │ time.   By   default,   only │
                 │                               │                     │ servers within 15ms  of  the │
                 │                               │                     │ fastest    round-trip   time │
                 │                               │                     │ receive queries.             │
                 ├───────────────────────────────┼─────────────────────┼──────────────────────────────┤
                 │MONGOC_URI_MAXSTALENESSSECONDS │ maxstalenessseconds │ The maximum replication lag, │
                 │                               │                     │ in wall clock time,  that  a │
                 │                               │                     │ secondary   can  suffer  and │
                 │                               │                     │ still   be   eligible.   The │
                 │                               │                     │ smallest  allowed  value for │
                 │                               │                     │ maxStalenessSeconds  is   90 │
                 │                               │                     │ seconds.                     │
                 └───────────────────────────────┴─────────────────────┴──────────────────────────────┘

       NOTE:
          When connecting to more than one mongos, libmongoc's localThresholdMS applies only to the selection of
          mongos servers. The threshold for selecting among replica set members in shards is controlled  by  the
          mongos's localThreshold command line option.

   Legacy Options
       For historical reasons, the following options are available. They should however not be used.

                          ┌───────────────────┬─────────┬───────────────────────────────────┐
                          │Constant           │ Key     │ Description                       │
                          ├───────────────────┼─────────┼───────────────────────────────────┤
                          │MONGOC_URI_SAFE    │ safe    │ {true|false} Same as w={1|0}      │
                          ├───────────────────┼─────────┼───────────────────────────────────┤
                          │MONGOC_URI_SLAVEOK │ slaveok │ When     set,     same    as      │
                          │                   │         │ readPreference=secondaryPreferred │
                          └───────────────────┴─────────┴───────────────────────────────────┘

   Version Checks
       Conditional compilation based on mongoc version

   Description
       The  following  preprocessor  macros  can  be  used to perform various checks based on the version of the
       library you are compiling against.  This may be useful if you only want to enable a feature on a  certain
       version of the library.

          #include <mongoc.h>

          #define MONGOC_MAJOR_VERSION (1)
          #define MONGOC_MINOR_VERSION (9)
          #define MONGOC_MICRO_VERSION (2)
          #define MONGOC_VERSION_S     "1.9.2"
          #define MONGOC_VERSION_HEX   ((1 << 24) | (0 << 16) | (0 << 8) | 0)
          #define MONGOC_CHECK_VERSION(major, minor, micro)

       Only compile a block on MongoDB C Driver 1.1.0 and newer.

          #if MONGOC_CHECK_VERSION(1, 1, 0)
          static void
          do_something (void)
          {
          }
          #endif

   mongoc_write_concern_t
       Write Concern abstraction

   Synopsis
       mongoc_write_concern_t  tells  the  driver  what  level  of  acknowledgment to await from the server. The
       default, MONGOC_WRITE_CONCERN_W_DEFAULT, is right for the great majority of applications.

       You can specify a  write  concern  on  connection  objects,  database  objects,  collection  objects,  or
       per-operation.  Data-modifying  operations typically use the write concern of the object they operate on,
       and check the server response  for  a  write  concern  error  or  write  concern  timeout.  For  example,
       mongoc_collection_drop_index uses the collection's write concern, and a write concern error or timeout in
       the response is considered a failure.

       Exceptions to this principle are the generic command functions:

       • mongoc_client_commandmongoc_client_command_simplemongoc_database_commandmongoc_database_command_simplemongoc_collection_commandmongoc_collection_command_simple

       These generic command functions do not automatically apply a write concern, and they  do  not  check  the
       server response for a write concern error or write concern timeout.

       See Write Concern on the MongoDB website for more information.

   Write Concern Levels
       Set the write concern level with mongoc_write_concern_set_w.

                    ┌──────────────────────────────────────┬───────────────────────────────────────┐
                    │MONGOC_WRITE_CONCERN_W_DEFAULT (1)    │ By  default,  writes  block  awaiting │
                    │                                      │ acknowledgment     from      MongoDB. │
                    │                                      │ Acknowledged   write  concern  allows │
                    │                                      │ clients to catch  network,  duplicate │
                    │                                      │ key, and other errors.                │
                    ├──────────────────────────────────────┼───────────────────────────────────────┤
                    │MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED │ With this write concern, MongoDB does │
                    │(0)                                   │ not  acknowledge the receipt of write │
                    │                                      │ operation. Unacknowledged is  similar │
                    │                                      │ to  errors  ignored;  however, mongoc │
                    │                                      │ attempts  to   receive   and   handle │
                    │                                      │ network errors when possible.         │
                    ├──────────────────────────────────────┼───────────────────────────────────────┤
                    │MONGOC_WRITE_CONCERN_W_MAJORITY       │ Block  until   a   write   has   been │
                    │(majority)                            │ propagated to a majority of the nodes │
                    │                                      │ in the replica set.                   │
                    ├──────────────────────────────────────┼───────────────────────────────────────┤
                    │n                                     │ Block  until   a   write   has   been │
                    │                                      │ propagated to at least n nodes in the │
                    │                                      │ replica set.                          │
                    └──────────────────────────────────────┴───────────────────────────────────────┘

   Deprecations
       The  write  concern  MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED  (value  -1)  is  a  deprecated  synonym   for
       MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED (value 0), and will be removed in the next major release.

       mongoc_write_concern_set_fsync is deprecated.

   Application Performance Monitoring (APM)
       The  MongoDB  C  Driver  allows  you  to  monitor  all  the  MongoDB operations the driver executes. This
       event-notification system conforms to two MongoDB driver specs:

       • Command Monitoring: events related to all application operations.

       • SDAM Monitoring: events related to the driver's Server Discovery And Monitoring logic.

       To receive notifications, create a mongoc_apm_callbacks_t with mongoc_apm_callbacks_new, set callbacks on
       it, then pass it to mongoc_client_set_apm_callbacks or mongoc_client_pool_set_apm_callbacks.

   Command-Monitoring Example
       example-command-monitoring.c.INDENT 0.0

          /* gcc example-command-monitoring.c -o example-command-monitoring \
           *     $(pkg-config --cflags --libs libmongoc-1.0) */

          /* ./example-command-monitoring [CONNECTION_STRING] */

          #include <mongoc.h>
          #include <stdio.h>

          typedef struct {
             int started;
             int succeeded;
             int failed;
          } stats_t;

          void
          command_started (const mongoc_apm_command_started_t *event)
          {
             char *s;

             s = bson_as_relaxed_extended_json (
                mongoc_apm_command_started_get_command (event), NULL);
             printf ("Command %s started on %s:\n%s\n\n",
                     mongoc_apm_command_started_get_command_name (event),
                     mongoc_apm_command_started_get_host (event)->host,
                     s);

             ((stats_t *) mongoc_apm_command_started_get_context (event))->started++;

             bson_free (s);
          }

          void
          command_succeeded (const mongoc_apm_command_succeeded_t *event)
          {
             char *s;

             s = bson_as_relaxed_extended_json (
                mongoc_apm_command_succeeded_get_reply (event), NULL);
             printf ("Command %s succeeded:\n%s\n\n",
                     mongoc_apm_command_succeeded_get_command_name (event),
                     s);

             ((stats_t *) mongoc_apm_command_succeeded_get_context (event))->succeeded++;

             bson_free (s);
          }

          void
          command_failed (const mongoc_apm_command_failed_t *event)
          {
             bson_error_t error;

             mongoc_apm_command_failed_get_error (event, &error);
             printf ("Command %s failed:\n\"%s\"\n\n",
                     mongoc_apm_command_failed_get_command_name (event),
                     error.message);

             ((stats_t *) mongoc_apm_command_failed_get_context (event))->failed++;
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_apm_callbacks_t *callbacks;
             stats_t stats = {0};
             mongoc_collection_t *collection;
             const char *uristr = "mongodb://127.0.0.1/?appname=cmd-monitoring-example";
             const char *collection_name = "test";
             bson_t *docs[2];

             mongoc_init ();

             if (argc > 1) {
                uristr = argv[1];
             }

             client = mongoc_client_new (uristr);

             if (!client) {
                fprintf (stderr, "Failed to parse URI.\n");
                return EXIT_FAILURE;
             }

             mongoc_client_set_error_api (client, 2);
             callbacks = mongoc_apm_callbacks_new ();
             mongoc_apm_set_command_started_cb (callbacks, command_started);
             mongoc_apm_set_command_succeeded_cb (callbacks, command_succeeded);
             mongoc_apm_set_command_failed_cb (callbacks, command_failed);
             mongoc_client_set_apm_callbacks (
                client, callbacks, (void *) &stats /* context pointer */);

             collection = mongoc_client_get_collection (client, "test", collection_name);
             mongoc_collection_drop (collection, NULL);

             docs[0] = BCON_NEW ("_id", BCON_INT32 (0));
             docs[1] = BCON_NEW ("_id", BCON_INT32 (1));
             mongoc_collection_insert_many (
                collection, (const bson_t **) docs, 2, NULL, NULL, NULL);

             /* duplicate key error on the second insert */
             mongoc_collection_insert_one (collection, docs[0], NULL, NULL, NULL);

             mongoc_collection_destroy (collection);
             mongoc_apm_callbacks_destroy (callbacks);
             mongoc_client_destroy (client);

             printf ("started: %d\nsucceeded: %d\nfailed: %d\n",
                     stats.started,
                     stats.succeeded,
                     stats.failed);

             bson_destroy (docs[0]);
             bson_destroy (docs[1]);

             mongoc_cleanup ();

             return EXIT_SUCCESS;
          }
          Command drop started on 127.0.0.1:
          { "drop" : "test" }

          Command drop succeeded:
          { "ns" : "test.test", "nIndexesWas" : 1, "ok" : 1.0 }

          Command insert started on 127.0.0.1:
          {
            "insert" : "test",
            "ordered" : true,
            "documents" : [
              { "_id" : 0 }, { "_id" : 1 }
            ]
          }

          Command insert succeeded:
          { "n" : 2, "ok" : 1.0 }

          Command insert started on 127.0.0.1:
          {
            "insert" : "test",
            "ordered" : true,
            "documents" : [
              { "_id" : 0 }
            ]
          }

          Command insert succeeded:
          {
            "n" : 0,
            "writeErrors" : [
              { "index" : 0, "code" : 11000, "errmsg" : "duplicate key" }
            ],
            "ok" : 1.0
          }

          started: 3
          succeeded: 3
          failed: 0

       The  output  has  been edited and formatted for clarity. Depending on your server configuration, messages
       may include metadata like database name, logical session ids, or cluster times that are not shown here.

       The final "insert" command is considered successful, despite the writeError, because the  server  replied
       to the overall command with "ok": 1.

   SDAM Monitoring Example
       example-sdam-monitoring.c.INDENT 0.0

          /* gcc example-sdam-monitoring.c -o example-sdam-monitoring \
           *     $(pkg-config --cflags --libs libmongoc-1.0) */

          /* ./example-sdam-monitoring [CONNECTION_STRING] */

          #include <mongoc.h>
          #include <stdio.h>

          typedef struct {
             int server_changed_events;
             int server_opening_events;
             int server_closed_events;
             int topology_changed_events;
             int topology_opening_events;
             int topology_closed_events;
             int heartbeat_started_events;
             int heartbeat_succeeded_events;
             int heartbeat_failed_events;
          } stats_t;

          static void
          server_changed (const mongoc_apm_server_changed_t *event)
          {
             stats_t *context;
             const mongoc_server_description_t *prev_sd, *new_sd;

             context = (stats_t *) mongoc_apm_server_changed_get_context (event);
             context->server_changed_events++;

             prev_sd = mongoc_apm_server_changed_get_previous_description (event);
             new_sd = mongoc_apm_server_changed_get_new_description (event);

             printf ("server changed: %s %s -> %s\n",
                     mongoc_apm_server_changed_get_host (event)->host_and_port,
                     mongoc_server_description_type (prev_sd),
                     mongoc_server_description_type (new_sd));
          }

          static void
          server_opening (const mongoc_apm_server_opening_t *event)
          {
             stats_t *context;

             context = (stats_t *) mongoc_apm_server_opening_get_context (event);
             context->server_opening_events++;

             printf ("server opening: %s\n",
                     mongoc_apm_server_opening_get_host (event)->host_and_port);
          }

          static void
          server_closed (const mongoc_apm_server_closed_t *event)
          {
             stats_t *context;

             context = (stats_t *) mongoc_apm_server_closed_get_context (event);
             context->server_closed_events++;

             printf ("server closed: %s\n",
                     mongoc_apm_server_closed_get_host (event)->host_and_port);
          }

          static void
          topology_changed (const mongoc_apm_topology_changed_t *event)
          {
             stats_t *context;
             const mongoc_topology_description_t *prev_td;
             const mongoc_topology_description_t *new_td;
             mongoc_server_description_t **prev_sds;
             size_t n_prev_sds;
             mongoc_server_description_t **new_sds;
             size_t n_new_sds;
             size_t i;

             context = (stats_t *) mongoc_apm_topology_changed_get_context (event);
             context->topology_changed_events++;

             prev_td = mongoc_apm_topology_changed_get_previous_description (event);
             prev_sds = mongoc_topology_description_get_servers (prev_td, &n_prev_sds);
             new_td = mongoc_apm_topology_changed_get_new_description (event);
             new_sds = mongoc_topology_description_get_servers (new_td, &n_new_sds);

             printf ("topology changed: %s -> %s\n",
                     mongoc_topology_description_type (prev_td),
                     mongoc_topology_description_type (new_td));

             if (n_prev_sds) {
                printf ("  previous servers:\n");
                for (i = 0; i < n_prev_sds; i++) {
                   printf ("      %s %s\n",
                           mongoc_server_description_type (prev_sds[i]),
                           mongoc_server_description_host (prev_sds[i])->host_and_port);
                }
             }

             if (n_new_sds) {
                printf ("  new servers:\n");
                for (i = 0; i < n_new_sds; i++) {
                   printf ("      %s %s\n",
                           mongoc_server_description_type (new_sds[i]),
                           mongoc_server_description_host (new_sds[i])->host_and_port);
                }
             }

             mongoc_server_descriptions_destroy_all (prev_sds, n_prev_sds);
             mongoc_server_descriptions_destroy_all (new_sds, n_new_sds);
          }

          static void
          topology_opening (const mongoc_apm_topology_opening_t *event)
          {
             stats_t *context;

             context = (stats_t *) mongoc_apm_topology_opening_get_context (event);
             context->topology_opening_events++;

             printf ("topology opening\n");
          }

          static void
          topology_closed (const mongoc_apm_topology_closed_t *event)
          {
             stats_t *context;

             context = (stats_t *) mongoc_apm_topology_closed_get_context (event);
             context->topology_closed_events++;

             printf ("topology closed\n");
          }

          static void
          server_heartbeat_started (const mongoc_apm_server_heartbeat_started_t *event)
          {
             stats_t *context;

             context =
                (stats_t *) mongoc_apm_server_heartbeat_started_get_context (event);
             context->heartbeat_started_events++;

             printf ("%s heartbeat started\n",
                     mongoc_apm_server_heartbeat_started_get_host (event)->host_and_port);
          }

          static void
          server_heartbeat_succeeded (
             const mongoc_apm_server_heartbeat_succeeded_t *event)
          {
             stats_t *context;
             char *reply;

             context =
                (stats_t *) mongoc_apm_server_heartbeat_succeeded_get_context (event);
             context->heartbeat_succeeded_events++;

             reply = bson_as_canonical_extended_json (
                mongoc_apm_server_heartbeat_succeeded_get_reply (event), NULL);

             printf (
                "%s heartbeat succeeded: %s\n",
                mongoc_apm_server_heartbeat_succeeded_get_host (event)->host_and_port,
                reply);

             bson_free (reply);
          }

          static void
          server_heartbeat_failed (const mongoc_apm_server_heartbeat_failed_t *event)
          {
             stats_t *context;
             bson_error_t error;

             context = (stats_t *) mongoc_apm_server_heartbeat_failed_get_context (event);
             context->heartbeat_failed_events++;
             mongoc_apm_server_heartbeat_failed_get_error (event, &error);

             printf ("%s heartbeat failed: %s\n",
                     mongoc_apm_server_heartbeat_failed_get_host (event)->host_and_port,
                     error.message);
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_apm_callbacks_t *cbs;
             stats_t stats = {0};
             const char *uristr = "mongodb://127.0.0.1/?appname=sdam-monitoring-example";
             bson_t cmd = BSON_INITIALIZER;
             bson_t reply;
             bson_error_t error;

             mongoc_init ();

             if (argc > 1) {
                uristr = argv[1];
             }

             client = mongoc_client_new (uristr);

             if (!client) {
                fprintf (stderr, "Failed to parse URI.\n");
                return EXIT_FAILURE;
             }

             mongoc_client_set_error_api (client, 2);
             cbs = mongoc_apm_callbacks_new ();
             mongoc_apm_set_server_changed_cb (cbs, server_changed);
             mongoc_apm_set_server_opening_cb (cbs, server_opening);
             mongoc_apm_set_server_closed_cb (cbs, server_closed);
             mongoc_apm_set_topology_changed_cb (cbs, topology_changed);
             mongoc_apm_set_topology_opening_cb (cbs, topology_opening);
             mongoc_apm_set_topology_closed_cb (cbs, topology_closed);
             mongoc_apm_set_server_heartbeat_started_cb (cbs, server_heartbeat_started);
             mongoc_apm_set_server_heartbeat_succeeded_cb (cbs,
                                                           server_heartbeat_succeeded);
             mongoc_apm_set_server_heartbeat_failed_cb (cbs, server_heartbeat_failed);
             mongoc_client_set_apm_callbacks (
                client, cbs, (void *) &stats /* context pointer */);

             /* the driver connects on demand to perform first operation */
             BSON_APPEND_INT32 (&cmd, "buildinfo", 1);
             mongoc_client_command_simple (client, "admin", &cmd, NULL, &reply, &error);
             mongoc_client_destroy (client);

             printf ("Events:\n"
                     "   server changed: %d\n"
                     "   server opening: %d\n"
                     "   server closed: %d\n"
                     "   topology changed: %d\n"
                     "   topology opening: %d\n"
                     "   topology closed: %d\n"
                     "   heartbeat started: %d\n"
                     "   heartbeat succeeded: %d\n"
                     "   heartbeat failed: %d\n",
                     stats.server_changed_events,
                     stats.server_opening_events,
                     stats.server_closed_events,
                     stats.topology_changed_events,
                     stats.topology_opening_events,
                     stats.topology_closed_events,
                     stats.heartbeat_started_events,
                     stats.heartbeat_succeeded_events,
                     stats.heartbeat_failed_events);

             bson_destroy (&cmd);
             bson_destroy (&reply);
             mongoc_apm_callbacks_destroy (cbs);

             mongoc_cleanup ();

             return EXIT_SUCCESS;
          }
          ./example-sdam-monitoring "mongodb://localhost:27017,localhost:27018/?replicaSet=rs"

       This example program prints something like:

          topology opening
          topology changed: Unknown -> ReplicaSetNoPrimary
          server opening: localhost:27017
          server opening: localhost:27018
          localhost:27017 heartbeat started
          localhost:27018 heartbeat started
          localhost:27017 heartbeat succeeded: { ... reply ... }
          server changed: localhost:27017 Unknown -> RSPrimary
          server opening: localhost:27019
          topology changed: ReplicaSetNoPrimary -> ReplicaSetWithPrimary
            new servers:
                RSPrimary localhost:27017
          localhost:27019 heartbeat started
          localhost:27018 heartbeat succeeded: { ... reply ... }
          server changed: localhost:27018 Unknown -> RSSecondary
          topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
            previous servers:
                RSPrimary localhost:27017
            new servers:
                RSPrimary localhost:27017
                RSSecondary localhost:27018
          localhost:27019 heartbeat succeeded: { ... reply ... }
          server changed: localhost:27019 Unknown -> RSSecondary
          topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
            previous servers:
                RSPrimary localhost:27017
                RSSecondary localhost:27018
            new servers:
                RSPrimary localhost:27017
                RSSecondary localhost:27018
                RSSecondary localhost:27019
          topology closed

          Events:
             server changed: 3
             server opening: 3
             server closed: 0
             topology changed: 4
             topology opening: 1
             topology closed: 1
             heartbeat started: 3
             heartbeat succeeded: 3
             heartbeat failed: 0

       The driver discovers the third member, "localhost:27019", and adds it to the topology.

AUTHOR

       MongoDB, Inc

       2018, MongoDB, Inc