1MONGOC_REFERENCE(3)                libmongoc               MONGOC_REFERENCE(3)
2
3
4

LIBMONGOC

6       A Cross Platform MongoDB Client Library for C
7
8   Introduction
9       The MongoDB C Driver, also known as "libmongoc", is a library for using
10       MongoDB from  C  applications,  and  for  writing  MongoDB  drivers  in
11       higher-level languages.
12
13       It  depends on libbson to generate and parse BSON documents, the native
14       data format of MongoDB.
15
16   Tutorials
17       This section contains tutorials on how to get started with  the  basics
18       of using the C driver.
19
20   Obtaining the MongoDB C Driver Libraries
21       There are a few methods of obtaining the mongo-c-driver codebase:
22
23   Building the C Driver Libraries from Source
24       This page details how to download, unpack, configure, and build libbson
25       and libmongoc from their original source-code form.
26
27       Extra information
28
29       Dropdowns (like this one) contain extra information and explanatory de‐
30       tails  that are not required to complete the tutorial, but may be help‐
31       ful for curious readers, and more advanced users that want an  explana‐
32       tion of the meaning of certain tutorial steps.
33
34       The  following  page  uses a few named "variables" that you must decide
35       up-front.  When you see such a value referrenced in  a  tutorial  step,
36       you should substitute the value into that step.
37
38       SEE ALSO:
39          Before  building,  you  may  want to check that you are running on a
40          supported platform. For the list of supported  platforms,  refer  to
41          the mongo-c-driver Platform Support page.
42
43   Choose a Version
44       Before  we begin, know what version of mongo-c-driver you will be down‐
45       loading.  A list of available versions  can  be  found  on  the  GitHub
46       repository  tags page. (The current version written for this documenta‐
47       tion is 1.25.1.)
48
49       For the remainder of this page, $VERSION will refer to the version num‐
50       ber of mongo-c-driver that you will be building for this tutorial.
51
52   Obtaining the Source
53       There   are   two   primary   recommended   methods  of  obtaining  the
54       mongo-c-driver source code:
55
56       1. Clone the repository using git (recommended).  (See below)
57
58       2. Download a source archive at a specific version.  (See below)
59
60       IMPORTANT:
61          It is highly recommended that new users use a stable  released  ver‐
62          sion  of the driver, rather than building from a development branch.
63          When you git clone or download an archive of the repository, be sure
64          to specify a release tag (e.g. with Git's --branch argument).
65
66   Downloading Using Git
67       Using  Git,  the  C driver repository can be cloned from the GitHub URL
68       https://github.com/mongodb/mongo-c-driver.git. Git  tags  for  released
69       versions  are  named  after the version for which they correspond (e.g.
70       "1.25.1"). To clone the repository using the command line, the  follow‐
71       ing command may be used:
72
73          $ git clone https://github.com/mongodb/mongo-c-driver.git --branch="$VERSION" "$SOURCE"
74
75       TIP:
76          Despite  the name, git-clone's --branch argument may also be used to
77          clone from repository tags.
78
79   Downloading a Release Archive
80       An archived snapshot of the repository can be obtained from the  GitHub
81       Releases  Page. The mongo-c-driver-x.y.z.tar.gz archive attached to any
82       release contains the minimal set of files  that  you'll  need  for  the
83       build.
84
85       Using wget + tar
86
87          ## Download using wget:
88          $ wget "https://github.com/mongodb/mongo-c-driver/archive/refs/tags/$VERSION.tar.gz" \
89              --output-document="mongo-c-driver-$VERSION.tar.gz"
90          ## Extract using tar:
91          $ tar xf "mongo-c-driver-$VERSION.tar.gz"
92
93       Using curl + tar
94
95          ## Using curl:
96          $ curl "https://github.com/mongodb/mongo-c-driver/archive/refs/tags/$VERSION.tar.gz" \
97              --output="mongo-c-driver-$VERSION.tar.gz"
98          ## Extract using tar:
99          $ tar xf "mongo-c-driver-$VERSION.tar.gz"
100
101       PowerShell
102
103          ## Use Invoke-WebRequest:
104          PS> $url = "https://github.com/mongodb/mongo-c-driver/archive/refs/tags/$VERSION.zip"
105          PS> $file = "mongo-c-driver-$VERSION.zip"
106          PS> Invoke-WebRequest -UseBasicParsing -Uri $url -OutFile $file
107          ## Extract using Expand-Archive:
108          PS> Expand-Archive mongo-c-driver-$VERSION.zip
109
110       The  above commands will create a new directory mongo-c-driver-$VERSION
111       within the directory in which you ran  the  tar/Expand-Archive  command
112       (note:  PowerShell  will create an additional intermediate subdirectory
113       of the same name). This directory is the root of the driver source tree
114       (which  we  refer to as $SOURCE in these documents). The $SOURCE direc‐
115       tory should contain the top-level CMakeLists.txt file.
116
117   Obtaining Prerequisites
118       In order to build the project, a few prerequisites need  to  be  avail‐
119       able.
120
121       Both libmongoc and libbson projects use CMake for build configuration.
122
123       NOTE:
124          It  is  highly  recommended -- but not required -- that you download
125          the latest stable CMake available for your platform.
126
127       Getting the Latest CMake
128
129       A new stable release of CMake can be obtained from the CMake  downloads
130       page.
131
132       For  Windows  and  macOS,  simply download the CMake .msi/.dmg (not the
133       .zip/.tar.gz) and use it to install CMake.
134
135       On Linux, download the self-extracting shell script (ending  with  .sh)
136       and  execute it using the sh utility, passing the appropriate arguments
137       to perform the install. For example,  with  the  CMake  3.27.0  on  the
138       x86_64   platform,   the   following   command   can  be  used  on  the
139       cmake-3.27.0-linux-x86_64.sh script:
140
141          $ sh cmake-3.27.0-linux-x86_64.sh --prefix="$HOME/.local" --exclude-subdir --skip-license
142
143       Assuming that $HOME/.local/bin is on your $PATH list, the cmake command
144       for 3.27.0 will then become available.
145
146       The  --help  option can be passed to the shell script for more informa‐
147       tion.
148
149       For the remainder of this page, it will be assumed that cmake is avail‐
150       able as a command on your PATH environment variable and can be executed
151       as "cmake" from a shell. You can test this by requesting the  --version
152       from CMake from the command line:
153
154          $ cmake --version
155          cmake version 3.21.4
156
157          CMake suite maintained and supported by Kitware (kitware.com/cmake).
158
159       NOTE:
160          If  you  intend  to build libbson only, then CMake is sufficient for
161          the build. Additional C driver features may require  additional  ex‐
162          ternal  dependencies  be installed, but we will not worry about them
163          here.
164
165   Configuring for libbson
166       IMPORTANT:
167          If you are building with Xcode [1] or Visual  Studio  [2],  you  may
168          need to execute CMake from within a special environment in which the
169          respective toolchain is available.
170
171       Let the name $BUILD be the path $SOURCE/_build. This will be the direc‐
172       tory where our built files will be written by CMake.
173
174       With  the  source directory for mongo-c-driver at $SOURCE and build di‐
175       rectory $BUILD, the following command  can  be  executed  from  a  com‐
176       mand-line to configure the project with both libbson and libmongoc:
177
178          $ cmake -S $SOURCE -B $BUILD \
179            -D ENABLE_EXTRA_ALIGNMENT=OFF \
180            -D ENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF \
181            -D CMAKE_BUILD_TYPE=RelWithDebInfo \
182            -D BUILD_VERSION="$VERSION" \
183            -D ENABLE_MONGOC=OFF
184
185       If all dependencies are satisfied, the above command should succeed and
186       end with:
187
188          $ cmake …
189          ## … (Lines of output) …
190          -- Generating done
191          -- Build files have been written to: $BUILD
192
193       If configuration failed with an error, refer to the  CMake  output  for
194       error  messages and information. Ensure that configuration succeeds be‐
195       fore proceeding.
196
197       What do these CMake arguments mean?
198
199       The BUILD_VERSION sets the version number that will be included in  the
200       build  results.  This should be set to the same value as the version of
201       the source driver that was downloaded in Obtaining the Source.
202
203       The ENABLE_EXTRA_ALIGNMENT  and  ENABLE_AUTOMATIC_INIT_AND_CLEANUP  are
204       part  of mongo-c-driver, and correspond to deprecated features that are
205       only enabled by default for ABI compatibility purposes.  It  is  highly
206       recommended to disable these features whenever possible.
207
208       The ENABLE_MONGOC=OFF argument disabled building libmongoc. We'll build
209       that in the next section.
210
211       The CMAKE_BUILD_TYPE setting tells CMake what variant of code  will  be
212       generated.  In  the  case of RelWithDebInfo, optimized binaries will be
213       produced, but still include debug information. The CMAKE_BUILD_TYPE has
214       no  effect  on  Multi-Config generators (i.e. Visual Studio), which in‐
215       stead rely on the --config option when building/installing.
216
217   Building the Project
218       After successfully configuring the project, the build can  be  executed
219       by using CMake:
220
221          $ cmake --build $BUILD --config RelWithDebInfo --parallel
222
223       If  configured  properly  and  all dependencies are satisfied, then the
224       above command should proceed to compile and link the configured  compo‐
225       nents.  If  the above command fails, then there is likely an error with
226       your environment, or you are using  an  unsupported/untested  platform.
227       Refer to the build tool output for more information.
228
229       The --config option
230
231       The  --config  option  is used to set the build configuration to use in
232       the case of Multi-Config generators (i.e. Visual Studio). It has no ef‐
233       fect on other generators, which instead use CMAKE_BUILD_TYPE.
234
235   Installing the Built Results
236       Let  $PREFIX  be the path $SOURCE/_install. We can use CMake to install
237       the built results:
238
239          $ cmake --install "$BUILD" --prefix "$PREFIX" --config RelWithDebInfo
240
241       This command will install the mongo-c-driver  build  results  into  the
242       $PREFIX directory.
243
244       The --config option
245
246       The --config option is only used for Multi-Config generators (i.e. Vis‐
247       ual Studio) and is otherwise ignored. The value given for --config must
248       be the same as was given for --config with cmake --build.
249
250       SEE ALSO:
251          The  above  snippet simply installs mongo-c-driver in a subdirectory
252          of the source directory itself, but this is not a  normal  workflow.
253          Once   you   feel   compfortable   about  configuring  and  building
254          mongo-c-driver, the page  How  to:  Install  libbson/libmongoc  from
255          Source will do a deeper dive on from-source installation options.
256
257   Configuring with libmongoc
258       If  you followed the above steps starting from Configuring for libbson,
259       your final result with only contain libbson and not the full C database
260       driver library. Building of libmongoc is enabled/disabled using the EN‐
261       ABLE_MONGOC CMake variable. Re-run CMake again, but  set  ENABLE_MONGOC
262       to TRUE:
263
264          $ cmake -D ENABLE_MONGOC=ON $BUILD
265
266       If  the  above command succeeds, then the project has been reconfigured
267       to build with libmongoc. Follow the process at Building the Project and
268       Installing the Built Results again to build and install libmongoc.
269

FOOTNOTES

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

AUTHOR

11757       MongoDB, Inc
11758
11760       2017-present, MongoDB, Inc
11761
11762
11763
11764
117651.25.1                           Nov 08, 2023              MONGOC_REFERENCE(3)
Impressum