text: /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
  /*
   *     Copyright 2010-2020 Couchbase, Inc.
   *
   *   Licensed under the Apache License, Version 2.0 (the "License");
   *   you may not use this file except in compliance with the License.
   *   You may obtain a copy of the License at
   *
   *       http://www.apache.org/licenses/LICENSE-2.0
   *
   *   Unless required by applicable law or agreed to in writing, software
   *   distributed under the License is distributed on an "AS IS" BASIS,
   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *   See the License for the specific language governing permissions and
   *   limitations under the License.
   */
  
  #ifndef LIBCOUCHBASE_COUCHBASE_H
  #define LIBCOUCHBASE_COUCHBASE_H 1
  
  /**
   * @file
   * Main header file for Couchbase
   */
  
  struct lcb_st;
  
  /**
   * @ingroup lcb-init
   * Library handle representing a connection to a cluster and its data buckets. The contents
   * of this structure are opaque.
   * @see lcb_create
   * @see lcb_destroy
   */
  typedef struct lcb_st lcb_INSTANCE;
  typedef struct lcb_HTTP_HANDLE_ lcb_HTTP_HANDLE;
  
  #include <stddef.h>
  #include <time.h>
  #include <stdarg.h>
  #include <stdio.h>
  #include <libcouchbase/sysdefs.h>
  #include <libcouchbase/assert.h>
  #include <libcouchbase/visibility.h>
  #include <libcouchbase/error.h>
  #include <libcouchbase/iops.h>
  #include <libcouchbase/configuration.h>
  #include <libcouchbase/kvbuf.h>
  #include <libcouchbase/auth.h>
  #include <libcouchbase/tracing.h>
  #include <libcouchbase/logger.h>
  #include <libcouchbase/cntl.h>
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /******************************************************************************
   ******************************************************************************
   ******************************************************************************
   ** INITIALIZATION                                                           **
   ******************************************************************************
   ******************************************************************************
   ******************************************************************************/
  
  /**
   * @ingroup lcb-public-api
   * @defgroup lcb-init Initialization
   *
   * @details
   *
   * To communicate with a Couchbase cluster, a new library handle instance is
   * created in the form of an lcb_INSTANCE. To create such an object, the lcb_create()
   * function is called, passing it a structure of type lcb_create_st. The structure
   * acts as a container for a union of other structures which are extended
   * as more features are added. This container is forwards and backwards
   * compatible, meaning that if the structure is extended, you code and application
   * will still function if using an older version of the structure. The current
   * sub-field of the lcb_create_st structure is the `v3` field.
   *
   * Connecting to the cluster involes the client knowing the necessary
   * information needed to actually locate its services and connect to it.
   *
   * A connection specification consists of:
   *
   * 1. One or more hosts which comprise the cluster
   * 2. The name of the bucket to access and perform operations on
   * 3. The credentials of the bucket
   *
   * All these options are specified within the form of a URI in the form of
   *
   * `couchbase://$HOSTS/$BUCKET?$OPTIONS`
   *
   * @note
   * If any of the fields (hosts, bucket, options) contain the `/` character then
   * it _must_ be url-encoded; thus a bucket named `foo/bar` would be specified
   * as `couchbase:///foo%2Fbar`
   *
   * @par Hosts
   *
   * In the most typical use case, you would specify a list of several hostnames
   * delimited by a comma (`,`); each host specified should be a member of the
   * cluster. The library will use this list to initially connect to the cluster.
   *
   * Note that it is not necessary to specify _all_ the nodes of the cluster as in
   * a normal situation the library will only initially connect to one of the nodes.
   * Passing multiple nodes increases the chance of a connection succeeding even
   * if some of the nodes are currently down. Once connected to the cluster, the
   * client will update itself with the other nodes actually found within the
   * cluster and discard the list passed to it
   *
   * You can specify multiple hosts like so:
   *
   * `couchbase://foo.com,bar.com,baz.com`
   *
   * Or a single host:
   *
   * `couchbase://localhost`
   *
   * #### Specifying Ports and Protocol Options
   *
   * The default `couchbase://` scheme will assume all hosts and/or ports
   * specify the _memcached_ port. If no port is specified, it is assumed
   * that the port is _11210). For more extended options there are additional
   * schemes available:
   *
   * * `couchbases://` - Will assume all ports refer to the SSL-enabled memcached
   *   ports. This setting implicitly enables SSL on the instance as well. If no
   *   ports are provided for the hosts, the implicit port for each host will be
   *   _11207_.
   *
   * * `http://` - Will assume all ports refer to the HTTP REST API ports used
   *   by Couchbase 2.2 and lower. These are also used when connecting to a
   *   memcached bucket. If no port is specified it will be assumed the port is
   *   _8091_.
   *
   * ### Bucket
   *
   * A bucket may be specified by using the optional _path_ component of the URI
   * For protected buckets a password will still need to be supplied out of band.
   *
   * * `couchbase://1.1.1.1,2.2.2.2,3.3.3.3/users` - Connect to the `users`
   *   bucket.
   *
   * ### Options
   *
   * @warning The key-value options here are considered to be an uncommitted interface
   * as their names may change.
   *
   * Options can be specified as the _query_ part of the connection string,
   * for example:
   *
   * `couchbase://cbnode.net/beer?operation_timeout=10000000`.
   *
   * Options may either be appropriate _key_ parameters for lcb_cntl_string()
   * or one of the following:
   *
   * * `boostrap_on` - specify bootstrap protocols. Values can be `http` to force
   *   old-style bootstrap mode for legacy clusters, `cccp` to force bootstrap
   *   over the memcached port (For clusters 2.5 and above), or `all` to try with
   *   _cccp_ and revert to _http_
   *
   * * `truststorepath` - Specify the path (on the local filesystem) to the server's
   *   SSL certificate truststore. Only applicable if SSL is being used (i.e. the
   *   scheme is `couchbases`). The trust store is optional, and when missing,
   *   the library will use `certpath` as location for verification, and expect
   *   any extra certificates to be concatenated in there.
   *
   * * `certpath` - Specify the path (on the local filesystem) to the server's
   *   SSL certificate. Only applicable if SSL is being used (i.e. the scheme is
   *   `couchbases`)
   *
   * * `keypath` - Specify the path (on the local filesystem) to the client
   *   SSL private key. Only applicable if SSL client certificate authentication
   *   is being used (i.e. the scheme is `couchbases` and `certpath` contains
   *   client certificate). Read more in the server documentation:
   *   https://developer.couchbase.com/documentation/server/5.0/security/security-certs-auth.html
   *
   * ### Bucket Identification and Credentials
   *
   * The most common settings you will wish to modify are the bucket name
   *  and the credentials field (`user` and `passwd`). If a
   * `bucket` is not specified it will revert to the `default` bucket (i.e. the
   * bucket which is created when Couchbase Server is installed).
   *
   * The `user` and `passwd` fields authenticate for the bucket. This is only
   * needed if you have configured your bucket to employ SASL auth. You can tell
   * if the bucket has been configured with SASL auth by
   *
   * 1. Logging into the Couchbase Administration Console
   * 2. Going to the _Data Buckets_ tab
   * 3. Locate the row for your bucket
   * 4. Expand the row into the detailed view (by clicking on the arrow at the
   *    left of the row)
   * 5. Click on _Edit_
   * 6. Inspect the _Access Control_ section in the pop-up
   *
   * The bucket name is specified as the _path_ portion of the URI.
   *
   * For security purposes, the _user_ and _passwd_ cannot be specified within
   * the URI
   *
   *
   * @note
   * You may not change the bucket or credentials after initializing the handle.
   *
   * #### Bootstrap Options
   *
   * The default configuration process will attempt to bootstrap first from
   * the new memcached configuration protocol (CCCP) and if that fails, use
   * the "HTTP" protocol via the REST API.
   *
   * The CCCP configuration will by default attempt to connect to one of
   * the nodes specified on the port 11201. While normally the memcached port
   * is determined by the configuration itself, this is not possible when
   * the configuration has not been attained. You may specify a list of
   * alternate memcached servers by using the 'mchosts' field.
   *
   * If you wish to modify the default bootstrap protocol selection, you
   * can use the `bootstrap_on` option to specify the desired bootstrap
   * specification
   * to use for configuration (note that the ordering of this array is
   * ignored). Using this mechanism, you can disable CCCP or HTTP.
   *
   * To force only "new-style" bootstrap, you may use `bootstrap_on=cccp`.
   * To force only "old-style" bootstrap, use `bootstrap_on=http`. To force the
   * default behavior, use `bootstrap_on=all`
   *
   *
   * @addtogroup lcb-init
   * @{
   */
  
  /**
   * @brief Type of the bucket
   *
   * @see https://developer.couchbase.com/documentation/server/current/architecture/core-data-access-buckets.html
   */
  typedef enum {
      LCB_BTYPE_UNSPEC = 0x00,    /**< Unknown or unspecified */
      LCB_BTYPE_COUCHBASE = 0x01, /**< Data persisted and replicated */
      LCB_BTYPE_EPHEMERAL = 0x02, /**< Data not persisted, but replicated */
      LCB_BTYPE_MEMCACHED = 0x03  /**< Data not persisted and not replicated */
  } lcb_BTYPE;
  
  typedef enum {
      LCB_CONFIG_TRANSPORT_LIST_END = 0,
      LCB_CONFIG_TRANSPORT_HTTP = 1,
      LCB_CONFIG_TRANSPORT_CCCP,
      LCB_CONFIG_TRANSPORT_MAX
  } lcb_BOOTSTRAP_TRANSPORT;
  
  /** @brief Handle types @see lcb_create_st3::type */
  typedef enum {
      LCB_TYPE_BUCKET = 0x00, /**< Handle for data access (default) */
      LCB_TYPE_CLUSTER = 0x01 /**< Handle for administrative access */
  } lcb_INSTANCE_TYPE;
  
  typedef struct lcb_CREATEOPTS_ lcb_CREATEOPTS;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_createopts_create(lcb_CREATEOPTS **options, lcb_INSTANCE_TYPE type);
  LIBCOUCHBASE_API lcb_STATUS lcb_createopts_destroy(lcb_CREATEOPTS *options);
  LIBCOUCHBASE_API lcb_STATUS lcb_createopts_connstr(lcb_CREATEOPTS *options, const char *connstr, size_t connstr_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_createopts_bucket(lcb_CREATEOPTS *options, const char *bucket, size_t bucket_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_createopts_logger(lcb_CREATEOPTS *options, const lcb_LOGGER *logger);
  LIBCOUCHBASE_API lcb_STATUS lcb_createopts_credentials(lcb_CREATEOPTS *options, const char *username,
                                                         size_t username_len, const char *password, size_t password_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_createopts_authenticator(lcb_CREATEOPTS *options, lcb_AUTHENTICATOR *auth);
  LIBCOUCHBASE_API lcb_STATUS lcb_createopts_io(lcb_CREATEOPTS *options, struct lcb_io_opt_st *io);
  
  /**
   * @brief Create an instance of lcb.
   * @param instance Where the instance should be returned
   * @param options How to create the libcouchbase instance
   * @return LCB_SUCCESS on success
   *
   *
   * ### Examples
   * Create an instance using the default values:
   *
   * @code{.c}
   * lcb_INSTANCE *instance;
   * lcb_STATUS err = lcb_create(&instance, NULL);
   * if (err != LCB_SUCCESS) {
   *    fprintf(stderr, "Failed to create instance: %s\n", lcb_strerror_short(err));
   *    exit(EXIT_FAILURE);
   * }
   * @endcode
   *
   * Specify server list
   *
   * @code{.c}
   * struct lcb_create_st options;
   * memset(&options, 0, sizeof(options));
   * options.version = 3;
   * options.v.v3.connstr = "couchbase://host1,host2,host3";
   * err = lcb_create(&instance, &options);
   * @endcode
   *
   *
   * Create a handle for data requests to protected bucket
   *
   * @code{.c}
   * struct lcb_create_st options;
   * memset(&options, 0, sizeof(options));
   * options.version = 3;
   * options.v.v3.host = "couchbase://example.com,example.org/protected"
   * options.v.v3.passwd = "secret";
   * err = lcb_create(&instance, &options);
   * @endcode
   * @committed
   * @see lcb_create_st3
   */
  LIBCOUCHBASE_API
  lcb_STATUS lcb_create(lcb_INSTANCE **instance, const lcb_CREATEOPTS *options);
  
  /**
   * @brief Schedule the initial connection
   * This function will schedule the initial connection for the handle. This
   * function _must_ be called before any operations can be performed.
   *
   * lcb_set_bootstrap_callback() or lcb_get_bootstrap_status() can be used to
   * determine if the scheduled connection completed successfully.
   *
   * @par Synchronous Usage
   * @code{.c}
   * lcb_STATUS rc = lcb_connect(instance);
   * if (rc != LCB_SUCCESS) {
   *    your_error_handling(rc);
   * }
   * lcb_wait(instance, LCB_WAIT_DEFAULT);
   * rc = lcb_get_bootstrap_status(instance);
   * if (rc != LCB_SUCCESS) {
   *    your_error_handler(rc);
   * }
   * @endcode
   * @committed
   */
  LIBCOUCHBASE_API
  lcb_STATUS lcb_connect(lcb_INSTANCE *instance);
  
  /**
   * Bootstrap callback. Invoked once the instance is ready to perform operations
   * @param instance The instance which was bootstrapped
   * @param err The error code received. If this is not LCB_SUCCESS then the
   * instance is not bootstrapped and must be recreated
   *
   * @attention This callback only receives information during instantiation.
   * @committed
   */
  typedef void (*lcb_bootstrap_callback)(lcb_INSTANCE *instance, lcb_STATUS err);
  
  /**
   * @brief Set the callback for notification of success or failure of
   * initial connection.
   *
   * @param instance the instance
   * @param callback the callback to set. If `NULL`, return the existing callback
   * @return The existing (and previous) callback.
   * @see lcb_connect()
   * @see lcb_get_bootstrap_status()
   */
  LIBCOUCHBASE_API
  lcb_bootstrap_callback lcb_set_bootstrap_callback(lcb_INSTANCE *instance, lcb_bootstrap_callback callback);
  
  /**
   * @brief Gets the initial bootstrap status
   *
   * This is an alternative to using the lcb_bootstrap_callback() and may be used
   * after the initial lcb_connect() and lcb_wait() sequence.
   * @param instance
   * @return LCB_SUCCESS if properly bootstrapped or an error code otherwise.
   *
   * @attention
   * Calling this function only makes sense during instantiation.
   * @committed
   */
  LIBCOUCHBASE_API
  lcb_STATUS lcb_get_bootstrap_status(lcb_INSTANCE *instance);
  
  /**
   * Sets the authenticator object for the instance. This may be done anytime, but
   * should probably be done before calling `lcb_connect()` for best effect.
   *
   * @param instance the handle
   * @param auth the authenticator object used. The library will increase the
   * refcount on the authenticator object.
   */
  LIBCOUCHBASE_API
  void lcb_set_auth(lcb_INSTANCE *instance, lcb_AUTHENTICATOR *auth);
  /**@}*/
  
  /**
   * @ingroup lcb-public-api
   * @defgroup lcb-kv-api Key/Value
   *
   * @brief Preview APIs for performing commands
   *
   * @details
   * Basic command and structure definitions for public API. This represents the
   * "V3" API of libcouchbase. This API replaces the legacy API (which now wraps
   * this one). It contains common definitions for scheduling, response structures
   * and callback signatures.
   *
   * @addtogroup lcb-kv-api
   * @{
   */
  
  /** @ingroup lcb-mutation-tokens */
  typedef struct {
      uint64_t uuid_;  /**< @private */
      uint64_t seqno_; /**< @private */
      uint16_t vbid_;  /**< @private */
  } lcb_MUTATION_TOKEN;
  
  LIBCOUCHBASE_API int lcb_mutation_token_is_valid(const lcb_MUTATION_TOKEN *token);
  
  /**
   * @brief Response flags.
   * These provide additional 'meta' information about the response
   * They can be read from the response object with a call like
   * `lcb_respXXX_flags`, where the `XXX` is the operation -- like
   * get, exists, store, etc...  There is also a `lcb_respXXX_is_final`
   * method which reads the LCB_RESP_F_FINAL flag for those operations
   * that execute the callback multiple times.
   */
  typedef enum {
      /** No more responses are to be received for this request */
      LCB_RESP_F_FINAL = 0x01,
  
      /**The response was artificially generated inside the client.
       * This does not contain reply data from the server for the command, but
       * rather contains the basic fields to indicate success or failure and is
       * otherwise empty.
       */
      LCB_RESP_F_CLIENTGEN = 0x02,
  
      /**The response was a result of a not-my-vbucket error */
      LCB_RESP_F_NMVGEN = 0x04,
  
      /**The response has additional internal data.
       * Used by lcb_resp_get_mutation_token() */
      LCB_RESP_F_EXTDATA = 0x08,
  
      /**Flag, only valid for subdoc responses, indicates that the response was
       * processed using the single-operation protocol. */
      LCB_RESP_F_SDSINGLE = 0x10,
  
      /**The response has extra error information as value (see SDK-RFC-28). */
      LCB_RESP_F_ERRINFO = 0x20
  } lcb_RESPFLAGS;
  
  /**
   * The type of response passed to the callback. This is used to install callbacks
   * for the library and to distinguish between responses if a single callback
   * is used for multiple response types.
   *
   * @note These callbacks may conflict with the older version 2 callbacks. The
   * rules are as follows:
   * * If a callback has been installed using lcb_install_callback3(), then
   * the older version 2 callback will not be invoked for that operation. The order
   * of installation does not matter.
   * * If the LCB_CALLBACK_DEFAULT callback is installed, _none_ of the version 2
   * callbacks are invoked.
   */
  typedef enum {
      LCB_CALLBACK_DEFAULT = 0, /**< Default callback invoked as a fallback */
      LCB_CALLBACK_GET,         /**< lcb_get() */
      LCB_CALLBACK_STORE,       /**< lcb_store() */
      LCB_CALLBACK_COUNTER,     /**< lcb_counter() */
      LCB_CALLBACK_TOUCH,       /**< lcb_touch() */
      LCB_CALLBACK_REMOVE,      /**< lcb_remove() */
      LCB_CALLBACK_UNLOCK,      /**< lcb_unlock() */
      LCB_CALLBACK_STATS,       /**< lcb_stats3() */
      LCB_CALLBACK_VERSIONS,    /**< lcb_server_versions() */
      LCB_CALLBACK_VERBOSITY,   /**< lcb_server_verbosity() */
      LCB_CALLBACK_OBSERVE,     /**< lcb_observe3_ctxnew() */
      LCB_CALLBACK_GETREPLICA,  /**< lcb_getreplica() */
      LCB_CALLBACK_ENDURE,      /**< lcb_endure3_ctxnew() */
      LCB_CALLBACK_HTTP,        /**< lcb_http() */
      LCB_CALLBACK_CBFLUSH,     /**< lcb_cbflush3() */
      LCB_CALLBACK_OBSEQNO,     /**< For lcb_observe_seqno3() */
      LCB_CALLBACK_STOREDUR,    /** <for lcb_storedur3() */
      LCB_CALLBACK_SDLOOKUP,
      LCB_CALLBACK_SDMUTATE,
      LCB_CALLBACK_NOOP,                     /**< lcb_noop3() */
      LCB_CALLBACK_PING,                     /**< lcb_ping3() */
      LCB_CALLBACK_DIAG,                     /**< lcb_diag() */
      LCB_CALLBACK_COLLECTIONS_GET_MANIFEST, /**< lcb_getmanifest() */
      LCB_CALLBACK_GETCID,                   /**< lcb_getcid() */
      LCB_CALLBACK_EXISTS,                   /**< lcb_exists() */
      LCB_CALLBACK__MAX                      /* Number of callbacks */
  } lcb_CALLBACK_TYPE;
  
  /* The following callback types cannot be set using lcb_install_callback(),
   * however, their value is passed along as the second argument of their
   * respective callbacks. This allows you to still use the same callback,
   * differentiating their meaning by the type. */
  
  /** Callback type for views (cannot be used for lcb_install_callback3()) */
  #define LCB_CALLBACK_VIEWQUERY -1
  
  /** Callback type for N1QL (cannot be used for lcb_install_callback3()) */
  #define LCB_CALLBACK_QUERY -2
  
  /** Callback type for N1QL index management (cannot be used for lcb_install_callback3()) */
  #define LCB_CALLBACK_IXMGMT -3
  
  /** Callback type for Analytics (cannot be used for lcb_install_callback3()) */
  #define LCB_CALLBACK_ANALYTICS -4
  
  /** Callback type for Search (cannot be used for lcb_install_callback3()) */
  #define LCB_CALLBACK_SEARCH -5
  
  #define LCB_CALLBACK_OPEN -6
  
  /**
   * @uncommitted
   * Durability levels
   */
  typedef enum {
      LCB_DURABILITYLEVEL_NONE = 0x00,
      /**
       * Mutation must be replicated to (i.e. held in memory of that node) a
       * majority ((configured_nodes / 2) + 1) of the configured nodes of the
       * bucket.
       */
      LCB_DURABILITYLEVEL_MAJORITY = 0x01,
      /**
       * As majority, but additionally persisted to the active node.
       */
      LCB_DURABILITYLEVEL_MAJORITY_AND_PERSIST_TO_ACTIVE = 0x02,
      /**
       * Mutation must be persisted to (i.e. written and fsync'd to disk) a
       * majority of the configured nodes of the bucket.
       */
      LCB_DURABILITYLEVEL_PERSIST_TO_MAJORITY = 0x03
  } lcb_DURABILITY_LEVEL;
  
  typedef struct lcb_CMDBASE_ lcb_CMDBASE;
  typedef struct lcb_RESPBASE_ lcb_RESPBASE;
  
  /**
   * Callback invoked for responses.
   * @param instance The handle
   * @param cbtype The type of callback - or in other words, the type of operation
   * this callback has been invoked for.
   * @param resp The response for the operation. Depending on the operation this
   * response structure should be casted into a more specialized type.
   */
  typedef void (*lcb_RESPCALLBACK)(lcb_INSTANCE *instance, int cbtype, const lcb_RESPBASE *resp);
  
  /**
   * @committed
   *
   * Install a new-style callback for an operation. The callback will be invoked
   * with the relevant response structure.
   *
   * @param instance the handle
   * @param cbtype the type of operation for which this callback should be installed.
   *        The value should be one of the lcb_CALLBACK_TYPE constants
   * @param cb the callback to install
   * @return the old callback
   *
   * @note LCB_CALLBACK_DEFAULT is initialized to the default handler which proxies
   * back to the older 2.x callbacks. If you set `cbtype` to LCB_CALLBACK_DEFAULT
   * then your `2.x` callbacks _will not work_.
   *
   * @note The old callback may be `NULL`. It is usually not an error to have a
   * `NULL` callback installed. If the callback is `NULL`, then the default callback
   * invocation pattern will take place (as desribed above). However it is an error
   * to set the default callback to `NULL`.
   */
  LIBCOUCHBASE_API
  lcb_RESPCALLBACK lcb_install_callback(lcb_INSTANCE *instance, int cbtype, lcb_RESPCALLBACK cb);
  
  /**
   * @committed
   *
   * Get the current callback installed as `cbtype`. Note that this does not
   * perform any kind of resolution (as described in lcb_install_callback3) and
   * will only return a non-`NULL` value if a callback had specifically been
   * installed via lcb_install_callback3() with the given `cbtype`.
   *
   * @param instance the handle
   * @param cbtype the type of callback to retrieve
   * @return the installed callback for the type.
   */
  LIBCOUCHBASE_API
  lcb_RESPCALLBACK lcb_get_callback(lcb_INSTANCE *instance, int cbtype);
  
  /**
   * Returns the type of the callback as a string.
   * This function is helpful for debugging and demonstrative processes.
   * @param cbtype the type of the callback (the second argument to the callback)
   * @return a string describing the callback type
   */
  LIBCOUCHBASE_API
  const char *lcb_strcbtype(int cbtype);
  
  /**
   * @ingroup lcb-kv-api
   * @defgroup lcb-get Read
   * @brief Retrieve a document from the cluster
   * @addtogroup lcb-get
   * @{
   */
  
  /**@brief Command for retrieving a single item
   *
   * @see lcb_get()
   * @see lcb_RESPGET
   *
   * ### Use of the `exptime` field
   *
   * <ul>
   * <li>Get And Touch:
   *
   * It is possible to retrieve an item and concurrently modify its expiration
   * time (thus keeping it "alive"). The item's expiry time can be set by
   * calling #lcb_cmdget_expiry.
   * </li>
   *
   * <li>Lock
   * Calling #lcb_cmdget_locktime will set the time the lock should be held for
   * </li>
   * </ul>
   */
  
  /**
   * @committed
   *
   * @brief Spool a single get operation
   * @param instance the handle
   * @param cookie a pointer to be associated with the command
   * @param cmd the command structure
   * @return LCB_SUCCESS if successful, an error code otherwise
   *
   * @par Request
   * @code{.c}
   * lcb_CMDGET* cmd;
   * lcb_cmdget_create(&cmd);
   * lcb_cmdget_key(cmd, "Hello", 5);
   * lcb_get(instance, cookie, cmd);
   * @endcode
   *
   * @par Response
   * @code{.c}
   * lcb_install_callback(instance, LCB_CALLBACK_GET, get_callback);
   * static void get_callback(lcb_INSTANCE *instance, int cbtype, const lcb_RESPBASE *rb) {
   *     const lcb_RESPGET *resp = (const lcb_RESPGET*)rb;
   *     char* key;
   *     char* value;
   *     size_t key_len;
   *     size_t value_len;
   *     uint64_t cas;
   *     uint32_t flags;
   *     lcb_respget_key(resp, &key, &key_len);
   *     printf("Got response for key: %.*s\n", key_len, key);
   *
   *
   *     lcb_STATUS rc = lcb_respget_status(resp);
   *     if (rc != LCB_SUCCESS) {
   *         printf("Couldn't get item: %s\n", lcb_strerror_short(rc));
   *     } else {
   *         lcb_respget_cas(resp, &cas);
   *         lcb_respget_value(resp, &value, &value_len);
   *         lcb_respget_flags(resp, &flags);
   *         printf("Got value: %.*s\n", value_len, value);
   *         printf("Got CAS: 0x%llx\n", cas);
   *         printf("Got item/formatting flags: 0x%x\n", flags);
   *     }
   * }
   *
   * @endcode
   *
   * @par Errors
   * @cb_err ::LCB_ERR_DOCUMENT_NOT_FOUND if the item does not exist in the cluster
   * @cb_err ::LCB_ERR_TEMPORARY_FAILURE if the lcb_cmdget_locktime was set but the item
   * was already locked. Note that this error may also be returned (as a generic
   * error) if there is a resource constraint within the server itself.
   */
  
  typedef struct lcb_RESPGET_ lcb_RESPGET;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respget_status(const lcb_RESPGET *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respget_error_context(const lcb_RESPGET *resp, const lcb_KEY_VALUE_ERROR_CONTEXT **ctx);
  LIBCOUCHBASE_API lcb_STATUS lcb_respget_cookie(const lcb_RESPGET *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respget_cas(const lcb_RESPGET *resp, uint64_t *cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_respget_datatype(const lcb_RESPGET *resp, uint8_t *datatype);
  LIBCOUCHBASE_API lcb_STATUS lcb_respget_flags(const lcb_RESPGET *resp, uint32_t *flags);
  LIBCOUCHBASE_API lcb_STATUS lcb_respget_key(const lcb_RESPGET *resp, const char **key, size_t *key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respget_value(const lcb_RESPGET *resp, const char **value, size_t *value_len);
  
  typedef struct lcb_CMDGET_ lcb_CMDGET;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_create(lcb_CMDGET **cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_destroy(lcb_CMDGET *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_parent_span(lcb_CMDGET *cmd, lcbtrace_SPAN *span);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_collection(lcb_CMDGET *cmd, const char *scope, size_t scope_len,
                                                    const char *collection, size_t collection_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_key(lcb_CMDGET *cmd, const char *key, size_t key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_expiry(lcb_CMDGET *cmd, uint32_t expiration);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_locktime(lcb_CMDGET *cmd, uint32_t duration);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdget_timeout(lcb_CMDGET *cmd, uint32_t timeout);
  
  LIBCOUCHBASE_API lcb_STATUS lcb_get(lcb_INSTANCE *instance, void *cookie, const lcb_CMDGET *cmd);
  /**@}*/
  
  /**
   * @ingroup lcb-kv-api
   * @defgroup lcb-get-replica Read (Replica)
   * @brief Retrieve a document from a replica if it cannot be fetched from the
   * primary
   * @addtogroup lcb-get-replica
   * @{
   */
  
  /**@committed
   *
   * @brief Spool a single get-with-replica request
   * @param instance
   * @param cookie
   * @param cmd
   * @return LCB_SUCCESS on success, error code otherwise.
   *
   * When a response is received, the callback installed for ::LCB_CALLBACK_GETREPLICA
   * will be invoked. The response will be an @ref lcb_RESPGET pointer.
   *
   * ### Request
   * @code{.c}
   * lcb_CMDGETREPLICA* cmd;
   * lcb_cmdgetreplica_create(&cmd);
   * lcb_cmdgetreplica_key(cmd, "key", 3);
   * lcb_cmdgetreplica(instance, cookie, &cmd);
   * @endcode
   *
   * ### Response
   * @code{.c}
   * lcb_install_callback(instance, LCB_CALLBACK_GETREPLICA, rget_callback);
   * static void rget_callback(lcb_INSTANCE *instance, int cbtype, const lcb_RESPBASE *rb)
   * {
   *     const lcb_RESPGET *resp = (const lcb_RESPGET *)rb;
   *     char* key;
   *     char* value;
   *     size_t key_len;
   *     size_t value_len;
   *     lcb_STATUS rc = lcb_respgetreplica_status(resp);
   *     lcb_respgetreplica_key(resp, &key, &key_len);
   *     printf("Got Get-From-Replica response for %.*s\n", key_len, key);
   *     if (rc == LCB_SUCCESS) {
   *         lcb_respgetreplica_value(resp, &value, &value_len);
   *         printf("Got response: %.*s\n", value_len, value);
   *     else {
   *         printf("Couldn't retrieve: %s\n", lcb_strerror_short(rc));
   *     }
   * }
   * @endcode
   *
   * @warning As this function queries a replica node for data it is possible
   * that the returned document may not reflect the latest document in the server.
   *
   * @warning This function should only be used in cases where a normal lcb_get3()
   * has failed, or where there is reason to believe it will fail. Because this
   * function may query more than a single replica it may cause additional network
   * and server-side CPU load. Use sparingly and only when necessary.
   *
   * @cb_err ::LCB_ERR_DOCUMENT_NOT_FOUND if the key is not found on the replica(s),
   * ::LCB_ERR_NO_MATCHING_SERVER if there are no replicas (either configured or online),
   * or if the given replica
   * (if lcb_CMDGETREPLICA::strategy is ::LCB_REPLICA_SELECT) is not available or
   * is offline.
   */
  
  typedef enum {
      LCB_REPLICA_MODE_ANY = 0x00,
      LCB_REPLICA_MODE_ALL = 0x01,
      LCB_REPLICA_MODE_IDX0 = 0x02,
      LCB_REPLICA_MODE_IDX1 = 0x03,
      LCB_REPLICA_MODE_IDX2 = 0x04,
      LCB_REPLICA_MODE__MAX
  } lcb_REPLICA_MODE;
  
  typedef struct lcb_RESPGETREPLICA_ lcb_RESPGETREPLICA;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respgetreplica_status(const lcb_RESPGETREPLICA *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respgetreplica_error_context(const lcb_RESPGETREPLICA *resp,
                                                               const lcb_KEY_VALUE_ERROR_CONTEXT **ctx);
  LIBCOUCHBASE_API lcb_STATUS lcb_respgetreplica_cookie(const lcb_RESPGETREPLICA *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respgetreplica_cas(const lcb_RESPGETREPLICA *resp, uint64_t *cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_respgetreplica_datatype(const lcb_RESPGETREPLICA *resp, uint8_t *datatype);
  LIBCOUCHBASE_API lcb_STATUS lcb_respgetreplica_flags(const lcb_RESPGETREPLICA *resp, uint32_t *flags);
  LIBCOUCHBASE_API lcb_STATUS lcb_respgetreplica_key(const lcb_RESPGETREPLICA *resp, const char **key, size_t *key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respgetreplica_value(const lcb_RESPGETREPLICA *resp, const char **value,
                                                       size_t *value_len);
  LIBCOUCHBASE_API int lcb_respgetreplica_is_final(const lcb_RESPGETREPLICA *resp);
  
  typedef struct lcb_CMDGETREPLICA_ lcb_CMDGETREPLICA;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdgetreplica_create(lcb_CMDGETREPLICA **cmd, lcb_REPLICA_MODE mode);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdgetreplica_destroy(lcb_CMDGETREPLICA *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdgetreplica_parent_span(lcb_CMDGETREPLICA *cmd, lcbtrace_SPAN *span);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdgetreplica_collection(lcb_CMDGETREPLICA *cmd, const char *scope, size_t scope_len,
                                                           const char *collection, size_t collection_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdgetreplica_key(lcb_CMDGETREPLICA *cmd, const char *key, size_t key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdgetreplica_timeout(lcb_CMDGETREPLICA *cmd, uint32_t timeout);
  LIBCOUCHBASE_API lcb_STATUS lcb_getreplica(lcb_INSTANCE *instance, void *cookie, const lcb_CMDGETREPLICA *cmd);
  
  /**@}*/
  
  typedef struct lcb_RESPEXISTS_ lcb_RESPEXISTS;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respexists_status(const lcb_RESPEXISTS *resp);
  LIBCOUCHBASE_API int lcb_respexists_is_found(const lcb_RESPEXISTS *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respexists_error_context(const lcb_RESPEXISTS *resp,
                                                           const lcb_KEY_VALUE_ERROR_CONTEXT **ctx);
  LIBCOUCHBASE_API lcb_STATUS lcb_respexists_cookie(const lcb_RESPEXISTS *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respexists_cas(const lcb_RESPEXISTS *resp, uint64_t *cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_respexists_key(const lcb_RESPEXISTS *resp, const char **key, size_t *key_len);
  
  typedef struct lcb_CMDEXISTS_ lcb_CMDEXISTS;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdexists_create(lcb_CMDEXISTS **cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdexists_destroy(lcb_CMDEXISTS *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdexists_parent_span(lcb_CMDEXISTS *cmd, lcbtrace_SPAN *span);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdexists_collection(lcb_CMDEXISTS *cmd, const char *scope, size_t scope_len,
                                                       const char *collection, size_t collection_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdexists_key(lcb_CMDEXISTS *cmd, const char *key, size_t key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdexists_timeout(lcb_CMDEXISTS *cmd, uint32_t timeout);
  
  LIBCOUCHBASE_API lcb_STATUS lcb_exists(lcb_INSTANCE *instance, void *cookie, const lcb_CMDEXISTS *cmd);
  
  /**
   * @ingroup lcb-kv-api
   * @defgroup lcb-store Create/Update
   * @brief Set the value of a document
   * @addtogroup lcb-store
   * @{
   */
  
  /**
   * @brief Values for lcb_CMDSTORE::operation
   *
   * Storing an item in couchbase is only one operation with a different
   * set of attributes / constraints.
   */
  typedef enum {
      /**
       * The default storage mode. This constant was added in version 2.6.2 for
       * the sake of maintaining a default storage mode, eliminating the need
       * for simple storage operations to explicitly define
       * lcb_CMDSTORE::operation. Behaviorally it is identical to @ref LCB_STORE_UPSERT
       * in that it will make the server unconditionally store the item, whether
       * it exists or not.
       */
      LCB_STORE_UPSERT = 0x00,
  
      /**
       * Will cause the operation to fail if the key already exists in the
       * cluster.
       */
      LCB_STORE_INSERT = 0x01,
  
      /**
       * Will cause the operation to fail _unless_ the key already exists in the
       * cluster.
       */
      LCB_STORE_REPLACE = 0x02,
  
      /**
       * Rather than setting the contents of the entire document, take the value
       * specified in lcb_CMDSTORE::value and _append_ it to the existing bytes in
       * the value.
       */
      LCB_STORE_APPEND = 0x04,
  
      /**
       * Like ::LCB_STORE_APPEND, but prepends the new value to the existing value.
       */
      LCB_STORE_PREPEND = 0x05
  } lcb_STORE_OPERATION;
  
  /**
   * @committed
   * @brief Schedule a single storage request
   * @param instance the handle
   * @param cookie pointer to associate with the command
   * @param cmd the command structure
   * @return LCB_SUCCESS on success, error code on failure
   *
   * ### Request
   *
   * @code{.c}
   * lcb_CMDSTORE* cmd;
   * // insert only if key doesn't already exist
   * lcb_cmdstore_create(&cmd, LCB_STORE_INSERT);
   * lcb_cmdstore_key(cmd, "Key", 3);
   * lcb_cmdstore_value(cmd, "value", 5);
   * lcb_cmdstore_expiry(cmd, 60); // expire in a minute
   * lcb_store(instance, cookie, &cmd);
   * lcb_wait(instance, LCB_WAIT_NOCHECK);
   * @endcode
   *
   * ### Response
   * @code{.c}
   * lcb_install_callback(instance, LCB_CALLBACK_STORE, store_callback);
   * void store_callback(lcb_INSTANCE *instance, int cbtype, const lcb_RESPBASE *rb)
   * {
   *     uint64_t cas;
   *     const lcb_RESPSTORE resp = (const lcb_RESPSTORE*)rb;
   *     lcb_STATUS rc = lcb_respstore_status(resp);
   *     if (rc == LCB_SUCCESS) {
   *         lcb_respstore_cas(resp, &cas)
   *         printf("Store success: CAS=%llx\n", cas);
   *     } else {
   *         printf("Store failed: %s\n", lcb_strerror_short(rc);
   *     }
   * }
   * @endcode
   *
   * Operation-specific error codes include:
   * @cb_err ::LCB_ERR_DOCUMENT_NOT_FOUND if ::LCB_REPLACE was used and the key does not exist
   * @cb_err ::LCB_ERR_DOCUMENT_EXISTS if ::LCB_INSERT was used and the key already exists
   * @cb_err ::LCB_ERR_DOCUMENT_EXISTS if the CAS was specified (for an operation other
   *          than ::LCB_INSERT) and the item exists on the server with a different
   *          CAS
   * @cb_err ::LCB_ERR_DOCUMENT_EXISTS if the item was locked and the CAS supplied did
   * not match the locked item's CAS (or if no CAS was supplied)
   * @cb_err ::LCB_ERR_NOT_STORED if an ::LCB_APPEND or ::LCB_PREPEND operation was
   * performed and the item did not exist on the server.
   * @cb_err ::LCB_ERR_VALUE_TOO_LARGE if the size of the value exceeds the cluster per-item
   *         value limit (currently 20MB).
   *
   *
   * For a 6.5 or later cluster, you should use the lcb_cmdstore_durability to make the lcb_store
   * not return until the requested durabilty is met.  If the cluster is an older version, you can
   * use lcb_cmdstore_durability_observe.
   */
  
  typedef struct lcb_RESPSTORE_ lcb_RESPSTORE;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respstore_status(const lcb_RESPSTORE *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respstore_error_context(const lcb_RESPSTORE *resp,
                                                          const lcb_KEY_VALUE_ERROR_CONTEXT **ctx);
  LIBCOUCHBASE_API lcb_STATUS lcb_respstore_cookie(const lcb_RESPSTORE *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respstore_cas(const lcb_RESPSTORE *resp, uint64_t *cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_respstore_key(const lcb_RESPSTORE *resp, const char **key, size_t *key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respstore_operation(const lcb_RESPSTORE *resp, lcb_STORE_OPERATION *operation);
  LIBCOUCHBASE_API lcb_STATUS lcb_respstore_mutation_token(const lcb_RESPSTORE *resp, lcb_MUTATION_TOKEN *token);
  
  LIBCOUCHBASE_API int lcb_respstore_observe_attached(const lcb_RESPSTORE *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respstore_observe_stored(const lcb_RESPSTORE *resp, int *store_ok);
  LIBCOUCHBASE_API lcb_STATUS lcb_respstore_observe_master_exists(const lcb_RESPSTORE *resp, int *master_exists);
  LIBCOUCHBASE_API lcb_STATUS lcb_respstore_observe_master_persisted(const lcb_RESPSTORE *resp, int *master_persisted);
  LIBCOUCHBASE_API lcb_STATUS lcb_respstore_observe_num_responses(const lcb_RESPSTORE *resp, uint16_t *num_responses);
  LIBCOUCHBASE_API lcb_STATUS lcb_respstore_observe_num_persisted(const lcb_RESPSTORE *resp, uint16_t *num_persisted);
  LIBCOUCHBASE_API lcb_STATUS lcb_respstore_observe_num_replicated(const lcb_RESPSTORE *resp, uint16_t *num_replicated);
  
  typedef struct lcb_CMDSTORE_ lcb_CMDSTORE;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_create(lcb_CMDSTORE **cmd, lcb_STORE_OPERATION operation);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_destroy(lcb_CMDSTORE *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_parent_span(lcb_CMDSTORE *cmd, lcbtrace_SPAN *span);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_collection(lcb_CMDSTORE *cmd, const char *scope, size_t scope_len,
                                                      const char *collection, size_t collection_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_key(lcb_CMDSTORE *cmd, const char *key, size_t key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_value(lcb_CMDSTORE *cmd, const char *value, size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_value_iov(lcb_CMDSTORE *cmd, const lcb_IOV *value, size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_expiry(lcb_CMDSTORE *cmd, uint32_t expiration);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_cas(lcb_CMDSTORE *cmd, uint64_t cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_flags(lcb_CMDSTORE *cmd, uint32_t flags);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_datatype(lcb_CMDSTORE *cmd, uint8_t datatype);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_durability(lcb_CMDSTORE *cmd, lcb_DURABILITY_LEVEL level);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_durability_observe(lcb_CMDSTORE *cmd, int persist_to, int replicate_to);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdstore_timeout(lcb_CMDSTORE *cmd, uint32_t timeout);
  LIBCOUCHBASE_API lcb_STATUS lcb_store(lcb_INSTANCE *instance, void *cookie, const lcb_CMDSTORE *cmd);
  /**@}*/
  
  /**
   * @ingroup lcb-kv-api
   * @defgroup lcb-open Open Bucket
   * @brief Open bucket in cluster
   * @addtogroup lcb-open
   * @{
   */
  
  typedef void (*lcb_open_callback)(lcb_INSTANCE *instance, lcb_STATUS err);
  /** @brief Callback to be called when bucket is opened
   *
   * @param instance
   * @param callback pointer to callback
   * @return LCB_SUCCESS on success, other code on failure.
   */
  LIBCOUCHBASE_API lcb_open_callback lcb_set_open_callback(lcb_INSTANCE *instance, lcb_open_callback callback);
  
  /**
   * Opens bucket.
   *
   * @param instance
   * @param bucket name of bucket to open
   * @param bucket_len length of bucket string
   * @return LCB_SUCCESS on success, other code on failure
   */
  
  LIBCOUCHBASE_API lcb_STATUS lcb_open(lcb_INSTANCE *instance, const char *bucket, size_t bucket_len);
  /**@}*/
  
  /**
   * @ingroup lcb-kv-api
   * @defgroup lcb-remove Remove
   * @brief Remove documents
   *
   * @addtogroup lcb-remove
   * @{
   */
  
  /**@committed
   * @brief Spool a removal of an item
   * @param instance the handle
   * @param cookie pointer to associate with the request
   * @param cmd the command
   * @return LCB_SUCCESS on success, other code on failure
   *
   * ### Request
   * @code{.c}
   * lcb_CMDREMOVE* cmd;
   * lcb_cmdremove_create(&cmd);
   * lcb_cmdremove_key(cmd, "deleteme", strlen("deleteme"));
   * lcb_remove(instance, cookie, &cmd);
   * @endcode
   *
   * ### Response
   * @code{.c}
   * lcb_install_callback(instance, LCB_CALLBACK_REMOVE, rm_callback);
   * void rm_callback(lcb_INSTANCE *instance, int cbtype, const lcb_RESPBASE *rb)
   * {
   *     const lcb_RESPREMOVE* resp = (const lcb_RESPREMOVE*)rb;
   *     char* key;
   *     size_t key_len;
   *     lcb_STATUS rc = lcb_respremove_status(resp);
   *     lcb_respremove_key(resp, &key, &key_len);
   *     printf("Key: %.*s...", key_len, key);
   *     if (rc != LCB_SUCCESS) {
   *         printf("Failed to remove item!: %s\n", lcb_strerror_short(rc));
   *     } else {
   *         printf("Removed item!\n");
   *     }
   * }
   * @endcode
   *
   * The following operation-specific error codes are returned in the callback
   * @cb_err ::LCB_ERR_DOCUMENT_NOT_FOUND if the key does not exist
   * @cb_err ::LCB_ERR_DOCUMENT_EXISTS if the CAS was specified and it does not match the
   *         CAS on the server
   * @cb_err ::LCB_ERR_DOCUMENT_EXISTS if the item was locked and no CAS (or an incorrect
   *         CAS) was specified.
   *
   */
  
  typedef struct lcb_RESPREMOVE_ lcb_RESPREMOVE;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respremove_status(const lcb_RESPREMOVE *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respremove_error_context(const lcb_RESPREMOVE *resp,
                                                           const lcb_KEY_VALUE_ERROR_CONTEXT **ctx);
  LIBCOUCHBASE_API lcb_STATUS lcb_respremove_cookie(const lcb_RESPREMOVE *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respremove_cas(const lcb_RESPREMOVE *resp, uint64_t *cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_respremove_key(const lcb_RESPREMOVE *resp, const char **key, size_t *key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respremove_mutation_token(const lcb_RESPREMOVE *resp, lcb_MUTATION_TOKEN *token);
  
  typedef struct lcb_CMDREMOVE_ lcb_CMDREMOVE;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdremove_create(lcb_CMDREMOVE **cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdremove_destroy(lcb_CMDREMOVE *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdremove_parent_span(lcb_CMDREMOVE *cmd, lcbtrace_SPAN *span);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdremove_collection(lcb_CMDREMOVE *cmd, const char *scope, size_t scope_len,
                                                       const char *collection, size_t collection_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdremove_key(lcb_CMDREMOVE *cmd, const char *key, size_t key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdremove_cas(lcb_CMDREMOVE *cmd, uint64_t cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdremove_durability(lcb_CMDREMOVE *cmd, lcb_DURABILITY_LEVEL level);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdremove_timeout(lcb_CMDREMOVE *cmd, uint32_t timeout);
  LIBCOUCHBASE_API lcb_STATUS lcb_remove(lcb_INSTANCE *instance, void *cookie, const lcb_CMDREMOVE *cmd);
  
  /**@}*/
  
  /**
   * @ingroup lcb-kv-api
   * @defgroup lcb-counter Counters
   * @brief Manipulate the numeric content of a document
   * @details Counter operations treat the document being accessed as a numeric
   * value (the document should contain a parseable integer as its content). This
   * value may then be incremented or decremented.
   *
   * @addtogroup lcb-counter
   * @{
   */
  
  /**@committed
   * @brief Schedule single counter operation
   * @param instance the instance
   * @param cookie the pointer to associate with the request
   * @param cmd the command to use
   * @return LCB_SUCCESS on success, other error on failure
   *
   * @par Request
   * @code{.c}
   * lcb_CMDCOUNTER* cmd;
   * lcb_cmdcounter_create(&cmd);
   * lcb_cmdcounter_key(cmd, "counter", strlen("counter"));
   * lcb_cmdcounter_delta(cmd, 1); // Increment by one
   * lcb_cmdcounter_value(cmd, 42); // Default value is 42 if it does not exist
   * lcb_cmdcounter_expiry(cmd, 300); // Expire in 5 minutes
   * lcb_counter(instance, NULL, cmd);
   * lcb_wait(instance, LCB_WAIT_NOCHECK);
   * @endcode
   *
   * @par Response
   * @code{.c}
   * lcb_install_callback(instance, LCB_CALLBACKTYPE_COUNTER, counter_cb);
   * void counter_cb(lcb_INSTANCE *instance, int cbtype, const lcb_RESPBASE *rb)
   * {
   *     const lcb_RESPCOUNTER *resp = (const lcb_RESPCOUNTER *)rb;
   *     lcb_STATUS = lcb_respcounter_status(resp);
   *     if (rc == LCB_SUCCESS) {
   *         char* key;
   *         size_t key_len;
   *         uint64_t value;
   *         lcb_respcounter_value(resp, &value);
   *         lcb_respcounter_key(resp, &key, &key_len);
   *         printf("Incremented counter for %.*s. Current value %llu\n",
   *                key_len, key, value);
   *     }
   * }
   * @endcode
   *
   * @par Callback Errors
   * In addition to generic errors, the following errors may be returned in the
   * callback (via lcb_respcounter_status):
   *
   * @cb_err ::LCB_ERR_DOCUMENT_NOT_FOUND if the counter doesn't exist
   * @cb_err ::LCB_ERR_INVALID_DELTA if the existing document's content could not
   * be parsed as a number by the server.
   */
  
  typedef struct lcb_RESPCOUNTER_ lcb_RESPCOUNTER;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respcounter_status(const lcb_RESPCOUNTER *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respcounter_error_context(const lcb_RESPCOUNTER *resp,
                                                            const lcb_KEY_VALUE_ERROR_CONTEXT **ctx);
  LIBCOUCHBASE_API lcb_STATUS lcb_respcounter_cookie(const lcb_RESPCOUNTER *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respcounter_cas(const lcb_RESPCOUNTER *resp, uint64_t *cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_respcounter_key(const lcb_RESPCOUNTER *resp, const char **key, size_t *key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respcounter_mutation_token(const lcb_RESPCOUNTER *resp, lcb_MUTATION_TOKEN *token);
  LIBCOUCHBASE_API lcb_STATUS lcb_respcounter_value(const lcb_RESPCOUNTER *resp, uint64_t *value);
  
  typedef struct lcb_CMDCOUNTER_ lcb_CMDCOUNTER;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_create(lcb_CMDCOUNTER **cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_destroy(lcb_CMDCOUNTER *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_parent_span(lcb_CMDCOUNTER *cmd, lcbtrace_SPAN *span);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_collection(lcb_CMDCOUNTER *cmd, const char *scope, size_t scope_len,
                                                        const char *collection, size_t collection_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_key(lcb_CMDCOUNTER *cmd, const char *key, size_t key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_expiry(lcb_CMDCOUNTER *cmd, uint32_t expiration);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_delta(lcb_CMDCOUNTER *cmd, int64_t number);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_initial(lcb_CMDCOUNTER *cmd, uint64_t number);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_durability(lcb_CMDCOUNTER *cmd, lcb_DURABILITY_LEVEL level);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_cas(lcb_CMDCOUNTER *cmd, uint64_t cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdcounter_timeout(lcb_CMDCOUNTER *cmd, uint32_t timeout);
  LIBCOUCHBASE_API lcb_STATUS lcb_counter(lcb_INSTANCE *instance, void *cookie, const lcb_CMDCOUNTER *cmd);
  
  /**@} (Group: Counter) */
  
  /* @ingroup lcb-kv-api
   * @defgroup lcb-lock Lock/Unlock
   * @details Documents may be locked and unlocked on the server. While a document
   * is locked, any attempt to modify it (or lock it again) will fail.
   *
   * @note Locks are not persistent across nodes (if a node fails over, the lock
   * is not transferred to a replica).
   * @note The recommended way to manage access and concurrency control for
   * documents in Couchbase is through the CAS, which can also be considered
   * a form of opportunistic locking.
   *
   * @par Locking an item
   * There is no exclusive function to lock an item. Locking an item is done
   * using @ref lcb_get(), by setting the lcb_cmdget_locktime.
   *
   * @addtogroup lcb-lock
   * @{
   */
  
  /**
   * @committed
   * @brief
   * Unlock a previously locked item using lcb_cmdunlock
   *
   * @param instance the instance
   * @param cookie the context pointer to associate with the command
   * @param cmd the command containing the information about the locked key
   * @return LCB_SUCCESS if successful, an error code otherwise
   * Note that you must specify the cas of the item to unlock it, and the only
   * way to get that cas is in the callback of the lock call.  Outside that, the
   * server will respond with a dummy cas if, for instance, you do a lcb_get.
   *
   * @see lcb_get()
   *
   * @par
   *
   * @code{.c}
   * void locked_callback(lcb_INSTANCE, lcb_CALLBACK_TYPE, const lcb_RESPBASE *rb) {
   *   const lcb_RESPGET* resp = (const lcb_RESPLOCK*)rb;
   *   lcb_CMDUNLOCK* cmd;
   *   char* key;
   *   size_t key_len;
   *   unit64_t cas;
   *   lcb_respget_cas(resp, &cas);
   *   lcb_respget_key(resp, &key, &key_len);
   *   lcb_cmdunlock_create(&cmd);
   *   lcb_cmdunlock_key(cmd, key, key_len);
   *   lcb_cmdunlock_cas(cmd, cas);
   *   lcb_unlock(instance, cookie, cmd);
   * }
   *
   * @endcode
   */
  
  typedef struct lcb_RESPUNLOCK_ lcb_RESPUNLOCK;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respunlock_status(const lcb_RESPUNLOCK *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respunlock_error_context(const lcb_RESPUNLOCK *resp,
                                                           const lcb_KEY_VALUE_ERROR_CONTEXT **ctx);
  LIBCOUCHBASE_API lcb_STATUS lcb_respunlock_cookie(const lcb_RESPUNLOCK *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respunlock_cas(const lcb_RESPUNLOCK *resp, uint64_t *cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_respunlock_key(const lcb_RESPUNLOCK *resp, const char **key, size_t *key_len);
  
  typedef struct lcb_CMDUNLOCK_ lcb_CMDUNLOCK;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdunlock_create(lcb_CMDUNLOCK **cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdunlock_destroy(lcb_CMDUNLOCK *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdunlock_parent_span(lcb_CMDUNLOCK *cmd, lcbtrace_SPAN *span);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdunlock_collection(lcb_CMDUNLOCK *cmd, const char *scope, size_t scope_len,
                                                       const char *collection, size_t collection_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdunlock_key(lcb_CMDUNLOCK *cmd, const char *key, size_t key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdunlock_cas(lcb_CMDUNLOCK *cmd, uint64_t cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdunlock_timeout(lcb_CMDUNLOCK *cmd, uint32_t timeout);
  LIBCOUCHBASE_API lcb_STATUS lcb_unlock(lcb_INSTANCE *instance, void *cookie, const lcb_CMDUNLOCK *cmd);
  
  /**@} (Group: Unlock) */
  
  /* @ingroup lcb-kv-api
   * @defgroup lcb-touch Touch/Expiry
   * @brief Modify or clear a document's expiration time
   * @details Couchbase allows documents to contain expiration times
   * (see lcb_CMDBASE::exptime). Most operations allow the expiry time to be
   * updated, however lcb_touch3() allows the exclusive update of the expiration
   * time without additional network overhead.
   *
   * @addtogroup lcb-touch
   * @{
   */
  
  /**@committed
   * @brief Spool a touch request
   * @param instance the handle
   * @param cookie the pointer to associate with the request
   * @param cmd the command
   * @return LCB_SUCCESS on success, other error code on failure
   *
   * @par Request
   * @code{.c}
   * lcb_CMDTOUCH* cmd;
   * lcb_cmdtouch_create(&cmd);
   * lcb_cmdtouch_key(cmd, "keep_me", strlen("keep_me"));
   * lcb_cmdtouch_expiry(cmd, 0); // Clear the expiration
   * lcb_touch(instance, cookie, cmd);
   * @endcode
   *
   * @par Response
   * @code{.c}
   * lcb_install_callback(instance, LCB_CALLBACK_TOUCH, touch_callback);
   * void touch_callback(lcb_INSTANCE *instance, int cbtype, const lcb_RESPBASE *rb)
   * {
   *     const lcb_RESPTOUCH* resp = (const lcb_RESPTOUCH*)rb;
   *     lcb_STATUS = lcb_resptouch_status(resp);
   *     if (rc == LCB_SUCCESS) {
   *         printf("Touch succeeded\n");
   *     }
   * }
   * @endcode
   */
  
  typedef struct lcb_RESPTOUCH_ lcb_RESPTOUCH;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_resptouch_status(const lcb_RESPTOUCH *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_resptouch_error_context(const lcb_RESPTOUCH *resp,
                                                          const lcb_KEY_VALUE_ERROR_CONTEXT **ctx);
  LIBCOUCHBASE_API lcb_STATUS lcb_resptouch_cookie(const lcb_RESPTOUCH *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_resptouch_cas(const lcb_RESPTOUCH *resp, uint64_t *cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_resptouch_key(const lcb_RESPTOUCH *resp, const char **key, size_t *key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_resptouch_mutation_token(const lcb_RESPTOUCH *resp, lcb_MUTATION_TOKEN *token);
  
  typedef struct lcb_CMDTOUCH_ lcb_CMDTOUCH;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdtouch_create(lcb_CMDTOUCH **cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdtouch_destroy(lcb_CMDTOUCH *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdtouch_parent_span(lcb_CMDTOUCH *cmd, lcbtrace_SPAN *span);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdtouch_collection(lcb_CMDTOUCH *cmd, const char *scope, size_t scope_len,
                                                      const char *collection, size_t collection_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdtouch_key(lcb_CMDTOUCH *cmd, const char *key, size_t key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdtouch_expiry(lcb_CMDTOUCH *cmd, uint32_t expiration);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdtouch_durability(lcb_CMDTOUCH *cmd, lcb_DURABILITY_LEVEL level);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdtouch_timeout(lcb_CMDTOUCH *cmd, uint32_t timeout);
  LIBCOUCHBASE_API lcb_STATUS lcb_touch(lcb_INSTANCE *instance, void *cookie, const lcb_CMDTOUCH *cmd);
  
  /**@} (Group: Touch) */
  /**@} (Group: KV API) */
  
  /**
   * @ingroup lcb-public-api
   * @defgroup lcb-ping PING
   * @brief Broadcast NOOP-like commands to each service in the cluster
   *
   * @addtogroup lcb-ping
   * @{
   */
  
  /**
   * Status of the service
   *
   * @committed
   */
  typedef enum {
      LCB_PING_STATUS_OK = 0,
      LCB_PING_STATUS_TIMEOUT,
      LCB_PING_STATUS_ERROR,
      LCB_PING_STATUS_INVALID, /* bad index or argument */
      LCB_PING_STATUS__MAX
  } lcb_PING_STATUS;
  
  /**
   * Type of the service. This enumeration is used in PING responses.
   *
   * @committed
   */
  typedef enum {
      LCB_PING_SERVICE_KV = 0,
      LCB_PING_SERVICE_VIEWS,
      LCB_PING_SERVICE_QUERY,
      LCB_PING_SERVICE_SEARCH,
      LCB_PING_SERVICE_ANALYTICS,
      LCB_PING_SERVICE__MAX
  } lcb_PING_SERVICE;
  
  typedef struct lcb_RESPPING_ lcb_RESPPING;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respping_status(const lcb_RESPPING *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respping_cookie(const lcb_RESPPING *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respping_value(const lcb_RESPPING *resp, const char **json, size_t *json_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respping_report_id(const lcb_RESPPING *resp, const char **report_id,
                                                     size_t *report_id_len);
  LIBCOUCHBASE_API size_t lcb_respping_result_size(const lcb_RESPPING *resp);
  LIBCOUCHBASE_API lcb_PING_STATUS lcb_respping_result_status(const lcb_RESPPING *resp, size_t index);
  LIBCOUCHBASE_API lcb_STATUS lcb_respping_result_id(const lcb_RESPPING *resp, size_t index, const char **endpoint_id,
                                                     size_t *endpoint_id_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respping_result_service(const lcb_RESPPING *resp, size_t index, lcb_PING_SERVICE *type);
  LIBCOUCHBASE_API lcb_STATUS lcb_respping_result_remote(const lcb_RESPPING *resp, size_t index, const char **address,
                                                         size_t *address_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respping_result_local(const lcb_RESPPING *resp, size_t index, const char **address,
                                                        size_t *address_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respping_result_latency(const lcb_RESPPING *resp, size_t index, uint64_t *latency);
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respping_result_namespace(const lcb_RESPPING *resp, size_t index, const char **name,
                                                            size_t *name_len);
  
  LCB_DEPRECATED2(LIBCOUCHBASE_API lcb_STATUS lcb_respping_result_scope(const lcb_RESPPING *resp, size_t index,
                                                                        const char **name, size_t *name_len),
                  "Use lcb_respping_result_namespace");
  
  typedef struct lcb_CMDPING_ lcb_CMDPING;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdping_create(lcb_CMDPING **cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdping_destroy(lcb_CMDPING *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdping_parent_span(lcb_CMDPING *cmd, lcbtrace_SPAN *span);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdping_report_id(lcb_CMDPING *cmd, const char *report_id, size_t report_id_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdping_all(lcb_CMDPING *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdping_kv(lcb_CMDPING *cmd, int enable);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdping_query(lcb_CMDPING *cmd, int enable);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdping_views(lcb_CMDPING *cmd, int enable);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdping_search(lcb_CMDPING *cmd, int enable);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdping_analytics(lcb_CMDPING *cmd, int enable);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdping_no_metrics(lcb_CMDPING *cmd, int enable);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdping_encode_json(lcb_CMDPING *cmd, int enable, int pretty, int with_details);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdping_timeout(lcb_CMDPING *cmd, uint32_t timeout);
  LIBCOUCHBASE_API lcb_STATUS lcb_ping(lcb_INSTANCE *instance, void *cookie, const lcb_CMDPING *cmd);
  
  typedef struct lcb_RESPDIAG_ lcb_RESPDIAG;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respdiag_status(const lcb_RESPDIAG *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respdiag_cookie(const lcb_RESPDIAG *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respdiag_value(const lcb_RESPDIAG *resp, const char **json, size_t *json_len);
  
  typedef struct lcb_CMDDIAG_ lcb_CMDDIAG;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmddiag_create(lcb_CMDDIAG **cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmddiag_destroy(lcb_CMDDIAG *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmddiag_report_id(lcb_CMDDIAG *cmd, const char *report_id, size_t report_id_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmddiag_prettify(lcb_CMDDIAG *cmd, int enable);
  /**
   * @brief Returns diagnostics report about network connections.
   *
   * @committed
   *
   * @par Request
   * @code{.c}
   * lcb_CMDDIAG cmd = { 0 };
   * lcb_diag(instance, fp, &cmd);
   * lcb_wait(instance, LCB_WAIT_DEFAULT);
   * @endcode
   *
   * @par Response
   * @code{.c}
   * lcb_install_callback(instance, LCB_CALLBACK_DIAG, diag_callback);
   * void diag_callback(lcb_INSTANCE, int, const lcb_RESPBASE *rb)
   * {
   *     const lcb_RESPDIAG *resp = (const lcb_RESPDIAG *)rb;
   *     char* json;
   *     size_t json_len;
   *     lcb_STATUS rc = lcb_respdiag_status(resp);
   *     if (rc != LCB_SUCCESS) {
   *         fprintf(stderr, "failed: %s\n", lcb_strerror_short(rc));
   *     } else {
             lcb_respdiag_value(resp, &json, &json_len);
   *         if (json) {
   *             fprintf(stderr, "\n%.*s", json_len, json);
   *         }
   *     }
   * }
   * @endcode
   *
   * @param instance the library handle
   * @param cookie the cookie passed in the callback
   * @param cmd command structure.
   * @return status code for scheduling.
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_diag(lcb_INSTANCE *instance, void *cookie, const lcb_CMDDIAG *cmd);
  
  /**@} (Group: PING) */
  
  /* @ingroup lcb-public-api
   * @defgroup lcb-http HTTP Client
   * @brief Access Couchbase HTTP APIs
   * @details The low-level HTTP client may be used to access various HTTP-based
   * Couchbase APIs.
   *
   * Note that existing higher level APIs can be used for N1QL queries (see
   * @ref lcb-n1ql-api) and MapReduce view queries (see @ref lcb-view-api)
   *
   * @addtogroup lcb-http
   * @{
   */
  
  /**
   * @brief The type of HTTP request to execute
   */
  typedef enum {
      /**
       * Execute a request against the bucket. The handle must be of
       * @ref LCB_TYPE_BUCKET and must be connected.
       */
      LCB_HTTP_TYPE_VIEW = 0,
  
      /**
       * Execute a management API request. The credentials used will match
       * those passed during the instance creation time. Thus is the instance
       * type is @ref LCB_TYPE_BUCKET then only bucket-level credentials will
       * be used.
       */
      LCB_HTTP_TYPE_MANAGEMENT = 1,
  
      /**
       * Execute an arbitrary request against a host and port
       */
      LCB_HTTP_TYPE_RAW = 2,
  
      /** Execute an N1QL Query */
      LCB_HTTP_TYPE_QUERY = 3,
  
      /** Search a fulltext index */
      LCB_HTTP_TYPE_SEARCH = 4,
  
      /** Execute an Analytics Query */
      LCB_HTTP_TYPE_ANALYTICS = 5,
  
      /**
       * Special pseudo-type, for ping endpoints in various services.
       * Behaves like RAW (the lcb_ping3() function will setup custom path),
       * but supports Keep-Alive
       */
      LCB_HTTP_TYPE_PING = 6,
  
      LCB_HTTP_TYPE_MAX
  } lcb_HTTP_TYPE;
  
  /**
   * @brief HTTP Request method enumeration
   * These just enumerate the various types of HTTP request methods supported.
   * Refer to the specific cluster or view API to see which method is appropriate
   * for your request
   */
  typedef enum {
      LCB_HTTP_METHOD_GET = 0,
      LCB_HTTP_METHOD_POST = 1,
      LCB_HTTP_METHOD_PUT = 2,
      LCB_HTTP_METHOD_DELETE = 3,
      LCB_HTTP_METHOD_MAX = 4
  } lcb_HTTP_METHOD;
  
  /**
   * @committed
   * Issue an HTTP API request.
   * @param instance the library handle
   * @param cookie cookie to be associated with the request
   * @param cmd the command
   * @return LCB_SUCCESS if the request was scheduled successfully.
   *
   *
   * @par Simple Response
   * @code{.c}
   * void http_callback(lcb_INSTANCE, int, const lcb_RESPBASE *rb)
   * {
   *     const lcb_RESPHTTP *resp = (const lcb_RESPHTTP *)rb;
   *     lcb_STATUS rc = lcb_resphttp_status(resp);
   *     uint16_t http_status;
   *     char* body;
   *     size_t body_len;
   *     const char* const* headers;
   *     lcb_resphttp_http_status(resp, &http_status);
   *     lcb_resphttp_body(resp, &body, &body_len);
   *     if (rc != LCB_SUCCESS) {
   *         printf("I/O Error for HTTP: %s\n", lcb_strerror_short(rc));
   *         return;
   *     }
   *     printf("Got HTTP Status: %d\n", http_status);
   *     printf("Got paylod: %.*s\n", body_len, body);
   *     lcb_resphttp_headers(resp, &headers);
   *     if (headers) {
   *         for(const char* const* cur = headers; *cur; cur+=2) {
   *             printf("%s: %s\n", cur[0], cur[1]);
   *         }
   *     }
   * }
   * @endcode
   *
   * @par Streaming Response
   * If the @ref LCB_CMDHTTP_F_STREAM flag is set in lcb_CMDHTTP::cmdflags then the
   * response callback is invoked multiple times as data arrives off the socket.
   * @code{.c}
   * void http_strm_callback(lcb_INSTANCE, int, const lcb_RESPBASE *rb)
   * {
   *     const lcb_RESPHTTP *resp = (const lcb_RESPHTTP *)resp;
   *     char* body;
   *     size_t body_len;
   *     const char* const* headers;
   *     if (lcb_resphttp_is_final(resp)) {
   *         if (lcb_resphttp_status(resp) != LCB_SUCCESS) {
   *             // ....
   *         }
   *         lcb_resphttp_headers(resp, &headers);
   *         if (headers) {
   *         // ...
   *         }
   *     } else {
             lcb_resphttp_body(resp, &body, &body_len);
   *         handle_body(body, body_len);
   *     }
   * }
   * @endcode
   *
   * @par Connection Reuse
   * The library will attempt to reuse connections for frequently contacted hosts.
   * By default the library will keep one idle connection to each host for a maximum
   * of 10 seconds. The number of open idle HTTP connections can be controlled with
   * @ref LCB_CNTL_HTTP_POOLSIZE.
   *
   */
  
  typedef struct lcb_RESPHTTP_ lcb_RESPHTTP;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_resphttp_status(const lcb_RESPHTTP *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_resphttp_cookie(const lcb_RESPHTTP *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_resphttp_http_status(const lcb_RESPHTTP *resp, uint16_t *status);
  LIBCOUCHBASE_API lcb_STATUS lcb_resphttp_path(const lcb_RESPHTTP *resp, const char **path, size_t *path_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_resphttp_body(const lcb_RESPHTTP *resp, const char **body, size_t *body_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_resphttp_handle(const lcb_RESPHTTP *resp, lcb_HTTP_HANDLE **handle);
  LIBCOUCHBASE_API lcb_STATUS lcb_resphttp_error_context(const lcb_RESPHTTP *resp, const lcb_HTTP_ERROR_CONTEXT **ctx);
  
  LIBCOUCHBASE_API int lcb_resphttp_is_final(const lcb_RESPHTTP *resp);
  /**
   * List of key-value headers. This field itself may be `NULL`. The list
   * is terminated by a `NULL` pointer to indicate no more headers.
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_resphttp_headers(const lcb_RESPHTTP *resp, const char *const **headers);
  
  typedef struct lcb_CMDHTTP_ lcb_CMDHTTP;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_create(lcb_CMDHTTP **cmd, lcb_HTTP_TYPE type);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_destroy(lcb_CMDHTTP *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_parent_span(lcb_CMDHTTP *cmd, lcbtrace_SPAN *span);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_method(lcb_CMDHTTP *cmd, lcb_HTTP_METHOD method);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_path(lcb_CMDHTTP *cmd, const char *path, size_t path_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_content_type(lcb_CMDHTTP *cmd, const char *content_type,
                                                       size_t content_type_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_body(lcb_CMDHTTP *cmd, const char *body, size_t body_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_handle(lcb_CMDHTTP *cmd, lcb_HTTP_HANDLE **handle);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_username(lcb_CMDHTTP *cmd, const char *username, size_t username_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_password(lcb_CMDHTTP *cmd, const char *password, size_t password_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_host(lcb_CMDHTTP *cmd, const char *host, size_t host_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_streaming(lcb_CMDHTTP *cmd, int streaming);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_skip_auth_header(lcb_CMDHTTP *cmd, int skip_auth);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdhttp_timeout(lcb_CMDHTTP *cmd, uint32_t timeout);
  LIBCOUCHBASE_API lcb_STATUS lcb_http(lcb_INSTANCE *instance, void *cookie, const lcb_CMDHTTP *cmd);
  
  /**
   * @brief Cancel ongoing HTTP request
   *
   * This API will stop the current request. Any pending callbacks will not be
   * invoked any any pending data will not be delivered. Useful for a long running
   * request which is no longer needed
   *
   * @param instance The handle to lcb
   * @param handle The request handle
   *
   * @committed
   *
   * @par Example
   * @code{.c}
   * lcb_CMDHTTP* cmd;
   * lcb_HTTP_HANDLE* handle;
   * lcb_cmdhttp_create(&cmd);
   * // flesh out the actual request...
   *
   * lcb_http(instance, cookie, cmd);
   * lcb_cmdhttp_handle(cmd, &handle);
   * do_stuff();
   * lcb_cancel_http_request(instance, handle);
   * @endcode
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_http_cancel(lcb_INSTANCE *instance, lcb_HTTP_HANDLE *handle);
  
  /**@} (Group: HTTP) */
  
  /**
   * @ingroup lcb-public-api
   * @defgroup lcb-cookie User Cookies
   * @brief Associate user-defined data with operations
   * @details
   *
   * User-defined pointers may be passed to all operations in the form of a
   * `cookie` parameter. This cookie parameter allows any kind of application
   * context to be accessible via the callback (in lcb_RESPBASE::cookie).
   *
   * The library will not inspect or manage the address or contents of the
   * cookie; it may live on the stack (especially if using the library
   * synchronously), on the heap, or may be NULL altogether.
   *
   * In addition to per-operation cookies, the library allows the instance itself
   * (i.e. the `lcb_INSTANCE` object) to contain its own cookie. This is helpful when
   * there is a wrapper object which needs to be accessed from within the callback
   *
   * @addtogroup lcb-cookie
   * @{
   */
  
  /**
   * Associate a cookie with an instance of lcb. The _cookie_ is a user defined
   * pointer which will remain attached to the specified `lcb_INSTANCE` for its duration.
   * This is the way to associate user data with the `lcb_INSTANCE`.
   *
   * @param instance the instance to associate the cookie to
   * @param cookie the cookie to associate with this instance.
   *
   * @attention
   * There is no destructor for the specified `cookie` stored with the instance;
   * thus you must ensure to manually free resources to the pointer (if it was
   * dynamically allocated) when it is no longer required.
   * @committed
   *
   * @code{.c}
   * typedef struct {
   *   const char *status;
   *   // ....
   * } instance_info;
   *
   * static void bootstrap_callback(lcb_INSTANCE *instance, lcb_STATUS err) {
   *   instance_info *info = (instance_info *)lcb_get_cookie(instance);
   *   if (err == LCB_SUCCESS) {
   *     info->status = "Connected";
   *   } else {
   *     info->status = "Error";
   *   }
   * }
   *
   * static void do_create(void) {
   *   instance_info *info = calloc(1, sizeof(*info));
   *   // info->status is currently NULL
   *   // .. create the instance here
   *   lcb_set_cookie(instance, info);
   *   lcb_set_bootstrap_callback(instance, bootstrap_callback);
   *   lcb_connect(instance);
   *   lcb_wait(instance, LCB_WAIT_DEFAULT);
   *   printf("Status of instance is %s\n", info->status);
   * }
   * @endcode
   */
  LIBCOUCHBASE_API
  void lcb_set_cookie(lcb_INSTANCE *instance, const void *cookie);
  
  /**
   * Retrieve the cookie associated with this instance
   * @param instance the instance of lcb
   * @return The cookie associated with this instance or NULL
   * @see lcb_set_cookie()
   * @committed
   */
  LIBCOUCHBASE_API
  const void *lcb_get_cookie(lcb_INSTANCE *instance);
  /**@} (Group: Cookies) */
  
  /**
   * @ingroup lcb-public-api
   * @defgroup lcb-wait Waiting
   * @brief Functions for synchronous I/O execution
   * @details The lcb_wait() family of functions allow to control when the
   * library sends the operations to the cluster and waits for their execution.
   *
   * It is also possible to use non-blocking I/O with the library
   *
   * @addtogroup lcb-wait
   * @{
   */
  
  /**
   * @volatile
   * This function will cause a single "tick" in the underlying event loop,
   * causing operations whose I/O can be executed immediately to be sent to
   * the server.
   *
   * Like lcb_wait(), callbacks for operations may be delivered here, however
   * some operations may be left incomplete if their I/O could not be processed
   * immediately. This function is intended as an optimization for large batches
   * of operations - so that some I/O can be completed during the batching process
   * itself, and only the remainder of those operations (which would have blocked)
   * will be completed with lcb_wait() (which should be invoked after the batch).
   *
   * This function is mainly useful if there is a significant delay in time
   * between each scheduling function, in which I/O may be completed during these
   * gaps (thereby emptying the socket's kernel write buffer, and allowing for
   * new operations to be added after the interval). Calling this function for
   * batches where all data is available up-front may actually make things slower.
   *
   * @warning
   * You must call lcb_wait() at least one after any batch of operations to ensure
   * they have been completed. This function is provided as an optimization only.
   *
   * @return LCB_ERR_SDK_FEATURE_UNAVAILABLE if the event loop does not support
   * the "tick" mode.
   */
  LIBCOUCHBASE_API
  lcb_STATUS lcb_tick_nowait(lcb_INSTANCE *instance);
  
  /**@brief Flags for lcb_wait()*/
  typedef enum {
      /**Behave like the old lcb_wait()*/
      LCB_WAIT_DEFAULT = 0x00,
  
      /**Do not check pending operations before running the event loop. By default
       * lcb_wait() will traverse the server list to check if any operations are
       * pending, and if nothing is pending the function will return without
       * running the event loop. This is usually not necessary for applications
       * which already _only_ call lcb_wait() when they know they have scheduled
       * at least one command.
       */
      LCB_WAIT_NOCHECK = 0x01
  } lcb_WAITFLAGS;
  
  /**
   * @committed
   * @brief Wait for completion of scheduled operations.
   * @param instance the instance
   * @param flags flags to modify the behavior of lcb_wait(). Pass 0 to obtain
   * behavior identical to lcb_wait().
   */
  LIBCOUCHBASE_API
  lcb_STATUS lcb_wait(lcb_INSTANCE *instance, lcb_WAITFLAGS flags);
  
  /**
   * @brief Forcefully break from the event loop.
   *
   * You may call this function from within any callback to signal to the library
   * that it return control to the function calling lcb_wait() as soon as possible.
   * Note that if there are pending functions which have not been processed, you
   * are responsible for calling lcb_wait() a second time.
   *
   * @param instance the instance to run the event loop for.
   * @committed
   */
  LIBCOUCHBASE_API
  void lcb_breakout(lcb_INSTANCE *instance);
  
  /**
   * @brief Check if instance is blocked in the event loop
   * @param instance the instance to run the event loop for.
   * @return non-zero if nobody is waiting for IO interaction
   * @uncommitted
   */
  LIBCOUCHBASE_API
  int lcb_is_waiting(lcb_INSTANCE *instance);
  /**@} (Group: Wait) */
  
  /**
   * @ingroup lcb-public-api
   * @defgroup lcb-sched Advanced Scheduling
   * @brief Additional functions for scheduling operations
   *
   * @details
   *
   * An application may spool multiple operations into the library with the
   * option of unspooling previously-spooled operations in case one of
   * the operations cannot be spooled. These semantics exist primarily to
   * support "all-or-nothing" scheduling found in the V2 API as well as in
   * some other wrapping SDKs.
   *
   * From version 2.4.0 to version 2.5.5, use of the explicit scheduling
   * API was mandatory to schedule operations. This API is optional since 2.5.6.
   *
   * The following operation APIs are low level entry points which create a
   * single operation. To use these operation APIs you should call the
   * lcb_sched_enter() which creates a virtual scope in which to create operations.
   *
   * For each of these operation APIs, the actual API call will insert the
   * created packet into a "Scheduling Queue" (this is done through
   * mcreq_sched_add() which is in mcreq.h). You may add as many items to this
   * scheduling queue as you would like.
   *
   * Note that an operation is only added to the queue if it was able to be
   * scheduled properly. If a scheduling failure occurred (for example, if a
   * configuration is missing, the command had invalid input, or memory allocation
   * failed) then the command will not be placed into the queue.
   *
   * Once all operations have been scheduled you can call
   * lcb_sched_leave() which will place all commands scheduled into the I/O
   * queue.
   *
   * If you wish to _discard_ all scheduled operations (for example, if one of
   * them errored, and your application cannot handle partial scheduling failures)
   * then you may call lcb_sched_fail() which will release all the resources
   * of the packets placed into the temporary queue.
   *
   * @par Behavior from version 2.5.6
   *
   * Starting from version 2.5.6, use of this API is optional. Scheduling functions
   * will now check if an empty call to lcb_sched_enter() is present. If no call
   * to lcb_sched_enter() is found then the library will implicitly call
   * lcb_sched_leave().
   *
   * @addtogroup lcb-sched
   * @{
   */
  
  /**
   * @brief Enter a scheduling context.
   *
   * @uncommitted
   *
   * A scheduling context is an ephemeral list of
   * commands issued to various servers. Operations (like lcb_get3(), lcb_store3())
   * place packets into the current context.
   *
   * The context mechanism allows you to efficiently pipeline and schedule multiple
   * operations of different types and quantities. The network is not touched
   * and nothing is scheduled until the context is exited.
   *
   * @param instance the instance
   *
   * @code{.c}
   * lcb_sched_enter(instance);
   * lcb_get(...);
   * lcb_store(...);
   * lcb_counter(...);
   * lcb_sched_leave(instance);
   * lcb_wait(instance, LCB_WAIT_NOCHECK);
   * @endcode
   */
  LIBCOUCHBASE_API
  void lcb_sched_enter(lcb_INSTANCE *instance);
  
  /**
   * @uncommitted
   *
   * @brief Leave the current scheduling context, scheduling the commands within the
   * context to be flushed to the network.
   *
   * @details This will initiate a network-level flush (depending on the I/O system)
   * to the network. For completion-based I/O systems this typically means
   * allocating a temporary write context to contain the buffer. If using a
   * completion-based I/O module (for example, Windows or libuv) then it is
   * recommended to limit the number of calls to one per loop iteration. If
   * limiting the number of calls to this function is not possible (for example,
   * if the legacy API is being used, or you wish to use implicit scheduling) then
   * the flushing may be decoupled from this function - see the documentation for
   * lcb_sched_flush().
   *
   * @param instance the instance
   */
  LIBCOUCHBASE_API
  void lcb_sched_leave(lcb_INSTANCE *instance);
  
  /**
   * @uncommitted
   * @brief Fail all commands in the current scheduling context.
   *
   * The commands placed within the current
   * scheduling context are released and are never flushed to the network.
   * @param instance
   *
   * @warning
   * This function only affects commands which have a direct correspondence
   * to memcached packets. Currently these are commands scheduled by:
   *
   * * lcb_get()
   * * lcb_getreplica()
   * * lcb_unlock()
   * * lcb_touch()
   * * lcb_store()
   * * lcb_counter()
   * * lcb_remove()
   *
   * Other commands are _compound_ commands and thus should be in their own
   * scheduling context.
   */
  LIBCOUCHBASE_API
  void lcb_sched_fail(lcb_INSTANCE *instance);
  
  /**
   * @committed
   * @brief Request commands to be flushed to the network
   *
   * By default, the library will implicitly request a flush to the network upon
   * every call to lcb_sched_leave().
   *
   * [ Note, this does not mean the items are flushed
   * and I/O is performed, but it means the relevant event loop watchers are
   * activated to perform the operations on the next iteration ]. If
   * @ref LCB_CNTL_SCHED_IMPLICIT_FLUSH
   * is disabled then this behavior is disabled and the
   * application must explicitly call lcb_sched_flush(). This may be considered
   * more performant in the cases where multiple discreet operations are scheduled
   * in an lcb_sched_enter()/lcb_sched_leave() pair. With implicit flush enabled,
   * each call to lcb_sched_leave() will possibly invoke system repeatedly.
   */
  LIBCOUCHBASE_API
  void lcb_sched_flush(lcb_INSTANCE *instance);
  
  /**@} (Group: Adanced Scheduling) */
  
  /* @ingroup lcb-public-api
   * @defgroup lcb-destroy Destroying
   * @brief Library destruction routines
   * @addtogroup lcb-destroy
   * @{
   */
  /**
   * Destroy (and release all allocated resources) an instance of lcb.
   * Using instance after calling destroy will most likely cause your
   * application to crash.
   *
   * Note that any pending operations will not have their callbacks invoked.
   *
   * @param instance the instance to destroy.
   * @committed
   */
  LIBCOUCHBASE_API
  void lcb_destroy(lcb_INSTANCE *instance);
  
  /**
   * @brief Callback received when instance is about to be destroyed
   * @param cookie cookie passed to lcb_destroy_async()
   */
  typedef void (*lcb_destroy_callback)(const void *cookie);
  
  /**
   * @brief Set the callback to be invoked when the instance is destroyed
   * asynchronously.
   * @return the previous callback.
   */
  LIBCOUCHBASE_API
  lcb_destroy_callback lcb_set_destroy_callback(lcb_INSTANCE *instance, lcb_destroy_callback);
  /**
   * @brief Asynchronously schedule the destruction of an instance.
   *
   * This function provides a safe way for asynchronous environments to destroy
   * the lcb_INSTANCE *handle without worrying about reentrancy issues.
   *
   * @param instance
   * @param arg a pointer passed to the callback.
   *
   * While the callback and cookie are optional, they are very much recommended
   * for testing scenarios where you wish to ensure that all resources allocated
   * by the instance have been closed. Specifically when the callback is invoked,
   * all timers (save for the one actually triggering the destruction) and sockets
   * will have been closed.
   *
   * As with lcb_destroy() you may call this function only once. You may not
   * call this function together with lcb_destroy as the two are mutually
   * exclusive.
   *
   * If for whatever reason this function is being called in a synchronous
   * flow, lcb_wait() must be invoked in order for the destruction to take effect
   *
   * @see lcb_set_destroy_callback
   *
   * @committed
   */
  LIBCOUCHBASE_API
  void lcb_destroy_async(lcb_INSTANCE *instance, const void *arg);
  /**@} (Group: Destroy) */
  
  /** @internal */
  #define LCB_DATATYPE_JSON 0x01
  
  /** @internal */
  typedef enum { LCB_VALUE_RAW = 0x00, LCB_VALUE_F_JSON = 0x01, LCB_VALUE_F_SNAPPYCOMP = 0x02 } lcb_VALUEFLAGS;
  
  /**
   * @ingroup lcb-public-api
   * @defgroup lcb-cntl Settings
   * @brief Get/Set Library Options
   *
   * @details
   *
   * The lcb_cntl() function and its various helpers are the means by which to
   * modify settings within the library
   *
   * @addtogroup lcb-cntl
   * @see <cntl.h>
   * @{
   */
  
  /**
   * This function exposes an ioctl/fcntl-like interface to read and write
   * various configuration properties to and from an lcb_INSTANCE *handle.
   *
   * @param instance The instance to modify
   *
   * @param mode One of LCB_CNTL_GET (to retrieve a setting) or LCB_CNTL_SET
   *      (to modify a setting). Note that not all configuration properties
   *      support SET.
   *
   * @param cmd The specific command/property to modify. This is one of the
   *      LCB_CNTL_* constants defined in this file. Note that it is safe
   *      (and even recommanded) to use the raw numeric value (i.e.
   *      to be backwards and forwards compatible with libcouchbase
   *      versions), as they are not subject to change.
   *
   *      Using the actual value may be useful in ensuring your application
   *      will still compile with an older libcouchbase version (though
   *      you may get a runtime error (see return) if the command is not
   *      supported
   *
   * @param arg The argument passed to the configuration handler.
   *      The actual type of this pointer is dependent on the
   *      command in question.  Typically for GET operations, the
   *      value of 'arg' is set to the current configuration value;
   *      and for SET operations, the current configuration is
   *      updated with the contents of *arg.
   *
   * @return ::LCB_ERR_UNSUPPORTED_OPERATION if the code is unrecognized
   * @return ::LCB_ERR_INVALID_ARGUMENT if there was a problem with the argument
   *         (typically for LCB_CNTL_SET) other error codes depending on the command.
   *
   * The following error codes are returned if the ::LCB_CNTL_DETAILED_ERRCODES
   * are enabled.
   *
   * @return ::LCB_ECTL_UNKNOWN if the code is unrecognized
   * @return ::LCB_ECTL_UNSUPPMODE An invalid _mode_ was passed
   * @return ::LCB_ERR_CONTROL_INVALID_ARGUMENT if the value was invalid
   *
   * @committed
   *
   * @see lcb_cntl_setu32()
   * @see lcb_cntl_string()
   */
  LIBCOUCHBASE_API
  lcb_STATUS lcb_cntl(lcb_INSTANCE *instance, int mode, int cmd, void *arg);
  
  /**
   * Alternatively one may change configuration settings by passing a string key
   * and value. This may be used to provide a simple interface from a command
   * line or higher level language to allow the setting of specific key-value
   * pairs.
   *
   * The format for the value is dependent on the option passed, the following
   * value types exist:
   *
   * - **Timeval**. A _timeval_ value can either be specified as fractional
   *   seconds (`"1.5"` for 1.5 seconds), or in microseconds (`"1500000"`). In
   *   releases prior to libcouchbase 2.8, this was called _timeout_.
   * - **Number**. This is any valid numerical value. This may be signed or
   *   unsigned depending on the setting.
   * - **Boolean**. This specifies a boolean. A true value is either a positive
   *   numeric value (i.e. `"1"`) or the string `"true"`. A false value
   *   is a zero (i.e. `"0"`) or the string `"false"`.
   * - **Float**. This is like a _Number_, but also allows fractional specification,
   *   e.g. `"2.4"`.
   * - **String**. Arbitrary string as `char *`, e.g. for client identification
   *   string.
   * - **Path**. File path.
   * - **FILE*, Path**. Set file stream pointer (lcb_cntl() style) or file path
   *   (lcb_cntl_string() style).
   *
   * | Code                                    | Name                      | Type              |
   * |-----------------------------------------|---------------------------|-------------------|
   * |@ref LCB_CNTL_OP_TIMEOUT                 | `"operation_timeout"`     | Timeval           |
   * |@ref LCB_CNTL_VIEW_TIMEOUT               | `"view_timeout"`          | Timeval           |
   * |@ref LCB_CNTL_QUERY_TIMEOUT              | `"n1ql_timeout"`          | Timeval           |
   * |@ref LCB_CNTL_HTTP_TIMEOUT               | `"http_timeout"`          | Timeval           |
   * |@ref LCB_CNTL_CONFIG_POLL_INTERVAL       | `"config_poll_interval"`  | Timeval           |
   * |@ref LCB_CNTL_CONFERRTHRESH              | `"error_thresh_count"`    | Number (Positive) |
   * |@ref LCB_CNTL_CONFIGURATION_TIMEOUT      | `"config_total_timeout"`  | Timeval           |
   * |@ref LCB_CNTL_CONFIG_NODE_TIMEOUT        | `"config_node_timeout"`   | Timeval           |
   * |@ref LCB_CNTL_CONFDELAY_THRESH           | `"error_thresh_delay"`    | Timeval           |
   * |@ref LCB_CNTL_DURABILITY_TIMEOUT         | `"durability_timeout"`    | Timeval           |
   * |@ref LCB_CNTL_DURABILITY_INTERVAL        | `"durability_interval"`   | Timeval           |
   * |@ref LCB_CNTL_RANDOMIZE_BOOTSTRAP_HOSTS  | `"randomize_nodes"`       | Boolean           |
   * |@ref LCB_CNTL_CONFIGCACHE                | `"config_cache"`          | Path              |
   * |@ref LCB_CNTL_DETAILED_ERRCODES          | `"detailed_errcodes"`     | Boolean           |
   * |@ref LCB_CNTL_HTCONFIG_URLTYPE           | `"http_urlmode"`          | Number (enum #lcb_HTCONFIG_URLTYPE) |
   * |@ref LCB_CNTL_RETRY_INTERVAL             | `"retry_interval"`        | Timeval           |
   * |@ref LCB_CNTL_HTTP_POOLSIZE              | `"http_poolsize"`         | Number            |
   * |@ref LCB_CNTL_VBGUESS_PERSIST            | `"vbguess_persist"`       | Boolean           |
   * |@ref LCB_CNTL_CONLOGGER_LEVEL            | `"console_log_level"`     | Number (enum #lcb_log_severity_t) |
   * |@ref LCB_CNTL_ENABLE_MUTATION_TOKENS     | `"enable_mutation_tokens"`| Boolean           |
   * |@ref LCB_CNTL_TCP_NODELAY                | `"tcp_nodelay"`           | Boolean           |
   * |@ref LCB_CNTL_CONLOGGER_FP               | `"console_log_file"`      | FILE*, Path       |
   * |@ref LCB_CNTL_CLIENT_STRING              | `"client_string"`         | String            |
   * |@ref LCB_CNTL_TCP_KEEPALIVE              | `"tcp_keepalive"`         | Boolean           |
   * |@ref LCB_CNTL_CONFIG_POLL_INTERVAL       | `"config_poll_interval"`  | Timeval           |
   * |@ref LCB_CNTL_IP6POLICY                  | `"ipv6"`                  | String ("disabled", "only", "allow") |
   *
   * @committed - Note, the actual API call is considered committed and will
   * not disappear, however the existence of the various string settings are
   * dependendent on the actual settings they map to. It is recommended that
   * applications use the numerical lcb_cntl() as the string names are
   * subject to change.
   *
   * @see lcb_cntl()
   * @see lcb-cntl-settings
   */
  LIBCOUCHBASE_API
  lcb_STATUS lcb_cntl_string(lcb_INSTANCE *instance, const char *key, const char *value);
  
  /**
   * @brief Convenience function to set a value as an lcb_U32
   * @param instance
   * @param cmd setting to modify
   * @param arg the new value
   * @return see lcb_cntl() for details
   * @committed
   */
  LIBCOUCHBASE_API
  lcb_STATUS lcb_cntl_setu32(lcb_INSTANCE *instance, int cmd, lcb_U32 arg);
  
  /**
   * @brief Retrieve an lcb_U32 setting
   * @param instance
   * @param cmd setting to retrieve
   * @return the value.
   * @warning This function does not return an error code. Ensure that the cntl is
   * correct for this version, or use lcb_cntl() directly.
   * @committed
   */
  LIBCOUCHBASE_API
  lcb_U32 lcb_cntl_getu32(lcb_INSTANCE *instance, int cmd);
  
  /**
   * Determine if a specific control code exists
   * @param ctl the code to check for
   * @return 0 if it does not exist, nonzero if it exists.
   */
  LIBCOUCHBASE_API
  int lcb_cntl_exists(int ctl);
  
  /**
   * @uncommitted
   *
   * @brief Force the library to refetch the cluster configuration
   *
   * The library by default employs various heuristics to determine if a new
   * configuration is needed from the cluster. However there are some situations
   * in which an application may wish to force a refresh of the configuration:
   *
   * * If a specific node has been failed
   *   over and the library has received a configuration in which there is no
   *   master node for a given key, the library will immediately return the error
   *   `LCB_ERR_NO_MATCHING_SERVER` for the given item and will not request a new
   *   configuration. In this state, the client will not perform any network I/O
   *   until a request has been made to it using a key that is mapped to a known
   *   active node.
   *
   * * The library's heuristics may have failed to detect an error warranting
   *   a configuration change, but the application either through its own
   *   heuristics, or through an out-of-band channel knows that the configuration
   *   has changed.
   *
   *
   * This function is provided as an aid to assist in such situations
   *
   * If you wish for your application to block until a new configuration is
   * received, you _must_ call lcb_wait() with the LCB_WAIT_NO_CHECK flag as
   * this function call is not bound to a specific operation. Additionally there
   * is no status notification as to whether this operation succeeded or failed
   * (the configuration callback via lcb_set_configuration_callback() may
   * provide hints as to whether a configuration was received or not, but by no
   * means should be considered to be part of this function's control flow).
   *
   * In general the use pattern of this function is like so:
   *
   * @code{.c}
   * unsigned retries = 5;
   * lcb_STATUS err;
   * do {
   *   retries--;
   *   err = lcb_get(instance, cookie, ncmds, cmds);
   *   if (err == LCB_ERR_NO_MATCHING_SERVER) {
   *     lcb_refresh_config(instance);
   *     usleep(100000);
   *     lcb_wait(instance, LCB_WAIT_NO_CHECK);
   *   } else {
   *     break;
   *   }
   * } while (retries);
   * if (err == LCB_SUCCESS) {
   *   lcb_wait(instance, 0); // equivalent to lcb_wait(instance, LCB_WAIT_DEFAULT);
   * } else {
   *   printf("Tried multiple times to fetch the key, but its node is down\n");
   * }
   * @endcode
   */
  
  LIBCOUCHBASE_API
  void lcb_refresh_config(lcb_INSTANCE *instance);
  
  /**@}*/
  
  /**
   * @ingroup lcb-public-api
   * @defgroup lcb-build-info Build Information
   * @brief Get library version and supported features
   * @details
   * These functions and macros may be used to conditionally compile features
   * depending on the version of the library being used. They may also be used
   * to employ various features at runtime and to retrieve the version for
   * informational purposes.
   * @addtogroup lcb-build-info
   * @{
   */
  
  #if !defined(LCB_VERSION_STRING) || defined(__LCB_DOXYGEN__)
  /** @brief libcouchbase version string */
  #define LCB_VERSION_STRING "unknown"
  #endif
  
  #if !defined(LCB_VERSION) || defined(__LCB_DOXYGEN__)
  /**@brief libcouchbase hex version
   *
   * This number contains the hexadecimal representation of the library version.
   * It is in a format of `0xXXYYZZ` where `XX` is the two digit major version
   * (e.g. `02`), `YY` is the minor version (e.g. `05`) and `ZZ` is the patch
   * version (e.g. `24`).
   *
   * For example:
   *
   * String   |Hex
   * ---------|---------
   * 2.0.0    | 0x020000
   * 2.1.3    | 0x020103
   * 3.0.15   | 0x030015
   */
  #define LCB_VERSION 0x000000
  #endif
  
  #if !defined(LCB_VERSION_CHANGESET) || defined(__LCB_DOXYGEN__)
  /**@brief The SCM revision ID. @see LCB_CNTL_CHANGESET */
  #define LCB_VERSION_CHANGESET "0xdeadbeef"
  #endif
  
  /**
   * Get the version of the library.
   *
   * @param version where to store the numeric representation of the
   *         version (or NULL if you don't care)
   *
   * @return the textual description of the version ('\0'
   *          terminated). Do <b>not</b> try to release this string.
   *
   */
  LIBCOUCHBASE_API
  const char *lcb_get_version(lcb_U32 *version);
  
  /** Global/extern variable containing the version of the library */
  LIBCOUCHBASE_API LCB_EXTERN_VAR const lcb_U32 lcb_version_g;
  
  /**@brief Whether the library has SSL support*/
  #define LCB_SUPPORTS_SSL 1
  /**@brief Whether the library has experimental compression support */
  #define LCB_SUPPORTS_SNAPPY 2
  /**@brief Whether the library has experimental tracing support */
  #define LCB_SUPPORTS_TRACING 3
  
  /**
   * @committed
   * Determine if this version has support for a particularl feature
   * @param n the feature ID to check for
   * @return 0 if not supported, nonzero if supported.
   */
  LIBCOUCHBASE_API
  int lcb_supports_feature(int n);
  
  /**@} (Group: Build Info) */
  
  /**
   * @ingroup lcb-public-api
   * @defgroup lcb-logging-api Logging
   * @brief Various logging functions
   * @addtogroup lcb-logging-api
   * @{
   */
  /**
   * Returns whether the library redacting logs for this connection instance.
   * @param instance the instance
   * @return non-zero if the logs are being redacted for this instance.
   */
  LIBCOUCHBASE_API
  int lcb_is_redacting_logs(lcb_INSTANCE *instance);
  
  /** @} */
  
  /**
   * @ingroup lcb-public-api
   * @defgroup lcb-analytics-api Analytics Queries
   * @brief Execute Analytics N1QL Queries
   * @addtogroup lcb-analytics-api
   * @{
   */
  
  typedef struct lcb_ANALYTICS_HANDLE_ lcb_ANALYTICS_HANDLE;
  typedef struct lcb_DEFERRED_HANDLE_ lcb_DEFERRED_HANDLE;
  
  /**
   * Response for a Analytics query. This is delivered in the @ref lcb_ANALYTICSCALLBACK
   * callback function for each result row received. The callback is also called
   * one last time when all
   */
  typedef struct lcb_RESPANALYTICS_ lcb_RESPANALYTICS;
  
  /**
   * Callback to be invoked for each row
   * @param The instance
   * @param Callback type. This is set to @ref LCB_CALLBACK_ANALYTICS
   * @param The response.
   */
  typedef void (*lcb_ANALYTICS_CALLBACK)(lcb_INSTANCE *, int, const lcb_RESPANALYTICS *);
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respanalytics_status(const lcb_RESPANALYTICS *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respanalytics_cookie(const lcb_RESPANALYTICS *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respanalytics_row(const lcb_RESPANALYTICS *resp, const char **row, size_t *row_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respanalytics_http_response(const lcb_RESPANALYTICS *resp, const lcb_RESPHTTP **http);
  /**
   * Get handle to analytics query.  Used when canceling analytics request.  See @ref lcb_cmdanalytics_handle also
   *
   * @param resp the analytics response
   * @param handle pointer to handle pointer
   * @return LCB_SUCCESS if successful, otherwise an error code
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_respanalytics_handle(const lcb_RESPANALYTICS *resp, lcb_ANALYTICS_HANDLE **handle);
  LIBCOUCHBASE_API lcb_STATUS lcb_respanalytics_error_context(const lcb_RESPANALYTICS *resp,
                                                              const lcb_ANALYTICS_ERROR_CONTEXT **ctx);
  LIBCOUCHBASE_API int lcb_respanalytics_is_final(const lcb_RESPANALYTICS *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respanalytics_deferred_handle_extract(const lcb_RESPANALYTICS *resp,
                                                                        lcb_DEFERRED_HANDLE **handle);
  LIBCOUCHBASE_API lcb_STATUS lcb_deferred_handle_destroy(lcb_DEFERRED_HANDLE *handle);
  LIBCOUCHBASE_API lcb_STATUS lcb_deferred_handle_status(lcb_DEFERRED_HANDLE *handle, const char **status,
                                                         size_t *status_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_deferred_handle_callback(lcb_DEFERRED_HANDLE *handle, lcb_ANALYTICS_CALLBACK callback);
  LIBCOUCHBASE_API lcb_STATUS lcb_deferred_handle_poll(lcb_INSTANCE *instance, void *cookie, lcb_DEFERRED_HANDLE *handle);
  
  typedef struct lcb_CMDANALYTICS_ lcb_CMDANALYTICS;
  
  typedef struct lcb_INGEST_OPTIONS_ lcb_INGEST_OPTIONS;
  typedef enum {
      LCB_INGEST_METHOD_NONE = 0,
      LCB_INGEST_METHOD_UPSERT,
      LCB_INGEST_METHOD_INSERT,
      LCB_INGEST_METHOD_REPLACE,
      LCB_INGEST_METHOD__MAX
  } lcb_INGEST_METHOD;
  
  typedef enum {
  
      /** @brief No consistency constraints
       *  @details
       *  The default.  When you are not concerned about the consistency of this query with regards to other queries.
       */
      LCB_ANALYTICS_CONSISTENCY_NOT_BOUNDED = 0,
      /**  @brief Strong consistency
       *   @details
       *   Ensures that the query won't execute until any pending indexing at the time of the request has completed.
       */
      LCB_ANALYTICS_CONSISTENCY_REQUEST_PLUS = 1
  } lcb_ANALYTICS_CONSISTENCY;
  
  typedef enum { LCB_INGEST_STATUS_OK = 0, LCB_INGEST_STATUS_IGNORE, LCB_INGEST_STATUS__MAX } lcb_INGEST_STATUS;
  
  typedef struct lcb_INGEST_PARAM_ lcb_INGEST_PARAM;
  
  typedef lcb_INGEST_STATUS (*lcb_INGEST_DATACONVERTER_CALLBACK)(lcb_INSTANCE *instance, lcb_INGEST_PARAM *param);
  
  LIBCOUCHBASE_API lcb_STATUS lcb_ingest_options_create(lcb_INGEST_OPTIONS **options);
  LIBCOUCHBASE_API lcb_STATUS lcb_ingest_options_destroy(lcb_INGEST_OPTIONS *options);
  LIBCOUCHBASE_API lcb_STATUS lcb_ingest_options_method(lcb_INGEST_OPTIONS *options, lcb_INGEST_METHOD method);
  LIBCOUCHBASE_API lcb_STATUS lcb_ingest_options_expiry(lcb_INGEST_OPTIONS *options, uint32_t expiration);
  LIBCOUCHBASE_API lcb_STATUS lcb_ingest_options_ignore_error(lcb_INGEST_OPTIONS *options, int flag);
  LIBCOUCHBASE_API lcb_STATUS lcb_ingest_options_data_converter(lcb_INGEST_OPTIONS *options,
                                                                lcb_INGEST_DATACONVERTER_CALLBACK callback);
  
  LIBCOUCHBASE_API lcb_STATUS lcb_ingest_dataconverter_param_cookie(lcb_INGEST_PARAM *param, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_ingest_dataconverter_param_row(lcb_INGEST_PARAM *param, const char **row,
                                                                 size_t *row_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_ingest_dataconverter_param_method(lcb_INGEST_PARAM *param, lcb_INGEST_METHOD *method);
  LIBCOUCHBASE_API lcb_STATUS lcb_ingest_dataconverter_param_set_id(lcb_INGEST_PARAM *param, const char *id,
                                                                    size_t id_len, void (*id_dtor)(const char *));
  LIBCOUCHBASE_API lcb_STATUS lcb_ingest_dataconverter_param_set_out(lcb_INGEST_PARAM *param, const char *out,
                                                                     size_t out_len, void (*out_dtor)(const char *));
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_create(lcb_CMDANALYTICS **cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_destroy(lcb_CMDANALYTICS *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_reset(lcb_CMDANALYTICS *cmd);
  /**@}*/
  /**
   * @ingroup lcb-public-api
   * @addtogroup lcb-tracing-api
   * @{
   */
  /**
   * Associate parent tracing span with the Analytics request.
   *
   * @param cmd the command
   * @param span parent span
   *
   * @par Attach parent tracing span to request object.
   * @code{.c}
   * lcb_CMDANALYTICS* cmd;
   * lcb_cmdanalytics_create(&cmd);
   *
   * lcb_analytics_parentspan(instance, span);
   *
   * lcb_error_t err = lcb_analytics_query(instance, cookie, cmd);
   * @endcode
   *
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_parent_span(lcb_CMDANALYTICS *cmd, lcbtrace_SPAN *span);
  /**@}*/
  /**
   * @ingroup lcb-public-api
   * @addtogroup lcb-analytics-api
   * @{
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_callback(lcb_CMDANALYTICS *cmd, lcb_ANALYTICS_CALLBACK callback);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_encoded_payload(lcb_CMDANALYTICS *cmd, const char **query,
                                                               size_t *query_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_payload(lcb_CMDANALYTICS *cmd, const char *query, size_t query_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_statement(lcb_CMDANALYTICS *cmd, const char *statement,
                                                         size_t statement_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_named_param(lcb_CMDANALYTICS *cmd, const char *name, size_t name_len,
                                                           const char *value, size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_positional_param(lcb_CMDANALYTICS *cmd, const char *value,
                                                                size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_ingest_options(lcb_CMDANALYTICS *cmd, lcb_INGEST_OPTIONS *options);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_deferred(lcb_CMDANALYTICS *cmd, int deferred);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_client_context_id(lcb_CMDANALYTICS *cmd, const char *value,
                                                                 size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_readonly(lcb_CMDANALYTICS *cmd, int readonly);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_priority(lcb_CMDANALYTICS *cmd, int priority);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_consistency(lcb_CMDANALYTICS *cmd, lcb_ANALYTICS_CONSISTENCY level);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_option(lcb_CMDANALYTICS *cmd, const char *name, size_t name_len,
                                                      const char *value, size_t value_len);
  /**
   * Get handle to analytics query.  Used when canceling a request.  See @ref lcb_respanalytics_handle as well
   *
   * @param cmd the command
   * @param handle pointer to handle pointer
   * @return LCB_SUCCESS if successful, otherwise an error code
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_handle(lcb_CMDANALYTICS *cmd, lcb_ANALYTICS_HANDLE **handle);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdanalytics_timeout(lcb_CMDANALYTICS *cmd, uint32_t timeout);
  /**
   * Execute a Analytics query.
   *
   * This function will send the query to a query server in the cluster
   * and will invoke the callback (lcb_CMDANALYTICS::callback) for each result returned.
   *
   * @param instance The instance
   * @param cookie Pointer to application data
   * @param cmd the command
   * @return LCB_SUCCESS if successfully scheduled otherwise a failure.
   */
  
  LIBCOUCHBASE_API lcb_STATUS lcb_analytics(lcb_INSTANCE *instance, void *cookie, const lcb_CMDANALYTICS *cmd);
  /**
   * Cancels an in-progress request. This will ensure that further callbacks
   * for the given request are not delivered.
   *
   * @param instance the instance
   * @param handle the handle for the request. This can be obtained from the command (see @ref lcb_cmdanalytics_handle),
   *      or from the response (see @ref lcb_respanalytics_handle)
   *
   * To obtain the `handle` parameter, do something like this:
   *
   * @code{.c}
   * lcb_CMDANALYTICS *cmd;
   * // (Initialize command...)
   * lcb_analytics(instance, cookie, &cmd);
   * lcb_ANALYTICS_HANDLE* handle;
   * lcb_cmdanalytics_gethandle(cmd, &handle);
   * @endcode
   *
   * If you happen to only have the lcb_RESPANALYTICS handy, say you are in the
   * callback:
   * @code{.c}
   * lcb_ANALYTICS_HANDLE* handle;
   * lcb_respanalytics_handle(resp, &handle);
   * @endcode
   *
   * If the lcb_analytics_query() function returns `LCB_SUCCESS` then the `handle`
   * above is populated with the opaque handle. You can then use this handle
   * to cancel the query at a later point, such as within the callback.
   *
   * @code{.c}
   * lcb_analytics_cancel(instance, handle);
   * @endcode
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_analytics_cancel(lcb_INSTANCE *instance, lcb_ANALYTICS_HANDLE *handle);
  
  /** @} */
  
  /**
   * @ingroup lcb-public-api
   * @defgroup lcb-cbft-api Full Text Search
   * @brief Search for strings in documents and more
   */
  
  /**
   * @addtogroup lcb-cbft-api
   * @{
   */
  typedef struct lcb_SEARCH_HANDLE_ lcb_SEARCH_HANDLE;
  typedef struct lcb_RESPSEARCH_ lcb_RESPSEARCH;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respsearch_status(const lcb_RESPSEARCH *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respsearch_cookie(const lcb_RESPSEARCH *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respsearch_row(const lcb_RESPSEARCH *resp, const char **row, size_t *row_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respsearch_http_response(const lcb_RESPSEARCH *resp, const lcb_RESPHTTP **http);
  /**
   * Get search handle from search response.  Used to cancel a request.  See @ref lcb_cmdsearch_handle as well
   *
   * @param resp the search response
   * @param handle pointer to handle pointer
   * @return LCB_SUCCESS if successful, otherwise an error code
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_respsearch_handle(const lcb_RESPSEARCH *resp, lcb_SEARCH_HANDLE **handle);
  LIBCOUCHBASE_API lcb_STATUS lcb_respsearch_error_context(const lcb_RESPSEARCH *resp,
                                                           const lcb_SEARCH_ERROR_CONTEXT **ctx);
  LIBCOUCHBASE_API int lcb_respsearch_is_final(const lcb_RESPSEARCH *resp);
  
  typedef struct lcb_CMDSEARCH_ lcb_CMDSEARCH;
  typedef void (*lcb_SEARCH_CALLBACK)(lcb_INSTANCE *, int, const lcb_RESPSEARCH *);
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsearch_create(lcb_CMDSEARCH **cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsearch_destroy(lcb_CMDSEARCH *cmd);
  /**@}*/
  
  /**
   * @ingroup lcb-public-api
   * @addtogroup lcb-tracing-api
   * @{
   */
  /**
   * Associate parent tracing span with the FTS request.
   *
   * @param cmd the command
   * @param span parent span
   *
   * @par Attach parent tracing span to request object.
   * @code{.c}
   * lcb_CMDSEARCH cmd;
   * lcb_cmdsearch_create(&cmd);
   * // create a search query...
  
   * lcb_error_t err = lcb_search(instance, cookie, cmd);
   * if (err == LCB_SUCCESS) {
   *     lcb_cmdsearch_parent_span(instance, span);
   * }
   * @endcode
   *
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsearch_parent_span(lcb_CMDSEARCH *cmd, lcbtrace_SPAN *span);
  /**@}*/
  /**
   * @ingroup lcb-public-api
   * @addtogroup lcb-cbft-api
   * @{
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsearch_callback(lcb_CMDSEARCH *cmd, lcb_SEARCH_CALLBACK callback);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsearch_payload(lcb_CMDSEARCH *cmd, const char *payload, size_t payload_len);
  /**
   * Obtain handle to search.  Used to cancel a query.  See @ref lcb_respsearch_handle as well
   * @param cmd the command
   * @param handle pointer to handle pointer
   * @return LCB_SUCCESS upon success, otherwise an error code
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsearch_handle(lcb_CMDSEARCH *cmd, lcb_SEARCH_HANDLE **handle);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsearch_timeout(lcb_CMDSEARCH *cmd, uint32_t timeout);
  
  /**
   * Issue a full-text query. The callback (lcb_SEARCH_CALLBACK) will be invoked
   * for each hit. It will then be invoked one last time with the result
   * metadata (including any facets) and the lcb_resp_is_final will return
   * true.
   *
   * @param instance the instance
   * @param cookie opaque user cookie to be set in the response object
   * @param cmd command containing the query and callback
   * @return LCB_SUCCESS if successfully scheduled, otherwise an error.
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_search(lcb_INSTANCE *instance, void *cookie, const lcb_CMDSEARCH *cmd);
  /**
   * Cancel a full-text query in progress. The handle is usually obtained via the
   * lcb_cmdsearch_handle call
   * @param instance the instance
   * @param handle the handle to the search.  See @ref lcb_cmdsearch_handle.
   * @return LCB_SUCCESS if successful, otherwise an error.
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_search_cancel(lcb_INSTANCE *instance, lcb_SEARCH_HANDLE *handle);
  /** @} */
  
  /**
   * @ingroup lcb-public-api
   * @defgroup lcb-n1ql-api N1QL Queries
   * @brief Execute N1QL queries.
   *
   * Query language based on SQL, but designed for structured and flexible JSON
   * documents. Querying can solve typical programming tasks such as finding a
   * user profile by email address, performing aggregations etc.
   *
   * @code{.c}
   * const char *query = "{\"statement\":\"SELECT * FROM breweries LIMIT 10\"}";
   * lcb_CMDQUERY* cmd = NULL;
   * int cookie = 0;
   * lcb_cmdquery_create(&cmd);
   * lcb_cmdquery_callback(cmd, row_callback)
   * lcb_n1ql_query(instance, &cookie, cmd);
   * lcb_wait(instance, LCB_WAIT_DEFAULT);
   * @endcode
   *
   * Where row_callback might be implemented like this:
   *
   * @code{.c}
   * static void row_callback(lcb_INSTANCE *instance, int type, const lcb_RESPQUERY *resp)
   * {
   *     int* idx = NULL;
   *     int row_len = 0;
   *     char* row = NULL;
   *
   *     int rc = lcb_respquery_status(resp);
   *     if (rc != LCB_SUCCESS) {
   *         printf("failed to execute query: %s\n", lcb_strerror_short(rc));
   *         exit(EXIT_FAILURE);
   *     }
   *     lcb_respquery_cookie(resp, (void**)(&idx))
   *     if (lcb_respquery_is_final(resp)) {
   *         printf("META: ");
   *     } else {
   *         printf("ROW #%d: ", (*idx)++);
   *     }
   *     lcb_respquery_row(resp, &row_len, &row);
   *     printf("%.*s\n", row_len, row);
   * }
   * @endcode
   *
   * @see more details on @ref lcb_query and @ref lcb_CMDQUERY.
   *
   */
  
  /**
   * @addtogroup lcb-n1ql-api
   * @{
   */
  
  /**
   * Opaque query response structure
   */
  typedef struct lcb_RESPQUERY_ lcb_RESPQUERY;
  
  /**
   * Opaque query command structure
   */
  typedef struct lcb_CMDQUERY_ lcb_CMDQUERY;
  /**
   * Pointer for request instance
   */
  typedef struct lcb_QUERY_HANDLE_ lcb_QUERY_HANDLE;
  
  /**
   * Callback to be invoked for each row
   * @param The instance
   * @param Callback type. This is set to @ref LCB_CALLBACK_QUERY
   * @param The response.
   */
  typedef void (*lcb_QUERY_CALLBACK)(lcb_INSTANCE *, int, const lcb_RESPQUERY *);
  
  typedef enum {
      /** No consistency constraints */
      LCB_QUERY_CONSISTENCY_NONE = 0,
  
      /**
       * This is implicitly set by @ref lcb_cmdquery_consistency_token_for_keyspace. This
       * will ensure that mutations up to the vector indicated by the mutation token
       * passed to @ref lcb_cmdquery_consistency_token_for_keyspace are used.
       */
      LCB_QUERY_CONSISTENCY_RYOW = 1,
  
      /** Refresh the snapshot for each request */
      LCB_QUERY_CONSISTENCY_REQUEST = 2,
  
      /** Refresh the snapshot for each statement */
      LCB_QUERY_CONSISTENCY_STATEMENT = 3
  } lcb_QUERY_CONSISTENCY;
  
  typedef enum {
      LCB_QUERY_PROFILE_OFF = 0,
      LCB_QUERY_PROFILE_PHASES = 1,
      LCB_QUERY_PROFILE_TIMINGS = 2
  } lcb_QUERY_PROFILE;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respquery_status(const lcb_RESPQUERY *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respquery_cookie(const lcb_RESPQUERY *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respquery_row(const lcb_RESPQUERY *resp, const char **row, size_t *row_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respquery_http_response(const lcb_RESPQUERY *resp, const lcb_RESPHTTP **http);
  LIBCOUCHBASE_API lcb_STATUS lcb_respquery_handle(const lcb_RESPQUERY *resp, lcb_QUERY_HANDLE **handle);
  LIBCOUCHBASE_API lcb_STATUS lcb_respquery_error_context(const lcb_RESPQUERY *resp, const lcb_QUERY_ERROR_CONTEXT **ctx);
  LIBCOUCHBASE_API int lcb_respquery_is_final(const lcb_RESPQUERY *resp);
  /**
   * Create a new lcb_CMDQUERY object. The returned object is an opaque
   * pointer which may be used to set various properties on a N1QL query.
   *
   * @param cmd pointer to an @ref lcb_CMDQUERY* which will be allocated
   * @return LCB_SUCCESS when successful, otherwise an error code
   */
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_create(lcb_CMDQUERY **cmd);
  /**
   * Free the command structure. This should be done when it is no longer
   * needed
   * @param cmd the command to destroy
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_destroy(lcb_CMDQUERY *cmd);
  /**
   * Reset the @ref lcb_CMDQUERY structure so that it may be reused for a subsequent
   * query.  Results in less memory allocator overhead that creating a cmd each time
   * you need one.
   *
   * @param cmd the command
   * @return LCB_SUCCESS when successful, otherwise an error code.
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_reset(lcb_CMDQUERY *cmd);
  /**
   * Get the JSON-encoded query payload.
   *
   * Helpful for re-issuing a query using @ref lcb_cmdquery_payload.
   * @param cmd the command
   * @param payload pointer to a string which will contain the payload
   * @param payload_len length of the payload string.
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_encoded_payload(lcb_CMDQUERY *cmd, const char **payload, size_t *payload_len);
  /**@}*/
  
  /**
   * @ingroup lcb-public-api
   * @addtogroup lcb-tracing-api
   * @{
   */
  /**
   * Associate parent tracing span with the N1QL request.
   *
   * @param cmd the command
   * @param span parent span
   *
   * @par Attach parent tracing span to request object.
   * @code{.c}
   * lcb_CMDQUERY* cmd;
   * lcb_cmdquery_create(&cmd);
   *
   * lcb_error_t err = lcb_query(instance, cookie, cmd);
   * if (err == LCB_SUCCESS) {
   *     lcb_cmdquery_parent_span(cmd, span);
   * }
   * @endcode
   *
   *
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_parent_span(lcb_CMDQUERY *cmd, lcbtrace_SPAN *span);
  /**@}*/
  
  /**
   * @ingroup lcb-public-api
   * @addtogroup lcb-n1ql-api
   * @{
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_callback(lcb_CMDQUERY *cmd, lcb_QUERY_CALLBACK callback);
  /**
   * Sets the JSON-encodes query payload to be executed
   * @param cmd the command
   * @param query the query payload, as a JSON-encoded string.
   * @param query_len length of the query payload string.
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_payload(lcb_CMDQUERY *cmd, const char *query, size_t query_len);
  /**
   * Sets the actual statement to be executed
   * @param cmd the command
   * @param statement the query string.  Note it can contain placeholders for positional or named parameters.
   * @param statement_len length of the statement string.
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_statement(lcb_CMDQUERY *cmd, const char *statement, size_t statement_len);
  /**
   * Associate scope name with the query
   * @param cmd the command
   * @param scope the name of the scope
   * @param scope_len length of the scope name string.
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_scope_name(lcb_CMDQUERY *cmd, const char *scope, size_t scope_len);
  /**
   * @uncommitted
   *
   * Associate scope_qualifier (also known as `query_context`) with the query.
   *
   * The qualifier must be in form `${bucket_name}.${scope_name}` or `default:${bucket_name}.${scope_name}`.
   *
   * @param cmd the command
   * @param qualifier the string containing qualifier
   * @param qualifier_len length of the qualifier
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_scope_qualifier(lcb_CMDQUERY *cmd, const char *qualifier,
                                                           size_t qualifier_len);
  /**
   * Sets a named argument for the query
   * @param cmd the command
   * @param name The argument name (e.g. `$age`)
   * @param name_len length of the name
   * @param value The argument value (e.g. `42`)
   * @param value_len length of the value
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_named_param(lcb_CMDQUERY *cmd, const char *name, size_t name_len,
                                                       const char *value, size_t value_len);
  /**
   * Adds a _positional_ argument for the query
   *
   * The position is assumed to be the order they are set.
   * @param cmd the command
   * @param value the argument
   * @param value_len the length of the argument.
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_positional_param(lcb_CMDQUERY *cmd, const char *value, size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_adhoc(lcb_CMDQUERY *cmd, int adhoc);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_client_context_id(lcb_CMDQUERY *cmd, const char *value, size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_pretty(lcb_CMDQUERY *cmd, int pretty);
  /**
   * Marks query as read-only.
   *
   * If the user knows the request is only ever a select, for security
   * reasons it can make sense to tell the server this thing is readonly
   * and it will prevent mutations from happening.
   *
   * If readonly is set, then the following statements are not allowed:
   *   * CREATE INDEX
   *   * DROP INDEX
   *   * INSERT
   *   * MERGE
   *   * UPDATE
   *   * UPSERT
   *   * DELETE
   *
   * @param cmd the command
   * @param readonly if non-zero, the query will be read-only
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_readonly(lcb_CMDQUERY *cmd, int readonly);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_metrics(lcb_CMDQUERY *cmd, int metrics);
  /**
   * Sets maximum buffered channel size between the indexer client
   * and the query service for index scans.
   *
   * This parameter controls when to use scan backfill. Use 0 or
   * a negative number to disable.
   *
   * @param cmd the command
   * @param value channel size
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_scan_cap(lcb_CMDQUERY *cmd, int value);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_scan_wait(lcb_CMDQUERY *cmd, uint32_t us);
  /**
   * @uncommitted
   *
   * Tells the query engine to use a flex index (utilizing the search service).
   *
   * @param cmd the command
   * @param value non-zero if a flex index should be used, zero is the default
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_flex_index(lcb_CMDQUERY *cmd, int value);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_profile(lcb_CMDQUERY *cmd, lcb_QUERY_PROFILE mode);
  /**
   * Sets maximum number of items each execution operator can buffer
   * between various operators.
   *
   * @param cmd the command
   * @param value number of items
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_pipeline_cap(lcb_CMDQUERY *cmd, int value);
  /**
   * Sets the number of items execution operators can batch for
   * fetch from the KV.
   *
   * @param cmd the command
   * @param value number of items
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_pipeline_batch(lcb_CMDQUERY *cmd, int value);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_max_parallelism(lcb_CMDQUERY *cmd, int value);
  /**
   * Sets the consistency mode for the request.
   * By default results are read from a potentially stale snapshot of the data.
   * This may be good for most cases; however at times you want the absolutely
   * most recent data.
   * @param cmd the command
   * @param mode one of the @ref lcb_QUERY_CONSISTENCY values
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_consistency(lcb_CMDQUERY *cmd, lcb_QUERY_CONSISTENCY mode);
  /**
   * Indicate that the query should synchronize its internal snapshot to reflect
   * the changes indicated by the given mutation token (`ss`).
   * @param cmd the command
   * @param keyspace the keyspace (or bucket name) which this mutation token
   *        pertains to
   * @param keyspace_len length of the keyspace string
   * @param token the mutation token
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_consistency_token_for_keyspace(lcb_CMDQUERY *cmd, const char *keyspace,
                                                                          size_t keyspace_len,
                                                                          const lcb_MUTATION_TOKEN *token);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_consistency_tokens(lcb_CMDQUERY *cmd, lcb_INSTANCE *instance);
  /**
   * Set a query option
   * @param cmd the command
   * @param name the name of the option
   * @param name_len length of the name
   * @param value the value of the option
   * @param value_len length of the value
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_option(lcb_CMDQUERY *cmd, const char *name, size_t name_len, const char *value,
                                                  size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_handle(lcb_CMDQUERY *cmd, lcb_QUERY_HANDLE **handle);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdquery_timeout(lcb_CMDQUERY *cmd, uint32_t timeout);
  /**
   * Execute a N1QL query.
   *
   * This function will send the query to a query server in the cluster
   * and will invoke the callback (lcb_QUERY_CALLBACK*) for each result returned.
   *
   * @param instance The instance
   * @param cookie Pointer to application data
   * @param cmd the command
   * @return LCB_SUCCESS if successfully scheduled, or a failure code.
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_query(lcb_INSTANCE *instance, void *cookie, const lcb_CMDQUERY *cmd);
  /**
   * Cancels an in-progress request. This will ensure that further callbacks
   * for the given request are not delivered.
   *
   * @param instance the instance
   * @param handle the handle for the request. This is obtained during the
   *  request as an 'out' parameter (see lcb_CMDN1QL::handle)
   *
   * To obtain the `handle` parameter, do something like this:
   *
   * @code{.c}
   * lcb_QUERYHANDLE* handle;
   * lcb_CMDQUERY* cmd;
   * lcb_cmdquery_create(&cmd);
   * // (Initialize command...)
   * lcb_cmdquery_handle(cmd, &handle);
   * lcb_query(instance, cookie, &cmd);
   * @endcode.
   *
   * If the lcb_query() function returns `LCB_SUCCESS` then the `handle`
   * above is populated with the opaque handle. You can then use this handle
   * to cancel the query at a later point, such as within the callback. You
   * can also get the handle from the response object using `lcb_respquery_handle`
   *
   * @code{.c}
   * lcb_query_cancel(instance, handle);
   * @endcode
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_query_cancel(lcb_INSTANCE *instance, lcb_QUERY_HANDLE *handle);
  /** @} */
  
  /**
   * @ingroup lcb-public-api
   * @defgroup lcb-view-api Views (Map-Reduce)
   * @brief Higher level API which splits view results into rows
   */
  
  /**
   * @addtogroup lcb-view-api
   * @{
   */
  
  typedef struct lcb_RESPVIEW_ lcb_RESPVIEW;
  typedef struct lcb_CMDVIEW_ lcb_CMDVIEW;
  
  /**
   * Pointer for request instance
   */
  typedef struct lcb_VIEW_HANDLE_ lcb_VIEW_HANDLE;
  
  /**
   * Callback function invoked for each row returned from the view
   * @param instance the library handle
   * @param cbtype the callback type. This is set to @ref LCB_CALLBACK_VIEWQUERY
   * @param row Information about the current row
   *
   * Note that this callback's `row->rflags` will contain the @ref LCB_RESP_F_FINAL
   * flag set after all rows have been returned. Applications should check for
   * the presence of this flag. If this flag is present, the row itself will
   * contain the raw response metadata in its lcb_RESPVIEWQUERY::value field.
   */
  typedef void (*lcb_VIEW_CALLBACK)(lcb_INSTANCE *instance, int cbtype, const lcb_RESPVIEW *row);
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respview_status(const lcb_RESPVIEW *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respview_cookie(const lcb_RESPVIEW *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respview_key(const lcb_RESPVIEW *resp, const char **key, size_t *key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respview_doc_id(const lcb_RESPVIEW *resp, const char **doc_id, size_t *doc_id_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respview_row(const lcb_RESPVIEW *resp, const char **row, size_t *row_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respview_document(const lcb_RESPVIEW *resp, const lcb_RESPGET **doc);
  LIBCOUCHBASE_API lcb_STATUS lcb_respview_http_response(const lcb_RESPVIEW *resp, const lcb_RESPHTTP **http);
  LIBCOUCHBASE_API lcb_STATUS lcb_respview_handle(const lcb_RESPVIEW *resp, lcb_VIEW_HANDLE **handle);
  LIBCOUCHBASE_API lcb_STATUS lcb_respview_error_context(const lcb_RESPVIEW *resp, const lcb_VIEW_ERROR_CONTEXT **ctx);
  LIBCOUCHBASE_API int lcb_respview_is_final(const lcb_RESPVIEW *resp);
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdview_create(lcb_CMDVIEW **cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdview_destroy(lcb_CMDVIEW *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdview_parent_span(lcb_CMDVIEW *cmd, lcbtrace_SPAN *span);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdview_callback(lcb_CMDVIEW *cmd, lcb_VIEW_CALLBACK callback);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdview_design_document(lcb_CMDVIEW *cmd, const char *ddoc, size_t ddoc_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdview_view_name(lcb_CMDVIEW *cmd, const char *view, size_t view_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdview_option_string(lcb_CMDVIEW *cmd, const char *optstr, size_t optstr_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdview_post_data(lcb_CMDVIEW *cmd, const char *data, size_t data_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdview_include_docs(lcb_CMDVIEW *cmd, int include_docs);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdview_max_concurrent_docs(lcb_CMDVIEW *cmd, uint32_t num);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdview_no_row_parse(lcb_CMDVIEW *cmd, int flag);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdview_handle(lcb_CMDVIEW *cmd, lcb_VIEW_HANDLE **handle);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdview_timeout(lcb_CMDVIEW *cmd, uint32_t timeout);
  LIBCOUCHBASE_API lcb_STATUS lcb_view(lcb_INSTANCE *instance, void *cookie, const lcb_CMDVIEW *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_view_cancel(lcb_INSTANCE *instance, lcb_VIEW_HANDLE *handle);
  /** @} */
  
  /* @ingroup lcb-public-api
   * @defgroup lcb-subdoc Sub-Document API
   * @brief Experimental in-document API access
   * @details The sub-document API uses features from the upcoming Couchbase
   * 4.5 release which allows access to parts of the document. These parts are
   * called _sub-documents_ and can be accessed using the sub-document API
   *
   * @addtogroup lcb-subdoc
   * @{
   */
  
  typedef struct lcb_RESPSUBDOC_ lcb_RESPSUBDOC;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_respsubdoc_status(const lcb_RESPSUBDOC *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respsubdoc_error_context(const lcb_RESPSUBDOC *resp,
                                                           const lcb_KEY_VALUE_ERROR_CONTEXT **ctx);
  LIBCOUCHBASE_API lcb_STATUS lcb_respsubdoc_cookie(const lcb_RESPSUBDOC *resp, void **cookie);
  LIBCOUCHBASE_API lcb_STATUS lcb_respsubdoc_cas(const lcb_RESPSUBDOC *resp, uint64_t *cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_respsubdoc_key(const lcb_RESPSUBDOC *resp, const char **key, size_t *key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_respsubdoc_mutation_token(const lcb_RESPSUBDOC *resp, lcb_MUTATION_TOKEN *token);
  
  LIBCOUCHBASE_API size_t lcb_respsubdoc_result_size(const lcb_RESPSUBDOC *resp);
  LIBCOUCHBASE_API lcb_STATUS lcb_respsubdoc_result_status(const lcb_RESPSUBDOC *resp, size_t index);
  LIBCOUCHBASE_API lcb_STATUS lcb_respsubdoc_result_value(const lcb_RESPSUBDOC *resp, size_t index, const char **value,
                                                          size_t *value_len);
  
  /**
   * @private
   * @return non-zero if if the fetched document is a tombstone.
   */
  LIBCOUCHBASE_API int lcb_respsubdoc_is_deleted(const lcb_RESPSUBDOC *resp);
  
  typedef struct lcb_SUBDOCSPECS_ lcb_SUBDOCSPECS;
  
  /** Create intermediate paths */
  #define LCB_SUBDOCSPECS_F_MKINTERMEDIATES (1u << 16u)
  
  /** Access document XATTR path */
  #define LCB_SUBDOCSPECS_F_XATTRPATH (1u << 18u)
  
  /** Access document virtual/materialized path. Implies F_XATTRPATH */
  #define LCB_SUBDOCSPECS_F_XATTR_MACROVALUES (1u << 19u)
  
  /** Access Xattrs of deleted documents */
  #define LCB_SUBDOCSPECS_F_XATTR_DELETED_OK (1u << 20u)
  
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_create(lcb_SUBDOCSPECS **operations, size_t capacity);
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_destroy(lcb_SUBDOCSPECS *operations);
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_get(lcb_SUBDOCSPECS *operations, size_t index, uint32_t flags,
                                                  const char *path, size_t path_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_exists(lcb_SUBDOCSPECS *operations, size_t index, uint32_t flags,
                                                     const char *path, size_t path_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_replace(lcb_SUBDOCSPECS *operations, size_t index, uint32_t flags,
                                                      const char *path, size_t path_len, const char *value,
                                                      size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_dict_add(lcb_SUBDOCSPECS *operations, size_t index, uint32_t flags,
                                                       const char *path, size_t path_len, const char *value,
                                                       size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_dict_upsert(lcb_SUBDOCSPECS *operations, size_t index, uint32_t flags,
                                                          const char *path, size_t path_len, const char *value,
                                                          size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_array_add_first(lcb_SUBDOCSPECS *operations, size_t index, uint32_t flags,
                                                              const char *path, size_t path_len, const char *value,
                                                              size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_array_add_last(lcb_SUBDOCSPECS *operations, size_t index, uint32_t flags,
                                                             const char *path, size_t path_len, const char *value,
                                                             size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_array_add_unique(lcb_SUBDOCSPECS *operations, size_t index, uint32_t flags,
                                                               const char *path, size_t path_len, const char *value,
                                                               size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_array_insert(lcb_SUBDOCSPECS *operations, size_t index, uint32_t flags,
                                                           const char *path, size_t path_len, const char *value,
                                                           size_t value_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_counter(lcb_SUBDOCSPECS *operations, size_t index, uint32_t flags,
                                                      const char *path, size_t path_len, int64_t delta);
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_remove(lcb_SUBDOCSPECS *operations, size_t index, uint32_t flags,
                                                     const char *path, size_t path_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_subdocspecs_get_count(lcb_SUBDOCSPECS *operations, size_t index, uint32_t flags,
                                                        const char *path, size_t path_len);
  
  typedef struct lcb_CMDSUBDOC_ lcb_CMDSUBDOC;
  
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_create(lcb_CMDSUBDOC **cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_destroy(lcb_CMDSUBDOC *cmd);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_parent_span(lcb_CMDSUBDOC *cmd, lcbtrace_SPAN *span);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_collection(lcb_CMDSUBDOC *cmd, const char *scope, size_t scope_len,
                                                       const char *collection, size_t collection_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_key(lcb_CMDSUBDOC *cmd, const char *key, size_t key_len);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_cas(lcb_CMDSUBDOC *cmd, uint64_t cas);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_specs(lcb_CMDSUBDOC *cmd, const lcb_SUBDOCSPECS *operations);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_expiry(lcb_CMDSUBDOC *cmd, uint32_t expiration);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_durability(lcb_CMDSUBDOC *cmd, lcb_DURABILITY_LEVEL level);
  typedef enum {
      LCB_SUBDOC_STORE_REPLACE = 0,
      LCB_SUBDOC_STORE_UPSERT,
      LCB_SUBDOC_STORE_INSERT
  } lcb_SUBDOC_STORE_SEMANTICS;
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_store_semantics(lcb_CMDSUBDOC *cmd, lcb_SUBDOC_STORE_SEMANTICS mode);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_access_deleted(lcb_CMDSUBDOC *cmd, int flag);
  
  /**
   * If new document created, the server will create it as a tombstone.
   * Any system or user XATTRs will be stored, but a document body will not be.
   */
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_create_as_deleted(lcb_CMDSUBDOC *cmd, int flag);
  LIBCOUCHBASE_API lcb_STATUS lcb_cmdsubdoc_timeout(lcb_CMDSUBDOC *cmd, uint32_t timeout);
  
  LIBCOUCHBASE_API lcb_STATUS lcb_subdoc(lcb_INSTANCE *instance, void *cookie, const lcb_CMDSUBDOC *cmd);
  /** @} */
  
  /* Post-include some other headers */
  #ifdef __cplusplus
  }
  #endif /* __cplusplus */
  #endif /* LIBCOUCHBASE_COUCHBASE_H */
  