diff options
author | Seppo Jaakola <seppo.jaakola@codership.com> | 2013-11-26 16:48:30 +0200 |
---|---|---|
committer | Seppo Jaakola <seppo.jaakola@codership.com> | 2013-11-26 16:48:30 +0200 |
commit | a2594e96f7c7fe762a8165916551ae96bcbb869f (patch) | |
tree | fa1e4eb2a6d6ef1ca8a039a2afe48a65bca6ab33 /wsrep | |
parent | 2b4183f10b54a5b3f8c848d897b3107859c23fa4 (diff) | |
download | mariadb-git-a2594e96f7c7fe762a8165916551ae96bcbb869f.tar.gz |
Merges from lp:codership-mysql/5.5 up to rev #3893, this changes to wsrep API #24
Diffstat (limited to 'wsrep')
-rw-r--r-- | wsrep/wsrep_api.h | 703 | ||||
-rw-r--r-- | wsrep/wsrep_dummy.c | 107 | ||||
-rw-r--r-- | wsrep/wsrep_loader.c | 8 | ||||
-rw-r--r-- | wsrep/wsrep_uuid.c | 27 |
4 files changed, 552 insertions, 293 deletions
diff --git a/wsrep/wsrep_api.h b/wsrep/wsrep_api.h index 2cd10afc7ff..987a47db578 100644 --- a/wsrep/wsrep_api.h +++ b/wsrep/wsrep_api.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2011 Codership Oy <info@codership.com> +/* Copyright (C) 2009-2013 Codership Oy <info@codership.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -9,11 +9,41 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +/*! + @file wsrep API declaration. + + HOW TO READ THIS FILE. + + Due to C language rules this header layout doesn't lend itself to intuitive + reading. So here's the scoop: in the end this header declares two main types: + + * struct wsrep_init_args + + and + + * struct wsrep + + wsrep_init_args contains initialization parameters for wsrep provider like + names, addresses, etc. and pointers to callbacks. The callbacks will be called + by provider when it needs to do something application-specific, like log a + message or apply a writeset. It should be passed to init() call from + wsrep API. It is an application part of wsrep API contract. + + struct wsrep is the interface to wsrep provider. It contains all wsrep API + calls. It is a provider part of wsrep API contract. + + Finally, wsrep_load() method loads (dlopens) wsrep provider library. It is + defined in wsrep_loader.c unit and is part of libwsrep.a (which is not a + wsrep provider, but a convenience library). + + wsrep_unload() does the reverse. + +*/ #ifndef WSREP_H #define WSREP_H @@ -27,14 +57,44 @@ extern "C" { #endif +/************************************************************************** + * * + * wsrep replication API * + * * + **************************************************************************/ + +#define WSREP_INTERFACE_VERSION "24" + +/*! Empty backend spec */ +#define WSREP_NONE "none" + + /*! - * wsrep replication API + * @brief log severity levels, passed as first argument to log handler */ +typedef enum wsrep_log_level +{ + WSREP_LOG_FATAL, //!< Unrecoverable error, application must quit. + WSREP_LOG_ERROR, //!< Operation failed, must be repeated. + WSREP_LOG_WARN, //!< Unexpected condition, but no operational failure. + WSREP_LOG_INFO, //!< Informational message. + WSREP_LOG_DEBUG //!< Debug message. Shows only of compiled with debug. +} wsrep_log_level_t; + +/*! + * @brief error log handler + * + * All messages from wsrep provider are directed to this + * handler, if present. + * + * @param level log level + * @param message log message + */ +typedef void (*wsrep_log_cb_t)(wsrep_log_level_t, const char *); -#define WSREP_INTERFACE_VERSION "23" /*! - * Certain provider capabilities application may need to know + * Certain provider capabilities application may want to know about */ #define WSREP_CAP_MULTI_MASTER ( 1ULL << 0 ) #define WSREP_CAP_CERTIFICATION ( 1ULL << 1 ) @@ -44,89 +104,148 @@ extern "C" { #define WSREP_CAP_PAUSE ( 1ULL << 5 ) #define WSREP_CAP_CAUSAL_READS ( 1ULL << 6 ) #define WSREP_CAP_CAUSAL_TRX ( 1ULL << 7 ) -#define WSREP_CAP_WRITE_SET_INCREMENTS ( 1ULL << 8 ) +#define WSREP_CAP_INCREMENTAL_WRITESET ( 1ULL << 8 ) #define WSREP_CAP_SESSION_LOCKS ( 1ULL << 9 ) #define WSREP_CAP_DISTRIBUTED_LOCKS ( 1ULL << 10 ) #define WSREP_CAP_CONSISTENCY_CHECK ( 1ULL << 11 ) +#define WSREP_CAP_UNORDERED ( 1ULL << 12 ) +#define WSREP_CAP_ANNOTATION ( 1ULL << 13 ) +#define WSREP_CAP_PREORDERED ( 1ULL << 14 ) + /*! - * Write set replication flags + * Writeset flags + * + * COMMIT the writeset and all preceding writesets must be committed + * ROLLBACK all preceding writesets in a transaction must be rolled back + * PA_UNSAFE the writeset cannot be applied in parallel + * ISOLATION the writeset must be applied AND committed in isolation + * COMMUTATIVE the order in which the writeset is applied does not matter + * NATIVE the writeset contains another writeset in this provider format + * + * Note that some of the flags are mutually exclusive (e.g. COMMIT and + * ROLLBACK). */ -#define WSREP_FLAG_PA_SAFE ( 1ULL << 0 ) +#define WSREP_FLAG_COMMIT ( 1ULL << 0 ) +#define WSREP_FLAG_ROLLBACK ( 1ULL << 1 ) +#define WSREP_FLAG_PA_UNSAFE ( 1ULL << 3 ) +#define WSREP_FLAG_ISOLATION ( 1ULL << 2 ) +#define WSREP_FLAG_COMMUTATIVE ( 1ULL << 4 ) +#define WSREP_FLAG_NATIVE ( 1ULL << 5 ) -/* Empty backend spec */ -#define WSREP_NONE "none" typedef uint64_t wsrep_trx_id_t; //!< application transaction ID typedef uint64_t wsrep_conn_id_t; //!< application connection ID typedef int64_t wsrep_seqno_t; //!< sequence number of a writeset, etc. +typedef _Bool wsrep_bool_t; //!< should be the same as standard (C99) bool /*! undefined seqno */ #define WSREP_SEQNO_UNDEFINED (-1) -/*! wsrep status codes */ -typedef enum wsrep_status { - WSREP_OK = 0, //!< success + +/*! wsrep provider status codes */ +typedef enum wsrep_status +{ + WSREP_OK = 0, //!< success WSREP_WARNING, //!< minor warning, error logged WSREP_TRX_MISSING, //!< transaction is not known by wsrep WSREP_TRX_FAIL, //!< transaction aborted, server can continue WSREP_BF_ABORT, //!< trx was victim of brute force abort + WSREP_SIZE_EXCEEDED, //!< data exceeded maximum supported size WSREP_CONN_FAIL, //!< error in client connection, must abort WSREP_NODE_FAIL, //!< error in node state, wsrep must reinit WSREP_FATAL, //!< fatal error, server must abort WSREP_NOT_IMPLEMENTED //!< feature not implemented } wsrep_status_t; -/*! - * @brief log severity levels, passed as first argument to log handler - */ -typedef enum wsrep_log_level + +/*! wsrep callbacks status codes */ +typedef enum wsrep_cb_status { - WSREP_LOG_FATAL, //!< Unrecoverable error, application must quit. - WSREP_LOG_ERROR, //!< Operation failed, must be repeated. - WSREP_LOG_WARN, //!< Unexpected condition, but no operational failure. - WSREP_LOG_INFO, //!< Informational message. - WSREP_LOG_DEBUG //!< Debug message. Shows only of compiled with debug. -} wsrep_log_level_t; + WSREP_CB_SUCCESS = 0, //!< success (as in "not critical failure") + WSREP_CB_FAILURE //!< critical failure (consistency violation) + /* Technically, wsrep provider has no use for specific failure codes since + * there is nothing it can do about it but abort execution. Therefore any + * positive number shall indicate a critical failure. Optionally that value + * may be used by provider to come to a consensus about state consistency + * in a group of nodes. */ +} wsrep_cb_status_t; -/*! - * @brief error log handler - * - * All messages from wsrep library are directed to this - * handler, if present. - * - * @param level log level - * @param message log message - */ -typedef void (*wsrep_log_cb_t)(wsrep_log_level_t, const char *); /*! * UUID type - for all unique IDs */ typedef struct wsrep_uuid { - uint8_t uuid[16]; + uint8_t data[16]; } wsrep_uuid_t; /*! Undefined UUID */ static const wsrep_uuid_t WSREP_UUID_UNDEFINED = {{0,}}; +/*! UUID string representation length, terminating '\0' not included */ +#define WSREP_UUID_STR_LEN 36 + /*! * Scan UUID from string * @return length of UUID string representation or negative error code */ -extern ssize_t +extern int wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid); /*! * Print UUID to string * @return length of UUID string representation or negative error code */ -extern ssize_t +extern int wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len); #define WSREP_MEMBER_NAME_LEN 32 //!< maximum logical member name length #define WSREP_INCOMING_LEN 256 //!< max Domain Name length + 0x00 + +/*! + * Global transaction identifier + */ +typedef struct wsrep_gtid +{ + wsrep_uuid_t uuid; /*!< History UUID */ + wsrep_seqno_t seqno; /*!< Sequence number */ +} wsrep_gtid_t; + +/*! Undefined GTID */ +static const wsrep_gtid_t WSREP_GTID_UNDEFINED = {{{0, }}, -1}; + +/*! Minimum number of bytes guaranteed to store GTID string representation, + * terminating '\0' not included (36 + 1 + 20) */ +#define WSREP_GTID_STR_LEN 57 + + +/*! + * Scan GTID from string + * @return length of GTID string representation or negative error code + */ +extern int +wsrep_gtid_scan(const char* str, size_t str_len, wsrep_gtid_t* gtid); + +/*! + * Print GTID to string + * @return length of GTID string representation or negative error code + */ +extern int +wsrep_gtid_print(const wsrep_gtid_t* gtid, char* str, size_t str_len); + + +/*! + * Transaction meta data + */ +typedef struct wsrep_trx_meta +{ + wsrep_gtid_t gtid; /*!< Global transaction identifier */ + wsrep_seqno_t depends_on; /*!< Sequence number part of the last transaction + this transaction depends on */ +} wsrep_trx_meta_t; + + /*! * member status */ @@ -163,15 +282,14 @@ typedef enum wsrep_view_status { * view of the group */ typedef struct wsrep_view_info { - wsrep_uuid_t uuid; //!< global state UUID - wsrep_seqno_t seqno; //!< global state seqno + wsrep_gtid_t state_id; //!< global state ID wsrep_seqno_t view; //!< global view number wsrep_view_status_t status; //!< view status - bool state_gap; //!< gap between global and local states + wsrep_bool_t state_gap; //!< gap between global and local states int my_idx; //!< index of this member in the view int memb_num; //!< number of members in the view - int proto_ver; //!< application protocol agreed on in the view - wsrep_member_info_t members[1]; //!< array of member information + int proto_ver; //!< application protocol agreed on the view + wsrep_member_info_t members[1];//!< array of member information } wsrep_view_info_t; /*! @@ -208,37 +326,43 @@ typedef struct wsrep_view_info { * @param state current state * @param state_len lenght of current state * @param sst_req location to store SST request - * @param sst_req_len location to store SST request length or error code + * @param sst_req_len location to store SST request length or error code, * value of 0 means no SST. */ -typedef void (*wsrep_view_cb_t) (void* app_ctx, - void* recv_ctx, - const wsrep_view_info_t* view, - const char* state, - size_t state_len, - void** sst_req, - ssize_t* sst_req_len); +typedef enum wsrep_cb_status (*wsrep_view_cb_t) ( + void* app_ctx, + void* recv_ctx, + const wsrep_view_info_t* view, + const char* state, + size_t state_len, + void** sst_req, + size_t* sst_req_len +); + /*! * @brief apply callback * - * This handler is called from wsrep library to apply replicated write set + * This handler is called from wsrep library to apply replicated writeset * Must support brute force applying for multi-master operation * * @param recv_ctx receiver context pointer provided by the application - * @param data data buffer containing the write set + * @param data data buffer containing the writeset * @param size data buffer size - * @param seqno global seqno part of the write set to be applied + * @param meta transaction meta data of the writeset to be applied * * @return success code: * @retval WSREP_OK - * @retval WSREP_NOT_IMPLEMENTED appl. does not support the write set format - * @retval WSREP_ERROR failed to apply the write set + * @retval WSREP_NOT_IMPLEMENTED appl. does not support the writeset format + * @retval WSREP_ERROR failed to apply the writeset */ -typedef enum wsrep_status (*wsrep_apply_cb_t) (void* recv_ctx, - const void* data, - size_t size, - wsrep_seqno_t seqno); +typedef enum wsrep_cb_status (*wsrep_apply_cb_t) ( + void* recv_ctx, + const void* data, + size_t size, + const wsrep_trx_meta_t* meta +); + /*! * @brief commit callback @@ -246,16 +370,38 @@ typedef enum wsrep_status (*wsrep_apply_cb_t) (void* recv_ctx, * This handler is called to commit the changes made by apply callback. * * @param recv_ctx receiver context pointer provided by the application - * @param seqno global seqno part of the write set to be committed + * @param meta transaction meta data of the writeset to be committed + * @param exit set to true to exit recv loop * @param commit true - commit writeset, false - rollback writeset * * @return success code: * @retval WSREP_OK * @retval WSREP_ERROR call failed */ -typedef enum wsrep_status (*wsrep_commit_cb_t) (void* recv_ctx, - wsrep_seqno_t seqno, - bool commit); +typedef enum wsrep_cb_status (*wsrep_commit_cb_t) ( + void* recv_ctx, + const wsrep_trx_meta_t* meta, + wsrep_bool_t* exit, + wsrep_bool_t commit +); + + +/*! + * @brief unordered callback + * + * This handler is called to execute unordered actions (actions that need not + * to be executed in any particular order) attached to writeset. + * + * @param recv_ctx receiver context pointer provided by the application + * @param data data buffer containing the writeset + * @param size data buffer size + */ +typedef enum wsrep_cb_status (*wsrep_unordered_cb_t) ( + void* recv_ctx, + const void* data, + size_t size +); + /*! * @brief a callback to donate state snapshot @@ -270,22 +416,22 @@ typedef enum wsrep_status (*wsrep_commit_cb_t) (void* recv_ctx, * @param recv_ctx receiver context * @param msg state transfer request message * @param msg_len state transfer request message length - * @param uuid current state uuid on this node - * @param seqno current state seqno on this node + * @param gtid current state ID on this node * @param state current wsrep internal state buffer * @param state_len current wsrep internal state buffer len * @param bypass bypass snapshot transfer, only transfer uuid:seqno pair - * @return 0 for success or negative error code */ -typedef int (*wsrep_sst_donate_cb_t) (void* app_ctx, - void* recv_ctx, - const void* msg, - size_t msg_len, - const wsrep_uuid_t* uuid, - wsrep_seqno_t seqno, - const char* state, - size_t state_len, - bool bypass); +typedef enum wsrep_cb_status (*wsrep_sst_donate_cb_t) ( + void* app_ctx, + void* recv_ctx, + const void* msg, + size_t msg_len, + const wsrep_gtid_t* state_id, + const char* state, + size_t state_len, + wsrep_bool_t bypass +); + /*! * @brief a callback to signal application that wsrep state is synced @@ -296,11 +442,11 @@ typedef int (*wsrep_sst_donate_cb_t) (void* app_ctx, * * @param app_ctx application context */ -typedef void (*wsrep_synced_cb_t)(void* app_ctx); +typedef void (*wsrep_synced_cb_t) (void* app_ctx); /*! - * Initialization parameters for wsrep, used as arguments for wsrep_init() + * Initialization parameters for wsrep provider. */ struct wsrep_init_args { @@ -315,24 +461,25 @@ struct wsrep_init_args int proto_ver; //!< Max supported application protocol version /* Application initial state information. */ - const wsrep_uuid_t* state_uuid; //!< Application state sequence UUID - wsrep_seqno_t state_seqno; //!< Applicaiton state sequence number - const char* state; //!< Initial state for wsrep implementation + const wsrep_gtid_t* state_id; //!< Application state GTID + const char* state; //!< Initial state for wsrep provider size_t state_len; //!< Length of state buffer /* Application callbacks */ wsrep_log_cb_t logger_cb; //!< logging handler wsrep_view_cb_t view_handler_cb; //!< group view change handler - /* applier callbacks */ + /* Applier callbacks */ wsrep_apply_cb_t apply_cb; //!< apply callback wsrep_commit_cb_t commit_cb; //!< commit callback + wsrep_unordered_cb_t unordered_cb; //!< callback for unordered actions - /* state snapshot transfer callbacks */ + /* State Snapshot Transfer callbacks */ wsrep_sst_donate_cb_t sst_donate_cb; //!< starting to donate wsrep_synced_cb_t synced_cb; //!< synced with group }; + /*! Type of the stats variable value in struct wsrep_status_var */ typedef enum wsrep_var_type { @@ -355,60 +502,94 @@ struct wsrep_stats_var }; -/*! Key part structure */ -typedef struct wsrep_key_part_ +/*! Abstract data buffer structure */ +typedef struct wsrep_buf { - const void* buf; /*!< Buffer containing key part data */ - size_t buf_len; /*!< Length of buffer */ -} wsrep_key_part_t; + const void* ptr; /*!< Pointer to data buffer */ + size_t len; /*!< Length of buffer */ +} wsrep_buf_t; /*! Key struct used to pass certification keys for transaction handling calls. * A key consists of zero or more key parts. */ -typedef struct wsrep_key_ +typedef struct wsrep_key { - const wsrep_key_part_t* key_parts; /*!< Array of key parts */ - size_t key_parts_len; /*!< Length of key parts array */ + const wsrep_buf_t* key_parts; /*!< Array of key parts */ + size_t key_parts_num; /*!< Number of key parts */ } wsrep_key_t; +/*! Key type: + * EXCLUSIVE conflicts with any key type + * SEMI reserved. If not supported, should be interpeted as EXCLUSIVE + * SHARED conflicts only with EXCLUSIVE keys */ +typedef enum wsrep_key_type +{ + WSREP_KEY_SHARED = 0, + WSREP_KEY_SEMI, + WSREP_KEY_EXCLUSIVE +} wsrep_key_type_t; + +/*! Data type: + * ORDERED state modification event that should be applied and committed + * in order. + * UNORDERED some action that does not modify state and execution of which is + * optional and does not need to happen in order. + * ANNOTATION (human readable) writeset annotation. */ +typedef enum wsrep_data_type +{ + WSREP_DATA_ORDERED = 0, + WSREP_DATA_UNORDERED, + WSREP_DATA_ANNOTATION +} wsrep_data_type_t; + + /*! Transaction handle struct passed for wsrep transaction handling calls */ -typedef struct wsrep_trx_handle_ +typedef struct wsrep_ws_handle { wsrep_trx_id_t trx_id; //!< transaction ID void* opaque; //!< opaque provider transaction context data -} wsrep_trx_handle_t; +} wsrep_ws_handle_t; /*! - * @brief Helper method to reset trx handle state when trx id changes + * @brief Helper method to reset trx writeset handle state when trx id changes * - * Instead of passing wsrep_trx_handle_t directly for wsrep calls, + * Instead of passing wsrep_ws_handle_t directly to wsrep calls, * wrapping handle with this call offloads bookkeeping from * application. */ -static inline wsrep_trx_handle_t* wsrep_trx_handle_for_id( - wsrep_trx_handle_t* trx_handle, - wsrep_trx_id_t trx_id) +static inline wsrep_ws_handle_t* wsrep_ws_handle_for_trx( + wsrep_ws_handle_t* ws_handle, + wsrep_trx_id_t trx_id) { - if (trx_handle->trx_id != trx_id) + if (ws_handle->trx_id != trx_id) { - trx_handle->trx_id = trx_id; - trx_handle->opaque = NULL; + ws_handle->trx_id = trx_id; + ws_handle->opaque = NULL; } - return trx_handle; + return ws_handle; } -typedef struct wsrep_ wsrep_t; +/*! + * A handle for processing preordered actions. + * Must be initialized to WSREP_PO_INITIALIZER before use. + */ +typedef struct wsrep_po_handle { void* opaque; } wsrep_po_handle_t; + +static const wsrep_po_handle_t WSREP_PO_INITIALIZER = { NULL }; + + +typedef struct wsrep wsrep_t; /*! * wsrep interface for dynamically loadable libraries */ -struct wsrep_ { +struct wsrep { const char *version; //!< interface version string /*! * @brief Initializes wsrep provider * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @param args wsrep initialization parameters */ wsrep_status_t (*init) (wsrep_t* wsrep, @@ -417,14 +598,14 @@ struct wsrep_ { /*! * @brief Returns provider capabilities flag bitmap * - * @param wsrep this wsrep handle + * @param wsrep provider handle */ uint64_t (*capabilities) (wsrep_t* wsrep); /*! * @brief Passes provider-specific configuration string to provider. * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @param conf configuration string * * @retval WSREP_OK configuration string was parsed successfully @@ -435,7 +616,7 @@ struct wsrep_ { /*! * @brief Returns provider-specific string with current configuration values. * - * @param wsrep this wsrep handle + * @param wsrep provider handle * * @return a dynamically allocated string with current configuration * parameter values @@ -448,15 +629,20 @@ struct wsrep_ { * Returns when either node is ready to operate as a part of the clsuter * or fails to reach operating status. * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @param cluster_name unique symbolic cluster name * @param cluster_url URL-like cluster address (backend://address) * @param state_donor name of the node to be asked for state transfer. + * @param bootstrap a flag to request initialization of a new wsrep + * service rather then a connection to the existing one. + * clister_url may still carry important initialization + * parameters, like backend spec and/or listen address. */ - wsrep_status_t (*connect) (wsrep_t* wsrep, - const char* cluster_name, - const char* cluster_url, - const char* state_donor); + wsrep_status_t (*connect) (wsrep_t* wsrep, + const char* cluster_name, + const char* cluster_url, + const char* state_donor, + wsrep_bool_t bootstrap); /*! * @brief Closes connection to cluster. @@ -473,7 +659,7 @@ struct wsrep_ { * * This function never returns * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @param recv_ctx receiver context */ wsrep_status_t (*recv)(wsrep_t* wsrep, void* recv_ctx); @@ -487,59 +673,55 @@ struct wsrep_ { * In case of WSREP_OK, starts commit critical section, transaction can * commit. Otherwise transaction must rollback. * - * @param wsrep this wsrep handle - * @param trx_handle transaction which is committing + * @param wsrep provider handle + * @param ws_handle writeset of committing transaction * @param conn_id connection ID - * @param app_data application specific applying data - * @param data_len the size of the applying data * @param flags fine tuning the replication WSREP_FLAG_* - * @param seqno seqno part of the global transaction ID + * @param meta transaction meta data * * @retval WSREP_OK cluster-wide commit succeeded * @retval WSREP_TRX_FAIL must rollback transaction * @retval WSREP_CONN_FAIL must close client connection * @retval WSREP_NODE_FAIL must close all connections and reinit */ - wsrep_status_t (*pre_commit)(wsrep_t* wsrep, - wsrep_conn_id_t conn_id, - wsrep_trx_handle_t* trx_handle, - const void* app_data, - size_t data_len, - uint64_t flags, - wsrep_seqno_t* seqno); + wsrep_status_t (*pre_commit)(wsrep_t* wsrep, + wsrep_conn_id_t conn_id, + wsrep_ws_handle_t* ws_handle, + uint64_t flags, + wsrep_trx_meta_t* meta); /*! * @brief Releases resources after transaction commit. * * Ends commit critical section. * - * @param wsrep this wsrep handle - * @param trx_handle transaction which is committing + * @param wsrep provider handle + * @param ws_handle writeset of committing transaction * @retval WSREP_OK post_commit succeeded */ wsrep_status_t (*post_commit) (wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle); + wsrep_ws_handle_t* ws_handle); /*! * @brief Releases resources after transaction rollback. * - * @param wsrep this wsrep handle - * @param trx_handle transaction which is committing + * @param wsrep provider handle + * @param ws_handle writeset of committing transaction * @retval WSREP_OK post_rollback succeeded */ wsrep_status_t (*post_rollback)(wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle); + wsrep_ws_handle_t* ws_handle); /*! - * @brief Replay trx as a slave write set + * @brief Replay trx as a slave writeset * * If local trx has been aborted by brute force, and it has already * replicated before this abort, we must try if we can apply it as - * slave trx. Note that slave nodes see only trx write sets and certification + * slave trx. Note that slave nodes see only trx writesets and certification * test based on write set content can be different to DBMS lock conflicts. * - * @param wsrep this wsrep handle - * @param trx_handle transaction which is committing + * @param wsrep provider handle + * @param ws_handle writeset of committing transaction * @param trx_ctx transaction context * * @retval WSREP_OK cluster commit succeeded @@ -550,7 +732,7 @@ struct wsrep_ { * @retval WSREP_NODE_FAIL must close all connections and reinit */ wsrep_status_t (*replay_trx)(wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle, + wsrep_ws_handle_t* ws_handle, void* trx_ctx); /*! @@ -562,76 +744,72 @@ struct wsrep_ { * The kill routine checks that abort is not attmpted against a transaction * which is front of the caller (in total order). * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @param bf_seqno seqno of brute force trx, running this cancel * @param victim_trx transaction to be aborted, and which is committing * - * @retval WSREP_OK abort secceded - * @retval WSREP_WARNING abort failed + * @retval WSREP_OK abort secceded + * @retval WSREP_WARNING abort failed */ wsrep_status_t (*abort_pre_commit)(wsrep_t* wsrep, wsrep_seqno_t bf_seqno, wsrep_trx_id_t victim_trx); /*! - * @brief Appends a query in transaction's write set + * @brief Appends a row reference to transaction writeset + * + * Both copy flag and key_type can be ignored by provider (key type + * interpreted as WSREP_KEY_EXCLUSIVE). * - * @param wsrep this wsrep handle - * @param trx_handle transaction handle - * @param query SQL statement string - * @param timeval time to use for time functions - * @param randseed seed for rand + * @param wsrep provider handle + * @param ws_handle writeset handle + * @param keys array of keys + * @param count length of the array of keys + * @param type type ot the key + * @param copy can be set to FALSE if keys persist through commit. */ - wsrep_status_t (*append_query)(wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle, - const char* query, - time_t timeval, - uint32_t randseed); + wsrep_status_t (*append_key)(wsrep_t* wsrep, + wsrep_ws_handle_t* ws_handle, + const wsrep_key_t* keys, + size_t count, + enum wsrep_key_type type, + wsrep_bool_t copy); /*! - * @brief Appends a row reference in transaction's write set + * @brief Appends data to transaction writeset + * + * This method can be called any time before commit and it + * appends a number of data buffers to transaction writeset. * - * @param wsrep this wsrep handle - * @param trx_handle transaction handle - * @param key array of keys - * @param key_len length of the array of keys - * @param shared boolean denoting if key corresponds to shared resource + * Both copy and unordered flags can be ignored by provider. + * + * @param wsrep provider handle + * @param ws_handle writeset handle + * @param data array of data buffers + * @param count buffer count + * @param type type of data + * @param copy can be set to FALSE if data persists through commit. */ - wsrep_status_t (*append_key)(wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle, - const wsrep_key_t* key, - size_t key_len, - bool shared); - /*! - * @brief Appends data in transaction's write set - * - * This method can be called any time before commit and it - * appends data block into transaction's write set. - * - * @param wsrep this wsrep handle - * @param trx_handle transaction handle - * @param data data buffer - * @param data_len data buffer length - */ - wsrep_status_t (*append_data)(wsrep_t* wsrep, - wsrep_trx_handle_t* trx_handle, - const void* data, - size_t data_len); - + wsrep_status_t (*append_data)(wsrep_t* wsrep, + wsrep_ws_handle_t* ws_handle, + const struct wsrep_buf* data, + size_t count, + enum wsrep_data_type type, + wsrep_bool_t copy); /*! * @brief Get causal ordering for read operation * * This call will block until causal ordering with all possible * preceding writes in the cluster is guaranteed. If pointer to - * seqno is non-null, the call stores the global transaction ID + * gtid is non-null, the call stores the global transaction ID * of the last transaction which is guaranteed to be ordered * causally before this call. * - * @param wsrep this wsrep handle - * @param seqno location to store global transaction ID + * @param wsrep provider handle + * @param gtid location to store GTID */ - wsrep_status_t (*causal_read)(wsrep_t* wsrep, wsrep_seqno_t* seqno); + wsrep_status_t (*causal_read)(wsrep_t* wsrep, wsrep_gtid_t* gtid); /*! * @brief Clears allocated connection context. @@ -641,7 +819,7 @@ struct wsrep_ { * connection. This call is to explicitly notify provider fo connection * closing. * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @param conn_id connection ID * @param query the 'set database' query * @param query_len length of query (does not end with 0) @@ -652,29 +830,28 @@ struct wsrep_ { /*! * @brief Replicates a query and starts "total order isolation" section. * - * Replicates the query and returns success code, which - * caller must check. Total order isolation continues - * until to_execute_end() is called. + * Replicates the action spec and returns success code, which caller must + * check. Total order isolation continues until to_execute_end() is called. * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @param conn_id connection ID - * @param key array of keys - * @param key_len lenght of the array of keys - * @param query query to be executed - * @param query_len length of the query string - * @param seqno seqno part of the action ID + * @param keys array of keys + * @param keys_num lenght of the array of keys + * @param action action buffer array to be executed + * @param count action buffer count + * @param meta transaction meta data * * @retval WSREP_OK cluster commit succeeded * @retval WSREP_CONN_FAIL must close client connection * @retval WSREP_NODE_FAIL must close all connections and reinit */ - wsrep_status_t (*to_execute_start)(wsrep_t* wsrep, - wsrep_conn_id_t conn_id, - const wsrep_key_t* key, - size_t key_len, - const void* query, - size_t query_len, - wsrep_seqno_t* seqno); + wsrep_status_t (*to_execute_start)(wsrep_t* wsrep, + wsrep_conn_id_t conn_id, + const wsrep_key_t* keys, + size_t keys_num, + const struct wsrep_buf* action, + size_t count, + wsrep_trx_meta_t* meta); /*! * @brief Ends the total order isolation section. @@ -682,7 +859,7 @@ struct wsrep_ { * Marks the end of total order isolation. TO locks are freed * and other transactions are free to commit from this point on. * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @param conn_id connection ID * * @retval WSREP_OK cluster commit succeeded @@ -692,32 +869,81 @@ struct wsrep_ { wsrep_status_t (*to_execute_end)(wsrep_t* wsrep, wsrep_conn_id_t conn_id); /*! + * @brief Collects preordered replication events into a writeset. + * + * @param wsrep wsrep provider handle + * @param handle a handle associated with a given writeset + * @param data an array of data buffers. + * @param count length of data buffer array. + * @param copy whether provider needs to make a copy of events. + * + * @retval WSREP_OK cluster-wide commit succeeded + * @retval WSREP_TRX_FAIL operation failed (e.g. trx size exceeded limit) + * @retval WSREP_NODE_FAIL must close all connections and reinit + */ + wsrep_status_t (*preordered_collect) (wsrep_t* wsrep, + wsrep_po_handle_t* handle, + const struct wsrep_buf* data, + size_t count, + wsrep_bool_t copy); + + /*! + * @brief "Commits" preordered writeset to cluster. + * + * The contract is that the writeset will be committed in the same (partial) + * order this method was called. Frees resources associated with the writeset + * handle and reinitializes the handle. + * + * @param wsrep wsrep provider handle + * @param po_handle a handle associated with a given writeset + * @param source_id ID of the event producer, also serves as the partial order + * or stream ID - events with different source_ids won't be + * ordered with respect to each other. + * @param flags WSREP_FLAG_... flags + * @param pa_range the number of preceding events this event can be processed + * in parallel with. A value of 0 means strict serial + * processing. Note: commits always happen in wsrep order. + * @param commit 'true' to commit writeset to cluster (replicate) or + * 'false' to rollback (cancel) the writeset. + * + * @retval WSREP_OK cluster-wide commit succeeded + * @retval WSREP_TRX_FAIL operation failed (e.g. NON-PRIMARY component) + * @retval WSREP_NODE_FAIL must close all connections and reinit + */ + wsrep_status_t (*preordered_commit) (wsrep_t* wsrep, + wsrep_po_handle_t* handle, + const wsrep_uuid_t* source_id, + uint64_t flags, + int pa_range, + wsrep_bool_t commit); + + /*! * @brief Signals to wsrep provider that state snapshot has been sent to * joiner. * - * @param wsrep this wsrep handle - * @param uuid sequence UUID (group UUID) - * @param seqno sequence number or negative error code of the operation + * @param wsrep provider handle + * @param state_id state ID + * @param rcode 0 or negative error code of the operation. */ wsrep_status_t (*sst_sent)(wsrep_t* wsrep, - const wsrep_uuid_t* uuid, - wsrep_seqno_t seqno); + const wsrep_gtid_t* state_id, + int rcode); /*! * @brief Signals to wsrep provider that new state snapshot has been received. * May deadlock if called from sst_prepare_cb. * - * @param wsrep this wsrep handle - * @param uuid sequence UUID (group UUID) - * @param seqno sequence number or negative error code of the operation + * @param wsrep provider handle + * @param state_id state ID * @param state initial state provided by SST donor * @param state_len length of state buffer + * @param rcode 0 or negative error code of the operation. */ wsrep_status_t (*sst_received)(wsrep_t* wsrep, - const wsrep_uuid_t* uuid, - wsrep_seqno_t seqno, - const char* state, - size_t state_len); + const wsrep_gtid_t* state_id, + const void* state, + size_t state_len, + int rcode); /*! @@ -729,9 +955,9 @@ struct wsrep_ { * called only locally. This call will block until sst_sent is called * from callback. * - * @param wsrep this wsrep handle - * @param msg context message for SST donate callback - * @param msg_len length of context message + * @param wsrep provider handle + * @param msg context message for SST donate callback + * @param msg_len length of context message * @param donor_spec list of snapshot donors */ wsrep_status_t (*snapshot)(wsrep_t* wsrep, @@ -743,7 +969,7 @@ struct wsrep_ { * @brief Returns an array fo status variables. * Array is terminated by Null variable name. * - * @param wsrep this wsrep handle + * @param wsrep provider handle * @return array of struct wsrep_status_var. */ struct wsrep_stats_var* (*stats_get) (wsrep_t* wsrep); @@ -751,11 +977,19 @@ struct wsrep_ { /*! * @brief Release resources that might be associated with the array. * - * @param wsrep this wsrep handle. + * @param wsrep provider handle. + * @param var_array array returned by stats_get(). */ void (*stats_free) (wsrep_t* wsrep, struct wsrep_stats_var* var_array); /*! + * @brief Reset some stats variables to inital value, provider-dependent. + * + * @param wsrep provider handle. + */ + void (*stats_reset) (wsrep_t* wsrep); + + /*! * @brief Pauses writeset applying/committing. * * @return global sequence number of the paused state or negative error code. @@ -786,28 +1020,30 @@ struct wsrep_ { /*! * @brief Acquire global named lock * - * @param wsrep wsrep provider handle - * @param name lock name - * @param owner 64-bit owner ID - * @param tout timeout in nanoseconds. - * 0 - return immediately, -1 wait forever. - * @return wsrep status or negative error code + * @param wsrep wsrep provider handle + * @param name lock name + * @param shared shared or exclusive lock + * @param owner 64-bit owner ID + * @param tout timeout in nanoseconds. + * 0 - return immediately, -1 wait forever. + * @return wsrep status or negative error code * @retval -EDEADLK lock was already acquired by this thread * @retval -EBUSY lock was busy */ - wsrep_status_t (*lock) (wsrep_t* wsrep, const char* name, int64_t owner, - int64_t tout); + wsrep_status_t (*lock) (wsrep_t* wsrep, + const char* name, wsrep_bool_t shared, + uint64_t owner, int64_t tout); /*! * @brief Release global named lock * - * @param wsrep wsrep provider handle - * @param name lock name - * @param owner 64-bit owner ID - * @return wsrep status or negative error code + * @param wsrep wsrep provider handle + * @param name lock name + * @param owner 64-bit owner ID + * @return wsrep status or negative error code * @retval -EPERM lock does not belong to this owner */ - wsrep_status_t (*unlock) (wsrep_t* wsrep, const char* name, int64_t owner); + wsrep_status_t (*unlock) (wsrep_t* wsrep, const char* name, uint64_t owner); /*! * @brief Check if global named lock is locked @@ -818,8 +1054,8 @@ struct wsrep_ { * @param node if not NULL will contain owner's node UUID * @return true if lock is locked */ - bool (*is_locked) (wsrep_t* wsrep, const char* name, int64_t* conn, - wsrep_uuid_t* node); + wsrep_bool_t (*is_locked) (wsrep_t* wsrep, const char* name, uint64_t* conn, + wsrep_uuid_t* node); /*! * wsrep provider name @@ -838,7 +1074,7 @@ struct wsrep_ { /*! * @brief Frees allocated resources before unloading the library. - * @param wsrep this wsrep handle + * @param wsrep provider handle */ void (*free)(wsrep_t* wsrep); @@ -846,7 +1082,6 @@ struct wsrep_ { void *ctx; //!< reserved for implemetation private context }; -typedef int (*wsrep_loader_fun)(wsrep_t*); /*! * diff --git a/wsrep/wsrep_dummy.c b/wsrep/wsrep_dummy.c index 6d01ce14b4e..33b61e6821f 100644 --- a/wsrep/wsrep_dummy.c +++ b/wsrep/wsrep_dummy.c @@ -16,10 +16,11 @@ /*! @file Dummy wsrep API implementation. */ -#include <errno.h> - #include "wsrep_api.h" +#include <errno.h> +#include <stdbool.h> + /*! Dummy backend context. */ typedef struct wsrep_dummy { @@ -74,9 +75,10 @@ static char* dummy_options_get (wsrep_t* w) static wsrep_status_t dummy_connect( wsrep_t* w, - const char* name __attribute__((unused)), - const char* url __attribute__((unused)), - const char* donor __attribute__((unused))) + const char* name __attribute__((unused)), + const char* url __attribute__((unused)), + const char* donor __attribute__((unused)), + wsrep_bool_t bootstrap __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -97,12 +99,12 @@ static wsrep_status_t dummy_recv(wsrep_t* w, static wsrep_status_t dummy_pre_commit( wsrep_t* w, - const wsrep_conn_id_t conn_id __attribute__((unused)), - wsrep_trx_handle_t* trx_handle __attribute__((unused)), - const void* query __attribute__((unused)), - const size_t query_len __attribute__((unused)), - uint64_t flags __attribute__((unused)), - wsrep_seqno_t* seqno __attribute__((unused))) + const wsrep_conn_id_t conn_id __attribute__((unused)), + wsrep_ws_handle_t* ws_handle __attribute__((unused)), +// const struct wsrep_buf* data __attribute__((unused)), +// const long count __attribute__((unused)), + uint64_t flags __attribute__((unused)), + wsrep_trx_meta_t* meta __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -110,7 +112,7 @@ static wsrep_status_t dummy_pre_commit( static wsrep_status_t dummy_post_commit( wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused))) + wsrep_ws_handle_t* ws_handle __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -118,7 +120,7 @@ static wsrep_status_t dummy_post_commit( static wsrep_status_t dummy_post_rollback( wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused))) + wsrep_ws_handle_t* ws_handle __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -126,7 +128,7 @@ static wsrep_status_t dummy_post_rollback( static wsrep_status_t dummy_replay_trx( wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused)), + wsrep_ws_handle_t* ws_handle __attribute__((unused)), void* trx_ctx __attribute__((unused))) { WSREP_DBUG_ENTER(w); @@ -142,23 +144,13 @@ static wsrep_status_t dummy_abort_pre_commit( return WSREP_OK; } -static wsrep_status_t dummy_append_query( - wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused)), - const char* query __attribute__((unused)), - const time_t timeval __attribute__((unused)), - const uint32_t randseed __attribute__((unused))) -{ - WSREP_DBUG_ENTER(w); - return WSREP_OK; -} - -static wsrep_status_t dummy_append_row_key( +static wsrep_status_t dummy_append_key( wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused)), - const wsrep_key_t* key __attribute__((unused)), - const size_t key_len __attribute__((unused)), - const bool shared __attribute__((unused))) + wsrep_ws_handle_t* ws_handle __attribute__((unused)), + const wsrep_key_t* key __attribute__((unused)), + const int key_num __attribute__((unused)), + const wsrep_key_type_t key_type __attribute__((unused)), + const bool copy __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -166,9 +158,11 @@ static wsrep_status_t dummy_append_row_key( static wsrep_status_t dummy_append_data( wsrep_t* w, - wsrep_trx_handle_t* trx_handle __attribute__((unused)), - const void* data __attribute__((unused)), - size_t data_len __attribute__((unused))) + wsrep_ws_handle_t* ws_handle __attribute__((unused)), + const struct wsrep_buf* data __attribute__((unused)), + const int count __attribute__((unused)), + const wsrep_data_type_t type __attribute__((unused)), + const bool copy __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -176,7 +170,7 @@ static wsrep_status_t dummy_append_data( static wsrep_status_t dummy_causal_read( wsrep_t* w, - wsrep_seqno_t* seqno __attribute__((unused))) + wsrep_gtid_t* gtid __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -192,12 +186,12 @@ static wsrep_status_t dummy_free_connection( static wsrep_status_t dummy_to_execute_start( wsrep_t* w, - const wsrep_conn_id_t conn_id __attribute__((unused)), - const wsrep_key_t* key __attribute__((unused)), - const size_t key_len __attribute__((unused)), - const void* query __attribute__((unused)), - const size_t query_len __attribute__((unused)), - wsrep_seqno_t* seqno __attribute__((unused))) + const wsrep_conn_id_t conn_id __attribute__((unused)), + const wsrep_key_t* key __attribute__((unused)), + const int key_num __attribute__((unused)), + const struct wsrep_buf* data __attribute__((unused)), + const int count __attribute__((unused)), + wsrep_trx_meta_t* meta __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -211,6 +205,19 @@ static wsrep_status_t dummy_to_execute_end( return WSREP_OK; } +static wsrep_status_t dummy_preordered( + wsrep_t* w, + const wsrep_uuid_t* source_id __attribute__((unused)), + int pa_range __attribute__((unused)), + const struct wsrep_buf* data __attribute__((unused)), + int count __attribute__((unused)), + uint64_t flags __attribute__((unused)), + wsrep_bool_t copy __attribute__((unused))) +{ + WSREP_DBUG_ENTER(w); + return WSREP_OK; +} + static wsrep_status_t dummy_sst_sent( wsrep_t* w, const wsrep_uuid_t* uuid __attribute__((unused)), @@ -234,7 +241,7 @@ static wsrep_status_t dummy_sst_received( static wsrep_status_t dummy_snapshot( wsrep_t* w, const void* msg __attribute__((unused)), - const size_t msg_len __attribute__((unused)), + const int msg_len __attribute__((unused)), const char* donor_spec __attribute__((unused))) { WSREP_DBUG_ENTER(w); @@ -258,6 +265,11 @@ static void dummy_stats_free ( WSREP_DBUG_ENTER(w); } +static void dummy_stats_reset (wsrep_t* w) +{ + WSREP_DBUG_ENTER(w); +} + static wsrep_seqno_t dummy_pause (wsrep_t* w) { WSREP_DBUG_ENTER(w); @@ -284,7 +296,8 @@ static wsrep_status_t dummy_resync (wsrep_t* w) static wsrep_status_t dummy_lock (wsrep_t* w, const char* s __attribute__((unused)), - int64_t o __attribute__((unused)), + bool r __attribute__((unused)), + uint64_t o __attribute__((unused)), int64_t t __attribute__((unused))) { WSREP_DBUG_ENTER(w); @@ -293,7 +306,7 @@ static wsrep_status_t dummy_lock (wsrep_t* w, static wsrep_status_t dummy_unlock (wsrep_t* w, const char* s __attribute__((unused)), - int64_t o __attribute__((unused))) + uint64_t o __attribute__((unused))) { WSREP_DBUG_ENTER(w); return WSREP_OK; @@ -301,7 +314,7 @@ static wsrep_status_t dummy_unlock (wsrep_t* w, static bool dummy_is_locked (wsrep_t* w, const char* s __attribute__((unused)), - int64_t* o __attribute__((unused)), + uint64_t* o __attribute__((unused)), wsrep_uuid_t* t __attribute__((unused))) { WSREP_DBUG_ENTER(w); @@ -322,18 +335,19 @@ static wsrep_t dummy_iface = { &dummy_post_rollback, &dummy_replay_trx, &dummy_abort_pre_commit, - &dummy_append_query, - &dummy_append_row_key, + &dummy_append_key, &dummy_append_data, &dummy_causal_read, &dummy_free_connection, &dummy_to_execute_start, &dummy_to_execute_end, + &dummy_preordered, &dummy_sst_sent, &dummy_sst_received, &dummy_snapshot, &dummy_stats_get, &dummy_stats_free, + &dummy_stats_reset, &dummy_pause, &dummy_resume, &dummy_desync, @@ -344,6 +358,7 @@ static wsrep_t dummy_iface = { WSREP_NONE, WSREP_INTERFACE_VERSION, "Codership Oy <info@codership.com>", + 0xdeadbeef, &dummy_free, NULL, NULL diff --git a/wsrep/wsrep_loader.c b/wsrep/wsrep_loader.c index b4460658f80..8ae6ea962ec 100644 --- a/wsrep/wsrep_loader.c +++ b/wsrep/wsrep_loader.c @@ -70,15 +70,18 @@ static int verify(const wsrep_t *wh, const char *iface_ver) VERIFY(wh->post_rollback); VERIFY(wh->replay_trx); VERIFY(wh->abort_pre_commit); - VERIFY(wh->append_query); VERIFY(wh->append_key); + VERIFY(wh->append_data); VERIFY(wh->free_connection); VERIFY(wh->to_execute_start); VERIFY(wh->to_execute_end); + VERIFY(wh->preordered_collect); + VERIFY(wh->preordered_commit); VERIFY(wh->sst_sent); VERIFY(wh->sst_received); VERIFY(wh->stats_get); VERIFY(wh->stats_free); + VERIFY(wh->stats_reset); VERIFY(wh->pause); VERIFY(wh->resume); VERIFY(wh->desync); @@ -93,6 +96,7 @@ static int verify(const wsrep_t *wh, const char *iface_ver) return 0; } +typedef int (*wsrep_loader_fun)(wsrep_t*); static wsrep_loader_fun wsrep_dlf(void *dlh, const char *sym) { @@ -175,7 +179,7 @@ out: *hptr = NULL; } else { snprintf (msg, msg_len, - "wsrep_load(): %s %s by %s loaded succesfully.", + "wsrep_load(): %s %s by %s loaded successfully.", (*hptr)->provider_name, (*hptr)->provider_version, (*hptr)->provider_vendor); logger (WSREP_LOG_INFO, msg); diff --git a/wsrep/wsrep_uuid.c b/wsrep/wsrep_uuid.c index c99240cc071..baa95b2578a 100644 --- a/wsrep/wsrep_uuid.c +++ b/wsrep/wsrep_uuid.c @@ -26,25 +26,31 @@ * Read UUID from string * @return length of UUID string representation or -EINVAL in case of error */ -ssize_t +int wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid) { - size_t uuid_len = 0; - size_t uuid_offt = 0; + unsigned int uuid_len = 0; + unsigned int uuid_offt = 0; while (uuid_len + 1 < str_len) { - if ((4 == uuid_offt || 6 == uuid_offt || 8 == uuid_offt || - 10 == uuid_offt) && str[uuid_len] == '-') { + /* We are skipping potential '-' after uuid_offt == 4, 6, 8, 10 + * which means + * (uuid_offt >> 1) == 2, 3, 4, 5, + * which in turn means + * (uuid_offt >> 1) - 2 <= 3 + * since it is always >= 0, because uuid_offt is unsigned */ + if (((uuid_offt >> 1) - 2) <= 3 && str[uuid_len] == '-') { // skip dashes after 4th, 6th, 8th and 10th positions uuid_len += 1; continue; } + if (isxdigit(str[uuid_len]) && isxdigit(str[uuid_len + 1])) { - // got hex digit - sscanf (str + uuid_len, "%2hhx", uuid->uuid + uuid_offt); + // got hex digit, scan another byte to uuid, increment uuid_offt + sscanf (str + uuid_len, "%2hhx", uuid->data + uuid_offt); uuid_len += 2; uuid_offt += 1; - if (sizeof (uuid->uuid) == uuid_offt) + if (sizeof (uuid->data) == uuid_offt) return uuid_len; } else { @@ -61,11 +67,11 @@ wsrep_uuid_scan (const char* str, size_t str_len, wsrep_uuid_t* uuid) * @return length of UUID string representation or -EMSGSIZE if string is too * short */ -ssize_t +int wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len) { if (str_len > 36) { - const unsigned char* u = uuid->uuid; + const unsigned char* u = uuid->data; return snprintf(str, str_len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x-%02x%02x%02x%02x%02x%02x", u[ 0], u[ 1], u[ 2], u[ 3], u[ 4], u[ 5], u[ 6], u[ 7], @@ -75,4 +81,3 @@ wsrep_uuid_print (const wsrep_uuid_t* uuid, char* str, size_t str_len) return -EMSGSIZE; } } - |