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

AUTHOR

9386       MongoDB, Inc
9387
9389       2017-present, MongoDB, Inc
9390
9391
9392
9393
93941.14.0                           Feb 22, 2019              MONGOC_REFERENCE(3)
Impressum