Skip to content

Instantly share code, notes, and snippets.

@mnunberg
Created June 9, 2015 16:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mnunberg/d1e17ceed8c28c590997 to your computer and use it in GitHub Desktop.
Save mnunberg/d1e17ceed8c28c590997 to your computer and use it in GitHub Desktop.
libcouchbase ABI-Safe command wrappers
/*
* Copyright 2015 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
#error "include <libcouchbase/couchbase.h> first"
#endif
#ifndef LIBCOUCHBASE_CMDWRAP_H
#define LIBCOUCHBASE_CMDWRAP_H
#include <libcouchbase/api3.h>
#include <libcouchbase/views.h>
#include <libcouchbase/n1ql.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @file */
/**
* @defgroup lcb-cmdwrap-api
* @brief ABI-Safe command wrappers
*
* @details
* These routines provide an ABI-safe manner in which to initialize commands
* and retrieve responses from callbacks. These wrap the commands and
* responses in the "V3" API (@ref lcb-public-api3).
*
* Applications which intend to dynamically link with any version of this
* library (and be upwards compatible and immune to any ABI changes) should use
* these routines. Any ABI/Layout changes will be abstracted in the library.
*
* @addtogroup lcb-cmdwrap-api
* @{
*/
#define LCB_CMDWRAP_XMAP(X) \
X(LCB_CALLBACK_GET, lcb_CMDGET, GET) \
X(LCB_CALLBACK_GETREPLICA, lcb_CMDGETREPLICA, GETREPLICA) \
X(LCB_CALLBACK_STORE, lcb_CMDSTORE, STORE) \
X(LCB_CALLBACK_COUNTER, lcb_CMDCOUNTER, COUNTER) \
X(LCB_CALLBACK_STATS, lcb_CMDSTATS, STATS) \
X(LCB_CALLBACK_REMOVE, lcb_CMDREMOVE, REMOVE) \
X(LCB_CALLBACK_OBSERVE, lcb_CMDOBSERVE, OBSERVE) \
X(LCB_CALLBACK_TOUCH, lcb_CMDTOUCH, TOUCH) \
X(LCB_CALLBACK_UNLOCK, lcb_CMDUNLOCK, UNLOCK) \
X(LCB_CALLBACK_ENDURE, lcb_CMDENDURE, ENDURE) \
X(LCB_CALLBACK_FLUSH, lcb_CMDFLUSH, FLUSH) \
X(LCB_CALLBACK_STATS, lcb_CMDSTATS, STATS) \
X(LCB_CALLBACK_VERSIONS, lcb_CMDBASE, VERSIONS) \
X(LCB_CALLBACK_HTTP, lcb_CMDHTTP, HTTP)
/**
* Command constants. These constants identify the type of command being used.
* The constants here go in the form of `LCB_CMDTYPE_xxx` where `xxx` is the
* actual name of the command (e.g. `lcb_CMDxxx`, `LCB_CALLBACK_xxx`). The
* `LCB_CALLBACK_xxx` constants are additionally the same value as their
* command type equivalent.
*/
typedef enum {
#define X(cbtype, cmdtype, name) LCB_CMDTYPE_##name = cbtype,
LCB_CMDWRAP_XMAP(X)
LCB_CMDWRAP_MAX
#undef X
} lcb_CMDTYPE;
/**
* @name Command initialization and destruction.
*
* Commands may be initialized on the stack provided sufficient space is
* allocated is available. The lcb_CmdGetSize() function is available to
* check at runtime whether sufficient space is available for the command.
*
* To initialize a command on the stack, one may do something like:
*
* @code{c}
* union {
* lcb_CMDBASE cmd;
* lcb_CMDGET gcmd;
* char buf[256];
* } ucmd;
*
* if (lcb_CmdGetSize(LCB_CMDTYPE_GET) > sizeof(ucmd)) {
* fprintf(stderr, "Recompile with bigger command size!\n");
* } else {
* lcb_CmdInit(LCB_CMDTYPE_GET, &ucmd.cmd);
* }
* @endcode
*
* Commands may also be allocated on the heap. This will require the command
* to be freed when no longer needed, however.
*
* @code{c}
* lcb_CMDBASE *cmd = lcb_CmdAlloc(LCB_CMDTYPE_GET);
* lcb_CmdSetKey(cmd, "hello", 5);
* lcb_sched_enter(instance);
* lcb_get3(instance, NULL, (const lcb_CMDGET*)cmd);
* lcb_sched_leave(instance);
* lcb_CmdFree(cmd);
* @endcode
*
* Note it is possible to invoke lcb_CmdInit() on an allocated command as well.
*
* @{
*/
/**
* Get the size necessary to initialize a command of a given type
* @param type the type of command
* @return the size of the command required
*/
LIBCOUCHBASE_API size_t
lcb_CmdGetSize(int type);
/**
* Allocate a new command of a given type
* @param type The type of command to allocated
* @return an allocated command
*/
LIBCOUCHBASE_API lcb_CMDBASE *
lcb_CmdAlloc(int type);
/**
* Initialize a command with a given type
* @param type The type of command
* @param cmd The command pointer. Note you do not need to call this if
* lcb_CmdAlloc() was used to create the command. You may also use this
* function once a command has been submitted. In this case, the command
* is cleared of its original contents.
*/
LIBCOUCHBASE_API void
lcb_CmdInit(int type, lcb_CMDBASE *cmd);
/**
* Free a command previously allocated by lcb_cmd_alloc()
* @param cmd The command to free
*/
LIBCOUCHBASE_API void
lcb_CmdFree(lcb_CMDBASE *cmd);
/**@}*/
/**
* @name Setting command properties
* @{
*/
/**
* Set the key for the command
* @param cmd The command. Must be a command which allows a key
* @param key The key buffer
* @param nkey The key length
*/
LIBCOUCHBASE_API void
lcb_CmdSetKey(lcb_CMDBASE *cmd, int type, const void *key, size_t nkey);
/**
* Set the value for the command
* @param cmd The command whose value should be set. Must be a command which
* allows a value
* @param value The value buffer
* @param nvalue The length of the buffer
*/
LIBCOUCHBASE_API void
lcb_CmdSetValue(lcb_CMDBASE *cmd, int type, const void *value, size_t nvalue);
/**
* Set the item's flags. This is valid for storage commands
* @param cmd The command
* @param itmflags The flags to set
*/
LIBCOUCHBASE_API void
lcb_CmdSetItemFlags(lcb_CMDBASE *cmd, int type, lcb_U32 itmflags);
/**
* Set the type of storage operation for a storage command
* @param cmd The command
* @param op the type of operation to perform
*/
LIBCOUCHBASE_API void
lcb_CmdSetStoreOp(lcb_CMDBASE *cmd, int type, lcb_storage_t op);
/**
* Set the CAS value for the command. Must be a command that supports CAS
* @param cmd The command
* @param cas The cas to set
*/
LIBCOUCHBASE_API void
lcb_CmdSetCas(lcb_CMDBASE *cmd, int type, lcb_CAS cas);
/**
* Set the expiration time on the command
* @param cmd The command
* @param exptime The expiration time
*/
LIBCOUCHBASE_API void
lcb_CmdSetExpiry(lcb_CMDBASE *cmd, int type, lcb_U32 exptime);
/**
* Set command-specific flags
* @param cmd The command
* @param flags The command specific flags to assign
*/
LIBCOUCHBASE_API void
lcb_CmdSetCmdFlags(lcb_CMDBASE *cmd, int type, lcb_U32 flags);
/**
* Add command-specific flags. This masks the existing flags previously set
* @param cmd The command
* @param flags The flag to be AND'd
*/
LIBCOUCHBASE_API void
lcb_CmdAddCmdFlags(lcb_CMDBASE *cmd, int type, lcb_U32 flags);
/**
* Set the 'lock' parameter on a get command
* @param cmd The command
* @param enabled whether lock is enabled
*/
LIBCOUCHBASE_API void
lcb_CmdSetLock(lcb_CMDBASE *cmd, int type, int enabled);
/**
* Set the delta value on a counter command
* @param cmd the command
* @param delta the delta
*/
LIBCOUCHBASE_API void
lcb_CmdSetCounterDelta(lcb_CMDBASE *cmd, int type, lcb_S64 delta);
/**
* Set a counter command's initial value
* @param cmd The command
* @param initial the initial value
*/
LIBCOUCHBASE_API void
lcb_CmdSetCounterInitial(lcb_CMDBASE *cmd, int type, lcb_U64 initial);
/**
* Set the create option on a counter command
* @param cmd The command
* @param create whether to create the value if it does not exist
*/
LIBCOUCHBASE_API void
lcb_CmdSetCounterCreate(lcb_CMDBASE *cmd, int type, int create);
/**
* Set the replica index for a get-replica command
* @param cmd The command
* @param ix the index
*/
LIBCOUCHBASE_API void
lcb_CmdSetReplicaIndex(lcb_CMDBASE *cmd, int type, int ix);
/**
* Set the strategy of the get-replica command
* @param cmd The command
* @param strategy the strategy
*/
LIBCOUCHBASE_API void
lcb_CmdSetReplicaStrategy(lcb_CMDBASE *cmd, int type, int strategy);
/**
* Set the HTTP request body on an HTTP command
* @param cmd The comand
* @param body The body buffer
* @param nbody The size of the body buffer
*/
LIBCOUCHBASE_API void
lcb_CmdSetHttpBody(lcb_CMDBASE *cmd, int type, const void *body, size_t nbody);
/**
* Set the path for an HTTP command
* @param cmd The command
* @param path The path buffer
* @param npath The size of the buffer
*/
LIBCOUCHBASE_API void
lcb_CmdSetHttpPath(lcb_CMDBASE *cmd, int type, const void *path, size_t npath);
/**
* Set the content type for the request body for an HTTP command
* @param cmd The command
* @param type The content-type value, as a NUL-terminated string
*/
LIBCOUCHBASE_API void
lcb_CmdSetHttpContentType(lcb_CMDBASE *cmd, int type, const char *content_type);
/**
* Set the request type for an HTTP command
* @param cmd The command
* @param type The request type
*/
LIBCOUCHBASE_API void
lcb_CmdSetHttpRequestMode(lcb_CMDBASE *cmd, int type, lcb_http_type_t req_type);
/**
* Set the HTTP request method type for an HTTP command
* @param cmd The command
* @param method The request method type
*/
LIBCOUCHBASE_API void
lcb_CmdSetHttpRequestMethod(lcb_CMDBASE *cmd, int type, lcb_http_method_t method);
/**
* Set the request host for an HTTP request. RequestMode must be of TYPE_RAW
* @param cmd The command
* @param host The host as a NUL-terminated string. Should also contain the
* @ :port
*/
LIBCOUCHBASE_API void
lcb_CmdSetHttpHost(lcb_CMDBASE *cmd, int type, const char *host);
/**
* Set the username and password for an HTTP command
* @param cmd The command
* @param user The username
* @param pass The password
*/
LIBCOUCHBASE_API void
lcb_CmdSetHttpCredentials(lcb_CMDBASE *cmd, int type,
const char *user, const char *pass);
LIBCOUCHBASE_API void
lcb_CmdSetViewName(lcb_CMDBASE *cmd, int type, const void *name, size_t len);
LIBCOUCHBASE_API void
lcb_CmdSetDesignName(lcb_CMDBASE *cmd, int type, const void *name, size_t len);
LIBCOUCHBASE_API void
lcb_CmdSetViewOptstr(lcb_CMDBASE *cmd, int type, const void *optstr, size_t len);
LIBCOUCHBASE_API void
lcb_CmdSetViewPostdata(lcb_CMDBASE *cmd, int type, const void *data, size_t ndata);
LIBCOUCHBASE_API void
lcb_CmdSetViewCallback(lcb_CMDBASE *cmd, int type, lcb_VIEWQUERYCALLBACK cb);
LIBCOUCHBASE_API void
lcb_CmdSetViewHandlePointer(lcb_CMDBASE *cmd, int type, lcb_VIEWHANDLE *handle);
/**@}*/
/**
* @name Getting response properties
* @{
*/
/**
* Get the request key buffer
* @param res The response
* @param type The type of request (second argument to callback)
* @return The key buffer, or NULL
*/
LIBCOUCHBASE_API const void*
lcb_ResGetKeyBuffer(const lcb_RESPBASE *res, int type);
/**
* Get the length of the key
* @param res the response
* @param type the type of the callback/response
* @return the length of the key buffer
*/
LIBCOUCHBASE_API size_t
lcb_ResGetKeySize(const lcb_RESPBASE *res, int type);
/**
* Get the key in IOV format. This allows retrieval of the buffer and its
* length in a single call
* @param res the response
* @param type the type of the callback/response
* @param[out] iov IOV structure which shall contain the result
*/
LIBCOUCHBASE_API void
lcb_ResGetKeyIOV(const lcb_RESPBASE *res, int type, lcb_IOV *iov);
/**
* Get the value buffer
* @param res the response
* @param type the type of response
* @return the key buffer
*/
LIBCOUCHBASE_API const void*
lcb_ResGetValueBuffer(const lcb_RESPBASE *res, int type);
/**
* Get the value size
* @param res the response
* @param type the type of response
* @return the length of the key buffer
*/
LIBCOUCHBASE_API size_t
lcb_ResGetValueSize(const lcb_RESPBASE *res, int type);
/**
* Get the value of the response in IOV format
* @param res the response
* @param type the response type
* @param[out] iov the IOV structure to contain the buffer/length information
*/
LIBCOUCHBASE_API void
lcb_ResGetValueIOV(const lcb_RESPBASE *res, int type, lcb_IOV *iov);
/**
* Get the CAS of the response
* @param res the response
* @param type the type of response
* @return the CAS
*/
LIBCOUCHBASE_API lcb_CAS
lcb_ResGetCas(const lcb_RESPBASE *res, int type);
/**
* Get the format/item flags for an item. Typically only valid on
* @ref LCB_CALLBACK_GET operations.
* @param res the response
* @param type the type of response
* @return the flags
*/
LIBCOUCHBASE_API lcb_U32
lcb_ResGetItemFlags(const lcb_RESPBASE *res, int type);
/**
* Get the error code for the operation. This can be done on any type of
* response
* @param res the response
* @param type the type of response
* @return the error code
*/
LIBCOUCHBASE_API lcb_error_t
lcb_ResGetError(const lcb_RESPBASE *res, int type);
/**
* Get the opaque user data pointer set with the scheduling function.
* @param res the response
* @param type the type of response
* @return the opaque user pointer
*/
LIBCOUCHBASE_API void *
lcb_ResGetCookie(const lcb_RESPBASE *res, int type);
/**
* Get the string identifying the server which returned this response.
*
* Valid only for responses which contain a server string as part of their
* payload (e.g. @ref LCB_CALLBACK_STATS)
*
* @param res the response
* @param type the response type
* @return the server string (NULL-terminated)
*/
LIBCOUCHBASE_API const char *
lcb_ResGetServer(const lcb_RESPBASE *res, int type);
/**
* Get the response flags. This is the lcb_RESPBASE::rflags field
* @param res the response
* @param type the response type
* @return the flags for the response
*/
LIBCOUCHBASE_API lcb_U32
lcb_ResGetResFlags(const lcb_RESPBASE *res, int type);
/**
* Get the current counter value (lcb_RESPCOUNTER::value)
* @param res the response
* @param type the response type
* @return the current counter value
*/
LIBCOUCHBASE_API lcb_U64
lcb_ResGetCounterValue(const lcb_RESPBASE *res, int type);
/**
* Get the status for a given OBSERVE response (lcb_RESPOBSERVE::status)
* @param res the response
* @param type the type of response
* @return the status for the key wrt persistence/replication
*/
LIBCOUCHBASE_API lcb_U8
lcb_ResGetObserveStatus(const lcb_RESPBASE *res, int type);
/**
* Determine if the current OBSERVE response is from the master node
* @param res the response
* @param type the type of the response
* @return nonzero if from master
*/
LIBCOUCHBASE_API lcb_U8
lcb_ResGetObserveIsMaster(const lcb_RESPBASE *res, int type);
/**
* Get the number of nodes the item was persisted to. Only valid on
* @ref LCB_CALLBACK_ENDURE. This returns the lcb_RESPENDURE::npersisted field
* @param res the response
* @param type the type of the response
* @return the number of nodes the current item was persisted to
*/
LIBCOUCHBASE_API lcb_U8
lcb_ResGetEnduredPersisted(const lcb_RESPBASE *res, int type);
/**
* Get the number of nodes the item was replicated to. Only valid on
* @ref LCB_CALLBACK_ENDURE.
* @param res the response
* @param type the type of the response
* @return the number of nodes the current item was replicated to.
* @see lcb_RESPENDURE::nreplicated
*/
LIBCOUCHBASE_API lcb_U8
lcb_ResGetEnduredReplicated(const lcb_RESPBASE *res, int type);
/**
* Determine whether the mutation was persisted to the master node
* @param res the response
* @param type the response type
* @return nonzero if persisted on master
* @see lcb_RESPENDURE::persisted_master
*/
LIBCOUCHBASE_API int
lcb_ResGetEnduredPersistedMaster(const lcb_RESPBASE *res, int type);
/**
* Get a list of HTTP headers. Only valid on @ref LCB_CALLBACK_HTTP.
* @param res the response
* @param type the callback type
* @return a list of headers
* @see lcb_RESPHTTP::headers
*/
LIBCOUCHBASE_API const char * const *
lcb_ResGetHttpHeaders(const lcb_RESPBASE *res, int type);
/**
* Get the actual HTTP status code for the operation. Only valid on @ref
* LCB_CALLBACK_HTTP and @ref lcb_RESPHTTP
*
* @param res the response
* @param type the response type
* @return the HTTP status code
* @see lcb_RESPHTTP::htstatus
*/
LIBCOUCHBASE_API short
lcb_ResGetHttpCode(const lcb_RESPBASE *res, int type);
LIBCOUCHBASE_API const char *
lcb_ResGetViewRowIdBuffer(const lcb_RESPVIEWQUERY *res, int type);
LIBCOUCHBASE_API size_t
lcb_ResGetViewRowIdSize(const lcb_RESPVIEWQUERY *res, int type);
LIBCOUCHBASE_API const char *
lcb_ResGetViewRowValueBuffer(const lcb_RESPVIEWQUERY *res, int type);
LIBCOUCHBASE_API size_t
lcb_ResGetViewRowValueSize(const lcb_RESPVIEWQUERY *res, int type);
LIBCOUCHBASE_API const char *
lcb_ResGetViewRowGeoBuffer(const lcb_RESPVIEWQUERY *res, int type);
LIBCOUCHBASE_API size_t
lcb_ResGetViewRowGeoSize(const lcb_RESPVIEWQUERY *res, int type);
LIBCOUCHBASE_API const lcb_RESPHTTP *
lcb_ResGetHttpResponse(const lcb_RESPBASE *res, int cbtype);
LIBCOUCHBASE_API const lcb_RESPGET *
lcb_ResGetViewDocresp(const lcb_RESPVIEWQUERY *res, int cbtype);
/**@}*/
/**
* @name
* Multi command handling routines
* @{
*/
LIBCOUCHBASE_API lcb_error_t
lcb_CmdMultiAdd(lcb_MULTICMD_CTX *mctx, const lcb_CMDBASE *cmd);
LIBCOUCHBASE_API lcb_error_t
lcb_CmdMultiDone(lcb_MULTICMD_CTX *mctx);
LIBCOUCHBASE_API void
lcb_CmdMultiFail(lcb_MULTICMD_CTX* mctx);
/**@}*/
/**@}*/
#ifdef __cplusplus
}
#endif
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment