1MONGOC_REFERENCE(3)            MongoDB C Driver            MONGOC_REFERENCE(3)
2
3
4

NAME

6       mongoc_reference - Index
7

MONGODB C DRIVER

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

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

AUTHOR

9434       MongoDB, Inc
9435
9437       2017-present, MongoDB, Inc
9438
9439
9440
9441
94421.15.2                           Nov 06, 2019              MONGOC_REFERENCE(3)
Impressum