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

AUTHOR

11235       MongoDB, Inc
11236
11238       2017-present, MongoDB, Inc
11239
11240
11241
11242
112431.20.0                           Nov 18, 2021              MONGOC_REFERENCE(3)
Impressum