Provided by: libmongoc-doc_2.2.0-1_all bug

LIBMONGOC - API

       A Cross Platform MongoDB Client Library for C

       This  site  documents  the  API. For tutorials, guides, and explainers, see MongoDB C Driver <https://www
       .mongodb.com/docs/languages/c/c-driver/current/>.

   Introduction
       The MongoDB C Driver, also known as "libmongoc", is a library for using MongoDB from C applications,  and
       for writing MongoDB drivers in higher-level languages.

       It  depends  on  libbson  <https://www.mongoc.org/libbson/current/index.html>  to generate and parse BSON
       documents, the native data format of MongoDB.

   API Reference
   Initialization and cleanup
   Synopsis
       Initialize the MongoDB C Driver by calling mongoc_init()  <>  exactly  once  at  the  beginning  of  your
       program.  It  is  responsible  for initializing global state such as process counters, SSL, and threading
       primitives.

       Exception to this is mongoc_log_set_handler(), which should be called before mongoc_init()  or  some  log
       traces  would  not  use  your log handling function. See Custom Log Handlers <#custom-log-handlers> for a
       detailed example.

       Call mongoc_cleanup() <> exactly once at the end  of  your  program  to  release  all  memory  and  other
       resources  allocated  by  the  driver.  You  must  not  call  any  other MongoDB C Driver functions after
       mongoc_cleanup() <>. Note that mongoc_init() <> does not reinitialize the driver  after  mongoc_cleanup()
       <>.

       Changed  in  version 2.0.0: Versions prior to 2.0.0 supported a non-portable automatic initialization and
       cleanup with the CMake option ENABLE_AUTOMATIC_INIT_AND_CLEANUP. This was removed in 2.0.0.  Ensure  your
       application call mongoc_init() <> and mongoc_cleanup() <>.

   Logging
       The MongoDB C driver has two different types of logging available:

       • The  original  mongoc_log  facility  supports  freeform  string messages that originate from the driver
         itself or from application code. This has been retroactively termed "unstructured logging".

       • A new mongoc_structured_log facility reports messages from  the  driver  itself  using  a  BSON  format
         defined  across  driver  implementations  by  the MongoDB Logging Specification <https://specifications
         .readthedocs.io/en/latest/logging/logging/>.

       These two systems are configured and used independently.

   Unstructured Logging
       This is the original logging facility that supports freeform string messages originating from the  driver
       itself  or  from  application  code.  This  has  been  retroactively  termed "unstructured logging".  See
       Structured Logging <> for the newer standardized logging facility.

          typedef enum {
             MONGOC_LOG_LEVEL_ERROR,
             MONGOC_LOG_LEVEL_CRITICAL,
             MONGOC_LOG_LEVEL_WARNING,
             MONGOC_LOG_LEVEL_MESSAGE,
             MONGOC_LOG_LEVEL_INFO,
             MONGOC_LOG_LEVEL_DEBUG,
             MONGOC_LOG_LEVEL_TRACE,
          } mongoc_log_level_t;

          #define MONGOC_ERROR(...)
          #define MONGOC_CRITICAL(...)
          #define MONGOC_WARNING(...)
          #define MONGOC_MESSAGE(...)
          #define MONGOC_INFO(...)
          #define MONGOC_DEBUG(...)

          typedef void (*mongoc_log_func_t) (mongoc_log_level_t log_level,
                                             const char *log_domain,
                                             const char *message,
                                             void *user_data);

          void
          mongoc_log_set_handler (mongoc_log_func_t log_func, void *user_data);
          void
          mongoc_log (mongoc_log_level_t log_level,
                      const char *log_domain,
                      const char *format,
                      ...);
          const char *
          mongoc_log_level_str (mongoc_log_level_t log_level);
          void
          mongoc_log_default_handler (mongoc_log_level_t log_level,
                                      const char *log_domain,
                                      const char *message,
                                      void *user_data);
          void
          mongoc_log_trace_enable (void);
          void
          mongoc_log_trace_disable (void);

       This abstraction can be used for logging in your application, or you can integrate  the  driver  with  an
       existing logging system.

   Macros
       To make logging a little less painful, various helper macros are provided. See the following example.

          #undef MONGOC_LOG_DOMAIN
          #define MONGOC_LOG_DOMAIN "my-custom-domain"

          MONGOC_WARNING ("An error occurred: %s", strerror (errno));

   Custom Log Handlers
       The  default  log  handler  prints  a timestamp and the log message to stdout, or to stderr for warnings,
       critical messages, and errors.  You can override the handler with mongoc_log_set_handler().  Your handler
       function is called in a mutex for thread safety.

       For example, you could register a custom handler to suppress messages at INFO level and below:

          void
          my_logger (mongoc_log_level_t log_level,
                     const char *log_domain,
                     const char *message,
                     void *user_data)
          {
             /* smaller values are more important */
             if (log_level < MONGOC_LOG_LEVEL_INFO) {
                mongoc_log_default_handler (log_level, log_domain, message, user_data);
             }
          }

          int
          main (int argc, char *argv[])
          {
             mongoc_log_set_handler (my_logger, NULL);
             mongoc_init ();

             /* ... your code ...  */

             mongoc_cleanup ();
             return 0;
          }

       Note that in the example above mongoc_log_set_handler() is called before mongoc_init().  Otherwise,  some
       log traces could not be processed by the log handler.

       To restore the default handler:

          mongoc_log_set_handler (mongoc_log_default_handler, NULL);

   Disable logging
       To disable all logging, including warnings, critical messages and errors, provide an empty log handler:

          mongoc_log_set_handler (NULL, NULL);

   Tracing
       If  compiling  your  own  copy  of the MongoDB C driver, consider configuring with -DENABLE_TRACING=ON to
       enable function tracing and hex dumps of network packets to STDERR  and  STDOUT  during  development  and
       debugging.

       This is especially useful when debugging what may be going on internally in the driver.

       Trace    messages    can   be   enabled   and   disabled   by   calling   mongoc_log_trace_enable()   and
       mongoc_log_trace_disable()

       Note:
          Compiling the driver with -DENABLE_TRACING=ON will affect  its  performance.  Disabling  tracing  with
          mongoc_log_trace_disable() significantly reduces the overhead, but cannot remove it completely.

   Structured Logging
       This  document  describes  a  newer  "structured" logging facility which reports messages from the driver
       itself using a BSON format defined across driver implementations by  the  MongoDB  Logging  Specification
       <https://specifications.readthedocs.io/en/latest/logging/logging/>.   See Unstructured Logging <> for the
       original freeform logging facility.

       These two systems are configured and used independently.

       Unstructured logging is global to the entire process, but structured logging is configured separately for
       each mongoc_client_t <> or mongoc_client_pool_t <>.  See mongoc_client_set_structured_log_opts()  <>  and
       mongoc_client_pool_set_structured_log_opts() <>.

   Options
       Structured log settings are tracked explicitly by a mongoc_structured_log_opts_t <> instance.

       Like other drivers supporting structured logging, we take default settings from environment variables and
       offer  additional  optional  programmatic  configuration.   Environment  variables  are  captured  during
       mongoc_structured_log_opts_new() <>, refer there for a full list of the supported variables.

       Normally environment variables provide defaults that can be overridden programmatically.  To request  the
       opposite  behavior,  where  your  programmatic  defaults  can  be  overridden  by  the  environment,  see
       mongoc_structured_log_opts_set_max_levels_from_env() <>.

       Structured log messages may be filtered in arbitrary ways by the  handler,  but  as  both  a  performance
       optimization  and a convenience, a built-in filter limits the maximum log level of reported messages with
       a per-component setting.

   mongoc_structured_log_opts_t
   Synopsis
          typedef struct mongoc_structured_log_opts_t mongoc_structured_log_opts_t;

       mongoc_structured_log_opts_t is  an  opaque  type  that  contains  options  for  the  structured  logging
       subsystem: per-component log levels, a maximum logged document length, and a handler function.

       Create  a  mongoc_structured_log_opts_t  with  mongoc_structured_log_opts_new()  <>,  set  options  and a
       callback    on    it,    then    pass    it    to    mongoc_client_set_structured_log_opts()    <>     or
       mongoc_client_pool_set_structured_log_opts()      <>.       Must      be     destroyed     by     calling
       mongoc_structured_log_opts_destroy() <>.

   Functions
   mongoc_structured_log_opts_new()
   Synopsis
          mongoc_structured_log_opts_t *
          mongoc_structured_log_opts_new (void);

       Creates  a  new  mongoc_structured_log_opts_t  <>,  filled  with  defaults  captured  from  the   current
       environment.

       Sets a default log handler which would write a text representation of each log message to stderr, stdout,
       or  another  file configurable using MONGODB_LOG_PATH.  This setting has no effect if the default handler
       is replaced using mongoc_structured_log_opts_set_handler() <>.

       Environment variable errors are non-fatal, and result in one-time warnings delivered as  an  unstructured
       log.

       Per-component maximum levels are initialized equivalently to:

          mongoc_structured_log_opts_set_max_level_for_all_components(opts, MONGOC_STRUCTURED_LOG_LEVEL_WARNING);
          mongoc_structured_log_opts_set_max_levels_from_env(opts);

   Environment Variables
       This is a full list of the captured environment variables.

       • MONGODB_LOG_MAX_DOCUMENT_LENGTH:  Maximum length for JSON-serialized documents that appear within a log
         message.   It  may  be  a  number,  in  bytes,  or  unlimited   (case   insensitive)   to   choose   an
         implementation-specific  value  near  the  maximum representable length.  By default, the limit is 1000
         bytes.  This limit affects interior documents like commands and replies, not  the  total  length  of  a
         structured log message.

       • MONGODB_LOG_PATH:  A  file  path  or  one  of  the  special strings stderr or stdout (case insensitive)
         specifying the destination for structured logs seen by the default handler.  By default, it  writes  to
         stderr.   This  path  will  be  captured  during  mongoc_structured_log_opts_new(),  but  it  will  not
         immediately be opened.  If the file can't be opened, a warning is then written to the unstructured  log
         and the handler writes structured logs to stderr instead.

         Warning:
            When  a  file path is given for MONGODB_LOG_PATH, each log instance (one stand-alone client or pool)
            will separately open this file for append.  The results are operating system specific. On  UNIX-like
            platforms each instance's output will be interleaved, in most cases without splitting individual log
            messages.  Notably  on  Windows  the file will be opened in exclusive mode by the first instance and
            subsequent instances will fail, falling back on  the  default  of  stderr.   Applications  that  use
            multiple  processes or multiple client pools will likely want to supply a log handler that annotates
            each message with information about its originating log instance.

       • MONGODB_LOG_COMMAND:     A     log     level     name     to     set     as     the     maximum     for
         MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND.

       • MONGODB_LOG_TOPOLOGY:     A     log     level     name     to     set     as     the     maximum    for
         MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY.

       • MONGODB_LOG_SERVER_SELECTION:    A    log    level    name    to    set    as    the    maximum     for
         MONGOC_STRUCTURED_LOG_COMPONENT_SERVER_SELECTION.

       • MONGODB_LOG_CONNECTION:     A     log     level     name     to     set     as    the    maximum    for
         MONGOC_STRUCTURED_LOG_COMPONENT_CONNECTION.

       • MONGODB_LOG_ALL: A log level name applied to all components not otherwise specified.

       Note that log level names are always case  insensitive.   This  is  a  full  list  of  recognized  names,
       including allowed aliases:

       • emergency, offalertcriticalerrorwarning, warnnoticeinformational, infodebugtrace

   Returns
       A newly allocated mongoc_structured_log_opts_t <>.

   mongoc_structured_log_opts_destroy()
   Synopsis
          void
          mongoc_structured_log_opts_destroy (mongoc_structured_log_opts_t *opts);

   Parametersopts:  Pointer to a mongoc_structured_log_opts_t <> allocated with mongoc_structured_log_opts_new() <>,
         or NULL.

   Description
       This function releases all resources associated with a mongoc_structured_log_opts_t <>.  Does nothing  if
       opts is NULL.

   mongoc_structured_log_opts_set_handler()
   Synopsis
          void
          mongoc_structured_log_opts_set_handler (mongoc_structured_log_opts_t *opts,
                                                  mongoc_structured_log_func_t log_func,
                                                  void *user_data);

       Sets the function to be called to handle structured log messages, as a mongoc_structured_log_func_t <>.

       The callback is given a mongoc_structured_log_entry_t <> as a handle for obtaining additional information
       about  the  log  message.   This  entry  pointer is only valid during a callback, because it's a low cost
       reference to temporary data.

       Structured log handlers must be thread-safe if they will be used with mongoc_client_pool_t <>.   Handlers
       must avoid unbounded recursion, preferably by avoiding the use of any libmongoc client or pool which uses
       the same handler.

       This function always replaces the default log handler from mongoc_structured_log_opts_new() <>, if it was
       still set.  If the log_func is set to NULL, structured logging will be disabled.

   Parametersopts: Structured log options, allocated with mongoc_structured_log_opts_new() <>.

       • log_func:  The  handler  to  install,  a mongoc_structured_log_func_t <>, or NULL to disable structured
         logging.

       • user_data: Optional user data, passed on to the handler.

       See also:
          Structured Logging <>

   mongoc_structured_log_opts_set_max_level_for_component()
   Synopsis
          bool
          mongoc_structured_log_opts_set_max_level_for_component (mongoc_structured_log_opts_t *opts,
                                                                  mongoc_structured_log_component_t component,
                                                                  mongoc_structured_log_level_t level);

       Sets the maximum log level per-component.  Only log messages at or below  this  severity  level  will  be
       passed to mongoc_structured_log_func_t <>.

       By    default,    each    component's   log   level   may   come   from   environment   variables.    See
       mongoc_structured_log_opts_set_max_levels_from_env() <>.

   Parametersopts: Structured log options, allocated with mongoc_structured_log_opts_new() <>.

       • component: The component to set a max log level. for, as a mongoc_structured_log_component_t <>.

       • level: The new max log level for this component, as a mongoc_structured_log_level_t <>.

   Returns
       Returns true on success, or false if the supplied parameters were incorrect.

       See also:
          Structured Logging <>

   mongoc_structured_log_opts_set_max_level_for_all_components()
   Synopsis
          bool
          mongoc_structured_log_opts_set_max_level_for_all_components (mongoc_structured_log_opts_t *opts,
                                                                       mongoc_structured_log_level_t level);

       Sets all per-component maximum log levels to the same value.  Only log messages at or below this severity
       level will be passed to mongoc_structured_log_func_t <>.  Effective even for logging components not known
       at compile-time.

   Parametersopts: Structured log options, allocated with mongoc_structured_log_opts_new() <>.

       • level: The max log level for all components, as a mongoc_structured_log_level_t <>.

   Returns
       Returns true on success, or false if the supplied parameters were incorrect.

       See also:
          Structured Logging <>

   mongoc_structured_log_opts_set_max_levels_from_env()
   Synopsis
          bool
          mongoc_structured_log_opts_set_max_levels_from_env (mongoc_structured_log_opts_t *opts);

       Sets any maximum log levels requested by  environment  variables:  MONGODB_LOG_ALL  for  all  components,
       followed  by  per-component log levels MONGODB_LOG_COMMAND, MONGODB_LOG_CONNECTION, MONGODB_LOG_TOPOLOGY,
       and MONGODB_LOG_SERVER_SELECTION.

       Expects the value to be recognizable by mongoc_structured_log_get_named_level()  <>.   Parse  errors  may
       cause a warning message, delivered via unstructured logging.

       Component levels with no valid environment variable setting will be left unmodified.

       This happens automatically when mongoc_structured_log_opts_new() <> establishes defaults.  Any subsequent
       programmatic  modifications to the mongoc_structured_log_opts_t <> will override the environment variable
       settings.  For applications that desire the opposite behavior, where environment variables  may  override
       programmatic  settings,  they may call mongoc_structured_log_opts_set_max_levels_from_env() after calling
       mongoc_structured_log_opts_set_max_level_for_component()                      <>                      and
       mongoc_structured_log_opts_set_max_level_for_all_components()  <>.   This  will process the environment a
       second time, allowing it to override customized defaults.

   Returns
       Returns true on success.  If warnings are encountered in the  environment,  returns  false  and  may  log
       additional  information  to the unstructured logging facility.  Note that, by design, these errors are by
       default non-fatal.  When mongoc_structured_log_opts_new() <> internally calls this function,  it  ignores
       the return value.

       See also:
          Structured Logging <>

   mongoc_structured_log_opts_get_max_level_for_component()
   Synopsis
          mongoc_structured_log_level_t
          mongoc_structured_log_opts_get_max_level_for_component (const mongoc_structured_log_opts_t *opts,
                                                                  mongoc_structured_log_component_t component);

   Parametersopts: Structured log options, allocated with mongoc_structured_log_opts_new() <>.

       • component: Log component as a mongoc_structured_log_component_t <>.

   Returns
       Returns the configured maximum log level for a specific component, as a mongoc_structured_log_level_t <>.
       This  may  be  the  last  value  set  with mongoc_structured_log_opts_set_max_level_for_component() <> or
       mongoc_structured_log_opts_set_max_level_for_all_components() <>, or it may be the default obtained  from
       environment variables.  If an invalid or unknown component enum is given, returns the lowest log level.

       See also:
          Structured Logging <>

   mongoc_structured_log_opts_set_max_document_length()
   Synopsis
          bool
          mongoc_structured_log_opts_set_max_document_length (mongoc_structured_log_opts_t *opts,
                                                              size_t max_document_length);

       Sets  a maximum length for BSON documents that appear serialized in JSON form as part of a structured log
       message.

       Serialized JSON will be truncated at  this  limit,  interpreted  as  a  count  of  UTF-8  encoded  bytes.
       Truncation  will  be indicated with a ... suffix, the length of which is not included in the max document
       length. If truncation at the exact indicated length would  split  a  valid  UTF-8  sequence,  we  instead
       truncate the document earlier at the nearest boundary between code points.

   Parametersopts: Structured log options, allocated with mongoc_structured_log_opts_new() <>.

       • max_document_length:  Maximum  length  for  each  embedded  JSON  document,  in bytes, not including an
         ellipsis (...) added to indicate truncation. Values near or above INT_MAX will be rejected.

   Returns
       Returns true on success, or false if the supplied maximum length is too large.

       See also:
          Structured Logging <>
          mongoc_structured_log_opts_set_max_document_length_from_env() <>

   mongoc_structured_log_opts_set_max_document_length_from_env()
   Synopsis
          bool
          mongoc_structured_log_opts_set_max_document_length_from_env (mongoc_structured_log_opts_t *opts);

       Sets a maximum document length from the MONGODB_LOG_MAX_DOCUMENT_LENGTH environment variable, if a  valid
       setting is found.  See mongoc_structured_log_opts_new() <> for a description of the supported environment
       variable formats.

       Parse errors may cause a warning message, delivered via unstructured logging.

       This happens automatically when mongoc_structured_log_opts_new() <> establishes defaults.  Any subsequent
       programmatic  modifications to the mongoc_structured_log_opts_t <> will override the environment variable
       settings.  For applications that desire the opposite behavior, where environment variables  may  override
       programmatic  settings, they may call mongoc_structured_log_opts_set_max_document_length_from_env() after
       calling mongoc_structured_log_opts_set_max_document_length() <>.  This will  process  the  environment  a
       second time, allowing it to override customized defaults.

   Returns
       Returns  true  on  success:  either a valid environment setting was found, or the value is unset and opts
       will not be modified.  If warnings are  encountered  in  the  environment,  returns  false  and  may  log
       additional  information  to the unstructured logging facility.  Note that, by design, these errors are by
       default non-fatal.  When mongoc_structured_log_opts_new() <> internally calls this function,  it  ignores
       the return value.

       See also:
          Structured Logging <>

   mongoc_structured_log_opts_get_max_document_length()
   Synopsis
          size_t
          mongoc_structured_log_opts_get_max_document_length (const mongoc_structured_log_opts_t *opts);

   Parametersopts: Structured log options, allocated with mongoc_structured_log_opts_new() <>.

   Returns
       Returns the current maximum document length set in opts, as a size_t.

       See also:
          Structured Logging <>

       See also:
          Structured Logging <>

   Levels and Components
       Log     levels    and    components    are    defined    as    mongoc_structured_log_level_t    <>    and
       mongoc_structured_log_component_t <> enumerations. Utilities are provided to convert between these values
       and their standard string representations. The string values are case-insensitive.

          typedef enum {
            MONGOC_STRUCTURED_LOG_LEVEL_EMERGENCY = 0,  // "Emergency" ("off" also accepted)
            MONGOC_STRUCTURED_LOG_LEVEL_ALERT = 1,      // "Alert"
            MONGOC_STRUCTURED_LOG_LEVEL_CRITICAL = 2,   // "Critical"
            MONGOC_STRUCTURED_LOG_LEVEL_ERROR = 3,      // "Error"
            MONGOC_STRUCTURED_LOG_LEVEL_WARNING = 4,    // "Warning" ("warn" also accepted)
            MONGOC_STRUCTURED_LOG_LEVEL_NOTICE = 5,     // "Notice"
            MONGOC_STRUCTURED_LOG_LEVEL_INFO = 6,       // "Informational" ("info" also accepted)
            MONGOC_STRUCTURED_LOG_LEVEL_DEBUG = 7,      // "Debug"
            MONGOC_STRUCTURED_LOG_LEVEL_TRACE = 8,      // "Trace"
          } mongoc_structured_log_level_t;

          typedef enum {
            MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND = 0,           // "command"
            MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY = 1,          // "topology"
            MONGOC_STRUCTURED_LOG_COMPONENT_SERVER_SELECTION = 2,  // "serverSelection"
            MONGOC_STRUCTURED_LOG_COMPONENT_CONNECTION = 3,        // "connection"
          } mongoc_structured_log_component_t;

   mongoc_structured_log_level_t
   Synopsis
          typedef enum {
             MONGOC_STRUCTURED_LOG_LEVEL_EMERGENCY = 0,
             MONGOC_STRUCTURED_LOG_LEVEL_ALERT = 1,
             MONGOC_STRUCTURED_LOG_LEVEL_CRITICAL = 2,
             MONGOC_STRUCTURED_LOG_LEVEL_ERROR = 3,
             MONGOC_STRUCTURED_LOG_LEVEL_WARNING = 4,
             MONGOC_STRUCTURED_LOG_LEVEL_NOTICE = 5,
             MONGOC_STRUCTURED_LOG_LEVEL_INFO = 6,
             MONGOC_STRUCTURED_LOG_LEVEL_DEBUG = 7,
             MONGOC_STRUCTURED_LOG_LEVEL_TRACE = 8,
          } mongoc_structured_log_level_t;

       mongoc_structured_log_level_t enumerates the available log levels for use with structured logging.

   Functions
   mongoc_structured_log_get_level_name()
   Synopsis
          const char *
          mongoc_structured_log_get_level_name (mongoc_structured_log_level_t level);

   Parameterslevel: Log level as a mongoc_structured_log_level_t <>.

   Returns
       If the level is known, returns a pointer to a constant string that should not be freed.  If the level has
       no known name, returns NULL.

       See also:
          Structured Logging <>

   mongoc_structured_log_get_named_level()
   Synopsis
          bool
          mongoc_structured_log_get_named_level (const char *name, mongoc_structured_log_level_t *out);

       Look up a log level by name. Case insensitive.

   Parametersname: A name to look up as a log level.

       • out: On success, the corresponding mongoc_structured_log_level_t <> is written here.

   Returns
       If the level name is known, returns true and writes the level enum to *out.  If the  level  name  is  not
       known, returns false and does not write *out.

       See also:
          Structured Logging <>

       See also:
          Structured Logging <>

   mongoc_structured_log_component_t
   Synopsis
          typedef enum {
             MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND = 0,
             MONGOC_STRUCTURED_LOG_COMPONENT_TOPOLOGY = 1,
             MONGOC_STRUCTURED_LOG_COMPONENT_SERVER_SELECTION = 2,
             MONGOC_STRUCTURED_LOG_COMPONENT_CONNECTION = 3,
          } mongoc_structured_log_component_t;

       mongoc_structured_log_component_t  enumerates  the  structured  logging  components.  Applications should
       never   rely   on   having   an   exhaustive   list   of    all    log    components.     Instead,    use
       mongoc_structured_log_opts_set_max_level_for_all_components() <> to set a default level if needed.

   Functions
   mongoc_structured_log_get_component_name()
   Synopsis
          const char *
          mongoc_structured_log_get_component_name (mongoc_structured_log_component_t component);

   Parameterscomponent: Log component as a mongoc_structured_log_component_t <>.

   Returns
       If  the  component  is  known,  returns  a pointer to a constant string that should not be freed.  If the
       component has no known name, returns NULL.

       See also:
          Structured Logging <>

   mongoc_structured_log_get_named_component()
   Synopsis
          bool
          mongoc_structured_log_get_named_component (const char *name, mongoc_structured_log_component_t *out);

       Look up a component by name. Case insensitive.

   Parametersname: A name to look up as a log component.

       • out: On success, the corresponding mongoc_structured_log_component_t <> is written here.

   Returns
       If the component name is known, returns true and writes the component enum to  *out.   If  the  component
       name is not known, returns false and does not write *out.

       See also:
          Structured Logging <>

       See also:
          Structured Logging <>

       See also:
          mongoc_structured_log_get_level_name                             mongoc_structured_log_get_named_level
          mongoc_structured_log_get_component_name mongoc_structured_log_get_named_component

   Log Handlers
       Each mongoc_client_pool_t <> or standalone mongoc_client_t <> has its  own  instance  of  the  structured
       logging subsystem, with its own settings and handler.

       When using mongoc_client_pool_t <>, the pooled clients all share a common logging instance. Handlers must
       be thread-safe.

       The  handler  is  called  for  each  log  entry  with a level no greater than its component's maximum.  A
       mongoc_structured_log_entry_t <> pointer provides access to further details, during the handler only.

       Handlers  must  take  care  not  to  re-enter   libmongoc   with   the   same   mongoc_client_t   <>   or
       mongoc_client_pool_t <> that the handler has been called by.

   mongoc_structured_log_func_t
   Synopsis
          typedef void (*mongoc_structured_log_func_t)
          (const mongoc_structured_log_entry_t *entry, void *user_data);

       Callback  function  for  mongoc_structured_log_opts_set_handler()  <>.   Structured  log handlers must be
       thread-safe if they will be used with mongoc_client_pool_t <>.  Handlers must avoid unbounded  recursion,
       preferably by avoiding the use of any libmongoc client or pool which uses the same handler.

   Parametersentry: A mongoc_structured_log_entry_t <> pointer, only valid during the handler invocation.

       • user_data: Optional user data from mongoc_structured_log_opts_set_handler() <>.

       See also:
          Structured Logging <>

   Log Entries
       Each  log  entry  is  represented  within  the  handler by a short-lived mongoc_structured_log_entry_t <>
       pointer.  During the handler, this pointer can be used to access the individual properties of  an  entry:
       its level, component, and message.

       The  message will be assembled as a bson_t <https://www.mongoc.org/libbson/current/bson_t.html> only when
       explicitly requested by a call to mongoc_structured_log_entry_message_as_bson() <>.  This  results  in  a
       standalone document that may be retained for any amount of time and must be explicitly destroyed.

   mongoc_structured_log_entry_t
   Synopsis
          typedef struct mongoc_structured_log_entry_t mongoc_structured_log_entry_t;

       mongoc_structured_log_entry_t  is  an  opaque  structure  which  represents  the  temporary  state  of an
       in-progress log entry.  It can only be used during a mongoc_structured_log_func_t <>,  it  is  not  valid
       after the log handler returns.  Use the functions below to query individual aspects of the log entry.

   Functions
   mongoc_structured_log_entry_get_component()
   Synopsis
          mongoc_structured_log_component_t
          mongoc_structured_log_entry_get_component (const mongoc_structured_log_entry_t *entry);

   Parametersentry: A mongoc_structured_log_entry_t <> pointer.

   Returns
       The mongoc_structured_log_component_t <> associated with this log entry.

       See also:
          Structured Logging <>

   mongoc_structured_log_entry_get_level()
   Synopsis
          mongoc_structured_log_level_t
          mongoc_structured_log_entry_get_level (const mongoc_structured_log_entry_t *entry);

   Parametersentry: A mongoc_structured_log_entry_t <> pointer.

   Returns
       The mongoc_structured_log_level_t <> associated with this log entry.

       See also:
          Structured Logging <>

   mongoc_structured_log_entry_get_message_string()
   Synopsis
          const char *
          mongoc_structured_log_entry_get_message_string (const mongoc_structured_log_entry_t *entry);

   Parametersentry: A mongoc_structured_log_entry_t <> pointer.

   Returns
       A  string,  guaranteed to be valid only during the lifetime of the structured log handler.  It should not
       be freed or modified.

       Identical    to    the    value    of    the    message    key    in    the    document    returned    by
       mongoc_structured_log_entry_message_as_bson() <>.

       This  is not a complete string representation of the structured log, but rather a standardized identifier
       for a particular log event.

       See also:
          Structured Logging <>

   mongoc_structured_log_entry_message_as_bson()
   Synopsis
          bson_t *
          mongoc_structured_log_entry_message_as_bson (const mongoc_structured_log_entry_t *entry);

       Make a new copy, as a bson_t <https://www.mongoc.org/libbson/current/bson_t.html>,  of  the  log  entry's
       standardized  BSON  representation.   When  possible, a log handler should avoid serializing log messages
       that will be discarded.  Each call allocates an independent copy of the message that must be freed.

   Parametersentry: A mongoc_structured_log_entry_t <> pointer.

   Returns
       A new allocated bson_t <https://www.mongoc.org/libbson/current/bson_t.html> that must  be  freed  with  a
       call to bson_destroy() <https://www.mongoc.org/libbson/current/bson_destroy.html>.

       See also:
          Structured Logging <>

       See also:
          Structured Logging <>

   Example
       example-structured-log.c

          /* gcc example-structured-log.c -o example-structured-log \
           *     $(pkg-config --cflags --libs libmongoc-1.0) */

          #include <mongoc/mongoc.h>

          #include <pthread.h>

          #include <stdio.h>
          #include <stdlib.h>

          static pthread_mutex_t handler_mutex;

          static void
          example_handler(const mongoc_structured_log_entry_t *entry, void *user_data)
          {
             (void)user_data;

             mongoc_structured_log_component_t component = mongoc_structured_log_entry_get_component(entry);
             mongoc_structured_log_level_t level = mongoc_structured_log_entry_get_level(entry);
             const char *message_string = mongoc_structured_log_entry_get_message_string(entry);

             /*
              * With a single-threaded mongoc_client_t, handlers will always be called
              * by the thread that owns the client. On a mongoc_client_pool_t, handlers
              * are shared by multiple threads and must be reentrant.
              *
              * Note that unstructured logging includes a global mutex in the API,
              * but structured logging allows applications to avoid lock contention
              * even when multiple threads are issuing commands simultaneously.
              *
              * Simple apps like this example can achieve thread safety by adding their
              * own global mutex. For other apps, this would be a performance bottleneck
              * and it would be more appropriate for handlers to process their log
              * messages concurrently.
              *
              * In this example, our mutex protects access to a global log counter.
              * In a real application, you may need to protect access to a shared stream
              * or queue.
              */
             pthread_mutex_lock(&handler_mutex);

             static unsigned log_serial_number = 0;

             printf("%u. Log entry with component=%s level=%s message_string='%s'\n",
                    ++log_serial_number,
                    mongoc_structured_log_get_component_name(component),
                    mongoc_structured_log_get_level_name(level),
                    message_string);

             /*
              * At this point, the handler might make additional filtering decisions
              * before asking for a bson_t. As an example, let's log the component and
              * level for all messages but only show contents for command logs.
              */
             if (component == MONGOC_STRUCTURED_LOG_COMPONENT_COMMAND) {
                bson_t *message = mongoc_structured_log_entry_message_as_bson(entry);
                char *json = bson_as_relaxed_extended_json(message, NULL);
                printf("Full log message, as json: %s\n", json);
                bson_destroy(message);
                bson_free(json);
             }

             pthread_mutex_unlock(&handler_mutex);
          }

          int
          main(void)
          {
             const char *uri_string = "mongodb://localhost:27017";
             int result = EXIT_FAILURE;
             bson_error_t error;
             mongoc_uri_t *uri = NULL;
             mongoc_structured_log_opts_t *log_opts = NULL;
             mongoc_client_t *client = NULL;
             mongoc_client_pool_t *pool = NULL;

             /*
              * Note that structured logging only applies per-client or per-pool,
              * and it won't be used during or before mongoc_init.
              */
             mongoc_init();

             /*
              * Logging options are represented by a mongoc_structured_log_opts_t,
              * which can be copied into a mongoc_client_t or mongoc_client_pool_t
              * using mongoc_client_set_structured_log_opts() or
              * mongoc_client_pool_set_structured_log_opts(), respectively.
              *
              * Default settings are captured from the environment into
              * this structure when it's constructed.
              */
             log_opts = mongoc_structured_log_opts_new();

             /*
              * For demonstration purposes, set up a handler that receives all possible log messages.
              */
             pthread_mutex_init(&handler_mutex, NULL);
             mongoc_structured_log_opts_set_max_level_for_all_components(log_opts, MONGOC_STRUCTURED_LOG_LEVEL_TRACE);
             mongoc_structured_log_opts_set_handler(log_opts, example_handler, NULL);

             /*
              * By default libmongoc processes log options from the environment first,
              * and then allows you to apply programmatic overrides. To request the
              * opposite behavior, allowing the environment to override programmatic
              * defaults, you can ask for the environment to be re-read after setting
              * your own defaults.
              */
             mongoc_structured_log_opts_set_max_levels_from_env(log_opts);

             /*
              * Create a MongoDB URI object. This example assumes a local server.
              */
             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                fprintf(stderr, "URI parse error: %s\n", error.message);
                goto done;
             }

             /*
              * Create a new client pool.
              */
             pool = mongoc_client_pool_new(uri);
             if (!pool) {
                goto done;
             }

             /*
              * Set the client pool's log options.
              * This must happen only once, and only before the first mongoc_client_pool_pop.
              * There's no need to keep log_opts after this point.
              */
             mongoc_client_pool_set_structured_log_opts(pool, log_opts);

             /*
              * Check out a client, and do some work that we'll see logs from.
              * This example just sends a 'ping' command.
              */
             client = mongoc_client_pool_pop(pool);
             if (!client) {
                goto done;
             }

             bson_t *command = BCON_NEW("ping", BCON_INT32(1));
             bson_t reply;
             bool command_ret = mongoc_client_command_simple(client, "admin", command, NULL, &reply, &error);
             bson_destroy(command);
             bson_destroy(&reply);
             mongoc_client_pool_push(pool, client);
             if (!command_ret) {
                fprintf(stderr, "Command error: %s\n", error.message);
                goto done;
             }

             result = EXIT_SUCCESS;
          done:
             mongoc_uri_destroy(uri);
             mongoc_structured_log_opts_destroy(log_opts);
             mongoc_client_pool_destroy(pool);
             mongoc_cleanup();
             return result;
          }

       See also:
          mongoc_structured_log_entry_get_component                        mongoc_structured_log_entry_get_level
          mongoc_structured_log_entry_message_as_bson
       « libmongoc - API <>

   Error Reporting
   Description
       Many C Driver functions report errors by returning false or -1 and filling out a  bson_error_t  <https://
       www.mongoc.org/libbson/current/bson_error_t.html>  structure  with  an  error  domain,  error  code,  and
       message. Use domain to determine which subsystem generated the error, and code for  the  specific  error.
       message is a human-readable error description.

       See also:
          Handling Errors in libbson <https://www.mongodb.com/docs/languages/c/c-driver/current/libbson/tutorials/errors/>.

┌─────────────────────────────────────┬──────────────────────────────────────────────┬───────────────────────────────────────────┐
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_CLIENTMONGOC_ERROR_CLIENT_TOO_BIG                  │ You  tried to send a message              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_CLIENT_AUTHENTICATE             │ Wrong    credentials,     or              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_CLIENT_NO_ACCEPTABLE_PEER       │ You  tried an TLS connection              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_CLIENT_IN_EXHAUST               │ You   began   iterating   an              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_CLIENT_SESSION_FAILURE          │ Failure related to  creating              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_CLIENT_INVALID_ENCRYPTION_ARG   │ Failure related to arguments              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_CLIENT_INVALID_ENCRYPTION_STATE │ Failure  related  to  In-Use              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_CLIENT_INVALID_LOAD_BALANCER    │ You  attempted to connect to              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_CLIENT_NOT_READY                │ You  attempted  to  create a              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_STREAMMONGOC_ERROR_STREAM_NAME_RESOLUTION          │ DNS failure.                              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_STREAM_SOCKET                   │ Timeout  communicating  with              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_STREAM_CONNECT                  │ Failed to connect to server.              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_PROTOCOLMONGOC_ERROR_PROTOCOL_INVALID_REPLY          │ Corrupt    response     from              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION       │ The  server  version  is too              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_CURSORMONGOC_ERROR_CURSOR_INVALID_CURSOR           │ You  passed bad arguments to              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_CHANGE_STREAM_NO_RESUME_TOKEN   │ A resume token was not returned in        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_QUERYMONGOC_ERROR_QUERY_FAILURE                   │ Error API Version 1: Server  error        │
│                                     │                                              │ error message is in message.              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_SERVERMONGOC_ERROR_QUERY_FAILURE                   │ Error API Version 2: Server  error        │
│                                     │                                              │ error message is in message.              │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_SASL                   │ A SASL error code.                           │ man  sasl_errors  for  a  list  of        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_BSONMONGOC_ERROR_BSON_INVALID                    │ You passed an invalid or oversized        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_NAMESPACEMONGOC_ERROR_NAMESPACE_INVALID               │ You tried to create  a  collection        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_COMMANDMONGOC_ERROR_COMMAND_INVALID_ARG             │ Many functions set this error code        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_PROTOCOL_BAD_WIRE_VERSION       │ You tried to use a command  option        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_DUPLICATE_KEY                   │ An insert or update failed because        │
│                                     │                                              │ because  of  a  duplicate  _id  or        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_MAX_TIME_MS_EXPIRED             │ The   operation   failed   because        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_SERVER_SELECTION_INVALID_ID     │ The   serverId   option   for   an        │
│                                     │                                              │ sessionId option).                        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_COMMAND                │ Error code from server  <https://github.com/ │ Error  API Version 1: Server error        │
│                                     │ error_codes.yml>.                            │ message is in message.                    │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_SERVER                 │ Error  code from server <https://github.com/ │ Error API Version 2: Server  error        │
│                                     │ error_codes.yml>.                            │ message is in message.                    │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_COLLECTIONMONGOC_ERROR_COLLECTION_INSERT_FAILED,       │ Invalid   or   empty   input    to        │
│                                     │ MONGOC_ERROR_COLLECTION_UPDATE_FAILED,       │ mongoc_collection_insert_one() <>,        │
│                                     │ MONGOC_ERROR_COLLECTION_DELETE_FAILED.       │ mongoc_collection_insert_many()           │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_COLLECTION             │ Error code from server  <https://github.com/ │ Error  API Version 1: Server error        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_SERVER                 │ Error code from server  <https://github.com/ │ Error  API Version 2: Server error        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_GRIDFSMONGOC_ERROR_GRIDFS_CHUNK_MISSING            │ The  GridFS  file  is  missing   a        │
│                                     │                                              │ document in its chunks collection.        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_GRIDFS_CORRUPT                  │ A  data inconsistency was detected        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_GRIDFS_INVALID_FILENAME         │ You  passed  a  NULL  filename  to        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_GRIDFS_PROTOCOL_ERROR           │ You                         called        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_GRIDFS_BUCKET_FILE_NOT_FOUND    │ A  GridFS  file  is  missing  from        │
│                                     │                                              │ files collection.                         │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_GRIDFS_BUCKET_STREAM            │ An  error  occurred  on  a  stream        │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_SCRAMMONGOC_ERROR_SCRAM_PROTOCOL_ERROR            │ Failure in SCRAM-SHA-1  or  SCRAM-SHA-256 │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_SERVER_SELECTIONMONGOC_ERROR_SERVER_SELECTION_FAILURE        │ No   replica  set  member  or  mongos  is │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_WRITE_CONCERN          │ Error  code from server <https://github.com/ │ There was a write  concern  <>  error  or │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_TRANSACTIONMONGOC_ERROR_TRANSACTION_INVALID             │ You attempted to start a transaction when │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_CLIENT_SIDE_ENCRYPTION │ Error code produced by libmongocrypt.        │ An  error   occurred   in   the   library │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_AZUREMONGOC_ERROR_KMS_SERVER_HTTP                 │ An  Azure  HTTP service responded with an │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_KMS_SERVER_BAD_JSON             │ An Azure service responded  with  invalid │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│ MONGOC_ERROR_GCPMONGOC_ERROR_KMS_SERVER_HTTP                 │ A  GCP  HTTP  service  responded  with an │
├─────────────────────────────────────┼──────────────────────────────────────────────┼───────────────────────────────────────────┤
│                                     │ MONGOC_ERROR_KMS_SERVER_BAD_JSON             │ A GCP service responded with invalid JSON │
└─────────────────────────────────────┴──────────────────────────────────────────────┴───────────────────────────────────────────┘

   Error Labels
       In some cases your application must make decisions based  on  what  category  of  error  the  driver  has
       returned,  but  these  categories  do not correspond perfectly to an error domain or code. In such cases,
       error labels provide a reliable way to determine how your application should respond to an error.

       Any  C  Driver  function   that   has   a   bson_t   <https://www.mongoc.org/libbson/current/bson_t.html>
       out-parameter  named  reply  may  include  error  labels  to the reply, in the form of a BSON field named
       "errorLabels" containing an array of strings:

          { "errorLabels": [ "TransientTransactionError" ] }

       Use   mongoc_error_has_label()   <>   to   test   if   a   reply   contains   a   specific   label.   See
       mongoc_client_session_start_transaction()  <>  for example code that demonstrates the use of error labels
       in application logic.

       The following error labels are currently defined. Future versions of MongoDB may introduce new labels.

   TransientTransactionError
       Within a multi-document transaction, certain errors can leave the transaction in an  unknown  or  aborted
       state. These include write conflicts, primary stepdowns, and network errors. In response, the application
       should abort the transaction and try the same sequence of operations again in a new transaction.

   UnknownTransactionCommitResult
       When  mongoc_client_session_commit_transaction()  <> encounters a network error or certain server errors,
       it is not known whether the  transaction  was  committed.  Applications  should  attempt  to  commit  the
       transaction   again   until:   the   commit  succeeds,  the  commit  fails  with  an  error  not  labeled
       "UnknownTransactionCommitResult", or the application chooses to give up.

   Setting the Error API Version
       The driver's error reporting began with a design flaw: when the error domain is  MONGOC_ERROR_COLLECTION,
       MONGOC_ERROR_QUERY,  or  MONGOC_ERROR_COMMAND,  the  error  code  might  originate from the server or the
       driver. An application cannot always know where an error originated, and therefore cannot tell  what  the
       code means.

       For  example, if mongoc_collection_update_one() <> sets the error's domain to MONGOC_ERROR_COLLECTION and
       its  code  to  24,  the  application  cannot  know  whether  24  is  the  generic   driver   error   code
       MONGOC_ERROR_COLLECTION_UPDATE_FAILED or the specific server error code "LockTimeout".

       To  fix  this  flaw  while  preserving  backward  compatibility,  the  C Driver 1.4 introduces "Error API
       Versions". Version 1, the default Error API Version, maintains the flawed behavior. Version 2 adds a  new
       error  domain, MONGOC_ERROR_SERVER. In Version 2, error codes originating on the server always have error
       domain MONGOC_ERROR_SERVER or MONGOC_ERROR_WRITE_CONCERN. When the driver uses Version 2 the  application
       can  always  determine  the origin and meaning of error codes. New applications should use Version 2, and
       existing applications should be updated to use Version 2 as well.
      ┌──────────────────────────────────────────────┬────────────────────────────┬────────────────────────────┐
      │ Error Source                                 │ API Version 1              │ API Version 2              │
      ├──────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤
      │ mongoc_cursor_error() <>                     │ MONGOC_ERROR_QUERYMONGOC_ERROR_SERVER        │
      ├──────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤
      │ mongoc_client_command_with_opts()            │ MONGOC_ERROR_QUERYMONGOC_ERROR_SERVER        │
      │ <>,                                          │                            │                            │
      │ mongoc_database_command_with_opts()          │                            │                            │
      │ <>,   and   other    command                 │                            │                            │
      │ functions                                    │                            │                            │
      ├──────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤
      │ mongoc_client_get_database_names_with_opts() │ MONGOC_ERROR_QUERYMONGOC_ERROR_SERVER        │
      │ <>   and   other   command   helper          │                            │                            │
      │ functions                                    │                            │                            │
      ├──────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤
      │ mongoc_collection_insert_one()            <> │ MONGOC_ERROR_COMMANDMONGOC_ERROR_SERVER        │
      │ mongoc_collection_insert_many()           <> │                            │                            │
      │ mongoc_collection_update_one()            <> │                            │                            │
      │ mongoc_collection_update_many()           <> │                            │                            │
      │ mongoc_collection_replace_one()           <> │                            │                            │
      │ mongoc_collection_delete_one()            <> │                            │                            │
      │ mongoc_collection_delete_many() <>           │                            │                            │
      ├──────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤
      │ mongoc_bulk_operation_execute() <>           │ MONGOC_ERROR_COMMANDMONGOC_ERROR_SERVER        │
      ├──────────────────────────────────────────────┼────────────────────────────┼────────────────────────────┤
      │ Write-concern timeout                        │ MONGOC_ERROR_WRITE_CONCERNMONGOC_ERROR_WRITE_CONCERN │
      └──────────────────────────────────────────────┴────────────────────────────┴────────────────────────────┘

       The Error API Versions are defined with MONGOC_ERROR_API_VERSION_LEGACY  and  MONGOC_ERROR_API_VERSION_2.
       Set the version with mongoc_client_set_error_api() <> or mongoc_client_pool_set_error_api() <>.

       See also:
          MongoDB Server Error Codes <https://github.com/mongodb/mongo/blob/master/src/mongo/base/error_codes.yml>

   Object Lifecycle
       This page documents the order of creation and destruction for libmongoc's main struct types.

   Clients and pools
       Call  mongoc_init()  <>  once, before calling any other libmongoc functions, and call mongoc_cleanup() <>
       once before your program exits.

       A program that uses libmongoc  from  multiple  threads  should  create  a  mongoc_client_pool_t  <>  with
       mongoc_client_pool_new()   <>.   Each   thread   acquires   a  mongoc_client_t  <>  from  the  pool  with
       mongoc_client_pool_pop() <> and returns it with mongoc_client_pool_push() <> when the thread is  finished
       using it. To destroy the pool, first return all clients, then call mongoc_client_pool_destroy() <>.

       If  your  program  uses  libmongoc  from  only  one  thread,  create  a  mongoc_client_t <> directly with
       mongoc_client_new() <> or mongoc_client_new_from_uri() <>. Destroy it with mongoc_client_destroy() <>.

   Databases, collections, and related objects
       You can create a mongoc_database_t <> or mongoc_collection_t <> from a mongoc_client_t <>, and  create  a
       mongoc_cursor_t <> or mongoc_bulk_operation_t <> from a mongoc_collection_t <>.

       Each of these objects must be destroyed before the client they were created from, but their lifetimes are
       otherwise independent.

   GridFS objects
       You  can  create  a  mongoc_gridfs_t  <>  from  a mongoc_client_t <>, create a mongoc_gridfs_file_t <> or
       mongoc_gridfs_file_list_t <>  from  a  mongoc_gridfs_t  <>,  create  a  mongoc_gridfs_file_t  <>  from  a
       mongoc_gridfs_file_list_t <>, and create a mongoc_stream_t <> from a mongoc_gridfs_file_t <>.

       Each  of  these  objects  depends on the object it was created from. Always destroy GridFS objects in the
       reverse of the order they were created. The sole exception is that a mongoc_gridfs_file_t <> need not  be
       destroyed before the mongoc_gridfs_file_list_t <> it was created from.

   GridFS bucket objects
       Create  mongoc_gridfs_bucket_t  <>  with  a  mongoc_database_t  <> derived from a mongoc_client_t <>. The
       mongoc_database_t <> is independent from the mongoc_gridfs_bucket_t <>. But the mongoc_client_t  <>  must
       outlive the mongoc_gridfs_bucket_t <>.

       A  mongoc_stream_t  <>  may  be created from the mongoc_gridfs_bucket_t <>. The mongoc_gridfs_bucket_t <>
       must outlive the mongoc_stream_t <>.

   Sessions
       Start a session with mongoc_client_start_session() <>, use the session for a sequence of  operations  and
       multi-document transactions, then free it with mongoc_client_session_destroy() <>. Any mongoc_cursor_t <>
       or  mongoc_change_stream_t <> using a session must be destroyed before the session, and a session must be
       destroyed before the mongoc_client_t <> it came from.

       By    default,    sessions    are    causally    consistent    <https://www.mongodb.com/docs/manual/core/
       read-isolation-consistency-recency/#causal-consistency>. To disable causal consistency, before starting a
       session    create    a    mongoc_session_opt_t    <>   with   mongoc_session_opts_new()   <>   and   call
       mongoc_session_opts_set_causal_consistency() <>, then free the struct with  mongoc_session_opts_destroy()
       <>.

       Unacknowledged writes are prohibited with sessions.

       A  mongoc_client_session_t  <>  must  be  used  by  only  one  thread  at a time. Due to session pooling,
       mongoc_client_start_session() <> may return a session that has been idle for some time and is about to be
       closed after its idle timeout. Use the session within one minute of acquiring it to refresh  the  session
       and avoid a timeout.

   Client Side Encryption
       When configuring a mongoc_client_t <> for automatic encryption via mongoc_client_enable_auto_encryption()
       <>,     if     a     separate     key     vault     client     is     set    in    the    options    (via
       mongoc_auto_encryption_opts_set_keyvault_client() <>) the key vault client  must  outlive  the  encrypted
       client.

       When      configuring      a     mongoc_client_pool_t     <>     for     automatic     encryption     via
       mongoc_client_pool_enable_auto_encryption() <>, if a separate key vault client pool is set in the options
       (via mongoc_auto_encryption_opts_set_keyvault_client_pool() <>) the key vault client  pool  must  outlive
       the encrypted client pool.

       When   creating   a   mongoc_client_encryption_t   <>,   the   configured   key  vault  client  (set  via
       mongoc_client_encryption_opts_set_keyvault_client() <>) must outlive the mongoc_client_encryption_t <>.

   GridFS
       The C driver includes two APIs for GridFS.

       The older API consists of mongoc_gridfs_t <> and its derivatives. It contains deprecated  API,  does  not
       support  read preferences, and is not recommended in new applications. It does not conform to the MongoDB
       GridFS   specification   <https://github.com/mongodb/specifications/blob/master/source/gridfs/gridfs-spec
       .md>.

       The  newer  API  consists  of  mongoc_gridfs_bucket_t <> and allows uploading/downloading through derived
       mongoc_stream_t <> objects. It conforms to the MongoDB GridFS specification  <https://github.com/mongodb/
       specifications/blob/master/source/gridfs/gridfs-spec.md>.

       There  is  not always a straightforward upgrade path from an application built with mongoc_gridfs_t <> to
       mongoc_gridfs_bucket_t <> (e.g. a mongoc_gridfs_file_t <> provides functions to seek but  mongoc_stream_t
       <> does not). But users are encouraged to upgrade when possible.

   mongoc_auto_encryption_opts_t
       Options  for enabling automatic encryption and decryption for In-Use Encryption <https://www.mongodb.com/
       docs/languages/c/c-driver/current/libmongoc/guides/in-use-encryption/>.

   Synopsis
          typedef struct _mongoc_auto_encryption_opts_t mongoc_auto_encryption_opts_t;

       See also:
          In-Use Encryption <https://www.mongodb.com/docs/languages/c/c-driver/current/libmongoc/guides/in-use-encryption/>

   mongoc_bulkwrite_t
   Synopsis
          typedef struct _mongoc_bulkwrite_t mongoc_bulkwrite_t;

   Description
       mongoc_bulkwrite_t <> provides an abstraction for submitting multiple write operations as a single batch.

       After adding all of the write operations to the mongoc_bulkwrite_t <>, call mongoc_bulkwrite_execute() <>
       to execute the operation.

       Warning:
          It is only valid to call  mongoc_bulkwrite_execute()  <>  once.  The  mongoc_bulkwrite_t  <>  must  be
          destroyed afterwards.

       Note:
          If  using  MongoDB server 8.0+, prefer mongoc_bulkwrite_t <> over mongoc_bulk_operation_t <> to reduce
          network round trips.

          mongoc_bulkwrite_t <> uses the bulkWrite server command introduced in MongoDB  server  8.0.  bulkWrite
          command  supports insert, update, and delete operations in the same payload. bulkWrite supports use of
          multiple collection namespaces in the same payload.

          mongoc_bulk_operation_t <> uses the insert, update and delete server commands available in all current
          MongoDB server versions. Write operations are grouped by type (insert, update,  delete)  and  sent  in
          separate commands. Only one collection may be specified per bulk write.

   mongoc_bulkwriteopts_t
   Synopsis
          typedef struct _mongoc_bulkwriteopts_t mongoc_bulkwriteopts_t;

   mongoc_bulkwriteresult_t
   Synopsis
          typedef struct _mongoc_bulkwriteresult_t mongoc_bulkwriteresult_t;

   mongoc_bulkwriteexception_t
   Synopsis
          typedef struct _mongoc_bulkwriteexception_t mongoc_bulkwriteexception_t;

   mongoc_bulkwrite_check_acknowledged_t
   Synopsis
          typedef struct {
             bool is_ok;           // true if no error
             bool is_acknowledged; // true if the previous call to `mongoc_bulkwrite_execute` used an acknowledged write concern
          } mongoc_bulkwrite_check_acknowledged_t;

   Description
       mongoc_bulkwrite_check_acknowledged_t <> is returned by mongoc_bulkwrite_check_acknowledged() <>.

       is_ok  is  false  if  there  was no previous call to mongoc_bulkwrite_execute() <> or if execution failed
       before the write concern could be determined.

       is_acknowledged is true if the previous mongoc_bulkwrite_execute() <> call  used  an  acknowledged  write
       concern.

   mongoc_bulkwrite_serverid_t
   Synopsis
          typedef struct {
             bool is_ok;        // true if no error
             uint32_t serverid; // the server ID last used in `mongoc_bulkwrite_execute`
          } mongoc_bulkwrite_serverid_t;

   Description
       mongoc_bulkwrite_serverid_t <> is returned by mongoc_bulkwrite_serverid() <>.

       is_ok is false if there was no previous call to mongoc_bulkwrite_execute() <> or if execution failed.

       serverid is the server ID last used in mongoc_bulkwrite_execute() <>.

   mongoc_bulk_operation_t
       Bulk Write Operations

   Synopsis
          typedef struct _mongoc_bulk_operation_t mongoc_bulk_operation_t;

   Description
       mongoc_bulk_operation_t  <>  provides an abstraction for submitting multiple write operations as a single
       batch.

       After   adding   all   of   the   write   operations   to   the    mongoc_bulk_operation_t    <>,    call
       mongoc_bulk_operation_execute() <> to execute the operation.

       Warning:
          It  is only valid to call mongoc_bulk_operation_execute() <> once. The mongoc_bulk_operation_t must be
          destroyed afterwards.

       See also:
          Bulk Write Operations <https://www.mongodb.com/docs/languages/c/c-driver/current/libmongoc/guides/bulk/>
          mongoc_bulkwrite_t <>

       Note:
          If using MongoDB server 8.0+, prefer mongoc_bulkwrite_t <> over mongoc_bulk_operation_t <>  to  reduce
          network round trips.

          mongoc_bulkwrite_t  <>  uses  the bulkWrite server command introduced in MongoDB server 8.0. bulkWrite
          command supports insert, update, and delete operations in the same payload. bulkWrite supports use  of
          multiple collection namespaces in the same payload.

          mongoc_bulk_operation_t <> uses the insert, update and delete server commands available in all current
          MongoDB  server  versions.  Write  operations are grouped by type (insert, update, delete) and sent in
          separate commands. Only one collection may be specified per bulk write.

   mongoc_change_stream_t
   Synopsis
          #include <mongoc/mongoc.h>

          typedef struct _mongoc_change_stream_t mongoc_change_stream_t;

       mongoc_change_stream_t <> is a handle to a change stream. A collection  change  stream  can  be  obtained
       using mongoc_collection_watch() <>.

       It  is recommended to use a mongoc_change_stream_t <> and its functions instead of a raw aggregation with
       a $changeStream stage. For more information see the MongoDB Manual Entry on Change  Streams  <https://www
       .mongodb.com/docs/manual/changeStreams>.

   Example
       example-collection-watch.c

          #include <mongoc/mongoc.h>

          int
          main(void)
          {
             bson_t empty = BSON_INITIALIZER;
             const bson_t *doc;
             bson_t *to_insert = BCON_NEW("x", BCON_INT32(1));
             const bson_t *err_doc;
             bson_error_t error;
             const char *uri_string;
             mongoc_uri_t *uri;
             mongoc_client_t *client;
             mongoc_collection_t *coll;
             mongoc_change_stream_t *stream;
             mongoc_write_concern_t *wc = mongoc_write_concern_new();
             bson_t opts = BSON_INITIALIZER;
             bool r;

             mongoc_init();

             uri_string = "mongodb://"
                          "localhost:27017,localhost:27018,localhost:"
                          "27019/db?replicaSet=rs0";

             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                fprintf(stderr,
                        "failed to parse URI: %s\n"
                        "error message:       %s\n",
                        uri_string,
                        error.message);
                return EXIT_FAILURE;
             }

             client = mongoc_client_new_from_uri(uri);
             if (!client) {
                return EXIT_FAILURE;
             }

             coll = mongoc_client_get_collection(client, "db", "coll");
             stream = mongoc_collection_watch(coll, &empty, NULL);

             mongoc_write_concern_set_wmajority(wc, 10000);
             mongoc_write_concern_append(wc, &opts);
             r = mongoc_collection_insert_one(coll, to_insert, &opts, NULL, &error);
             if (!r) {
                fprintf(stderr, "Error: %s\n", error.message);
                return EXIT_FAILURE;
             }

             while (mongoc_change_stream_next(stream, &doc)) {
                char *as_json = bson_as_relaxed_extended_json(doc, NULL);
                fprintf(stderr, "Got document: %s\n", as_json);
                bson_free(as_json);
             }

             if (mongoc_change_stream_error_document(stream, &error, &err_doc)) {
                if (!bson_empty(err_doc)) {
                   fprintf(stderr, "Server Error: %s\n", bson_as_relaxed_extended_json(err_doc, NULL));
                } else {
                   fprintf(stderr, "Client Error: %s\n", error.message);
                }
                return EXIT_FAILURE;
             }

             bson_destroy(to_insert);
             mongoc_write_concern_destroy(wc);
             bson_destroy(&opts);
             mongoc_change_stream_destroy(stream);
             mongoc_collection_destroy(coll);
             mongoc_uri_destroy(uri);
             mongoc_client_destroy(client);
             mongoc_cleanup();

             return EXIT_SUCCESS;
          }

   Starting and Resuming
       All  watch  functions  accept  several  options  to indicate where a change stream should start returning
       changes from: resumeAfter, startAfter, and startAtOperationTime.

       All changes returned by mongoc_change_stream_next() <> include a resume token in the _id  field.  MongoDB
       4.2  also  includes  an additional resume token in each "aggregate" and "getMore" command response, which
       points to the end of that response's batch. The current token is automatically cached  by  libmongoc.  In
       the  event  of  an  error, libmongoc attempts to recreate the change stream starting where it left off by
       passing the cached resume token. libmongoc only attempts to resume  once,  but  client  applications  can
       access  the  cached resume token with mongoc_change_stream_get_resume_token() <> and use it for their own
       resume logic by passing it as either the resumeAfter or startAfter option.

       Additionally,  change  streams  can  start  returning  changes  at  an  operation  time  by   using   the
       startAtOperationTime  field.  This  can be the timestamp returned in the operationTime field of a command
       reply.

       resumeAfter, startAfter, and startAtOperationTime are mutually exclusive options. Setting more  than  one
       will result in a server error.

       The following example implements custom resuming logic, persisting the resume token in a file.

       example-resume.c

          #include <mongoc/mongoc.h>

          /* An example implementation of custom resume logic in a change stream.
           * example-resume starts a client-wide change stream and persists the resume
           * token in a file "resume-token.json". On restart, if "resume-token.json"
           * exists, the change stream starts watching after the persisted resume token.
           *
           * This behavior allows a user to exit example-resume, and restart it later
           * without missing any change events.
           */
          #include <unistd.h>

          static const char *RESUME_TOKEN_PATH = "resume-token.json";

          static bool
          _save_resume_token(const bson_t *doc)
          {
             FILE *file_stream;
             bson_iter_t iter;
             bson_t resume_token_doc;
             char *as_json = NULL;
             size_t as_json_len;
             const bson_value_t *resume_token;

             if (!bson_iter_init_find(&iter, doc, "_id")) {
                fprintf(stderr, "reply does not contain operationTime.");
                return false;
             }
             resume_token = bson_iter_value(&iter);
             /* store the resume token in a document, { resumeAfter: <resume token> }
              * which we can later append easily. */
             file_stream = fopen(RESUME_TOKEN_PATH, "w+");
             if (!file_stream) {
                fprintf(stderr, "failed to open %s for writing\n", RESUME_TOKEN_PATH);
                return false;
             }
             bson_init(&resume_token_doc);
             BSON_APPEND_VALUE(&resume_token_doc, "resumeAfter", resume_token);
             as_json = bson_as_canonical_extended_json(&resume_token_doc, &as_json_len);
             bson_destroy(&resume_token_doc);
             size_t n_written = 0;
             while (n_written < as_json_len) {
                ssize_t r = fwrite((void *)(as_json + n_written), sizeof(char), as_json_len - n_written, file_stream);
                if (r == -1) {
                   fprintf(stderr, "failed to write to %s\n", RESUME_TOKEN_PATH);
                   bson_free(as_json);
                   fclose(file_stream);
                   return false;
                }
                n_written += r;
             }

             bson_free(as_json);
             fclose(file_stream);
             return true;
          }

          bool
          _load_resume_token(bson_t *opts)
          {
             bson_error_t error;
             bson_json_reader_t *reader;
             bson_t doc;

             /* if the file does not exist, skip. */
             if (-1 == access(RESUME_TOKEN_PATH, R_OK)) {
                return true;
             }
             reader = bson_json_reader_new_from_file(RESUME_TOKEN_PATH, &error);
             if (!reader) {
                fprintf(stderr, "failed to open %s for reading: %s\n", RESUME_TOKEN_PATH, error.message);
                return false;
             }

             bson_init(&doc);
             if (-1 == bson_json_reader_read(reader, &doc, &error)) {
                fprintf(stderr, "failed to read doc from %s\n", RESUME_TOKEN_PATH);
                bson_destroy(&doc);
                bson_json_reader_destroy(reader);
                return false;
             }

             printf("found cached resume token in %s, resuming change stream.\n", RESUME_TOKEN_PATH);

             bson_concat(opts, &doc);
             bson_destroy(&doc);
             bson_json_reader_destroy(reader);
             return true;
          }

          int
          main(void)
          {
             int exit_code = EXIT_FAILURE;
             const char *uri_string;
             mongoc_uri_t *uri = NULL;
             bson_error_t error;
             mongoc_client_t *client = NULL;
             bson_t pipeline = BSON_INITIALIZER;
             bson_t opts = BSON_INITIALIZER;
             mongoc_change_stream_t *stream = NULL;
             const bson_t *doc;

             const int max_time = 30; /* max amount of time, in seconds, that
                                         mongoc_change_stream_next can block. */

             mongoc_init();
             uri_string = "mongodb://localhost:27017/db?replicaSet=rs0";
             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                fprintf(stderr,
                        "failed to parse URI: %s\n"
                        "error message:       %s\n",
                        uri_string,
                        error.message);
                goto cleanup;
             }

             client = mongoc_client_new_from_uri(uri);
             if (!client) {
                goto cleanup;
             }

             if (!_load_resume_token(&opts)) {
                goto cleanup;
             }
             BSON_APPEND_INT64(&opts, "maxAwaitTimeMS", max_time * 1000);

             printf("listening for changes on the client (max %d seconds).\n", max_time);
             stream = mongoc_client_watch(client, &pipeline, &opts);

             while (mongoc_change_stream_next(stream, &doc)) {
                char *as_json;

                as_json = bson_as_canonical_extended_json(doc, NULL);
                printf("change received: %s\n", as_json);
                bson_free(as_json);
                if (!_save_resume_token(doc)) {
                   goto cleanup;
                }
             }

             exit_code = EXIT_SUCCESS;

          cleanup:
             mongoc_uri_destroy(uri);
             bson_destroy(&pipeline);
             bson_destroy(&opts);
             mongoc_change_stream_destroy(stream);
             mongoc_client_destroy(client);
             mongoc_cleanup();
             return exit_code;
          }

       The  following  example  shows  using  startAtOperationTime  to  synchronize a change stream with another
       operation.

       example-start-at-optime.c

          /* An example of starting a change stream with startAtOperationTime. */
          #include <mongoc/mongoc.h>

          int
          main(void)
          {
             int exit_code = EXIT_FAILURE;
             const char *uri_string;
             mongoc_uri_t *uri = NULL;
             bson_error_t error;
             mongoc_client_t *client = NULL;
             mongoc_collection_t *coll = NULL;
             bson_t pipeline = BSON_INITIALIZER;
             bson_t opts = BSON_INITIALIZER;
             mongoc_change_stream_t *stream = NULL;
             bson_iter_t iter;
             const bson_t *doc;
             bson_value_t cached_operation_time = {0};
             int i;
             bool r;

             mongoc_init();
             uri_string = "mongodb://localhost:27017/db?replicaSet=rs0";
             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                fprintf(stderr,
                        "failed to parse URI: %s\n"
                        "error message:       %s\n",
                        uri_string,
                        error.message);
                goto cleanup;
             }

             client = mongoc_client_new_from_uri(uri);
             if (!client) {
                goto cleanup;
             }

             /* insert five documents. */
             coll = mongoc_client_get_collection(client, "db", "coll");
             for (i = 0; i < 5; i++) {
                bson_t reply;
                bson_t *insert_cmd = BCON_NEW("insert", "coll", "documents", "[", "{", "x", BCON_INT64(i), "}", "]");

                r = mongoc_collection_write_command_with_opts(coll, insert_cmd, NULL, &reply, &error);
                bson_destroy(insert_cmd);
                if (!r) {
                   bson_destroy(&reply);
                   fprintf(stderr, "failed to insert: %s\n", error.message);
                   goto cleanup;
                }
                if (i == 0) {
                   /* cache the operation time in the first reply. */
                   if (bson_iter_init_find(&iter, &reply, "operationTime")) {
                      bson_value_copy(bson_iter_value(&iter), &cached_operation_time);
                   } else {
                      fprintf(stderr, "reply does not contain operationTime.");
                      bson_destroy(&reply);
                      goto cleanup;
                   }
                }
                bson_destroy(&reply);
             }

             /* start a change stream at the first returned operationTime. */
             BSON_APPEND_VALUE(&opts, "startAtOperationTime", &cached_operation_time);
             stream = mongoc_collection_watch(coll, &pipeline, &opts);

             /* since the change stream started at the operation time of the first
              * insert, the five inserts are returned. */
             printf("listening for changes on db.coll:\n");
             while (mongoc_change_stream_next(stream, &doc)) {
                char *as_json;

                as_json = bson_as_canonical_extended_json(doc, NULL);
                printf("change received: %s\n", as_json);
                bson_free(as_json);
             }

             exit_code = EXIT_SUCCESS;

          cleanup:
             mongoc_uri_destroy(uri);
             bson_destroy(&pipeline);
             bson_destroy(&opts);
             if (cached_operation_time.value_type) {
                bson_value_destroy(&cached_operation_time);
             }
             mongoc_change_stream_destroy(stream);
             mongoc_collection_destroy(coll);
             mongoc_client_destroy(client);
             mongoc_cleanup();
             return exit_code;
          }

   mongoc_client_encryption_t
   Synopsis
          typedef struct _mongoc_client_encryption_t mongoc_client_encryption_t;

       mongoc_client_encryption_t provides utility functions  for  In-Use  Encryption  <https://www.mongodb.com/
       docs/languages/c/c-driver/current/libmongoc/guides/in-use-encryption/>.

   Thread Safety
       mongoc_client_encryption_t  <>  is  NOT  thread-safe  and  should  only be used in the same thread as the
       mongoc_client_t <> that is configured via mongoc_client_encryption_opts_set_keyvault_client() <>.

   Lifecycle
       The key vault client, configured via mongoc_client_encryption_opts_set_keyvault_client() <>, must outlive
       the mongoc_client_encryption_t <>.

       See also:
          mongoc_client_enable_auto_encryption() <>

          mongoc_client_pool_enable_auto_encryption() <>

          In-Use Encryption <https://www.mongodb.com/docs/languages/c/c-driver/current/libmongoc/guides/in-use-encryption/> for libmongoc

          The MongoDB Manual for Client-Side Field Level Encryption <https://www.mongodb.com/docs/manual/core/security-client-side-encryption/>

          The MongoDB Manual for Queryable Encryption <https://www.mongodb.com/docs/manual/core/queryable-encryption/>

   mongoc_client_encryption_datakey_opts_t
   Synopsis
          typedef struct _mongoc_client_encryption_datakey_opts_t mongoc_client_encryption_datakey_opts_t;

       Used to set options for mongoc_client_encryption_create_datakey() <>.

       See also:
          mongoc_client_encryption_create_datakey() <>

   mongoc_client_encryption_rewrap_many_datakey_result_t
   Synopsis
          typedef struct _mongoc_client_encryption_rewrap_many_datakey_result_t
             mongoc_client_encryption_rewrap_many_datakey_result_t;

       Used to access the result of mongoc_client_encryption_rewrap_many_datakey() <>.

       See also:
          mongoc_client_encryption_rewrap_many_datakey() <>

   mongoc_client_encryption_encrypt_opts_t
   Synopsis
          typedef struct _mongoc_client_encryption_encrypt_opts_t mongoc_client_encryption_encrypt_opts_t;

       Used to set options for mongoc_client_encryption_encrypt() <>.

       See also:
          mongoc_client_encryption_encrypt() <>

   mongoc_client_encryption_encrypt_text_opts_t
   Synopsis
          typedef struct _mongoc_client_encryption_encrypt_text_opts_t mongoc_client_encryption_encrypt_text_opts_t;

       Added in version 2.2.0.

       TextOpts specifies index options for a Queryable Encryption field supporting "textPreview" queries.  Used
       to set options for mongoc_client_encryption_encrypt() <>.

       Case  sensitive  and  diacritic sensitive must be set. If prefix or suffix are set, substring must not be
       set.

       The "TextPreview" algorithm is in preview and should be used  for  experimental  workloads  only.   These
       features  are  unstable  and their security is not guaranteed until released as Generally Available (GA).
       The GA version of these features may not be backwards compatible with the preview version.

       See also:
          mongoc_client_encryption_encrypt() <>
          mongoc_client_encryption_encrypt_opts_t <>

   mongoc_client_encryption_encrypt_range_opts_t
   Synopsis
          typedef struct _mongoc_client_encryption_encrypt_range_opts_t mongoc_client_encryption_encrypt_range_opts_t;

       Added in version 1.24.0.

       RangeOpts specifies index options for a Queryable Encryption field supporting "range"  queries.  Used  to
       set options for mongoc_client_encryption_encrypt() <>.

       The  options  min, max, trim factor, sparsity, and range must match the values set in the encryptedFields
       of the destination collection.

       For double and decimal128 fields, min/max/precision must all be set, or all be unset.

       See also:
          mongoc_client_encryption_encrypt() <>
          mongoc_client_encryption_encrypt_opts_t <>

   mongoc_client_encryption_opts_t
   Synopsis
          typedef struct _mongoc_client_encryption_opts_t mongoc_client_encryption_opts_t;

       Used to set options for mongoc_client_encryption_new() <>.

       See also:
          mongoc_client_encryption_new() <>

   mongoc_client_pool_t
       A connection pool for multi-threaded  programs.  See  Connection  Pooling  <https://www.mongodb.com/docs/
       languages/c/c-driver/current/connect/connection-pools/.>.

   Synopsis
          typedef struct _mongoc_client_pool_t mongoc_client_pool_t

       mongoc_client_pool_t  is  the basis for multi-threading in the MongoDB C driver. Since mongoc_client_t <>
       structures are not thread-safe, this structure is used to retrieve a new mongoc_client_t <> for  a  given
       thread. This structure is thread-safe, except for its destructor method, mongoc_client_pool_destroy() <>,
       which is not thread-safe and must only be called from one thread.

   Example
       example-pool.c

          /* gcc example-pool.c -o example-pool $(pkg-config --cflags --libs
           * libmongoc-1.0) */

          /* ./example-pool [CONNECTION_STRING] */

          #include <mongoc/mongoc.h>

          #include <pthread.h>

          #include <stdio.h>

          static pthread_mutex_t mutex;
          static bool in_shutdown = false;

          static void *
          worker(void *data)
          {
             mongoc_client_pool_t *pool = data;
             mongoc_client_t *client;
             bson_t ping = BSON_INITIALIZER;
             bson_error_t error;
             bool r;

             BSON_APPEND_INT32(&ping, "ping", 1);

             while (true) {
                client = mongoc_client_pool_pop(pool);
                /* Do something with client. If you are writing an HTTP server, you
                 * probably only want to hold onto the client for the portion of the
                 * request performing database queries.
                 */
                r = mongoc_client_command_simple(client, "admin", &ping, NULL, NULL, &error);

                if (!r) {
                   fprintf(stderr, "%s\n", error.message);
                }

                mongoc_client_pool_push(pool, client);

                pthread_mutex_lock(&mutex);
                if (in_shutdown || !r) {
                   pthread_mutex_unlock(&mutex);
                   break;
                }

                pthread_mutex_unlock(&mutex);
             }

             bson_destroy(&ping);
             return NULL;
          }

          int
          main(int argc, char *argv[])
          {
             const char *uri_string = "mongodb://127.0.0.1/?appname=pool-example";
             mongoc_uri_t *uri;
             bson_error_t error;
             mongoc_client_pool_t *pool;
             pthread_t threads[10];
             unsigned i;
             void *ret;

             pthread_mutex_init(&mutex, NULL);
             mongoc_init();

             if (argc > 1) {
                uri_string = argv[1];
             }

             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                fprintf(stderr,
                        "failed to parse URI: %s\n"
                        "error message:       %s\n",
                        uri_string,
                        error.message);
                return EXIT_FAILURE;
             }

             pool = mongoc_client_pool_new(uri);
             mongoc_client_pool_set_error_api(pool, 2);

             for (i = 0; i < 10; i++) {
                pthread_create(&threads[i], NULL, worker, pool);
             }

             sleep(10);
             pthread_mutex_lock(&mutex);
             in_shutdown = true;
             pthread_mutex_unlock(&mutex);

             for (i = 0; i < 10; i++) {
                pthread_join(threads[i], &ret);
             }

             mongoc_client_pool_destroy(pool);
             mongoc_uri_destroy(uri);

             mongoc_cleanup();

             return EXIT_SUCCESS;
          }

   mongoc_client_session_t
       Use  a  session  for a sequence of operations, optionally with causal consistency. See the MongoDB Manual
       Entry         for         Causal          Consistency          <https://www.mongodb.com/docs/manual/core/
       read-isolation-consistency-recency/#causal-consistency>.

   Synopsis
       Start  a  session with mongoc_client_start_session() <>, use the session for a sequence of operations and
       multi-document transactions, then free it with mongoc_client_session_destroy() <>. Any mongoc_cursor_t <>
       or mongoc_change_stream_t <> using a session must be destroyed before the session, and a session must  be
       destroyed before the mongoc_client_t <> it came from.

       By    default,    sessions    are    causally    consistent    <https://www.mongodb.com/docs/manual/core/
       read-isolation-consistency-recency/#causal-consistency>. To disable causal consistency, before starting a
       session   create   a   mongoc_session_opt_t   <>   with    mongoc_session_opts_new()    <>    and    call
       mongoc_session_opts_set_causal_consistency()  <>, then free the struct with mongoc_session_opts_destroy()
       <>.

       Unacknowledged writes are prohibited with sessions.

       A mongoc_client_session_t <> must be used by  only  one  thread  at  a  time.  Due  to  session  pooling,
       mongoc_client_start_session() <> may return a session that has been idle for some time and is about to be
       closed  after  its idle timeout. Use the session within one minute of acquiring it to refresh the session
       and avoid a timeout.

   Fork Safety
       A mongoc_client_session_t <> is only usable in the parent process after a fork. The  child  process  must
       call mongoc_client_reset() <> on the client field.

   Example
       example-session.c

          /* gcc example-session.c -o example-session \
           *     $(pkg-config --cflags --libs libmongoc-1.0) */

          /* ./example-session [CONNECTION_STRING] */

          #include <mongoc/mongoc.h>

          #include <stdio.h>

          int
          main(int argc, char *argv[])
          {
             int exit_code = EXIT_FAILURE;

             mongoc_client_t *client = NULL;
             const char *uri_string = "mongodb://127.0.0.1/?appname=session-example";
             mongoc_uri_t *uri = NULL;
             mongoc_client_session_t *client_session = NULL;
             mongoc_collection_t *collection = NULL;
             bson_error_t error;
             bson_t *selector = NULL;
             bson_t *update = NULL;
             bson_t *update_opts = NULL;
             bson_t *find_opts = NULL;
             mongoc_read_prefs_t *secondary = NULL;
             mongoc_cursor_t *cursor = NULL;
             const bson_t *doc;
             char *str;
             bool r;

             mongoc_init();

             if (argc > 1) {
                uri_string = argv[1];
             }

             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                fprintf(stderr,
                        "failed to parse URI: %s\n"
                        "error message:       %s\n",
                        uri_string,
                        error.message);
                goto done;
             }

             client = mongoc_client_new_from_uri(uri);
             if (!client) {
                goto done;
             }

             mongoc_client_set_error_api(client, 2);

             /* pass NULL for options - by default the session is causally consistent */
             client_session = mongoc_client_start_session(client, NULL, &error);
             if (!client_session) {
                fprintf(stderr, "Failed to start session: %s\n", error.message);
                goto done;
             }

             collection = mongoc_client_get_collection(client, "test", "collection");
             selector = BCON_NEW("_id", BCON_INT32(1));
             update = BCON_NEW("$inc", "{", "x", BCON_INT32(1), "}");
             update_opts = bson_new();
             if (!mongoc_client_session_append(client_session, update_opts, &error)) {
                fprintf(stderr, "Could not add session to opts: %s\n", error.message);
                goto done;
             }

             r = mongoc_collection_update_one(collection, selector, update, update_opts, NULL /* reply */, &error);

             if (!r) {
                fprintf(stderr, "Update failed: %s\n", error.message);
                goto done;
             }

             bson_destroy(selector);
             selector = BCON_NEW("_id", BCON_INT32(1));
             secondary = mongoc_read_prefs_new(MONGOC_READ_SECONDARY);

             find_opts = BCON_NEW("maxTimeMS", BCON_INT32(2000));
             if (!mongoc_client_session_append(client_session, find_opts, &error)) {
                fprintf(stderr, "Could not add session to opts: %s\n", error.message);
                goto done;
             }

             /* read from secondary. since we're in a causally consistent session, the
              * data is guaranteed to reflect the update we did on the primary. the query
              * blocks waiting for the secondary to catch up, if necessary, or times out
              * and fails after 2000 ms.
              */
             cursor = mongoc_collection_find_with_opts(collection, selector, find_opts, secondary);

             while (mongoc_cursor_next(cursor, &doc)) {
                str = bson_as_relaxed_extended_json(doc, NULL);
                fprintf(stdout, "%s\n", str);
                bson_free(str);
             }

             if (mongoc_cursor_error(cursor, &error)) {
                fprintf(stderr, "Cursor Failure: %s\n", error.message);
                goto done;
             }

             exit_code = EXIT_SUCCESS;

          done:
             if (find_opts) {
                bson_destroy(find_opts);
             }
             if (update) {
                bson_destroy(update);
             }
             if (selector) {
                bson_destroy(selector);
             }
             if (update_opts) {
                bson_destroy(update_opts);
             }
             if (secondary) {
                mongoc_read_prefs_destroy(secondary);
             }
             /* destroy cursor, collection, session before the client they came from */
             if (cursor) {
                mongoc_cursor_destroy(cursor);
             }
             if (collection) {
                mongoc_collection_destroy(collection);
             }
             if (client_session) {
                mongoc_client_session_destroy(client_session);
             }
             if (uri) {
                mongoc_uri_destroy(uri);
             }
             if (client) {
                mongoc_client_destroy(client);
             }

             mongoc_cleanup();

             return exit_code;
          }

   mongoc_client_session_with_transaction_cb_t
   Synopsis
          typedef bool (*mongoc_client_session_with_transaction_cb_t) (
             mongoc_client_session_t *session,
             void *ctx,
             bson_t **reply,
             bson_error_t *error);

       Provide  this callback to mongoc_client_session_with_transaction() <>. The callback should run a sequence
       of operations meant to be contained within a transaction.  The callback should not attempt  to  start  or
       commit transactions.

   Parameterssession: A mongoc_client_session_t <>.

       • ctx: A void* set to the the user-provided ctx passed to mongoc_client_session_with_transaction() <>.

       • reply:  An optional location for a bson_t <https://www.mongoc.org/libbson/current/bson_t.html> or NULL.
         The callback should set this if it runs any operations against the server and receives replies.

       • error: A bson_error_t <https://www.mongoc.org/libbson/current/bson_error_t.html>. The  callback  should
         set this if it receives any errors while running operations against the server.

   Return
       Returns true for success and false on failure. If cb returns false then it should also set error.

       See also:
          mongoc_client_session_with_transaction() <>

   mongoc_client_t
       A  single-threaded  MongoDB connection. See Connection Pooling <https://www.mongodb.com/docs/languages/c/
       c-driver/current/connect/connection-pools/.>.

   Synopsis
          typedef struct _mongoc_client_t mongoc_client_t;

          typedef mongoc_stream_t *(*mongoc_stream_initiator_t) (
             const mongoc_uri_t *uri,
             const mongoc_host_list_t *host,
             void *user_data,
             bson_error_t *error);

       mongoc_client_t is an opaque type that provides access to a  MongoDB  server,  replica  set,  or  sharded
       cluster.  It  maintains  management  of  underlying  sockets  and  routing  to  individual nodes based on
       mongoc_read_prefs_t <> or mongoc_write_concern_t <>.

   Streams
       The underlying transport for a given client can be customized, wrapped or replaced by any  implementation
       that fulfills mongoc_stream_t <>. A custom transport can be set with mongoc_client_set_stream_initiator()
       <>.

   Thread Safety
       mongoc_client_t  is  NOT  thread-safe  and  should  only  be used from one thread at a time. When used in
       multi-threaded scenarios, it is recommended that you  use  the  thread-safe  mongoc_client_pool_t  <>  to
       retrieve a mongoc_client_t for your thread.

   Fork Safety
       A  mongoc_client_t  <>  is  only  usable  in the parent process after a fork. The child process must call
       mongoc_client_reset() <>.

   Example
       example-client.c

          /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
           * libmongoc-1.0) */

          /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */

          #include <mongoc/mongoc.h>

          #include <stdio.h>
          #include <stdlib.h>

          int
          main(int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             mongoc_cursor_t *cursor;
             bson_error_t error;
             const bson_t *doc;
             const char *collection_name = "test";
             bson_t query;
             char *str;
             const char *uri_string = "mongodb://127.0.0.1/?appname=client-example";
             mongoc_uri_t *uri;

             mongoc_init();
             if (argc > 1) {
                uri_string = argv[1];
             }

             if (argc > 2) {
                collection_name = argv[2];
             }

             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                fprintf(stderr,
                        "failed to parse URI: %s\n"
                        "error message:       %s\n",
                        uri_string,
                        error.message);
                return EXIT_FAILURE;
             }

             client = mongoc_client_new_from_uri(uri);
             if (!client) {
                return EXIT_FAILURE;
             }

             mongoc_client_set_error_api(client, 2);

             bson_init(&query);
             collection = mongoc_client_get_collection(client, "test", collection_name);
             cursor = mongoc_collection_find_with_opts(collection,
                                                       &query,
                                                       NULL,  /* additional options */
                                                       NULL); /* read prefs, NULL for default */

             while (mongoc_cursor_next(cursor, &doc)) {
                str = bson_as_canonical_extended_json(doc, NULL);
                fprintf(stdout, "%s\n", str);
                bson_free(str);
             }

             if (mongoc_cursor_error(cursor, &error)) {
                fprintf(stderr, "Cursor Failure: %s\n", error.message);
                return EXIT_FAILURE;
             }

             bson_destroy(&query);
             mongoc_cursor_destroy(cursor);
             mongoc_collection_destroy(collection);
             mongoc_uri_destroy(uri);
             mongoc_client_destroy(client);
             mongoc_cleanup();

             return EXIT_SUCCESS;
          }

   mongoc_collection_t
   Synopsis
          typedef struct _mongoc_collection_t mongoc_collection_t;

       mongoc_collection_t provides access to a MongoDB collection.  This handle is useful for actions for  most
       CRUD operations, I.e. insert, update, delete, find, etc.

   Read Preferences and Write Concerns
       Read preferences and write concerns are inherited from the parent client. They can be overridden by set_*
       commands if so desired.

   mongoc_cursor_t
       Client-side cursor abstraction

   Synopsis
          typedef struct _mongoc_cursor_t mongoc_cursor_t;

       mongoc_cursor_t  provides  access  to  a MongoDB query cursor.  It wraps up the wire protocol negotiation
       required to initiate a query and retrieve an unknown number of documents.

       Common cursor operations include:

       • Determine which host we've connected to with mongoc_cursor_get_host() <>.

       • Retrieve more records with repeated calls to mongoc_cursor_next() <>.

       • Clone a query to repeat execution at a later point with mongoc_cursor_clone() <>.

       • Test for errors with mongoc_cursor_error() <>.

       Cursors are lazy, meaning that no connection is established and no network traffic occurs until the first
       call to mongoc_cursor_next() <>.

   Thread Safety
       mongoc_cursor_t is NOT thread safe. It may only be used from within the thread in which it was created.

   Example
       Query MongoDB and iterate results

          /* gcc example-client.c -o example-client $(pkg-config --cflags --libs
           * libmongoc-1.0) */

          /* ./example-client [CONNECTION_STRING [COLLECTION_NAME]] */

          #include <mongoc/mongoc.h>

          #include <stdio.h>
          #include <stdlib.h>

          int
          main(int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_collection_t *collection;
             mongoc_cursor_t *cursor;
             bson_error_t error;
             const bson_t *doc;
             const char *collection_name = "test";
             bson_t query;
             char *str;
             const char *uri_string = "mongodb://127.0.0.1/?appname=client-example";
             mongoc_uri_t *uri;

             mongoc_init();
             if (argc > 1) {
                uri_string = argv[1];
             }

             if (argc > 2) {
                collection_name = argv[2];
             }

             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                fprintf(stderr,
                        "failed to parse URI: %s\n"
                        "error message:       %s\n",
                        uri_string,
                        error.message);
                return EXIT_FAILURE;
             }

             client = mongoc_client_new_from_uri(uri);
             if (!client) {
                return EXIT_FAILURE;
             }

             mongoc_client_set_error_api(client, 2);

             bson_init(&query);
             collection = mongoc_client_get_collection(client, "test", collection_name);
             cursor = mongoc_collection_find_with_opts(collection,
                                                       &query,
                                                       NULL,  /* additional options */
                                                       NULL); /* read prefs, NULL for default */

             while (mongoc_cursor_next(cursor, &doc)) {
                str = bson_as_canonical_extended_json(doc, NULL);
                fprintf(stdout, "%s\n", str);
                bson_free(str);
             }

             if (mongoc_cursor_error(cursor, &error)) {
                fprintf(stderr, "Cursor Failure: %s\n", error.message);
                return EXIT_FAILURE;
             }

             bson_destroy(&query);
             mongoc_cursor_destroy(cursor);
             mongoc_collection_destroy(collection);
             mongoc_uri_destroy(uri);
             mongoc_client_destroy(client);
             mongoc_cleanup();

             return EXIT_SUCCESS;
          }

   mongoc_database_t
       MongoDB Database Abstraction

   Synopsis
          typedef struct _mongoc_database_t mongoc_database_t;

       mongoc_database_t provides access to a MongoDB database. This handle is useful for actions  a  particular
       database object. It is not a container for mongoc_collection_t <> structures.

       Read  preferences  and  write  concerns are inherited from the parent client. They can be overridden with
       mongoc_database_set_read_prefs() <> and mongoc_database_set_write_concern() <>.

   Examples
          #include <mongoc/mongoc.h>

          int
          main (int argc, char *argv[])
          {
             mongoc_database_t *database;
             mongoc_client_t *client;

             mongoc_init ();

             client = mongoc_client_new ("mongodb://localhost/");
             database = mongoc_client_get_database (client, "test");

             mongoc_database_destroy (database);
             mongoc_client_destroy (client);

             mongoc_cleanup ();

             return 0;
          }

   mongoc_find_and_modify_opts_t
       find_and_modify abstraction

   Synopsis
       mongoc_find_and_modify_opts_t is a builder interface to construct the findAndModify command  <https://www
       .mongodb.com/docs/manual/reference/command/findAndModify/>.

       It  was created to be able to accommodate new arguments to the findAndModify command <https://www.mongodb
       .com/docs/manual/reference/command/findAndModify/>.

       As of MongoDB 3.2, the mongoc_write_concern_t <> specified on the mongoc_collection_t <> will be used, if
       any.

   Example
       flags.c

          void
          fam_flags(mongoc_collection_t *collection)
          {
             mongoc_find_and_modify_opts_t *opts;
             bson_t reply;
             bson_error_t error;
             bson_t query = BSON_INITIALIZER;
             bson_t *update;
             bool success;

             /* Find Zlatan Ibrahimovic, the striker */
             BSON_APPEND_UTF8(&query, "firstname", "Zlatan");
             BSON_APPEND_UTF8(&query, "lastname", "Ibrahimovic");
             BSON_APPEND_UTF8(&query, "profession", "Football player");
             BSON_APPEND_INT32(&query, "age", 34);
             BSON_APPEND_INT32(&query, "goals", (16 + 35 + 23 + 57 + 16 + 14 + 28 + 84) + (1 + 6 + 62));

             /* Add his football position */
             update = BCON_NEW("$set", "{", "position", BCON_UTF8("striker"), "}");

             opts = mongoc_find_and_modify_opts_new();

             mongoc_find_and_modify_opts_set_update(opts, update);

             /* Create the document if it didn't exist, and return the updated document */
             mongoc_find_and_modify_opts_set_flags(opts, MONGOC_FIND_AND_MODIFY_UPSERT | MONGOC_FIND_AND_MODIFY_RETURN_NEW);

             success = mongoc_collection_find_and_modify_with_opts(collection, &query, opts, &reply, &error);

             if (success) {
                char *str;

                str = bson_as_canonical_extended_json(&reply, NULL);
                printf("%s\n", str);
                bson_free(str);
             } else {
                fprintf(stderr, "Got error: \"%s\" on line %d\n", error.message, (int)(__LINE__));
             }

             bson_destroy(&reply);
             bson_destroy(update);
             bson_destroy(&query);
             mongoc_find_and_modify_opts_destroy(opts);
          }

       bypass.c

          void
          fam_bypass(mongoc_collection_t *collection)
          {
             mongoc_find_and_modify_opts_t *opts;
             bson_t reply;
             bson_t *update;
             bson_error_t error;
             bson_t query = BSON_INITIALIZER;
             bool success;

             /* Find Zlatan Ibrahimovic, the striker */
             BSON_APPEND_UTF8(&query, "firstname", "Zlatan");
             BSON_APPEND_UTF8(&query, "lastname", "Ibrahimovic");
             BSON_APPEND_UTF8(&query, "profession", "Football player");

             /* Bump his age */
             update = BCON_NEW("$inc", "{", "age", BCON_INT32(1), "}");

             opts = mongoc_find_and_modify_opts_new();
             mongoc_find_and_modify_opts_set_update(opts, update);
             /* He can still play, even though he is pretty old. */
             mongoc_find_and_modify_opts_set_bypass_document_validation(opts, true);

             success = mongoc_collection_find_and_modify_with_opts(collection, &query, opts, &reply, &error);

             if (success) {
                char *str;

                str = bson_as_canonical_extended_json(&reply, NULL);
                printf("%s\n", str);
                bson_free(str);
             } else {
                fprintf(stderr, "Got error: \"%s\" on line %d\n", error.message, (int)(__LINE__));
             }

             bson_destroy(&reply);
             bson_destroy(update);
             bson_destroy(&query);
             mongoc_find_and_modify_opts_destroy(opts);
          }

       update.c

          void
          fam_update(mongoc_collection_t *collection)
          {
             mongoc_find_and_modify_opts_t *opts;
             bson_t *update;
             bson_t reply;
             bson_error_t error;
             bson_t query = BSON_INITIALIZER;
             bool success;

             /* Find Zlatan Ibrahimovic */
             BSON_APPEND_UTF8(&query, "firstname", "Zlatan");
             BSON_APPEND_UTF8(&query, "lastname", "Ibrahimovic");

             /* Make him a book author */
             update = BCON_NEW("$set", "{", "author", BCON_BOOL(true), "}");

             opts = mongoc_find_and_modify_opts_new();
             /* Note that the document returned is the _previous_ version of the document
              * To fetch the modified new version, use
              * mongoc_find_and_modify_opts_set_flags (opts,
              * MONGOC_FIND_AND_MODIFY_RETURN_NEW);
              */
             mongoc_find_and_modify_opts_set_update(opts, update);

             success = mongoc_collection_find_and_modify_with_opts(collection, &query, opts, &reply, &error);

             if (success) {
                char *str;

                str = bson_as_canonical_extended_json(&reply, NULL);
                printf("%s\n", str);
                bson_free(str);
             } else {
                fprintf(stderr, "Got error: \"%s\" on line %d\n", error.message, (int)(__LINE__));
             }

             bson_destroy(&reply);
             bson_destroy(update);
             bson_destroy(&query);
             mongoc_find_and_modify_opts_destroy(opts);
          }

       fields.c

          void
          fam_fields(mongoc_collection_t *collection)
          {
             mongoc_find_and_modify_opts_t *opts;
             bson_t fields = BSON_INITIALIZER;
             bson_t *update;
             bson_t reply;
             bson_error_t error;
             bson_t query = BSON_INITIALIZER;
             bool success;

             /* Find Zlatan Ibrahimovic */
             BSON_APPEND_UTF8(&query, "lastname", "Ibrahimovic");
             BSON_APPEND_UTF8(&query, "firstname", "Zlatan");

             /* Return his goal tally */
             BSON_APPEND_INT32(&fields, "goals", 1);

             /* Bump his goal tally */
             update = BCON_NEW("$inc", "{", "goals", BCON_INT32(1), "}");

             opts = mongoc_find_and_modify_opts_new();
             mongoc_find_and_modify_opts_set_update(opts, update);
             mongoc_find_and_modify_opts_set_fields(opts, &fields);
             /* Return the new tally */
             mongoc_find_and_modify_opts_set_flags(opts, MONGOC_FIND_AND_MODIFY_RETURN_NEW);

             success = mongoc_collection_find_and_modify_with_opts(collection, &query, opts, &reply, &error);

             if (success) {
                char *str;

                str = bson_as_canonical_extended_json(&reply, NULL);
                printf("%s\n", str);
                bson_free(str);
             } else {
                fprintf(stderr, "Got error: \"%s\" on line %d\n", error.message, (int)(__LINE__));
             }

             bson_destroy(&reply);
             bson_destroy(update);
             bson_destroy(&fields);
             bson_destroy(&query);
             mongoc_find_and_modify_opts_destroy(opts);
          }

       sort.c

          void
          fam_sort(mongoc_collection_t *collection)
          {
             mongoc_find_and_modify_opts_t *opts;
             bson_t *update;
             bson_t sort = BSON_INITIALIZER;
             bson_t reply;
             bson_error_t error;
             bson_t query = BSON_INITIALIZER;
             bool success;

             /* Find all users with the lastname Ibrahimovic */
             BSON_APPEND_UTF8(&query, "lastname", "Ibrahimovic");

             /* Sort by age (descending) */
             BSON_APPEND_INT32(&sort, "age", -1);

             /* Bump his goal tally */
             update = BCON_NEW("$set", "{", "oldest", BCON_BOOL(true), "}");

             opts = mongoc_find_and_modify_opts_new();
             mongoc_find_and_modify_opts_set_update(opts, update);
             mongoc_find_and_modify_opts_set_sort(opts, &sort);

             success = mongoc_collection_find_and_modify_with_opts(collection, &query, opts, &reply, &error);

             if (success) {
                char *str;

                str = bson_as_canonical_extended_json(&reply, NULL);
                printf("%s\n", str);
                bson_free(str);
             } else {
                fprintf(stderr, "Got error: \"%s\" on line %d\n", error.message, (int)(__LINE__));
             }

             bson_destroy(&reply);
             bson_destroy(update);
             bson_destroy(&sort);
             bson_destroy(&query);
             mongoc_find_and_modify_opts_destroy(opts);
          }

       opts.c

          void
          fam_opts(mongoc_collection_t *collection)
          {
             mongoc_find_and_modify_opts_t *opts;
             bson_t reply;
             bson_t *update;
             bson_error_t error;
             bson_t query = BSON_INITIALIZER;
             mongoc_write_concern_t *wc;
             bson_t extra = BSON_INITIALIZER;
             bool success;

             /* Find Zlatan Ibrahimovic, the striker */
             BSON_APPEND_UTF8(&query, "firstname", "Zlatan");
             BSON_APPEND_UTF8(&query, "lastname", "Ibrahimovic");
             BSON_APPEND_UTF8(&query, "profession", "Football player");

             /* Bump his age */
             update = BCON_NEW("$inc", "{", "age", BCON_INT32(1), "}");

             opts = mongoc_find_and_modify_opts_new();
             mongoc_find_and_modify_opts_set_update(opts, update);

             /* Abort if the operation takes too long. */
             mongoc_find_and_modify_opts_set_max_time_ms(opts, 100);

             /* Set write concern w: 2 */
             wc = mongoc_write_concern_new();
             mongoc_write_concern_set_w(wc, 2);
             mongoc_write_concern_append(wc, &extra);

             /* Some future findAndModify option the driver doesn't support conveniently
              */
             BSON_APPEND_INT32(&extra, "futureOption", 42);
             mongoc_find_and_modify_opts_append(opts, &extra);

             success = mongoc_collection_find_and_modify_with_opts(collection, &query, opts, &reply, &error);

             if (success) {
                char *str;

                str = bson_as_canonical_extended_json(&reply, NULL);
                printf("%s\n", str);
                bson_free(str);
             } else {
                fprintf(stderr, "Got error: \"%s\" on line %d\n", error.message, (int)(__LINE__));
             }

             bson_destroy(&reply);
             bson_destroy(&extra);
             bson_destroy(update);
             bson_destroy(&query);
             mongoc_write_concern_destroy(wc);
             mongoc_find_and_modify_opts_destroy(opts);
          }

       fam.c

          int
          main(void)
          {
             mongoc_collection_t *collection;
             mongoc_database_t *database;
             mongoc_client_t *client;
             const char *uri_string = "mongodb://localhost:27017/admin?appname=find-and-modify-opts-example";
             mongoc_uri_t *uri;
             bson_error_t error;
             bson_t *options;

             mongoc_init();

             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                fprintf(stderr,
                        "failed to parse URI: %s\n"
                        "error message:       %s\n",
                        uri_string,
                        error.message);
                return EXIT_FAILURE;
             }

             client = mongoc_client_new_from_uri(uri);
             if (!client) {
                return EXIT_FAILURE;
             }

             mongoc_client_set_error_api(client, 2);
             database = mongoc_client_get_database(client, "databaseName");

             options = BCON_NEW("validator",
                                "{",
                                "age",
                                "{",
                                "$lte",
                                BCON_INT32(34),
                                "}",
                                "}",
                                "validationAction",
                                BCON_UTF8("error"),
                                "validationLevel",
                                BCON_UTF8("moderate"));

             collection = mongoc_database_create_collection(database, "collectionName", options, &error);
             if (!collection) {
                fprintf(stderr, "Got error: \"%s\" on line %d\n", error.message, (int)(__LINE__));
                return EXIT_FAILURE;
             }

             fam_flags(collection);
             fam_bypass(collection);
             fam_update(collection);
             fam_fields(collection);
             fam_opts(collection);
             fam_sort(collection);

             mongoc_collection_drop(collection, NULL);
             bson_destroy(options);
             mongoc_uri_destroy(uri);
             mongoc_database_destroy(database);
             mongoc_collection_destroy(collection);
             mongoc_client_destroy(client);

             mongoc_cleanup();
             return EXIT_SUCCESS;
          }

       Outputs:

          {
              "lastErrorObject": {
                  "updatedExisting": false,
                  "n": 1,
                  "upserted": {
                      "$oid": "56562a99d13e6d86239c7b00"
                  }
              },
              "value": {
                  "_id": {
                      "$oid": "56562a99d13e6d86239c7b00"
                  },
                  "age": 34,
                  "firstname": "Zlatan",
                  "goals": 342,
                  "lastname": "Ibrahimovic",
                  "profession": "Football player",
                  "position": "striker"
              },
              "ok": 1
          }
          {
              "lastErrorObject": {
                  "updatedExisting": true,
                  "n": 1
              },
              "value": {
                  "_id": {
                      "$oid": "56562a99d13e6d86239c7b00"
                  },
                  "age": 34,
                  "firstname": "Zlatan",
                  "goals": 342,
                  "lastname": "Ibrahimovic",
                  "profession": "Football player",
                  "position": "striker"
              },
              "ok": 1
          }
          {
              "lastErrorObject": {
                  "updatedExisting": true,
                  "n": 1
              },
              "value": {
                  "_id": {
                      "$oid": "56562a99d13e6d86239c7b00"
                  },
                  "age": 35,
                  "firstname": "Zlatan",
                  "goals": 342,
                  "lastname": "Ibrahimovic",
                  "profession": "Football player",
                  "position": "striker"
              },
              "ok": 1
          }
          {
              "lastErrorObject": {
                  "updatedExisting": true,
                  "n": 1
              },
              "value": {
                  "_id": {
                      "$oid": "56562a99d13e6d86239c7b00"
                  },
                  "goals": 343
              },
              "ok": 1
          }
          {
              "lastErrorObject": {
                  "updatedExisting": true,
                  "n": 1
              },
              "value": {
                  "_id": {
                      "$oid": "56562a99d13e6d86239c7b00"
                  },
                  "age": 35,
                  "firstname": "Zlatan",
                  "goals": 343,
                  "lastname": "Ibrahimovic",
                  "profession": "Football player",
                  "position": "striker",
                  "author": true
              },
              "ok": 1
          }

   mongoc_gridfs_file_list_t
   Synopsis
          #include <mongoc/mongoc.h>

          typedef struct _mongoc_gridfs_file_list_t mongoc_gridfs_file_list_t;

   Description
       mongoc_gridfs_file_list_t provides a gridfs file list  abstraction.   It  provides  iteration  and  basic
       marshalling  on  top  of  a regular mongoc_collection_find_with_opts() <> style query. In interface, it's
       styled after mongoc_cursor_t <>.

   Example
          mongoc_gridfs_file_list_t *list;
          mongoc_gridfs_file_t *file;

          list = mongoc_gridfs_find_with_opts (gridfs, query, NULL);

          while ((file = mongoc_gridfs_file_list_next (list))) {
             do_something (file);

             mongoc_gridfs_file_destroy (file);
          }

          mongoc_gridfs_file_list_destroy (list);

   mongoc_gridfs_file_opt_t
   Synopsis
          typedef struct {
             const char *md5;
             const char *filename;
             const char *content_type;
             const bson_t *aliases;
             const bson_t *metadata;
             uint32_t chunk_size;
          } mongoc_gridfs_file_opt_t;

   Description
       This structure contains options that can be set on a mongoc_gridfs_file_t <>. It can be used  by  various
       functions when creating a new gridfs file.

   mongoc_gridfs_file_t
   Synopsis
          typedef struct _mongoc_gridfs_file_t mongoc_gridfs_file_t;

   Description
       This structure provides a MongoDB GridFS file abstraction. It provides several APIs.

       • readv, writev, seek, and tell.

       • General file metadata such as filename and length.

       • GridFS metadata such as md5, filename, content_type, aliases, metadata, chunk_size, and upload_date.

   Thread Safety
       This structure is NOT thread-safe and should only be used from one thread at a time.

   Related
       • mongoc_client_t <>

       • mongoc_gridfs_t <>

       • mongoc_gridfs_file_list_t <>

       • mongoc_gridfs_file_opt_t <>

   mongoc_gridfs_bucket_t
   Synopsis
          #include <mongoc/mongoc.h>

          typedef struct _mongoc_gridfs_bucket_t mongoc_gridfs_bucket_t;

   Description
       mongoc_gridfs_bucket_t   provides   a   spec-compliant   MongoDB   GridFS   implementation,   superseding
       mongoc_gridfs_t <>.  See  the  GridFS  MongoDB  documentation  <https://www.mongodb.com/docs/manual/core/
       gridfs/>.

   Thread Safety
       mongoc_gridfs_bucket_t  <>  is  NOT  thread-safe and should only be used in the same thread as the owning
       mongoc_client_t <>.

   Lifecycle
       It  is  an  error  to  free  a  mongoc_gridfs_bucket_t  <>  before  freeing  all  derived  instances   of
       mongoc_stream_t <>. The owning mongoc_client_t <> must outlive the mongoc_gridfs_bucket_t <>.

   Example
       example-gridfs-bucket.c

          #include <mongoc/mongoc.h>

          #include <stdio.h>
          #include <stdlib.h>

          int
          main(int argc, char *argv[])
          {
             const char *uri_string = "mongodb://localhost:27017/?appname=new-gridfs-example";
             mongoc_client_t *client;
             mongoc_database_t *db;
             mongoc_stream_t *file_stream;
             mongoc_gridfs_bucket_t *bucket;
             mongoc_cursor_t *cursor;
             bson_t filter;
             bool res;
             bson_value_t file_id;
             bson_error_t error;
             const bson_t *doc;
             char *str;
             mongoc_init();

             if (argc != 3) {
                fprintf(stderr, "usage: %s SOURCE_FILE_PATH FILE_COPY_PATH\n", argv[0]);
                return EXIT_FAILURE;
             }

             /* 1. Make a bucket. */
             client = mongoc_client_new(uri_string);
             db = mongoc_client_get_database(client, "test");
             bucket = mongoc_gridfs_bucket_new(db, NULL, NULL, &error);
             if (!bucket) {
                printf("Error creating gridfs bucket: %s\n", error.message);
                return EXIT_FAILURE;
             }

             /* 2. Insert a file.  */
             file_stream = mongoc_stream_file_new_for_path(argv[1], O_RDONLY, 0);
             res = mongoc_gridfs_bucket_upload_from_stream(bucket, "my-file", file_stream, NULL, &file_id, &error);
             if (!res) {
                printf("Error uploading file: %s\n", error.message);
                return EXIT_FAILURE;
             }

             mongoc_stream_close(file_stream);
             mongoc_stream_destroy(file_stream);

             /* 3. Download the file in GridFS to a local file. */
             file_stream = mongoc_stream_file_new_for_path(argv[2], O_CREAT | O_RDWR, 0);
             if (!file_stream) {
                perror("Error opening file stream");
                return EXIT_FAILURE;
             }

             res = mongoc_gridfs_bucket_download_to_stream(bucket, &file_id, file_stream, &error);
             if (!res) {
                printf("Error downloading file to stream: %s\n", error.message);
                return EXIT_FAILURE;
             }
             mongoc_stream_close(file_stream);
             mongoc_stream_destroy(file_stream);

             /* 4. List what files are available in GridFS. */
             bson_init(&filter);
             cursor = mongoc_gridfs_bucket_find(bucket, &filter, NULL);

             while (mongoc_cursor_next(cursor, &doc)) {
                str = bson_as_canonical_extended_json(doc, NULL);
                printf("%s\n", str);
                bson_free(str);
             }

             /* 5. Delete the file that we added. */
             res = mongoc_gridfs_bucket_delete_by_id(bucket, &file_id, &error);
             if (!res) {
                printf("Error deleting the file: %s\n", error.message);
                return EXIT_FAILURE;
             }

             /* 6. Cleanup. */
             mongoc_stream_close(file_stream);
             mongoc_stream_destroy(file_stream);
             mongoc_cursor_destroy(cursor);
             bson_destroy(&filter);
             mongoc_gridfs_bucket_destroy(bucket);
             mongoc_database_destroy(db);
             mongoc_client_destroy(client);
             mongoc_cleanup();

             return EXIT_SUCCESS;
          }

       See also:
          The MongoDB GridFS specification <https://github.com/mongodb/specifications/blob/master/source/gridfs/gridfs-spec.md>.

          The non spec-compliant mongoc_gridfs_t <>.

   mongoc_gridfs_t
       Warning:
          This  GridFS  implementation does not conform to the MongoDB GridFS specification <https://github.com/
          mongodb/specifications/blob/master/source/gridfs/gridfs-spec.md>. For a spec compliant implementation,
          use mongoc_gridfs_bucket_t <>.

   Synopsis
          #include <mongoc/mongoc.h>

          typedef struct _mongoc_gridfs_t mongoc_gridfs_t;

   Description
       mongoc_gridfs_t provides a MongoDB gridfs implementation. The system as a whole  is  made  up  of  gridfs
       objects, which contain gridfs_files and gridfs_file_lists.  Essentially, a basic file system API.

       There  are  extensive  caveats  about  the  kind of use cases gridfs is practical for. In particular, any
       writing after initial file creation is  likely  to  both  break  any  concurrent  readers  and  be  quite
       expensive. That said, this implementation does allow for arbitrary writes to existing gridfs object, just
       use them with caution.

       mongoc_gridfs  also  integrates  tightly  with  the  mongoc_stream_t  <> abstraction, which provides some
       convenient wrapping for file creation and reading/writing.  It can be used without, but its worth looking
       to see if your problem can fit that model.

       Warning:
          mongoc_gridfs_t does not support read preferences. In a replica set, GridFS queries are always  routed
          to the primary.

   Thread Safety
       mongoc_gridfs_t  is  NOT  thread-safe  and  should  only  be  used  in  the  same  thread  as  the owning
       mongoc_client_t <>.

   Lifecycle
       It is an error to free a mongoc_gridfs_t before freeing all related instances of mongoc_gridfs_file_t  <>
       and mongoc_gridfs_file_list_t <>.

   Example
       example-gridfs.c

          #include <mongoc/mongoc.h>

          #include <fcntl.h>

          #include <assert.h>
          #include <stdio.h>
          #include <stdlib.h>

          int
          main(int argc, char *argv[])
          {
             mongoc_gridfs_t *gridfs;
             mongoc_gridfs_file_t *file;
             mongoc_gridfs_file_list_t *list;
             mongoc_gridfs_file_opt_t opt = {0};
             mongoc_client_t *client;
             const char *uri_string = "mongodb://127.0.0.1:27017/?appname=gridfs-example";
             mongoc_uri_t *uri;
             mongoc_stream_t *stream;
             bson_t filter;
             bson_t opts;
             bson_t child;
             bson_error_t error;
             ssize_t r;
             char buf[4096];
             mongoc_iovec_t iov;
             const char *filename;
             const char *command;
             bson_value_t id;

             if (argc < 2) {
                fprintf(stderr, "usage - %s command ...\n", argv[0]);
                return EXIT_FAILURE;
             }

             mongoc_init();

             iov.iov_base = (void *)buf;
             iov.iov_len = sizeof buf;

             /* connect to localhost client */
             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                fprintf(stderr,
                        "failed to parse URI: %s\n"
                        "error message:       %s\n",
                        uri_string,
                        error.message);
                return EXIT_FAILURE;
             }

             client = mongoc_client_new_from_uri(uri);
             assert(client);
             mongoc_client_set_error_api(client, 2);

             /* grab a gridfs handle in test prefixed by fs */
             gridfs = mongoc_client_get_gridfs(client, "test", "fs", &error);
             assert(gridfs);

             command = argv[1];
             filename = argv[2];

             if (strcmp(command, "read") == 0) {
                if (argc != 3) {
                   fprintf(stderr, "usage - %s read filename\n", argv[0]);
                   return EXIT_FAILURE;
                }
                file = mongoc_gridfs_find_one_by_filename(gridfs, filename, &error);
                assert(file);

                stream = mongoc_stream_gridfs_new(file);
                assert(stream);

                for (;;) {
                   r = mongoc_stream_readv(stream, &iov, 1, -1, 0);

                   assert(r >= 0);

                   if (r == 0) {
                      break;
                   }

                   if (fwrite(iov.iov_base, 1, r, stdout) != (size_t)r) {
                      MONGOC_ERROR("Failed to write to stdout. Exiting.\n");
                      exit(1);
                   }
                }

                mongoc_stream_destroy(stream);
                mongoc_gridfs_file_destroy(file);
             } else if (strcmp(command, "list") == 0) {
                bson_init(&filter);

                bson_init(&opts);
                bson_append_document_begin(&opts, "sort", -1, &child);
                BSON_APPEND_INT32(&child, "filename", 1);
                bson_append_document_end(&opts, &child);

                list = mongoc_gridfs_find_with_opts(gridfs, &filter, &opts);

                bson_destroy(&filter);
                bson_destroy(&opts);

                while ((file = mongoc_gridfs_file_list_next(list))) {
                   const char *name = mongoc_gridfs_file_get_filename(file);
                   printf("%s\n", name ? name : "?");

                   mongoc_gridfs_file_destroy(file);
                }

                mongoc_gridfs_file_list_destroy(list);
             } else if (strcmp(command, "write") == 0) {
                if (argc != 4) {
                   fprintf(stderr, "usage - %s write filename input_file\n", argv[0]);
                   return EXIT_FAILURE;
                }

                stream = mongoc_stream_file_new_for_path(argv[3], O_RDONLY, 0);
                assert(stream);

                opt.filename = filename;

                /* the driver generates a file_id for you */
                file = mongoc_gridfs_create_file_from_stream(gridfs, stream, &opt);
                assert(file);

                id.value_type = BSON_TYPE_INT32;
                id.value.v_int32 = 1;

                /* optional: the following method specifies a file_id of any
                   BSON type */
                if (!mongoc_gridfs_file_set_id(file, &id, &error)) {
                   fprintf(stderr, "%s\n", error.message);
                   return EXIT_FAILURE;
                }

                if (!mongoc_gridfs_file_save(file)) {
                   mongoc_gridfs_file_error(file, &error);
                   fprintf(stderr, "Could not save: %s\n", error.message);
                   return EXIT_FAILURE;
                }

                mongoc_gridfs_file_destroy(file);
             } else {
                fprintf(stderr, "Unknown command");
                return EXIT_FAILURE;
             }

             mongoc_gridfs_destroy(gridfs);
             mongoc_uri_destroy(uri);
             mongoc_client_destroy(client);

             mongoc_cleanup();

             return EXIT_SUCCESS;
          }

       See also:
          The MongoDB GridFS specification <https://github.com/mongodb/specifications/blob/master/source/gridfs/gridfs-spec.md>.

          The spec-compliant mongoc_gridfs_bucket_t <>.

   mongoc_host_list_t
   Synopsis
          typedef struct {
             mongoc_host_list_t *next;
             char host[BSON_HOST_NAME_MAX + 1];
             char host_and_port[BSON_HOST_NAME_MAX + 7];
             uint16_t port;
             int family;
             void *padding[4];
          } mongoc_host_list_t;

   Description
       The  host  and  port  of  a MongoDB server. Can be part of a linked list: for example the return value of
       mongoc_uri_get_hosts() <> when multiple hosts are provided in the MongoDB URI.

       See also:
          mongoc_uri_get_hosts() <> and mongoc_cursor_get_host() <>.

   mongoc_insert_flags_t
       Flags for insert operations

   Synopsis
          typedef enum {
             MONGOC_INSERT_NONE = 0,
             MONGOC_INSERT_CONTINUE_ON_ERROR = 1 << 0,
          } mongoc_insert_flags_t;

          #define MONGOC_INSERT_NO_VALIDATE (1U << 31)

   Description
       These flags correspond to the MongoDB wire protocol. They may be bitwise or'd together. They  may  modify
       how an insert happens on the MongoDB server.

   Flag Values
                     ┌─────────────────────────────────┬───────────────────────────────────────┐
                     │ MONGOC_INSERT_NONE              │ Specify no insert flags.              │
                     ├─────────────────────────────────┼───────────────────────────────────────┤
                     │ MONGOC_INSERT_CONTINUE_ON_ERROR │ Continue inserting documents from the │
                     │                                 │ insertion  set  even  if  one  insert │
                     │                                 │ fails.                                │
                     ├─────────────────────────────────┼───────────────────────────────────────┤
                     │ MONGOC_INSERT_NO_VALIDATE       │ Do not validate  insertion  documents │
                     │                                 │ before    performing    an    insert. │
                     │                                 │ Validation can be expensive, so  this │
                     │                                 │ can  save  some time if you know your │
                     │                                 │ documents are already valid.          │
                     └─────────────────────────────────┴───────────────────────────────────────┘

   mongoc_iovec_t
   Synopsis
   Synopsis
          #include <mongoc/mongoc.h>

          #ifdef _WIN32
          typedef struct {
             u_long iov_len;
             char *iov_base;
          } mongoc_iovec_t;
          #else
          typedef struct iovec mongoc_iovec_t;
          #endif

       The mongoc_iovec_t structure is a  portability  abstraction  for  consumers  of  the  mongoc_stream_t  <>
       interfaces. It allows for scatter/gather I/O through the socket subsystem.

       Warning:
          When  writing  portable  code, beware of the ordering of iov_len and iov_base as they are different on
          various platforms. Therefore, you should not use C initializers for initialization.

   mongoc_oidc_callback_fn_t
   Synopsis
          typedef mongoc_oidc_credential_t *(*mongoc_oidc_callback_fn_t) (mongoc_oidc_callback_params_t *params);

       The type of the function pointer stored by mongoc_oidc_callback_t <>.

   Parametersparams:   A   mongoc_oidc_callback_params_t   <>   object   representing   in/out   parameters   of   a
         mongoc_oidc_callback_t <>.

   Returns
       A mongoc_oidc_credential_t <> object created with mongoc_oidc_credential_new() <>, or NULL to indicate an
       error or timeout.

       • The function MUST return a mongoc_oidc_credential_t <> object to indicate success.

       • The function MUST return NULL to indicate an error.

       • The  function  MUST  call mongoc_oidc_callback_params_cancel_with_timeout() <> before returning NULL to
         indicate a timeout instead of an error.

       The cancel_with_timeout out parameter is ignored if the return value is not NULL.

       See also:

          • mongoc_oidc_callback_t <>

          • mongoc_oidc_callback_params_t <>

          • mongoc_oidc_credential_t <>

   mongoc_oidc_callback_params_t
   Synopsis
          typedef struct _mongoc_oidc_callback_params_t mongoc_oidc_callback_params_t;

       Represents the in/out parameters of a mongoc_oidc_callback_t <>.

       The parameters will be passed to the mongoc_oidc_callback_fn_t <> stored in an mongoc_oidc_callback_t  <>
       object when it is invoked by an mongoc_client_t <> or mongoc_client_pool_t <> object.

   Parameters
       The list of currently supported parameters are:
                          ┌─────────────────────┬──────────┬──────────────────────────────┐
                          │ Parameter           │ Versions │ Description                  │
                          ├─────────────────────┼──────────┼──────────────────────────────┤
                          │ version             │ 1        │ The  current  OIDC  callback │
                          │                     │          │ API version number.          │
                          ├─────────────────────┼──────────┼──────────────────────────────┤
                          │ user_data           │ 1        │ A pointer to  data  provided │
                          │                     │          │ by the user.                 │
                          ├─────────────────────┼──────────┼──────────────────────────────┤
                          │ timeout             │ 1        │ The  timestamp  after  which │
                          │                     │          │ the callback  function  must │
                          │                     │          │ report a timeout.            │
                          ├─────────────────────┼──────────┼──────────────────────────────┤
                          │ username            │ 1        │ The  username  specified  by │
                          │                     │          │ the URI  of  the  associated │
                          │                     │          │ client object.               │
                          ├─────────────────────┼──────────┼──────────────────────────────┤
                          │ cancel_with_timeout │ 1        │ An  out parameter indicating │
                          │                     │          │ cancellation of the callback │
                          │                     │          │ function due  to  a  timeout │
                          │                     │          │ instead of an error.         │
                          └─────────────────────┴──────────┴──────────────────────────────┘

       The "Version" column indicates the OIDC callback API versions for which the parameter is applicable.

   Version
       The  version  parameter is used to communicate backward compatible changes to the OIDC callback API (i.e.
       the addition of a new parameter).

       This parameter may be used to detect when existing usage  of  mongoc_oidc_callback_t  <>  or  a  relevant
       callback function may need to be reviewed.

       For example, users may add the following check to their callback function:

          mongoc_oidc_credential_t *
          example_callback_fn (mongoc_oidc_callback_params_t *params)
          {
             // A runtime message that new features are available in the OIDC Callback API.
             if (mongoc_oidc_callback_params_get_version (params) > 1) {
                printf ("OIDC Callback API has been updated to a new version!");
             }

             // ...
          }

   User Data
       The  user_data  parameter  may be used to pass additional arguments to the callback function or to return
       additional values out of the callback function.

       This  parameter  must  be  set  in  advance  via  mongoc_oidc_callback_set_user_data()  <>   before   the
       mongoc_oidc_callback_t  <>  object  is  associated  with  a mongoc_client_t <> or mongoc_client_pool_t <>
       object.

       Warning:
          The lifetime of the object pointed to by user_data is managed the user, not by  mongoc_oidc_callback_t
          <>!

          typedef struct {
             int counter;
             const char *error_message;
          } user_data_t;

          mongoc_oidc_credential_t *
          example_callback_fn (mongoc_oidc_callback_params_t *params)
          {
             user_data_t *user_data = (user_data_t *) mongoc_oidc_callback_params_get_user_data (params);

             user_data->counter += 1;

             // ...

             if (/* ... */) {
                user_data->error_message = "OIDC callback failed due to ...";
                return NULL;
             }

             // ...
          }

          void
          example (void)
          {
             mongoc_client_t *client = /* ... */;
             bson_error_t error;

             {
                user_data_t *user_data = malloc (sizeof (*user_data));
                *user_data = (user_data_t){.counter = 0, .error_message = NULL};
                mongoc_oidc_callback_t *callback = mongoc_oidc_callback_new_with_user_data (&example_callback_fn, (void *) user_data);
                BSON_ASSERT (mongoc_client_set_oidc_callback (client, callback));
                mongoc_oidc_callback_destroy (callback);
             }

             // ... client operations ...

             {
                const mongoc_oidc_callback_t *callback = mongoc_client_get_oidc_callback (client);
                user_data_t *user_data = (user_data_t *) mongoc_oidc_callback_get_user_data (callback);

                if (error.code != 0) {
                   printf ("client error message: %s\n", error.message);
                }

                if (user_data->error_message) {
                   printf ("custom error message: %s\n", user_data->error_message);
                }

                printf ("The callback function was invoked %d times!", user_data->counter);

                free (user_data);
             }

             mongoc_client_destroy (client);
          }

   Timeout
       The timeout parameter is used to determine when the callback function should report cancellation due to a
       timeout.

       When  System  Clock <https://www.mongoc.org/libbson/current/bson_get_monotonic_time.html> is greater than
       timeout, the callback  function  must  invoke  mongoc_oidc_callback_params_cancel_with_timeout()  <>  and
       return NULL.

   Username
       The  username  parameter  is  the  value  of  the  username  component  of  the  URI  of  the  associated
       mongoc_client_t <> or mongoc_client_pool_t <> object from which the callback function is invoked.

   Cancel With Timeout
       The cancel_with_timeout out parameter indicates cancellation of the callback function due  to  a  timeout
       instead of an error.

       Important:
          The callback function MUST return NULL, otherwise the invocation will be interpreted as a success even
          when cancel_with_timeout is set.

          mongoc_oidc_credential_t *
          example_callback_fn (mongoc_oidc_callback_params_t *params) {
             const int64_t *timeout = mongoc_oidc_callback_params_get_timeout (params);

             // NULL means "infinite" timeout.
             if (timeout && bson_get_monotonic_time () > *timeout) {
                return mongoc_oidc_callback_params_cancel_with_timeout (params);
             }

             // ...
          }

   Error Handling
       A  NULL  return  value (without setting cancel_with_timeout) indicates failure to provide an access token
       due to an error.

       Important:
          The callback function MUST return NULL, otherwise the invocation will be interpreted as a success.

          mongoc_oidc_credential_t *
          example_callback_fn (mongoc_oidc_callback_params_t *params) {
             // ...

             if (/* ... */) {
                // The OIDC callback function could not provide an access token due to an error.
                return NULL;
             }

             // ...
          }

       See also:

          • mongoc_oidc_callback_t <>

          • mongoc_oidc_callback_fn_t <>

   mongoc_oidc_callback_t
   Synopsis
          typedef struct _mongoc_oidc_callback_t mongoc_oidc_callback_t;

       mongoc_oidc_callback_t <> represents a user-defined callback function mongoc_oidc_callback_fn_t  <>  that
       returns an OIDC access token.

       The callback may be used to integrate with OIDC providers that are not supported by the built-in provider
       integrations (Authentication Mechanism Properties <#authentication-mechanism-properties>).

   Lifecycle
       The  function  and  optional  user  data  stored by mongoc_oidc_callback_t <> must outlive any associated
       client or client pool object which may invoke the stored callback function.

   Thread Safety
       The callback function stored by a mongoc_oidc_callback_t <> object will be invoked by at most one  thread
       at a time for an associated mongoc_client_t <> or mongoc_client_pool_t <> object:

          static mongoc_oidc_credential_t *
          single_thread_only (mongoc_oidc_callback_params_t *params)
          {
             // This function does not need to support invocation by more than thread at a time.

             // ...
          }

          void
          with_single_client (void)
          {
             mongoc_client_t *client = /* ... */;

             {
                mongoc_oidc_callback_t *callback = mongoc_oidc_callback_new (&single_thread_only);
                BSON_ASSERT (mongoc_client_set_oidc_callback (client, callback));
                mongoc_oidc_callback_destroy (callback);
             }

             // ... client operations ...

             mongoc_client_destroy (client);
          }

          void
          with_single_pool (void)
          {
             mongoc_client_pool_t *pool = /* ... */;

             {
                mongoc_oidc_callback_t *callback = mongoc_oidc_callback_new (&single_thread_only);
                BSON_ASSERT (mongoc_client_pool_set_oidc_callback (pool, callback));
                mongoc_oidc_callback_destroy (callback);
             }

             // ... client pool operations ...

             mongoc_client_pool_destroy (pool);
          }

       If the callback is associated with more than one mongoc_client_t <> object (in multiple threads), or with
       more  than  one  mongoc_client_pool_t  <>  object  (even  in a single thread), the callback function MUST
       support invocation by more than one thread at a time:

          static mongoc_oidc_credential_t *
          many_threads_possible (mongoc_oidc_callback_params_t *params)
          {
             // This function MUST support invocation by more than one thread at a time.

             // ...
          }

          void
          with_many_clients (void)
          {
             mongoc_client_t *client_a = /* ... */;
             mongoc_client_t *client_b = /* ... */;

             {
                mongoc_oidc_callback_t *callback = mongoc_oidc_callback_new (&many_threads_possible);
                BSON_ASSERT (mongoc_client_set_oidc_callback (client_a, callback));
                BSON_ASSERT (mongoc_client_set_oidc_callback (client_b, callback));
                mongoc_oidc_callback_destroy (callback);
             }

             pthread_t thread_a;
             pthread_t thread_b;

             if (pthread_create (&thread_a, NULL, /* thread_a_fn */, client_a) != 0) { /* ... */ }
             if (pthread_create (&thread_b, NULL, /* thread_b_fn */, client_b) != 0) { /* ... */ }

             // ... client operations using multiple threads ...

             if (pthread_join (&thread_a, NULL) != 0) { /* ... */ }
             if (pthread_join (&thread_b, NULL) != 0) { /* ... */ }

             mongoc_client_destroy (client_a);
             mongoc_client_destroy (client_b);
          }

          void
          with_many_pools (void)
          {
             mongoc_client_pool_t *pool_a = /* ... */;
             mongoc_client_pool_t *pool_b = /* ... */;

             {
                mongoc_oidc_callback_t *callback = mongoc_oidc_callback_new (&many_threads_possible);
                BSON_ASSERT (mongoc_client_pool_set_oidc_callback (pool_a, callback));
                BSON_ASSERT (mongoc_client_pool_set_oidc_callback (pool_b, callback));
                mongoc_oidc_callback_destroy (callback);
             }

             // ... client operations using multiple client pools ...

             mongoc_client_pool_destroy (pool_a);
             mongoc_client_pool_destroy (pool_b);
          }

       See also:

          • mongoc_client_t <>

          • mongoc_client_pool_t <>

          • mongoc_oidc_callback_fn_t <>

          • mongoc_oidc_callback_params_t <>

          • mongoc_oidc_credential_t <>

   mongoc_oidc_credential_t
   Synopsis
          typedef struct _mongoc_oidc_credential_t mongoc_oidc_credential_t;

       Represents the return value of a mongoc_oidc_callback_fn_t <>.

       The value will be returned by the mongoc_oidc_callback_fn_t <> stored  in  an  mongoc_oidc_callback_t  <>
       object when it is invoked by an associated mongoc_client_t <> or mongoc_client_pool_t <> object.

   Return Values
       The list of currently supported return values are:
                              ┌──────────────┬──────────┬──────────────────────────────┐
                              │ Value        │ Versions │ Description                  │
                              ├──────────────┼──────────┼──────────────────────────────┤
                              │ access_token │ 1        │ The OIDC access token.       │
                              ├──────────────┼──────────┼──────────────────────────────┤
                              │ expires_in   │ 1        │ An    optional    expiration │
                              │              │          │ duration (in milliseconds).  │
                              └──────────────┴──────────┴──────────────────────────────┘

       The "Version" column indicates the OIDC callback API versions for which the parameter is applicable.

   Access Token
       An OIDC access token (a signed JWT token).

       Warning:
          access_token is NOT directly validated by the driver.

   Expiry Duration
       An optional expiry duration (in milliseconds) for the access token.

       Important:
          An unset value is interpreted as an infinite expiry duration.

       See also:

          • mongoc_oidc_callback_t <>

          • mongoc_oidc_callback_fn_t <>

   mongoc_optional_t
       A struct to store optional boolean values.

   Synopsis
       Used to specify optional boolean flags, which may remain unset.

       This is used within mongoc_server_api_t <> to track whether a flag was explicitly set.

   mongoc_query_flags_t
       Flags for query operations

   Synopsis
          typedef enum {
             MONGOC_QUERY_NONE = 0,
             MONGOC_QUERY_TAILABLE_CURSOR = 1 << 1,
             MONGOC_QUERY_SECONDARY_OK = 1 << 2,
             MONGOC_QUERY_OPLOG_REPLAY = 1 << 3,
             MONGOC_QUERY_NO_CURSOR_TIMEOUT = 1 << 4,
             MONGOC_QUERY_AWAIT_DATA = 1 << 5,
             MONGOC_QUERY_EXHAUST = 1 << 6,
             MONGOC_QUERY_PARTIAL = 1 << 7,
          } mongoc_query_flags_t;

   Description
       These flags correspond to the MongoDB wire protocol. They may be bitwise or'd together. They  may  modify
       how a query is performed in the MongoDB server.

   Flag Values
                      ┌────────────────────────────────┬───────────────────────────────────────┐
                      │ MONGOC_QUERY_NONE              │ Specify no query flags.               │
                      ├────────────────────────────────┼───────────────────────────────────────┤
                      │ MONGOC_QUERY_TAILABLE_CURSOR   │ Cursor  will  not  be closed when the │
                      │                                │ last  data  is  retrieved.  You   can │
                      │                                │ resume this cursor later.             │
                      ├────────────────────────────────┼───────────────────────────────────────┤
                      │ MONGOC_QUERY_SECONDARY_OK      │ Allow    query    of    replica   set │
                      │                                │ secondaries.                          │
                      ├────────────────────────────────┼───────────────────────────────────────┤
                      │ MONGOC_QUERY_OPLOG_REPLAY      │ Used internally by MongoDB.           │
                      ├────────────────────────────────┼───────────────────────────────────────┤
                      │ MONGOC_QUERY_NO_CURSOR_TIMEOUT │ The server normally times out an idle │
                      │                                │ cursor after an inactivity period (10 │
                      │                                │ minutes). This prevents that.         │
                      ├────────────────────────────────┼───────────────────────────────────────┤
                      │ MONGOC_QUERY_AWAIT_DATA        │ Use                              with │
                      │                                │ MONGOC_QUERY_TAILABLE_CURSOR.   Block │
                      │                                │ rather than returning no data.  After │
                      │                                │ a period, time out.                   │
                      ├────────────────────────────────┼───────────────────────────────────────┤
                      │ MONGOC_QUERY_EXHAUST           │ Unused.                               │
                      ├────────────────────────────────┼───────────────────────────────────────┤
                      │ MONGOC_QUERY_PARTIAL           │ Get  partial  results  from mongos if │
                      │                                │ some  shards  are  down  (instead  of │
                      │                                │ throwing an error).                   │
                      └────────────────────────────────┴───────────────────────────────────────┘

   mongoc_rand
       MongoDB Random Number Generator

   Synopsis
          void
          mongoc_rand_add (const void *buf, int num, double entropy);

          void
          mongoc_rand_seed (const void *buf, int num);

          int
          mongoc_rand_status (void);

   Description
       The  mongoc_rand  family  of  functions provide access to the low level randomness primitives used by the
       MongoDB C Driver.  In particular, they control the creation  of  cryptographically  strong  pseudo-random
       bytes required by some security mechanisms.

       While  we  can  usually  pull  enough  entropy from the environment, you may be required to seed the PRNG
       manually depending on your OS, hardware and other entropy consumers running on the same system.

   Entropy
       mongoc_rand_add and mongoc_rand_seed allow the user to directly provide entropy.  They differ insofar  as
       mongoc_rand_seed  requires  that  each  bit provided is fully random.  mongoc_rand_add allows the user to
       specify the degree of randomness in the provided bytes as well.

   Status
       The mongoc_rand_status function allows the user to check the status of the mongoc PRNG.  This can be used
       to guarantee sufficient entropy at program startup, rather than waiting for runtime errors to occur.

   mongoc_read_concern_t
       Read Concern abstraction

   Synopsis
       New in MongoDB 3.2.

       The mongoc_read_concern_t allows clients to choose a level of isolation for  their  reads.  The  default,
       MONGOC_READ_CONCERN_LEVEL_LOCAL, is right for the great majority of applications.

       You can specify a read concern on connection objects, database objects, or collection objects.

       See  readConcern  <https://www.mongodb.com/docs/master/reference/readConcern/> on the MongoDB website for
       more information.

       Read Concern is only sent to MongoDB when it has explicitly been set  by  mongoc_read_concern_set_level()
       <> to anything other than NULL.

   Read Concern Levels
           ┌────────────────────────────────────────┬─────────────────────────────┬───────────────────────┐
           │ Macro                                  │ Description                 │ First MongoDB version │
           ├────────────────────────────────────────┼─────────────────────────────┼───────────────────────┤
           │ MONGOC_READ_CONCERN_LEVEL_LOCAL        │ Level "local", the default. │ 3.2                   │
           ├────────────────────────────────────────┼─────────────────────────────┼───────────────────────┤
           │ MONGOC_READ_CONCERN_LEVEL_MAJORITY     │ Level "majority".           │ 3.2                   │
           ├────────────────────────────────────────┼─────────────────────────────┼───────────────────────┤
           │ MONGOC_READ_CONCERN_LEVEL_LINEARIZABLE │ Level "linearizable".       │ 3.4                   │
           ├────────────────────────────────────────┼─────────────────────────────┼───────────────────────┤
           │ MONGOC_READ_CONCERN_LEVEL_AVAILABLE    │ Level "available".          │ 3.6                   │
           ├────────────────────────────────────────┼─────────────────────────────┼───────────────────────┤
           │ MONGOC_READ_CONCERN_LEVEL_SNAPSHOT     │ Level "snapshot".           │ 4.0                   │
           └────────────────────────────────────────┴─────────────────────────────┴───────────────────────┘

       For  the sake of compatibility with future versions of MongoDB, mongoc_read_concern_set_level() <> allows
       any string, not just this list of known read concern levels.

       See Read Concern Levels <https://www.mongodb.com/docs/manual/reference/read-concern/#read-concern-levels>
       in the MongoDB manual for more information about the individual read concern levels.

   mongoc_read_mode_t
       Read Preference Modes

   Synopsis
          typedef enum {
             MONGOC_READ_PRIMARY = (1 << 0),
             MONGOC_READ_SECONDARY = (1 << 1),
             MONGOC_READ_PRIMARY_PREFERRED = (1 << 2) | MONGOC_READ_PRIMARY,
             MONGOC_READ_SECONDARY_PREFERRED = (1 << 2) | MONGOC_READ_SECONDARY,
             MONGOC_READ_NEAREST = (1 << 3) | MONGOC_READ_SECONDARY,
          } mongoc_read_mode_t;

   Description
       This enum describes how reads should be dispatched. The default is MONGOC_READ_PRIMARY.

       Please see the MongoDB website for  a  description  of  Read  Preferences  <https://www.mongodb.com/docs/
       manual/core/read-preference/>.

   mongoc_read_prefs_t
       A read preference abstraction

   Synopsis
       mongoc_read_prefs_t  <>  provides  an  abstraction  on top of the MongoDB connection read preferences. It
       allows for hinting to the driver which nodes in a replica set should be accessed first and how.

       You can specify a read preference mode on connection objects, database objects,  collection  objects,  or
       per-operation.    Generally,   it   makes  the  most  sense  to  stick  with  the  global  default  mode,
       MONGOC_READ_PRIMARY.  All of the other modes come with caveats that won't  be  covered  in  great  detail
       here.

   Read Modes
                     ┌─────────────────────────────────┬───────────────────────────────────────┐
                     │ MONGOC_READ_PRIMARY             │ Default  mode.  All  operations  read │
                     │                                 │ from the current replica set primary. │
                     ├─────────────────────────────────┼───────────────────────────────────────┤
                     │ MONGOC_READ_SECONDARY           │ All operations read  from  among  the │
                     │                                 │ nearest   secondary  members  of  the │
                     │                                 │ replica set.                          │
                     ├─────────────────────────────────┼───────────────────────────────────────┤
                     │ MONGOC_READ_PRIMARY_PREFERRED   │ In most situations,  operations  read │
                     │                                 │ from   the   primary  but  if  it  is │
                     │                                 │ unavailable,  operations  read   from │
                     │                                 │ secondary members.                    │
                     ├─────────────────────────────────┼───────────────────────────────────────┤
                     │ MONGOC_READ_SECONDARY_PREFERRED │ In  most  situations, operations read │
                     │                                 │ from  among  the  nearest   secondary │
                     │                                 │ members,  but  if  no secondaries are │
                     │                                 │ available, operations read  from  the │
                     │                                 │ primary.                              │
                     ├─────────────────────────────────┼───────────────────────────────────────┤
                     │ MONGOC_READ_NEAREST             │ Operations   read   from   among  the │
                     │                                 │ nearest members of the  replica  set, │
                     │                                 │ irrespective of the member's type.    │
                     └─────────────────────────────────┴───────────────────────────────────────┘

   Tag Sets
       Tag  sets  allow  you  to specify custom read preferences and write concerns so that your application can
       target operations to specific members.

       Custom read preferences and write concerns  evaluate  tags  sets  in  different  ways:  read  preferences
       consider  the  value of a tag when selecting a member to read from, while write concerns ignore the value
       of a tag when selecting a member, except to consider whether or not the value is unique.

       You can specify tag sets with the following read preference modes:

       • primaryPreferred

       • secondary

       • secondaryPreferred

       • nearest

       Tags are not compatible with MONGOC_READ_PRIMARY and, in general, only apply when selecting  a  secondary
       member  of a set for a read operation. However, the nearest read mode, when combined with a tag set, will
       select the nearest member that matches the specified tag set, which may be a primary or secondary.

       Tag sets are represented as a comma-separated list of colon-separated key-value pairs when provided as  a
       connection string, e.g. dc:ny,rack:1.

       To specify a list of tag sets, using multiple readPreferenceTags, e.g.

          readPreferenceTags=dc:ny,rack:1;readPreferenceTags=dc:ny;readPreferenceTags=

       Note the empty value for the last one, which means "match any secondary as a last resort".

       Order matters when using multiple readPreferenceTags.

       Tag Sets can also be configured using mongoc_read_prefs_set_tags() <>.

       All  interfaces  use  the  same  member  selection  logic  to  choose  the member to which to direct read
       operations, basing the choice on read preference mode and tag sets.

   Max Staleness
       When connected to replica set running MongoDB 3.4 or later, the driver estimates the  staleness  of  each
       secondary based on lastWriteDate values provided in server hello responses.

       Max Staleness is the maximum replication lag in seconds (wall clock time) that a secondary can suffer and
       still  be  eligible  for  reads. The default is MONGOC_NO_MAX_STALENESS, which disables staleness checks.
       Otherwise, it must be a positive integer at least MONGOC_SMALLEST_MAX_STALENESS_SECONDS (90 seconds).

       Max Staleness is also supported by sharded clusters of replica sets if all servers  run  MongoDB  3.4  or
       later.

   Hedged Reads
       Deprecated since version MongoDB: Server 8.0

       Hedged reads are deprecated in MongoDB version 8.0 and will be removed in a future release.

       When  connecting  to a sharded cluster running MongoDB 4.4 or later, reads can be sent in parallel to the
       two "best" hosts. Once one result returns, any other outstanding operations that were part of the  hedged
       read are cancelled.

       When  the  read  preference mode is MONGOC_READ_NEAREST and the sharded cluster is running MongoDB 4.4 or
       later, hedged reads are enabled by default.  Additionally, hedged reads  may  be  explicitly  enabled  or
       disabled by calling mongoc_read_prefs_set_hedge() <> with a BSON document, e.g.

          {
             enabled: true
          }

       Appropriate values for the enabled key are true or false.

   mongoc_remove_flags_t
       Flags for deletion operations

   Synopsis
          typedef enum {
             MONGOC_REMOVE_NONE = 0,
             MONGOC_REMOVE_SINGLE_REMOVE = 1 << 0,
          } mongoc_remove_flags_t;

   Description
       These  flags  correspond to the MongoDB wire protocol. They may be bitwise or'd together. They may change
       the number of documents that are removed during a remove command.

   Flag Values
                       ┌─────────────────────────────┬───────────────────────────────────────┐
                       │ MONGOC_REMOVE_NONE          │ Specify   no   removal   flags.   All │
                       │                             │ matching documents will be removed.   │
                       ├─────────────────────────────┼───────────────────────────────────────┤
                       │ MONGOC_REMOVE_SINGLE_REMOVE │ Only   remove   the   first  matching │
                       │                             │ document from the selector.           │
                       └─────────────────────────────┴───────────────────────────────────────┘

   mongoc_server_api_t
       A versioned API to use for connections.

   Synopsis
       Used to specify which version of the MongoDB server's API to use for driver connections.

       The server API type takes a mongoc_server_api_version_t <>. It can optionally be strict about the list of
       allowed commands in that API version, and can also optionally provide errors for deprecated  commands  in
       that API version.

       A  mongoc_server_api_t  <> can be set on a client, and will then be sent to MongoDB for most commands run
       using that client.

   mongoc_server_api_version_t
       A representation of server API version numbers.

   Synopsis
       Used to specify which version of the MongoDB server's API to use for driver connections.

   Supported API Versions
       The driver currently supports the following MongoDB API versions:
                                  ┌──────────────────────┬────────────────────────┐
                                  │ Enum value           │ MongoDB version string │
                                  ├──────────────────────┼────────────────────────┤
                                  │ MONGOC_SERVER_API_V1 │ "1"                    │
                                  └──────────────────────┴────────────────────────┘

   mongoc_server_description_t
       Server description

   Synopsis
          #include <mongoc/mongoc.h>
          typedef struct _mongoc_server_description_t mongoc_server_description_t

       mongoc_server_description_t holds information about a mongod or mongos the driver is connected to.

   Lifecycle
       Clean up a mongoc_server_description_t with mongoc_server_description_destroy() <> when necessary.

       Applications receive a temporary reference to a mongoc_server_description_t as a  parameter  to  an  SDAM
       Monitoring  callback  that  must not be destroyed. See Introduction to Application Performance Monitoring
       <>.

       See also:
          mongoc_client_get_server_descriptions() <>.

   mongoc_session_opt_t
          #include <mongoc/mongoc.h>

          typedef struct _mongoc_session_opt_t mongoc_session_opt_t;

   Synopsis
       Start a session with mongoc_client_start_session() <>, use the session for a sequence of  operations  and
       multi-document transactions, then free it with mongoc_client_session_destroy() <>. Any mongoc_cursor_t <>
       or  mongoc_change_stream_t <> using a session must be destroyed before the session, and a session must be
       destroyed before the mongoc_client_t <> it came from.

       By    default,    sessions    are    causally    consistent    <https://www.mongodb.com/docs/manual/core/
       read-isolation-consistency-recency/#causal-consistency>. To disable causal consistency, before starting a
       session    create    a    mongoc_session_opt_t    <>   with   mongoc_session_opts_new()   <>   and   call
       mongoc_session_opts_set_causal_consistency() <>, then free the struct with  mongoc_session_opts_destroy()
       <>.

       Unacknowledged writes are prohibited with sessions.

       A  mongoc_client_session_t  <>  must  be  used  by  only  one  thread  at a time. Due to session pooling,
       mongoc_client_start_session() <> may return a session that has been idle for some time and is about to be
       closed after its idle timeout. Use the session within one minute of acquiring it to refresh  the  session
       and avoid a timeout.

       See the example code for mongoc_session_opts_set_causal_consistency() <>.

   mongoc_socket_t
       Portable socket abstraction

   Synopsis
          #include <mongoc/mongoc.h>

          typedef struct _mongoc_socket_t mongoc_socket_t

   Synopsis
       This  structure  provides  a  socket  abstraction  that  is  friendlier  for portability than BSD sockets
       directly. Inconsistencies between Linux, various BSDs, Solaris, and Windows are handled here.

   mongoc_ssl_opt_t
   Synopsis
          typedef struct {
             const char *pem_file;
             const char *pem_pwd;
             const char *ca_file;
             const char *ca_dir;
             const char *crl_file;
             bool weak_cert_validation;
             bool allow_invalid_hostname;
             void *internal;
             void *padding[6];
          } mongoc_ssl_opt_t;

       Note:
          Though some API names include the term "ssl", the C driver only support TLS protocols, which supersede
          SSL.

   Description
       This structure is used to set the TLS options for a mongoc_client_t <> or mongoc_client_pool_t <>.

       Beginning in version 1.2.0, once a pool or client has any TLS options set, all connections use TLS,  even
       if  ssl=true  is  omitted  from  the  MongoDB  URI.  Before, TLS options were ignored unless tls=true was
       included in the URI.

       As of 1.4.0, the mongoc_client_pool_set_ssl_opts() <> and mongoc_client_set_ssl_opts() <> will  not  only
       shallow  copy  the  struct,  but will also copy the const char*. It is therefore no longer needed to make
       sure the values remain valid after setting them.

       See also:
          Configuring TLS <https://www.mongodb.com/docs/languages/c/c-driver/current/libmongoc/guides/configuring_tls/>

          mongoc_client_set_ssl_opts() <>

          mongoc_client_pool_set_ssl_opts() <>

   mongoc_stream_buffered_t
   Synopsis
          typedef struct _mongoc_stream_buffered_t mongoc_stream_buffered_t;

   Description
       mongoc_stream_buffered_t should be considered a subclass of mongoc_stream_t <>. It performs buffering  on
       an underlying stream.

       See also:
          mongoc_stream_buffered_new() <>

          mongoc_stream_destroy() <>

   mongoc_stream_file_t
   Synopsis
          typedef struct _mongoc_stream_file_t mongoc_stream_file_t

       mongoc_stream_file_t   is   a   mongoc_stream_t   <>  subclass  for  working  with  standard  UNIX  style
       file-descriptors.

   mongoc_stream_socket_t
   Synopsis
          typedef struct _mongoc_stream_socket_t mongoc_stream_socket_t

       mongoc_stream_socket_t should be considered a subclass of  mongoc_stream_t  <>  that  works  upon  socket
       streams.

   mongoc_stream_t
   Synopsis
          typedef struct _mongoc_stream_t mongoc_stream_t

       mongoc_stream_t  provides a generic streaming IO abstraction based on a struct of pointers interface. The
       idea is to allow wrappers, perhaps other language drivers, to easily shim  their  IO  system  on  top  of
       mongoc_stream_t.

       The API for the stream abstraction is currently private and non-extensible.

   Stream Types
       There  are  a  number  of  built  in  stream  types that come with mongoc. The default configuration is a
       buffered unix stream. If TLS is in use, that in turn is wrapped in a tls stream.

       See also:
          mongoc_stream_buffered_t <>

          mongoc_stream_file_t <>

          mongoc_stream_socket_t <>

          mongoc_stream_tls_t <>

   mongoc_stream_tls_t
   Synopsis
          typedef struct _mongoc_stream_tls_t mongoc_stream_tls_t

       mongoc_stream_tls_t is a mongoc_stream_t <> subclass for working with TLS streams.

   mongoc_topology_description_t
       Status of MongoDB Servers

   Synopsis
          typedef struct _mongoc_topology_description_t mongoc_topology_description_t;

       mongoc_topology_description_t is an opaque type representing the driver's knowledge of the MongoDB server
       or servers it is connected to.  Its API conforms to the  SDAM  Monitoring  Specification  <https://github
       .com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-
       monitoring.md>.

       Applications  receive  a temporary reference to a mongoc_topology_description_t as a parameter to an SDAM
       Monitoring callback that must not be destroyed. See Introduction to  Application  Performance  Monitoring
       <>.

   mongoc_transaction_opt_t
          #include <mongoc/mongoc.h>

          typedef struct _mongoc_transaction_opt_t mongoc_transaction_opt_t;

   Synopsis
       Options for starting a multi-document transaction.

       When  a  session  is first created with mongoc_client_start_session() <>, it inherits from the client the
       read concern, write concern, and read preference with which to start transactions. Each of  these  fields
       can  be overridden independently. Create a mongoc_transaction_opt_t <> with mongoc_transaction_opts_new()
       <>, and pass a non-NULL option to any of the mongoc_transaction_opt_t <> setter functions:

       • mongoc_transaction_opts_set_read_concern() <>

       • mongoc_transaction_opts_set_write_concern() <>

       • mongoc_transaction_opts_set_read_prefs() <>

       Pass the resulting transaction options to mongoc_client_session_start_transaction() <>. Each field set in
       the transaction options overrides the inherited client configuration.

   Example
       example-transaction.c

          /* gcc example-transaction.c -o example-transaction \
           *     $(pkg-config --cflags --libs libmongoc-1.0) */

          /* ./example-transaction [CONNECTION_STRING] */

          #include <mongoc/mongoc.h>

          #include <stdio.h>

          int
          main(int argc, char *argv[])
          {
             int exit_code = EXIT_FAILURE;

             mongoc_client_t *client = NULL;
             mongoc_database_t *database = NULL;
             mongoc_collection_t *collection = NULL;
             mongoc_client_session_t *session = NULL;
             mongoc_session_opt_t *session_opts = NULL;
             mongoc_transaction_opt_t *default_txn_opts = NULL;
             mongoc_transaction_opt_t *txn_opts = NULL;
             mongoc_read_concern_t *read_concern = NULL;
             mongoc_write_concern_t *write_concern = NULL;
             const char *uri_string = "mongodb://127.0.0.1/?appname=transaction-example";
             mongoc_uri_t *uri;
             bson_error_t error;
             bson_t *doc = NULL;
             bson_t *insert_opts = NULL;
             int32_t i;
             int64_t start;
             bson_t reply = BSON_INITIALIZER;
             char *reply_json;
             bool r;

             mongoc_init();

             if (argc > 1) {
                uri_string = argv[1];
             }

             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                MONGOC_ERROR("failed to parse URI: %s\n"
                             "error message:       %s\n",
                             uri_string,
                             error.message);
                goto done;
             }

             client = mongoc_client_new_from_uri(uri);
             if (!client) {
                goto done;
             }

             mongoc_client_set_error_api(client, 2);
             database = mongoc_client_get_database(client, "example-transaction");

             /* inserting into a nonexistent collection normally creates it, but a
              * collection can't be created in a transaction; create it now */
             collection = mongoc_database_create_collection(database, "collection", NULL, &error);

             if (!collection) {
                /* code 48 is NamespaceExists, see error_codes.err in mongodb source */
                if (error.code == 48) {
                   collection = mongoc_database_get_collection(database, "collection");
                } else {
                   MONGOC_ERROR("Failed to create collection: %s", error.message);
                   goto done;
                }
             }

             /* a transaction's read preferences, read concern, and write concern can be
              * set on the client, on the default transaction options, or when starting
              * the transaction. for the sake of this example, set read concern on the
              * default transaction options. */
             default_txn_opts = mongoc_transaction_opts_new();
             read_concern = mongoc_read_concern_new();
             mongoc_read_concern_set_level(read_concern, "snapshot");
             mongoc_transaction_opts_set_read_concern(default_txn_opts, read_concern);
             session_opts = mongoc_session_opts_new();
             mongoc_session_opts_set_default_transaction_opts(session_opts, default_txn_opts);

             session = mongoc_client_start_session(client, session_opts, &error);
             if (!session) {
                MONGOC_ERROR("Failed to start session: %s", error.message);
                goto done;
             }

             /* in this example, set write concern when starting the transaction */
             txn_opts = mongoc_transaction_opts_new();
             write_concern = mongoc_write_concern_new();
             mongoc_write_concern_set_wmajority(write_concern, 1000 /* wtimeout */);
             mongoc_transaction_opts_set_write_concern(txn_opts, write_concern);

             insert_opts = bson_new();
             if (!mongoc_client_session_append(session, insert_opts, &error)) {
                MONGOC_ERROR("Could not add session to opts: %s", error.message);
                goto done;
             }

          retry_transaction:
             r = mongoc_client_session_start_transaction(session, txn_opts, &error);
             if (!r) {
                MONGOC_ERROR("Failed to start transaction: %s", error.message);
                goto done;
             }

             /* insert two documents - on error, retry the whole transaction */
             for (i = 0; i < 2; i++) {
                doc = BCON_NEW("_id", BCON_INT32(i));
                bson_destroy(&reply);
                r = mongoc_collection_insert_one(collection, doc, insert_opts, &reply, &error);

                bson_destroy(doc);

                if (!r) {
                   MONGOC_ERROR("Insert failed: %s", error.message);
                   mongoc_client_session_abort_transaction(session, NULL);

                   /* a network error, primary failover, or other temporary error in a
                    * transaction includes {"errorLabels": ["TransientTransactionError"]},
                    * meaning that trying the entire transaction again may succeed
                    */
                   if (mongoc_error_has_label(&reply, "TransientTransactionError")) {
                      goto retry_transaction;
                   }

                   goto done;
                }

                reply_json = bson_as_relaxed_extended_json(&reply, NULL);
                printf("%s\n", reply_json);
                bson_free(reply_json);
             }

             /* in case of transient errors, retry for 5 seconds to commit transaction */
             start = bson_get_monotonic_time();
             while (bson_get_monotonic_time() - start < 5 * 1000 * 1000) {
                bson_destroy(&reply);
                r = mongoc_client_session_commit_transaction(session, &reply, &error);
                if (r) {
                   /* success */
                   break;
                } else {
                   MONGOC_ERROR("Warning: commit failed: %s", error.message);
                   if (mongoc_error_has_label(&reply, "TransientTransactionError")) {
                      goto retry_transaction;
                   } else if (mongoc_error_has_label(&reply, "UnknownTransactionCommitResult")) {
                      /* try again to commit */
                      continue;
                   }

                   /* unrecoverable error trying to commit */
                   break;
                }
             }

             exit_code = EXIT_SUCCESS;

          done:
             bson_destroy(&reply);
             bson_destroy(insert_opts);
             mongoc_write_concern_destroy(write_concern);
             mongoc_read_concern_destroy(read_concern);
             mongoc_transaction_opts_destroy(txn_opts);
             mongoc_transaction_opts_destroy(default_txn_opts);
             mongoc_client_session_destroy(session);
             mongoc_collection_destroy(collection);
             mongoc_database_destroy(database);
             mongoc_uri_destroy(uri);
             mongoc_client_destroy(client);

             mongoc_cleanup();

             return exit_code;
          }

   mongoc_transaction_state_t
       Constants for transaction states

   Synopsis
          typedef enum {
            MONGOC_TRANSACTION_NONE = 0,
            MONGOC_TRANSACTION_STARTING = 1,
            MONGOC_TRANSACTION_IN_PROGRESS = 2,
            MONGOC_TRANSACTION_COMMITTED = 3,
            MONGOC_TRANSACTION_ABORTED = 4,
          } mongoc_transaction_state_t;

   Description
       These constants describe the current transaction state of a session.

   Flag Values
                      ┌────────────────────────────────┬───────────────────────────────────────┐
                      │ MONGOC_TRANSACTION_NONE        │ There is no transaction in progress.  │
                      ├────────────────────────────────┼───────────────────────────────────────┤
                      │ MONGOC_TRANSACTION_STARTING    │ A transaction has been  started,  but │
                      │                                │ no  operation  has  been  sent to the │
                      │                                │ server.                               │
                      ├────────────────────────────────┼───────────────────────────────────────┤
                      │ MONGOC_TRANSACTION_IN_PROGRESS │ A transaction is in progress.         │
                      ├────────────────────────────────┼───────────────────────────────────────┤
                      │ MONGOC_TRANSACTION_COMMITTED   │ The transaction was committed.        │
                      ├────────────────────────────────┼───────────────────────────────────────┤
                      │ MONGOC_TRANSACTION_ABORTED     │ The transaction was aborted.          │
                      └────────────────────────────────┴───────────────────────────────────────┘

   mongoc_update_flags_t
       Flags for update operations

   Synopsis
          typedef enum {
             MONGOC_UPDATE_NONE = 0,
             MONGOC_UPDATE_UPSERT = 1 << 0,
             MONGOC_UPDATE_MULTI_UPDATE = 1 << 1,
          } mongoc_update_flags_t;

          #define MONGOC_UPDATE_NO_VALIDATE (1U << 31)

   Description
       These flags correspond to the MongoDB wire protocol. They may be bitwise or'd  together.  The  allow  for
       modifying the way an update is performed in the MongoDB server.

   Flag Values
                        ┌────────────────────────────┬───────────────────────────────────────┐
                        │ MONGOC_UPDATE_NONE         │ No update flags set.                  │
                        ├────────────────────────────┼───────────────────────────────────────┤
                        │ MONGOC_UPDATE_UPSERT       │ If an upsert should be performed.     │
                        ├────────────────────────────┼───────────────────────────────────────┤
                        │ MONGOC_UPDATE_MULTI_UPDATE │ If   more   than  a  single  matching │
                        │                            │ document  should   be   updated.   By │
                        │                            │ default  only  the  first document is │
                        │                            │ updated.                              │
                        ├────────────────────────────┼───────────────────────────────────────┤
                        │ MONGOC_UPDATE_NO_VALIDATE  │ Do  not  perform  client  side   BSON │
                        │                            │ validations    when   performing   an │
                        │                            │ update. This is useful if you already │
                        │                            │ know your BSON documents are valid.   │
                        └────────────────────────────┴───────────────────────────────────────┘

   mongoc_uri_t
   Synopsis
          typedef struct _mongoc_uri_t mongoc_uri_t;

   Description
       mongoc_uri_t provides  an  abstraction  on  top  of  the  MongoDB  connection  URI  format.  It  provides
       standardized  parsing  as  well  as convenience methods for extracting useful information such as replica
       hosts or authorization information.

       See Connection String URI Reference <https://www.mongodb.com/docs/manual/reference/connection-string/> on
       the MongoDB website for more information.

   Format
          mongodb[+srv]://                             <1>
             [username:password@]                      <2>
             host1                                     <3>
             [:port1]                                  <4>
             [,host2[:port2],...[,hostN[:portN]]]      <5>
             [/[database]                              <6>
             [?options]]                               <7>

       1. "mongodb" is the specifier of the MongoDB protocol. Use "mongodb+srv" with a single  service  name  in
          place of "host1" to specify the initial list of servers with an SRV record.

       2. An optional username and password.

       3. The  only  required  part  of  the  uri.  This specifies either a hostname, IPv4 address, IPv6 address
          enclosed in "[" and "]", or UNIX domain socket.

       4. An optional port number.  Defaults to :27017.

       5. Extra optional hosts and ports.  You would specify multiple hosts, for  example,  for  connections  to
          replica sets.

       6. The name of the database to authenticate if the connection string includes authentication credentials.
          If  /database is not specified and the connection string includes credentials, defaults to the 'admin'
          database.

       7. Connection specific options.

       Note:
          Option    names    are    case-insensitive.    Do    not    repeat    the    same     option     (e.g.
          "mongodb://localhost/db?opt=value1&OPT=value2") since this may have unexpected results.

       The  MongoDB  C  Driver  exposes  constants for each supported connection option. These constants make it
       easier to discover connection options, but their string values can be used as well.

       For example, the following calls are equal.

          uri = mongoc_uri_new ("mongodb://localhost/?" MONGOC_URI_APPNAME "=applicationName");
          uri = mongoc_uri_new ("mongodb://localhost/?appname=applicationName");
          uri = mongoc_uri_new ("mongodb://localhost/?appName=applicationName");

   Replica Set Example
       To describe a connection to a replica set named 'test' with the following mongod hosts:

       • db1.example.com on port 27017db2.example.com on port 2500

       You would use a connection string that resembles the following.

          mongodb://db1.example.com,db2.example.com:2500/?replicaSet=test

   SRV Example
       If  you  have  configured  an  SRV  record  <https://www.ietf.org/rfc/rfc2782.txt>  with  a   name   like
       "_mongodb._tcp.server.example.com"  whose records are a list of one or more MongoDB server hostnames, use
       a connection string like this:

          uri = mongoc_uri_new ("mongodb+srv://server.example.com/?replicaSet=rs&appName=applicationName");

       The driver prefixes the service name with "_mongodb._tcp.", then performs a DNS SRV query to resolve  the
       service name to one or more hostnames. If this query succeeds, the driver performs a DNS TXT query on the
       service name (without the "_mongodb._tcp" prefix) for additional URI options configured as TXT records.

       On  Unix,  the  MongoDB  C  Driver  relies  on  libresolv to look up SRV and TXT records. If libresolv is
       unavailable, then using a "mongodb+srv" URI will cause an error. If your libresolv lacks res_nsearch then
       the driver will fall back to res_search, which is not thread-safe.

       Set the environment variable MONGOC_EXPERIMENTAL_SRV_PREFER_TCP to prefer TCP for  the  initial  queries.
       The  environment variable is ignored for res_search. Large DNS responses over UDP may be truncated due to
       UDP size limitations. DNS resolvers are expected  to  retry  over  TCP  if  the  UDP  response  indicates
       truncation. Some observed DNS environments do not set the truncation flag (TC), preventing the TCP retry.
       This environment variable is currently experimental and subject to change.

   IPv4 and IPv6
       If  connecting  to  a  hostname  that  has  both IPv4 and IPv6 DNS records, the behavior follows RFC-6555
       <https://www.ietf.org/rfc/rfc6555.txt>. A connection to the IPv6 address  is  attempted  first.  If  IPv6
       fails,  then  a  connection  is attempted to the IPv4 address. If the connection attempt to IPv6 does not
       complete within 250ms, then IPv4 is tried in parallel. Whichever succeeds connection  first  cancels  the
       other. The successful DNS result is cached for 10 minutes.

       As a consequence, attempts to connect to a mongod only listening on IPv4 may be delayed if there are both
       A (IPv4) and AAAA (IPv6) DNS records associated with the host.

       To  avoid  a  delay,  configure  hostnames  to match the MongoDB configuration. That is, only create an A
       record if the mongod is only listening on IPv4.

   Connection Options
┌─────────────────────────────────┬──────────────────────┬────────────────────────┬───────────────────────────────────┐
├─────────────────────────────────┼──────────────────────┼────────────────────────┼───────────────────────────────────┤
├─────────────────────────────────┼──────────────────────┼────────────────────────┼───────────────────────────────────┤
├─────────────────────────────────┼──────────────────────┼────────────────────────┼───────────────────────────────────┤
├─────────────────────────────────┼──────────────────────┼────────────────────────┼───────────────────────────────────┤
├─────────────────────────────────┼──────────────────────┼────────────────────────┼───────────────────────────────────┤
├─────────────────────────────────┼──────────────────────┼────────────────────────┼───────────────────────────────────┤
├─────────────────────────────────┼──────────────────────┼────────────────────────┼───────────────────────────────────┤
├─────────────────────────────────┼──────────────────────┼────────────────────────┼───────────────────────────────────┤
├─────────────────────────────────┼──────────────────────┼────────────────────────┼───────────────────────────────────┤
├─────────────────────────────────┼──────────────────────┼────────────────────────┼───────────────────────────────────┤
├─────────────────────────────────┼──────────────────────┼────────────────────────┼───────────────────────────────────┤
└─────────────────────────────────┴──────────────────────┴────────────────────────┴───────────────────────────────────┘

       Warning:
          Setting any of the *timeoutMS options above to either 0 or a negative  value  is  discouraged  due  to
          unspecified and inconsistent behavior.  The "default value" historically specified as a fallback for 0
          or  a negative value is NOT related to the default values for the *timeoutMS options documented above.
          The meaning of a timeout of 0 or a negative value may vary depending on the operation being  executed,
          even  when specified by the same URI option.  To specify the documented default value for a *timeoutMS
          option, use the MONGOC_DEFAULT_* constants defined in mongoc-client.h instead.

   Authentication Options
           ┌────────────────────────────────────┬─────────────────────────┬──────────────────────────────┐
           │ Constant                           │ Key                     │ Description                  │
           ├────────────────────────────────────┼─────────────────────────┼──────────────────────────────┤
           │ MONGOC_URI_AUTHMECHANISM           │ authmechanism           │ Specifies the  mechanism  to │
           │                                    │                         │ use  when  authenticating as │
           │                                    │                         │ the   provided   user.   See │
           │                                    │                         │ Authentication  <https://www │
           │                                    │                         │ .mongodb.com/docs/languages/ │
           │                                    │                         │ c/c-driver/current/          │
           │                                    │                         │ libmongoc/authentication/>   │
           │                                    │                         │ for supported values.        │
           ├────────────────────────────────────┼─────────────────────────┼──────────────────────────────┤
           │ MONGOC_URI_AUTHMECHANISMPROPERTIES │ authmechanismproperties │ Additional  properties   for │
           │                                    │                         │ the    specified   mechanism │
           │                                    │                         │ using key-value pair format, │
           │                                    │                         │ e.g.                         │
           │                                    │                         │ key1:value1,key2:value2.     │
           ├────────────────────────────────────┼─────────────────────────┼──────────────────────────────┤
           │ MONGOC_URI_AUTHSOURCE              │ authsource              │ The name of the database  to │
           │                                    │                         │ which         authentication │
           │                                    │                         │ commands   are    sent    or │
           │                                    │                         │ $external  depending  on the │
           │                                    │                         │ specified         mechanism. │
           │                                    │                         │ Overrides  the auth database │
           │                                    │                         │ in the URI when applicable.  │
           └────────────────────────────────────┴─────────────────────────┴──────────────────────────────┘

   Mechanism Properties
       The following properties may be specified as key-value pairs for  the  MONGOC_URI_AUTHMECHANISMPROPERTIES
       option.

       Invalid  or  unsupported properties may be reported as a client error when a corresponding authentication
       mechanism is also specified.

   MONGODB-OIDC
                              ┌────────────────┬───────────────────────────────────────┐
                              │ Key            │ Value                                 │
                              ├────────────────┼───────────────────────────────────────┤
                              │ ENVIRONMENT    │ The name of a built-in OIDC  provider │
                              │                │ integration. Must be one of ["azure", │
                              │                │ "gcp", "k8s"].                        │
                              ├────────────────┼───────────────────────────────────────┤
                              │ TOKEN_RESOURCE │ The   URI  of  the  target  resource. │
                              │                │ ENVIRONMENT must be one of  ["azure", │
                              │                │ "gcp"].                               │
                              └────────────────┴───────────────────────────────────────┘

       Warning:
          A  TOKEN_RESOURCE  property  value  MUST  NOT  contain  the  comma  character  "," when specified as a
          connection string query option, even when percent-encoded.  A value containing a comma  character  may
          be  set  using  mongoc_uri_set_mechanism_properties()  <> instead.  However, the value MAY contain the
          colon character ":", as only the first colon is interpreted as a key-value delimiter.

   GSSAPI
                          ┌────────────────────────┬───────────────────────────────────────┐
                          │ Key                    │ Value                                 │
                          ├────────────────────────┼───────────────────────────────────────┤
                          │ SERVICE_NAME           │ Optional. Defaults to "mongodb".      │
                          ├────────────────────────┼───────────────────────────────────────┤
                          │ CANONICALIZE_HOST_NAME │ Optional. Must be  one  of  ["false", │
                          │                        │ "true"].    "false"    performs    no │
                          │                        │ canonicalization (aka "none"). "true" │
                          │                        │ performs a  forward  DNS  lookup  and │
                          │                        │ then  a  reverse lookup on that value │
                          │                        │ to  canonicalize  the  hostname  (aka │
                          │                        │ "forwardAndReverse").                 │
                          ├────────────────────────┼───────────────────────────────────────┤
                          │ SERVICE_REALM          │ Optional.    May    be   needed   for │
                          │                        │ cross-realm authentication where  the │
                          │                        │ user  and  service exist in different │
                          │                        │ realms.                               │
                          ├────────────────────────┼───────────────────────────────────────┤
                          │ SERVICE_HOST           │ Optional. May  be  needed  to  use  a │
                          │                        │ service  host  that  differs from the │
                          │                        │ initial role.                         │
                          └────────────────────────┴───────────────────────────────────────┘

   MONGODB-AWS
                            ┌───────────────────┬───────────────────────────────────────┐
                            │ Key               │ Value                                 │
                            ├───────────────────┼───────────────────────────────────────┤
                            │ AWS_SESSION_TOKEN │ Optional. An AWS session token to use │
                            │                   │ for  authentication  with   temporary │
                            │                   │ credentials.                          │
                            └───────────────────┴───────────────────────────────────────┘

   Deprecated Mechanism Property Options
       The following options have been deprecated and may be removed from future releases of libmongoc.
┌─────────────────────────────────┬──────────────────────┬────────────────────────────────────┬─────────────────────────┐
├─────────────────────────────────┼──────────────────────┼────────────────────────────────────┼─────────────────────────┤
├─────────────────────────────────┼──────────────────────┼────────────────────────────────────┼─────────────────────────┤
└─────────────────────────────────┴──────────────────────┴────────────────────────────────────┴─────────────────────────┘

   TLS Options
┌─────────────────────────────────────────────────┬──────────────────────────────────────┬────────────────────────────────────────┐
├─────────────────────────────────────────────────┼──────────────────────────────────────┼────────────────────────────────────────┤
├─────────────────────────────────────────────────┼──────────────────────────────────────┼────────────────────────────────────────┤
├─────────────────────────────────────────────────┼──────────────────────────────────────┼────────────────────────────────────────┤
├─────────────────────────────────────────────────┼──────────────────────────────────────┼────────────────────────────────────────┤
├─────────────────────────────────────────────────┼──────────────────────────────────────┼────────────────────────────────────────┤
├─────────────────────────────────────────────────┼──────────────────────────────────────┼────────────────────────────────────────┤
├─────────────────────────────────────────────────┼──────────────────────────────────────┼────────────────────────────────────────┤
├─────────────────────────────────────────────────┼──────────────────────────────────────┼────────────────────────────────────────┤
├─────────────────────────────────────────────────┼──────────────────────────────────────┼────────────────────────────────────────┤
└─────────────────────────────────────────────────┴──────────────────────────────────────┴────────────────────────────────────────┘

       See    Configuring    TLS    <https://www.mongodb.com/docs/languages/c/c-driver/current/libmongoc/guides/
       configuring_tls/> for details about these options and about building libmongoc with TLS support.

   Deprecated SSL Options
       The following options have been deprecated and may be removed from future releases of libmongoc.
┌────────────────────────────────────────────┬─────────────────────────────────┬──────────────────────────────────────────┬─────────────────────────────┐
├────────────────────────────────────────────┼─────────────────────────────────┼──────────────────────────────────────────┼─────────────────────────────┤
├────────────────────────────────────────────┼─────────────────────────────────┼──────────────────────────────────────────┼─────────────────────────────┤
├────────────────────────────────────────────┼─────────────────────────────────┼──────────────────────────────────────────┼─────────────────────────────┤
├────────────────────────────────────────────┼─────────────────────────────────┼──────────────────────────────────────────┼─────────────────────────────┤
├────────────────────────────────────────────┼─────────────────────────────────┼──────────────────────────────────────────┼─────────────────────────────┤
├────────────────────────────────────────────┼─────────────────────────────────┼──────────────────────────────────────────┼─────────────────────────────┤
└────────────────────────────────────────────┴─────────────────────────────────┴──────────────────────────────────────────┴─────────────────────────────┘

   Server Discovery, Monitoring, and Selection Options
       Clients in a mongoc_client_pool_t <> share a topology scanner that  runs  on  a  background  thread.  The
       thread  wakes  every  heartbeatFrequencyMS  (default 10 seconds) to scan all MongoDB servers in parallel.
       Whenever an application operation requires a server that is not known--for example, if there is no  known
       primary  and  your  application  attempts an insert--the thread rescans all servers every half-second. In
       this situation the pooled client waits up to serverSelectionTimeoutMS (default 30 seconds) for the thread
       to   find   a   server   suitable   for   the   operation,   then   returns   an   error   with    domain
       MONGOC_ERROR_SERVER_SELECTION.

       Technically,  the total time an operation may wait while a pooled client scans the topology is controlled
       both by serverSelectionTimeoutMS and connectTimeoutMS. The longest wait occurs if the  last  scan  begins
       just  at the end of the selection timeout, and a slow or down server requires the full connection timeout
       before the client gives up.

       A non-pooled client is single-threaded.  Every  heartbeatFrequencyMS,  it  blocks  the  next  application
       operation  while  it does a parallel scan. This scan takes as long as needed to check the slowest server:
       roughly connectTimeoutMS. Therefore the  default  heartbeatFrequencyMS  for  single-threaded  clients  is
       greater than for pooled clients: 60 seconds.

       By  default, single-threaded (non-pooled) clients scan only once when an operation requires a server that
       is not known. If you attempt an insert and there is no known primary, the client checks all servers  once
       trying  to  find  it, then succeeds or returns an error with domain MONGOC_ERROR_SERVER_SELECTION. But if
       you set serverSelectionTryOnce to "false", the single-threaded client loops, checking all  servers  every
       half-second, until serverSelectionTimeoutMS.

       The  total  time an operation may wait for a single-threaded client to scan the topology is determined by
       connectTimeoutMS  in  the  try-once   case,   or   serverSelectionTimeoutMS   and   connectTimeoutMS   if
       serverSelectionTryOnce is set "false".
          ┌─────────────────────────────────────┬──────────────────────────┬──────────────────────────────┐
          │ Constant                            │ Key                      │ Description                  │
          ├─────────────────────────────────────┼──────────────────────────┼──────────────────────────────┤
          │ MONGOC_URI_HEARTBEATFREQUENCYMS     │ heartbeatfrequencyms     │ The  interval between server │
          │                                     │                          │ monitoring checks.  Defaults │
          │                                     │                          │ to  10,000ms (10 seconds) in │
          │                                     │                          │ pooled      (multi-threaded) │
          │                                     │                          │ mode,  60,000ms (60 seconds) │
          │                                     │                          │ in      non-pooled      mode │
          │                                     │                          │ (single-threaded).           │
          ├─────────────────────────────────────┼──────────────────────────┼──────────────────────────────┤
          │ MONGOC_URI_SERVERSELECTIONTIMEOUTMS │ serverselectiontimeoutms │ A timeout in milliseconds to │
          │                                     │                          │ block  for  server selection │
          │                                     │                          │ before      throwing      an │
          │                                     │                          │ exception.  The  default  is │
          │                                     │                          │ 30,0000ms (30 seconds).      │
          ├─────────────────────────────────────┼──────────────────────────┼──────────────────────────────┤
          │ MONGOC_URI_SERVERSELECTIONTRYONCE   │ serverselectiontryonce   │ If "true", the driver  scans │
          │                                     │                          │ the  topology  exactly  once │
          │                                     │                          │ after    server    selection │
          │                                     │                          │ fails, then either selects a │
          │                                     │                          │ server  or returns an error. │
          │                                     │                          │ If it  is  false,  then  the │
          │                                     │                          │ driver  repeatedly  searches │
          │                                     │                          │ for a suitable server for up │
          │                                     │                          │ to  serverSelectionTimeoutMS │
          │                                     │                          │ milliseconds (pausing a half │
          │                                     │                          │ second   between  attempts). │
          │                                     │                          │ The       default        for │
          │                                     │                          │ serverSelectionTryOnce    is │
          │                                     │                          │ "false" for pooled  clients, │
          │                                     │                          │ otherwise   "true".   Pooled │
          │                                     │                          │ clients               ignore │
          │                                     │                          │ serverSelectionTryOnce; they │
          │                                     │                          │ signal  the thread to rescan │
          │                                     │                          │ the      topology      every │
          │                                     │                          │ half-second            until │
          │                                     │                          │ serverSelectionTimeoutMS     │
          │                                     │                          │ expires.                     │
          ├─────────────────────────────────────┼──────────────────────────┼──────────────────────────────┤
          │ MONGOC_URI_SOCKETCHECKINTERVALMS    │ socketcheckintervalms    │ Only   applies   to   single │
          │                                     │                          │ threaded   clients.   If   a │
          │                                     │                          │ socket  has  not  been  used │
          │                                     │                          │ within    this   time,   its │
          │                                     │                          │ connection is checked with a │
          │                                     │                          │ quick "hello" call before it │
          │                                     │                          │ is used again.  Defaults  to │
          │                                     │                          │ 5,000ms (5 seconds).         │
          ├─────────────────────────────────────┼──────────────────────────┼──────────────────────────────┤
          │ MONGOC_URI_DIRECTCONNECTION         │ directconnection         │ If    "true",   the   driver │
          │                                     │                          │ connects to a single  server │
          │                                     │                          │ directly    and   will   not │
          │                                     │                          │ monitor additional  servers. │
          │                                     │                          │ If   "false",   the   driver │
          │                                     │                          │ connects   based   on    the │
          │                                     │                          │ presence  and  value  of the │
          │                                     │                          │ replicaSet option.           │
          └─────────────────────────────────────┴──────────────────────────┴──────────────────────────────┘

       Setting any of the *TimeoutMS options above to 0 will be interpreted as "use the default value".

   Connection Pool Options
       These options govern the behavior of  a  mongoc_client_pool_t  <>.  They  are  ignored  by  a  non-pooled
       mongoc_client_t <>.
                ┌───────────────────────────────┬────────────────────┬──────────────────────────────┐
                │ Constant                      │ Key                │ Description                  │
                ├───────────────────────────────┼────────────────────┼──────────────────────────────┤
                │ MONGOC_URI_MAXPOOLSIZE        │ maxpoolsize        │ The    maximum   number   of │
                │                               │                    │ clients   created    by    a │
                │                               │                    │ mongoc_client_pool_t      <> │
                │                               │                    │ total (both in the pool  and │
                │                               │                    │ checked  out).  The  default │
                │                               │                    │ value is  100.  Once  it  is │
                │                               │                    │ reached,                     │
                │                               │                    │ mongoc_client_pool_pop()  <> │
                │                               │                    │ blocks until another  thread │
                │                               │                    │ pushes a client.             │
                ├───────────────────────────────┼────────────────────┼──────────────────────────────┤
                │ MONGOC_URI_WAITQUEUETIMEOUTMS │ waitqueuetimeoutms │ The maximum time to wait for │
                │                               │                    │ a client to become available │
                │                               │                    │ from the pool.               │
                └───────────────────────────────┴────────────────────┴──────────────────────────────┘

   Write Concern Options
                        ┌───────────────────────┬────────────┬──────────────────────────────┐
                        │ Constant              │ Key        │ Description                  │
                        ├───────────────────────┼────────────┼──────────────────────────────┤
                        │ MONGOC_URI_W          │ w          │ Determines the write concern │
                        │                       │            │ (guarantee). Valid values:   │
                        │                       │            │                              │
                        │                       │            │        • 0 = The driver will │
                        │                       │            │          not     acknowledge │
                        │                       │            │          write    operations │
                        │                       │            │          but  will  pass  or │
                        │                       │            │          handle any  network │
                        │                       │            │          and  socket  errors │
                        │                       │            │          that it receives to │
                        │                       │            │          the client. If  you │
                        │                       │            │          disable       write │
                        │                       │            │          concern but  enable │
                        │                       │            │          the    getLastError │
                        │                       │            │          command’s w option, │
                        │                       │            │          w overrides  the  w │
                        │                       │            │          option.             │
                        │                       │            │                              │
                        │                       │            │        • 1  = Provides basic │
                        │                       │            │          acknowledgement  of │
                        │                       │            │          write   operations. │
                        │                       │            │          By  specifying   1, │
                        │                       │            │          you  require that a │
                        │                       │            │          standalone   mongod │
                        │                       │            │          instance,   or  the │
                        │                       │            │          primary for replica │
                        │                       │            │          sets,   acknowledge │
                        │                       │            │          all           write │
                        │                       │            │          operations.     For │
                        │                       │            │          drivers    released │
                        │                       │            │          after  the  default │
                        │                       │            │          write       concern │
                        │                       │            │          change, this is the │
                        │                       │            │          default       write │
                        │                       │            │          concern setting.    │
                        │                       │            │                              │
                        │                       │            │        • majority    =   For │
                        │                       │            │          replica  sets,   if │
                        │                       │            │          you   specify   the │
                        │                       │            │          special    majority │
                        │                       │            │          value  to w option, │
                        │                       │            │          write    operations │
                        │                       │            │          will   only  return │
                        │                       │            │          successfully  after │
                        │                       │            │          a  majority  of the │
                        │                       │            │          configured  replica │
                        │                       │            │          set   members  have │
                        │                       │            │          acknowledged    the │
                        │                       │            │          write operation.    │
                        │                       │            │                              │
                        │                       │            │        • n   =  For  replica │
                        │                       │            │          sets,    if     you │
                        │                       │            │          specify  a number n │
                        │                       │            │          greater   than   1, │
                        │                       │            │          operations     with │
                        │                       │            │          this write  concern │
                        │                       │            │          return only after n │
                        │                       │            │          members  of the set │
                        │                       │            │          have   acknowledged │
                        │                       │            │          the  write.  If you │
                        │                       │            │          set n to  a  number │
                        │                       │            │          that   is   greater │
                        │                       │            │          than the number  of │
                        │                       │            │          available       set │
                        │                       │            │          members or  members │
                        │                       │            │          that   hold   data, │
                        │                       │            │          MongoDB will  wait, │
                        │                       │            │          potentially         │
                        │                       │            │          indefinitely,   for │
                        │                       │            │          these  members   to │
                        │                       │            │          become available.   │
                        │                       │            │                              │
                        │                       │            │        • tags  = For replica │
                        │                       │            │          sets,    you    can │
                        │                       │            │          specify  a  tag set │
                        │                       │            │          to require that all │
                        │                       │            │          members of the  set │
                        │                       │            │          that   have   these │
                        │                       │            │          tags     configured │
                        │                       │            │          return confirmation │
                        │                       │            │          of     the    write │
                        │                       │            │          operation.          │
                        ├───────────────────────┼────────────┼──────────────────────────────┤
                        │ MONGOC_URI_WTIMEOUTMS │ wtimeoutms │ The time in milliseconds  to │
                        │                       │            │ wait   for   replication  to │
                        │                       │            │ succeed, as specified in the │
                        │                       │            │ w option, before timing out. │
                        │                       │            │ When wtimeoutMS is 0,  write │
                        │                       │            │ operations  will  never time │
                        │                       │            │ out.                         │
                        ├───────────────────────┼────────────┼──────────────────────────────┤
                        │ MONGOC_URI_JOURNAL    │ journal    │ Controls    whether    write │
                        │                       │            │ operations  will  wait until │
                        │                       │            │ the mongod acknowledges  the │
                        │                       │            │ write operations and commits │
                        │                       │            │ the  data  to  the  on  disk │
                        │                       │            │ journal.                     │
                        │                       │            │                              │
                        │                       │            │        • true    =   Enables │
                        │                       │            │          journal      commit │
                        │                       │            │          acknowledgement     │
                        │                       │            │          write      concern. │
                        │                       │            │          Equivalent       to │
                        │                       │            │          specifying      the │
                        │                       │            │          getLastError        │
                        │                       │            │          command  with the j │
                        │                       │            │          option enabled.     │
                        │                       │            │                              │
                        │                       │            │        • false  =  Does  not │
                        │                       │            │          require that mongod │
                        │                       │            │          commit        write │
                        │                       │            │          operations  to  the │
                        │                       │            │          journal      before │
                        │                       │            │          acknowledging   the │
                        │                       │            │          write    operation. │
                        │                       │            │          This is the default │
                        │                       │            │          option   for    the │
                        │                       │            │          journal parameter.  │
                        └───────────────────────┴────────────┴──────────────────────────────┘

   Read Concern Options
                  ┌─────────────────────────────┬──────────────────┬──────────────────────────────┐
                  │ Constant                    │ Key              │ Description                  │
                  ├─────────────────────────────┼──────────────────┼──────────────────────────────┤
                  │ MONGOC_URI_READCONCERNLEVEL │ readconcernlevel │ The  level  of isolation for │
                  │                             │                  │ read  operations.   If   the │
                  │                             │                  │ level  is  left unspecified, │
                  │                             │                  │ the server default  will  be │
                  │                             │                  │ used. See readConcern in the │
                  │                             │                  │ MongoDB  Manual <https://www │
                  │                             │                  │ .mongodb.com/docs/master/    │
                  │                             │                  │ reference/readConcern/>  for │
                  │                             │                  │ details.                     │
                  └─────────────────────────────┴──────────────────┴──────────────────────────────┘

   Read Preference Options
       When connected to a replica set, the driver chooses which member to query using the read preference:

       1. Choose members whose type matches "readPreference".

       2. From these, if there are any tags sets configured, choose members matching the first tag set. If there
          are  none,  fall back to the next tag set and so on, until some members are chosen or the tag sets are
          exhausted.

       3. From the chosen servers, distribute queries randomly among the  server  with  the  fastest  round-trip
          times.  These  include  the server with the fastest time and any whose round-trip time is no more than
          "localThresholdMS" slower.
               ┌────────────────────────────────┬─────────────────────┬──────────────────────────────┐
               │ Constant                       │ Key                 │ Description                  │
               ├────────────────────────────────┼─────────────────────┼──────────────────────────────┤
               │ MONGOC_URI_READPREFERENCE      │ readpreference      │ Specifies  the  replica  set │
               │                                │                     │ read   preference  for  this │
               │                                │                     │ connection.   This   setting │
               │                                │                     │ overrides   any  secondaryOk │
               │                                │                     │ value. The  read  preference │
               │                                │                     │ values are the following:    │
               │                                │                     │                              │
               │                                │                     │        • primary (default)   │
               │                                │                     │                              │
               │                                │                     │        • primaryPreferred    │
               │                                │                     │                              │
               │                                │                     │        • secondary           │
               │                                │                     │                              │
               │                                │                     │        • secondaryPreferred  │
               │                                │                     │                              │
               │                                │                     │        • nearest             │
               ├────────────────────────────────┼─────────────────────┼──────────────────────────────┤
               │ MONGOC_URI_READPREFERENCETAGS  │ readpreferencetags  │ A  representation  of  a tag │
               │                                │                     │ set. See also  Tag  Sets  <# │
               │                                │                     │ mongoc-read-prefs-tag-sets>. │
               ├────────────────────────────────┼─────────────────────┼──────────────────────────────┤
               │ MONGOC_URI_LOCALTHRESHOLDMS    │ localthresholdms    │ How    far   to   distribute │
               │                                │                     │ queries, beyond  the  server │
               │                                │                     │ with  the fastest round-trip │
               │                                │                     │ time.   By   default,   only │
               │                                │                     │ servers  within  15ms of the │
               │                                │                     │ fastest   round-trip    time │
               │                                │                     │ receive queries.             │
               ├────────────────────────────────┼─────────────────────┼──────────────────────────────┤
               │ MONGOC_URI_MAXSTALENESSSECONDS │ maxstalenessseconds │ The maximum replication lag, │
               │                                │                     │ in  wall  clock time, that a │
               │                                │                     │ secondary  can  suffer   and │
               │                                │                     │ still   be   eligible.   The │
               │                                │                     │ smallest allowed  value  for │
               │                                │                     │ maxStalenessSeconds   is  90 │
               │                                │                     │ seconds.                     │
               └────────────────────────────────┴─────────────────────┴──────────────────────────────┘

       Note:
          When connecting to more than one mongos, libmongoc's localThresholdMS applies only to the selection of
          mongos servers. The threshold for selecting among replica set members in shards is controlled  by  the
          mongos's  localThreshold  command  line option <https://www.mongodb.com/docs/manual/reference/program/
          mongos/#cmdoption-localthreshold>.

   Legacy Options
       For historical reasons, the following options are available. They should however not be used.
                              ┌─────────────────┬──────┬──────────────────────────────┐
                              │ Constant        │ Key  │ Description                  │
                              ├─────────────────┼──────┼──────────────────────────────┤
                              │ MONGOC_URI_SAFE │ safe │ {true|false} Same as w={1|0} │
                              └─────────────────┴──────┴──────────────────────────────┘

   Version Checks
       Conditional compilation based on mongoc version

   Description
       The following preprocessor macros can be used to perform various checks  based  on  the  version  of  the
       library  you are compiling against.  This may be useful if you only want to enable a feature on a certain
       version of the library.

          #include <mongoc/mongoc.h>

          #define MONGOC_MAJOR_VERSION (x)
          #define MONGOC_MINOR_VERSION (y)
          #define MONGOC_MICRO_VERSION (z)
          #define MONGOC_VERSION_S     "x.y.z"
          #define MONGOC_VERSION_HEX   ((1 << 24) | (0 << 16) | (0 << 8) | 0)
          #define MONGOC_CHECK_VERSION(major, minor, micro)

       Only compile a block on MongoDB C Driver 1.1.0 and newer.

          #if MONGOC_CHECK_VERSION(1, 1, 0)
          static void
          do_something (void)
          {
          }
          #endif

   mongoc_write_concern_t
       Write Concern abstraction

   Synopsis
       mongoc_write_concern_t tells the driver what level of acknowledgement  to  await  from  the  server.  The
       default, MONGOC_WRITE_CONCERN_W_DEFAULT, is right for the great majority of applications.

       You  can  specify  a  write  concern  on  connection  objects,  database  objects, collection objects, or
       per-operation. Data-modifying operations typically use the write concern of the object they  operate  on,
       and  check  the  server  response  for  a  write  concern  error  or  write concern timeout. For example,
       mongoc_collection_drop_index() <> uses the collection's write concern,  and  a  write  concern  error  or
       timeout in the response is considered a failure.

       Exceptions to this principle are the generic command functions:

       • mongoc_client_command_simple() <>

       • mongoc_database_command_simple() <>

       • mongoc_collection_command_simple() <>

       These  generic  command  functions  do not automatically apply a write concern, and they do not check the
       server response for a write concern error or write concern timeout.

       See Write Concern <https://www.mongodb.com/docs/manual/core/write-concern/> on the  MongoDB  website  for
       more information.

   Write Concern Levels
       Set the write concern level with mongoc_write_concern_set_w() <>.
                  ┌───────────────────────────────────────┬───────────────────────────────────────┐
                  │ MONGOC_WRITE_CONCERN_W_DEFAULT (1)    │ By  default,  writes  block  awaiting │
                  │                                       │ acknowledgement     from     MongoDB. │
                  │                                       │ Acknowledged   write  concern  allows │
                  │                                       │ clients to catch  network,  duplicate │
                  │                                       │ key, and other errors.                │
                  ├───────────────────────────────────────┼───────────────────────────────────────┤
                  │ MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED │ With this write concern, MongoDB does │
                  │ (0)                                   │ not  acknowledge the receipt of write │
                  │                                       │ operation. Unacknowledged is  similar │
                  │                                       │ to  errors  ignored;  however, mongoc │
                  │                                       │ attempts  to   receive   and   handle │
                  │                                       │ network errors when possible.         │
                  ├───────────────────────────────────────┼───────────────────────────────────────┤
                  │ MONGOC_WRITE_CONCERN_W_MAJORITY       │ Block   until   a   write   has  been │
                  │ (majority)                            │ propagated to a majority of the nodes │
                  │                                       │ in the replica set.                   │
                  ├───────────────────────────────────────┼───────────────────────────────────────┤
                  │ n                                     │ Block  until   a   write   has   been │
                  │                                       │ propagated to at least n nodes in the │
                  │                                       │ replica set.                          │
                  └───────────────────────────────────────┴───────────────────────────────────────┘

   Application Performance Monitoring (APM)
       The  MongoDB  C  Driver  allows  you  to  monitor  all  the  MongoDB operations the driver executes. This
       event-notification system conforms to two MongoDB driver specs:

       • Command   Logging   and    Monitoring    <https://github.com/mongodb/specifications/blob/master/source/
         command-logging-and-monitoring/command-logging-and-monitoring.md>:  events  related  to all application
         operations.

       • SDAM             Monitoring              <https://github.com/mongodb/specifications/blob/master/source/
         server-discovery-and-monitoring/server-discovery-and-monitoring.md>:  events  related  to  the driver's
         Server Discovery And Monitoring logic.

       To receive  notifications,  create  a  mongoc_apm_callbacks_t  with  mongoc_apm_callbacks_new()  <>,  set
       callbacks     on     it,     then     pass     it     to    mongoc_client_set_apm_callbacks()    <>    or
       mongoc_client_pool_set_apm_callbacks() <>.

   Command-Monitoring Example
       example-command-monitoring.c

          /* gcc example-command-monitoring.c -o example-command-monitoring \
           *     $(pkg-config --cflags --libs libmongoc-1.0) */

          /* ./example-command-monitoring [CONNECTION_STRING] */

          #include <mongoc/mongoc.h>

          #include <stdio.h>

          typedef struct {
             int started;
             int succeeded;
             int failed;
          } stats_t;

          void
          command_started(const mongoc_apm_command_started_t *event)
          {
             char *s;

             s = bson_as_relaxed_extended_json(mongoc_apm_command_started_get_command(event), NULL);
             printf("Command %s started on %s:\n%s\n\n",
                    mongoc_apm_command_started_get_command_name(event),
                    mongoc_apm_command_started_get_host(event)->host,
                    s);

             ((stats_t *)mongoc_apm_command_started_get_context(event))->started++;

             bson_free(s);
          }

          void
          command_succeeded(const mongoc_apm_command_succeeded_t *event)
          {
             char *s;

             s = bson_as_relaxed_extended_json(mongoc_apm_command_succeeded_get_reply(event), NULL);
             printf("Command %s succeeded:\n%s\n\n", mongoc_apm_command_succeeded_get_command_name(event), s);

             ((stats_t *)mongoc_apm_command_succeeded_get_context(event))->succeeded++;

             bson_free(s);
          }

          void
          command_failed(const mongoc_apm_command_failed_t *event)
          {
             bson_error_t error;

             mongoc_apm_command_failed_get_error(event, &error);
             printf("Command %s failed:\n\"%s\"\n\n", mongoc_apm_command_failed_get_command_name(event), error.message);

             ((stats_t *)mongoc_apm_command_failed_get_context(event))->failed++;
          }

          int
          main(int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_apm_callbacks_t *callbacks;
             stats_t stats = {0};
             mongoc_collection_t *collection;
             bson_error_t error;
             const char *uri_string = "mongodb://127.0.0.1/?appname=cmd-monitoring-example";
             mongoc_uri_t *uri;
             const char *collection_name = "test";
             bson_t *docs[2];

             mongoc_init();

             if (argc > 1) {
                uri_string = argv[1];
             }

             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                fprintf(stderr,
                        "failed to parse URI: %s\n"
                        "error message:       %s\n",
                        uri_string,
                        error.message);
                return EXIT_FAILURE;
             }

             client = mongoc_client_new_from_uri(uri);
             if (!client) {
                return EXIT_FAILURE;
             }

             mongoc_client_set_error_api(client, 2);
             callbacks = mongoc_apm_callbacks_new();
             mongoc_apm_set_command_started_cb(callbacks, command_started);
             mongoc_apm_set_command_succeeded_cb(callbacks, command_succeeded);
             mongoc_apm_set_command_failed_cb(callbacks, command_failed);
             mongoc_client_set_apm_callbacks(client, callbacks, (void *)&stats /* context pointer */);

             collection = mongoc_client_get_collection(client, "test", collection_name);
             mongoc_collection_drop(collection, NULL);

             docs[0] = BCON_NEW("_id", BCON_INT32(0));
             docs[1] = BCON_NEW("_id", BCON_INT32(1));
             mongoc_collection_insert_many(collection, (const bson_t **)docs, 2, NULL, NULL, NULL);

             /* duplicate key error on the second insert */
             mongoc_collection_insert_one(collection, docs[0], NULL, NULL, NULL);

             mongoc_collection_destroy(collection);
             mongoc_apm_callbacks_destroy(callbacks);
             mongoc_uri_destroy(uri);
             mongoc_client_destroy(client);

             printf("started: %d\nsucceeded: %d\nfailed: %d\n", stats.started, stats.succeeded, stats.failed);

             bson_destroy(docs[0]);
             bson_destroy(docs[1]);

             mongoc_cleanup();

             return EXIT_SUCCESS;
          }

       This example program prints:

          Command drop started on 127.0.0.1:
          { "drop" : "test" }

          Command drop succeeded:
          { "ns" : "test.test", "nIndexesWas" : 1, "ok" : 1.0 }

          Command insert started on 127.0.0.1:
          {
            "insert" : "test",
            "ordered" : true,
            "documents" : [
              { "_id" : 0 }, { "_id" : 1 }
            ]
          }

          Command insert succeeded:
          { "n" : 2, "ok" : 1.0 }

          Command insert started on 127.0.0.1:
          {
            "insert" : "test",
            "ordered" : true,
            "documents" : [
              { "_id" : 0 }
            ]
          }

          Command insert succeeded:
          {
            "n" : 0,
            "writeErrors" : [
              { "index" : 0, "code" : 11000, "errmsg" : "duplicate key" }
            ],
            "ok" : 1.0
          }

          started: 3
          succeeded: 3
          failed: 0

       The output has been edited and formatted for clarity. Depending on your  server  configuration,  messages
       may include metadata like database name, logical session ids, or cluster times that are not shown here.

       The  final  "insert" command is considered successful, despite the writeError, because the server replied
       to the overall command with "ok": 1.

   SDAM Monitoring Example
       example-sdam-monitoring.c

          /* gcc example-sdam-monitoring.c -o example-sdam-monitoring \
           *     $(pkg-config --cflags --libs libmongoc-1.0) */

          /* ./example-sdam-monitoring [CONNECTION_STRING] */

          #include <mongoc/mongoc.h>

          #include <stdio.h>

          typedef struct {
             int server_changed_events;
             int server_opening_events;
             int server_closed_events;
             int topology_changed_events;
             int topology_opening_events;
             int topology_closed_events;
             int heartbeat_started_events;
             int heartbeat_succeeded_events;
             int heartbeat_failed_events;
          } stats_t;

          static void
          server_changed(const mongoc_apm_server_changed_t *event)
          {
             stats_t *context;
             const mongoc_server_description_t *prev_sd, *new_sd;

             context = (stats_t *)mongoc_apm_server_changed_get_context(event);
             context->server_changed_events++;

             prev_sd = mongoc_apm_server_changed_get_previous_description(event);
             new_sd = mongoc_apm_server_changed_get_new_description(event);

             printf("server changed: %s %s -> %s\n",
                    mongoc_apm_server_changed_get_host(event)->host_and_port,
                    mongoc_server_description_type(prev_sd),
                    mongoc_server_description_type(new_sd));
          }

          static void
          server_opening(const mongoc_apm_server_opening_t *event)
          {
             stats_t *context;

             context = (stats_t *)mongoc_apm_server_opening_get_context(event);
             context->server_opening_events++;

             printf("server opening: %s\n", mongoc_apm_server_opening_get_host(event)->host_and_port);
          }

          static void
          server_closed(const mongoc_apm_server_closed_t *event)
          {
             stats_t *context;

             context = (stats_t *)mongoc_apm_server_closed_get_context(event);
             context->server_closed_events++;

             printf("server closed: %s\n", mongoc_apm_server_closed_get_host(event)->host_and_port);
          }

          static void
          topology_changed(const mongoc_apm_topology_changed_t *event)
          {
             stats_t *context;
             const mongoc_topology_description_t *prev_td;
             const mongoc_topology_description_t *new_td;
             mongoc_server_description_t **prev_sds;
             size_t n_prev_sds;
             mongoc_server_description_t **new_sds;
             size_t n_new_sds;
             size_t i;
             mongoc_read_prefs_t *prefs;

             context = (stats_t *)mongoc_apm_topology_changed_get_context(event);
             context->topology_changed_events++;

             prev_td = mongoc_apm_topology_changed_get_previous_description(event);
             prev_sds = mongoc_topology_description_get_servers(prev_td, &n_prev_sds);
             new_td = mongoc_apm_topology_changed_get_new_description(event);
             new_sds = mongoc_topology_description_get_servers(new_td, &n_new_sds);

             printf("topology changed: %s -> %s\n",
                    mongoc_topology_description_type(prev_td),
                    mongoc_topology_description_type(new_td));

             if (n_prev_sds) {
                printf("  previous servers:\n");
                for (i = 0; i < n_prev_sds; i++) {
                   printf("      %s %s\n",
                          mongoc_server_description_type(prev_sds[i]),
                          mongoc_server_description_host(prev_sds[i])->host_and_port);
                }
             }

             if (n_new_sds) {
                printf("  new servers:\n");
                for (i = 0; i < n_new_sds; i++) {
                   printf("      %s %s\n",
                          mongoc_server_description_type(new_sds[i]),
                          mongoc_server_description_host(new_sds[i])->host_and_port);
                }
             }

             prefs = mongoc_read_prefs_new(MONGOC_READ_SECONDARY);

             if (mongoc_topology_description_has_readable_server(new_td, prefs)) {
                printf("  secondary AVAILABLE\n");
             } else {
                printf("  secondary UNAVAILABLE\n");
             }

             if (mongoc_topology_description_has_writable_server(new_td)) {
                printf("  primary AVAILABLE\n");
             } else {
                printf("  primary UNAVAILABLE\n");
             }

             mongoc_read_prefs_destroy(prefs);
             mongoc_server_descriptions_destroy_all(prev_sds, n_prev_sds);
             mongoc_server_descriptions_destroy_all(new_sds, n_new_sds);
          }

          static void
          topology_opening(const mongoc_apm_topology_opening_t *event)
          {
             stats_t *context;

             context = (stats_t *)mongoc_apm_topology_opening_get_context(event);
             context->topology_opening_events++;

             printf("topology opening\n");
          }

          static void
          topology_closed(const mongoc_apm_topology_closed_t *event)
          {
             stats_t *context;

             context = (stats_t *)mongoc_apm_topology_closed_get_context(event);
             context->topology_closed_events++;

             printf("topology closed\n");
          }

          static void
          server_heartbeat_started(const mongoc_apm_server_heartbeat_started_t *event)
          {
             stats_t *context;

             context = (stats_t *)mongoc_apm_server_heartbeat_started_get_context(event);
             context->heartbeat_started_events++;

             printf("%s heartbeat started\n", mongoc_apm_server_heartbeat_started_get_host(event)->host_and_port);
          }

          static void
          server_heartbeat_succeeded(const mongoc_apm_server_heartbeat_succeeded_t *event)
          {
             stats_t *context;
             char *reply;

             context = (stats_t *)mongoc_apm_server_heartbeat_succeeded_get_context(event);
             context->heartbeat_succeeded_events++;

             reply = bson_as_canonical_extended_json(mongoc_apm_server_heartbeat_succeeded_get_reply(event), NULL);

             printf("%s heartbeat succeeded: %s\n", mongoc_apm_server_heartbeat_succeeded_get_host(event)->host_and_port, reply);

             bson_free(reply);
          }

          static void
          server_heartbeat_failed(const mongoc_apm_server_heartbeat_failed_t *event)
          {
             stats_t *context;
             bson_error_t error;

             context = (stats_t *)mongoc_apm_server_heartbeat_failed_get_context(event);
             context->heartbeat_failed_events++;
             mongoc_apm_server_heartbeat_failed_get_error(event, &error);

             printf(
                "%s heartbeat failed: %s\n", mongoc_apm_server_heartbeat_failed_get_host(event)->host_and_port, error.message);
          }

          int
          main(int argc, char *argv[])
          {
             mongoc_client_t *client;
             mongoc_apm_callbacks_t *cbs;
             stats_t stats = {0};
             const char *uri_string = "mongodb://127.0.0.1/?appname=sdam-monitoring-example";
             mongoc_uri_t *uri;
             bson_t cmd = BSON_INITIALIZER;
             bson_t reply;
             bson_error_t error;

             mongoc_init();

             if (argc > 1) {
                uri_string = argv[1];
             }

             uri = mongoc_uri_new_with_error(uri_string, &error);
             if (!uri) {
                fprintf(stderr,
                        "failed to parse URI: %s\n"
                        "error message:       %s\n",
                        uri_string,
                        error.message);
                return EXIT_FAILURE;
             }

             client = mongoc_client_new_from_uri(uri);
             if (!client) {
                return EXIT_FAILURE;
             }

             mongoc_client_set_error_api(client, 2);
             cbs = mongoc_apm_callbacks_new();
             mongoc_apm_set_server_changed_cb(cbs, server_changed);
             mongoc_apm_set_server_opening_cb(cbs, server_opening);
             mongoc_apm_set_server_closed_cb(cbs, server_closed);
             mongoc_apm_set_topology_changed_cb(cbs, topology_changed);
             mongoc_apm_set_topology_opening_cb(cbs, topology_opening);
             mongoc_apm_set_topology_closed_cb(cbs, topology_closed);
             mongoc_apm_set_server_heartbeat_started_cb(cbs, server_heartbeat_started);
             mongoc_apm_set_server_heartbeat_succeeded_cb(cbs, server_heartbeat_succeeded);
             mongoc_apm_set_server_heartbeat_failed_cb(cbs, server_heartbeat_failed);
             mongoc_client_set_apm_callbacks(client, cbs, (void *)&stats /* context pointer */);

             /* the driver connects on demand to perform first operation */
             BSON_APPEND_INT32(&cmd, "buildinfo", 1);
             mongoc_client_command_simple(client, "admin", &cmd, NULL, &reply, &error);
             mongoc_uri_destroy(uri);
             mongoc_client_destroy(client);

             printf("Events:\n"
                    "   server changed: %d\n"
                    "   server opening: %d\n"
                    "   server closed: %d\n"
                    "   topology changed: %d\n"
                    "   topology opening: %d\n"
                    "   topology closed: %d\n"
                    "   heartbeat started: %d\n"
                    "   heartbeat succeeded: %d\n"
                    "   heartbeat failed: %d\n",
                    stats.server_changed_events,
                    stats.server_opening_events,
                    stats.server_closed_events,
                    stats.topology_changed_events,
                    stats.topology_opening_events,
                    stats.topology_closed_events,
                    stats.heartbeat_started_events,
                    stats.heartbeat_succeeded_events,
                    stats.heartbeat_failed_events);

             bson_destroy(&cmd);
             bson_destroy(&reply);
             mongoc_apm_callbacks_destroy(cbs);

             mongoc_cleanup();

             return EXIT_SUCCESS;
          }

       Start a 3-node replica set on localhost with set name "rs" and start the program:

          ./example-sdam-monitoring "mongodb://localhost:27017,localhost:27018/?replicaSet=rs"

       This example program prints something like:

          topology opening
          topology changed: Unknown -> ReplicaSetNoPrimary
            secondary UNAVAILABLE
            primary UNAVAILABLE
          server opening: localhost:27017
          server opening: localhost:27018
          localhost:27017 heartbeat started
          localhost:27018 heartbeat started
          localhost:27017 heartbeat succeeded: { ... reply ... }
          server changed: localhost:27017 Unknown -> RSPrimary
          server opening: localhost:27019
          topology changed: ReplicaSetNoPrimary -> ReplicaSetWithPrimary
            new servers:
                RSPrimary localhost:27017
            secondary UNAVAILABLE
            primary AVAILABLE
          localhost:27019 heartbeat started
          localhost:27018 heartbeat succeeded: { ... reply ... }
          server changed: localhost:27018 Unknown -> RSSecondary
          topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
            previous servers:
                RSPrimary localhost:27017
            new servers:
                RSPrimary localhost:27017
                RSSecondary localhost:27018
            secondary AVAILABLE
            primary AVAILABLE
          localhost:27019 heartbeat succeeded: { ... reply ... }
          server changed: localhost:27019 Unknown -> RSSecondary
          topology changed: ReplicaSetWithPrimary -> ReplicaSetWithPrimary
            previous servers:
                RSPrimary localhost:27017
                RSSecondary localhost:27018
            new servers:
                RSPrimary localhost:27017
                RSSecondary localhost:27018
                RSSecondary localhost:27019
            secondary AVAILABLE
            primary AVAILABLE
          topology closed

          Events:
             server changed: 3
             server opening: 3
             server closed: 0
             topology changed: 4
             topology opening: 1
             topology closed: 1
             heartbeat started: 3
             heartbeat succeeded: 3
             heartbeat failed: 0

       The driver connects to the mongods on ports 27017 and  27018,  which  were  specified  in  the  URI,  and
       determines  which  is  primary. It also discovers the third member, "localhost:27019", and adds it to the
       topology.

Author

       MongoDB, Inc

Copyright

       2009-present, MongoDB, Inc.

2.2.0                                             Nov 26, 2025                               MONGOC_REFERENCE(3)