Merge branch feature226_patch into master
Title: patch ob-connector-c 2.2.6 patch226分支libobclient到开源分支 Link: https://code.alibaba-inc.com/oceanbase-ce-publish/obconnector-c/codereview/16946956
This commit is contained in:
commit
6838fdf533
@ -22,6 +22,7 @@ SET(MARIADB_CLIENT_INCLUDES ${CC_SOURCE_DIR}/include/mariadb_com.h
|
||||
${CC_SOURCE_DIR}/include/ob_protocol20.h
|
||||
${CC_SOURCE_DIR}/include/ob_object.h
|
||||
${CC_SOURCE_DIR}/include/ob_full_link_trace.h
|
||||
${CC_SOURCE_DIR}/include/ob_load_balance.h
|
||||
${CC_SOURCE_DIR}/include/mariadb_rpl.h
|
||||
)
|
||||
IF(NOT IS_SUBPROJECT)
|
||||
|
@ -27,6 +27,7 @@ extern "C" {
|
||||
void init_client_errs(void);
|
||||
extern const char *client_errors[]; /* Error messages */
|
||||
extern const char *mariadb_client_errors[]; /* Error messages */
|
||||
extern const char *ob_client_errors[];
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -35,11 +36,14 @@ extern const char *mariadb_client_errors[]; /* Error messages */
|
||||
|
||||
#define CR_MIN_ERROR 2000 /* For easier client code */
|
||||
#define CR_MAX_ERROR 2999
|
||||
#define CER_MIN_ERROR 5000
|
||||
#define CER_MAX_ERROR 5999
|
||||
#define CER_MIN_ERROR 5000
|
||||
#define CER_MAX_ERROR 5999
|
||||
#define OB_MIN_ERROR 8000
|
||||
#define OB_MAX_ERROR 8999
|
||||
#define CER(X) mariadb_client_errors[(X)-CER_MIN_ERROR]
|
||||
#define ER(X) client_errors[(X)-CR_MIN_ERROR]
|
||||
#define CLIENT_ERRMAP 2 /* Errormap used by ma_error() */
|
||||
#define OBER(X) ob_client_errors[(X)-OB_MIN_ERROR]
|
||||
#define CLIENT_ERRMAP 3 /* Errormap used by ma_error() */
|
||||
|
||||
#define CR_UNKNOWN_ERROR 2000
|
||||
#define CR_SOCKET_CREATE_ERROR 2001
|
||||
@ -105,4 +109,24 @@ extern const char *mariadb_client_errors[]; /* Error messages */
|
||||
/* Always last, if you add new error codes please update the
|
||||
value for CR_MARIADB_LAST_ERROR */
|
||||
#define CR_MARIADB_LAST_ERROR CR_VERSION_MISMATCH
|
||||
|
||||
/*
|
||||
oceanbase erros:
|
||||
*/
|
||||
#define CR_STATUS_ERROR_NOT_READY 8000
|
||||
#define CR_STATUS_ERROR_NOT_GET_RESULT 8001
|
||||
#define CR_STATES_ERROR_NEXT_RESULT 8002
|
||||
#define CR_STATUS_ERROR_CURSOR_FETCH 8003
|
||||
#define CR_STATUS_ERROR_FETCH_ORACLE_IMPLICIT_CURSOR 8004
|
||||
#define CR_STATUS_ERROR_FETCH_ORACLE_BUFFERED_RESULT 8005
|
||||
#define CR_STATUS_ERROR_STMT_USE_RESULT 8006
|
||||
#define CR_STATUS_ERROR_STMT_FETCH 8007
|
||||
#define CR_FETCH_FIELD_COUNT_IS_ZERO 8008
|
||||
#define CR_STATUS_ERROR_STORE_RESULT 8009
|
||||
#define CR_STATUS_ERROR_NOT_STMT_RESULT 8010
|
||||
#define CR_STATES_ERROR_NOT_PREPARED 8011
|
||||
#define CR_STATUS_ERROR_STMT_NEXT_RESULT 8012
|
||||
#define CR_STATES_ERROR_NOT_PREPARED_EXECUTE_V2 8013
|
||||
#define CR_OB_LAST_ERROR CR_STATES_ERROR_NOT_PREPARED_EXECUTE_V2
|
||||
|
||||
#endif
|
||||
|
@ -1115,8 +1115,16 @@ typedef unsigned long long intptr;
|
||||
#define OB_ERROR -4000
|
||||
#define UNUSED(x) (void)x
|
||||
|
||||
#define OB_LIKELY(x) __builtin_expect(!!(x),1)
|
||||
#define OB_UNLIKELY(x) __builtin_expect(!!(x),0)
|
||||
#ifdef _WIN32
|
||||
#define OB_LIKELY(x) (x)
|
||||
#define OB_UNLIKELY(x) (x)
|
||||
#define __UINT64_C(c) c ## ULL
|
||||
#define __INT64_C(c) c ## LL
|
||||
#else
|
||||
#define OB_LIKELY(x) __builtin_expect(!!(x),1)
|
||||
#define OB_UNLIKELY(x) __builtin_expect(!!(x),0)
|
||||
#endif
|
||||
|
||||
#define OB_ISNULL(statement) (OB_UNLIKELY(NULL == (statement)))
|
||||
#define OB_NOT_NULL(statement) (OB_LIKELY(NULL != (statement)))
|
||||
|
||||
|
@ -114,6 +114,7 @@ struct st_ma_pvio_methods
|
||||
my_bool (*is_alive)(MARIADB_PVIO *pvio);
|
||||
my_bool (*has_data)(MARIADB_PVIO *pvio, ssize_t *data_len);
|
||||
int(*shutdown)(MARIADB_PVIO *pvio);
|
||||
int(*socket5_auth)(MARIADB_PVIO *pvio, char *user, char *pwd, char *host, unsigned short port);
|
||||
};
|
||||
|
||||
/* Function prototypes */
|
||||
@ -135,5 +136,6 @@ my_bool ma_pvio_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo);
|
||||
my_bool ma_pvio_is_alive(MARIADB_PVIO *pvio);
|
||||
my_bool ma_pvio_get_handle(MARIADB_PVIO *pvio, void *handle);
|
||||
my_bool ma_pvio_has_data(MARIADB_PVIO *pvio, ssize_t *length);
|
||||
int ma_pvio_socket5_auth(MARIADB_PVIO *pvio, char *user, char *pwd, char *host, unsigned short port);
|
||||
|
||||
#endif /* _ma_pvio_h_ */
|
||||
|
@ -51,7 +51,7 @@ do {\
|
||||
ma_init();\
|
||||
} while(0)
|
||||
|
||||
#define MAXMAPS (4) /* Number of error message maps */
|
||||
#define MAXMAPS (5) /* Number of error message maps */
|
||||
#define ERRMOD (1000) /* Max number of errors in a map */
|
||||
#define ERRMSGSIZE (SC_MAXWIDTH) /* Max length of a error message */
|
||||
#define NRERRBUFFS (2) /* Buffers for parameters */
|
||||
|
@ -381,7 +381,9 @@ enum ObCapabilityFlagShift
|
||||
OBCLIENT_CAP_PROXY_NEW_EXTRA_INFO_SHIFT,
|
||||
OBCLIENT_CAP_PROXY_SESSION_VAR_SYNC_SHIFT,
|
||||
OBCLIENT_CAP_PROXY_WEAK_STALE_FEEDBACK_SHIFT,
|
||||
OBCLIENT_CAP_PROXY_FULL_LINK_TRACE_SHOW_TRACE_SHIFT
|
||||
OBCLIENT_CAP_PROXY_FULL_LINK_TRACE_SHOW_TRACE_SHIFT,
|
||||
OBCLIENT_CAP_SERVER_DUP_SESS_INFO_SYNC_SHIFT,
|
||||
OBCLIENT_CAP_PROXY_LOCAL_INFILES_SHIFT
|
||||
};
|
||||
|
||||
#define OBCLIENT_TEST_CAPABILITY(cap, tg_cap) (((cap) & (tg_cap)) == (tg_cap))
|
||||
@ -403,6 +405,7 @@ enum ObCapabilityFlagShift
|
||||
#define OBCLIENT_CAP_PROXY_SESSION_VAR_SYNC OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PROXY_SESSION_VAR_SYNC_SHIFT)
|
||||
#define OBCLIENT_CAP_PROXY_WEAK_STALE_FEEDBACK OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PROXY_WEAK_STALE_FEEDBACK_SHIFT)
|
||||
#define OBCLIENT_CAP_PROXY_FULL_LINK_TRACE_SHOW_TRACE OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PROXY_FULL_LINK_TRACE_SHOW_TRACE_SHIFT)
|
||||
#define OBCLIENT_CAP_PROXY_LOCAL_INFILES OBCLIENT_CAP_GET_TYPE(OBCLIENT_CAP_PROXY_LOCAL_INFILES_SHIFT)
|
||||
|
||||
static const unsigned long OBPROXY_DEFAULT_CAPABILITY_FLAG =
|
||||
(OBCLIENT_CAP_OB_PROTOCOL_V2
|
||||
@ -419,6 +422,9 @@ static const char *const OB_MYSQL_CAPABILITY_FLAG = "__proxy_capability_flag";
|
||||
static const char *const OB_MYSQL_CLIENT_MODE = "__mysql_client_type";
|
||||
static const char *const OB_MYSQL_CLIENT_OBPROXY_MODE = "__ob_proxy";
|
||||
static const char *const OB_MYSQL_CONNECTION_ID = "__connection_id";
|
||||
static const char *const OB_MYSQL_CLIENT_NAME_KEY = "__ob_client_name";
|
||||
static const char *const OB_MYSQL_CLIENT_NAME_VALUE = "OceanBase Connector/C";
|
||||
static const char *const OB_MYSQL_CLIENT_VERSION_KEY = "__ob_client_version";
|
||||
static const char *const OB_MYSQL_PROXY_CONNECTION_ID = "__proxy_connection_id";
|
||||
static const char *const OB_MYSQL_GLOBAL_VARS_VERSION = "__global_vars_version";
|
||||
|
||||
@ -437,6 +443,7 @@ enum ObCapabilityFlagLob
|
||||
static const unsigned long OBCLIENT_CAP_OB_LOB_LOCATOR_V2_FLAG = OBCLIENT_CAP_OB_LOB_LOCATOR_V2;
|
||||
static const char *const OB_MYSQL_LOB_LOCATOR_V2 = "__ob_client_attribute_capability_flag";
|
||||
|
||||
static const char *const OB_MYSQL_PROXY_USER_NAME = "__ob_client_proxy_user_name";
|
||||
|
||||
typedef enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
|
||||
MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
|
||||
|
@ -49,6 +49,15 @@ do { \
|
||||
(a)->last_error[MYSQL_ERRMSG_SIZE - 1]= 0;\
|
||||
} while (0)
|
||||
|
||||
#define SET_OB_CLIENT_STMT_ERROR(a, b, c, d) \
|
||||
do { \
|
||||
(a)->last_errno= (b);\
|
||||
strncpy((a)->sqlstate, (c), SQLSTATE_LENGTH);\
|
||||
(a)->sqlstate[SQLSTATE_LENGTH]= 0;\
|
||||
strncpy((a)->last_error, (d) ? (d) : OBER((b)), MYSQL_ERRMSG_SIZE);\
|
||||
(a)->last_error[MYSQL_ERRMSG_SIZE - 1]= 0;\
|
||||
} while (0)
|
||||
|
||||
#define CLEAR_CLIENT_STMT_ERROR(a) \
|
||||
do { \
|
||||
(a)->last_errno= 0;\
|
||||
@ -471,8 +480,18 @@ enum enum_ob_client_lob_locatorv2
|
||||
};
|
||||
my_bool determine_ob_client_lob_locatorv2(MYSQL *mysql);
|
||||
my_bool get_use_ob_client_lob_locatorv2(MYSQL *mysql);
|
||||
/*end for support lobv2*/
|
||||
|
||||
my_bool set_nls_format(MYSQL *mysql);
|
||||
enum enum_load_infiles
|
||||
{
|
||||
LOAD_INFILES_FORCE_CLOSE = 0,
|
||||
LOAD_INFILES_AUTO_OPEN,
|
||||
LOAD_INFILES_FORCE_OPEN,
|
||||
LOAD_INFILES_FLAY_MAX
|
||||
};
|
||||
my_bool determine_load_infiles(MYSQL *mysql);
|
||||
my_bool get_use_load_infiles(MYSQL *mysql);
|
||||
/*end for load infiles*/
|
||||
|
||||
/* add for support bindbyname for plarray */
|
||||
struct prepare_extend_args_t
|
||||
|
@ -171,6 +171,15 @@ enum ObClientRoutineParamInOut
|
||||
(a)->net.last_error[MYSQL_ERRMSG_SIZE - 1]= 0;\
|
||||
} while(0)
|
||||
|
||||
#define SET_OB_CLIENT_ERROR(a, b, c, d) \
|
||||
do { \
|
||||
(a)->net.last_errno= (b);\
|
||||
strncpy((a)->net.sqlstate, (c), SQLSTATE_LENGTH);\
|
||||
(a)->net.sqlstate[SQLSTATE_LENGTH]= 0;\
|
||||
strncpy((a)->net.last_error, (d) ? (d) : OBER((b)), MYSQL_ERRMSG_SIZE - 1);\
|
||||
(a)->net.last_error[MYSQL_ERRMSG_SIZE - 1]= 0;\
|
||||
} while(0)
|
||||
|
||||
/* For mysql_async.c */
|
||||
#define set_mariadb_error(A,B,C) SET_CLIENT_ERROR((A),(B),(C),0)
|
||||
extern const char *SQLSTATE_UNKNOWN;
|
||||
@ -279,7 +288,8 @@ extern const char *SQLSTATE_UNKNOWN;
|
||||
MARIADB_OPT_MULTI_STATEMENTS,
|
||||
MARIADB_OPT_INTERACTIVE,
|
||||
MARIADB_OPT_PROXY_HEADER,
|
||||
MARIADB_OPT_IO_WAIT
|
||||
MARIADB_OPT_IO_WAIT,
|
||||
OB_OPT_PROXY_USER = 8000 /*ob option start 8000*/
|
||||
};
|
||||
|
||||
enum mariadb_value {
|
||||
@ -340,7 +350,7 @@ struct st_mysql_options {
|
||||
unsigned int connect_timeout, read_timeout, write_timeout;
|
||||
unsigned int port, protocol;
|
||||
unsigned long client_flag;
|
||||
char *host,*user,*password,*unix_socket,*db;
|
||||
char *host,*user,*password,*unix_socket,*db,*proxy_user;
|
||||
struct st_dynamic_array *init_command;
|
||||
char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name;
|
||||
char *ssl_key; /* PEM key file */
|
||||
@ -369,7 +379,7 @@ struct st_mysql_options {
|
||||
typedef struct st_mysql {
|
||||
NET net; /* Communication parameters */
|
||||
void *unused_0;
|
||||
char *host,*user,*passwd,*unix_socket,*server_version,*host_info;
|
||||
char *host,*user,*passwd,*unix_socket,*server_version,*host_info,*proxy_user;
|
||||
char *info,*db;
|
||||
const struct ma_charset_info_st *charset; /* character set */
|
||||
MYSQL_FIELD *fields;
|
||||
@ -410,9 +420,14 @@ struct st_mysql_options {
|
||||
my_bool can_use_full_link_trace;
|
||||
my_bool can_use_ob_client_lob_locatorv2;
|
||||
my_bool can_use_flt_show_trace;
|
||||
my_bool can_use_load_infiles;
|
||||
unsigned long ob_server_version;
|
||||
unsigned long ob_proxy_version;
|
||||
unsigned long capability; // system varaiable
|
||||
my_bool is_socket5; //1 open socket5
|
||||
char socket5_authtype;
|
||||
char *socket5_host, *socket5_user, *socket5_pwd;
|
||||
int socket5_port;
|
||||
} MYSQL;
|
||||
|
||||
/**
|
||||
@ -425,9 +440,9 @@ struct st_mysql_options {
|
||||
* This structure is used as mysql->extension.res_extension field
|
||||
*/
|
||||
typedef struct st_ob_result_extension {
|
||||
ulong pkt_len;
|
||||
unsigned long pkt_len;
|
||||
char *pkt_buffer;
|
||||
MYSQL_FIELD *mysql_fields; // 保存field信息
|
||||
MYSQL_FIELD *mysql_fields; // 保存field信息
|
||||
} OB_RES_EXT;
|
||||
|
||||
struct st_mysql_trace_info;
|
||||
@ -1017,6 +1032,8 @@ struct st_mariadb_methods {
|
||||
#define mysql_library_end mysql_server_end
|
||||
|
||||
/* new api functions */
|
||||
void ob_get_libobclient_version(int *major, int *minor, int *patch, char* version, int len);
|
||||
void ob_set_socket5_proxy(MYSQL *mysql, char socket5_authtype, char *socket5_host, int socket5_port, char *socket5_user, char *socket5_pwd);
|
||||
|
||||
#define HAVE_MYSQL_REAL_CONNECT
|
||||
|
||||
|
@ -305,7 +305,7 @@ typedef struct st_fltfunc
|
||||
flt_get_serialize_size_func get_serialize_size_func;
|
||||
} FLTFunc;
|
||||
|
||||
typedef struct st_uuid
|
||||
typedef struct st_obclient_uuid
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
@ -321,8 +321,8 @@ typedef struct st_uuid
|
||||
uint8_t node[6];
|
||||
};
|
||||
};
|
||||
} UUID;
|
||||
DEFINE_TO_STRING_FUNC_FOR(UUID);
|
||||
} OBCLIENT_UUID;
|
||||
DEFINE_TO_STRING_FUNC_FOR(OBCLIENT_UUID);
|
||||
|
||||
enum enum_flt_tagtype{
|
||||
FLT_TAG_COMMAND_NAME = 0,
|
||||
@ -342,7 +342,7 @@ DEFINE_TO_STRING_FUNC_FOR(ObTagCtx);
|
||||
typedef struct st_obspanctx
|
||||
{
|
||||
uint16_t span_type_;
|
||||
UUID span_id_;
|
||||
OBCLIENT_UUID span_id_;
|
||||
struct st_obspanctx *source_span_;
|
||||
my_bool is_follow_;
|
||||
int64_t start_ts_;
|
||||
@ -363,8 +363,8 @@ struct st_obtrace
|
||||
my_bool slow_query_print_;
|
||||
FLTInfo *flt; // point to flt struct
|
||||
uint64_t uuid_random_seed[2];
|
||||
UUID trace_id_;
|
||||
UUID root_span_id_;
|
||||
OBCLIENT_UUID trace_id_;
|
||||
OBCLIENT_UUID root_span_id_;
|
||||
LIST *current_span_list_;
|
||||
LIST *free_span_list_;
|
||||
ObSpanCtx *last_active_span_;
|
||||
@ -407,11 +407,11 @@ DEFINE_FLT_SERIALIZE_FUNC(nosupport); // FLT_EXTRA_INFO_TYPE_END
|
||||
|
||||
my_bool flt_is_vaild(FLTInfo *flt);
|
||||
|
||||
int serialize_UUID(char *buf, const int64_t buf_len, int64_t* pos, UUID *uuid);
|
||||
int deserialize_UUID(const char *buf, const int64_t buf_len, int64_t *pos, UUID *uuid);
|
||||
int serialize_UUID(char *buf, const int64_t buf_len, int64_t* pos, OBCLIENT_UUID *uuid);
|
||||
int deserialize_UUID(const char *buf, const int64_t buf_len, int64_t *pos, OBCLIENT_UUID *uuid);
|
||||
|
||||
int uuid4_init(uint64_t *seed, size_t seed_size);
|
||||
UUID uuid4_generate(uint64_t *seed);
|
||||
OBCLIENT_UUID uuid4_generate(uint64_t *seed);
|
||||
|
||||
int flt_init(FLTInfo *flt);
|
||||
void flt_end(FLTInfo *flt);
|
||||
|
66
include/ob_load_balance.h
Normal file
66
include/ob_load_balance.h
Normal file
@ -0,0 +1,66 @@
|
||||
#ifndef _OB_LOAD_BALANCE_H_
|
||||
#define _OB_LOAD_BALANCE_H_
|
||||
#include "mysql.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _st_obclient_lb_Address {
|
||||
char host[128];
|
||||
unsigned int port;
|
||||
}ObClientLbAddress;
|
||||
|
||||
typedef struct _st_obclient_lb_AddressList {
|
||||
ObClientLbAddress *address_list;
|
||||
unsigned int address_list_count;
|
||||
}ObClientLbAddressList;
|
||||
|
||||
typedef struct _st_obclient_lb_config{
|
||||
int retry_all_downs; //总的次数
|
||||
int black_remove_strategy; //2001
|
||||
int black_remove_timeout; //移出黑名单时间
|
||||
int black_append_strategy; //3002 NORMAL, 3001 RETRYDURATION
|
||||
int black_append_retrytimes; //单个address次数
|
||||
int black_append_duration; //时间duration内,执行>= retrytimes次加黑
|
||||
|
||||
unsigned int mysql_connect_timeout;
|
||||
unsigned int mysql_read_timeout;
|
||||
unsigned int mysql_write_timeout;
|
||||
my_bool mysql_is_local_infile;
|
||||
unsigned int mysql_local_infile;
|
||||
unsigned int mysql_opt_protocol;
|
||||
my_bool mysql_is_proxy_mode;
|
||||
my_bool mysql_is_compress;
|
||||
my_bool mysql_opt_secure_auth;
|
||||
char* mysql_init_command;
|
||||
char* mysql_charset_name;
|
||||
char* mysql_opt_plugin_dir;
|
||||
char* mysql_opt_default_auth;
|
||||
char* mysql_program_name;
|
||||
char* mysql_ob_proxy_user;
|
||||
my_bool mysql_opt_interactive;
|
||||
my_bool mysql_report_data_truncation;
|
||||
my_bool mysql_opt_reconnect;
|
||||
|
||||
my_bool mysql_opt_use_ssl;
|
||||
my_bool mysql_opt_ssl_verify_server_cert;
|
||||
char *mysql_opt_ssl_key;
|
||||
char *mysql_opt_ssl_cert;
|
||||
char *mysql_opt_ssl_ca;
|
||||
char *mysql_opt_ssl_capath;
|
||||
char *mysql_opt_ssl_cipher;
|
||||
char *mysql_opt_ssl_crl;
|
||||
char *mysql_opt_ssl_crlpath;
|
||||
char *mysql_opt_tls_version;
|
||||
}ObClientLbConfig;
|
||||
|
||||
|
||||
MYSQL* ob_mysql_real_connect(MYSQL* mysql, const char* tns_name, ObClientLbAddressList *addr_list, ObClientLbConfig *config,
|
||||
const char *user, const char *passwd, const char *db, const char *unix_socket, unsigned long client_flag, ObClientLbAddress* success);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -87,7 +87,7 @@ typedef enum enum_obobjtype
|
||||
ObMaxType // invalid type, or count of obj type
|
||||
} ObObjType;
|
||||
|
||||
enum enum_obcollationtype
|
||||
typedef enum enum_obcollationtype
|
||||
{
|
||||
CS_TYPE_INVALID = 0,
|
||||
CS_TYPE_GBK_CHINESE_CI = 28,
|
||||
@ -104,7 +104,7 @@ enum enum_obcollationtype
|
||||
CS_TYPE_MAX,
|
||||
} ObCollationType;
|
||||
|
||||
enum enum_obcollationlevel
|
||||
typedef enum enum_obcollationlevel
|
||||
{
|
||||
CS_LEVEL_EXPLICIT = 0,
|
||||
CS_LEVEL_NONE = 1,
|
||||
|
@ -103,6 +103,7 @@ typedef struct st_ob20protocol
|
||||
|
||||
// extra info
|
||||
FLTInfo *flt; // full link trace
|
||||
my_bool update_request_id;
|
||||
} Ob20Protocol;
|
||||
|
||||
typedef int (*extrainfo_serialize_func)(char *buf, const int64_t len, int64_t *pos, void *data);
|
||||
|
13
include/ob_utils.h
Normal file
13
include/ob_utils.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef _OB_UTILS_H_
|
||||
#define _OB_UTILS_H_
|
||||
#include "mysql.h"
|
||||
#include "ma_global.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
int gettimeofday(struct timeval *tp, void *tzp);
|
||||
#endif
|
||||
|
||||
int ob_gettimeofday(struct timeval *tp, void *tzp);
|
||||
int64_t get_current_time_us();
|
||||
|
||||
#endif
|
@ -341,6 +341,9 @@ SET(MARIADB_NONBLOCK_SYMBOLS
|
||||
get_ob_lob_locator_version
|
||||
get_ob_lob_payload_data_len
|
||||
stmt_get_data_from_lobv2
|
||||
ob_mysql_real_connect
|
||||
ob_get_libobclient_version
|
||||
ob_set_socket5_proxy
|
||||
)
|
||||
|
||||
# handle static plugins
|
||||
@ -392,6 +395,9 @@ ob_full_link_trace.c
|
||||
ob_rwlock.c
|
||||
ob_cond.c
|
||||
ob_thread_key.c
|
||||
ob_load_balance.c
|
||||
ob_utils.c
|
||||
ob_tnsname.c
|
||||
${CC_BINARY_DIR}/libmariadb/ma_client_plugin.c
|
||||
ma_io.c
|
||||
${SSL_SOURCES}
|
||||
|
@ -162,6 +162,25 @@ const char *mariadb_client_errors[] =
|
||||
""
|
||||
};
|
||||
|
||||
const char *ob_client_errors[] =
|
||||
{
|
||||
/*8000*/ "The previous packet of data is still unprocessed before new command",
|
||||
/*8001*/ "Status is not MYSQL_STATUS_GET_RESULT in mysql_store_result/mysql_use_result",
|
||||
/*8002*/ "Status is not MYSQL_STATUS_READY in mysql_next_result",
|
||||
/*8003*/ "State less than MYSQL_STMT_USE_OR_STORE_CALLED in stmt_cursor_fetch",
|
||||
/*8004*/ "State less than or equal to MYSQL_STMT_EXECUTED in mysql_stmt_fetch_oracle_implicit_cursor",
|
||||
/*8005*/ "State less than or equal to MYSQL_STMT_EXECUTED in mysql_stmt_fetch_oracle_buffered_result",
|
||||
/*8006*/ "State is error in _mysql_stmt_use_result",
|
||||
/*8007*/ "State less than or equal to MYSQL_STMT_EXECUTED in mysql_stmt_fetch",
|
||||
/*8008*/ "fetch field count is zero",
|
||||
/*8009*/ "State less than MYSQL_STMT_EXECUTED in mysql_stmt_store_result",
|
||||
/*8010*/ "States is not MYSQL_STATUS_STMT_RESULT in mysql_stmt_store_result",
|
||||
/*8011*/ "stmt is not prepared before mysql_stmt_execute",
|
||||
/*8012*/ "state less than MYSQL_STMT_EXECUTED in mysql_stmt_next_result",
|
||||
/*8013*/ "stmt is not prepared before mysql_stmt_execute_v2",
|
||||
""
|
||||
};
|
||||
|
||||
const char ** NEAR my_errmsg[MAXMAPS]={0,0,0,0};
|
||||
char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
|
||||
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include <share.h>
|
||||
#endif
|
||||
#include <ma_common.h>
|
||||
#include <ob_protocol20.h>
|
||||
|
||||
typedef struct st_mysql_infile_info
|
||||
{
|
||||
@ -200,6 +201,11 @@ my_bool mysql_handle_local_infile(MYSQL *conn, const char *filename, my_bool can
|
||||
mysql_set_local_infile_default(conn);
|
||||
}
|
||||
|
||||
//ob20 don't update requestid
|
||||
if (conn->net.use_ob20protocol && OB_NOT_NULL(conn->net.ob20protocol)) {
|
||||
conn->net.ob20protocol->update_request_id = 0;
|
||||
}
|
||||
|
||||
if (!(conn->options.client_flag & CLIENT_LOCAL_FILES) ||
|
||||
!can_local_infile)
|
||||
{
|
||||
@ -230,7 +236,7 @@ my_bool mysql_handle_local_infile(MYSQL *conn, const char *filename, my_bool can
|
||||
/* read data */
|
||||
while ((bufread= conn->options.local_infile_read(info, (char *)buf, buflen)) > 0)
|
||||
{
|
||||
if (ma_net_write(&conn->net, (unsigned char *)buf, bufread))
|
||||
if (ma_net_write(&conn->net, (unsigned char *)buf, bufread) || ma_net_flush(&conn->net))
|
||||
{
|
||||
my_set_error(conn, CR_SERVER_LOST, SQLSTATE_UNKNOWN, NULL);
|
||||
goto infile_error;
|
||||
@ -238,7 +244,7 @@ my_bool mysql_handle_local_infile(MYSQL *conn, const char *filename, my_bool can
|
||||
}
|
||||
|
||||
/* send empty packet for eof */
|
||||
if (ma_net_write(&conn->net, (unsigned char *)"", 0) ||
|
||||
if (ma_net_write(&conn->net, (unsigned char *)"", 0) ||
|
||||
ma_net_flush(&conn->net))
|
||||
{
|
||||
my_set_error(conn, CR_SERVER_LOST, SQLSTATE_UNKNOWN, NULL);
|
||||
@ -257,6 +263,9 @@ my_bool mysql_handle_local_infile(MYSQL *conn, const char *filename, my_bool can
|
||||
result = 0;
|
||||
|
||||
infile_error:
|
||||
if (conn->net.use_ob20protocol && OB_NOT_NULL(conn->net.ob20protocol)) {
|
||||
conn->net.ob20protocol->update_request_id = 1;
|
||||
}
|
||||
conn->options.local_infile_end(info);
|
||||
free(buf);
|
||||
return(result);
|
||||
|
@ -203,7 +203,7 @@ int ma_net_write(NET *net, const uchar *packet, size_t len)
|
||||
uchar buff[NET_HEADER_SIZE];
|
||||
unsigned long max_packet_length = MAX_PACKET_LENGTH;
|
||||
// update ob20 request id
|
||||
if (net->use_ob20protocol && OB_NOT_NULL(net->ob20protocol)) {
|
||||
if (net->use_ob20protocol && OB_NOT_NULL(net->ob20protocol) && net->ob20protocol->update_request_id) {
|
||||
update_request_id(&net->ob20protocol->header.request_id);
|
||||
}
|
||||
while (len >= max_packet_length)
|
||||
|
@ -516,6 +516,13 @@ my_bool ma_pvio_has_data(MARIADB_PVIO *pvio, ssize_t *data_len)
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
int ma_pvio_socket5_auth(MARIADB_PVIO *pvio, char *user, char *pwd, char *host, unsigned short port)
|
||||
{
|
||||
if (pvio && pvio->methods->socket5_auth)
|
||||
return pvio->methods->socket5_auth(pvio, user, pwd, host, port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_TLS
|
||||
/* {{{ my_bool ma_pvio_start_ssl */
|
||||
|
@ -1251,7 +1251,7 @@ void ps_fetch_oracle_interval(MYSQL_BIND *param, const MYSQL_FIELD *field, uchar
|
||||
{
|
||||
case MYSQL_TYPE_OB_INTERVAL_DS: {
|
||||
*param->length = sizeof(ORACLE_INTERVAL);
|
||||
if (length != 14) {
|
||||
if (param->buffer_length < sizeof(ORACLE_INTERVAL) || length != 14) {
|
||||
*param->error = 1;
|
||||
} else {
|
||||
ORACLE_INTERVAL * interval = (ORACLE_INTERVAL*)param->buffer;
|
||||
@ -1269,7 +1269,7 @@ void ps_fetch_oracle_interval(MYSQL_BIND *param, const MYSQL_FIELD *field, uchar
|
||||
}
|
||||
case MYSQL_TYPE_OB_INTERVAL_YM: {
|
||||
*param->length = sizeof(ORACLE_INTERVAL);
|
||||
if (length != 7) {
|
||||
if (param->buffer_length < sizeof(ORACLE_INTERVAL) || length != 7) {
|
||||
*param->error = 1;
|
||||
} else {
|
||||
ORACLE_INTERVAL * interval = (ORACLE_INTERVAL*)param->buffer;
|
||||
|
@ -469,7 +469,8 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||
if (mysql->status != MYSQL_STATUS_READY ||
|
||||
mysql->server_status & SERVER_MORE_RESULTS_EXIST)
|
||||
{
|
||||
SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_ERROR(mysql, CR_STATUS_ERROR_NOT_READY, SQLSTATE_UNKNOWN, 0);
|
||||
goto end;
|
||||
}
|
||||
|
||||
@ -753,6 +754,7 @@ struct st_default_options mariadb_defaults[] =
|
||||
{MYSQL_SERVER_PUBLIC_KEY, MARIADB_OPTION_STR, "server-public-key"},
|
||||
{MYSQL_OPT_BIND, MARIADB_OPTION_STR, "bind-address"},
|
||||
{MYSQL_OPT_SSL_ENFORCE, MARIADB_OPTION_BOOL, "ssl-enforce"},
|
||||
{OB_OPT_PROXY_USER, MARIADB_OPTION_STR, "proxy-user"},
|
||||
{0, 0, NULL}
|
||||
};
|
||||
|
||||
@ -2019,6 +2021,7 @@ mysql_init(MYSQL *mysql)
|
||||
!(mysql->extension= (struct st_mariadb_extension *)
|
||||
calloc(1, sizeof(struct st_mariadb_extension))))
|
||||
goto error;
|
||||
|
||||
mysql->options.report_data_truncation= 1;
|
||||
mysql->options.connect_timeout=CONNECT_TIMEOUT;
|
||||
mysql->charset= mysql_find_charset_name(MARIADB_DEFAULT_CHARSET);
|
||||
@ -2142,17 +2145,25 @@ ma_set_ob_connect_attrs(MYSQL *mysql)
|
||||
cap &= ~OBCLIENT_CAP_PROXY_NEW_EXTRA_INFO;
|
||||
cap &= ~OBCLIENT_CAP_PROXY_FULL_LINK_TRACE_SHOW_TRACE;
|
||||
}
|
||||
if (mysql->can_use_load_infiles) {
|
||||
cap |= OBCLIENT_CAP_PROXY_LOCAL_INFILES;
|
||||
}
|
||||
|
||||
snprintf(cap_buf, OB_MAX_UINT64_BUF_LEN, "%lu", cap);
|
||||
|
||||
rc += mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, OB_MYSQL_CAPABILITY_FLAG, cap_buf);
|
||||
rc += mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, OB_MYSQL_CLIENT_MODE, "__ob_libobclient");
|
||||
rc += mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, OB_MYSQL_CLIENT_NAME_KEY, OB_MYSQL_CLIENT_NAME_VALUE);
|
||||
rc += mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, OB_MYSQL_CLIENT_VERSION_KEY, LIBOBCLIENT_VERSION);
|
||||
|
||||
if (mysql->can_use_ob_client_lob_locatorv2) {
|
||||
caplob |= OBCLIENT_CAP_OB_LOB_LOCATOR_V2;
|
||||
snprintf(caplob_buf, OB_MAX_UINT64_BUF_LEN, "%lu", caplob);
|
||||
rc += mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, OB_MYSQL_LOB_LOCATOR_V2, caplob_buf);
|
||||
}
|
||||
if (mysql->proxy_user && mysql->proxy_user[0]) {
|
||||
rc += mysql_optionsv(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, OB_MYSQL_PROXY_USER_NAME, mysql->proxy_user);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -2365,6 +2376,38 @@ static int get_ob_server_version(MYSQL *con)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static my_bool set_nls_format(MYSQL *mysql)
|
||||
{
|
||||
my_bool bret = TRUE;
|
||||
if (mysql->oracle_mode) {
|
||||
char *nls_date_format = getenv("NLS_DATE_FORMAT");
|
||||
char *nls_timestamp_format = getenv("NLS_TIMESTAMP_FORMAT");
|
||||
char *nls_timestamp_tz_format = getenv("NLS_TIMESTAMP_TZ_FORMAT");
|
||||
|
||||
if (NULL != nls_date_format) {
|
||||
char change_date_format_sql[100];
|
||||
snprintf(change_date_format_sql, 100, "ALTER SESSION SET NLS_DATE_FORMAT='%s';", nls_date_format);
|
||||
if (mysql_query(mysql, change_date_format_sql)) {
|
||||
bret = FALSE;
|
||||
}
|
||||
}
|
||||
if (bret && NULL != nls_timestamp_format) {
|
||||
char change_timestamp_format_sql[100];
|
||||
snprintf(change_timestamp_format_sql, 100, "ALTER SESSION SET NLS_TIMESTAMP_FORMAT='%s';", nls_timestamp_format);
|
||||
if (mysql_query(mysql, change_timestamp_format_sql)) {
|
||||
bret = FALSE;
|
||||
}
|
||||
}
|
||||
if (bret && NULL != nls_timestamp_tz_format) {
|
||||
char change_timestamp_tz_format_sql[100];
|
||||
snprintf(change_timestamp_tz_format_sql, 100, "ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='%s';", nls_timestamp_tz_format);
|
||||
if (mysql_query(mysql, change_timestamp_tz_format_sql)) {
|
||||
bret = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bret;
|
||||
}
|
||||
|
||||
MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
|
||||
const char *passwd, const char *db,
|
||||
@ -2483,6 +2526,10 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
|
||||
cinfo.host= host;
|
||||
cinfo.port= port;
|
||||
cinfo.type= PVIO_TYPE_SOCKET;
|
||||
if (mysql->is_socket5) {
|
||||
cinfo.host = mysql->socket5_host;
|
||||
cinfo.port = mysql->socket5_port;
|
||||
}
|
||||
sprintf(host_info=buff,ER(CR_TCP_CONNECTION), cinfo.host);
|
||||
}
|
||||
/* Initialize and load pvio plugin */
|
||||
@ -2496,6 +2543,16 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
|
||||
goto error;
|
||||
}
|
||||
|
||||
//socket5
|
||||
if (mysql->is_socket5)
|
||||
{
|
||||
int ret = 0;
|
||||
if (0 != (ret = ma_pvio_socket5_auth(pvio, mysql->socket5_user, mysql->socket5_pwd, (char*)host, port))) {
|
||||
my_set_error(mysql, CR_SOCKET_CREATE_ERROR, SQLSTATE_UNKNOWN, "socket5 proxy communication fail(%d).", ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (mysql->options.extension && mysql->options.extension->proxy_header)
|
||||
{
|
||||
char *hdr = mysql->options.extension->proxy_header;
|
||||
@ -2567,9 +2624,13 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
|
||||
/* Save connection information */
|
||||
if (!user) user="";
|
||||
|
||||
if (mysql->options.proxy_user && mysql->options.proxy_user[0]) {
|
||||
mysql->proxy_user = strdup(mysql->options.proxy_user);
|
||||
}
|
||||
|
||||
if (!(mysql->host_info= strdup(host_info)) ||
|
||||
!(mysql->host= strdup(cinfo.host ? cinfo.host : "")) ||
|
||||
!(mysql->user=strdup(user)) ||
|
||||
!(mysql->user=strdup(user ? user:"")) ||
|
||||
!(mysql->passwd=strdup(passwd)))
|
||||
{
|
||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
|
||||
@ -2688,6 +2749,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
|
||||
determine_full_link_trace(mysql);
|
||||
determine_ob_client_lob_locatorv2(mysql);
|
||||
determine_flt_show_trace(mysql);
|
||||
determine_load_infiles(mysql);
|
||||
|
||||
if (run_plugin_auth(mysql, scramble_data, scramble_len,
|
||||
scramble_plugin, db))
|
||||
@ -3040,6 +3102,9 @@ static void mysql_close_options(MYSQL *mysql)
|
||||
free(mysql->options.ssl_capath);
|
||||
free(mysql->options.ssl_cipher);
|
||||
|
||||
if (mysql->options.proxy_user) {
|
||||
free(mysql->options.proxy_user);
|
||||
}
|
||||
if (mysql->options.extension)
|
||||
{
|
||||
struct mysql_async_context *ctxt;
|
||||
@ -3081,13 +3146,9 @@ static void mysql_close_memory(MYSQL *mysql)
|
||||
free(mysql->db);
|
||||
free(mysql->unix_socket);
|
||||
free(mysql->server_version);
|
||||
if (mysql->extension) {
|
||||
free(mysql->extension);
|
||||
mysql->extension = NULL;
|
||||
}
|
||||
if (mysql->ob_extension) {
|
||||
mysql_extension_free((struct st_mysql_extension *)mysql->ob_extension);
|
||||
mysql->ob_extension = NULL;
|
||||
if (mysql->proxy_user) {
|
||||
free(mysql->proxy_user);
|
||||
mysql->proxy_user = 0;
|
||||
}
|
||||
mysql->host_info= mysql->host= mysql->unix_socket=
|
||||
mysql->server_version=mysql->user=mysql->passwd=mysql->db=0;
|
||||
@ -3106,9 +3167,11 @@ void my_set_error(MYSQL *mysql,
|
||||
if (!format)
|
||||
{
|
||||
if (error_nr >= CR_MIN_ERROR && error_nr <= CR_MYSQL_LAST_ERROR)
|
||||
errmsg= ER(error_nr);
|
||||
errmsg = ER(error_nr);
|
||||
else if (error_nr >= CER_MIN_ERROR && error_nr <= CR_MARIADB_LAST_ERROR)
|
||||
errmsg= CER(error_nr);
|
||||
errmsg = CER(error_nr);
|
||||
else if (error_nr >= OB_MIN_ERROR && error_nr <= CR_OB_LAST_ERROR)
|
||||
errmsg = OBER(error_nr);
|
||||
else
|
||||
errmsg= ER(CR_UNKNOWN_ERROR);
|
||||
}
|
||||
@ -3176,20 +3239,45 @@ mysql_close(MYSQL *mysql)
|
||||
mysql_close_options(mysql);
|
||||
ma_clear_session_state(mysql);
|
||||
|
||||
if (mysql->net.extension)
|
||||
if (mysql->net.extension) {
|
||||
free(mysql->net.extension);
|
||||
mysql->net.extension = NULL;
|
||||
}
|
||||
|
||||
mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
|
||||
mysql->proxy_user = 0;
|
||||
|
||||
/* Clear pointers for better safety */
|
||||
memset((char*) &mysql->options, 0, sizeof(mysql->options));
|
||||
|
||||
if (mysql->extension)
|
||||
if (mysql->extension) {
|
||||
free(mysql->extension);
|
||||
mysql->extension = NULL;
|
||||
}
|
||||
|
||||
if (mysql->ob_extension) {
|
||||
mysql_extension_free((struct st_mysql_extension *)mysql->ob_extension);
|
||||
mysql->ob_extension = NULL;
|
||||
}
|
||||
|
||||
mysql->is_socket5 = 0;
|
||||
if (mysql->socket5_host) {
|
||||
free(mysql->socket5_host);
|
||||
mysql->socket5_host = NULL;
|
||||
}
|
||||
if (mysql->socket5_user) {
|
||||
free(mysql->socket5_user);
|
||||
mysql->socket5_user = NULL;
|
||||
}
|
||||
if (mysql->socket5_pwd) {
|
||||
free(mysql->socket5_pwd);
|
||||
mysql->socket5_pwd = NULL;
|
||||
}
|
||||
|
||||
/* Clear pointers for better safety */
|
||||
mysql->net.extension = NULL;
|
||||
mysql->extension = NULL;
|
||||
mysql->ob_extension = NULL;
|
||||
|
||||
mysql->net.pvio= 0;
|
||||
if (mysql->free_me)
|
||||
@ -3542,7 +3630,8 @@ mysql_store_result(MYSQL *mysql)
|
||||
return(0);
|
||||
if (mysql->status != MYSQL_STATUS_GET_RESULT)
|
||||
{
|
||||
SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_CLIENT_ERROR(mysql, CR_STATUS_ERROR_NOT_GET_RESULT, SQLSTATE_UNKNOWN, 0);
|
||||
return(0);
|
||||
}
|
||||
mysql->status=MYSQL_STATUS_READY; /* server is ready */
|
||||
@ -3591,7 +3680,8 @@ mysql_use_result(MYSQL *mysql)
|
||||
return(0);
|
||||
if (mysql->status != MYSQL_STATUS_GET_RESULT)
|
||||
{
|
||||
SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_CLIENT_ERROR(mysql, CR_STATUS_ERROR_NOT_GET_RESULT, SQLSTATE_UNKNOWN, 0);
|
||||
return(0);
|
||||
}
|
||||
if (!(result=(MYSQL_RES*) calloc(1, sizeof(*result)+
|
||||
@ -4227,6 +4317,8 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
|
||||
case MARIADB_OPT_USER:
|
||||
OPT_SET_VALUE_STR(&mysql->options, user, arg1);
|
||||
break;
|
||||
case OB_OPT_PROXY_USER:
|
||||
OPT_SET_VALUE_STR(&mysql->options, proxy_user, arg1);
|
||||
case MARIADB_OPT_HOST:
|
||||
OPT_SET_VALUE_STR(&mysql->options, host, arg1);
|
||||
break;
|
||||
@ -4753,7 +4845,8 @@ int STDCALL mysql_next_result(MYSQL *mysql)
|
||||
/* make sure communication is not blocking */
|
||||
if (mysql->status != MYSQL_STATUS_READY)
|
||||
{
|
||||
SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_CLIENT_ERROR(mysql, CR_STATES_ERROR_NEXT_RESULT, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -5558,3 +5651,40 @@ struct st_mariadb_methods MARIADB_DEFAULT_METHODS = {
|
||||
/* API functions */
|
||||
&MARIADB_API
|
||||
};
|
||||
|
||||
void ob_get_libobclient_version(int *major, int *minor, int *patch, char* version, int len)
|
||||
{
|
||||
if (major)
|
||||
*major = LIBOBCLIENT_VERSION_MAJOR;
|
||||
if (minor)
|
||||
*minor = LIBOBCLIENT_VERSION_MINOR;
|
||||
if (patch)
|
||||
*patch = LIBOBCLIENT_VERSION_PATCH;
|
||||
if (version)
|
||||
memcpy(version, LIBOBCLIENT_VERSION, min(len, strlen(LIBOBCLIENT_VERSION)));
|
||||
}
|
||||
|
||||
void ob_set_socket5_proxy(MYSQL *mysql, char socket5_authtype, char *socket5_host, int socket5_port, char *socket5_user, char *socket5_pwd)
|
||||
{
|
||||
mysql->is_socket5 = 1;
|
||||
mysql->socket5_authtype = socket5_authtype;
|
||||
mysql->socket5_port = socket5_port;
|
||||
if (mysql->socket5_host) {
|
||||
free(mysql->socket5_host);
|
||||
mysql->socket5_host = NULL;
|
||||
}
|
||||
if (mysql->socket5_user) {
|
||||
free(mysql->socket5_user);
|
||||
mysql->socket5_user = NULL;
|
||||
}
|
||||
if (mysql->socket5_pwd) {
|
||||
free(mysql->socket5_pwd);
|
||||
mysql->socket5_pwd = NULL;
|
||||
}
|
||||
if (socket5_host)
|
||||
mysql->socket5_host = strdup(socket5_host);
|
||||
if (socket5_user)
|
||||
mysql->socket5_user = strdup(socket5_user);
|
||||
if (socket5_pwd)
|
||||
mysql->socket5_pwd = strdup(socket5_pwd);
|
||||
}
|
@ -116,6 +116,8 @@ void stmt_set_error(MYSQL_STMT *stmt,
|
||||
error= ER(error_nr);
|
||||
else if (error_nr >= CER_MIN_ERROR && error_nr <= CR_MARIADB_LAST_ERROR)
|
||||
error= CER(error_nr);
|
||||
else if (error_nr >=OB_MIN_ERROR && error_nr <=CR_OB_LAST_ERROR)
|
||||
error = OBER(error_nr);
|
||||
|
||||
stmt->last_errno= error_nr;
|
||||
ma_strmake(stmt->sqlstate, sqlstate, SQLSTATE_LENGTH);
|
||||
@ -211,7 +213,13 @@ static int stmt_unbuffered_fetch(MYSQL_STMT *stmt, uchar **row)
|
||||
|
||||
if (stmt->mysql->net.read_pos[0] == 254)
|
||||
{
|
||||
//EOF, update server_status
|
||||
char *p = stmt->mysql->net.read_pos;
|
||||
*row = NULL;
|
||||
p++;
|
||||
stmt->upsert_status.warning_count = stmt->mysql->warning_count = uint2korr(p);
|
||||
p += 2;
|
||||
stmt->upsert_status.server_status = stmt->mysql->server_status = uint2korr(p);
|
||||
stmt->fetch_row_func= stmt_unbuffered_eof;
|
||||
return(MYSQL_NO_DATA);
|
||||
}
|
||||
@ -347,7 +355,8 @@ static int stmt_cursor_fetch(MYSQL_STMT *stmt, uchar **row)
|
||||
int back_status = 0;
|
||||
if (stmt->state < MYSQL_STMT_USE_OR_STORE_CALLED)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_STMT_ERROR(stmt, CR_STATUS_ERROR_CURSOR_FETCH, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
}
|
||||
if (stmt->mysql == NULL)
|
||||
@ -744,7 +753,8 @@ int STDCALL mysql_stmt_fetch_oracle_implicit_cursor(MYSQL_STMT *stmt, my_bool is
|
||||
int rc = 0;
|
||||
if (stmt->state <= MYSQL_STMT_EXECUTED)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_STMT_ERROR(stmt, CR_STATUS_ERROR_FETCH_ORACLE_IMPLICIT_CURSOR, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
}
|
||||
if ((rc = do_stmt_read_row_from_oracle_implicit_cursor(stmt, &row, is_need_fetch_from_server)))
|
||||
@ -767,7 +777,8 @@ int STDCALL mysql_stmt_fetch_oracle_buffered_result(MYSQL_STMT *stmt)
|
||||
int rc = 0;
|
||||
if (stmt->state <= MYSQL_STMT_EXECUTED)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_STMT_ERROR(stmt, CR_STATUS_ERROR_FETCH_ORACLE_BUFFERED_RESULT, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
}
|
||||
/* just read the buffered result for some situation, not to fetch the result from ObServer any more */
|
||||
@ -804,9 +815,9 @@ void mthd_stmt_flush_unbuffered(MYSQL_STMT *stmt)
|
||||
}
|
||||
if (packet_len < 8 && *pos == 254) /* EOF */
|
||||
{
|
||||
stmt->mysql->server_status = uint2korr(pos + 3);
|
||||
if (mariadb_connection(stmt->mysql))
|
||||
{
|
||||
stmt->mysql->server_status= uint2korr(pos + 3);
|
||||
if (in_resultset)
|
||||
goto end;
|
||||
in_resultset= 1;
|
||||
@ -899,7 +910,8 @@ MYSQL_RES *_mysql_stmt_use_result(MYSQL_STMT *stmt)
|
||||
(stmt->cursor_exists && mysql->status != MYSQL_STATUS_READY) ||
|
||||
(stmt->state != MYSQL_STMT_WAITING_USE_OR_STORE))
|
||||
{
|
||||
SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_ERROR(mysql, CR_STATUS_ERROR_STMT_USE_RESULT, SQLSTATE_UNKNOWN, 0);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
@ -2935,13 +2947,15 @@ int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
|
||||
|
||||
if (stmt->state <= MYSQL_STMT_EXECUTED)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_STMT_ERROR(stmt, CR_STATUS_ERROR_STMT_FETCH, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
if (stmt->state < MYSQL_STMT_WAITING_USE_OR_STORE || !stmt->field_count)
|
||||
{
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_STMT_ERROR(stmt, CR_FETCH_FIELD_COUNT_IS_ZERO, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
} else if (stmt->state== MYSQL_STMT_WAITING_USE_OR_STORE)
|
||||
{
|
||||
@ -3276,8 +3290,10 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
|
||||
|
||||
if (stmt->state < MYSQL_STMT_EXECUTED)
|
||||
{
|
||||
SET_CLIENT_ERROR(stmt->mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_ERROR(stmt->mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_ERROR(stmt->mysql, CR_STATUS_ERROR_STORE_RESULT, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_STMT_ERROR(stmt, CR_STATUS_ERROR_STORE_RESULT, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -3299,8 +3315,10 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
|
||||
}
|
||||
else if (stmt->mysql->status != MYSQL_STATUS_STMT_RESULT)
|
||||
{
|
||||
SET_CLIENT_ERROR(stmt->mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_ERROR(stmt->mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_ERROR(stmt->mysql, CR_STATUS_ERROR_NOT_STMT_RESULT, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_STMT_ERROR(stmt, CR_STATUS_ERROR_NOT_STMT_RESULT, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -3632,8 +3650,8 @@ my_bool cli_read_piece_result(MYSQL_STMT *stmt)
|
||||
int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
||||
{
|
||||
MYSQL *mysql= stmt->mysql;
|
||||
char *request;
|
||||
int ret;
|
||||
char *request = NULL;
|
||||
int ret = 0;
|
||||
size_t request_len= 0;
|
||||
FLT_DECLARE;
|
||||
|
||||
@ -3645,8 +3663,10 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
||||
|
||||
if (stmt->state < MYSQL_STMT_PREPARED)
|
||||
{
|
||||
SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_ERROR(mysql, CR_STATES_ERROR_NOT_PREPARED, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_STMT_ERROR(stmt, CR_STATES_ERROR_NOT_PREPARED, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -4064,6 +4084,7 @@ static ulong calculate_param_object_type_len(MYSQL *mysql, MYSQL_COMPLEX_BIND_OB
|
||||
static ulong calculate_param_array_type_len(MYSQL *mysql, MYSQL_COMPLEX_BIND_ARRAY *param)
|
||||
{
|
||||
ulong len;
|
||||
MYSQL_COMPLEX_BIND_OBJECT *param_tmp = (MYSQL_COMPLEX_BIND_OBJECT *)param;
|
||||
MYSQL_COMPLEX_BIND_HEADER *header = (MYSQL_COMPLEX_BIND_HEADER *)param->buffer;
|
||||
|
||||
//shcema_name
|
||||
@ -4073,15 +4094,19 @@ static ulong calculate_param_array_type_len(MYSQL *mysql, MYSQL_COMPLEX_BIND_ARR
|
||||
|
||||
//elem_type
|
||||
len += 1;
|
||||
if (MYSQL_TYPE_OBJECT == header->buffer_type) {
|
||||
MYSQL_COMPLEX_BIND_OBJECT sub_header;
|
||||
sub_header.owner_name = ((MYSQL_COMPLEX_BIND_OBJECT*)header)->owner_name;
|
||||
sub_header.type_name = ((MYSQL_COMPLEX_BIND_OBJECT*)header)->type_name;
|
||||
len += calculate_param_object_type_len(mysql, &sub_header);
|
||||
} else if (MYSQL_TYPE_ARRAY == header->buffer_type) {
|
||||
MYSQL_COMPLEX_BIND_ARRAY sub_header;
|
||||
sub_header.buffer = header->buffer;
|
||||
len += calculate_param_array_type_len(mysql, &sub_header);
|
||||
|
||||
//elem length may be zero
|
||||
if (param_tmp->length > 0) {
|
||||
if (MYSQL_TYPE_OBJECT == header->buffer_type) {
|
||||
MYSQL_COMPLEX_BIND_OBJECT sub_header;
|
||||
sub_header.owner_name = ((MYSQL_COMPLEX_BIND_OBJECT*)header)->owner_name;
|
||||
sub_header.type_name = ((MYSQL_COMPLEX_BIND_OBJECT*)header)->type_name;
|
||||
len += calculate_param_object_type_len(mysql, &sub_header);
|
||||
} else if (MYSQL_TYPE_ARRAY == header->buffer_type) {
|
||||
MYSQL_COMPLEX_BIND_ARRAY sub_header;
|
||||
sub_header.buffer = header->buffer;
|
||||
len += calculate_param_array_type_len(mysql, &sub_header);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
@ -4125,8 +4150,10 @@ int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
|
||||
|
||||
if (stmt->state < MYSQL_STMT_EXECUTED)
|
||||
{
|
||||
SET_CLIENT_ERROR(stmt->mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_ERROR(stmt->mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_ERROR(stmt->mysql, CR_STATUS_ERROR_STMT_NEXT_RESULT, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_STMT_ERROR(stmt, CR_STATUS_ERROR_STMT_NEXT_RESULT, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -4841,6 +4868,37 @@ my_bool get_use_ob_client_lob_locatorv2(MYSQL *mysql)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
my_bool determine_load_infiles(MYSQL *mysql)
|
||||
{
|
||||
my_bool bret = TRUE;
|
||||
int ival = LOAD_INFILES_AUTO_OPEN; //default is AUTO
|
||||
int tmp_val = 0;
|
||||
char* env = getenv("ENABLE_LOAD_INFILES");
|
||||
if (env) {
|
||||
tmp_val = atoi(env);
|
||||
if (tmp_val >= 0 && tmp_val < LOAD_INFILES_FLAY_MAX) {
|
||||
ival = tmp_val;
|
||||
}
|
||||
}
|
||||
if (ival == LOAD_INFILES_FORCE_OPEN) {
|
||||
bret = TRUE;
|
||||
} else if (ival == LOAD_INFILES_FORCE_CLOSE) {
|
||||
bret = FALSE;
|
||||
}
|
||||
if (mysql) {
|
||||
mysql->can_use_load_infiles = bret;
|
||||
}
|
||||
DBUG_RETURN(bret);
|
||||
}
|
||||
my_bool get_use_load_infiles(MYSQL *mysql)
|
||||
{
|
||||
if (mysql) {
|
||||
return mysql->can_use_load_infiles;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
uint8_t get_ob_lob_locator_version(void *lob)
|
||||
{
|
||||
uint8_t ver = 0;
|
||||
@ -4875,7 +4933,7 @@ int64_t get_ob_lob_payload_data_len(void *lob)
|
||||
int tmp_len = tmp->extern_header.payload_offset_+ tmp->extern_header.payload_size_;
|
||||
char *tmp_buf = tmp->data_;
|
||||
uint16_t ex_size = uint2korr(tmp_buf);
|
||||
int offset = MAX_OB_LOB_LOCATOR_HEADER_LENGTH + sizeof(uint16) + ex_size + tmp->extern_header.rowkey_size_ + sizeof(ObClientLobCommon) + sizeof(ObClientLobData);
|
||||
int offset = sizeof(uint16) + ex_size + tmp->extern_header.rowkey_size_ + sizeof(ObClientLobCommon) + sizeof(ObClientLobData);
|
||||
if (tmp_len > offset) {
|
||||
len = uint8korr(tmp_buf + offset - 8);
|
||||
}
|
||||
@ -4908,10 +4966,10 @@ int prepare_execute_v2(MYSQL *mysql, MYSQL_STMT* stmt, const char* query, MYSQL_
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int stmt_get_data_from_lobv2( MYSQL *mysql, void * lob, enum_field_types type,
|
||||
int64_t char_offset, int64_t byte_offset, int64_t char_len, int64_t byte_len, char *buf, const int64_t buf_len, int64_t *data_len, int64_t *act_len)
|
||||
int get_lob_data(MYSQL *mysql, void* lob, enum_field_types type,
|
||||
int64_t offset, int64_t* char_len, int64_t* byte_len, char *buf, const int64_t buf_len)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret = 0;
|
||||
const char *read_sql = "call DBMS_LOB.read(?, ?, ?, ?)";
|
||||
MYSQL_BIND param_bind[4];
|
||||
MYSQL_BIND param_res[2];
|
||||
@ -4919,30 +4977,98 @@ int stmt_get_data_from_lobv2( MYSQL *mysql, void * lob, enum_field_types type,
|
||||
int64_t length = 0;
|
||||
OB_LOB_LOCATOR_V2 *loblocator = (OB_LOB_LOCATOR_V2*)lob;
|
||||
|
||||
memset(param_bind, 0, sizeof(param_bind));
|
||||
param_bind[0].buffer = lob;
|
||||
param_bind[0].buffer_length = loblocator->extern_header.payload_size_ + loblocator->extern_header.payload_offset_ + MAX_OB_LOB_LOCATOR_HEADER_LENGTH;
|
||||
param_bind[0].buffer_type = type;
|
||||
param_bind[1].buffer = (char *)byte_len;
|
||||
param_bind[1].buffer_type = MYSQL_TYPE_LONGLONG;
|
||||
param_bind[2].buffer = (char *)&offset;
|
||||
param_bind[2].buffer_type = MYSQL_TYPE_LONGLONG;
|
||||
param_bind[3].is_null = ¶m_bind[3].is_null_value;
|
||||
*param_bind[3].is_null = 1;
|
||||
if (MYSQL_TYPE_ORA_CLOB == type) {
|
||||
param_bind[3].buffer_type = MYSQL_TYPE_VAR_STRING;
|
||||
} else {
|
||||
param_bind[3].buffer_type = MYSQL_TYPE_OB_RAW;
|
||||
}
|
||||
|
||||
//result
|
||||
memset(param_res, 0, sizeof(param_res));
|
||||
param_res[0].error = ¶m_res[0].error_value;
|
||||
param_res[0].is_null = ¶m_res[0].is_null_value;
|
||||
param_res[0].buffer = &length;
|
||||
param_res[0].buffer_type = MYSQL_TYPE_LONGLONG;
|
||||
param_res[1].error = ¶m_res[1].error_value;
|
||||
param_res[1].is_null = ¶m_res[1].is_null_value;
|
||||
param_res[1].length = ¶m_res[1].length_value;
|
||||
param_res[1].buffer = buf;
|
||||
param_res[1].buffer_length = buf_len;
|
||||
if (MYSQL_TYPE_ORA_CLOB == type) {
|
||||
param_res[1].buffer_type = MYSQL_TYPE_VAR_STRING;
|
||||
} else {
|
||||
param_res[1].buffer_type = MYSQL_TYPE_OB_RAW;
|
||||
}
|
||||
|
||||
if (NULL == (stmt = mysql_stmt_init(mysql))) {
|
||||
ret = -1;
|
||||
} else if (prepare_execute_v2(mysql, stmt, read_sql, param_bind)) {
|
||||
ret = -1;
|
||||
} else if (mysql_stmt_bind_result(stmt, param_res)) {
|
||||
ret = -1;
|
||||
} else {
|
||||
int64_t data_len = 0;
|
||||
ret = mysql_stmt_fetch(stmt);
|
||||
if (0 == ret) {
|
||||
*byte_len = param_res[1].length_value;
|
||||
*char_len = length;
|
||||
} else if (MYSQL_DATA_TRUNCATED == ret) {
|
||||
*byte_len = param_res[1].length_value;
|
||||
*char_len = length;
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
if (NULL != stmt) {
|
||||
mysql_stmt_close(stmt);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int stmt_get_data_from_lobv2( MYSQL *mysql, void * lob, enum_field_types type,
|
||||
int64_t char_offset, int64_t byte_offset, int64_t char_len, int64_t byte_len, char *buf, const int64_t buf_len, int64_t *data_len, int64_t *act_len)
|
||||
{
|
||||
#define DBMS_LOB_MAX_LENGTH 32766
|
||||
int ret = -1;
|
||||
int64_t length = 0;
|
||||
OB_LOB_LOCATOR_V2 *loblocator = (OB_LOB_LOCATOR_V2*)lob;
|
||||
|
||||
char_offset = char_offset;
|
||||
char_len = char_len;
|
||||
|
||||
if (!mysql) {
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
|
||||
SET_CLIENT_ERROR(mysql, CR_SERVER_LOST, unknown_sqlstate, NULL);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (NULL == lob) {
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, unknown_sqlstate, NULL);
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate, NULL);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (OBCLIENT_LOB_LOCATORV2 != get_ob_lob_locator_version(lob)) {
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, unknown_sqlstate, NULL);
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate, NULL);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (type != MYSQL_TYPE_ORA_CLOB && type != MYSQL_TYPE_ORA_BLOB) {
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, unknown_sqlstate, NULL);
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate, NULL);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (1 != loblocator->common.has_extern) {
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, unknown_sqlstate, NULL);
|
||||
SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate, NULL);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
*act_len = get_ob_lob_payload_data_len(loblocator);
|
||||
|
||||
if (1 == loblocator->common.is_inrow_) {
|
||||
length = byte_len > buf_len ? buf_len : byte_len;
|
||||
length = length > loblocator->extern_header.payload_size_ ? loblocator->extern_header.payload_size_ : length;
|
||||
@ -4953,106 +5079,46 @@ int stmt_get_data_from_lobv2( MYSQL *mysql, void * lob, enum_field_types type,
|
||||
*act_len = loblocator->extern_header.payload_size_;
|
||||
ret = 0;
|
||||
} else {
|
||||
int64_t tmp_len = byte_len + 1;
|
||||
char *tmp_buf = calloc(1, byte_len);
|
||||
if (NULL != tmp_buf) {
|
||||
//params
|
||||
memset(param_bind, 0, sizeof(param_bind));
|
||||
param_bind[0].buffer = lob;
|
||||
param_bind[0].buffer_length = loblocator->extern_header.payload_size_ + loblocator->extern_header.payload_offset_ + MAX_OB_LOB_LOCATOR_HEADER_LENGTH;
|
||||
param_bind[0].buffer_type = type;
|
||||
param_bind[1].buffer = (char *)&tmp_len;
|
||||
param_bind[1].buffer_type = MYSQL_TYPE_LONGLONG;
|
||||
param_bind[2].buffer = (char *)&byte_offset;
|
||||
param_bind[2].buffer_type = MYSQL_TYPE_LONGLONG;
|
||||
param_bind[3].is_null = ¶m_bind[3].is_null_value;
|
||||
*param_bind[3].is_null = 1;
|
||||
if (MYSQL_TYPE_ORA_CLOB == type) {
|
||||
param_bind[3].buffer_type = MYSQL_TYPE_VAR_STRING;
|
||||
char *pdata = buf;
|
||||
int64_t amtp = 0;
|
||||
int64_t read_len = 0;
|
||||
int64_t char_len;
|
||||
int64_t buf_use = 0;
|
||||
|
||||
do {
|
||||
if (byte_len - amtp > DBMS_LOB_MAX_LENGTH) {
|
||||
read_len = DBMS_LOB_MAX_LENGTH;
|
||||
} else if (byte_len - amtp > 0) {
|
||||
read_len = (byte_len - amtp);
|
||||
} else {
|
||||
param_bind[3].buffer_type = MYSQL_TYPE_OB_RAW;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
//result
|
||||
memset(param_res, 0, sizeof(param_res));
|
||||
param_res[0].error = ¶m_res[0].error_value;
|
||||
param_res[0].is_null = ¶m_res[0].is_null_value;
|
||||
param_res[0].buffer = &length;
|
||||
param_res[0].buffer_type = MYSQL_TYPE_LONGLONG;
|
||||
param_res[1].error = ¶m_res[1].error_value;
|
||||
param_res[1].is_null = ¶m_res[1].is_null_value;
|
||||
param_res[1].length = ¶m_res[1].length_value;
|
||||
param_res[1].buffer = tmp_buf;
|
||||
param_res[1].buffer_length = tmp_len;
|
||||
if (MYSQL_TYPE_ORA_CLOB == type) {
|
||||
param_res[1].buffer_type = MYSQL_TYPE_VAR_STRING;
|
||||
if (0 != get_lob_data(mysql, lob, type, byte_offset, &char_len, &read_len, pdata, buf_len - buf_use)) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (type == MYSQL_TYPE_ORA_CLOB) {
|
||||
byte_offset += char_len;
|
||||
} else {
|
||||
param_res[1].buffer_type = MYSQL_TYPE_OB_RAW;
|
||||
byte_offset += read_len;
|
||||
}
|
||||
|
||||
if (NULL == (stmt = mysql_stmt_init(mysql))) {
|
||||
ret = -1;
|
||||
} else if (prepare_execute_v2(mysql, stmt, read_sql, param_bind)) {
|
||||
ret = -1;
|
||||
} else if (mysql_stmt_bind_result(stmt, param_res)) {
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = mysql_stmt_fetch(stmt);
|
||||
if (0 == ret) {
|
||||
*data_len = param_res[1].length_value;
|
||||
*act_len = *data_len;
|
||||
if (*data_len > byte_len) {
|
||||
*data_len = byte_len > buf_len ? buf_len : byte_len;
|
||||
} else {
|
||||
*data_len = *data_len > buf_len ? buf_len : *data_len;
|
||||
}
|
||||
memcpy(buf, tmp_buf, *data_len);
|
||||
}
|
||||
}
|
||||
amtp += char_len;
|
||||
pdata += read_len;
|
||||
buf_use += read_len;
|
||||
*data_len += read_len;
|
||||
|
||||
if (NULL != stmt) {
|
||||
mysql_stmt_close(stmt);
|
||||
if (buf_len - buf_use <= 0 || buf_use >= *act_len) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
free(tmp_buf);
|
||||
tmp_buf = NULL;
|
||||
}
|
||||
} while (read_len >= DBMS_LOB_MAX_LENGTH);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
my_bool set_nls_format(MYSQL *mysql)
|
||||
{
|
||||
my_bool bret = TRUE;
|
||||
if (mysql->oracle_mode) {
|
||||
char *nls_date_format = getenv("NLS_DATE_FORMAT");
|
||||
char *nls_timestamp_format = getenv("NLS_TIMESTAMP_FORMAT");
|
||||
char *nls_timestamp_tz_format = getenv("NLS_TIMESTAMP_TZ_FORMAT");
|
||||
|
||||
if (NULL != nls_date_format) {
|
||||
char change_date_format_sql[100];
|
||||
snprintf(change_date_format_sql, 100, "ALTER SESSION SET NLS_DATE_FORMAT='%s';", nls_date_format);
|
||||
if (mysql_query(mysql, change_date_format_sql)) {
|
||||
bret = FALSE;
|
||||
}
|
||||
}
|
||||
if (bret && NULL != nls_timestamp_format) {
|
||||
char change_timestamp_format_sql[100];
|
||||
snprintf(change_timestamp_format_sql, 100, "ALTER SESSION SET NLS_TIMESTAMP_FORMAT='%s';", nls_timestamp_format);
|
||||
if (mysql_query(mysql, change_timestamp_format_sql)) {
|
||||
bret = FALSE;
|
||||
}
|
||||
}
|
||||
if (bret && NULL != nls_timestamp_tz_format) {
|
||||
char change_timestamp_tz_format_sql[100];
|
||||
snprintf(change_timestamp_tz_format_sql, 100, "ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='%s';", nls_timestamp_tz_format);
|
||||
if (mysql_query(mysql, change_timestamp_tz_format_sql)) {
|
||||
bret = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bret;
|
||||
}
|
||||
/*
|
||||
* judge where can use prepare_execute protocol
|
||||
* use version to judge
|
||||
@ -5775,7 +5841,7 @@ static int stmt_read_prepare_execute_response(MYSQL_STMT* stmt)
|
||||
}
|
||||
if (param_count != 0)
|
||||
{
|
||||
if (stmt->is_handle_returning_into && stmt->field_count + stmt->param_count == param_count)
|
||||
if (stmt->is_handle_returning_into /*&& stmt->field_count + stmt->param_count == param_count*/)
|
||||
{
|
||||
/* It needs to exec prepare operation for the sql with piece data send and returning ... into, Like:
|
||||
* UPDATE TABLE ta SET c1 = :v1, c2 =:v2, c3 = :v3 RETURNING c0 INTO :c0
|
||||
@ -5875,8 +5941,10 @@ int STDCALL mysql_stmt_execute_v2(MYSQL_STMT *stmt,
|
||||
|
||||
if (stmt->state < MYSQL_STMT_PREPARED)
|
||||
{
|
||||
SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_ERROR(mysql, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
//SET_CLIENT_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_ERROR(mysql, CR_STATES_ERROR_NOT_PREPARED_EXECUTE_V2, SQLSTATE_UNKNOWN, 0);
|
||||
SET_OB_CLIENT_STMT_ERROR(stmt, CR_STATES_ERROR_NOT_PREPARED_EXECUTE_V2, SQLSTATE_UNKNOWN, 0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <time.h>
|
||||
|
||||
#include <limits.h>
|
||||
union ft64 {
|
||||
FILETIME ft;
|
||||
__int64 i64;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "mariadb_com.h"
|
||||
#include "ob_protocol20.h"
|
||||
#include "ob_serialize.h"
|
||||
#include "ob_utils.h"
|
||||
|
||||
#define TYPE_LENGTH 2
|
||||
#define LEN_LENGTH 4
|
||||
@ -103,14 +104,6 @@ inline void flt_set_send_trans_flag(FLTInfo *flt, my_bool flag)
|
||||
}
|
||||
}
|
||||
|
||||
static inline int64_t get_current_time_us()
|
||||
{
|
||||
struct timeval tv;
|
||||
// todo: Here to be compatible with windows
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
}
|
||||
|
||||
static inline double flt_get_pct(uint64_t *seed)
|
||||
{
|
||||
uint64_t rand64;
|
||||
@ -1359,9 +1352,9 @@ int uuid4_init(uint64_t *seed, size_t seed_size) {
|
||||
}
|
||||
|
||||
|
||||
UUID uuid4_generate(uint64_t *seed) {
|
||||
OBCLIENT_UUID uuid4_generate(uint64_t *seed) {
|
||||
uint64_t word;
|
||||
UUID ret;
|
||||
OBCLIENT_UUID ret;
|
||||
/* get random */
|
||||
word = xorshift128plus(seed);
|
||||
// word[1] = xorshift128plus(seed);
|
||||
@ -1826,7 +1819,7 @@ void reset_tag(ObTrace *trace, ObSpanCtx *span, ObTagCtx *tag)
|
||||
}
|
||||
}
|
||||
|
||||
int serialize_UUID(char *buf, const int64_t buf_len, int64_t *pos, UUID *uuid)
|
||||
int serialize_UUID(char *buf, const int64_t buf_len, int64_t *pos, OBCLIENT_UUID *uuid)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(encode_i64(buf, buf_len, pos, uuid->high_))) {
|
||||
@ -1837,7 +1830,7 @@ int serialize_UUID(char *buf, const int64_t buf_len, int64_t *pos, UUID *uuid)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int deserialize_UUID(const char *buf, const int64_t buf_len, int64_t *pos, UUID *uuid)
|
||||
int deserialize_UUID(const char *buf, const int64_t buf_len, int64_t *pos, OBCLIENT_UUID *uuid)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(decode_i64(buf, buf_len, pos, (int64_t *)(&uuid->high_)))) {
|
||||
@ -1848,7 +1841,7 @@ int deserialize_UUID(const char *buf, const int64_t buf_len, int64_t *pos, UUID
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_TO_STRING_FUNC_FOR(UUID)
|
||||
DEFINE_TO_STRING_FUNC_FOR(OBCLIENT_UUID)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t tmp_pos = *pos;
|
||||
|
562
libmariadb/ob_load_balance.c
Normal file
562
libmariadb/ob_load_balance.c
Normal file
@ -0,0 +1,562 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "mysql.h"
|
||||
#include "ob_rwlock.h"
|
||||
#include "ma_global.h"
|
||||
#include "errmsg.h"
|
||||
#include "ob_utils.h"
|
||||
#include "ob_tnsname.h"
|
||||
#include "ob_load_balance.h"
|
||||
|
||||
//#define DEBUG_LOAD_BALANCE 1
|
||||
#define CONNECT_CNT_INIT 32
|
||||
|
||||
typedef enum _enum_ob_lb_address_state
|
||||
{
|
||||
OBCLIENT_LB_BLACK, // black
|
||||
OBCLIENT_LB_WHITE, // white
|
||||
OBCLIENT_LB_GRAY, // gray
|
||||
OBCLIENT_LB_MAX_STATE
|
||||
}ObLbAddressState;
|
||||
|
||||
typedef struct _st_ob_lb_address {
|
||||
char host[128];
|
||||
int port;
|
||||
int weight;
|
||||
int state;
|
||||
int64_t black_time;
|
||||
int64_t last_time;
|
||||
void *connect_info;
|
||||
}ObLbAddress;
|
||||
|
||||
typedef struct _st_ob_lb_address_list {
|
||||
ObClientLBOption option; //ROTATION,SERVERAFFINITY,RANDOM
|
||||
unsigned int count; //count
|
||||
unsigned int rotation_flag;
|
||||
ObLbAddress *add_arr;
|
||||
}ObLbAddressList;
|
||||
|
||||
typedef struct _st_connect_info {
|
||||
int connect_cnt;
|
||||
int connect_max;
|
||||
int64_t *connect_list;
|
||||
}ConnectInfo;
|
||||
|
||||
static void init_connect_info(ObLbAddress *address) {
|
||||
if (NULL == address->connect_info) {
|
||||
ConnectInfo *p = malloc(sizeof(ConnectInfo));
|
||||
if (NULL != p) {
|
||||
p->connect_cnt = 0;
|
||||
p->connect_max = CONNECT_CNT_INIT;
|
||||
p->connect_list = malloc(sizeof(int64_t) * p->connect_max);
|
||||
}
|
||||
address->connect_info = p;
|
||||
} else {
|
||||
ConnectInfo *p = (ConnectInfo*)(address->connect_info);
|
||||
if (p->connect_cnt >= p->connect_max - 1) {
|
||||
p->connect_max *= 2;
|
||||
p->connect_list = realloc(p->connect_list, sizeof(int64_t) * p->connect_max);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void release_connect_info(ObLbAddress *address) {
|
||||
if (NULL != address->connect_info) {
|
||||
ConnectInfo *p = (ConnectInfo *)(address->connect_info);
|
||||
if (NULL != p->connect_list) {
|
||||
free(p->connect_list);
|
||||
p->connect_list = NULL;
|
||||
}
|
||||
free(address->connect_info);
|
||||
address->connect_info = NULL;
|
||||
}
|
||||
}
|
||||
static my_bool check_connect_info(ObLbAddress* address) {
|
||||
my_bool rst = 1;
|
||||
if (NULL != address->connect_info) {
|
||||
ConnectInfo *p = (ConnectInfo *)(address->connect_info);
|
||||
rst = NULL != p->connect_list ? 1 : 0;
|
||||
} else {
|
||||
rst = 0;
|
||||
}
|
||||
return rst;
|
||||
}
|
||||
|
||||
static void append_ob_address_connect_info(ObLbAddress * address) {
|
||||
init_connect_info(address);
|
||||
if (check_connect_info(address)) {
|
||||
ConnectInfo *p = (ConnectInfo*)(address->connect_info);
|
||||
int64_t *tmp = (int64_t*)p->connect_list;
|
||||
tmp[p->connect_cnt] = get_current_time_us();
|
||||
p->connect_cnt++;
|
||||
address->last_time = get_current_time_us();
|
||||
} else {
|
||||
address->state = OBCLIENT_LB_BLACK;
|
||||
address->black_time = get_current_time_us();
|
||||
}
|
||||
}
|
||||
|
||||
static ObLbAddress* get_ob_address_by_address_list(ObLbAddressList *addr_list)
|
||||
{
|
||||
ObLbAddress* rst = NULL;
|
||||
unsigned int cnt = addr_list->count;
|
||||
unsigned int i = 0, j = 0;
|
||||
unsigned int weight = 0;
|
||||
|
||||
if (cnt > 0) {
|
||||
int *idxarr = calloc(1, sizeof(int) * cnt);
|
||||
if (idxarr != NULL) {
|
||||
int valid_cnt = 0;
|
||||
memset(idxarr, 0, sizeof(int) * cnt);
|
||||
for (i = 0; i < cnt; i++) {
|
||||
if (addr_list->add_arr[i].weight <= 0) {
|
||||
addr_list->add_arr[i].weight = 1;
|
||||
}
|
||||
if (OBCLIENT_LB_WHITE == addr_list->add_arr[i].state) {
|
||||
idxarr[valid_cnt] = i;
|
||||
weight += addr_list->add_arr[i].weight;
|
||||
valid_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_cnt == 0) {
|
||||
rst = NULL;
|
||||
} else if (valid_cnt == 1) {
|
||||
rst = &(addr_list->add_arr[idxarr[0]]);
|
||||
} else {
|
||||
switch (addr_list->option) {
|
||||
case OBCLIENT_LB_OPTION_RANDOM: {
|
||||
unsigned int random_index = (unsigned int)rand() % valid_cnt;
|
||||
rst = &(addr_list->add_arr[idxarr[random_index]]);
|
||||
break;
|
||||
}
|
||||
case OBCLIENT_LB_OPTION_SERVERAFFINITY: {
|
||||
int rand_number = (int)rand() % weight + 1;
|
||||
int index = 0;
|
||||
for (index = 0; index < valid_cnt; ++index) {
|
||||
rand_number -= addr_list->add_arr[idxarr[index]].weight;
|
||||
if (index == valid_cnt - 1 || rand_number <= 0) {
|
||||
rst = &(addr_list->add_arr[idxarr[index]]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OBCLIENT_LB_OPTION_ROTATION: {
|
||||
for (i = addr_list->rotation_flag%cnt; i < cnt; i++) {
|
||||
addr_list->rotation_flag++;
|
||||
if (OBCLIENT_LB_WHITE == addr_list->add_arr[i].state) {
|
||||
rst = &(addr_list->add_arr[i]);
|
||||
addr_list->add_arr[i].last_time = get_current_time_us();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(idxarr);
|
||||
|
||||
if (NULL != rst) {
|
||||
append_ob_address_connect_info(rst);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rst;
|
||||
}
|
||||
|
||||
static void check_ob_address_black(ObLbAddress * address, ObClientLbConfig *config) {
|
||||
if (!check_connect_info(address))
|
||||
address->state = OBCLIENT_LB_BLACK;
|
||||
|
||||
if (OBCLIENT_LB_WHITE == address->state) {
|
||||
ConnectInfo *info = (ConnectInfo *)address->connect_info;
|
||||
switch (config->black_append_strategy) {
|
||||
case OBCLIENT_LB_OPTION_NORMAL: {
|
||||
address->state = OBCLIENT_LB_BLACK;
|
||||
address->black_time = get_current_time_us();
|
||||
#ifdef DEBUG_LOAD_BALANCE
|
||||
printf("white 2 black: %s, %d\n", address->host, address->port);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case OBCLIENT_LB_OPTION_RETRY_DERUATION: {
|
||||
int idx = 0;
|
||||
int newsize = 0;
|
||||
int len = info->connect_cnt;
|
||||
int64_t *list = info->connect_list;
|
||||
int64_t curtime = get_current_time_us();
|
||||
int64_t duration = config->black_append_duration * 1000;// ��λmsתΪus
|
||||
for (idx = 0; idx < len; idx++) {
|
||||
if (curtime - list[idx] <= duration) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
newsize = len - idx;
|
||||
if (0 != idx) {
|
||||
int64_t* offset = info->connect_list + idx;
|
||||
memmove(info->connect_list, offset, newsize);
|
||||
}
|
||||
info->connect_cnt = newsize;
|
||||
if (info->connect_cnt >= config->black_append_retrytimes) {
|
||||
address->state = OBCLIENT_LB_BLACK;
|
||||
address->black_time = get_current_time_us();
|
||||
#ifdef DEBUG_LOAD_BALANCE
|
||||
printf("white 2 black: %s, %d\n", address->host, address->port);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void check_ob_address_white(ObLbAddressList * addr_list, ObClientLbConfig *config) {
|
||||
unsigned int i = 0;
|
||||
int64_t curtime = get_current_time_us();
|
||||
int64_t timeout = config->black_remove_timeout * 1000;
|
||||
ObLbAddress* address = addr_list->add_arr;
|
||||
if (timeout > 0) {
|
||||
for (i = 0; i < addr_list->count; i++) {
|
||||
if (OBCLIENT_LB_BLACK == address[i].state) {
|
||||
if (curtime - address[i].black_time >= timeout) {
|
||||
address[i].state = OBCLIENT_LB_WHITE;
|
||||
#ifdef DEBUG_LOAD_BALANCE
|
||||
printf("black 2 white: %s, %d\n", address->host, address->port);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int init_oblb_addresslist(ObLbAddressList* list, ObClientLbAddressList* addrlist) {
|
||||
int ret = 0;
|
||||
|
||||
if (!list || !addrlist || !addrlist->address_list || addrlist->address_list_count <= 0) {
|
||||
ret = -1;
|
||||
} else if (OB_ISNULL(list->add_arr = (ObLbAddress*)malloc(addrlist->address_list_count * sizeof(ObLbAddress)))) {
|
||||
ret = -1;
|
||||
} else {
|
||||
unsigned int i = 0;
|
||||
memset(list->add_arr, 0, addrlist->address_list_count * sizeof(ObLbAddress));
|
||||
for (i = 0; i < addrlist->address_list_count; i++) {
|
||||
memcpy(list->add_arr[i].host, addrlist->address_list[i].host, strlen(addrlist->address_list[i].host));
|
||||
list->add_arr[i].port = addrlist->address_list[i].port;
|
||||
list->add_arr[i].weight = 1;
|
||||
list->add_arr[i].state = OBCLIENT_LB_WHITE;
|
||||
}
|
||||
list->count = addrlist->address_list_count;
|
||||
list->rotation_flag = 0;
|
||||
list->option = OBCLIENT_LB_OPTION_ROTATION;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int init_oblb_addresslist_tns(ObLbAddressList* list, ObClientAddressList* addrlist) {
|
||||
int ret = 0;
|
||||
if (!list || !addrlist || !addrlist->address || addrlist->address_count <= 0) {
|
||||
ret = -1;
|
||||
} else if (OB_ISNULL(list->add_arr = (ObLbAddress*)malloc(addrlist->address_count * sizeof(ObLbAddress)))){
|
||||
ret = -1;
|
||||
} else {
|
||||
unsigned int i = 0;
|
||||
memset(list->add_arr, 0, addrlist->address_count * sizeof(ObLbAddress));
|
||||
for (i = 0; i < addrlist->address_count; i++) {
|
||||
memcpy(list->add_arr[i].host, addrlist->address[i].host, addrlist->address[i].host_len);
|
||||
list->add_arr[i].port = addrlist->address[i].port;
|
||||
list->add_arr[i].weight = addrlist->address[i].weight;
|
||||
list->add_arr[i].state = OBCLIENT_LB_WHITE;
|
||||
}
|
||||
list->count = addrlist->address_count;
|
||||
list->rotation_flag = 0;
|
||||
list->option = addrlist->oblb_strategy;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, ObClientLbConfig *config,
|
||||
const char *user, const char *passwd, const char *db, const char *unix_socket, unsigned long client_flag, ObClientLbAddress* success)
|
||||
{
|
||||
ObLbAddress *address = NULL;
|
||||
MYSQL* tmp = NULL;
|
||||
unsigned int i = 0;
|
||||
int err = 0;
|
||||
|
||||
unsigned int mysql_connect_timeout = 0;
|
||||
unsigned int mysql_read_timeout = 0;
|
||||
unsigned int mysql_write_timeout = 0;
|
||||
my_bool mysql_is_local_infile = 0;
|
||||
unsigned int mysql_local_infile = 0;
|
||||
unsigned int mysql_opt_protocol = 0;
|
||||
my_bool mysql_is_proxy_mode = 0;
|
||||
my_bool mysql_is_compress = 0;
|
||||
my_bool mysql_opt_secure_auth = 0;
|
||||
|
||||
char *mysql_init_command = NULL;
|
||||
char *mysql_charset_name = NULL;
|
||||
char* mysql_opt_plugin_dir = NULL;
|
||||
char* mysql_opt_default_auth = NULL;
|
||||
char* mysql_program_name = NULL;
|
||||
char* mysql_ob_proxy_user = NULL;
|
||||
my_bool mysql_opt_interactive = 0;
|
||||
my_bool mysql_report_data_truncation = 0;
|
||||
my_bool mysql_opt_reconnect = 0;
|
||||
|
||||
my_bool mysql_opt_use_ssl = 0;
|
||||
my_bool mysql_opt_ssl_verify_server_cert = 0;
|
||||
char *mysql_opt_ssl_key = NULL;
|
||||
char *mysql_opt_ssl_cert = NULL;
|
||||
char *mysql_opt_ssl_ca = NULL;
|
||||
char *mysql_opt_ssl_capath = NULL;
|
||||
char *mysql_opt_ssl_cipher = NULL;
|
||||
char *mysql_opt_ssl_crl = NULL;
|
||||
char *mysql_opt_ssl_crlpath = NULL;
|
||||
char *mysql_opt_tls_version = NULL;
|
||||
|
||||
if (mysql == NULL || addr_list == NULL || config == NULL || addr_list->add_arr == NULL || addr_list->count <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (addr_list->option != OBCLIENT_LB_OPTION_RANDOM &&
|
||||
addr_list->option != OBCLIENT_LB_OPTION_ROTATION &&
|
||||
addr_list->option != OBCLIENT_LB_OPTION_SERVERAFFINITY) {
|
||||
addr_list->option = OBCLIENT_LB_OPTION_ROTATION;
|
||||
}
|
||||
if (config->black_append_strategy != OBCLIENT_LB_OPTION_NORMAL &&
|
||||
config->black_append_strategy != OBCLIENT_LB_OPTION_RETRY_DERUATION) {
|
||||
config->black_append_strategy = OBCLIENT_LB_OPTION_NORMAL;
|
||||
}
|
||||
if (config->retry_all_downs <= 0) config->retry_all_downs = addr_list->count;
|
||||
if (config->black_append_duration <= 0) config->black_append_duration = 60 * 1000;
|
||||
if (config->black_append_retrytimes <= 0) config->black_append_retrytimes = 1;
|
||||
|
||||
for (i = 0; i < addr_list->count; i++) {
|
||||
addr_list->add_arr[i].state = OBCLIENT_LB_WHITE;
|
||||
addr_list->add_arr[i].connect_info = NULL;
|
||||
if (addr_list->add_arr[i].weight <= 0) {
|
||||
addr_list->add_arr[i].weight = 1;
|
||||
}
|
||||
init_connect_info(&(addr_list->add_arr[i]));
|
||||
}
|
||||
|
||||
//init mysql options
|
||||
mysql_connect_timeout = config->mysql_connect_timeout;
|
||||
mysql_read_timeout = config->mysql_read_timeout;
|
||||
mysql_write_timeout = config->mysql_write_timeout;
|
||||
mysql_is_proxy_mode = config->mysql_is_proxy_mode;
|
||||
mysql_init_command = config->mysql_init_command;
|
||||
mysql_charset_name = config->mysql_charset_name;
|
||||
mysql_is_compress = config->mysql_is_compress;
|
||||
mysql_is_local_infile = config->mysql_is_local_infile;
|
||||
mysql_local_infile = config->mysql_local_infile;
|
||||
mysql_opt_protocol = config->mysql_opt_protocol;
|
||||
mysql_opt_plugin_dir = config->mysql_opt_plugin_dir;
|
||||
mysql_ob_proxy_user = config->mysql_ob_proxy_user;
|
||||
mysql_opt_default_auth = config->mysql_opt_default_auth;
|
||||
mysql_program_name = config->mysql_program_name;
|
||||
mysql_opt_secure_auth = config->mysql_opt_secure_auth;
|
||||
mysql_opt_interactive = config->mysql_opt_interactive;
|
||||
mysql_report_data_truncation = config->mysql_report_data_truncation;
|
||||
mysql_opt_reconnect = config->mysql_opt_reconnect;
|
||||
|
||||
mysql_opt_use_ssl = config->mysql_opt_use_ssl;
|
||||
mysql_opt_ssl_verify_server_cert = config->mysql_opt_ssl_verify_server_cert;
|
||||
mysql_opt_ssl_key = config->mysql_opt_ssl_key;
|
||||
mysql_opt_ssl_cert = config->mysql_opt_ssl_cert;
|
||||
mysql_opt_ssl_ca = config->mysql_opt_ssl_ca;
|
||||
mysql_opt_ssl_capath = config->mysql_opt_ssl_capath;
|
||||
mysql_opt_ssl_cipher = config->mysql_opt_ssl_cipher;
|
||||
mysql_opt_ssl_crl = config->mysql_opt_ssl_crl;
|
||||
mysql_opt_ssl_crlpath = config->mysql_opt_ssl_crlpath;
|
||||
mysql_opt_tls_version = config->mysql_opt_tls_version;
|
||||
|
||||
do {
|
||||
//check address white
|
||||
check_ob_address_white(addr_list, config);
|
||||
|
||||
//get address
|
||||
if (NULL == (address = get_ob_address_by_address_list(addr_list))) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (OBCLIENT_LB_WHITE != address->state) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOAD_BALANCE
|
||||
printf("host:%s,port:%d,state:%d\n", address->host, address->port, address->state);
|
||||
#endif
|
||||
|
||||
//mysql options
|
||||
if (mysql_connect_timeout > 0)
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &mysql_connect_timeout);
|
||||
if (mysql_read_timeout > 0)
|
||||
mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, &mysql_read_timeout);
|
||||
if (mysql_write_timeout > 0)
|
||||
mysql_options(mysql, MYSQL_OPT_WRITE_TIMEOUT, &mysql_write_timeout);
|
||||
if (mysql_is_proxy_mode)
|
||||
mysql->ob_server_version = 0xfe;
|
||||
if (mysql_init_command && *mysql_init_command)
|
||||
mysql_options(mysql, MYSQL_INIT_COMMAND, mysql_init_command);
|
||||
if (mysql_charset_name && *mysql_charset_name)
|
||||
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, mysql_charset_name);
|
||||
if (mysql_is_compress)
|
||||
mysql_options(mysql, MYSQL_OPT_COMPRESS, NullS);
|
||||
if (mysql_is_local_infile)
|
||||
mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, (char*)&mysql_local_infile);
|
||||
if (mysql_opt_protocol)
|
||||
mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char*)&mysql_opt_protocol);
|
||||
if (mysql_opt_plugin_dir && *mysql_opt_plugin_dir)
|
||||
mysql_options(mysql, MYSQL_PLUGIN_DIR, mysql_opt_plugin_dir);
|
||||
if (mysql_opt_default_auth && *mysql_opt_default_auth)
|
||||
mysql_options(mysql, MYSQL_DEFAULT_AUTH, mysql_opt_default_auth);
|
||||
if (mysql_program_name && *mysql_program_name) {
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
|
||||
mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", mysql_program_name);
|
||||
}
|
||||
if (mysql_ob_proxy_user && *mysql_ob_proxy_user)
|
||||
mysql_options(mysql, OB_OPT_PROXY_USER, mysql_ob_proxy_user);
|
||||
if (mysql_opt_secure_auth)
|
||||
mysql_options(mysql, MYSQL_SECURE_AUTH, (char *)&mysql_opt_secure_auth);
|
||||
if (mysql_opt_interactive)
|
||||
mysql_options(mysql, MARIADB_OPT_INTERACTIVE, (char *)&mysql_opt_interactive);
|
||||
if (mysql_report_data_truncation)
|
||||
mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, (char *)&mysql_report_data_truncation);
|
||||
if (mysql_opt_reconnect)
|
||||
mysql_options(mysql, MYSQL_OPT_RECONNECT, (char *)&mysql_opt_reconnect);
|
||||
|
||||
if (mysql_opt_use_ssl) {
|
||||
mysql_ssl_set(mysql, mysql_opt_ssl_key, mysql_opt_ssl_cert, mysql_opt_ssl_ca, mysql_opt_ssl_capath, mysql_opt_ssl_cipher);
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_CRL, mysql_opt_ssl_crl);
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, mysql_opt_ssl_crlpath);
|
||||
mysql_options(mysql, MARIADB_OPT_TLS_VERSION, mysql_opt_tls_version);
|
||||
}
|
||||
if (mysql_opt_ssl_verify_server_cert)
|
||||
mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (char*)&mysql_opt_ssl_verify_server_cert);
|
||||
|
||||
//connect to server
|
||||
if (NULL != (tmp = mysql_real_connect(mysql, address->host, user, passwd, db, address->port, unix_socket, client_flag))) {
|
||||
//connect success
|
||||
if (success) {
|
||||
memcpy(success->host, address->host, strlen(address->host));
|
||||
success->port = address->port;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
//connect fail, user/passwd is error break;
|
||||
err = mysql_errno(mysql);
|
||||
if (1045 == err) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//check black
|
||||
check_ob_address_black(address, config);
|
||||
|
||||
config->retry_all_downs--;
|
||||
} while (address && config->retry_all_downs > 0);
|
||||
|
||||
//release connect
|
||||
for (i = 0; i < addr_list->count; i++) {
|
||||
release_connect_info(&(addr_list->add_arr[i]));
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static MYSQL* connect_by_tnsname(MYSQL* mysql, const char* tns_name, ObClientLbConfig * config,
|
||||
const char *user, const char* passwd, const char *db, const char* unix_socket, unsigned long client_flag, ObClientLbAddress *success)
|
||||
{
|
||||
int ret = 0;
|
||||
MYSQL *tmp = NULL;
|
||||
my_bool find = 0;
|
||||
ObClientTns tns;
|
||||
const char *sid = db;
|
||||
char new_user_name[256] = { 0 };
|
||||
int user_len = strlen((const char *)user ? user : "");
|
||||
|
||||
if (OB_FAIL(ObClientTnsInit(&tns))) {
|
||||
tmp = NULL;
|
||||
} else if (OB_FAIL(ObClientTnsBuild(&tns, tns_name, strlen(tns_name), &find))) {
|
||||
tmp = NULL;
|
||||
} else if (1 != find || !tns.tns_service || !tns.tns_service->description || tns.tns_service->description_count == 0) {
|
||||
tmp = NULL;
|
||||
} else {
|
||||
unsigned int i = 0;
|
||||
ObClientDescription *des = tns.tns_service->description;
|
||||
#ifdef DEBUG_LOAD_BALANCE
|
||||
ObClientTnsDisplay(&tns);
|
||||
#endif
|
||||
|
||||
strncpy(new_user_name, (const char *)user ? user : "", user_len);
|
||||
|
||||
if (des && des->connect_data) {
|
||||
if (!des->connect_data->use_default_sid) {
|
||||
sid = des->connect_data->service_name;
|
||||
}
|
||||
if (des->connect_data->user_extra_info_len > 0) {
|
||||
strncpy(new_user_name + user_len, (const char *)des->connect_data->user_extra_info, des->connect_data->user_extra_info_len);
|
||||
}
|
||||
}
|
||||
|
||||
//tns config
|
||||
config->retry_all_downs = des->retry_all_downs;
|
||||
config->black_remove_strategy = des->black_list_conf.remove_strategy;
|
||||
config->black_remove_timeout = des->black_list_conf.remove_timeout;
|
||||
config->black_append_strategy = des->black_list_conf.append_strategy;
|
||||
config->black_append_duration = des->black_list_conf.duration;
|
||||
config->black_append_retrytimes = des->black_list_conf.retry_times;
|
||||
|
||||
for (i = 0; i < des->address_list_count; i++) {
|
||||
ObLbAddressList list;
|
||||
memset(&list, 0, sizeof(list));
|
||||
#ifdef DEBUG_LOAD_BALANCE
|
||||
printf("------------------------------------------\n");
|
||||
#endif
|
||||
|
||||
if (OB_SUCC(init_oblb_addresslist_tns(&list, &(des->address_list[i])))) {
|
||||
tmp = connect_by_addresslist(mysql, &list, config, new_user_name, passwd, sid, unix_socket, client_flag, success);
|
||||
}
|
||||
if (list.add_arr) {
|
||||
free(list.add_arr);
|
||||
list.add_arr = NULL;
|
||||
list.count = 0;
|
||||
}
|
||||
if (tmp) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ObClientTnsClear(&tns);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
MYSQL* ob_mysql_real_connect(MYSQL* mysql, const char* tns_name, ObClientLbAddressList *addr_list, ObClientLbConfig *config,
|
||||
const char *user, const char *passwd, const char *db, const char *unix_socket, unsigned long client_flag, ObClientLbAddress* success)
|
||||
{
|
||||
int ret = 0;
|
||||
MYSQL *tmp = NULL;
|
||||
|
||||
if (tns_name && *tns_name) {
|
||||
tmp = connect_by_tnsname(mysql, tns_name, config, user, passwd, db, unix_socket, client_flag, success);
|
||||
} else {
|
||||
ObLbAddressList list;
|
||||
memset(&list, 0, sizeof(list));
|
||||
if (OB_SUCC(init_oblb_addresslist(&list, addr_list))) {
|
||||
tmp = connect_by_addresslist(mysql, &list, config, user, passwd, db, unix_socket, client_flag, success);
|
||||
}
|
||||
if (list.add_arr) {
|
||||
free(list.add_arr);
|
||||
list.add_arr = NULL;
|
||||
list.count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
@ -331,6 +331,7 @@ int ob20_init(Ob20Protocol *ob20protocol, unsigned long conid, my_bool use_flt)
|
||||
ob20protocol->extra_info_list.current = NULL;
|
||||
ob20protocol->header.connection_id = conid;
|
||||
ob20protocol->flt = NULL;
|
||||
ob20protocol->update_request_id = 1;
|
||||
if (use_flt) {
|
||||
ob20protocol->flt = malloc(sizeof(FLTInfo));
|
||||
if (OB_ISNULL(ob20protocol->flt)) {
|
||||
@ -715,4 +716,4 @@ int ob20_set_extra_info(MYSQL *mysql, ExtraInfoKeyType key, void *value)
|
||||
ob20protocol->extra_info_list.list = list_add(ob20protocol->extra_info_list.list, extra_info_list_item);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
1592
libmariadb/ob_tnsname.c
Normal file
1592
libmariadb/ob_tnsname.c
Normal file
File diff suppressed because it is too large
Load Diff
264
libmariadb/ob_tnsname.h
Normal file
264
libmariadb/ob_tnsname.h
Normal file
@ -0,0 +1,264 @@
|
||||
#ifndef OCI_TNSNAME_H_
|
||||
#define OCI_TNSNAME_H_
|
||||
#include "mysql.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define OBCLIENT_TNS_KEY_SIZE 256
|
||||
#define OBCLIENT_TNS_HOST_BUFFER_SIZE OBCLIENT_TNS_KEY_SIZE // 可能会有域名的形式,host很长
|
||||
#define OBCLIENT_TNS_PORT_BUFFER_SIZE 6 // 65535
|
||||
#define OBCLIENT_TNS_BUFFER_SIZE 1024
|
||||
#define OBCLIENT_TNS_MEMORY_COUNT 6
|
||||
|
||||
typedef struct obclient_tns ObClientTns;
|
||||
typedef struct obclient_tns_service ObClientTnsService;
|
||||
typedef struct obclient_description_list ObClientDescriptionList;
|
||||
typedef struct obclient_description ObClientDescription;
|
||||
typedef struct obclient_address_list ObClientAddressList;
|
||||
typedef struct obclient_address ObClientAddress;
|
||||
typedef struct obclient_connect_data ObClientConnectData;
|
||||
typedef struct obclient_black_list_conf ObClientBlacklistConf;
|
||||
typedef struct obclient_system_variables ObClientSystemVariables;
|
||||
typedef struct obclient_tns_parse_params ObClientTnsParseParams;
|
||||
|
||||
typedef enum enum_obclient_tns_parse_mode {
|
||||
TNS_MODE_FILE = 1,
|
||||
TNS_MODE_DESCRIPTION
|
||||
}ObClientTnsParseMode;
|
||||
|
||||
typedef enum obclient_tns_token_type
|
||||
{
|
||||
TNS_EQUAL_SIGN,
|
||||
TNS_LEFT_PARENTHESES,
|
||||
TNS_RIGHT_PARENTHESES,
|
||||
TNS_KEY,
|
||||
TNS_ERROR_TYPE,
|
||||
TNS_MAX_TOKEN_TYPE
|
||||
} ObClientTnsTokenType;
|
||||
|
||||
typedef enum obclient_tns_parse_status
|
||||
{
|
||||
TNS_PARSE_NORMAL,
|
||||
TNS_PARSE_QUOTE
|
||||
} ObClientTnsParseStatus;
|
||||
|
||||
// TNS File中的所有关键字, 解析TNS File时使用
|
||||
typedef enum enum_obclient_lb_key_type
|
||||
{
|
||||
OBCLIENT_LB_ERROR_KEY,
|
||||
OBCLIENT_LB_DESCRIPTION,
|
||||
OBCLIENT_LB_OBLB,
|
||||
OBCLIENT_LB_CONNECT_TIMEOUT,
|
||||
OBCLIENT_LB_READ_TIMEOUT,
|
||||
OBCLIENT_LB_WRITE_TIMEOUT,
|
||||
OBCLIENT_LB_OBLB_GROUP_STRATEGY,
|
||||
OBCLIENT_LB_OBLB_RETRY_ALL_DOWNS,
|
||||
OBCLIENT_LB_OBLB_RETRY_TIMEOUT,
|
||||
OBCLIENT_LB_OBLB_BLACKLIST,
|
||||
OBCLIENT_LB_REMOVE_STRATEGY,
|
||||
OBCLIENT_LB_NAME,
|
||||
OBCLIENT_LB_TIMEOUT,
|
||||
OBCLIENT_LB_APPEND_STRATEGY,
|
||||
OBCLIENT_LB_RETRY_TIMES,
|
||||
OBCLIENT_LB_DRUATION,
|
||||
OBCLIENT_LB_ADDRESS_LIST,
|
||||
OBCLIENT_LB_OBLB_STRATEGY,
|
||||
OBCLIENT_LB_ADDRESS,
|
||||
OBCLIENT_LB_PROTOCOL,
|
||||
OBCLIENT_LB_HOST,
|
||||
OBCLIENT_LB_PORT,
|
||||
OBCLIENT_LB_WEIGHT,
|
||||
OBCLIENT_LB_CONNECT_DATA,
|
||||
OBCLIENT_LB_SERVICE_NAME,
|
||||
OBCLIENT_LB_SID,
|
||||
OBCLIENT_LB_EXTRA_INFO,
|
||||
OBCLIENT_LB_OB_MODE,
|
||||
OBCLIENT_LB_USE_DEFAULT_SID,
|
||||
OBCLIENT_LB_SESSION_VARIABLE,
|
||||
OBCLIENT_LB_MAX_KEY_TYPE
|
||||
} ObClientLBKeyType;
|
||||
|
||||
/*
|
||||
0 - 1000 表示group LB策略
|
||||
1001 - 2000 表示每个组内LB的策略
|
||||
2001 - 3000 表示黑名单删除策略
|
||||
3001 - 4000 表示黑名单加入策略
|
||||
*/
|
||||
typedef enum enum_obclient_lb_option
|
||||
{
|
||||
// GROUP
|
||||
OBCLIENT_LB_OPTION_GROUP_ROTATION = 0, // 组内轮询
|
||||
// INTERNEL
|
||||
OBCLIENT_LB_OPTION_RANDOM = 1001, // 随机
|
||||
OBCLIENT_LB_OPTION_SERVERAFFINITY, // 加权随机
|
||||
OBCLIENT_LB_OPTION_ROTATION, // 轮询
|
||||
// BLACK LIST DELETE OPTION
|
||||
OBCLIENT_LB_OPTION_TIMEOUT = 2001, // 超时删除
|
||||
// BLACK LIST INSERT OPTION
|
||||
OBCLIENT_LB_OPTION_RETRY_DERUATION = 3001, // 时间段内失败多少次加入黑名单
|
||||
OBCLIENT_LB_OPTION_NORMAL = 3002, // 直接拉黑
|
||||
OBCLIENT_LB_OPTION_MAX
|
||||
} ObClientLBOption;
|
||||
|
||||
struct obclient_system_variables
|
||||
{
|
||||
char session_variable[OBCLIENT_TNS_KEY_SIZE + 1];
|
||||
unsigned long session_variable_len;
|
||||
};
|
||||
|
||||
struct obclient_tns
|
||||
{
|
||||
ObClientTnsService *tns_service;
|
||||
unsigned long tns_service_count;
|
||||
};
|
||||
|
||||
struct obclient_tns_service
|
||||
{
|
||||
ObClientDescription *description;
|
||||
unsigned long description_count;
|
||||
unsigned long description_memory;
|
||||
ObClientSystemVariables sys_vars;
|
||||
unsigned long net_service_name_len;
|
||||
char net_service_name[OBCLIENT_TNS_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
struct obclient_black_list_conf
|
||||
{
|
||||
ObClientLBOption remove_strategy;
|
||||
unsigned long remove_timeout;
|
||||
ObClientLBOption append_strategy;
|
||||
unsigned long retry_times;
|
||||
unsigned long duration;
|
||||
};
|
||||
|
||||
struct obclient_description
|
||||
{
|
||||
ObClientAddressList *address_list;
|
||||
unsigned long address_list_count;
|
||||
unsigned long address_list_memory;
|
||||
ObClientConnectData *connect_data;
|
||||
// more member
|
||||
my_bool oblb; // TRUE on/ FALSE off
|
||||
unsigned long retry_all_downs;
|
||||
unsigned long connect_timout; // 单次连接的超时时间
|
||||
unsigned long read_timout; // 单次读的超时时间
|
||||
unsigned long write_timout; // 单次写的超时时间
|
||||
unsigned long retry_timeout; // 整个LB阶段的超时时间
|
||||
ObClientLBOption oblb_group_strategy;
|
||||
ObClientBlacklistConf black_list_conf;
|
||||
};
|
||||
|
||||
struct obclient_address_list
|
||||
{
|
||||
ObClientAddress *address;
|
||||
unsigned long address_count;
|
||||
unsigned long address_memory;
|
||||
my_bool oblb; // TRUE on/ FALSE off
|
||||
ObClientLBOption oblb_strategy;
|
||||
};
|
||||
|
||||
struct obclient_address
|
||||
{
|
||||
char host[OBCLIENT_TNS_HOST_BUFFER_SIZE + 1]; // 长度加一为了调用mysql接口时加上结尾0
|
||||
char protocol[OBCLIENT_TNS_PORT_BUFFER_SIZE];
|
||||
unsigned long host_len;
|
||||
unsigned long protocol_len;
|
||||
unsigned long port;
|
||||
unsigned long weight;
|
||||
};
|
||||
|
||||
struct obclient_connect_data
|
||||
{
|
||||
char service_name[OBCLIENT_TNS_KEY_SIZE + 1]; // 长度加一为了调用mysql接口时加上结尾0
|
||||
unsigned int service_name_len;
|
||||
char user_extra_info[OBCLIENT_TNS_KEY_SIZE];
|
||||
unsigned int user_extra_info_len;
|
||||
unsigned long ob_mode;
|
||||
unsigned long use_default_sid;
|
||||
};
|
||||
|
||||
struct obclient_tns_parse_params
|
||||
{
|
||||
char tns_buffer[OBCLIENT_TNS_BUFFER_SIZE];
|
||||
char tns_key[OBCLIENT_TNS_KEY_SIZE];
|
||||
unsigned int buffer_pos;
|
||||
unsigned int buffer_len;
|
||||
unsigned int tns_key_len;
|
||||
int is_eof;
|
||||
int mode; //1=file,2=description
|
||||
char *tns_name;
|
||||
FILE *tns_file;
|
||||
char *description;
|
||||
int description_len;
|
||||
int description_offset;
|
||||
ObClientTnsTokenType tns_token_type;
|
||||
ObClientLBKeyType key_type;
|
||||
};
|
||||
|
||||
|
||||
int ObClientTnsInit(ObClientTns *tns);
|
||||
int ObClientTnsClear(ObClientTns *tns);
|
||||
int ObClientTnsDisplay(ObClientTns *tns);
|
||||
int ObClientTnsBuild(ObClientTns *tns, const char *dbname, unsigned int dbname_len, my_bool *find);
|
||||
int ObClientTnsBuildDes(ObClientTns *tns, const char *dbname, unsigned int dbname_len, my_bool *find);
|
||||
|
||||
int ObClientTnsServiceCheck(ObClientTnsService *tns_service);
|
||||
int ObClientTnsServiceInit(ObClientTnsService *tns_service, unsigned int name_size, const char *name);
|
||||
int ObClientTnsServiceClear(ObClientTnsService *tns_service);
|
||||
int ObClientTnsServiceDisplay(ObClientTnsService *tns_service, FILE *display_file);
|
||||
int ObClientTnsServiceBuild(ObClientTns *tns, ObClientTnsParseParams *parse_params);
|
||||
int ObClientTnsServiceSkip(ObClientTnsParseParams *parse_params);
|
||||
// 非负载均衡模式下获取extra info
|
||||
int ObClientTnsServiceExtraInfoGet(ObClientTnsService *tns_service, char *extra_info, int *extra_info_len, int *ob_mode);
|
||||
// 非负载均衡模式下获取dblink, 直接获取第一个address,拼接dblink
|
||||
int ObClientTnsServiceDblinkGet(ObClientTnsService *tns_service, char *dblink, int *dblink_len);
|
||||
|
||||
int ObClientDescriptionCheck(ObClientDescription *des);
|
||||
int ObClientDescriptionInit(ObClientDescription *des);
|
||||
int ObClientDescriptionClear(ObClientDescription *des);
|
||||
int ObClientDescriptionDisplay(ObClientDescription *des, FILE *display_file);
|
||||
int ObClientDescriptionBuild(ObClientTnsService *tns, ObClientTnsParseParams *parse_params);
|
||||
|
||||
int ObClientBlacklistConfInit(ObClientBlacklistConf *black_list_conf);
|
||||
int ObClientBlacklistConfBuild(ObClientBlacklistConf *black, ObClientTnsParseParams *parse_params);
|
||||
int ObClientRemoveStrategyBuild(ObClientBlacklistConf *black, ObClientTnsParseParams *parse_params);
|
||||
int ObClientAppendStrategyBuild(ObClientBlacklistConf *black, ObClientTnsParseParams *parse_params);
|
||||
|
||||
int ObClientAddressListCheck(ObClientAddressList *address_list);
|
||||
int ObClientAddressListInit(ObClientAddressList *address_list);
|
||||
int ObClientAddressListClear(ObClientAddressList *address_list);
|
||||
int ObClientAddressListDisplay(ObClientAddressList *address_list, FILE *display_file);
|
||||
int ObClientAddressListBuild(ObClientDescription *des, ObClientTnsParseParams *parse_params);
|
||||
|
||||
int ObClientAddressInit(ObClientAddress *address);
|
||||
int ObClientAddressClear(ObClientAddress *address);
|
||||
int ObClientAddressDisplay(ObClientAddress *address, FILE *display_file);
|
||||
int ObClientAddressBuild(ObClientAddressList *address_list, ObClientTnsParseParams *parse_params);
|
||||
|
||||
int ObClientConnectDataInit(ObClientConnectData *con_data);
|
||||
int ObClientConnectDataClear(ObClientConnectData *con_data);
|
||||
int ObClientConnectDataDisplay(ObClientConnectData *con_data, FILE *display_file);
|
||||
int ObClientConnectDataBuild(ObClientDescription *des, ObClientTnsParseParams *parse_params);
|
||||
|
||||
int ObClientSystemVariablesInit(ObClientSystemVariables *sys_vars);
|
||||
int ObClientSystemVariablesClear(ObClientSystemVariables *sys_vars);
|
||||
int ObClientSystemVariablesDisplay(ObClientSystemVariables *sys_vars, FILE *display_file);
|
||||
int ObClientSystemVariablesBuild(ObClientSystemVariables *sys_vars, ObClientTnsParseParams *parse_params);
|
||||
|
||||
// 解析文件相关函数
|
||||
int ObClientTnsParse(ObClientTnsParseParams *parse_params, ObClientTnsTokenType expect_type);
|
||||
int ObClientTnsCheckBuffer(ObClientTnsParseParams *parse_params);
|
||||
int ObClientTnsParseBlank(ObClientTnsParseParams *parse_params);
|
||||
int ObClientTnsParseKey(ObClientTnsParseParams *parse_params);
|
||||
int ObClientTnsGetKeyType(ObClientTnsParseParams *parse_params);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
36
libmariadb/ob_utils.c
Normal file
36
libmariadb/ob_utils.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include "ob_utils.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
int gettimeofday(struct timeval *tp, void *tzp)
|
||||
{
|
||||
time_t clock;
|
||||
struct tm tm;
|
||||
SYSTEMTIME wtm;
|
||||
|
||||
GetLocalTime(&wtm);
|
||||
tm.tm_year = wtm.wYear - 1900;
|
||||
tm.tm_mon = wtm.wMonth - 1;
|
||||
tm.tm_mday = wtm.wDay;
|
||||
tm.tm_hour = wtm.wHour;
|
||||
tm.tm_min = wtm.wMinute;
|
||||
tm.tm_sec = wtm.wSecond;
|
||||
tm.tm_isdst = -1;
|
||||
|
||||
clock = mktime(&tm);
|
||||
tp->tv_sec = clock;
|
||||
tp->tv_usec = wtm.wMilliseconds * 1000;
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ob_gettimeofday(struct timeval *tp, void *tzp)
|
||||
{
|
||||
return gettimeofday(tp, tzp);
|
||||
}
|
||||
|
||||
int64_t get_current_time_us()
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
}
|
@ -62,7 +62,8 @@ struct st_ma_pvio_methods pvio_npipe_methods= {
|
||||
pvio_npipe_is_blocking,
|
||||
pvio_npipe_is_alive,
|
||||
NULL,
|
||||
pvio_npipe_shutdown
|
||||
pvio_npipe_shutdown,
|
||||
NULL
|
||||
};
|
||||
|
||||
#ifndef PLUGIN_DYNAMIC
|
||||
|
@ -60,7 +60,8 @@ struct st_ma_pvio_methods pvio_shm_methods= {
|
||||
NULL,
|
||||
pvio_shm_is_alive,
|
||||
NULL,
|
||||
pvio_shm_shutdown
|
||||
pvio_shm_shutdown,
|
||||
NULL
|
||||
};
|
||||
|
||||
#ifndef PLUGIN_DYNAMIC
|
||||
|
@ -108,6 +108,7 @@ my_bool pvio_socket_is_blocking(MARIADB_PVIO *pvio);
|
||||
my_bool pvio_socket_is_alive(MARIADB_PVIO *pvio);
|
||||
my_bool pvio_socket_has_data(MARIADB_PVIO *pvio, ssize_t *data_len);
|
||||
int pvio_socket_shutdown(MARIADB_PVIO *pvio);
|
||||
int pvio_socket_socket5_auth(MARIADB_PVIO *pvio, char *user, char *pwd, char *host, unsigned short port);
|
||||
|
||||
static int pvio_socket_init(char *unused1,
|
||||
size_t unused2,
|
||||
@ -134,7 +135,8 @@ struct st_ma_pvio_methods pvio_socket_methods= {
|
||||
pvio_socket_is_blocking,
|
||||
pvio_socket_is_alive,
|
||||
pvio_socket_has_data,
|
||||
pvio_socket_shutdown
|
||||
pvio_socket_shutdown,
|
||||
pvio_socket_socket5_auth
|
||||
};
|
||||
|
||||
#ifndef PLUGIN_DYNAMIC
|
||||
@ -1126,3 +1128,161 @@ int pvio_socket_shutdown(MARIADB_PVIO *pvio)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int socket5_auth(int socket, char *user, char *pwd, char *host, unsigned short port) {
|
||||
#define SOCKET5_VERSION 5
|
||||
#define SOCKET5_ERROR -2
|
||||
#define ATYPE_IPV4 1
|
||||
#define ATYPE_DOMAIN 3
|
||||
#define ATYPE_IPV6 4
|
||||
|
||||
int len = 0;
|
||||
char sendbuf[512] = { 0 };
|
||||
char recvbuf[512] = { 0 };
|
||||
int auth_success = 0;
|
||||
int request_success = -1;
|
||||
int support_method = -1;
|
||||
int response_ver = -1;
|
||||
|
||||
|
||||
//printf("socket:%d, user=%s, pwd=%s, host=%s, port=%d\n", socket, user ? user : "", pwd ? pwd : "", host ? host : "", port);
|
||||
|
||||
//shake hands
|
||||
{
|
||||
char *shakehands = sendbuf;
|
||||
shakehands[0] = SOCKET5_VERSION;
|
||||
shakehands[1] = 0x01;
|
||||
if (user == NULL || pwd == NULL || strlen(user) == 0 || strlen(pwd) == 0) {
|
||||
shakehands[2] = 0x00;
|
||||
} else {
|
||||
shakehands[2] = 0x02;
|
||||
}
|
||||
|
||||
if (3 != send(socket, shakehands, 3, 0)) {
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
if (2 != recv(socket, recvbuf, 2, 0)) {
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
response_ver = recvbuf[0];
|
||||
support_method = recvbuf[1];
|
||||
//printf("shakehands ver:%d, method:%d\n", response_ver, support_method);
|
||||
}
|
||||
|
||||
if (response_ver != SOCKET5_VERSION ||
|
||||
(support_method != 0x00 && support_method != 0x02)) {
|
||||
return SOCKET5_ERROR;
|
||||
}
|
||||
|
||||
//auth user,password
|
||||
if (support_method == 0x02) {
|
||||
char *auth = sendbuf;
|
||||
char *pos = auth;
|
||||
char *puser = (char*)(user ? user : "");
|
||||
char *ppwd = (char*)(pwd ? pwd : "");
|
||||
*pos++ = SOCKET5_VERSION;
|
||||
*pos++ = (unsigned char)strlen(puser);
|
||||
memcpy(pos, puser, strlen(puser));
|
||||
pos += strlen(puser);
|
||||
*pos++ = (unsigned char)strlen(ppwd);
|
||||
memcpy(pos, ppwd, strlen(ppwd));
|
||||
pos += strlen(ppwd);
|
||||
|
||||
len = 3 + strlen(puser) + strlen(ppwd);
|
||||
if (len != send(socket, auth, len, 0)) {
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
if (2 != recv(socket, recvbuf, 2, 0)) {
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
response_ver = recvbuf[0];
|
||||
auth_success = recvbuf[1];
|
||||
//printf("auth ver:%d, status:%d\n", recvbuf[0], recvbuf[1]);
|
||||
}
|
||||
|
||||
if (response_ver != SOCKET5_VERSION || auth_success != 0) {
|
||||
return SOCKET5_ERROR;
|
||||
}
|
||||
|
||||
//request
|
||||
if (0 == auth_success) {
|
||||
char* request = sendbuf;
|
||||
char *pos = request;
|
||||
char atyp = 0;
|
||||
if (strchr(host, ':')) {
|
||||
atyp = ATYPE_IPV6;
|
||||
} else {
|
||||
int i = 0;
|
||||
bool domain = 0;
|
||||
for (i = 0; i < (int)strlen(host); i++) {
|
||||
if ((host[i] >= '0' &&host[i] <= '9') || host[i] == '.') {
|
||||
continue;
|
||||
} else {
|
||||
domain = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
atyp = domain ? ATYPE_DOMAIN : ATYPE_IPV4;
|
||||
}
|
||||
*pos++ = SOCKET5_VERSION;
|
||||
*pos++ = 0x01; //1=connect,2=bind,3=udp, default connect
|
||||
*pos++ = 0x00;
|
||||
*pos++ = atyp; //1=ipv4 (4),3=domain,4=ipv6(16)
|
||||
if (atyp == ATYPE_IPV4) { //ipv4
|
||||
unsigned int *addr = (unsigned int*)pos;
|
||||
*addr = inet_addr(host);
|
||||
pos += 4;
|
||||
} else if (atyp == ATYPE_DOMAIN) { //domain
|
||||
*pos++ = (unsigned char)strlen(host);
|
||||
memcpy(pos, host, strlen(host));
|
||||
pos += strlen(host);
|
||||
} else { //ipv6
|
||||
if (1 != inet_pton(AF_INET6, host, pos)) {
|
||||
return SOCKET5_ERROR;
|
||||
}
|
||||
pos += 16;
|
||||
}
|
||||
unsigned short *pport = (unsigned short*)pos;
|
||||
*pport = htons(port);
|
||||
pos += 2;
|
||||
|
||||
len = pos - request;
|
||||
if (len != send(socket, request, len, 0)) {
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
if (4 != recv(socket, recvbuf, 4, 0)) {
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
response_ver = recvbuf[0];
|
||||
request_success = recvbuf[1];
|
||||
//printf("request recv:ver=%d, rep=%d, atyp=%d\n", recvbuf[0], recvbuf[1], recvbuf[3]);
|
||||
|
||||
{
|
||||
int will = 2; //port
|
||||
if (recvbuf[3] == ATYPE_IPV4) { //ipv4
|
||||
will += 4;
|
||||
} else if (recvbuf[3] = ATYPE_DOMAIN) { //domain
|
||||
if (1 != recv(socket, recvbuf, 1, 0))
|
||||
return SOCKET_ERROR;
|
||||
will += recvbuf[0];
|
||||
} else { //ipv6
|
||||
will += 16;
|
||||
}
|
||||
if (will != recv(socket, recvbuf, will, 0)) {
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
return request_success;
|
||||
}
|
||||
int pvio_socket_socket5_auth(MARIADB_PVIO *pvio, char *user, char *pwd, char *host, unsigned short port)
|
||||
{
|
||||
struct st_pvio_socket *csock = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!pvio || !pvio->data)
|
||||
return -1;
|
||||
|
||||
csock = (struct st_pvio_socket *)pvio->data;
|
||||
return socket5_auth(csock->socket, user, pwd, host, port);
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
2.2.3
|
||||
2.2.6
|
||||
|
@ -1,6 +1,6 @@
|
||||
Name: %NAME
|
||||
Version: %VERSION
|
||||
Release: %(echo %RELEASE)%{?dist}
|
||||
Release: %(echo %RELEASE)
|
||||
License: LGPL
|
||||
Group: applications/database
|
||||
buildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
||||
@ -14,7 +14,7 @@ LibObClient is a driver used to connect applications developed in C to OceanBase
|
||||
%define MYSQL_USER root
|
||||
%define MYSQL_GROUP root
|
||||
%define __os_install_post %{nil}
|
||||
%define base_dir /u01/mysql
|
||||
#%define base_dir /u01/mysql
|
||||
%define file_dir /app/mariadb
|
||||
|
||||
|
||||
@ -54,11 +54,12 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%pre
|
||||
|
||||
%post
|
||||
if [ -d %{base_dir} ]; then
|
||||
cp -rf %{prefix}/* %{base_dir}
|
||||
else
|
||||
cp -rf %{prefix} %{base_dir}
|
||||
fi
|
||||
#if [ -d %{base_dir} ]; then
|
||||
# cp -rf %{prefix}/* %{base_dir}
|
||||
#else
|
||||
# cp -rf %{prefix} %{base_dir}
|
||||
#fi
|
||||
|
||||
%preun
|
||||
|
||||
%changelog
|
||||
|
Loading…
x
Reference in New Issue
Block a user