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

AUTHOR

11153       MongoDB, Inc
11154
11156       2017-present, MongoDB, Inc
11157
11158
11159
11160
111611.23.1                           Oct 20, 2022              MONGOC_REFERENCE(3)
Impressum