1MONGOC_REFERENCE(3)                libmongoc               MONGOC_REFERENCE(3)
2
3
4

NAME

6       mongoc_reference - Index
7

LIBMONGOC

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

AUTHOR

11064       MongoDB, Inc
11065
11067       2017-present, MongoDB, Inc
11068
11069
11070
11071
110721.17.6                           Jun 03, 2021              MONGOC_REFERENCE(3)
Impressum