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

AUTHOR

11081       MongoDB, Inc
11082
11084       2017-present, MongoDB, Inc
11085
11086
11087
11088
110891.17.4                           Feb 04, 2021              MONGOC_REFERENCE(3)
Impressum