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

AUTHOR

11092       MongoDB, Inc
11093
11095       2017-present, MongoDB, Inc
11096
11097
11098
11099
111001.24.3                           Aug 17, 2023              MONGOC_REFERENCE(3)
Impressum