Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
MONGOC_REFERENCE(3)		   libmongoc		   MONGOC_REFERENCE(3)

LIBMONGOC - API
       A Cross Platform	MongoDB	Client Library for C

       This site documents the API. For	tutorials, guides, and explainers, see
       MongoDB C Driver.

   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 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 for a detailed	example.

       Call mongoc_cleanup() exactly once at the end of	your  program  to  re-
       lease  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().

   Deprecated feature: automatic initialization	and cleanup
       On some platforms the driver can	automatically call  mongoc_init()  be-
       fore  main,  and	 call  mongoc_cleanup()	 as the	process	exits. This is
       problematic in situations where related libraries also execute  cleanup
       code  on	 shutdown, and it creates inconsistent rules across platforms.
       Therefore the automatic initialization and cleanup  feature  is	depre-
       cated, and will be dropped in version 2.0. Meanwhile, for backward com-
       patibility,  the	feature	is enabled by default on platforms where it is
       available.

       For  portable,  future-proof  code,  always  call   mongoc_init()   and
       mongoc_cleanup()	yourself, and configure	the driver like:

	  cmake	-DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF

   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.

       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  pro-
       vided. 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 std-
       out, or to stderr for warnings, critical	messages, and errors.  You can
       override	the handler with mongoc_log_set_handler().  Your handler func-
       tion 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 be-
       fore 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 er-
       rors, provide an	empty log handler:

	  mongoc_log_set_handler (NULL,	NULL);

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

       This  is	 especially  useful when debugging what	may be going on	inter-
       nally in	the driver.

       Trace  messages	can  be	 enabled  and	disabled   by	calling	  mon-
       goc_log_trace_enable() and mongoc_log_trace_disable()

       NOTE:
	  Compiling  the  driver with -DENABLE_TRACING=ON will affect its per-
	  formance. Disabling tracing with mongoc_log_trace_disable() signifi-
	  cantly reduces the overhead, but cannot remove it completely.

   Structured Logging
       This document describes a newer "structured" logging facility which re-
       ports messages from the driver  itself  using  a	 BSON  format  defined
       across  driver  implementations	by  the	MongoDB	Logging	Specification.
       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  set-
       tings from environment variables	and offer additional optional program-
       matic   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  pro-
       grammatic   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  han-
       dler,  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 maxi-
       mum 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  cap-
       tured 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 warn-
       ings 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 implementa-
	 tion-specific value near the maximum representable  length.   By  de-
	 fault,	 the  limit  is	1000 bytes.  This limit	affects	interior docu-
	 ments 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 in-
	    stance and subsequent instances will fail, falling back on the de-
	    fault of stderr.  Applications that	use multiple processes or mul-
	    tiple  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 MON-
	 GOC_STRUCTURED_LOG_COMPONENT_COMMAND.

        MONGODB_LOG_TOPOLOGY: A log level name	to set as the maximum for MON-
	 GOC_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  oth-
	 erwise	specified.

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

        emergency, off

        alert

        critical

        error

        warning, warn

        notice

        informational,	info

        debug

        trace

   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);

   Parameters
        opts:	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	refer-
       ence 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, prefer-
       ably 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.

   Parameters
        opts:	    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 be-
       low this	severity level will be passed to mongoc_structured_log_func_t.

       By default, each	component's log	level may come from environment	 vari-
       ables.  See mongoc_structured_log_opts_set_max_levels_from_env().

   Parameters
        opts:	    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  in-
       correct.

       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.

   Parameters
        opts:	    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  in-
       correct.

       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: MON-
       GODB_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()	estab-
       lishes  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  environ-
       ment,  returns false and	may log	additional information to the unstruc-
       tured logging facility.	Note that, by design, these errors are by  de-
       fault   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);

   Parameters
        opts:	    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  se-
       quence,	we instead truncate the	document earlier at the	nearest	bound-
       ary between code	points.

   Parameters
        opts:	    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  trunca-
	 tion. 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 en-
       vironment variable formats.

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

       This happens automatically when mongoc_structured_log_opts_new()	estab-
       lishes  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  de-
       sign,	these	 errors	   are	  by	default	   non-fatal.	  When
       mongoc_structured_log_opts_new()	internally calls this function,	it ig-
       nores 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);

   Parameters
        opts:	    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  pro-
       vided  to convert between these values and their	standard string	repre-
       sentations. 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);

   Parameters
        level:	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.

   Parameters
        name: 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);

   Parameters
        component: 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.

   Parameters
        name: 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_struc-
	  tured_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 in-
       stance 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 pro-
       vides 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().	Struc-
       tured log handlers must be  thread-safe	if  they  will	be  used  with
       mongoc_client_pool_t.  Handlers must avoid unbounded recursion, prefer-
       ably by avoiding	the use	of any libmongoc client	or pool	which uses the
       same handler.

   Parameters
        entry:	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 only when	explicitly re-
       quested 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);

   Parameters
        entry:	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);

   Parameters
        entry:	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);

   Parameters
        entry:	A mongoc_structured_log_entry_t	pointer.

   Returns
       A string, guaranteed to be valid	only during the	lifetime of the	struc-
       tured 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, of	the log	entry's	standardized BSON rep-
       resentation.  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.

   Parameters
        entry:	A mongoc_structured_log_entry_t	pointer.

   Returns
       A  new  allocated  bson_t  that	must  be  freed	  with	 a   call   to
       bson_destroy().

       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)
	  {
	     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 proceses 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_en-
	  try_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 structure with an error domain, error code,
       and message. Use	domain to determine which subsystem generated the  er-
       ror, and	code for the specific error. message is	a human-readable error
       description.

       SEE ALSO:
	  Handling Errors in libbson.

+---------------------+----------------------------------+--------------------------------------------+
| Code		      |	Description			 |					      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_CLIENT |	MONGOC_ER-			 | You tried to	send a			      |
|		      |	ROR_CLIENT_TOO_BIG		 | message larger than			      |
|		      |					 | the	 server's  max			      |
|		      |					 | message size.			      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ER-			 | Wrong  credentials,			      |
|		      |	ROR_CLIENT_AUTHEN-		 | or  failure sending			      |
|		      |	TICATE				 | or  receiving   au-			      |
|		      |					 | thentication	  mes-			      |
|		      |					 | sages.				      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ER-			 | You	tried  an  TLS			      |
|		      |	ROR_CLIENT_NO_AC-		 | connection  but the			      |
|		      |	CEPTABLE_PEER			 | driver   was	   not			      |
|		      |					 | built with TLS.			      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ER-			 | You began iterating			      |
|		      |	ROR_CLIENT_IN_EX-		 | an  exhaust cursor,			      |
|		      |	HAUST				 | then	tried to begin			      |
|		      |					 | another   operation			      |
|		      |					 | with	   the	  same			      |
|		      |					 | mongoc_client_t.			      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ER-			 | Failure related  to			      |
|		      |	ROR_CLIENT_SES-			 | creating or using a			      |
|		      |	SION_FAILURE			 | logical session.			      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ER-			 | Failure  related to			      |
|		      |	ROR_CLIENT_IN-			 | arguments	passed			      |
|		      |	VALID_ENCRYP-			 | when	  initializing			      |
|		      |	TION_ARG			 | In-Use Encryption.			      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ER-			 | Failure related  to			      |
|		      |	ROR_CLIENT_IN-			 | In-Use Encryption.			      |
|		      |	VALID_ENCRYP-			 |					      |
|		      |	TION_STATE			 |					      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ER-			 | You	 attempted  to			      |
|		      |	ROR_CLIENT_IN-			 | connect to  a  Mon-			      |
|		      |	VALID_LOAD_BALANCER		 | goDB	 server	behind			      |
|		      |					 | a  load   balancer,			      |
|		      |					 | but the server does			      |
|		      |					 | not	advertize load			      |
|		      |					 | balanced support.			      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_STREAM |	MONGOC_ER-			 | DNS failure.				      |
|		      |	ROR_STREAM_NAME_RES-		 |					      |
|		      |	OLUTION				 |					      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ER-			 | Timeout communicat-			      |
|		      |	ROR_STREAM_SOCKET		 | ing with server, or			      |
|		      |					 | connection closed.			      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ER-			 | Failed  to  connect			      |
|		      |	ROR_STREAM_CONNECT		 | to server.				      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_PROTO- |	MONGOC_ERROR_PROTO-		 | Corrupt    response			      |
| COL		      |	COL_INVALID_REPLY		 | from	server.				      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ERROR_PROTO-		 | The server  version			      |
|		      |	COL_BAD_WIRE_VERSION		 | is  too  old	or too			      |
|		      |					 | new to  communicate			      |
|		      |					 | with	the driver.			      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_CURSOR |	MONGOC_ERROR_CUR-		 | You	passed bad ar-			      |
|		      |	SOR_INVALID_CURSOR		 | guments	    to			      |
|		      |					 | mongoc_collection_find_with_opts(),	      |
|		      |					 | or	 you	called			      |
|		      |					 | mongoc_cursor_next()			      |
|		      |					 | on a	 completed  or			      |
|		      |					 | failed  cursor,  or			      |
|		      |					 | the	cursor	 timed			      |
|		      |					 | out on the server.			      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ER-			 | A  resume token was not returned in	      |
|		      |	ROR_CHANGE_STREAM_NO_RE-	 | a	 document      found	  with	      |
|		      |	SUME_TOKEN			 | mongoc_change_stream_next()		      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_QUERY  |	MONGOC_ERROR_QUERY_FAIL-	 | Error  API  Version 1: Server error	      |
|		      |	URE				 | from	command	or query.  The	server	      |
|		      |					 | error message is in message.		      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_SERVER |	MONGOC_ERROR_QUERY_FAIL-	 | Error  API  Version 2: Server error	      |
|		      |	URE				 | from	command	or query.  The	server	      |
|		      |					 | error message is in message.		      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_SASL   |	A SASL error code.		 | man	 sasl_errors  for  a  list  of	      |
|		      |					 | codes.				      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_BSON   |	MONGOC_ERROR_BSON_IN-		 | You passed an invalid or  oversized	      |
|		      |	VALID				 | BSON	 document  as  a parameter, or	      |
|		      |					 | called				      |
|		      |					 | mongoc_collection_create_index()	      |
|		      |					 | with	invalid	keys,  or  the	server	      |
|		      |					 | reply was corrupt.			      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_NAME-  |	MONGOC_ERROR_NAME-		 | You	tried  to  create a collection	      |
| SPACE		      |	SPACE_INVALID			 | with	an invalid name.		      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_COM-   |	MONGOC_ERROR_COMMAND_IN-	 | Many	functions set this error  code	      |
| MAND		      |	VALID_ARG			 | when	 passed	 bad parameters. Print	      |
|		      |					 | the error message for details.	      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ERROR_PROTO-		 | You tried to	use a  command	option	      |
|		      |	COL_BAD_WIRE_VERSION		 | the server does not support.		      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ERROR_DUPLI-		 | An  insert or update	failed because	      |
|		      |	CATE_KEY			 | because of a	duplicate _id or other	      |
|		      |					 | unique-index	violation.		      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ER-			 | The operation failed	 because  max-	      |
|		      |	ROR_MAX_TIME_MS_EXPIRED		 | TimeMS expired.			      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ERROR_SERVER_SE-		 | The	serverId  option for an	opera-	      |
|		      |	LECTION_INVALID_ID		 | tion	 conflicts  with  the	pinned	      |
|		      |					 | server  for that operation's	client	      |
|		      |					 | session (denoted by	the  sessionId	      |
|		      |					 | option).				      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_COM-   |	Error code from	server.		 | Error  API  Version 1: Server error	      |
| MAND		      |					 | from	a command.  The	 server	 error	      |
|		      |					 | message is in message.		      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_SERVER |	Error code from	server.		 | Error  API  Version 2: Server error	      |
|		      |					 | from	a command.  The	 server	 error	      |
|		      |					 | message is in message.		      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_COL-   |	MONGOC_ERROR_COLLEC-		 | Invalid   or	  empty	   input    to	      |
| LECTION	      |	TION_INSERT_FAILED, MON-	 | mongoc_collection_insert_one(),	      |
|		      |	GOC_ERROR_COLLECTION_UP-	 | mongoc_collection_insert_bulk(),	      |
|		      |	DATE_FAILED,  MONGOC_ER-	 | mongoc_collection_update_one(),	      |
|		      |	ROR_COLLEC-			 | mongoc_collection_update_many(),	      |
|		      |	TION_DELETE_FAILED.		 | mongoc_collection_replace_one(),	      |
|		      |					 | mongoc_collection_delete_one(),  or	      |
|		      |					 | mongoc_collection_delete_many().	      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_COL-   |	Error code from	server.		 | Error API Version 1:	 Server	 error	      |
| LECTION	      |					 | from					      |
|		      |					 | mongoc_collection_insert_one(),	      |
|		      |					 | mongoc_collection_insert_bulk(),	      |
|		      |					 | mongoc_collection_update_one(),	      |
|		      |					 | mongoc_collection_update_many(),	      |
|		      |					 | mongoc_collection_replace_one(),	      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_SERVER |	Error code from	server.		 | Error  API  Version 2: Server error	      |
|		      |					 | from					      |
|		      |					 | mongoc_collection_insert_one(),	      |
|		      |					 | mongoc_collection_insert_bulk(),	      |
|		      |					 | mongoc_collection_update_one(),	      |
|		      |					 | mongoc_collection_update_many(),	      |
|		      |					 | mongoc_collection_replace_one(),	      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_GRIDFS |	MONGOC_ER-			 | The GridFS file is missing a	 docu-	      |
|		      |	ROR_GRIDFS_CHUNK_MISSING	 | ment	in its chunks collection.	      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ERROR_GRIDFS_COR-	 | A  data  inconsistency was detected	      |
|		      |	RUPT				 | in GridFS.				      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ERROR_GRIDFS_IN-		 | You	passed	a  NULL	 filename   to	      |
|		      |	VALID_FILENAME			 | mongoc_gridfs_remove_by_filename().	      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ERROR_GRIDFS_PRO-	 | You				called	      |
|		      |	TOCOL_ERROR			 | mongoc_gridfs_file_set_id()	 after	      |
|		      |					 | mongoc_gridfs_file_save(), or tried	      |
|		      |					 | to write on a closed	GridFS stream.	      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ER-			 | A GridFS file is missing from files	      |
|		      |	ROR_GRIDFS_BUCKET_FILE_NOT_FOUND | collection.				      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ER-			 | An  error occurred on a stream cre-	      |
|		      |	ROR_GRIDFS_BUCKET_STREAM	 | ated	from a GridFS  operation  like	      |
|		      |					 | mongoc_gridfs_bucket_upload_from_stream(). |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_SCRAM  |	MONGOC_ERROR_SCRAM_PROTOCOL_ER-	 | Failure  in	SCRAM-SHA-1  or	SCRAM-SHA-256 |
|		      |	ROR				 | authentication.			      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ER-	      |	MONGOC_ERROR_SERVER_SELEC-	 | No replica set member or mongos is  avail- |
| ROR_SERVER_SELEC-   |	TION_FAILURE			 | able,  or  none  matches your read prefer- |
| TION		      |					 | ence,   or	you   supplied	 an   invalid |
|		      |					 | mongoc_read_prefs_t.			      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ER-	      |	Error code from	server.		 | There was a write concern error or timeout |
| ROR_WRITE_CONCERN   |					 | from	the server.			      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_TRANS- |	MONGOC_ERROR_TRANSACTION_INVALID | You	attempted to start a transaction when |
| ACTION	      |					 | one is already in progress, or  commit  or |
|		      |					 | abort when there is no transaction.	      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ER-	      |	Error  code  produced by libmon- | An error occurred in	the library responsi- |
| ROR_CLIENT_SIDE_EN- |	gocrypt.			 | ble for In-Use Encryption		      |
| CRYPTION	      |					 |					      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_AZURE  |	MONGOC_ERROR_KMS_SERVER_HTTP	 | An Azure HTTP service  responded  with  an |
|		      |					 | error status				      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ERROR_KMS_SERVER_BAD_JSON | An  Azure  service  responded with invalid |
|		      |					 | JSON	data				      |
+---------------------+----------------------------------+--------------------------------------------+
| MONGOC_ERROR_GCP    |	MONGOC_ERROR_KMS_SERVER_HTTP	 | A GCP HTTP service responded	with an	error |
|		      |					 | status				      |
+---------------------+----------------------------------+--------------------------------------------+
|		      |	MONGOC_ERROR_KMS_SERVER_BAD_JSON | A GCP service responded with	invalid	 JSON |
|		      |					 | data					      |
+---------------------+----------------------------------+--------------------------------------------+

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

       Any C Driver function that has a	bson_t 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 la-
       bel. 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 con-
       flicts, primary stepdowns, and network errors. In response, the	appli-
       cation should abort the transaction and try the same sequence of	opera-
       tions 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_ER-
       ROR_COMMAND, the	error code might originate from	the server or the dri-
       ver. 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_COLLEC-
       TION_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  do-
       main, MONGOC_ERROR_SERVER. In Version 2,	error codes originating	on the
       server  always  have  error  domain  MONGOC_ERROR_SERVER	 or MONGOC_ER-
       ROR_WRITE_CONCERN. When the driver uses Version 2 the  application  can
       always  determine  the  origin and meaning of error codes. New applica-
       tions 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_QUERY | MONGOC_ERROR_SERVER |
+-----------------------------------------------+--------------------+---------------------+
| mongoc_client_command_with_opts(),		| MONGOC_ERROR_QUERY | MONGOC_ERROR_SERVER |
| mongoc_database_command_with_opts(),		|		     |			   |
| and	other	command				|		     |			   |
| functions					|		     |			   |
+-----------------------------------------------+--------------------+---------------------+
| mongoc_collection_count_with_opts()		| MONGOC_ERROR_QUERY | MONGOC_ERROR_SERVER |
| mongoc_client_get_database_names_with_opts(),	|		     |			   |
| and other command helper functions		|		     |			   |
+-----------------------------------------------+--------------------+---------------------+
| mongoc_collection_insert_one()		| MONGOC_ERROR_COM-  | MONGOC_ERROR_SERVER |
| mongoc_collection_insert_bulk()		| MAND		     |			   |
| 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_COM-  | MONGOC_ERROR_SERVER |
|						| MAND		     |			   |
+-----------------------------------------------+--------------------+---------------------+
| Write-concern	timeout				| MONGOC_ER-	     | MONGOC_ER-	   |
|						| ROR_WRITE_CONCERN  | ROR_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

   Object Lifecycle
       This page documents the order of	creation and destruction  for  libmon-
       goc'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 ac-
       quires a	mongoc_client_t	from the  pool	with  mongoc_client_pool_pop()
       and  returns  it	with mongoc_client_pool_push() when the	thread is fin-
       ished 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. To	disable	causal consis-
       tency,  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 ses-
       sion 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 con-
       tains deprecated	API, does not support read  preferences,  and  is  not
       recommended  in	new  applications.  It does not	conform	to the MongoDB
       GridFS specification.

       The newer API consists of  mongoc_gridfs_bucket_t  and  allows  upload-
       ing/downloading through derived mongoc_stream_t objects.	It conforms to
       the MongoDB GridFS specification.

       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 En-
       cryption.

   Synopsis
	  typedef struct _mongoc_auto_encryption_opts_t	mongoc_auto_encryption_opts_t;

       SEE ALSO:
	  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 op-
	  erations 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_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 exe-
       cute 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
	  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 op-
	  erations 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 in-
       stead  of a raw aggregation with	a $changeStream	stage. For more	infor-
       mation see the MongoDB Manual Entry on Change Streams.

   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	opera-
       tion  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	exclu-
       sive 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;
	     ssize_t r,	n_written;
	     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);
	     n_written = 0;
	     while (n_written <	as_json_len) {
		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  En-
       cryption.

   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 for	libmongoc

	  The MongoDB Manual for Client-Side Field Level Encryption

	  The MongoDB Manual for 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_range_opts_t
   Synopsis
	  typedef struct _mongoc_client_encryption_encrypt_range_opts_t	mongoc_client_encryption_encrypt_range_opts_t;

       New in version 1.24.0.

       RangeOpts specifies index options for a Queryable Encryption field sup-
       porting	  "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.

   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 con-
       sistency. See the MongoDB Manual	Entry for 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. To	disable	causal consis-
       tency,  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 ses-
       sion 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 <stdio.h>
	  #include <mongoc/mongoc.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 com-
       mit transactions.

   Parameters
        session: 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 or NULL. The callback	should
	 set  this  if	it runs	any operations against the server and receives
	 replies.

        error:	A bson_error_t.	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.

   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 un-
       derlying	 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 cus-
       tom 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	recom-
       mended 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 han-
       dle is useful for actions for most CRUD operations,  I.e.  insert,  up-
       date, 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 net-
       work 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_delete_flags_t
       WARNING:
	  Deprecated  since  version 1.9.0: Use	mongoc_collection_delete_one()
	  or mongoc_collection_delete_many() instead.

   Synopsis
	  typedef enum {
	     MONGOC_DELETE_NONE	= 0,
	     MONGOC_DELETE_SINGLE_REMOVE = 1 <<	0,
	  } mongoc_delete_flags_t;

       Flags for deletion operations

   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.

       It  was created to be able to accommodate new arguments to the findAnd-
       Modify command.

       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 (gridfs, query);

	  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,	 meta-
	 data, 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	imple-
       mentation, superseding mongoc_gridfs_t. See the GridFS MongoDB documen-
       tation.

   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  de-
       rived  instances	 of  mongoc_stream_t.  The owning mongoc_client_t must
       outlive the mongoc_gridfs_bucket_t.

   Example
       example-gridfs-bucket.c

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

	  #include <mongoc/mongoc.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.

	  The non spec-compliant mongoc_gridfs_t.

   mongoc_gridfs_t
       WARNING:
	  This GridFS implementation does not conform to  the  MongoDB	GridFS
	  specification.    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 prac-
       tical  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 ex-
       isting gridfs object, just use them with	caution.

       mongoc_gridfs also integrates tightly with the mongoc_stream_t abstrac-
       tion, 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 in-
       stances of mongoc_gridfs_file_t and mongoc_gridfs_file_list_t.

   Example
       example-gridfs.c

	  #include <assert.h>
	  #include <mongoc/mongoc.h>
	  #include <stdio.h>
	  #include <stdlib.h>
	  #include <fcntl.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) != 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.

	  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_index_opt_geo_t
   Synopsis
	  #include <mongoc/mongoc.h>

	  typedef struct {
	     uint8_t twod_sphere_version;
	     uint8_t twod_bits_precision;
	     double twod_location_min;
	     double twod_location_max;
	     double haystack_bucket_size;
	     uint8_t *padding[32];
	  } mongoc_index_opt_geo_t;

   Description
       This  structure	contains the options that may be used for tuning a GEO
       index.

       SEE ALSO:
	  mongoc_index_opt_t

	  mongoc_index_opt_wt_t

   mongoc_index_opt_t
       WARNING:
	  Deprecated since version 1.8.0: See Manage  Collection  Indexes  for
	  alternatives.

   Synopsis
	  #include <mongoc/mongoc.h>

	  typedef struct {
	     bool is_initialized;
	     bool background;
	     bool unique;
	     const char	*name;
	     bool drop_dups;
	     bool sparse;
	     int32_t expire_after_seconds;
	     int32_t v;
	     const bson_t *weights;
	     const char	*default_language;
	     const char	*language_override;
	     mongoc_index_opt_geo_t *geo_options;
	     mongoc_index_opt_storage_t	*storage_options;
	     const bson_t *partial_filter_expression;
	     const bson_t *collation;
	     void *padding[4];
	  } mongoc_index_opt_t;

   Description
       This  structure contains	the options that may be	used for tuning	a spe-
       cific index.

       See the createIndexes documentations in the MongoDB manual for descrip-
       tions of	individual options.

       NOTE:
	  dropDups is deprecated as of MongoDB version 3.0.0.  This option  is
	  silently  ignored  by	 the server and	unique index builds using this
	  option will fail if a	duplicate value	is detected.

   Example
	  {
	     bson_t keys;
	     bson_error_t error;
	     mongoc_index_opt_t	opt;
	     mongoc_index_opt_geo_t geo_opt;

	     mongoc_index_opt_init (&opt);
	     mongoc_index_opt_geo_init (&geo_opt);

	     bson_init (&keys);
	     BSON_APPEND_UTF8 (&keys, "location", "2d");

	     geo_opt.twod_location_min = -123;
	     geo_opt.twod_location_max = +123;
	     geo_opt.twod_bits_precision = 30;
	     opt.geo_options = &geo_opt;

	     collection	= mongoc_client_get_collection (client,	"test",	"geo_test");
	     if	(mongoc_collection_create_index	(collection, &keys, &opt, &error)) {
		/* Successfully	created	the geo	index */
	     }
	     bson_destroy (&keys);
	     mongoc_collection_destroy (&collection);
	  }

       SEE ALSO:
	  mongoc_index_opt_geo_t

	  mongoc_index_opt_wt_t

   mongoc_index_opt_wt_t
   Synopsis
	  #include <mongoc/mongoc.h>

	  typedef struct {
	     mongoc_index_opt_storage_t	base;
	     const char	*config_str;
	     void *padding[8];
	  } mongoc_index_opt_wt_t;

   Description
       This structure contains the options that	 may  be  used	for  tuning  a
       WiredTiger specific index.

       SEE ALSO:
	  mongoc_index_opt_t

	  mongoc_index_opt_geo_t

   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 bit-
       wise or'd together. They	may modify how an insert happens on  the  Mon-
       goDB server.

   Flag	Values
	     +---------------------------+----------------------------+
	     | MONGOC_INSERT_NONE	 | Specify no insert flags.   |
	     +---------------------------+----------------------------+
	     | MONGOC_INSERT_CON-	 | Continue  inserting	docu- |
	     | TINUE_ON_ERROR		 | ments from  the  insertion |
	     |				 | set	even  if  one  insert |
	     |				 | fails.		      |
	     +---------------------------+----------------------------+
	     | MONGOC_INSERT_NO_VALIDATE | Do not validate  insertion |
	     |				 | documents  before perform- |
	     |				 | ing 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_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 ex-
       plicitly	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 bit-
       wise 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_CUR- | Cursor  will	not be closed |
	    | SOR			 | when	the last data is  re- |
	    |				 | trieved.  You  can  resume |
	    |				 | this	cursor later.	      |
	    +----------------------------+----------------------------+
	    | MONGOC_QUERY_SECONDARY_OK	 | Allow query of replica set |
	    |				 | secondaries.		      |
	    +----------------------------+----------------------------+
	    | MONGOC_QUERY_OPLOG_REPLAY	 | Used	 internally  by	 Mon- |
	    |				 | goDB.		      |
	    +----------------------------+----------------------------+
	    | MONGOC_QUERY_NO_CUR-	 | The	server normally	times |
	    | SOR_TIMEOUT		 | out an idle	cursor	after |
	    |				 | an  inactivity  period (10 |
	    |				 | minutes).  This   prevents |
	    |				 | that.		      |
	    +----------------------------+----------------------------+
	    | MONGOC_QUERY_AWAIT_DATA	 | Use	      with	 MON- |
	    |				 | GOC_QUERY_TAILABLE_CURSOR. |
	    |				 | Block rather	than  return- |
	    |				 | ing	no  data. After	a pe- |
	    |				 | riod, time out.	      |
	    +----------------------------+----------------------------+
	    | MONGOC_QUERY_EXHAUST	 | Stream the data down	 full |
	    |				 | blast  in multiple "reply" |
	    |				 | packets. Faster  when  you |
	    |				 | are	pulling	down a lot of |
	    |				 | data	and you	know you want |
	    |				 | to retrieve it all.	 Only |
	    |				 | applies to cursors created |
	    |				 | from	  a   find  operation |
	    |				 | (i.e.		      |
	    |				 | mongoc_collection_find()). |
	    +----------------------------+----------------------------+
	    | 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 spec-
       ify 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 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 ver- |
	|		      |			    | sion		  |
	+---------------------+---------------------+---------------------+
	| MONGOC_READ_CON-    |	Level "local",	the | 3.2		  |
	| CERN_LEVEL_LOCAL    |	default.	    |			  |
	+---------------------+---------------------+---------------------+
	| MONGOC_READ_CON-    |	Level "majority".   | 3.2		  |
	| CERN_LEVEL_MAJORITY |			    |			  |
	+---------------------+---------------------+---------------------+
	| MONGOC_READ_CON-    |	Level	 "lineariz- | 3.4		  |
	| CERN_LEVEL_LIN-     |	able".		    |			  |
	| EARIZABLE	      |			    |			  |
	+---------------------+---------------------+---------------------+
	| MONGOC_READ_CON-    |	Level "available".  | 3.6		  |
	| CERN_LEVEL_AVAIL-   |			    |			  |
	| ABLE		      |			    |			  |
	+---------------------+---------------------+---------------------+
	| MONGOC_READ_CON-    |	Level "snapshot".   | 4.0		  |
	| CERN_LEVEL_SNAPSHOT |			    |			  |
	+---------------------+---------------------+---------------------+

       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 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 MON-
       GOC_READ_PRIMARY.

       Please see the MongoDB website for a description	of Read	Preferences.

   mongoc_read_prefs_t
       A read preference abstraction

   Synopsis
       mongoc_read_prefs_t  provides an	abstraction on top of the MongoDB con-
       nection 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 opera- |
	    |				 | tions read from  the	 cur- |
	    |				 | rent	replica	set primary.  |
	    +----------------------------+----------------------------+
	    | MONGOC_READ_SECONDARY	 | All	operations  read from |
	    |				 | among  the  nearest	 sec- |
	    |				 | ondary   members   of  the |
	    |				 | replica set.		      |
	    +----------------------------+----------------------------+
	    | MONGOC_READ_PRIMARY_PRE-	 | In most situations, opera- |
	    | FERRED			 | tions read from  the	 pri- |
	    |				 | mary	but if it is unavail- |
	    |				 | able, operations read from |
	    |				 | secondary members.	      |
	    +----------------------------+----------------------------+
	    | MONGOC_READ_SECONDARY_PRE- | In most situations, opera- |
	    | FERRED			 | tions  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  con-
       cerns  so  that your application	can target operations to specific mem-
       bers.

       Custom read preferences and write concerns evaluate tags	sets  in  dif-
       ferent  ways: read preferences consider the value of a tag when select-
       ing 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  se-
       lect  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  prefer-
       ence 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_SMALL-
       EST_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
       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 dis-
       abled 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 bit-
       wise 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_RE-	| Only	 remove	  the  first |
	     | MOVE			| matching document from the |
	     |				| selector.		     |
	     +--------------------------+----------------------------+

   mongoc_reply_flags_t
       Flags from server replies

   Synopsis
	  typedef enum {
	     MONGOC_REPLY_NONE = 0,
	     MONGOC_REPLY_CURSOR_NOT_FOUND = 1 << 0,
	     MONGOC_REPLY_QUERY_FAILURE	= 1 << 1,
	     MONGOC_REPLY_SHARD_CONFIG_STALE = 1 << 2,
	     MONGOC_REPLY_AWAIT_CAPABLE	= 1 << 3,
	  } mongoc_reply_flags_t;

   Description
       These flags correspond to the wire protocol. They may be	 bitwise  or'd
       together.

   Flag	Values
	    +----------------------------+----------------------------+
	    | MONGOC_REPLY_NONE		 | No flags set.	      |
	    +----------------------------+----------------------------+
	    | MONGOC_REPLY_CUR-		 | No	matching  cursor  was |
	    | SOR_NOT_FOUND		 | found on the	server.	      |
	    +----------------------------+----------------------------+
	    | MONGOC_REPLY_QUERY_FAILURE | The query  failed  or  was |
	    |				 | invalid.   Error  document |
	    |				 | has been provided.	      |
	    +----------------------------+----------------------------+
	    | MONGOC_REPLY_SHARD_CON-	 | Shard config	is stale.     |
	    | FIG_STALE			 |			      |
	    +----------------------------+----------------------------+
	    | MONGOC_REPLY_AWAIT_CAPABLE | If the returned cursor  is |
	    |				 | capable	 of	 MON- |
	    |				 | GOC_QUERY_AWAIT_DATA.      |
	    +----------------------------+----------------------------+

   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 option-
       ally  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_descrip-
       tion_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. To	disable	causal consis-
       tency,  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 ses-
       sion 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 sup-
	  port 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 Mon-
       goDB 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

	  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 mon-
       goc_stream_t.

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

   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 dri-
       ver's knowledge of the MongoDB server or	servers	it  is	connected  to.
       Its API conforms	to the SDAM Monitoring Specification.

       Applications  receive  a	 temporary  reference to a mongoc_topology_de-
       scription_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	trans-
       action 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 <stdio.h>
	  #include <mongoc/mongoc.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_START-	 | A   transaction  has	 been |
	    | ING			 | started, but	no  operation |
	    |				 | has	 been	sent  to  the |
	    |				 | server.		      |
	    +----------------------------+----------------------------+
	    | MONGOC_TRANSAC-		 | A   transaction   is	   in |
	    | TION_IN_PROGRESS		 | progress.		      |
	    +----------------------------+----------------------------+
	    | MONGOC_TRANSACTION_COMMIT- | The	transaction  was com- |
	    | TED			 | mitted.		      |
	    +----------------------------+----------------------------+
	    | 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 bit-
       wise or'd together. The allow for modifying the way an update  is  per-
       formed 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 per- |
	    |				 | forming 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  au-
       thorization information.

       See Connection String URI Reference on the MongoDB website for more in-
       formation.

   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 "mon-
	  godb+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 host-
	  name,	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 'ad-
	  min' 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 follow-
       ing mongod hosts:

        db1.example.com on port 27017

        db2.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  with	 a  name  like	"_mon-
       godb._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 per-
       forms a DNS SRV query to	resolve	the service name to one	or more	 host-
       names.  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 pre-
       fer 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 en-
       vironment 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. A connection to the IPv6	address	is at-
       tempted 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  con-
       nection	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  configura-
       tion.  That is, only create an A	record if the mongod is	only listening
       on IPv4.

   Connection Options
+--------------------+------------------+------------------+-------------------------------------+
| Constant	     | Key		| Default	   | Description			 |
+--------------------+------------------+------------------+-------------------------------------+
| MON-		     | retryreads	| true		   | If	 "true"	  and			 |
| GOC_URI_RETRYREADS |			|		   | the  server is a			 |
|		     |			|		   | MongoDB	 3.6+			 |
|		     |			|		   | standalone,			 |
|		     |			|		   | replica  set, or			 |
|		     |			|		   | sharded cluster,			 |
|		     |			|		   | the       driver			 |
|		     |			|		   | safely retries a			 |
|		     |			|		   | read that failed			 |
|		     |			|		   | due to a network			 |
|		     |			|		   | error or replica			 |
|		     |			|		   | set failover.			 |
+--------------------+------------------+------------------+-------------------------------------+
| MONGOC_URI_RETRY-  | retrywrites	| true	if  driver | If	 "true"	  and			 |
| WRITES	     |			| built	w/ TLS	   | the  server is a			 |
|		     |			|		   | MongoDB	 3.6+			 |
|		     |			|		   | replica  set  or			 |
|		     |			|		   | sharded cluster,			 |
|		     |			|		   | the       driver			 |
|		     |			|		   | safely retries a			 |
|		     |			|		   | write	 that			 |
|		     |			|		   | failed due	to  a			 |
|		     |			|		   | network error or			 |
|		     |			|		   | replica	  set			 |
|		     |			|		   | failover.	 Only			 |
|		     |			|		   | inserts, updates			 |
|		     |			|		   | of	 single	docu-			 |
|		     |			|		   | ments,	   or			 |
|		     |			|		   | deletes  of sin-			 |
|		     |			|		   | gle    documents			 |
|		     |			|		   | are retried.			 |
+--------------------+------------------+------------------+-------------------------------------+
| MONGOC_URI_APPNAME | appname		| Empty	 (no  app- | The  client  ap-			 |
|		     |			| name)		   | plication	name.			 |
|		     |			|		   | This  value   is			 |
|		     |			|		   | used  by MongoDB			 |
|		     |			|		   | when   it	 logs			 |
|		     |			|		   | connection	  in-			 |
|		     |			|		   | formation	  and			 |
|		     |			|		   | profile informa-			 |
|		     |			|		   | tion,   such  as			 |
|		     |			|		   | slow queries.			 |
+--------------------+------------------+------------------+-------------------------------------+
| MONGOC_URI_TLS     | tls		| Empty	(not  set, | {true|false},			 |
|		     |			| same as false)   | indicating	   if			 |
|		     |			|		   | TLS   must	   be			 |
|		     |			|		   | used.  (See also			 |
|		     |			|		   | mongoc_client_set_ssl_opts()	 |
|		     |			|		   | and				 |
|		     |			|		   | mongoc_client_pool_set_ssl_opts().) |
+--------------------+------------------+------------------+-------------------------------------+
| MONGOC_URI_COM-    | compressors	| Empty	 (no  com- | Comma  separated  list  of	compres- |
| PRESSORS	     |			| pressors)	   | sors, if any, to  use  to	compress |
|		     |			|		   | the wire protocol messages. Snappy, |
|		     |			|		   | zlib,  and	 zstd are optional build |
|		     |			|		   | time dependencies,	and  enable  the |
|		     |			|		   | "snappy", "zlib", and "zstd" values |
|		     |			|		   | respectively.			 |
+--------------------+------------------+------------------+-------------------------------------+
| MONGOC_URI_CON-    | connecttimeoutms	| 10,000   ms  (10 | This setting applies to new  server |
| NECTTIMEOUTMS	     |			| seconds)	   | connections. It is	also used as the |
|		     |			|		   | socket timeout for	server discovery |
|		     |			|		   | and monitoring operations.		 |
+--------------------+------------------+------------------+-------------------------------------+
| MONGOC_URI_SOCKET- | sockettimeoutms	| 300,000   ms	(5 | The time in milliseconds to attempt |
| TIMEOUTMS	     |			| minutes)	   | to	send or	receive	on a socket  be- |
|		     |			|		   | fore the attempt times out.	 |
+--------------------+------------------+------------------+-------------------------------------+
| MONGOC_URI_REPLI-  | replicaset	| Empty	(no repli- | The  name	of  the	Replica	Set that |
| CASET		     |			| caset)	   | the driver	should connect to.	 |
+--------------------+------------------+------------------+-------------------------------------+
| MONGOC_URI_ZLIB-   | zlibcompression-	| -1		   | When the MONGOC_URI_COMPRESSORS in- |
| COMPRESSIONLEVEL   | level		|		   | cludes "zlib" this	options	 config- |
|		     |			|		   | ures  the	zlib  compression level, |
|		     |			|		   | when the zlib compressor is used to |
|		     |			|		   | compress client data.		 |
+--------------------+------------------+------------------+-------------------------------------+
| MONGOC_URI_LOAD-   | loadbalanced	| false		   | If	true, this indicates the  driver |
| BALANCED	     |			|		   | is	 connecting to a MongoDB cluster |
|		     |			|		   | behind a load balancer.		 |
+--------------------+------------------+------------------+-------------------------------------+
| MONGOC_URI_SRVMAX- | srvmaxhosts	| 0		   | If	zero, the number of hosts in DNS |
| HOSTS		     |			|		   | results is	 unlimited.  If	 greater |
|		     |			|		   | than  zero,  the number of	hosts in |
|		     |			|		   | DNS results  is  limited  to  being |
|		     |			|		   | less  than	 or  equal  to the given |
|		     |			|		   | value.				 |
+--------------------+------------------+------------------+-------------------------------------+

       WARNING:
	  Setting any of the *timeoutMS	options	above to either	0 or  a	 nega-
	  tive value is	discouraged due	to unspecified and inconsistent	behav-
	  ior.	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 exe-
	  cuted, even when specified by	the same URI option.  To  specify  the
	  documented default value for a *timeoutMS option, use	the MONGOC_DE-
	  FAULT_* constants defined in mongoc-client.h instead.

   Authentication Options
	 +---------------------+--------------------+---------------------+
	 | Constant	       | Key		    | Description	  |
	 +---------------------+--------------------+---------------------+
	 | MONGOC_URI_AUTH-    | authmechanism	    | Specifies	the mech- |
	 | MECHANISM	       |		    | anism  to	 use when |
	 |		       |		    | authenticating   as |
	 |		       |		    | the  provided user. |
	 |		       |		    | See  Authentication |
	 |		       |		    | for  supported val- |
	 |		       |		    | ues.		  |
	 +---------------------+--------------------+---------------------+
	 | MONGOC_URI_AUTH-    | authmechanismprop- | Certain authentica- |
	 | MECHANISMPROPERTIES | erties		    | tion     mechanisms |
	 |		       |		    | have additional op- |
	 |		       |		    | tions  that  can be |
	 |		       |		    | configured.   These |
	 |		       |		    | options  should  be |
	 |		       |		    | provided	as  comma |
	 |		       |		    | separated	      op- |
	 |		       |		    | tion_key:op-	  |
	 |		       |		    | tion_value pair and |
	 |		       |		    | provided	as  auth- |
	 |		       |		    | MechanismProper-	  |
	 |		       |		    | ties.    Specifying |
	 |		       |		    | the same option_key |
	 |		       |		    | multiple times  has |
	 |		       |		    | undefined	behavior. |
	 +---------------------+--------------------+---------------------+
	 | MONGOC_URI_AUTH-    | authsource	    | The  authSource de- |
	 | SOURCE	       |		    | fines the	 database |
	 |		       |		    | that should be used |
	 |		       |		    | to authenticate to. |
	 |		       |		    | It  is  unnecessary |
	 |		       |		    | to provide this op- |
	 |		       |		    | tion  the	 database |
	 |		       |		    | name is the same as |
	 |		       |		    | the  database  used |
	 |		       |		    | in the URI.	  |
	 +---------------------+--------------------+---------------------+

   Mechanism Properties
	 +---------------------+-------------------+---------------------+
	 | Constant	       | Key		   | Description	 |
	 +---------------------+-------------------+---------------------+
	 | MONGOC_URI_CANONI-  | canonicalizehost- | Use  the  canonical |
	 | CALIZEHOSTNAME      | name		   | hostname	of   the |
	 |		       |		   | service,	  rather |
	 |		       |		   | than its configured |
	 |		       |		   | alias, when authen- |
	 |		       |		   | ticating	    with |
	 |		       |		   | Cyrus-SASL	    Ker- |
	 |		       |		   | beros.		 |
	 +---------------------+-------------------+---------------------+
	 | MONGOC_URI_GSSAPIS- | gssapiservicename | Use     alternative |
	 | ERVICENAME	       |		   | service  name.  The |
	 |		       |		   | default is	mongodb. |
	 +---------------------+-------------------+---------------------+

   TLS Options
	+---------------------+---------------------+---------------------+
	| Constant	      |	Key		    | Description	  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_TLS      |	tls		    | {true|false}, indi- |
	|		      |			    | cating  if TLS must |
	|		      |			    | be used.		  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_TLSCER-  |	tlscertificatekey-  | Path to PEM format- |
	| TIFICATEKEYFILE     |	file		    | ted  Private   Key, |
	|		      |			    | with   its   Public |
	|		      |			    | Certificate    con- |
	|		      |			    | catenated	  at  the |
	|		      |			    | end.		  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_TLSCER-  |	tlscertificatekey-  | The  password,   if |
	| TIFICATEKEY-	      |	password	    | any,  to use to un- |
	| FILEPASSWORD	      |			    | lock encrypted Pri- |
	|		      |			    | vate Key.		  |
	+---------------------+---------------------+---------------------+
	| MON-		      |	tlscafile	    | One,  or	a  bundle |
	| GOC_URI_TLSCAFILE   |			    | of, Certificate Au- |
	|		      |			    | thorities	     whom |
	|		      |			    | should  be  consid- |
	|		      |			    | ered to be trusted. |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_TLSAL-   |	tlsallowinvalidcer- | Accept  and  ignore |
	| LOWINVALIDCERTIFI-  |	tificates	    | certificate verifi- |
	| CATES		      |			    | cation errors (e.g. |
	|		      |			    | untrusted	  issuer, |
	|		      |			    | expired, etc.)	  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_TLSAL-   |	tlsallowinvalid-    | Ignore	 hostname |
	| LOWINVALIDHOSTNAMES |	hostnames	    | verification of the |
	|		      |			    | certificate   (e.g. |
	|		      |			    | Man  In The Middle, |
	|		      |			    | using  valid   cer- |
	|		      |			    | tificate,	 but  is- |
	|		      |			    | sued  for	  another |
	|		      |			    | hostname)		  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_TLSINSE- |	tlsinsecure	    | {true|false}, indi- |
	| CURE		      |			    | cating  if insecure |
	|		      |			    | TLS options  should |
	|		      |			    | be  used.	Currently |
	|		      |			    | this  implies  MON- |
	|		      |			    | GOC_URI_TLSALLOWIN- |
	|		      |			    | VALIDCERTIFICATES	  |
	|		      |			    | and  MONGOC_URI_TL- |
	|		      |			    | SALLOWINVALIDHOST-  |
	|		      |			    | NAMES.		  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_TLSDIS-  |	tlsdisablecertifi-  | {true|false}, indi- |
	| ABLECERTIFICATERE-  |	caterevocationcheck | cates if revocation |
	| VOCATIONCHECK	      |			    | checking	 (CRL	/ |
	|		      |			    | OCSP)   should   be |
	|		      |			    | disabled.		  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_TLSDIS-  |	tlsdisableocspend-  | {true|false}, indi- |
	| ABLEOCSPEND-	      |	pointcheck	    | cates if	OCSP  re- |
	| POINTCHECK	      |			    | sponder	endpoints |
	|		      |			    | should not  be  re- |
	|		      |			    | quested	when   an |
	|		      |			    | OCSP  response   is |
	|		      |			    | not stapled.	  |
	+---------------------+---------------------+---------------------+

       See  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  fu-
       ture releases of	libmongoc.
 +-----------------------+------------------+-------------------+------------------+
 | Constant		 | Key		    | Deprecated For	| Key		   |
 +-----------------------+------------------+-------------------+------------------+
 | MONGOC_URI_SSL	 | ssl		    | MONGOC_URI_TLS	| tls		   |
 +-----------------------+------------------+-------------------+------------------+
 | MON-			 | sslclientcer-    | MON-		| tlscertifi-	   |
 | GOC_URI_SSLCLIENTCER- | tificatekeyfile  | GOC_URI_TLSCER-	| catekeyfile	   |
 | TIFICATEKEYFILE	 |		    | TIFICATEKEYFILE	|		   |
 +-----------------------+------------------+-------------------+------------------+
 | MON-			 | sslclientcer-    | MON-		| tlscertifi-	   |
 | GOC_URI_SSLCLIENTCER- | tificatekeypass- | GOC_URI_TLSCER-	| catekeypassword  |
 | TIFICATEKEYPASSWORD	 | word		    | TIFICATEKEY-	|		   |
 |			 |		    | FILEPASSWORD	|		   |
 +-----------------------+------------------+-------------------+------------------+
 | MONGOC_URI_SSLCER-	 | sslcertifi-	    | MON-		| tlscafile	   |
 | TIFICATEAUTHORITYFILE | cateauthority-   | GOC_URI_TLSCAFILE	|		   |
 |			 | file		    |			|		   |
 +-----------------------+------------------+-------------------+------------------+
 | MONGOC_URI_SSLALLOW-	 | sslallowinvalid- | MONGOC_URI_TLSAL-	| tlsallowinvalid- |
 | INVALIDCERTIFICATES	 | certificates	    | LOWINVALIDCER-	| certificates	   |
 |			 |		    | TIFICATES		|		   |
 +-----------------------+------------------+-------------------+------------------+
 | MONGOC_URI_SSLALLOW-	 | sslallowinvalid- | MONGOC_URI_TLSAL-	| tlsallowinvalid- |
 | INVALIDHOSTNAMES	 | hostnames	    | LOWINVALIDHOST-	| hostnames	   |
 |			 |		    | NAMES		|		   |
 +-----------------------+------------------+-------------------+------------------+

   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 (de-
       fault 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 in-
       sert--the thread	rescans	all servers every half-second. In this	situa-
       tion 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 sin-
       gle-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  try-
       ing  to	find  it,  then	 succeeds or returns an	error with domain MON-
       GOC_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  serverSelec-
       tionTryOnce is set "false".
	+---------------------+---------------------+---------------------+
	| Constant	      |	Key		    | Description	  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_HEART-   |	heartbeatfrequen-   | The   interval  be- |
	| BEATFREQUENCYMS     |	cyms		    | tween server  moni- |
	|		      |			    | toring  checks. De- |
	|		      |			    | faults to	 10,000ms |
	|		      |			    | (10   seconds)   in |
	|		      |			    | pooled		  |
	|		      |			    | (multi-threaded)	  |
	|		      |			    | mode, 60,000ms  (60 |
	|		      |			    | seconds)	       in |
	|		      |			    | non-pooled     mode |
	|		      |			    | (single-threaded).  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_SERVERS- |	serverselection-    | A	 timeout  in mil- |
	| ELECTIONTIMEOUTMS   |	timeoutms	    | liseconds	to  block |
	|		      |			    | for  server  selec- |
	|		      |			    | tion before  throw- |
	|		      |			    | ing  an  exception. |
	|		      |			    | The   default    is |
	|		      |			    | 30,0000ms	 (30 sec- |
	|		      |			    | onds).		  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_SERVERS- |	serverselectiontry- | If "true", the dri- |
	| ELECTIONTRYONCE     |	once		    | ver    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  serverSelec- |
	|		      |			    | tionTimeoutMS  mil- |
	|		      |			    | liseconds	 (pausing |
	|		      |			    | a	 half  second be- |
	|		      |			    | tween    attempts). |
	|		      |			    | The   default   for |
	|		      |			    | serverSelectionTry- |
	|		      |			    | Once is "false" for |
	|		      |			    | pooled	 clients, |
	|		      |			    | otherwise	  "true". |
	|		      |			    | Pooled clients  ig- |
	|		      |			    | nore   serverSelec- |
	|		      |			    | tionTryOnce;   they |
	|		      |			    | signal  the  thread |
	|		      |			    | to    rescan    the |
	|		      |			    | topology	    every |
	|		      |			    | half-second   until |
	|		      |			    | serverSelection-	  |
	|		      |			    | TimeoutMS	expires.  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_SOCK-    |	socketcheckinter-   | Only   applies   to |
	| ETCHECKINTERVALMS   |	valms		    | single	 threaded |
	|		      |			    | clients.	  If	a |
	|		      |			    | socket has not been |
	|		      |			    | used  within   this |
	|		      |			    | time,  its  connec- |
	|		      |			    | tion   is	  checked |
	|		      |			    | with     a    quick |
	|		      |			    | "hello" call before |
	|		      |			    | it is  used  again. |
	|		      |			    | Defaults to 5,000ms |
	|		      |			    | (5 seconds).	  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_DIRECT-  |	directconnection    | If "true", the dri- |
	| CONNECTION	      |			    | ver  connects  to	a |
	|		      |			    | single  server  di- |
	|		      |			    | rectly and will not |
	|		      |			    | monitor  additional |
	|		      |			    | servers.	       If |
	|		      |			    | "false", the driver |
	|		      |			    | connects	based  on |
	|		      |			    | the  presence   and |
	|		      |			    | value of the repli- |
	|		      |			    | caSet 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_MAXPOOL- | maxpoolsize	  | The	maximum	 number	     |
       | SIZE		     |			  | 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   an-	     |
       |		     |			  | other thread pushes	     |
       |		     |			  | a client.		     |
       +---------------------+--------------------+--------------------------+
       | MONGOC_URI_MINPOOL- | minpoolsize	  | Deprecated.	  This	 op- |
       | SIZE		     |			  | tion's behavior does not |
       |		     |			  | match its name, and	 its |
       |		     |			  | actual   behavior	will |
       |		     |			  | likely hurt	performance. |
       +---------------------+--------------------+--------------------------+
       | MONGOC_URI_MAXIDLE- | maxidletimems	  | Not	implemented.	     |
       | TIMEMS		     |			  |			     |
       +---------------------+--------------------+--------------------------+
       | MONGOC_URI_WAIT-    | waitqueuemultiple  | Not	implemented.	     |
       | QUEUEMULTIPLE	     |			  |			     |
       +---------------------+--------------------+--------------------------+
       | MONGOC_URI_WAIT-    | waitqueuetimeoutms | The	maximum	time to	wait |
       | QUEUETIMEOUTMS	     |			  | 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 |
	     |			  |	       |	  acknowl-   |
	     |			  |	       |	  edge write |
	     |			  |	       |	  operations |
	     |			  |	       |	  but	will |
	     |			  |	       |	  pass	  or |
	     |			  |	       |	  handle any |
	     |			  |	       |	  network    |
	     |			  |	       |	  and socket |
	     |			  |	       |	  errors     |
	     |			  |	       |	  that	  it |
	     |			  |	       |	  receives   |
	     |			  |	       |	  to	 the |
	     |			  |	       |	  client. If |
	     |			  |	       |	  you	dis- |
	     |			  |	       |	  able write |
	     |			  |	       |	  concern    |
	     |			  |	       |	  but enable |
	     |			  |	       |	  the	get- |
	     |			  |	       |	  LastError  |
	     |			  |	       |	  commands w |
	     |			  |	       |	  option,  w |
	     |			  |	       |	  overrides  |
	     |			  |	       |	  the  w op- |
	     |			  |	       |	  tion.	     |
	     |			  |	       |		     |
	     |			  |	       |	 1  =	Pro- |
	     |			  |	       |	  vides	 ba- |
	     |			  |	       |	  sic	 ac- |
	     |			  |	       |	  knowledge- |
	     |			  |	       |	  ment	  of |
	     |			  |	       |	  write	 op- |
	     |			  |	       |	  erations.  |
	     |			  |	       |	  By  speci- |
	     |			  |	       |	  fying	  1, |
	     |			  |	       |	  you	 re- |
	     |			  |	       |	  quire	that |
	     |			  |	       |	  a   stand- |
	     |			  |	       |	  alone	mon- |
	     |			  |	       |	  god	 in- |
	     |			  |	       |	  stance, or |
	     |			  |	       |	  the	pri- |
	     |			  |	       |	  mary	 for |
	     |			  |	       |	  replica    |
	     |			  |	       |	  sets,	 ac- |
	     |			  |	       |	  knowledge  |
	     |			  |	       |	  all  write |
	     |			  |	       |	  opera-     |
	     |			  |	       |	  tions. For |
	     |			  |	       |	  drivers    |
	     |			  |	       |	  released   |
	     |			  |	       |	  after	 the |
	     |			  |	       |	  default    |
	     |			  |	       |	  write	con- |
	     |			  |	       |	  cern	     |
	     |			  |	       |	  change,    |
	     |			  |	       |	  this	  is |
	     |			  |	       |	  the	 de- |
	     |			  |	       |	  fault	     |
	     |			  |	       |	  write	con- |
	     |			  |	       |	  cern	set- |
	     |			  |	       |	  ting.	     |
	     |			  |	       |		     |
	     |			  |	       |	 majority = |
	     |			  |	       |	  For	     |
	     |			  |	       |	  replica    |
	     |			  |	       |	  sets,	  if |
	     |			  |	       |	  you  spec- |
	     |			  |	       |	  ify	 the |
	     |			  |	       |	  special    |
	     |			  |	       |	  majority   |
	     |			  |	       |	  value	to w |
	     |			  |	       |	  option,    |
	     |			  |	       |	  write	 op- |
	     |			  |	       |	  erations   |
	     |			  |	       |	  will	only |
	     |			  |	       |	  return     |
	     |			  |	       |	  success-   |
	     |			  |	       |	  fully	 af- |
	     |			  |	       |	  ter a	 ma- |
	     |			  |	       |	  jority  of |
	     |			  |	       |	  the	con- |
	     |			  |	       |	  figured    |
	     |			  |	       |	  replica    |
	     |			  |	       |	  set	mem- |
	     |			  |	       |	  bers	have |
	     |			  |	       |	  acknowl-   |
	     |			  |	       |	  edged	 the |
	     |			  |	       |	  write	 op- |
	     |			  |	       |	  eration.   |
	     |			  |	       |		     |
	     |			  |	       |	 n   =	 For |
	     |			  |	       |	  replica    |
	     |			  |	       |	  sets,	  if |
	     |			  |	       |	  you  spec- |
	     |			  |	       |	  ify a	num- |
	     |			  |	       |	  ber	   n |
	     |			  |	       |	  greater    |
	     |			  |	       |	  than	  1, |
	     |			  |	       |	  operations |
	     |			  |	       |	  with	this |
	     |			  |	       |	  write	con- |
	     |			  |	       |	  cern	 re- |
	     |			  |	       |	  turn	only |
	     |			  |	       |	  after	   n |
	     |			  |	       |	  members of |
	     |			  |	       |	  the	 set |
	     |			  |	       |	  have	 ac- |
	     |			  |	       |	  knowledged |
	     |			  |	       |	  the write. |
	     |			  |	       |	  If you set |
	     |			  |	       |	  n   to   a |
	     |			  |	       |	  number     |
	     |			  |	       |	  that	  is |
	     |			  |	       |	  greater    |
	     |			  |	       |	  than	 the |
	     |			  |	       |	  number  of |
	     |			  |	       |	  available  |
	     |			  |	       |	  set	mem- |
	     |			  |	       |	  bers	  or |
	     |			  |	       |	  members    |
	     |			  |	       |	  that	hold |
	     |			  |	       |	  data,	Mon- |
	     |			  |	       |	  goDB	will |
	     |			  |	       |	  wait,	 po- |
	     |			  |	       |	  tentially  |
	     |			  |	       |	  indefi-    |
	     |			  |	       |	  nitely,    |
	     |			  |	       |	  for  these |
	     |			  |	       |	  members to |
	     |			  |	       |	  become     |
	     |			  |	       |	  available. |
	     |			  |	       |		     |
	     |			  |	       |	 tags = For |
	     |			  |	       |	  replica    |
	     |			  |	       |	  sets,	 you |
	     |			  |	       |	  can  spec- |
	     |			  |	       |	  ify a	 tag |
	     |			  |	       |	  set to re- |
	     |			  |	       |	  quire	that |
	     |			  |	       |	  all	mem- |
	     |			  |	       |	  bers	  of |
	     |			  |	       |	  the	 set |
	     |			  |	       |	  that	have |
	     |			  |	       |	  these	tags |
	     |			  |	       |	  configured |
	     |			  |	       |	  return     |
	     |			  |	       |	  confirma-  |
	     |			  |	       |	  tion	  of |
	     |			  |	       |	  the  write |
	     |			  |	       |	  operation. |
	     +--------------------+------------+---------------------+
	     | MONGOC_URI_WTIME-  | wtimeoutms | The  time  in	mil- |
	     | OUTMS		  |	       | liseconds  to	wait |
	     |			  |	       | for  replication to |
	     |			  |	       | succeed, as  speci- |
	     |			  |	       | fied  in  the w op- |
	     |			  |	       | tion, before timing |
	     |			  |	       | out.  When   wtime- |
	     |			  |	       | outMS	is  0, write |
	     |			  |	       | operations	will |
	     |			  |	       | never time out.     |
	     +--------------------+------------+---------------------+
	     | MONGOC_URI_JOURNAL | journal    | Controls    whether |
	     |			  |	       | write	  operations |
	     |			  |	       | will wait until the |
	     |			  |	       | mongod	acknowledges |
	     |			  |	       | the   write  opera- |
	     |			  |	       | tions	and  commits |
	     |			  |	       | the  data to the on |
	     |			  |	       | disk journal.	     |
	     |			  |	       |		     |
	     |			  |	       |	 true	   = |
	     |			  |	       |	  Enables    |
	     |			  |	       |	  journal    |
	     |			  |	       |	  commit ac- |
	     |			  |	       |	  knowledge- |
	     |			  |	       |	  ment write |
	     |			  |	       |	  concern.   |
	     |			  |	       |	  Equivalent |
	     |			  |	       |	  to  speci- |
	     |			  |	       |	  fying	 the |
	     |			  |	       |	  getLastEr- |
	     |			  |	       |	  ror	com- |
	     |			  |	       |	  mand	with |
	     |			  |	       |	  the  j op- |
	     |			  |	       |	  tion	 en- |
	     |			  |	       |	  abled.     |
	     |			  |	       |		     |
	     |			  |	       |	 false	   = |
	     |			  |	       |	  Does	 not |
	     |			  |	       |	  require    |
	     |			  |	       |	  that	mon- |
	     |			  |	       |	  god commit |
	     |			  |	       |	  write	 op- |
	     |			  |	       |	  erations   |
	     |			  |	       |	  to	 the |
	     |			  |	       |	  journal    |
	     |			  |	       |	  before ac- |
	     |			  |	       |	  knowledg-  |
	     |			  |	       |	  ing	 the |
	     |			  |	       |	  write	 op- |
	     |			  |	       |	  eration.   |
	     |			  |	       |	  This	  is |
	     |			  |	       |	  the	 de- |
	     |			  |	       |	  fault	 op- |
	     |			  |	       |	  tion	 for |
	     |			  |	       |	  the  jour- |
	     |			  |	       |	  nal  para- |
	     |			  |	       |	  meter.     |
	     +--------------------+------------+---------------------+

   Read	Concern	Options
	  +---------------------+------------------+---------------------+
	  | Constant		| Key		   | Description	 |
	  +---------------------+------------------+---------------------+
	  | MONGOC_URI_READCON-	| readconcernlevel | The level of isola- |
	  | CERNLEVEL		|		   | tion for read oper- |
	  |			|		   | ations.   If    the |
	  |			|		   | level  is	left un- |
	  |			|		   | specified,	     the |
	  |			|		   | server default will |
	  |			|		   | be	    used.    See |
	  |			|		   | readConcern in  the |
	  |			|		   | MongoDB  Manual 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_READ-    |	readpreference	    | Specifies	      the |
	| PREFERENCE	      |			    | replica  set   read |
	|		      |			    | preference for this |
	|		      |			    | connection.    This |
	|		      |			    | setting	overrides |
	|		      |			    | any     secondaryOk |
	|		      |			    | value.   The   read |
	|		      |			    | preference   values |
	|		      |			    | are the following:  |
	|		      |			    |			  |
	|		      |			    |	      primary	  |
	|		      |			    |	       (default)  |
	|		      |			    |			  |
	|		      |			    |	      prima-	  |
	|		      |			    |	       ryPre-	  |
	|		      |			    |	       ferred	  |
	|		      |			    |			  |
	|		      |			    |	      secondary  |
	|		      |			    |			  |
	|		      |			    |	      sec-	  |
	|		      |			    |	       ondaryPre- |
	|		      |			    |	       ferred	  |
	|		      |			    |			  |
	|		      |			    |	      nearest	  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_READ-    |	readpreferencetags  | A	representation of |
	| PREFERENCETAGS      |			    | a	tag set. See also |
	|		      |			    | Tag Sets.		  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_LO-      |	localthresholdms    | How far to distrib- |
	| CALTHRESHOLDMS      |			    | ute queries, beyond |
	|		      |			    | the server with the |
	|		      |			    | fastest  round-trip |
	|		      |			    | time.  By	 default, |
	|		      |			    | only servers within |
	|		      |			    | 15ms of the fastest |
	|		      |			    | round-trip time re- |
	|		      |			    | ceive queries.	  |
	+---------------------+---------------------+---------------------+
	| MONGOC_URI_MAXSTAL- |	maxstalenessseconds | The maximum  repli- |
	| ENESSSECONDS	      |			    | cation lag, in wall |
	|		      |			    | clock  time, that	a |
	|		      |			    | secondary	can  suf- |
	|		      |			    | fer  and	still  be |
	|		      |			    | eligible.	      The |
	|		      |			    | smallest	  allowed |
	|		      |			    | value for	maxStale- |
	|		      |			    | nessSeconds  is  90 |
	|		      |			    | seconds.		  |
	+---------------------+---------------------+---------------------+

       NOTE:
	  When	connecting  to	more than one mongos, libmongoc's localThresh-
	  oldMS	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.

   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  ob-
       jects,  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  collec-
       tion's  write  concern, and a write concern error or timeout in the re-
       sponse is considered a failure.

       Exceptions to this principle are	the generic command functions:

        mongoc_client_command()

        mongoc_client_command_simple()

        mongoc_database_command()

        mongoc_database_command_simple()

        mongoc_collection_command()

        mongoc_collection_command_simple()

       These generic command functions do not automatically apply a write con-
       cern, and they do not check the server response for a write concern er-
       ror or write concern timeout.

       See 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_DE- | By default,	writes	block |
	    | FAULT (1)			 | awaiting   acknowledgement |
	    |				 | from	MongoDB. Acknowledged |
	    |				 | write    concern    allows |
	    |				 | clients  to catch network, |
	    |				 | duplicate key,  and	other |
	    |				 | errors.		      |
	    +----------------------------+----------------------------+
	    | MONGOC_WRITE_CONCERN_W_UN- | With	 this  write concern, |
	    | ACKNOWLEDGED (0)		 | MongoDB does	not  acknowl- |
	    |				 | edge	 the receipt of	write |
	    |				 | operation.  Unacknowledged |
	    |				 | is  similar	to errors ig- |
	    |				 | nored; however, mongoc at- |
	    |				 | tempts to receive and han- |
	    |				 | dle	network	 errors	 when |
	    |				 | possible.		      |
	    +----------------------------+----------------------------+
	    | MONGOC_WRITE_CONCERN_W_MA- | Block  until	 a  write has |
	    | JORITY (majority)		 | been	propagated to  a  ma- |
	    |				 | jority of the nodes in the |
	    |				 | replica set.		      |
	    +----------------------------+----------------------------+
	    | n				 | Block  until	 a  write has |
	    |				 | been	 propagated   to   at |
	    |				 | least   n   nodes  in  the |
	    |				 | replica set.		      |
	    +----------------------------+----------------------------+

   Deprecations
       The write concern MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED (value -1) is a
       deprecated synonym for MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED (value 0),
       and will	be removed in the next major release.

       mongoc_write_concern_set_fsync()	is deprecated.

   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: events	related	to all application op-
	 erations.

        SDAM Monitoring: 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 discov-
       ers the third member, "localhost:27019",	and adds it to the topology.

AUTHOR
       MongoDB,	Inc

COPYRIGHT
       2009-present, MongoDB, Inc.

1.30.2				 Apr 12, 2025		   MONGOC_REFERENCE(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=mongoc_reference&sektion=3&manpath=FreeBSD+Ports+14.3.quarterly>

home | help