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  variety  of  platforms
26       including:
27
28       · Archlinux
29
30       · Debian 9.2
31
32       · macOS 10.12
33
34       · Microsoft Windows Server 2008
35
36       · RHEL 7.0, 7.1, 7.2
37
38       · Ubuntu 16.04, 18.04
39
40       · Clang 3.4, 3.5, 3.7, 3.8
41
42       · GCC 4.6, 4.8, 4.9, 5.4, 6.3
43
44       · MinGW-W64
45
46       · Visual Studio 2010, 2013, 2015
47
48       · x86, x86_64, ARM (aarch64), Power8 (ppc64le), zSeries (s390x)
49
50   Install libmongoc with a Package Manager
51       Several  Linux  distributions  provide  packages  for libmongoc and its
52       dependencies. One advantage of installing libmongoc with a package man‐
53       ager  is  that  its  dependencies (including libbson) will be installed
54       automatically.
55
56       The libmongoc package is available on recent  versions  of  Debian  and
57       Ubuntu.
58
59          $ apt-get install libmongoc-1.0-0
60
61       On Fedora, a mongo-c-driver package is available in the default reposi‐
62       tories and can be installed with:
63
64          $ dnf install mongo-c-driver
65
66       On recent Red Hat systems, such as CentOS and RHEL 7, a  mongo-c-driver
67       package  is available in the EPEL repository. To check which version is
68       available, see  https://apps.fedoraproject.org/packages/mongo-c-driver.
69       The package can be installed with:
70
71          $ yum install mongo-c-driver
72
73   Install libbson with a Package Manager
74       The  libbson  package  is  available  on  recent versions of Debian and
75       Ubuntu. If you have installed libmongoc, then libbson will have already
76       been  installed as a dependency. It is also possible to install libbson
77       without libmongoc.
78
79          $ apt-get install libbson-1.0
80
81       On Fedora, a libbson package is available in the  default  repositories
82       and can be installed with:
83
84          $ dnf install libbson
85
86       On recent Red Hat systems, such as CentOS and RHEL 7, a libbson package
87       is available in the EPEL repository. To check which version  is  avail‐
88       able, see https://apps.fedoraproject.org/packages/libbson.  The package
89       can be installed with:
90
91          $ yum install libbson
92
93   Building on Unix
94   Prerequisites for libmongoc
95       OpenSSL is required for authentication or for SSL connections  to  Mon‐
96       goDB. Kerberos or LDAP support requires Cyrus SASL.
97
98       To install all optional dependencies on RedHat / Fedora:
99
100          $ sudo yum install cmake openssl-devel cyrus-sasl-devel
101
102       On Debian / Ubuntu:
103
104          $ sudo apt-get install cmake libssl-dev libsasl2-dev
105
106       On FreeBSD:
107
108          $ su -c 'pkg install cmake openssl cyrus-sasl'
109
110   Prerequisites for libbson
111       The  only prerequisite for building libbson is cmake. The command lines
112       above can be adjusted to install only cmake.
113
114   Building from a release tarball
115       Unless you intend to contribute to mongo-c-driver and/or  libbson,  you
116       will want to build from a release tarball.
117
118       The  most  recent  release  of libmongoc and libbson, both of which are
119       included in mongo-c-driver, can be downloaded here. The instructions in
120       this document utilize cmake's out-of-source build feature to keep build
121       artifacts separate from source files.
122
123       The following snippet will download and extract the driver, and config‐
124       ure it:
125
126          $ wget https://github.com/mongodb/mongo-c-driver/releases/download/x.y.z/mongo-c-driver-x.y.z.tar.gz
127          $ tar xzf mongo-c-driver-x.y.z.tar.gz
128          $ cd mongo-c-driver-x.y.z
129          $ mkdir cmake-build
130          $ cd cmake-build
131          $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF ..
132
133       The  -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF option is recommended, see
134       init-cleanup. Another useful cmake option is -DCMAKE_BUILD_TYPE=Release
135       for  a release optimized build and -DCMAKE_BUILD_TYPE=Debug for a debug
136       build. For a list of all configure options, run cmake -L ...
137
138       If cmake completed successfully, you will see a considerable amount  of
139       output  describing  your  build configuration. The final line of output
140       should look something like this:
141
142          -- Build files have been written to: /home/user/mongo-c-driver-x.y.z/cmake-build
143
144       If cmake concludes with anything different, then  there  is  likely  an
145       error  or some other problem with the build. Review the output to iden‐
146       tify and correct the problem.
147
148       mongo-c-driver contains a copy of libbson, in case your system does not
149       already have libbson installed. The build will detect if libbson is not
150       installed and use the bundled libbson.
151
152       Additionally, it is possible to build only libbson by setting the -DEN‐
153       ABLE_MONGOC=OFF option:
154
155          $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF -DENABLE_MONGOC=OFF ..
156
157       A build configuration description similar to the one above will be dis‐
158       played, though with fewer entries. Once the configuration is  complete,
159       the selected items can be built and installed with these commands:
160
161          $ sudo make install
162
163       There  are  two  ways  to  uninstall  the  components  that  have  been
164       installed.  The first is to invoke the uninstall program directly.   On
165       Linux/Unix:
166
167          $ sudo /usr/local/share/mongo-c-driver/uninstall.sh
168
169       On Windows:
170
171          $ C:\mongo-c-driver\share\mongo-c-driver\uninstall.bat
172
173       The  second way to uninstall is from within the build directory, assum‐
174       ing that it is in the exact same state as when the install command  was
175       invoked:
176
177          $ sudo make uninstall
178
179       The  second approach simply invokes the uninstall program referenced in
180       the first approach.
181
182   Building from git
183       Clone the repository and build  the  current  master  or  a  particular
184       release tag:
185
186          $ git clone https://github.com/mongodb/mongo-c-driver.git
187          $ cd mongo-c-driver
188          $ git checkout x.y.z  # To build a particular release
189          $ python build/calc_release_version.py > VERSION_CURRENT
190          $ mkdir cmake-build
191          $ cd cmake-build
192          $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF ..
193          $ sudo make install
194
195   Generating the documentation
196       Install Sphinx, then:
197
198          $ cmake -DENABLE_MAN_PAGES=ON -DENABLE_HTML_DOCS=ON ..
199          $ make mongoc-doc
200
201       To build only the libbson documentation:
202
203          $ cmake -DENABLE_MAN_PAGES=ON -DENABLE_HTML_DOCS=ON ..
204          $ make bson-doc
205
206       The  -DENABLE_MAN_PAGES=ON  and -DENABLE_HTML_DOCS=ON can also be added
207       as options to a normal build from a release tarball or from git so that
208       the documentation is built at the same time as other components.
209
210   Building on macOS
211       Install the XCode Command Line Tools:
212
213          $ xcode-select --install
214
215       The cmake utility is also required. First install Homebrew according to
216       its instructions, then:
217
218          $ brew install cmake
219
220       Download the latest release tarball:
221
222          $ curl -LO https://github.com/mongodb/mongo-c-driver/releases/download/x.y.z/mongo-c-driver-x.y.z.tar.gz
223          $ tar xzf mongo-c-driver-x.y.z.tar.gz
224          $ cd mongo-c-driver-x.y.z
225
226       Build and install the driver:
227
228          $ mkdir cmake-build
229          $ cd cmake-build
230          $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF ..
231          $ make install
232
233       All of the same variations described above (e.g., building  only  libb‐
234       son,  building documentation, etc.) are available when building on mac‐
235       OS.
236
237   Building on Windows with Visual Studio
238       Building on Windows requires Windows Vista or newer and  Visual  Studio
239       2010  or newer. Additionally, cmake is required to generate Visual Stu‐
240       dio project files.
241
242       Let's start by generating Visual Studio project  files.  The  following
243       assumes  we  are  compiling for 64-bit Windows using Visual Studio 2015
244       Express, which can be freely downloaded from Microsoft. We will be uti‐
245       lizing cmake's out-of-source build feature to keep build artifacts sep‐
246       arate from source files.
247
248          $ cd mongo-c-driver-x.y.z
249          $ mkdir cmake-build
250          $ cd cmake-build
251          $ cmake -G "Visual Studio 14 2015 Win64" \
252              "-DCMAKE_INSTALL_PREFIX=C:\mongo-c-driver" \
253              "-DCMAKE_PREFIX_PATH=C:\mongo-c-driver" \
254              ..
255
256       (Run cmake -LH .. for a list of other options.)
257
258       Now that we have project  files  generated,  we  can  either  open  the
259       project  in Visual Studio or compile from the command line. Let's build
260       using the command line program msbuild.exe:
261
262          $ msbuild.exe /p:Configuration=RelWithDebInfo ALL_BUILD.vcxproj
263
264       Visual Studio's default build type is Debug, but we recommend a release
265       build  with debug info for production use. Now that libmongoc and libb‐
266       son are  compiled,  let's  install  them  using  msbuild.  It  will  be
267       installed to the path specified by CMAKE_INSTALL_PREFIX.
268
269          $ msbuild.exe INSTALL.vcxproj
270
271       You should now see libmongoc and libbson installed in C:\mongo-c-driver
272
273       To use the driver libraries in your program, see visual-studio-guide.
274
275   Building on Windows with MinGW-W64 and MSYS2
276       Install  MSYS2  from  msys2.github.io.  Choose  the x86_64 version, not
277       i686.
278
279       Open the MingGW shell with c:\msys64\ming64.exe (not the  msys2_shell).
280       Install dependencies:
281
282          $ pacman --noconfirm -Syu
283          $ pacman --noconfirm -S mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake
284          $ pacman --noconfirm -S mingw-w64-x86_64-extra-cmake-modules make tar
285          $ pacman --noconfirm -S mingw64/mingw-w64-x86_64-cyrus-sasl
286
287       Download and untar the latest tarball.
288
289          $ curl -LO https://github.com/mongodb/mongo-c-driver/releases/download/x.y.z/mongo-c-driver-x.y.z.tar.gz
290          $ tar xzf mongo-c-driver-x.y.z.tar.gz
291          $ cd mongo-c-driver-x.y.z
292
293       Create a build directory and build and install with cmake:
294
295          $ mkdir cmake-build
296          $ cd cmake-build
297          $ CC=/mingw64/bin/gcc.exe /mingw64/bin/cmake -G "MSYS Makefiles" -DCMAKE_INSTALL_PREFIX="C:/mongo-c-driver" -DCMAKE_C_FLAGS="-D__USE_MINGW_ANSI_STDIO=1" ..
298          $ make install
299
300   Additional Options for Integrators
301       In the event that you are building the BSON library and/or the C driver
302       to embed with other components and you wish to avoid the potential  for
303       collision  with  components  installed  from a standard build or from a
304       distribution package manager, you can make use of the BSON_OUTPUT_BASE‐
305       NAME and MONGOC_OUTPUT_BASENAME options to cmake.
306
307          $ mkdir cmake-build
308          $ cd cmake-build
309          $ cmake -DBSON_OUTPUT_BASENAME=custom_bson -DMONGOC_OUTPUT_BASENAME=custom_mongoc ..
310
311       The  above  command would produce libraries named libcustom_bson.so and
312       libcustom_mongoc.so (or with the extension appropriate  for  the  build
313       platform).  Those libraries could be placed in a standard system direc‐
314       tory or in an alternate location and could be linked to  by  specifying
315       something like -lcustom_mongoc -lcustom_bson on the linker command line
316       (possibly adjusting the  specific  flags  to  those  required  by  your
317       linker).
318
319   Tutorial
320       This guide offers a brief introduction to the MongoDB C Driver.
321
322       For more information on the C API, please refer to the api.
323
324   Contents
325       · Tutorial
326
327         · Installing
328
329         · Starting MongoDB
330
331         · Include and link libmongoc in your C program
332
333         · Use libmongoc in a Microsoft Visual Studio Project
334
335         · Making a Connection
336
337         · Creating BSON Documents
338
339         · Basic CRUD Operations
340
341         · Executing Commands
342
343         · Threading
344
345         · Next Steps
346
347   Installing
348       For  detailed instructions on installing the MongoDB C Driver on a par‐
349       ticular platform, please see the installation guide.
350
351   Starting MongoDB
352       To run the examples in this tutorial, MongoDB  must  be  installed  and
353       running  on  localhost on the default port, 27017. To check if it is up
354       and running, connect to it with the MongoDB shell.
355
356          $ mongo --host localhost --port 27017
357          MongoDB shell version: 3.0.6
358          connecting to: localhost:27017/test
359          >
360
361   Include and link libmongoc in your C program
362   Include mongoc.h
363       All libmongoc's functions and types are available in one  header  file.
364       Simply include mongoc/mongoc.h:
365
366          #include <mongoc/mongoc.h>
367
368   CMake
369       The libmongoc installation includes a CMake config-file package, so you
370       can use CMake's find_package command to import libmongoc's CMake target
371       and link to libmongoc (as a shared library): CMakeLists.txt.INDENT 0.0
372
373          # Specify the minimum version you require.
374          find_package (mongoc-1.0 1.7 REQUIRED)
375
376          # The "hello_mongoc.c" sample program is shared among four tests.
377          add_executable (hello_mongoc ../../hello_mongoc.c)
378          target_link_libraries (hello_mongoc PRIVATE mongo::mongoc_shared)
379
380
381You  can  also  use libmongoc as a static library instead: Use the mongo::mon‐

goc_static CMake target:

383
384          # Specify the minimum version you require.
385          find_package (mongoc-1.0 1.7 REQUIRED)
386
387          # The "hello_mongoc.c" sample program is shared among four tests.
388          add_executable (hello_mongoc ../../hello_mongoc.c)
389          target_link_libraries (hello_mongoc PRIVATE mongo::mongoc_static)
390
391
392   pkg-config
393       If you're not using CMake, use pkg-config on the command  line  to  set
394       header and library paths:
395
396          gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-1.0)
397
398
399       Or to statically link to libmongoc:
400
401          gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-static-1.0)
402
403
404   Specifying header and include paths manually
405       If  you  aren't  using  CMake or pkg-config, paths and libraries can be
406       managed manually.
407
408          $ gcc -o hello_mongoc hello_mongoc.c \
409              -I/usr/local/include/libbson-1.0 -I/usr/local/include/libmongoc-1.0 \
410              -lmongoc-1.0 -lbson-1.0
411          $ ./hello_mongoc
412          { "ok" : 1.000000 }
413
414       For Windows users, the code can be compiled and run with the  following
415       commands. (This assumes that the MongoDB C Driver has been installed to
416       C:\mongo-c-driver; change the include directory as needed.)
417
418          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 hello_mongoc.c
419          C:\> hello_mongoc
420          { "ok" : 1.000000 }
421
422   Use libmongoc in a Microsoft Visual Studio Project
423       See the libmongoc and Visual Studio guide.
424
425   Making a Connection
426       Access MongoDB with a mongoc_client_t.  It  transparently  connects  to
427       standalone  servers,  replica  sets  and sharded clusters on demand. To
428       perform operations on a database or collection, create  a  mongoc_data‐
429       base_t or mongoc_collection_t struct from the mongoc_client_t.
430
431       At  the start of an application, call mongoc_init before any other lib‐
432       mongoc functions. At the end, call the appropriate destroy function for
433       each  collection, database, or client handle, in reverse order from how
434       they were constructed. Call mongoc_cleanup before exiting.
435
436       The example below establishes a connection to a  standalone  server  on
437       localhost,  registers  the client application as "connect-example," and
438       performs a simple command.
439
440       More information about database operations can be  found  in  the  CRUD
441       Operations  and  Executing Commands sections. Examples of connecting to
442       replica sets and sharded clusters can be found on the Advanced  Connec‐
443       tions page.  hello_mongoc.c.INDENT 0.0
444
445          #include <mongoc/mongoc.h>
446
447          int
448          main (int argc, char *argv[])
449          {
450             const char *uri_string = "mongodb://localhost:27017";
451             mongoc_uri_t *uri;
452             mongoc_client_t *client;
453             mongoc_database_t *database;
454             mongoc_collection_t *collection;
455             bson_t *command, reply, *insert;
456             bson_error_t error;
457             char *str;
458             bool retval;
459
460             /*
461              * Required to initialize libmongoc's internals
462              */
463             mongoc_init ();
464
465             /*
466              * Optionally get MongoDB URI from command line
467              */
468             if (argc > 1) {
469                uri_string = argv[1];
470             }
471
472             /*
473              * Safely create a MongoDB URI object from the given string
474              */
475             uri = mongoc_uri_new_with_error (uri_string, &error);
476             if (!uri) {
477                fprintf (stderr,
478                         "failed to parse URI: %s\n"
479                         "error message:       %s\n",
480                         uri_string,
481                         error.message);
482                return EXIT_FAILURE;
483             }
484
485             /*
486              * Create a new client instance
487              */
488             client = mongoc_client_new_from_uri (uri);
489             if (!client) {
490                return EXIT_FAILURE;
491             }
492
493             /*
494              * Register the application name so we can track it in the profile logs
495              * on the server. This can also be done from the URI (see other examples).
496              */
497             mongoc_client_set_appname (client, "connect-example");
498
499             /*
500              * Get a handle on the database "db_name" and collection "coll_name"
501              */
502             database = mongoc_client_get_database (client, "db_name");
503             collection = mongoc_client_get_collection (client, "db_name", "coll_name");
504
505             /*
506              * Do work. This example pings the database, prints the result as JSON and
507              * performs an insert
508              */
509             command = BCON_NEW ("ping", BCON_INT32 (1));
510
511             retval = mongoc_client_command_simple (
512                client, "admin", command, NULL, &reply, &error);
513
514             if (!retval) {
515                fprintf (stderr, "%s\n", error.message);
516                return EXIT_FAILURE;
517             }
518
519             str = bson_as_json (&reply, NULL);
520             printf ("%s\n", str);
521
522             insert = BCON_NEW ("hello", BCON_UTF8 ("world"));
523
524             if (!mongoc_collection_insert_one (collection, insert, NULL, NULL, &error)) {
525                fprintf (stderr, "%s\n", error.message);
526             }
527
528             bson_destroy (insert);
529             bson_destroy (&reply);
530             bson_destroy (command);
531             bson_free (str);
532
533             /*
534              * Release our handles and clean up libmongoc
535              */
536             mongoc_collection_destroy (collection);
537             mongoc_database_destroy (database);
538             mongoc_uri_destroy (uri);
539             mongoc_client_destroy (client);
540             mongoc_cleanup ();
541
542             return EXIT_SUCCESS;
543          }
544
545
546   Creating BSON Documents
547       Documents  are stored in MongoDB's data format, BSON. The C driver uses
548       libbson to create BSON documents. There are several ways  to  construct
549       them: appending key-value pairs, using BCON, or parsing JSON.
550
551   Appending BSON
552       A  BSON  document,  represented as a bson_t in code, can be constructed
553       one field at a time using libbson's append functions.
554
555       For example, to create a document like this:
556
557          {
558             born : ISODate("1906-12-09"),
559             died : ISODate("1992-01-01"),
560             name : {
561                first : "Grace",
562                last : "Hopper"
563             },
564             languages : [ "MATH-MATIC", "FLOW-MATIC", "COBOL" ],
565             degrees: [ { degree: "BA", school: "Vassar" }, { degree: "PhD", school: "Yale" } ]
566          }
567
568       Use the following code:
569
570          #include <bson/bson.h>
571
572          int
573          main (int   argc,
574                char *argv[])
575          {
576             struct tm   born = { 0 };
577             struct tm   died = { 0 };
578             const char *lang_names[] = {"MATH-MATIC", "FLOW-MATIC", "COBOL"};
579             const char *schools[] = {"Vassar", "Yale"};
580             const char *degrees[] = {"BA", "PhD"};
581             uint32_t    i;
582             char        buf[16];
583             const       char *key;
584             size_t      keylen;
585             bson_t     *document;
586             bson_t      child;
587             bson_t      child2;
588             char       *str;
589
590             document = bson_new ();
591
592             /*
593              * Append { "born" : ISODate("1906-12-09") } to the document.
594              * Passing -1 for the length argument tells libbson to calculate the string length.
595              */
596             born.tm_year = 6;  /* years are 1900-based */
597             born.tm_mon = 11;  /* months are 0-based */
598             born.tm_mday = 9;
599             bson_append_date_time (document, "born", -1, mktime (&born) * 1000);
600
601             /*
602              * Append { "died" : ISODate("1992-01-01") } to the document.
603              */
604             died.tm_year = 92;
605             died.tm_mon = 0;
606             died.tm_mday = 1;
607
608             /*
609              * For convenience, this macro passes length -1 by default.
610              */
611             BSON_APPEND_DATE_TIME (document, "died", mktime (&died) * 1000);
612
613             /*
614              * Append a subdocument.
615              */
616             BSON_APPEND_DOCUMENT_BEGIN (document, "name", &child);
617             BSON_APPEND_UTF8 (&child, "first", "Grace");
618             BSON_APPEND_UTF8 (&child, "last", "Hopper");
619             bson_append_document_end (document, &child);
620
621             /*
622              * Append array of strings. Generate keys "0", "1", "2".
623              */
624             BSON_APPEND_ARRAY_BEGIN (document, "languages", &child);
625             for (i = 0; i < sizeof lang_names / sizeof (char *); ++i) {
626                keylen = bson_uint32_to_string (i, &key, buf, sizeof buf);
627                bson_append_utf8 (&child, key, (int) keylen, lang_names[i], -1);
628             }
629             bson_append_array_end (document, &child);
630
631             /*
632              * Array of subdocuments:
633              *    degrees: [ { degree: "BA", school: "Vassar" }, ... ]
634              */
635             BSON_APPEND_ARRAY_BEGIN (document, "degrees", &child);
636             for (i = 0; i < sizeof degrees / sizeof (char *); ++i) {
637                keylen = bson_uint32_to_string (i, &key, buf, sizeof buf);
638                bson_append_document_begin (&child, key, (int) keylen, &child2);
639                BSON_APPEND_UTF8 (&child2, "degree", degrees[i]);
640                BSON_APPEND_UTF8 (&child2, "school", schools[i]);
641                bson_append_document_end (&child, &child2);
642             }
643             bson_append_array_end (document, &child);
644
645             /*
646              * Print the document as a JSON string.
647              */
648             str = bson_as_canonical_extended_json (document, NULL);
649             printf ("%s\n", str);
650             bson_free (str);
651
652             /*
653              * Clean up allocated bson documents.
654              */
655             bson_destroy (document);
656             return 0;
657          }
658
659       See the libbson documentation for all of the types that can be appended
660       to a bson_t.
661
662   Using BCON
663       BSON  C  Object Notation, BCON for short, is an alternative way of con‐
664       structing BSON documents in a manner closer to the intended format.  It
665       has  less  type-safety than BSON's append functions but results in less
666       code.
667
668          #include <bson/bson.h>
669
670          int
671          main (int   argc,
672                char *argv[])
673          {
674             struct tm born = { 0 };
675             struct tm died = { 0 };
676             bson_t   *document;
677             char     *str;
678
679             born.tm_year = 6;
680             born.tm_mon = 11;
681             born.tm_mday = 9;
682
683             died.tm_year = 92;
684             died.tm_mon = 0;
685             died.tm_mday = 1;
686
687             document = BCON_NEW (
688                "born", BCON_DATE_TIME (mktime (&born) * 1000),
689                "died", BCON_DATE_TIME (mktime (&died) * 1000),
690                "name", "{",
691                "first", BCON_UTF8 ("Grace"),
692                "last", BCON_UTF8 ("Hopper"),
693                "}",
694                "languages", "[",
695                BCON_UTF8 ("MATH-MATIC"),
696                BCON_UTF8 ("FLOW-MATIC"),
697                BCON_UTF8 ("COBOL"),
698                "]",
699                "degrees", "[",
700                "{", "degree", BCON_UTF8 ("BA"), "school", BCON_UTF8 ("Vassar"), "}",
701                "{", "degree", BCON_UTF8 ("PhD"), "school", BCON_UTF8 ("Yale"), "}",
702                "]");
703
704             /*
705              * Print the document as a JSON string.
706              */
707             str = bson_as_canonical_extended_json (document, NULL);
708             printf ("%s\n", str);
709             bson_free (str);
710
711             /*
712              * Clean up allocated bson documents.
713              */
714             bson_destroy (document);
715             return 0;
716          }
717
718       Notice that BCON can create arrays, subdocuments and arbitrary fields.
719
720   Creating BSON from JSON
721       For single documents,  BSON  can  be  created  from  JSON  strings  via
722       bson_new_from_json.
723
724          #include <bson/bson.h>
725
726          int
727          main (int   argc,
728                char *argv[])
729          {
730             bson_error_t error;
731             bson_t      *bson;
732             char        *string;
733
734             const char *json = "{\"name\": {\"first\":\"Grace\", \"last\":\"Hopper\"}}";
735             bson = bson_new_from_json ((const uint8_t *)json, -1, &error);
736
737             if (!bson) {
738                fprintf (stderr, "%s\n", error.message);
739                return EXIT_FAILURE;
740             }
741
742             string = bson_as_canonical_extended_json (bson, NULL);
743             printf ("%s\n", string);
744             bson_free (string);
745
746             return 0;
747          }
748
749       To   initialize   BSON   from   a   sequence  of  JSON  documents,  use
750       bson_json_reader_t.
751
752   Basic CRUD Operations
753       This section demonstrates the basics of using the C Driver to  interact
754       with MongoDB.
755
756   Inserting a Document
757       To  insert documents into a collection, first obtain a handle to a mon‐
758       goc_collection_t  via  a  mongoc_client_t.  Then,  use   mongoc_collec‐
759       tion_insert_one  to  add BSON documents to the collection. This example
760       inserts into the database "mydb" and collection "mycoll".
761
762       When finished, ensure that allocated  structures  are  freed  by  using
763       their respective destroy functions.
764
765          #include <bson/bson.h>
766          #include <mongoc/mongoc.h>
767          #include <stdio.h>
768
769          int
770          main (int   argc,
771                char *argv[])
772          {
773              mongoc_client_t *client;
774              mongoc_collection_t *collection;
775              bson_error_t error;
776              bson_oid_t oid;
777              bson_t *doc;
778
779              mongoc_init ();
780
781              client = mongoc_client_new ("mongodb://localhost:27017/?appname=insert-example");
782              collection = mongoc_client_get_collection (client, "mydb", "mycoll");
783
784              doc = bson_new ();
785              bson_oid_init (&oid, NULL);
786              BSON_APPEND_OID (doc, "_id", &oid);
787              BSON_APPEND_UTF8 (doc, "hello", "world");
788
789              if (!mongoc_collection_insert_one (
790                     collection, doc, NULL, NULL, &error)) {
791                  fprintf (stderr, "%s\n", error.message);
792              }
793
794              bson_destroy (doc);
795              mongoc_collection_destroy (collection);
796              mongoc_client_destroy (client);
797              mongoc_cleanup ();
798
799              return 0;
800          }
801
802       Compile the code and run it:
803
804          $ gcc -o insert insert.c $(pkg-config --cflags --libs libmongoc-1.0)
805          $ ./insert
806
807       On Windows:
808
809          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 insert.c
810          C:\> insert
811
812       To verify that the insert succeeded, connect with the MongoDB shell.
813
814          $ mongo
815          MongoDB shell version: 3.0.6
816          connecting to: test
817          > use mydb
818          switched to db mydb
819          > db.mycoll.find()
820          { "_id" : ObjectId("55ef43766cb5f36a3bae6ee4"), "hello" : "world" }
821          >
822
823   Finding a Document
824       To  query a MongoDB collection with the C driver, use the function mon‐
825       goc_collection_find_with_opts(). This returns a cursor to the  matching
826       documents.  The  following  examples iterate through the result cursors
827       and print the matches to stdout as JSON strings.
828
829       Use a document as a query specifier; for example,
830
831          { "color" : "red" }
832
833       will match any document with a field named "color" with value "red". An
834       empty document {} can be used to match all documents.
835
836       This  first example uses an empty query specifier to find all documents
837       in the database "mydb" and collection "mycoll".
838
839          #include <bson/bson.h>
840          #include <mongoc/mongoc.h>
841          #include <stdio.h>
842
843          int
844          main (int argc, char *argv[])
845          {
846             mongoc_client_t *client;
847             mongoc_collection_t *collection;
848             mongoc_cursor_t *cursor;
849             const bson_t *doc;
850             bson_t *query;
851             char *str;
852
853             mongoc_init ();
854
855             client =
856                mongoc_client_new ("mongodb://localhost:27017/?appname=find-example");
857             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
858             query = bson_new ();
859             cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
860
861             while (mongoc_cursor_next (cursor, &doc)) {
862                str = bson_as_canonical_extended_json (doc, NULL);
863                printf ("%s\n", str);
864                bson_free (str);
865             }
866
867             bson_destroy (query);
868             mongoc_cursor_destroy (cursor);
869             mongoc_collection_destroy (collection);
870             mongoc_client_destroy (client);
871             mongoc_cleanup ();
872
873             return 0;
874          }
875
876       Compile the code and run it:
877
878          $ gcc -o find find.c $(pkg-config --cflags --libs libmongoc-1.0)
879          $ ./find
880          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
881
882       On Windows:
883
884          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find.c
885          C:\> find
886          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
887
888       To look for a specific document, add a specifier to query. This example
889       adds  a  call  to BSON_APPEND_UTF8() to look for all documents matching
890       {"hello" : "world"}.
891
892          #include <bson/bson.h>
893          #include <mongoc/mongoc.h>
894          #include <stdio.h>
895
896          int
897          main (int argc, char *argv[])
898          {
899             mongoc_client_t *client;
900             mongoc_collection_t *collection;
901             mongoc_cursor_t *cursor;
902             const bson_t *doc;
903             bson_t *query;
904             char *str;
905
906             mongoc_init ();
907
908             client = mongoc_client_new (
909                "mongodb://localhost:27017/?appname=find-specific-example");
910             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
911             query = bson_new ();
912             BSON_APPEND_UTF8 (query, "hello", "world");
913
914             cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
915
916             while (mongoc_cursor_next (cursor, &doc)) {
917                str = bson_as_canonical_extended_json (doc, NULL);
918                printf ("%s\n", str);
919                bson_free (str);
920             }
921
922             bson_destroy (query);
923             mongoc_cursor_destroy (cursor);
924             mongoc_collection_destroy (collection);
925             mongoc_client_destroy (client);
926             mongoc_cleanup ();
927
928             return 0;
929          }
930
931          $ gcc -o find-specific find-specific.c $(pkg-config --cflags --libs libmongoc-1.0)
932          $ ./find-specific
933          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
934
935          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 find-specific.c
936          C:\> find-specific
937          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
938
939   Updating a Document
940       This  code  snippet  gives   an   example   of   using   mongoc_collec‐
941       tion_update_one() to update the fields of a document.
942
943       Using  the  "mydb"  database,  the following example inserts an example
944       document into the "mycoll" collection. Then, using its _id  field,  the
945       document is updated with different values and a new field.
946
947          #include <bson/bson.h>
948          #include <mongoc/mongoc.h>
949          #include <stdio.h>
950
951          int
952          main (int argc, char *argv[])
953          {
954             mongoc_collection_t *collection;
955             mongoc_client_t *client;
956             bson_error_t error;
957             bson_oid_t oid;
958             bson_t *doc = NULL;
959             bson_t *update = NULL;
960             bson_t *query = NULL;
961
962             mongoc_init ();
963
964             client =
965                mongoc_client_new ("mongodb://localhost:27017/?appname=update-example");
966             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
967
968             bson_oid_init (&oid, NULL);
969             doc = BCON_NEW ("_id", BCON_OID (&oid), "key", BCON_UTF8 ("old_value"));
970
971             if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) {
972                fprintf (stderr, "%s\n", error.message);
973                goto fail;
974             }
975
976             query = BCON_NEW ("_id", BCON_OID (&oid));
977             update = BCON_NEW ("$set",
978                                "{",
979                                "key",
980                                BCON_UTF8 ("new_value"),
981                                "updated",
982                                BCON_BOOL (true),
983                                "}");
984
985             if (!mongoc_collection_update_one (
986                    collection, query, update, NULL, NULL, &error)) {
987                fprintf (stderr, "%s\n", error.message);
988                goto fail;
989             }
990
991          fail:
992             if (doc)
993                bson_destroy (doc);
994             if (query)
995                bson_destroy (query);
996             if (update)
997                bson_destroy (update);
998
999             mongoc_collection_destroy (collection);
1000             mongoc_client_destroy (client);
1001             mongoc_cleanup ();
1002
1003             return 0;
1004          }
1005
1006       Compile the code and run it:
1007
1008          $ gcc -o update update.c $(pkg-config --cflags --libs libmongoc-1.0)
1009          $ ./update
1010
1011       On Windows:
1012
1013          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 update.c
1014          C:\> update
1015          { "_id" : { "$oid" : "55ef43766cb5f36a3bae6ee4" }, "hello" : "world" }
1016
1017       To verify that the update succeeded, connect with the MongoDB shell.
1018
1019          $ mongo
1020          MongoDB shell version: 3.0.6
1021          connecting to: test
1022          > use mydb
1023          switched to db mydb
1024          > db.mycoll.find({"updated" : true})
1025          { "_id" : ObjectId("55ef549236fe322f9490e17b"), "updated" : true, "key" : "new_value" }
1026          >
1027
1028   Deleting a Document
1029       This  example  illustrates the use of mongoc_collection_delete_one() to
1030       delete a document.
1031
1032       The following code inserts a sample document into the  database  "mydb"
1033       and  collection  "mycoll".  Then,  it  deletes  all  documents matching
1034       {"hello" : "world"}.
1035
1036          #include <bson/bson.h>
1037          #include <mongoc/mongoc.h>
1038          #include <stdio.h>
1039
1040          int
1041          main (int argc, char *argv[])
1042          {
1043             mongoc_client_t *client;
1044             mongoc_collection_t *collection;
1045             bson_error_t error;
1046             bson_oid_t oid;
1047             bson_t *doc;
1048
1049             mongoc_init ();
1050
1051             client =
1052                mongoc_client_new ("mongodb://localhost:27017/?appname=delete-example");
1053             collection = mongoc_client_get_collection (client, "test", "test");
1054
1055             doc = bson_new ();
1056             bson_oid_init (&oid, NULL);
1057             BSON_APPEND_OID (doc, "_id", &oid);
1058             BSON_APPEND_UTF8 (doc, "hello", "world");
1059
1060             if (!mongoc_collection_insert_one (collection, doc, NULL, &error)) {
1061                fprintf (stderr, "Insert failed: %s\n", error.message);
1062             }
1063
1064             bson_destroy (doc);
1065
1066             doc = bson_new ();
1067             BSON_APPEND_OID (doc, "_id", &oid);
1068
1069             if (!mongoc_collection_delete_one (
1070                    collection, doc, NULL, NULL, &error)) {
1071                fprintf (stderr, "Delete failed: %s\n", error.message);
1072             }
1073
1074             bson_destroy (doc);
1075             mongoc_collection_destroy (collection);
1076             mongoc_client_destroy (client);
1077             mongoc_cleanup ();
1078
1079             return 0;
1080          }
1081
1082       Compile the code and run it:
1083
1084          $ gcc -o delete delete.c $(pkg-config --cflags --libs libmongoc-1.0)
1085          $ ./delete
1086
1087       On Windows:
1088
1089          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 delete.c
1090          C:\> delete
1091
1092       Use the MongoDB shell to prove that the  documents  have  been  removed
1093       successfully.
1094
1095          $ mongo
1096          MongoDB shell version: 3.0.6
1097          connecting to: test
1098          > use mydb
1099          switched to db mydb
1100          > db.mycoll.count({"hello" : "world"})
1101          0
1102          >
1103
1104   Counting Documents
1105       Counting  the number of documents in a MongoDB collection is similar to
1106       performing a find operation. This example counts the  number  of  docu‐
1107       ments  matching  {"hello" : "world"} in the database "mydb" and collec‐
1108       tion "mycoll".
1109
1110          #include <bson/bson.h>
1111          #include <mongoc/mongoc.h>
1112          #include <stdio.h>
1113
1114          int
1115          main (int argc, char *argv[])
1116          {
1117             mongoc_client_t *client;
1118             mongoc_collection_t *collection;
1119             bson_error_t error;
1120             bson_t *doc;
1121             int64_t count;
1122
1123             mongoc_init ();
1124
1125             client =
1126                mongoc_client_new ("mongodb://localhost:27017/?appname=count-example");
1127             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
1128             doc = bson_new_from_json (
1129                (const uint8_t *) "{\"hello\" : \"world\"}", -1, &error);
1130
1131             count = mongoc_collection_count (
1132                collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error);
1133
1134             if (count < 0) {
1135                fprintf (stderr, "%s\n", error.message);
1136             } else {
1137                printf ("%" PRId64 "\n", count);
1138             }
1139
1140             bson_destroy (doc);
1141             mongoc_collection_destroy (collection);
1142             mongoc_client_destroy (client);
1143             mongoc_cleanup ();
1144
1145             return 0;
1146          }
1147
1148       Compile the code and run it:
1149
1150          $ gcc -o count count.c $(pkg-config --cflags --libs libmongoc-1.0)
1151          $ ./count
1152          1
1153
1154       On Windows:
1155
1156          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 count.c
1157          C:\> count
1158          1
1159
1160   Executing Commands
1161       The driver provides helper functions for executing MongoDB commands  on
1162       client, database and collection structures. These functions return cur‐
1163       sors; the _simple variants return booleans indicating success or  fail‐
1164       ure.
1165
1166       This  example  executes  the  collStats  command against the collection
1167       "mycoll" in database "mydb".
1168
1169          #include <bson/bson.h>
1170          #include <mongoc/mongoc.h>
1171          #include <stdio.h>
1172
1173          int
1174          main (int argc, char *argv[])
1175          {
1176             mongoc_client_t *client;
1177             mongoc_collection_t *collection;
1178             bson_error_t error;
1179             bson_t *command;
1180             bson_t reply;
1181             char *str;
1182
1183             mongoc_init ();
1184
1185             client = mongoc_client_new (
1186                "mongodb://localhost:27017/?appname=executing-example");
1187             collection = mongoc_client_get_collection (client, "mydb", "mycoll");
1188
1189             command = BCON_NEW ("collStats", BCON_UTF8 ("mycoll"));
1190             if (mongoc_collection_command_simple (
1191                    collection, command, NULL, &reply, &error)) {
1192                str = bson_as_canonical_extended_json (&reply, NULL);
1193                printf ("%s\n", str);
1194                bson_free (str);
1195             } else {
1196                fprintf (stderr, "Failed to run command: %s\n", error.message);
1197             }
1198
1199             bson_destroy (command);
1200             bson_destroy (&reply);
1201             mongoc_collection_destroy (collection);
1202             mongoc_client_destroy (client);
1203             mongoc_cleanup ();
1204
1205             return 0;
1206          }
1207
1208       Compile the code and run it:
1209
1210          $ gcc -o executing executing.c $(pkg-config --cflags --libs libmongoc-1.0)
1211          $ ./executing
1212          { "ns" : "mydb.mycoll", "count" : 1, "size" : 48, "avgObjSize" : 48, "numExtents" : 1, "storageSize" : 8192,
1213          "lastExtentSize" : 8192.000000, "paddingFactor" : 1.000000, "userFlags" : 1, "capped" : false, "nindexes" : 1,
1214          "indexDetails" : {  }, "totalIndexSize" : 8176, "indexSizes" : { "_id_" : 8176 }, "ok" : 1.000000 }
1215
1216       On Windows:
1217
1218          C:\> cl.exe /IC:\mongo-c-driver\include\libbson-1.0 /IC:\mongo-c-driver\include\libmongoc-1.0 executing.c
1219          C:\> executing
1220          { "ns" : "mydb.mycoll", "count" : 1, "size" : 48, "avgObjSize" : 48, "numExtents" : 1, "storageSize" : 8192,
1221          "lastExtentSize" : 8192.000000, "paddingFactor" : 1.000000, "userFlags" : 1, "capped" : false, "nindexes" : 1,
1222          "indexDetails" : {  }, "totalIndexSize" : 8176, "indexSizes" : { "_id_" : 8176 }, "ok" : 1.000000 }
1223
1224   Threading
1225       The MongoDB C Driver is thread-unaware in  the  vast  majority  of  its
1226       operations.  This  means  it  is  up  to  the  programmer  to guarantee
1227       thread-safety.
1228
1229       However, mongoc_client_pool_t is thread-safe and is  used  to  fetch  a
1230       mongoc_client_t in a thread-safe manner. After retrieving a client from
1231       the pool, the client structure should be considered owned by the  call‐
1232       ing  thread.  When  the thread is finished, the client should be placed
1233       back into the pool.  example-pool.c.INDENT 0.0
1234
1235          /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs
1236           * libmongoc-1.0) */
1237
1238          /* ./example-pool [CONNECTION_STRING] */
1239
1240          #include <mongoc/mongoc.h>
1241          #include <pthread.h>
1242          #include <stdio.h>
1243
1244          static pthread_mutex_t mutex;
1245          static bool in_shutdown = false;
1246
1247          static void *
1248          worker (void *data)
1249          {
1250             mongoc_client_pool_t *pool = data;
1251             mongoc_client_t *client;
1252             bson_t ping = BSON_INITIALIZER;
1253             bson_error_t error;
1254             bool r;
1255
1256             BSON_APPEND_INT32 (&ping, "ping", 1);
1257
1258             while (true) {
1259                client = mongoc_client_pool_pop (pool);
1260                /* Do something with client. If you are writing an HTTP server, you
1261                 * probably only want to hold onto the client for the portion of the
1262                 * request performing database queries.
1263                 */
1264                r = mongoc_client_command_simple (
1265                   client, "admin", &ping, NULL, NULL, &error);
1266
1267                if (!r) {
1268                   fprintf (stderr, "%s\n", error.message);
1269                }
1270
1271                mongoc_client_pool_push (pool, client);
1272
1273                pthread_mutex_lock (&mutex);
1274                if (in_shutdown || !r) {
1275                   pthread_mutex_unlock (&mutex);
1276                   break;
1277                }
1278
1279                pthread_mutex_unlock (&mutex);
1280             }
1281
1282             bson_destroy (&ping);
1283             return NULL;
1284          }
1285
1286          int
1287          main (int argc, char *argv[])
1288          {
1289             const char *uri_string = "mongodb://127.0.0.1/?appname=pool-example";
1290             mongoc_uri_t *uri;
1291             bson_error_t error;
1292             mongoc_client_pool_t *pool;
1293             pthread_t threads[10];
1294             unsigned i;
1295             void *ret;
1296
1297             pthread_mutex_init (&mutex, NULL);
1298             mongoc_init ();
1299
1300             if (argc > 1) {
1301                uri_string = argv[1];
1302             }
1303
1304             uri = mongoc_uri_new_with_error (uri_string, &error);
1305             if (!uri) {
1306                fprintf (stderr,
1307                         "failed to parse URI: %s\n"
1308                         "error message:       %s\n",
1309                         uri_string,
1310                         error.message);
1311                return EXIT_FAILURE;
1312             }
1313
1314             pool = mongoc_client_pool_new (uri);
1315             mongoc_client_pool_set_error_api (pool, 2);
1316
1317             for (i = 0; i < 10; i++) {
1318                pthread_create (&threads[i], NULL, worker, pool);
1319             }
1320
1321             sleep (10);
1322             pthread_mutex_lock (&mutex);
1323             in_shutdown = true;
1324             pthread_mutex_unlock (&mutex);
1325
1326             for (i = 0; i < 10; i++) {
1327                pthread_join (threads[i], &ret);
1328             }
1329
1330             mongoc_client_pool_destroy (pool);
1331             mongoc_uri_destroy (uri);
1332
1333             mongoc_cleanup ();
1334
1335             return EXIT_SUCCESS;
1336          }
1337
1338
1339   Next Steps
1340       To find information on advanced topics, browse the rest of the C driver
1341       guide or the official MongoDB documentation.
1342
1343       For  help  with  common  issues,  consult  the Troubleshooting page. To
1344       report a bug or request a new feature, follow these instructions.
1345
1346   Authentication
1347       This guide covers the use of authentication options with the MongoDB  C
1348       Driver.  Ensure that the MongoDB server is also properly configured for
1349       authentication before making a connection. For  more  information,  see
1350       the MongoDB security documentation.
1351
1352       The MongoDB C driver supports several authentication mechanisms through
1353       the use of MongoDB connection URIs.
1354
1355       By default, if a username and password are provided as part of the con‐
1356       nection string (and an optional authentication database), they are used
1357       to connect via the default authentication mechanism of the server.
1358
1359       To select a specific authentication mechanism other than  the  default,
1360       see the list of supported mechanism below.
1361
1362          mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authSource=mydb");
1363
1364       Currently  supported  values  for  the  authMechanism connection string
1365       option are:
1366
1367       · SCRAM-SHA-1
1368
1369       · MONGODB-CR (deprecated)
1370
1371       · GSSAPI
1372
1373       · PLAIN
1374
1375       · X509
1376
1377   Basic Authentication (SCRAM-SHA-256)
1378       MongoDB 4.0 introduces support for authenticating using the SCRAM  pro‐
1379       tocol  with  the  more secure SHA-256 hash described in RFC 7677. Using
1380       this authentication mechanism means that the password is never actually
1381       sent  over  the  wire  when authenticating, but rather a computed proof
1382       that the client password is the same as the password the server  knows.
1383       In  MongoDB 4.0, the C driver can determine the correct default authen‐
1384       tication mechanism for users with stored SCRAM-SHA-1 and  SCRAM-SHA-256
1385       credentials:
1386
1387          mongoc_client_t *client =  mongoc_client_new ("mongodb://user:password@localhost/?authSource=mydb");
1388          /* the correct authMechanism is negotiated between the driver and server. */
1389
1390       Alternatively,  SCRAM-SHA-256  can  be explicitly specified as an auth‐
1391       Mechanism.
1392
1393          mongoc_client_t *client =  mongoc_client_new ("mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-256&authSource=mydb");
1394
1395       Passwords for SCRAM-SHA-256 undergo the  preprocessing  step  known  as
1396       SASLPrep  specified  in  RFC  4013. SASLPrep will only be performed for
1397       passwords containing non-ASCII characters.  SASLPrep  requires  libicu.
1398       If   libicu   is   not   available,  attempting  to  authenticate  over
1399       SCRAM-SHA-256 with non-ASCII passwords will result in error.
1400
1401       Usernames never undergo SASLPrep.
1402
1403       By default, when building the C driver libicu is linked  if  available.
1404       This  can  be  changed  with the ENABLE_ICU cmake option. To specify an
1405       installation path of libicu, specify ICU_ROOT as a  cmake  option.  See
1406       the FindICU documentation for more information.
1407
1408   Basic Authentication (SCRAM-SHA-1)
1409       The  default authentication mechanism before MongoDB 4.0 is SCRAM-SHA-1
1410       (RFC 5802). Using this authentication mechanism means that the password
1411       is  never actually sent over the wire when authenticating, but rather a
1412       computed proof that the client password is the same as the password the
1413       server knows.
1414
1415          mongoc_client_t *client = mongoc_client_new ("mongodb://user:password@localhost/?authMechanism=SCRAM-SHA-1&authSource=mydb");
1416
1417       NOTE:
1418          SCRAM-SHA-1  authenticates against the admin database by default. If
1419          the user is created in another database, then specifying  the  auth‐
1420          Source is required.
1421
1422   Legacy Authentication (MONGODB-CR)
1423       The  MONGODB-CR authMechanism is deprecated and will no longer function
1424       in MongoDB 4.0. Instead, specify no authMechanism and the  driver  will
1425       use an authentication mechanism compatible with your server.
1426
1427   GSSAPI (Kerberos) Authentication
1428       NOTE:
1429          Kerberos support requires compiling the driver against cyrus-sasl on
1430          UNIX-like environments. On Windows, configure the  driver  to  build
1431          against the Windows Native SSPI.
1432
1433       GSSAPI (Kerberos) authentication is available in the Enterprise Edition
1434       of MongoDB. To authenticate using GSSAPI, the MongoDB C driver must  be
1435       installed with SASL support.
1436
1437       On  UNIX-like environments, run the kinit command before using the fol‐
1438       lowing authentication methods:
1439
1440          $ kinit mongodbuser@EXAMPLE.COM
1441          mongodbuser@EXAMPLE.COM's Password:
1442          $ klistCredentials cache: FILE:/tmp/krb5cc_1000
1443                  Principal: mongodbuser@EXAMPLE.COM
1444
1445            Issued                Expires               Principal
1446          Feb  9 13:48:51 2013  Feb  9 23:48:51 2013  krbtgt/EXAMPLE.COM@EXAMPLE.COM
1447
1448       Now authenticate using the MongoDB URI.  GSSAPI  authenticates  against
1449       the $external virtual database, so a database does not need to be spec‐
1450       ified in the URI. Note that the Kerberos principal must be URL-encoded:
1451
1452          mongoc_client_t *client;
1453
1454          client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI");
1455
1456       NOTE:
1457          GSSAPI authenticates against the $external database,  so  specifying
1458          the authSource database is not required.
1459
1460       The driver supports these GSSAPI properties:
1461
1462       · CANONICALIZE_HOST_NAME:  This  might be required with Cyrus-SASL when
1463         the hosts report different hostnames than what is used  in  the  Ker‐
1464         beros database. The default is "false".
1465
1466       · SERVICE_NAME:  Use  a  different service name than the default, "mon‐
1467         godb".
1468
1469       Set properties in the URL:
1470
1471          mongoc_client_t *client;
1472
1473          client = mongoc_client_new ("mongodb://mongodbuser%40EXAMPLE.COM@mongo-server.example.com/?authMechanism=GSSAPI&"
1474                                      "authMechanismProperties=SERVICE_NAME:other,CANONICALIZE_HOST_NAME:true");
1475
1476       If you encounter errors such as  Invalid  net  address,  check  if  the
1477       application  is behind a NAT (Network Address Translation) firewall. If
1478       so, create a ticket that  uses  forwardable  and  addressless  Kerberos
1479       tickets. This can be done by passing -f -A to kinit.
1480
1481          $ kinit -f -A mongodbuser@EXAMPLE.COM
1482
1483   SASL Plain Authentication
1484       NOTE:
1485          The  MongoDB C Driver must be compiled with SASL support in order to
1486          use SASL PLAIN authentication.
1487
1488       MongoDB Enterprise Edition supports the SASL PLAIN authentication mech‐
1489       anism,  initially  intended  for  delegating  authentication to an LDAP
1490       server. Using the SASL PLAIN mechanism is very similar to the challenge
1491       response  mechanism  with  usernames and passwords. This authentication
1492       mechanism uses the $external virtual database for LDAP support:
1493
1494       NOTE:
1495          SASL PLAIN is a clear-text authentication mechanism. It is  strongly
1496          recommended to connect to MongoDB using SSL with certificate valida‐
1497          tion when using the PLAIN mechanism.
1498
1499          mongoc_client_t *client;
1500
1501          client = mongoc_client_new ("mongodb://user:password@example.com/?authMechanism=PLAIN");
1502
1503       PLAIN authenticates against the $external database, so  specifying  the
1504       authSource database is not required.
1505
1506   X.509 Certificate Authentication
1507       NOTE:
1508          The  MongoDB  C  Driver  must be compiled with SSL support for X.509
1509          authentication support. Once this is done, start a server  with  the
1510          following options:
1511
1512              $ mongod --sslMode requireSSL --sslPEMKeyFile server.pem --sslCAFile ca.pem
1513
1514       The  MONGODB-X509  mechanism  authenticates a username derived from the
1515       distinguished subject name of the X.509 certificate  presented  by  the
1516       driver  during SSL negotiation. This authentication method requires the
1517       use of SSL connections with certificate validation.
1518
1519          mongoc_client_t *client;
1520          mongoc_ssl_opt_t ssl_opts = { 0 };
1521
1522          ssl_opts.pem_file = "mycert.pem";
1523          ssl_opts.pem_pwd = "mycertpassword";
1524          ssl_opts.ca_file = "myca.pem";
1525          ssl_opts.ca_dir = "trust_dir";
1526          ssl_opts.weak_cert_validation = false;
1527
1528          client = mongoc_client_new ("mongodb://x509_derived_username@localhost/?authMechanism=MONGODB-X509");
1529          mongoc_client_set_ssl_opts (client, &ssl_opts);
1530
1531       MONGODB-X509 authenticates against the $external database, so  specify‐
1532       ing  the  authSource  database is not required. For more information on
1533       the x509_derived_username, see the MongoDB server x.509 tutorial.
1534
1535       NOTE:
1536          The MongoDB C Driver will attempt  to  determine  the  x509  derived
1537          username  when none is provided, and as of MongoDB 3.4 providing the
1538          username is not required at all.
1539
1540   Basic Troubleshooting
1541   Troubleshooting Checklist
1542       The following is a short list of things to check when you have a  prob‐
1543       lem.
1544
1545       · Did  you  call mongoc_init() in main()? If not, you will likely see a
1546         segfault.
1547
1548       · Have you leaked any clients or cursors as  can  be  found  with  mon‐
1549         goc-stat <PID>?
1550
1551       · Have packets been delivered to the server? See egress bytes from mon‐
1552         goc-stat <PID>.
1553
1554       · Does valgrind show any leaks? Ensure you call mongoc_cleanup() at the
1555         end of your process to cleanup lingering allocations from the MongoDB
1556         C driver.
1557
1558       · If compiling your own copy of MongoDB C Driver,  consider  using  the
1559         cmake  option  -DENABLE_TRACING=ON to enable function tracing and hex
1560         dumps of network packets to STDERR and STDOUT.
1561
1562   Performance Counters
1563       The MongoDB C driver comes with an  optional  unique  feature  to  help
1564       developers  and sysadmins troubleshoot problems in production.  Perfor‐
1565       mance counters are available for each process  using  the  driver.   If
1566       available,  the  counters  can  be  accessed outside of the application
1567       process via a shared memory segment.  This means  that  you  can  graph
1568       statistics  about your application process easily from tools like Munin
1569       or Nagios.  Your author often uses watch --interval=0.5 -d  mongoc-stat
1570       $PID to monitor an application.
1571
1572       Performance  counters  are only available on Linux platforms supporting
1573       shared memory segments.  On supported platforms  they  are  enabled  by
1574       default.   Applications can be built without the counters by specifying
1575       the cmake option -DENABLE_SHM_COUNTERS=OFF.  Additionally,  if  perfor‐
1576       mance counters are already compiled, they can be disabled at runtime by
1577       specifying the environment variable MONGOC_DISABLE_SHM.
1578
1579       Performance counters keep track of the following:
1580
1581       · Active and Disposed Cursors
1582
1583       · Active and Disposed Clients, Client Pools, and Socket Streams.
1584
1585       · Number of operations sent and received, by type.
1586
1587       · Bytes transferred and received.
1588
1589       · Authentication successes and failures.
1590
1591       · Number of wire protocol errors.
1592
1593       To access counters for a given process, simply provide the  process  id
1594       to the mongoc-stat program installed with the MongoDB C Driver.
1595
1596          $ mongoc-stat 22203
1597             Operations : Egress Total        : The number of sent operations.                    : 13247
1598             Operations : Ingress Total       : The number of received operations.                : 13246
1599             Operations : Egress Queries      : The number of sent Query operations.              : 13247
1600             Operations : Ingress Queries     : The number of received Query operations.          : 0
1601             Operations : Egress GetMore      : The number of sent GetMore operations.            : 0
1602             Operations : Ingress GetMore     : The number of received GetMore operations.        : 0
1603             Operations : Egress Insert       : The number of sent Insert operations.             : 0
1604             Operations : Ingress Insert      : The number of received Insert operations.         : 0
1605             Operations : Egress Delete       : The number of sent Delete operations.             : 0
1606             Operations : Ingress Delete      : The number of received Delete operations.         : 0
1607             Operations : Egress Update       : The number of sent Update operations.             : 0
1608             Operations : Ingress Update      : The number of received Update operations.         : 0
1609             Operations : Egress KillCursors  : The number of sent KillCursors operations.        : 0
1610             Operations : Ingress KillCursors : The number of received KillCursors operations.    : 0
1611             Operations : Egress Msg          : The number of sent Msg operations.                : 0
1612             Operations : Ingress Msg         : The number of received Msg operations.            : 0
1613             Operations : Egress Reply        : The number of sent Reply operations.              : 0
1614             Operations : Ingress Reply       : The number of received Reply operations.          : 13246
1615                Cursors : Active              : The number of active cursors.                     : 1
1616                Cursors : Disposed            : The number of disposed cursors.                   : 13246
1617                Clients : Active              : The number of active clients.                     : 1
1618                Clients : Disposed            : The number of disposed clients.                   : 0
1619                Streams : Active              : The number of active streams.                     : 1
1620                Streams : Disposed            : The number of disposed streams.                   : 0
1621                Streams : Egress Bytes        : The number of bytes sent.                         : 794931
1622                Streams : Ingress Bytes       : The number of bytes received.                     : 589694
1623                Streams : N Socket Timeouts   : The number of socket timeouts.                    : 0
1624           Client Pools : Active              : The number of active client pools.                : 1
1625           Client Pools : Disposed            : The number of disposed client pools.              : 0
1626               Protocol : Ingress Errors      : The number of protocol errors on ingress.         : 0
1627                   Auth : Failures            : The number of failed authentication requests.     : 0
1628                   Auth : Success             : The number of successful authentication requests. : 0
1629
1630   Submitting a Bug Report
1631       Think  you've  found  a bug? Want to see a new feature in the MongoDB C
1632       driver? Please open a case in our issue management tool, JIRA:
1633
1634       · Create an account and login.
1635
1636       · Navigate to the CDRIVER project.
1637
1638       · Click Create Issue - Please provide as much information  as  possible
1639         about the issue type and how to reproduce it.
1640
1641       Bug  reports  in  JIRA  for  all driver projects (i.e. CDRIVER, CSHARP,
1642       JAVA) and the Core Server (i.e. SERVER) project are public.
1643
1644   Guides
1645   Common Tasks
1646       Drivers for some other languages provide helper  functions  to  perform
1647       certain common tasks. In the C Driver we must explicitly build commands
1648       to send to the server.
1649
1650   Setup
1651       First  we'll  write  some  code  to  insert   sample   data:   doc-com‐
1652       mon-insert.c.INDENT 0.0
1653
1654          /* Don't try to compile this file on its own. It's meant to be #included
1655             by example code */
1656
1657          /* Insert some sample data */
1658          bool
1659          insert_data (mongoc_collection_t *collection)
1660          {
1661             mongoc_bulk_operation_t *bulk;
1662             enum N { ndocs = 4 };
1663             bson_t *docs[ndocs];
1664             bson_error_t error;
1665             int i = 0;
1666             bool ret;
1667
1668             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
1669
1670             docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
1671             docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
1672             docs[2] = BCON_NEW (
1673                "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
1674             docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
1675
1676             for (i = 0; i < ndocs; i++) {
1677                mongoc_bulk_operation_insert (bulk, docs[i]);
1678                bson_destroy (docs[i]);
1679                docs[i] = NULL;
1680             }
1681
1682             ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
1683
1684             if (!ret) {
1685                fprintf (stderr, "Error inserting data: %s\n", error.message);
1686             }
1687
1688             mongoc_bulk_operation_destroy (bulk);
1689             return ret;
1690          }
1691
1692          /* A helper which we'll use a lot later on */
1693          void
1694          print_res (const bson_t *reply)
1695          {
1696             char *str;
1697             BSON_ASSERT (reply);
1698             str = bson_as_canonical_extended_json (reply, NULL);
1699             printf ("%s\n", str);
1700             bson_free (str);
1701          }
1702
1703
1704   explain Command
1705       This   is   how   to   use   the   explain  command  in  MongoDB  3.2+:
1706       explain.c.INDENT 0.0
1707
1708          bool
1709          explain (mongoc_collection_t *collection)
1710          {
1711             bson_t *command;
1712             bson_t reply;
1713             bson_error_t error;
1714             bool res;
1715
1716             command = BCON_NEW ("explain",
1717                                 "{",
1718                                 "find",
1719                                 BCON_UTF8 (COLLECTION_NAME),
1720                                 "filter",
1721                                 "{",
1722                                 "x",
1723                                 BCON_INT32 (1),
1724                                 "}",
1725                                 "}");
1726             res = mongoc_collection_command_simple (
1727                collection, command, NULL, &reply, &error);
1728             if (!res) {
1729                fprintf (stderr, "Error with explain: %s\n", error.message);
1730                goto cleanup;
1731             }
1732
1733             /* Do something with the reply */
1734             print_res (&reply);
1735
1736          cleanup:
1737             bson_destroy (&reply);
1738             bson_destroy (command);
1739             return res;
1740          }
1741
1742
1743   Running the Examples
1744       common-operations.c.INDENT 0.0
1745
1746          /*
1747           * Copyright 2016 MongoDB, Inc.
1748           *
1749           * Licensed under the Apache License, Version 2.0 (the "License");
1750           * you may not use this file except in compliance with the License.
1751           * You may obtain a copy of the License at
1752           *
1753           *   http://www.apache.org/licenses/LICENSE-2.0
1754           *
1755           * Unless required by applicable law or agreed to in writing, software
1756           * distributed under the License is distributed on an "AS IS" BASIS,
1757           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1758           * See the License for the specific language governing permissions and
1759           * limitations under the License.
1760           */
1761
1762
1763          #include <mongoc/mongoc.h>
1764          #include <stdio.h>
1765
1766
1767          const char *COLLECTION_NAME = "things";
1768
1769          #include "../doc-common-insert.c"
1770          #include "explain.c"
1771
1772
1773          int
1774          main (int argc, char *argv[])
1775          {
1776             mongoc_database_t *database = NULL;
1777             mongoc_client_t *client = NULL;
1778             mongoc_collection_t *collection = NULL;
1779             mongoc_uri_t *uri = NULL;
1780             bson_error_t error;
1781             char *host_and_port;
1782             int res = 0;
1783
1784             if (argc < 2 || argc > 3) {
1785                fprintf (stderr,
1786                         "usage: %s MONGOD-1-CONNECTION-STRING "
1787                         "[MONGOD-2-HOST-NAME:MONGOD-2-PORT]\n",
1788                         argv[0]);
1789                fprintf (stderr,
1790                         "MONGOD-1-CONNECTION-STRING can be "
1791                         "of the following forms:\n");
1792                fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
1793                fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
1794                fprintf (stderr,
1795                         "mongodb://user:pass@localhost:27017\t"
1796                         "local machine on port 27017, and authenticate with username "
1797                         "user and password pass\n");
1798                return EXIT_FAILURE;
1799             }
1800
1801             mongoc_init ();
1802
1803             if (strncmp (argv[1], "mongodb://", 10) == 0) {
1804                host_and_port = bson_strdup (argv[1]);
1805             } else {
1806                host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
1807             }
1808
1809             uri = mongoc_uri_new_with_error (host_and_port, &error);
1810             if (!uri) {
1811                fprintf (stderr,
1812                         "failed to parse URI: %s\n"
1813                         "error message:       %s\n",
1814                         host_and_port,
1815                         error.message);
1816                res = EXIT_FAILURE;
1817                goto cleanup;
1818             }
1819
1820             client = mongoc_client_new_from_uri (uri);
1821             if (!client) {
1822                res = EXIT_FAILURE;
1823                goto cleanup;
1824             }
1825
1826             mongoc_client_set_error_api (client, 2);
1827             database = mongoc_client_get_database (client, "test");
1828             collection = mongoc_database_get_collection (database, COLLECTION_NAME);
1829
1830             printf ("Inserting data\n");
1831             if (!insert_data (collection)) {
1832                res = EXIT_FAILURE;
1833                goto cleanup;
1834             }
1835
1836             printf ("explain\n");
1837             if (!explain (collection)) {
1838                res = EXIT_FAILURE;
1839                goto cleanup;
1840             }
1841
1842          cleanup:
1843             if (collection) {
1844                mongoc_collection_destroy (collection);
1845             }
1846
1847             if (database) {
1848                mongoc_database_destroy (database);
1849             }
1850
1851             if (client) {
1852                mongoc_client_destroy (client);
1853             }
1854
1855             if (uri) {
1856                mongoc_uri_destroy (uri);
1857             }
1858
1859             bson_free (host_and_port);
1860             mongoc_cleanup ();
1861             return res;
1862          }
1863
1864
1865First launch two separate instances of mongod  (must  be  done  from  separate
1866shells):
1867
1868          $ mongod
1869
1870          $ mkdir /tmp/db2
1871          $ mongod --dbpath /tmp/db2 --port 27018 # second instance
1872
1873       Now compile and run the example program:
1874
1875          $ cd examples/common_operations/$ gcc -Wall -o example common-operations.c $(pkg-config --cflags --libs libmongoc-1.0)$ ./example localhost:27017 localhost:27018
1876          Inserting data
1877          explain
1878          {
1879             "executionStats" : {
1880                "allPlansExecution" : [],
1881                "executionStages" : {
1882                   "advanced" : 19,
1883                   "direction" : "forward" ,
1884                   "docsExamined" : 76,
1885                   "executionTimeMillisEstimate" : 0,
1886                   "filter" : {
1887                      "x" : {
1888                         "$eq" : 1
1889                      }
1890                   },
1891                   "invalidates" : 0,
1892                   "isEOF" : 1,
1893                   "nReturned" : 19,
1894                   "needTime" : 58,
1895                   "needYield" : 0,
1896                   "restoreState" : 0,
1897                   "saveState" : 0,
1898                   "stage" : "COLLSCAN" ,
1899                   "works" : 78
1900                },
1901                "executionSuccess" : true,
1902                "executionTimeMillis" : 0,
1903                "nReturned" : 19,
1904                "totalDocsExamined" : 76,
1905                "totalKeysExamined" : 0
1906             },
1907             "ok" : 1,
1908             "queryPlanner" : {
1909                "indexFilterSet" : false,
1910                "namespace" : "test.things",
1911                "parsedQuery" : {
1912                   "x" : {
1913                      "$eq" : 1
1914                   }
1915                },
1916                "plannerVersion" : 1,
1917                "rejectedPlans" : [],
1918                "winningPlan" : {
1919                   "direction" : "forward" ,
1920                   "filter" : {
1921                      "x" : {
1922                         "$eq" : 1
1923                      }
1924                   },
1925                   "stage" : "COLLSCAN"
1926                }
1927             },
1928             "serverInfo" : {
1929                "gitVersion" : "05552b562c7a0b3143a729aaa0838e558dc49b25" ,
1930                "host" : "MacBook-Pro-57.local",
1931                "port" : 27017,
1932                "version" : "3.2.6"
1933             }
1934          }
1935
1936   Advanced Connections
1937       The  following  guide contains information specific to certain types of
1938       MongoDB configurations.
1939
1940       For an example of connecting to a simple  standalone  server,  see  the
1941       Tutorial.   To  establish  a  connection  with  authentication  options
1942       enabled, see the Authentication page.
1943
1944   Connecting to a Replica Set
1945       Connecting to a replica set is much like  connecting  to  a  standalone
1946       MongoDB  server.  Simply specify the replica set name using the ?repli‐
1947       caSet=myreplset URI option.
1948
1949          #include <bson/bson.h>
1950          #include <mongoc/mongoc.h>
1951
1952          int
1953          main (int argc, char *argv[])
1954          {
1955             mongoc_client_t *client;
1956
1957             mongoc_init ();
1958
1959             /* Create our MongoDB Client */
1960             client = mongoc_client_new (
1961                "mongodb://host01:27017,host02:27017,host03:27017/?replicaSet=myreplset");
1962
1963             /* Do some work */
1964             /* TODO */
1965
1966             /* Clean up */
1967             mongoc_client_destroy (client);
1968             mongoc_cleanup ();
1969
1970             return 0;
1971          }
1972
1973       TIP:
1974          Multiple hostnames can be specified in the MongoDB connection string
1975          URI, with a comma separating hosts in the seed list.
1976
1977          It  is  recommended to use a seed list of members of the replica set
1978          to allow the driver to connect to any node.
1979
1980   Connecting to a Sharded Cluster
1981       To connect to a sharded cluster, specify the mongos  nodes  the  client
1982       should  connect  to. The C Driver will automatically detect that it has
1983       connected to a mongos sharding server.
1984
1985       If more than one hostname is specified, a seed list will be created  to
1986       attempt failover between the mongos instances.
1987
1988       WARNING:
1989          Specifying  the  replicaSet  parameter  when  connecting to a mongos
1990          sharding server is invalid.
1991
1992          #include <bson/bson.h>
1993          #include <mongoc/mongoc.h>
1994
1995          int
1996          main (int argc, char *argv[])
1997          {
1998             mongoc_client_t *client;
1999
2000             mongoc_init ();
2001
2002             /* Create our MongoDB Client */
2003             client = mongoc_client_new ("mongodb://myshard01:27017/");
2004
2005             /* Do something with client ... */
2006
2007             /* Free the client */
2008             mongoc_client_destroy (client);
2009
2010             mongoc_cleanup ();
2011
2012             return 0;
2013          }
2014
2015   Connecting to an IPv6 Address
2016       The MongoDB C Driver will automatically  resolve  IPv6  addresses  from
2017       host  names.  However,  to  specify  an IPv6 address directly, wrap the
2018       address in [].
2019
2020          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://[::1]:27017");
2021
2022   Connecting with IPv4 and IPv6
2023       If connecting to a hostname that has both IPv4 and  IPv6  DNS  records,
2024       the  behavior  follows  RFC-6555.  A  connection to the IPv6 address is
2025       attempted first. If IPv6 fails, then a connection is attempted  to  the
2026       IPv4  address.  If  the  connection  attempt  to IPv6 does not complete
2027       within 250ms, then IPv4 is tried in parallel. Whichever  succeeds  con‐
2028       nection  first  cancels  the other. The successful DNS result is cached
2029       for 10 minutes.
2030
2031       As a consequence, attempts to connect to a  mongod  only  listening  on
2032       IPv4  may  be  delayed  if  there are both A (IPv4) and AAAA (IPv6) DNS
2033       records associated with the host.
2034
2035       To avoid a delay, configure hostnames to match the  MongoDB  configura‐
2036       tion.  That is, only create an A record if the mongod is only listening
2037       on IPv4.
2038
2039   Connecting to a UNIX Domain Socket
2040       On UNIX-like systems, the C Driver can connect directly  to  a  MongoDB
2041       server  using  a  UNIX  domain socket. Pass the URL-encoded path to the
2042       socket, which must be suffixed with .sock. For example, to connect to a
2043       domain socket at /tmp/mongodb-27017.sock:
2044
2045          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://%2Ftmp%2Fmongodb-27017.sock");
2046
2047       Include username and password like so:
2048
2049          mongoc_uri_t *uri = mongoc_uri_new ("mongodb://user:pass@%2Ftmp%2Fmongodb-27017.sock");
2050
2051   Connecting to a server over SSL
2052       These are instructions for configuring TLS/SSL connections.
2053
2054       To run a server locally (on port 27017, for example):
2055
2056          $ mongod --port 27017 --sslMode requireSSL --sslPEMKeyFile server.pem --sslCAFile ca.pem
2057
2058       Add /?ssl=true to the end of a client URI.
2059
2060          mongoc_client_t *client = NULL;
2061          client = mongoc_client_new ("mongodb://localhost:27017/?ssl=true");
2062
2063       MongoDB requires client certificates by default, unless the --sslAllow‐
2064       ConnectionsWithoutCertificates is provided. The C Driver can be config‐
2065       ured to present a client certificate using a mongoc_ssl_opt_t:
2066
2067          const mongoc_ssl_opt_t *ssl_default = mongoc_ssl_opt_get_default ();
2068          mongoc_ssl_opt_t ssl_opts = { 0 };
2069
2070          /* optionally copy in a custom trust directory or file; otherwise the default is used. */
2071          memcpy (&ssl_opts, ssl_default, sizeof ssl_opts);
2072          ssl_opts.pem_file = "client.pem"
2073
2074          mongoc_client_set_ssl_opts (client, &ssl_opts);
2075
2076       The  client  certificate  provided by pem_file must be issued by one of
2077       the server trusted Certificate Authorities listed  in  --sslCAFile,  or
2078       issued by a CA in the native certificate store on the server when omit‐
2079       ted.
2080
2081       To verify the server certificate against a specific CA, provide  a  PEM
2082       armored file with a CA certificate, or concatenated list of CA certifi‐
2083       cates using the ca_file option, or c_rehash directory structure of CAs,
2084       pointed  to  using the ca_dir option. When no ca_file or ca_dir is pro‐
2085       vided, the driver will use CAs provided by the native platform certifi‐
2086       cate store.
2087
2088       See  mongoc_ssl_opt_t  for  more information on the various SSL related
2089       options.
2090
2091   Compressing data to and from MongoDB
2092       MongoDB 3.4 added Snappy compression support, zlib compression in  3.6,
2093       and  zstd compression in 4.2.  To enable compression support the client
2094       must be configured with which compressors to use:
2095
2096          mongoc_client_t *client = NULL;
2097          client = mongoc_client_new ("mongodb://localhost:27017/?compressors=snappy,zlib,zstd");
2098
2099       The compressors option specifies the priority order of compressors  the
2100       client  wants  to use. Messages are compressed if the client and server
2101       share any compressors in common.
2102
2103       Note that the compressor used by the server might not be the same  com‐
2104       pressor  as  the client used.  For example, if the client uses the con‐
2105       nection string compressors=zlib,snappy the client will  use  zlib  com‐
2106       pression  to  send data (if possible), but the server might still reply
2107       using snappy, depending on how the server was configured.
2108
2109       The driver must be built with zlib and/or snappy and/or zstd support to
2110       enable compression support, any unknown (or not compiled in) compressor
2111       value will be ignored. Note: to build with zstd requires cmake 3.12  or
2112       higher.
2113
2114   Additional Connection Options
2115       The  full  list  of connection options can be found in the mongoc_uri_t
2116       docs.
2117
2118       Certain socket/connection related options are not configurable:
2119
2120             ┌──────────────┬─────────────────────┬─────────────────────┐
2121             │Option        │ Description         │ Value               │
2122             ├──────────────┼─────────────────────┼─────────────────────┤
2123             │SO_KEEPALIVE  │ TCP Keep Alive      │ Enabled             │
2124             └──────────────┴─────────────────────┴─────────────────────┘
2125
2126
2127
2128
2129             │TCP_KEEPIDLE  │ How long a  connec‐ │ 300 seconds         │
2130             │              │ tion    needs    to │                     │
2131             │              │ remain idle  before │                     │
2132             │              │ TCP  starts sending │                     │
2133             │              │ keepalive probes    │                     │
2134             ├──────────────┼─────────────────────┼─────────────────────┤
2135             │TCP_KEEPINTVL │ The time in seconds │ 10 seconds          │
2136             │              │ between TCP probes  │                     │
2137             ├──────────────┼─────────────────────┼─────────────────────┤
2138             │TCP_KEEPCNT   │ How  many probes to │ 9 probes            │
2139             │              │ send,       without │                     │
2140             │              │ acknowledgement,    │                     │
2141             │              │ before dropping the │                     │
2142             │              │ connection          │                     │
2143             ├──────────────┼─────────────────────┼─────────────────────┤
2144             │TCP_NODELAY   │ Send   packets   as │ Enabled (no buffer‐ │
2145             │              │ soon as possible or │ ing)                │
2146             │              │ buffer  small pack‐ │                     │
2147             │              │ ets  (Nagle   algo‐ │                     │
2148             │              │ rithm)              │                     │
2149             └──────────────┴─────────────────────┴─────────────────────┘
2150
2151   Connection Pooling
2152       The MongoDB C driver has  two  connection  modes:  single-threaded  and
2153       pooled.  Single-threaded  mode  is  optimized  for embedding the driver
2154       within languages like PHP. Multi-threaded programs  should  use  pooled
2155       mode:  this  mode  minimizes  the total connection count, and in pooled
2156       mode a background thread monitors the MongoDB server topology,  so  the
2157       program need not block to scan it.
2158
2159   Single Mode
2160       In single mode, your program creates a mongoc_client_t directly:
2161
2162          mongoc_client_t *client = mongoc_client_new (
2163             "mongodb://hostA,hostB/?replicaSet=my_rs");
2164
2165       The  client  connects  on  demand when your program first uses it for a
2166       MongoDB operation. Using a non-blocking socket per server, it begins  a
2167       check  on  each  server concurrently, and uses the asynchronous poll or
2168       select function to receive events from  the  sockets,  until  all  have
2169       responded  or timed out. Put another way, in single-threaded mode the C
2170       Driver fans out to begin all checks concurrently, then fans in once all
2171       checks have completed or timed out. Once the scan completes, the client
2172       executes your program's operation and returns.
2173
2174       In single mode, the client re-scans the server  topology  roughly  once
2175       per  minute. If more than a minute has elapsed since the previous scan,
2176       the next operation on the client will block while the client  completes
2177       its  scan.  This  interval is configurable with heartbeatFrequencyMS in
2178       the connection string. (See mongoc_uri_t.)
2179
2180       A single client opens one connection per server in your topology: these
2181       connections are used both for scanning the topology and performing nor‐
2182       mal operations.
2183
2184   Pooled Mode
2185       To activate pooled mode, create a mongoc_client_pool_t:
2186
2187          mongoc_uri_t *uri = mongoc_uri_new (
2188             "mongodb://hostA,hostB/?replicaSet=my_rs");
2189
2190          mongoc_client_pool_t *pool = mongoc_client_pool_new (uri);
2191
2192       When your program first calls mongoc_client_pool_pop, the pool launches
2193       a background thread for monitoring. The thread fans out and connects to
2194       all servers in the connection string, using non-blocking sockets and  a
2195       simple  event loop. As it receives ismaster responses from the servers,
2196       it updates its view of the server topology. Each time the  thread  dis‐
2197       covers a new server it begins connecting to it, and adds the new socket
2198       to the list of non-blocking sockets in the event loop.
2199
2200       Each thread that executes MongoDB operations must check  out  a  client
2201       from the pool:
2202
2203          mongoc_client_t *client = mongoc_client_pool_pop (pool);
2204
2205          /* use the client for operations ... */
2206
2207          mongoc_client_pool_push (pool, client);
2208
2209       The   mongoc_client_t   object   is  not  thread-safe,  only  the  mon‐
2210       goc_client_pool_t is.
2211
2212       When the driver is  in  pooled  mode,  your  program's  operations  are
2213       unblocked as soon as monitoring discovers a usable server. For example,
2214       if a thread in your program is waiting to execute an  "insert"  on  the
2215       primary,  it  is unblocked as soon as the primary is discovered, rather
2216       than waiting for all secondaries to be checked as well.
2217
2218       The pool opens one connection  per  server  for  monitoring,  and  each
2219       client  opens its own connection to each server it uses for application
2220       operations. The background thread re-scans the server topology  roughly
2221       every  10 seconds. This interval is configurable with heartbeatFrequen‐
2222       cyMS in the connection string. (See mongoc_uri_t.)
2223
2224       See connection_pool_options to configure pool size  and  behavior,  and
2225       see  mongoc_client_pool_t  for  an extended example of a multi-threaded
2226       program that uses the driver in pooled mode.
2227
2228   Cursors
2229   Handling Cursor Failures
2230       Cursors exist on a MongoDB server. However, the mongoc_cursor_t  struc‐
2231       ture gives the local process a handle to the cursor. It is possible for
2232       errors to occur on the server while iterating a cursor on  the  client.
2233       Even a network partition may occur. This means that applications should
2234       be robust in handling cursor failures.
2235
2236       While iterating cursors, you should  check  to  see  if  an  error  has
2237       occurred.  See  the  following  example  for  how to robustly check for
2238       errors.
2239
2240          static void
2241          print_all_documents (mongoc_collection_t *collection)
2242          {
2243             mongoc_cursor_t *cursor;
2244             const bson_t *doc;
2245             bson_error_t error;
2246             bson_t query = BSON_INITIALIZER;
2247             char *str;
2248
2249             cursor = mongoc_collection_find_with_opts (collection, query, NULL, NULL);
2250
2251             while (mongoc_cursor_next (cursor, &doc)) {
2252                str = bson_as_canonical_extended_json (doc, NULL);
2253                printf ("%s\n", str);
2254                bson_free (str);
2255             }
2256
2257             if (mongoc_cursor_error (cursor, &error)) {
2258                fprintf (stderr, "Failed to iterate all documents: %s\n", error.message);
2259             }
2260
2261             mongoc_cursor_destroy (cursor);
2262          }
2263
2264   Destroying Server-Side Cursors
2265       The MongoDB C driver will automatically destroy  a  server-side  cursor
2266       when  mongoc_cursor_destroy()  is called. Failure to call this function
2267       when done with a cursor will leak memory client side as well as consume
2268       extra  memory  server side. If the cursor was configured to never time‐
2269       out, it will become a memory leak on the server.
2270
2271   Tailable Cursors
2272       Tailable cursors are  cursors  that  remain  open  even  after  they've
2273       returned  a  final  result.  This way, if more documents are added to a
2274       collection (i.e., to the cursor's result set), then you can continue to
2275       call mongoc_cursor_next() to retrieve those additional results.
2276
2277       Here's  a complete test case that demonstrates the use of tailable cur‐
2278       sors.
2279
2280       NOTE:
2281          Tailable cursors are for capped collections only.
2282
2283       An example to tail the oplog from a replica set.   mongoc-tail.c.INDENT
2284       0.0
2285
2286          #include <bson/bson.h>
2287          #include <mongoc/mongoc.h>
2288          #include <stdio.h>
2289          #include <stdlib.h>
2290
2291          #ifdef _WIN32
2292          #define sleep(_n) Sleep ((_n) *1000)
2293          #endif
2294
2295
2296          static void
2297          print_bson (const bson_t *b)
2298          {
2299             char *str;
2300
2301             str = bson_as_canonical_extended_json (b, NULL);
2302             fprintf (stdout, "%s\n", str);
2303             bson_free (str);
2304          }
2305
2306
2307          static mongoc_cursor_t *
2308          query_collection (mongoc_collection_t *collection, uint32_t last_time)
2309          {
2310             mongoc_cursor_t *cursor;
2311             bson_t query;
2312             bson_t gt;
2313             bson_t opts;
2314
2315             BSON_ASSERT (collection);
2316
2317             bson_init (&query);
2318             BSON_APPEND_DOCUMENT_BEGIN (&query, "ts", &gt);
2319             BSON_APPEND_TIMESTAMP (&gt, "$gt", last_time, 0);
2320             bson_append_document_end (&query, &gt);
2321
2322             bson_init (&opts);
2323             BSON_APPEND_BOOL (&opts, "tailable", true);
2324             BSON_APPEND_BOOL (&opts, "awaitData", true);
2325
2326             cursor = mongoc_collection_find_with_opts (collection, &query, &opts, NULL);
2327
2328             bson_destroy (&query);
2329             bson_destroy (&opts);
2330
2331             return cursor;
2332          }
2333
2334
2335          static void
2336          tail_collection (mongoc_collection_t *collection)
2337          {
2338             mongoc_cursor_t *cursor;
2339             uint32_t last_time;
2340             const bson_t *doc;
2341             bson_error_t error;
2342             bson_iter_t iter;
2343
2344             BSON_ASSERT (collection);
2345
2346             last_time = (uint32_t) time (NULL);
2347
2348             while (true) {
2349                cursor = query_collection (collection, last_time);
2350                while (!mongoc_cursor_error (cursor, &error) &&
2351                       mongoc_cursor_more (cursor)) {
2352                   if (mongoc_cursor_next (cursor, &doc)) {
2353                      if (bson_iter_init_find (&iter, doc, "ts") &&
2354                          BSON_ITER_HOLDS_TIMESTAMP (&iter)) {
2355                         bson_iter_timestamp (&iter, &last_time, NULL);
2356                      }
2357                      print_bson (doc);
2358                   }
2359                }
2360                if (mongoc_cursor_error (cursor, &error)) {
2361                   if (error.domain == MONGOC_ERROR_SERVER) {
2362                      fprintf (stderr, "%s\n", error.message);
2363                      exit (1);
2364                   }
2365                }
2366
2367                mongoc_cursor_destroy (cursor);
2368                sleep (1);
2369             }
2370          }
2371
2372
2373          int
2374          main (int argc, char *argv[])
2375          {
2376             mongoc_collection_t *collection;
2377             mongoc_client_t *client;
2378             mongoc_uri_t *uri;
2379             bson_error_t error;
2380
2381             if (argc != 2) {
2382                fprintf (stderr, "usage: %s MONGO_URI\n", argv[0]);
2383                return EXIT_FAILURE;
2384             }
2385
2386             mongoc_init ();
2387
2388             uri = mongoc_uri_new_with_error (argv[1], &error);
2389             if (!uri) {
2390                fprintf (stderr,
2391                         "failed to parse URI: %s\n"
2392                         "error message:       %s\n",
2393                         argv[1],
2394                         error.message);
2395                return EXIT_FAILURE;
2396             }
2397
2398             client = mongoc_client_new_from_uri (uri);
2399             if (!client) {
2400                return EXIT_FAILURE;
2401             }
2402
2403             mongoc_client_set_error_api (client, 2);
2404
2405             collection = mongoc_client_get_collection (client, "local", "oplog.rs");
2406
2407             tail_collection (collection);
2408
2409             mongoc_collection_destroy (collection);
2410             mongoc_uri_destroy (uri);
2411             mongoc_client_destroy (client);
2412
2413             return EXIT_SUCCESS;
2414          }
2415
2416
2417Let's  compile  and  run  this example against a replica set to see updates as
2418they are made.
2419
2420          $ gcc -Wall -o mongoc-tail mongoc-tail.c $(pkg-config --cflags --libs libmongoc-1.0)
2421          $ ./mongoc-tail mongodb://example.com/?replicaSet=myReplSet
2422          {
2423              "h" : -8458503739429355503,
2424              "ns" : "test.test",
2425              "o" : {
2426                  "_id" : {
2427                      "$oid" : "5372ab0a25164be923d10d50"
2428                  }
2429              },
2430              "op" : "i",
2431              "ts" : {
2432                  "$timestamp" : {
2433                      "i" : 1,
2434                      "t" : 1400023818
2435                  }
2436              },
2437              "v" : 2
2438          }
2439
2440       The line of output is a sample from performing db.test.insert({})  from
2441       the mongo shell on the replica set.
2442
2443       See also mongoc_cursor_set_max_await_time_ms.
2444
2445   Bulk Write Operations
2446       This  tutorial  explains how to take advantage of MongoDB C driver bulk
2447       write operation features. Executing write operations in batches reduces
2448       the number of network round trips, increasing write throughput.
2449
2450   Bulk Insert
2451       First  we need to fetch a bulk operation handle from the mongoc_collec‐
2452       tion_t.
2453
2454          mongoc_bulk_operation_t *bulk =
2455             mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2456
2457       We can now start inserting documents to the bulk operation. These  will
2458       be buffered until we execute the operation.
2459
2460       The  bulk operation will coalesce insertions as a single batch for each
2461       consecutive call  to  mongoc_bulk_operation_insert().  This  creates  a
2462       pipelined effect when possible.
2463
2464       To  execute  the  bulk  operation  and  receive the result we call mon‐
2465       goc_bulk_operation_execute().  bulk1.c.INDENT 0.0
2466
2467          #include <assert.h>
2468          #include <mongoc/mongoc.h>
2469          #include <stdio.h>
2470
2471          static void
2472          bulk1 (mongoc_collection_t *collection)
2473          {
2474             mongoc_bulk_operation_t *bulk;
2475             bson_error_t error;
2476             bson_t *doc;
2477             bson_t reply;
2478             char *str;
2479             bool ret;
2480             int i;
2481
2482             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2483
2484             for (i = 0; i < 10000; i++) {
2485                doc = BCON_NEW ("i", BCON_INT32 (i));
2486                mongoc_bulk_operation_insert (bulk, doc);
2487                bson_destroy (doc);
2488             }
2489
2490             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
2491
2492             str = bson_as_canonical_extended_json (&reply, NULL);
2493             printf ("%s\n", str);
2494             bson_free (str);
2495
2496             if (!ret) {
2497                fprintf (stderr, "Error: %s\n", error.message);
2498             }
2499
2500             bson_destroy (&reply);
2501             mongoc_bulk_operation_destroy (bulk);
2502          }
2503
2504          int
2505          main (int argc, char *argv[])
2506          {
2507             mongoc_client_t *client;
2508             mongoc_collection_t *collection;
2509             const char *uri_string = "mongodb://localhost/?appname=bulk1-example";
2510             mongoc_uri_t *uri;
2511             bson_error_t error;
2512
2513             mongoc_init ();
2514
2515             uri = mongoc_uri_new_with_error (uri_string, &error);
2516             if (!uri) {
2517                fprintf (stderr,
2518                         "failed to parse URI: %s\n"
2519                         "error message:       %s\n",
2520                         uri_string,
2521                         error.message);
2522                return EXIT_FAILURE;
2523             }
2524
2525             client = mongoc_client_new_from_uri (uri);
2526             if (!client) {
2527                return EXIT_FAILURE;
2528             }
2529
2530             mongoc_client_set_error_api (client, 2);
2531             collection = mongoc_client_get_collection (client, "test", "test");
2532
2533             bulk1 (collection);
2534
2535             mongoc_uri_destroy (uri);
2536             mongoc_collection_destroy (collection);
2537             mongoc_client_destroy (client);
2538
2539             mongoc_cleanup ();
2540
2541             return EXIT_SUCCESS;
2542          }
2543
2544
2545Example reply document:
2546
2547          {"nInserted"   : 10000,
2548           "nMatched"    : 0,
2549           "nModified"   : 0,
2550           "nRemoved"    : 0,
2551           "nUpserted"   : 0,
2552           "writeErrors" : []
2553           "writeConcernErrors" : [] }
2554
2555   Mixed Bulk Write Operations
2556       MongoDB C driver also supports executing mixed bulk write operations. A
2557       batch of insert, update, and remove operations can be executed together
2558       using the bulk write operations API.
2559
2560   Ordered Bulk Write Operations
2561       Ordered bulk write operations are batched and sent to the server in the
2562       order  provided  for serial execution. The reply document describes the
2563       type and count of operations performed.  bulk2.c.INDENT 0.0
2564
2565          #include <assert.h>
2566          #include <mongoc/mongoc.h>
2567          #include <stdio.h>
2568
2569          static void
2570          bulk2 (mongoc_collection_t *collection)
2571          {
2572             mongoc_bulk_operation_t *bulk;
2573             bson_error_t error;
2574             bson_t *query;
2575             bson_t *doc;
2576             bson_t *opts;
2577             bson_t reply;
2578             char *str;
2579             bool ret;
2580             int i;
2581
2582             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2583
2584             /* Remove everything */
2585             query = bson_new ();
2586             mongoc_bulk_operation_remove (bulk, query);
2587             bson_destroy (query);
2588
2589             /* Add a few documents */
2590             for (i = 1; i < 4; i++) {
2591                doc = BCON_NEW ("_id", BCON_INT32 (i));
2592                mongoc_bulk_operation_insert (bulk, doc);
2593                bson_destroy (doc);
2594             }
2595
2596             /* {_id: 1} => {$set: {foo: "bar"}} */
2597             query = BCON_NEW ("_id", BCON_INT32 (1));
2598             doc = BCON_NEW ("$set", "{", "foo", BCON_UTF8 ("bar"), "}");
2599             mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, NULL, &error);
2600             bson_destroy (query);
2601             bson_destroy (doc);
2602
2603             /* {_id: 4} => {'$inc': {'j': 1}} (upsert) */
2604             opts = BCON_NEW ("upsert", BCON_BOOL (true));
2605             query = BCON_NEW ("_id", BCON_INT32 (4));
2606             doc = BCON_NEW ("$inc", "{", "j", BCON_INT32 (1), "}");
2607             mongoc_bulk_operation_update_many_with_opts (bulk, query, doc, opts, &error);
2608             bson_destroy (query);
2609             bson_destroy (doc);
2610             bson_destroy (opts);
2611
2612             /* replace {j:1} with {j:2} */
2613             query = BCON_NEW ("j", BCON_INT32 (1));
2614             doc = BCON_NEW ("j", BCON_INT32 (2));
2615             mongoc_bulk_operation_replace_one_with_opts (bulk, query, doc, NULL, &error);
2616             bson_destroy (query);
2617             bson_destroy (doc);
2618
2619             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
2620
2621             str = bson_as_canonical_extended_json (&reply, NULL);
2622             printf ("%s\n", str);
2623             bson_free (str);
2624
2625             if (!ret) {
2626                printf ("Error: %s\n", error.message);
2627             }
2628
2629             bson_destroy (&reply);
2630             mongoc_bulk_operation_destroy (bulk);
2631          }
2632
2633          int
2634          main (int argc, char *argv[])
2635          {
2636             mongoc_client_t *client;
2637             mongoc_collection_t *collection;
2638             const char *uri_string = "mongodb://localhost/?appname=bulk2-example";
2639             mongoc_uri_t *uri;
2640             bson_error_t error;
2641
2642             mongoc_init ();
2643
2644             uri = mongoc_uri_new_with_error (uri_string, &error);
2645             if (!uri) {
2646                fprintf (stderr,
2647                         "failed to parse URI: %s\n"
2648                         "error message:       %s\n",
2649                         uri_string,
2650                         error.message);
2651                return EXIT_FAILURE;
2652             }
2653
2654             client = mongoc_client_new_from_uri (uri);
2655             if (!client) {
2656                return EXIT_FAILURE;
2657             }
2658
2659             mongoc_client_set_error_api (client, 2);
2660             collection = mongoc_client_get_collection (client, "test", "test");
2661
2662             bulk2 (collection);
2663
2664             mongoc_uri_destroy (uri);
2665             mongoc_collection_destroy (collection);
2666             mongoc_client_destroy (client);
2667
2668             mongoc_cleanup ();
2669
2670             return EXIT_SUCCESS;
2671          }
2672
2673
2674Example reply document:
2675
2676          { "nInserted"   : 3,
2677            "nMatched"    : 2,
2678            "nModified"   : 2,
2679            "nRemoved"    : 10000,
2680            "nUpserted"   : 1,
2681            "upserted"    : [{"index" : 5, "_id" : 4}],
2682            "writeErrors" : []
2683            "writeConcernErrors" : [] }
2684
2685       The index field in the upserted array  is  the  0-based  index  of  the
2686       upsert  operation;  in this example, the sixth operation of the overall
2687       bulk operation was an upsert, so its index is 5.
2688
2689   Unordered Bulk Write Operations
2690       Unordered bulk write operations are batched and sent to the  server  in
2691       arbitrary order where they may be executed in parallel. Any errors that
2692       occur are reported after all operations are attempted.
2693
2694       In the next example the first and third  operations  fail  due  to  the
2695       unique  constraint  on  _id. Since we are doing unordered execution the
2696       second and fourth operations succeed.  bulk3.c.INDENT 0.0
2697
2698          #include <assert.h>
2699          #include <mongoc/mongoc.h>
2700          #include <stdio.h>
2701
2702          static void
2703          bulk3 (mongoc_collection_t *collection)
2704          {
2705             bson_t opts = BSON_INITIALIZER;
2706             mongoc_bulk_operation_t *bulk;
2707             bson_error_t error;
2708             bson_t *query;
2709             bson_t *doc;
2710             bson_t reply;
2711             char *str;
2712             bool ret;
2713
2714             /* false indicates unordered */
2715             BSON_APPEND_BOOL (&opts, "ordered", false);
2716             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
2717             bson_destroy (&opts);
2718
2719             /* Add a document */
2720             doc = BCON_NEW ("_id", BCON_INT32 (1));
2721             mongoc_bulk_operation_insert (bulk, doc);
2722             bson_destroy (doc);
2723
2724             /* remove {_id: 2} */
2725             query = BCON_NEW ("_id", BCON_INT32 (2));
2726             mongoc_bulk_operation_remove_one (bulk, query);
2727             bson_destroy (query);
2728
2729             /* insert {_id: 3} */
2730             doc = BCON_NEW ("_id", BCON_INT32 (3));
2731             mongoc_bulk_operation_insert (bulk, doc);
2732             bson_destroy (doc);
2733
2734             /* replace {_id:4} {'i': 1} */
2735             query = BCON_NEW ("_id", BCON_INT32 (4));
2736             doc = BCON_NEW ("i", BCON_INT32 (1));
2737             mongoc_bulk_operation_replace_one (bulk, query, doc, false);
2738             bson_destroy (query);
2739             bson_destroy (doc);
2740
2741             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
2742
2743             str = bson_as_canonical_extended_json (&reply, NULL);
2744             printf ("%s\n", str);
2745             bson_free (str);
2746
2747             if (!ret) {
2748                printf ("Error: %s\n", error.message);
2749             }
2750
2751             bson_destroy (&reply);
2752             mongoc_bulk_operation_destroy (bulk);
2753             bson_destroy (&opts);
2754          }
2755
2756          int
2757          main (int argc, char *argv[])
2758          {
2759             mongoc_client_t *client;
2760             mongoc_collection_t *collection;
2761             const char *uri_string = "mongodb://localhost/?appname=bulk3-example";
2762             mongoc_uri_t *uri;
2763             bson_error_t error;
2764
2765             mongoc_init ();
2766
2767             uri = mongoc_uri_new_with_error (uri_string, &error);
2768             if (!uri) {
2769                fprintf (stderr,
2770                         "failed to parse URI: %s\n"
2771                         "error message:       %s\n",
2772                         uri_string,
2773                         error.message);
2774                return EXIT_FAILURE;
2775             }
2776
2777             client = mongoc_client_new_from_uri (uri);
2778             if (!client) {
2779                return EXIT_FAILURE;
2780             }
2781
2782             mongoc_client_set_error_api (client, 2);
2783             collection = mongoc_client_get_collection (client, "test", "test");
2784
2785             bulk3 (collection);
2786
2787             mongoc_uri_destroy (uri);
2788             mongoc_collection_destroy (collection);
2789             mongoc_client_destroy (client);
2790
2791             mongoc_cleanup ();
2792
2793             return EXIT_SUCCESS;
2794          }
2795
2796
2797Example reply document:
2798
2799          { "nInserted"    : 0,
2800            "nMatched"     : 1,
2801            "nModified"    : 1,
2802            "nRemoved"     : 1,
2803            "nUpserted"    : 0,
2804            "writeErrors"  : [
2805              { "index"  : 0,
2806                "code"   : 11000,
2807                "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }" },
2808              { "index"  : 2,
2809                "code"   : 11000,
2810                "errmsg" : "E11000 duplicate key error index: test.test.$_id_ dup key: { : 3 }" } ],
2811            "writeConcernErrors" : [] }
2812
2813          Error: E11000 duplicate key error index: test.test.$_id_ dup key: { : 1 }
2814
2815       The bson_error_t domain is MONGOC_ERROR_COMMAND and its code is 11000.
2816
2817   Bulk Operation Bypassing Document Validation
2818       This feature is only available when using MongoDB 3.2 and later.
2819
2820       By default bulk operations are validated against the schema, if any  is
2821       defined.  In  certain  cases  however it may be necessary to bypass the
2822       document validation.  bulk5.c.INDENT 0.0
2823
2824          #include <assert.h>
2825          #include <mongoc/mongoc.h>
2826          #include <stdio.h>
2827
2828          static void
2829          bulk5_fail (mongoc_collection_t *collection)
2830          {
2831             mongoc_bulk_operation_t *bulk;
2832             bson_error_t error;
2833             bson_t *doc;
2834             bson_t reply;
2835             char *str;
2836             bool ret;
2837
2838             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2839
2840             /* Two inserts */
2841             doc = BCON_NEW ("_id", BCON_INT32 (31));
2842             mongoc_bulk_operation_insert (bulk, doc);
2843             bson_destroy (doc);
2844
2845             doc = BCON_NEW ("_id", BCON_INT32 (32));
2846             mongoc_bulk_operation_insert (bulk, doc);
2847             bson_destroy (doc);
2848
2849             /* The above documents do not comply to the schema validation rules
2850              * we created previously, so this will result in an error */
2851             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
2852
2853             str = bson_as_canonical_extended_json (&reply, NULL);
2854             printf ("%s\n", str);
2855             bson_free (str);
2856
2857             if (!ret) {
2858                printf ("Error: %s\n", error.message);
2859             }
2860
2861             bson_destroy (&reply);
2862             mongoc_bulk_operation_destroy (bulk);
2863          }
2864
2865          static void
2866          bulk5_success (mongoc_collection_t *collection)
2867          {
2868             mongoc_bulk_operation_t *bulk;
2869             bson_error_t error;
2870             bson_t *doc;
2871             bson_t reply;
2872             char *str;
2873             bool ret;
2874
2875             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
2876
2877             /* Allow this document to bypass document validation.
2878              * NOTE: When authentication is enabled, the authenticated user must have
2879              * either the "dbadmin" or "restore" roles to bypass document validation */
2880             mongoc_bulk_operation_set_bypass_document_validation (bulk, true);
2881
2882             /* Two inserts */
2883             doc = BCON_NEW ("_id", BCON_INT32 (31));
2884             mongoc_bulk_operation_insert (bulk, doc);
2885             bson_destroy (doc);
2886
2887             doc = BCON_NEW ("_id", BCON_INT32 (32));
2888             mongoc_bulk_operation_insert (bulk, doc);
2889             bson_destroy (doc);
2890
2891             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
2892
2893             str = bson_as_canonical_extended_json (&reply, NULL);
2894             printf ("%s\n", str);
2895             bson_free (str);
2896
2897             if (!ret) {
2898                printf ("Error: %s\n", error.message);
2899             }
2900
2901             bson_destroy (&reply);
2902             mongoc_bulk_operation_destroy (bulk);
2903          }
2904
2905          int
2906          main (int argc, char *argv[])
2907          {
2908             bson_t *options;
2909             bson_error_t error;
2910             mongoc_client_t *client;
2911             mongoc_collection_t *collection;
2912             mongoc_database_t *database;
2913             const char *uri_string = "mongodb://localhost/?appname=bulk5-example";
2914             mongoc_uri_t *uri;
2915
2916             mongoc_init ();
2917
2918             uri = mongoc_uri_new_with_error (uri_string, &error);
2919             if (!uri) {
2920                fprintf (stderr,
2921                         "failed to parse URI: %s\n"
2922                         "error message:       %s\n",
2923                         uri_string,
2924                         error.message);
2925                return EXIT_FAILURE;
2926             }
2927
2928             client = mongoc_client_new_from_uri (uri);
2929             if (!client) {
2930                return EXIT_FAILURE;
2931             }
2932
2933             mongoc_client_set_error_api (client, 2);
2934             database = mongoc_client_get_database (client, "testasdf");
2935
2936             /* Create schema validator */
2937             options = BCON_NEW (
2938                "validator", "{", "number", "{", "$gte", BCON_INT32 (5), "}", "}");
2939             collection =
2940                mongoc_database_create_collection (database, "collname", options, &error);
2941
2942             if (collection) {
2943                bulk5_fail (collection);
2944                bulk5_success (collection);
2945                mongoc_collection_destroy (collection);
2946             } else {
2947                fprintf (stderr, "Couldn't create collection: '%s'\n", error.message);
2948             }
2949
2950             bson_free (options);
2951             mongoc_uri_destroy (uri);
2952             mongoc_database_destroy (database);
2953             mongoc_client_destroy (client);
2954
2955             mongoc_cleanup ();
2956
2957             return EXIT_SUCCESS;
2958          }
2959
2960
2961Running the above example will result in:
2962
2963          { "nInserted" : 0,
2964            "nMatched" : 0,
2965            "nModified" : 0,
2966            "nRemoved" : 0,
2967            "nUpserted" : 0,
2968            "writeErrors" : [
2969              { "index" : 0,
2970                "code" : 121,
2971                "errmsg" : "Document failed validation" } ] }
2972
2973          Error: Document failed validation
2974
2975          { "nInserted" : 2,
2976            "nMatched" : 0,
2977            "nModified" : 0,
2978            "nRemoved" : 0,
2979            "nUpserted" : 0,
2980            "writeErrors" : [] }
2981
2982       The bson_error_t domain is MONGOC_ERROR_COMMAND.
2983
2984   Bulk Operation Write Concerns
2985       By default bulk operations are executed with the write_concern  of  the
2986       collection  they  are  executed  against. A custom write concern can be
2987       passed   to   the   mongoc_collection_create_bulk_operation_with_opts()
2988       method. Write concern errors (e.g. wtimeout) will be reported after all
2989       operations   are   attempted,   regardless    of    execution    order.
2990       bulk4.c.INDENT 0.0
2991
2992          #include <assert.h>
2993          #include <mongoc/mongoc.h>
2994          #include <stdio.h>
2995
2996          static void
2997          bulk4 (mongoc_collection_t *collection)
2998          {
2999             bson_t opts = BSON_INITIALIZER;
3000             mongoc_write_concern_t *wc;
3001             mongoc_bulk_operation_t *bulk;
3002             bson_error_t error;
3003             bson_t *doc;
3004             bson_t reply;
3005             char *str;
3006             bool ret;
3007
3008             wc = mongoc_write_concern_new ();
3009             mongoc_write_concern_set_w (wc, 4);
3010             mongoc_write_concern_set_wtimeout_int64 (wc, 100); /* milliseconds */
3011             mongoc_write_concern_append (wc, &opts);
3012
3013             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
3014
3015             /* Two inserts */
3016             doc = BCON_NEW ("_id", BCON_INT32 (10));
3017             mongoc_bulk_operation_insert (bulk, doc);
3018             bson_destroy (doc);
3019
3020             doc = BCON_NEW ("_id", BCON_INT32 (11));
3021             mongoc_bulk_operation_insert (bulk, doc);
3022             bson_destroy (doc);
3023
3024             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3025
3026             str = bson_as_canonical_extended_json (&reply, NULL);
3027             printf ("%s\n", str);
3028             bson_free (str);
3029
3030             if (!ret) {
3031                printf ("Error: %s\n", error.message);
3032             }
3033
3034             bson_destroy (&reply);
3035             mongoc_bulk_operation_destroy (bulk);
3036             mongoc_write_concern_destroy (wc);
3037             bson_destroy (&opts);
3038          }
3039
3040          int
3041          main (int argc, char *argv[])
3042          {
3043             mongoc_client_t *client;
3044             mongoc_collection_t *collection;
3045             const char *uri_string = "mongodb://localhost/?appname=bulk4-example";
3046             mongoc_uri_t *uri;
3047             bson_error_t error;
3048
3049             mongoc_init ();
3050
3051             uri = mongoc_uri_new_with_error (uri_string, &error);
3052             if (!uri) {
3053                fprintf (stderr,
3054                         "failed to parse URI: %s\n"
3055                         "error message:       %s\n",
3056                         uri_string,
3057                         error.message);
3058                return EXIT_FAILURE;
3059             }
3060
3061             client = mongoc_client_new_from_uri (uri);
3062             if (!client) {
3063                return EXIT_FAILURE;
3064             }
3065
3066             mongoc_client_set_error_api (client, 2);
3067             collection = mongoc_client_get_collection (client, "test", "test");
3068
3069             bulk4 (collection);
3070
3071             mongoc_uri_destroy (uri);
3072             mongoc_collection_destroy (collection);
3073             mongoc_client_destroy (client);
3074
3075             mongoc_cleanup ();
3076
3077             return EXIT_SUCCESS;
3078          }
3079
3080
3081Example reply document and error message:
3082
3083          { "nInserted"    : 2,
3084            "nMatched"     : 0,
3085            "nModified"    : 0,
3086            "nRemoved"     : 0,
3087            "nUpserted"    : 0,
3088            "writeErrors"  : [],
3089            "writeConcernErrors" : [
3090              { "code"   : 64,
3091                "errmsg" : "waiting for replication timed out" }
3092          ] }
3093
3094          Error: waiting for replication timed out
3095
3096       The  bson_error_t  domain  is  MONGOC_ERROR_WRITE_CONCERN  if there are
3097       write concern errors and no write errors. Write errors indicate  failed
3098       operations,  so  they  take precedence over write concern errors, which
3099       mean merely that the write concern is not satisfied yet.
3100
3101   Setting Collation Order
3102       This feature is only  available  when  using  MongoDB  3.4  and  later.
3103       bulk-collation.c.INDENT 0.0
3104
3105          #include <mongoc/mongoc.h>
3106          #include <stdio.h>
3107
3108          static void
3109          bulk_collation (mongoc_collection_t *collection)
3110          {
3111             mongoc_bulk_operation_t *bulk;
3112             bson_t *opts;
3113             bson_t *doc;
3114             bson_t *selector;
3115             bson_t *update;
3116             bson_error_t error;
3117             bson_t reply;
3118             char *str;
3119             uint32_t ret;
3120
3121             /* insert {_id: "one"} and {_id: "One"} */
3122             bulk = mongoc_collection_create_bulk_operation_with_opts (
3123                collection, NULL);
3124             doc = BCON_NEW ("_id", BCON_UTF8 ("one"));
3125             mongoc_bulk_operation_insert (bulk, doc);
3126             bson_destroy (doc);
3127
3128             doc = BCON_NEW ("_id", BCON_UTF8 ("One"));
3129             mongoc_bulk_operation_insert (bulk, doc);
3130             bson_destroy (doc);
3131
3132             /* "One" normally sorts before "one"; make "one" come first */
3133             opts = BCON_NEW ("collation",
3134                              "{",
3135                              "locale",
3136                              BCON_UTF8 ("en_US"),
3137                              "caseFirst",
3138                              BCON_UTF8 ("lower"),
3139                              "}");
3140
3141             /* set x=1 on the document with _id "One", which now sorts after "one" */
3142             update = BCON_NEW ("$set", "{", "x", BCON_INT64 (1), "}");
3143             selector = BCON_NEW ("_id", "{", "$gt", BCON_UTF8 ("one"), "}");
3144             mongoc_bulk_operation_update_one_with_opts (
3145                bulk, selector, update, opts, &error);
3146
3147             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3148
3149             str = bson_as_canonical_extended_json (&reply, NULL);
3150             printf ("%s\n", str);
3151             bson_free (str);
3152
3153             if (!ret) {
3154                printf ("Error: %s\n", error.message);
3155             }
3156
3157             bson_destroy (&reply);
3158             bson_destroy (update);
3159             bson_destroy (selector);
3160             bson_destroy (opts);
3161             mongoc_bulk_operation_destroy (bulk);
3162          }
3163
3164          int
3165          main (int argc, char *argv[])
3166          {
3167             mongoc_client_t *client;
3168             mongoc_collection_t *collection;
3169             const char *uri_string = "mongodb://localhost/?appname=bulk-collation";
3170             mongoc_uri_t *uri;
3171             bson_error_t error;
3172
3173             mongoc_init ();
3174
3175             uri = mongoc_uri_new_with_error (uri_string, &error);
3176             if (!uri) {
3177                fprintf (stderr,
3178                         "failed to parse URI: %s\n"
3179                         "error message:       %s\n",
3180                         uri_string,
3181                         error.message);
3182                return EXIT_FAILURE;
3183             }
3184
3185             client = mongoc_client_new_from_uri (uri);
3186             if (!client) {
3187                return EXIT_FAILURE;
3188             }
3189
3190             mongoc_client_set_error_api (client, 2);
3191             collection = mongoc_client_get_collection (client, "db", "collection");
3192             bulk_collation (collection);
3193
3194             mongoc_uri_destroy (uri);
3195             mongoc_collection_destroy (collection);
3196             mongoc_client_destroy (client);
3197
3198             mongoc_cleanup ();
3199
3200             return EXIT_SUCCESS;
3201          }
3202
3203
3204Running the above example will result in:
3205
3206          { "nInserted" : 2,
3207             "nMatched" : 1,
3208             "nModified" : 1,
3209             "nRemoved" : 0,
3210             "nUpserted" : 0,
3211             "writeErrors" : [  ]
3212          }
3213
3214   Unacknowledged Bulk Writes
3215       Set  "w"  to  zero  for an unacknowledged write. The driver sends unac‐
3216       knowledged writes using the legacy opcodes  OP_INSERT,  OP_UPDATE,  and
3217       OP_DELETE.  bulk6.c.INDENT 0.0
3218
3219          #include <mongoc/mongoc.h>
3220          #include <stdio.h>
3221
3222          static void
3223          bulk6 (mongoc_collection_t *collection)
3224          {
3225             bson_t opts = BSON_INITIALIZER;
3226             mongoc_write_concern_t *wc;
3227             mongoc_bulk_operation_t *bulk;
3228             bson_error_t error;
3229             bson_t *doc;
3230             bson_t *selector;
3231             bson_t reply;
3232             char *str;
3233             bool ret;
3234
3235             wc = mongoc_write_concern_new ();
3236             mongoc_write_concern_set_w (wc, 0);
3237             mongoc_write_concern_append (wc, &opts);
3238
3239             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, &opts);
3240
3241             doc = BCON_NEW ("_id", BCON_INT32 (10));
3242             mongoc_bulk_operation_insert (bulk, doc);
3243             bson_destroy (doc);
3244
3245             selector = BCON_NEW ("_id", BCON_INT32 (11));
3246             mongoc_bulk_operation_remove_one (bulk, selector);
3247             bson_destroy (selector);
3248
3249             ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
3250
3251             str = bson_as_canonical_extended_json (&reply, NULL);
3252             printf ("%s\n", str);
3253             bson_free (str);
3254
3255             if (!ret) {
3256                printf ("Error: %s\n", error.message);
3257             }
3258
3259             bson_destroy (&reply);
3260             mongoc_bulk_operation_destroy (bulk);
3261             mongoc_write_concern_destroy (wc);
3262             bson_destroy (&opts);
3263          }
3264
3265          int
3266          main (int argc, char *argv[])
3267          {
3268             mongoc_client_t *client;
3269             mongoc_collection_t *collection;
3270             const char *uri_string = "mongodb://localhost/?appname=bulk6-example";
3271             mongoc_uri_t *uri;
3272             bson_error_t error;
3273
3274             mongoc_init ();
3275
3276             uri = mongoc_uri_new_with_error (uri_string, &error);
3277             if (!uri) {
3278                fprintf (stderr,
3279                         "failed to parse URI: %s\n"
3280                         "error message:       %s\n",
3281                         uri_string,
3282                         error.message);
3283                return EXIT_FAILURE;
3284             }
3285
3286             client = mongoc_client_new_from_uri (uri);
3287             if (!client) {
3288                return EXIT_FAILURE;
3289             }
3290
3291             mongoc_client_set_error_api (client, 2);
3292             collection = mongoc_client_get_collection (client, "test", "test");
3293
3294             bulk6 (collection);
3295
3296             mongoc_uri_destroy (uri);
3297             mongoc_collection_destroy (collection);
3298             mongoc_client_destroy (client);
3299
3300             mongoc_cleanup ();
3301
3302             return EXIT_SUCCESS;
3303          }
3304
3305
3306The reply document is empty:
3307
3308          { }
3309
3310   Further Reading
3311       See the Driver Bulk API Spec, which describes bulk write operations for
3312       all MongoDB drivers.
3313
3314   Aggregation Framework Examples
3315       This document provides a number of practical examples that display  the
3316       capabilities of the aggregation framework.
3317
3318       The  Aggregations using the Zip Codes Data Set examples uses a publicly
3319       available data set of  all  zipcodes  and  populations  in  the  United
3320       States. These data are available at: zips.json.
3321
3322   Requirements
3323       Let's check if everything is installed.
3324
3325       Use  the  following  command  to  load  zips.json  data set into mongod
3326       instance:
3327
3328          $ mongoimport --drop -d test -c zipcodes zips.json
3329
3330       Let's use the MongoDB shell to verify that everything was imported suc‐
3331       cessfully.
3332
3333          $ mongo test
3334          connecting to: test
3335          > db.zipcodes.count()
3336          29467
3337          > db.zipcodes.findOne()
3338          {
3339                "_id" : "35004",
3340                "city" : "ACMAR",
3341                "loc" : [
3342                        -86.51557,
3343                        33.584132
3344                ],
3345                "pop" : 6055,
3346                "state" : "AL"
3347          }
3348
3349   Aggregations using the Zip Codes Data Set
3350       Each document in this collection has the following form:
3351
3352          {
3353            "_id" : "35004",
3354            "city" : "Acmar",
3355            "state" : "AL",
3356            "pop" : 6055,
3357            "loc" : [-86.51557, 33.584132]
3358          }
3359
3360       In these documents:
3361
3362       · The _id field holds the zipcode as a string.
3363
3364       · The city field holds the city name.
3365
3366       · The state field holds the two letter state abbreviation.
3367
3368       · The pop field holds the population.
3369
3370       · The loc field holds the location as a [latitude, longitude] array.
3371
3372   States with Populations Over 10 Million
3373       To  get  all  states with a population greater than 10 million, use the
3374       following aggregation pipeline: aggregation1.c.INDENT 0.0
3375
3376          #include <mongoc/mongoc.h>
3377          #include <stdio.h>
3378
3379          static void
3380          print_pipeline (mongoc_collection_t *collection)
3381          {
3382             mongoc_cursor_t *cursor;
3383             bson_error_t error;
3384             const bson_t *doc;
3385             bson_t *pipeline;
3386             char *str;
3387
3388             pipeline = BCON_NEW ("pipeline",
3389                                  "[",
3390                                  "{",
3391                                  "$group",
3392                                  "{",
3393                                  "_id",
3394                                  "$state",
3395                                  "total_pop",
3396                                  "{",
3397                                  "$sum",
3398                                  "$pop",
3399                                  "}",
3400                                  "}",
3401                                  "}",
3402                                  "{",
3403                                  "$match",
3404                                  "{",
3405                                  "total_pop",
3406                                  "{",
3407                                  "$gte",
3408                                  BCON_INT32 (10000000),
3409                                  "}",
3410                                  "}",
3411                                  "}",
3412                                  "]");
3413
3414             cursor = mongoc_collection_aggregate (
3415                collection, MONGOC_QUERY_NONE, pipeline, NULL, NULL);
3416
3417             while (mongoc_cursor_next (cursor, &doc)) {
3418                str = bson_as_canonical_extended_json (doc, NULL);
3419                printf ("%s\n", str);
3420                bson_free (str);
3421             }
3422
3423             if (mongoc_cursor_error (cursor, &error)) {
3424                fprintf (stderr, "Cursor Failure: %s\n", error.message);
3425             }
3426
3427             mongoc_cursor_destroy (cursor);
3428             bson_destroy (pipeline);
3429          }
3430
3431          int
3432          main (int argc, char *argv[])
3433          {
3434             mongoc_client_t *client;
3435             mongoc_collection_t *collection;
3436             const char *uri_string =
3437                "mongodb://localhost:27017/?appname=aggregation-example";
3438             mongoc_uri_t *uri;
3439             bson_error_t error;
3440
3441             mongoc_init ();
3442
3443             uri = mongoc_uri_new_with_error (uri_string, &error);
3444             if (!uri) {
3445                fprintf (stderr,
3446                         "failed to parse URI: %s\n"
3447                         "error message:       %s\n",
3448                         uri_string,
3449                         error.message);
3450                return EXIT_FAILURE;
3451             }
3452
3453             client = mongoc_client_new_from_uri (uri);
3454             if (!client) {
3455                return EXIT_FAILURE;
3456             }
3457
3458             mongoc_client_set_error_api (client, 2);
3459             collection = mongoc_client_get_collection (client, "test", "zipcodes");
3460
3461             print_pipeline (collection);
3462
3463             mongoc_uri_destroy (uri);
3464             mongoc_collection_destroy (collection);
3465             mongoc_client_destroy (client);
3466
3467             mongoc_cleanup ();
3468
3469             return EXIT_SUCCESS;
3470          }
3471
3472
3473You should see a result like the following:
3474
3475          { "_id" : "PA", "total_pop" : 11881643 }
3476          { "_id" : "OH", "total_pop" : 10847115 }
3477          { "_id" : "NY", "total_pop" : 17990455 }
3478          { "_id" : "FL", "total_pop" : 12937284 }
3479          { "_id" : "TX", "total_pop" : 16986510 }
3480          { "_id" : "IL", "total_pop" : 11430472 }
3481          { "_id" : "CA", "total_pop" : 29760021 }
3482
3483       The above aggregation pipeline is build from  two  pipeline  operators:
3484       $group and $match.
3485
3486       The $group pipeline operator requires _id field where we specify group‐
3487       ing; remaining fields specify how to generate composite value and  must
3488       use  one  of the group aggregation functions: $addToSet, $first, $last,
3489       $max, $min, $avg, $push, $sum. The $match pipeline operator  syntax  is
3490       the same as the read operation query syntax.
3491
3492       The  $group process reads all documents and for each state it creates a
3493       separate document, for example:
3494
3495          { "_id" : "WA", "total_pop" : 4866692 }
3496
3497       The total_pop field uses the $sum aggregation function to sum the  val‐
3498       ues of all pop fields in the source documents.
3499
3500       Documents  created by $group are piped to the $match pipeline operator.
3501       It returns the documents with the value of total_pop field greater than
3502       or equal to 10 million.
3503
3504   Average City Population by State
3505       To  get the first three states with the greatest average population per
3506       city, use the following aggregation:
3507
3508          pipeline = BCON_NEW ("pipeline", "[",
3509             "{", "$group", "{", "_id", "{", "state", "$state", "city", "$city", "}", "pop", "{", "$sum", "$pop", "}", "}", "}",
3510             "{", "$group", "{", "_id", "$_id.state", "avg_city_pop", "{", "$avg", "$pop", "}", "}", "}",
3511             "{", "$sort", "{", "avg_city_pop", BCON_INT32 (-1), "}", "}",
3512             "{", "$limit", BCON_INT32 (3) "}",
3513          "]");
3514
3515       This aggregate pipeline produces:
3516
3517          { "_id" : "DC", "avg_city_pop" : 303450.0 }
3518          { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
3519          { "_id" : "CA", "avg_city_pop" : 27735.341099720412 }
3520
3521       The above aggregation pipeline is build from three pipeline  operators:
3522       $group, $sort and $limit.
3523
3524       The first $group operator creates the following documents:
3525
3526          { "_id" : { "state" : "WY", "city" : "Smoot" }, "pop" : 414 }
3527
3528       Note,  that  the  $group operator can't use nested documents except the
3529       _id field.
3530
3531       The second $group uses these documents to create  the  following  docu‐
3532       ments:
3533
3534          { "_id" : "FL", "avg_city_pop" : 27942.29805615551 }
3535
3536       These  documents  are  sorted  by  the avg_city_pop field in descending
3537       order. Finally, the $limit pipeline operator returns the first 3  docu‐
3538       ments from the sorted set.
3539
3540   distinct and mapReduce
3541       This  document provides some practical, simple, examples to demonstrate
3542       the distinct and mapReduce commands.
3543
3544   Setup
3545       First  we'll  write  some  code  to  insert   sample   data:   doc-com‐
3546       mon-insert.c.INDENT 0.0
3547
3548          /* Don't try to compile this file on its own. It's meant to be #included
3549             by example code */
3550
3551          /* Insert some sample data */
3552          bool
3553          insert_data (mongoc_collection_t *collection)
3554          {
3555             mongoc_bulk_operation_t *bulk;
3556             enum N { ndocs = 4 };
3557             bson_t *docs[ndocs];
3558             bson_error_t error;
3559             int i = 0;
3560             bool ret;
3561
3562             bulk = mongoc_collection_create_bulk_operation_with_opts (collection, NULL);
3563
3564             docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
3565             docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
3566             docs[2] = BCON_NEW (
3567                "x", BCON_DOUBLE (2.0), "tags", "[", "mouse", "cat", "dog", "]");
3568             docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
3569
3570             for (i = 0; i < ndocs; i++) {
3571                mongoc_bulk_operation_insert (bulk, docs[i]);
3572                bson_destroy (docs[i]);
3573                docs[i] = NULL;
3574             }
3575
3576             ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
3577
3578             if (!ret) {
3579                fprintf (stderr, "Error inserting data: %s\n", error.message);
3580             }
3581
3582             mongoc_bulk_operation_destroy (bulk);
3583             return ret;
3584          }
3585
3586          /* A helper which we'll use a lot later on */
3587          void
3588          print_res (const bson_t *reply)
3589          {
3590             char *str;
3591             BSON_ASSERT (reply);
3592             str = bson_as_canonical_extended_json (reply, NULL);
3593             printf ("%s\n", str);
3594             bson_free (str);
3595          }
3596
3597
3598   distinct command
3599       This is how to use the distinct command to get the distinct values of x
3600       which are greater than 1: distinct.c.INDENT 0.0
3601
3602          bool
3603          distinct (mongoc_database_t *database)
3604          {
3605             bson_t *command;
3606             bson_t reply;
3607             bson_error_t error;
3608             bool res;
3609             bson_iter_t iter;
3610             bson_iter_t array_iter;
3611             double val;
3612
3613             command = BCON_NEW ("distinct",
3614                                 BCON_UTF8 (COLLECTION_NAME),
3615                                 "key",
3616                                 BCON_UTF8 ("x"),
3617                                 "query",
3618                                 "{",
3619                                 "x",
3620                                 "{",
3621                                 "$gt",
3622                                 BCON_DOUBLE (1.0),
3623                                 "}",
3624                                 "}");
3625             res =
3626                mongoc_database_command_simple (database, command, NULL, &reply, &error);
3627             if (!res) {
3628                fprintf (stderr, "Error with distinct: %s\n", error.message);
3629                goto cleanup;
3630             }
3631
3632             /* Do something with reply (in this case iterate through the values) */
3633             if (!(bson_iter_init_find (&iter, &reply, "values") &&
3634                   BSON_ITER_HOLDS_ARRAY (&iter) &&
3635                   bson_iter_recurse (&iter, &array_iter))) {
3636                fprintf (stderr, "Couldn't extract \"values\" field from response\n");
3637                goto cleanup;
3638             }
3639
3640             while (bson_iter_next (&array_iter)) {
3641                if (BSON_ITER_HOLDS_DOUBLE (&array_iter)) {
3642                   val = bson_iter_double (&array_iter);
3643                   printf ("Next double: %f\n", val);
3644                }
3645             }
3646
3647          cleanup:
3648             /* cleanup */
3649             bson_destroy (command);
3650             bson_destroy (&reply);
3651             return res;
3652          }
3653
3654
3655   mapReduce - basic example
3656       A simple example using the map reduce framework. It simply adds up  the
3657       number of occurrences of each "tag".
3658
3659       First define the map and reduce functions: constants.c.INDENT 0.0
3660
3661          const char *const COLLECTION_NAME = "things";
3662
3663          /* Our map function just emits a single (key, 1) pair for each tag
3664             in the array: */
3665          const char *const MAPPER = "function () {"
3666                                     "this.tags.forEach(function(z) {"
3667                                     "emit(z, 1);"
3668                                     "});"
3669                                     "}";
3670
3671          /* The reduce function sums over all of the emitted values for a
3672             given key: */
3673          const char *const REDUCER = "function (key, values) {"
3674                                      "var total = 0;"
3675                                      "for (var i = 0; i < values.length; i++) {"
3676                                      "total += values[i];"
3677                                      "}"
3678                                      "return total;"
3679                                      "}";
3680          /* Note We can't just return values.length as the reduce function
3681             might be called iteratively on the results of other reduce
3682             steps. */
3683
3684
3685Run  the mapReduce command. Use the generic command helpers (e.g. mongoc_data‐

base_command_simple()). Do not the read command helpers (e.g. mongoc_data‐

base_read_command_with_opts()) because they are considered retryable read

3688operations. If retryable reads are enabled, those operations will  retry  once
3689on   a   retryable   error,   giving   undesirable   behavior  for  mapReduce.
3690map-reduce-basic.c.INDENT 0.0
3691
3692          bool
3693          map_reduce_basic (mongoc_database_t *database)
3694          {
3695             bson_t reply;
3696             bson_t *command;
3697             bool res;
3698             bson_error_t error;
3699             mongoc_cursor_t *cursor;
3700             const bson_t *doc;
3701
3702             bool query_done = false;
3703
3704             const char *out_collection_name = "outCollection";
3705             mongoc_collection_t *out_collection;
3706
3707             /* Empty find query */
3708             bson_t find_query = BSON_INITIALIZER;
3709
3710             /* Construct the mapReduce command */
3711
3712             /* Other arguments can also be specified here, like "query" or
3713                "limit" and so on */
3714             command = BCON_NEW ("mapReduce",
3715                                 BCON_UTF8 (COLLECTION_NAME),
3716                                 "map",
3717                                 BCON_CODE (MAPPER),
3718                                 "reduce",
3719                                 BCON_CODE (REDUCER),
3720                                 "out",
3721                                 BCON_UTF8 (out_collection_name));
3722             res =
3723                mongoc_database_command_simple (database, command, NULL, &reply, &error);
3724
3725             if (!res) {
3726                fprintf (stderr, "MapReduce failed: %s\n", error.message);
3727                goto cleanup;
3728             }
3729
3730             /* Do something with the reply (it doesn't contain the mapReduce results) */
3731             print_res (&reply);
3732
3733             /* Now we'll query outCollection to see what the results are */
3734             out_collection =
3735                mongoc_database_get_collection (database, out_collection_name);
3736             cursor = mongoc_collection_find_with_opts (
3737                out_collection, &find_query, NULL, NULL);
3738             query_done = true;
3739
3740             /* Do something with the results */
3741             while (mongoc_cursor_next (cursor, &doc)) {
3742                print_res (doc);
3743             }
3744
3745             if (mongoc_cursor_error (cursor, &error)) {
3746                fprintf (stderr, "ERROR: %s\n", error.message);
3747                res = false;
3748                goto cleanup;
3749             }
3750
3751          cleanup:
3752             /* cleanup */
3753             if (query_done) {
3754                mongoc_cursor_destroy (cursor);
3755                mongoc_collection_destroy (out_collection);
3756             }
3757
3758             bson_destroy (&reply);
3759             bson_destroy (command);
3760
3761             return res;
3762          }
3763
3764
3765   mapReduce - more complicated example
3766       You must have replica set running for this.
3767
3768       In this example we contact a secondary in the replica  set  and  do  an
3769       "inline"   map   reduce,  so  the  results  are  returned  immediately:
3770       map-reduce-advanced.c.INDENT 0.0
3771
3772          bool
3773          map_reduce_advanced (mongoc_database_t *database)
3774          {
3775             bson_t *command;
3776             bson_error_t error;
3777             bool res = true;
3778             mongoc_cursor_t *cursor;
3779             mongoc_read_prefs_t *read_pref;
3780             const bson_t *doc;
3781
3782             /* Construct the mapReduce command */
3783             /* Other arguments can also be specified here, like "query" or "limit"
3784                and so on */
3785
3786             /* Read the results inline from a secondary replica */
3787             command = BCON_NEW ("mapReduce",
3788                                 BCON_UTF8 (COLLECTION_NAME),
3789                                 "map",
3790                                 BCON_CODE (MAPPER),
3791                                 "reduce",
3792                                 BCON_CODE (REDUCER),
3793                                 "out",
3794                                 "{",
3795                                 "inline",
3796                                 "1",
3797                                 "}");
3798
3799             read_pref = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
3800             cursor = mongoc_database_command (
3801                database, MONGOC_QUERY_NONE, 0, 0, 0, command, NULL, read_pref);
3802
3803             /* Do something with the results */
3804             while (mongoc_cursor_next (cursor, &doc)) {
3805                print_res (doc);
3806             }
3807
3808             if (mongoc_cursor_error (cursor, &error)) {
3809                fprintf (stderr, "ERROR: %s\n", error.message);
3810                res = false;
3811             }
3812
3813             mongoc_cursor_destroy (cursor);
3814             mongoc_read_prefs_destroy (read_pref);
3815             bson_destroy (command);
3816
3817             return res;
3818          }
3819
3820
3821   Running the Examples
3822       Here's how to run the example code basic-aggregation.c.INDENT 0.0
3823
3824          /*
3825           * Copyright 2016 MongoDB, Inc.
3826           *
3827           * Licensed under the Apache License, Version 2.0 (the "License");
3828           * you may not use this file except in compliance with the License.
3829           * You may obtain a copy of the License at
3830           *
3831           *   http://www.apache.org/licenses/LICENSE-2.0
3832           *
3833           * Unless required by applicable law or agreed to in writing, software
3834           * distributed under the License is distributed on an "AS IS" BASIS,
3835           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3836           * See the License for the specific language governing permissions and
3837           * limitations under the License.
3838           */
3839
3840
3841          #include <mongoc/mongoc.h>
3842          #include <stdio.h>
3843
3844
3845          #include "constants.c"
3846
3847          #include "../doc-common-insert.c"
3848          #include "distinct.c"
3849          #include "map-reduce-basic.c"
3850          #include "map-reduce-advanced.c"
3851
3852
3853          int
3854          main (int argc, char *argv[])
3855          {
3856             mongoc_database_t *database = NULL;
3857             mongoc_client_t *client = NULL;
3858             mongoc_collection_t *collection = NULL;
3859             mongoc_uri_t *uri = NULL;
3860             bson_error_t error;
3861             char *host_and_port = NULL;
3862             int exit_code = EXIT_FAILURE;
3863
3864             if (argc != 2) {
3865                fprintf (stderr, "usage: %s CONNECTION-STRING\n", argv[0]);
3866                fprintf (stderr,
3867                         "the connection string can be of the following forms:\n");
3868                fprintf (stderr, "localhost\t\t\t\tlocal machine\n");
3869                fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n");
3870                fprintf (stderr,
3871                         "mongodb://user:pass@localhost:27017\t"
3872                         "local machine on port 27017, and authenticate with username "
3873                         "user and password pass\n");
3874                return exit_code;
3875             }
3876
3877             mongoc_init ();
3878
3879             if (strncmp (argv[1], "mongodb://", 10) == 0) {
3880                host_and_port = bson_strdup (argv[1]);
3881             } else {
3882                host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]);
3883             }
3884
3885             uri = mongoc_uri_new_with_error (host_and_port, &error);
3886             if (!uri) {
3887                fprintf (stderr,
3888                         "failed to parse URI: %s\n"
3889                         "error message:       %s\n",
3890                         host_and_port,
3891                         error.message);
3892                goto cleanup;
3893             }
3894
3895             client = mongoc_client_new_from_uri (uri);
3896             if (!client) {
3897                goto cleanup;
3898             }
3899
3900             mongoc_client_set_error_api (client, 2);
3901             database = mongoc_client_get_database (client, "test");
3902             collection = mongoc_database_get_collection (database, COLLECTION_NAME);
3903
3904             printf ("Inserting data\n");
3905             if (!insert_data (collection)) {
3906                goto cleanup;
3907             }
3908
3909             printf ("distinct\n");
3910             if (!distinct (database)) {
3911                goto cleanup;
3912             }
3913
3914             printf ("map reduce\n");
3915             if (!map_reduce_basic (database)) {
3916                goto cleanup;
3917             }
3918
3919             printf ("more complicated map reduce\n");
3920             if (!map_reduce_advanced (database)) {
3921                goto cleanup;
3922             }
3923
3924             exit_code = EXIT_SUCCESS;
3925
3926          cleanup:
3927             if (collection) {
3928                mongoc_collection_destroy (collection);
3929             }
3930
3931             if (database) {
3932                mongoc_database_destroy (database);
3933             }
3934
3935             if (client) {
3936                mongoc_client_destroy (client);
3937             }
3938
3939             if (uri) {
3940                mongoc_uri_destroy (uri);
3941             }
3942
3943             if (host_and_port) {
3944                bson_free (host_and_port);
3945             }
3946
3947             mongoc_cleanup ();
3948             return exit_code;
3949          }
3950
3951
3952If you want to try the advanced map reduce example with a secondary,  start  a
3953replica set (instructions for how to do this can be found here).
3954
3955Otherwise, just start an instance of MongoDB:
3956
3957          $ mongod
3958
3959       Now compile and run the example program:
3960
3961          $ cd examples/basic_aggregation/
3962          $ gcc -Wall -o agg-example basic-aggregation.c $(pkg-config --cflags --libs libmongoc-1.0)
3963          $ ./agg-example localhost
3964
3965          Inserting data
3966          distinct
3967          Next double: 2.000000
3968          Next double: 3.000000
3969          map reduce
3970          { "result" : "outCollection", "timeMillis" : 155, "counts" : { "input" : 84, "emit" : 126, "reduce" : 3, "output" : 3 }, "ok" : 1 }
3971          { "_id" : "cat", "value" : 63 }
3972          { "_id" : "dog", "value" : 42 }
3973          { "_id" : "mouse", "value" : 21 }
3974          more complicated map reduce
3975          { "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 }
3976
3977   Using libmongoc in a Microsoft Visual Studio project
3978       Download and install libmongoc on your system, then open Visual Studio,
3979       select "File→New→Project...", and create a new Win32  Console  Applica‐
3980       tion.  [image]
3981
3982       Remember to switch the platform from 32-bit to 64-bit: [image]
3983
3984       Right-click  on  your  console application in the Solution Explorer and
3985       select "Properties". Choose to  edit  properties  for  "All  Configura‐
3986       tions",  expand  the  "C/C++"  options and choose "General". Add to the
3987       "Additional Include Directories" these paths:
3988
3989          C:\mongo-c-driver\include\libbson-1.0
3990          C:\mongo-c-driver\include\libmongoc-1.0
3991       [image]
3992
3993       (If you chose a different CMAKE_INSTALL_PREFIX when you ran CMake, your
3994       include paths will be different.)
3995
3996       Also  in  the Properties dialog, expand the "Linker" options and choose
3997       "Input", and add to the "Additional Dependencies" these libraries:
3998
3999          C:\mongo-c-driver\lib\bson-1.0.lib
4000          C:\mongo-c-driver\lib\mongoc-1.0.lib
4001       [image]
4002
4003       Adding these libraries as dependencies provides linker symbols to build
4004       your  application,  but  to  actually run it, libbson's and libmongoc's
4005       DLLs must be in your executable path. Select "Debugging" in the Proper‐
4006       ties dialog, and set the "Environment" option to:
4007
4008          PATH=c:/mongo-c-driver/bin
4009       [image]
4010
4011       Finally, include "mongoc/mongoc.h" in your project's "stdafx.h":
4012
4013          #include <mongoc/mongoc.h>
4014
4015   Static linking
4016       Following  the  instructions  above,  you  have dynamically linked your
4017       application to the libbson and libmongoc  DLLs.  This  is  usually  the
4018       right  choice.  If  you  want  to  link statically instead, update your
4019       "Additional  Dependencies"  list  by  removing  bson-1.0.lib  and  mon‐
4020       goc-1.0.lib and replacing them with these libraries:
4021
4022          C:\mongo-c-driver\lib\bson-static-1.0.lib
4023          C:\mongo-c-driver\lib\mongoc-static-1.0.lib
4024          ws2_32.lib
4025          Secur32.lib
4026          Crypt32.lib
4027          BCrypt.lib
4028       [image]
4029
4030       (To  explain  the purpose of each library: bson-static-1.0.lib and mon‐
4031       goc-static-1.0.lib are static archives of the driver code.  The  socket
4032       library  ws2_32  is  required by libbson, which uses the socket routine
4033       gethostname to help guarantee ObjectId uniqueness. The  BCrypt  library
4034       is  used  by  libmongoc for SSL connections to MongoDB, and Secur32 and
4035       Crypt32 are required for enterprise authentication  methods  like  Ker‐
4036       beros.)
4037
4038       Finally,  define  two preprocessor symbols before including mongoc/mon‐
4039       goc.h in your stdafx.h:
4040
4041          #define BSON_STATIC
4042          #define MONGOC_STATIC
4043          #include <mongoc/mongoc.h>
4044
4045       Making these changes to your project is only required for static  link‐
4046       ing;  for  most people, the dynamic-linking instructions above are pre‐
4047       ferred.
4048
4049   Next Steps
4050       Now you can build and debug applications  in  Visual  Studio  that  use
4051       libbson  and  libmongoc. Proceed to making-a-connection in the tutorial
4052       to learn how connect to MongoDB and perform operations.
4053
4054   Creating Indexes
4055       To create indexes on a MongoDB collection,  execute  the  createIndexes
4056       command   with   a  command  function  like  mongoc_database_write_com‐
4057       mand_with_opts or  mongoc_collection_write_command_with_opts.  See  the
4058       MongoDB Manual entry for the createIndexes command for details.
4059
4060   Example
4061       example-create-indexes.c.INDENT 0.0
4062
4063          /* gcc example-create-indexes.c -o example-create-indexes $(pkg-config --cflags
4064           * --libs libmongoc-1.0) */
4065
4066          /* ./example-create-indexes [CONNECTION_STRING [COLLECTION_NAME]] */
4067
4068          #include <mongoc/mongoc.h>
4069          #include <stdio.h>
4070          #include <stdlib.h>
4071
4072          int
4073          main (int argc, char *argv[])
4074          {
4075             mongoc_client_t *client;
4076             const char *uri_string =
4077                "mongodb://127.0.0.1/?appname=create-indexes-example";
4078             mongoc_uri_t *uri;
4079             mongoc_database_t *db;
4080             const char *collection_name = "test";
4081             bson_t keys;
4082             char *index_name;
4083             bson_t *create_indexes;
4084             bson_t reply;
4085             char *reply_str;
4086             bson_error_t error;
4087             bool r;
4088
4089             mongoc_init ();
4090
4091             if (argc > 1) {
4092                uri_string = argv[1];
4093             }
4094
4095             if (argc > 2) {
4096                collection_name = argv[2];
4097             }
4098
4099             uri = mongoc_uri_new_with_error (uri_string, &error);
4100             if (!uri) {
4101                fprintf (stderr,
4102                         "failed to parse URI: %s\n"
4103                         "error message:       %s\n",
4104                         uri_string,
4105                         error.message);
4106                return EXIT_FAILURE;
4107             }
4108
4109             client = mongoc_client_new_from_uri (uri);
4110             if (!client) {
4111                return EXIT_FAILURE;
4112             }
4113
4114             mongoc_client_set_error_api (client, 2);
4115             db = mongoc_client_get_database (client, "test");
4116
4117             /* ascending index on field "x" */
4118             bson_init (&keys);
4119             BSON_APPEND_INT32 (&keys, "x", 1);
4120             index_name = mongoc_collection_keys_to_index_string (&keys);
4121             create_indexes = BCON_NEW ("createIndexes",
4122                                        BCON_UTF8 (collection_name),
4123                                        "indexes",
4124                                        "[",
4125                                        "{",
4126                                        "key",
4127                                        BCON_DOCUMENT (&keys),
4128                                        "name",
4129                                        BCON_UTF8 (index_name),
4130                                        "}",
4131                                        "]");
4132
4133             r = mongoc_database_write_command_with_opts (
4134                db, create_indexes, NULL /* opts */, &reply, &error);
4135
4136             reply_str = bson_as_json (&reply, NULL);
4137             printf ("%s\n", reply_str);
4138
4139             if (!r) {
4140                fprintf (stderr, "Error in createIndexes: %s\n", error.message);
4141             }
4142
4143             bson_free (index_name);
4144             bson_free (reply_str);
4145             bson_destroy (&reply);
4146             bson_destroy (create_indexes);
4147             mongoc_database_destroy (db);
4148             mongoc_uri_destroy (uri);
4149             mongoc_client_destroy (client);
4150
4151             mongoc_cleanup ();
4152
4153             return r ? EXIT_SUCCESS : EXIT_FAILURE;
4154          }
4155
4156
4157   Aids for Debugging
4158   GDB
4159       This repository contains a .gdbinit file that contains helper functions
4160       to  aid  debugging  of  data  structures.  GDB  will  load  this   file
4161       automatically  if  you  have  added  the  directory  which contains the
4162       .gdbinit file to GDB's auto-load safe-path, and you start GDB from  the
4163       directory which holds the .gdbinit file.
4164
4165       You  can  see  the  safe-path  with  show  auto-load safe-path on a GDB
4166       prompt. You can configure it by setting it in ~/.gdbinit with:
4167
4168          add-auto-load-safe-path /path/to/mongo-c-driver
4169
4170       If you haven't added the path to your auto-load safe-path, or start GDB
4171       in another directory, load the file with:
4172
4173          source path/to/mongo-c-driver/.gdbinit
4174
4175       The  .gdbinit file defines the printbson function, which shows the con‐
4176       tents of a bson_t * variable.  If you have a  local  bson_t,  then  you
4177       must prefix the variable with a &.
4178
4179       An example GDB session looks like:
4180
4181          (gdb) printbson bson
4182          ALLOC [0x555556cd7310 + 0] (len=475)
4183          {
4184              'bool' : true,
4185              'int32' : NumberInt("42"),
4186              'int64' : NumberLong("3000000042"),
4187              'string' : "Stŕìñg",
4188              'objectId' : ObjectID("5A1442F3122D331C3C6757E1"),
4189              'utcDateTime' : UTCDateTime(1511277299031),
4190              'arrayOfInts' : [
4191                  '0' : NumberInt("1"),
4192                  '1' : NumberInt("2")
4193              ],
4194              'embeddedDocument' : {
4195                  'arrayOfStrings' : [
4196                      '0' : "one",
4197                      '1' : "two"
4198                  ],
4199                  'double' : 2.718280,
4200                  'notherDoc' : {
4201                      'true' : NumberInt("1"),
4202                      'false' : false
4203                  }
4204              },
4205              'binary' : Binary("02", "3031343532333637"),
4206              'regex' : Regex("@[a-z]+@", "im"),
4207              'null' : null,
4208              'js' : JavaScript("print foo"),
4209              'jsws' : JavaScript("print foo") with scope: {
4210                  'f' : NumberInt("42"),
4211                  'a' : [
4212                      '0' : 3.141593,
4213                      '1' : 2.718282
4214                  ]
4215              },
4216              'timestamp' : Timestamp(4294967295, 4294967295),
4217              'double' : 3.141593
4218          }
4219
4220   LLDB
4221       This  repository also includes a script that customizes LLDB's standard
4222       print command to print a bson_t or bson_t * as JSON:
4223
4224          (lldb) print b
4225          (bson_t) $0 = {"x": 1, "y": 2}
4226
4227       The custom bson command provides more options:
4228
4229          (lldb) bson --verbose b
4230          len=19
4231          flags=INLINE|STATIC
4232          {
4233            "x": 1,
4234            "y": 2
4235          }
4236          (lldb) bson --raw b
4237          '\x13\x00\x00\x00\x10x\x00\x01\x00\x00\x00\x10y\x00\x02\x00\x00\x00\x00'
4238
4239       Type help bson for a list of options.
4240
4241       The script requires a build of  libbson  with  debug  symbols,  and  an
4242       installation of PyMongo. Install PyMongo with:
4243
4244          python -m pip install pymongo
4245
4246       If  you  see  "No module named pip" then you must install pip, then run
4247       the previous command again.
4248
4249       Create a file ~/.lldbinit containing:
4250
4251          command script import /path/to/mongo-c-driver/lldb_bson.py
4252
4253       If you see "bson command installed by lldb_bson" at  the  beginning  of
4254       your LLDB session, you've installed the script correctly.
4255
4256   Using Client-Side Field Level Encryption
4257       New  in  MongoDB 4.2, Client-Side Field Level Encryption (also referred
4258       to as Client-Side Encryption) allows administrators and  developers  to
4259       encrypt  specific  data  fields in addition to other MongoDB encryption
4260       features.
4261
4262       With Client-Side Encryption, developers can encrypt fields client  side
4263       without   any  server-side  configuration  or  directives.  Client-Side
4264       Encryption supports workloads where applications  must  guarantee  that
4265       unauthorized  parties, including server administrators, cannot read the
4266       encrypted data.
4267
4268       Automatic encryption, where sensitive fields in commands are  encrypted
4269       automatically,  requires  an Enterprise-only process to do query analy‐
4270       sis.
4271
4272   Installation
4273   libmongocrypt
4274       There is a separate library,  libmongocrypt,  that  must  be  installed
4275       prior to configuring libmongoc to enable Client-Side Encryption.
4276
4277       libmongocrypt  depends  on libbson. To build libmongoc with Client-Side
4278       Encryption support you must:
4279
4280       1. Install libbson
4281
4282       2. Build and install libmongocrypt
4283
4284       3. Build libmongoc
4285
4286       To install libbson, follow the instructions to install with  a  package
4287       manager:  Install  libbson  with a Package Manager or build from source
4288       with cmake (disable building libmongoc with -DENABLE_MONGOC=OFF):
4289
4290          $ cd mongo-c-driver
4291          $ mkdir cmake-build && cd cmake-build
4292          $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF -DENABLE_MONGOC=OFF ..
4293          $ cmake --build . --target install
4294
4295       To build and install libmongocrypt, clone the repository and  configure
4296       as follows:
4297
4298          $ cd libmongocrypt
4299          $ mkdir cmake-build && cd cmake-build
4300          $ cmake -DENABLE_SHARED_BSON=ON ..
4301          $ cmake --build . --target install
4302
4303       Then,  you  should  be able to build libmongoc with Client-Side Encryp‐
4304       tion.
4305
4306          $ cd mongo-c-driver
4307          $ mkdir cmake-build && cd cmake-build
4308          $ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF -DENABLE_MONGOC=ON -DENABLE_CLIENT_SIDE_ENCRYPTION=ON ..
4309          $ cmake --build . --target install
4310
4311   mongocryptd
4312       The mongocryptd binary is required for automatic Client-Side Encryption
4313       and  is  included as a component in the MongoDB Enterprise Server pack‐
4314       age. For detailed installation instructions see the MongoDB  documenta‐
4315       tion on mongocryptd.
4316
4317       mongocryptd performs the following:
4318
4319       · Parses  the automatic encryption rules specified to the database con‐
4320         nection. If the JSON schema  contains  invalid  automatic  encryption
4321         syntax  or  any  document  validation  syntax, mongocryptd returns an
4322         error.
4323
4324       · Uses the specified automatic encryption rules to mark fields in  read
4325         and write operations for encryption.
4326
4327       · Rejects read/write operations that may return unexpected or incorrect
4328         results when applied to an encrypted field. For supported and  unsup‐
4329         ported  operations, see Read/Write Support with Automatic Field Level
4330         Encryption.
4331
4332       A mongoc_client_t configured with auto  encryption  will  automatically
4333       spawn the mongocryptd process from the application's PATH. Applications
4334       can control the spawning behavior as part of the  automatic  encryption
4335       options.  For example, to set a custom path to the mongocryptd process,
4336       set     the     mongocryptdSpawnPath      with      mongoc_auto_encryp‐
4337       tion_opts_set_extra().
4338
4339          bson_t *extra = BCON_NEW ("mongocryptdSpawnPath", "/path/to/mongocryptd");
4340          mongoc_auto_encryption_opts_set_extra (opts, extra);
4341
4342       To  control the logging output of mongocryptd pass mongocryptdSpawnArgs
4343       to mongoc_auto_encryption_opts_set_extra():
4344
4345          bson_t *extra = BCON_NEW ("mongocryptdSpawnArgs",
4346             "[", "--logpath=/path/to/mongocryptd.log", "--logappend", "]");
4347          mongoc_auto_encryption_opts_set_extra (opts, extra);
4348
4349       If your application wishes to manage the mongocryptd process  manually,
4350       it is possible to disable spawning mongocryptd:
4351
4352          bson_t *extra = BCON_NEW ("mongocryptdBypassSpawn",
4353             BCON_BOOL(true), "mongocryptdURI", "mongodb://localhost:27020");
4354          mongoc_auto_encryption_opts_set_extra (opts, extra);
4355
4356       mongocryptd  is  only  responsible for supporting automatic Client-Side
4357       Encryption in the driver and does not itself perform any encryption  or
4358       decryption.
4359
4360   Automatic Client-Side Field Level Encryption
4361       Automatic   Client-Side   Encryption   is   enabled   by  calling  mon‐
4362       goc_client_enable_auto_encryption() on a mongoc_client_t. The following
4363       examples  show  how to set up automatic client-side field level encryp‐
4364       tion using mongoc_client_encryption_t to create a new  encryption  data
4365       key.
4366
4367       NOTE:
4368          Automatic  client-side  field  level encryption requires MongoDB 4.2
4369          enterprise or a MongoDB 4.2 Atlas cluster. The community version  of
4370          the server supports automatic decryption as well as Explicit Encryp‐
4371          tion.
4372
4373   Providing Local Automatic Encryption Rules
4374       The following example shows how to specify automatic  encryption  rules
4375       using     a     schema     map     set     with     mongoc_auto_encryp‐
4376       tion_opts_set_schema_map().  The   automatic   encryption   rules   are
4377       expressed using a strict subset of the JSON Schema syntax.
4378
4379       Supplying  a  schema  map  provides  more security than relying on JSON
4380       Schemas obtained from the  server.  It  protects  against  a  malicious
4381       server  advertising  a  false JSON Schema, which could trick the client
4382       into sending unencrypted data that should be encrypted.
4383
4384       JSON Schemas supplied in the schema map only apply to configuring auto‐
4385       matic client-side field level encryption. Other validation rules in the
4386       JSON schema will not be enforced by the driver and will  result  in  an
4387       error: client-side-encryption-schema-map.c.INDENT 0.0
4388
4389          #include <mongoc/mongoc.h>
4390          #include <stdio.h>
4391          #include <stdlib.h>
4392
4393          #include "client-side-encryption-helpers.h"
4394
4395          /* Helper method to create a new data key in the key vault, a schema to use that
4396           * key, and writes the schema to a file for later use. */
4397          static bool
4398          create_schema_file (bson_t *kms_providers,
4399                              const char *keyvault_db,
4400                              const char *keyvault_coll,
4401                              mongoc_client_t *keyvault_client,
4402                              bson_error_t *error)
4403          {
4404             mongoc_client_encryption_t *client_encryption = NULL;
4405             mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
4406             mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
4407             bson_value_t datakey_id = {0};
4408             char *keyaltnames[] = {"mongoc_encryption_example_1"};
4409             bson_t *schema = NULL;
4410             char *schema_string = NULL;
4411             size_t schema_string_len;
4412             FILE *outfile = NULL;
4413             bool ret = false;
4414
4415             client_encryption_opts = mongoc_client_encryption_opts_new ();
4416             mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
4417                                                              kms_providers);
4418             mongoc_client_encryption_opts_set_keyvault_namespace (
4419                client_encryption_opts, keyvault_db, keyvault_coll);
4420             mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
4421                                                                keyvault_client);
4422
4423             client_encryption =
4424                mongoc_client_encryption_new (client_encryption_opts, error);
4425             if (!client_encryption) {
4426                goto fail;
4427             }
4428
4429             /* Create a new data key and json schema for the encryptedField.
4430              * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
4431              */
4432             datakey_opts = mongoc_client_encryption_datakey_opts_new ();
4433             mongoc_client_encryption_datakey_opts_set_keyaltnames (
4434                datakey_opts, keyaltnames, 1);
4435             if (!mongoc_client_encryption_create_datakey (
4436                    client_encryption, "local", datakey_opts, &datakey_id, error)) {
4437                goto fail;
4438             }
4439
4440             /* Create a schema describing that "encryptedField" is a string encrypted
4441              * with the newly created data key using deterministic encryption. */
4442             schema = BCON_NEW ("properties",
4443                                "{",
4444                                "encryptedField",
4445                                "{",
4446                                "encrypt",
4447                                "{",
4448                                "keyId",
4449                                "[",
4450                                BCON_BIN (datakey_id.value.v_binary.subtype,
4451                                          datakey_id.value.v_binary.data,
4452                                          datakey_id.value.v_binary.data_len),
4453                                "]",
4454                                "bsonType",
4455                                "string",
4456                                "algorithm",
4457                                MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
4458                                "}",
4459                                "}",
4460                                "}",
4461                                "bsonType",
4462                                "object");
4463
4464             /* Use canonical JSON so that other drivers and tools will be
4465              * able to parse the MongoDB extended JSON file. */
4466             schema_string = bson_as_canonical_extended_json (schema, &schema_string_len);
4467             outfile = fopen ("jsonSchema.json", "w");
4468             if (0 == fwrite (schema_string, sizeof (char), schema_string_len, outfile)) {
4469                fprintf (stderr, "failed to write to file\n");
4470                goto fail;
4471             }
4472
4473             ret = true;
4474          fail:
4475             mongoc_client_encryption_destroy (client_encryption);
4476             mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
4477             mongoc_client_encryption_opts_destroy (client_encryption_opts);
4478             bson_free (schema_string);
4479             bson_destroy (schema);
4480             bson_value_destroy (&datakey_id);
4481             if (outfile) {
4482                fclose (outfile);
4483             }
4484             return true;
4485          }
4486
4487          /* This example demonstrates how to use automatic encryption with a client-side
4488           * schema map using the enterprise version of MongoDB */
4489          int
4490          main (int argc, char **argv)
4491          {
4492          /* The collection used to store the encryption data keys. */
4493          #define KEYVAULT_DB "encryption"
4494          #define KEYVAULT_COLL "__libmongocTestKeyVault"
4495          /* The collection used to store the encrypted documents in this example. */
4496          #define ENCRYPTED_DB "test"
4497          #define ENCRYPTED_COLL "coll"
4498
4499             int exit_status = EXIT_FAILURE;
4500             bool ret;
4501             uint8_t *local_masterkey = NULL;
4502             uint32_t local_masterkey_len;
4503             bson_t *kms_providers = NULL;
4504             bson_error_t error = {0};
4505             bson_t *index_keys = NULL;
4506             char *index_name = NULL;
4507             bson_t *create_index_cmd = NULL;
4508             bson_json_reader_t *reader = NULL;
4509             bson_t schema = BSON_INITIALIZER;
4510             bson_t *schema_map = NULL;
4511
4512             /* The MongoClient used to access the key vault (keyvault_namespace). */
4513             mongoc_client_t *keyvault_client = NULL;
4514             mongoc_collection_t *keyvault_coll = NULL;
4515             mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
4516             mongoc_client_t *client = NULL;
4517             mongoc_collection_t *coll = NULL;
4518             bson_t *to_insert = NULL;
4519             mongoc_client_t *unencrypted_client = NULL;
4520             mongoc_collection_t *unencrypted_coll = NULL;
4521
4522             mongoc_init ();
4523
4524             /* Configure the master key. This must be the same master key that was used
4525              * to create the encryption key. */
4526             local_masterkey =
4527                hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
4528             if (!local_masterkey || local_masterkey_len != 96) {
4529                fprintf (stderr,
4530                         "Specify LOCAL_MASTERKEY environment variable as a "
4531                         "secure random 96 byte hex value.\n");
4532                goto fail;
4533             }
4534
4535             kms_providers = BCON_NEW ("local",
4536                                       "{",
4537                                       "key",
4538                                       BCON_BIN (0, local_masterkey, local_masterkey_len),
4539                                       "}");
4540
4541             /* Set up the key vault for this example. */
4542             keyvault_client = mongoc_client_new (
4543                "mongodb://localhost/?appname=client-side-encryption-keyvault");
4544             keyvault_coll = mongoc_client_get_collection (
4545                keyvault_client, KEYVAULT_DB, KEYVAULT_COLL);
4546             mongoc_collection_drop (keyvault_coll, NULL);
4547
4548             /* Create a unique index to ensure that two data keys cannot share the same
4549              * keyAltName. This is recommended practice for the key vault. */
4550             index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
4551             index_name = mongoc_collection_keys_to_index_string (index_keys);
4552             create_index_cmd = BCON_NEW ("createIndexes",
4553                                          KEYVAULT_COLL,
4554                                          "indexes",
4555                                          "[",
4556                                          "{",
4557                                          "key",
4558                                          BCON_DOCUMENT (index_keys),
4559                                          "name",
4560                                          index_name,
4561                                          "unique",
4562                                          BCON_BOOL (true),
4563                                          "partialFilterExpression",
4564                                          "{",
4565                                          "keyAltNames",
4566                                          "{",
4567                                          "$exists",
4568                                          BCON_BOOL (true),
4569                                          "}",
4570                                          "}",
4571                                          "}",
4572                                          "]");
4573             ret = mongoc_client_command_simple (keyvault_client,
4574                                                 KEYVAULT_DB,
4575                                                 create_index_cmd,
4576                                                 NULL /* read prefs */,
4577                                                 NULL /* reply */,
4578                                                 &error);
4579
4580             if (!ret) {
4581                goto fail;
4582             }
4583
4584             /* Create a new data key and a schema using it for encryption. Save the
4585              * schema to the file jsonSchema.json */
4586             ret = create_schema_file (
4587                kms_providers, KEYVAULT_DB, KEYVAULT_COLL, keyvault_client, &error);
4588
4589             if (!ret) {
4590                goto fail;
4591             }
4592
4593             /* Load the JSON Schema and construct the local schema_map option. */
4594             reader = bson_json_reader_new_from_file ("jsonSchema.json", &error);
4595             if (!reader) {
4596                goto fail;
4597             }
4598
4599             bson_json_reader_read (reader, &schema, &error);
4600
4601             /* Construct the schema map, mapping the namespace of the collection to the
4602              * schema describing encryption. */
4603             schema_map =
4604                BCON_NEW (ENCRYPTED_DB "." ENCRYPTED_COLL, BCON_DOCUMENT (&schema));
4605
4606             auto_encryption_opts = mongoc_auto_encryption_opts_new ();
4607             mongoc_auto_encryption_opts_set_keyvault_client (auto_encryption_opts,
4608                                                              keyvault_client);
4609             mongoc_auto_encryption_opts_set_keyvault_namespace (
4610                auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
4611             mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
4612                                                            kms_providers);
4613             mongoc_auto_encryption_opts_set_schema_map (auto_encryption_opts,
4614                                                         schema_map);
4615
4616             client =
4617                mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
4618
4619             /* Enable automatic encryption. It will determine that encryption is
4620              * necessary from the schema map instead of relying on the server to provide
4621              * a schema. */
4622             ret = mongoc_client_enable_auto_encryption (
4623                client, auto_encryption_opts, &error);
4624             if (!ret) {
4625                goto fail;
4626             }
4627
4628             coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
4629
4630             /* Clear old data */
4631             mongoc_collection_drop (coll, NULL);
4632
4633             to_insert = BCON_NEW ("encryptedField", "123456789");
4634             ret = mongoc_collection_insert_one (
4635                coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
4636             if (!ret) {
4637                goto fail;
4638             }
4639             printf ("decrypted document: ");
4640             if (!print_one_document (coll, &error)) {
4641                goto fail;
4642             }
4643             printf ("\n");
4644
4645             unencrypted_client = mongoc_client_new (
4646                "mongodb://localhost/?appname=client-side-encryption-unencrypted");
4647             unencrypted_coll = mongoc_client_get_collection (
4648                unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
4649             printf ("encrypted document: ");
4650             if (!print_one_document (unencrypted_coll, &error)) {
4651                goto fail;
4652             }
4653             printf ("\n");
4654
4655             exit_status = EXIT_SUCCESS;
4656          fail:
4657             if (error.code) {
4658                fprintf (stderr, "error: %s\n", error.message);
4659             }
4660
4661             bson_free (local_masterkey);
4662             bson_destroy (kms_providers);
4663             mongoc_collection_destroy (keyvault_coll);
4664             bson_destroy (index_keys);
4665             bson_free (index_name);
4666             bson_destroy (create_index_cmd);
4667             bson_json_reader_destroy (reader);
4668             mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
4669             mongoc_collection_destroy (coll);
4670             mongoc_client_destroy (client);
4671             bson_destroy (to_insert);
4672             mongoc_collection_destroy (unencrypted_coll);
4673             mongoc_client_destroy (unencrypted_client);
4674             mongoc_client_destroy (keyvault_client);
4675             bson_destroy (&schema);
4676             bson_destroy (schema_map);
4677             mongoc_cleanup ();
4678             return exit_status;
4679          }
4680
4681   Server-Side Field Level Encryption Enforcement
4682       The  MongoDB  4.2  server  supports  using schema validation to enforce
4683       encryption of specific fields in a collection. This  schema  validation
4684       will  prevent  an application from inserting unencrypted values for any
4685       fields marked with the "encrypt" JSON schema keyword.
4686
4687       The following example shows how to set up automatic  client-side  field
4688       level  encryption  using  mongoc_client_encryption_t  to  create  a new
4689       encryption data key and create a collection with the Automatic  Encryp‐
4690       tion  JSON Schema Syntax: client-side-encryption-server-schema.c.INDENT
4691       0.0
4692
4693          #include <mongoc/mongoc.h>
4694          #include <stdio.h>
4695          #include <stdlib.h>
4696
4697          #include "client-side-encryption-helpers.h"
4698
4699          /* Helper method to create and return a JSON schema to use for encryption.
4700          The caller will use the returned schema for server-side encryption validation.
4701          */
4702          static bson_t *
4703          create_schema (bson_t *kms_providers,
4704                         const char *keyvault_db,
4705                         const char *keyvault_coll,
4706                         mongoc_client_t *keyvault_client,
4707                         bson_error_t *error)
4708          {
4709             mongoc_client_encryption_t *client_encryption = NULL;
4710             mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
4711             mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
4712             bson_value_t datakey_id = {0};
4713             char *keyaltnames[] = {"mongoc_encryption_example_2"};
4714             bson_t *schema = NULL;
4715
4716             client_encryption_opts = mongoc_client_encryption_opts_new ();
4717             mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
4718                                                              kms_providers);
4719             mongoc_client_encryption_opts_set_keyvault_namespace (
4720                client_encryption_opts, keyvault_db, keyvault_coll);
4721             mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
4722                                                                keyvault_client);
4723
4724             client_encryption =
4725                mongoc_client_encryption_new (client_encryption_opts, error);
4726             if (!client_encryption) {
4727                goto fail;
4728             }
4729
4730             /* Create a new data key and json schema for the encryptedField.
4731              * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
4732              */
4733             datakey_opts = mongoc_client_encryption_datakey_opts_new ();
4734             mongoc_client_encryption_datakey_opts_set_keyaltnames (
4735                datakey_opts, keyaltnames, 1);
4736             if (!mongoc_client_encryption_create_datakey (
4737                    client_encryption, "local", datakey_opts, &datakey_id, error)) {
4738                goto fail;
4739             }
4740
4741             /* Create a schema describing that "encryptedField" is a string encrypted
4742              * with the newly created data key using deterministic encryption. */
4743             schema = BCON_NEW ("properties",
4744                                "{",
4745                                "encryptedField",
4746                                "{",
4747                                "encrypt",
4748                                "{",
4749                                "keyId",
4750                                "[",
4751                                BCON_BIN (datakey_id.value.v_binary.subtype,
4752                                          datakey_id.value.v_binary.data,
4753                                          datakey_id.value.v_binary.data_len),
4754                                "]",
4755                                "bsonType",
4756                                "string",
4757                                "algorithm",
4758                                MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC,
4759                                "}",
4760                                "}",
4761                                "}",
4762                                "bsonType",
4763                                "object");
4764
4765          fail:
4766             mongoc_client_encryption_destroy (client_encryption);
4767             mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
4768             mongoc_client_encryption_opts_destroy (client_encryption_opts);
4769             bson_value_destroy (&datakey_id);
4770             return schema;
4771          }
4772
4773          /* This example demonstrates how to use automatic encryption with a server-side
4774           * schema using the enterprise version of MongoDB */
4775          int
4776          main (int argc, char **argv)
4777          {
4778          /* The collection used to store the encryption data keys. */
4779          #define KEYVAULT_DB "encryption"
4780          #define KEYVAULT_COLL "__libmongocTestKeyVault"
4781          /* The collection used to store the encrypted documents in this example. */
4782          #define ENCRYPTED_DB "test"
4783          #define ENCRYPTED_COLL "coll"
4784
4785             int exit_status = EXIT_FAILURE;
4786             bool ret;
4787             uint8_t *local_masterkey = NULL;
4788             uint32_t local_masterkey_len;
4789             bson_t *kms_providers = NULL;
4790             bson_error_t error = {0};
4791             bson_t *index_keys = NULL;
4792             char *index_name = NULL;
4793             bson_t *create_index_cmd = NULL;
4794             bson_json_reader_t *reader = NULL;
4795             bson_t *schema = NULL;
4796
4797             /* The MongoClient used to access the key vault (keyvault_namespace). */
4798             mongoc_client_t *keyvault_client = NULL;
4799             mongoc_collection_t *keyvault_coll = NULL;
4800             mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
4801             mongoc_client_t *client = NULL;
4802             mongoc_collection_t *coll = NULL;
4803             bson_t *to_insert = NULL;
4804             mongoc_client_t *unencrypted_client = NULL;
4805             mongoc_collection_t *unencrypted_coll = NULL;
4806             bson_t *create_cmd = NULL;
4807             bson_t *create_cmd_opts = NULL;
4808             mongoc_write_concern_t *wc = NULL;
4809
4810             mongoc_init ();
4811
4812             /* Configure the master key. This must be the same master key that was used
4813              * to create
4814              * the encryption key. */
4815             local_masterkey =
4816                hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
4817             if (!local_masterkey || local_masterkey_len != 96) {
4818                fprintf (stderr,
4819                         "Specify LOCAL_MASTERKEY environment variable as a "
4820                         "secure random 96 byte hex value.\n");
4821                goto fail;
4822             }
4823
4824             kms_providers = BCON_NEW ("local",
4825                                       "{",
4826                                       "key",
4827                                       BCON_BIN (0, local_masterkey, local_masterkey_len),
4828                                       "}");
4829
4830             /* Set up the key vault for this example. */
4831             keyvault_client = mongoc_client_new (
4832                "mongodb://localhost/?appname=client-side-encryption-keyvault");
4833             keyvault_coll = mongoc_client_get_collection (
4834                keyvault_client, KEYVAULT_DB, KEYVAULT_COLL);
4835             mongoc_collection_drop (keyvault_coll, NULL);
4836
4837             /* Create a unique index to ensure that two data keys cannot share the same
4838              * keyAltName. This is recommended practice for the key vault. */
4839             index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
4840             index_name = mongoc_collection_keys_to_index_string (index_keys);
4841             create_index_cmd = BCON_NEW ("createIndexes",
4842                                          KEYVAULT_COLL,
4843                                          "indexes",
4844                                          "[",
4845                                          "{",
4846                                          "key",
4847                                          BCON_DOCUMENT (index_keys),
4848                                          "name",
4849                                          index_name,
4850                                          "unique",
4851                                          BCON_BOOL (true),
4852                                          "partialFilterExpression",
4853                                          "{",
4854                                          "keyAltNames",
4855                                          "{",
4856                                          "$exists",
4857                                          BCON_BOOL (true),
4858                                          "}",
4859                                          "}",
4860                                          "}",
4861                                          "]");
4862             ret = mongoc_client_command_simple (keyvault_client,
4863                                                 KEYVAULT_DB,
4864                                                 create_index_cmd,
4865                                                 NULL /* read prefs */,
4866                                                 NULL /* reply */,
4867                                                 &error);
4868
4869             if (!ret) {
4870                goto fail;
4871             }
4872
4873             auto_encryption_opts = mongoc_auto_encryption_opts_new ();
4874             mongoc_auto_encryption_opts_set_keyvault_client (auto_encryption_opts,
4875                                                              keyvault_client);
4876             mongoc_auto_encryption_opts_set_keyvault_namespace (
4877                auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
4878             mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
4879                                                            kms_providers);
4880             schema = create_schema (
4881                kms_providers, KEYVAULT_DB, KEYVAULT_COLL, keyvault_client, &error);
4882
4883             if (!schema) {
4884                goto fail;
4885             }
4886
4887             client =
4888                mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
4889             ret = mongoc_client_enable_auto_encryption (
4890                client, auto_encryption_opts, &error);
4891             if (!ret) {
4892                goto fail;
4893             }
4894
4895             coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
4896
4897             /* Clear old data */
4898             mongoc_collection_drop (coll, NULL);
4899
4900             /* Create the collection with the encryption JSON Schema. */
4901             create_cmd = BCON_NEW ("create",
4902                                    ENCRYPTED_COLL,
4903                                    "validator",
4904                                    "{",
4905                                    "$jsonSchema",
4906                                    BCON_DOCUMENT (schema),
4907                                    "}");
4908             wc = mongoc_write_concern_new ();
4909             mongoc_write_concern_set_wmajority (wc, 0);
4910             create_cmd_opts = bson_new ();
4911             mongoc_write_concern_append (wc, create_cmd_opts);
4912             ret = mongoc_client_command_with_opts (client,
4913                                                    ENCRYPTED_DB,
4914                                                    create_cmd,
4915                                                    NULL /* read prefs */,
4916                                                    create_cmd_opts,
4917                                                    NULL /* reply */,
4918                                                    &error);
4919             if (!ret) {
4920                goto fail;
4921             }
4922
4923             to_insert = BCON_NEW ("encryptedField", "123456789");
4924             ret = mongoc_collection_insert_one (
4925                coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
4926             if (!ret) {
4927                goto fail;
4928             }
4929             printf ("decrypted document: ");
4930             if (!print_one_document (coll, &error)) {
4931                goto fail;
4932             }
4933             printf ("\n");
4934
4935             unencrypted_client = mongoc_client_new (
4936                "mongodb://localhost/?appname=client-side-encryption-unencrypted");
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             /* Expect a server-side error if inserting with the unencrypted collection.
4946              */
4947             ret = mongoc_collection_insert_one (
4948                unencrypted_coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
4949             if (!ret) {
4950                printf ("insert with unencrypted collection failed: %s\n", error.message);
4951                memset (&error, 0, sizeof (error));
4952             }
4953
4954             exit_status = EXIT_SUCCESS;
4955          fail:
4956             if (error.code) {
4957                fprintf (stderr, "error: %s\n", error.message);
4958             }
4959
4960             bson_free (local_masterkey);
4961             bson_destroy (kms_providers);
4962             mongoc_collection_destroy (keyvault_coll);
4963             bson_destroy (index_keys);
4964             bson_free (index_name);
4965             bson_destroy (create_index_cmd);
4966             bson_json_reader_destroy (reader);
4967             mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
4968             mongoc_collection_destroy (coll);
4969             mongoc_client_destroy (client);
4970             bson_destroy (to_insert);
4971             mongoc_collection_destroy (unencrypted_coll);
4972             mongoc_client_destroy (unencrypted_client);
4973             mongoc_client_destroy (keyvault_client);
4974             bson_destroy (schema);
4975             bson_destroy (create_cmd);
4976             bson_destroy (create_cmd_opts);
4977             mongoc_write_concern_destroy (wc);
4978
4979             mongoc_cleanup ();
4980             return exit_status;
4981          }
4982
4983   Explicit Encryption
4984       Explicit encryption is a MongoDB community feature and does not use the
4985       mongocryptd  process.  Explicit  encryption  is  provided  by  the mon‐
4986       goc_client_encryption_t   class,   for   example:   client-side-encryp‐
4987       tion-explicit.c.INDENT 0.0
4988
4989          #include <mongoc/mongoc.h>
4990          #include <stdio.h>
4991          #include <stdlib.h>
4992
4993          #include "client-side-encryption-helpers.h"
4994
4995          /* This example demonstrates how to use explicit encryption and decryption using
4996           * the community version of MongoDB */
4997          int
4998          main (int argc, char **argv)
4999          {
5000          /* The collection used to store the encryption data keys. */
5001          #define KEYVAULT_DB "encryption"
5002          #define KEYVAULT_COLL "__libmongocTestKeyVault"
5003          /* The collection used to store the encrypted documents in this example. */
5004          #define ENCRYPTED_DB "test"
5005          #define ENCRYPTED_COLL "coll"
5006
5007             int exit_status = EXIT_FAILURE;
5008             bool ret;
5009             uint8_t *local_masterkey = NULL;
5010             uint32_t local_masterkey_len;
5011             bson_t *kms_providers = NULL;
5012             bson_error_t error = {0};
5013             bson_t *index_keys = NULL;
5014             char *index_name = NULL;
5015             bson_t *create_index_cmd = NULL;
5016             bson_t *schema = NULL;
5017             mongoc_client_t *client = NULL;
5018             mongoc_collection_t *coll = NULL;
5019             mongoc_collection_t *keyvault_coll = NULL;
5020             bson_t *to_insert = NULL;
5021             bson_t *create_cmd = NULL;
5022             bson_t *create_cmd_opts = NULL;
5023             mongoc_write_concern_t *wc = NULL;
5024             mongoc_client_encryption_t *client_encryption = NULL;
5025             mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
5026             mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
5027             char *keyaltnames[] = {"mongoc_encryption_example_3"};
5028             bson_value_t datakey_id = {0};
5029             bson_value_t encrypted_field = {0};
5030             bson_value_t to_encrypt = {0};
5031             mongoc_client_encryption_encrypt_opts_t *encrypt_opts = NULL;
5032             bson_value_t decrypted = {0};
5033
5034             mongoc_init ();
5035
5036             /* Configure the master key. This must be the same master key that was used
5037              * to create the encryption key. */
5038             local_masterkey =
5039                hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
5040             if (!local_masterkey || local_masterkey_len != 96) {
5041                fprintf (stderr,
5042                         "Specify LOCAL_MASTERKEY environment variable as a "
5043                         "secure random 96 byte hex value.\n");
5044                goto fail;
5045             }
5046
5047             kms_providers = BCON_NEW ("local",
5048                                       "{",
5049                                       "key",
5050                                       BCON_BIN (0, local_masterkey, local_masterkey_len),
5051                                       "}");
5052
5053             /* The mongoc_client_t used to read/write application data. */
5054             client =
5055                mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5056             coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
5057
5058             /* Clear old data */
5059             mongoc_collection_drop (coll, NULL);
5060
5061             /* Set up the key vault for this example. */
5062             keyvault_coll =
5063                mongoc_client_get_collection (client, KEYVAULT_DB, KEYVAULT_COLL);
5064             mongoc_collection_drop (keyvault_coll, NULL);
5065
5066             /* Create a unique index to ensure that two data keys cannot share the same
5067              * keyAltName. This is recommended practice for the key vault. */
5068             index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
5069             index_name = mongoc_collection_keys_to_index_string (index_keys);
5070             create_index_cmd = BCON_NEW ("createIndexes",
5071                                          KEYVAULT_COLL,
5072                                          "indexes",
5073                                          "[",
5074                                          "{",
5075                                          "key",
5076                                          BCON_DOCUMENT (index_keys),
5077                                          "name",
5078                                          index_name,
5079                                          "unique",
5080                                          BCON_BOOL (true),
5081                                          "partialFilterExpression",
5082                                          "{",
5083                                          "keyAltNames",
5084                                          "{",
5085                                          "$exists",
5086                                          BCON_BOOL (true),
5087                                          "}",
5088                                          "}",
5089                                          "}",
5090                                          "]");
5091             ret = mongoc_client_command_simple (client,
5092                                                 KEYVAULT_DB,
5093                                                 create_index_cmd,
5094                                                 NULL /* read prefs */,
5095                                                 NULL /* reply */,
5096                                                 &error);
5097
5098             if (!ret) {
5099                goto fail;
5100             }
5101
5102             client_encryption_opts = mongoc_client_encryption_opts_new ();
5103             mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
5104                                                              kms_providers);
5105             mongoc_client_encryption_opts_set_keyvault_namespace (
5106                client_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5107
5108             /* Set a mongoc_client_t to use for reading/writing to the key vault. This
5109              * can be the same mongoc_client_t used by the main application. */
5110             mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
5111                                                                client);
5112             client_encryption =
5113                mongoc_client_encryption_new (client_encryption_opts, &error);
5114             if (!client_encryption) {
5115                goto fail;
5116             }
5117
5118             /* Create a new data key for the encryptedField.
5119              * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
5120              */
5121             datakey_opts = mongoc_client_encryption_datakey_opts_new ();
5122             mongoc_client_encryption_datakey_opts_set_keyaltnames (
5123                datakey_opts, keyaltnames, 1);
5124             if (!mongoc_client_encryption_create_datakey (
5125                    client_encryption, "local", datakey_opts, &datakey_id, &error)) {
5126                goto fail;
5127             }
5128
5129             /* Explicitly encrypt a field */
5130             encrypt_opts = mongoc_client_encryption_encrypt_opts_new ();
5131             mongoc_client_encryption_encrypt_opts_set_algorithm (
5132                encrypt_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
5133             mongoc_client_encryption_encrypt_opts_set_keyid (encrypt_opts, &datakey_id);
5134             to_encrypt.value_type = BSON_TYPE_UTF8;
5135             to_encrypt.value.v_utf8.str = "123456789";
5136             to_encrypt.value.v_utf8.len = strlen (to_encrypt.value.v_utf8.str);
5137
5138             ret = mongoc_client_encryption_encrypt (
5139                client_encryption, &to_encrypt, encrypt_opts, &encrypted_field, &error);
5140             if (!ret) {
5141                goto fail;
5142             }
5143
5144             to_insert = bson_new ();
5145             BSON_APPEND_VALUE (to_insert, "encryptedField", &encrypted_field);
5146             ret = mongoc_collection_insert_one (
5147                coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5148             if (!ret) {
5149                goto fail;
5150             }
5151
5152             printf ("encrypted document: ");
5153             if (!print_one_document (coll, &error)) {
5154                goto fail;
5155             }
5156             printf ("\n");
5157
5158             /* Explicitly decrypt a field */
5159             ret = mongoc_client_encryption_decrypt (
5160                client_encryption, &encrypted_field, &decrypted, &error);
5161             if (!ret) {
5162                goto fail;
5163             }
5164             printf ("decrypted value: %s\n", decrypted.value.v_utf8.str);
5165
5166             exit_status = EXIT_SUCCESS;
5167          fail:
5168             if (error.code) {
5169                fprintf (stderr, "error: %s\n", error.message);
5170             }
5171
5172             bson_free (local_masterkey);
5173             bson_destroy (kms_providers);
5174             mongoc_collection_destroy (keyvault_coll);
5175             bson_destroy (index_keys);
5176             bson_free (index_name);
5177             bson_destroy (create_index_cmd);
5178             mongoc_collection_destroy (coll);
5179             mongoc_client_destroy (client);
5180             bson_destroy (to_insert);
5181             bson_destroy (schema);
5182             bson_destroy (create_cmd);
5183             bson_destroy (create_cmd_opts);
5184             mongoc_write_concern_destroy (wc);
5185             mongoc_client_encryption_destroy (client_encryption);
5186             mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
5187             mongoc_client_encryption_opts_destroy (client_encryption_opts);
5188             bson_value_destroy (&encrypted_field);
5189             mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts);
5190             bson_value_destroy (&decrypted);
5191             bson_value_destroy (&datakey_id);
5192
5193             mongoc_cleanup ();
5194             return exit_status;
5195          }
5196
5197   Explicit Encryption with Automatic Decryption
5198       Although automatic encryption requires MongoDB 4.2 enterprise or a Mon‐
5199       goDB 4.2 Atlas cluster,  automatic  decryption  is  supported  for  all
5200       users.  To  configure automatic decryption without automatic encryption
5201       set   bypass_auto_encryption=True   in   mongoc_auto_encryption_opts_t:
5202       client-side-encryption-auto-decryption.c.INDENT 0.0
5203
5204          #include <mongoc/mongoc.h>
5205          #include <stdio.h>
5206          #include <stdlib.h>
5207
5208          #include "client-side-encryption-helpers.h"
5209
5210          /* This example demonstrates how to set up automatic decryption without
5211           * automatic encryption using the community version of MongoDB */
5212          int
5213          main (int argc, char **argv)
5214          {
5215          /* The collection used to store the encryption data keys. */
5216          #define KEYVAULT_DB "encryption"
5217          #define KEYVAULT_COLL "__libmongocTestKeyVault"
5218          /* The collection used to store the encrypted documents in this example. */
5219          #define ENCRYPTED_DB "test"
5220          #define ENCRYPTED_COLL "coll"
5221
5222             int exit_status = EXIT_FAILURE;
5223             bool ret;
5224             uint8_t *local_masterkey = NULL;
5225             uint32_t local_masterkey_len;
5226             bson_t *kms_providers = NULL;
5227             bson_error_t error = {0};
5228             bson_t *index_keys = NULL;
5229             char *index_name = NULL;
5230             bson_t *create_index_cmd = NULL;
5231             bson_t *schema = NULL;
5232             mongoc_client_t *client = NULL;
5233             mongoc_collection_t *coll = NULL;
5234             mongoc_collection_t *keyvault_coll = NULL;
5235             bson_t *to_insert = NULL;
5236             bson_t *create_cmd = NULL;
5237             bson_t *create_cmd_opts = NULL;
5238             mongoc_write_concern_t *wc = NULL;
5239             mongoc_client_encryption_t *client_encryption = NULL;
5240             mongoc_client_encryption_opts_t *client_encryption_opts = NULL;
5241             mongoc_client_encryption_datakey_opts_t *datakey_opts = NULL;
5242             char *keyaltnames[] = {"mongoc_encryption_example_4"};
5243             bson_value_t datakey_id = {0};
5244             bson_value_t encrypted_field = {0};
5245             bson_value_t to_encrypt = {0};
5246             mongoc_client_encryption_encrypt_opts_t *encrypt_opts = NULL;
5247             bson_value_t decrypted = {0};
5248             mongoc_auto_encryption_opts_t *auto_encryption_opts = NULL;
5249             mongoc_client_t *unencrypted_client = NULL;
5250             mongoc_collection_t *unencrypted_coll = NULL;
5251
5252             mongoc_init ();
5253
5254             /* Configure the master key. This must be the same master key that was used
5255              * to create the encryption key. */
5256             local_masterkey =
5257                hex_to_bin (getenv ("LOCAL_MASTERKEY"), &local_masterkey_len);
5258             if (!local_masterkey || local_masterkey_len != 96) {
5259                fprintf (stderr,
5260                         "Specify LOCAL_MASTERKEY environment variable as a "
5261                         "secure random 96 byte hex value.\n");
5262                goto fail;
5263             }
5264
5265             kms_providers = BCON_NEW ("local",
5266                                       "{",
5267                                       "key",
5268                                       BCON_BIN (0, local_masterkey, local_masterkey_len),
5269                                       "}");
5270
5271             client =
5272                mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5273             auto_encryption_opts = mongoc_auto_encryption_opts_new ();
5274             mongoc_auto_encryption_opts_set_keyvault_namespace (
5275                auto_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5276             mongoc_auto_encryption_opts_set_kms_providers (auto_encryption_opts,
5277                                                            kms_providers);
5278
5279             /* Setting bypass_auto_encryption to true disables automatic encryption but
5280              * keeps the automatic decryption behavior. bypass_auto_encryption will also
5281              * disable spawning mongocryptd */
5282             mongoc_auto_encryption_opts_set_bypass_auto_encryption (auto_encryption_opts,
5283                                                                     true);
5284
5285             /* Once bypass_auto_encryption is set, community users can enable auto
5286              * encryption on the client. This will, in fact, only perform automatic
5287              * decryption. */
5288             ret = mongoc_client_enable_auto_encryption (
5289                client, auto_encryption_opts, &error);
5290             if (!ret) {
5291                goto fail;
5292             }
5293
5294             /* Now that automatic decryption is on, we can test it by inserting a
5295              * document with an explicitly encrypted value into the collection. When we
5296              * look up the document later, it should be automatically decrypted for us.
5297              */
5298             coll = mongoc_client_get_collection (client, ENCRYPTED_DB, ENCRYPTED_COLL);
5299
5300             /* Clear old data */
5301             mongoc_collection_drop (coll, NULL);
5302
5303             /* Set up the key vault for this example. */
5304             keyvault_coll =
5305                mongoc_client_get_collection (client, KEYVAULT_DB, KEYVAULT_COLL);
5306             mongoc_collection_drop (keyvault_coll, NULL);
5307
5308             /* Create a unique index to ensure that two data keys cannot share the same
5309              * keyAltName. This is recommended practice for the key vault. */
5310             index_keys = BCON_NEW ("keyAltNames", BCON_INT32 (1));
5311             index_name = mongoc_collection_keys_to_index_string (index_keys);
5312             create_index_cmd = BCON_NEW ("createIndexes",
5313                                          KEYVAULT_COLL,
5314                                          "indexes",
5315                                          "[",
5316                                          "{",
5317                                          "key",
5318                                          BCON_DOCUMENT (index_keys),
5319                                          "name",
5320                                          index_name,
5321                                          "unique",
5322                                          BCON_BOOL (true),
5323                                          "partialFilterExpression",
5324                                          "{",
5325                                          "keyAltNames",
5326                                          "{",
5327                                          "$exists",
5328                                          BCON_BOOL (true),
5329                                          "}",
5330                                          "}",
5331                                          "}",
5332                                          "]");
5333             ret = mongoc_client_command_simple (client,
5334                                                 KEYVAULT_DB,
5335                                                 create_index_cmd,
5336                                                 NULL /* read prefs */,
5337                                                 NULL /* reply */,
5338                                                 &error);
5339
5340             if (!ret) {
5341                goto fail;
5342             }
5343
5344             client_encryption_opts = mongoc_client_encryption_opts_new ();
5345             mongoc_client_encryption_opts_set_kms_providers (client_encryption_opts,
5346                                                              kms_providers);
5347             mongoc_client_encryption_opts_set_keyvault_namespace (
5348                client_encryption_opts, KEYVAULT_DB, KEYVAULT_COLL);
5349
5350             /* The key vault client is used for reading to/from the key vault. This can
5351              * be the same mongoc_client_t used by the application. */
5352             mongoc_client_encryption_opts_set_keyvault_client (client_encryption_opts,
5353                                                                client);
5354             client_encryption =
5355                mongoc_client_encryption_new (client_encryption_opts, &error);
5356             if (!client_encryption) {
5357                goto fail;
5358             }
5359
5360             /* Create a new data key for the encryptedField.
5361              * https://dochub.mongodb.org/core/client-side-field-level-encryption-automatic-encryption-rules
5362              */
5363             datakey_opts = mongoc_client_encryption_datakey_opts_new ();
5364             mongoc_client_encryption_datakey_opts_set_keyaltnames (
5365                datakey_opts, keyaltnames, 1);
5366             ret = mongoc_client_encryption_create_datakey (
5367                client_encryption, "local", datakey_opts, &datakey_id, &error);
5368             if (!ret) {
5369                goto fail;
5370             }
5371
5372             /* Explicitly encrypt a field. */
5373             encrypt_opts = mongoc_client_encryption_encrypt_opts_new ();
5374             mongoc_client_encryption_encrypt_opts_set_algorithm (
5375                encrypt_opts, MONGOC_AEAD_AES_256_CBC_HMAC_SHA_512_DETERMINISTIC);
5376             mongoc_client_encryption_encrypt_opts_set_keyaltname (
5377                encrypt_opts, "mongoc_encryption_example_4");
5378             to_encrypt.value_type = BSON_TYPE_UTF8;
5379             to_encrypt.value.v_utf8.str = "123456789";
5380             to_encrypt.value.v_utf8.len = strlen (to_encrypt.value.v_utf8.str);
5381
5382             ret = mongoc_client_encryption_encrypt (
5383                client_encryption, &to_encrypt, encrypt_opts, &encrypted_field, &error);
5384             if (!ret) {
5385                goto fail;
5386             }
5387
5388             to_insert = bson_new ();
5389             BSON_APPEND_VALUE (to_insert, "encryptedField", &encrypted_field);
5390             ret = mongoc_collection_insert_one (
5391                coll, to_insert, NULL /* opts */, NULL /* reply */, &error);
5392             if (!ret) {
5393                goto fail;
5394             }
5395
5396             /* When we retrieve the document, any encrypted fields will get automatically
5397              * decrypted by the driver. */
5398             printf ("decrypted document: ");
5399             if (!print_one_document (coll, &error)) {
5400                goto fail;
5401             }
5402             printf ("\n");
5403
5404             unencrypted_client =
5405                mongoc_client_new ("mongodb://localhost/?appname=client-side-encryption");
5406             unencrypted_coll = mongoc_client_get_collection (
5407                unencrypted_client, ENCRYPTED_DB, ENCRYPTED_COLL);
5408
5409             printf ("encrypted document: ");
5410             if (!print_one_document (unencrypted_coll, &error)) {
5411                goto fail;
5412             }
5413             printf ("\n");
5414
5415             exit_status = EXIT_SUCCESS;
5416          fail:
5417             if (error.code) {
5418                fprintf (stderr, "error: %s\n", error.message);
5419             }
5420
5421             bson_free (local_masterkey);
5422             bson_destroy (kms_providers);
5423             mongoc_collection_destroy (keyvault_coll);
5424             bson_destroy (index_keys);
5425             bson_free (index_name);
5426             bson_destroy (create_index_cmd);
5427             mongoc_collection_destroy (coll);
5428             mongoc_client_destroy (client);
5429             bson_destroy (to_insert);
5430             bson_destroy (schema);
5431             bson_destroy (create_cmd);
5432             bson_destroy (create_cmd_opts);
5433             mongoc_write_concern_destroy (wc);
5434             mongoc_client_encryption_destroy (client_encryption);
5435             mongoc_client_encryption_datakey_opts_destroy (datakey_opts);
5436             mongoc_client_encryption_opts_destroy (client_encryption_opts);
5437             bson_value_destroy (&encrypted_field);
5438             mongoc_client_encryption_encrypt_opts_destroy (encrypt_opts);
5439             bson_value_destroy (&decrypted);
5440             bson_value_destroy (&datakey_id);
5441             mongoc_collection_destroy (unencrypted_coll);
5442             mongoc_client_destroy (unencrypted_client);
5443             mongoc_auto_encryption_opts_destroy (auto_encryption_opts);
5444
5445             mongoc_cleanup ();
5446             return exit_status;
5447          }
5448
5449   API Reference
5450   Initialization and cleanup
5451   Synopsis
5452       Initialize  the MongoDB C Driver by calling mongoc_init exactly once at
5453       the beginning of your  program.  It  is  responsible  for  initializing
5454       global state such as process counters, SSL, and threading primitives.
5455
5456       Call  mongoc_cleanup exactly once at the end of your program to release
5457       all memory and other resources allocated by the driver.  You  must  not
5458       call  any  other  MongoDB C Driver functions after mongoc_cleanup. Note
5459       that mongoc_init does not reinitialize the driver after mongoc_cleanup.
5460
5461   Deprecated feature: automatic initialization and cleanup
5462       On some platforms the driver can automatically call mongoc_init  before
5463       main, and call mongoc_cleanup as the process exits. This is problematic
5464       in situations where related libraries  also  execute  cleanup  code  on
5465       shutdown, and it creates inconsistent rules across platforms. Therefore
5466       the automatic initialization and cleanup  feature  is  deprecated,  and
5467       will  be dropped in version 2.0. Meanwhile, for backward compatibility,
5468       the feature is enabled by default on platforms where it is available.
5469
5470       For portable, future-proof  code,  always  call  mongoc_init  and  mon‐
5471       goc_cleanup yourself, and configure the driver like:
5472
5473          cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=NO
5474
5475   Logging
5476       MongoDB C driver Logging Abstraction
5477
5478   Synopsis
5479          typedef enum {
5480             MONGOC_LOG_LEVEL_ERROR,
5481             MONGOC_LOG_LEVEL_CRITICAL,
5482             MONGOC_LOG_LEVEL_WARNING,
5483             MONGOC_LOG_LEVEL_MESSAGE,
5484             MONGOC_LOG_LEVEL_INFO,
5485             MONGOC_LOG_LEVEL_DEBUG,
5486             MONGOC_LOG_LEVEL_TRACE,
5487          } mongoc_log_level_t;
5488
5489          #define MONGOC_ERROR(...)
5490          #define MONGOC_CRITICAL(...)
5491          #define MONGOC_WARNING(...)
5492          #define MONGOC_MESSAGE(...)
5493          #define MONGOC_INFO(...)
5494          #define MONGOC_DEBUG(...)
5495
5496          typedef void (*mongoc_log_func_t) (mongoc_log_level_t log_level,
5497                                             const char *log_domain,
5498                                             const char *message,
5499                                             void *user_data);
5500
5501          void
5502          mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data);
5503          void
5504          mongoc_log (mongoc_log_level_t log_level,
5505                      const char *log_domain,
5506                      const char *format,
5507                      ...) BSON_GNUC_PRINTF (3, 4);
5508          const char *
5509          mongoc_log_level_str (mongoc_log_level_t log_level);
5510          void
5511          mongoc_log_default_handler (mongoc_log_level_t log_level,
5512                                      const char *log_domain,
5513                                      const char *message,
5514                                      void *user_data);
5515          void
5516          mongoc_log_trace_enable (void);
5517          void
5518          mongoc_log_trace_disable (void);
5519
5520       The MongoDB C driver comes with an abstraction for logging that you can
5521       use in your application, or integrate with an existing logging system.
5522
5523   Macros
5524       To make logging a little less painful, various helper macros  are  pro‐
5525       vided. See the following example.
5526
5527          #undef MONGOC_LOG_DOMAIN
5528          #define MONGOC_LOG_DOMAIN "my-custom-domain"
5529
5530          MONGOC_WARNING ("An error occurred: %s", strerror (errno));
5531
5532   Custom Log Handlers
5533       The  default log handler prints a timestamp and the log message to std‐
5534       out, or to stderr for warnings, critical messages, and errors.
5535              You can  override  the  handler  with  mongoc_log_set_handler().
5536              Your handler function is called in a mutex for thread safety.
5537
5538       For  example,  you could register a custom handler to suppress messages
5539       at INFO level and below:
5540
5541          void
5542          my_logger (mongoc_log_level_t log_level,
5543                     const char *log_domain,
5544                     const char *message,
5545                     void *user_data)
5546          {
5547             /* smaller values are more important */
5548             if (log_level < MONGOC_LOG_LEVEL_INFO) {
5549                mongoc_log_default_handler (log_level, log_domain, message, user_data);
5550             }
5551          }
5552
5553          int
5554          main (int argc, char *argv[])
5555          {
5556             mongoc_init ();
5557             mongoc_log_set_handler (my_logger, NULL);
5558
5559             /* ... your code ...  */
5560
5561             mongoc_cleanup ();
5562             return 0;
5563          }
5564
5565       To restore the default handler:
5566
5567          mongoc_log_set_handler (mongoc_log_default_handler, NULL);
5568
5569   Disable logging
5570       To disable all  logging,  including  warnings,  critical  messages  and
5571       errors, provide an empty log handler:
5572
5573          mongoc_log_set_handler (NULL, NULL);
5574
5575   Tracing
5576       If  compiling your own copy of the MongoDB C driver, consider configur‐
5577       ing with -DENABLE_TRACING=ON to enable function tracing and  hex  dumps
5578       of  network  packets to STDERR and STDOUT during development and debug‐
5579       ging.
5580
5581       This is especially useful when debugging what may be  going  on  inter‐
5582       nally in the driver.
5583
5584       Trace   messages   can   be   enabled  and  disabled  by  calling  mon‐
5585       goc_log_trace_enable() and mongoc_log_trace_disable()
5586
5587       NOTE:
5588          Compiling the driver with -DENABLE_TRACING=ON will affect  its  per‐
5589          formance. Disabling tracing with mongoc_log_trace_disable() signifi‐
5590          cantly reduces the overhead, but cannot remove it completely.
5591       « index
5592
5593   Error Reporting
5594   Description
5595       Many C Driver functions report errors by  returning  false  or  -1  and
5596       filling  out a bson_error_t structure with an error domain, error code,
5597       and message. Use domain to  determine  which  subsystem  generated  the
5598       error,  and  code  for  the specific error. message is a human-readable
5599       error description.
5600
5601       See also: Handling Errors in libbson.
5602
5603┌──────────────────────────────┬─────────────────────────────────────────┬───────────────────────────────────────┐
5604│Domain                        │ Code                                    │ Description                           │
5605├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5606MONGOC_ERROR_CLIENT           MON‐                                    │ You tried to send a                   │
5607│                              │ GOC_ERROR_CLIENT_TOO_BIG                │ message larger than                   │
5608│                              │                                         │ the  server's   max                   │
5609│                              │                                         │ message size.                         │
5610├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5611│                              │ MON‐                                    │ Wrong  credentials,                   │
5612│                              │ GOC_ERROR_CLIENT_AUTHEN‐                │ or failure  sending                   │
5613│                              │ TICATE                                  │ or        receiving                   │
5614│                              │                                         │ authentication mes‐                   │
5615│                              │                                         │ sages.                                │
5616├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5617│                              │ MON‐                                    │ You  tried  an  SSL                   │
5618│                              │ GOC_ERROR_CLIENT_NO_ACCEPT‐             │ connection but  the                   │
5619│                              │ ABLE_PEER                               │ driver    was   not                   │
5620│                              │                                         │ built with SSL.                       │
5621├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5622│                              │ MON‐                                    │ You began iterating                   │
5623│                              │ GOC_ERROR_CLIENT_IN_EXHAUST             │ an exhaust  cursor,                   │
5624│                              │                                         │ then tried to begin                   │
5625│                              │                                         │ another   operation                   │
5626│                              │                                         │ with  the same mon‐                   
5627│                              │                                         │ goc_client_t.                         │
5628├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5629│                              │ MONGOC_ERROR_CLIENT_SES‐                │ Failure  related to                   │
5630│                              │ SION_FAILURE                            │ creating or using a                   │
5631│                              │                                         │ logical session.                      │
5632├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5633│                              │ MON‐                                    │ Failure  related to                   │
5634│                              │ GOC_ERROR_CLIENT_INVALID_ENCRYP‐        │ arguments    passed                   │
5635│                              │ TION_ARG                                │ when   initializing                   │
5636│                              │                                         │ Client-Side   Field                   │
5637│                              │                                         │ Level Encryption.                     │
5638├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5639│                              │ MON‐                                    │ Failure  related to                   │
5640│                              │ GOC_ERROR_CLIENT_INVALID_ENCRYP‐        │ Client-Side   Field                   │
5641│                              │ TION_STATE                              │ Level Encryption.                     │
5642├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5643MONGOC_ERROR_STREAM           MONGOC_ERROR_STREAM_NAME_RESOLU‐        │ DNS failure.                          │
5644│                              │ TION                                    │                                       │
5645├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5646│                              │ MONGOC_ERROR_STREAM_SOCKET              │ Timeout communicat‐                   │
5647│                              │                                         │ ing with server, or                   │
5648│                              │                                         │ connection closed.                    │
5649├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5650│                              │ MONGOC_ERROR_STREAM_CONNECT             │ Failed  to  connect                   │
5651│                              │                                         │ to server.                            │
5652├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5653MONGOC_ERROR_PROTO‐           MONGOC_ERROR_PROTO‐                     │ Corrupt    response                   │
5654COL                           COL_INVALID_REPLY                       │ from server.                          │
5655├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5656│                              │ MONGOC_ERROR_PROTO‐                     │ The  server version                   │
5657│                              │ COL_BAD_WIRE_VERSION                    │ is too old  or  too                   │
5658│                              │                                         │ new  to communicate                   │
5659│                              │                                         │ with the driver.                      │
5660├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5661MONGOC_ERROR_CURSOR           MONGOC_ERROR_CURSOR_INVALID_CUR‐        │ You    passed   bad                   │
5662│                              │ SOR                                     │ arguments  to  mon‐                   
5663│                              │                                         │ goc_collec‐                           
5664│                              │                                         │ tion_find_with_opts,                  │
5665│                              │                                         │ or  you called mon‐                   
5666│                              │                                         │ goc_cursor_next  on                   │
5667│                              │                                         │ a    completed   or                   │
5668│                              │                                         │ failed  cursor,  or                   │
5669│                              │                                         │ the   cursor  timed                   │
5670│                              │                                         │ out on the server.                    │
5671└──────────────────────────────┴─────────────────────────────────────────┴───────────────────────────────────────┘
5672
5673│                              │ MON‐                                    │ A resume  token  was                  │
5674│                              │ GOC_ERROR_CHANGE_STREAM_NO_RESUME_TOKEN │ not  returned  in  a                  │
5675│                              │                                         │ document found  with                  │
5676│                              │                                         │ mon‐                                  
5677│                              │                                         │ goc_change_stream_next                
5678├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5679MONGOC_ERROR_QUERY            MONGOC_ERROR_QUERY_FAILURE              Error  API  Version 1:                │
5680│                              │                                         │ Server error from com‐                │
5681│                              │                                         │ mand   or  query.  The                │
5682│                              │                                         │ server  error  message                │
5683│                              │                                         │ is in message.                        │
5684├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5685MONGOC_ERROR_SERVER           MONGOC_ERROR_QUERY_FAILURE              Error  API  Version 2:                │
5686│                              │                                         │ Server error from com‐                │
5687│                              │                                         │ mand   or  query.  The                │
5688│                              │                                         │ server  error  message                │
5689│                              │                                         │ is in message.                        │
5690├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5691MONGOC_ERROR_SASL             │ A SASL error code.                      │ man  sasl_errors for a                │
5692│                              │                                         │ list of codes.                        │
5693├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5694MONGOC_ERROR_BSON             MONGOC_ERROR_BSON_INVALID               │ You passed an  invalid                │
5695│                              │                                         │ or oversized BSON doc‐                │
5696│                              │                                         │ ument as a  parameter,                │
5697│                              │                                         │ or  called mongoc_col‐                
5698│                              │                                         │ lection_create_index                  
5699│                              │                                         │ with  invalid keys, or                │
5700│                              │                                         │ the server  reply  was                │
5701│                              │                                         │ corrupt.                              │
5702├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5703MONGOC_ERROR_NAMES‐           MONGOC_ERROR_NAMESPACE_INVALID          │ You tried to create  a                │
5704PACE                          │                                         │ collection   with   an                │
5705│                              │                                         │ invalid name.                         │
5706├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5707MONGOC_ERROR_COM‐             MONGOC_ERROR_COMMAND_INVALID_ARG        │ Many   functions   set                │
5708MAND                          │                                         │ this error  code  when                │
5709│                              │                                         │ passed bad parameters.                │
5710│                              │                                         │ Print the  error  mes‐                │
5711│                              │                                         │ sage for details.                     │
5712├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5713│                              │ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION  │ You  tried  to  use  a                │
5714│                              │                                         │ command   option   the                │
5715│                              │                                         │ server  does  not sup‐                │
5716│                              │                                         │ port.                                 │
5717├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5718│                              │ MONGOC_ERROR_DUPLICATE_KEY              │ An  insert  or  update                │
5719│                              │                                         │ failed because because                │
5720│                              │                                         │ of a duplicate _id  or                │
5721│                              │                                         │ other     unique-index                │
5722│                              │                                         │ violation.                            │
5723├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5724│                              │ MONGOC_ERROR_MAX_TIME_MS_EXPIRED        │ The  operation  failed                │
5725│                              │                                         │ because      maxTimeMS                │
5726│                              │                                         │ expired.                              │
5727├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5728│                              │ MONGOC_ERROR_SERVER_SELEC‐              │ The   serverId  option                │
5729│                              │ TION_INVALID_ID                         │ for an operation  con‐                │
5730│                              │                                         │ flicts with the pinned                │
5731│                              │                                         │ server for that opera‐                │
5732│                              │                                         │ tion's  client session                │
5733│                              │                                         │ (denoted by  the  ses‐                
5734│                              │                                         │ sionId option).                       │
5735├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5736MONGOC_ERROR_COM‐             Error code from server.                 │ Error API  Version  1:                │
5737MAND                          │                                         │ Server  error  from  a                │
5738│                              │                                         │ command.  The   server                │
5739│                              │                                         │ error  message  is  in                │
5740│                              │                                         │ message.                              │
5741└──────────────────────────────┴─────────────────────────────────────────┴───────────────────────────────────────┘
5742
5743
5744
5745MONGOC_ERROR_SERVER           Error code from server.                 │ Error API  Version  2:                │
5746│                              │                                         │ Server  error  from  a                │
5747│                              │                                         │ command.  The   server                │
5748│                              │                                         │ error  message  is  in                │
5749│                              │                                         │ message.                              │
5750├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5751MONGOC_ERROR_COL‐             MONGOC_ERROR_COLLECTION_INSERT_FAILED,  │ Invalid or empty input                │
5752LECTION                       MONGOC_ERROR_COLLECTION_UPDATE_FAILED,  │ to      mongoc_collec‐                
5753│                              │ MONGOC_ERROR_COLLECTION_DELETE_FAILED.  │ tion_insert_one,  mon‐                
5754│                              │                                         │ goc_collec‐                           
5755│                              │                                         │ tion_insert_bulk, mon‐                
5756│                              │                                         │ goc_collec‐                           
5757│                              │                                         │ tion_update_one,  mon‐                
5758│                              │                                         │ goc_collec‐                           
5759│                              │                                         │ tion_update_many, mon‐                
5760│                              │                                         │ goc_collec‐                           
5761│                              │                                         │ tion_replace_one, mon‐                
5762│                              │                                         │ goc_collec‐                           
5763│                              │                                         │ tion_delete_one,    or                │
5764│                              │                                         │ mongoc_collec‐                        
5765│                              │                                         │ tion_delete_many.                     │
5766├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5767MONGOC_ERROR_COL‐             Error code from server.                 │ Error API  Version  1:                │
5768LECTION                       │                                         │ Server error from mon‐                
5769│                              │                                         │ goc_collec‐                           
5770│                              │                                         │ tion_insert_one,  mon‐                
5771│                              │                                         │ goc_collec‐                           
5772│                              │                                         │ tion_insert_bulk, mon‐                
5773│                              │                                         │ goc_collec‐                           
5774│                              │                                         │ tion_update_one,  mon‐                
5775│                              │                                         │ goc_collec‐                           
5776│                              │                                         │ tion_update_many, mon‐                
5777│                              │                                         │ goc_collec‐                           
5778│                              │                                         │ tion_replace_one,                     │
5779├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5780MONGOC_ERROR_SERVER           Error code from server.                 │ Error  API  Version 2:                │
5781│                              │                                         │ Server error from mon‐                
5782│                              │                                         │ goc_collec‐                           
5783│                              │                                         │ tion_insert_one,  mon‐                
5784│                              │                                         │ goc_collec‐                           
5785│                              │                                         │ tion_insert_bulk, mon‐                
5786│                              │                                         │ goc_collec‐                           
5787│                              │                                         │ tion_update_one,  mon‐                
5788│                              │                                         │ goc_collec‐                           
5789│                              │                                         │ tion_update_many, mon‐                
5790│                              │                                         │ goc_collec‐                           
5791│                              │                                         │ tion_replace_one,                     │
5792├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5793MONGOC_ERROR_GRIDFS           MONGOC_ERROR_GRIDFS_CHUNK_MISSING       │ The  GridFS  file   is                │
5794│                              │                                         │ missing  a document in                │
5795│                              │                                         │ its chunks collection.                │
5796├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5797│                              │ MONGOC_ERROR_GRIDFS_CORRUPT             │ A  data  inconsistency                │
5798│                              │                                         │ was     detected    in                │
5799│                              │                                         │ GridFS.                               │
5800├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5801│                              │ MONGOC_ERROR_GRIDFS_INVALID_FILENAME    │ You  passed   a   NULL                │
5802│                              │                                         │ filename    to    mon‐                
5803│                              │                                         │ goc_gridfs_remove_by_file‐            
5804│                              │                                         │ name.                                 │
5805├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5806│                              │ MONGOC_ERROR_GRIDFS_PROTOCOL_ERROR      │ You       called      mon‐            
5807│                              │                                         │ goc_gridfs_file_set_id                
5808│                              │                                         │ after                 mon‐            
5809│                              │                                         │ goc_gridfs_file_save,   or            │
5810│                              │                                         │ tried to write on a closed            │
5811│                              │                                         │ GridFS stream.                        │
5812├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5813│                              │ MON‐                                    │ A  GridFS  file is missing            │
5814│                              │ GOC_ERROR_GRIDFS_BUCKET_FILE_NOT_FOUND  │ from files collection.                │
5815└──────────────────────────────┴─────────────────────────────────────────┴───────────────────────────────────────┘
5816
5817│                              │ MONGOC_ERROR_GRIDFS_BUCKET_STREAM       │ An  error  occurred  on  a            │
5818│                              │                                         │ stream   created   from  a            │
5819│                              │                                         │ GridFS operation like mon‐            
5820│                              │                                         │ goc_gridfs_bucket_upload_from_stream. │
5821├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5822MONGOC_ERROR_SCRAM            MONGOC_ERROR_SCRAM_PROTOCOL_ERROR       │ Failure  in  SCRAM-SHA-1  authentica‐ │
5823│                              │                                         │ tion.                                 │
5824├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5825MON‐                          MONGOC_ERROR_SERVER_SELECTION_FAILURE   │ No  replica  set  member or mongos is │
5826GOC_ERROR_SERVER_SELEC‐       │                                         │ available, or none matches your  read │
5827TION                          │                                         │ preference,   or   you   supplied  an │
5828│                              │                                         │ invalid mongoc_read_prefs_t.          │
5829├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5830MONGOC_ERROR_WRITE_CON‐       Error code from server.                 │ There  was  a  write concern error or │
5831CERN                          │                                         │ timeout from the server.              │
5832├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5833MONGOC_ERROR_TRANSAC‐         MONGOC_ERROR_TRANSACTION_INVALID        │ You  attempted to start a transaction │
5834TION                          │                                         │ when one is already in  progress,  or │
5835│                              │                                         │ commit  or  abort  when  there  is no │
5836│                              │                                         │ transaction.                          │
5837├──────────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────┤
5838MON‐                          │ Error code produced by libmongocrypt.   │ An  error  occurred  in  the  library │
5839GOC_ERROR_CLIENT_SIDE_ENCRYP‐ │                                         │ responsible  for  Client Side Encryp‐ │
5840TION                          │                                         │ tion                                  │
5841└──────────────────────────────┴─────────────────────────────────────────┴───────────────────────────────────────┘
5842
5843   Error Labels
5844       In some cases your application must make decisions based on what  cate‐
5845       gory of error the driver has returned, but these categories do not cor‐
5846       respond perfectly to an error domain or  code.  In  such  cases,  error
5847       labels  provide a reliable way to determine how your application should
5848       respond to an error.
5849
5850       Any C Driver function that has a bson_t out-parameter named  reply  may
5851       include  error  labels  to the reply, in the form of a BSON field named
5852       "errorLabels" containing an array of strings:
5853
5854          { "errorLabels": [ "TransientTransactionError" ] }
5855
5856       Use mongoc_error_has_label to test  if  a  reply  contains  a  specific
5857       label.  See  mongoc_client_session_start_transaction  for  example code
5858       that demonstrates the use of error labels in application logic.
5859
5860       The following error labels are currently defined.  Future  versions  of
5861       MongoDB may introduce new labels.
5862
5863   TransientTransactionError
5864       Within  a  multi-document  transaction,  certain  errors  can leave the
5865       transaction in an unknown or aborted state. These  include  write  con‐
5866       flicts,  primary stepdowns, and network errors. In response, the appli‐
5867       cation should abort the transaction and try the same sequence of opera‐
5868       tions again in a new transaction.
5869
5870   UnknownTransactionCommitResult
5871       When   mongoc_client_session_commit_transaction  encounters  a  network
5872       error or certain server errors, it is not known whether the transaction
5873       was  committed.  Applications  should attempt to commit the transaction
5874       again until: the commit succeeds, the commit fails with  an  error  not
5875       labeled "UnknownTransactionCommitResult", or the application chooses to
5876       give up.
5877
5878   Setting the Error API Version
5879       The driver's error reporting began with a design flaw: when  the  error
5880       domain   is   MONGOC_ERROR_COLLECTION,   MONGOC_ERROR_QUERY,   or  MON‐
5881       GOC_ERROR_COMMAND, the error code might originate from  the  server  or
5882       the  driver.  An  application  cannot always know where an error origi‐
5883       nated, and therefore cannot tell what the code means.
5884
5885       For example, if mongoc_collection_update_one sets the error's domain to
5886       MONGOC_ERROR_COLLECTION and its code to 24, the application cannot know
5887       whether 24  is  the  generic  driver  error  code  MONGOC_ERROR_COLLEC‐
5888       TION_UPDATE_FAILED or the specific server error code "LockTimeout".
5889
5890       To  fix this flaw while preserving backward compatibility, the C Driver
5891       1.4 introduces "Error API Versions". Version 1, the default  Error  API
5892       Version,  maintains  the  flawed  behavior.  Version 2 adds a new error
5893       domain, MONGOC_ERROR_SERVER. In Version 2, error codes  originating  on
5894       the  server  always  have  error  domain  MONGOC_ERROR_SERVER  or  MON‐
5895       GOC_ERROR_WRITE_CONCERN. When the driver uses Version 2 the application
5896       can  always determine the origin and meaning of error codes. New appli‐
5897       cations should use Version  2,  and  existing  applications  should  be
5898       updated to use Version 2 as well.
5899
5900        ┌──────────────────────┬──────────────────────┬──────────────────────┐
5901        │Error Source          │ API Version 1        │ API Version 2        │
5902        ├──────────────────────┼──────────────────────┼──────────────────────┤
5903mongoc_cursor_error   MONGOC_ERROR_QUERY   MONGOC_ERROR_SERVER  
5904        ├──────────────────────┼──────────────────────┼──────────────────────┤
5905mongoc_client_com‐    MONGOC_ERROR_QUERY   MONGOC_ERROR_SERVER  
5906mand_with_opts,       │                      │                      │
5907mongoc_data‐          │                      │                      │
5908base_com‐             │                      │                      │
5909mand_with_opts, and   │                      │                      │
5910        │other command func‐   │                      │                      │
5911        │tions                 │                      │                      │
5912        ├──────────────────────┼──────────────────────┼──────────────────────┤
5913mongoc_collec‐        MONGOC_ERROR_QUERY   MONGOC_ERROR_SERVER  
5914tion_count_with_opts  │                      │                      │
5915mon‐                  │                      │                      │
5916goc_client_get_data‐  │                      │                      │
5917base_names_with_opts, │                      │                      │
5918        │and  other  command   │                      │                      │
5919        │helper functions      │                      │                      │
5920        ├──────────────────────┼──────────────────────┼──────────────────────┤
5921mongoc_collec‐        MONGOC_ERROR_COM‐    MONGOC_ERROR_SERVER  
5922tion_insert_one  mon‐ MAND                 │                      │
5923goc_collec‐           │                      │                      │
5924tion_insert_bulk mon‐ │                      │                      │
5925goc_collec‐           │                      │                      │
5926tion_update_one  mon‐ │                      │                      │
5927goc_collec‐           │                      │                      │
5928tion_update_many mon‐ │                      │                      │
5929goc_collec‐           │                      │                      │
5930tion_replace_one mon‐ │                      │                      │
5931goc_collec‐           │                      │                      │
5932tion_delete_one  mon‐ │                      │                      │
5933goc_collec‐           │                      │                      │
5934tion_delete_many      │                      │                      │
5935        ├──────────────────────┼──────────────────────┼──────────────────────┤
5936mongoc_bulk_opera‐    MONGOC_ERROR_COM‐    MONGOC_ERROR_SERVER  
5937tion_execute          MAND                 │                      │
5938        ├──────────────────────┼──────────────────────┼──────────────────────┤
5939        │Write-concern timeout │ MON‐                 MON‐                 
5940        │                      │ GOC_ERROR_WRITE_CON‐ GOC_ERROR_WRITE_CON‐ 
5941        │                      │ CERN                 CERN                 
5942        └──────────────────────┴──────────────────────┴──────────────────────┘
5943
5944       The Error API Versions are defined with MONGOC_ERROR_API_VERSION_LEGACY
5945       and   MONGOC_ERROR_API_VERSION_2.   Set   the   version    with    mon‐
5946       goc_client_set_error_api or mongoc_client_pool_set_error_api.
5947
5948   See Also
5949       MongoDB Server Error Codes
5950
5951   Object Lifecycle
5952       This  page  documents the order of creation and destruction for libmon‐
5953       goc's main struct types.
5954
5955   Clients and pools
5956       Call mongoc_init() once, before calling any other libmongoc  functions,
5957       and call mongoc_cleanup() once before your program exits.
5958
5959       A  program  that  uses  libmongoc from multiple threads should create a
5960       mongoc_client_pool_t   with   mongoc_client_pool_new().   Each   thread
5961       acquires  a mongoc_client_t from the pool with mongoc_client_pool_pop()
5962       and returns it with mongoc_client_pool_push() when the thread  is  fin‐
5963       ished  using  it.  To  destroy the pool, first return all clients, then
5964       call mongoc_client_pool_destroy().
5965
5966       If your program uses libmongoc from only  one  thread,  create  a  mon‐
5967       goc_client_t     directly     with    mongoc_client_new()    or    mon‐
5968       goc_client_new_from_uri(). Destroy it with mongoc_client_destroy().
5969
5970   Databases, collections, and related objects
5971       You can create a mongoc_database_t or mongoc_collection_t from  a  mon‐
5972       goc_client_t,  and  create a mongoc_cursor_t or mongoc_bulk_operation_t
5973       from a mongoc_collection_t.
5974
5975       Each of these objects must be destroyed before  the  client  they  were
5976       created from, but their lifetimes are otherwise independent.
5977
5978   GridFS objects
5979       You  can create a mongoc_gridfs_t from a mongoc_client_t, create a mon‐
5980       goc_gridfs_file_t or mongoc_gridfs_file_list_t from a  mongoc_gridfs_t,
5981       create  a  mongoc_gridfs_file_t  from  a mongoc_gridfs_file_list_t, and
5982       create a mongoc_stream_t from a mongoc_gridfs_file_t.
5983
5984       Each of these objects depends on the object it was created from. Always
5985       destroy  GridFS  objects in the reverse of the order they were created.
5986       The sole exception is that a mongoc_gridfs_file_t need not be destroyed
5987       before the mongoc_gridfs_file_list_t it was created from.
5988
5989   GridFS bucket objects
5990       Create  mongoc_gridfs_bucket_t  with a mongoc_database_t derived from a
5991       mongoc_client_t. The mongoc_database_t is  independent  from  the  mon‐
5992       goc_gridfs_bucket_t.  But  the  mongoc_client_t  must  outlive the mon‐
5993       goc_gridfs_bucket_t.
5994
5995       A mongoc_stream_t may be created from the  mongoc_gridfs_bucket_t.  The
5996       mongoc_gridfs_bucket_t must outlive the mongoc_stream_t.
5997
5998   Sessions
5999       Start a session with mongoc_client_start_session, use the session for a
6000       sequence of operations and multi-document transactions,  then  free  it
6001       with   mongoc_client_session_destroy().  Any  mongoc_cursor_t  or  mon‐
6002       goc_change_stream_t using a session must be destroyed before  the  ses‐
6003       sion,  and  a  session  must be destroyed before the mongoc_client_t it
6004       came from.
6005
6006       By default, sessions are causally consistent. To disable causal consis‐
6007       tency,  before  starting  a  session create a mongoc_session_opt_t with
6008       mongoc_session_opts_new() and call  mongoc_session_opts_set_causal_con‐
6009       sistency(), then free the struct with mongoc_session_opts_destroy.
6010
6011       Unacknowledged writes are prohibited with sessions.
6012
6013       A  mongoc_client_session_t  must  be used by only one thread at a time.
6014       Due to session pooling, mongoc_client_start_session may return  a  ses‐
6015       sion  that  has been idle for some time and is about to be closed after
6016       its idle timeout. Use the session within one minute of acquiring it  to
6017       refresh the session and avoid a timeout.
6018
6019   Client Side Encryption
6020       When  configuring  a  mongoc_client_t for automatic encryption via mon‐
6021       goc_client_enable_auto_encryption(), if a separate key vault client  is
6022       set    in   the   options   (via   mongoc_auto_encryption_opts_set_key‐
6023       vault_client()) the key vault client must outlive the encrypted client.
6024
6025       When configuring a mongoc_client_pool_t for  automatic  encryption  via
6026       mongoc_client_pool_enable_auto_encryption(),  if  a  separate key vault
6027       client  pool  is  set   in   the   options   (via   mongoc_auto_encryp‐
6028       tion_opts_set_keyvault_client_pool())  the  key  vault client pool must
6029       outlive the encrypted client pool.
6030
6031       When creating a mongoc_client_encryption_t, the  configured  key  vault
6032       client  (set  via  mongoc_client_encryption_opts_set_keyvault_client())
6033       must outlive the mongoc_client_encryption_t.
6034
6035   GridFS
6036       The C driver includes two APIs for GridFS.
6037
6038       The older API consists of mongoc_gridfs_t and its derivatives. It  con‐
6039       tains  deprecated  API,  does  not support read preferences, and is not
6040       recommended in new applications. It does not  conform  to  the  MongoDB
6041       GridFS specification.
6042
6043       The  newer  API  consists  of mongoc_gridfs_bucket_t and allows upload‐
6044       ing/downloading through derived mongoc_stream_t objects. It conforms to
6045       the MongoDB GridFS specification.
6046
6047       There  is not always a straightforward upgrade path from an application
6048       built with  mongoc_gridfs_t  to  mongoc_gridfs_bucket_t  (e.g.  a  mon‐
6049       goc_gridfs_file_t  provides  functions to seek but mongoc_stream_t does
6050       not). But users are encouraged to upgrade when possible.
6051
6052   mongoc_auto_encryption_opts_t
6053       Options  for  enabling  automatic   encryption   and   decryption   for
6054       Client-Side Field Level Encryption.
6055
6056   Synopsis
6057          typedef struct _mongoc_auto_encryption_opts_t mongoc_auto_encryption_opts_t;
6058
6059   See Also
6060       · The guide for Using Client-Side Field Level Encryption
6061
6062   mongoc_bulk_operation_t
6063       Bulk Write Operations
6064
6065   Synopsis
6066          typedef struct _mongoc_bulk_operation_t mongoc_bulk_operation_t;
6067
6068       The  opaque  type  mongoc_bulk_operation_t  provides an abstraction for
6069       submitting multiple write operations as a single batch.
6070
6071       After adding all of the  write  operations  to  the  mongoc_bulk_opera‐
6072       tion_t, call mongoc_bulk_operation_execute() to execute the operation.
6073
6074       WARNING:
6075          It  is  only valid to call mongoc_bulk_operation_execute() once. The
6076          mongoc_bulk_operation_t must be destroyed afterwards.
6077
6078   See Also
6079       Bulk Write Operations
6080
6081   mongoc_change_stream_t
6082   Synopsis
6083          #include <mongoc/mongoc.h>
6084
6085          typedef struct _mongoc_change_stream_t mongoc_change_stream_t;
6086
6087       mongoc_change_stream_t is a handle to a  change  stream.  A  collection
6088       change stream can be obtained using mongoc_collection_watch.
6089
6090       It  is  recommended  to  use a mongoc_change_stream_t and its functions
6091       instead of a raw aggregation  with  a  $changeStream  stage.  For  more
6092       information see the MongoDB Manual Entry on Change Streams.
6093
6094   Example
6095       example-collection-watch.c.INDENT 0.0
6096
6097          #include <mongoc/mongoc.h>
6098
6099          int
6100          main ()
6101          {
6102             bson_t empty = BSON_INITIALIZER;
6103             const bson_t *doc;
6104             bson_t *to_insert = BCON_NEW ("x", BCON_INT32 (1));
6105             const bson_t *err_doc;
6106             bson_error_t error;
6107             const char *uri_string;
6108             mongoc_uri_t *uri;
6109             mongoc_client_t *client;
6110             mongoc_collection_t *coll;
6111             mongoc_change_stream_t *stream;
6112             mongoc_write_concern_t *wc = mongoc_write_concern_new ();
6113             bson_t opts = BSON_INITIALIZER;
6114             bool r;
6115
6116             mongoc_init ();
6117
6118             uri_string = "mongodb://"
6119                          "localhost:27017,localhost:27018,localhost:"
6120                          "27019/db?replicaSet=rs0";
6121
6122             uri = mongoc_uri_new_with_error (uri_string, &error);
6123             if (!uri) {
6124                fprintf (stderr,
6125                         "failed to parse URI: %s\n"
6126                         "error message:       %s\n",
6127                         uri_string,
6128                         error.message);
6129                return EXIT_FAILURE;
6130             }
6131
6132             client = mongoc_client_new_from_uri (uri);
6133             if (!client) {
6134                return EXIT_FAILURE;
6135             }
6136
6137             coll = mongoc_client_get_collection (client, "db", "coll");
6138             stream = mongoc_collection_watch (coll, &empty, NULL);
6139
6140             mongoc_write_concern_set_wmajority (wc, 10000);
6141             mongoc_write_concern_append (wc, &opts);
6142             r = mongoc_collection_insert_one (coll, to_insert, &opts, NULL, &error);
6143             if (!r) {
6144                fprintf (stderr, "Error: %s\n", error.message);
6145                return EXIT_FAILURE;
6146             }
6147
6148             while (mongoc_change_stream_next (stream, &doc)) {
6149                char *as_json = bson_as_relaxed_extended_json (doc, NULL);
6150                fprintf (stderr, "Got document: %s\n", as_json);
6151                bson_free (as_json);
6152             }
6153
6154             if (mongoc_change_stream_error_document (stream, &error, &err_doc)) {
6155                if (!bson_empty (err_doc)) {
6156                   fprintf (stderr,
6157                            "Server Error: %s\n",
6158                            bson_as_relaxed_extended_json (err_doc, NULL));
6159                } else {
6160                   fprintf (stderr, "Client Error: %s\n", error.message);
6161                }
6162                return EXIT_FAILURE;
6163             }
6164
6165             bson_destroy (to_insert);
6166             mongoc_write_concern_destroy (wc);
6167             bson_destroy (&opts);
6168             mongoc_change_stream_destroy (stream);
6169             mongoc_collection_destroy (coll);
6170             mongoc_uri_destroy (uri);
6171             mongoc_client_destroy (client);
6172             mongoc_cleanup ();
6173
6174             return EXIT_SUCCESS;
6175          }
6176
6177
6178   Starting and Resuming
6179       All  watch  functions accept several options to indicate where a change
6180       stream should start returning changes  from:  resumeAfter,  startAfter,
6181       and startAtOperationTime.
6182
6183       All  changes  returned  by  mongoc_change_stream_next  include a resume
6184       token in the _id field. MongoDB 4.2 also includes an additional  resume
6185       token  in each "aggregate" and "getMore" command response, which points
6186       to the end of that response's batch. The current token is automatically
6187       cached  by  libmongoc.  In the event of an error, libmongoc attempts to
6188       recreate the change stream starting where it left off  by  passing  the
6189       cached resume token. libmongoc only attempts to resume once, but client
6190       applications  can  access   the   cached   resume   token   with   mon‐
6191       goc_change_stream_get_resume_token  and  use  it  for  their own resume
6192       logic by passing it as either the resumeAfter or startAfter option.
6193
6194       Additionally, change streams can start returning changes at  an  opera‐
6195       tion  time  by  using  the  startAtOperationTime field. This can be the
6196       timestamp returned in the operationTime field of a command reply.
6197
6198       resumeAfter, startAfter, and startAtOperationTime are  mutually  exclu‐
6199       sive options. Setting more than one will result in a server error.
6200
6201       The  following example implements custom resuming logic, persisting the
6202       resume token in a file.  example-resume.c.INDENT 0.0
6203
6204          #include <mongoc/mongoc.h>
6205
6206          /* An example implementation of custom resume logic in a change stream.
6207          * example-resume starts a client-wide change stream and persists the resume
6208          * token in a file "resume-token.json". On restart, if "resume-token.json"
6209          * exists, the change stream starts watching after the persisted resume token.
6210          *
6211          * This behavior allows a user to exit example-resume, and restart it later
6212          * without missing any change events.
6213          */
6214          #include <unistd.h>
6215
6216          static const char *RESUME_TOKEN_PATH = "resume-token.json";
6217
6218          static bool
6219          _save_resume_token (const bson_t *doc)
6220          {
6221             FILE *file_stream;
6222             bson_iter_t iter;
6223             bson_t resume_token_doc;
6224             char *as_json = NULL;
6225             size_t as_json_len;
6226             ssize_t r, n_written;
6227             const bson_value_t *resume_token;
6228
6229             if (!bson_iter_init_find (&iter, doc, "_id")) {
6230                fprintf (stderr, "reply does not contain operationTime.");
6231                return false;
6232             }
6233             resume_token = bson_iter_value (&iter);
6234             /* store the resume token in a document, { resumeAfter: <resume token> }
6235              * which we can later append easily. */
6236             file_stream = fopen (RESUME_TOKEN_PATH, "w+");
6237             if (!file_stream) {
6238                fprintf (stderr, "failed to open %s for writing\n", RESUME_TOKEN_PATH);
6239                return false;
6240             }
6241             bson_init (&resume_token_doc);
6242             BSON_APPEND_VALUE (&resume_token_doc, "resumeAfter", resume_token);
6243             as_json = bson_as_canonical_extended_json (&resume_token_doc, &as_json_len);
6244             bson_destroy (&resume_token_doc);
6245             n_written = 0;
6246             while (n_written < as_json_len) {
6247                r = fwrite ((void *) (as_json + n_written),
6248                            sizeof (char),
6249                            as_json_len - n_written,
6250                            file_stream);
6251                if (r == -1) {
6252                   fprintf (stderr, "failed to write to %s\n", RESUME_TOKEN_PATH);
6253                   bson_free (as_json);
6254                   fclose (file_stream);
6255                   return false;
6256                }
6257                n_written += r;
6258             }
6259
6260             bson_free (as_json);
6261             fclose (file_stream);
6262             return true;
6263          }
6264
6265          bool
6266          _load_resume_token (bson_t *opts)
6267          {
6268             bson_error_t error;
6269             bson_json_reader_t *reader;
6270             bson_t doc;
6271
6272             /* if the file does not exist, skip. */
6273             if (-1 == access (RESUME_TOKEN_PATH, R_OK)) {
6274                return true;
6275             }
6276             reader = bson_json_reader_new_from_file (RESUME_TOKEN_PATH, &error);
6277             if (!reader) {
6278                fprintf (stderr,
6279                         "failed to open %s for reading: %s\n",
6280                         RESUME_TOKEN_PATH,
6281                         error.message);
6282                return false;
6283             }
6284
6285             bson_init (&doc);
6286             if (-1 == bson_json_reader_read (reader, &doc, &error)) {
6287                fprintf (stderr, "failed to read doc from %s\n", RESUME_TOKEN_PATH);
6288                bson_destroy (&doc);
6289                bson_json_reader_destroy (reader);
6290                return false;
6291             }
6292
6293             printf ("found cached resume token in %s, resuming change stream.\n",
6294                     RESUME_TOKEN_PATH);
6295
6296             bson_concat (opts, &doc);
6297             bson_destroy (&doc);
6298             bson_json_reader_destroy (reader);
6299             return true;
6300          }
6301
6302          int
6303          main ()
6304          {
6305             int exit_code = EXIT_FAILURE;
6306             const char *uri_string;
6307             mongoc_uri_t *uri = NULL;
6308             bson_error_t error;
6309             mongoc_client_t *client = NULL;
6310             bson_t pipeline = BSON_INITIALIZER;
6311             bson_t opts = BSON_INITIALIZER;
6312             mongoc_change_stream_t *stream = NULL;
6313             const bson_t *doc;
6314
6315             const int max_time = 30; /* max amount of time, in seconds, that
6316                                         mongoc_change_stream_next can block. */
6317
6318             mongoc_init ();
6319             uri_string = "mongodb://localhost:27017/db?replicaSet=rs0";
6320             uri = mongoc_uri_new_with_error (uri_string, &error);
6321             if (!uri) {
6322                fprintf (stderr,
6323                         "failed to parse URI: %s\n"
6324                         "error message:       %s\n",
6325                         uri_string,
6326                         error.message);
6327                goto cleanup;
6328             }
6329
6330             client = mongoc_client_new_from_uri (uri);
6331             if (!client) {
6332                goto cleanup;
6333             }
6334
6335             if (!_load_resume_token (&opts)) {
6336                goto cleanup;
6337             }
6338             BSON_APPEND_INT64 (&opts, "maxAwaitTimeMS", max_time * 1000);
6339
6340             printf ("listening for changes on the client (max %d seconds).\n", max_time);
6341             stream = mongoc_client_watch (client, &pipeline, &opts);
6342
6343             while (mongoc_change_stream_next (stream, &doc)) {
6344                char *as_json;
6345
6346                as_json = bson_as_canonical_extended_json (doc, NULL);
6347                printf ("change received: %s\n", as_json);
6348                bson_free (as_json);
6349                if (!_save_resume_token (doc)) {
6350                   goto cleanup;
6351                }
6352             }
6353
6354             exit_code = EXIT_SUCCESS;
6355
6356          cleanup:
6357             mongoc_uri_destroy (uri);
6358             bson_destroy (&pipeline);
6359             bson_destroy (&opts);
6360             mongoc_change_stream_destroy (stream);
6361             mongoc_client_destroy (client);
6362             mongoc_cleanup ();
6363             return exit_code;
6364          }
6365
6366
6367The following example shows using startAtOperationTime to synchronize a change
6368stream with another operation.  example-start-at-optime.c.INDENT 0.0
6369
6370          /* An example of starting a change stream with startAtOperationTime. */
6371          #include <mongoc/mongoc.h>
6372
6373          int
6374          main ()
6375          {
6376             int exit_code = EXIT_FAILURE;
6377             const char *uri_string;
6378             mongoc_uri_t *uri = NULL;
6379             bson_error_t error;
6380             mongoc_client_t *client = NULL;
6381             mongoc_collection_t *coll = NULL;
6382             bson_t pipeline = BSON_INITIALIZER;
6383             bson_t opts = BSON_INITIALIZER;
6384             mongoc_change_stream_t *stream = NULL;
6385             bson_iter_t iter;
6386             const bson_t *doc;
6387             bson_value_t cached_operation_time = {0};
6388             int i;
6389             bool r;
6390
6391             mongoc_init ();
6392             uri_string = "mongodb://localhost:27017/db?replicaSet=rs0";
6393             uri = mongoc_uri_new_with_error (uri_string, &error);
6394             if (!uri) {
6395                fprintf (stderr,
6396                         "failed to parse URI: %s\n"
6397                         "error message:       %s\n",
6398                         uri_string,
6399                         error.message);
6400                goto cleanup;
6401             }
6402
6403             client = mongoc_client_new_from_uri (uri);
6404             if (!client) {
6405                goto cleanup;
6406             }
6407
6408             /* insert five documents. */
6409             coll = mongoc_client_get_collection (client, "db", "coll");
6410             for (i = 0; i < 5; i++) {
6411                bson_t reply;
6412                bson_t *insert_cmd = BCON_NEW ("insert",
6413                                               "coll",
6414                                               "documents",
6415                                               "[",
6416                                               "{",
6417                                               "x",
6418                                               BCON_INT64 (i),
6419                                               "}",
6420                                               "]");
6421
6422                r = mongoc_collection_write_command_with_opts (
6423                   coll, insert_cmd, NULL, &reply, &error);
6424                bson_destroy (insert_cmd);
6425                if (!r) {
6426                   bson_destroy (&reply);
6427                   fprintf (stderr, "failed to insert: %s\n", error.message);
6428                   goto cleanup;
6429                }
6430                if (i == 0) {
6431                   /* cache the operation time in the first reply. */
6432                   if (bson_iter_init_find (&iter, &reply, "operationTime")) {
6433                      bson_value_copy (bson_iter_value (&iter), &cached_operation_time);
6434                   } else {
6435                      fprintf (stderr, "reply does not contain operationTime.");
6436                      bson_destroy (&reply);
6437                      goto cleanup;
6438                   }
6439                }
6440                bson_destroy (&reply);
6441             }
6442
6443             /* start a change stream at the first returned operationTime. */
6444             BSON_APPEND_VALUE (&opts, "startAtOperationTime", &cached_operation_time);
6445             stream = mongoc_collection_watch (coll, &pipeline, &opts);
6446
6447             /* since the change stream started at the operation time of the first
6448              * insert, the five inserts are returned. */
6449             printf ("listening for changes on db.coll:\n");
6450             while (mongoc_change_stream_next (stream, &doc)) {
6451                char *as_json;
6452
6453                as_json = bson_as_canonical_extended_json (doc, NULL);
6454                printf ("change received: %s\n", as_json);
6455                bson_free (as_json);
6456             }
6457
6458             exit_code = EXIT_SUCCESS;
6459
6460          cleanup:
6461             mongoc_uri_destroy (uri);
6462             bson_destroy (&pipeline);
6463             bson_destroy (&opts);
6464             if (cached_operation_time.value_type) {
6465                bson_value_destroy (&cached_operation_time);
6466             }
6467             mongoc_change_stream_destroy (stream);
6468             mongoc_collection_destroy (coll);
6469             mongoc_client_destroy (client);
6470             mongoc_cleanup ();
6471             return exit_code;
6472          }
6473
6474   mongoc_client_encryption_t
6475   Synopsis
6476          typedef struct _mongoc_client_encryption_t mongoc_client_encryption_t;
6477
6478       mongoc_client_encryption_t  provides  utility functions for Client-Side
6479       Field Level Encryption. See the guide for Using Client-Side Field Level
6480       Encryption.
6481
6482   Thread Safety
6483       mongoc_client_encryption_t  is  NOT thread-safe and should only be used
6484       in the same thread as the mongoc_client_t that is configured  via  mon‐
6485       goc_client_encryption_opts_set_keyvault_client().
6486
6487   Lifecycle
6488       The    key   vault   client,   configured   via   mongoc_client_encryp‐
6489       tion_opts_set_keyvault_client(), must outlive the mongoc_client_encryp‐
6490       tion_t.
6491
6492   See also
6493       · mongoc_client_enable_auto_encryption()
6494
6495       · mongoc_client_pool_enable_auto_encryption()
6496
6497       · The guide for Using Client-Side Field Level Encryption for libmongoc
6498
6499       · The MongoDB Manual for Client-Side Field Level Encryption
6500
6501   mongoc_client_encryption_datakey_opts_t
6502   Synopsis
6503          typedef struct _mongoc_client_encryption_datakey_opts_t mongoc_client_encryption_datakey_opts_t;
6504
6505       Used to set options for mongoc_client_encryption_create_datakey().
6506
6507   See also
6508       · mongoc_client_encryption_create_datakey()
6509
6510   mongoc_client_encryption_encrypt_opts_t
6511   Synopsis
6512          typedef struct _mongoc_client_encryption_encrypt_opts_t mongoc_client_encryption_encrypt_opts_t;
6513
6514       Used to set options for mongoc_client_encryption_encrypt().
6515
6516   See also
6517       · mongoc_client_encryption_encrypt()
6518
6519   mongoc_client_encryption_opts_t
6520   Synopsis
6521          typedef struct _mongoc_client_encryption_opts_t mongoc_client_encryption_opts_t;
6522
6523       Used to set options for mongoc_client_encryption_new().
6524
6525   See also
6526       · mongoc_client_encryption_new()
6527
6528   mongoc_client_pool_t
6529       A connection pool for multi-threaded programs. See connection-pooling.
6530
6531   Synopsis
6532          typedef struct _mongoc_client_pool_t mongoc_client_pool_t
6533
6534       mongoc_client_pool_t  is the basis for multi-threading in the MongoDB C
6535       driver. Since mongoc_client_t  structures  are  not  thread-safe,  this
6536       structure is used to retrieve a new mongoc_client_t for a given thread.
6537       This structure is thread-safe, except for its destructor  method,  mon‐
6538       goc_client_pool_destroy,  which  is  not  thread-safe  and must only be
6539       called from one thread.
6540
6541   Example
6542       example-pool.c.INDENT 0.0
6543
6544          /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs
6545           * libmongoc-1.0) */
6546
6547          /* ./example-pool [CONNECTION_STRING] */
6548
6549          #include <mongoc/mongoc.h>
6550          #include <pthread.h>
6551          #include <stdio.h>
6552
6553          static pthread_mutex_t mutex;
6554          static bool in_shutdown = false;
6555
6556          static void *
6557          worker (void *data)
6558          {
6559             mongoc_client_pool_t *pool = data;
6560             mongoc_client_t *client;
6561             bson_t ping = BSON_INITIALIZER;
6562             bson_error_t error;
6563             bool r;
6564
6565             BSON_APPEND_INT32 (&ping, "ping", 1);
6566
6567             while (true) {
6568                client = mongoc_client_pool_pop (pool);
6569                /* Do something with client. If you are writing an HTTP server, you
6570                 * probably only want to hold onto the client for the portion of the
6571                 * request performing database queries.
6572                 */
6573                r = mongoc_client_command_simple (
6574                   client, "admin", &ping, NULL, NULL, &error);
6575
6576                if (!r) {
6577                   fprintf (stderr, "%s\n", error.message);
6578                }
6579
6580                mongoc_client_pool_push (pool, client);
6581
6582                pthread_mutex_lock (&mutex);
6583                if (in_shutdown || !r) {
6584                   pthread_mutex_unlock (&mutex);
6585                   break;
6586                }
6587
6588                pthread_mutex_unlock (&mutex);
6589             }
6590
6591             bson_destroy (&ping);
6592             return NULL;
6593          }
6594
6595          int
6596          main (int argc, char *argv[])
6597          {
6598             const char *uri_string = "mongodb://127.0.0.1/?appname=pool-example";
6599             mongoc_uri_t *uri;
6600             bson_error_t error;
6601             mongoc_client_pool_t *pool;
6602             pthread_t threads[10];
6603             unsigned i;
6604             void *ret;
6605
6606             pthread_mutex_init (&mutex, NULL);
6607             mongoc_init ();
6608
6609             if (argc > 1) {
6610                uri_string = argv[1];
6611             }
6612
6613             uri = mongoc_uri_new_with_error (uri_string, &error);
6614             if (!uri) {
6615                fprintf (stderr,
6616                         "failed to parse URI: %s\n"
6617                         "error message:       %s\n",
6618                         uri_string,
6619                         error.message);
6620                return EXIT_FAILURE;
6621             }
6622
6623             pool = mongoc_client_pool_new (uri);
6624             mongoc_client_pool_set_error_api (pool, 2);
6625
6626             for (i = 0; i < 10; i++) {
6627                pthread_create (&threads[i], NULL, worker, pool);
6628             }
6629
6630             sleep (10);
6631             pthread_mutex_lock (&mutex);
6632             in_shutdown = true;
6633             pthread_mutex_unlock (&mutex);
6634
6635             for (i = 0; i < 10; i++) {
6636                pthread_join (threads[i], &ret);
6637             }
6638
6639             mongoc_client_pool_destroy (pool);
6640             mongoc_uri_destroy (uri);
6641
6642             mongoc_cleanup ();
6643
6644             return EXIT_SUCCESS;
6645          }
6646
6647
6648   mongoc_client_session_t
6649       Use a session for a sequence of operations, optionally with causal con‐
6650       sistency. See the MongoDB Manual Entry for Causal Consistency.
6651
6652   Synopsis
6653       Start a session with mongoc_client_start_session, use the session for a
6654       sequence of operations and multi-document transactions,  then  free  it
6655       with   mongoc_client_session_destroy().  Any  mongoc_cursor_t  or  mon‐
6656       goc_change_stream_t using a session must be destroyed before  the  ses‐
6657       sion,  and  a  session  must be destroyed before the mongoc_client_t it
6658       came from.
6659
6660       By default, sessions are causally consistent. To disable causal consis‐
6661       tency,  before  starting  a  session create a mongoc_session_opt_t with
6662       mongoc_session_opts_new() and call  mongoc_session_opts_set_causal_con‐
6663       sistency(), then free the struct with mongoc_session_opts_destroy.
6664
6665       Unacknowledged writes are prohibited with sessions.
6666
6667       A  mongoc_client_session_t  must  be used by only one thread at a time.
6668       Due to session pooling, mongoc_client_start_session may return  a  ses‐
6669       sion  that  has been idle for some time and is about to be closed after
6670       its idle timeout. Use the session within one minute of acquiring it  to
6671       refresh the session and avoid a timeout.
6672
6673   Example
6674       example-session.c.INDENT 0.0
6675
6676          /* gcc example-session.c -o example-session \
6677           *     $(pkg-config --cflags --libs libmongoc-1.0) */
6678
6679          /* ./example-session [CONNECTION_STRING] */
6680
6681          #include <stdio.h>
6682          #include <mongoc/mongoc.h>
6683
6684
6685          int
6686          main (int argc, char *argv[])
6687          {
6688             int exit_code = EXIT_FAILURE;
6689
6690             mongoc_client_t *client = NULL;
6691             const char *uri_string = "mongodb://127.0.0.1/?appname=session-example";
6692             mongoc_uri_t *uri = NULL;
6693             mongoc_client_session_t *client_session = NULL;
6694             mongoc_collection_t *collection = NULL;
6695             bson_error_t error;
6696             bson_t *selector = NULL;
6697             bson_t *update = NULL;
6698             bson_t *update_opts = NULL;
6699             bson_t *find_opts = NULL;
6700             mongoc_read_prefs_t *secondary = NULL;
6701             mongoc_cursor_t *cursor = NULL;
6702             const bson_t *doc;
6703             char *str;
6704             bool r;
6705
6706             mongoc_init ();
6707
6708             if (argc > 1) {
6709                uri_string = argv[1];
6710             }
6711
6712             uri = mongoc_uri_new_with_error (uri_string, &error);
6713             if (!uri) {
6714                fprintf (stderr,
6715                         "failed to parse URI: %s\n"
6716                         "error message:       %s\n",
6717                         uri_string,
6718                         error.message);
6719                goto done;
6720             }
6721
6722             client = mongoc_client_new_from_uri (uri);
6723             if (!client) {
6724                goto done;
6725             }
6726
6727             mongoc_client_set_error_api (client, 2);
6728
6729             /* pass NULL for options - by default the session is causally consistent */
6730             client_session = mongoc_client_start_session (client, NULL, &error);
6731             if (!client_session) {
6732                fprintf (stderr, "Failed to start session: %s\n", error.message);
6733                goto done;
6734             }
6735
6736             collection = mongoc_client_get_collection (client, "test", "collection");
6737             selector = BCON_NEW ("_id", BCON_INT32 (1));
6738             update = BCON_NEW ("$inc", "{", "x", BCON_INT32 (1), "}");
6739             update_opts = bson_new ();
6740             if (!mongoc_client_session_append (client_session, update_opts, &error)) {
6741                fprintf (stderr, "Could not add session to opts: %s\n", error.message);
6742                goto done;
6743             }
6744
6745             r = mongoc_collection_update_one (
6746                collection, selector, update, update_opts, NULL /* reply */, &error);
6747
6748             if (!r) {
6749                fprintf (stderr, "Update failed: %s\n", error.message);
6750                goto done;
6751             }
6752
6753             bson_destroy (selector);
6754             selector = BCON_NEW ("_id", BCON_INT32 (1));
6755             secondary = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
6756
6757             find_opts = BCON_NEW ("maxTimeMS", BCON_INT32 (2000));
6758             if (!mongoc_client_session_append (client_session, find_opts, &error)) {
6759                fprintf (stderr, "Could not add session to opts: %s\n", error.message);
6760                goto done;
6761             };
6762
6763             /* read from secondary. since we're in a causally consistent session, the
6764              * data is guaranteed to reflect the update we did on the primary. the query
6765              * blocks waiting for the secondary to catch up, if necessary, or times out
6766              * and fails after 2000 ms.
6767              */
6768             cursor = mongoc_collection_find_with_opts (
6769                collection, selector, find_opts, secondary);
6770
6771             while (mongoc_cursor_next (cursor, &doc)) {
6772                str = bson_as_json (doc, NULL);
6773                fprintf (stdout, "%s\n", str);
6774                bson_free (str);
6775             }
6776
6777             if (mongoc_cursor_error (cursor, &error)) {
6778                fprintf (stderr, "Cursor Failure: %s\n", error.message);
6779                goto done;
6780             }
6781
6782             exit_code = EXIT_SUCCESS;
6783
6784          done:
6785             if (find_opts) {
6786                bson_destroy (find_opts);
6787             }
6788             if (update) {
6789                bson_destroy (update);
6790             }
6791             if (selector) {
6792                bson_destroy (selector);
6793             }
6794             if (update_opts) {
6795                bson_destroy (update_opts);
6796             }
6797             if (secondary) {
6798                mongoc_read_prefs_destroy (secondary);
6799             }
6800             /* destroy cursor, collection, session before the client they came from */
6801             if (cursor) {
6802                mongoc_cursor_destroy (cursor);
6803             }
6804             if (collection) {
6805                mongoc_collection_destroy (collection);
6806             }
6807             if (client_session) {
6808                mongoc_client_session_destroy (client_session);
6809             }
6810             if (uri) {
6811                mongoc_uri_destroy (uri);
6812             }
6813             if (client) {
6814                mongoc_client_destroy (client);
6815             }
6816
6817             mongoc_cleanup ();
6818
6819             return exit_code;
6820          }
6821
6822
6823   mongoc_client_session_with_transaction_cb_t
6824   Synopsis
6825          typedef bool (*mongoc_client_session_with_transaction_cb_t) (
6826             mongoc_client_session_t *session,
6827             void *ctx,
6828             bson_t **reply,
6829             bson_error_t *error);
6830
6831       Provide  this  callback  to mongoc_client_session_with_transaction. The
6832       callback should run a sequence of  operations  meant  to  be  contained
6833       within a transaction.  The callback should not attempt to start or com‐
6834       mit transactions.
6835
6836   Parameters
6837       · session: A mongoc_client_session_t.
6838
6839       · ctx: A void*  set  to  the  the  user-provided  ctx  passed  to  mon‐
6840         goc_client_session_with_transaction.
6841
6842       · reply: An optional location for a bson_t or NULL. The callback should
6843         set this if it runs any operations against the  server  and  receives
6844         replies.
6845
6846       · error:  A  bson_error_t.  The callback should set this if it receives
6847         any errors while running operations against the server.
6848
6849   Return
6850       Returns true for success and false on failure. If cb returns false then
6851       it should also set error.
6852
6853   See Also
6854       mongoc_client_session_with_transaction
6855
6856   mongoc_client_t
6857       A single-threaded MongoDB connection. See connection-pooling.
6858
6859   Synopsis
6860          typedef struct _mongoc_client_t mongoc_client_t;
6861
6862          typedef mongoc_stream_t *(*mongoc_stream_initiator_t) (
6863             const mongoc_uri_t *uri,
6864             const mongoc_host_list_t *host,
6865             void *user_data,
6866             bson_error_t *error);
6867
6868       mongoc_client_t  is  an  opaque  type that provides access to a MongoDB
6869       server, replica set, or sharded cluster.  It  maintains  management  of
6870       underlying  sockets  and  routing  to  individual  nodes  based on mon‐
6871       goc_read_prefs_t or mongoc_write_concern_t.
6872
6873   Streams
6874       The underlying transport for a given client can be customized,  wrapped
6875       or replaced by any implementation that fulfills mongoc_stream_t. A cus‐
6876       tom transport can be set with mongoc_client_set_stream_initiator().
6877
6878   Thread Safety
6879       mongoc_client_t is NOT thread-safe and should only  be  used  from  one
6880       thread  at  a time. When used in multi-threaded scenarios, it is recom‐
6881       mended that you use the thread-safe mongoc_client_pool_t to retrieve  a
6882       mongoc_client_t for your thread.
6883
6884   Example
6885       example-client.c.INDENT 0.0
6886
6887          /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
6888           * libmongoc-1.0) */
6889
6890          /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */
6891
6892          #include <mongoc/mongoc.h>
6893          #include <stdio.h>
6894          #include <stdlib.h>
6895
6896          int
6897          main (int argc, char *argv[])
6898          {
6899             mongoc_client_t *client;
6900             mongoc_collection_t *collection;
6901             mongoc_cursor_t *cursor;
6902             bson_error_t error;
6903             const bson_t *doc;
6904             const char *collection_name = "test";
6905             bson_t query;
6906             char *str;
6907             const char *uri_string = "mongodb://127.0.0.1/?appname=client-example";
6908             mongoc_uri_t *uri;
6909
6910             mongoc_init ();
6911             if (argc > 1) {
6912                uri_string = argv[1];
6913             }
6914
6915             if (argc > 2) {
6916                collection_name = argv[2];
6917             }
6918
6919             uri = mongoc_uri_new_with_error (uri_string, &error);
6920             if (!uri) {
6921                fprintf (stderr,
6922                         "failed to parse URI: %s\n"
6923                         "error message:       %s\n",
6924                         uri_string,
6925                         error.message);
6926                return EXIT_FAILURE;
6927             }
6928
6929             client = mongoc_client_new_from_uri (uri);
6930             if (!client) {
6931                return EXIT_FAILURE;
6932             }
6933
6934             mongoc_client_set_error_api (client, 2);
6935
6936             bson_init (&query);
6937
6938          #if 0
6939             bson_append_utf8 (&query, "hello", -1, "world", -1);
6940          #endif
6941
6942             collection = mongoc_client_get_collection (client, "test", collection_name);
6943             cursor = mongoc_collection_find_with_opts (
6944                collection,
6945                &query,
6946                NULL,  /* additional options */
6947                NULL); /* read prefs, NULL for default */
6948
6949             while (mongoc_cursor_next (cursor, &doc)) {
6950                str = bson_as_canonical_extended_json (doc, NULL);
6951                fprintf (stdout, "%s\n", str);
6952                bson_free (str);
6953             }
6954
6955             if (mongoc_cursor_error (cursor, &error)) {
6956                fprintf (stderr, "Cursor Failure: %s\n", error.message);
6957                return EXIT_FAILURE;
6958             }
6959
6960             bson_destroy (&query);
6961             mongoc_cursor_destroy (cursor);
6962             mongoc_collection_destroy (collection);
6963             mongoc_uri_destroy (uri);
6964             mongoc_client_destroy (client);
6965             mongoc_cleanup ();
6966
6967             return EXIT_SUCCESS;
6968          }
6969
6970
6971   mongoc_collection_t
6972   Synopsis
6973          typedef struct _mongoc_collection_t mongoc_collection_t;
6974
6975       mongoc_collection_t provides access to a MongoDB collection.  This han‐
6976       dle is useful for  actions  for  most  CRUD  operations,  I.e.  insert,
6977       update, delete, find, etc.
6978
6979   Read Preferences and Write Concerns
6980       Read  preferences  and  write  concerns  are  inherited from the parent
6981       client. They can be overridden by set_* commands if so desired.
6982
6983   mongoc_cursor_t
6984       Client-side cursor abstraction
6985
6986   Synopsis
6987          typedef struct _mongoc_cursor_t mongoc_cursor_t;
6988
6989       mongoc_cursor_t provides access to a MongoDB query cursor.  It wraps up
6990       the wire protocol negotiation required to initiate a query and retrieve
6991       an unknown number of documents.
6992
6993       Common cursor operations include:
6994
6995       · Determine  which   host   we've   connected   to   with   mongoc_cur‐
6996         sor_get_host().
6997
6998       · Retrieve more records with repeated calls to mongoc_cursor_next().
6999
7000       · Clone  a  query to repeat execution at a later point with mongoc_cur‐
7001         sor_clone().
7002
7003       · Test for errors with mongoc_cursor_error().
7004
7005       Cursors are lazy, meaning that no connection is established and no net‐
7006       work traffic occurs until the first call to mongoc_cursor_next().
7007
7008   Thread Safety
7009       mongoc_cursor_t is NOT thread safe. It may only be used from within the
7010       thread in which it was created.
7011
7012   Example
7013       Query MongoDB and iterate results.INDENT 0.0
7014
7015          /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
7016           * libmongoc-1.0) */
7017
7018          /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */
7019
7020          #include <mongoc/mongoc.h>
7021          #include <stdio.h>
7022          #include <stdlib.h>
7023
7024          int
7025          main (int argc, char *argv[])
7026          {
7027             mongoc_client_t *client;
7028             mongoc_collection_t *collection;
7029             mongoc_cursor_t *cursor;
7030             bson_error_t error;
7031             const bson_t *doc;
7032             const char *collection_name = "test";
7033             bson_t query;
7034             char *str;
7035             const char *uri_string = "mongodb://127.0.0.1/?appname=client-example";
7036             mongoc_uri_t *uri;
7037
7038             mongoc_init ();
7039             if (argc > 1) {
7040                uri_string = argv[1];
7041             }
7042
7043             if (argc > 2) {
7044                collection_name = argv[2];
7045             }
7046
7047             uri = mongoc_uri_new_with_error (uri_string, &error);
7048             if (!uri) {
7049                fprintf (stderr,
7050                         "failed to parse URI: %s\n"
7051                         "error message:       %s\n",
7052                         uri_string,
7053                         error.message);
7054                return EXIT_FAILURE;
7055             }
7056
7057             client = mongoc_client_new_from_uri (uri);
7058             if (!client) {
7059                return EXIT_FAILURE;
7060             }
7061
7062             mongoc_client_set_error_api (client, 2);
7063
7064             bson_init (&query);
7065
7066          #if 0
7067             bson_append_utf8 (&query, "hello", -1, "world", -1);
7068          #endif
7069
7070             collection = mongoc_client_get_collection (client, "test", collection_name);
7071             cursor = mongoc_collection_find_with_opts (
7072                collection,
7073                &query,
7074                NULL,  /* additional options */
7075                NULL); /* read prefs, NULL for default */
7076
7077             while (mongoc_cursor_next (cursor, &doc)) {
7078                str = bson_as_canonical_extended_json (doc, NULL);
7079                fprintf (stdout, "%s\n", str);
7080                bson_free (str);
7081             }
7082
7083             if (mongoc_cursor_error (cursor, &error)) {
7084                fprintf (stderr, "Cursor Failure: %s\n", error.message);
7085                return EXIT_FAILURE;
7086             }
7087
7088             bson_destroy (&query);
7089             mongoc_cursor_destroy (cursor);
7090             mongoc_collection_destroy (collection);
7091             mongoc_uri_destroy (uri);
7092             mongoc_client_destroy (client);
7093             mongoc_cleanup ();
7094
7095             return EXIT_SUCCESS;
7096          }
7097
7098
7099   mongoc_database_t
7100       MongoDB Database Abstraction
7101
7102   Synopsis
7103          typedef struct _mongoc_database_t mongoc_database_t;
7104
7105       mongoc_database_t provides access to a MongoDB database. This handle is
7106       useful  for actions a particular database object. It is not a container
7107       for mongoc_collection_t structures.
7108
7109       Read preferences and write  concerns  are  inherited  from  the  parent
7110       client.  They  can  be overridden with mongoc_database_set_read_prefs()
7111       and mongoc_database_set_write_concern().
7112
7113   Examples
7114          #include <mongoc/mongoc.h>
7115
7116          int
7117          main (int argc, char *argv[])
7118          {
7119             mongoc_database_t *database;
7120             mongoc_client_t *client;
7121
7122             mongoc_init ();
7123
7124             client = mongoc_client_new ("mongodb://localhost/");
7125             database = mongoc_client_get_database (client, "test");
7126
7127             mongoc_database_destroy (database);
7128             mongoc_client_destroy (client);
7129
7130             mongoc_cleanup ();
7131
7132             return 0;
7133          }
7134
7135   mongoc_delete_flags_t
7136       Flags for deletion operations
7137
7138   Synopsis
7139          typedef enum {
7140             MONGOC_DELETE_NONE = 0,
7141             MONGOC_DELETE_SINGLE_REMOVE = 1 << 0,
7142          } mongoc_delete_flags_t;
7143
7144   Deprecated
7145       WARNING:
7146          These flags are deprecated and should not be used in new code.
7147
7148       Please    use    mongoc_collection_delete_one()    or    mongoc_collec‐
7149       tion_delete_many() instead.
7150
7151   mongoc_find_and_modify_opts_t
7152       find_and_modify abstraction
7153
7154   Synopsis
7155       mongoc_find_and_modify_opts_t  is  a  builder  interface to construct a
7156       find_and_modify command.
7157
7158       It was created to be able to accommodate new arguments to  the  MongoDB
7159       find_and_modify command.
7160
7161       As  of  MongoDB  3.2,  the mongoc_write_concern_t specified on the mon‐
7162       goc_collection_t will be used, if any.
7163
7164   Example
7165       flags.c.INDENT 0.0
7166
7167          void
7168          fam_flags (mongoc_collection_t *collection)
7169          {
7170             mongoc_find_and_modify_opts_t *opts;
7171             bson_t reply;
7172             bson_error_t error;
7173             bson_t query = BSON_INITIALIZER;
7174             bson_t *update;
7175             bool success;
7176
7177
7178             /* Find Zlatan Ibrahimovic, the striker */
7179             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7180             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7181             BSON_APPEND_UTF8 (&query, "profession", "Football player");
7182             BSON_APPEND_INT32 (&query, "age", 34);
7183             BSON_APPEND_INT32 (
7184                &query, "goals", (16 + 35 + 23 + 57 + 16 + 14 + 28 + 84) + (1 + 6 + 62));
7185
7186             /* Add his football position */
7187             update = BCON_NEW ("$set", "{", "position", BCON_UTF8 ("striker"), "}");
7188
7189             opts = mongoc_find_and_modify_opts_new ();
7190
7191             mongoc_find_and_modify_opts_set_update (opts, update);
7192
7193             /* Create the document if it didn't exist, and return the updated document */
7194             mongoc_find_and_modify_opts_set_flags (
7195                opts, MONGOC_FIND_AND_MODIFY_UPSERT | MONGOC_FIND_AND_MODIFY_RETURN_NEW);
7196
7197             success = mongoc_collection_find_and_modify_with_opts (
7198                collection, &query, opts, &reply, &error);
7199
7200             if (success) {
7201                char *str;
7202
7203                str = bson_as_canonical_extended_json (&reply, NULL);
7204                printf ("%s\n", str);
7205                bson_free (str);
7206             } else {
7207                fprintf (
7208                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7209             }
7210
7211             bson_destroy (&reply);
7212             bson_destroy (update);
7213             bson_destroy (&query);
7214             mongoc_find_and_modify_opts_destroy (opts);
7215          }
7216
7217bypass.c.INDENT 0.0
7218
7219          void
7220          fam_bypass (mongoc_collection_t *collection)
7221          {
7222             mongoc_find_and_modify_opts_t *opts;
7223             bson_t reply;
7224             bson_t *update;
7225             bson_error_t error;
7226             bson_t query = BSON_INITIALIZER;
7227             bool success;
7228
7229
7230             /* Find Zlatan Ibrahimovic, the striker */
7231             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7232             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7233             BSON_APPEND_UTF8 (&query, "profession", "Football player");
7234
7235             /* Bump his age */
7236             update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}");
7237
7238             opts = mongoc_find_and_modify_opts_new ();
7239             mongoc_find_and_modify_opts_set_update (opts, update);
7240             /* He can still play, even though he is pretty old. */
7241             mongoc_find_and_modify_opts_set_bypass_document_validation (opts, true);
7242
7243             success = mongoc_collection_find_and_modify_with_opts (
7244                collection, &query, opts, &reply, &error);
7245
7246             if (success) {
7247                char *str;
7248
7249                str = bson_as_canonical_extended_json (&reply, NULL);
7250                printf ("%s\n", str);
7251                bson_free (str);
7252             } else {
7253                fprintf (
7254                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7255             }
7256
7257             bson_destroy (&reply);
7258             bson_destroy (update);
7259             bson_destroy (&query);
7260             mongoc_find_and_modify_opts_destroy (opts);
7261          }
7262
7263update.c.INDENT 0.0
7264
7265          void
7266          fam_update (mongoc_collection_t *collection)
7267          {
7268             mongoc_find_and_modify_opts_t *opts;
7269             bson_t *update;
7270             bson_t reply;
7271             bson_error_t error;
7272             bson_t query = BSON_INITIALIZER;
7273             bool success;
7274
7275
7276             /* Find Zlatan Ibrahimovic */
7277             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7278             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7279
7280             /* Make him a book author */
7281             update = BCON_NEW ("$set", "{", "author", BCON_BOOL (true), "}");
7282
7283             opts = mongoc_find_and_modify_opts_new ();
7284             /* Note that the document returned is the _previous_ version of the document
7285              * To fetch the modified new version, use
7286              * mongoc_find_and_modify_opts_set_flags (opts,
7287              * MONGOC_FIND_AND_MODIFY_RETURN_NEW);
7288              */
7289             mongoc_find_and_modify_opts_set_update (opts, update);
7290
7291             success = mongoc_collection_find_and_modify_with_opts (
7292                collection, &query, opts, &reply, &error);
7293
7294             if (success) {
7295                char *str;
7296
7297                str = bson_as_canonical_extended_json (&reply, NULL);
7298                printf ("%s\n", str);
7299                bson_free (str);
7300             } else {
7301                fprintf (
7302                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7303             }
7304
7305             bson_destroy (&reply);
7306             bson_destroy (update);
7307             bson_destroy (&query);
7308             mongoc_find_and_modify_opts_destroy (opts);
7309          }
7310
7311fields.c.INDENT 0.0
7312
7313          void
7314          fam_fields (mongoc_collection_t *collection)
7315          {
7316             mongoc_find_and_modify_opts_t *opts;
7317             bson_t fields = BSON_INITIALIZER;
7318             bson_t *update;
7319             bson_t reply;
7320             bson_error_t error;
7321             bson_t query = BSON_INITIALIZER;
7322             bool success;
7323
7324
7325             /* Find Zlatan Ibrahimovic */
7326             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7327             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7328
7329             /* Return his goal tally */
7330             BSON_APPEND_INT32 (&fields, "goals", 1);
7331
7332             /* Bump his goal tally */
7333             update = BCON_NEW ("$inc", "{", "goals", BCON_INT32 (1), "}");
7334
7335             opts = mongoc_find_and_modify_opts_new ();
7336             mongoc_find_and_modify_opts_set_update (opts, update);
7337             mongoc_find_and_modify_opts_set_fields (opts, &fields);
7338             /* Return the new tally */
7339             mongoc_find_and_modify_opts_set_flags (opts,
7340                                                    MONGOC_FIND_AND_MODIFY_RETURN_NEW);
7341
7342             success = mongoc_collection_find_and_modify_with_opts (
7343                collection, &query, opts, &reply, &error);
7344
7345             if (success) {
7346                char *str;
7347
7348                str = bson_as_canonical_extended_json (&reply, NULL);
7349                printf ("%s\n", str);
7350                bson_free (str);
7351             } else {
7352                fprintf (
7353                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7354             }
7355
7356             bson_destroy (&reply);
7357             bson_destroy (update);
7358             bson_destroy (&fields);
7359             bson_destroy (&query);
7360             mongoc_find_and_modify_opts_destroy (opts);
7361          }
7362
7363sort.c.INDENT 0.0
7364
7365          void
7366          fam_sort (mongoc_collection_t *collection)
7367          {
7368             mongoc_find_and_modify_opts_t *opts;
7369             bson_t *update;
7370             bson_t sort = BSON_INITIALIZER;
7371             bson_t reply;
7372             bson_error_t error;
7373             bson_t query = BSON_INITIALIZER;
7374             bool success;
7375
7376
7377             /* Find all users with the lastname Ibrahimovic */
7378             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7379
7380             /* Sort by age (descending) */
7381             BSON_APPEND_INT32 (&sort, "age", -1);
7382
7383             /* Bump his goal tally */
7384             update = BCON_NEW ("$set", "{", "oldest", BCON_BOOL (true), "}");
7385
7386             opts = mongoc_find_and_modify_opts_new ();
7387             mongoc_find_and_modify_opts_set_update (opts, update);
7388             mongoc_find_and_modify_opts_set_sort (opts, &sort);
7389
7390             success = mongoc_collection_find_and_modify_with_opts (
7391                collection, &query, opts, &reply, &error);
7392
7393             if (success) {
7394                char *str;
7395
7396                str = bson_as_canonical_extended_json (&reply, NULL);
7397                printf ("%s\n", str);
7398                bson_free (str);
7399             } else {
7400                fprintf (
7401                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7402             }
7403
7404             bson_destroy (&reply);
7405             bson_destroy (update);
7406             bson_destroy (&sort);
7407             bson_destroy (&query);
7408             mongoc_find_and_modify_opts_destroy (opts);
7409          }
7410
7411opts.c.INDENT 0.0
7412
7413          void
7414          fam_opts (mongoc_collection_t *collection)
7415          {
7416             mongoc_find_and_modify_opts_t *opts;
7417             bson_t reply;
7418             bson_t *update;
7419             bson_error_t error;
7420             bson_t query = BSON_INITIALIZER;
7421             mongoc_write_concern_t *wc;
7422             bson_t extra = BSON_INITIALIZER;
7423             bool success;
7424
7425
7426             /* Find Zlatan Ibrahimovic, the striker */
7427             BSON_APPEND_UTF8 (&query, "firstname", "Zlatan");
7428             BSON_APPEND_UTF8 (&query, "lastname", "Ibrahimovic");
7429             BSON_APPEND_UTF8 (&query, "profession", "Football player");
7430
7431             /* Bump his age */
7432             update = BCON_NEW ("$inc", "{", "age", BCON_INT32 (1), "}");
7433
7434             opts = mongoc_find_and_modify_opts_new ();
7435             mongoc_find_and_modify_opts_set_update (opts, update);
7436
7437             /* Abort if the operation takes too long. */
7438             mongoc_find_and_modify_opts_set_max_time_ms (opts, 100);
7439
7440             /* Set write concern w: 2 */
7441             wc = mongoc_write_concern_new ();
7442             mongoc_write_concern_set_w (wc, 2);
7443             mongoc_write_concern_append (wc, &extra);
7444
7445             /* Some future findAndModify option the driver doesn't support conveniently
7446              */
7447             BSON_APPEND_INT32 (&extra, "futureOption", 42);
7448             mongoc_find_and_modify_opts_append (opts, &extra);
7449
7450             success = mongoc_collection_find_and_modify_with_opts (
7451                collection, &query, opts, &reply, &error);
7452
7453             if (success) {
7454                char *str;
7455
7456                str = bson_as_canonical_extended_json (&reply, NULL);
7457                printf ("%s\n", str);
7458                bson_free (str);
7459             } else {
7460                fprintf (
7461                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7462             }
7463
7464             bson_destroy (&reply);
7465             bson_destroy (&extra);
7466             bson_destroy (update);
7467             bson_destroy (&query);
7468             mongoc_write_concern_destroy (wc);
7469             mongoc_find_and_modify_opts_destroy (opts);
7470          }
7471
7472fam.c.INDENT 0.0
7473
7474          int
7475          main (void)
7476          {
7477             mongoc_collection_t *collection;
7478             mongoc_database_t *database;
7479             mongoc_client_t *client;
7480             const char *uri_string =
7481                "mongodb://localhost:27017/admin?appname=find-and-modify-opts-example";
7482             mongoc_uri_t *uri;
7483             bson_error_t error;
7484             bson_t *options;
7485
7486             mongoc_init ();
7487
7488             uri = mongoc_uri_new_with_error (uri_string, &error);
7489             if (!uri) {
7490                fprintf (stderr,
7491                         "failed to parse URI: %s\n"
7492                         "error message:       %s\n",
7493                         uri_string,
7494                         error.message);
7495                return EXIT_FAILURE;
7496             }
7497
7498             client = mongoc_client_new_from_uri (uri);
7499             if (!client) {
7500                return EXIT_FAILURE;
7501             }
7502
7503             mongoc_client_set_error_api (client, 2);
7504             database = mongoc_client_get_database (client, "databaseName");
7505
7506             options = BCON_NEW ("validator",
7507                                 "{",
7508                                 "age",
7509                                 "{",
7510                                 "$lte",
7511                                 BCON_INT32 (34),
7512                                 "}",
7513                                 "}",
7514                                 "validationAction",
7515                                 BCON_UTF8 ("error"),
7516                                 "validationLevel",
7517                                 BCON_UTF8 ("moderate"));
7518
7519             collection = mongoc_database_create_collection (
7520                database, "collectionName", options, &error);
7521             if (!collection) {
7522                fprintf (
7523                   stderr, "Got error: \"%s\" on line %d\n", error.message, __LINE__);
7524                return EXIT_FAILURE;
7525             }
7526
7527             fam_flags (collection);
7528             fam_bypass (collection);
7529             fam_update (collection);
7530             fam_fields (collection);
7531             fam_opts (collection);
7532             fam_sort (collection);
7533
7534             mongoc_collection_drop (collection, NULL);
7535             bson_destroy (options);
7536             mongoc_uri_destroy (uri);
7537             mongoc_database_destroy (database);
7538             mongoc_collection_destroy (collection);
7539             mongoc_client_destroy (client);
7540
7541             mongoc_cleanup ();
7542             return EXIT_SUCCESS;
7543          }
7544
7545
7546Outputs:
7547
7548          {
7549              "lastErrorObject": {
7550                  "updatedExisting": false,
7551                  "n": 1,
7552                  "upserted": {
7553                      "$oid": "56562a99d13e6d86239c7b00"
7554                  }
7555              },
7556              "value": {
7557                  "_id": {
7558                      "$oid": "56562a99d13e6d86239c7b00"
7559                  },
7560                  "age": 34,
7561                  "firstname": "Zlatan",
7562                  "goals": 342,
7563                  "lastname": "Ibrahimovic",
7564                  "profession": "Football player",
7565                  "position": "striker"
7566              },
7567              "ok": 1
7568          }
7569          {
7570              "lastErrorObject": {
7571                  "updatedExisting": true,
7572                  "n": 1
7573              },
7574              "value": {
7575                  "_id": {
7576                      "$oid": "56562a99d13e6d86239c7b00"
7577                  },
7578                  "age": 34,
7579                  "firstname": "Zlatan",
7580                  "goals": 342,
7581                  "lastname": "Ibrahimovic",
7582                  "profession": "Football player",
7583                  "position": "striker"
7584              },
7585              "ok": 1
7586          }
7587          {
7588              "lastErrorObject": {
7589                  "updatedExisting": true,
7590                  "n": 1
7591              },
7592              "value": {
7593                  "_id": {
7594                      "$oid": "56562a99d13e6d86239c7b00"
7595                  },
7596                  "age": 35,
7597                  "firstname": "Zlatan",
7598                  "goals": 342,
7599                  "lastname": "Ibrahimovic",
7600                  "profession": "Football player",
7601                  "position": "striker"
7602              },
7603              "ok": 1
7604          }
7605          {
7606              "lastErrorObject": {
7607                  "updatedExisting": true,
7608                  "n": 1
7609              },
7610              "value": {
7611                  "_id": {
7612                      "$oid": "56562a99d13e6d86239c7b00"
7613                  },
7614                  "goals": 343
7615              },
7616              "ok": 1
7617          }
7618          {
7619              "lastErrorObject": {
7620                  "updatedExisting": true,
7621                  "n": 1
7622              },
7623              "value": {
7624                  "_id": {
7625                      "$oid": "56562a99d13e6d86239c7b00"
7626                  },
7627                  "age": 35,
7628                  "firstname": "Zlatan",
7629                  "goals": 343,
7630                  "lastname": "Ibrahimovic",
7631                  "profession": "Football player",
7632                  "position": "striker",
7633                  "author": true
7634              },
7635              "ok": 1
7636          }
7637
7638   mongoc_gridfs_file_list_t
7639   Synopsis
7640          #include <mongoc/mongoc.h>
7641
7642          typedef struct _mongoc_gridfs_file_list_t mongoc_gridfs_file_list_t;
7643
7644   Description
7645       mongoc_gridfs_file_list_t provides a gridfs file list abstraction.   It
7646       provides  iteration  and  basic  marshalling  on  top of a regular mon‐
7647       goc_collection_find_with_opts() style query. In interface, it's  styled
7648       after mongoc_cursor_t.
7649
7650   Example
7651          mongoc_gridfs_file_list_t *list;
7652          mongoc_gridfs_file_t *file;
7653
7654          list = mongoc_gridfs_find (gridfs, query);
7655
7656          while ((file = mongoc_gridfs_file_list_next (list))) {
7657             do_something (file);
7658
7659             mongoc_gridfs_file_destroy (file);
7660          }
7661
7662          mongoc_gridfs_file_list_destroy (list);
7663
7664   mongoc_gridfs_file_opt_t
7665   Synopsis
7666          typedef struct {
7667             const char *md5;
7668             const char *filename;
7669             const char *content_type;
7670             const bson_t *aliases;
7671             const bson_t *metadata;
7672             uint32_t chunk_size;
7673          } mongoc_gridfs_file_opt_t;
7674
7675   Description
7676       This   structure   contains   options   that  can  be  set  on  a  mon‐
7677       goc_gridfs_file_t. It can be used by various functions when creating  a
7678       new gridfs file.
7679
7680   mongoc_gridfs_file_t
7681   Synopsis
7682          typedef struct _mongoc_gridfs_file_t mongoc_gridfs_file_t;
7683
7684   Description
7685       This  structure provides a MongoDB GridFS file abstraction. It provides
7686       several APIs.
7687
7688       · readv, writev, seek, and tell.
7689
7690       · General file metadata such as filename and length.
7691
7692       · GridFS metadata such as md5, filename, content_type,  aliases,  meta‐
7693         data, chunk_size, and upload_date.
7694
7695   Thread Safety
7696       This  structure  is  NOT  thread-safe  and should only be used from one
7697       thread at a time.
7698
7699   Related
7700       · mongoc_client_t
7701
7702       · mongoc_gridfs_t
7703
7704       · mongoc_gridfs_file_list_t
7705
7706       · mongoc_gridfs_file_opt_t
7707
7708   mongoc_gridfs_bucket_t
7709   Synopsis
7710          #include <mongoc/mongoc.h>
7711
7712          typedef struct _mongoc_gridfs_bucket_t mongoc_gridfs_bucket_t;
7713
7714   Description
7715       mongoc_gridfs_bucket_t provides a spec-compliant MongoDB GridFS  imple‐
7716       mentation, superseding mongoc_gridfs_t. See the GridFS MongoDB documen‐
7717       tation.
7718
7719   Thread Safety
7720       mongoc_gridfs_bucket_t is NOT thread-safe and should only  be  used  in
7721       the same thread as the owning mongoc_client_t.
7722
7723   Lifecycle
7724       It  is  an  error  to  free a mongoc_gridfs_bucket_t before freeing all
7725       derived instances of mongoc_stream_t. The owning  mongoc_client_t  must
7726       outlive the mongoc_gridfs_bucket_t.
7727
7728   Example
7729       example-gridfs-bucket.c.INDENT 0.0
7730
7731          #include <stdio.h>
7732          #include <stdlib.h>
7733
7734          #include <mongoc/mongoc.h>
7735
7736          int
7737          main (int argc, char *argv[])
7738          {
7739             const char *uri_string =
7740                "mongodb://localhost:27017/?appname=new-gridfs-example";
7741             mongoc_client_t *client;
7742             mongoc_database_t *db;
7743             mongoc_stream_t *file_stream;
7744             mongoc_gridfs_bucket_t *bucket;
7745             mongoc_cursor_t *cursor;
7746             bson_t filter;
7747             bool res;
7748             bson_value_t file_id;
7749             bson_error_t error;
7750             const bson_t *doc;
7751             char *str;
7752             mongoc_init ();
7753
7754             if (argc != 3) {
7755                fprintf (stderr, "usage: %s SOURCE_FILE_PATH FILE_COPY_PATH\n", argv[0]);
7756                return EXIT_FAILURE;
7757             }
7758
7759             /* 1. Make a bucket. */
7760             client = mongoc_client_new (uri_string);
7761             db = mongoc_client_get_database (client, "test");
7762             bucket = mongoc_gridfs_bucket_new (db, NULL, NULL, &error);
7763             if (!bucket) {
7764                printf ("Error creating gridfs bucket: %s\n", error.message);
7765                return EXIT_FAILURE;
7766             }
7767
7768             /* 2. Insert a file.  */
7769             file_stream = mongoc_stream_file_new_for_path (argv[1], O_RDONLY, 0);
7770             res = mongoc_gridfs_bucket_upload_from_stream (
7771                bucket, "my-file", file_stream, NULL, &file_id, &error);
7772             if (!res) {
7773                printf ("Error uploading file: %s\n", error.message);
7774                return EXIT_FAILURE;
7775             }
7776
7777             mongoc_stream_close (file_stream);
7778             mongoc_stream_destroy (file_stream);
7779
7780             /* 3. Download the file in GridFS to a local file. */
7781             file_stream = mongoc_stream_file_new_for_path (argv[2], O_CREAT | O_RDWR, 0);
7782             if (!file_stream) {
7783                perror ("Error opening file stream");
7784                return EXIT_FAILURE;
7785             }
7786
7787             res = mongoc_gridfs_bucket_download_to_stream (
7788                bucket, &file_id, file_stream, &error);
7789             if (!res) {
7790                printf ("Error downloading file to stream: %s\n", error.message);
7791                return EXIT_FAILURE;
7792             }
7793             mongoc_stream_close (file_stream);
7794             mongoc_stream_destroy (file_stream);
7795
7796             /* 4. List what files are available in GridFS. */
7797             bson_init (&filter);
7798             cursor = mongoc_gridfs_bucket_find (bucket, &filter, NULL);
7799
7800             while (mongoc_cursor_next (cursor, &doc)) {
7801                str = bson_as_canonical_extended_json (doc, NULL);
7802                printf ("%s\n", str);
7803                bson_free (str);
7804             }
7805
7806             /* 5. Delete the file that we added. */
7807             res = mongoc_gridfs_bucket_delete_by_id (bucket, &file_id, &error);
7808             if (!res) {
7809                printf ("Error deleting the file: %s\n", error.message);
7810                return EXIT_FAILURE;
7811             }
7812
7813             /* 6. Cleanup. */
7814             mongoc_stream_close (file_stream);
7815             mongoc_stream_destroy (file_stream);
7816             mongoc_cursor_destroy (cursor);
7817             bson_destroy (&filter);
7818             mongoc_gridfs_bucket_destroy (bucket);
7819             mongoc_database_destroy (db);
7820             mongoc_client_destroy (client);
7821             mongoc_cleanup ();
7822
7823             return EXIT_SUCCESS;
7824          }
7825
7826   See also
7827       · The MongoDB GridFS specification.
7828
7829       · The non spec-compliant mongoc_gridfs_t.
7830
7831   mongoc_gridfs_t
7832       WARNING:
7833          This  GridFS  implementation  does not conform to the MongoDB GridFS
7834          specification.  For  a  spec  compliant  implementation,  use   mon‐
7835          goc_gridfs_bucket_t.
7836
7837   Synopsis
7838          #include <mongoc/mongoc.h>
7839
7840          typedef struct _mongoc_gridfs_t mongoc_gridfs_t;
7841
7842   Description
7843       mongoc_gridfs_t provides a MongoDB gridfs implementation. The system as
7844       a whole is made up of gridfs objects, which  contain  gridfs_files  and
7845       gridfs_file_lists.  Essentially, a basic file system API.
7846
7847       There are extensive caveats about the kind of use cases gridfs is prac‐
7848       tical for. In particular, any writing after initial  file  creation  is
7849       likely  to  both  break  any concurrent readers and be quite expensive.
7850       That said, this implementation  does  allow  for  arbitrary  writes  to
7851       existing gridfs object, just use them with caution.
7852
7853       mongoc_gridfs also integrates tightly with the mongoc_stream_t abstrac‐
7854       tion, which provides some convenient wrapping  for  file  creation  and
7855       reading/writing.   It can be used without, but its worth looking to see
7856       if your problem can fit that model.
7857
7858       WARNING:
7859          mongoc_gridfs_t does not support read preferences. In a replica set,
7860          GridFS queries are always routed to the primary.
7861
7862   Thread Safety
7863       mongoc_gridfs_t  is NOT thread-safe and should only be used in the same
7864       thread as the owning mongoc_client_t.
7865
7866   Lifecycle
7867       It is an error to free a mongoc_gridfs_t  before  freeing  all  related
7868       instances of mongoc_gridfs_file_t and mongoc_gridfs_file_list_t.
7869
7870   Example
7871       example-gridfs.c.INDENT 0.0
7872
7873          #include <assert.h>
7874          #include <mongoc/mongoc.h>
7875          #include <stdio.h>
7876          #include <stdlib.h>
7877          #include <fcntl.h>
7878
7879          int
7880          main (int argc, char *argv[])
7881          {
7882             mongoc_gridfs_t *gridfs;
7883             mongoc_gridfs_file_t *file;
7884             mongoc_gridfs_file_list_t *list;
7885             mongoc_gridfs_file_opt_t opt = {0};
7886             mongoc_client_t *client;
7887             const char *uri_string = "mongodb://127.0.0.1:27017/?appname=gridfs-example";
7888             mongoc_uri_t *uri;
7889             mongoc_stream_t *stream;
7890             bson_t filter;
7891             bson_t opts;
7892             bson_t child;
7893             bson_error_t error;
7894             ssize_t r;
7895             char buf[4096];
7896             mongoc_iovec_t iov;
7897             const char *filename;
7898             const char *command;
7899             bson_value_t id;
7900
7901             if (argc < 2) {
7902                fprintf (stderr, "usage - %s command ...\n", argv[0]);
7903                return EXIT_FAILURE;
7904             }
7905
7906             mongoc_init ();
7907
7908             iov.iov_base = (void *) buf;
7909             iov.iov_len = sizeof buf;
7910
7911             /* connect to localhost client */
7912             uri = mongoc_uri_new_with_error (uri_string, &error);
7913             if (!uri) {
7914                fprintf (stderr,
7915                         "failed to parse URI: %s\n"
7916                         "error message:       %s\n",
7917                         uri_string,
7918                         error.message);
7919                return EXIT_FAILURE;
7920             }
7921
7922             client = mongoc_client_new_from_uri (uri);
7923             assert (client);
7924             mongoc_client_set_error_api (client, 2);
7925
7926             /* grab a gridfs handle in test prefixed by fs */
7927             gridfs = mongoc_client_get_gridfs (client, "test", "fs", &error);
7928             assert (gridfs);
7929
7930             command = argv[1];
7931             filename = argv[2];
7932
7933             if (strcmp (command, "read") == 0) {
7934                if (argc != 3) {
7935                   fprintf (stderr, "usage - %s read filename\n", argv[0]);
7936                   return EXIT_FAILURE;
7937                }
7938                file = mongoc_gridfs_find_one_by_filename (gridfs, filename, &error);
7939                assert (file);
7940
7941                stream = mongoc_stream_gridfs_new (file);
7942                assert (stream);
7943
7944                for (;;) {
7945                   r = mongoc_stream_readv (stream, &iov, 1, -1, 0);
7946
7947                   assert (r >= 0);
7948
7949                   if (r == 0) {
7950                      break;
7951                   }
7952
7953                   if (fwrite (iov.iov_base, 1, r, stdout) != r) {
7954                      MONGOC_ERROR ("Failed to write to stdout. Exiting.\n");
7955                      exit (1);
7956                   }
7957                }
7958
7959                mongoc_stream_destroy (stream);
7960                mongoc_gridfs_file_destroy (file);
7961             } else if (strcmp (command, "list") == 0) {
7962                bson_init (&filter);
7963
7964                bson_init (&opts);
7965                bson_append_document_begin (&opts, "sort", -1, &child);
7966                BSON_APPEND_INT32 (&child, "filename", 1);
7967                bson_append_document_end (&opts, &child);
7968
7969                list = mongoc_gridfs_find_with_opts (gridfs, &filter, &opts);
7970
7971                bson_destroy (&filter);
7972                bson_destroy (&opts);
7973
7974                while ((file = mongoc_gridfs_file_list_next (list))) {
7975                   const char *name = mongoc_gridfs_file_get_filename (file);
7976                   printf ("%s\n", name ? name : "?");
7977
7978                   mongoc_gridfs_file_destroy (file);
7979                }
7980
7981                mongoc_gridfs_file_list_destroy (list);
7982             } else if (strcmp (command, "write") == 0) {
7983                if (argc != 4) {
7984                   fprintf (stderr, "usage - %s write filename input_file\n", argv[0]);
7985                   return EXIT_FAILURE;
7986                }
7987
7988                stream = mongoc_stream_file_new_for_path (argv[3], O_RDONLY, 0);
7989                assert (stream);
7990
7991                opt.filename = filename;
7992
7993                /* the driver generates a file_id for you */
7994                file = mongoc_gridfs_create_file_from_stream (gridfs, stream, &opt);
7995                assert (file);
7996
7997                id.value_type = BSON_TYPE_INT32;
7998                id.value.v_int32 = 1;
7999
8000                /* optional: the following method specifies a file_id of any
8001                   BSON type */
8002                if (!mongoc_gridfs_file_set_id (file, &id, &error)) {
8003                   fprintf (stderr, "%s\n", error.message);
8004                   return EXIT_FAILURE;
8005                }
8006
8007                if (!mongoc_gridfs_file_save (file)) {
8008                   mongoc_gridfs_file_error (file, &error);
8009                   fprintf (stderr, "Could not save: %s\n", error.message);
8010                   return EXIT_FAILURE;
8011                }
8012
8013                mongoc_gridfs_file_destroy (file);
8014             } else {
8015                fprintf (stderr, "Unknown command");
8016                return EXIT_FAILURE;
8017             }
8018
8019             mongoc_gridfs_destroy (gridfs);
8020             mongoc_uri_destroy (uri);
8021             mongoc_client_destroy (client);
8022
8023             mongoc_cleanup ();
8024
8025             return EXIT_SUCCESS;
8026          }
8027
8028
8029   See also
8030       · The MongoDB GridFS specification.
8031
8032       · The spec-compliant mongoc_gridfs_bucket_t.
8033
8034   mongoc_host_list_t
8035   Synopsis
8036          typedef struct {
8037             mongoc_host_list_t *next;
8038             char host[BSON_HOST_NAME_MAX + 1];
8039             char host_and_port[BSON_HOST_NAME_MAX + 7];
8040             uint16_t port;
8041             int family;
8042             void *padding[4];
8043          } mongoc_host_list_t;
8044
8045   Description
8046       The  host  and  port of a MongoDB server. Can be part of a linked list:
8047       for example the return  value  of  mongoc_uri_get_hosts  when  multiple
8048       hosts are provided in the MongoDB URI.
8049
8050   See Also
8051       mongoc_uri_get_hosts and mongoc_cursor_get_host.
8052
8053   mongoc_index_opt_geo_t
8054   Synopsis
8055          #include <mongoc/mongoc.h>
8056
8057          typedef struct {
8058             uint8_t twod_sphere_version;
8059             uint8_t twod_bits_precision;
8060             double twod_location_min;
8061             double twod_location_max;
8062             double haystack_bucket_size;
8063             uint8_t *padding[32];
8064          } mongoc_index_opt_geo_t;
8065
8066   Description
8067       This  structure  contains the options that may be used for tuning a GEO
8068       index.
8069
8070   See Also
8071       mongoc_index_opt_t
8072
8073       mongoc_index_opt_wt_t
8074
8075   mongoc_index_opt_t
8076   Synopsis
8077          #include <mongoc/mongoc.h>
8078
8079          typedef struct {
8080             bool is_initialized;
8081             bool background;
8082             bool unique;
8083             const char *name;
8084             bool drop_dups;
8085             bool sparse;
8086             int32_t expire_after_seconds;
8087             int32_t v;
8088             const bson_t *weights;
8089             const char *default_language;
8090             const char *language_override;
8091             mongoc_index_opt_geo_t *geo_options;
8092             mongoc_index_opt_storage_t *storage_options;
8093             const bson_t *partial_filter_expression;
8094             const bson_t *collation;
8095             void *padding[4];
8096          } mongoc_index_opt_t;
8097
8098   Deprecated
8099       This structure is deprecated and should not be used in  new  code.  See
8100       create-indexes.
8101
8102   Description
8103       This  structure contains the options that may be used for tuning a spe‐
8104       cific index.
8105
8106       See the createIndexes documentations in the MongoDB manual for descrip‐
8107       tions of individual options.
8108
8109       NOTE:
8110          dropDups  is deprecated as of MongoDB version 3.0.0.  This option is
8111          silently ignored by the server and unique index  builds  using  this
8112          option will fail if a duplicate value is detected.
8113
8114   Example
8115          {
8116             bson_t keys;
8117             bson_error_t error;
8118             mongoc_index_opt_t opt;
8119             mongoc_index_opt_geo_t geo_opt;
8120
8121             mongoc_index_opt_init (&opt);
8122             mongoc_index_opt_geo_init (&geo_opt);
8123
8124             bson_init (&keys);
8125             BSON_APPEND_UTF8 (&keys, "location", "2d");
8126
8127             geo_opt.twod_location_min = -123;
8128             geo_opt.twod_location_max = +123;
8129             geo_opt.twod_bits_precision = 30;
8130             opt.geo_options = &geo_opt;
8131
8132             collection = mongoc_client_get_collection (client, "test", "geo_test");
8133             if (mongoc_collection_create_index (collection, &keys, &opt, &error)) {
8134                /* Successfully created the geo index */
8135             }
8136             bson_destroy (&keys);
8137             mongoc_collection_destroy (&collection);
8138          }
8139
8140   See Also
8141       mongoc_index_opt_geo_t
8142
8143       mongoc_index_opt_wt_t
8144
8145   mongoc_index_opt_wt_t
8146   Synopsis
8147          #include <mongoc/mongoc.h>
8148
8149          typedef struct {
8150             mongoc_index_opt_storage_t base;
8151             const char *config_str;
8152             void *padding[8];
8153          } mongoc_index_opt_wt_t;
8154
8155   Description
8156       This  structure  contains  the  options  that  may be used for tuning a
8157       WiredTiger specific index.
8158
8159   See Also
8160       mongoc_index_opt_t
8161
8162       mongoc_index_opt_geo_t
8163
8164   mongoc_insert_flags_t
8165       Flags for insert operations
8166
8167   Synopsis
8168          typedef enum {
8169             MONGOC_INSERT_NONE = 0,
8170             MONGOC_INSERT_CONTINUE_ON_ERROR = 1 << 0,
8171          } mongoc_insert_flags_t;
8172
8173          #define MONGOC_INSERT_NO_VALIDATE (1U << 31)
8174
8175   Description
8176       These flags correspond to the MongoDB wire protocol. They may  be  bit‐
8177       wise  or'd  together. They may modify how an insert happens on the Mon‐
8178       goDB server.
8179
8180   Flag Values
8181              ┌──────────────────────────┬────────────────────────────┐
8182              │MONGOC_INSERT_NONE        │ Specify no insert flags.   │
8183              ├──────────────────────────┼────────────────────────────┤
8184              │MONGOC_INSERT_CON‐        │ Continue  inserting  docu‐ │
8185              │TINUE_ON_ERROR            │ ments from  the  insertion │
8186              │                          │ set  even  if  one  insert │
8187              │                          │ fails.                     │
8188              ├──────────────────────────┼────────────────────────────┤
8189              │MONGOC_INSERT_NO_VALIDATE │ Do not validate  insertion │
8190              │                          │ documents  before perform‐ │
8191              │                          │ ing an insert.  Validation │
8192              │                          │ can  be expensive, so this │
8193              │                          │ can save some time if  you │
8194              │                          │ know  your  documents  are │
8195              │                          │ already valid.             │
8196              └──────────────────────────┴────────────────────────────┘
8197
8198   mongoc_iovec_t
8199   Synopsis
8200   Synopsis
8201          #include <mongoc/mongoc.h>
8202
8203          #ifdef _WIN32
8204          typedef struct {
8205             u_long iov_len;
8206             char *iov_base;
8207          } mongoc_iovec_t;
8208          #else
8209          typedef struct iovec mongoc_iovec_t;
8210          #endif
8211
8212       The mongoc_iovec_t structure is a portability abstraction for consumers
8213       of  the  mongoc_stream_t  interfaces.  It allows for scatter/gather I/O
8214       through the socket subsystem.
8215
8216       WARNING:
8217          When writing portable code, beware of the ordering  of  iov_len  and
8218          iov_base  as they are different on various platforms. Therefore, you
8219          should not use C initializers for initialization.
8220
8221   mongoc_matcher_t
8222       Client-side document matching abstraction
8223
8224   Synopsis
8225          typedef struct _mongoc_matcher_t mongoc_matcher_t;
8226
8227       mongoc_matcher_t provides a reduced-interface for client-side  matching
8228       of BSON documents.
8229
8230       It can perform the basics such as $in, $nin, $eq, $neq, $gt, $gte, $lt,
8231       and $lte.
8232
8233       WARNING:
8234          mongoc_matcher_t does not currently support  the  full  spectrum  of
8235          query operations that the MongoDB server supports.
8236
8237   Deprecated
8238       WARNING:
8239          mongoc_matcher_t is deprecated and will be removed in version 2.0.
8240
8241   Example
8242       Filter  a sequence of BSON documents from STDIN based on a query.INDENT
8243       0.0
8244
8245          #include <bson/bson.h>
8246          #include <mongoc/mongoc.h>
8247          #include <stdio.h>
8248
8249          int
8250          main (int argc, char *argv[])
8251          {
8252             mongoc_matcher_t *matcher;
8253             bson_reader_t *reader;
8254             const bson_t *bson;
8255             bson_t *spec;
8256             char *str;
8257             int fd;
8258
8259             mongoc_init ();
8260
8261          #ifdef _WIN32
8262             fd = fileno (stdin);
8263          #else
8264             fd = STDIN_FILENO;
8265          #endif
8266
8267             reader = bson_reader_new_from_fd (fd, false);
8268
8269             spec = BCON_NEW ("hello", "world");
8270             matcher = mongoc_matcher_new (spec, NULL);
8271
8272             while ((bson = bson_reader_read (reader, NULL))) {
8273                if (mongoc_matcher_match (matcher, bson)) {
8274                   str = bson_as_canonical_extended_json (bson, NULL);
8275                   printf ("%s\n", str);
8276                   bson_free (str);
8277                }
8278             }
8279
8280             bson_reader_destroy (reader);
8281             bson_destroy (spec);
8282
8283             mongoc_cleanup ();
8284
8285             return 0;
8286          }
8287
8288   mongoc_query_flags_t
8289       Flags for query operations
8290
8291   Synopsis
8292          typedef enum {
8293             MONGOC_QUERY_NONE = 0,
8294             MONGOC_QUERY_TAILABLE_CURSOR = 1 << 1,
8295             MONGOC_QUERY_SLAVE_OK = 1 << 2,
8296             MONGOC_QUERY_OPLOG_REPLAY = 1 << 3,
8297             MONGOC_QUERY_NO_CURSOR_TIMEOUT = 1 << 4,
8298             MONGOC_QUERY_AWAIT_DATA = 1 << 5,
8299             MONGOC_QUERY_EXHAUST = 1 << 6,
8300             MONGOC_QUERY_PARTIAL = 1 << 7,
8301          } mongoc_query_flags_t;
8302
8303   Description
8304       These flags correspond to the MongoDB wire protocol. They may  be  bit‐
8305       wise  or'd  together.  They  may modify how a query is performed in the
8306       MongoDB server.
8307
8308   Flag Values
8309              ┌───────────────────────────┬────────────────────────────┐
8310              │MONGOC_QUERY_NONE          │ Specify no query flags.    │
8311              ├───────────────────────────┼────────────────────────────┤
8312              │MONGOC_QUERY_TAILABLE_CUR‐ │ Cursor  will not be closed │
8313              │SOR                        │ when  the  last  data   is │
8314              │                           │ retrieved.  You can resume │
8315              │                           │ this cursor later.         │
8316              ├───────────────────────────┼────────────────────────────┤
8317              │MONGOC_QUERY_SLAVE_OK      │ Allow query of replica set │
8318              │                           │ secondaries.               │
8319              ├───────────────────────────┼────────────────────────────┤
8320              │MONGOC_QUERY_OPLOG_REPLAY  │ Used  internally  by  Mon‐ │
8321              │                           │ goDB.                      │
8322              ├───────────────────────────┼────────────────────────────┤
8323              │MONGOC_QUERY_NO_CUR‐       │ The  server normally times │
8324              │SOR_TIMEOUT                │ out an idle  cursor  after │
8325              │                           │ an  inactivity  period (10 │
8326              │                           │ minutes).  This   prevents │
8327              │                           │ that.                      │
8328              └───────────────────────────┴────────────────────────────┘
8329
8330
8331
8332
8333
8334
8335              │MONGOC_QUERY_AWAIT_DATA    │ Use        with       MON‐ │
8336              │                           │ GOC_QUERY_TAILABLE_CURSOR. │
8337              │                           │ Block  rather than return‐ │
8338              │                           │ ing  no  data.   After   a │
8339              │                           │ period, time out.          │
8340              ├───────────────────────────┼────────────────────────────┤
8341              │MONGOC_QUERY_EXHAUST       │ Stream  the data down full │
8342              │                           │ blast in multiple  "reply" │
8343              │                           │ packets.  Faster  when you │
8344              │                           │ are pulling down a lot  of │
8345              │                           │ data and you know you want │
8346              │                           │ to retrieve it all.        │
8347              ├───────────────────────────┼────────────────────────────┤
8348              │MONGOC_QUERY_PARTIAL       │ Get partial  results  from │
8349              │                           │ mongos  if some shards are │
8350              │                           │ down (instead of  throwing │
8351              │                           │ an error).                 │
8352              └───────────────────────────┴────────────────────────────┘
8353
8354   mongoc_rand
8355       MongoDB Random Number Generator
8356
8357   Synopsis
8358          void
8359          mongoc_rand_add (const void *buf, int num, double entropy);
8360
8361          void
8362          mongoc_rand_seed (const void *buf, int num);
8363
8364          int
8365          mongoc_rand_status (void);
8366
8367   Description
8368       The  mongoc_rand  family  of  functions provide access to the low level
8369       randomness primitives used by the MongoDB  C  Driver.   In  particular,
8370       they  control  the  creation  of cryptographically strong pseudo-random
8371       bytes required by some security mechanisms.
8372
8373       While we can usually pull enough entropy from the environment, you  may
8374       be  required  to  seed the PRNG manually depending on your OS, hardware
8375       and other entropy consumers running on the same system.
8376
8377   Entropy
8378       mongoc_rand_add and mongoc_rand_seed allow the user to directly provide
8379       entropy.   They  differ  insofar as mongoc_rand_seed requires that each
8380       bit provided is fully random.  mongoc_rand_add allows the user to spec‐
8381       ify the degree of randomness in the provided bytes as well.
8382
8383   Status
8384       The  mongoc_rand_status function allows the user to check the status of
8385       the mongoc PRNG.  This can be used to guarantee sufficient  entropy  at
8386       program startup, rather than waiting for runtime errors to occur.
8387
8388   mongoc_read_concern_t
8389       Read Concern abstraction
8390
8391   Synopsis
8392       New in MongoDB 3.2.
8393
8394       The mongoc_read_concern_t allows clients to choose a level of isolation
8395       for their reads. The default, MONGOC_READ_CONCERN_LEVEL_LOCAL, is right
8396       for the great majority of applications.
8397
8398       You can specify a read concern on connection objects, database objects,
8399       or collection objects.
8400
8401       See readConcern on the MongoDB website for more information.
8402
8403       Read Concern is only sent to MongoDB when it has explicitly been set by
8404       mongoc_read_concern_set_level to anything other than NULL.
8405
8406   Read Concern Levels
8407          ┌────────────────────┬─────────────────────┬─────────────────────┐
8408          │Macro               │ Description         │ First  MongoDB ver‐ │
8409          │                    │                     │ sion                │
8410          └────────────────────┴─────────────────────┴─────────────────────┘
8411
8412
8413          │MONGOC_READ_CON‐    │ Level  "local", the │ 3.2                 │
8414          │CERN_LEVEL_LOCAL    │ default.            │                     │
8415          ├────────────────────┼─────────────────────┼─────────────────────┤
8416          │MONGOC_READ_CON‐    │ Level "majority".   │ 3.2                 │
8417          │CERN_LEVEL_MAJORITY │                     │                     │
8418          ├────────────────────┼─────────────────────┼─────────────────────┤
8419          │MONGOC_READ_CON‐    │ Level    "lineariz‐ │ 3.4                 │
8420          │CERN_LEVEL_LIN‐     │ able".              │                     │
8421          │EARIZABLE           │                     │                     │
8422          ├────────────────────┼─────────────────────┼─────────────────────┤
8423          │MONGOC_READ_CON‐    │ Level "available".  │ 3.6                 │
8424          │CERN_LEVEL_AVAIL‐   │                     │                     │
8425          │ABLE                │                     │                     │
8426          ├────────────────────┼─────────────────────┼─────────────────────┤
8427          │MONGOC_READ_CON‐    │ Level "snapshot".   │ 4.0                 │
8428          │CERN_LEVEL_SNAPSHOT │                     │                     │
8429          └────────────────────┴─────────────────────┴─────────────────────┘
8430
8431       For  the  sake  of  compatibility with future versions of MongoDB, mon‐
8432       goc_read_concern_set_level allows any string, not  just  this  list  of
8433       known read concern levels.
8434
8435       See  Read  Concern  Levels  in  the MongoDB manual for more information
8436       about the individual read concern levels.
8437
8438   mongoc_read_mode_t
8439       Read Preference Modes
8440
8441   Synopsis
8442          typedef enum {
8443             MONGOC_READ_PRIMARY = (1 << 0),
8444             MONGOC_READ_SECONDARY = (1 << 1),
8445             MONGOC_READ_PRIMARY_PREFERRED = (1 << 2) | MONGOC_READ_PRIMARY,
8446             MONGOC_READ_SECONDARY_PREFERRED = (1 << 2) | MONGOC_READ_SECONDARY,
8447             MONGOC_READ_NEAREST = (1 << 3) | MONGOC_READ_SECONDARY,
8448          } mongoc_read_mode_t;
8449
8450   Description
8451       This enum describes how reads should be dispatched. The default is MON‐
8452       GOC_READ_PRIMARY.
8453
8454       Please see the MongoDB website for a description of Read Preferences.
8455
8456   mongoc_read_prefs_t
8457       A read preference abstraction
8458
8459   Synopsis
8460       mongoc_read_prefs_t  provides an abstraction on top of the MongoDB con‐
8461       nection read preferences. It allows for hinting  to  the  driver  which
8462       nodes in a replica set should be accessed first.
8463
8464       You  can specify a read preference mode on connection objects, database
8465       objects, collection objects, or per-operation.  Generally, it makes the
8466       most  sense to stick with the global default, MONGOC_READ_PRIMARY.  All
8467       of the other modes come with caveats that won't  be  covered  in  great
8468       detail here.
8469
8470   Read Modes
8471              ┌───────────────────────────┬────────────────────────────┐
8472              │MONGOC_READ_PRIMARY        │ Default  mode.  All opera‐ │
8473              │                           │ tions read from  the  cur‐ │
8474              │                           │ rent replica set primary.  │
8475              ├───────────────────────────┼────────────────────────────┤
8476              │MONGOC_READ_SECONDARY      │ All  operations  read from │
8477              │                           │ among  the  nearest   sec‐ │
8478              │                           │ ondary   members   of  the │
8479              │                           │ replica set.               │
8480              ├───────────────────────────┼────────────────────────────┤
8481              │MONGOC_READ_PRIMARY_PRE‐   │ In most situations, opera‐ │
8482              │FERRED                     │ tions read from  the  pri‐ │
8483              │                           │ mary but if it is unavail‐ │
8484              │                           │ able, operations read from │
8485              │                           │ secondary members.         │
8486              └───────────────────────────┴────────────────────────────┘
8487
8488
8489
8490
8491              │MONGOC_READ_SECONDARY_PRE‐ │ In most situations, opera‐ │
8492              │FERRED                     │ tions  read from among the │
8493              │                           │ nearest secondary members, │
8494              │                           │ but  if no secondaries are │
8495              │                           │ available, operations read │
8496              │                           │ from the primary.          │
8497              ├───────────────────────────┼────────────────────────────┤
8498              │MONGOC_READ_NEAREST        │ Operations read from among │
8499              │                           │ the nearest members of the │
8500              │                           │ replica  set, irrespective │
8501              │                           │ of the member's type.      │
8502              └───────────────────────────┴────────────────────────────┘
8503
8504   Tag Sets
8505       Tag sets allow you to specify custom read preferences  and  write  con‐
8506       cerns  so  that your application can target operations to specific mem‐
8507       bers.
8508
8509       Custom read preferences and write concerns evaluate tags sets  in  dif‐
8510       ferent  ways: read preferences consider the value of a tag when select‐
8511       ing a member to read from. while write concerns ignore the value  of  a
8512       tag  to  when  selecting a member except to consider whether or not the
8513       value is unique.
8514
8515       You can specify tag sets with the following read preference modes:
8516
8517       · primaryPreferred
8518
8519       · secondary
8520
8521       · secondaryPreferred
8522
8523       · nearest
8524
8525       Tags are not compatible with MONGOC_READ_PRIMARY and, in general,  only
8526       apply  when selecting a secondary member of a set for a read operation.
8527       However, the nearest read mode, when  combined  with  a  tag  set  will
8528       select the nearest member that matches the specified tag set, which may
8529       be a primary or secondary.
8530
8531       Tag sets are represented as a comma-separated list  of  colon-separated
8532       key-value   pairs   when   provided   as   a  connection  string,  e.g.
8533       dc:ny,rack:1.
8534
8535       To specify a list of tag sets, using multiple readPreferenceTags, e.g.
8536
8537          readPreferenceTags=dc:ny,rack:1;readPreferenceTags=dc:ny;readPreferenceTags=
8538
8539       Note the empty value for the last one, which means match any  secondary
8540       as a last resort.
8541
8542       Order matters when using multiple readPreferenceTags.
8543
8544       Tag Sets can also be configured using mongoc_read_prefs_set_tags.
8545
8546       All interfaces use the same member selection logic to choose the member
8547       to which to direct read operations, basing the choice on  read  prefer‐
8548       ence mode and tag sets.
8549
8550   Max Staleness
8551       When  connected to replica set running MongoDB 3.4 or later, the driver
8552       estimates the staleness of each secondary based on lastWriteDate values
8553       provided in server isMaster responses.
8554
8555       Max  Staleness  is  the  maximum replication lag in seconds (wall clock
8556       time) that a secondary can suffer and still be eligible for reads.  The
8557       default  is  MONGOC_NO_MAX_STALENESS,  which disables staleness checks.
8558       Otherwise, it  must  be  a  positive  integer  at  least  MONGOC_SMALL‐
8559       EST_MAX_STALENESS_SECONDS (90 seconds).
8560
8561       Max  Staleness is also supported by sharded clusters of replica sets if
8562       all servers run MongoDB 3.4 or later.
8563
8564   mongoc_remove_flags_t
8565       Flags for deletion operations
8566
8567   Synopsis
8568          typedef enum {
8569             MONGOC_REMOVE_NONE = 0,
8570             MONGOC_REMOVE_SINGLE_REMOVE = 1 << 0,
8571          } mongoc_remove_flags_t;
8572
8573   Description
8574       These flags correspond to the MongoDB wire protocol. They may  be  bit‐
8575       wise  or'd  together.  They may change the number of documents that are
8576       removed during a remove command.
8577
8578   Flag Values
8579                  ┌───────────────────┬────────────────────────────┐
8580                  │MONGOC_REMOVE_NONE │ Specify no removal  flags. │
8581                  │                   │ All   matching   documents │
8582                  │                   │ will be removed.           │
8583                  ├───────────────────┼────────────────────────────┤
8584                  │MONGOC_REMOVE_SIN‐ │ Only   remove   the  first │
8585                  │GLE_REMOVE         │ matching document from the │
8586                  │                   │ selector.                  │
8587                  └───────────────────┴────────────────────────────┘
8588
8589   mongoc_reply_flags_t
8590       Flags from server replies
8591
8592   Synopsis
8593          typedef enum {
8594             MONGOC_REPLY_NONE = 0,
8595             MONGOC_REPLY_CURSOR_NOT_FOUND = 1 << 0,
8596             MONGOC_REPLY_QUERY_FAILURE = 1 << 1,
8597             MONGOC_REPLY_SHARD_CONFIG_STALE = 1 << 2,
8598             MONGOC_REPLY_AWAIT_CAPABLE = 1 << 3,
8599          } mongoc_reply_flags_t;
8600
8601   Description
8602       These  flags  correspond to the wire protocol. They may be bitwise or'd
8603       together.
8604
8605   Flag Values
8606              ┌───────────────────────────┬────────────────────────────┐
8607              │MONGOC_REPLY_NONE          │ No flags set.              │
8608              ├───────────────────────────┼────────────────────────────┤
8609              │MONGOC_REPLY_CUR‐          │ No   matching  cursor  was │
8610              │SOR_NOT_FOUND              │ found on the server.       │
8611              ├───────────────────────────┼────────────────────────────┤
8612              │MONGOC_REPLY_QUERY_FAILURE │ The query  failed  or  was │
8613              │                           │ invalid.   Error  document │
8614              │                           │ has been provided.         │
8615              ├───────────────────────────┼────────────────────────────┤
8616              │MONGOC_REPLY_SHARD_CON‐    │ Shard config is stale.     │
8617              │FIG_STALE                  │                            │
8618              ├───────────────────────────┼────────────────────────────┤
8619              │MONGOC_REPLY_AWAIT_CAPABLE │ If  the returned cursor is │
8620              │                           │ capable      of       MON‐ │
8621              │                           │ GOC_QUERY_AWAIT_DATA.      │
8622              └───────────────────────────┴────────────────────────────┘
8623
8624   mongoc_server_description_t
8625       Server description
8626
8627   Synopsis
8628          #include <mongoc/mongoc.h>
8629          typedef struct _mongoc_server_description_t mongoc_server_description_t
8630
8631       mongoc_server_description_t  holds information about a mongod or mongos
8632       the driver is connected to.
8633
8634       See also mongoc_client_get_server_descriptions().
8635
8636   Lifecycle
8637       Clean up with mongoc_server_description_destroy().
8638
8639   mongoc_session_opt_t
8640          #include <mongoc/mongoc.h>
8641
8642          typedef struct _mongoc_session_opt_t mongoc_session_opt_t;
8643
8644   Synopsis
8645       Start a session with mongoc_client_start_session, use the session for a
8646       sequence  of  operations  and multi-document transactions, then free it
8647       with  mongoc_client_session_destroy().  Any  mongoc_cursor_t  or   mon‐
8648       goc_change_stream_t  using  a session must be destroyed before the ses‐
8649       sion, and a session must be destroyed  before  the  mongoc_client_t  it
8650       came from.
8651
8652       By default, sessions are causally consistent. To disable causal consis‐
8653       tency, before starting a session  create  a  mongoc_session_opt_t  with
8654       mongoc_session_opts_new()  and call mongoc_session_opts_set_causal_con‐
8655       sistency(), then free the struct with mongoc_session_opts_destroy.
8656
8657       Unacknowledged writes are prohibited with sessions.
8658
8659       A mongoc_client_session_t must be used by only one thread  at  a  time.
8660       Due  to  session pooling, mongoc_client_start_session may return a ses‐
8661       sion that has been idle for some time and is about to be  closed  after
8662       its  idle timeout. Use the session within one minute of acquiring it to
8663       refresh the session and avoid a timeout.
8664
8665       See the example code for mongoc_session_opts_set_causal_consistency.
8666
8667   mongoc_socket_t
8668       Portable socket abstraction
8669
8670   Synopsis
8671          #include <mongoc/mongoc.h>
8672
8673          typedef struct _mongoc_socket_t mongoc_socket_t
8674
8675   Synopsis
8676       This structure provides a socket abstraction  that  is  friendlier  for
8677       portability  than  BSD sockets directly. Inconsistencies between Linux,
8678       various BSDs, Solaris, and Windows are handled here.
8679
8680   mongoc_ssl_opt_t
8681   Synopsis
8682          typedef struct {
8683             const char *pem_file;
8684             const char *pem_pwd;
8685             const char *ca_file;
8686             const char *ca_dir;
8687             const char *crl_file;
8688             bool weak_cert_validation;
8689             bool allow_invalid_hostname;
8690             void *padding[7];
8691          } mongoc_ssl_opt_t;
8692
8693   Description
8694       This structure is used to set the SSL options for a mongoc_client_t  or
8695       mongoc_client_pool_t.
8696
8697       Beginning  in  version 1.2.0, once a pool or client has any SSL options
8698       set, all connections use SSL, even if ssl=true is omitted from the Mon‐
8699       goDB URI. Before, SSL options were ignored unless ssl=true was included
8700       in the URI.
8701
8702       As   of   1.4.0,   the   mongoc_client_pool_set_ssl_opts    and    mon‐
8703       goc_client_set_ssl_opts will not only shallow copy the struct, but will
8704       also copy the const char*. It is therefore no  longer  needed  to  make
8705       sure the values remain valid after setting them.
8706
8707   Configuration through URI Options
8708       Most of the configurable options can be using the Connection URI.
8709
8710                 ┌───────────────────────┬──────────────────────────┐
8711mongoc_ssl_opt_t key   URI key                  
8712                 ├───────────────────────┼──────────────────────────┤
8713                 │pem_file               │ sslClientCertificateKey‐ │
8714                 │                       │ File                     │
8715                 ├───────────────────────┼──────────────────────────┤
8716                 │pem_pwd                │ sslClientCertificateKey‐ │
8717                 │                       │ Password                 │
8718                 ├───────────────────────┼──────────────────────────┤
8719                 │ca_file                │ sslCertificateAuthority‐ │
8720                 │                       │ File                     │
8721                 ├───────────────────────┼──────────────────────────┤
8722                 │weak_cert_validation   │ sslAllowInvalidCertifi‐  │
8723                 │                       │ cates                    │
8724                 ├───────────────────────┼──────────────────────────┤
8725                 │allow_invalid_hostname │ sslAllowInvalidHostnames │
8726                 └───────────────────────┴──────────────────────────┘
8727
8728   Client Authentication
8729       When  MongoDB  is  started with SSL enabled, it will by default require
8730       the client to provide a client  certificate  issued  by  a  certificate
8731       authority  specified  by  --sslCAFile,  or  an authority trusted by the
8732       native certificate store in use on the server.
8733
8734       To provide the client certificate, the user must configure the pem_file
8735       to point at a PEM armored certificate.
8736
8737          mongoc_ssl_opt_t ssl_opts = {0};
8738
8739          ssl_opts.pem_file = "/path/to/client-certificate.pem"
8740
8741          /* Then set the client ssl_opts, when using a single client mongoc_client_t */
8742          mongoc_client_set_ssl_opts (client, &ssl_opts);
8743
8744          /* or, set the pool ssl_opts, when using a the thread safe mongoc_client_pool_t */
8745          mongoc_client_pool_set_ssl_opts (pool, &ssl_opts);
8746
8747   Server Certificate Verification
8748       The  MongoDB  C  Driver  will  automatically verify the validity of the
8749       server certificate, such as issued by configured Certificate Authority,
8750       hostname validation, and expiration.
8751
8752       To overwrite this behaviour, it is possible to disable hostname valida‐
8753       tion, and/or allow otherwise invalid certificates.  This  behaviour  is
8754       controlled  using  the  allow_invalid_hostname and weak_cert_validation
8755       fields. By default, both are set to false. It  is  not  recommended  to
8756       change  these  defaults  as  it exposes the client to Man In The Middle
8757       attacks (when allow_invalid_hostname is set) and otherwise invalid cer‐
8758       tificates when weak_cert_validation is set to true.
8759
8760   OpenSSL
8761       The  MongoDB  C  Driver  uses  OpenSSL, if available, on Linux and Unix
8762       platforms (besides macOS). Industry best practices and some regulations
8763       require  the  use  of TLS 1.1 or newer, which requires at least OpenSSL
8764       1.0.1. Check your OpenSSL version like so:
8765
8766          $ openssl version
8767
8768       Ensure your system's OpenSSL is a recent version (at least  1.0.1),  or
8769       install  a  recent  version  in  a non-system path and build against it
8770       with:
8771
8772          cmake -DOPENSSL_ROOT_DIR=/absolute/path/to/openssl
8773
8774       When compiled against OpenSSL, the driver will attempt to load the sys‐
8775       tem  default  certificate  store, as configured by the distribution, if
8776       the ca_file and ca_dir are not set.
8777
8778   LibreSSL / libtls
8779       The MongoDB C Driver supports LibreSSL through the use of OpenSSL  com‐
8780       patibility  checks  when configured to compile against openssl. It also
8781       supports the new  libtls  library  when  configured  to  build  against
8782       libressl.
8783
8784   Native TLS Support on Windows (Secure Channel)
8785       The  MongoDB  C  Driver supports the Windows native TLS library (Secure
8786       Channel, or SChannel), and its native crypto library (Cryptography API:
8787       Next Generation, or CNG).
8788
8789       When  compiled  against the Windows native libraries, the ca_dir option
8790       is not supported, and will issue an error if used.
8791
8792       Encrypted PEM files (e.g., requiring pem_pwd) are also  not  supported,
8793       and will result in error when attempting to load them.
8794
8795       When  ca_file  is  provided, the driver will only allow server certifi‐
8796       cates issued by  the  authority  (or  authorities)  provided.  When  no
8797       ca_file  is provided, the driver will look up the Certificate Authority
8798       using the System Local Machine Root certificate store  to  confirm  the
8799       provided certificate.
8800
8801       When  crl_file  is provided, the driver will import the revocation list
8802       to the System Local Machine Root certificate store.
8803
8804   Native TLS Support on macOS / Darwin (Secure Transport)
8805       The MongoDB C Driver supports the  Darwin  (OS  X,  macOS,  iOS,  etc.)
8806       native  TLS  library  (Secure Transport), and its native crypto library
8807       (Common Crypto, or CC).
8808
8809       When compiled against Secure Transport, the ca_dir option is  not  sup‐
8810       ported, and will issue an error if used.
8811
8812       When  ca_file  is  provided, the driver will only allow server certifi‐
8813       cates issued by  the  authority  (or  authorities)  provided.  When  no
8814       ca_file is provided, the driver will use the Certificate Authorities in
8815       the currently unlocked keychains.
8816
8817   See Also
8818       · mongoc_client_set_ssl_opts
8819
8820       · mongoc_client_pool_set_ssl_opts
8821
8822   mongoc_stream_buffered_t
8823   Synopsis
8824          typedef struct _mongoc_stream_buffered_t mongoc_stream_buffered_t;
8825
8826   Description
8827       mongoc_stream_buffered_t  should  be  considered  a  subclass  of  mon‐
8828       goc_stream_t. It performs buffering on an underlying stream.
8829
8830   See Also
8831       mongoc_stream_buffered_new()
8832
8833       mongoc_stream_destroy()
8834
8835   mongoc_stream_file_t
8836   Synopsis
8837          typedef struct _mongoc_stream_file_t mongoc_stream_file_t
8838
8839       mongoc_stream_file_t  is  a  mongoc_stream_t  subclass for working with
8840       standard UNIX style file-descriptors.
8841
8842   mongoc_stream_socket_t
8843   Synopsis
8844          typedef struct _mongoc_stream_socket_t mongoc_stream_socket_t
8845
8846       mongoc_stream_socket_t  should  be  considered  a  subclass   of   mon‐
8847       goc_stream_t that works upon socket streams.
8848
8849   mongoc_stream_t
8850   Synopsis
8851          typedef struct _mongoc_stream_t mongoc_stream_t
8852
8853       mongoc_stream_t  provides a generic streaming IO abstraction based on a
8854       struct of pointers interface. The idea is to  allow  wrappers,  perhaps
8855       other  language  drivers, to easily shim their IO system on top of mon‐
8856       goc_stream_t.
8857
8858       The API for the stream abstraction is currently private and  non-exten‐
8859       sible.
8860
8861   Stream Types
8862       There  are a number of built in stream types that come with mongoc. The
8863       default configuration is a buffered unix stream.  If  SSL  is  in  use,
8864       that in turn is wrapped in a tls stream.
8865
8866   See Also
8867       mongoc_stream_buffered_t
8868
8869       mongoc_stream_file_t
8870
8871       mongoc_stream_socket_t
8872
8873       mongoc_stream_tls_t
8874
8875   mongoc_stream_tls_t
8876   Synopsis
8877          typedef struct _mongoc_stream_tls_t mongoc_stream_tls_t
8878
8879       mongoc_stream_tls_t  is  a  mongoc_stream_t  subclass  for working with
8880       OpenSSL TLS streams.
8881
8882   mongoc_topology_description_t
8883       Status of MongoDB Servers
8884
8885   Synopsis
8886          typedef struct _mongoc_topology_description_t mongoc_topology_description_t;
8887
8888       mongoc_topology_description_t  is  an  opaque  type  representing   the
8889       driver's knowledge of the MongoDB server or servers it is connected to.
8890       Its API conforms to the SDAM Monitoring Specification.
8891
8892       Applications  receive  a  temporary  reference   to   a   mongoc_topol‐
8893       ogy_description_t  as  a  parameter to an SDAM Monitoring callback. See
8894       Introduction to Application Performance Monitoring.
8895
8896   mongoc_transaction_opt_t
8897          #include <mongoc/mongoc.h>
8898
8899          typedef struct _mongoc_transaction_opt_t mongoc_transaction_opt_t;
8900
8901   Synopsis
8902       Options for starting a multi-document transaction.
8903
8904       When a session is first created  with  mongoc_client_start_session,  it
8905       inherits  from  the  client  the  read concern, write concern, and read
8906       preference with which to start transactions. Each of these  fields  can
8907       be  overridden  independently.  Create  a mongoc_transaction_opt_t with
8908       mongoc_transaction_opts_new, and pass a non-NULL option to any  of  the
8909       mongoc_transaction_opt_t setter functions:
8910
8911       · mongoc_transaction_opts_set_read_concern
8912
8913       · mongoc_transaction_opts_set_write_concern
8914
8915       · mongoc_transaction_opts_set_read_prefs
8916
8917       Pass   the   resulting   transaction   options   to  mongoc_client_ses‐
8918       sion_start_transaction. Each field set in the transaction options over‐
8919       rides the inherited client configuration.
8920
8921   Example
8922       example-transaction.c.INDENT 0.0
8923
8924          /* gcc example-transaction.c -o example-transaction \
8925           *     $(pkg-config --cflags --libs libmongoc-1.0) */
8926
8927          /* ./example-transaction [CONNECTION_STRING] */
8928
8929          #include <stdio.h>
8930          #include <mongoc/mongoc.h>
8931
8932
8933          int
8934          main (int argc, char *argv[])
8935          {
8936             int exit_code = EXIT_FAILURE;
8937
8938             mongoc_client_t *client = NULL;
8939             mongoc_database_t *database = NULL;
8940             mongoc_collection_t *collection = NULL;
8941             mongoc_client_session_t *session = NULL;
8942             mongoc_session_opt_t *session_opts = NULL;
8943             mongoc_transaction_opt_t *default_txn_opts = NULL;
8944             mongoc_transaction_opt_t *txn_opts = NULL;
8945             mongoc_read_concern_t *read_concern = NULL;
8946             mongoc_write_concern_t *write_concern = NULL;
8947             const char *uri_string = "mongodb://127.0.0.1/?appname=transaction-example";
8948             mongoc_uri_t *uri;
8949             bson_error_t error;
8950             bson_t *doc = NULL;
8951             bson_t *insert_opts = NULL;
8952             int32_t i;
8953             int64_t start;
8954             bson_t reply = BSON_INITIALIZER;
8955             char *reply_json;
8956             bool r;
8957
8958             mongoc_init ();
8959
8960             if (argc > 1) {
8961                uri_string = argv[1];
8962             }
8963
8964             uri = mongoc_uri_new_with_error (uri_string, &error);
8965             if (!uri) {
8966                MONGOC_ERROR ("failed to parse URI: %s\n"
8967                              "error message:       %s\n",
8968                              uri_string,
8969                              error.message);
8970                goto done;
8971             }
8972
8973             client = mongoc_client_new_from_uri (uri);
8974             if (!client) {
8975                goto done;
8976             }
8977
8978             mongoc_client_set_error_api (client, 2);
8979             database = mongoc_client_get_database (client, "example-transaction");
8980
8981             /* inserting into a nonexistent collection normally creates it, but a
8982              * collection can't be created in a transaction; create it now */
8983             collection =
8984                mongoc_database_create_collection (database, "collection", NULL, &error);
8985
8986             if (!collection) {
8987                /* code 48 is NamespaceExists, see error_codes.err in mongodb source */
8988                if (error.code == 48) {
8989                   collection = mongoc_database_get_collection (database, "collection");
8990                } else {
8991                   MONGOC_ERROR ("Failed to create collection: %s", error.message);
8992                   goto done;
8993                }
8994             }
8995
8996             /* a transaction's read preferences, read concern, and write concern can be
8997              * set on the client, on the default transaction options, or when starting
8998              * the transaction. for the sake of this example, set read concern on the
8999              * default transaction options. */
9000             default_txn_opts = mongoc_transaction_opts_new ();
9001             read_concern = mongoc_read_concern_new ();
9002             mongoc_read_concern_set_level (read_concern, "snapshot");
9003             mongoc_transaction_opts_set_read_concern (default_txn_opts, read_concern);
9004             session_opts = mongoc_session_opts_new ();
9005             mongoc_session_opts_set_default_transaction_opts (session_opts,
9006                                                               default_txn_opts);
9007
9008             session = mongoc_client_start_session (client, session_opts, &error);
9009             if (!session) {
9010                MONGOC_ERROR ("Failed to start session: %s", error.message);
9011                goto done;
9012             }
9013
9014             /* in this example, set write concern when starting the transaction */
9015             txn_opts = mongoc_transaction_opts_new ();
9016             write_concern = mongoc_write_concern_new ();
9017             mongoc_write_concern_set_wmajority (write_concern, 1000 /* wtimeout */);
9018             mongoc_transaction_opts_set_write_concern (txn_opts, write_concern);
9019
9020             insert_opts = bson_new ();
9021             if (!mongoc_client_session_append (session, insert_opts, &error)) {
9022                MONGOC_ERROR ("Could not add session to opts: %s", error.message);
9023                goto done;
9024             }
9025
9026          retry_transaction:
9027             r = mongoc_client_session_start_transaction (session, txn_opts, &error);
9028             if (!r) {
9029                MONGOC_ERROR ("Failed to start transaction: %s", error.message);
9030                goto done;
9031             }
9032
9033             /* insert two documents - on error, retry the whole transaction */
9034             for (i = 0; i < 2; i++) {
9035                doc = BCON_NEW ("_id", BCON_INT32 (i));
9036                bson_destroy (&reply);
9037                r = mongoc_collection_insert_one (
9038                   collection, doc, insert_opts, &reply, &error);
9039
9040                bson_destroy (doc);
9041
9042                if (!r) {
9043                   MONGOC_ERROR ("Insert failed: %s", error.message);
9044                   mongoc_client_session_abort_transaction (session, NULL);
9045
9046                   /* a network error, primary failover, or other temporary error in a
9047                    * transaction includes {"errorLabels": ["TransientTransactionError"]},
9048                    * meaning that trying the entire transaction again may succeed
9049                    */
9050                   if (mongoc_error_has_label (&reply, "TransientTransactionError")) {
9051                      goto retry_transaction;
9052                   }
9053
9054                   goto done;
9055                }
9056
9057                reply_json = bson_as_json (&reply, NULL);
9058                printf ("%s\n", reply_json);
9059                bson_free (reply_json);
9060             }
9061
9062             /* in case of transient errors, retry for 5 seconds to commit transaction */
9063             start = bson_get_monotonic_time ();
9064             while (bson_get_monotonic_time () - start < 5 * 1000 * 1000) {
9065                bson_destroy (&reply);
9066                r = mongoc_client_session_commit_transaction (session, &reply, &error);
9067                if (r) {
9068                   /* success */
9069                   break;
9070                } else {
9071                   MONGOC_ERROR ("Warning: commit failed: %s", error.message);
9072                   if (mongoc_error_has_label (&reply, "TransientTransactionError")) {
9073                      goto retry_transaction;
9074                   } else if (mongoc_error_has_label (&reply,
9075                                                      "UnknownTransactionCommitResult")) {
9076                      /* try again to commit */
9077                      continue;
9078                   }
9079
9080                   /* unrecoverable error trying to commit */
9081                   break;
9082                }
9083             }
9084
9085             exit_code = EXIT_SUCCESS;
9086
9087          done:
9088             bson_destroy (&reply);
9089             bson_destroy (insert_opts);
9090             mongoc_write_concern_destroy (write_concern);
9091             mongoc_read_concern_destroy (read_concern);
9092             mongoc_transaction_opts_destroy (txn_opts);
9093             mongoc_transaction_opts_destroy (default_txn_opts);
9094             mongoc_client_session_destroy (session);
9095             mongoc_collection_destroy (collection);
9096             mongoc_database_destroy (database);
9097             mongoc_uri_destroy (uri);
9098             mongoc_client_destroy (client);
9099
9100             mongoc_cleanup ();
9101
9102             return exit_code;
9103          }
9104
9105
9106   mongoc_transaction_state_t
9107       Constants for transaction states
9108
9109   Synopsis
9110          typedef enum {
9111            MONGOC_TRANSACTION_NONE = 0,
9112            MONGOC_TRANSACTION_STARTING = 1,
9113            MONGOC_TRANSACTION_IN_PROGRESS = 2,
9114            MONGOC_TRANSACTION_COMMITTED = 3,
9115            MONGOC_TRANSACTION_ABORTED = 4,
9116          } mongoc_transaction_state_t;
9117
9118   Description
9119       These constants describe the current transaction state of a session.
9120
9121   Flag Values
9122              ┌───────────────────────────┬────────────────────────────┐
9123              │MONGOC_TRANSACTION_NONE    │ There is no transaction in │
9124              │                           │ progress.                  │
9125              └───────────────────────────┴────────────────────────────┘
9126
9127
9128
9129
9130
9131              │MONGOC_TRANSACTION_START‐  │ A   transaction  has  been │
9132              │ING                        │ started, but no  operation │
9133              │                           │ has   been   sent  to  the │
9134              │                           │ server.                    │
9135              ├───────────────────────────┼────────────────────────────┤
9136              │MONGOC_TRANSAC‐            │ A    transaction   is   in │
9137              │TION_IN_PROGRESS           │ progress.                  │
9138              ├───────────────────────────┼────────────────────────────┤
9139              │MONGOC_TRANSACTION_COMMIT‐ │ The  transaction  was com‐ │
9140              │TED                        │ mitted.                    │
9141              ├───────────────────────────┼────────────────────────────┤
9142              │MONGOC_TRANSACTION_ABORTED │ The    transaction     was │
9143              │                           │ aborted.                   │
9144              └───────────────────────────┴────────────────────────────┘
9145
9146   mongoc_update_flags_t
9147       Flags for update operations
9148
9149   Synopsis
9150          typedef enum {
9151             MONGOC_UPDATE_NONE = 0,
9152             MONGOC_UPDATE_UPSERT = 1 << 0,
9153             MONGOC_UPDATE_MULTI_UPDATE = 1 << 1,
9154          } mongoc_update_flags_t;
9155
9156          #define MONGOC_UPDATE_NO_VALIDATE (1U << 31)
9157
9158   Description
9159       These  flags  correspond to the MongoDB wire protocol. They may be bit‐
9160       wise or'd together. The allow for modifying the way an update  is  per‐
9161       formed in the MongoDB server.
9162
9163   Flag Values
9164              ┌───────────────────────────┬────────────────────────────┐
9165              │MONGOC_UPDATE_NONE         │ No update flags set.       │
9166              ├───────────────────────────┼────────────────────────────┤
9167              │MONGOC_UPDATE_UPSERT       │ If  an  upsert  should  be │
9168              │                           │ performed.                 │
9169              ├───────────────────────────┼────────────────────────────┤
9170              │MONGOC_UPDATE_MULTI_UPDATE │ If  more  than  a   single │
9171              │                           │ matching  document  should │
9172              │                           │ be  updated.  By   default │
9173              │                           │ only the first document is │
9174              │                           │ updated.                   │
9175              ├───────────────────────────┼────────────────────────────┤
9176              │MONGOC_UPDATE_NO_VALIDATE  │ Do not perform client side │
9177              │                           │ BSON validations when per‐ │
9178              │                           │ forming an update. This is │
9179              │                           │ useful if you already know │
9180              │                           │ your  BSON  documents  are │
9181              │                           │ valid.                     │
9182              └───────────────────────────┴────────────────────────────┘
9183
9184   mongoc_uri_t
9185   Synopsis
9186          typedef struct _mongoc_uri_t mongoc_uri_t;
9187
9188   Description
9189       mongoc_uri_t  provides  an abstraction on top of the MongoDB connection
9190       URI format. It provides standardized parsing  as  well  as  convenience
9191       methods  for  extracting  useful  information  such as replica hosts or
9192       authorization information.
9193
9194       See Connection String URI Reference on the  MongoDB  website  for  more
9195       information.
9196
9197   Format
9198          mongodb[+srv]://                             <1>
9199             [username:password@]                      <2>
9200             host1                                     <3>
9201             [:port1]                                  <4>
9202             [,host2[:port2],...[,hostN[:portN]]]      <5>
9203             [/[database]                              <6>
9204             [?options]]                               <7>
9205
9206       1. "mongodb"  is  the  specifier  of  the  MongoDB  protocol. Use "mon‐
9207          godb+srv" with a single service name in place of "host1" to  specify
9208          the initial list of servers with an SRV record.
9209
9210       2. An optional username and password.
9211
9212       3. The  only  required  part of the uri.  This specifies either a host‐
9213          name, IPv4 address, IPv6 address enclosed in "[" and  "]",  or  UNIX
9214          domain socket.
9215
9216       4. An optional port number.  Defaults to :27017.
9217
9218       5. Extra  optional  hosts and ports.  You would specify multiple hosts,
9219          for example, for connections to replica sets.
9220
9221       6. The name of the database to authenticate if  the  connection  string
9222          includes  authentication credentials.  If /database is not specified
9223          and the connection string  includes  credentials,  defaults  to  the
9224          'admin' database.
9225
9226       7. Connection specific options.
9227
9228       NOTE:
9229          Option  names  are  case-insensitive.  Do not repeat the same option
9230          (e.g. "mongodb://localhost/db?opt=value1&OPT=value2") since this may
9231          have unexpected results.
9232
9233       The  MongoDB  C  Driver exposes constants for each supported connection
9234       option. These constants make it easier to discover connection  options,
9235       but their string values can be used as well.
9236
9237       For example, the following calls are equal.
9238
9239          uri = mongoc_uri_new ("mongodb://localhost/?" MONGOC_URI_APPNAME "=applicationName");
9240          uri = mongoc_uri_new ("mongodb://localhost/?appname=applicationName");
9241          uri = mongoc_uri_new ("mongodb://localhost/?appName=applicationName");
9242
9243   Replica Set Example
9244       To describe a connection to a replica set named 'test' with the follow‐
9245       ing mongod hosts:
9246
9247       · db1.example.com on port 27017
9248
9249       · db2.example.com on port 2500
9250
9251       You would use a connection string that resembles the following.
9252
9253          mongodb://db1.example.com,db2.example.com:2500/?replicaSet=test
9254
9255   SRV Example
9256       If  you  have  configured  an  SRV  record  with  a  name  like  "_mon‐
9257       godb._tcp.server.example.com"  whose  records are a list of one or more
9258       MongoDB server hostnames, use a connection string like this:
9259
9260          uri = mongoc_uri_new ("mongodb+srv://server.example.com/?replicaSet=rs&appName=applicationName");
9261
9262       The driver prefixes the service name with "_mongodb._tcp.",  then  per‐
9263       forms  a DNS SRV query to resolve the service name to one or more host‐
9264       names. If this query succeeds, the driver performs a DNS TXT  query  on
9265       the  service  name  (without the "_mongodb._tcp" prefix) for additional
9266       URI options configured as TXT records.
9267
9268       On Unix, the MongoDB C Driver relies on libresolv to look  up  SRV  and
9269       TXT  records.  If  libresolv is unavailable, then using a "mongodb+srv"
9270       URI will cause an error. If your libresolv lacks res_nsearch  then  the
9271       driver will fall back to res_search, which is not thread-safe.
9272
9273   IPv4 and IPv6
9274       If  connecting  to  a hostname that has both IPv4 and IPv6 DNS records,
9275       the behavior follows RFC-6555. A connection  to  the  IPv6  address  is
9276       attempted  first.  If IPv6 fails, then a connection is attempted to the
9277       IPv4 address. If the connection  attempt  to  IPv6  does  not  complete
9278       within  250ms,  then IPv4 is tried in parallel. Whichever succeeds con‐
9279       nection first cancels the other. The successful DNS  result  is  cached
9280       for 10 minutes.
9281
9282       As  a  consequence,  attempts  to connect to a mongod only listening on
9283       IPv4 may be delayed if there are both A  (IPv4)  and  AAAA  (IPv6)  DNS
9284       records associated with the host.
9285
9286       To  avoid  a delay, configure hostnames to match the MongoDB configura‐
9287       tion. That is, only create an A record if the mongod is only  listening
9288       on IPv4.
9289
9290   Connection Options
9291      ──────────────────────────────────────────────────────────────────────────
9292       Constant              Key                Description
9293      ──────────────────────────────────────────────────────────────────────────
9294       MON‐                  retryreads         If "true"  and  the
9295       GOC_URI_RETRYREADS                       server is a MongoDB
9296                                                3.6+    standalone,
9297                                                replica   set,   or
9298                                                sharded    cluster,
9299                                                the  driver  safely
9300                                                retries a read that
9301                                                failed   due  to  a
9302                                                network  error   or
9303                                                replica         set
9304                                                failover.
9305      ──────────────────────────────────────────────────────────────────────────
9306       MONGOC_URI_RETRY‐     retrywrites        If  "true"  and the
9307       WRITES                                   server is a MongoDB
9308                                                3.6+ replica set or
9309                                                sharded    cluster,
9310                                                the  driver  safely
9311                                                retries   a   write
9312                                                that  failed due to
9313                                                a network error  or
9314                                                replica         set
9315                                                failover.      Only
9316                                                inserts, updates of
9317                                                single   documents,
9318                                                or  deletes of sin‐
9319                                                gle  documents  are
9320                                                retried.
9321      ──────────────────────────────────────────────────────────────────────────
9322       MONGOC_URI_APPNAME    appname            The client applica‐
9323                                                tion   name.   This
9324                                                value  is  used  by
9325                                                MongoDB   when   it
9326                                                logs     connection
9327                                                information     and
9328                                                profile    informa‐
9329                                                tion, such as  slow
9330                                                queries.
9331      ──────────────────────────────────────────────────────────────────────────
9332       MONGOC_URI_TLS        tls                {true|false}, indi‐
9333                                                cating if TLS  must
9334                                                be  used. (See also
9335                                                mon‐
9336                                                goc_client_set_ssl_opts
9337                                                and            mon‐
9338                                                goc_client_pool_set_ssl_opts.)
9339      ──────────────────────────────────────────────────────────────────────────
9340       MONGOC_URI_COMPRES‐   compressors        Comma  separated  list of com‐
9341       SORS                                     pressors, if any,  to  use  to
9342                                                compress   the  wire  protocol
9343                                                messages.  Snappy,  zlib,  and
9344                                                zstd  are  optional build time
9345                                                dependencies, and  enable  the
9346                                                "snappy",  "zlib",  and "zstd"
9347                                                values respectively.  Defaults
9348                                                to empty (no compressors).
9349      ──────────────────────────────────────────────────────────────────────────
9350       MONGOC_URI_CONNECT‐   connecttimeoutms   This setting  applies  to  new
9351       TIMEOUTMS                                server connections. It is also
9352                                                used as the socket timeout for
9353                                                server  discovery and monitor‐
9354                                                ing operations. The default is
9355                                                10,000 ms (10 seconds).
9356      ──────────────────────────────────────────────────────────────────────────
9357       MONGOC_URI_SOCKET‐    sockettimeoutms    The time  in  milliseconds  to
9358       TIMEOUTMS                                attempt  to send or receive on
9359                                                a socket  before  the  attempt
9360                                                times   out.  The  default  is
9361                                                300,000 (5 minutes).
9362      ──────────────────────────────────────────────────────────────────────────
9363       MONGOC_URI_REPLI‐     replicaset         The  name  of  the Replica Set
9364       CASET                                    that the driver should connect
9365                                                to.
9366      ┌────────────────────┬──────────────────┬────────────────────────────────┐
9367      │                    │                  │                                │
9368      │                    │                  │                                │
9369      │                    │                  │                                │
9370      │                    │                  │                                │
9371      │                    │                  │                                │
9372      │                    │                  │                                │
9373
9374      │MONGOC_URI_ZLIBCOM‐ │ zlibcompression‐ │ When  the  MONGOC_URI_COMPRES‐ │
9375      │PRESSIONLEVEL       │ level            │ SORS  includes   "zlib"   this │
9376      │                    │                  │ options  configures  the  zlib │
9377      │                    │                  │ compression  level,  when  the │
9378      │                    │                  │ zlib  compressor  is  used  to │
9379      │                    │                  │ compress client data.          │
9380      └────────────────────┴──────────────────┴────────────────────────────────┘
9381
9382       Setting any of the *timeoutMS options above to 0 will be interpreted as
9383       "use the default value".
9384
9385   Authentication Options
9386        ┌────────────────────┬────────────────────┬─────────────────────────┐
9387        │Constant            │ Key                │ Description             │
9388        ├────────────────────┼────────────────────┼─────────────────────────┤
9389        │MONGOC_URI_AUTH‐    │ authmechanism      │ Specifies the mech‐     │
9390        │MECHANISM           │                    │ anism  to  use when     │
9391        │                    │                    │ authenticating   as     │
9392        │                    │                    │ the  provided user.     │
9393        │                    │                    │ See  Authentication     │
9394        │                    │                    │ for  supported val‐     │
9395        │                    │                    │ ues.                    │
9396        ├────────────────────┼────────────────────┼─────────────────────────┤
9397        │MONGOC_URI_AUTH‐    │ authmechanismprop‐ │ Certain authentica‐     │
9398        │MECHANISMPROPERTIES │ erties             │ tion     mechanisms     │
9399        │                    │                    │ have     additional     │
9400        │                    │                    │ options that can be     │
9401        │                    │                    │ configured.   These     │
9402        │                    │                    │ options  should  be     │
9403        │                    │                    │ provided  as  comma     │
9404        │                    │                    │ separated               │
9405        │                    │                    │ option_key:option_value │
9406        │                    │                    │ pair  and  provided     │
9407        │                    │                    │ as   authMechanism‐     │
9408        │                    │                    │ Properties.             │
9409        ├────────────────────┼────────────────────┼─────────────────────────┤
9410        │MONGOC_URI_AUTH‐    │ authsource         │ The authSource  defines │
9411        │SOURCE              │                    │ the    database    that │
9412        │                    │                    │ should   be   used   to │
9413        │                    │                    │ authenticate  to. It is │
9414        │                    │                    │ unnecessary to  provide │
9415        │                    │                    │ this  option  the data‐ │
9416        │                    │                    │ base name is  the  same │
9417        │                    │                    │ as the database used in │
9418        │                    │                    │ the URI.                │
9419        └────────────────────┴────────────────────┴─────────────────────────┘
9420
9421   Mechanism Properties
9422           ┌────────────────────┬───────────────────┬─────────────────────┐
9423           │Constant            │ Key               │ Description         │
9424           ├────────────────────┼───────────────────┼─────────────────────┤
9425           │MONGOC_URI_CANONI‐  │ canonicalizehost‐ │ Use  the  canonical │
9426           │CALIZEHOSTNAME      │ name              │ hostname   of   the │
9427           │                    │                   │ service,     rather │
9428           │                    │                   │ than its configured │
9429           │                    │                   │ alias, when authen‐ │
9430           │                    │                   │ ticating       with │
9431           │                    │                   │ Cyrus-SASL     Ker‐ │
9432           │                    │                   │ beros.              │
9433           ├────────────────────┼───────────────────┼─────────────────────┤
9434           │MONGOC_URI_GSSAPIS‐ │ gssapiservicename │ Use     alternative │
9435           │ERVICENAME          │                   │ service  name.  The │
9436           │                    │                   │ default is mongodb. │
9437           └────────────────────┴───────────────────┴─────────────────────┘
9438
9439   TLS Options
9440          ┌────────────────────┬─────────────────────┬─────────────────────┐
9441          │Constant            │ Key                 │ Description         │
9442          ├────────────────────┼─────────────────────┼─────────────────────┤
9443          │MONGOC_URI_TLSCER‐  │ tlscertificatekey‐  │ Path to PEM format‐ │
9444          │TIFICATEKEYFILE     │ file                │ ted   Private  Key, │
9445          │                    │                     │ with   its   Public │
9446          │                    │                     │ Certificate    con‐ │
9447          │                    │                     │ catenated  at   the │
9448          │                    │                     │ end.                │
9449          └────────────────────┴─────────────────────┴─────────────────────┘
9450
9451
9452
9453
9454
9455          │MONGOC_URI_TLSCER‐  │ tlscertificatekey‐  │ The   password,  if │
9456          │TIFICATEKEYPASSWORD │ password            │ any,  to   use   to │
9457          │                    │                     │ unlock    encrypted │
9458          │                    │                     │ Private Key.        │
9459          ├────────────────────┼─────────────────────┼─────────────────────┤
9460          │MONGOC_URI_TLSCER‐  │ tlscertificateau‐   │ One,  or  a  bundle │
9461          │TIFICATEAUTHORITY‐  │ thorityfile         │ of,     Certificate │
9462          │FILE                │                     │ Authorities    whom │
9463          │                    │                     │ should  be  consid‐ │
9464          │                    │                     │ ered to be trusted. │
9465          ├────────────────────┼─────────────────────┼─────────────────────┤
9466          │MONGOC_URI_TLSAL‐   │ tlsallowinvalidcer‐ │ Accept  and  ignore │
9467          │LOWINVALIDCERTIFI‐  │ tificates           │ certificate verifi‐ │
9468          │CATES               │                     │ cation errors (e.g. │
9469          │                    │                     │ untrusted   issuer, │
9470          │                    │                     │ expired, etc etc)   │
9471          ├────────────────────┼─────────────────────┼─────────────────────┤
9472          │MONGOC_URI_TLSAL‐   │ tlsallowinvalid‐    │ Ignore     hostname │
9473          │LOWINVALIDHOSTNAMES │ hostnames           │ verification of the │
9474          │                    │                     │ certificate   (e.g. │
9475          │                    │                     │ Man  In The Middle, │
9476          │                    │                     │ using  valid   cer‐ │
9477          │                    │                     │ tificate,       but │
9478          │                    │                     │ issued for  another │
9479          │                    │                     │ hostname)           │
9480          ├────────────────────┼─────────────────────┼─────────────────────┤
9481          │MONGOC_URI_TLSINSE‐ │ tlsinsecure         │ {true|false}, indi‐ │
9482          │CURE                │                     │ cating  if insecure │
9483          │                    │                     │ TLS options  should │
9484          │                    │                     │ be  used. Currently │
9485          │                    │                     │ this  implies  MON‐ │
9486          │                    │                     │ GOC_URI_TLSALLOWIN‐ │
9487          │                    │                     │ VALIDCERTIFICATES   │
9488          │                    │                     │ and            MON‐ │
9489          │                    │                     │ GOC_URI_TLSALLOWIN‐ │
9490          │                    │                     │ VALIDHOSTNAMES.     │
9491          └────────────────────┴─────────────────────┴─────────────────────┘
9492
9493       See mongoc_ssl_opt_t for details about these options and about building
9494       libmongoc with SSL support.
9495
9496   Deprecated SSL Options
9497       The following options have been deprecated  and  may  be  removed  from
9498       future releases of libmongoc.
9499
9500   ┌──────────────────────┬──────────────────┬──────────────────┬──────────────────┐
9501   │Constant              │ Key              │ Deprecated For   │ Key              │
9502   ├──────────────────────┼──────────────────┼──────────────────┼──────────────────┤
9503   │MONGOC_URI_SSL        │ ssl              │ MONGOC_URI_TLS   │ tls              │
9504   ├──────────────────────┼──────────────────┼──────────────────┼──────────────────┤
9505   │MON‐                  │ sslclientcer‐    │ MON‐             │ tlscertifi‐      │
9506   │GOC_URI_SSLCLIENTCER‐ │ tificatekeyfile  │ GOC_URI_TLSCER‐  │ catekeyfile      │
9507   │TIFICATEKEYFILE       │                  │ TIFICATEKEYFILE  │                  │
9508   ├──────────────────────┼──────────────────┼──────────────────┼──────────────────┤
9509   │MON‐                  │ sslclientcer‐    │ MON‐             │ tlscertifi‐      │
9510   │GOC_URI_SSLCLIENTCER‐ │ tificatekeypass‐ │ GOC_URI_TLSCER‐  │ catekeypassword  │
9511   │TIFICATEKEYPASSWORD   │ word             │ TIFICATEKEYPASS‐ │                  │
9512   │                      │                  │ WORD             │                  │
9513   ├──────────────────────┼──────────────────┼──────────────────┼──────────────────┤
9514   │MONGOC_URI_SSLCER‐    │ sslcertifi‐      │ MON‐             │ tlscertifi‐      │
9515   │TIFICATEAUTHORITYFILE │ cateauthority‐   │ GOC_URI_TLSCER‐  │ cateauthority‐   │
9516   │                      │ file             │ TIFICATEAUTHORI‐ │ file             │
9517   │                      │                  │ TYFILE           │                  │
9518   ├──────────────────────┼──────────────────┼──────────────────┼──────────────────┤
9519   │MONGOC_URI_SSLALLOW‐  │ sslallowinvalid‐ │ MON‐             │ tlsallowinvalid‐ │
9520   │INVALIDCERTIFICATES   │ certificates     │ GOC_URI_TLSAL‐   │ certificates     │
9521   │                      │                  │ LOWINVALIDCER‐   │                  │
9522   │                      │                  │ TIFICATES        │                  │
9523   ├──────────────────────┼──────────────────┼──────────────────┼──────────────────┤
9524   │MONGOC_URI_SSLALLOW‐  │ sslallowinvalid‐ │ MON‐             │ tlsallowinvalid‐ │
9525   │INVALIDHOSTNAMES      │ hostnames        │ GOC_URI_TLSAL‐   │ hostnames        │
9526   │                      │                  │ LOWINVALIDHOST‐  │                  │
9527   │                      │                  │ NAMES            │                  │
9528   └──────────────────────┴──────────────────┴──────────────────┴──────────────────┘
9529
9530   Server Discovery, Monitoring, and Selection Options
9531       Clients in a mongoc_client_pool_t share a topology scanner that runs on
9532       a  background  thread.  The  thread  wakes  every  heartbeatFrequencyMS
9533       (default  10 seconds) to scan all MongoDB servers in parallel. Whenever
9534       an application operation requires a server that is not known--for exam‐
9535       ple,  if  there  is  no  known primary and your application attempts an
9536       insert--the thread rescans all servers every half-second. In this situ‐
9537       ation  the  pooled client waits up to serverSelectionTimeoutMS (default
9538       30 seconds) for the thread to find a server suitable for the operation,
9539       then returns an error with domain MONGOC_ERROR_SERVER_SELECTION.
9540
9541       Technically, the total time an operation may wait while a pooled client
9542       scans the topology is controlled both by  serverSelectionTimeoutMS  and
9543       connectTimeoutMS.  The longest wait occurs if the last scan begins just
9544       at the end of the selection timeout, and a slow or down server requires
9545       the full connection timeout before the client gives up.
9546
9547       A  non-pooled client is single-threaded. Every heartbeatFrequencyMS, it
9548       blocks the next application operation while it does  a  parallel  scan.
9549       This  scan takes as long as needed to check the slowest server: roughly
9550       connectTimeoutMS. Therefore the default heartbeatFrequencyMS  for  sin‐
9551       gle-threaded clients is greater than for pooled clients: 60 seconds.
9552
9553       By default, single-threaded (non-pooled) clients scan only once when an
9554       operation requires a server that is not known. If you attempt an insert
9555       and  there is no known primary, the client checks all servers once try‐
9556       ing to find it, then succeeds or returns  an  error  with  domain  MON‐
9557       GOC_ERROR_SERVER_SELECTION.  But  if  you set serverSelectionTryOnce to
9558       "false", the single-threaded client loops, checking all  servers  every
9559       half-second, until serverSelectionTimeoutMS.
9560
9561       The  total  time  an operation may wait for a single-threaded client to
9562       scan the topology is determined by  connectTimeoutMS  in  the  try-once
9563       case,  or serverSelectionTimeoutMS and connectTimeoutMS if serverSelec‐
9564       tionTryOnce is set "false".
9565
9566          ┌────────────────────┬─────────────────────┬─────────────────────┐
9567          │Constant            │ Key                 │ Description         │
9568          ├────────────────────┼─────────────────────┼─────────────────────┤
9569          │MONGOC_URI_HEART‐   │ heartbeatfrequen‐   │ The        interval │
9570          │BEATFREQUENCYMS     │ cyms                │ between server mon‐ │
9571          │                    │                     │ itoring     checks. │
9572          │                    │                     │ Defaults         to │
9573          │                    │                     │ 10,000ms  (10  sec‐ │
9574          │                    │                     │ onds)   in   pooled │
9575          │                    │                     │ (multi-threaded)    │
9576          │                    │                     │ mode,  60,000ms (60 │
9577          │                    │                     │ seconds)         in │
9578          │                    │                     │ non-pooled     mode │
9579          │                    │                     │ (single-threaded).  │
9580          ├────────────────────┼─────────────────────┼─────────────────────┤
9581          │MONGOC_URI_SERVERS‐ │ serverselection‐    │ A timeout  in  mil‐ │
9582          │ELECTIONTIMEOUTMS   │ timeoutms           │ liseconds  to block │
9583          │                    │                     │ for  server  selec‐ │
9584          │                    │                     │ tion  before throw‐ │
9585          │                    │                     │ ing  an  exception. │
9586          │                    │                     │ The    default   is │
9587          │                    │                     │ 30,0000ms (30  sec‐ │
9588          │                    │                     │ onds).              │
9589          └────────────────────┴─────────────────────┴─────────────────────┘
9590
9591
9592
9593
9594
9595
9596
9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
9609
9610
9611
9612
9613
9614
9615
9616
9617          │MONGOC_URI_SERVERS‐ │ serverselectiontry‐ │ If    "true",   the │
9618          │ELECTIONTRYONCE     │ once                │ driver  scans   the │
9619          │                    │                     │ topology    exactly │
9620          │                    │                     │ once  after  server │
9621          │                    │                     │ selection    fails, │
9622          │                    │                     │ then either selects │
9623          │                    │                     │ a server or returns │
9624          │                    │                     │ an error. If it  is │
9625          │                    │                     │ false,   then   the │
9626          │                    │                     │ driver   repeatedly │
9627          │                    │                     │ searches    for   a │
9628          │                    │                     │ suitable server for │
9629          │                    │                     │ up  to serverSelec‐ 
9630          │                    │                     │ tionTimeoutMS  mil‐ │
9631          │                    │                     │ liseconds  (pausing │
9632          │                    │                     │ a    half    second │
9633          │                    │                     │ between  attempts). │
9634          │                    │                     │ The   default   for │
9635          │                    │                     │ serverSelectionTry‐ 
9636          │                    │                     │ Once is "false" for │
9637          │                    │                     │ pooled     clients, │
9638          │                    │                     │ otherwise   "true". │
9639          │                    │                     │ Pooled      clients │
9640          │                    │                     │ ignore serverSelec‐ │
9641          │                    │                     │ tionTryOnce;   they │
9642          │                    │                     │ signal  the  thread │
9643          │                    │                     │ to    rescan    the │
9644          │                    │                     │ topology      every │
9645          │                    │                     │ half-second   until │
9646          │                    │                     │ serverSelection‐    │
9647          │                    │                     │ TimeoutMS expires.  │
9648          ├────────────────────┼─────────────────────┼─────────────────────┤
9649          │MONGOC_URI_SOCK‐    │ socketcheckinter‐   │ Only   applies   to │
9650          │ETCHECKINTERVALMS   │ valms               │ single     threaded │
9651          │                    │                     │ clients.    If    a │
9652          │                    │                     │ socket has not been │
9653          │                    │                     │ used   within  this │
9654          │                    │                     │ time,  its  connec‐ │
9655          │                    │                     │ tion   is   checked │
9656          │                    │                     │ with    a     quick │
9657          │                    │                     │ "isMaster"     call │
9658          │                    │                     │ before it  is  used │
9659          │                    │                     │ again.  Defaults to │
9660          │                    │                     │ 5,000ms   (5   sec‐ │
9661          │                    │                     │ onds).              │
9662          └────────────────────┴─────────────────────┴─────────────────────┘
9663
9664       Setting any of the *TimeoutMS options above to 0 will be interpreted as
9665       "use the default value".
9666
9667   Connection Pool Options
9668       These options govern the behavior of a mongoc_client_pool_t.  They  are
9669       ignored by a non-pooled mongoc_client_t.
9670
9671          ┌────────────────────┬────────────────────┬─────────────────────┐
9672          │Constant            │ Key                │ Description         │
9673          ├────────────────────┼────────────────────┼─────────────────────┤
9674          │MONGOC_URI_MAXPOOL‐ │ maxpoolsize        │ The maximum  number │
9675          │SIZE                │                    │ of  clients created │
9676          │                    │                    │ by      a      mon‐ 
9677          │                    │                    │ goc_client_pool_t   
9678          │                    │                    │ total (both in  the │
9679          │                    │                    │ pool   and  checked │
9680          │                    │                    │ out).  The  default │
9681          │                    │                    │ value  is 100. Once │
9682          │                    │                    │ it is reached, mon‐ 
9683          │                    │                    │ goc_client_pool_pop 
9684          │                    │                    │ blocks        until │
9685          │                    │                    │ another      thread │
9686          │                    │                    │ pushes a client.    │
9687          ├────────────────────┼────────────────────┼─────────────────────┤
9688          │MONGOC_URI_MINPOOL‐ │ minpoolsize        │ Deprecated.    This │
9689          │SIZE                │                    │ option's   behavior │
9690          │                    │                    │ does  not match its │
9691          │                    │                    │ name,    and    its │
9692          │                    │                    │ actual     behavior │
9693          │                    │                    │ will  likely   hurt │
9694          │                    │                    │ performance.        │
9695          └────────────────────┴────────────────────┴─────────────────────┘
9696
9697
9698          │MONGOC_URI_MAXIDLE‐ │ maxidletimems      │ Not implemented.    │
9699          │TIMEMS              │                    │                     │
9700          ├────────────────────┼────────────────────┼─────────────────────┤
9701          │MONGOC_URI_WAIT‐    │ waitqueuemultiple  │ Not implemented.    │
9702          │QUEUEMULTIPLE       │                    │                     │
9703          ├────────────────────┼────────────────────┼─────────────────────┤
9704          │MONGOC_URI_WAIT‐    │ waitqueuetimeoutms │ Not implemented.    │
9705          │QUEUETIMEOUTMS      │                    │                     │
9706          └────────────────────┴────────────────────┴─────────────────────┘
9707
9708   Write Concern Options
9709               ┌───────────────────┬────────────┬─────────────────────┐
9710               │Constant           │ Key        │ Description         │
9711               └───────────────────┴────────────┴─────────────────────┘
9712
9713
9714
9715
9716
9717
9718
9719
9720
9721
9722
9723
9724
9725
9726
9727
9728
9729
9730
9731
9732
9733
9734
9735
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752
9753
9754
9755
9756
9757
9758
9759
9760
9761
9762
9763
9764
9765
9766
9767
9768
9769
9770
9771
9772
9773
9774
9775
9776
9777
9778
9779                MONGOC_URI_W         w            Determines      the
9780                                                  write       concern
9781                                                  (guarantee).  Valid
9782                                                  values:
9783
9784                                                         · 0   =  The
9785                                                           driver
9786                                                           will   not
9787                                                           acknowl‐
9788                                                           edge write
9789                                                           operations
9790                                                           but   will
9791                                                           pass    or
9792                                                           handle any
9793                                                           network
9794                                                           and socket
9795                                                           errors
9796                                                           that    it
9797                                                           receives
9798                                                           to     the
9799                                                           client. If
9800                                                           you   dis‐
9801                                                           able write
9802                                                           concern
9803                                                           but enable
9804                                                           the   get‐
9805                                                           LastError
9806                                                           command’s
9807                                                           w  option,
9808                                                           w    over‐
9809                                                           rides  the
9810                                                           w option.
9811
9812                                                         · 1  =  Pro‐
9813                                                           vides
9814                                                           basic
9815                                                           acknowl‐
9816                                                           edgement
9817                                                           of   write
9818                                                           opera‐
9819                                                           tions.  By
9820                                                           specifying
9821                                                           1,     you
9822                                                           require
9823                                                           that     a
9824                                                           standalone
9825                                                           mongod
9826                                                           instance,
9827                                                           or     the
9828                                                           primary
9829                                                           for
9830                                                           replica
9831                                                           sets,
9832                                                           acknowl‐
9833                                                           edge   all
9834                                                           write
9835                                                           opera‐
9836                                                           tions. For
9837                                                           drivers
9838                                                           released
9839                                                           after  the
9840                                                           default
9841                                                           write con‐
9842                                                           cern
9843                                                           change,
9844                                                           this    is
9845                                                           the
9846                                                           default
9847                                                           write con‐
9848                                                           cern  set‐
9849                                                           ting.
9850
9851                                                         · majority =
9852                                                           For
9853                                                           replica
9854                                                           sets,   if
9855                                                           you  spec‐
9856                                                           ify    the
9857                                                           special
9858                                                           majority
9859                                                           value to w
9860                                                           option,
9861                                                           write
9862                                                           operations
9863                                                           will  only
9864                                                           return
9865                                                           success‐
9866                                                           fully
9867                                                           after    a
9868                                                           majority
9869                                                           of     the
9870                                                           configured
9871                                                           replica
9872                                                           set   mem‐
9873                                                           bers  have
9874                                                           acknowl‐
9875                                                           edged  the
9876                                                           write
9877                                                           operation.
9878
9879                                                         · n  =   For
9880                                                           replica
9881                                                           sets,   if
9882                                                           you  spec‐
9883                                                           ify a num‐
9884                                                           ber      n
9885                                                           greater
9886                                                           than    1,
9887                                                           operations
9888                                                           with  this
9889                                                           write con‐
9890                                                           cern
9891                                                           return
9892                                                           only after
9893                                                           n  members
9894                                                           of the set
9895                                                           have
9896                                                           acknowl‐
9897                                                           edged  the
9898                                                           write.  If
9899                                                           you set  n
9900                                                           to  a num‐
9901                                                           ber   that
9902                                                           is greater
9903                                                           than   the
9904                                                           number  of
9905                                                           available
9906                                                           set   mem‐
9907                                                           bers    or
9908                                                           members
9909                                                           that  hold
9910                                                           data, Mon‐
9911                                                           goDB  will
9912                                                           wait,
9913                                                           poten‐
9914                                                           tially
9915                                                           indefi‐
9916                                                           nitely,
9917                                                           for  these
9918                                                           members to
9919                                                           become
9920                                                           available.
9921
9922                                                         · tags = For
9923                                                           replica
9924                                                           sets,  you
9925                                                           can  spec‐
9926                                                           ify  a tag
9927                                                           set     to
9928                                                           require
9929                                                           that   all
9930                                                           members of
9931                                                           the    set
9932                                                           that  have
9933                                                           these tags
9934                                                           configured
9935                                                           return
9936                                                           confirma‐
9937                                                           tion    of
9938                                                           the  write
9939                                                           operation.
9940               ├───────────────────┼────────────┼─────────────────────┤
9941               │MONGOC_URI_WTIME‐  │ wtimeoutms │ The  time  in  mil‐ │
9942               │OUTMS              │            │ liseconds  to  wait │
9943               │                   │            │ for  replication to │
9944               │                   │            │ succeed, as  speci‐ │
9945               │                   │            │ fied   in   the   w │
9946               │                   │            │ option, before tim‐ │
9947               │                   │            │ ing    out.    When │
9948               │                   │            │ wtimeoutMS  is   0, │
9949               │                   │            │ write    operations │
9950               │                   │            │ will   never   time │
9951               │                   │            │ out.                │
9952               ├───────────────────┼────────────┼─────────────────────┤
9953               │MONGOC_URI_JOURNAL │ journal    │ Controls    whether │
9954               │                   │            │ write    operations │
9955               │                   │            │ will wait until the │
9956               │                   │            │ mongod acknowledges │
9957               │                   │            │ the   write  opera‐ │
9958               │                   │            │ tions  and  commits │
9959               │                   │            │ the  data to the on │
9960               │                   │            │ disk journal.       │
9961               │                   │            │                     │
9962               │                   │            │        · true     = │
9963               │                   │            │          Enables    │
9964               │                   │            │          journal    │
9965               │                   │            │          commit     │
9966               │                   │            │          acknowl‐   │
9967               │                   │            │          edgement   │
9968               │                   │            │          write con‐ │
9969               │                   │            │          cern.      │
9970               │                   │            │          Equivalent │
9971               │                   │            │          to  speci‐ │
9972               │                   │            │          fying  the │
9973               │                   │            │          getLastEr‐ │
9974               │                   │            │          ror   com‐ │
9975               │                   │            │          mand  with │
9976               │                   │            │          the      j │
9977               │                   │            │          option     │
9978               │                   │            │          enabled.   │
9979               │                   │            │                     │
9980               │                   │            │        · false    = │
9981               │                   │            │          Does   not │
9982               │                   │            │          require    │
9983               │                   │            │          that  mon‐ │
9984               │                   │            │          god commit │
9985               │                   │            │          write      │
9986               │                   │            │          operations │
9987               │                   │            │          to     the │
9988               │                   │            │          journal    │
9989               │                   │            │          before     │
9990               │                   │            │          acknowl‐   │
9991               │                   │            │          edging the │
9992               │                   │            │          write      │
9993               │                   │            │          operation. │
9994               │                   │            │          This    is │
9995               │                   │            │          the        │
9996               │                   │            │          default    │
9997               │                   │            │          option for │
9998               │                   │            │          the  jour‐ │
9999               │                   │            │          nal param‐ │
10000               │                   │            │          eter.      │
10001               └───────────────────┴────────────┴─────────────────────┘
10002
10003   Read Concern Options
10004           ┌────────────────────┬──────────────────┬─────────────────────┐
10005           │Constant            │ Key              │ Description         │
10006           ├────────────────────┼──────────────────┼─────────────────────┤
10007           │MONGOC_URI_READCON‐ │ readconcernlevel │ The level of isola‐ │
10008           │CERNLEVEL           │                  │ tion for read oper‐ │
10009           │                    │                  │ ations.    If   the │
10010           │                    │                  │ level    is    left │
10011           │                    │                  │ unspecified,    the │
10012           │                    │                  │ server default will │
10013           │                    │                  │ be     used.    See │
10014           │                    │                  │ readConcern in  the
10015           │                    │                  │ MongoDB  Manual for │
10016           │                    │                  │ details.            │
10017           └────────────────────┴──────────────────┴─────────────────────┘
10018
10019   Read Preference Options
10020       When connected to a replica set, the driver  chooses  which  member  to
10021       query using the read preference:
10022
10023       1. Choose members whose type matches "readPreference".
10024
10025       2. From  these,  if  there are any tags sets configured, choose members
10026          matching the first tag set. If there are none, fall back to the next
10027          tag set and so on, until some members are chosen or the tag sets are
10028          exhausted.
10029
10030       3. From the chosen  servers,  distribute  queries  randomly  among  the
10031          server  with  the fastest round-trip times. These include the server
10032          with the fastest time and any whose round-trip time is no more  than
10033          "localThresholdMS" slower.
10034
10035       ┌─────────────────────┬─────────────────────┬──────────────────────────┐
10036       │Constant             │ Key                 │ Description              │
10037       ├─────────────────────┼─────────────────────┼──────────────────────────┤
10038       │MONGOC_URI_READ‐     │ readpreference      │ Specifies       the      │
10039       │PREFERENCE           │                     │ replica   set  read      │
10040       │                     │                     │ preference for this      │
10041       │                     │                     │ connection.    This      │
10042       │                     │                     │ setting   overrides      │
10043       │                     │                     │ any  slaveOk value.      │
10044       │                     │                     │ The read preference      │
10045       │                     │                     │ values are the fol‐      │
10046       │                     │                     │ lowing:                  │
10047       │                     │                     │                          │
10048       │                     │                     │        · primary         │
10049       │                     │                     │          (default)       │
10050       │                     │                     │                          │
10051       │                     │                     │        · prima‐          │
10052       │                     │                     │          ryPre‐          │
10053       │                     │                     │          ferred          │
10054       │                     │                     │                          │
10055       │                     │                     │        · secondary       │
10056       │                     │                     │                          │
10057       │                     │                     │        · sec‐            │
10058       │                     │                     │          ondaryPre‐      │
10059       │                     │                     │          ferred          │
10060       │                     │                     │                          │
10061       │                     │                     │        · nearest         │
10062       ├─────────────────────┼─────────────────────┼──────────────────────────┤
10063       │MONGOC_URI_READ‐     │ readpreferencetags  │ A representation of      │
10064       │PREFERENCETAGS       │                     │ a tag set. See also      │
10065       │                     │                     │ mon‐                     │
10066       │                     │                     │ goc-read-prefs-tag-sets. │
10067       ├─────────────────────┼─────────────────────┼──────────────────────────┤
10068       │MON‐                 │ localthresholdms    │ How  far  to  distribute │
10069       │GOC_URI_LOCALTHRESH‐ │                     │ queries,    beyond   the │
10070       │OLDMS                │                     │ server with the  fastest │
10071       │                     │                     │ round-trip    time.   By │
10072       │                     │                     │ default,  only   servers │
10073       │                     │                     │ within   15ms   of   the │
10074       │                     │                     │ fastest round-trip  time │
10075       │                     │                     │ receive queries.         │
10076       ├─────────────────────┼─────────────────────┼──────────────────────────┤
10077       │MONGOC_URI_MAXSTALE‐ │ maxstalenessseconds │ The maximum  replication │
10078       │NESSSECONDS          │                     │ lag, in wall clock time, │
10079       │                     │                     │ that  a  secondary   can │
10080       │                     │                     │ suffer and still be eli‐ │
10081       │                     │                     │ gible.   The    smallest │
10082       │                     │                     │ allowed     value    for │
10083       │                     │                     │ maxStalenessSeconds   is │
10084       │                     │                     │ 90 seconds.              │
10085       └─────────────────────┴─────────────────────┴──────────────────────────┘
10086
10087       NOTE:
10088          When  connecting  to  more than one mongos, libmongoc's localThresh‐
10089          oldMS applies only to the selection of mongos servers. The threshold
10090          for  selecting  among replica set members in shards is controlled by
10091          the mongos's localThreshold command line option.
10092
10093   Legacy Options
10094       For historical reasons,  the  following  options  are  available.  They
10095       should however not be used.
10096
10097                ┌───────────────────┬─────────┬─────────────────────┐
10098                │Constant           │ Key     │ Description         │
10099                ├───────────────────┼─────────┼─────────────────────┤
10100                │MONGOC_URI_SAFE    │ safe    │ {true|false}   Same │
10101                │                   │         │ as w={1|0}          │
10102                └───────────────────┴─────────┴─────────────────────┘
10103
10104                │MONGOC_URI_SLAVEOK │ slaveok │ When set,  same  as │
10105                │                   │         │ readPreference=sec‐ │
10106                │                   │         │ ondaryPreferred     │
10107                └───────────────────┴─────────┴─────────────────────┘
10108
10109   Version Checks
10110       Conditional compilation based on mongoc version
10111
10112   Description
10113       The following preprocessor macros can be used to perform various checks
10114       based  on  the  version of the library you are compiling against.  This
10115       may be useful if you only want to enable a feature on a certain version
10116       of the library.
10117
10118          #include <mongoc/mongoc.h>
10119
10120          #define MONGOC_MAJOR_VERSION (x)
10121          #define MONGOC_MINOR_VERSION (y)
10122          #define MONGOC_MICRO_VERSION (z)
10123          #define MONGOC_VERSION_S     "x.y.z"
10124          #define MONGOC_VERSION_HEX   ((1 << 24) | (0 << 16) | (0 << 8) | 0)
10125          #define MONGOC_CHECK_VERSION(major, minor, micro)
10126
10127       Only compile a block on MongoDB C Driver 1.1.0 and newer.
10128
10129          #if MONGOC_CHECK_VERSION(1, 1, 0)
10130          static void
10131          do_something (void)
10132          {
10133          }
10134          #endif
10135
10136   mongoc_write_concern_t
10137       Write Concern abstraction
10138
10139   Synopsis
10140       mongoc_write_concern_t  tells  the driver what level of acknowledgement
10141       to await from the server. The default,  MONGOC_WRITE_CONCERN_W_DEFAULT,
10142       is right for the great majority of applications.
10143
10144       You  can  specify  a  write  concern  on  connection  objects, database
10145       objects, collection objects, or  per-operation.  Data-modifying  opera‐
10146       tions  typically  use  the write concern of the object they operate on,
10147       and check the server response for a write concern error or  write  con‐
10148       cern  timeout.  For example, mongoc_collection_drop_index uses the col‐
10149       lection's write concern, and a write concern error or  timeout  in  the
10150       response is considered a failure.
10151
10152       Exceptions to this principle are the generic command functions:
10153
10154       · mongoc_client_command
10155
10156       · mongoc_client_command_simple
10157
10158       · mongoc_database_command
10159
10160       · mongoc_database_command_simple
10161
10162       · mongoc_collection_command
10163
10164       · mongoc_collection_command_simple
10165
10166       These generic command functions do not automatically apply a write con‐
10167       cern, and they do not check the server response  for  a  write  concern
10168       error or write concern timeout.
10169
10170       See Write Concern on the MongoDB website for more information.
10171
10172   Write Concern Levels
10173       Set the write concern level with mongoc_write_concern_set_w.
10174
10175              ┌───────────────────────────┬────────────────────────────┐
10176              │MONGOC_WRITE_CON‐          │ By default,  writes  block │
10177              │CERN_W_DEFAULT (1)         │ awaiting   acknowledgement │
10178              │                           │ from MongoDB. Acknowledged │
10179              │                           │ write    concern    allows │
10180              │                           │ clients to catch  network, │
10181              │                           │ duplicate  key,  and other │
10182              │                           │ errors.                    │
10183              └───────────────────────────┴────────────────────────────┘
10184
10185
10186              │MONGOC_WRITE_CON‐          │ With  this  write concern, │
10187              │CERN_W_UNACKNOWLEDGED (0)  │ MongoDB does not  acknowl‐ │
10188              │                           │ edge  the receipt of write │
10189              │                           │ operation.  Unacknowledged │
10190              │                           │ is   similar   to   errors │
10191              │                           │ ignored;  however,  mongoc │
10192              │                           │ attempts  to  receive  and │
10193              │                           │ handle network errors when │
10194              │                           │ possible.                  │
10195              ├───────────────────────────┼────────────────────────────┤
10196              │MONGOC_WRITE_CON‐          │ Block until  a  write  has │
10197              │CERN_W_MAJORITY (majority) │ been   propagated   to   a │
10198              │                           │ majority of the  nodes  in │
10199              │                           │ the replica set.           │
10200              ├───────────────────────────┼────────────────────────────┤
10201              │n                          │ Block  until  a  write has │
10202              │                           │ been  propagated   to   at │
10203              │                           │ least   n   nodes  in  the │
10204              │                           │ replica set.               │
10205              └───────────────────────────┴────────────────────────────┘
10206
10207   Deprecations
10208       The write concern MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED (value -1) is a
10209       deprecated synonym for MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED (value 0),
10210       and will be removed in the next major release.
10211
10212       mongoc_write_concern_set_fsync is deprecated.
10213
10214   Application Performance Monitoring (APM)
10215       The MongoDB C Driver allows you to monitor all the  MongoDB  operations
10216       the  driver  executes.  This  event-notification system conforms to two
10217       MongoDB driver specs:
10218
10219       · Command Monitoring: events related to all application operations.
10220
10221       · SDAM Monitoring: events related to the driver's Server Discovery  And
10222         Monitoring logic.
10223
10224       To  receive  notifications,  create  a mongoc_apm_callbacks_t with mon‐
10225       goc_apm_callbacks_new, set callbacks  on  it,  then  pass  it  to  mon‐
10226       goc_client_set_apm_callbacks or mongoc_client_pool_set_apm_callbacks.
10227
10228   Command-Monitoring Example
10229       example-command-monitoring.c.INDENT 0.0
10230
10231          /* gcc example-command-monitoring.c -o example-command-monitoring \
10232           *     $(pkg-config --cflags --libs libmongoc-1.0) */
10233
10234          /* ./example-command-monitoring [CONNECTION_STRING] */
10235
10236          #include <mongoc/mongoc.h>
10237          #include <stdio.h>
10238
10239
10240          typedef struct {
10241             int started;
10242             int succeeded;
10243             int failed;
10244          } stats_t;
10245
10246
10247          void
10248          command_started (const mongoc_apm_command_started_t *event)
10249          {
10250             char *s;
10251
10252             s = bson_as_relaxed_extended_json (
10253                mongoc_apm_command_started_get_command (event), NULL);
10254             printf ("Command %s started on %s:\n%s\n\n",
10255                     mongoc_apm_command_started_get_command_name (event),
10256                     mongoc_apm_command_started_get_host (event)->host,
10257                     s);
10258
10259             ((stats_t *) mongoc_apm_command_started_get_context (event))->started++;
10260
10261             bson_free (s);
10262          }
10263
10264
10265          void
10266          command_succeeded (const mongoc_apm_command_succeeded_t *event)
10267          {
10268             char *s;
10269
10270             s = bson_as_relaxed_extended_json (
10271                mongoc_apm_command_succeeded_get_reply (event), NULL);
10272             printf ("Command %s succeeded:\n%s\n\n",
10273                     mongoc_apm_command_succeeded_get_command_name (event),
10274                     s);
10275
10276             ((stats_t *) mongoc_apm_command_succeeded_get_context (event))->succeeded++;
10277
10278             bson_free (s);
10279          }
10280
10281
10282          void
10283          command_failed (const mongoc_apm_command_failed_t *event)
10284          {
10285             bson_error_t error;
10286
10287             mongoc_apm_command_failed_get_error (event, &error);
10288             printf ("Command %s failed:\n\"%s\"\n\n",
10289                     mongoc_apm_command_failed_get_command_name (event),
10290                     error.message);
10291
10292             ((stats_t *) mongoc_apm_command_failed_get_context (event))->failed++;
10293          }
10294
10295
10296          int
10297          main (int argc, char *argv[])
10298          {
10299             mongoc_client_t *client;
10300             mongoc_apm_callbacks_t *callbacks;
10301             stats_t stats = {0};
10302             mongoc_collection_t *collection;
10303             bson_error_t error;
10304             const char *uri_string =
10305                "mongodb://127.0.0.1/?appname=cmd-monitoring-example";
10306             mongoc_uri_t *uri;
10307             const char *collection_name = "test";
10308             bson_t *docs[2];
10309
10310             mongoc_init ();
10311
10312             if (argc > 1) {
10313                uri_string = argv[1];
10314             }
10315
10316             uri = mongoc_uri_new_with_error (uri_string, &error);
10317             if (!uri) {
10318                fprintf (stderr,
10319                         "failed to parse URI: %s\n"
10320                         "error message:       %s\n",
10321                         uri_string,
10322                         error.message);
10323                return EXIT_FAILURE;
10324             }
10325
10326             client = mongoc_client_new_from_uri (uri);
10327             if (!client) {
10328                return EXIT_FAILURE;
10329             }
10330
10331             mongoc_client_set_error_api (client, 2);
10332             callbacks = mongoc_apm_callbacks_new ();
10333             mongoc_apm_set_command_started_cb (callbacks, command_started);
10334             mongoc_apm_set_command_succeeded_cb (callbacks, command_succeeded);
10335             mongoc_apm_set_command_failed_cb (callbacks, command_failed);
10336             mongoc_client_set_apm_callbacks (
10337                client, callbacks, (void *) &stats /* context pointer */);
10338
10339             collection = mongoc_client_get_collection (client, "test", collection_name);
10340             mongoc_collection_drop (collection, NULL);
10341
10342             docs[0] = BCON_NEW ("_id", BCON_INT32 (0));
10343             docs[1] = BCON_NEW ("_id", BCON_INT32 (1));
10344             mongoc_collection_insert_many (
10345                collection, (const bson_t **) docs, 2, NULL, NULL, NULL);
10346
10347             /* duplicate key error on the second insert */
10348             mongoc_collection_insert_one (collection, docs[0], NULL, NULL, NULL);
10349
10350             mongoc_collection_destroy (collection);
10351             mongoc_apm_callbacks_destroy (callbacks);
10352             mongoc_uri_destroy (uri);
10353             mongoc_client_destroy (client);
10354
10355             printf ("started: %d\nsucceeded: %d\nfailed: %d\n",
10356                     stats.started,
10357                     stats.succeeded,
10358                     stats.failed);
10359
10360             bson_destroy (docs[0]);
10361             bson_destroy (docs[1]);
10362
10363             mongoc_cleanup ();
10364
10365             return EXIT_SUCCESS;
10366          }
10367
10368
10369This example program prints:
10370
10371          Command drop started on 127.0.0.1:
10372          { "drop" : "test" }
10373
10374          Command drop succeeded:
10375          { "ns" : "test.test", "nIndexesWas" : 1, "ok" : 1.0 }
10376
10377          Command insert started on 127.0.0.1:
10378          {
10379            "insert" : "test",
10380            "ordered" : true,
10381            "documents" : [
10382              { "_id" : 0 }, { "_id" : 1 }
10383            ]
10384          }
10385
10386          Command insert succeeded:
10387          { "n" : 2, "ok" : 1.0 }
10388
10389          Command insert started on 127.0.0.1:
10390          {
10391            "insert" : "test",
10392            "ordered" : true,
10393            "documents" : [
10394              { "_id" : 0 }
10395            ]
10396          }
10397
10398          Command insert succeeded:
10399          {
10400            "n" : 0,
10401            "writeErrors" : [
10402              { "index" : 0, "code" : 11000, "errmsg" : "duplicate key" }
10403            ],
10404            "ok" : 1.0
10405          }
10406
10407          started: 3
10408          succeeded: 3
10409          failed: 0
10410
10411       The output has been edited and formatted for clarity. Depending on your
10412       server configuration, messages may include metadata like database name,
10413       logical session ids, or cluster times that are not shown here.
10414
10415       The  final  "insert"  command  is  considered  successful,  despite the
10416       writeError, because the server replied  to  the  overall  command  with
10417       "ok": 1.
10418
10419   SDAM Monitoring Example
10420       example-sdam-monitoring.c.INDENT 0.0
10421
10422          /* gcc example-sdam-monitoring.c -o example-sdam-monitoring \
10423           *     $(pkg-config --cflags --libs libmongoc-1.0) */
10424
10425          /* ./example-sdam-monitoring [CONNECTION_STRING] */
10426
10427          #include <mongoc/mongoc.h>
10428          #include <stdio.h>
10429
10430
10431          typedef struct {
10432             int server_changed_events;
10433             int server_opening_events;
10434             int server_closed_events;
10435             int topology_changed_events;
10436             int topology_opening_events;
10437             int topology_closed_events;
10438             int heartbeat_started_events;
10439             int heartbeat_succeeded_events;
10440             int heartbeat_failed_events;
10441          } stats_t;
10442
10443
10444          static void
10445          server_changed (const mongoc_apm_server_changed_t *event)
10446          {
10447             stats_t *context;
10448             const mongoc_server_description_t *prev_sd, *new_sd;
10449
10450             context = (stats_t *) mongoc_apm_server_changed_get_context (event);
10451             context->server_changed_events++;
10452
10453             prev_sd = mongoc_apm_server_changed_get_previous_description (event);
10454             new_sd = mongoc_apm_server_changed_get_new_description (event);
10455
10456             printf ("server changed: %s %s -> %s\n",
10457                     mongoc_apm_server_changed_get_host (event)->host_and_port,
10458                     mongoc_server_description_type (prev_sd),
10459                     mongoc_server_description_type (new_sd));
10460          }
10461
10462
10463          static void
10464          server_opening (const mongoc_apm_server_opening_t *event)
10465          {
10466             stats_t *context;
10467
10468             context = (stats_t *) mongoc_apm_server_opening_get_context (event);
10469             context->server_opening_events++;
10470
10471             printf ("server opening: %s\n",
10472                     mongoc_apm_server_opening_get_host (event)->host_and_port);
10473          }
10474
10475
10476          static void
10477          server_closed (const mongoc_apm_server_closed_t *event)
10478          {
10479             stats_t *context;
10480
10481             context = (stats_t *) mongoc_apm_server_closed_get_context (event);
10482             context->server_closed_events++;
10483
10484             printf ("server closed: %s\n",
10485                     mongoc_apm_server_closed_get_host (event)->host_and_port);
10486          }
10487
10488
10489          static void
10490          topology_changed (const mongoc_apm_topology_changed_t *event)
10491          {
10492             stats_t *context;
10493             const mongoc_topology_description_t *prev_td;
10494             const mongoc_topology_description_t *new_td;
10495             mongoc_server_description_t **prev_sds;
10496             size_t n_prev_sds;
10497             mongoc_server_description_t **new_sds;
10498             size_t n_new_sds;
10499             size_t i;
10500             mongoc_read_prefs_t *prefs;
10501
10502             context = (stats_t *) mongoc_apm_topology_changed_get_context (event);
10503             context->topology_changed_events++;
10504
10505             prev_td = mongoc_apm_topology_changed_get_previous_description (event);
10506             prev_sds = mongoc_topology_description_get_servers (prev_td, &n_prev_sds);
10507             new_td = mongoc_apm_topology_changed_get_new_description (event);
10508             new_sds = mongoc_topology_description_get_servers (new_td, &n_new_sds);
10509
10510             printf ("topology changed: %s -> %s\n",
10511                     mongoc_topology_description_type (prev_td),
10512                     mongoc_topology_description_type (new_td));
10513
10514             if (n_prev_sds) {
10515                printf ("  previous servers:\n");
10516                for (i = 0; i < n_prev_sds; i++) {
10517                   printf ("      %s %s\n",
10518                           mongoc_server_description_type (prev_sds[i]),
10519                           mongoc_server_description_host (prev_sds[i])->host_and_port);
10520                }
10521             }
10522
10523             if (n_new_sds) {
10524                printf ("  new servers:\n");
10525                for (i = 0; i < n_new_sds; i++) {
10526                   printf ("      %s %s\n",
10527                           mongoc_server_description_type (new_sds[i]),
10528                           mongoc_server_description_host (new_sds[i])->host_and_port);
10529                }
10530             }
10531
10532             prefs = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
10533
10534             /* it is safe, and unfortunately necessary, to cast away const here */
10535             if (mongoc_topology_description_has_readable_server (
10536                    (mongoc_topology_description_t *) new_td, prefs)) {
10537                printf ("  secondary AVAILABLE\n");
10538             } else {
10539                printf ("  secondary UNAVAILABLE\n");
10540             }
10541
10542             if (mongoc_topology_description_has_writable_server (
10543                    (mongoc_topology_description_t *) new_td)) {
10544                printf ("  primary AVAILABLE\n");
10545             } else {
10546                printf ("  primary UNAVAILABLE\n");
10547             }
10548
10549             mongoc_read_prefs_destroy (prefs);
10550             mongoc_server_descriptions_destroy_all (prev_sds, n_prev_sds);
10551             mongoc_server_descriptions_destroy_all (new_sds, n_new_sds);
10552          }
10553
10554
10555          static void
10556          topology_opening (const mongoc_apm_topology_opening_t *event)
10557          {
10558             stats_t *context;
10559
10560             context = (stats_t *) mongoc_apm_topology_opening_get_context (event);
10561             context->topology_opening_events++;
10562
10563             printf ("topology opening\n");
10564          }
10565
10566
10567          static void
10568          topology_closed (const mongoc_apm_topology_closed_t *event)
10569          {
10570             stats_t *context;
10571
10572             context = (stats_t *) mongoc_apm_topology_closed_get_context (event);
10573             context->topology_closed_events++;
10574
10575             printf ("topology closed\n");
10576          }
10577
10578
10579          static void
10580          server_heartbeat_started (const mongoc_apm_server_heartbeat_started_t *event)
10581          {
10582             stats_t *context;
10583
10584             context =
10585                (stats_t *) mongoc_apm_server_heartbeat_started_get_context (event);
10586             context->heartbeat_started_events++;
10587
10588             printf ("%s heartbeat started\n",
10589                     mongoc_apm_server_heartbeat_started_get_host (event)->host_and_port);
10590          }
10591
10592
10593          static void
10594          server_heartbeat_succeeded (
10595             const mongoc_apm_server_heartbeat_succeeded_t *event)
10596          {
10597             stats_t *context;
10598             char *reply;
10599
10600             context =
10601                (stats_t *) mongoc_apm_server_heartbeat_succeeded_get_context (event);
10602             context->heartbeat_succeeded_events++;
10603
10604             reply = bson_as_canonical_extended_json (
10605                mongoc_apm_server_heartbeat_succeeded_get_reply (event), NULL);
10606
10607             printf (
10608                "%s heartbeat succeeded: %s\n",
10609                mongoc_apm_server_heartbeat_succeeded_get_host (event)->host_and_port,
10610                reply);
10611
10612             bson_free (reply);
10613          }
10614
10615
10616          static void
10617          server_heartbeat_failed (const mongoc_apm_server_heartbeat_failed_t *event)
10618          {
10619             stats_t *context;
10620             bson_error_t error;
10621
10622             context = (stats_t *) mongoc_apm_server_heartbeat_failed_get_context (event);
10623             context->heartbeat_failed_events++;
10624             mongoc_apm_server_heartbeat_failed_get_error (event, &error);
10625
10626             printf ("%s heartbeat failed: %s\n",
10627                     mongoc_apm_server_heartbeat_failed_get_host (event)->host_and_port,
10628                     error.message);
10629          }
10630
10631
10632          int
10633          main (int argc, char *argv[])
10634          {
10635             mongoc_client_t *client;
10636             mongoc_apm_callbacks_t *cbs;
10637             stats_t stats = {0};
10638             const char *uri_string =
10639                "mongodb://127.0.0.1/?appname=sdam-monitoring-example";
10640             mongoc_uri_t *uri;
10641             bson_t cmd = BSON_INITIALIZER;
10642             bson_t reply;
10643             bson_error_t error;
10644
10645             mongoc_init ();
10646
10647             if (argc > 1) {
10648                uri_string = argv[1];
10649             }
10650
10651             uri = mongoc_uri_new_with_error (uri_string, &error);
10652             if (!uri) {
10653                fprintf (stderr,
10654                         "failed to parse URI: %s\n"
10655                         "error message:       %s\n",
10656                         uri_string,
10657                         error.message);
10658                return EXIT_FAILURE;
10659             }
10660
10661             client = mongoc_client_new_from_uri (uri);
10662             if (!client) {
10663                return EXIT_FAILURE;
10664             }
10665
10666             mongoc_client_set_error_api (client, 2);
10667             cbs = mongoc_apm_callbacks_new ();
10668             mongoc_apm_set_server_changed_cb (cbs, server_changed);
10669             mongoc_apm_set_server_opening_cb (cbs, server_opening);
10670             mongoc_apm_set_server_closed_cb (cbs, server_closed);
10671             mongoc_apm_set_topology_changed_cb (cbs, topology_changed);
10672             mongoc_apm_set_topology_opening_cb (cbs, topology_opening);
10673             mongoc_apm_set_topology_closed_cb (cbs, topology_closed);
10674             mongoc_apm_set_server_heartbeat_started_cb (cbs, server_heartbeat_started);
10675             mongoc_apm_set_server_heartbeat_succeeded_cb (cbs,
10676                                                           server_heartbeat_succeeded);
10677             mongoc_apm_set_server_heartbeat_failed_cb (cbs, server_heartbeat_failed);
10678             mongoc_client_set_apm_callbacks (
10679                client, cbs, (void *) &stats /* context pointer */);
10680
10681             /* the driver connects on demand to perform first operation */
10682             BSON_APPEND_INT32 (&cmd, "buildinfo", 1);
10683             mongoc_client_command_simple (client, "admin", &cmd, NULL, &reply, &error);
10684             mongoc_uri_destroy (uri);
10685             mongoc_client_destroy (client);
10686
10687             printf ("Events:\n"
10688                     "   server changed: %d\n"
10689                     "   server opening: %d\n"
10690                     "   server closed: %d\n"
10691                     "   topology changed: %d\n"
10692                     "   topology opening: %d\n"
10693                     "   topology closed: %d\n"
10694                     "   heartbeat started: %d\n"
10695                     "   heartbeat succeeded: %d\n"
10696                     "   heartbeat failed: %d\n",
10697                     stats.server_changed_events,
10698                     stats.server_opening_events,
10699                     stats.server_closed_events,
10700                     stats.topology_changed_events,
10701                     stats.topology_opening_events,
10702                     stats.topology_closed_events,
10703                     stats.heartbeat_started_events,
10704                     stats.heartbeat_succeeded_events,
10705                     stats.heartbeat_failed_events);
10706
10707             bson_destroy (&cmd);
10708             bson_destroy (&reply);
10709             mongoc_apm_callbacks_destroy (cbs);
10710
10711             mongoc_cleanup ();
10712
10713             return EXIT_SUCCESS;
10714          }
10715
10716
10717Start  a 3-node replica set on localhost with set name "rs" and start the pro‐
10718gram:
10719
10720          ./example-sdam-monitoring "mongodb://localhost:27017,localhost:27018/?replicaSet=rs"
10721
10722       This example program prints something like:
10723
10724          topology opening
10725          topology changed: Unknown -> ReplicaSetNoPrimary
10726            secondary UNAVAILABLE
10727            primary UNAVAILABLE
10728          server opening: localhost:27017
10729          server opening: localhost:27018
10730          localhost:27017 heartbeat started
10731          localhost:27018 heartbeat started
10732          localhost:27017 heartbeat succeeded: { ... reply ... }
10733          server changed: localhost:27017 Unknown -> RSPrimary
10734          server opening: localhost:27019
10735          topology changed: ReplicaSetNoPrimary -> ReplicaSetWithPrimary
10736            new servers:
10737                RSPrimary localhost:27017
10738            secondary UNAVAILABLE
10739            primary AVAILABLE
10740          localhost:27019 heartbeat started
10741          localhost:27018 heartbeat succeeded: { ... reply ... }
10742          server changed: localhost:27018 Unknown -> RSSecondary
10743          topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
10744            previous servers:
10745                RSPrimary localhost:27017
10746            new servers:
10747                RSPrimary localhost:27017
10748                RSSecondary localhost:27018
10749            secondary AVAILABLE
10750            primary AVAILABLE
10751          localhost:27019 heartbeat succeeded: { ... reply ... }
10752          server changed: localhost:27019 Unknown -> RSSecondary
10753          topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
10754            previous servers:
10755                RSPrimary localhost:27017
10756                RSSecondary localhost:27018
10757            new servers:
10758                RSPrimary localhost:27017
10759                RSSecondary localhost:27018
10760                RSSecondary localhost:27019
10761            secondary AVAILABLE
10762            primary AVAILABLE
10763          topology closed
10764
10765          Events:
10766             server changed: 3
10767             server opening: 3
10768             server closed: 0
10769             topology changed: 4
10770             topology opening: 1
10771             topology closed: 1
10772             heartbeat started: 3
10773             heartbeat succeeded: 3
10774             heartbeat failed: 0
10775
10776       The driver connects to the mongods on ports 27017 and 27018, which were
10777       specified  in the URI, and determines which is primary. It also discov‐
10778       ers the third member, "localhost:27019", and adds it to the topology.
10779

AUTHOR

10781       MongoDB, Inc
10782
10784       2017-present, MongoDB, Inc
10785
10786
10787
10788
107891.16.2                           Feb 25, 2020              MONGOC_REFERENCE(3)
Impressum