1MONGOC_REFERENCE(3)            MongoDB C Driver            MONGOC_REFERENCE(3)
2
3
4

NAME

6       mongoc_reference - Index
7

MONGODB C DRIVER

9       A Cross Platform MongoDB Client Library for C
10
11   Introduction
12       The MongoDB C Driver, also known as "libmongoc", is a library for using
13       MongoDB from  C  applications,  and  for  writing  MongoDB  drivers  in
14       higher-level languages.
15
16       It  depends on libbson to generate and parse BSON documents, the native
17       data format of MongoDB.
18
19   Installing the MongoDB C Driver (libmongoc) and BSON library (libbson)
20       The following guide will step you through the process  of  downloading,
21       building,  and  installing  the current release of the MongoDB C Driver
22       (libmongoc) and BSON library (libbson).
23
24   Supported Platforms
25       The MongoDB C Driver is continuously tested  on  variety  of  platforms
26       including:
27
28       · Archlinux
29
30       · Debian 8.1
31
32       · macOS 10.10
33
34       · Microsoft Windows Server 2008
35
36       · RHEL 7.0, 7.1, 7.2
37
38       · SUSE 12
39
40       · Ubuntu 12.04, 14.04, 16.04
41
42       · Clang 3.4, 3.5, 3.7, 3.8
43
44       · GCC 4.6, 4.8, 4.9, 5.3
45
46       · MinGW-W64
47
48       · Visual Studio 2010, 2013, 2015
49
50       · x86, x86_64, ARM (aarch64), Power8 (ppc64le), zSeries (s390x)
51
52   Install libmongoc with a Package Manager
53       Several  Linux  distributions  provide  packages  for libmongoc and its
54       dependencies. One advantage of installing libmongoc with a package man‐
55       ager  is  that  its  dependencies (including libbson) will be installed
56       automatically.
57
58       The libmongoc package is available on recent  versions  of  Debian  and
59       Ubuntu.
60
61          $ apt-get install libmongoc-1.0-0
62
63       On Fedora, a mongo-c-driver package is available in the default reposi‐
64       tories and can be installed with:
65
66          $ dnf install mongo-c-driver
67
68       On recent Red Hat systems, such as CentOS and RHEL 7, a  mongo-c-driver
69       package  is available in the EPEL repository. To check which version is
70       available, see  https://apps.fedoraproject.org/packages/mongo-c-driver.
71       The package can be installed with:
72
73          $ yum install mongo-c-driver
74
75   Install libbson with a Package Manager
76       The  libbson  package  is  available  on  recent versions of Debian and
77       Ubuntu. If you have installed libmongoc, then libbson will have already
78       been  installed as a dependency. It is also possible to install libbson
79       without libmongoc.
80
81          $ apt-get install libbson-1.0
82
83       On Fedora, a libbson package is available in the  default  repositories
84       and can be installed with:
85
86          $ dnf install libbson
87
88       On recent Red Hat systems, such as CentOS and RHEL 7, a libbson package
89       is available in the EPEL repository. To check which version  is  avail‐
90       able, see https://apps.fedoraproject.org/packages/libbson.  The package
91       can be installed with:
92
93          $ yum install libbson
94
95   Building on Unix
96   Prerequisites for libmongoc
97       OpenSSL is required for authentication or for SSL connections  to  Mon‐
98       goDB. Kerberos or LDAP support requires Cyrus SASL.
99
100       To install all optional dependencies on RedHat / Fedora:
101
102          $ sudo yum install cmake openssl-devel cyrus-sasl-devel
103
104       On Debian / Ubuntu:
105
106          $ sudo apt-get install cmake libssl-dev libsasl2-dev
107
108       On FreeBSD:
109
110          $ su -c 'pkg install cmake openssl cyrus-sasl'
111
112   Prerequisites for libbson
113       The  only prerequisite for building libbson is cmake. The command lines
114       above can be adjusted to install only cmake.
115
116   Building from a release tarball
117       Unless you intend to contribute to mongo-c-driver and/or  libbson,  you
118       will want to build from a release tarball.
119
120       The  most  recent  release  of libmongoc and libbson, both of which are
121       included in mongo-c-driver, is 1.13.1 and can be downloaded  here.  The
122       instructions  in this document utilize cmake's out-of-source build fea‐
123       ture to keep build artifacts separate from source files.
124
125       The following snippet will download and extract the driver, and config‐
126       ure it:
127
128          $ wget https://github.com/mongodb/mongo-c-driver/releases/download/1.13.1/mongo-c-driver-1.13.1.tar.gz
129          $ tar xzf mongo-c-driver-1.13.1.tar.gz
130          $ cd mongo-c-driver-1.13.1
131          $ mkdir cmake-build
132          $ cd cmake-build
133          $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF ..
134
135       The  -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF option is recommended, see
136       init-cleanup. Another useful cmake option is -DCMAKE_BUILD_TYPE=Release
137       for  a release optimized build and -DCMAKE_BUILD_TYPE=Debug for a debug
138       build. For a list of all configure options, run cmake -L ...
139
140       If cmake completed successfully, you will see a considerable amount  of
141       output  describing  your  build configuration. The final line of output
142       should look something like this:
143
144          -- Build files have been written to: /home/user/mongo-c-driver-1.13.1/cmake-build
145
146       If cmake concludes with anything different, then  there  is  likely  an
147       error  or some other problem with the build. Review the output to iden‐
148       tify and correct the problem.
149
150       mongo-c-driver contains a copy of libbson, in case your system does not
151       already have libbson installed. The build will detect if libbson is not
152       installed and use the bundled libbson.
153
154       Additionally, it is possible to build only libbson by setting the -DEN‐
155       ABLE_MONGOC=OFF option:
156
157          $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF -DENABLE_MONGOC=OFF ..
158
159       A build configuration description similar to the one above will be dis‐
160       played, though with fewer entries. Once the configuration is  complete,
161       the selected items can be built and installed with these commands:
162
163          $ make
164          $ sudo make install
165
166       There  are  two  ways  to  uninstall  the  components  that  have  been
167       installed.  The first is to invoke the uninstall program directly.   On
168       Linux/Unix:
169
170          $ sudo /usr/local/share/mongo-c-driver/uninstall.sh
171
172       On Windows:
173
174          C:\Users\user> C:\mongo-c-driver\share\mongo-c-driver\uninstall.bat
175
176       The  second way to uninstall is from within the build directory, assum‐
177       ing that it is in the exact same state as when the install command  was
178       invoked:
179
180          $ sudo make uninstall
181
182       The  second approach simply invokes the uninstall program referenced in
183       the first approach.
184
185   Building from git
186       Clone the repository and build  the  current  master  or  a  particular
187       release tag:
188
189          $ git clone https://github.com/mongodb/mongo-c-driver.git
190          $ cd mongo-c-driver
191          $ git checkout x.y.z  # To build a particular release
192          $ mkdir cmake-build
193          $ cd cmake-build
194          $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF ..
195          $ make
196          $ sudo make install
197
198   Generating the documentation
199       Install Sphinx, then:
200
201          $ cmake -DENABLE_MAN_PAGES=ON -DENABLE_HTML_DOCS=ON ..
202          $ make mongoc-doc
203
204       To build only the libbson documentation:
205
206          $ cmake -DENABLE_MAN_PAGES=ON -DENABLE_HTML_DOCS=ON ..
207          $ make bson-doc
208
209       The  -DENABLE_MAN_PAGES=ON  and -DENABLE_HTML_DOCS=ON can also be added
210       as options to a normal build from a release tarball or from git so that
211       the documentation is built at the same time as other components.
212
213   Building on macOS
214       Install the XCode Command Line Tools:
215
216          $ xcode-select --install
217
218       The cmake utility is also required. First install Homebrew according to
219       its instructions, then:
220
221          $ brew install cmake
222
223       Download the latest release tarball:
224
225          $ curl -LO https://github.com/mongodb/mongo-c-driver/releases/download/1.13.1/mongo-c-driver-1.13.1.tar.gz
226          $ tar xzf mongo-c-driver-1.13.1.tar.gz
227          $ cd mongo-c-driver-1.13.1
228
229       Build and install the driver:
230
231          $ mkdir cmake-build
232          $ cd cmake-build
233          $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF ..
234
235       All of the same variations described above (e.g., building  only  libb‐
236       son,  building documentation, etc.) are available when building on mac‐
237       OS.
238
239   Building on Windows with Visual Studio
240       Building on Windows requires Windows Vista or newer and  Visual  Studio
241       2010  or newer. Additionally, cmake is required to generate Visual Stu‐
242       dio project files.
243
244       Let's start by generating Visual Studio project  files.  The  following
245       assumes  we  are  compiling for 64-bit Windows using Visual Studio 2015
246       Express, which can be freely downloaded from Microsoft. We will be uti‐
247       lizing cmake's out-of-source build feature to keep build artifacts sep‐
248       arate from source files.
249
250          cd mongo-c-driver-1.13.1
251          mkdir cmake-build
252          cd cmake-build
253          cmake -G "Visual Studio 14 2015 Win64" \
254            "-DCMAKE_INSTALL_PREFIX=C:\mongo-c-driver" \
255            "-DCMAKE_PREFIX_PATH=C:\mongo-c-driver" \
256            ..
257
258       (Run cmake -LH .. for a list of other options.)
259
260       Now that we have project  files  generated,  we  can  either  open  the
261       project  in Visual Studio or compile from the command line. Let's build
262       using the command line program msbuild.exe:
263
264          msbuild.exe /p:Configuration=RelWithDebInfo ALL_BUILD.vcxproj
265
266       Visual Studio's default build type is Debug, but we recommend a release
267       build  with debug info for production use. Now that libmongoc and libb‐
268       son are  compiled,  let's  install  them  using  msbuild.  It  will  be
269       installed to the path specified by CMAKE_INSTALL_PREFIX.
270
271          msbuild.exe INSTALL.vcxproj
272
273       You should now see libmongoc and libbson installed in C:\mongo-c-driver
274
275       To use the driver libraries in your program, see visual-studio-guide.
276
277   Building on Windows with MinGW-W64 and MSYS2
278       Install  MSYS2  from  msys2.github.io.  Choose  the x86_64 version, not
279       i686.
280
281       Open c:\msys64\ming64_shell.bat (not the msys2_shell).  Install  depen‐
282       dencies:
283
284          pacman --noconfirm -Syu
285          pacman --noconfirm -S mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake
286          pacman --noconfirm -S mingw-w64-x86_64-extra-cmake-modules make tar
287          pacman --noconfirm -S mingw64/mingw-w64-x86_64-cyrus-sasl
288
289       Download  and  untar the latest tarball, enter its directory, and build
290       with CMake:
291
292          CC=/mingw64/bin/gcc.exe /mingw64/bin/cmake -G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX="C:/mongo-c-driver" ..
293          make
294
295   Tutorial
296       This guide offers a brief introduction to the MongoDB C Driver.
297
298       For more information on the C API, please refer to the api.
299
300   Contents
301       · Tutorial
302
303         · Installing
304
305         · Starting MongoDB
306
307         · Include and link libmongoc in your C program
308
309         · Use libmongoc in a Microsoft Visual Studio Project
310
311         · Making a Connection
312
313         · Creating BSON Documents
314
315         · Basic CRUD Operations
316
317         · Executing Commands
318
319         · Threading
320
321         · Next Steps
322
323   Installing
324       For detailed instructions on installing the MongoDB C Driver on a  par‐
325       ticular platform, please see the installation guide.
326
327   Starting MongoDB
328       To  run  the  examples  in this tutorial, MongoDB must be installed and
329       running on localhost on the default port, 27017. To check if it  is  up
330       and running, connect to it with the MongoDB shell.
331
332          $ mongo --host localhost --port 27017
333          MongoDB shell version: 3.0.6
334          connecting to: localhost:27017/test
335          >
336
337   Include and link libmongoc in your C program
338   Include mongoc.h
339       All  libmongoc's  functions and types are available in one header file.
340       Simply include mongoc/mongoc.h:
341
342          #include <mongoc/mongoc.h>
343
344   CMake
345       The libmongoc installation includes a CMake config-file package, so you
346       can  use  CMake's  find_package  command to find libmongoc's header and
347       library paths and link to libmongoc: CMakeLists.txt.INDENT 0.0
348
349          # Specify the minimum version you require.
350          find_package (libmongoc-1.0 1.7 REQUIRED)
351
352          message ("--   mongoc found version \"${MONGOC_VERSION}\"")
353          message ("--   mongoc include path \"${MONGOC_INCLUDE_DIRS}\"")
354          message ("--   mongoc libraries \"${MONGOC_LIBRARIES}\"")
355
356          # The "hello_mongoc.c" sample program is shared among four tests.
357          add_executable (hello_mongoc ../../hello_mongoc.c)
358          target_include_directories (hello_mongoc PRIVATE "${MONGOC_INCLUDE_DIRS}")
359          target_link_libraries (hello_mongoc PRIVATE "${MONGOC_LIBRARIES}")
360          target_compile_definitions (hello_mongoc PRIVATE "${MONGOC_DEFINITIONS}")
361
362
363By default, libmongoc is dynamically linked. You can use libmongoc as a static
364library instead: Use the included libmongoc-static-1.0 config-file package:
365
366          # Specify the minimum version you require.
367          find_package (libmongoc-static-1.0 1.7 REQUIRED)
368
369          message ("--   mongoc found version \"${MONGOC_STATIC_VERSION}\"")
370          message ("--   mongoc include path \"${MONGOC_STATIC_INCLUDE_DIRS}\"")
371          message ("--   mongoc libraries \"${MONGOC_STATIC_LIBRARIES}\"")
372
373          # The "hello_mongoc.c" sample program is shared among four tests.
374          add_executable (hello_mongoc ../../hello_mongoc.c)
375          target_include_directories (hello_mongoc PRIVATE "${MONGOC_STATIC_INCLUDE_DIRS}")
376          target_link_libraries (hello_mongoc PRIVATE "${MONGOC_STATIC_LIBRARIES}")
377          target_compile_definitions (hello_mongoc PRIVATE "${MONGOC_STATIC_DEFINITIONS}")
378
379
380   pkg-config
381       If  you're  not  using CMake, use pkg-config on the command line to set
382       header and library paths:
383
384          gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-1.0)
385
386
387       Or to statically link to libmongoc:
388
389          gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-static-1.0)
390
391
392   Specifying header and include paths manually
393       If you aren't using CMake or pkg-config, paths  and  libraries  can  be
394       managed manually.
395
396          $ gcc -o hello_mongoc hello_mongoc.c \
397              -I/usr/local/include/libbson-1.0 -I/usr/local/include/libmongoc-1.0 \
398              -lmongoc-1.0 -lbson-1.0
399          $ ./hello_mongoc
400          { "ok" : 1.000000 }
401
402       For  Windows users, the code can be compiled and run with the following
403       commands. (This assumes that the MongoDB C Driver has been installed to
404       C:\mongo-c-driver; change the include directory as needed.)
405
406          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 hello_mongoc.c
407          C:\> hello_mongoc
408          { "ok" : 1.000000 }
409
410   Use libmongoc in a Microsoft Visual Studio Project
411       See the libmongoc and Visual Studio guide.
412
413   Making a Connection
414       Access  MongoDB  with  a  mongoc_client_t. It transparently connects to
415       standalone servers, replica sets and sharded  clusters  on  demand.  To
416       perform  operations  on a database or collection, create a mongoc_data‐
417       base_t or mongoc_collection_t struct from the mongoc_client_t.
418
419       At the start of an application, call mongoc_init before any other  lib‐
420       mongoc functions. At the end, call the appropriate destroy function for
421       each collection, database, or client handle, in reverse order from  how
422       they were constructed. Call mongoc_cleanup before exiting.
423
424       The  example  below  establishes a connection to a standalone server on
425       localhost, registers the client application as  "connect-example,"  and
426       performs a simple command.
427
428       More  information  about  database  operations can be found in the CRUD
429       Operations and Executing Commands sections. Examples of  connecting  to
430       replica  sets and sharded clusters can be found on the Advanced Connec‐
431       tions page.  hello_mongoc.c.INDENT 0.0
432
433          #include <mongoc/mongoc.h>
434
435          int
436          main (int argc, char *argv[])
437          {
438             const char *uri_string = "mongodb://localhost:27017";
439             mongoc_uri_t *uri;
440             mongoc_client_t *client;
441             mongoc_database_t *database;
442             mongoc_collection_t *collection;
443             bson_t *command, reply, *insert;
444             bson_error_t error;
445             char *str;
446             bool retval;
447
448             /*
449              * Required to initialize libmongoc's internals
450              */
451             mongoc_init ();
452
453             /*
454              * Optionally get MongoDB URI from command line
455              */
456             if (argc > 1) {
457                uri_string = argv[1];
458             }
459
460             /*
461              * Safely create a MongoDB URI object from the given string
462              */
463             uri = mongoc_uri_new_with_error (uri_string, &error);
464             if (!uri) {
465                fprintf (stderr,
466                         "failed to parse URI: %s\n"
467                         "error message:       %s\n",
468                         uri_string,
469                         error.message);
470                return EXIT_FAILURE;
471             }
472
473             /*
474              * Create a new client instance
475              */
476             client = mongoc_client_new_from_uri (uri);
477             if (!client) {
478                return EXIT_FAILURE;
479             }
480
481             /*
482              * Register the application name so we can track it in the profile logs
483              * on the server. This can also be done from the URI (see other examples).
484              */
485             mongoc_client_set_appname (client, "connect-example");
486
487             /*
488              * Get a handle on the database "db_name" and collection "coll_name"
489              */
490             database = mongoc_client_get_database (client, "db_name");
491             collection = mongoc_client_get_collection (client, "db_name", "coll_name");
492
493             /*
494              * Do work. This example pings the database, prints the result as JSON and
495              * performs an insert
496              */
497             command = BCON_NEW ("ping", BCON_INT32 (1));
498
499             retval = mongoc_client_command_simple (
500                client, "admin", command, NULL, &reply, &error);
501
502             if (!retval) {
503                fprintf (stderr, "%s\n", error.message);
504                return EXIT_FAILURE;
505             }
506
507             str = bson_as_json (&reply, NULL);
508             printf ("%s\n", str);
509
510             insert = BCON_NEW ("hello", BCON_UTF8 ("world"));
511
512             if (!mongoc_collection_insert_one (collection, insert, NULL, NULL, &error)) {
513                fprintf (stderr, "%s\n", error.message);
514             }
515
516             bson_destroy (insert);
517             bson_destroy (&reply);
518             bson_destroy (command);
519             bson_free (str);
520
521             /*
522              * Release our handles and clean up libmongoc
523              */
524             mongoc_collection_destroy (collection);
525             mongoc_database_destroy (database);
526             mongoc_uri_destroy (uri);
527             mongoc_client_destroy (client);
528             mongoc_cleanup ();
529
530             return EXIT_SUCCESS;
531          }
532
533
534   Creating BSON Documents
535       Documents are stored in MongoDB's data format, BSON. The C driver  uses
536       libbson  to  create BSON documents. There are several ways to construct
537       them: appending key-value pairs, using BCON, or parsing JSON.
538
539   Appending BSON
540       A BSON document, represented as a bson_t in code,  can  be  constructed
541       one field at a time using libbson's append functions.
542
543       For example, to create a document like this:
544
545          {
546             born : ISODate("1906-12-09"),
547             died : ISODate("1992-01-01"),
548             name : {
549                first : "Grace",
550                last : "Hopper"
551             },
552             languages : [ "MATH-MATIC", "FLOW-MATIC", "COBOL" ],
553             degrees: [ { degree: "BA", school: "Vassar" }, { degree: "PhD", school: "Yale" } ]
554          }
555
556       Use the following code:
557
558          #include <bson/bson.h>
559
560          int
561          main (int   argc,
562                char *argv[])
563          {
564             struct tm   born = { 0 };
565             struct tm   died = { 0 };
566             const char *lang_names[] = {"MATH-MATIC", "FLOW-MATIC", "COBOL"};
567             const char *schools[] = {"Vassar", "Yale"};
568             const char *degrees[] = {"BA", "PhD"};
569             uint32_t    i;
570             char        buf[16];
571             const       char *key;
572             size_t      keylen;
573             bson_t     *document;
574             bson_t      child;
575             bson_t      child2;
576             char       *str;
577
578             document = bson_new ();
579
580             /*
581              * Append { "born" : ISODate("1906-12-09") } to the document.
582              * Passing -1 for the length argument tells libbson to calculate the string length.
583              */
584             born.tm_year = 6;  /* years are 1900-based */
585             born.tm_mon = 11;  /* months are 0-based */
586             born.tm_mday = 9;
587             bson_append_date_time (document, "born", -1, mktime (&born) * 1000);
588
589             /*
590              * Append { "died" : ISODate("1992-01-01") } to the document.
591              */
592             died.tm_year = 92;
593             died.tm_mon = 0;
594             died.tm_mday = 1;
595
596             /*
597              * For convenience, this macro passes length -1 by default.
598              */
599             BSON_APPEND_DATE_TIME (document, "died", mktime (&died) * 1000);
600
601             /*
602              * Append a subdocument.
603              */
604             BSON_APPEND_DOCUMENT_BEGIN (document, "name", &child);
605             BSON_APPEND_UTF8 (&child, "first", "Grace");
606             BSON_APPEND_UTF8 (&child, "last", "Hopper");
607             bson_append_document_end (document, &child);
608
609             /*
610              * Append array of strings. Generate keys "0", "1", "2".
611              */
612             BSON_APPEND_ARRAY_BEGIN (document, "languages", &child);
613             for (i = 0; i < sizeof lang_names / sizeof (char *); ++i) {
614                keylen = bson_uint32_to_string (i, &key, buf, sizeof buf);
615                bson_append_utf8 (&child, key, (int) keylen, lang_names[i], -1);
616             }
617             bson_append_array_end (document, &child);
618
619             /*
620              * Array of subdocuments:
621              *    degrees: [ { degree: "BA", school: "Vassar" }, ... ]
622              */
623             BSON_APPEND_ARRAY_BEGIN (document, "degrees", &child);
624             for (i = 0; i < sizeof degrees / sizeof (char *); ++i) {
625                keylen = bson_uint32_to_string (i, &key, buf, sizeof buf);
626                bson_append_document_begin (&child, key, (int) keylen, &child2);
627                BSON_APPEND_UTF8 (&child2, "degree", degrees[i]);
628                BSON_APPEND_UTF8 (&child2, "school", schools[i]);
629                bson_append_document_end (&child, &child2);
630             }
631             bson_append_array_end (document, &child);
632
633             /*
634              * Print the document as a JSON string.
635              */
636             str = bson_as_canonical_extended_json (document, NULL);
637             printf ("%s\n", str);
638             bson_free (str);
639
640             /*
641              * Clean up allocated bson documents.
642              */
643             bson_destroy (document);
644             return 0;
645          }
646
647       See the libbson documentation for all of the types that can be appended
648       to a bson_t.
649
650   Using BCON
651       BSON C Object Notation, BCON for short, is an alternative way  of  con‐
652       structing  BSON documents in a manner closer to the intended format. It
653       has less type-safety than BSON's append functions but results  in  less
654       code.
655
656          #include <bson/bson.h>
657
658          int
659          main (int   argc,
660                char *argv[])
661          {
662             struct tm born = { 0 };
663             struct tm died = { 0 };
664             bson_t   *document;
665             char     *str;
666
667             born.tm_year = 6;
668             born.tm_mon = 11;
669             born.tm_mday = 9;
670
671             died.tm_year = 92;
672             died.tm_mon = 0;
673             died.tm_mday = 1;
674
675             document = BCON_NEW (
676                "born", BCON_DATE_TIME (mktime (&born) * 1000),
677                "died", BCON_DATE_TIME (mktime (&died) * 1000),
678                "name", "{",
679                "first", BCON_UTF8 ("Grace"),
680                "last", BCON_UTF8 ("Hopper"),
681                "}",
682                "languages", "[",
683                BCON_UTF8 ("MATH-MATIC"),
684                BCON_UTF8 ("FLOW-MATIC"),
685                BCON_UTF8 ("COBOL"),
686                "]",
687                "degrees", "[",
688                "{", "degree", BCON_UTF8 ("BA"), "school", BCON_UTF8 ("Vassar"), "}",
689                "{", "degree", BCON_UTF8 ("PhD"), "school", BCON_UTF8 ("Yale"), "}",
690                "]");
691
692             /*
693              * Print the document as a JSON string.
694              */
695             str = bson_as_canonical_extended_json (document, NULL);
696             printf ("%s\n", str);
697             bson_free (str);
698
699             /*
700              * Clean up allocated bson documents.
701              */
702             bson_destroy (document);
703             return 0;
704          }
705
706       Notice that BCON can create arrays, subdocuments and arbitrary fields.
707
708   Creating BSON from JSON
709       For  single  documents,  BSON  can  be  created  from  JSON strings via
710       bson_new_from_json.
711
712          #include <bson/bson.h>
713
714          int
715          main (int   argc,
716                char *argv[])
717          {
718             bson_error_t error;
719             bson_t      *bson;
720             char        *string;
721
722             const char *json = "{\"name\": {\"first\":\"Grace\", \"last\":\"Hopper\"}}";
723             bson = bson_new_from_json ((const uint8_t *)json, -1, &error);
724
725             if (!bson) {
726                fprintf (stderr, "%s\n", error.message);
727                return EXIT_FAILURE;
728             }
729
730             string = bson_as_canonical_extended_json (bson, NULL);
731             printf ("%s\n", string);
732             bson_free (string);
733
734             return 0;
735          }
736
737       To  initialize  BSON  from  a   sequence   of   JSON   documents,   use
738       bson_json_reader_t.
739
740   Basic CRUD Operations
741       This  section demonstrates the basics of using the C Driver to interact
742       with MongoDB.
743
744   Inserting a Document
745       To insert documents into a collection, first obtain a handle to a  mon‐
746       goc_collection_t   via  a  mongoc_client_t.  Then,  use  mongoc_collec‐
747       tion_insert_one to add BSON documents to the collection.  This  example
748       inserts into the database "mydb" and collection "mycoll".
749
750       When  finished,  ensure  that  allocated  structures are freed by using
751       their respective destroy functions.
752
753          #include <bson/bson.h>
754          #include <mongoc/mongoc.h>
755          #include <stdio.h>
756
757          int
758          main (int   argc,
759                char *argv[])
760          {
761              mongoc_client_t *client;
762              mongoc_collection_t *collection;
763              bson_error_t error;
764              bson_oid_t oid;
765              bson_t *doc;
766
767              mongoc_init ();
768
769              client = mongoc_client_new ("mongodb://localhost:27017/?appname=insert-example");
770              collection = mongoc_client_get_collection (client, "mydb", "mycoll");
771
772              doc = bson_new ();
773              bson_oid_init (&oid, NULL);
774              BSON_APPEND_OID (doc, "_id", &oid);
775              BSON_APPEND_UTF8 (doc, "hello", "world");
776
777              if (!mongoc_collection_insert_one (
778                     collection, doc, NULL, NULL, &error)) {
779                  fprintf (stderr, "%s\n", error.message);
780              }
781
782              bson_destroy (doc);
783              mongoc_collection_destroy (collection);
784              mongoc_client_destroy (client);
785              mongoc_cleanup ();
786
787              return 0;
788          }
789
790       Compile the code and run it:
791
792          $ gcc -o insert insert.c $(pkg-config --cflags --libs libmongoc-1.0)
793          $ ./insert
794
795       On Windows:
796
797          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 insert.c
798          C:\> insert
799
800       To verify that the insert succeeded, connect with the MongoDB shell.
801
802          $ mongo
803          MongoDB shell version: 3.0.6
804          connecting to: test
805          > use mydb
806          switched to db mydb
807          > db.mycoll.find()
808          { "_id" : ObjectId("55ef43766cb5f36a3bae6ee4"), "hello" : "world" }
809          >
810
811   Finding a Document
812       To query a MongoDB collection with the C driver, use the function  mon‐
813       goc_collection_find_with_opts().  This returns a cursor to the matching
814       documents. The following examples iterate through  the  result  cursors
815       and print the matches to stdout as JSON strings.
816
817       Use a document as a query specifier; for example,
818
819          { "color" : "red" }
820
821       will match any document with a field named "color" with value "red". An
822       empty document {} can be used to match all documents.
823
824       This first example uses an empty query specifier to find all  documents
825       in the database "mydb" and collection "mycoll".
826
827          #include <bson/bson.h>
828          #include <mongoc/mongoc.h>
829          #include <stdio.h>
830
831          int
832          main (int argc, char *argv[])
833          {
834             mongoc_client_t *client;
835             mongoc_collection_t *collection;
836             mongoc_cursor_t *cursor;
837             const bson_t *doc;
838             bson_t *query;
839             char *str;
840
841             mongoc_init ();
842
843             client =
844                mongoc_client_new ("mongodb://localhost:27017/?appname=find-example");
845             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
846             query = bson_new ();
847             cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
848
849             while (mongoc_cursor_next (cursor, &doc)) {
850                str = bson_as_canonical_extended_json (doc, NULL);
851                printf ("%s\n", str);
852                bson_free (str);
853             }
854
855             bson_destroy (query);
856             mongoc_cursor_destroy (cursor);
857             mongoc_collection_destroy (collection);
858             mongoc_client_destroy (client);
859             mongoc_cleanup ();
860
861             return 0;
862          }
863
864       Compile the code and run it:
865
866          $ gcc -o find find.c $(pkg-config --cflags --libs libmongoc-1.0)
867          $ ./find
868          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
869
870       On Windows:
871
872          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find.c
873          C:\> find
874          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
875
876       To look for a specific document, add a specifier to query. This example
877       adds a call to BSON_APPEND_UTF8() to look for  all  documents  matching
878       {"hello" : "world"}.
879
880          #include <bson/bson.h>
881          #include <mongoc/mongoc.h>
882          #include <stdio.h>
883
884          int
885          main (int argc, char *argv[])
886          {
887             mongoc_client_t *client;
888             mongoc_collection_t *collection;
889             mongoc_cursor_t *cursor;
890             const bson_t *doc;
891             bson_t *query;
892             char *str;
893
894             mongoc_init ();
895
896             client = mongoc_client_new (
897                "mongodb://localhost:27017/?appname=find-specific-example");
898             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
899             query = bson_new ();
900             BSON_APPEND_UTF8 (query, "hello", "world");
901
902             cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
903
904             while (mongoc_cursor_next (cursor, &doc)) {
905                str = bson_as_canonical_extended_json (doc, NULL);
906                printf ("%s\n", str);
907                bson_free (str);
908             }
909
910             bson_destroy (query);
911             mongoc_cursor_destroy (cursor);
912             mongoc_collection_destroy (collection);
913             mongoc_client_destroy (client);
914             mongoc_cleanup ();
915
916             return 0;
917          }
918
919          $ gcc -o find-specific find-specific.c $(pkg-config --cflags --libs libmongoc-1.0)
920          $ ./find-specific
921          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
922
923          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find-specific.c
924          C:\> find-specific
925          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
926
927   Updating a Document
928       This   code   snippet   gives   an   example  of  using  mongoc_collec‐
929       tion_update_one() to update the fields of a document.
930
931       Using the "mydb" database, the following  example  inserts  an  example
932       document  into  the "mycoll" collection. Then, using its _id field, the
933       document is updated with different values and a new field.
934
935          #include <bson/bson.h>
936          #include <mongoc/mongoc.h>
937          #include <stdio.h>
938
939          int
940          main (int argc, char *argv[])
941          {
942             mongoc_collection_t *collection;
943             mongoc_client_t *client;
944             bson_error_t error;
945             bson_oid_t oid;
946             bson_t *doc = NULL;
947             bson_t *update = NULL;
948             bson_t *query = NULL;
949
950             mongoc_init ();
951
952             client =
953                mongoc_client_new ("mongodb://localhost:27017/?appname=update-example");
954             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
955
956             bson_oid_init (&oid, NULL);
957             doc = BCON_NEW ("_id", BCON_OID (&oid), "key", BCON_UTF8 ("old_value"));
958
959             if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) {
960                fprintf (stderr, "%s\n", error.message);
961                goto fail;
962             }
963
964             query = BCON_NEW ("_id", BCON_OID (&oid));
965             update = BCON_NEW ("$set",
966                                "{",
967                                "key",
968                                BCON_UTF8 ("new_value"),
969                                "updated",
970                                BCON_BOOL (true),
971                                "}");
972
973             if (!mongoc_collection_update_one (
974                    collection, query, update, NULL, NULL, &error)) {
975                fprintf (stderr, "%s\n", error.message);
976                goto fail;
977             }
978
979          fail:
980             if (doc)
981                bson_destroy (doc);
982             if (query)
983                bson_destroy (query);
984             if (update)
985                bson_destroy (update);
986
987             mongoc_collection_destroy (collection);
988             mongoc_client_destroy (client);
989             mongoc_cleanup ();
990
991             return 0;
992          }
993
994       Compile the code and run it:
995
996          $ gcc -o update update.c $(pkg-config --cflags --libs libmongoc-1.0)
997          $ ./update
998
999       On Windows:
1000
1001          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 update.c
1002          C:\> update
1003          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
1004
1005       To verify that the update succeeded, connect with the MongoDB shell.
1006
1007          $ mongo
1008          MongoDB shell version: 3.0.6
1009          connecting to: test
1010          > use mydb
1011          switched to db mydb
1012          > db.mycoll.find({"updated" : true})
1013          { "_id" : ObjectId("55ef549236fe322f9490e17b"), "updated" : true, "key" : "new_value" }
1014          >
1015
1016   Deleting a Document
1017       This example illustrates the use of  mongoc_collection_delete_one()  to
1018       delete a document.
1019
1020       The  following  code inserts a sample document into the database "mydb"
1021       and collection  "mycoll".  Then,  it  deletes  all  documents  matching
1022       {"hello" : "world"}.
1023
1024          #include <bson/bson.h>
1025          #include <mongoc/mongoc.h>
1026          #include <stdio.h>
1027
1028          int
1029          main (int argc, char *argv[])
1030          {
1031             mongoc_client_t *client;
1032             mongoc_collection_t *collection;
1033             bson_error_t error;
1034             bson_oid_t oid;
1035             bson_t *doc;
1036
1037             mongoc_init ();
1038
1039             client =
1040                mongoc_client_new ("mongodb://localhost:27017/?appname=delete-example");
1041             collection = mongoc_client_get_collection (client, "test", "test");
1042
1043             doc = bson_new ();
1044             bson_oid_init (&oid, NULL);
1045             BSON_APPEND_OID (doc, "_id", &oid);
1046             BSON_APPEND_UTF8 (doc, "hello", "world");
1047
1048             if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) {
1049                fprintf (stderr, "Insert failed: %s\n", error.message);
1050             }
1051
1052             bson_destroy (doc);
1053
1054             doc = bson_new ();
1055             BSON_APPEND_OID (doc, "_id", &oid);
1056
1057             if (!mongoc_collection_delete_one (
1058                    collection, doc, NULL, NULL, &error)) {
1059                fprintf (stderr, "Delete failed: %s\n", error.message);
1060             }
1061
1062             bson_destroy (doc);
1063             mongoc_collection_destroy (collection);
1064             mongoc_client_destroy (client);
1065             mongoc_cleanup ();
1066
1067             return 0;
1068          }
1069
1070       Compile the code and run it:
1071
1072          $ gcc -o delete delete.c $(pkg-config --cflags --libs libmongoc-1.0)
1073          $ ./delete
1074
1075       On Windows:
1076
1077          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 delete.c
1078          C:\> delete
1079
1080       Use  the  MongoDB  shell  to prove that the documents have been removed
1081       successfully.
1082
1083          $ mongo
1084          MongoDB shell version: 3.0.6
1085          connecting to: test
1086          > use mydb
1087          switched to db mydb
1088          > db.mycoll.count({"hello" : "world"})
1089          0
1090          >
1091
1092   Counting Documents
1093       Counting the number of documents in a MongoDB collection is similar  to
1094       performing  a  find  operation. This example counts the number of docu‐
1095       ments matching {"hello" : "world"} in the database "mydb"  and  collec‐
1096       tion "mycoll".
1097
1098          #include <bson/bson.h>
1099          #include <mongoc/mongoc.h>
1100          #include <stdio.h>
1101
1102          int
1103          main (int argc, char *argv[])
1104          {
1105             mongoc_client_t *client;
1106             mongoc_collection_t *collection;
1107             bson_error_t error;
1108             bson_t *doc;
1109             int64_t count;
1110
1111             mongoc_init ();
1112
1113             client =
1114                mongoc_client_new ("mongodb://localhost:27017/?appname=count-example");
1115             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
1116             doc = bson_new_from_json (
1117                (const uint8_t *) "{\"hello\" : \"world\"}", -1, &error);
1118
1119             count = mongoc_collection_count (
1120                collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error);
1121
1122             if (count < 0) {
1123                fprintf (stderr, "%s\n", error.message);
1124             } else {
1125                printf ("%" PRId64 "\n", count);
1126             }
1127
1128             bson_destroy (doc);
1129             mongoc_collection_destroy (collection);
1130             mongoc_client_destroy (client);
1131             mongoc_cleanup ();
1132
1133             return 0;
1134          }
1135
1136       Compile the code and run it:
1137
1138          $ gcc -o count count.c $(pkg-config --cflags --libs libmongoc-1.0)
1139          $ ./count
1140          1
1141
1142       On Windows:
1143
1144          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 count.c
1145          C:\> count
1146          1
1147
1148   Executing Commands
1149       The  driver provides helper functions for executing MongoDB commands on
1150       client, database and collection structures. These functions return cur‐
1151       sors;  the _simple variants return booleans indicating success or fail‐
1152       ure.
1153
1154       This example executes the  collStats  command  against  the  collection
1155       "mycoll" in database "mydb".
1156
1157          #include <bson/bson.h>
1158          #include <mongoc/mongoc.h>
1159          #include <stdio.h>
1160
1161          int
1162          main (int argc, char *argv[])
1163          {
1164             mongoc_client_t *client;
1165             mongoc_collection_t *collection;
1166             bson_error_t error;
1167             bson_t *command;
1168             bson_t reply;
1169             char *str;
1170
1171             mongoc_init ();
1172
1173             client = mongoc_client_new (
1174                "mongodb://localhost:27017/?appname=executing-example");
1175             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
1176
1177             command = BCON_NEW ("collStats", BCON_UTF8 ("mycoll"));
1178             if (mongoc_collection_command_simple (
1179                    collection, command, NULL, &reply, &error)) {
1180                str = bson_as_canonical_extended_json (&reply, NULL);
1181                printf ("%s\n", str);
1182                bson_free (str);
1183             } else {
1184                fprintf (stderr, "Failed to run command: %s\n", error.message);
1185             }
1186
1187             bson_destroy (command);
1188             bson_destroy (&reply);
1189             mongoc_collection_destroy (collection);
1190             mongoc_client_destroy (client);
1191             mongoc_cleanup ();
1192
1193             return 0;
1194          }
1195
1196       Compile the code and run it:
1197
1198          $ gcc -o executing executing.c $(pkg-config --cflags --libs libmongoc-1.0)
1199          $ ./executing
1200          { "ns" : "mydb.mycoll", "count" : 1, "size" : 48, "avgObjSize" : 48, "numExtents" : 1, "storageSize" : 8192,
1201          "lastExtentSize" : 8192.000000, "paddingFactor" : 1.000000, "userFlags" : 1, "capped" : false, "nindexes" : 1,
1202          "indexDetails" : {  }, "totalIndexSize" : 8176, "indexSizes" : { "_id_" : 8176 }, "ok" : 1.000000 }
1203
1204       On Windows:
1205
1206          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 executing.c
1207          C:\> executing
1208          { "ns" : "mydb.mycoll", "count" : 1, "size" : 48, "avgObjSize" : 48, "numExtents" : 1, "storageSize" : 8192,
1209          "lastExtentSize" : 8192.000000, "paddingFactor" : 1.000000, "userFlags" : 1, "capped" : false, "nindexes" : 1,
1210          "indexDetails" : {  }, "totalIndexSize" : 8176, "indexSizes" : { "_id_" : 8176 }, "ok" : 1.000000 }
1211
1212   Threading
1213       The  MongoDB  C  Driver  is  thread-unaware in the vast majority of its
1214       operations. This  means  it  is  up  to  the  programmer  to  guarantee
1215       thread-safety.
1216
1217       However,  mongoc_client_pool_t  is  thread-safe  and is used to fetch a
1218       mongoc_client_t in a thread-safe manner. After retrieving a client from
1219       the  pool, the client structure should be considered owned by the call‐
1220       ing thread. When the thread is finished, the client  should  be  placed
1221       back into the pool.  example-pool.c.INDENT 0.0
1222
1223          /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs
1224           * libmongoc-1.0) */
1225
1226          /* ./example-pool [CONNECTION_STRING] */
1227
1228          #include <mongoc/mongoc.h>
1229          #include <pthread.h>
1230          #include <stdio.h>
1231
1232          static pthread_mutex_t mutex;
1233          static bool in_shutdown = false;
1234
1235          static void *
1236          worker (void *data)
1237          {
1238             mongoc_client_pool_t *pool = data;
1239             mongoc_client_t *client;
1240             bson_t ping = BSON_INITIALIZER;
1241             bson_error_t error;
1242             bool r;
1243
1244             BSON_APPEND_INT32 (&ping, "ping", 1);
1245
1246             while (true) {
1247                client = mongoc_client_pool_pop (pool);
1248                /* Do something with client. If you are writing an HTTP server, you
1249                 * probably only want to hold onto the client for the portion of the
1250                 * request performing database queries.
1251                 */
1252                r = mongoc_client_command_simple (
1253                   client, "admin", &ping, NULL, NULL, &error);
1254
1255                if (!r) {
1256                   fprintf (stderr, "%s\n", error.message);
1257                }
1258
1259                mongoc_client_pool_push (pool, client);
1260
1261                pthread_mutex_lock (&mutex);
1262                if (in_shutdown || !r) {
1263                   pthread_mutex_unlock (&mutex);
1264                   break;
1265                }
1266
1267                pthread_mutex_unlock (&mutex);
1268             }
1269
1270             bson_destroy (&ping);
1271             return NULL;
1272          }
1273
1274          int
1275          main (int argc, char *argv[])
1276          {
1277             const char *uri_string = "mongodb://127.0.0.1/?appname=pool-example";
1278             mongoc_uri_t *uri;
1279             bson_error_t error;
1280             mongoc_client_pool_t *pool;
1281             pthread_t threads[10];
1282             unsigned i;
1283             void *ret;
1284
1285             pthread_mutex_init (&mutex, NULL);
1286             mongoc_init ();
1287
1288             if (argc > 1) {
1289                uri_string = argv[1];
1290             }
1291
1292             uri = mongoc_uri_new_with_error (uri_string, &error);
1293             if (!uri) {
1294                fprintf (stderr,
1295                         "failed to parse URI: %s\n"
1296                         "error message:       %s\n",
1297                         uri_string,
1298                         error.message);
1299                return EXIT_FAILURE;
1300             }
1301
1302             pool = mongoc_client_pool_new (uri);
1303             mongoc_client_pool_set_error_api (pool, 2);
1304
1305             for (i = 0; i < 10; i++) {
1306                pthread_create (&threads[i], NULL, worker, pool);
1307             }
1308
1309             sleep (10);
1310             pthread_mutex_lock (&mutex);
1311             in_shutdown = true;
1312             pthread_mutex_unlock (&mutex);
1313
1314             for (i = 0; i < 10; i++) {
1315                pthread_join (threads[i], &ret);
1316             }
1317
1318             mongoc_client_pool_destroy (pool);
1319             mongoc_uri_destroy (uri);
1320
1321             mongoc_cleanup ();
1322
1323             return EXIT_SUCCESS;
1324          }
1325
1326
1327   Next Steps
1328       To find information on advanced topics, browse the rest of the C driver
1329       guide or the official MongoDB documentation.
1330
1331       For help with common  issues,  consult  the  Troubleshooting  page.  To
1332       report a bug or request a new feature, follow these instructions.
1333
1334   Authentication
1335       This  guide covers the use of authentication options with the MongoDB C
1336       Driver. Ensure that the MongoDB server is also properly configured  for
1337       authentication  before  making  a connection. For more information, see
1338       the MongoDB security documentation.
1339
1340       The MongoDB C driver supports several authentication mechanisms through
1341       the use of MongoDB connection URIs.
1342
1343       By default, if a username and password are provided as part of the con‐
1344       nection string (and an optional authentication database), they are used
1345       to connect via the default authentication mechanism of the server.
1346
1347       To  select  a specific authentication mechanism other than the default,
1348       see the list of supported mechanism below.
1349
1350          mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authSource=mydb");
1351
1352       Currently supported values  for  the  authMechanism  connection  string
1353       option are:
1354
1355       · SCRAM-SHA-1
1356
1357       · MONGODB-CR (deprecated)
1358
1359       · GSSAPI
1360
1361       · PLAIN
1362
1363       · X509
1364
1365   Basic Authentication (SCRAM-SHA-256)
1366       MongoDB  4.0 introduces support for authenticating using the SCRAM pro‐
1367       tocol with the more secure SHA-256 hash described in  RFC  7677.  Using
1368       this authentication mechanism means that the password is never actually
1369       sent over the wire when authenticating, but  rather  a  computed  proof
1370       that  the client password is the same as the password the server knows.
1371       In MongoDB 4.0, the C driver can determine the correct default  authen‐
1372       tication  mechanism for users with stored SCRAM-SHA-1 and SCRAM-SHA-256
1373       credentials:
1374
1375          mongoc_client_t *client =  mongoc_client_new ("mongodb://user:password@localhost/?authSource=mydb");
1376          /* the correct authMechanism is negotiated between the driver and server. */
1377
1378       Alternatively, SCRAM-SHA-256 can be explicitly specified  as  an  auth‐
1379       Mechanism.
1380
1381          mongoc_client_t *client =  mongoc_client_new ("mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-256&authSource=mydb");
1382
1383       Passwords  for  SCRAM-SHA-256  undergo  the preprocessing step known as
1384       SASLPrep specified in RFC 4013. SASLPrep will  only  be  performed  for
1385       passwords  containing  non-ASCII characters.  SASLPrep requires libicu.
1386       If  libicu  is  not  available,   attempting   to   authenticate   over
1387       SCRAM-SHA-256 with non-ASCII passwords will result in error.
1388
1389       Usernames never undergo SASLPrep.
1390
1391       By  default,  when building the C driver libicu is linked if available.
1392       This can be changed with the ENABLE_ICU cmake  option.  To  specify  an
1393       installation  path  of  libicu, specify ICU_ROOT as a cmake option. See
1394       the FindICU documentation for more information.
1395
1396   Basic Authentication (SCRAM-SHA-1)
1397       The default authentication mechanism before MongoDB 4.0 is  SCRAM-SHA-1
1398       (RFC 5802). Using this authentication mechanism means that the password
1399       is never actually sent over the wire when authenticating, but rather  a
1400       computed proof that the client password is the same as the password the
1401       server knows.
1402
1403          mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-1&authSource=mydb");
1404
1405       NOTE:
1406          SCRAM-SHA-1 authenticates against the admin database by default.  If
1407          the  user  is created in another database, then specifying the auth‐
1408          Source is required.
1409
1410   Legacy Authentication (MONGODB-CR)
1411       The MONGODB-CR authMechanism is deprecated and will no longer  function
1412       in  MongoDB  4.0. Instead, specify no authMechanism and the driver will
1413       use an authentication mechanism compatible with your server.
1414
1415   GSSAPI (Kerberos) Authentication
1416       NOTE:
1417          Kerberos support requires compiling the driver against cyrus-sasl on
1418          UNIX-like  environments.  On  Windows, configure the driver to build
1419          against the Windows Native SSPI.
1420
1421       GSSAPI (Kerberos) authentication is available in the Enterprise Edition
1422       of  MongoDB. To authenticate using GSSAPI, the MongoDB C driver must be
1423       installed with SASL support.
1424
1425       On UNIX-like environments, run the kinit command before using the  fol‐
1426       lowing authentication methods:
1427
1428          $ kinit mongodbuser@EXAMPLE.COM
1429          mongodbuser@EXAMPLE.COM's Password:
1430          $ klistCredentials cache: FILE:/tmp/krb5cc_1000
1431                  Principal: mongodbuser@EXAMPLE.COM
1432
1433            Issued                Expires               Principal
1434          Feb  9 13:48:51 2013  Feb  9 23:48:51 2013  krbtgt/EXAMPLE.COM@EXAMPLE.COM
1435
1436       Now  authenticate  using  the MongoDB URI. GSSAPI authenticates against
1437       the $external virtual database, so a database does not need to be spec‐
1438       ified in the URI. Note that the Kerberos principal must be URL-encoded:
1439
1440          mongoc_client_t *client;
1441
1442          client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI");
1443
1444       NOTE:
1445          GSSAPI  authenticates  against the $external database, so specifying
1446          the authSource database is not required.
1447
1448       The driver supports these GSSAPI properties:
1449
1450       · CANONICALIZE_HOST_NAME: This might be required with  Cyrus-SASL  when
1451         the  hosts  report  different hostnames than what is used in the Ker‐
1452         beros database. The default is "false".
1453
1454       · SERVICE_NAME: Use a different service name than  the  default,  "mon‐
1455         godb".
1456
1457       Set properties in the URL:
1458
1459          mongoc_client_t *client;
1460
1461          client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI&"
1462                                      "authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true");
1463
1464       If  you  encounter  errors  such  as  Invalid net address, check if the
1465       application is behind a NAT (Network Address Translation) firewall.  If
1466       so,  create  a  ticket  that  uses forwardable and addressless Kerberos
1467       tickets. This can be done by passing -f -A to kinit.
1468
1469          $ kinit -f -A mongodbuser@EXAMPLE.COM
1470
1471   SASL Plain Authentication
1472       NOTE:
1473          The MongoDB C Driver must be compiled with SASL support in order  to
1474          use SASL PLAIN authentication.
1475
1476       MongoDB Enterprise Edition supports the SASL PLAIN authentication mech‐
1477       anism, initially intended for  delegating  authentication  to  an  LDAP
1478       server. Using the SASL PLAIN mechanism is very similar to the challenge
1479       response mechanism with usernames and  passwords.  This  authentication
1480       mechanism uses the $external virtual database for LDAP support:
1481
1482       NOTE:
1483          SASL  PLAIN is a clear-text authentication mechanism. It is strongly
1484          recommended to connect to MongoDB using SSL with certificate valida‐
1485          tion when using the PLAIN mechanism.
1486
1487          mongoc_client_t *client;
1488
1489          client = mongoc_client_new ("mongodb://user:password@example.com/?authMechanism=PLAIN");
1490
1491       PLAIN  authenticates  against the $external database, so specifying the
1492       authSource database is not required.
1493
1494   X.509 Certificate Authentication
1495       NOTE:
1496          The MongoDB C Driver must be compiled with  SSL  support  for  X.509
1497          authentication  support.  Once this is done, start a server with the
1498          following options:
1499
1500              $ mongod --sslMode requireSSL --sslPEMKeyFile server.pem --sslCAFile ca.pem
1501
1502       The MONGODB-X509 mechanism authenticates a username  derived  from  the
1503       distinguished  subject  name  of the X.509 certificate presented by the
1504       driver during SSL negotiation. This authentication method requires  the
1505       use of SSL connections with certificate validation.
1506
1507          mongoc_client_t *client;
1508          mongoc_ssl_opt_t ssl_opts = { 0 };
1509
1510          ssl_opts.pem_file = "mycert.pem";
1511          ssl_opts.pem_pwd = "mycertpassword";
1512          ssl_opts.ca_file = "myca.pem";
1513          ssl_opts.ca_dir = "trust_dir";
1514          ssl_opts.weak_cert_validation = false;
1515
1516          client = mongoc_client_new ("mongodb://x509_derived_username@localhost/?authMechanism=MONGODB-X509");
1517          mongoc_client_set_ssl_opts (client, &ssl_opts);
1518
1519       MONGODB-X509  authenticates against the $external database, so specify‐
1520       ing the authSource database is not required. For  more  information  on
1521       the x509_derived_username, see the MongoDB server x.509 tutorial.
1522
1523       NOTE:
1524          The  MongoDB  C  Driver  will  attempt to determine the x509 derived
1525          username when none is provided, and as of MongoDB 3.4 providing  the
1526          username is not required at all.
1527
1528   Basic Troubleshooting
1529   Troubleshooting Checklist
1530       The  following is a short list of things to check when you have a prob‐
1531       lem.
1532
1533       · Did you call mongoc_init() in main()? If not, you will likely  see  a
1534         segfault.
1535
1536       · Have  you  leaked  any  clients  or cursors as can be found with mon‐
1537         goc-stat <PID>?
1538
1539       · Have packets been delivered to the server? See egress bytes from mon‐
1540         goc-stat <PID>.
1541
1542       · Does valgrind show any leaks? Ensure you call mongoc_cleanup() at the
1543         end of your process to cleanup lingering allocations from the MongoDB
1544         C driver.
1545
1546       · If  compiling  your  own copy of MongoDB C Driver, consider using the
1547         cmake option -DENABLE_TRACING=ON to enable function tracing  and  hex
1548         dumps of network packets to STDERR and STDOUT.
1549
1550   Performance Counters
1551       The  MongoDB  C  driver  comes  with an optional unique feature to help
1552       developers and sysadmins troubleshoot problems in production.   Perfor‐
1553       mance  counters  are  available  for each process using the driver.  If
1554       available, the counters can be  accessed  outside  of  the  application
1555       process  via  a  shared  memory segment.  This means that you can graph
1556       statistics about your application process easily from tools like  Munin
1557       or  Nagios.  Your author often uses watch --interval=0.5 -d mongoc-stat
1558       $PID to monitor an application.
1559
1560       Performance counters are only available on Linux  platforms  supporting
1561       shared  memory  segments.   On  supported platforms they are enabled by
1562       default.  Applications can be built without the counters by  specifying
1563       the  cmake  option  -DENABLE_SHM_COUNTERS=OFF. Additionally, if perfor‐
1564       mance counters are already compiled, they can be disabled at runtime by
1565       specifying the environment variable MONGOC_DISABLE_SHM.
1566
1567       Performance counters keep track of the following:
1568
1569       · Active and Disposed Cursors
1570
1571       · Active and Disposed Clients, Client Pools, and Socket Streams.
1572
1573       · Number of operations sent and received, by type.
1574
1575       · Bytes transferred and received.
1576
1577       · Authentication successes and failures.
1578
1579       · Number of wire protocol errors.
1580
1581       To  access  counters for a given process, simply provide the process id
1582       to the mongoc-stat program installed with the MongoDB C Driver.
1583
1584          $ mongoc-stat 22203
1585             Operations : Egress Total        : The number of sent operations.                    : 13247
1586             Operations : Ingress Total       : The number of received operations.                : 13246
1587             Operations : Egress Queries      : The number of sent Query operations.              : 13247
1588             Operations : Ingress Queries     : The number of received Query operations.          : 0
1589             Operations : Egress GetMore      : The number of sent GetMore operations.            : 0
1590             Operations : Ingress GetMore     : The number of received GetMore operations.        : 0
1591             Operations : Egress Insert       : The number of sent Insert operations.             : 0
1592             Operations : Ingress Insert      : The number of received Insert operations.         : 0
1593             Operations : Egress Delete       : The number of sent Delete operations.             : 0
1594             Operations : Ingress Delete      : The number of received Delete operations.         : 0
1595             Operations : Egress Update       : The number of sent Update operations.             : 0
1596             Operations : Ingress Update      : The number of received Update operations.         : 0
1597             Operations : Egress KillCursors  : The number of sent KillCursors operations.        : 0
1598             Operations : Ingress KillCursors : The number of received KillCursors operations.    : 0
1599             Operations : Egress Msg          : The number of sent Msg operations.                : 0
1600             Operations : Ingress Msg         : The number of received Msg operations.            : 0
1601             Operations : Egress Reply        : The number of sent Reply operations.              : 0
1602             Operations : Ingress Reply       : The number of received Reply operations.          : 13246
1603                Cursors : Active              : The number of active cursors.                     : 1
1604                Cursors : Disposed            : The number of disposed cursors.                   : 13246
1605                Clients : Active              : The number of active clients.                     : 1
1606                Clients : Disposed            : The number of disposed clients.                   : 0
1607                Streams : Active              : The number of active streams.                     : 1
1608                Streams : Disposed            : The number of disposed streams.                   : 0
1609                Streams : Egress Bytes        : The number of bytes sent.                         : 794931
1610                Streams : Ingress Bytes       : The number of bytes received.                     : 589694
1611                Streams : N Socket Timeouts   : The number of socket timeouts.                    : 0
1612           Client Pools : Active              : The number of active client pools.                : 1
1613           Client Pools : Disposed            : The number of disposed client pools.              : 0
1614               Protocol : Ingress Errors      : The number of protocol errors on ingress.         : 0
1615                   Auth : Failures            : The number of failed authentication requests.     : 0
1616                   Auth : Success             : The number of successful authentication requests. : 0
1617
1618   Submitting a Bug Report
1619       Think you've found a bug? Want to see a new feature in  the  MongoDB  C
1620       driver? Please open a case in our issue management tool, JIRA:
1621
1622       · Create an account and login.
1623
1624       · Navigate to the CDRIVER project.
1625
1626       · Click  Create  Issue - Please provide as much information as possible
1627         about the issue type and how to reproduce it.
1628
1629       Bug reports in JIRA for all  driver  projects  (i.e.  CDRIVER,  CSHARP,
1630       JAVA) and the Core Server (i.e. SERVER) project are public.
1631
1632   Guides
1633   Common Tasks
1634       Drivers  for  some  other languages provide helper functions to perform
1635       certain common tasks. In the C Driver we must explicitly build commands
1636       to send to the server.
1637
1638       This  snippet  contains  example  code  for  the  explain,  copydb  and
1639       cloneCollection commands.
1640
1641   Setup
1642       First  we'll  write  some  code  to  insert   sample   data:   doc-com‐
1643       mon-insert.c.INDENT 0.0
1644
1645          /* Don't try to compile this file on its own. It's meant to be #included
1646             by example code */
1647
1648          /* Insert some sample data */
1649          bool
1650          insert_data (mongoc_collection_t *collection)
1651          {
1652             mongoc_bulk_operation_t *bulk;
1653             enum N { ndocs = 4 };
1654             bson_t *docs[ndocs];
1655             bson_error_t error;
1656             int i = 0;
1657             bool ret;
1658
1659             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
1660
1661             docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
1662             docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
1663             docs[2] = BCON_NEW (
1664                "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
1665             docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
1666
1667             for (i = 0; i < ndocs; i++) {
1668                mongoc_bulk_operation_insert (bulk, docs[i]);
1669                bson_destroy (docs[i]);
1670                docs[i] = NULL;
1671             }
1672
1673             ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
1674
1675             if (!ret) {
1676                fprintf (stderr, "Error inserting data: %s\n", error.message);
1677             }
1678
1679             mongoc_bulk_operation_destroy (bulk);
1680             return ret;
1681          }
1682
1683          /* A helper which we'll use a lot later on */
1684          void
1685          print_res (const bson_t *reply)
1686          {
1687             char *str;
1688             BSON_ASSERT (reply);
1689             str = bson_as_canonical_extended_json (reply, NULL);
1690             printf ("%s\n", str);
1691             bson_free (str);
1692          }
1693
1694
1695   explain Command
1696       This   is   how   to   use   the   explain  command  in  MongoDB  3.2+:
1697       explain.c.INDENT 0.0
1698
1699          bool
1700          explain (mongoc_collection_t *collection)
1701          {
1702             bson_t *command;
1703             bson_t reply;
1704             bson_error_t error;
1705             bool res;
1706
1707             command = BCON_NEW ("explain",
1708                                 "{",
1709                                 "find",
1710                                 BCON_UTF8 (COLLECTION_NAME),
1711                                 "filter",
1712                                 "{",
1713                                 "x",
1714                                 BCON_INT32 (1),
1715                                 "}",
1716                                 "}");
1717             res = mongoc_collection_command_simple (
1718                collection, command, NULL, &reply, &error);
1719             if (!res) {
1720                fprintf (stderr, "Error with explain: %s\n", error.message);
1721                goto cleanup;
1722             }
1723
1724             /* Do something with the reply */
1725             print_res (&reply);
1726
1727          cleanup:
1728             bson_destroy (&reply);
1729             bson_destroy (command);
1730             return res;
1731          }
1732
1733
1734   copydb Command
1735       This example requires two instances of mongo to be running.
1736
1737       Here's how to use the copydb command to copy a  database  from  another
1738       instance of MongoDB: copydb.c.INDENT 0.0
1739
1740          bool
1741          copydb (mongoc_client_t *client, const char *other_host_and_port)
1742          {
1743             mongoc_database_t *admindb;
1744             bson_t *command;
1745             bson_t reply;
1746             bson_error_t error;
1747             bool res;
1748
1749             BSON_ASSERT (other_host_and_port);
1750             /* Must do this from the admin db */
1751             admindb = mongoc_client_get_database (client, "admin");
1752
1753             command = BCON_NEW ("copydb",
1754                                 BCON_INT32 (1),
1755                                 "fromdb",
1756                                 BCON_UTF8 ("test"),
1757                                 "todb",
1758                                 BCON_UTF8 ("test2"),
1759
1760                                 /* If you want from a different host */
1761                                 "fromhost",
1762                                 BCON_UTF8 (other_host_and_port));
1763             res =
1764                mongoc_database_command_simple (admindb, command, NULL, &reply, &error);
1765             if (!res) {
1766                fprintf (stderr, "Error with copydb: %s\n", error.message);
1767                goto cleanup;
1768             }
1769
1770             /* Do something with the reply */
1771             print_res (&reply);
1772
1773          cleanup:
1774             bson_destroy (&reply);
1775             bson_destroy (command);
1776             mongoc_database_destroy (admindb);
1777
1778             return res;
1779          }
1780
1781
1782   cloneCollection Command
1783       This example requires two instances of mongo to be running.
1784
1785       Here's  an example of the cloneCollection command to clone a collection
1786       from another instance of MongoDB: clone-collection.c.INDENT 0.0
1787
1788          bool
1789          clone_collection (mongoc_database_t *database, const char *other_host_and_port)
1790          {
1791             bson_t *command;
1792             bson_t reply;
1793             bson_error_t error;
1794             bool res;
1795
1796             BSON_ASSERT (other_host_and_port);
1797             command = BCON_NEW ("cloneCollection",
1798                                 BCON_UTF8 ("test.remoteThings"),
1799                                 "from",
1800                                 BCON_UTF8 (other_host_and_port),
1801                                 "query",
1802                                 "{",
1803                                 "x",
1804                                 BCON_INT32 (1),
1805                                 "}");
1806             res =
1807                mongoc_database_command_simple (database, command, NULL, &reply, &error);
1808             if (!res) {
1809                fprintf (stderr, "Error with clone: %s\n", error.message);
1810                goto cleanup;
1811             }
1812
1813             /* Do something with the reply */
1814             print_res (&reply);
1815
1816          cleanup:
1817             bson_destroy (&reply);
1818             bson_destroy (command);
1819
1820             return res;
1821          }
1822
1823
1824   Running the Examples
1825       common-operations.c.INDENT 0.0
1826
1827          /*
1828           * Copyright 2016 MongoDB, Inc.
1829           *
1830           * Licensed under the Apache License, Version 2.0 (the "License");
1831           * you may not use this file except in compliance with the License.
1832           * You may obtain a copy of the License at
1833           *
1834           *   http://www.apache.org/licenses/LICENSE-2.0
1835           *
1836           * Unless required by applicable law or agreed to in writing, software
1837           * distributed under the License is distributed on an "AS IS" BASIS,
1838           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1839           * See the License for the specific language governing permissions and
1840           * limitations under the License.
1841           */
1842
1843
1844          #include <mongoc/mongoc.h>
1845          #include <stdio.h>
1846
1847
1848          const char *COLLECTION_NAME = "things";
1849
1850          #include "../doc-common-insert.c"
1851          #include "explain.c"
1852          #include "copydb.c"
1853          #include "clone-collection.c"
1854
1855
1856          int
1857          main (int argc, char *argv[])
1858          {
1859             mongoc_database_t *database = NULL;
1860             mongoc_client_t *client = NULL;
1861             mongoc_collection_t *collection = NULL;
1862             mongoc_uri_t *uri = NULL;
1863             bson_error_t error;
1864             char *host_and_port;
1865             int res = 0;
1866             char *other_host_and_port = NULL;
1867
1868             if (argc < 2 || argc > 3) {
1869                fprintf (stderr,
1870                         "usage: %s MONGOD-1-CONNECTION-STRING "
1871                         "[MONGOD-2-HOST-NAME:MONGOD-2-PORT]\n",
1872                         argv[0]);
1873                fprintf (stderr,
1874                         "MONGOD-1-CONNECTION-STRING can be "
1875                         "of the following forms:\n");
1876                fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
1877                fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
1878                fprintf (stderr,
1879                         "mongodb://user:pass@localhost:27017\t"
1880                         "local machine on port 27017, and authenticate with username "
1881                         "user and password pass\n");
1882                return EXIT_FAILURE;
1883             }
1884
1885             mongoc_init ();
1886
1887             if (strncmp (argv[1], "mongodb://", 10) == 0) {
1888                host_and_port = bson_strdup (argv[1]);
1889             } else {
1890                host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
1891             }
1892             other_host_and_port = argc > 2 ? argv[2] : NULL;
1893
1894             uri = mongoc_uri_new_with_error (host_and_port, &error);
1895             if (!uri) {
1896                fprintf (stderr,
1897                         "failed to parse URI: %s\n"
1898                         "error message:       %s\n",
1899                         host_and_port,
1900                         error.message);
1901                res = EXIT_FAILURE;
1902                goto cleanup;
1903             }
1904
1905             client = mongoc_client_new_from_uri (uri);
1906             if (!client) {
1907                res = EXIT_FAILURE;
1908                goto cleanup;
1909             }
1910
1911             mongoc_client_set_error_api (client, 2);
1912             database = mongoc_client_get_database (client, "test");
1913             collection = mongoc_database_get_collection (database, COLLECTION_NAME);
1914
1915             printf ("Inserting data\n");
1916             if (!insert_data (collection)) {
1917                res = EXIT_FAILURE;
1918                goto cleanup;
1919             }
1920
1921             printf ("explain\n");
1922             if (!explain (collection)) {
1923                res = EXIT_FAILURE;
1924                goto cleanup;
1925             }
1926
1927             if (other_host_and_port) {
1928                printf ("copydb\n");
1929                if (!copydb (client, other_host_and_port)) {
1930                   res = EXIT_FAILURE;
1931                   goto cleanup;
1932                }
1933
1934                printf ("clone collection\n");
1935                if (!clone_collection (database, other_host_and_port)) {
1936                   res = EXIT_FAILURE;
1937                   goto cleanup;
1938                }
1939             }
1940
1941          cleanup:
1942             if (collection) {
1943                mongoc_collection_destroy (collection);
1944             }
1945
1946             if (database) {
1947                mongoc_database_destroy (database);
1948             }
1949
1950             if (client) {
1951                mongoc_client_destroy (client);
1952             }
1953
1954             if (uri) {
1955                mongoc_uri_destroy (uri);
1956             }
1957
1958             bson_free (host_and_port);
1959             mongoc_cleanup ();
1960             return res;
1961          }
1962
1963
1964First launch two separate instances of mongod  (must  be  done  from  separate
1965shells):
1966
1967          $ mongod
1968
1969          $ mkdir /tmp/db2$ mongod --dbpath /tmp/db2 --port 27018 # second instance
1970
1971       Now compile and run the example program:
1972
1973          $ cd examples/common_operations/$ gcc -Wall -o example common-operations.c $(pkg-config --cflags --libs libmongoc-1.0)$ ./example localhost:27017 localhost:27018
1974          Inserting data
1975          explain
1976          {
1977             "executionStats" : {
1978                "allPlansExecution" : [],
1979                "executionStages" : {
1980                   "advanced" : 19,
1981                   "direction" : "forward" ,
1982                   "docsExamined" : 76,
1983                   "executionTimeMillisEstimate" : 0,
1984                   "filter" : {
1985                      "x" : {
1986                         "$eq" : 1
1987                      }
1988                   },
1989                   "invalidates" : 0,
1990                   "isEOF" : 1,
1991                   "nReturned" : 19,
1992                   "needTime" : 58,
1993                   "needYield" : 0,
1994                   "restoreState" : 0,
1995                   "saveState" : 0,
1996                   "stage" : "COLLSCAN" ,
1997                   "works" : 78
1998                },
1999                "executionSuccess" : true,
2000                "executionTimeMillis" : 0,
2001                "nReturned" : 19,
2002                "totalDocsExamined" : 76,
2003                "totalKeysExamined" : 0
2004             },
2005             "ok" : 1,
2006             "queryPlanner" : {
2007                "indexFilterSet" : false,
2008                "namespace" : "test.things",
2009                "parsedQuery" : {
2010                   "x" : {
2011                      "$eq" : 1
2012                   }
2013                },
2014                "plannerVersion" : 1,
2015                "rejectedPlans" : [],
2016                "winningPlan" : {
2017                   "direction" : "forward" ,
2018                   "filter" : {
2019                      "x" : {
2020                         "$eq" : 1
2021                      }
2022                   },
2023                   "stage" : "COLLSCAN"
2024                }
2025             },
2026             "serverInfo" : {
2027                "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25" ,
2028                "host" : "MacBook-Pro-57.local",
2029                "port" : 27017,
2030                "version" : "3.2.6"
2031             }
2032          }
2033          copydb
2034          { "ok" : 1 }
2035          clone collection
2036          { "ok" : 1 }
2037
2038   Advanced Connections
2039       The  following  guide contains information specific to certain types of
2040       MongoDB configurations.
2041
2042       For an example of connecting to a simple  standalone  server,  see  the
2043       Tutorial.   To  establish  a  connection  with  authentication  options
2044       enabled, see the Authentication page.
2045
2046   Connecting to a Replica Set
2047       Connecting to a replica set is much like  connecting  to  a  standalone
2048       MongoDB  server.  Simply specify the replica set name using the ?repli‐
2049       caSet=myreplset URI option.
2050
2051          #include <bson/bson.h>
2052          #include <mongoc/mongoc.h>
2053
2054          int
2055          main (int argc, char *argv[])
2056          {
2057             mongoc_client_t *client;
2058
2059             mongoc_init ();
2060
2061             /* Create our MongoDB Client */
2062             client = mongoc_client_new (
2063                "mongodb://host01:27017,host02:27017,host03:27017/?replicaSet=myreplset");
2064
2065             /* Do some work */
2066             /* TODO */
2067
2068             /* Clean up */
2069             mongoc_client_destroy (client);
2070             mongoc_cleanup ();
2071
2072             return 0;
2073          }
2074
2075       TIP:
2076          Multiple hostnames can be specified in the MongoDB connection string
2077          URI, with a comma separating hosts in the seed list.
2078
2079          It  is  recommended to use a seed list of members of the replica set
2080          to allow the driver to connect to any node.
2081
2082   Connecting to a Sharded Cluster
2083       To connect to a sharded cluster, specify the mongos  nodes  the  client
2084       should  connect  to. The C Driver will automatically detect that it has
2085       connected to a mongos sharding server.
2086
2087       If more than one hostname is specified, a seed list will be created  to
2088       attempt failover between the mongos instances.
2089
2090       WARNING:
2091          Specifying  the  replicaSet  parameter  when  connecting to a mongos
2092          sharding server is invalid.
2093
2094          #include <bson/bson.h>
2095          #include <mongoc/mongoc.h>
2096
2097          int
2098          main (int argc, char *argv[])
2099          {
2100             mongoc_client_t *client;
2101
2102             mongoc_init ();
2103
2104             /* Create our MongoDB Client */
2105             client = mongoc_client_new ("mongodb://myshard01:27017/");
2106
2107             /* Do something with client ... */
2108
2109             /* Free the client */
2110             mongoc_client_destroy (client);
2111
2112             mongoc_cleanup ();
2113
2114             return 0;
2115          }
2116
2117   Connecting to an IPv6 Address
2118       The MongoDB C Driver will automatically  resolve  IPv6  addresses  from
2119       host  names.  However,  to  specify  an IPv6 address directly, wrap the
2120       address in [].
2121
2122          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://[::1]:27017");
2123
2124   Connecting with IPv4 and IPv6
2125       If connecting to a hostname that has both IPv4 and  IPv6  DNS  records,
2126       the  behavior  follows  RFC-6555.  A  connection to the IPv6 address is
2127       attempted first. If IPv6 fails, then a connection is attempted  to  the
2128       IPv4  address.  If  the  connection  attempt  to IPv6 does not complete
2129       within 250ms, then IPv4 is tried in parallel. Whichever  succeeds  con‐
2130       nection  first  cancels  the other. The successful DNS result is cached
2131       for 10 minutes.
2132
2133       As a consequence, attempts to connect to a  mongod  only  listening  on
2134       IPv4  may  be  delayed  if  there are both A (IPv4) and AAAA (IPv6) DNS
2135       records associated with the host.
2136
2137       To avoid a delay, configure hostnames to match the  MongoDB  configura‐
2138       tion.  That is, only create an A record if the mongod is only listening
2139       on IPv4.
2140
2141   Connecting to a UNIX Domain Socket
2142       On UNIX-like systems, the C Driver can connect directly  to  a  MongoDB
2143       server  using  a  UNIX  domain socket. Pass the URL-encoded path to the
2144       socket, which must be suffixed with .sock. For example, to connect to a
2145       domain socket at /tmp/mongodb-27017.sock:
2146
2147          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://%2Ftmp%2Fmongodb-27017.sock");
2148
2149       Include username and password like so:
2150
2151          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://user:pass@%2Ftmp%2Fmongodb-27017.sock");
2152
2153   Connecting to a server over SSL
2154       These are instructions for configuring TLS/SSL connections.
2155
2156       To run a server locally (on port 27017, for example):
2157
2158          $ mongod --port 27017 --sslMode requireSSL --sslPEMKeyFile server.pem --sslCAFile ca.pem
2159
2160       Add /?ssl=true to the end of a client URI.
2161
2162          mongoc_client_t *client = NULL;
2163          client = mongoc_client_new ("mongodb://localhost:27017/?ssl=true");
2164
2165       MongoDB requires client certificates by default, unless the --sslAllow‐
2166       ConnectionsWithoutCertificates is provided. The C Driver can be config‐
2167       ured to present a client certificate using a mongoc_ssl_opt_t:
2168
2169          const mongoc_ssl_opt_t *ssl_default = mongoc_ssl_opt_get_default ();
2170          mongoc_ssl_opt_t ssl_opts = { 0 };
2171
2172          /* optionally copy in a custom trust directory or file; otherwise the default is used. */
2173          memcpy (&ssl_opts, ssl_default, sizeof ssl_opts);
2174          ssl_opts.pem_file = "client.pem"
2175
2176          mongoc_client_set_ssl_opts (client, &ssl_opts);
2177
2178       The  client  certificate  provided by pem_file must be issued by one of
2179       the server trusted Certificate Authorities listed  in  --sslCAFile,  or
2180       issued by a CA in the native certificate store on the server when omit‐
2181       ted.
2182
2183       To verify the server certificate against a specific CA, provide  a  PEM
2184       armored file with a CA certificate, or concatenated list of CA certifi‐
2185       cates using the ca_file option, or c_rehash directory structure of CAs,
2186       pointed  to  using the ca_dir option. When no ca_file or ca_dir is pro‐
2187       vided, the driver will use CAs provided by the native platform certifi‐
2188       cate store.
2189
2190       See  mongoc_ssl_opt_t  for  more information on the various SSL related
2191       options.
2192
2193   Compressing data to and from MongoDB
2194       MongoDB 3.4 added Snappy compression support, and zlib  compression  in
2195       3.6.   To enable compression support the client must be configured with
2196       which compressors to use:
2197
2198          mongoc_client_t *client = NULL;
2199          client = mongoc_client_new ("mongodb://localhost:27017/?compressors=snappy,zlib");
2200
2201       The compressors option specifies the priority order of compressors  the
2202       client  wants  to use. Messages are compressed if the client and server
2203       share any compressors in common.
2204
2205       Note that the compressor used by the server might not be the same  com‐
2206       pressor  as  the client used.  For example, if the client uses the con‐
2207       nection string compressors=zlib,snappy the client will  use  zlib  com‐
2208       pression  to  send data (if possible), but the server might still reply
2209       using snappy, depending on how the server was configured.
2210
2211       The driver must be built with zlib and/or snappy support to enable com‐
2212       pression  support,  any  unknown  (or not compiled in) compressor value
2213       will be ignored.
2214
2215   Additional Connection Options
2216       The full list of connection options can be found  in  the  mongoc_uri_t
2217       docs.
2218
2219       Certain socket/connection related options are not configurable:
2220
2221             ┌──────────────┬─────────────────────┬─────────────────────┐
2222             │Option        │ Description         │ Value               │
2223             ├──────────────┼─────────────────────┼─────────────────────┤
2224             │SO_KEEPALIVE  │ TCP Keep Alive      │ Enabled             │
2225             ├──────────────┼─────────────────────┼─────────────────────┤
2226             │TCP_KEEPIDLE  │ How  long a connec‐ │ 300 seconds         │
2227             │              │ tion    needs    to │                     │
2228             │              │ remain  idle before │                     │
2229             │              │ TCP starts  sending │                     │
2230             │              │ keepalive probes    │                     │
2231             ├──────────────┼─────────────────────┼─────────────────────┤
2232             │TCP_KEEPINTVL │ The time in seconds │ 10 seconds          │
2233             │              │ between TCP probes  │                     │
2234             ├──────────────┼─────────────────────┼─────────────────────┤
2235             │TCP_KEEPCNT   │ How many probes  to │ 9 probes            │
2236             │              │ send,       without │                     │
2237             │              │ acknowledgement,    │                     │
2238             │              │ before dropping the │                     │
2239             │              │ connection          │                     │
2240             ├──────────────┼─────────────────────┼─────────────────────┤
2241             │TCP_NODELAY   │ Send   packets   as │ Enabled (no buffer‐ │
2242             │              │ soon as possible or │ ing)                │
2243             │              │ buffer small  pack‐ │                     │
2244             │              │ ets   (Nagle  algo‐ │                     │
2245             │              │ rithm)              │                     │
2246             └──────────────┴─────────────────────┴─────────────────────┘
2247
2248   Connection Pooling
2249       The  MongoDB  C  driver  has  two connection modes: single-threaded and
2250       pooled. Single-threaded mode is  optimized  for  embedding  the  driver
2251       within  languages  like  PHP. Multi-threaded programs should use pooled
2252       mode: this mode minimizes the total connection  count,  and  in  pooled
2253       mode  a  background thread monitors the MongoDB server topology, so the
2254       program need not block to scan it.
2255
2256   Single Mode
2257       In single mode, your program creates a mongoc_client_t directly:
2258
2259          mongoc_client_t *client = mongoc_client_new (
2260             "mongodb://hostA,hostB/?replicaSet=my_rs");
2261
2262       The client connects on demand when your program first  uses  it  for  a
2263       MongoDB  operation. Using a non-blocking socket per server, it begins a
2264       check on each server concurrently, and uses the  asynchronous  poll  or
2265       select  function  to  receive  events  from the sockets, until all have
2266       responded or timed out. Put another way, in single-threaded mode the  C
2267       Driver fans out to begin all checks concurrently, then fans in once all
2268       checks have completed or timed out. Once the scan completes, the client
2269       executes your program's operation and returns.
2270
2271       In  single  mode,  the client re-scans the server topology roughly once
2272       per minute. If more than a minute has elapsed since the previous  scan,
2273       the  next operation on the client will block while the client completes
2274       its scan. This interval is configurable  with  heartbeatFrequencyMS  in
2275       the connection string. (See mongoc_uri_t.)
2276
2277       A single client opens one connection per server in your topology: these
2278       connections are used both for scanning the topology and performing nor‐
2279       mal operations.
2280
2281   Pooled Mode
2282       To activate pooled mode, create a mongoc_client_pool_t:
2283
2284          mongoc_uri_t *uri = mongoc_uri_new (
2285             "mongodb://hostA,hostB/?replicaSet=my_rs");
2286
2287          mongoc_client_pool_t *pool = mongoc_client_pool_new (uri);
2288
2289       When your program first calls mongoc_client_pool_pop, the pool launches
2290       a background thread for monitoring. The thread fans out and connects to
2291       all  servers in the connection string, using non-blocking sockets and a
2292       simple event loop. As it receives ismaster responses from the  servers,
2293       it  updates  its view of the server topology. Each time the thread dis‐
2294       covers a new server it begins connecting to it, and adds the new socket
2295       to the list of non-blocking sockets in the event loop.
2296
2297       Each  thread  that  executes MongoDB operations must check out a client
2298       from the pool:
2299
2300          mongoc_client_t *client = mongoc_client_pool_pop (pool);
2301
2302          /* use the client for operations ... */
2303
2304          mongoc_client_pool_push (pool, client);
2305
2306       The  mongoc_client_t  object  is  not  thread-safe,   only   the   mon‐
2307       goc_client_pool_t is.
2308
2309       When  the  driver  is  in  pooled  mode,  your program's operations are
2310       unblocked as soon as monitoring discovers a usable server. For example,
2311       if  a  thread  in your program is waiting to execute an "insert" on the
2312       primary, it is unblocked as soon as the primary is  discovered,  rather
2313       than waiting for all secondaries to be checked as well.
2314
2315       The  pool  opens  one  connection  per  server for monitoring, and each
2316       client opens its own connection to each server it uses for  application
2317       operations.  The background thread re-scans the server topology roughly
2318       every 10 seconds. This interval is configurable with  heartbeatFrequen‐
2319       cyMS in the connection string. (See mongoc_uri_t.)
2320
2321       See  connection_pool_options  to  configure pool size and behavior, and
2322       see mongoc_client_pool_t for an extended example  of  a  multi-threaded
2323       program that uses the driver in pooled mode.
2324
2325   Cursors
2326   Handling Cursor Failures
2327       Cursors  exist on a MongoDB server. However, the mongoc_cursor_t struc‐
2328       ture gives the local process a handle to the cursor. It is possible for
2329       errors  to  occur on the server while iterating a cursor on the client.
2330       Even a network partition may occur. This means that applications should
2331       be robust in handling cursor failures.
2332
2333       While  iterating  cursors,  you  should  check  to  see if an error has
2334       occurred. See the following example  for  how  to  robustly  check  for
2335       errors.
2336
2337          static void
2338          print_all_documents (mongoc_collection_t *collection)
2339          {
2340             mongoc_cursor_t *cursor;
2341             const bson_t *doc;
2342             bson_error_t error;
2343             bson_t query = BSON_INITIALIZER;
2344             char *str;
2345
2346             cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
2347
2348             while (mongoc_cursor_next (cursor, &doc)) {
2349                str = bson_as_canonical_extended_json (doc, NULL);
2350                printf ("%s\n", str);
2351                bson_free (str);
2352             }
2353
2354             if (mongoc_cursor_error (cursor, &error)) {
2355                fprintf (stderr, "Failed to iterate all documents: %s\n", error.message);
2356             }
2357
2358             mongoc_cursor_destroy (cursor);
2359          }
2360
2361   Destroying Server-Side Cursors
2362       The  MongoDB  C  driver will automatically destroy a server-side cursor
2363       when mongoc_cursor_destroy() is called. Failure to call  this  function
2364       when done with a cursor will leak memory client side as well as consume
2365       extra memory server side. If the cursor was configured to  never  time‐
2366       out, it will become a memory leak on the server.
2367
2368   Tailable Cursors
2369       Tailable  cursors  are  cursors  that  remain  open  even after they've
2370       returned a final result. This way, if more documents  are  added  to  a
2371       collection (i.e., to the cursor's result set), then you can continue to
2372       call mongoc_cursor_next() to retrieve those additional results.
2373
2374       Here's a complete test case that demonstrates the use of tailable  cur‐
2375       sors.
2376
2377       NOTE:
2378          Tailable cursors are for capped collections only.
2379
2380       An  example to tail the oplog from a replica set.  mongoc-tail.c.INDENT
2381       0.0
2382
2383          #include <bson/bson.h>
2384          #include <mongoc/mongoc.h>
2385          #include <stdio.h>
2386          #include <stdlib.h>
2387
2388          #ifdef _WIN32
2389          #define sleep(_n) Sleep ((_n) *1000)
2390          #endif
2391
2392
2393          static void
2394          print_bson (const bson_t *b)
2395          {
2396             char *str;
2397
2398             str = bson_as_canonical_extended_json (b, NULL);
2399             fprintf (stdout, "%s\n", str);
2400             bson_free (str);
2401          }
2402
2403
2404          static mongoc_cursor_t *
2405          query_collection (mongoc_collection_t *collection, uint32_t last_time)
2406          {
2407             mongoc_cursor_t *cursor;
2408             bson_t query;
2409             bson_t gt;
2410             bson_t opts;
2411
2412             BSON_ASSERT (collection);
2413
2414             bson_init (&query);
2415             BSON_APPEND_DOCUMENT_BEGIN (&query, "ts", &gt);
2416             BSON_APPEND_TIMESTAMP (&gt, "$gt", last_time, 0);
2417             bson_append_document_end (&query, &gt);
2418
2419             bson_init (&opts);
2420             BSON_APPEND_BOOL (&opts, "tailable", true);
2421             BSON_APPEND_BOOL (&opts, "awaitData", true);
2422
2423             cursor = mongoc_collection_find_with_opts (collection, &query, &opts, NULL);
2424
2425             bson_destroy (&query);
2426             bson_destroy (&opts);
2427
2428             return cursor;
2429          }
2430
2431
2432          static void
2433          tail_collection (mongoc_collection_t *collection)
2434          {
2435             mongoc_cursor_t *cursor;
2436             uint32_t last_time;
2437             const bson_t *doc;
2438             bson_error_t error;
2439             bson_iter_t iter;
2440
2441             BSON_ASSERT (collection);
2442
2443             last_time = (uint32_t) time (NULL);
2444
2445             while (true) {
2446                cursor = query_collection (collection, last_time);
2447                while (!mongoc_cursor_error (cursor, &error) &&
2448                       mongoc_cursor_more (cursor)) {
2449                   if (mongoc_cursor_next (cursor, &doc)) {
2450                      if (bson_iter_init_find (&iter, doc, "ts") &&
2451                          BSON_ITER_HOLDS_TIMESTAMP (&iter)) {
2452                         bson_iter_timestamp (&iter, &last_time, NULL);
2453                      }
2454                      print_bson (doc);
2455                   }
2456                }
2457                if (mongoc_cursor_error (cursor, &error)) {
2458                   if (error.domain == MONGOC_ERROR_SERVER) {
2459                      fprintf (stderr, "%s\n", error.message);
2460                      exit (1);
2461                   }
2462                }
2463
2464                mongoc_cursor_destroy (cursor);
2465                sleep (1);
2466             }
2467          }
2468
2469
2470          int
2471          main (int argc, char *argv[])
2472          {
2473             mongoc_collection_t *collection;
2474             mongoc_client_t *client;
2475             mongoc_uri_t *uri;
2476             bson_error_t error;
2477
2478             if (argc != 2) {
2479                fprintf (stderr, "usage: %s MONGO_URI\n", argv[0]);
2480                return EXIT_FAILURE;
2481             }
2482
2483             mongoc_init ();
2484
2485             uri = mongoc_uri_new_with_error (argv[1], &error);
2486             if (!uri) {
2487                fprintf (stderr,
2488                         "failed to parse URI: %s\n"
2489                         "error message:       %s\n",
2490                         argv[1],
2491                         error.message);
2492                return EXIT_FAILURE;
2493             }
2494
2495             client = mongoc_client_new_from_uri (uri);
2496             if (!client) {
2497                return EXIT_FAILURE;
2498             }
2499
2500             mongoc_client_set_error_api (client, 2);
2501
2502             collection = mongoc_client_get_collection (client, "local", "oplog.rs");
2503
2504             tail_collection (collection);
2505
2506             mongoc_collection_destroy (collection);
2507             mongoc_uri_destroy (uri);
2508             mongoc_client_destroy (client);
2509
2510             return EXIT_SUCCESS;
2511          }
2512
2513
2514Let's compile and run this example against a replica set  to  see  updates  as
2515they are made.
2516
2517          $ gcc -Wall -o mongoc-tail mongoc-tail.c $(pkg-config --cflags --libs libmongoc-1.0)
2518          $ ./mongoc-tail mongodb://example.com/?replicaSet=myReplSet
2519          {
2520              "h" : -8458503739429355503,
2521              "ns" : "test.test",
2522              "o" : {
2523                  "_id" : {
2524                      "$oid" : "5372ab0a25164be923d10d50"
2525                  }
2526              },
2527              "op" : "i",
2528              "ts" : {
2529                  "$timestamp" : {
2530                      "i" : 1,
2531                      "t" : 1400023818
2532                  }
2533              },
2534              "v" : 2
2535          }
2536
2537       The  line of output is a sample from performing db.test.insert({}) from
2538       the mongo shell on the replica set.
2539
2540       See also mongoc_cursor_set_max_await_time_ms.
2541
2542   Bulk Write Operations
2543       This tutorial explains how to take advantage of MongoDB C  driver  bulk
2544       write operation features. Executing write operations in batches reduces
2545       the number of network round trips, increasing write throughput.
2546
2547   Bulk Insert
2548       First we need to fetch a bulk operation handle from the  mongoc_collec‐
2549       tion_t.
2550
2551          mongoc_bulk_operation_t *bulk =
2552             mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2553
2554       We  can now start inserting documents to the bulk operation. These will
2555       be buffered until we execute the operation.
2556
2557       The bulk operation will coalesce insertions as a single batch for  each
2558       consecutive  call  to  mongoc_bulk_operation_insert().  This  creates a
2559       pipelined effect when possible.
2560
2561       To execute the bulk operation and  receive  the  result  we  call  mon‐
2562       goc_bulk_operation_execute().  bulk1.c.INDENT 0.0
2563
2564          #include <assert.h>
2565          #include <bson/bcon.h>
2566          #include <mongoc/mongoc.h>
2567          #include <stdio.h>
2568
2569          static void
2570          bulk1 (mongoc_collection_t *collection)
2571          {
2572             mongoc_bulk_operation_t *bulk;
2573             bson_error_t error;
2574             bson_t *doc;
2575             bson_t reply;
2576             char *str;
2577             bool ret;
2578             int i;
2579
2580             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2581
2582             for (i = 0; i < 10000; i++) {
2583                doc = BCON_NEW ("i", BCON_INT32 (i));
2584                mongoc_bulk_operation_insert (bulk, doc);
2585                bson_destroy (doc);
2586             }
2587
2588             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
2589
2590             str = bson_as_canonical_extended_json (&reply, NULL);
2591             printf ("%s\n", str);
2592             bson_free (str);
2593
2594             if (!ret) {
2595                fprintf (stderr, "Error: %s\n", error.message);
2596             }
2597
2598             bson_destroy (&reply);
2599             mongoc_bulk_operation_destroy (bulk);
2600          }
2601
2602          int
2603          main (int argc, char *argv[])
2604          {
2605             mongoc_client_t *client;
2606             mongoc_collection_t *collection;
2607             const char *uri_string = "mongodb://localhost/?appname=bulk1-example";
2608             mongoc_uri_t *uri;
2609             bson_error_t error;
2610
2611             mongoc_init ();
2612
2613             uri = mongoc_uri_new_with_error (uri_string, &error);
2614             if (!uri) {
2615                fprintf (stderr,
2616                         "failed to parse URI: %s\n"
2617                         "error message:       %s\n",
2618                         uri_string,
2619                         error.message);
2620                return EXIT_FAILURE;
2621             }
2622
2623             client = mongoc_client_new_from_uri (uri);
2624             if (!client) {
2625                return EXIT_FAILURE;
2626             }
2627
2628             mongoc_client_set_error_api (client, 2);
2629             collection = mongoc_client_get_collection (client, "test", "test");
2630
2631             bulk1 (collection);
2632
2633             mongoc_uri_destroy (uri);
2634             mongoc_collection_destroy (collection);
2635             mongoc_client_destroy (client);
2636
2637             mongoc_cleanup ();
2638
2639             return EXIT_SUCCESS;
2640          }
2641
2642
2643Example reply document:
2644
2645          {"nInserted"   : 10000,
2646           "nMatched"    : 0,
2647           "nModified"   : 0,
2648           "nRemoved"    : 0,
2649           "nUpserted"   : 0,
2650           "writeErrors" : []
2651           "writeConcernErrors" : [] }
2652
2653   Mixed Bulk Write Operations
2654       MongoDB C driver also supports executing mixed bulk write operations. A
2655       batch of insert, update, and remove operations can be executed together
2656       using the bulk write operations API.
2657
2658   Ordered Bulk Write Operations
2659       Ordered bulk write operations are batched and sent to the server in the
2660       order provided for serial execution. The reply document  describes  the
2661       type and count of operations performed.  bulk2.c.INDENT 0.0
2662
2663          #include <assert.h>
2664          #include <bson/bcon.h>
2665          #include <mongoc/mongoc.h>
2666          #include <stdio.h>
2667
2668          static void
2669          bulk2 (mongoc_collection_t *collection)
2670          {
2671             mongoc_bulk_operation_t *bulk;
2672             bson_error_t error;
2673             bson_t *query;
2674             bson_t *doc;
2675             bson_t *opts;
2676             bson_t reply;
2677             char *str;
2678             bool ret;
2679             int i;
2680
2681             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2682
2683             /* Remove everything */
2684             query = bson_new ();
2685             mongoc_bulk_operation_remove (bulk, query);
2686             bson_destroy (query);
2687
2688             /* Add a few documents */
2689             for (i = 1; i < 4; i++) {
2690                doc = BCON_NEW ("_id", BCON_INT32 (i));
2691                mongoc_bulk_operation_insert (bulk, doc);
2692                bson_destroy (doc);
2693             }
2694
2695             /* {_id: 1} => {$set: {foo: "bar"}} */
2696             query = BCON_NEW ("_id", BCON_INT32 (1));
2697             doc = BCON_NEW ("$set", "{", "foo", BCON_UTF8 ("bar"), "}");
2698             mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, NULL, &error);
2699             bson_destroy (query);
2700             bson_destroy (doc);
2701
2702             /* {_id: 4} => {'$inc': {'j': 1}} (upsert) */
2703             opts = BCON_NEW ("upsert", BCON_BOOL (true));
2704             query = BCON_NEW ("_id", BCON_INT32 (4));
2705             doc = BCON_NEW ("$inc", "{", "j", BCON_INT32 (1), "}");
2706             mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, opts, &error);
2707             bson_destroy (query);
2708             bson_destroy (doc);
2709             bson_destroy (opts);
2710
2711             /* replace {j:1} with {j:2} */
2712             query = BCON_NEW ("j", BCON_INT32 (1));
2713             doc = BCON_NEW ("j", BCON_INT32 (2));
2714             mongoc_bulk_operation_replace_one_with_opts (bulk, query, doc, NULL, &error);
2715             bson_destroy (query);
2716             bson_destroy (doc);
2717
2718             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
2719
2720             str = bson_as_canonical_extended_json (&reply, NULL);
2721             printf ("%s\n", str);
2722             bson_free (str);
2723
2724             if (!ret) {
2725                printf ("Error: %s\n", error.message);
2726             }
2727
2728             bson_destroy (&reply);
2729             mongoc_bulk_operation_destroy (bulk);
2730          }
2731
2732          int
2733          main (int argc, char *argv[])
2734          {
2735             mongoc_client_t *client;
2736             mongoc_collection_t *collection;
2737             const char *uri_string = "mongodb://localhost/?appname=bulk2-example";
2738             mongoc_uri_t *uri;
2739             bson_error_t error;
2740
2741             mongoc_init ();
2742
2743             uri = mongoc_uri_new_with_error (uri_string, &error);
2744             if (!uri) {
2745                fprintf (stderr,
2746                         "failed to parse URI: %s\n"
2747                         "error message:       %s\n",
2748                         uri_string,
2749                         error.message);
2750                return EXIT_FAILURE;
2751             }
2752
2753             client = mongoc_client_new_from_uri (uri);
2754             if (!client) {
2755                return EXIT_FAILURE;
2756             }
2757
2758             mongoc_client_set_error_api (client, 2);
2759             collection = mongoc_client_get_collection (client, "test", "test");
2760
2761             bulk2 (collection);
2762
2763             mongoc_uri_destroy (uri);
2764             mongoc_collection_destroy (collection);
2765             mongoc_client_destroy (client);
2766
2767             mongoc_cleanup ();
2768
2769             return EXIT_SUCCESS;
2770          }
2771
2772
2773Example reply document:
2774
2775          { "nInserted"   : 3,
2776            "nMatched"    : 2,
2777            "nModified"   : 2,
2778            "nRemoved"    : 10000,
2779            "nUpserted"   : 1,
2780            "upserted"    : [{"index" : 5, "_id" : 4}],
2781            "writeErrors" : []
2782            "writeConcernErrors" : [] }
2783
2784       The  index  field  in  the  upserted  array is the 0-based index of the
2785       upsert operation; in this example, the sixth operation of  the  overall
2786       bulk operation was an upsert, so its index is 5.
2787
2788   Unordered Bulk Write Operations
2789       Unordered  bulk  write operations are batched and sent to the server in
2790       arbitrary order where they may be executed in parallel. Any errors that
2791       occur are reported after all operations are attempted.
2792
2793       In  the  next  example  the  first and third operations fail due to the
2794       unique constraint on _id. Since we are doing  unordered  execution  the
2795       second and fourth operations succeed.  bulk3.c.INDENT 0.0
2796
2797          #include <assert.h>
2798          #include <bson/bcon.h>
2799          #include <mongoc/mongoc.h>
2800          #include <stdio.h>
2801
2802          static void
2803          bulk3 (mongoc_collection_t *collection)
2804          {
2805             bson_t opts = BSON_INITIALIZER;
2806             mongoc_bulk_operation_t *bulk;
2807             bson_error_t error;
2808             bson_t *query;
2809             bson_t *doc;
2810             bson_t reply;
2811             char *str;
2812             bool ret;
2813
2814             /* false indicates unordered */
2815             BSON_APPEND_BOOL (&opts, "ordered", false);
2816             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
2817             bson_destroy (&opts);
2818
2819             /* Add a document */
2820             doc = BCON_NEW ("_id", BCON_INT32 (1));
2821             mongoc_bulk_operation_insert (bulk, doc);
2822             bson_destroy (doc);
2823
2824             /* remove {_id: 2} */
2825             query = BCON_NEW ("_id", BCON_INT32 (2));
2826             mongoc_bulk_operation_remove_one (bulk, query);
2827             bson_destroy (query);
2828
2829             /* insert {_id: 3} */
2830             doc = BCON_NEW ("_id", BCON_INT32 (3));
2831             mongoc_bulk_operation_insert (bulk, doc);
2832             bson_destroy (doc);
2833
2834             /* replace {_id:4} {'i': 1} */
2835             query = BCON_NEW ("_id", BCON_INT32 (4));
2836             doc = BCON_NEW ("i", BCON_INT32 (1));
2837             mongoc_bulk_operation_replace_one (bulk, query, doc, false);
2838             bson_destroy (query);
2839             bson_destroy (doc);
2840
2841             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
2842
2843             str = bson_as_canonical_extended_json (&reply, NULL);
2844             printf ("%s\n", str);
2845             bson_free (str);
2846
2847             if (!ret) {
2848                printf ("Error: %s\n", error.message);
2849             }
2850
2851             bson_destroy (&reply);
2852             mongoc_bulk_operation_destroy (bulk);
2853             bson_destroy (&opts);
2854          }
2855
2856          int
2857          main (int argc, char *argv[])
2858          {
2859             mongoc_client_t *client;
2860             mongoc_collection_t *collection;
2861             const char *uri_string = "mongodb://localhost/?appname=bulk3-example";
2862             mongoc_uri_t *uri;
2863             bson_error_t error;
2864
2865             mongoc_init ();
2866
2867             uri = mongoc_uri_new_with_error (uri_string, &error);
2868             if (!uri) {
2869                fprintf (stderr,
2870                         "failed to parse URI: %s\n"
2871                         "error message:       %s\n",
2872                         uri_string,
2873                         error.message);
2874                return EXIT_FAILURE;
2875             }
2876
2877             client = mongoc_client_new_from_uri (uri);
2878             if (!client) {
2879                return EXIT_FAILURE;
2880             }
2881
2882             mongoc_client_set_error_api (client, 2);
2883             collection = mongoc_client_get_collection (client, "test", "test");
2884
2885             bulk3 (collection);
2886
2887             mongoc_uri_destroy (uri);
2888             mongoc_collection_destroy (collection);
2889             mongoc_client_destroy (client);
2890
2891             mongoc_cleanup ();
2892
2893             return EXIT_SUCCESS;
2894          }
2895
2896
2897Example reply document:
2898
2899          { "nInserted"    : 0,
2900            "nMatched"     : 1,
2901            "nModified"    : 1,
2902            "nRemoved"     : 1,
2903            "nUpserted"    : 0,
2904            "writeErrors"  : [
2905              { "index"  : 0,
2906                "code"   : 11000,
2907                "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }" },
2908              { "index"  : 2,
2909                "code"   : 11000,
2910                "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 3 }" } ],
2911            "writeConcernErrors" : [] }
2912
2913          Error: E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }
2914
2915       The bson_error_t domain is MONGOC_ERROR_COMMAND and its code is 11000.
2916
2917   Bulk Operation Bypassing Document Validation
2918       This feature is only available when using MongoDB 3.2 and later.
2919
2920       By  default bulk operations are validated against the schema, if any is
2921       defined. In certain cases however it may be  necessary  to  bypass  the
2922       document validation.  bulk5.c.INDENT 0.0
2923
2924          #include <assert.h>
2925          #include <bson/bcon.h>
2926          #include <mongoc/mongoc.h>
2927          #include <stdio.h>
2928
2929          static void
2930          bulk5_fail (mongoc_collection_t *collection)
2931          {
2932             mongoc_bulk_operation_t *bulk;
2933             bson_error_t error;
2934             bson_t *doc;
2935             bson_t reply;
2936             char *str;
2937             bool ret;
2938
2939             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2940
2941             /* Two inserts */
2942             doc = BCON_NEW ("_id", BCON_INT32 (31));
2943             mongoc_bulk_operation_insert (bulk, doc);
2944             bson_destroy (doc);
2945
2946             doc = BCON_NEW ("_id", BCON_INT32 (32));
2947             mongoc_bulk_operation_insert (bulk, doc);
2948             bson_destroy (doc);
2949
2950             /* The above documents do not comply to the schema validation rules
2951              * we created previously, so this will result in an error */
2952             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
2953
2954             str = bson_as_canonical_extended_json (&reply, NULL);
2955             printf ("%s\n", str);
2956             bson_free (str);
2957
2958             if (!ret) {
2959                printf ("Error: %s\n", error.message);
2960             }
2961
2962             bson_destroy (&reply);
2963             mongoc_bulk_operation_destroy (bulk);
2964          }
2965
2966          static void
2967          bulk5_success (mongoc_collection_t *collection)
2968          {
2969             mongoc_bulk_operation_t *bulk;
2970             bson_error_t error;
2971             bson_t *doc;
2972             bson_t reply;
2973             char *str;
2974             bool ret;
2975
2976             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2977
2978             /* Allow this document to bypass document validation.
2979              * NOTE: When authentication is enabled, the authenticated user must have
2980              * either the "dbadmin" or "restore" roles to bypass document validation */
2981             mongoc_bulk_operation_set_bypass_document_validation (bulk, true);
2982
2983             /* Two inserts */
2984             doc = BCON_NEW ("_id", BCON_INT32 (31));
2985             mongoc_bulk_operation_insert (bulk, doc);
2986             bson_destroy (doc);
2987
2988             doc = BCON_NEW ("_id", BCON_INT32 (32));
2989             mongoc_bulk_operation_insert (bulk, doc);
2990             bson_destroy (doc);
2991
2992             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
2993
2994             str = bson_as_canonical_extended_json (&reply, NULL);
2995             printf ("%s\n", str);
2996             bson_free (str);
2997
2998             if (!ret) {
2999                printf ("Error: %s\n", error.message);
3000             }
3001
3002             bson_destroy (&reply);
3003             mongoc_bulk_operation_destroy (bulk);
3004          }
3005
3006          int
3007          main (int argc, char *argv[])
3008          {
3009             bson_t *options;
3010             bson_error_t error;
3011             mongoc_client_t *client;
3012             mongoc_collection_t *collection;
3013             mongoc_database_t *database;
3014             const char *uri_string = "mongodb://localhost/?appname=bulk5-example";
3015             mongoc_uri_t *uri;
3016
3017             mongoc_init ();
3018
3019             uri = mongoc_uri_new_with_error (uri_string, &error);
3020             if (!uri) {
3021                fprintf (stderr,
3022                         "failed to parse URI: %s\n"
3023                         "error message:       %s\n",
3024                         uri_string,
3025                         error.message);
3026                return EXIT_FAILURE;
3027             }
3028
3029             client = mongoc_client_new_from_uri (uri);
3030             if (!client) {
3031                return EXIT_FAILURE;
3032             }
3033
3034             mongoc_client_set_error_api (client, 2);
3035             database = mongoc_client_get_database (client, "testasdf");
3036
3037             /* Create schema validator */
3038             options = BCON_NEW (
3039                "validator", "{", "number", "{", "$gte", BCON_INT32 (5), "}", "}");
3040             collection =
3041                mongoc_database_create_collection (database, "collname", options, &error);
3042
3043             if (collection) {
3044                bulk5_fail (collection);
3045                bulk5_success (collection);
3046                mongoc_collection_destroy (collection);
3047             } else {
3048                fprintf (stderr, "Couldn't create collection: '%s'\n", error.message);
3049             }
3050
3051             bson_free (options);
3052             mongoc_uri_destroy (uri);
3053             mongoc_database_destroy (database);
3054             mongoc_client_destroy (client);
3055
3056             mongoc_cleanup ();
3057
3058             return EXIT_SUCCESS;
3059          }
3060
3061
3062Running the above example will result in:
3063
3064          { "nInserted" : 0,
3065            "nMatched" : 0,
3066            "nModified" : 0,
3067            "nRemoved" : 0,
3068            "nUpserted" : 0,
3069            "writeErrors" : [
3070              { "index" : 0,
3071                "code" : 121,
3072                "errmsg" : "Document failed validation" } ] }
3073
3074          Error: Document failed validation
3075
3076          { "nInserted" : 2,
3077            "nMatched" : 0,
3078            "nModified" : 0,
3079            "nRemoved" : 0,
3080            "nUpserted" : 0,
3081            "writeErrors" : [] }
3082
3083       The bson_error_t domain is MONGOC_ERROR_COMMAND.
3084
3085   Bulk Operation Write Concerns
3086       By  default  bulk operations are executed with the write_concern of the
3087       collection they are executed against. A custom  write  concern  can  be
3088       passed   to   the   mongoc_collection_create_bulk_operation_with_opts()
3089       method. Write concern errors (e.g. wtimeout) will be reported after all
3090       operations    are    attempted,    regardless   of   execution   order.
3091       bulk4.c.INDENT 0.0
3092
3093          #include <assert.h>
3094          #include <bson/bcon.h>
3095          #include <mongoc/mongoc.h>
3096          #include <stdio.h>
3097
3098          static void
3099          bulk4 (mongoc_collection_t *collection)
3100          {
3101             bson_t opts = BSON_INITIALIZER;
3102             mongoc_write_concern_t *wc;
3103             mongoc_bulk_operation_t *bulk;
3104             bson_error_t error;
3105             bson_t *doc;
3106             bson_t reply;
3107             char *str;
3108             bool ret;
3109
3110             wc = mongoc_write_concern_new ();
3111             mongoc_write_concern_set_w (wc, 4);
3112             mongoc_write_concern_set_wtimeout (wc, 100); /* milliseconds */
3113             mongoc_write_concern_append (wc, &opts);
3114
3115             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
3116
3117             /* Two inserts */
3118             doc = BCON_NEW ("_id", BCON_INT32 (10));
3119             mongoc_bulk_operation_insert (bulk, doc);
3120             bson_destroy (doc);
3121
3122             doc = BCON_NEW ("_id", BCON_INT32 (11));
3123             mongoc_bulk_operation_insert (bulk, doc);
3124             bson_destroy (doc);
3125
3126             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3127
3128             str = bson_as_canonical_extended_json (&reply, NULL);
3129             printf ("%s\n", str);
3130             bson_free (str);
3131
3132             if (!ret) {
3133                printf ("Error: %s\n", error.message);
3134             }
3135
3136             bson_destroy (&reply);
3137             mongoc_bulk_operation_destroy (bulk);
3138             mongoc_write_concern_destroy (wc);
3139             bson_destroy (&opts);
3140          }
3141
3142          int
3143          main (int argc, char *argv[])
3144          {
3145             mongoc_client_t *client;
3146             mongoc_collection_t *collection;
3147             const char *uri_string = "mongodb://localhost/?appname=bulk4-example";
3148             mongoc_uri_t *uri;
3149             bson_error_t error;
3150
3151             mongoc_init ();
3152
3153             uri = mongoc_uri_new_with_error (uri_string, &error);
3154             if (!uri) {
3155                fprintf (stderr,
3156                         "failed to parse URI: %s\n"
3157                         "error message:       %s\n",
3158                         uri_string,
3159                         error.message);
3160                return EXIT_FAILURE;
3161             }
3162
3163             client = mongoc_client_new_from_uri (uri);
3164             if (!client) {
3165                return EXIT_FAILURE;
3166             }
3167
3168             mongoc_client_set_error_api (client, 2);
3169             collection = mongoc_client_get_collection (client, "test", "test");
3170
3171             bulk4 (collection);
3172
3173             mongoc_uri_destroy (uri);
3174             mongoc_collection_destroy (collection);
3175             mongoc_client_destroy (client);
3176
3177             mongoc_cleanup ();
3178
3179             return EXIT_SUCCESS;
3180          }
3181
3182
3183Example reply document and error message:
3184
3185          { "nInserted"    : 2,
3186            "nMatched"     : 0,
3187            "nModified"    : 0,
3188            "nRemoved"     : 0,
3189            "nUpserted"    : 0,
3190            "writeErrors"  : [],
3191            "writeConcernErrors" : [
3192              { "code"   : 64,
3193                "errmsg" : "waiting for replication timed out" }
3194          ] }
3195
3196          Error: waiting for replication timed out
3197
3198       The bson_error_t domain  is  MONGOC_ERROR_WRITE_CONCERN  if  there  are
3199       write  concern errors and no write errors. Write errors indicate failed
3200       operations, so they take precedence over write  concern  errors,  which
3201       mean merely that the write concern is not satisfied yet.
3202
3203   Setting Collation Order
3204       This  feature  is  only  available  when  using  MongoDB 3.4 and later.
3205       bulk-collation.c.INDENT 0.0
3206
3207          #include <bson/bcon.h>
3208          #include <mongoc/mongoc.h>
3209          #include <stdio.h>
3210
3211          static void
3212          bulk_collation (mongoc_collection_t *collection)
3213          {
3214             mongoc_bulk_operation_t *bulk;
3215             bson_t *opts;
3216             bson_t *doc;
3217             bson_t *selector;
3218             bson_t *update;
3219             bson_error_t error;
3220             bson_t reply;
3221             char *str;
3222             uint32_t ret;
3223
3224             /* insert {_id: "one"} and {_id: "One"} */
3225             bulk = mongoc_collection_create_bulk_operation_with_opts (
3226                collection, NULL);
3227             doc = BCON_NEW ("_id", BCON_UTF8 ("one"));
3228             mongoc_bulk_operation_insert (bulk, doc);
3229             bson_destroy (doc);
3230
3231             doc = BCON_NEW ("_id", BCON_UTF8 ("One"));
3232             mongoc_bulk_operation_insert (bulk, doc);
3233             bson_destroy (doc);
3234
3235             /* "One" normally sorts before "one"; make "one" come first */
3236             opts = BCON_NEW ("collation",
3237                              "{",
3238                              "locale",
3239                              BCON_UTF8 ("en_US"),
3240                              "caseFirst",
3241                              BCON_UTF8 ("lower"),
3242                              "}");
3243
3244             /* set x=1 on the document with _id "One", which now sorts after "one" */
3245             update = BCON_NEW ("$set", "{", "x", BCON_INT64 (1), "}");
3246             selector = BCON_NEW ("_id", "{", "$gt", BCON_UTF8 ("one"), "}");
3247             mongoc_bulk_operation_update_one_with_opts (
3248                bulk, selector, update, opts, &error);
3249
3250             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3251
3252             str = bson_as_canonical_extended_json (&reply, NULL);
3253             printf ("%s\n", str);
3254             bson_free (str);
3255
3256             if (!ret) {
3257                printf ("Error: %s\n", error.message);
3258             }
3259
3260             bson_destroy (&reply);
3261             bson_destroy (update);
3262             bson_destroy (selector);
3263             bson_destroy (opts);
3264             mongoc_bulk_operation_destroy (bulk);
3265          }
3266
3267          int
3268          main (int argc, char *argv[])
3269          {
3270             mongoc_client_t *client;
3271             mongoc_collection_t *collection;
3272             const char *uri_string = "mongodb://localhost/?appname=bulk-collation";
3273             mongoc_uri_t *uri;
3274             bson_error_t error;
3275
3276             mongoc_init ();
3277
3278             uri = mongoc_uri_new_with_error (uri_string, &error);
3279             if (!uri) {
3280                fprintf (stderr,
3281                         "failed to parse URI: %s\n"
3282                         "error message:       %s\n",
3283                         uri_string,
3284                         error.message);
3285                return EXIT_FAILURE;
3286             }
3287
3288             client = mongoc_client_new_from_uri (uri);
3289             if (!client) {
3290                return EXIT_FAILURE;
3291             }
3292
3293             mongoc_client_set_error_api (client, 2);
3294             collection = mongoc_client_get_collection (client, "db", "collection");
3295             bulk_collation (collection);
3296
3297             mongoc_uri_destroy (uri);
3298             mongoc_collection_destroy (collection);
3299             mongoc_client_destroy (client);
3300
3301             mongoc_cleanup ();
3302
3303             return EXIT_SUCCESS;
3304          }
3305
3306
3307Running the above example will result in:
3308
3309          { "nInserted" : 2,
3310             "nMatched" : 1,
3311             "nModified" : 1,
3312             "nRemoved" : 0,
3313             "nUpserted" : 0,
3314             "writeErrors" : [  ]
3315          }
3316
3317   Unacknowledged Bulk Writes
3318       Set "w" to zero for an unacknowledged write.  The  driver  sends  unac‐
3319       knowledged  writes  using  the legacy opcodes OP_INSERT, OP_UPDATE, and
3320       OP_DELETE.  bulk6.c.INDENT 0.0
3321
3322          #include <bson/bcon.h>
3323          #include <mongoc/mongoc.h>
3324          #include <stdio.h>
3325
3326          static void
3327          bulk6 (mongoc_collection_t *collection)
3328          {
3329             bson_t opts = BSON_INITIALIZER;
3330             mongoc_write_concern_t *wc;
3331             mongoc_bulk_operation_t *bulk;
3332             bson_error_t error;
3333             bson_t *doc;
3334             bson_t *selector;
3335             bson_t reply;
3336             char *str;
3337             bool ret;
3338
3339             wc = mongoc_write_concern_new ();
3340             mongoc_write_concern_set_w (wc, 0);
3341             mongoc_write_concern_append (wc, &opts);
3342
3343             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
3344
3345             doc = BCON_NEW ("_id", BCON_INT32 (10));
3346             mongoc_bulk_operation_insert (bulk, doc);
3347             bson_destroy (doc);
3348
3349             selector = BCON_NEW ("_id", BCON_INT32 (11));
3350             mongoc_bulk_operation_remove_one (bulk, selector);
3351             bson_destroy (selector);
3352
3353             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3354
3355             str = bson_as_canonical_extended_json (&reply, NULL);
3356             printf ("%s\n", str);
3357             bson_free (str);
3358
3359             if (!ret) {
3360                printf ("Error: %s\n", error.message);
3361             }
3362
3363             bson_destroy (&reply);
3364             mongoc_bulk_operation_destroy (bulk);
3365             mongoc_write_concern_destroy (wc);
3366             bson_destroy (&opts);
3367          }
3368
3369          int
3370          main (int argc, char *argv[])
3371          {
3372             mongoc_client_t *client;
3373             mongoc_collection_t *collection;
3374             const char *uri_string = "mongodb://localhost/?appname=bulk6-example";
3375             mongoc_uri_t *uri;
3376             bson_error_t error;
3377
3378             mongoc_init ();
3379
3380             uri = mongoc_uri_new_with_error (uri_string, &error);
3381             if (!uri) {
3382                fprintf (stderr,
3383                         "failed to parse URI: %s\n"
3384                         "error message:       %s\n",
3385                         uri_string,
3386                         error.message);
3387                return EXIT_FAILURE;
3388             }
3389
3390             client = mongoc_client_new_from_uri (uri);
3391             if (!client) {
3392                return EXIT_FAILURE;
3393             }
3394
3395             mongoc_client_set_error_api (client, 2);
3396             collection = mongoc_client_get_collection (client, "test", "test");
3397
3398             bulk6 (collection);
3399
3400             mongoc_uri_destroy (uri);
3401             mongoc_collection_destroy (collection);
3402             mongoc_client_destroy (client);
3403
3404             mongoc_cleanup ();
3405
3406             return EXIT_SUCCESS;
3407          }
3408
3409
3410The reply document is empty:
3411
3412          { }
3413
3414   Further Reading
3415       See the Driver Bulk API Spec, which describes bulk write operations for
3416       all MongoDB drivers.
3417
3418   Aggregation Framework Examples
3419       This  document provides a number of practical examples that display the
3420       capabilities of the aggregation framework.
3421
3422       The Aggregations using the Zip Codes Data Set examples uses a  publicly
3423       available  data  set  of  all  zipcodes  and  populations in the United
3424       States. These data are available at: zips.json.
3425
3426   Requirements
3427       Let's check if everything is installed.
3428
3429       Use the following command  to  load  zips.json  data  set  into  mongod
3430       instance:
3431
3432          $ mongoimport --drop -d test -c zipcodes zips.json
3433
3434       Let's use the MongoDB shell to verify that everything was imported suc‐
3435       cessfully.
3436
3437          $ mongo test
3438          connecting to: test
3439          > db.zipcodes.count()
3440          29467
3441          > db.zipcodes.findOne()
3442          {
3443                "_id" : "35004",
3444                "city" : "ACMAR",
3445                "loc" : [
3446                        -86.51557,
3447                        33.584132
3448                ],
3449                "pop" : 6055,
3450                "state" : "AL"
3451          }
3452
3453   Aggregations using the Zip Codes Data Set
3454       Each document in this collection has the following form:
3455
3456          {
3457            "_id" : "35004",
3458            "city" : "Acmar",
3459            "state" : "AL",
3460            "pop" : 6055,
3461            "loc" : [-86.51557, 33.584132]
3462          }
3463
3464       In these documents:
3465
3466       · The _id field holds the zipcode as a string.
3467
3468       · The city field holds the city name.
3469
3470       · The state field holds the two letter state abbreviation.
3471
3472       · The pop field holds the population.
3473
3474       · The loc field holds the location as a [latitude, longitude] array.
3475
3476   States with Populations Over 10 Million
3477       To get all states with a population greater than 10  million,  use  the
3478       following aggregation pipeline: aggregation1.c.INDENT 0.0
3479
3480          #include <mongoc/mongoc.h>
3481          #include <stdio.h>
3482
3483          static void
3484          print_pipeline (mongoc_collection_t *collection)
3485          {
3486             mongoc_cursor_t *cursor;
3487             bson_error_t error;
3488             const bson_t *doc;
3489             bson_t *pipeline;
3490             char *str;
3491
3492             pipeline = BCON_NEW ("pipeline",
3493                                  "[",
3494                                  "{",
3495                                  "$group",
3496                                  "{",
3497                                  "_id",
3498                                  "$state",
3499                                  "total_pop",
3500                                  "{",
3501                                  "$sum",
3502                                  "$pop",
3503                                  "}",
3504                                  "}",
3505                                  "}",
3506                                  "{",
3507                                  "$match",
3508                                  "{",
3509                                  "total_pop",
3510                                  "{",
3511                                  "$gte",
3512                                  BCON_INT32 (10000000),
3513                                  "}",
3514                                  "}",
3515                                  "}",
3516                                  "]");
3517
3518             cursor = mongoc_collection_aggregate (
3519                collection, MONGOC_QUERY_NONE, pipeline, NULL, NULL);
3520
3521             while (mongoc_cursor_next (cursor, &doc)) {
3522                str = bson_as_canonical_extended_json (doc, NULL);
3523                printf ("%s\n", str);
3524                bson_free (str);
3525             }
3526
3527             if (mongoc_cursor_error (cursor, &error)) {
3528                fprintf (stderr, "Cursor Failure: %s\n", error.message);
3529             }
3530
3531             mongoc_cursor_destroy (cursor);
3532             bson_destroy (pipeline);
3533          }
3534
3535          int
3536          main (int argc, char *argv[])
3537          {
3538             mongoc_client_t *client;
3539             mongoc_collection_t *collection;
3540             const char *uri_string =
3541                "mongodb://localhost:27017/?appname=aggregation-example";
3542             mongoc_uri_t *uri;
3543             bson_error_t error;
3544
3545             mongoc_init ();
3546
3547             uri = mongoc_uri_new_with_error (uri_string, &error);
3548             if (!uri) {
3549                fprintf (stderr,
3550                         "failed to parse URI: %s\n"
3551                         "error message:       %s\n",
3552                         uri_string,
3553                         error.message);
3554                return EXIT_FAILURE;
3555             }
3556
3557             client = mongoc_client_new_from_uri (uri);
3558             if (!client) {
3559                return EXIT_FAILURE;
3560             }
3561
3562             mongoc_client_set_error_api (client, 2);
3563             collection = mongoc_client_get_collection (client, "test", "zipcodes");
3564
3565             print_pipeline (collection);
3566
3567             mongoc_uri_destroy (uri);
3568             mongoc_collection_destroy (collection);
3569             mongoc_client_destroy (client);
3570
3571             mongoc_cleanup ();
3572
3573             return EXIT_SUCCESS;
3574          }
3575
3576
3577You should see a result like the following:
3578
3579          { "_id" : "PA", "total_pop" : 11881643 }
3580          { "_id" : "OH", "total_pop" : 10847115 }
3581          { "_id" : "NY", "total_pop" : 17990455 }
3582          { "_id" : "FL", "total_pop" : 12937284 }
3583          { "_id" : "TX", "total_pop" : 16986510 }
3584          { "_id" : "IL", "total_pop" : 11430472 }
3585          { "_id" : "CA", "total_pop" : 29760021 }
3586
3587       The  above  aggregation  pipeline is build from two pipeline operators:
3588       $group and $match.
3589
3590       The $group pipeline operator requires _id field where we specify group‐
3591       ing;  remaining fields specify how to generate composite value and must
3592       use one of the group aggregation functions: $addToSet,  $first,  $last,
3593       $max,  $min,  $avg, $push, $sum. The $match pipeline operator syntax is
3594       the same as the read operation query syntax.
3595
3596       The $group process reads all documents and for each state it creates  a
3597       separate document, for example:
3598
3599          { "_id" : "WA", "total_pop" : 4866692 }
3600
3601       The  total_pop field uses the $sum aggregation function to sum the val‐
3602       ues of all pop fields in the source documents.
3603
3604       Documents created by $group are piped to the $match pipeline  operator.
3605       It returns the documents with the value of total_pop field greater than
3606       or equal to 10 million.
3607
3608   Average City Population by State
3609       To get the first three states with the greatest average population  per
3610       city, use the following aggregation:
3611
3612          pipeline = BCON_NEW ("pipeline", "[",
3613             "{", "$group", "{", "_id", "{", "state", "$state", "city", "$city", "}", "pop", "{", "$sum", "$pop", "}", "}", "}",
3614             "{", "$group", "{", "_id", "$_id.state", "avg_city_pop", "{", "$avg", "$pop", "}", "}", "}",
3615             "{", "$sort", "{", "avg_city_pop", BCON_INT32 (-1), "}", "}",
3616             "{", "$limit", BCON_INT32 (3) "}",
3617          "]");
3618
3619       This aggregate pipeline produces:
3620
3621          { "_id" : "DC", "avg_city_pop" : 303450.0 }
3622          { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
3623          { "_id" : "CA", "avg_city_pop" : 27735.341099720412 }
3624
3625       The  above aggregation pipeline is build from three pipeline operators:
3626       $group, $sort and $limit.
3627
3628       The first $group operator creates the following documents:
3629
3630          { "_id" : { "state" : "WY", "city" : "Smoot" }, "pop" : 414 }
3631
3632       Note, that the $group operator can't use nested  documents  except  the
3633       _id field.
3634
3635       The  second  $group  uses these documents to create the following docu‐
3636       ments:
3637
3638          { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
3639
3640       These documents are sorted by  the  avg_city_pop  field  in  descending
3641       order.  Finally, the $limit pipeline operator returns the first 3 docu‐
3642       ments from the sorted set.
3643
3644   distinct and mapReduce
3645       This document provides some practical, simple, examples to  demonstrate
3646       the distinct and mapReduce commands.
3647
3648   Setup
3649       First   we'll   write   some  code  to  insert  sample  data:  doc-com‐
3650       mon-insert.c.INDENT 0.0
3651
3652          /* Don't try to compile this file on its own. It's meant to be #included
3653             by example code */
3654
3655          /* Insert some sample data */
3656          bool
3657          insert_data (mongoc_collection_t *collection)
3658          {
3659             mongoc_bulk_operation_t *bulk;
3660             enum N { ndocs = 4 };
3661             bson_t *docs[ndocs];
3662             bson_error_t error;
3663             int i = 0;
3664             bool ret;
3665
3666             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
3667
3668             docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
3669             docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
3670             docs[2] = BCON_NEW (
3671                "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
3672             docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
3673
3674             for (i = 0; i < ndocs; i++) {
3675                mongoc_bulk_operation_insert (bulk, docs[i]);
3676                bson_destroy (docs[i]);
3677                docs[i] = NULL;
3678             }
3679
3680             ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
3681
3682             if (!ret) {
3683                fprintf (stderr, "Error inserting data: %s\n", error.message);
3684             }
3685
3686             mongoc_bulk_operation_destroy (bulk);
3687             return ret;
3688          }
3689
3690          /* A helper which we'll use a lot later on */
3691          void
3692          print_res (const bson_t *reply)
3693          {
3694             char *str;
3695             BSON_ASSERT (reply);
3696             str = bson_as_canonical_extended_json (reply, NULL);
3697             printf ("%s\n", str);
3698             bson_free (str);
3699          }
3700
3701
3702   distinct command
3703       This is how to use the distinct command to get the distinct values of x
3704       which are greater than 1: distinct.c.INDENT 0.0
3705
3706          bool
3707          distinct (mongoc_database_t *database)
3708          {
3709             bson_t *command;
3710             bson_t reply;
3711             bson_error_t error;
3712             bool res;
3713             bson_iter_t iter;
3714             bson_iter_t array_iter;
3715             double val;
3716
3717             command = BCON_NEW ("distinct",
3718                                 BCON_UTF8 (COLLECTION_NAME),
3719                                 "key",
3720                                 BCON_UTF8 ("x"),
3721                                 "query",
3722                                 "{",
3723                                 "x",
3724                                 "{",
3725                                 "$gt",
3726                                 BCON_DOUBLE (1.0),
3727                                 "}",
3728                                 "}");
3729             res =
3730                mongoc_database_command_simple (database, command, NULL, &reply, &error);
3731             if (!res) {
3732                fprintf (stderr, "Error with distinct: %s\n", error.message);
3733                goto cleanup;
3734             }
3735
3736             /* Do something with reply (in this case iterate through the values) */
3737             if (!(bson_iter_init_find (&iter, &reply, "values") &&
3738                   BSON_ITER_HOLDS_ARRAY (&iter) &&
3739                   bson_iter_recurse (&iter, &array_iter))) {
3740                fprintf (stderr, "Couldn't extract \"values\" field from response\n");
3741                goto cleanup;
3742             }
3743
3744             while (bson_iter_next (&array_iter)) {
3745                if (BSON_ITER_HOLDS_DOUBLE (&array_iter)) {
3746                   val = bson_iter_double (&array_iter);
3747                   printf ("Next double: %f\n", val);
3748                }
3749             }
3750
3751          cleanup:
3752             /* cleanup */
3753             bson_destroy (command);
3754             bson_destroy (&reply);
3755             return res;
3756          }
3757
3758
3759   mapReduce - basic example
3760       A  simple example using the map reduce framework. It simply adds up the
3761       number of occurrences of each "tag".
3762
3763       First define the map and reduce functions: constants.c.INDENT 0.0
3764
3765          const char *const COLLECTION_NAME = "things";
3766
3767          /* Our map function just emits a single (key, 1) pair for each tag
3768             in the array: */
3769          const char *const MAPPER = "function () {"
3770                                     "this.tags.forEach(function(z) {"
3771                                     "emit(z, 1);"
3772                                     "});"
3773                                     "}";
3774
3775          /* The reduce function sums over all of the emitted values for a
3776             given key: */
3777          const char *const REDUCER = "function (key, values) {"
3778                                      "var total = 0;"
3779                                      "for (var i = 0; i < values.length; i++) {"
3780                                      "total += values[i];"
3781                                      "}"
3782                                      "return total;"
3783                                      "}";
3784          /* Note We can't just return values.length as the reduce function
3785             might be called iteratively on the results of other reduce
3786             steps. */
3787
3788
3789Run the mapReduce command: map-reduce-basic.c.INDENT 0.0
3790
3791          bool
3792          map_reduce_basic (mongoc_database_t *database)
3793          {
3794             bson_t reply;
3795             bson_t *command;
3796             bool res;
3797             bson_error_t error;
3798             mongoc_cursor_t *cursor;
3799             const bson_t *doc;
3800
3801             bool query_done = false;
3802
3803             const char *out_collection_name = "outCollection";
3804             mongoc_collection_t *out_collection;
3805
3806             /* Empty find query */
3807             bson_t find_query = BSON_INITIALIZER;
3808
3809             /* Construct the mapReduce command */
3810
3811             /* Other arguments can also be specified here, like "query" or
3812                "limit" and so on */
3813             command = BCON_NEW ("mapReduce",
3814                                 BCON_UTF8 (COLLECTION_NAME),
3815                                 "map",
3816                                 BCON_CODE (MAPPER),
3817                                 "reduce",
3818                                 BCON_CODE (REDUCER),
3819                                 "out",
3820                                 BCON_UTF8 (out_collection_name));
3821             res =
3822                mongoc_database_command_simple (database, command, NULL, &reply, &error);
3823
3824             if (!res) {
3825                fprintf (stderr, "MapReduce failed: %s\n", error.message);
3826                goto cleanup;
3827             }
3828
3829             /* Do something with the reply (it doesn't contain the mapReduce results) */
3830             print_res (&reply);
3831
3832             /* Now we'll query outCollection to see what the results are */
3833             out_collection =
3834                mongoc_database_get_collection (database, out_collection_name);
3835             cursor = mongoc_collection_find_with_opts (
3836                out_collection, &find_query, NULL, NULL);
3837             query_done = true;
3838
3839             /* Do something with the results */
3840             while (mongoc_cursor_next (cursor, &doc)) {
3841                print_res (doc);
3842             }
3843
3844             if (mongoc_cursor_error (cursor, &error)) {
3845                fprintf (stderr, "ERROR: %s\n", error.message);
3846                res = false;
3847                goto cleanup;
3848             }
3849
3850          cleanup:
3851             /* cleanup */
3852             if (query_done) {
3853                mongoc_cursor_destroy (cursor);
3854                mongoc_collection_destroy (out_collection);
3855             }
3856
3857             bson_destroy (&reply);
3858             bson_destroy (command);
3859
3860             return res;
3861          }
3862
3863
3864   mapReduce - more complicated example
3865       You must have replica set running for this.
3866
3867       In this example we contact a secondary in the replica  set  and  do  an
3868       "inline"   map   reduce,  so  the  results  are  returned  immediately:
3869       map-reduce-advanced.c.INDENT 0.0
3870
3871          bool
3872          map_reduce_advanced (mongoc_database_t *database)
3873          {
3874             bson_t *command;
3875             bson_error_t error;
3876             bool res = true;
3877             mongoc_cursor_t *cursor;
3878             mongoc_read_prefs_t *read_pref;
3879             const bson_t *doc;
3880
3881             /* Construct the mapReduce command */
3882             /* Other arguments can also be specified here, like "query" or "limit"
3883                and so on */
3884
3885             /* Read the results inline from a secondary replica */
3886             command = BCON_NEW ("mapReduce",
3887                                 BCON_UTF8 (COLLECTION_NAME),
3888                                 "map",
3889                                 BCON_CODE (MAPPER),
3890                                 "reduce",
3891                                 BCON_CODE (REDUCER),
3892                                 "out",
3893                                 "{",
3894                                 "inline",
3895                                 "1",
3896                                 "}");
3897
3898             read_pref = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
3899             cursor = mongoc_database_command (
3900                database, MONGOC_QUERY_NONE, 0, 0, 0, command, NULL, read_pref);
3901
3902             /* Do something with the results */
3903             while (mongoc_cursor_next (cursor, &doc)) {
3904                print_res (doc);
3905             }
3906
3907             if (mongoc_cursor_error (cursor, &error)) {
3908                fprintf (stderr, "ERROR: %s\n", error.message);
3909                res = false;
3910             }
3911
3912             mongoc_cursor_destroy (cursor);
3913             mongoc_read_prefs_destroy (read_pref);
3914             bson_destroy (command);
3915
3916             return res;
3917          }
3918
3919
3920   Running the Examples
3921       Here's how to run the example code basic-aggregation.c.INDENT 0.0
3922
3923          /*
3924           * Copyright 2016 MongoDB, Inc.
3925           *
3926           * Licensed under the Apache License, Version 2.0 (the "License");
3927           * you may not use this file except in compliance with the License.
3928           * You may obtain a copy of the License at
3929           *
3930           *   http://www.apache.org/licenses/LICENSE-2.0
3931           *
3932           * Unless required by applicable law or agreed to in writing, software
3933           * distributed under the License is distributed on an "AS IS" BASIS,
3934           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3935           * See the License for the specific language governing permissions and
3936           * limitations under the License.
3937           */
3938
3939
3940          #include <mongoc/mongoc.h>
3941          #include <stdio.h>
3942
3943
3944          #include "constants.c"
3945
3946          #include "../doc-common-insert.c"
3947          #include "distinct.c"
3948          #include "map-reduce-basic.c"
3949          #include "map-reduce-advanced.c"
3950
3951
3952          int
3953          main (int argc, char *argv[])
3954          {
3955             mongoc_database_t *database = NULL;
3956             mongoc_client_t *client = NULL;
3957             mongoc_collection_t *collection = NULL;
3958             mongoc_uri_t *uri = NULL;
3959             bson_error_t error;
3960             char *host_and_port = NULL;
3961             int exit_code = EXIT_FAILURE;
3962
3963             if (argc != 2) {
3964                fprintf (stderr, "usage: %s CONNECTION-STRING\n", argv[0]);
3965                fprintf (stderr,
3966                         "the connection string can be of the following forms:\n");
3967                fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
3968                fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
3969                fprintf (stderr,
3970                         "mongodb://user:pass@localhost:27017\t"
3971                         "local machine on port 27017, and authenticate with username "
3972                         "user and password pass\n");
3973                return exit_code;
3974             }
3975
3976             mongoc_init ();
3977
3978             if (strncmp (argv[1], "mongodb://", 10) == 0) {
3979                host_and_port = bson_strdup (argv[1]);
3980             } else {
3981                host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
3982             }
3983
3984             uri = mongoc_uri_new_with_error (host_and_port, &error);
3985             if (!uri) {
3986                fprintf (stderr,
3987                         "failed to parse URI: %s\n"
3988                         "error message:       %s\n",
3989                         host_and_port,
3990                         error.message);
3991                goto cleanup;
3992             }
3993
3994             client = mongoc_client_new_from_uri (uri);
3995             if (!client) {
3996                goto cleanup;
3997             }
3998
3999             mongoc_client_set_error_api (client, 2);
4000             database = mongoc_client_get_database (client, "test");
4001             collection = mongoc_database_get_collection (database, COLLECTION_NAME);
4002
4003             printf ("Inserting data\n");
4004             if (!insert_data (collection)) {
4005                goto cleanup;
4006             }
4007
4008             printf ("distinct\n");
4009             if (!distinct (database)) {
4010                goto cleanup;
4011             }
4012
4013             printf ("map reduce\n");
4014             if (!map_reduce_basic (database)) {
4015                goto cleanup;
4016             }
4017
4018             printf ("more complicated map reduce\n");
4019             if (!map_reduce_advanced (database)) {
4020                goto cleanup;
4021             }
4022
4023             exit_code = EXIT_SUCCESS;
4024
4025          cleanup:
4026             if (collection) {
4027                mongoc_collection_destroy (collection);
4028             }
4029
4030             if (database) {
4031                mongoc_database_destroy (database);
4032             }
4033
4034             if (client) {
4035                mongoc_client_destroy (client);
4036             }
4037
4038             if (uri) {
4039                mongoc_uri_destroy (uri);
4040             }
4041
4042             if (host_and_port) {
4043                bson_free (host_and_port);
4044             }
4045
4046             mongoc_cleanup ();
4047             return exit_code;
4048          }
4049
4050
4051If you want to try the advanced map reduce example with a secondary,  start  a
4052replica set (instructions for how to do this can be found here).
4053
4054Otherwise, just start an instance of MongoDB:
4055
4056          $ mongod
4057
4058       Now compile and run the example program:
4059
4060          $ cd examples/basic_aggregation/
4061          $ gcc -Wall -o agg-example basic-aggregation.c $(pkg-config --cflags --libs libmongoc-1.0)
4062          $ ./agg-example localhost
4063
4064          Inserting data
4065          distinct
4066          Next double: 2.000000
4067          Next double: 3.000000
4068          map reduce
4069          { "result" : "outCollection", "timeMillis" : 155, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 }
4070          { "_id" : "cat", "value" : 63 }
4071          { "_id" : "dog", "value" : 42 }
4072          { "_id" : "mouse", "value" : 21 }
4073          more complicated map reduce
4074          { "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 }
4075
4076   Using libmongoc in a Microsoft Visual Studio project
4077       Download and install libmongoc on your system, then open Visual Studio,
4078       select "File→New→Project...", and create a new Win32  Console  Applica‐
4079       tion.  [image]
4080
4081       Remember to switch the platform from 32-bit to 64-bit: [image]
4082
4083       Right-click  on  your  console application in the Solution Explorer and
4084       select "Properties". Choose to  edit  properties  for  "All  Configura‐
4085       tions",  expand  the  "C/C++"  options and choose "General". Add to the
4086       "Additional Include Directories" these paths:
4087
4088          C:\mongo-c-driver\include\libbson-1.0
4089          C:\mongo-c-driver\include\libmongoc-1.0
4090       [image]
4091
4092       (If you chose a different CMAKE_INSTALL_PREFIX when you ran CMake, your
4093       include paths will be different.)
4094
4095       Also  in  the Properties dialog, expand the "Linker" options and choose
4096       "Input", and add to the "Additional Dependencies" these libraries:
4097
4098          C:\mongo-c-driver\lib\bson-1.0.lib
4099          C:\mongo-c-driver\lib\mongoc-1.0.lib
4100       [image]
4101
4102       Adding these libraries as dependencies provides linker symbols to build
4103       your  application,  but  to  actually run it, libbson's and libmongoc's
4104       DLLs must be in your executable path. Select "Debugging" in the Proper‐
4105       ties dialog, and set the "Environment" option to:
4106
4107          PATH=c:/mongo-c-driver/bin
4108       [image]
4109
4110       Finally, include "mongoc/mongoc.h" in your project's "stdafx.h":
4111
4112          #include <mongoc/mongoc.h>
4113
4114   Static linking
4115       Following  the  instructions  above,  you  have dynamically linked your
4116       application to the libbson and libmongoc  DLLs.  This  is  usually  the
4117       right  choice.  If  you  want  to  link statically instead, update your
4118       "Additional  Dependencies"  list  by  removing  bson-1.0.lib  and  mon‐
4119       goc-1.0.lib and replacing them with these libraries:
4120
4121          C:\mongo-c-driver\lib\bson-static-1.0.lib
4122          C:\mongo-c-driver\lib\mongoc-static-1.0.lib
4123          ws2_32.lib
4124          Secur32.lib
4125          Crypt32.lib
4126          BCrypt.lib
4127       [image]
4128
4129       (To  explain  the purpose of each library: bson-static-1.0.lib and mon‐
4130       goc-static-1.0.lib are static archives of the driver code.  The  socket
4131       library  ws2_32  is  required by libbson, which uses the socket routine
4132       gethostname to help guarantee ObjectId uniqueness. The  BCrypt  library
4133       is  used  by  libmongoc for SSL connections to MongoDB, and Secur32 and
4134       Crypt32 are required for enterprise authentication  methods  like  Ker‐
4135       beros.)
4136
4137       Finally,  define  two preprocessor symbols before including mongoc/mon‐
4138       goc.h in your stdafx.h:
4139
4140          #define BSON_STATIC
4141          #define MONGOC_STATIC
4142          #include <mongoc/mongoc.h>
4143
4144       Making these changes to your project is only required for static  link‐
4145       ing;  for  most people, the dynamic-linking instructions above are pre‐
4146       ferred.
4147
4148   Next Steps
4149       Now you can build and debug applications  in  Visual  Studio  that  use
4150       libbson  and  libmongoc. Proceed to making-a-connection in the tutorial
4151       to learn how connect to MongoDB and perform operations.
4152
4153   Creating Indexes
4154       To create indexes on a MongoDB collection,  execute  the  createIndexes
4155       command   with   a  command  function  like  mongoc_database_write_com‐
4156       mand_with_opts or  mongoc_collection_write_command_with_opts.  See  the
4157       MongoDB Manual entry for the createIndexes command for details.
4158
4159   Example
4160       example-create-indexes.c.INDENT 0.0
4161
4162          /* gcc example-create-indexes.c -o example-create-indexes $(pkg-config --cflags
4163           * --libs libmongoc-1.0) */
4164
4165          /* ./example-create-indexes [CONNECTION_STRING [COLLECTION_NAME]] */
4166
4167          #include <mongoc/mongoc.h>
4168          #include <stdio.h>
4169          #include <stdlib.h>
4170
4171          int
4172          main (int argc, char *argv[])
4173          {
4174             mongoc_client_t *client;
4175             const char *uri_string =
4176                "mongodb://127.0.0.1/?appname=create-indexes-example";
4177             mongoc_uri_t *uri;
4178             mongoc_database_t *db;
4179             const char *collection_name = "test";
4180             bson_t keys;
4181             char *index_name;
4182             bson_t *create_indexes;
4183             bson_t reply;
4184             char *reply_str;
4185             bson_error_t error;
4186             bool r;
4187
4188             mongoc_init ();
4189
4190             if (argc > 1) {
4191                uri_string = argv[1];
4192             }
4193
4194             if (argc > 2) {
4195                collection_name = argv[2];
4196             }
4197
4198             uri = mongoc_uri_new_with_error (uri_string, &error);
4199             if (!uri) {
4200                fprintf (stderr,
4201                         "failed to parse URI: %s\n"
4202                         "error message:       %s\n",
4203                         uri_string,
4204                         error.message);
4205                return EXIT_FAILURE;
4206             }
4207
4208             client = mongoc_client_new_from_uri (uri);
4209             if (!client) {
4210                return EXIT_FAILURE;
4211             }
4212
4213             mongoc_client_set_error_api (client, 2);
4214             db = mongoc_client_get_database (client, "test");
4215
4216             /* ascending index on field "x" */
4217             bson_init (&keys);
4218             BSON_APPEND_INT32 (&keys, "x", 1);
4219             index_name = mongoc_collection_keys_to_index_string (&keys);
4220             create_indexes = BCON_NEW ("createIndexes",
4221                                        BCON_UTF8 (collection_name),
4222                                        "indexes",
4223                                        "[",
4224                                        "{",
4225                                        "key",
4226                                        BCON_DOCUMENT (&keys),
4227                                        "name",
4228                                        BCON_UTF8 (index_name),
4229                                        "}",
4230                                        "]");
4231
4232             r = mongoc_database_write_command_with_opts (
4233                db, create_indexes, NULL /* opts */, &reply, &error);
4234
4235             reply_str = bson_as_json (&reply, NULL);
4236             printf ("%s\n", reply_str);
4237
4238             if (!r) {
4239                fprintf (stderr, "Error in createIndexes: %s\n", error.message);
4240             }
4241
4242             bson_free (index_name);
4243             bson_free (reply_str);
4244             bson_destroy (&reply);
4245             bson_destroy (create_indexes);
4246             mongoc_database_destroy (db);
4247             mongoc_uri_destroy (uri);
4248             mongoc_client_destroy (client);
4249
4250             mongoc_cleanup ();
4251
4252             return r ? EXIT_SUCCESS : EXIT_FAILURE;
4253          }
4254
4255
4256   Aids for Debugging
4257   GDB
4258       This repository contains a .gdbinit file that contains helper functions
4259       to  aid  debugging  of  data  structures.  GDB  will  load  this   file
4260       automatically  if  you  have  added  the  directory  which contains the
4261       .gdbinit file to GDB's auto-load safe-path, and you start GDB from  the
4262       directory which holds the .gdbinit file.
4263
4264       You  can  see  the  safe-path  with  show  auto-load safe-path on a GDB
4265       prompt. You can configure it by setting it in ~/.gdbinit with:
4266
4267          add-auto-load-safe-path /path/to/mongo-c-driver
4268
4269       If you haven't added the path to your auto-load safe-path, or start GDB
4270       in another directory, load the file with:
4271
4272          source path/to/mongo-c-driver/.gdbinit
4273
4274       The  .gdbinit file defines the printbson function, which shows the con‐
4275       tents of a bson_t * variable.  If you have a  local  bson_t,  then  you
4276       must prefix the variable with a &.
4277
4278       An example GDB session looks like:
4279
4280          (gdb) printbson bson
4281          ALLOC [0x555556cd7310 + 0] (len=475)
4282          {
4283              'bool' : true,
4284              'int32' : NumberInt("42"),
4285              'int64' : NumberLong("3000000042"),
4286              'string' : "Stŕìñg",
4287              'objectId' : ObjectID("5A1442F3122D331C3C6757E1"),
4288              'utcDateTime' : UTCDateTime(1511277299031),
4289              'arrayOfInts' : [
4290                  '0' : NumberInt("1"),
4291                  '1' : NumberInt("2")
4292              ],
4293              'embeddedDocument' : {
4294                  'arrayOfStrings' : [
4295                      '0' : "one",
4296                      '1' : "two"
4297                  ],
4298                  'double' : 2.718280,
4299                  'notherDoc' : {
4300                      'true' : NumberInt("1"),
4301                      'false' : false
4302                  }
4303              },
4304              'binary' : Binary("02", "3031343532333637"),
4305              'regex' : Regex("@[a-z]+@", "im"),
4306              'null' : null,
4307              'js' : JavaScript("print foo"),
4308              'jsws' : JavaScript("print foo") with scope: {
4309                  'f' : NumberInt("42"),
4310                  'a' : [
4311                      '0' : 3.141593,
4312                      '1' : 2.718282
4313                  ]
4314              },
4315              'timestamp' : Timestamp(4294967295, 4294967295),
4316              'double' : 3.141593
4317          }
4318
4319   LLDB
4320       This  repository also includes a script that customizes LLDB's standard
4321       print command to print a bson_t or bson_t * as JSON:
4322
4323          (lldb) print b
4324          (bson_t) $0 = {"x": 1, "y": 2}
4325
4326       The custom bson command provides more options:
4327
4328          (lldb) bson --verbose b
4329          len=19
4330          flags=INLINE|STATIC
4331          {
4332            "x": 1,
4333            "y": 2
4334          }
4335          (lldb) bson --raw b
4336          '\x13\x00\x00\x00\x10x\x00\x01\x00\x00\x00\x10y\x00\x02\x00\x00\x00\x00'
4337
4338       Type help bson for a list of options.
4339
4340       The script requires a build of  libbson  with  debug  symbols,  and  an
4341       installation of PyMongo. Install PyMongo with:
4342
4343          python -m pip install pymongo
4344
4345       If  you  see  "No module named pip" then you must install pip, then run
4346       the previous command again.
4347
4348       Create a file ~/.lldbinit containing:
4349
4350          command script import /path/to/mongo-c-driver/lldb_bson.py
4351
4352       If you see "bson command installed by lldb_bson" at  the  beginning  of
4353       your LLDB session, you've installed the script correctly.
4354
4355   API Reference
4356   Initialization and cleanup
4357   Synopsis
4358       Initialize  the MongoDB C Driver by calling mongoc_init exactly once at
4359       the beginning of your  program.  It  is  responsible  for  initializing
4360       global state such as process counters, SSL, and threading primitives.
4361
4362       Call  mongoc_cleanup exactly once at the end of your program to release
4363       all memory and other resources allocated by the driver.  You  must  not
4364       call  any  other  MongoDB C Driver functions after mongoc_cleanup. Note
4365       that mongoc_init does not reinitialize the driver after mongoc_cleanup.
4366
4367   Deprecated feature: automatic initialization and cleanup
4368       On some platforms the driver can automatically call mongoc_init  before
4369       main, and call mongoc_cleanup as the process exits. This is problematic
4370       in situations where related libraries  also  execute  cleanup  code  on
4371       shutdown, and it creates inconsistent rules across platforms. Therefore
4372       the automatic initialization and cleanup  feature  is  deprecated,  and
4373       will  be dropped in version 2.0. Meanwhile, for backward compatibility,
4374       the feature is enabled by default on platforms where it is available.
4375
4376       For portable, future-proof  code,  always  call  mongoc_init  and  mon‐
4377       goc_cleanup yourself, and configure the driver like:
4378
4379          cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=NO
4380
4381   Logging
4382       MongoDB C driver Logging Abstraction
4383
4384   Synopsis
4385          typedef enum {
4386             MONGOC_LOG_LEVEL_ERROR,
4387             MONGOC_LOG_LEVEL_CRITICAL,
4388             MONGOC_LOG_LEVEL_WARNING,
4389             MONGOC_LOG_LEVEL_MESSAGE,
4390             MONGOC_LOG_LEVEL_INFO,
4391             MONGOC_LOG_LEVEL_DEBUG,
4392             MONGOC_LOG_LEVEL_TRACE,
4393          } mongoc_log_level_t;
4394
4395          #define MONGOC_ERROR(...)
4396          #define MONGOC_CRITICAL(...)
4397          #define MONGOC_WARNING(...)
4398          #define MONGOC_MESSAGE(...)
4399          #define MONGOC_INFO(...)
4400          #define MONGOC_DEBUG(...)
4401
4402          typedef void (*mongoc_log_func_t) (mongoc_log_level_t log_level,
4403                                             const char *log_domain,
4404                                             const char *message,
4405                                             void *user_data);
4406
4407          void
4408          mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data);
4409          void
4410          mongoc_log (mongoc_log_level_t log_level,
4411                      const char *log_domain,
4412                      const char *format,
4413                      ...) BSON_GNUC_PRINTF (3, 4);
4414          const char *
4415          mongoc_log_level_str (mongoc_log_level_t log_level);
4416          void
4417          mongoc_log_default_handler (mongoc_log_level_t log_level,
4418                                      const char *log_domain,
4419                                      const char *message,
4420                                      void *user_data);
4421          void
4422          mongoc_log_trace_enable (void);
4423          void
4424          mongoc_log_trace_disable (void);
4425
4426       The MongoDB C driver comes with an abstraction for logging that you can
4427       use in your application, or integrate with an existing logging system.
4428
4429   Macros
4430       To make logging a little less painful, various helper macros  are  pro‐
4431       vided. See the following example.
4432
4433          #undef MONGOC_LOG_DOMAIN
4434          #define MONGOC_LOG_DOMAIN "my-custom-domain"
4435
4436          MONGOC_WARNING ("An error occurred: %s", strerror (errno));
4437
4438   Custom Log Handlers
4439       The  default log handler prints a timestamp and the log message to std‐
4440       out, or to stderr for warnings, critical messages, and errors.
4441              You can  override  the  handler  with  mongoc_log_set_handler().
4442              Your handler function is called in a mutex for thread safety.
4443
4444       For  example,  you could register a custom handler to suppress messages
4445       at INFO level and below:
4446
4447          void
4448          my_logger (mongoc_log_level_t log_level,
4449                     const char *log_domain,
4450                     const char *message,
4451                     void *user_data)
4452          {
4453             /* smaller values are more important */
4454             if (log_level < MONGOC_LOG_LEVEL_INFO) {
4455                mongoc_log_default_handler (log_level, log_domain, message, user_data);
4456             }
4457          }
4458
4459          int
4460          main (int argc, char *argv[])
4461          {
4462             mongoc_init ();
4463             mongoc_log_set_handler (my_logger, NULL);
4464
4465             /* ... your code ...  */
4466
4467             mongoc_cleanup ();
4468             return 0;
4469          }
4470
4471       To restore the default handler:
4472
4473          mongoc_log_set_handler (mongoc_log_default_handler, NULL);
4474
4475   Disable logging
4476       To disable all  logging,  including  warnings,  critical  messages  and
4477       errors, provide an empty log handler:
4478
4479          mongoc_log_set_handler (NULL, NULL);
4480
4481   Tracing
4482       If  compiling your own copy of the MongoDB C driver, consider configur‐
4483       ing with -DENABLE_TRACING=ON to enable function tracing and  hex  dumps
4484       of  network  packets to STDERR and STDOUT during development and debug‐
4485       ging.
4486
4487       This is especially useful when debugging what may be  going  on  inter‐
4488       nally in the driver.
4489
4490       Trace   messages   can   be   enabled  and  disabled  by  calling  mon‐
4491       goc_log_trace_enable() and mongoc_log_trace_disable()
4492
4493       NOTE:
4494          Compiling the driver with -DENABLE_TRACING=ON will affect  its  per‐
4495          formance. Disabling tracing with mongoc_log_trace_disable() signifi‐
4496          cantly reduces the overhead, but cannot remove it completely.
4497       « index
4498
4499   Error Reporting
4500   Description
4501       Many C Driver functions report errors by  returning  false  or  -1  and
4502       filling  out a bson_error_t structure with an error domain, error code,
4503       and message. Use domain to  determine  which  subsystem  generated  the
4504       error,  and  code  for  the specific error. message is a human-readable
4505       error description.
4506
4507       See also: Handling Errors in libbson.
4508
4509┌────────────────────────┬─────────────────────────────────────────┬────────────────────────────┐
4510│Domain                  │ Code                                    │ Description                │
4511├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4512MONGOC_ERROR_CLIENT     MON‐                                    │ You tried to send a        │
4513│                        │ GOC_ERROR_CLIENT_TOO_BIG                │ message larger than        │
4514│                        │                                         │ the  server's   max        │
4515│                        │                                         │ message size.              │
4516├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4517│                        │ MON‐                                    │ Wrong  credentials,        │
4518│                        │ GOC_ERROR_CLIENT_AUTHEN‐                │ or failure  sending        │
4519│                        │ TICATE                                  │ or        receiving        │
4520│                        │                                         │ authentication mes‐        │
4521│                        │                                         │ sages.                     │
4522├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4523│                        │ MON‐                                    │ You  tried  an  SSL        │
4524│                        │ GOC_ERROR_CLIENT_NO_ACCEPT‐             │ connection but  the        │
4525│                        │ ABLE_PEER                               │ driver    was   not        │
4526│                        │                                         │ built with SSL.            │
4527├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4528│                        │ MON‐                                    │ You began iterating        │
4529│                        │ GOC_ERROR_CLIENT_IN_EXHAUST             │ an exhaust  cursor,        │
4530│                        │                                         │ then tried to begin        │
4531│                        │                                         │ another   operation        │
4532│                        │                                         │ with  the same mon‐        
4533│                        │                                         │ goc_client_t.              │
4534├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4535│                        │ MONGOC_ERROR_CLIENT_SES‐                │ Failure  related to        │
4536│                        │ SION_FAILURE                            │ creating or using a        │
4537│                        │                                         │ logical session.           │
4538├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4539MONGOC_ERROR_STREAM     MON‐                                    │ DNS failure.               │
4540│                        │ GOC_ERROR_STREAM_NAME_RESO‐             │                            │
4541│                        │ LUTION                                  │                            │
4542├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4543│                        │ MONGOC_ERROR_STREAM_SOCKET              │ Timeout communicat‐        │
4544│                        │                                         │ ing with server, or        │
4545│                        │                                         │ connection closed.         │
4546├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4547│                        │ MONGOC_ERROR_STREAM_CONNECT             │ Failed  to  connect        │
4548│                        │                                         │ to server.                 │
4549├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4550MONGOC_ERROR_PROTO‐     MONGOC_ERROR_PROTO‐                     │ Corrupt    response        │
4551COL                     COL_INVALID_REPLY                       │ from server.               │
4552├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4553│                        │ MONGOC_ERROR_PROTO‐                     │ The server  version        │
4554│                        │ COL_BAD_WIRE_VERSION                    │ is  too  old or too        │
4555│                        │                                         │ new to  communicate        │
4556│                        │                                         │ with the driver.           │
4557└────────────────────────┴─────────────────────────────────────────┴────────────────────────────┘
4558
4559
4560
4561
4562
4563
4564
4565MONGOC_ERROR_CURSOR     MONGOC_ERROR_CUR‐                       │ You   passed    bad        │
4566│                        │ SOR_INVALID_CURSOR                      │ arguments  to  mon‐        
4567│                        │                                         │ goc_collec‐                
4568│                        │                                         │ tion_find_with_opts,       │
4569│                        │                                         │ or you called  mon‐        
4570│                        │                                         │ goc_cursor_next  on        │
4571│                        │                                         │ a   completed    or        │
4572│                        │                                         │ failed  cursor,  or        │
4573│                        │                                         │ the  cursor   timed        │
4574│                        │                                         │ out on the server.         │
4575├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4576│                        │ MON‐                                    │ A  resume  token was       │
4577│                        │ GOC_ERROR_CHANGE_STREAM_NO_RESUME_TOKEN │ not  returned  in  a       │
4578│                        │                                         │ document  found with       │
4579│                        │                                         │ mon‐                       
4580│                        │                                         │ goc_change_stream_next     
4581├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4582MONGOC_ERROR_QUERY      MONGOC_ERROR_QUERY_FAILURE              Error API  Version  1:     │
4583│                        │                                         │ Server error from com‐     │
4584│                        │                                         │ mand  or  query.   The     │
4585│                        │                                         │ server  error  message     │
4586│                        │                                         │ is in message.             │
4587├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4588MONGOC_ERROR_SERVER     MONGOC_ERROR_QUERY_FAILURE              Error API  Version  2:     │
4589│                        │                                         │ Server error from com‐     │
4590│                        │                                         │ mand  or  query.   The     │
4591│                        │                                         │ server  error  message     │
4592│                        │                                         │ is in message.             │
4593├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4594MONGOC_ERROR_SASL       │ A SASL error code.                      │ man sasl_errors for  a     │
4595│                        │                                         │ list of codes.             │
4596├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4597MONGOC_ERROR_BSON       MONGOC_ERROR_BSON_INVALID               │ You  passed an invalid     │
4598│                        │                                         │ or oversized BSON doc‐     │
4599│                        │                                         │ ument  as a parameter,     │
4600│                        │                                         │ or called  mongoc_col‐     
4601│                        │                                         │ lection_create_index       
4602│                        │                                         │ with invalid keys,  or     │
4603│                        │                                         │ the  server  reply was     │
4604│                        │                                         │ corrupt.                   │
4605├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4606MONGOC_ERROR_NAMES‐     MONGOC_ERROR_NAMESPACE_INVALID          │ You  tried to create a     │
4607PACE                    │                                         │ collection   with   an     │
4608│                        │                                         │ invalid name.              │
4609├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4610MONGOC_ERROR_COM‐       MONGOC_ERROR_COMMAND_INVALID_ARG        │ Many   functions   set     │
4611MAND                    │                                         │ this  error  code when     │
4612│                        │                                         │ passed bad parameters.     │
4613│                        │                                         │ Print  the  error mes‐     │
4614│                        │                                         │ sage for details.          │
4615├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4616│                        │ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION  │ You  tried  to  use  a     │
4617│                        │                                         │ command   option   the     │
4618│                        │                                         │ server does  not  sup‐     │
4619│                        │                                         │ port.                      │
4620├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4621│                        │ MONGOC_ERROR_DUPLICATE_KEY              │ An  insert  or  update     │
4622│                        │                                         │ failed because because     │
4623│                        │                                         │ of  a duplicate _id or     │
4624│                        │                                         │ other     unique-index     │
4625│                        │                                         │ violation.                 │
4626├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4627MONGOC_ERROR_COM‐       Error code from server.                 │ Error API  Version  1:     │
4628MAND                    │                                         │ Server  error  from  a     │
4629│                        │                                         │ command.  The   server     │
4630│                        │                                         │ error  message  is  in     │
4631│                        │                                         │ message.                   │
4632└────────────────────────┴─────────────────────────────────────────┴────────────────────────────┘
4633
4634
4635
4636
4637
4638MONGOC_ERROR_SERVER     Error code from server.                 │ Error API  Version  2:     │
4639│                        │                                         │ Server  error  from  a     │
4640│                        │                                         │ command.  The   server     │
4641│                        │                                         │ error  message  is  in     │
4642│                        │                                         │ message.                   │
4643├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4644MONGOC_ERROR_COL‐       MONGOC_ERROR_COLLECTION_INSERT_FAILED,  │ Invalid or empty input     │
4645LECTION                 MONGOC_ERROR_COLLECTION_UPDATE_FAILED,  │ to      mongoc_collec‐     
4646│                        │ MONGOC_ERROR_COLLECTION_DELETE_FAILED.  │ tion_insert_one,  mon‐     
4647│                        │                                         │ goc_collec‐                
4648│                        │                                         │ tion_insert_bulk, mon‐     
4649│                        │                                         │ goc_collec‐                
4650│                        │                                         │ tion_update_one,  mon‐     
4651│                        │                                         │ goc_collec‐                
4652│                        │                                         │ tion_update_many, mon‐     
4653│                        │                                         │ goc_collec‐                
4654│                        │                                         │ tion_replace_one, mon‐     
4655│                        │                                         │ goc_collec‐                
4656│                        │                                         │ tion_delete_one,    or     │
4657│                        │                                         │ mongoc_collec‐             
4658│                        │                                         │ tion_delete_many.          │
4659├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4660MONGOC_ERROR_COL‐       Error code from server.                 │ Error API  Version  1:     │
4661LECTION                 │                                         │ Server error from mon‐     
4662│                        │                                         │ goc_collec‐                
4663│                        │                                         │ tion_insert_one,  mon‐     
4664│                        │                                         │ goc_collec‐                
4665│                        │                                         │ tion_insert_bulk, mon‐     
4666│                        │                                         │ goc_collec‐                
4667│                        │                                         │ tion_update_one,  mon‐     
4668│                        │                                         │ goc_collec‐                
4669│                        │                                         │ tion_update_many, mon‐     
4670│                        │                                         │ goc_collec‐                
4671│                        │                                         │ tion_replace_one, mon‐     
4672│                        │                                         │ goc_collec‐                
4673│                        │                                         │ tion_delete_one,    or     │
4674│                        │                                         │ mongoc_collec‐             
4675│                        │                                         │ tion_delete_many.          │
4676├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4677MONGOC_ERROR_SERVER     Error code from server.                 │ Error  API  Version 2:     │
4678│                        │                                         │ Server error from mon‐     
4679│                        │                                         │ goc_collec‐                
4680│                        │                                         │ tion_insert_one,  mon‐     
4681│                        │                                         │ goc_collec‐                
4682│                        │                                         │ tion_insert_bulk, mon‐     
4683│                        │                                         │ goc_collec‐                
4684│                        │                                         │ tion_update_one,  mon‐     
4685│                        │                                         │ goc_collec‐                
4686│                        │                                         │ tion_update_many, mon‐     
4687│                        │                                         │ goc_collec‐                
4688│                        │                                         │ tion_replace_one, mon‐     
4689│                        │                                         │ goc_collec‐                
4690│                        │                                         │ tion_delete_one,    or     │
4691│                        │                                         │ mongoc_collec‐             
4692│                        │                                         │ tion_delete_many.          │
4693├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4694MONGOC_ERROR_GRIDFS     MONGOC_ERROR_GRIDFS_CHUNK_MISSING       │ The  GridFS  file   is     │
4695│                        │                                         │ missing  a document in     │
4696│                        │                                         │ its chunks collection.     │
4697├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4698│                        │ MONGOC_ERROR_GRIDFS_CORRUPT             │ A  data  inconsistency     │
4699│                        │                                         │ was     detected    in     │
4700│                        │                                         │ GridFS.                    │
4701├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4702│                        │ MONGOC_ERROR_GRIDFS_INVALID_FILENAME    │ You  passed   a   NULL     │
4703│                        │                                         │ filename    to    mon‐     
4704│                        │                                         │ goc_gridfs_remove_by_file‐ 
4705│                        │                                         │ name.                      │
4706└────────────────────────┴─────────────────────────────────────────┴────────────────────────────┘
4707
4708
4709
4710
4711│                        │ MONGOC_ERROR_GRIDFS_PROTOCOL_ERROR      │ You       called      mon‐ 
4712│                        │                                         │ goc_gridfs_file_set_id     
4713│                        │                                         │ after                 mon‐ 
4714│                        │                                         │ goc_gridfs_file_save.      │
4715├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4716MONGOC_ERROR_SCRAM      MONGOC_ERROR_SCRAM_PROTOCOL_ERROR       │ Failure   in   SCRAM-SHA-1 │
4717│                        │                                         │ authentication.            │
4718├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4719MON‐                    MONGOC_ERROR_SERVER_SELECTION_FAILURE   │ No  replica  set member or │
4720GOC_ERROR_SERVER_SELEC‐ │                                         │ mongos  is  available,  or │
4721TION                    │                                         │ none   matches  your  read │
4722│                        │                                         │ preference,  or  you  sup‐ │
4723│                        │                                         │ plied   an   invalid  mon‐ 
4724│                        │                                         │ goc_read_prefs_t.          │
4725├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4726MONGOC_ERROR_WRITE_CON‐ Error code from server.                 │ There  was a write concern │
4727CERN                    │                                         │ error or timeout from  the │
4728│                        │                                         │ server.                    │
4729├────────────────────────┼─────────────────────────────────────────┼────────────────────────────┤
4730MONGOC_ERROR_TRANSAC‐   MONGOC_ERROR_TRANSACTION_INVALID        │ You attempted to  start  a │
4731TION                    │                                         │ transaction  when  one  is │
4732│                        │                                         │ already  in  progress,  or │
4733│                        │                                         │ commit or abort when there │
4734│                        │                                         │ is no transaction.         │
4735└────────────────────────┴─────────────────────────────────────────┴────────────────────────────┘
4736
4737   Error Labels
4738       In some cases your application must make decisions based on what  cate‐
4739       gory of error the driver has returned, but these categories do not cor‐
4740       respond perfectly to an error domain or  code.  In  such  cases,  error
4741       labels  provide a reliable way to determine how your application should
4742       respond to an error.
4743
4744       Any C Driver function that has a bson_t out-parameter named  reply  may
4745       include  error  labels  to the reply, in the form of a BSON field named
4746       "errorLabels" containing an array of strings:
4747
4748          { "errorLabels": [ "TransientTransactionError" ] }
4749
4750       Use mongoc_error_has_label to test  if  a  reply  contains  a  specific
4751       label.  See  mongoc_client_session_start_transaction  for  example code
4752       that demonstrates the use of error labels in application logic.
4753
4754       The following error labels are currently defined.  Future  versions  of
4755       MongoDB may introduce new labels.
4756
4757   TransientTransactionError
4758       Within  a  multi-document  transaction,  certain  errors  can leave the
4759       transaction in an unknown or aborted state. These  include  write  con‐
4760       flicts,  primary stepdowns, and network errors. In response, the appli‐
4761       cation should abort the transaction and try the same sequence of opera‐
4762       tions again in a new transaction.
4763
4764   UnknownTransactionCommitResult
4765       When   mongoc_client_session_commit_transaction  encounters  a  network
4766       error or certain server errors, it is not known whether the transaction
4767       was  committed.  Applications  should attempt to commit the transaction
4768       again until: the commit succeeds, the commit fails with  an  error  not
4769       labeled "UnknownTransactionCommitResult", or the application chooses to
4770       give up.
4771
4772   Setting the Error API Version
4773       The driver's error reporting began with a design flaw: when  the  error
4774       domain   is   MONGOC_ERROR_COLLECTION,   MONGOC_ERROR_QUERY,   or  MON‐
4775       GOC_ERROR_COMMAND, the error code might originate from  the  server  or
4776       the  driver.  An  application  cannot always know where an error origi‐
4777       nated, and therefore cannot tell what the code means.
4778
4779       For example, if mongoc_collection_update_one sets the error's domain to
4780       MONGOC_ERROR_COLLECTION and its code to 24, the application cannot know
4781       whether 24  is  the  generic  driver  error  code  MONGOC_ERROR_COLLEC‐
4782       TION_UPDATE_FAILED or the specific server error code "LockTimeout".
4783
4784       To  fix this flaw while preserving backward compatibility, the C Driver
4785       1.4 introduces "Error API Versions". Version 1, the default  Error  API
4786       Version,  maintains  the  flawed  behavior.  Version 2 adds a new error
4787       domain, MONGOC_ERROR_SERVER. In Version 2, error codes  originating  on
4788       the  server  always  have  error  domain  MONGOC_ERROR_SERVER  or  MON‐
4789       GOC_ERROR_WRITE_CONCERN. When the driver uses Version 2 the application
4790       can  always determine the origin and meaning of error codes. New appli‐
4791       cations should use Version  2,  and  existing  applications  should  be
4792       updated to use Version 2 as well.
4793
4794        ┌──────────────────────┬──────────────────────┬──────────────────────┐
4795        │Error Source          │ API Version 1        │ API Version 2        │
4796        ├──────────────────────┼──────────────────────┼──────────────────────┤
4797mongoc_cursor_error   MONGOC_ERROR_QUERY   MONGOC_ERROR_SERVER  
4798        ├──────────────────────┼──────────────────────┼──────────────────────┤
4799mongoc_client_com‐    MONGOC_ERROR_QUERY   MONGOC_ERROR_SERVER  
4800mand_with_opts,       │                      │                      │
4801mongoc_data‐          │                      │                      │
4802base_com‐             │                      │                      │
4803mand_with_opts, and   │                      │                      │
4804        │other command func‐   │                      │                      │
4805        │tions                 │                      │                      │
4806        ├──────────────────────┼──────────────────────┼──────────────────────┤
4807mongoc_collec‐        MONGOC_ERROR_QUERY   MONGOC_ERROR_SERVER  
4808tion_count_with_opts  │                      │                      │
4809mon‐                  │                      │                      │
4810goc_client_get_data‐  │                      │                      │
4811base_names_with_opts, │                      │                      │
4812        │and  other  command   │                      │                      │
4813        │helper functions      │                      │                      │
4814        ├──────────────────────┼──────────────────────┼──────────────────────┤
4815mongoc_collec‐        MONGOC_ERROR_COM‐    MONGOC_ERROR_SERVER  
4816tion_insert_one  mon‐ MAND                 │                      │
4817goc_collec‐           │                      │                      │
4818tion_insert_bulk mon‐ │                      │                      │
4819goc_collec‐           │                      │                      │
4820tion_update_one  mon‐ │                      │                      │
4821goc_collec‐           │                      │                      │
4822tion_update_many mon‐ │                      │                      │
4823goc_collec‐           │                      │                      │
4824tion_replace_one mon‐ │                      │                      │
4825goc_collec‐           │                      │                      │
4826tion_delete_one  mon‐ │                      │                      │
4827goc_collec‐           │                      │                      │
4828tion_delete_many      │                      │                      │
4829        ├──────────────────────┼──────────────────────┼──────────────────────┤
4830mongoc_bulk_opera‐    MONGOC_ERROR_COM‐    MONGOC_ERROR_SERVER  
4831tion_execute          MAND                 │                      │
4832        ├──────────────────────┼──────────────────────┼──────────────────────┤
4833        │Write-concern timeout │ MON‐                 MON‐                 
4834        │                      │ GOC_ERROR_WRITE_CON‐ GOC_ERROR_WRITE_CON‐ 
4835        │                      │ CERN                 CERN                 
4836        └──────────────────────┴──────────────────────┴──────────────────────┘
4837
4838       The Error API Versions are defined with MONGOC_ERROR_API_VERSION_LEGACY
4839       and   MONGOC_ERROR_API_VERSION_2.   Set   the   version    with    mon‐
4840       goc_client_set_error_api or mongoc_client_pool_set_error_api.
4841
4842   See Also
4843       MongoDB Server Error Codes
4844
4845   Object Lifecycle
4846       This  page  documents the order of creation and destruction for libmon‐
4847       goc's main struct types.
4848
4849   Clients and pools
4850       Call mongoc_init() once, before calling any other libmongoc  functions,
4851       and call mongoc_cleanup() once before your program exits.
4852
4853       A  program  that  uses  libmongoc from multiple threads should create a
4854       mongoc_client_pool_t   with   mongoc_client_pool_new().   Each   thread
4855       acquires  a mongoc_client_t from the pool with mongoc_client_pool_pop()
4856       and returns it with mongoc_client_pool_push() when the thread  is  fin‐
4857       ished  using  it.  To  destroy the pool, first return all clients, then
4858       call mongoc_client_pool_destroy().
4859
4860       If your program uses libmongoc from only  one  thread,  create  a  mon‐
4861       goc_client_t     directly     with    mongoc_client_new()    or    mon‐
4862       goc_client_new_from_uri(). Destroy it with mongoc_client_destroy().
4863
4864   Databases, collections, and related objects
4865       You can create a mongoc_database_t or mongoc_collection_t from  a  mon‐
4866       goc_client_t,  and  create a mongoc_cursor_t or mongoc_bulk_operation_t
4867       from a mongoc_collection_t.
4868
4869       Each of these objects must be destroyed before  the  client  they  were
4870       created from, but their lifetimes are otherwise independent.
4871
4872   GridFS objects
4873       You  can create a mongoc_gridfs_t from a mongoc_client_t, create a mon‐
4874       goc_gridfs_file_t or mongoc_gridfs_file_list_t from a  mongoc_gridfs_t,
4875       create  a  mongoc_gridfs_file_t  from  a mongoc_gridfs_file_list_t, and
4876       create a mongoc_stream_t from a mongoc_gridfs_file_t.
4877
4878       Each of these objects depends on the object it was created from. Always
4879       destroy  GridFS  objects in the reverse of the order they were created.
4880       The sole exception is that a mongoc_gridfs_file_t need not be destroyed
4881       before the mongoc_gridfs_file_list_t it was created from.
4882
4883   Sessions
4884       Start a session with mongoc_client_start_session, use the session for a
4885       sequence of operations and multi-document transactions,  then  free  it
4886       with   mongoc_client_session_destroy().  Any  mongoc_cursor_t  or  mon‐
4887       goc_change_stream_t using a session must be destroyed before  the  ses‐
4888       sion,  and  a  session  must be destroyed before the mongoc_client_t it
4889       came from.
4890
4891       By default, sessions are causally consistent. To disable causal consis‐
4892       tency,  before  starting  a  session create a mongoc_session_opt_t with
4893       mongoc_session_opts_new() and call  mongoc_session_opts_set_causal_con‐
4894       sistency(), then free the struct with mongoc_session_opts_destroy.
4895
4896       Unacknowledged writes are prohibited with sessions.
4897
4898       A  mongoc_client_session_t  must  be used by only one thread at a time.
4899       Due to session pooling, mongoc_client_start_session may return  a  ses‐
4900       sion  that  has been idle for some time and is about to be closed after
4901       its idle timeout. Use the session within one minute of acquiring it  to
4902       refresh the session and avoid a timeout.
4903
4904   mongoc_bulk_operation_t
4905       Bulk Write Operations
4906
4907   Synopsis
4908          typedef struct _mongoc_bulk_operation_t mongoc_bulk_operation_t;
4909
4910       The  opaque  type  mongoc_bulk_operation_t  provides an abstraction for
4911       submitting multiple write operations as a single batch.
4912
4913       After adding all of the  write  operations  to  the  mongoc_bulk_opera‐
4914       tion_t, call mongoc_bulk_operation_execute() to execute the operation.
4915
4916       WARNING:
4917          It  is  only valid to call mongoc_bulk_operation_execute() once. The
4918          mongoc_bulk_operation_t must be destroyed afterwards.
4919
4920   See Also
4921       Bulk Write Operations
4922
4923   mongoc_change_stream_t
4924   Synopsis
4925          #include <mongoc/mongoc.h>
4926
4927          typedef struct _mongoc_change_stream_t mongoc_change_stream_t;
4928
4929       mongoc_change_stream_t is a handle to a  change  stream.  A  collection
4930       change stream can be obtained using mongoc_collection_watch.
4931
4932       It  is  recommended  to  use a mongoc_change_stream_t and its functions
4933       instead of a raw aggregation  with  a  $changeStream  stage.  For  more
4934       information see the MongoDB Manual Entry on Change Streams.
4935
4936   Example
4937       example-collection-watch.c.INDENT 0.0
4938
4939          #include <mongoc/mongoc.h>
4940
4941          int
4942          main ()
4943          {
4944             bson_t empty = BSON_INITIALIZER;
4945             const bson_t *doc;
4946             bson_t *to_insert = BCON_NEW ("x", BCON_INT32 (1));
4947             const bson_t *err_doc;
4948             bson_error_t error;
4949             const char *uri_string;
4950             mongoc_uri_t *uri;
4951             mongoc_client_t *client;
4952             mongoc_collection_t *coll;
4953             mongoc_change_stream_t *stream;
4954             mongoc_write_concern_t *wc = mongoc_write_concern_new ();
4955             bson_t opts = BSON_INITIALIZER;
4956             bool r;
4957
4958             mongoc_init ();
4959
4960             uri_string = "mongodb://"
4961                          "localhost:27017,localhost:27018,localhost:"
4962                          "27019/db?replicaSet=rs0";
4963
4964             uri = mongoc_uri_new_with_error (uri_string, &error);
4965             if (!uri) {
4966                fprintf (stderr,
4967                         "failed to parse URI: %s\n"
4968                         "error message:       %s\n",
4969                         uri_string,
4970                         error.message);
4971                return EXIT_FAILURE;
4972             }
4973
4974             client = mongoc_client_new_from_uri (uri);
4975             if (!client) {
4976                return EXIT_FAILURE;
4977             }
4978
4979             coll = mongoc_client_get_collection (client, "db", "coll");
4980             stream = mongoc_collection_watch (coll, &empty, NULL);
4981
4982             mongoc_write_concern_set_wmajority (wc, 10000);
4983             mongoc_write_concern_append (wc, &opts);
4984             r = mongoc_collection_insert_one (coll, to_insert, &opts, NULL, &error);
4985             if (!r) {
4986                fprintf (stderr, "Error: %s\n", error.message);
4987                return EXIT_FAILURE;
4988             }
4989
4990             while (mongoc_change_stream_next (stream, &doc)) {
4991                char *as_json = bson_as_relaxed_extended_json (doc, NULL);
4992                fprintf (stderr, "Got document: %s\n", as_json);
4993                bson_free (as_json);
4994             }
4995
4996             if (mongoc_change_stream_error_document (stream, &error, &err_doc)) {
4997                if (!bson_empty (err_doc)) {
4998                   fprintf (stderr,
4999                            "Server Error: %s\n",
5000                            bson_as_relaxed_extended_json (err_doc, NULL));
5001                } else {
5002                   fprintf (stderr, "Client Error: %s\n", error.message);
5003                }
5004                return EXIT_FAILURE;
5005             }
5006
5007             bson_destroy (to_insert);
5008             mongoc_write_concern_destroy (wc);
5009             bson_destroy (&opts);
5010             mongoc_change_stream_destroy (stream);
5011             mongoc_collection_destroy (coll);
5012             mongoc_uri_destroy (uri);
5013             mongoc_client_destroy (client);
5014             mongoc_cleanup ();
5015
5016             return EXIT_SUCCESS;
5017          }
5018
5019
5020   Starting and Resuming
5021       All  watch  functions  accept  two  options  to indicate where a change
5022       stream should start returning changes  from:  startAtOperationTime  and
5023       resumeAfter.
5024
5025       All  changes  returned  by  mongoc_change_stream_next  include a resume
5026       token in the _id field. This resume token is  automatically  cached  in
5027       libmongoc.   In  the  event of an error, libmongoc attempts to recreate
5028       the change stream starting where it left  off  by  passing  the  resume
5029       token.  libmongoc only attempts to resume once, but client applications
5030       can cache this resume token and use it for their own  resume  logic  by
5031       passing it as the option resumeAfter.
5032
5033       Additionally,  change  streams can start returning changes at an opera‐
5034       tion time by using the startAtOperationTime  field.  This  can  be  the
5035       timestamp returned in the operationTime field of a command reply.
5036
5037       startAtOperationTime  and  resumeAfter  are mutually exclusive options.
5038       Setting them both will result in a server error.
5039
5040       The following example implements custom resuming logic, persisting  the
5041       resume token in a file.  example-resume.c.INDENT 0.0
5042
5043          #include <mongoc/mongoc.h>
5044
5045          /* An example implementation of custom resume logic in a change stream.
5046          * example-resume starts a client-wide change stream and persists the resume
5047          * token in a file "resume-token.json". On restart, if "resume-token.json"
5048          * exists, the change stream starts watching after the persisted resume token.
5049          *
5050          * This behavior allows a user to exit example-resume, and restart it later
5051          * without missing any change events.
5052          */
5053          #include <unistd.h>
5054
5055          static const char *RESUME_TOKEN_PATH = "resume-token.json";
5056
5057          static bool
5058          _save_resume_token (const bson_t *doc)
5059          {
5060             FILE *file_stream;
5061             bson_iter_t iter;
5062             bson_t resume_token_doc;
5063             char *as_json = NULL;
5064             size_t as_json_len;
5065             ssize_t r, n_written;
5066             const bson_value_t *resume_token;
5067
5068             if (!bson_iter_init_find (&iter, doc, "_id")) {
5069                fprintf (stderr, "reply does not contain operationTime.");
5070                return false;
5071             }
5072             resume_token = bson_iter_value (&iter);
5073             /* store the resume token in a document, { resumeAfter: <resume token> }
5074              * which we can later append easily. */
5075             file_stream = fopen (RESUME_TOKEN_PATH, "w+");
5076             if (!file_stream) {
5077                fprintf (stderr, "failed to open %s for writing\n", RESUME_TOKEN_PATH);
5078                return false;
5079             }
5080             bson_init (&resume_token_doc);
5081             BSON_APPEND_VALUE (&resume_token_doc, "resumeAfter", resume_token);
5082             as_json = bson_as_canonical_extended_json (&resume_token_doc, &as_json_len);
5083             bson_destroy (&resume_token_doc);
5084             n_written = 0;
5085             while (n_written < as_json_len) {
5086                r = fwrite ((void *) (as_json + n_written),
5087                            sizeof (char),
5088                            as_json_len - n_written,
5089                            file_stream);
5090                if (r == -1) {
5091                   fprintf (stderr, "failed to write to %s\n", RESUME_TOKEN_PATH);
5092                   bson_free (as_json);
5093                   fclose (file_stream);
5094                   return false;
5095                }
5096                n_written += r;
5097             }
5098
5099             bson_free (as_json);
5100             fclose (file_stream);
5101             return true;
5102          }
5103
5104          bool
5105          _load_resume_token (bson_t *opts)
5106          {
5107             bson_error_t error;
5108             bson_json_reader_t *reader;
5109             bson_t doc;
5110
5111             /* if the file does not exist, skip. */
5112             if (-1 == access (RESUME_TOKEN_PATH, R_OK)) {
5113                return true;
5114             }
5115             reader = bson_json_reader_new_from_file (RESUME_TOKEN_PATH, &error);
5116             if (!reader) {
5117                fprintf (stderr,
5118                         "failed to open %s for reading: %s\n",
5119                         RESUME_TOKEN_PATH,
5120                         error.message);
5121                return false;
5122             }
5123
5124             bson_init (&doc);
5125             if (-1 == bson_json_reader_read (reader, &doc, &error)) {
5126                fprintf (stderr, "failed to read doc from %s\n", RESUME_TOKEN_PATH);
5127                bson_destroy (&doc);
5128                bson_json_reader_destroy (reader);
5129                return false;
5130             }
5131
5132             printf ("found cached resume token in %s, resuming change stream.\n",
5133                     RESUME_TOKEN_PATH);
5134
5135             bson_concat (opts, &doc);
5136             bson_destroy (&doc);
5137             bson_json_reader_destroy (reader);
5138             return true;
5139          }
5140
5141          int
5142          main ()
5143          {
5144             int exit_code = EXIT_FAILURE;
5145             const char *uri_string;
5146             mongoc_uri_t *uri = NULL;
5147             bson_error_t error;
5148             mongoc_client_t *client = NULL;
5149             bson_t pipeline = BSON_INITIALIZER;
5150             bson_t opts = BSON_INITIALIZER;
5151             mongoc_change_stream_t *stream = NULL;
5152             const bson_t *doc;
5153
5154             const int max_time = 30; /* max amount of time, in seconds, that
5155                                         mongoc_change_stream_next can block. */
5156
5157             mongoc_init ();
5158             uri_string = "mongodb://localhost:27017/db?replicaSet=rs0";
5159             uri = mongoc_uri_new_with_error (uri_string, &error);
5160             if (!uri) {
5161                fprintf (stderr,
5162                         "failed to parse URI: %s\n"
5163                         "error message:       %s\n",
5164                         uri_string,
5165                         error.message);
5166                goto cleanup;
5167             }
5168
5169             client = mongoc_client_new_from_uri (uri);
5170             if (!client) {
5171                goto cleanup;
5172             }
5173
5174             if (!_load_resume_token (&opts)) {
5175                goto cleanup;
5176             }
5177             BSON_APPEND_INT64 (&opts, "maxAwaitTimeMS", max_time * 1000);
5178
5179             printf ("listening for changes on the client (max %d seconds).\n", max_time);
5180             stream = mongoc_client_watch (client, &pipeline, &opts);
5181
5182             while (mongoc_change_stream_next (stream, &doc)) {
5183                char *as_json;
5184
5185                as_json = bson_as_canonical_extended_json (doc, NULL);
5186                printf ("change received: %s\n", as_json);
5187                bson_free (as_json);
5188                if (!_save_resume_token (doc)) {
5189                   goto cleanup;
5190                }
5191             }
5192
5193             exit_code = EXIT_SUCCESS;
5194
5195          cleanup:
5196             mongoc_uri_destroy (uri);
5197             bson_destroy (&pipeline);
5198             bson_destroy (&opts);
5199             mongoc_change_stream_destroy (stream);
5200             mongoc_client_destroy (client);
5201             mongoc_cleanup ();
5202             return exit_code;
5203          }
5204
5205
5206The following example shows using startAtOperationTime to synchronize a change
5207stream with another operation.  example-start-at-optime.c.INDENT 0.0
5208
5209          /* An example of starting a change stream with startAtOperationTime. */
5210          #include <mongoc/mongoc.h>
5211
5212          int
5213          main ()
5214          {
5215             int exit_code = EXIT_FAILURE;
5216             const char *uri_string;
5217             mongoc_uri_t *uri = NULL;
5218             bson_error_t error;
5219             mongoc_client_t *client = NULL;
5220             mongoc_collection_t *coll = NULL;
5221             bson_t pipeline = BSON_INITIALIZER;
5222             bson_t opts = BSON_INITIALIZER;
5223             mongoc_change_stream_t *stream = NULL;
5224             bson_iter_t iter;
5225             const bson_t *doc;
5226             bson_value_t cached_operation_time = {0};
5227             int i;
5228             bool r;
5229
5230             mongoc_init ();
5231             uri_string = "mongodb://localhost:27017/db?replicaSet=rs0";
5232             uri = mongoc_uri_new_with_error (uri_string, &error);
5233             if (!uri) {
5234                fprintf (stderr,
5235                         "failed to parse URI: %s\n"
5236                         "error message:       %s\n",
5237                         uri_string,
5238                         error.message);
5239                goto cleanup;
5240             }
5241
5242             client = mongoc_client_new_from_uri (uri);
5243             if (!client) {
5244                goto cleanup;
5245             }
5246
5247             /* insert five documents. */
5248             coll = mongoc_client_get_collection (client, "db", "coll");
5249             for (i = 0; i < 5; i++) {
5250                bson_t reply;
5251                bson_t *insert_cmd = BCON_NEW ("insert",
5252                                               "coll",
5253                                               "documents",
5254                                               "[",
5255                                               "{",
5256                                               "x",
5257                                               BCON_INT64 (i),
5258                                               "}",
5259                                               "]");
5260
5261                r = mongoc_collection_write_command_with_opts (
5262                   coll, insert_cmd, NULL, &reply, &error);
5263                bson_destroy (insert_cmd);
5264                if (!r) {
5265                   bson_destroy (&reply);
5266                   fprintf (stderr, "failed to insert: %s\n", error.message);
5267                   goto cleanup;
5268                }
5269                if (i == 0) {
5270                   /* cache the operation time in the first reply. */
5271                   if (bson_iter_init_find (&iter, &reply, "operationTime")) {
5272                      bson_value_copy (bson_iter_value (&iter), &cached_operation_time);
5273                   } else {
5274                      fprintf (stderr, "reply does not contain operationTime.");
5275                      bson_destroy (&reply);
5276                      goto cleanup;
5277                   }
5278                }
5279                bson_destroy (&reply);
5280             }
5281
5282             /* start a change stream at the first returned operationTime. */
5283             BSON_APPEND_VALUE (&opts, "startAtOperationTime", &cached_operation_time);
5284             stream = mongoc_collection_watch (coll, &pipeline, &opts);
5285
5286             /* since the change stream started at the operation time of the first
5287              * insert, the five inserts are returned. */
5288             printf ("listening for changes on db.coll:\n");
5289             while (mongoc_change_stream_next (stream, &doc)) {
5290                char *as_json;
5291
5292                as_json = bson_as_canonical_extended_json (doc, NULL);
5293                printf ("change received: %s\n", as_json);
5294                bson_free (as_json);
5295             }
5296
5297             exit_code = EXIT_SUCCESS;
5298
5299          cleanup:
5300             mongoc_uri_destroy (uri);
5301             bson_destroy (&pipeline);
5302             bson_destroy (&opts);
5303             if (cached_operation_time.value_type) {
5304                bson_value_destroy (&cached_operation_time);
5305             }
5306             mongoc_change_stream_destroy (stream);
5307             mongoc_collection_destroy (coll);
5308             mongoc_client_destroy (client);
5309             mongoc_cleanup ();
5310             return exit_code;
5311          }
5312
5313   mongoc_client_pool_t
5314       A connection pool for multi-threaded programs. See connection-pooling.
5315
5316   Synopsis
5317          typedef struct _mongoc_client_pool_t mongoc_client_pool_t
5318
5319       mongoc_client_pool_t is the basis for multi-threading in the MongoDB  C
5320       driver.  Since  mongoc_client_t  structures  are  not thread-safe, this
5321       structure is used to retrieve a new mongoc_client_t for a given thread.
5322       This structure is thread-safe.
5323
5324   Example
5325       example-pool.c.INDENT 0.0
5326
5327          /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs
5328           * libmongoc-1.0) */
5329
5330          /* ./example-pool [CONNECTION_STRING] */
5331
5332          #include <mongoc/mongoc.h>
5333          #include <pthread.h>
5334          #include <stdio.h>
5335
5336          static pthread_mutex_t mutex;
5337          static bool in_shutdown = false;
5338
5339          static void *
5340          worker (void *data)
5341          {
5342             mongoc_client_pool_t *pool = data;
5343             mongoc_client_t *client;
5344             bson_t ping = BSON_INITIALIZER;
5345             bson_error_t error;
5346             bool r;
5347
5348             BSON_APPEND_INT32 (&ping, "ping", 1);
5349
5350             while (true) {
5351                client = mongoc_client_pool_pop (pool);
5352                /* Do something with client. If you are writing an HTTP server, you
5353                 * probably only want to hold onto the client for the portion of the
5354                 * request performing database queries.
5355                 */
5356                r = mongoc_client_command_simple (
5357                   client, "admin", &ping, NULL, NULL, &error);
5358
5359                if (!r) {
5360                   fprintf (stderr, "%s\n", error.message);
5361                }
5362
5363                mongoc_client_pool_push (pool, client);
5364
5365                pthread_mutex_lock (&mutex);
5366                if (in_shutdown || !r) {
5367                   pthread_mutex_unlock (&mutex);
5368                   break;
5369                }
5370
5371                pthread_mutex_unlock (&mutex);
5372             }
5373
5374             bson_destroy (&ping);
5375             return NULL;
5376          }
5377
5378          int
5379          main (int argc, char *argv[])
5380          {
5381             const char *uri_string = "mongodb://127.0.0.1/?appname=pool-example";
5382             mongoc_uri_t *uri;
5383             bson_error_t error;
5384             mongoc_client_pool_t *pool;
5385             pthread_t threads[10];
5386             unsigned i;
5387             void *ret;
5388
5389             pthread_mutex_init (&mutex, NULL);
5390             mongoc_init ();
5391
5392             if (argc > 1) {
5393                uri_string = argv[1];
5394             }
5395
5396             uri = mongoc_uri_new_with_error (uri_string, &error);
5397             if (!uri) {
5398                fprintf (stderr,
5399                         "failed to parse URI: %s\n"
5400                         "error message:       %s\n",
5401                         uri_string,
5402                         error.message);
5403                return EXIT_FAILURE;
5404             }
5405
5406             pool = mongoc_client_pool_new (uri);
5407             mongoc_client_pool_set_error_api (pool, 2);
5408
5409             for (i = 0; i < 10; i++) {
5410                pthread_create (&threads[i], NULL, worker, pool);
5411             }
5412
5413             sleep (10);
5414             pthread_mutex_lock (&mutex);
5415             in_shutdown = true;
5416             pthread_mutex_unlock (&mutex);
5417
5418             for (i = 0; i < 10; i++) {
5419                pthread_join (threads[i], &ret);
5420             }
5421
5422             mongoc_client_pool_destroy (pool);
5423             mongoc_uri_destroy (uri);
5424
5425             mongoc_cleanup ();
5426
5427             return EXIT_SUCCESS;
5428          }
5429
5430
5431   mongoc_client_session_t
5432       Use a session for a sequence of operations, optionally with causal con‐
5433       sistency. See the MongoDB Manual Entry for Causal Consistency.
5434
5435   Synopsis
5436       Start a session with mongoc_client_start_session, use the session for a
5437       sequence  of  operations  and multi-document transactions, then free it
5438       with  mongoc_client_session_destroy().  Any  mongoc_cursor_t  or   mon‐
5439       goc_change_stream_t  using  a session must be destroyed before the ses‐
5440       sion, and a session must be destroyed  before  the  mongoc_client_t  it
5441       came from.
5442
5443       By default, sessions are causally consistent. To disable causal consis‐
5444       tency, before starting a session  create  a  mongoc_session_opt_t  with
5445       mongoc_session_opts_new()  and call mongoc_session_opts_set_causal_con‐
5446       sistency(), then free the struct with mongoc_session_opts_destroy.
5447
5448       Unacknowledged writes are prohibited with sessions.
5449
5450       A mongoc_client_session_t must be used by only one thread  at  a  time.
5451       Due  to  session pooling, mongoc_client_start_session may return a ses‐
5452       sion that has been idle for some time and is about to be  closed  after
5453       its  idle timeout. Use the session within one minute of acquiring it to
5454       refresh the session and avoid a timeout.
5455
5456   Example
5457       example-session.c.INDENT 0.0
5458
5459          /* gcc example-session.c -o example-session \
5460           *     $(pkg-config --cflags --libs libmongoc-1.0) */
5461
5462          /* ./example-session [CONNECTION_STRING] */
5463
5464          #include <stdio.h>
5465          #include <mongoc/mongoc.h>
5466
5467
5468          int
5469          main (int argc, char *argv[])
5470          {
5471             int exit_code = EXIT_FAILURE;
5472
5473             mongoc_client_t *client = NULL;
5474             const char *uri_string = "mongodb://127.0.0.1/?appname=session-example";
5475             mongoc_uri_t *uri = NULL;
5476             mongoc_client_session_t *client_session = NULL;
5477             mongoc_collection_t *collection = NULL;
5478             bson_error_t error;
5479             bson_t *selector = NULL;
5480             bson_t *update = NULL;
5481             bson_t *update_opts = NULL;
5482             bson_t *find_opts = NULL;
5483             mongoc_read_prefs_t *secondary = NULL;
5484             mongoc_cursor_t *cursor = NULL;
5485             const bson_t *doc;
5486             char *str;
5487             bool r;
5488
5489             mongoc_init ();
5490
5491             if (argc > 1) {
5492                uri_string = argv[1];
5493             }
5494
5495             uri = mongoc_uri_new_with_error (uri_string, &error);
5496             if (!uri) {
5497                fprintf (stderr,
5498                         "failed to parse URI: %s\n"
5499                         "error message:       %s\n",
5500                         uri_string,
5501                         error.message);
5502                goto done;
5503             }
5504
5505             client = mongoc_client_new_from_uri (uri);
5506             if (!client) {
5507                goto done;
5508             }
5509
5510             mongoc_client_set_error_api (client, 2);
5511
5512             /* pass NULL for options - by default the session is causally consistent */
5513             client_session = mongoc_client_start_session (client, NULL, &error);
5514             if (!client_session) {
5515                fprintf (stderr, "Failed to start session: %s\n", error.message);
5516                goto done;
5517             }
5518
5519             collection = mongoc_client_get_collection (client, "test", "collection");
5520             selector = BCON_NEW ("_id", BCON_INT32 (1));
5521             update = BCON_NEW ("$inc", "{", "x", BCON_INT32 (1), "}");
5522             update_opts = bson_new ();
5523             if (!mongoc_client_session_append (client_session, update_opts, &error)) {
5524                fprintf (stderr, "Could not add session to opts: %s\n", error.message);
5525                goto done;
5526             }
5527
5528             r = mongoc_collection_update_one (
5529                collection, selector, update, update_opts, NULL /* reply */, &error);
5530
5531             if (!r) {
5532                fprintf (stderr, "Update failed: %s\n", error.message);
5533                goto done;
5534             }
5535
5536             bson_destroy (selector);
5537             selector = BCON_NEW ("_id", BCON_INT32 (1));
5538             secondary = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
5539
5540             find_opts = BCON_NEW ("maxTimeMS", BCON_INT32 (2000));
5541             if (!mongoc_client_session_append (client_session, find_opts, &error)) {
5542                fprintf (stderr, "Could not add session to opts: %s\n", error.message);
5543                goto done;
5544             };
5545
5546             /* read from secondary. since we're in a causally consistent session, the
5547              * data is guaranteed to reflect the update we did on the primary. the query
5548              * blocks waiting for the secondary to catch up, if necessary, or times out
5549              * and fails after 2000 ms.
5550              */
5551             cursor = mongoc_collection_find_with_opts (
5552                collection, selector, find_opts, secondary);
5553
5554             while (mongoc_cursor_next (cursor, &doc)) {
5555                str = bson_as_json (doc, NULL);
5556                fprintf (stdout, "%s\n", str);
5557                bson_free (str);
5558             }
5559
5560             if (mongoc_cursor_error (cursor, &error)) {
5561                fprintf (stderr, "Cursor Failure: %s\n", error.message);
5562                goto done;
5563             }
5564
5565             exit_code = EXIT_SUCCESS;
5566
5567          done:
5568             if (find_opts) {
5569                bson_destroy (find_opts);
5570             }
5571             if (update) {
5572                bson_destroy (update);
5573             }
5574             if (selector) {
5575                bson_destroy (selector);
5576             }
5577             if (update_opts) {
5578                bson_destroy (update_opts);
5579             }
5580             if (secondary) {
5581                mongoc_read_prefs_destroy (secondary);
5582             }
5583             /* destroy cursor, collection, session before the client they came from */
5584             if (cursor) {
5585                mongoc_cursor_destroy (cursor);
5586             }
5587             if (collection) {
5588                mongoc_collection_destroy (collection);
5589             }
5590             if (client_session) {
5591                mongoc_client_session_destroy (client_session);
5592             }
5593             if (uri) {
5594                mongoc_uri_destroy (uri);
5595             }
5596             if (client) {
5597                mongoc_client_destroy (client);
5598             }
5599
5600             mongoc_cleanup ();
5601
5602             return exit_code;
5603          }
5604
5605
5606   mongoc_client_t
5607       A single-threaded MongoDB connection. See connection-pooling.
5608
5609   Synopsis
5610          typedef struct _mongoc_client_t mongoc_client_t;
5611
5612          typedef mongoc_stream_t *(*mongoc_stream_initiator_t) (
5613             const mongoc_uri_t *uri,
5614             const mongoc_host_list_t *host,
5615             void *user_data,
5616             bson_error_t *error);
5617
5618       mongoc_client_t is an opaque type that provides  access  to  a  MongoDB
5619       server,  replica  set,  or  sharded cluster. It maintains management of
5620       underlying sockets and  routing  to  individual  nodes  based  on  mon‐
5621       goc_read_prefs_t or mongoc_write_concern_t.
5622
5623   Streams
5624       The  underlying transport for a given client can be customized, wrapped
5625       or replaced by any implementation that fulfills mongoc_stream_t. A cus‐
5626       tom transport can be set with mongoc_client_set_stream_initiator().
5627
5628   Thread Safety
5629       mongoc_client_t  is  NOT  thread-safe  and should only be used from one
5630       thread at a time. When used in multi-threaded scenarios, it  is  recom‐
5631       mended  that you use the thread-safe mongoc_client_pool_t to retrieve a
5632       mongoc_client_t for your thread.
5633
5634   Example
5635       example-client.c.INDENT 0.0
5636
5637          /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
5638           * libmongoc-1.0) */
5639
5640          /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */
5641
5642          #include <mongoc/mongoc.h>
5643          #include <stdio.h>
5644          #include <stdlib.h>
5645
5646          int
5647          main (int argc, char *argv[])
5648          {
5649             mongoc_client_t *client;
5650             mongoc_collection_t *collection;
5651             mongoc_cursor_t *cursor;
5652             bson_error_t error;
5653             const bson_t *doc;
5654             const char *collection_name = "test";
5655             bson_t query;
5656             char *str;
5657             const char *uri_string = "mongodb://127.0.0.1/?appname=client-example";
5658             mongoc_uri_t *uri;
5659
5660             mongoc_init ();
5661
5662             if (argc > 1) {
5663                uri_string = argv[1];
5664             }
5665
5666             if (argc > 2) {
5667                collection_name = argv[2];
5668             }
5669
5670             uri = mongoc_uri_new_with_error (uri_string, &error);
5671             if (!uri) {
5672                fprintf (stderr,
5673                         "failed to parse URI: %s\n"
5674                         "error message:       %s\n",
5675                         uri_string,
5676                         error.message);
5677                return EXIT_FAILURE;
5678             }
5679
5680             client = mongoc_client_new_from_uri (uri);
5681             if (!client) {
5682                return EXIT_FAILURE;
5683             }
5684
5685             mongoc_client_set_error_api (client, 2);
5686
5687             bson_init (&query);
5688
5689          #if 0
5690             bson_append_utf8 (&query, "hello", -1, "world", -1);
5691          #endif
5692
5693             collection = mongoc_client_get_collection (client, "test", collection_name);
5694             cursor = mongoc_collection_find_with_opts (
5695                collection,
5696                &query,
5697                NULL,  /* additional options */
5698                NULL); /* read prefs, NULL for default */
5699
5700             while (mongoc_cursor_next (cursor, &doc)) {
5701                str = bson_as_canonical_extended_json (doc, NULL);
5702                fprintf (stdout, "%s\n", str);
5703                bson_free (str);
5704             }
5705
5706             if (mongoc_cursor_error (cursor, &error)) {
5707                fprintf (stderr, "Cursor Failure: %s\n", error.message);
5708                return EXIT_FAILURE;
5709             }
5710
5711             bson_destroy (&query);
5712             mongoc_cursor_destroy (cursor);
5713             mongoc_collection_destroy (collection);
5714             mongoc_uri_destroy (uri);
5715             mongoc_client_destroy (client);
5716             mongoc_cleanup ();
5717
5718             return EXIT_SUCCESS;
5719          }
5720
5721
5722   mongoc_collection_t
5723   Synopsis
5724          #include <mongoc/mongoc.h>
5725
5726          typedef struct _mongoc_collection_t mongoc_collection_t;
5727
5728       mongoc_collection_t provides access to a MongoDB collection.  This han‐
5729       dle  is  useful  for  actions  for  most  CRUD operations, I.e. insert,
5730       update, delete, find, etc.
5731
5732   Read Preferences and Write Concerns
5733       Read preferences and write  concerns  are  inherited  from  the  parent
5734       client. They can be overridden by set_* commands if so desired.
5735
5736   mongoc_cursor_t
5737       Client-side cursor abstraction
5738
5739   Synopsis
5740          typedef struct _mongoc_cursor_t mongoc_cursor_t;
5741
5742       mongoc_cursor_t provides access to a MongoDB query cursor.  It wraps up
5743       the wire protocol negotiation required to initiate a query and retrieve
5744       an unknown number of documents.
5745
5746       Common cursor operations include:
5747
5748       · Determine   which   host   we've   connected   to   with  mongoc_cur‐
5749         sor_get_host().
5750
5751       · Retrieve more records with repeated calls to mongoc_cursor_next().
5752
5753       · Clone a query to repeat execution at a later point  with  mongoc_cur‐
5754         sor_clone().
5755
5756       · Test for errors with mongoc_cursor_error().
5757
5758       Cursors are lazy, meaning that no connection is established and no net‐
5759       work traffic occurs until the first call to mongoc_cursor_next().
5760
5761   Thread Safety
5762       mongoc_cursor_t is NOT thread safe. It may only be used from within the
5763       thread in which it was created.
5764
5765   Example
5766       Query MongoDB and iterate results.INDENT 0.0
5767
5768          /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
5769           * libmongoc-1.0) */
5770
5771          /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */
5772
5773          #include <mongoc/mongoc.h>
5774          #include <stdio.h>
5775          #include <stdlib.h>
5776
5777          int
5778          main (int argc, char *argv[])
5779          {
5780             mongoc_client_t *client;
5781             mongoc_collection_t *collection;
5782             mongoc_cursor_t *cursor;
5783             bson_error_t error;
5784             const bson_t *doc;
5785             const char *collection_name = "test";
5786             bson_t query;
5787             char *str;
5788             const char *uri_string = "mongodb://127.0.0.1/?appname=client-example";
5789             mongoc_uri_t *uri;
5790
5791             mongoc_init ();
5792
5793             if (argc > 1) {
5794                uri_string = argv[1];
5795             }
5796
5797             if (argc > 2) {
5798                collection_name = argv[2];
5799             }
5800
5801             uri = mongoc_uri_new_with_error (uri_string, &error);
5802             if (!uri) {
5803                fprintf (stderr,
5804                         "failed to parse URI: %s\n"
5805                         "error message:       %s\n",
5806                         uri_string,
5807                         error.message);
5808                return EXIT_FAILURE;
5809             }
5810
5811             client = mongoc_client_new_from_uri (uri);
5812             if (!client) {
5813                return EXIT_FAILURE;
5814             }
5815
5816             mongoc_client_set_error_api (client, 2);
5817
5818             bson_init (&query);
5819
5820          #if 0
5821             bson_append_utf8 (&query, "hello", -1, "world", -1);
5822          #endif
5823
5824             collection = mongoc_client_get_collection (client, "test", collection_name);
5825             cursor = mongoc_collection_find_with_opts (
5826                collection,
5827                &query,
5828                NULL,  /* additional options */
5829                NULL); /* read prefs, NULL for default */
5830
5831             while (mongoc_cursor_next (cursor, &doc)) {
5832                str = bson_as_canonical_extended_json (doc, NULL);
5833                fprintf (stdout, "%s\n", str);
5834                bson_free (str);
5835             }
5836
5837             if (mongoc_cursor_error (cursor, &error)) {
5838                fprintf (stderr, "Cursor Failure: %s\n", error.message);
5839                return EXIT_FAILURE;
5840             }
5841
5842             bson_destroy (&query);
5843             mongoc_cursor_destroy (cursor);
5844             mongoc_collection_destroy (collection);
5845             mongoc_uri_destroy (uri);
5846             mongoc_client_destroy (client);
5847             mongoc_cleanup ();
5848
5849             return EXIT_SUCCESS;
5850          }
5851
5852
5853   mongoc_database_t
5854       MongoDB Database Abstraction
5855
5856   Synopsis
5857          typedef struct _mongoc_database_t mongoc_database_t;
5858
5859       mongoc_database_t provides access to a MongoDB database. This handle is
5860       useful for actions a particular database object. It is not a  container
5861       for mongoc_collection_t structures.
5862
5863       Read  preferences  and  write  concerns  are  inherited from the parent
5864       client. They can be  overridden  with  mongoc_database_set_read_prefs()
5865       and mongoc_database_set_write_concern().
5866
5867   Examples
5868          #include <mongoc/mongoc.h>
5869
5870          int
5871          main (int argc, char *argv[])
5872          {
5873             mongoc_database_t *database;
5874             mongoc_client_t *client;
5875
5876             mongoc_init ();
5877
5878             client = mongoc_client_new ("mongodb://localhost/");
5879             database = mongoc_client_get_database (client, "test");
5880
5881             mongoc_database_destroy (database);
5882             mongoc_client_destroy (client);
5883
5884             mongoc_cleanup ();
5885
5886             return 0;
5887          }
5888
5889   mongoc_delete_flags_t
5890       Flags for deletion operations
5891
5892   Synopsis
5893          typedef enum {
5894             MONGOC_DELETE_NONE = 0,
5895             MONGOC_DELETE_SINGLE_REMOVE = 1 << 0,
5896          } mongoc_delete_flags_t;
5897
5898   Deprecated
5899       WARNING:
5900          These flags are deprecated and should not be used in new code.
5901
5902       Please    use    mongoc_collection_delete_one()    or    mongoc_collec‐
5903       tion_delete_many() instead.
5904
5905   mongoc_find_and_modify_opts_t
5906       find_and_modify abstraction
5907
5908   Synopsis
5909       mongoc_find_and_modify_opts_t is a builder  interface  to  construct  a
5910       find_and_modify command.
5911
5912       It  was  created to be able to accommodate new arguments to the MongoDB
5913       find_and_modify command.
5914
5915       As of MongoDB 3.2, the mongoc_write_concern_t  specified  on  the  mon‐
5916       goc_collection_t will be used, if any.
5917
5918   Example
5919       flags.c.INDENT 0.0
5920
5921          void
5922          fam_flags (mongoc_collection_t *collection)
5923          {
5924             mongoc_find_and_modify_opts_t *opts;
5925             bson_t reply;
5926             bson_error_t error;
5927             bson_t query = BSON_INITIALIZER;
5928             bson_t *update;
5929             bool success;
5930
5931
5932             /* Find Zlatan Ibrahimovic, the striker */
5933             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
5934             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
5935             BSON_APPEND_UTF8 (&query, "profession", "Football player");
5936             BSON_APPEND_INT32 (&query, "age", 34);
5937             BSON_APPEND_INT32 (
5938                &query, "goals", (16 + 35 + 23 + 57 + 16 + 14 + 28 + 84) + (1 + 6 + 62));
5939
5940             /* Add his football position */
5941             update = BCON_NEW ("$set", "{", "position", BCON_UTF8 ("striker"), "}");
5942
5943             opts = mongoc_find_and_modify_opts_new ();
5944
5945             mongoc_find_and_modify_opts_set_update (opts, update);
5946
5947             /* Create the document if it didn't exist, and return the updated document */
5948             mongoc_find_and_modify_opts_set_flags (
5949                opts, MONGOC_FIND_AND_MODIFY_UPSERT | MONGOC_FIND_AND_MODIFY_RETURN_NEW);
5950
5951             success = mongoc_collection_find_and_modify_with_opts (
5952                collection, &query, opts, &reply, &error);
5953
5954             if (success) {
5955                char *str;
5956
5957                str = bson_as_canonical_extended_json (&reply, NULL);
5958                printf ("%s\n", str);
5959                bson_free (str);
5960             } else {
5961                fprintf (
5962                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
5963             }
5964
5965             bson_destroy (&reply);
5966             bson_destroy (update);
5967             bson_destroy (&query);
5968             mongoc_find_and_modify_opts_destroy (opts);
5969          }
5970
5971bypass.c.INDENT 0.0
5972
5973          void
5974          fam_bypass (mongoc_collection_t *collection)
5975          {
5976             mongoc_find_and_modify_opts_t *opts;
5977             bson_t reply;
5978             bson_t *update;
5979             bson_error_t error;
5980             bson_t query = BSON_INITIALIZER;
5981             bool success;
5982
5983
5984             /* Find Zlatan Ibrahimovic, the striker */
5985             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
5986             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
5987             BSON_APPEND_UTF8 (&query, "profession", "Football player");
5988
5989             /* Bump his age */
5990             update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}");
5991
5992             opts = mongoc_find_and_modify_opts_new ();
5993             mongoc_find_and_modify_opts_set_update (opts, update);
5994             /* He can still play, even though he is pretty old. */
5995             mongoc_find_and_modify_opts_set_bypass_document_validation (opts, true);
5996
5997             success = mongoc_collection_find_and_modify_with_opts (
5998                collection, &query, opts, &reply, &error);
5999
6000             if (success) {
6001                char *str;
6002
6003                str = bson_as_canonical_extended_json (&reply, NULL);
6004                printf ("%s\n", str);
6005                bson_free (str);
6006             } else {
6007                fprintf (
6008                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
6009             }
6010
6011             bson_destroy (&reply);
6012             bson_destroy (update);
6013             bson_destroy (&query);
6014             mongoc_find_and_modify_opts_destroy (opts);
6015          }
6016
6017update.c.INDENT 0.0
6018
6019          void
6020          fam_update (mongoc_collection_t *collection)
6021          {
6022             mongoc_find_and_modify_opts_t *opts;
6023             bson_t *update;
6024             bson_t reply;
6025             bson_error_t error;
6026             bson_t query = BSON_INITIALIZER;
6027             bool success;
6028
6029
6030             /* Find Zlatan Ibrahimovic */
6031             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
6032             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
6033
6034             /* Make him a book author */
6035             update = BCON_NEW ("$set", "{", "author", BCON_BOOL (true), "}");
6036
6037             opts = mongoc_find_and_modify_opts_new ();
6038             /* Note that the document returned is the _previous_ version of the document
6039              * To fetch the modified new version, use
6040              * mongoc_find_and_modify_opts_set_flags (opts,
6041              * MONGOC_FIND_AND_MODIFY_RETURN_NEW);
6042              */
6043             mongoc_find_and_modify_opts_set_update (opts, update);
6044
6045             success = mongoc_collection_find_and_modify_with_opts (
6046                collection, &query, opts, &reply, &error);
6047
6048             if (success) {
6049                char *str;
6050
6051                str = bson_as_canonical_extended_json (&reply, NULL);
6052                printf ("%s\n", str);
6053                bson_free (str);
6054             } else {
6055                fprintf (
6056                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
6057             }
6058
6059             bson_destroy (&reply);
6060             bson_destroy (update);
6061             bson_destroy (&query);
6062             mongoc_find_and_modify_opts_destroy (opts);
6063          }
6064
6065fields.c.INDENT 0.0
6066
6067          void
6068          fam_fields (mongoc_collection_t *collection)
6069          {
6070             mongoc_find_and_modify_opts_t *opts;
6071             bson_t fields = BSON_INITIALIZER;
6072             bson_t *update;
6073             bson_t reply;
6074             bson_error_t error;
6075             bson_t query = BSON_INITIALIZER;
6076             bool success;
6077
6078
6079             /* Find Zlatan Ibrahimovic */
6080             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
6081             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
6082
6083             /* Return his goal tally */
6084             BSON_APPEND_INT32 (&fields, "goals", 1);
6085
6086             /* Bump his goal tally */
6087             update = BCON_NEW ("$inc", "{", "goals", BCON_INT32 (1), "}");
6088
6089             opts = mongoc_find_and_modify_opts_new ();
6090             mongoc_find_and_modify_opts_set_update (opts, update);
6091             mongoc_find_and_modify_opts_set_fields (opts, &fields);
6092             /* Return the new tally */
6093             mongoc_find_and_modify_opts_set_flags (opts,
6094                                                    MONGOC_FIND_AND_MODIFY_RETURN_NEW);
6095
6096             success = mongoc_collection_find_and_modify_with_opts (
6097                collection, &query, opts, &reply, &error);
6098
6099             if (success) {
6100                char *str;
6101
6102                str = bson_as_canonical_extended_json (&reply, NULL);
6103                printf ("%s\n", str);
6104                bson_free (str);
6105             } else {
6106                fprintf (
6107                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
6108             }
6109
6110             bson_destroy (&reply);
6111             bson_destroy (update);
6112             bson_destroy (&fields);
6113             bson_destroy (&query);
6114             mongoc_find_and_modify_opts_destroy (opts);
6115          }
6116
6117sort.c.INDENT 0.0
6118
6119          void
6120          fam_sort (mongoc_collection_t *collection)
6121          {
6122             mongoc_find_and_modify_opts_t *opts;
6123             bson_t *update;
6124             bson_t sort = BSON_INITIALIZER;
6125             bson_t reply;
6126             bson_error_t error;
6127             bson_t query = BSON_INITIALIZER;
6128             bool success;
6129
6130
6131             /* Find all users with the lastname Ibrahimovic */
6132             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
6133
6134             /* Sort by age (descending) */
6135             BSON_APPEND_INT32 (&sort, "age", -1);
6136
6137             /* Bump his goal tally */
6138             update = BCON_NEW ("$set", "{", "oldest", BCON_BOOL (true), "}");
6139
6140             opts = mongoc_find_and_modify_opts_new ();
6141             mongoc_find_and_modify_opts_set_update (opts, update);
6142             mongoc_find_and_modify_opts_set_sort (opts, &sort);
6143
6144             success = mongoc_collection_find_and_modify_with_opts (
6145                collection, &query, opts, &reply, &error);
6146
6147             if (success) {
6148                char *str;
6149
6150                str = bson_as_canonical_extended_json (&reply, NULL);
6151                printf ("%s\n", str);
6152                bson_free (str);
6153             } else {
6154                fprintf (
6155                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
6156             }
6157
6158             bson_destroy (&reply);
6159             bson_destroy (update);
6160             bson_destroy (&sort);
6161             bson_destroy (&query);
6162             mongoc_find_and_modify_opts_destroy (opts);
6163          }
6164
6165opts.c.INDENT 0.0
6166
6167          void
6168          fam_opts (mongoc_collection_t *collection)
6169          {
6170             mongoc_find_and_modify_opts_t *opts;
6171             bson_t reply;
6172             bson_t *update;
6173             bson_error_t error;
6174             bson_t query = BSON_INITIALIZER;
6175             mongoc_write_concern_t *wc;
6176             bson_t extra = BSON_INITIALIZER;
6177             bool success;
6178
6179
6180             /* Find Zlatan Ibrahimovic, the striker */
6181             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
6182             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
6183             BSON_APPEND_UTF8 (&query, "profession", "Football player");
6184
6185             /* Bump his age */
6186             update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}");
6187
6188             opts = mongoc_find_and_modify_opts_new ();
6189             mongoc_find_and_modify_opts_set_update (opts, update);
6190
6191             /* Abort if the operation takes too long. */
6192             mongoc_find_and_modify_opts_set_max_time_ms (opts, 100);
6193
6194             /* Set write concern w: 2 */
6195             wc = mongoc_write_concern_new ();
6196             mongoc_write_concern_set_w (wc, 2);
6197             mongoc_write_concern_append (wc, &extra);
6198
6199             /* Some future findAndModify option the driver doesn't support conveniently
6200              */
6201             BSON_APPEND_INT32 (&extra, "futureOption", 42);
6202             mongoc_find_and_modify_opts_append (opts, &extra);
6203
6204             success = mongoc_collection_find_and_modify_with_opts (
6205                collection, &query, opts, &reply, &error);
6206
6207             if (success) {
6208                char *str;
6209
6210                str = bson_as_canonical_extended_json (&reply, NULL);
6211                printf ("%s\n", str);
6212                bson_free (str);
6213             } else {
6214                fprintf (
6215                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
6216             }
6217
6218             bson_destroy (&reply);
6219             bson_destroy (&extra);
6220             bson_destroy (update);
6221             bson_destroy (&query);
6222             mongoc_write_concern_destroy (wc);
6223             mongoc_find_and_modify_opts_destroy (opts);
6224          }
6225
6226fam.c.INDENT 0.0
6227
6228          int
6229          main (void)
6230          {
6231             mongoc_collection_t *collection;
6232             mongoc_database_t *database;
6233             mongoc_client_t *client;
6234             const char *uri_string =
6235                "mongodb://localhost:27017/admin?appname=find-and-modify-opts-example";
6236             mongoc_uri_t *uri;
6237             bson_error_t error;
6238             bson_t *options;
6239
6240             mongoc_init ();
6241
6242             uri = mongoc_uri_new_with_error (uri_string, &error);
6243             if (!uri) {
6244                fprintf (stderr,
6245                         "failed to parse URI: %s\n"
6246                         "error message:       %s\n",
6247                         uri_string,
6248                         error.message);
6249                return EXIT_FAILURE;
6250             }
6251
6252             client = mongoc_client_new_from_uri (uri);
6253             if (!client) {
6254                return EXIT_FAILURE;
6255             }
6256
6257             mongoc_client_set_error_api (client, 2);
6258             database = mongoc_client_get_database (client, "databaseName");
6259
6260             options = BCON_NEW ("validator",
6261                                 "{",
6262                                 "age",
6263                                 "{",
6264                                 "$lte",
6265                                 BCON_INT32 (34),
6266                                 "}",
6267                                 "}",
6268                                 "validationAction",
6269                                 BCON_UTF8 ("error"),
6270                                 "validationLevel",
6271                                 BCON_UTF8 ("moderate"));
6272
6273             collection = mongoc_database_create_collection (
6274                database, "collectionName", options, &error);
6275             if (!collection) {
6276                fprintf (
6277                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
6278                return EXIT_FAILURE;
6279             }
6280
6281             fam_flags (collection);
6282             fam_bypass (collection);
6283             fam_update (collection);
6284             fam_fields (collection);
6285             fam_opts (collection);
6286             fam_sort (collection);
6287
6288             mongoc_collection_drop (collection, NULL);
6289             bson_destroy (options);
6290             mongoc_uri_destroy (uri);
6291             mongoc_database_destroy (database);
6292             mongoc_collection_destroy (collection);
6293             mongoc_client_destroy (client);
6294
6295             mongoc_cleanup ();
6296             return EXIT_SUCCESS;
6297          }
6298
6299
6300Outputs:
6301
6302          {
6303              "lastErrorObject": {
6304                  "updatedExisting": false,
6305                  "n": 1,
6306                  "upserted": {
6307                      "$oid": "56562a99d13e6d86239c7b00"
6308                  }
6309              },
6310              "value": {
6311                  "_id": {
6312                      "$oid": "56562a99d13e6d86239c7b00"
6313                  },
6314                  "age": 34,
6315                  "firstname": "Zlatan",
6316                  "goals": 342,
6317                  "lastname": "Ibrahimovic",
6318                  "profession": "Football player",
6319                  "position": "striker"
6320              },
6321              "ok": 1
6322          }
6323          {
6324              "lastErrorObject": {
6325                  "updatedExisting": true,
6326                  "n": 1
6327              },
6328              "value": {
6329                  "_id": {
6330                      "$oid": "56562a99d13e6d86239c7b00"
6331                  },
6332                  "age": 34,
6333                  "firstname": "Zlatan",
6334                  "goals": 342,
6335                  "lastname": "Ibrahimovic",
6336                  "profession": "Football player",
6337                  "position": "striker"
6338              },
6339              "ok": 1
6340          }
6341          {
6342              "lastErrorObject": {
6343                  "updatedExisting": true,
6344                  "n": 1
6345              },
6346              "value": {
6347                  "_id": {
6348                      "$oid": "56562a99d13e6d86239c7b00"
6349                  },
6350                  "age": 35,
6351                  "firstname": "Zlatan",
6352                  "goals": 342,
6353                  "lastname": "Ibrahimovic",
6354                  "profession": "Football player",
6355                  "position": "striker"
6356              },
6357              "ok": 1
6358          }
6359          {
6360              "lastErrorObject": {
6361                  "updatedExisting": true,
6362                  "n": 1
6363              },
6364              "value": {
6365                  "_id": {
6366                      "$oid": "56562a99d13e6d86239c7b00"
6367                  },
6368                  "goals": 343
6369              },
6370              "ok": 1
6371          }
6372          {
6373              "lastErrorObject": {
6374                  "updatedExisting": true,
6375                  "n": 1
6376              },
6377              "value": {
6378                  "_id": {
6379                      "$oid": "56562a99d13e6d86239c7b00"
6380                  },
6381                  "age": 35,
6382                  "firstname": "Zlatan",
6383                  "goals": 343,
6384                  "lastname": "Ibrahimovic",
6385                  "profession": "Football player",
6386                  "position": "striker",
6387                  "author": true
6388              },
6389              "ok": 1
6390          }
6391
6392   mongoc_gridfs_file_list_t
6393   Synopsis
6394          #include <mongoc/mongoc.h>
6395
6396          typedef struct _mongoc_gridfs_file_list_t mongoc_gridfs_file_list_t;
6397
6398   Description
6399       mongoc_gridfs_file_list_t  provides a gridfs file list abstraction.  It
6400       provides iteration and basic marshalling  on  top  of  a  regular  mon‐
6401       goc_collection_find_with_opts()  style query. In interface, it's styled
6402       after mongoc_cursor_t.
6403
6404   Example
6405          mongoc_gridfs_file_list_t *list;
6406          mongoc_gridfs_file_t *file;
6407
6408          list = mongoc_gridfs_find (gridfs, query);
6409
6410          while ((file = mongoc_gridfs_file_list_next (list))) {
6411             do_something (file);
6412
6413             mongoc_gridfs_file_destroy (file);
6414          }
6415
6416          mongoc_gridfs_file_list_destroy (list);
6417
6418   mongoc_gridfs_file_opt_t
6419   Synopsis
6420          typedef struct {
6421             const char *md5;
6422             const char *filename;
6423             const char *content_type;
6424             const bson_t *aliases;
6425             const bson_t *metadata;
6426             uint32_t chunk_size;
6427          } mongoc_gridfs_file_opt_t;
6428
6429   Description
6430       This  structure  contains  options  that  can  be   set   on   a   mon‐
6431       goc_gridfs_file_t.  It can be used by various functions when creating a
6432       new gridfs file.
6433
6434   mongoc_gridfs_file_t
6435   Synopsis
6436          typedef struct _mongoc_gridfs_file_t mongoc_gridfs_file_t;
6437
6438   Description
6439       This structure provides a MongoDB GridFS file abstraction. It  provides
6440       several APIs.
6441
6442       · readv, writev, seek, and tell.
6443
6444       · General file metadata such as filename and length.
6445
6446       · GridFS  metadata  such as md5, filename, content_type, aliases, meta‐
6447         data, chunk_size, and upload_date.
6448
6449   Thread Safety
6450       This structure is NOT thread-safe and should  only  be  used  from  one
6451       thread at a time.
6452
6453   Related
6454       · mongoc_client_t
6455
6456       · mongoc_gridfs_t
6457
6458       · mongoc_gridfs_file_list_t
6459
6460       · mongoc_gridfs_file_opt_t
6461
6462   mongoc_gridfs_t
6463   Synopsis
6464          #include <mongoc/mongoc.h>
6465
6466          typedef struct _mongoc_gridfs_t mongoc_gridfs_t;
6467
6468   Description
6469       mongoc_gridfs_t provides a MongoDB gridfs implementation. The system as
6470       a whole is made up of gridfs objects, which  contain  gridfs_files  and
6471       gridfs_file_lists.  Essentially, a basic file system API.
6472
6473       There are extensive caveats about the kind of use cases gridfs is prac‐
6474       tical for. In particular, any writing after initial  file  creation  is
6475       likely  to  both  break  any concurrent readers and be quite expensive.
6476       That said, this implementation  does  allow  for  arbitrary  writes  to
6477       existing gridfs object, just use them with caution.
6478
6479       mongoc_gridfs also integrates tightly with the mongoc_stream_t abstrac‐
6480       tion, which provides some convenient wrapping  for  file  creation  and
6481       reading/writing.   It can be used without, but its worth looking to see
6482       if your problem can fit that model.
6483
6484       WARNING:
6485          mongoc_gridfs_t does not support read preferences. In a replica set,
6486          GridFS queries are always routed to the primary.
6487
6488   Thread Safety
6489       mongoc_gridfs_t  is NOT thread-safe and should only be used in the same
6490       thread as the owning mongoc_client_t.
6491
6492   Lifecycle
6493       It is an error to free a mongoc_gridfs_t  before  freeing  all  related
6494       instances of mongoc_gridfs_file_t and mongoc_gridfs_file_list_t.
6495
6496   Example
6497       example-gridfs.c.INDENT 0.0
6498
6499          #include <assert.h>
6500          #include <mongoc/mongoc.h>
6501          #include <stdio.h>
6502          #include <stdlib.h>
6503          #include <fcntl.h>
6504
6505          int
6506          main (int argc, char *argv[])
6507          {
6508             mongoc_gridfs_t *gridfs;
6509             mongoc_gridfs_file_t *file;
6510             mongoc_gridfs_file_list_t *list;
6511             mongoc_gridfs_file_opt_t opt = {0};
6512             mongoc_client_t *client;
6513             const char *uri_string = "mongodb://127.0.0.1:27017/?appname=gridfs-example";
6514             mongoc_uri_t *uri;
6515             mongoc_stream_t *stream;
6516             bson_t filter;
6517             bson_t opts;
6518             bson_t child;
6519             bson_error_t error;
6520             ssize_t r;
6521             char buf[4096];
6522             mongoc_iovec_t iov;
6523             const char *filename;
6524             const char *command;
6525             bson_value_t id;
6526
6527             if (argc < 2) {
6528                fprintf (stderr, "usage - %s command ...\n", argv[0]);
6529                return EXIT_FAILURE;
6530             }
6531
6532             mongoc_init ();
6533
6534             iov.iov_base = (void *) buf;
6535             iov.iov_len = sizeof buf;
6536
6537             /* connect to localhost client */
6538             uri = mongoc_uri_new_with_error (uri_string, &error);
6539             if (!uri) {
6540                fprintf (stderr,
6541                         "failed to parse URI: %s\n"
6542                         "error message:       %s\n",
6543                         uri_string,
6544                         error.message);
6545                return EXIT_FAILURE;
6546             }
6547
6548             client = mongoc_client_new_from_uri (uri);
6549             assert (client);
6550             mongoc_client_set_error_api (client, 2);
6551
6552             /* grab a gridfs handle in test prefixed by fs */
6553             gridfs = mongoc_client_get_gridfs (client, "test", "fs", &error);
6554             assert (gridfs);
6555
6556             command = argv[1];
6557             filename = argv[2];
6558
6559             if (strcmp (command, "read") == 0) {
6560                if (argc != 3) {
6561                   fprintf (stderr, "usage - %s read filename\n", argv[0]);
6562                   return EXIT_FAILURE;
6563                }
6564                file = mongoc_gridfs_find_one_by_filename (gridfs, filename, &error);
6565                assert (file);
6566
6567                stream = mongoc_stream_gridfs_new (file);
6568                assert (stream);
6569
6570                for (;;) {
6571                   r = mongoc_stream_readv (stream, &iov, 1, -1, 0);
6572
6573                   assert (r >= 0);
6574
6575                   if (r == 0) {
6576                      break;
6577                   }
6578
6579                   if (fwrite (iov.iov_base, 1, r, stdout) != r) {
6580                      MONGOC_ERROR ("Failed to write to stdout. Exiting.\n");
6581                      exit (1);
6582                   }
6583                }
6584
6585                mongoc_stream_destroy (stream);
6586                mongoc_gridfs_file_destroy (file);
6587             } else if (strcmp (command, "list") == 0) {
6588                bson_init (&filter);
6589
6590                bson_init (&opts);
6591                bson_append_document_begin (&opts, "sort", -1, &child);
6592                BSON_APPEND_INT32 (&child, "filename", 1);
6593                bson_append_document_end (&opts, &child);
6594
6595                list = mongoc_gridfs_find_with_opts (gridfs, &filter, &opts);
6596
6597                bson_destroy (&filter);
6598                bson_destroy (&opts);
6599
6600                while ((file = mongoc_gridfs_file_list_next (list))) {
6601                   const char *name = mongoc_gridfs_file_get_filename (file);
6602                   printf ("%s\n", name ? name : "?");
6603
6604                   mongoc_gridfs_file_destroy (file);
6605                }
6606
6607                mongoc_gridfs_file_list_destroy (list);
6608             } else if (strcmp (command, "write") == 0) {
6609                if (argc != 4) {
6610                   fprintf (stderr, "usage - %s write filename input_file\n", argv[0]);
6611                   return EXIT_FAILURE;
6612                }
6613
6614                stream = mongoc_stream_file_new_for_path (argv[3], O_RDONLY, 0);
6615                assert (stream);
6616
6617                opt.filename = filename;
6618
6619                /* the driver generates a file_id for you */
6620                file = mongoc_gridfs_create_file_from_stream (gridfs, stream, &opt);
6621                assert (file);
6622
6623                id.value_type = BSON_TYPE_INT32;
6624                id.value.v_int32 = 1;
6625
6626                /* optional: the following method specifies a file_id of any
6627                   BSON type */
6628                if (!mongoc_gridfs_file_set_id (file, &id, &error)) {
6629                   fprintf (stderr, "%s\n", error.message);
6630                   return EXIT_FAILURE;
6631                }
6632
6633                if (!mongoc_gridfs_file_save (file)) {
6634                   mongoc_gridfs_file_error (file, &error);
6635                   fprintf (stderr, "Could not save: %s\n", error.message);
6636                   return EXIT_FAILURE;
6637                }
6638
6639                mongoc_gridfs_file_destroy (file);
6640             } else {
6641                fprintf (stderr, "Unknown command");
6642                return EXIT_FAILURE;
6643             }
6644
6645             mongoc_gridfs_destroy (gridfs);
6646             mongoc_uri_destroy (uri);
6647             mongoc_client_destroy (client);
6648
6649             mongoc_cleanup ();
6650
6651             return EXIT_SUCCESS;
6652          }
6653
6654
6655   mongoc_host_list_t
6656   Synopsis
6657          typedef struct {
6658             mongoc_host_list_t *next;
6659             char host[BSON_HOST_NAME_MAX + 1];
6660             char host_and_port[BSON_HOST_NAME_MAX + 7];
6661             uint16_t port;
6662             int family;
6663             void *padding[4];
6664          } mongoc_host_list_t;
6665
6666   Description
6667       The  host  and  port of a MongoDB server. Can be part of a linked list:
6668       for example the return  value  of  mongoc_uri_get_hosts  when  multiple
6669       hosts are provided in the MongoDB URI.
6670
6671   See Also
6672       mongoc_uri_get_hosts and mongoc_cursor_get_host.
6673
6674   mongoc_index_opt_geo_t
6675   Synopsis
6676          #include <mongoc/mongoc.h>
6677
6678          typedef struct {
6679             uint8_t twod_sphere_version;
6680             uint8_t twod_bits_precision;
6681             double twod_location_min;
6682             double twod_location_max;
6683             double haystack_bucket_size;
6684             uint8_t *padding[32];
6685          } mongoc_index_opt_geo_t;
6686
6687   Description
6688       This  structure  contains the options that may be used for tuning a GEO
6689       index.
6690
6691   See Also
6692       mongoc_index_opt_t
6693
6694       mongoc_index_opt_wt_t
6695
6696   mongoc_index_opt_t
6697   Synopsis
6698          #include <mongoc/mongoc.h>
6699
6700          typedef struct {
6701             bool is_initialized;
6702             bool background;
6703             bool unique;
6704             const char *name;
6705             bool drop_dups;
6706             bool sparse;
6707             int32_t expire_after_seconds;
6708             int32_t v;
6709             const bson_t *weights;
6710             const char *default_language;
6711             const char *language_override;
6712             mongoc_index_opt_geo_t *geo_options;
6713             mongoc_index_opt_storage_t *storage_options;
6714             const bson_t *partial_filter_expression;
6715             const bson_t *collation;
6716             void *padding[4];
6717          } mongoc_index_opt_t;
6718
6719   Deprecated
6720       This structure is deprecated and should not be used in  new  code.  See
6721       create-indexes.
6722
6723   Description
6724       This  structure contains the options that may be used for tuning a spe‐
6725       cific index.
6726
6727       See the createIndexes documentations in the MongoDB manual for descrip‐
6728       tions of individual options.
6729
6730       NOTE:
6731          dropDups  is deprecated as of MongoDB version 3.0.0.  This option is
6732          silently ignored by the server and unique index  builds  using  this
6733          option will fail if a duplicate value is detected.
6734
6735   Example
6736          {
6737             bson_t keys;
6738             bson_error_t error;
6739             mongoc_index_opt_t opt;
6740             mongoc_index_opt_geo_t geo_opt;
6741
6742             mongoc_index_opt_init (&opt);
6743             mongoc_index_opt_geo_init (&geo_opt);
6744
6745             bson_init (&keys);
6746             BSON_APPEND_UTF8 (&keys, "location", "2d");
6747
6748             geo_opt.twod_location_min = -123;
6749             geo_opt.twod_location_max = +123;
6750             geo_opt.twod_bits_precision = 30;
6751             opt.geo_options = &geo_opt;
6752
6753             collection = mongoc_client_get_collection (client, "test", "geo_test");
6754             if (mongoc_collection_create_index (collection, &keys, &opt, &error)) {
6755                /* Successfully created the geo index */
6756             }
6757             bson_destroy (&keys);
6758             mongoc_collection_destroy (&collection);
6759          }
6760
6761   See Also
6762       mongoc_index_opt_geo_t
6763
6764       mongoc_index_opt_wt_t
6765
6766   mongoc_index_opt_wt_t
6767   Synopsis
6768          #include <mongoc/mongoc.h>
6769
6770          typedef struct {
6771             mongoc_index_opt_storage_t base;
6772             const char *config_str;
6773             void *padding[8];
6774          } mongoc_index_opt_wt_t;
6775
6776   Description
6777       This  structure  contains  the  options  that  may be used for tuning a
6778       WiredTiger specific index.
6779
6780   See Also
6781       mongoc_index_opt_t
6782
6783       mongoc_index_opt_geo_t
6784
6785   mongoc_insert_flags_t
6786       Flags for insert operations
6787
6788   Synopsis
6789          typedef enum {
6790             MONGOC_INSERT_NONE = 0,
6791             MONGOC_INSERT_CONTINUE_ON_ERROR = 1 << 0,
6792          } mongoc_insert_flags_t;
6793
6794          #define MONGOC_INSERT_NO_VALIDATE (1U << 31)
6795
6796   Description
6797       These flags correspond to the MongoDB wire protocol. They may  be  bit‐
6798       wise  or'd  together. They may modify how an insert happens on the Mon‐
6799       goDB server.
6800
6801   Flag Values
6802              ┌──────────────────────────┬────────────────────────────┐
6803              │MONGOC_INSERT_NONE        │ Specify no insert flags.   │
6804              ├──────────────────────────┼────────────────────────────┤
6805              │MONGOC_INSERT_CON‐        │ Continue  inserting  docu‐ │
6806              │TINUE_ON_ERROR            │ ments from  the  insertion │
6807              │                          │ set  even  if  one  insert │
6808              │                          │ fails.                     │
6809              ├──────────────────────────┼────────────────────────────┤
6810              │MONGOC_INSERT_NO_VALIDATE │ Do not validate  insertion │
6811              │                          │ documents  before perform‐ │
6812              │                          │ ing an insert.  Validation │
6813              │                          │ can  be expensive, so this │
6814              │                          │ can save some time if  you │
6815              │                          │ know  your  documents  are │
6816              │                          │ already valid.             │
6817              └──────────────────────────┴────────────────────────────┘
6818
6819   mongoc_iovec_t
6820   Synopsis
6821   Synopsis
6822          #include <mongoc/mongoc.h>
6823
6824          #ifdef _WIN32
6825          typedef struct {
6826             u_long iov_len;
6827             char *iov_base;
6828          } mongoc_iovec_t;
6829          #else
6830          typedef struct iovec mongoc_iovec_t;
6831          #endif
6832
6833       The mongoc_iovec_t structure is a portability abstraction for consumers
6834       of  the  mongoc_stream_t  interfaces.  It allows for scatter/gather I/O
6835       through the socket subsystem.
6836
6837       WARNING:
6838          When writing portable code, beware of the ordering  of  iov_len  and
6839          iov_base  as they are different on various platforms. Therefore, you
6840          should not use C initializers for initialization.
6841
6842   mongoc_matcher_t
6843       Client-side document matching abstraction
6844
6845   Synopsis
6846          typedef struct _mongoc_matcher_t mongoc_matcher_t;
6847
6848       mongoc_matcher_t provides a reduced-interface for client-side  matching
6849       of BSON documents.
6850
6851       It can perform the basics such as $in, $nin, $eq, $neq, $gt, $gte, $lt,
6852       and $lte.
6853
6854       WARNING:
6855          mongoc_matcher_t does not currently support  the  full  spectrum  of
6856          query operations that the MongoDB server supports.
6857
6858   Deprecated
6859       WARNING:
6860          mongoc_matcher_t is deprecated and will be removed in version 2.0.
6861
6862   Example
6863       Filter  a sequence of BSON documents from STDIN based on a query.INDENT
6864       0.0
6865
6866          #include <bson/bson.h>
6867          #include <mongoc/mongoc.h>
6868          #include <stdio.h>
6869
6870          int
6871          main (int argc, char *argv[])
6872          {
6873             mongoc_matcher_t *matcher;
6874             bson_reader_t *reader;
6875             const bson_t *bson;
6876             bson_t *spec;
6877             char *str;
6878             int fd;
6879
6880             mongoc_init ();
6881
6882          #ifdef _WIN32
6883             fd = fileno (stdin);
6884          #else
6885             fd = STDIN_FILENO;
6886          #endif
6887
6888             reader = bson_reader_new_from_fd (fd, false);
6889
6890             spec = BCON_NEW ("hello", "world");
6891             matcher = mongoc_matcher_new (spec, NULL);
6892
6893             while ((bson = bson_reader_read (reader, NULL))) {
6894                if (mongoc_matcher_match (matcher, bson)) {
6895                   str = bson_as_canonical_extended_json (bson, NULL);
6896                   printf ("%s\n", str);
6897                   bson_free (str);
6898                }
6899             }
6900
6901             bson_reader_destroy (reader);
6902             bson_destroy (spec);
6903
6904             mongoc_cleanup ();
6905
6906             return 0;
6907          }
6908
6909   mongoc_query_flags_t
6910       Flags for query operations
6911
6912   Synopsis
6913          typedef enum {
6914             MONGOC_QUERY_NONE = 0,
6915             MONGOC_QUERY_TAILABLE_CURSOR = 1 << 1,
6916             MONGOC_QUERY_SLAVE_OK = 1 << 2,
6917             MONGOC_QUERY_OPLOG_REPLAY = 1 << 3,
6918             MONGOC_QUERY_NO_CURSOR_TIMEOUT = 1 << 4,
6919             MONGOC_QUERY_AWAIT_DATA = 1 << 5,
6920             MONGOC_QUERY_EXHAUST = 1 << 6,
6921             MONGOC_QUERY_PARTIAL = 1 << 7,
6922          } mongoc_query_flags_t;
6923
6924   Description
6925       These flags correspond to the MongoDB wire protocol. They may  be  bit‐
6926       wise  or'd  together.  They  may modify how a query is performed in the
6927       MongoDB server.
6928
6929   Flag Values
6930              ┌───────────────────────────┬────────────────────────────┐
6931              │MONGOC_QUERY_NONE          │ Specify no query flags.    │
6932              └───────────────────────────┴────────────────────────────┘
6933
6934
6935
6936
6937              │MONGOC_QUERY_TAILABLE_CUR‐ │ Cursor  will not be closed │
6938              │SOR                        │ when  the  last  data   is │
6939              │                           │ retrieved.  You can resume │
6940              │                           │ this cursor later.         │
6941              ├───────────────────────────┼────────────────────────────┤
6942              │MONGOC_QUERY_SLAVE_OK      │ Allow query of replica set │
6943              │                           │ secondaries.               │
6944              ├───────────────────────────┼────────────────────────────┤
6945              │MONGOC_QUERY_OPLOG_REPLAY  │ Used  internally  by  Mon‐ │
6946              │                           │ goDB.                      │
6947              ├───────────────────────────┼────────────────────────────┤
6948              │MONGOC_QUERY_NO_CUR‐       │ The  server normally times │
6949              │SOR_TIMEOUT                │ out an idle  cursor  after │
6950              │                           │ an  inactivity  period (10 │
6951              │                           │ minutes).  This   prevents │
6952              │                           │ that.                      │
6953              ├───────────────────────────┼────────────────────────────┤
6954              │MONGOC_QUERY_AWAIT_DATA    │ Use        with       MON‐ │
6955              │                           │ GOC_QUERY_TAILABLE_CURSOR. │
6956              │                           │ Block  rather than return‐ │
6957              │                           │ ing  no  data.   After   a │
6958              │                           │ period, time out.          │
6959              ├───────────────────────────┼────────────────────────────┤
6960              │MONGOC_QUERY_EXHAUST       │ Stream  the data down full │
6961              │                           │ blast in multiple  "reply" │
6962              │                           │ packets.  Faster  when you │
6963              │                           │ are pulling down a lot  of │
6964              │                           │ data and you know you want │
6965              │                           │ to retrieve it all.        │
6966              ├───────────────────────────┼────────────────────────────┤
6967              │MONGOC_QUERY_PARTIAL       │ Get partial  results  from │
6968              │                           │ mongos  if some shards are │
6969              │                           │ down (instead of  throwing │
6970              │                           │ an error).                 │
6971              └───────────────────────────┴────────────────────────────┘
6972
6973   mongoc_rand
6974       MongoDB Random Number Generator
6975
6976   Synopsis
6977          void
6978          mongoc_rand_add (const void *buf, int num, doubel entropy);
6979
6980          void
6981          mongoc_rand_seed (const void *buf, int num);
6982
6983          int
6984          mongoc_rand_status (void);
6985
6986   Description
6987       The  mongoc_rand  family  of  functions provide access to the low level
6988       randomness primitives used by the MongoDB  C  Driver.   In  particular,
6989       they  control  the  creation  of cryptographically strong pseudo-random
6990       bytes required by some security mechanisms.
6991
6992       While we can usually pull enough entropy from the environment, you  may
6993       be  required  to  seed the PRNG manually depending on your OS, hardware
6994       and other entropy consumers running on the same system.
6995
6996   Entropy
6997       mongoc_rand_add and mongoc_rand_seed allow the user to directly provide
6998       entropy.   They  differ  insofar as mongoc_rand_seed requires that each
6999       bit provided is fully random.  mongoc_rand_add allows the user to spec‐
7000       ify the degree of randomness in the provided bytes as well.
7001
7002   Status
7003       The  mongoc_rand_status function allows the user to check the status of
7004       the mongoc PRNG.  This can be used to guarantee sufficient  entropy  at
7005       program startup, rather than waiting for runtime errors to occur.
7006
7007   mongoc_read_concern_t
7008       Read Concern abstraction
7009
7010   Synopsis
7011       New in MongoDB 3.2.
7012
7013       The mongoc_read_concern_t allows clients to choose a level of isolation
7014       for their reads. The default, MONGOC_READ_CONCERN_LEVEL_LOCAL, is right
7015       for the great majority of applications.
7016
7017       You can specify a read concern on connection objects, database objects,
7018       or collection objects.
7019
7020       See readConcern on the MongoDB website for more information.
7021
7022       Read Concern is only sent to MongoDB when it has explicitly been set by
7023       mongoc_read_concern_set_level to anything other than NULL.
7024
7025   Read Concern Levels
7026          ┌────────────────────┬─────────────────────┬─────────────────────┐
7027          │Macro               │ Description         │ First  MongoDB ver‐ │
7028          │                    │                     │ sion                │
7029          ├────────────────────┼─────────────────────┼─────────────────────┤
7030          │MONGOC_READ_CON‐    │ Level  "local", the │ 3.2                 │
7031          │CERN_LEVEL_LOCAL    │ default.            │                     │
7032          ├────────────────────┼─────────────────────┼─────────────────────┤
7033          │MONGOC_READ_CON‐    │ Level "majority".   │ 3.2                 │
7034          │CERN_LEVEL_MAJORITY │                     │                     │
7035          ├────────────────────┼─────────────────────┼─────────────────────┤
7036          │MONGOC_READ_CON‐    │ Level    "lineariz‐ │ 3.4                 │
7037          │CERN_LEVEL_LIN‐     │ able".              │                     │
7038          │EARIZABLE           │                     │                     │
7039          ├────────────────────┼─────────────────────┼─────────────────────┤
7040          │MONGOC_READ_CON‐    │ Level "available".  │ 3.6                 │
7041          │CERN_LEVEL_AVAIL‐   │                     │                     │
7042          │ABLE                │                     │                     │
7043          ├────────────────────┼─────────────────────┼─────────────────────┤
7044          │MONGOC_READ_CON‐    │ Level "snapshot".   │ 4.0                 │
7045          │CERN_LEVEL_SNAPSHOT │                     │                     │
7046          └────────────────────┴─────────────────────┴─────────────────────┘
7047
7048       For  the  sake  of  compatibility with future versions of MongoDB, mon‐
7049       goc_read_concern_set_level allows any string, not  just  this  list  of
7050       known read concern levels.
7051
7052       See  Read  Concern  Levels  in  the MongoDB manual for more information
7053       about the individual read concern levels.
7054
7055   mongoc_read_mode_t
7056       Read Preference Modes
7057
7058   Synopsis
7059          typedef enum {
7060             MONGOC_READ_PRIMARY = (1 << 0),
7061             MONGOC_READ_SECONDARY = (1 << 1),
7062             MONGOC_READ_PRIMARY_PREFERRED = (1 << 2) | MONGOC_READ_PRIMARY,
7063             MONGOC_READ_SECONDARY_PREFERRED = (1 << 2) | MONGOC_READ_SECONDARY,
7064             MONGOC_READ_NEAREST = (1 << 3) | MONGOC_READ_SECONDARY,
7065          } mongoc_read_mode_t;
7066
7067   Description
7068       This enum describes how reads should be dispatched. The default is MON‐
7069       GOC_READ_PRIMARY.
7070
7071       Please see the MongoDB website for a description of Read Preferences.
7072
7073   mongoc_read_prefs_t
7074       A read preference abstraction
7075
7076   Synopsis
7077       mongoc_read_prefs_t  provides an abstraction on top of the MongoDB con‐
7078       nection read prefences. It allows for hinting to the driver which nodes
7079       in a replica set should be accessed first.
7080
7081       You  can specify a read preference mode on connection objects, database
7082       objects, collection objects, or per-operation.  Generally, it makes the
7083       most  sense to stick with the global default, MONGOC_READ_PRIMARY.  All
7084       of the other modes come with caveats that won't  be  covered  in  great
7085       detail here.
7086
7087   Read Modes
7088              ──────────────────────────────────────────────────────────
7089               MONGOC_READ_PRIMARY          Default  mode.  All opera‐
7090                                            tions read from  the  cur‐
7091                                            rent replica set primary.
7092              ──────────────────────────────────────────────────────────
7093               MONGOC_READ_SECONDARY        All  operations  read from
7094                                            among  the  nearest   sec‐
7095                                            ondary   members   of  the
7096                                            replica set.
7097              ──────────────────────────────────────────────────────────
7098               MONGOC_READ_PRIMARY_PRE‐     In most situations, opera‐
7099               FERRED                       tions read from  the  pri‐
7100                                            mary but if it is unavail‐
7101                                            able, operations read from
7102                                            secondary members.
7103              ──────────────────────────────────────────────────────────
7104               MONGOC_READ_SECONDARY_PRE‐   In most situations, opera‐
7105               FERRED                       tions  read from among the
7106                                            nearest secondary members,
7107                                            but  if no secondaries are
7108                                            available, operations read
7109                                            from the primary.
7110              ──────────────────────────────────────────────────────────
7111               MONGOC_READ_NEAREST          Operations read from among
7112                                            the nearest members of the
7113                                            replica  set, irrespective
7114                                            of the member's type.
7115              ┌───────────────────────────┬────────────────────────────┐
7116              │                           │                            │
7117   Tag Sets   │                           │                            │
7118       Tag set│s allow you to specify custo│m read preferences  and  writ│e  con‐
7119       cerns  │so  that your application ca│n target operations to specif│ic mem‐
7120       bers.  │                           │                            │
7121              │                           │                            │
7122       Custom │read preferences and write c│oncerns evaluate tags sets  i│n  dif‐
7123       ferent │ways: read preferences cons│ider the value of a tag when │select‐
7124       ing a m│ember to read from. while wr│ite concerns ignore the value│ of  a
7125       tag  to│ when  selecting a member e│xcept to consider whether or │not the
7126       value i│s unique.                   │                            │
7127              │                           │                            │
7128       You can│specify tag sets with the f│ollowing read preference mode│s:
7129              │                           │                            │
7130       · prima│ryPreferred                 │                            │
7131              │                           │                            │
7132       · secon│dary                        │                            │
7133              │                           │                            │
7134       · secon│daryPreferred               │                            │
7135              │                           │                            │
7136       · neare│st                          │                            │
7137              │                           │                            │
7138       Tags ar│e not compatible with MONGOC│_READ_PRIMARY and, in general│,  only
7139       apply  │when selecting a secondary m│ember of a set for a read ope│ration.
7140       However│, the nearest read mode, whe│n  combined  with  a  tag  se│t  will
7141       select │the nearest member that matc│hes the specified tag set, wh│ich may
7142       be a pr│imary or secondary.         │                            │
7143              │                           │                            │
7144       Tag set│s are represented as a comma│-separated list  of  colon-se│parated
7145       key-val│ue   pairs   when   provided│  as   a  connection  string│,  e.g.
7146       dc:ny,r│ack:1.                      │                            │
7147              │                           │                            │
7148       To spec│ify a list of tag sets, usin│g multiple readPreferenceTags│, e.g.
7149              │                           │                            │
7150          read│PreferenceTags=dc:ny,rack:1;│readPreferenceTags=dc:ny;read│PreferenceTags=
7151              │                           │                            │
7152       Note th│e empty value for the last o│ne, which means match any  se│condary
7153       as a la│st resort.                  │                            │
7154              │                           │                            │
7155       Order m│atters when using multiple r│eadPreferenceTags.           │
7156              │                           │                            │
7157       Tag Set│s can also be configured usi│ng mongoc_read_prefs_set_tags│.
7158              │                           │                            │
7159       All int│erfaces use the same member │selection logic to choose the│member
7160       to whic│h to direct read operations,│basing the choice on  read  │prefer‐
7161       ence mo│de and tag sets.            │                            │
7162              │                           │                            │
7163   Max Stalene│ss                          │                            │
7164       When  c│onnected to replica set runn│ing MongoDB 3.4 or later, the│driver
7165       estimat│es the staleness of each sec│ondary based on lastWriteDate│values
7166       provide│d in server isMaster respons│es.                          │
7167              │                           │                            │
7168       Max  Staleness  is  the  maximum replication lag in seconds (wall clock
7169       time) that a secondary can suffer and still be eligible for reads.  The
7170       default  is  MONGOC_NO_MAX_STALENESS,  which disables staleness checks.
7171       Otherwise, it  must  be  a  positive  integer  at  least  MONGOC_SMALL‐
7172       EST_MAX_STALENESS_SECONDS (90 seconds).
7173
7174       Max  Staleness is also supported by sharded clusters of replica sets if
7175       all servers run MongoDB 3.4 or later.
7176
7177   mongoc_remove_flags_t
7178       Flags for deletion operations
7179
7180   Synopsis
7181          typedef enum {
7182             MONGOC_REMOVE_NONE = 0,
7183             MONGOC_REMOVE_SINGLE_REMOVE = 1 << 0,
7184          } mongoc_remove_flags_t;
7185
7186   Description
7187       These flags correspond to the MongoDB wire protocol. They may  be  bit‐
7188       wise  or'd  together.  They may change the number of documents that are
7189       removed during a remove command.
7190
7191   Flag Values
7192                  ┌───────────────────┬────────────────────────────┐
7193                  │MONGOC_REMOVE_NONE │ Specify no removal  flags. │
7194                  │                   │ All   matching   documents │
7195                  │                   │ will be removed.           │
7196                  ├───────────────────┼────────────────────────────┤
7197                  │MONGOC_REMOVE_SIN‐ │ Only   remove   the  first │
7198                  │GLE_REMOVE         │ matching document from the │
7199                  │                   │ selector.                  │
7200                  └───────────────────┴────────────────────────────┘
7201
7202   mongoc_reply_flags_t
7203       Flags from server replies
7204
7205   Synopsis
7206          typedef enum {
7207             MONGOC_REPLY_NONE = 0,
7208             MONGOC_REPLY_CURSOR_NOT_FOUND = 1 << 0,
7209             MONGOC_REPLY_QUERY_FAILURE = 1 << 1,
7210             MONGOC_REPLY_SHARD_CONFIG_STALE = 1 << 2,
7211             MONGOC_REPLY_AWAIT_CAPABLE = 1 << 3,
7212          } mongoc_reply_flags_t;
7213
7214   Description
7215       These  flags  correspond to the wire protocol. They may be bitwise or'd
7216       together.
7217
7218   Flag Values
7219              ┌───────────────────────────┬────────────────────────────┐
7220              │MONGOC_REPLY_NONE          │ No flags set.              │
7221              ├───────────────────────────┼────────────────────────────┤
7222              │MONGOC_REPLY_CUR‐          │ No   matching  cursor  was │
7223              │SOR_NOT_FOUND              │ found on the server.       │
7224              ├───────────────────────────┼────────────────────────────┤
7225              │MONGOC_REPLY_QUERY_FAILURE │ The query  failed  or  was │
7226              │                           │ invalid.   Error  document │
7227              │                           │ has been provided.         │
7228              ├───────────────────────────┼────────────────────────────┤
7229              │MONGOC_REPLY_SHARD_CON‐    │ Shard config is stale.     │
7230              │FIG_STALE                  │                            │
7231              ├───────────────────────────┼────────────────────────────┤
7232              │MONGOC_REPLY_AWAIT_CAPABLE │ If  the returned cursor is │
7233              │                           │ capable      of       MON‐ │
7234              │                           │ GOC_QUERY_AWAIT_DATA.      │
7235              └───────────────────────────┴────────────────────────────┘
7236
7237   mongoc_server_description_t
7238       Server description
7239
7240   Synopsis
7241          #include <mongoc/mongoc.h>
7242          typedef struct _mongoc_server_description_t mongoc_server_description_t
7243
7244       mongoc_server_description_t  holds information about a mongod or mongos
7245       the driver is connected to.
7246
7247       See also mongoc_client_get_server_descriptions().
7248
7249   Lifecycle
7250       Clean up with mongoc_server_description_destroy().
7251
7252   mongoc_session_opt_t
7253          #include <mongoc/mongoc.h>
7254
7255          typedef struct _mongoc_session_opt_t mongoc_session_opt_t;
7256
7257   Synopsis
7258       Start a session with mongoc_client_start_session, use the session for a
7259       sequence  of  operations  and multi-document transactions, then free it
7260       with  mongoc_client_session_destroy().  Any  mongoc_cursor_t  or   mon‐
7261       goc_change_stream_t  using  a session must be destroyed before the ses‐
7262       sion, and a session must be destroyed  before  the  mongoc_client_t  it
7263       came from.
7264
7265       By default, sessions are causally consistent. To disable causal consis‐
7266       tency, before starting a session  create  a  mongoc_session_opt_t  with
7267       mongoc_session_opts_new()  and call mongoc_session_opts_set_causal_con‐
7268       sistency(), then free the struct with mongoc_session_opts_destroy.
7269
7270       Unacknowledged writes are prohibited with sessions.
7271
7272       A mongoc_client_session_t must be used by only one thread  at  a  time.
7273       Due  to  session pooling, mongoc_client_start_session may return a ses‐
7274       sion that has been idle for some time and is about to be  closed  after
7275       its  idle timeout. Use the session within one minute of acquiring it to
7276       refresh the session and avoid a timeout.
7277
7278       See the example code for mongoc_session_opts_set_causal_consistency.
7279
7280   mongoc_socket_t
7281       Portable socket abstraction
7282
7283   Synopsis
7284          #include <mongoc/mongoc.h>
7285
7286          typedef struct _mongoc_socket_t mongoc_socket_t
7287
7288   Synopsis
7289       This structure provides a socket abstraction  that  is  friendlier  for
7290       portability  than  BSD sockets directly. Inconsistencies between Linux,
7291       various BSDs, Solaris, and Windows are handled here.
7292
7293   mongoc_ssl_opt_t
7294   Synopsis
7295          typedef struct {
7296             const char *pem_file;
7297             const char *pem_pwd;
7298             const char *ca_file;
7299             const char *ca_dir;
7300             const char *crl_file;
7301             bool weak_cert_validation;
7302             bool allow_invalid_hostname;
7303             void *padding[7];
7304          } mongoc_ssl_opt_t;
7305
7306   Description
7307       This structure is used to set the SSL options for a mongoc_client_t  or
7308       mongoc_client_pool_t.
7309
7310       Beginning  in  version 1.2.0, once a pool or client has any SSL options
7311       set, all connections use SSL, even if ssl=true is omitted from the Mon‐
7312       goDB URI. Before, SSL options were ignored unless ssl=true was included
7313       in the URI.
7314
7315       As   of   1.4.0,   the   mongoc_client_pool_set_ssl_opts    and    mon‐
7316       goc_client_set_ssl_opts will not only shallow copy the struct, but will
7317       also copy the const char*. It is therefore no  longer  needed  to  make
7318       sure the values remain valid after setting them.
7319
7320   Configuration through URI Options
7321       Most of the configurable options can be using the Connection URI.
7322
7323                 ┌───────────────────────┬──────────────────────────┐
7324mongoc_ssl_opt_t key   URI key                  
7325                 ├───────────────────────┼──────────────────────────┤
7326                 │pem_file               │ sslClientCertificateKey‐ │
7327                 │                       │ File                     │
7328                 ├───────────────────────┼──────────────────────────┤
7329                 │pem_pwd                │ sslClientCertificateKey‐ │
7330                 │                       │ Password                 │
7331                 ├───────────────────────┼──────────────────────────┤
7332                 │ca_file                │ sslCertificateAuthority‐ │
7333                 │                       │ File                     │
7334                 ├───────────────────────┼──────────────────────────┤
7335                 │weak_cert_validation   │ sslAllowInvalidCertifi‐  │
7336                 │                       │ cates                    │
7337                 ├───────────────────────┼──────────────────────────┤
7338                 │allow_invalid_hostname │ sslAllowInvalidHostnames │
7339                 └───────────────────────┴──────────────────────────┘
7340
7341   Client Authentication
7342       When  MongoDB  is  started with SSL enabled, it will by default require
7343       the client to provide a client  certificate  issued  by  a  certificate
7344       authority  specified  by  --sslCAFile,  or  an authority trusted by the
7345       native certificate store in use on the server.
7346
7347       To provide the client certificate, the user must configure the pem_file
7348       to point at a PEM armored certificate.
7349
7350          mongoc_ssl_opt_t ssl_opts = {0};
7351
7352          ssl_opts.pem_file = "/path/to/client-certificate.pem"
7353
7354          /* Then set the client ssl_opts, when using a single client mongoc_client_t */
7355          mongoc_client_pool_set_ssl_opts (pool, &ssl_opts);
7356
7357          /* or, set the pool ssl_opts, when using a the thread safe mongoc_client_pool_t */
7358          mongoc_client_set_ssl_opts (client, &ssl_opts);
7359
7360   Server Certificate Verification
7361       The  MongoDB  C  Driver  will  automatically verify the validity of the
7362       server certificate, such as issued by configured Certificate Authority,
7363       hostname validation, and expiration.
7364
7365       To overwrite this behaviour, it is possible to disable hostname valida‐
7366       tion, and/or allow otherwise invalid certificates.  This  behaviour  is
7367       controlled  using  the  allow_invalid_hostname and weak_cert_validation
7368       fields. By default, both are set to false. It  is  not  recommended  to
7369       change  these  defaults  as  it exposes the client to Man In The Middle
7370       attacks (when allow_invalid_hostname is set) and otherwise invalid cer‐
7371       tificates when weak_cert_validation is set to true.
7372
7373   OpenSSL
7374       The  MongoDB  C  Driver  uses  OpenSSL, if available, on Linux and Unix
7375       platforms (besides macOS). Industry best practices and some regulations
7376       require  the  use  of TLS 1.1 or newer, which requires at least OpenSSL
7377       1.0.1. Check your OpenSSL version like so:
7378
7379          $ openssl version
7380
7381       Ensure your system's OpenSSL is a recent version (at least  1.0.1),  or
7382       install  a  recent  version  in  a non-system path and build against it
7383       with:
7384
7385          cmake -DOPENSSL_ROOT_DIR=/absolute/path/to/openssl
7386
7387       When compiled against OpenSSL, the driver will attempt to load the sys‐
7388       tem  default  certificate  store, as configured by the distribution, if
7389       the ca_file and ca_dir are not set.
7390
7391   LibreSSL / libtls
7392       The MongoDB C Driver supports LibreSSL through the use of OpenSSL  com‐
7393       patibility  checks  when configured to compile against openssl. It also
7394       supports the new  libtls  library  when  configured  to  build  against
7395       libressl.
7396
7397   Native TLS Support on Windows (Secure Channel)
7398       The  MongoDB  C  Driver supports the Windows native TLS library (Secure
7399       Channel, or SChannel), and its native crypto library (Cryptography API:
7400       Next Generation, or CNG).
7401
7402       When  compiled  against the Windows native libraries, the ca_dir option
7403       is not supported, and will issue an error if used.
7404
7405       Encrypted PEM files (e.g., requiring pem_pwd) are also  not  supported,
7406       and will result in error when attempting to load them.
7407
7408       When  ca_file  is  provided, the driver will only allow server certifi‐
7409       cates issued by  the  authority  (or  authorities)  provided.  When  no
7410       ca_file  is provided, the driver will look up the Certificate Authority
7411       using the System Local Machine Root certificate store  to  confirm  the
7412       provided certificate.
7413
7414       When  crl_file  is provided, the driver will import the revocation list
7415       to the System Local Machine Root certificate store.
7416
7417   Native TLS Support on macOS / Darwin (Secure Transport)
7418       The MongoDB C Driver supports the  Darwin  (OS  X,  macOS,  iOS,  etc.)
7419       native  TLS  library  (Secure Transport), and its native crypto library
7420       (Common Crypto, or CC).
7421
7422       When compiled against Secure Transport, the ca_dir option is  not  sup‐
7423       ported, and will issue an error if used.
7424
7425       When  ca_file  is  provided, the driver will only allow server certifi‐
7426       cates issued by  the  authority  (or  authorities)  provided.  When  no
7427       ca_file is provided, the driver will use the Certificate Authorities in
7428       the currently unlocked keychains.
7429
7430   See Also
7431       · mongoc_client_set_ssl_opts
7432
7433       · mongoc_client_pool_set_ssl_opts
7434
7435   mongoc_stream_buffered_t
7436   Synopsis
7437          typedef struct _mongoc_stream_buffered_t mongoc_stream_buffered_t;
7438
7439   Description
7440       mongoc_stream_buffered_t  should  be  considered  a  subclass  of  mon‐
7441       goc_stream_t. It performs buffering on an underlying stream.
7442
7443   See Also
7444       mongoc_stream_buffered_new()
7445
7446       mongoc_stream_destroy()
7447
7448   mongoc_stream_file_t
7449   Synopsis
7450          typedef struct _mongoc_stream_file_t mongoc_stream_file_t
7451
7452       mongoc_stream_file_t  is  a  mongoc_stream_t  subclass for working with
7453       standard UNIX style file-descriptors.
7454
7455   mongoc_stream_socket_t
7456   Synopsis
7457          typedef struct _mongoc_stream_socket_t mongoc_stream_socket_t
7458
7459       mongoc_stream_socket_t  should  be  considered  a  subclass   of   mon‐
7460       goc_stream_t that works upon socket streams.
7461
7462   mongoc_stream_t
7463   Synopsis
7464          typedef struct _mongoc_stream_t mongoc_stream_t
7465
7466       mongoc_stream_t  provides a generic streaming IO abstraction based on a
7467       struct of pointers interface. The idea is to  allow  wrappers,  perhaps
7468       other  language  drivers, to easily shim their IO system on top of mon‐
7469       goc_stream_t.
7470
7471       The API for the stream abstraction is currently private and  non-exten‐
7472       sible.
7473
7474   Stream Types
7475       There  are a number of built in stream types that come with mongoc. The
7476       default configuration is a buffered unix stream.  If  SSL  is  in  use,
7477       that in turn is wrapped in a tls stream.
7478
7479   See Also
7480       mongoc_stream_buffered_t
7481
7482       mongoc_stream_file_t
7483
7484       mongoc_stream_socket_t
7485
7486       mongoc_stream_tls_t
7487
7488   mongoc_stream_tls_t
7489   Synopsis
7490          typedef struct _mongoc_stream_tls_t mongoc_stream_tls_t
7491
7492       mongoc_stream_tls_t  is  a  mongoc_stream_t  subclass  for working with
7493       OpenSSL TLS streams.
7494
7495   mongoc_topology_description_t
7496       Status of MongoDB Servers
7497
7498   Synopsis
7499          typedef struct _mongoc_topology_description_t mongoc_topology_description_t;
7500
7501       mongoc_topology_description_t  is  an  opaque  type  representing   the
7502       driver's knowledge of the MongoDB server or servers it is connected to.
7503       Its API conforms to the SDAM Monitoring Specification.
7504
7505       Applications  receive  a  temporary  reference   to   a   mongoc_topol‐
7506       ogy_description_t  as  a  parameter to an SDAM Monitoring callback. See
7507       Introduction to Application Performance Monitoring.
7508
7509   mongoc_transaction_opt_t
7510          #include <mongoc/mongoc.h>
7511
7512          typedef struct _mongoc_transaction_opt_t mongoc_transaction_opt_t;
7513
7514   Synopsis
7515       Options for starting a multi-document transaction.
7516
7517       When a session is first created  with  mongoc_client_start_session,  it
7518       inherits  from  the  client  the  read concern, write concern, and read
7519       preference with which to start transactions. Each of these  fields  can
7520       be  overridden  independently.  Create  a mongoc_transaction_opt_t with
7521       mongoc_transaction_opts_new, and pass a non-NULL option to any  of  the
7522       mongoc_transaction_opt_t setter functions:
7523
7524       · mongoc_transaction_opts_set_read_concern
7525
7526       · mongoc_transaction_opts_set_write_concern
7527
7528       · mongoc_transaction_opts_set_read_prefs
7529
7530       Pass   the   resulting   transaction   options   to  mongoc_client_ses‐
7531       sion_start_transaction. Each field set in the transaction options over‐
7532       rides the inherited client configuration.
7533
7534   Example
7535       example-transaction.c.INDENT 0.0
7536
7537          /* gcc example-transaction.c -o example-transaction \
7538           *     $(pkg-config --cflags --libs libmongoc-1.0) */
7539
7540          /* ./example-transaction [CONNECTION_STRING] */
7541
7542          #include <stdio.h>
7543          #include <mongoc/mongoc.h>
7544
7545
7546          int
7547          main (int argc, char *argv[])
7548          {
7549             int exit_code = EXIT_FAILURE;
7550
7551             mongoc_client_t *client = NULL;
7552             mongoc_database_t *database = NULL;
7553             mongoc_collection_t *collection = NULL;
7554             mongoc_client_session_t *session = NULL;
7555             mongoc_session_opt_t *session_opts = NULL;
7556             mongoc_transaction_opt_t *default_txn_opts = NULL;
7557             mongoc_transaction_opt_t *txn_opts = NULL;
7558             mongoc_read_concern_t *read_concern = NULL;
7559             mongoc_write_concern_t *write_concern = NULL;
7560             const char *uri_string = "mongodb://127.0.0.1/?appname=transaction-example";
7561             mongoc_uri_t *uri;
7562             bson_error_t error;
7563             bson_t *doc = NULL;
7564             bson_t *insert_opts = NULL;
7565             int32_t i;
7566             int64_t start;
7567             bson_t reply = BSON_INITIALIZER;
7568             char *reply_json;
7569             bool r;
7570
7571             mongoc_init ();
7572
7573             if (argc > 1) {
7574                uri_string = argv[1];
7575             }
7576
7577             uri = mongoc_uri_new_with_error (uri_string, &error);
7578             if (!uri) {
7579                MONGOC_ERROR ("failed to parse URI: %s\n"
7580                              "error message:       %s\n",
7581                              uri_string,
7582                              error.message);
7583                goto done;
7584             }
7585
7586             client = mongoc_client_new_from_uri (uri);
7587             if (!client) {
7588                goto done;
7589             }
7590
7591             mongoc_client_set_error_api (client, 2);
7592             database = mongoc_client_get_database (client, "example-transaction");
7593
7594             /* inserting into a nonexistent collection normally creates it, but a
7595              * collection can't be created in a transaction; create it now */
7596             collection =
7597                mongoc_database_create_collection (database, "collection", NULL, &error);
7598
7599             if (!collection) {
7600                /* code 48 is NamespaceExists, see error_codes.err in mongodb source */
7601                if (error.code == 48) {
7602                   collection = mongoc_database_get_collection (database, "collection");
7603                } else {
7604                   MONGOC_ERROR ("Failed to create collection: %s", error.message);
7605                   goto done;
7606                }
7607             }
7608
7609             /* a transaction's read preferences, read concern, and write concern can be
7610              * set on the client, on the default transaction options, or when starting
7611              * the transaction. for the sake of this example, set read concern on the
7612              * default transaction options. */
7613             default_txn_opts = mongoc_transaction_opts_new ();
7614             read_concern = mongoc_read_concern_new ();
7615             mongoc_read_concern_set_level (read_concern, "snapshot");
7616             mongoc_transaction_opts_set_read_concern (default_txn_opts, read_concern);
7617             session_opts = mongoc_session_opts_new ();
7618             mongoc_session_opts_set_default_transaction_opts (session_opts,
7619                                                               default_txn_opts);
7620
7621             session = mongoc_client_start_session (client, session_opts, &error);
7622             if (!session) {
7623                MONGOC_ERROR ("Failed to start session: %s", error.message);
7624                goto done;
7625             }
7626
7627             /* in this example, set write concern when starting the transaction */
7628             txn_opts = mongoc_transaction_opts_new ();
7629             write_concern = mongoc_write_concern_new ();
7630             mongoc_write_concern_set_wmajority (write_concern, 1000 /* wtimeout */);
7631             mongoc_transaction_opts_set_write_concern (txn_opts, write_concern);
7632
7633             insert_opts = bson_new ();
7634             if (!mongoc_client_session_append (session, insert_opts, &error)) {
7635                MONGOC_ERROR ("Could not add session to opts: %s", error.message);
7636                goto done;
7637             }
7638
7639          retry_transaction:
7640             r = mongoc_client_session_start_transaction (session, txn_opts, &error);
7641             if (!r) {
7642                MONGOC_ERROR ("Failed to start transaction: %s", error.message);
7643                goto done;
7644             }
7645
7646             /* insert two documents - on error, retry the whole transaction */
7647             for (i = 0; i < 2; i++) {
7648                doc = BCON_NEW ("_id", BCON_INT32 (i));
7649                bson_destroy (&reply);
7650                r = mongoc_collection_insert_one (
7651                   collection, doc, insert_opts, &reply, &error);
7652
7653                bson_destroy (doc);
7654
7655                if (!r) {
7656                   MONGOC_ERROR ("Insert failed: %s", error.message);
7657                   mongoc_client_session_abort_transaction (session, NULL);
7658
7659                   /* a network error, primary failover, or other temporary error in a
7660                    * transaction includes {"errorLabels": ["TransientTransactionError"]},
7661                    * meaning that trying the entire transaction again may succeed
7662                    */
7663                   if (mongoc_error_has_label (&reply, "TransientTransactionError")) {
7664                      goto retry_transaction;
7665                   }
7666
7667                   goto done;
7668                }
7669
7670                reply_json = bson_as_json (&reply, NULL);
7671                printf ("%s\n", reply_json);
7672                bson_free (reply_json);
7673             }
7674
7675             /* in case of transient errors, retry for 5 seconds to commit transaction */
7676             start = bson_get_monotonic_time ();
7677             while (bson_get_monotonic_time () - start < 5 * 1000 * 1000) {
7678                bson_destroy (&reply);
7679                r = mongoc_client_session_commit_transaction (session, &reply, &error);
7680                if (r) {
7681                   /* success */
7682                   break;
7683                } else {
7684                   MONGOC_ERROR ("Warning: commit failed: %s", error.message);
7685                   if (mongoc_error_has_label (&reply, "TransientTransactionError")) {
7686                      goto retry_transaction;
7687                   } else if (mongoc_error_has_label (&reply,
7688                                                      "UnknownTransactionCommitResult")) {
7689                      /* try again to commit */
7690                      continue;
7691                   }
7692
7693                   /* unrecoverable error trying to commit */
7694                   break;
7695                }
7696             }
7697
7698             exit_code = EXIT_SUCCESS;
7699
7700          done:
7701             bson_destroy (&reply);
7702             bson_destroy (insert_opts);
7703             mongoc_write_concern_destroy (write_concern);
7704             mongoc_read_concern_destroy (read_concern);
7705             mongoc_transaction_opts_destroy (txn_opts);
7706             mongoc_transaction_opts_destroy (default_txn_opts);
7707             mongoc_client_session_destroy (session);
7708             mongoc_collection_destroy (collection);
7709             mongoc_database_destroy (database);
7710             mongoc_uri_destroy (uri);
7711             mongoc_client_destroy (client);
7712
7713             mongoc_cleanup ();
7714
7715             return exit_code;
7716          }
7717
7718
7719   mongoc_update_flags_t
7720       Flags for update operations
7721
7722   Synopsis
7723          typedef enum {
7724             MONGOC_UPDATE_NONE = 0,
7725             MONGOC_UPDATE_UPSERT = 1 << 0,
7726             MONGOC_UPDATE_MULTI_UPDATE = 1 << 1,
7727          } mongoc_update_flags_t;
7728
7729          #define MONGOC_UPDATE_NO_VALIDATE (1U << 31)
7730
7731   Description
7732       These  flags  correspond to the MongoDB wire protocol. They may be bit‐
7733       wise or'd together. The allow for modifying the way an update  is  per‐
7734       formed in the MongoDB server.
7735
7736   Flag Values
7737              ┌───────────────────────────┬────────────────────────────┐
7738              │MONGOC_UPDATE_NONE         │ No update flags set.       │
7739              ├───────────────────────────┼────────────────────────────┤
7740              │MONGOC_UPDATE_UPSERT       │ If  an  upsert  should  be │
7741              │                           │ performed.                 │
7742              ├───────────────────────────┼────────────────────────────┤
7743              │MONGOC_UPDATE_MULTI_UPDATE │ If  more  than  a   single │
7744              │                           │ matching  document  should │
7745              │                           │ be  updated.  By   default │
7746              │                           │ only the first document is │
7747              │                           │ updated.                   │
7748              ├───────────────────────────┼────────────────────────────┤
7749              │MONGOC_UPDATE_NO_VALIDATE  │ Do not perform client side │
7750              │                           │ BSON validations when per‐ │
7751              │                           │ forming an update. This is │
7752              │                           │ useful if you already know │
7753              │                           │ your  BSON  documents  are │
7754              │                           │ valid.                     │
7755              └───────────────────────────┴────────────────────────────┘
7756
7757   mongoc_uri_t
7758   Synopsis
7759          typedef struct _mongoc_uri_t mongoc_uri_t;
7760
7761   Description
7762       mongoc_uri_t  provides  an abstraction on top of the MongoDB connection
7763       URI format. It provides standardized parsing  as  well  as  convenience
7764       methods  for  extracting  useful  information  such as replica hosts or
7765       authorization information.
7766
7767       See Connection String URI Reference on the  MongoDB  website  for  more
7768       information.
7769
7770   Format
7771          mongodb[+srv]://                             <1>
7772             [username:password@]                      <2>
7773             host1                                     <3>
7774             [:port1]                                  <4>
7775             [,host2[:port2],...[,hostN[:portN]]]      <5>
7776             [/[database]                              <6>
7777             [?options]]                               <7>
7778
7779       1. "mongodb"  is  the  specifier  of  the  MongoDB  protocol. Use "mon‐
7780          godb+srv" with a single service name in place of "host1" to  specify
7781          the initial list of servers with an SRV record.
7782
7783       2. An optional username and password.
7784
7785       3. The  only  required  part of the uri.  This specifies either a host‐
7786          name, IPv4 address, IPv6 address enclosed in "[" and  "]",  or  UNIX
7787          domain socket.
7788
7789       4. An optional port number.  Defaults to :27017.
7790
7791       5. Extra  optional  hosts and ports.  You would specify multiple hosts,
7792          for example, for connections to replica sets.
7793
7794       6. The name of the database to authenticate if  the  connection  string
7795          includes  authentication credentials.  If /database is not specified
7796          and the connection string  includes  credentials,  defaults  to  the
7797          'admin' database.
7798
7799       7. Connection specific options.
7800
7801       NOTE:
7802          Option names are case-insensitive
7803
7804       The  MongoDB  C  Driver exposes constants for each supported connection
7805       option. These constants make it easier to discover connection  options,
7806       but their string values can be used as well.
7807
7808       For example, the following calls are equal.
7809
7810          uri = mongoc_uri_new ("mongodb://localhost/?" MONGOC_URI_APPNAME "=applicationName");
7811          uri = mongoc_uri_new ("mongodb://localhost/?appname=applicationName");
7812          uri = mongoc_uri_new ("mongodb://localhost/?appName=applicationName");
7813
7814   Replica Set Example
7815       To describe a connection to a replica set named 'test' with the follow‐
7816       ing mongod hosts:
7817
7818       · db1.example.com on port 27017
7819
7820       · db2.example.com on port 2500
7821
7822       You would use a connection string that resembles the following.
7823
7824          mongodb://db1.example.com,db2.example.com:2500/?replicaSet=test
7825
7826   SRV Example
7827       If  you  have  configured  an  SRV  record  with  a  name  like  "_mon‐
7828       godb._tcp.server.example.com"  whose  records are a list of one or more
7829       MongoDB server hostnames, use a connection string like this:
7830
7831          uri = mongoc_uri_new ("mongodb+srv://server.example.com/?replicaSet=rs&appName=applicationName");
7832
7833       The driver prefixes the service name with "_mongodb._tcp.",  then  per‐
7834       forms  a DNS SRV query to resolve the service name to one or more host‐
7835       names. If this query succeeds, the driver performs a DNS TXT  query  on
7836       the  service  name  (without the "_mongodb._tcp" prefix) for additional
7837       URI options configured as TXT records.
7838
7839       On Unix, the MongoDB C Driver relies on libresolv to look  up  SRV  and
7840       TXT  records.  If  libresolv is unavailable, then using a "mongodb+srv"
7841       URI will cause an error. If your libresolv lacks res_nsearch  then  the
7842       driver will fall back to res_search, which is not thread-safe.
7843
7844   IPv4 and IPv6
7845       If  connecting  to  a hostname that has both IPv4 and IPv6 DNS records,
7846       the behavior follows RFC-6555. A connection  to  the  IPv6  address  is
7847       attempted  first.  If IPv6 fails, then a connection is attempted to the
7848       IPv4 address. If the connection  attempt  to  IPv6  does  not  complete
7849       within  250ms,  then IPv4 is tried in parallel. Whichever succeeds con‐
7850       nection first cancels the other. The successful DNS  result  is  cached
7851       for 10 minutes.
7852
7853       As  a  consequence,  attempts  to connect to a mongod only listening on
7854       IPv4 may be delayed if there are both A  (IPv4)  and  AAAA  (IPv6)  DNS
7855       records associated with the host.
7856
7857       To  avoid  a delay, configure hostnames to match the MongoDB configura‐
7858       tion. That is, only create an A record if the mongod is only  listening
7859       on IPv4.
7860
7861   Connection Options
7862      ──────────────────────────────────────────────────────────────────────────
7863       Constant              Key                Description
7864      ──────────────────────────────────────────────────────────────────────────
7865       MONGOC_URI_RETRY‐     retrywrites        If "true"  and  the
7866       WRITES                                   server is a MongoDB
7867                                                3.6+ replica set or
7868                                                sharded    cluster,
7869                                                the  driver  safely
7870                                                retries   a   write
7871                                                that failed due  to
7872                                                a  network error or
7873                                                replica         set
7874                                                failover.      Only
7875                                                inserts, updates of
7876                                                single   documents,
7877                                                or deletes of  sin‐
7878                                                gle  documents  are
7879                                                retried.
7880      ──────────────────────────────────────────────────────────────────────────
7881       MONGOC_URI_APPNAME    appname            The client applica‐
7882                                                tion   name.   This
7883                                                value  is  used  by
7884                                                MongoDB   when   it
7885                                                logs     connection
7886                                                information     and
7887                                                profile    informa‐
7888                                                tion,  such as slow
7889                                                queries.
7890      ──────────────────────────────────────────────────────────────────────────
7891       MONGOC_URI_SSL        ssl                {true|false}, indi‐
7892                                                cating  if SSL must
7893                                                be used. (See  also
7894                                                mon‐
7895                                                goc_client_set_ssl_opts
7896                                                and            mon‐
7897                                                goc_client_pool_set_ssl_opts.)
7898      ──────────────────────────────────────────────────────────────────────────
7899       MONGOC_URI_COMPRES‐   compressors        Comma separated list  of  com‐
7900       SORS                                     pressors,  if  any,  to use to
7901                                                compress  the  wire   protocol
7902                                                messages.  Snappy are Zlib are
7903                                                optional build time  dependen‐
7904                                                cies,  and enable the "snappy"
7905                                                and  "zlib"   values   respec‐
7906                                                tively.  Defaults to empty (no
7907                                                compressors).
7908      ──────────────────────────────────────────────────────────────────────────
7909       MONGOC_URI_CONNECT‐   connecttimeoutms   This  setting  applies  to new
7910       TIMEOUTMS                                server connections. It is also
7911                                                used as the socket timeout for
7912                                                server discovery and  monitor‐
7913                                                ing operations. The default is
7914                                                10,000 ms (10 seconds).
7915      ──────────────────────────────────────────────────────────────────────────
7916       MONGOC_URI_SOCKET‐    sockettimeoutms    The  time  in  milliseconds to
7917       TIMEOUTMS                                attempt to send or receive  on
7918                                                a  socket  before  the attempt
7919                                                times  out.  The  default   is
7920                                                300,000 (5 minutes).
7921      ──────────────────────────────────────────────────────────────────────────
7922       MONGOC_URI_REPLI‐     replicaset         The name of  the  Replica  Set
7923       CASET                                    that the driver should connect
7924                                                to.
7925      ──────────────────────────────────────────────────────────────────────────
7926       MONGOC_URI_ZLIBCOM‐   zlibcompression‐   When  the  MONGOC_URI_COMPRES‐
7927       PRESSIONLEVEL         level              SORS   includes   "zlib"  this
7928                                                options  configures  the  zlib
7929                                                compression  level,  when  the
7930                                                zlib  compressor  is  used  to
7931                                                compress client data.
7932      ┌────────────────────┬──────────────────┬────────────────────────────────┐
7933      │                    │                  │                                │
7934      │Setting any of the *│timeoutMS options a│bove to 0 will be interpreted as │
7935      │"use the default val│ue".               │                                │
7936      │                    │                  │                                │
7937   Aut│hentication Options  │                  │                                │
7938      │ ┌──────────────────┼─┬────────────────┼───┬─────────────────────────┐  │
7939      │ │Constant          │ │ Key            │   │ Description             │  │
7940      │ └──────────────────┼─┴────────────────┼───┴─────────────────────────┘  │
7941      │                    │                  │                                │
7942
7943        │MONGOC_URI_AUTH‐    │ authmechanism      │ Specifies the mech‐     │
7944        │MECHANISM           │                    │ anism to  use  when     │
7945        │                    │                    │ authenticating   as     │
7946        │                    │                    │ the provided  user.     │
7947        │                    │                    │ See  Authentication     │
7948        │                    │                    │ for supported  val‐     │
7949        │                    │                    │ ues.                    │
7950        ├────────────────────┼────────────────────┼─────────────────────────┤
7951        │MONGOC_URI_AUTH‐    │ authmechanismprop‐ │ Certain authentica‐     │
7952        │MECHANISMPROPERTIES │ erties             │ tion     mechanisms     │
7953        │                    │                    │ have     additional     │
7954        │                    │                    │ options that can be     │
7955        │                    │                    │ configured.   These     │
7956        │                    │                    │ options  should  be     │
7957        │                    │                    │ provided  as  comma     │
7958        │                    │                    │ separated               │
7959        │                    │                    │ option_key:option_value │
7960        │                    │                    │ pair  and  provided     │
7961        │                    │                    │ as   authMechanism‐     │
7962        │                    │                    │ Properties.             │
7963        ├────────────────────┼────────────────────┼─────────────────────────┤
7964        │MONGOC_URI_AUTH‐    │ authsource         │ The  authSource defines │
7965        │SOURCE              │                    │ the    database    that │
7966        │                    │                    │ should   be   used   to │
7967        │                    │                    │ authenticate to. It  is │
7968        │                    │                    │ unnecessary  to provide │
7969        │                    │                    │ this option  the  data‐ │
7970        │                    │                    │ base  name  is the same │
7971        │                    │                    │ as the database used in │
7972        │                    │                    │ the URI.                │
7973        └────────────────────┴────────────────────┴─────────────────────────┘
7974
7975   Mechanism Properties
7976           ┌────────────────────┬───────────────────┬─────────────────────┐
7977           │Constant            │ Key               │ Description         │
7978           ├────────────────────┼───────────────────┼─────────────────────┤
7979           │MONGOC_URI_CANONI‐  │ canonicalizehost‐ │ Use  the  canonical │
7980           │CALIZEHOSTNAME      │ name              │ hostname   of   the │
7981           │                    │                   │ service,     rather │
7982           │                    │                   │ than its configured │
7983           │                    │                   │ alias, when authen‐ │
7984           │                    │                   │ ticating       with │
7985           │                    │                   │ Cyrus-SASL     Ker‐ │
7986           │                    │                   │ beros.              │
7987           ├────────────────────┼───────────────────┼─────────────────────┤
7988           │MONGOC_URI_GSSAPIS‐ │ gssapiservicename │ Use     alternative │
7989           │ERVICENAME          │                   │ service  name.  The │
7990           │                    │                   │ default is mongodb. │
7991           └────────────────────┴───────────────────┴─────────────────────┘
7992
7993   SSL Options
7994         ┌──────────────────────┬─────────────────────┬─────────────────────┐
7995         │Constant              │ Key                 │ Description         │
7996         ├──────────────────────┼─────────────────────┼─────────────────────┤
7997         │MON‐                  │ sslclientcertifi‐   │ Path to PEM format‐ │
7998         │GOC_URI_SSLCLIENTCER‐ │ catekeyfile         │ ted   Private  Key, │
7999         │TIFICATEKEYFILE       │                     │ with   its   Public │
8000         │                      │                     │ Certificate    con‐ │
8001         │                      │                     │ catenated  at   the │
8002         │                      │                     │ end.                │
8003         ├──────────────────────┼─────────────────────┼─────────────────────┤
8004         │MON‐                  │ sslclientcertifi‐   │ The  password,   if │
8005         │GOC_URI_SSLCLIENTCER‐ │ catekeypassword     │ any,   to   use  to │
8006         │TIFICATEKEYPASSWORD   │                     │ unlock    encrypted │
8007         │                      │                     │ Private Key.        │
8008         ├──────────────────────┼─────────────────────┼─────────────────────┤
8009         │MONGOC_URI_SSLCER‐    │ sslcertificateau‐   │ One,  or  a  bundle │
8010         │TIFICATEAUTHORITYFILE │ thorityfile         │ of,     Certificate │
8011         │                      │                     │ Authorities    whom │
8012         │                      │                     │ should  be  consid‐ │
8013         │                      │                     │ ered to be trusted. │
8014         ├──────────────────────┼─────────────────────┼─────────────────────┤
8015         │MONGOC_URI_SSLALLOW‐  │ sslallowinvalidcer‐ │ Accept  and  ignore │
8016         │INVALIDCERTIFICATES   │ tificates           │ certificate verifi‐ │
8017         │                      │                     │ cation errors (e.g. │
8018         │                      │                     │ untrusted   issuer, │
8019         │                      │                     │ expired, etc etc)   │
8020         └──────────────────────┴─────────────────────┴─────────────────────┘
8021
8022         │MONGOC_URI_SSLALLOW‐  │ sslallowinvalid‐    │ Ignore     hostname │
8023         │INVALIDHOSTNAMES      │ hostnames           │ verification of the │
8024         │                      │                     │ certificate   (e.g. │
8025         │                      │                     │ Man In The  Middle, │
8026         │                      │                     │ using   valid  cer‐ │
8027         │                      │                     │ tificate,       but │
8028         │                      │                     │ issued  for another │
8029         │                      │                     │ hostname)           │
8030         └──────────────────────┴─────────────────────┴─────────────────────┘
8031
8032       See mongoc_ssl_opt_t for details about these options and about building
8033       libmongoc with SSL support.
8034
8035   Server Discovery, Monitoring, and Selection Options
8036       Clients in a mongoc_client_pool_t share a topology scanner that runs on
8037       a  background  thread.  The  thread  wakes  every  heartbeatFrequencyMS
8038       (default  10 seconds) to scan all MongoDB servers in parallel. Whenever
8039       an application operation requires a server that is not known--for exam‐
8040       ple,  if  there  is  no  known primary and your application attempts an
8041       insert--the thread rescans all servers every half-second. In this situ‐
8042       ation  the  pooled client waits up to serverSelectionTimeoutMS (default
8043       30 seconds) for the thread to find a server suitable for the operation,
8044       then returns an error with domain MONGOC_ERROR_SERVER_SELECTION.
8045
8046       Technically, the total time an operation may wait while a pooled client
8047       scans the topology is controlled both by  serverSelectionTimeoutMS  and
8048       connectTimeoutMS.  The longest wait occurs if the last scan begins just
8049       at the end of the selection timeout, and a slow or down server requires
8050       the full connection timeout before the client gives up.
8051
8052       A  non-pooled client is single-threaded. Every heartbeatFrequencyMS, it
8053       blocks the next application operation while it does  a  parallel  scan.
8054       This  scan takes as long as needed to check the slowest server: roughly
8055       connectTimeoutMS. Therefore the default heartbeatFrequencyMS  for  sin‐
8056       gle-threaded clients is greater than for pooled clients: 60 seconds.
8057
8058       By default, single-threaded (non-pooled) clients scan only once when an
8059       operation requires a server that is not known. If you attempt an insert
8060       and  there is no known primary, the client checks all servers once try‐
8061       ing to find it, then succeeds or returns  an  error  with  domain  MON‐
8062       GOC_ERROR_SERVER_SELECTION.  But  if  you set serverSelectionTryOnce to
8063       "false", the single-threaded client loops, checking all  servers  every
8064       half-second, until serverSelectionTimeoutMS.
8065
8066       The  total  time  an operation may wait for a single-threaded client to
8067       scan the topology is determined by  connectTimeoutMS  in  the  try-once
8068       case,  or serverSelectionTimeoutMS and connectTimeoutMS if serverSelec‐
8069       tionTryOnce is set "false".
8070
8071          ┌────────────────────┬─────────────────────┬─────────────────────┐
8072          │Constant            │ Key                 │ Description         │
8073          ├────────────────────┼─────────────────────┼─────────────────────┤
8074          │MONGOC_URI_HEART‐   │ heartbeatfrequen‐   │ The        interval │
8075          │BEATFREQUENCYMS     │ cyms                │ between server mon‐ │
8076          │                    │                     │ itoring     checks. │
8077          │                    │                     │ Defaults         to │
8078          │                    │                     │ 10,000ms  (10  sec‐ │
8079          │                    │                     │ onds)   in   pooled │
8080          │                    │                     │ (multi-threaded)    │
8081          │                    │                     │ mode,  60,000ms (60 │
8082          │                    │                     │ seconds)         in │
8083          │                    │                     │ non-pooled     mode │
8084          │                    │                     │ (single-threaded).  │
8085          ├────────────────────┼─────────────────────┼─────────────────────┤
8086          │MONGOC_URI_SERVERS‐ │ serverselection‐    │ A timeout  in  mil‐ │
8087          │ELECTIONTIMEOUTMS   │ timeoutms           │ liseconds  to block │
8088          │                    │                     │ for  server  selec‐ │
8089          │                    │                     │ tion  before throw‐ │
8090          │                    │                     │ ing  an  exception. │
8091          │                    │                     │ The    default   is │
8092          │                    │                     │ 30,0000ms (30  sec‐ │
8093          │                    │                     │ onds).              │
8094          └────────────────────┴─────────────────────┴─────────────────────┘
8095
8096
8097
8098
8099
8100
8101          │MONGOC_URI_SERVERS‐ │ serverselectiontry‐ │ If    "true",   the │
8102          │ELECTIONTRYONCE     │ once                │ driver  scans   the │
8103          │                    │                     │ topology    exactly │
8104          │                    │                     │ once  after  server │
8105          │                    │                     │ selection    fails, │
8106          │                    │                     │ then either selects │
8107          │                    │                     │ a server or returns │
8108          │                    │                     │ an error. If it  is │
8109          │                    │                     │ false,   then   the │
8110          │                    │                     │ driver   repeatedly │
8111          │                    │                     │ searches    for   a │
8112          │                    │                     │ suitable server for │
8113          │                    │                     │ up  to serverSelec‐ 
8114          │                    │                     │ tionTimeoutMS  mil‐ │
8115          │                    │                     │ liseconds  (pausing │
8116          │                    │                     │ a    half    second │
8117          │                    │                     │ between  attempts). │
8118          │                    │                     │ The   default   for │
8119          │                    │                     │ serverSelectionTry‐ 
8120          │                    │                     │ Once is "false" for │
8121          │                    │                     │ pooled     clients, │
8122          │                    │                     │ otherwise   "true". │
8123          │                    │                     │ Pooled      clients │
8124          │                    │                     │ ignore serverSelec‐ │
8125          │                    │                     │ tionTryOnce;   they │
8126          │                    │                     │ signal  the  thread │
8127          │                    │                     │ to    rescan    the │
8128          │                    │                     │ topology      every │
8129          │                    │                     │ half-second   until │
8130          │                    │                     │ serverSelection‐    │
8131          │                    │                     │ TimeoutMS expires.  │
8132          ├────────────────────┼─────────────────────┼─────────────────────┤
8133          │MONGOC_URI_SOCK‐    │ socketcheckinter‐   │ Only   applies   to │
8134          │ETCHECKINTERVALMS   │ valms               │ single     threaded │
8135          │                    │                     │ clients.    If    a │
8136          │                    │                     │ socket has not been │
8137          │                    │                     │ used   within  this │
8138          │                    │                     │ time,  its  connec‐ │
8139          │                    │                     │ tion   is   checked │
8140          │                    │                     │ with    a     quick │
8141          │                    │                     │ "isMaster"     call │
8142          │                    │                     │ before it  is  used │
8143          │                    │                     │ again.  Defaults to │
8144          │                    │                     │ 5,000ms   (5   sec‐ │
8145          │                    │                     │ onds).              │
8146          └────────────────────┴─────────────────────┴─────────────────────┘
8147
8148       Setting any of the *TimeoutMS options above to 0 will be interpreted as
8149       "use the default value".
8150
8151   Connection Pool Options
8152       These options govern the behavior of a mongoc_client_pool_t.  They  are
8153       ignored by a non-pooled mongoc_client_t.
8154
8155          ┌────────────────────┬────────────────────┬─────────────────────┐
8156          │Constant            │ Key                │ Description         │
8157          ├────────────────────┼────────────────────┼─────────────────────┤
8158          │MONGOC_URI_MAXPOOL‐ │ maxpoolsize        │ The maximum  number │
8159          │SIZE                │                    │ of  clients created │
8160          │                    │                    │ by      a      mon‐ 
8161          │                    │                    │ goc_client_pool_t   
8162          │                    │                    │ total (both in  the │
8163          │                    │                    │ pool   and  checked │
8164          │                    │                    │ out).  The  default │
8165          │                    │                    │ value  is 100. Once │
8166          │                    │                    │ it is reached, mon‐ 
8167          │                    │                    │ goc_client_pool_pop 
8168          │                    │                    │ blocks        until │
8169          │                    │                    │ another      thread │
8170          │                    │                    │ pushes a client.    │
8171          └────────────────────┴────────────────────┴─────────────────────┘
8172
8173
8174
8175
8176
8177
8178
8179
8180          │MONGOC_URI_MINPOOL‐ │ minpoolsize        │ Deprecated.    This │
8181          │SIZE                │                    │ option's   behavior │
8182          │                    │                    │ does  not match its │
8183          │                    │                    │ name,    and    its │
8184          │                    │                    │ actual     behavior │
8185          │                    │                    │ will  likely   hurt │
8186          │                    │                    │ performance.        │
8187          ├────────────────────┼────────────────────┼─────────────────────┤
8188          │MONGOC_URI_MAXIDLE‐ │ maxidletimems      │ Not implemented.    │
8189          │TIMEMS              │                    │                     │
8190          ├────────────────────┼────────────────────┼─────────────────────┤
8191          │MONGOC_URI_WAIT‐    │ waitqueuemultiple  │ Not implemented.    │
8192          │QUEUEMULTIPLE       │                    │                     │
8193          ├────────────────────┼────────────────────┼─────────────────────┤
8194          │MONGOC_URI_WAIT‐    │ waitqueuetimeoutms │ Not implemented.    │
8195          │QUEUETIMEOUTMS      │                    │                     │
8196          └────────────────────┴────────────────────┴─────────────────────┘
8197
8198   Write Concern Options
8199               ┌───────────────────┬────────────┬─────────────────────┐
8200               │Constant           │ Key        │ Description         │
8201               └───────────────────┴────────────┴─────────────────────┘
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259                MONGOC_URI_W         w            Determines      the
8260                                                  write       concern
8261                                                  (guarantee).  Valid
8262                                                  values:
8263
8264                                                         · 0   =  The
8265                                                           driver
8266                                                           will   not
8267                                                           acknowl‐
8268                                                           edge write
8269                                                           operations
8270                                                           but   will
8271                                                           pass    or
8272                                                           handle any
8273                                                           network
8274                                                           and socket
8275                                                           errors
8276                                                           that    it
8277                                                           receives
8278                                                           to     the
8279                                                           client. If
8280                                                           you   dis‐
8281                                                           able write
8282                                                           concern
8283                                                           but enable
8284                                                           the   get‐
8285                                                           LastError
8286                                                           command’s
8287                                                           w  option,
8288                                                           w    over‐
8289                                                           rides  the
8290                                                           w option.
8291
8292                                                         · 1  =  Pro‐
8293                                                           vides
8294                                                           basic
8295                                                           acknowl‐
8296                                                           edgement
8297                                                           of   write
8298                                                           opera‐
8299                                                           tions.  By
8300                                                           specifying
8301                                                           1,     you
8302                                                           require
8303                                                           that     a
8304                                                           standalone
8305                                                           mongod
8306                                                           instance,
8307                                                           or     the
8308                                                           primary
8309                                                           for
8310                                                           replica
8311                                                           sets,
8312                                                           acknowl‐
8313                                                           edge   all
8314                                                           write
8315                                                           opera‐
8316                                                           tions. For
8317                                                           drivers
8318                                                           released
8319                                                           after  the
8320                                                           default
8321                                                           write con‐
8322                                                           cern
8323                                                           change,
8324                                                           this    is
8325                                                           the
8326                                                           default
8327                                                           write con‐
8328                                                           cern  set‐
8329                                                           ting.
8330
8331                                                         · majority =
8332                                                           For
8333                                                           replica
8334                                                           sets,   if
8335                                                           you  spec‐
8336                                                           ify    the
8337                                                           special
8338                                                           majority
8339                                                           value to w
8340                                                           option,
8341                                                           write
8342                                                           operations
8343                                                           will  only
8344                                                           return
8345                                                           success‐
8346                                                           fully
8347                                                           after    a
8348                                                           majority
8349                                                           of     the
8350                                                           configured
8351                                                           replica
8352                                                           set   mem‐
8353                                                           bers  have
8354                                                           acknowl‐
8355                                                           edged  the
8356                                                           write
8357                                                           operation.
8358
8359                                                         · n  =   For
8360                                                           replica
8361                                                           sets,   if
8362                                                           you  spec‐
8363                                                           ify a num‐
8364                                                           ber      n
8365                                                           greater
8366                                                           than    1,
8367                                                           operations
8368                                                           with  this
8369                                                           write con‐
8370                                                           cern
8371                                                           return
8372                                                           only after
8373                                                           n  members
8374                                                           of the set
8375                                                           have
8376                                                           acknowl‐
8377                                                           edged  the
8378                                                           write.  If
8379                                                           you set  n
8380                                                           to  a num‐
8381                                                           ber   that
8382                                                           is greater
8383                                                           than   the
8384                                                           number  of
8385                                                           available
8386                                                           set   mem‐
8387                                                           bers    or
8388                                                           members
8389                                                           that  hold
8390                                                           data, Mon‐
8391                                                           goDB  will
8392                                                           wait,
8393                                                           poten‐
8394                                                           tially
8395                                                           indefi‐
8396                                                           nitely,
8397                                                           for  these
8398                                                           members to
8399                                                           become
8400                                                           available.
8401
8402                                                         · tags = For
8403                                                           replica
8404                                                           sets,  you
8405                                                           can  spec‐
8406                                                           ify  a tag
8407                                                           set     to
8408                                                           require
8409                                                           that   all
8410                                                           members of
8411                                                           the    set
8412                                                           that  have
8413                                                           these tags
8414                                                           configured
8415                                                           return
8416                                                           confirma‐
8417                                                           tion    of
8418                                                           the  write
8419                                                           operation.
8420               ├───────────────────┼────────────┼─────────────────────┤
8421               │MONGOC_URI_WTIME‐  │ wtimeoutms │ The  time  in  mil‐ │
8422               │OUTMS              │            │ liseconds  to  wait │
8423               │                   │            │ for  replication to │
8424               │                   │            │ succeed, as  speci‐ │
8425               │                   │            │ fied   in   the   w │
8426               │                   │            │ option, before tim‐ │
8427               │                   │            │ ing    out.    When │
8428               │                   │            │ wtimeoutMS  is   0, │
8429               │                   │            │ write    operations │
8430               │                   │            │ will   never   time │
8431               │                   │            │ out.                │
8432               ├───────────────────┼────────────┼─────────────────────┤
8433               │MONGOC_URI_JOURNAL │ journal    │ Controls    whether │
8434               │                   │            │ write    operations │
8435               │                   │            │ will wait until the │
8436               │                   │            │ mongod acknowledges │
8437               │                   │            │ the   write  opera‐ │
8438               │                   │            │ tions  and  commits │
8439               │                   │            │ the  data to the on │
8440               │                   │            │ disk journal.       │
8441               │                   │            │                     │
8442               │                   │            │        · true     = │
8443               │                   │            │          Enables    │
8444               │                   │            │          journal    │
8445               │                   │            │          commit     │
8446               │                   │            │          acknowl‐   │
8447               │                   │            │          edgement   │
8448               │                   │            │          write con‐ │
8449               │                   │            │          cern.      │
8450               │                   │            │          Equivalent │
8451               │                   │            │          to  speci‐ │
8452               │                   │            │          fying  the │
8453               │                   │            │          getLastEr‐ │
8454               │                   │            │          ror   com‐ │
8455               │                   │            │          mand  with │
8456               │                   │            │          the      j │
8457               │                   │            │          option     │
8458               │                   │            │          enabled.   │
8459               │                   │            │                     │
8460               │                   │            │        · false    = │
8461               │                   │            │          Does   not │
8462               │                   │            │          require    │
8463               │                   │            │          that  mon‐ │
8464               │                   │            │          god commit │
8465               │                   │            │          write      │
8466               │                   │            │          operations │
8467               │                   │            │          to     the │
8468               │                   │            │          journal    │
8469               │                   │            │          before     │
8470               │                   │            │          acknowl‐   │
8471               │                   │            │          edging the │
8472               │                   │            │          write      │
8473               │                   │            │          operation. │
8474               │                   │            │          This    is │
8475               │                   │            │          the        │
8476               │                   │            │          default    │
8477               │                   │            │          option for │
8478               │                   │            │          the  jour‐ │
8479               │                   │            │          nal param‐ │
8480               │                   │            │          eter.      │
8481               └───────────────────┴────────────┴─────────────────────┘
8482
8483   Read Concern Options
8484           ┌────────────────────┬──────────────────┬─────────────────────┐
8485           │Constant            │ Key              │ Description         │
8486           ├────────────────────┼──────────────────┼─────────────────────┤
8487           │MONGOC_URI_READCON‐ │ readconcernlevel │ The level of isola‐ │
8488           │CERNLEVEL           │                  │ tion for read oper‐ │
8489           │                    │                  │ ations.    If   the │
8490           │                    │                  │ level    is    left │
8491           │                    │                  │ unspecified,    the │
8492           │                    │                  │ server default will │
8493           │                    │                  │ be     used.    See │
8494           │                    │                  │ readConcern in  the
8495           │                    │                  │ MongoDB  Manual for │
8496           │                    │                  │ details.            │
8497           └────────────────────┴──────────────────┴─────────────────────┘
8498
8499   Read Preference Options
8500       When connected to a replica set, the driver  chooses  which  member  to
8501       query using the read preference:
8502
8503       1. Choose members whose type matches "readPreference".
8504
8505       2. From  these,  if  there are any tags sets configured, choose members
8506          matching the first tag set. If there are none, fall back to the next
8507          tag set and so on, until some members are chosen or the tag sets are
8508          exhausted.
8509
8510       3. From the chosen  servers,  distribute  queries  randomly  among  the
8511          server  with  the fastest round-trip times. These include the server
8512          with the fastest time and any whose round-trip time is no more  than
8513          "localThresholdMS" slower.
8514
8515       ┌─────────────────────┬─────────────────────┬──────────────────────────┐
8516       │Constant             │ Key                 │ Description              │
8517       ├─────────────────────┼─────────────────────┼──────────────────────────┤
8518       │MONGOC_URI_READ‐     │ readpreference      │ Specifies       the      │
8519       │PREFERENCE           │                     │ replica   set  read      │
8520       │                     │                     │ preference for this      │
8521       │                     │                     │ connection.    This      │
8522       │                     │                     │ setting   overrides      │
8523       │                     │                     │ any  slaveOk value.      │
8524       │                     │                     │ The read preference      │
8525       │                     │                     │ values are the fol‐      │
8526       │                     │                     │ lowing:                  │
8527       │                     │                     │                          │
8528       │                     │                     │        · primary         │
8529       │                     │                     │          (default)       │
8530       │                     │                     │                          │
8531       │                     │                     │        · prima‐          │
8532       │                     │                     │          ryPre‐          │
8533       │                     │                     │          ferred          │
8534       │                     │                     │                          │
8535       │                     │                     │        · secondary       │
8536       │                     │                     │                          │
8537       │                     │                     │        · sec‐            │
8538       │                     │                     │          ondaryPre‐      │
8539       │                     │                     │          ferred          │
8540       │                     │                     │                          │
8541       │                     │                     │        · nearest         │
8542       ├─────────────────────┼─────────────────────┼──────────────────────────┤
8543       │MONGOC_URI_READ‐     │ readpreferencetags  │ A representation of      │
8544       │PREFERENCETAGS       │                     │ a tag set. See also      │
8545       │                     │                     │ mon‐                     │
8546       │                     │                     │ goc-read-prefs-tag-sets. │
8547       ├─────────────────────┼─────────────────────┼──────────────────────────┤
8548       │MON‐                 │ localthresholdms    │ How  far  to  distribute │
8549       │GOC_URI_LOCALTHRESH‐ │                     │ queries,    beyond   the │
8550       │OLDMS                │                     │ server with the  fastest │
8551       │                     │                     │ round-trip    time.   By │
8552       │                     │                     │ default,  only   servers │
8553       │                     │                     │ within   15ms   of   the │
8554       │                     │                     │ fastest round-trip  time │
8555       │                     │                     │ receive queries.         │
8556       ├─────────────────────┼─────────────────────┼──────────────────────────┤
8557       │MONGOC_URI_MAXSTALE‐ │ maxstalenessseconds │ The maximum  replication │
8558       │NESSSECONDS          │                     │ lag, in wall clock time, │
8559       │                     │                     │ that  a  secondary   can │
8560       │                     │                     │ suffer and still be eli‐ │
8561       │                     │                     │ gible.   The    smallest │
8562       │                     │                     │ allowed     value    for │
8563       │                     │                     │ maxStalenessSeconds   is │
8564       │                     │                     │ 90 seconds.              │
8565       └─────────────────────┴─────────────────────┴──────────────────────────┘
8566
8567       NOTE:
8568          When  connecting  to  more than one mongos, libmongoc's localThresh‐
8569          oldMS applies only to the selection of mongos servers. The threshold
8570          for  selecting  among replica set members in shards is controlled by
8571          the mongos's localThreshold command line option.
8572
8573   Legacy Options
8574       For historical reasons,  the  following  options  are  available.  They
8575       should however not be used.
8576
8577
8578                ┌───────────────────┬─────────┬─────────────────────┐
8579                │Constant           │ Key     │ Description         │
8580                ├───────────────────┼─────────┼─────────────────────┤
8581                │MONGOC_URI_SAFE    │ safe    │ {true|false}   Same │
8582                │                   │         │ as w={1|0}          │
8583                ├───────────────────┼─────────┼─────────────────────┤
8584                │MONGOC_URI_SLAVEOK │ slaveok │ When set,  same  as │
8585                │                   │         │ readPreference=sec‐ │
8586                │                   │         │ ondaryPreferred     │
8587                └───────────────────┴─────────┴─────────────────────┘
8588
8589   Version Checks
8590       Conditional compilation based on mongoc version
8591
8592   Description
8593       The following preprocessor macros can be used to perform various checks
8594       based  on  the  version of the library you are compiling against.  This
8595       may be useful if you only want to enable a feature on a certain version
8596       of the library.
8597
8598          #include <mongoc/mongoc.h>
8599
8600          #define MONGOC_MAJOR_VERSION (1)
8601          #define MONGOC_MINOR_VERSION (13)
8602          #define MONGOC_MICRO_VERSION (1)
8603          #define MONGOC_VERSION_S     "1.13.1"
8604          #define MONGOC_VERSION_HEX   ((1 << 24) | (0 << 16) | (0 << 8) | 0)
8605          #define MONGOC_CHECK_VERSION(major, minor, micro)
8606
8607       Only compile a block on MongoDB C Driver 1.1.0 and newer.
8608
8609          #if MONGOC_CHECK_VERSION(1, 1, 0)
8610          static void
8611          do_something (void)
8612          {
8613          }
8614          #endif
8615
8616   mongoc_write_concern_t
8617       Write Concern abstraction
8618
8619   Synopsis
8620       mongoc_write_concern_t  tells  the driver what level of acknowledgement
8621       to await from the server. The default,  MONGOC_WRITE_CONCERN_W_DEFAULT,
8622       is right for the great majority of applications.
8623
8624       You  can  specify  a  write  concern  on  connection  objects, database
8625       objects, collection objects, or  per-operation.  Data-modifying  opera‐
8626       tions  typically  use  the write concern of the object they operate on,
8627       and check the server response for a write concern error or  write  con‐
8628       cern  timeout.  For example, mongoc_collection_drop_index uses the col‐
8629       lection's write concern, and a write concern error or  timeout  in  the
8630       response is considered a failure.
8631
8632       Exceptions to this principle are the generic command functions:
8633
8634       · mongoc_client_command
8635
8636       · mongoc_client_command_simple
8637
8638       · mongoc_database_command
8639
8640       · mongoc_database_command_simple
8641
8642       · mongoc_collection_command
8643
8644       · mongoc_collection_command_simple
8645
8646       These generic command functions do not automatically apply a write con‐
8647       cern, and they do not check the server response  for  a  write  concern
8648       error or write concern timeout.
8649
8650       See Write Concern on the MongoDB website for more information.
8651
8652   Write Concern Levels
8653       Set the write concern level with mongoc_write_concern_set_w.
8654
8655
8656
8657              ┌───────────────────────────┬────────────────────────────┐
8658              │MONGOC_WRITE_CON‐          │ By default,  writes  block │
8659              │CERN_W_DEFAULT (1)         │ awaiting   acknowledgement │
8660              │                           │ from MongoDB. Acknowledged │
8661              │                           │ write    concern    allows │
8662              │                           │ clients to catch  network, │
8663              │                           │ duplicate  key,  and other │
8664              │                           │ errors.                    │
8665              ├───────────────────────────┼────────────────────────────┤
8666              │MONGOC_WRITE_CON‐          │ With  this  write concern, │
8667              │CERN_W_UNACKNOWLEDGED (0)  │ MongoDB does not  acknowl‐ │
8668              │                           │ edge  the receipt of write │
8669              │                           │ operation.  Unacknowledged │
8670              │                           │ is   similar   to   errors │
8671              │                           │ ignored;  however,  mongoc │
8672              │                           │ attempts  to  receive  and │
8673              │                           │ handle network errors when │
8674              │                           │ possible.                  │
8675              ├───────────────────────────┼────────────────────────────┤
8676              │MONGOC_WRITE_CON‐          │ Block until  a  write  has │
8677              │CERN_W_MAJORITY (majority) │ been   propagated   to   a │
8678              │                           │ majority of the  nodes  in │
8679              │                           │ the replica set.           │
8680              ├───────────────────────────┼────────────────────────────┤
8681              │n                          │ Block  until  a  write has │
8682              │                           │ been  propagated   to   at │
8683              │                           │ least   n   nodes  in  the │
8684              │                           │ replica set.               │
8685              └───────────────────────────┴────────────────────────────┘
8686
8687   Deprecations
8688       The write concern MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED (value -1) is a
8689       deprecated synonym for MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED (value 0),
8690       and will be removed in the next major release.
8691
8692       mongoc_write_concern_set_fsync is deprecated.
8693
8694   Application Performance Monitoring (APM)
8695       The MongoDB C Driver allows you to monitor all the  MongoDB  operations
8696       the  driver  executes.  This  event-notification system conforms to two
8697       MongoDB driver specs:
8698
8699       · Command Monitoring: events related to all application operations.
8700
8701       · SDAM Monitoring: events related to the driver's Server Discovery  And
8702         Monitoring logic.
8703
8704       To  receive  notifications,  create  a mongoc_apm_callbacks_t with mon‐
8705       goc_apm_callbacks_new, set callbacks  on  it,  then  pass  it  to  mon‐
8706       goc_client_set_apm_callbacks or mongoc_client_pool_set_apm_callbacks.
8707
8708   Command-Monitoring Example
8709       example-command-monitoring.c.INDENT 0.0
8710
8711          /* gcc example-command-monitoring.c -o example-command-monitoring \
8712           *     $(pkg-config --cflags --libs libmongoc-1.0) */
8713
8714          /* ./example-command-monitoring [CONNECTION_STRING] */
8715
8716          #include <mongoc/mongoc.h>
8717          #include <stdio.h>
8718
8719
8720          typedef struct {
8721             int started;
8722             int succeeded;
8723             int failed;
8724          } stats_t;
8725
8726
8727          void
8728          command_started (const mongoc_apm_command_started_t *event)
8729          {
8730             char *s;
8731
8732             s = bson_as_relaxed_extended_json (
8733                mongoc_apm_command_started_get_command (event), NULL);
8734             printf ("Command %s started on %s:\n%s\n\n",
8735                     mongoc_apm_command_started_get_command_name (event),
8736                     mongoc_apm_command_started_get_host (event)->host,
8737                     s);
8738
8739             ((stats_t *) mongoc_apm_command_started_get_context (event))->started++;
8740
8741             bson_free (s);
8742          }
8743
8744
8745          void
8746          command_succeeded (const mongoc_apm_command_succeeded_t *event)
8747          {
8748             char *s;
8749
8750             s = bson_as_relaxed_extended_json (
8751                mongoc_apm_command_succeeded_get_reply (event), NULL);
8752             printf ("Command %s succeeded:\n%s\n\n",
8753                     mongoc_apm_command_succeeded_get_command_name (event),
8754                     s);
8755
8756             ((stats_t *) mongoc_apm_command_succeeded_get_context (event))->succeeded++;
8757
8758             bson_free (s);
8759          }
8760
8761
8762          void
8763          command_failed (const mongoc_apm_command_failed_t *event)
8764          {
8765             bson_error_t error;
8766
8767             mongoc_apm_command_failed_get_error (event, &error);
8768             printf ("Command %s failed:\n\"%s\"\n\n",
8769                     mongoc_apm_command_failed_get_command_name (event),
8770                     error.message);
8771
8772             ((stats_t *) mongoc_apm_command_failed_get_context (event))->failed++;
8773          }
8774
8775
8776          int
8777          main (int argc, char *argv[])
8778          {
8779             mongoc_client_t *client;
8780             mongoc_apm_callbacks_t *callbacks;
8781             stats_t stats = {0};
8782             mongoc_collection_t *collection;
8783             bson_error_t error;
8784             const char *uri_string =
8785                "mongodb://127.0.0.1/?appname=cmd-monitoring-example";
8786             mongoc_uri_t *uri;
8787             const char *collection_name = "test";
8788             bson_t *docs[2];
8789
8790             mongoc_init ();
8791
8792             if (argc > 1) {
8793                uri_string = argv[1];
8794             }
8795
8796             uri = mongoc_uri_new_with_error (uri_string, &error);
8797             if (!uri) {
8798                fprintf (stderr,
8799                         "failed to parse URI: %s\n"
8800                         "error message:       %s\n",
8801                         uri_string,
8802                         error.message);
8803                return EXIT_FAILURE;
8804             }
8805
8806             client = mongoc_client_new_from_uri (uri);
8807             if (!client) {
8808                return EXIT_FAILURE;
8809             }
8810
8811             mongoc_client_set_error_api (client, 2);
8812             callbacks = mongoc_apm_callbacks_new ();
8813             mongoc_apm_set_command_started_cb (callbacks, command_started);
8814             mongoc_apm_set_command_succeeded_cb (callbacks, command_succeeded);
8815             mongoc_apm_set_command_failed_cb (callbacks, command_failed);
8816             mongoc_client_set_apm_callbacks (
8817                client, callbacks, (void *) &stats /* context pointer */);
8818
8819             collection = mongoc_client_get_collection (client, "test", collection_name);
8820             mongoc_collection_drop (collection, NULL);
8821
8822             docs[0] = BCON_NEW ("_id", BCON_INT32 (0));
8823             docs[1] = BCON_NEW ("_id", BCON_INT32 (1));
8824             mongoc_collection_insert_many (
8825                collection, (const bson_t **) docs, 2, NULL, NULL, NULL);
8826
8827             /* duplicate key error on the second insert */
8828             mongoc_collection_insert_one (collection, docs[0], NULL, NULL, NULL);
8829
8830             mongoc_collection_destroy (collection);
8831             mongoc_apm_callbacks_destroy (callbacks);
8832             mongoc_uri_destroy (uri);
8833             mongoc_client_destroy (client);
8834
8835             printf ("started: %d\nsucceeded: %d\nfailed: %d\n",
8836                     stats.started,
8837                     stats.succeeded,
8838                     stats.failed);
8839
8840             bson_destroy (docs[0]);
8841             bson_destroy (docs[1]);
8842
8843             mongoc_cleanup ();
8844
8845             return EXIT_SUCCESS;
8846          }
8847
8848
8849This example program prints:
8850
8851          Command drop started on 127.0.0.1:
8852          { "drop" : "test" }
8853
8854          Command drop succeeded:
8855          { "ns" : "test.test", "nIndexesWas" : 1, "ok" : 1.0 }
8856
8857          Command insert started on 127.0.0.1:
8858          {
8859            "insert" : "test",
8860            "ordered" : true,
8861            "documents" : [
8862              { "_id" : 0 }, { "_id" : 1 }
8863            ]
8864          }
8865
8866          Command insert succeeded:
8867          { "n" : 2, "ok" : 1.0 }
8868
8869          Command insert started on 127.0.0.1:
8870          {
8871            "insert" : "test",
8872            "ordered" : true,
8873            "documents" : [
8874              { "_id" : 0 }
8875            ]
8876          }
8877
8878          Command insert succeeded:
8879          {
8880            "n" : 0,
8881            "writeErrors" : [
8882              { "index" : 0, "code" : 11000, "errmsg" : "duplicate key" }
8883            ],
8884            "ok" : 1.0
8885          }
8886
8887          started: 3
8888          succeeded: 3
8889          failed: 0
8890
8891       The output has been edited and formatted for clarity. Depending on your
8892       server configuration, messages may include metadata like database name,
8893       logical session ids, or cluster times that are not shown here.
8894
8895       The  final  "insert"  command  is  considered  successful,  despite the
8896       writeError, because the server replied  to  the  overall  command  with
8897       "ok": 1.
8898
8899   SDAM Monitoring Example
8900       example-sdam-monitoring.c.INDENT 0.0
8901
8902          /* gcc example-sdam-monitoring.c -o example-sdam-monitoring \
8903           *     $(pkg-config --cflags --libs libmongoc-1.0) */
8904
8905          /* ./example-sdam-monitoring [CONNECTION_STRING] */
8906
8907          #include <mongoc/mongoc.h>
8908          #include <stdio.h>
8909
8910
8911          typedef struct {
8912             int server_changed_events;
8913             int server_opening_events;
8914             int server_closed_events;
8915             int topology_changed_events;
8916             int topology_opening_events;
8917             int topology_closed_events;
8918             int heartbeat_started_events;
8919             int heartbeat_succeeded_events;
8920             int heartbeat_failed_events;
8921          } stats_t;
8922
8923
8924          static void
8925          server_changed (const mongoc_apm_server_changed_t *event)
8926          {
8927             stats_t *context;
8928             const mongoc_server_description_t *prev_sd, *new_sd;
8929
8930             context = (stats_t *) mongoc_apm_server_changed_get_context (event);
8931             context->server_changed_events++;
8932
8933             prev_sd = mongoc_apm_server_changed_get_previous_description (event);
8934             new_sd = mongoc_apm_server_changed_get_new_description (event);
8935
8936             printf ("server changed: %s %s -> %s\n",
8937                     mongoc_apm_server_changed_get_host (event)->host_and_port,
8938                     mongoc_server_description_type (prev_sd),
8939                     mongoc_server_description_type (new_sd));
8940          }
8941
8942
8943          static void
8944          server_opening (const mongoc_apm_server_opening_t *event)
8945          {
8946             stats_t *context;
8947
8948             context = (stats_t *) mongoc_apm_server_opening_get_context (event);
8949             context->server_opening_events++;
8950
8951             printf ("server opening: %s\n",
8952                     mongoc_apm_server_opening_get_host (event)->host_and_port);
8953          }
8954
8955
8956          static void
8957          server_closed (const mongoc_apm_server_closed_t *event)
8958          {
8959             stats_t *context;
8960
8961             context = (stats_t *) mongoc_apm_server_closed_get_context (event);
8962             context->server_closed_events++;
8963
8964             printf ("server closed: %s\n",
8965                     mongoc_apm_server_closed_get_host (event)->host_and_port);
8966          }
8967
8968
8969          static void
8970          topology_changed (const mongoc_apm_topology_changed_t *event)
8971          {
8972             stats_t *context;
8973             const mongoc_topology_description_t *prev_td;
8974             const mongoc_topology_description_t *new_td;
8975             mongoc_server_description_t **prev_sds;
8976             size_t n_prev_sds;
8977             mongoc_server_description_t **new_sds;
8978             size_t n_new_sds;
8979             size_t i;
8980             mongoc_read_prefs_t *prefs;
8981
8982             context = (stats_t *) mongoc_apm_topology_changed_get_context (event);
8983             context->topology_changed_events++;
8984
8985             prev_td = mongoc_apm_topology_changed_get_previous_description (event);
8986             prev_sds = mongoc_topology_description_get_servers (prev_td, &n_prev_sds);
8987             new_td = mongoc_apm_topology_changed_get_new_description (event);
8988             new_sds = mongoc_topology_description_get_servers (new_td, &n_new_sds);
8989
8990             printf ("topology changed: %s -> %s\n",
8991                     mongoc_topology_description_type (prev_td),
8992                     mongoc_topology_description_type (new_td));
8993
8994             if (n_prev_sds) {
8995                printf ("  previous servers:\n");
8996                for (i = 0; i < n_prev_sds; i++) {
8997                   printf ("      %s %s\n",
8998                           mongoc_server_description_type (prev_sds[i]),
8999                           mongoc_server_description_host (prev_sds[i])->host_and_port);
9000                }
9001             }
9002
9003             if (n_new_sds) {
9004                printf ("  new servers:\n");
9005                for (i = 0; i < n_new_sds; i++) {
9006                   printf ("      %s %s\n",
9007                           mongoc_server_description_type (new_sds[i]),
9008                           mongoc_server_description_host (new_sds[i])->host_and_port);
9009                }
9010             }
9011
9012             prefs = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
9013
9014             /* it is safe, and unfortunately necessary, to cast away const here */
9015             if (mongoc_topology_description_has_readable_server (
9016                    (mongoc_topology_description_t *) new_td, prefs)) {
9017                printf ("  secondary AVAILABLE\n");
9018             } else {
9019                printf ("  secondary UNAVAILABLE\n");
9020             }
9021
9022             if (mongoc_topology_description_has_writable_server (
9023                    (mongoc_topology_description_t *) new_td)) {
9024                printf ("  primary AVAILABLE\n");
9025             } else {
9026                printf ("  primary UNAVAILABLE\n");
9027             }
9028
9029             mongoc_read_prefs_destroy (prefs);
9030             mongoc_server_descriptions_destroy_all (prev_sds, n_prev_sds);
9031             mongoc_server_descriptions_destroy_all (new_sds, n_new_sds);
9032          }
9033
9034
9035          static void
9036          topology_opening (const mongoc_apm_topology_opening_t *event)
9037          {
9038             stats_t *context;
9039
9040             context = (stats_t *) mongoc_apm_topology_opening_get_context (event);
9041             context->topology_opening_events++;
9042
9043             printf ("topology opening\n");
9044          }
9045
9046
9047          static void
9048          topology_closed (const mongoc_apm_topology_closed_t *event)
9049          {
9050             stats_t *context;
9051
9052             context = (stats_t *) mongoc_apm_topology_closed_get_context (event);
9053             context->topology_closed_events++;
9054
9055             printf ("topology closed\n");
9056          }
9057
9058
9059          static void
9060          server_heartbeat_started (const mongoc_apm_server_heartbeat_started_t *event)
9061          {
9062             stats_t *context;
9063
9064             context =
9065                (stats_t *) mongoc_apm_server_heartbeat_started_get_context (event);
9066             context->heartbeat_started_events++;
9067
9068             printf ("%s heartbeat started\n",
9069                     mongoc_apm_server_heartbeat_started_get_host (event)->host_and_port);
9070          }
9071
9072
9073          static void
9074          server_heartbeat_succeeded (
9075             const mongoc_apm_server_heartbeat_succeeded_t *event)
9076          {
9077             stats_t *context;
9078             char *reply;
9079
9080             context =
9081                (stats_t *) mongoc_apm_server_heartbeat_succeeded_get_context (event);
9082             context->heartbeat_succeeded_events++;
9083
9084             reply = bson_as_canonical_extended_json (
9085                mongoc_apm_server_heartbeat_succeeded_get_reply (event), NULL);
9086
9087             printf (
9088                "%s heartbeat succeeded: %s\n",
9089                mongoc_apm_server_heartbeat_succeeded_get_host (event)->host_and_port,
9090                reply);
9091
9092             bson_free (reply);
9093          }
9094
9095
9096          static void
9097          server_heartbeat_failed (const mongoc_apm_server_heartbeat_failed_t *event)
9098          {
9099             stats_t *context;
9100             bson_error_t error;
9101
9102             context = (stats_t *) mongoc_apm_server_heartbeat_failed_get_context (event);
9103             context->heartbeat_failed_events++;
9104             mongoc_apm_server_heartbeat_failed_get_error (event, &error);
9105
9106             printf ("%s heartbeat failed: %s\n",
9107                     mongoc_apm_server_heartbeat_failed_get_host (event)->host_and_port,
9108                     error.message);
9109          }
9110
9111
9112          int
9113          main (int argc, char *argv[])
9114          {
9115             mongoc_client_t *client;
9116             mongoc_apm_callbacks_t *cbs;
9117             stats_t stats = {0};
9118             const char *uri_string =
9119                "mongodb://127.0.0.1/?appname=sdam-monitoring-example";
9120             mongoc_uri_t *uri;
9121             bson_t cmd = BSON_INITIALIZER;
9122             bson_t reply;
9123             bson_error_t error;
9124
9125             mongoc_init ();
9126
9127             if (argc > 1) {
9128                uri_string = argv[1];
9129             }
9130
9131             uri = mongoc_uri_new_with_error (uri_string, &error);
9132             if (!uri) {
9133                fprintf (stderr,
9134                         "failed to parse URI: %s\n"
9135                         "error message:       %s\n",
9136                         uri_string,
9137                         error.message);
9138                return EXIT_FAILURE;
9139             }
9140
9141             client = mongoc_client_new_from_uri (uri);
9142             if (!client) {
9143                return EXIT_FAILURE;
9144             }
9145
9146             mongoc_client_set_error_api (client, 2);
9147             cbs = mongoc_apm_callbacks_new ();
9148             mongoc_apm_set_server_changed_cb (cbs, server_changed);
9149             mongoc_apm_set_server_opening_cb (cbs, server_opening);
9150             mongoc_apm_set_server_closed_cb (cbs, server_closed);
9151             mongoc_apm_set_topology_changed_cb (cbs, topology_changed);
9152             mongoc_apm_set_topology_opening_cb (cbs, topology_opening);
9153             mongoc_apm_set_topology_closed_cb (cbs, topology_closed);
9154             mongoc_apm_set_server_heartbeat_started_cb (cbs, server_heartbeat_started);
9155             mongoc_apm_set_server_heartbeat_succeeded_cb (cbs,
9156                                                           server_heartbeat_succeeded);
9157             mongoc_apm_set_server_heartbeat_failed_cb (cbs, server_heartbeat_failed);
9158             mongoc_client_set_apm_callbacks (
9159                client, cbs, (void *) &stats /* context pointer */);
9160
9161             /* the driver connects on demand to perform first operation */
9162             BSON_APPEND_INT32 (&cmd, "buildinfo", 1);
9163             mongoc_client_command_simple (client, "admin", &cmd, NULL, &reply, &error);
9164             mongoc_uri_destroy (uri);
9165             mongoc_client_destroy (client);
9166
9167             printf ("Events:\n"
9168                     "   server changed: %d\n"
9169                     "   server opening: %d\n"
9170                     "   server closed: %d\n"
9171                     "   topology changed: %d\n"
9172                     "   topology opening: %d\n"
9173                     "   topology closed: %d\n"
9174                     "   heartbeat started: %d\n"
9175                     "   heartbeat succeeded: %d\n"
9176                     "   heartbeat failed: %d\n",
9177                     stats.server_changed_events,
9178                     stats.server_opening_events,
9179                     stats.server_closed_events,
9180                     stats.topology_changed_events,
9181                     stats.topology_opening_events,
9182                     stats.topology_closed_events,
9183                     stats.heartbeat_started_events,
9184                     stats.heartbeat_succeeded_events,
9185                     stats.heartbeat_failed_events);
9186
9187             bson_destroy (&cmd);
9188             bson_destroy (&reply);
9189             mongoc_apm_callbacks_destroy (cbs);
9190
9191             mongoc_cleanup ();
9192
9193             return EXIT_SUCCESS;
9194          }
9195
9196
9197Start  a 3-node replica set on localhost with set name "rs" and start the pro‐
9198gram:
9199
9200          ./example-sdam-monitoring "mongodb://localhost:27017,localhost:27018/?replicaSet=rs"
9201
9202       This example program prints something like:
9203
9204          topology opening
9205          topology changed: Unknown -> ReplicaSetNoPrimary
9206            secondary UNAVAILABLE
9207            primary UNAVAILABLE
9208          server opening: localhost:27017
9209          server opening: localhost:27018
9210          localhost:27017 heartbeat started
9211          localhost:27018 heartbeat started
9212          localhost:27017 heartbeat succeeded: { ... reply ... }
9213          server changed: localhost:27017 Unknown -> RSPrimary
9214          server opening: localhost:27019
9215          topology changed: ReplicaSetNoPrimary -> ReplicaSetWithPrimary
9216            new servers:
9217                RSPrimary localhost:27017
9218            secondary UNAVAILABLE
9219            primary AVAILABLE
9220          localhost:27019 heartbeat started
9221          localhost:27018 heartbeat succeeded: { ... reply ... }
9222          server changed: localhost:27018 Unknown -> RSSecondary
9223          topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
9224            previous servers:
9225                RSPrimary localhost:27017
9226            new servers:
9227                RSPrimary localhost:27017
9228                RSSecondary localhost:27018
9229            secondary AVAILABLE
9230            primary AVAILABLE
9231          localhost:27019 heartbeat succeeded: { ... reply ... }
9232          server changed: localhost:27019 Unknown -> RSSecondary
9233          topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
9234            previous servers:
9235                RSPrimary localhost:27017
9236                RSSecondary localhost:27018
9237            new servers:
9238                RSPrimary localhost:27017
9239                RSSecondary localhost:27018
9240                RSSecondary localhost:27019
9241            secondary AVAILABLE
9242            primary AVAILABLE
9243          topology closed
9244
9245          Events:
9246             server changed: 3
9247             server opening: 3
9248             server closed: 0
9249             topology changed: 4
9250             topology opening: 1
9251             topology closed: 1
9252             heartbeat started: 3
9253             heartbeat succeeded: 3
9254             heartbeat failed: 0
9255
9256       The driver connects to the mongods on ports 27017 and 27018, which were
9257       specified  in the URI, and determines which is primary. It also discov‐
9258       ers the third member, "localhost:27019", and adds it to the topology.
9259

AUTHOR

9261       MongoDB, Inc
9262
9264       2017-present, MongoDB, Inc
9265
9266
9267
9268
92691.13.1                           Jan 24, 2019              MONGOC_REFERENCE(3)
Impressum