diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b2ae0b..bcd8ca6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,11 +144,11 @@ SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DDBUG_OFF") SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DDBUG_OFF") SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDBUG_OFF") -IF(UNIX) - SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -z noexecstack -z now -pie -fPIC -fstack-protector-all") - SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -z noexecstack -z now -pie -fPIC -fstack-protector-all") - SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -z noexecstack -z now -pie -fPIC -fstack-protector-all") - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -z noexecstack -z now -pie -fPIC -fstack-protector-all") +IF(UNIX AND NOT APPLE) + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -z noexecstack -z relro -z now -pie -fPIC -fstack-protector") + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -z noexecstack -z relro -z now -pie -fPIC -fstack-protector") + SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -z noexecstack -z relro -z now -pie -fPIC -fstack-protector") + SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -z noexecstack -z relro -z now -pie -fPIC -fstack-protector") ENDIF() IF(CMAKE_COMPILER_IS_GNUCC) diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index dd0049e..0000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,228 +0,0 @@ -resources: - containers: - - - container: ubuntu-1804 - image: ubuntu:18.04 - options: "--name ubuntu-1804 --add-host=mariadb.example.com:127.0.0.1 -v /usr/bin/docker:/tmp/docker:ro" - -jobs: - - - job: SSLFiles - displayName: 'Creating SSL Files' - pool: - vmImage: 'ubuntu-16.04' - container: $[ variables['containerImage'] ] - steps: - - script: | - java --version - mkdir tmp - chmod 777 .travis/gen-ssl.sh - .travis/gen-ssl.sh mariadb.example.com tmp - cp -R tmp $BUILD_ARTIFACTSTAGINGDIRECTORY - displayName: 'create SSL certificates' - - - task: PublishPipelineArtifact@0 - inputs: - targetPath: '$(Build.ArtifactStagingDirectory)' - artifactName: ssl_certs - - - job: windowsTest - displayName: 'test windows' - pool: - vmImage: 'windows-2019' - dependsOn: - - SSLFiles - steps: - - task: DownloadPipelineArtifact@2 - displayName: 'Download SSL files' - inputs: - artifactName: ssl_certs - targetPath: $(System.DefaultWorkingDirectory) - - - task: DownloadPipelineArtifact@2 - displayName: 'Download 10.4 server' - inputs: - source: 'specific' - project: '550599d3-6165-4abd-8c86-e3f7e53a1847' - artifact: 'Windows' - pipeline: 3 - runVersion: 'latestFromBranch' - runBranch: 'refs/heads/10.4-enterprise' - downloadPath: $(System.DefaultWorkingDirectory) - - - script: | - for /f %%a in ('dir /B $(System.DefaultWorkingDirectory)\win_build\mariadb-enterprise-10.*-winx64.msi') do set servername=$(System.DefaultWorkingDirectory)\win_build\%%a - echo %servername% - msiexec /i %servername% INSTALLDIR=c:\projects\server SERVICENAME=mariadb ALLOWREMOTEROOTACCESS=true /qn - c:\projects\server\bin\mysql.exe -e "create database testc" --user=root - displayName: 'install server' - - - script: | - echo 127.0.0.1 mariadb.example.com >> %WINDIR%\System32\Drivers\Etc\Hosts - displayName: 'set hostname' - - - script: | - cmake -G "Visual Studio 16 2019" -DCMAKE_BUILD_TYPE=RelWithDebInfo - cmake --build . --config RelWithDebInfo - displayName: 'build connector' - - - script: | - cd $(System.DefaultWorkingDirectory)\unittest\libmariadb - set MARIADB_PLUGIN_DIR=$(System.DefaultWorkingDirectory)\plugins\lib\RelWithDebInfo - ctest -V - if %ERRORLEVEL% EQU 0 ( - echo Success - ) else ( - echo exit code is %errorlevel% - exit /b %errorlevel% - ) - displayName: 'run tests' - env: - MYSQL_TEST_HOST: "mariadb.example.com" - MYSQL_TEST_USER: 'someUser' - MYSQL_TEST_DB: 'testc' - MYSQL_TEST_PORT: 3306 - TEST_SSL_CA_FILE: "$(System.DefaultWorkingDirectory)/tmp/server.crt" - TEST_SSL_CLIENT_KEY_FILE: "$(System.DefaultWorkingDirectory)/tmp/client.key" - TEST_SSL_CLIENT_CERT_FILE: "$(System.DefaultWorkingDirectory)/tmp/client.crt" - TEST_SSL_CLIENT_KEYSTORE_FILE: "$(System.DefaultWorkingDirectory)/tmp/client-keystore.p12" - - - job: RunInContainer - pool: - vmImage: 'ubuntu-16.04' - displayName: 'test ubuntu bionic' - dependsOn: - - SSLFiles - strategy: - matrix: - ubuntu-1804: - containerImage: ubuntu-1804 - containerName: bionic - - container: $[variables['containerImage']] - - steps: - - - task: DownloadPipelineArtifact@2 - inputs: - artifactName: ssl_certs - targetPath: $(System.DefaultWorkingDirectory) - - - script: /tmp/docker exec -t -u 0 $(containerImage) sh -c "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confold" -y install sudo" - displayName: Set up sudo - - - task: DownloadPipelineArtifact@2 - displayName: 'Download 10.4 enterprise server artifact files' - inputs: - source: 'specific' - project: '550599d3-6165-4abd-8c86-e3f7e53a1847' - artifact: '$(containerImage)' - pipeline: 3 - runVersion: 'latestFromBranch' - runBranch: 'refs/heads/10.4-enterprise' - downloadPath: $(System.DefaultWorkingDirectory) - - - task: DownloadPipelineArtifact@2 - displayName: 'Download galera server artifact files' - inputs: - source: 'specific' - project: '550599d3-6165-4abd-8c86-e3f7e53a1847' - artifact: $(containerImage) - runVersion: 'latestFromBranch' - pipeline: 2 - runBranch: 'refs/heads/es-mariadb-4.x' - downloadPath: $(System.DefaultWorkingDirectory) - - - - script: | - tar xf mariadb-enterprise* - - sudo ln -fs /usr/share/zoneinfo/UTC /etc/localtime - - sudo apt-get update && sudo apt-get install -y --no-install-recommends apt-transport-https ca-certificates tzdata pwgen - export DEBIAN_FRONTEND="noninteractive" - sudo debconf-set-selections <<< "mariadb-server-10.4 mysql-server/root_password password P4ssw@rd" - sudo debconf-set-selections <<< "mariadb-server-10.4 mysql-server/root_password_again password P4ssw@rd" - sudo apt-get update -y - sudo apt-get install --allow-unauthenticated -f -y libssl-dev libaio1 libaio-dev libxml2 libcurl4 curl libc-dev linux-libc-dev libc-dev-bin libdbi-perl rsync socat libnuma1 zlib1g-dev libreadline5 libjemalloc1 libsnappy1v5 libcrack2 gawk lsof psmisc perl libreadline5 - - cd mariadb-enterprise*/ - sudo groupadd mysql - sudo useradd -g mysql mysql - - export PROJ_PATH=`pwd` - echo $PROJ_PATH - - cat <> my.cnf - [mysqld] - port=3306 - max_allowed_packet=16M - datadir=$PROJ_PATH/data - socket=/tmp/mysql.sock - user=mysql - ssl-ca=$(System.DefaultWorkingDirectory)/tmp/ca.crt - ssl-cert=$(System.DefaultWorkingDirectory)/tmp/server.crt - ssl-key=$(System.DefaultWorkingDirectory)/tmp/server.key - EOT - - sudo chown mysql $PROJ_PATH/my.cnf - sudo tail -n 5000 $PROJ_PATH/my.cnf - - sudo chmod 777 $PROJ_PATH - sudo ln -s $PROJ_PATH /usr/local/mysql - - sudo ./scripts/mysql_install_db --defaults-file=$PROJ_PATH/my.cnf --user=mysql - sudo chown -R root . - sudo chown -R mysql data - - export PATH=$PATH:$PROJ_PATH/bin/ - - env: - WORKING_DIR: $(System.DefaultWorkingDirectory) - displayName: 'install server' - - - script: | - sudo apt-get install -f -y make cmake - cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_SSL=OPENSSL -DCERT_PATH=$(System.DefaultWorkingDirectory)/tmp - make - displayName: 'Build' - - - script: | - cd mariadb-enterprise*/ - sudo ./bin/mysqld --defaults-file=./my.cnf & - - for i in {30..0}; do - if sudo ./bin/mysql -e "SELECT 1" &> /dev/null; then - echo 'MySQL connected...' - break - fi - echo 'MySQL init process in progress...' - sleep 1 - done - if [ "$i" = 0 ]; then - echo >&2 'MySQL init process failed.' - sudo ./bin/mysql -e "SELECT 1" - exit 1 - fi - - sudo ./bin/mysql -e "CREATE DATABASE testc;" - - echo "Running tests" - cd ../unittest/libmariadb - ctest -V - if [ $? -ne 0 ]; then - exit 1 - fi - cd $(System.DefaultWorkingDirectory)/mariadb-enterprise*/ - sudo ./bin/mysqladmin shutdown - env: - MYSQL_TEST_HOST: mariadb.example.com - MYSQL_TEST_DB: testc - MYSQL_TEST_USER: 'someUser' - MYSQL_TEST_PORT: 3306 - MYSQL_TEST_TRAVIS: 1 - TEST_SSL_CA_FILE: "$(System.DefaultWorkingDirectory)/tmp/server.crt" - TEST_SSL_CLIENT_KEY_FILE: "$(System.DefaultWorkingDirectory)/tmp/client.key" - TEST_SSL_CLIENT_CERT_FILE: "$(System.DefaultWorkingDirectory)/tmp/client.crt" - TEST_SSL_CLIENT_KEYSTORE_FILE: "$(System.DefaultWorkingDirectory)/tmp/client-keystore.p12" - displayName: 'run tests' \ No newline at end of file diff --git a/include/ma_priv.h b/include/ma_priv.h index 166b9c7..fc69793 100644 --- a/include/ma_priv.h +++ b/include/ma_priv.h @@ -39,7 +39,7 @@ static inline uint ma_extended_type_info_rows(const MYSQL *mysql) static inline uint ma_result_set_rows(const MYSQL *mysql) { - return ma_has_extended_type_info(mysql) ? 9 : 8; + return ma_has_extended_type_info(mysql) ? 8 : 7; } MA_FIELD_EXTENSION *ma_field_extension_deep_dup(MA_MEM_ROOT *memroot, diff --git a/include/mysql.h b/include/mysql.h index fb626ad..a28b9f7 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -200,6 +200,7 @@ extern const char *SQLSTATE_UNKNOWN; typedef struct st_mysql_rows { struct st_mysql_rows *next; /* list of rows */ MYSQL_ROW data; + unsigned long* data_length; unsigned long length; } MYSQL_ROWS; diff --git a/include/ob_complex.h b/include/ob_complex.h index 780dc5f..6f8905d 100644 --- a/include/ob_complex.h +++ b/include/ob_complex.h @@ -47,6 +47,13 @@ typedef enum enum_types { TYPE_SHORT, TYPE_FLOAT, TYPE_DOUBLE, + TYPE_NVARCHAR2, + TYPE_OB_NUMBER_FLOAT, + TYPE_OB_TIMESTAMP_NANO, + TYPE_OB_TIMESTAMP_WITH_TIME_ZONE, + TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE, + TYPE_OB_INTERVAL_YM, + TYPE_OB_INTERVAL_DS, TYPE_UNKNOW, TYPE_MAX } enum_types; diff --git a/include/ob_load_balance.h b/include/ob_load_balance.h index d27a728..5ed643f 100644 --- a/include/ob_load_balance.h +++ b/include/ob_load_balance.h @@ -17,12 +17,13 @@ typedef struct _st_obclient_lb_AddressList { }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 retry_all_downs; //总的次数 + unsigned int retry_timeout; // LB 阶段总的超时时间(ms) + unsigned int black_remove_strategy; //2001 + unsigned int black_remove_timeout; //移出黑名单时间(ms) + unsigned int black_append_strategy; //3002 NORMAL, 3001 RETRYDURATION + unsigned int black_append_retrytimes; //单个address次数 + unsigned int black_append_duration; //时间duration内(ms),执行>= retrytimes次加黑 unsigned int mysql_connect_timeout; unsigned int mysql_read_timeout; @@ -42,6 +43,7 @@ typedef struct _st_obclient_lb_config{ my_bool mysql_opt_interactive; my_bool mysql_report_data_truncation; my_bool mysql_opt_reconnect; + char* mysql_read_default_file; my_bool mysql_opt_use_ssl; my_bool mysql_opt_ssl_verify_server_cert; @@ -59,6 +61,10 @@ typedef struct _st_obclient_lb_config{ 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); +//addr_list [fe80::42:acff:fe11:2%eth0]:38884,[xxx.xxx.xxx.xxx]:2222,xxx.xxx.xxx.xxx:38884 +MYSQL* ob_mysql_real_connect2(MYSQL* mysql, const char* tns_name, const char *addr_list, ObClientLbConfig *config, + const char *user, const char *passwd, const char *db, const char *unix_socket, unsigned long client_flag, char* success, int len_success); + #ifdef __cplusplus } #endif diff --git a/libmariadb/CMakeLists.txt b/libmariadb/CMakeLists.txt index 3bb1b2d..53b206a 100644 --- a/libmariadb/CMakeLists.txt +++ b/libmariadb/CMakeLists.txt @@ -342,6 +342,7 @@ SET(MARIADB_NONBLOCK_SYMBOLS get_ob_lob_payload_data_len stmt_get_data_from_lobv2 ob_mysql_real_connect + ob_mysql_real_connect2 ob_get_libobclient_version ob_set_socket5_proxy ) diff --git a/libmariadb/ma_stmt_codec.c b/libmariadb/ma_stmt_codec.c index 4211125..77e02b7 100644 --- a/libmariadb/ma_stmt_codec.c +++ b/libmariadb/ma_stmt_codec.c @@ -1535,6 +1535,7 @@ static ulong get_complex_header_length(enum_types type) { return sizeof(MYSQL_COMPLEX_BIND_OBJECT); case TYPE_COLLECTION: return sizeof(MYSQL_COMPLEX_BIND_ARRAY); + case TYPE_NVARCHAR2: case TYPE_VARCHAR2: case TYPE_CHAR: case TYPE_RAW: @@ -1548,6 +1549,14 @@ static ulong get_complex_header_length(enum_types type) { case TYPE_FLOAT: case TYPE_DOUBLE: return sizeof(MYSQL_COMPLEX_BIND_BASIC); + case TYPE_OB_NUMBER_FLOAT: + return sizeof(MYSQL_COMPLEX_BIND_STRING); + case TYPE_OB_INTERVAL_YM: + case TYPE_OB_INTERVAL_DS: + case TYPE_OB_TIMESTAMP_NANO: + case TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE: + case TYPE_OB_TIMESTAMP_WITH_TIME_ZONE: + return sizeof(MYSQL_COMPLEX_BIND_BASIC); default: return sizeof(MYSQL_COMPLEX_BIND_BASIC); } @@ -1671,6 +1680,122 @@ static void fetch_result_double_complex(MYSQL_COMPLEX_BIND_BASIC *header, return; } +static void read_binary_interval(int type, ORACLE_INTERVAL *tm, uchar **pos) +{ + uint length = net_field_length(pos); + uchar *to = *pos; + ORACLE_INTERVAL *interval = tm; + + switch (type) + { + case MYSQL_TYPE_OB_INTERVAL_DS: { + if (length == 14) { + interval->mysql_type = MYSQL_TYPE_OB_INTERVAL_DS; + interval->data_symbol = (to[0] > 0 ? -1 : 1); + interval->data_object.ds_object.ds_day = sint4korr(to + 1); + interval->data_object.ds_object.ds_hour = to[5]; + interval->data_object.ds_object.ds_minute = to[6]; + interval->data_object.ds_object.ds_second = to[7]; + interval->data_object.ds_object.ds_frac_second = sint4korr(to + 8); + interval->data_object.ds_object.ds_day_scale = to[12]; + interval->data_object.ds_object.ds_frac_second_scale = to[13]; + } + break; + } + case MYSQL_TYPE_OB_INTERVAL_YM: { + if (length == 7) { + interval->mysql_type = MYSQL_TYPE_OB_INTERVAL_YM; + interval->data_symbol = (to[0] > 0 ? -1 : 1); + interval->data_object.ym_object.ym_year = sint4korr(to + 1); + interval->data_object.ym_object.ym_month = to[5]; + interval->data_object.ym_object.ym_scale = to[6]; + } + break; + } + } + *pos += length; +} +static void fetch_result_ob_interval_complex(MYSQL_COMPLEX_BIND_BASIC *header, + MYSQL_BIND *param, + uchar **row) +{ + ORACLE_INTERVAL *tm = NULL; + + tm = fetch_result_complex_alloc_space(header, param, sizeof(ORACLE_INTERVAL)); + if (NULL == tm) { + return; + } + + read_binary_interval(header->buffer_type, tm, row); + return; +} + +static void fetch_result_ob_timestamp_complex(MYSQL_COMPLEX_BIND_BASIC *header, + MYSQL_BIND *param, + uchar **row) +{ + void *buffer = NULL; + ulong bufferlen = 0; + ulong length = 0; + ulong tz_length = 0; + ulong buffer_offset = 0; + ulong buffer_length = 0; + ORACLE_TIME *tm = NULL; + uchar *to = NULL; + + length = net_field_length(row); + bufferlen = sizeof(ORACLE_TIME) + length; //+length 包括TZ信息 + buffer = fetch_result_complex_alloc_space((MYSQL_COMPLEX_BIND_HEADER *)header, param, bufferlen); + if (NULL == buffer || length < 12) { + return; + } + + to = *row; + + tm = (ORACLE_TIME*)buffer; + memset(tm, 0, sizeof(ORACLE_TIME)); + tm->century = (int)(*(char*)to++); + tm->year = (int)(*(char*)to++); + tm->month = (uint)(*to++); + tm->day = (uint)(*to++); + tm->hour = (uint)(*to++); + tm->minute = (uint)(*to++); + tm->second = (uint)(*to++); + + tm->second_part = (ulong)sint4korr(to); + to += 4; + tm->scale = (uint)(*to++); + + buffer_length = buffer_offset = sizeof(ORACLE_TIME); + if (length > 12) { + tm->offset_hour = (int)(*(char*)to++); + tm->offset_minute = (int)(*(char*)to++); + + tz_length = (uint)(*to++); + buffer_length += (tz_length + 1); + if (tz_length > 0 && buffer_offset + tz_length + 1 < bufferlen) { + memcpy((char*)buffer + buffer_offset, to, tz_length); + tm->tz_name = (char*)buffer + buffer_offset; + buffer_offset += tz_length; + *((char*)buffer + buffer_offset) = '\0'; + buffer_offset++; + } + to += tz_length; + + tz_length = (uint)(*to++); + buffer_length += (tz_length + 1); + if (tz_length > 0 && buffer_offset + tz_length + 1 < bufferlen) { + memcpy((char*)buffer + buffer_offset, to, tz_length); + tm->tz_abbr = (char*)buffer + buffer_offset; + buffer_offset += tz_length; + *((char*)buffer + buffer_offset) = '\0'; + buffer_offset++; + } + to += tz_length; + } + *row = to; + return; +} static void fetch_result_object_complex(MYSQL_COMPLEX_BIND_OBJECT *header, MYSQL_BIND *param, @@ -1725,6 +1850,7 @@ static void fetch_result_object_complex(MYSQL_COMPLEX_BIND_OBJECT *header, header->length = (char*)buffer - (char*)header->buffer; return; } + static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos) { uint length= net_field_length(pos); @@ -1850,11 +1976,13 @@ static void fetch_result_complex(MYSQL_BIND *param, void *buffer, CHILD_TYPE *child, uchar **row) { switch (child->type) { + case TYPE_OB_NUMBER_FLOAT: case TYPE_NUMBER: { fetch_result_str_complex((MYSQL_COMPLEX_BIND_STRING *)buffer, param, row); break; } + case TYPE_NVARCHAR2: case TYPE_VARCHAR2: case TYPE_CHAR: { @@ -1911,6 +2039,19 @@ static void fetch_result_complex(MYSQL_BIND *param, void *buffer, fetch_result_double_complex((MYSQL_COMPLEX_BIND_BASIC *)buffer, param, row); break; } + case TYPE_OB_INTERVAL_DS: + case TYPE_OB_INTERVAL_YM: + { + fetch_result_ob_interval_complex((MYSQL_COMPLEX_BIND_BASIC *)buffer, param, row); + break; + } + case TYPE_OB_TIMESTAMP_NANO: + case TYPE_OB_TIMESTAMP_WITH_TIME_ZONE: + case TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE: + { + fetch_result_ob_timestamp_complex((MYSQL_COMPLEX_BIND_BASIC *)buffer, param, row); + break; + } default: *param->error= 1; break; @@ -1987,6 +2128,11 @@ static uint mysql_type_to_object_type(uint mysql_type) object_type = TYPE_VARCHAR2; break; } + case MYSQL_TYPE_OB_NVARCHAR2: + { + object_type = TYPE_NVARCHAR2; + break; + } case MYSQL_TYPE_OB_RAW: { object_type = TYPE_RAW; @@ -2007,6 +2153,36 @@ static uint mysql_type_to_object_type(uint mysql_type) object_type = TYPE_COLLECTION; break; } + case MYSQL_TYPE_OB_NUMBER_FLOAT: + { + object_type = TYPE_OB_NUMBER_FLOAT; + break; + } + case MYSQL_TYPE_OB_INTERVAL_DS: + { + object_type = TYPE_OB_INTERVAL_DS; + break; + } + case MYSQL_TYPE_OB_INTERVAL_YM: + { + object_type = TYPE_OB_INTERVAL_YM; + break; + } + case MYSQL_TYPE_OB_TIMESTAMP_NANO: + { + object_type = TYPE_OB_TIMESTAMP_NANO; + break; + } + case MYSQL_TYPE_OB_TIMESTAMP_WITH_TIME_ZONE: + { + object_type = TYPE_OB_TIMESTAMP_WITH_TIME_ZONE; + break; + } + case MYSQL_TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE: + { + object_type = TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE; + break; + } default: object_type = TYPE_UNKNOW; break; @@ -2031,6 +2207,12 @@ static void fill_complex_type(MYSQL_BIND *param, void *buffer, header->buffer_type = MYSQL_TYPE_VARCHAR; break; } + case TYPE_NVARCHAR2: + { + MYSQL_COMPLEX_BIND_STRING *header = (MYSQL_COMPLEX_BIND_STRING *)buffer; + header->buffer_type = MYSQL_TYPE_OB_NVARCHAR2; + break; + } case TYPE_RAW: { MYSQL_COMPLEX_BIND_STRING *header = (MYSQL_COMPLEX_BIND_STRING *)buffer; @@ -2079,6 +2261,42 @@ static void fill_complex_type(MYSQL_BIND *param, void *buffer, header->buffer_type = MYSQL_TYPE_DOUBLE; break; } + case TYPE_OB_NUMBER_FLOAT: + { + MYSQL_COMPLEX_BIND_STRING *header = (MYSQL_COMPLEX_BIND_STRING *)buffer; + header->buffer_type = MYSQL_TYPE_OB_NUMBER_FLOAT; + break; + } + case TYPE_OB_INTERVAL_DS: + { + MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer; + header->buffer_type = MYSQL_TYPE_OB_INTERVAL_DS; + break; + } + case TYPE_OB_INTERVAL_YM: + { + MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer; + header->buffer_type = MYSQL_TYPE_OB_INTERVAL_YM; + break; + } + case TYPE_OB_TIMESTAMP_NANO: + { + MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer; + header->buffer_type = MYSQL_TYPE_OB_TIMESTAMP_NANO; + break; + } + case TYPE_OB_TIMESTAMP_WITH_TIME_ZONE: + { + MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer; + header->buffer_type = MYSQL_TYPE_OB_TIMESTAMP_WITH_TIME_ZONE; + break; + } + case TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE: + { + MYSQL_COMPLEX_BIND_BASIC *header = (MYSQL_COMPLEX_BIND_BASIC *)buffer; + header->buffer_type = MYSQL_TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE; + break; + } case TYPE_OBJECT: { MYSQL_COMPLEX_BIND_OBJECT *header = (MYSQL_COMPLEX_BIND_OBJECT *)buffer; diff --git a/libmariadb/mariadb_lib.c b/libmariadb/mariadb_lib.c index 081c520..7018bc1 100644 --- a/libmariadb/mariadb_lib.c +++ b/libmariadb/mariadb_lib.c @@ -946,15 +946,18 @@ static size_t rset_field_offsets[]= { MYSQL_FIELD * unpack_fields(const MYSQL *mysql, - MYSQL_DATA *data, MA_MEM_ROOT *alloc, uint fields, - my_bool default_value) + MYSQL_DATA *data, MA_MEM_ROOT *alloc, uint fields, my_bool default_value) { +#define CHECK_PKT_LENGTH(len1, len2) {if ((len1) > (len2)) goto error;} +#define CHECK_PKT_LENGTH_END(len1, len2) {if ((len1) >= (len2)) goto error;} + MYSQL_ROWS *row; MYSQL_FIELD *field,*result; uchar *p; /* use unsigned char for data to avoid convert error for char to uint. */ unsigned int i, field_count= sizeof(rset_field_offsets)/sizeof(size_t)/2; - uchar *complex_type; - ulong len; + uchar *complex_type = NULL; + ulong len = 0; + ulong pkt_len = 0; field=result=(MYSQL_FIELD*) ma_alloc_root(alloc,sizeof(MYSQL_FIELD)*fields); if (!result) @@ -1016,27 +1019,32 @@ unpack_fields(const MYSQL *mysql, if (MYSQL_TYPE_OBJECT == field->type) { complex_type = (uchar*)row->data[i]; + pkt_len = row->data_length[i]; len=(ulong) net_field_length(&complex_type); field->owner_name_length = len; if (0 == len) { field->owner_name = NULL; } else { - field->owner_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len+1); + CHECK_PKT_LENGTH(len, (pkt_len - ((char*)complex_type - row->data[i]))); + field->owner_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len + 1); field->owner_name[len] = 0; complex_type += len; } + CHECK_PKT_LENGTH_END((char*)complex_type - row->data[i], (long)pkt_len); len=(ulong) net_field_length(&complex_type); field->type_name_length = len; if (0 == len) { field->type_name = NULL; } else { + CHECK_PKT_LENGTH(len, (pkt_len - ((char*)complex_type - row->data[i]))); field->type_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len+1); field->type_name[len] = 0; complex_type += len; } + CHECK_PKT_LENGTH_END((char*)complex_type - row->data[i], (long)pkt_len); field->version = (ulong) net_field_length(&complex_type); if (0 == len) { @@ -1044,6 +1052,7 @@ unpack_fields(const MYSQL *mysql, complex_type++; if (MYSQL_TYPE_OBJECT == field->elem_type) { + CHECK_PKT_LENGTH_END((char*)complex_type - row->data[i], (long)pkt_len); len=(ulong) net_field_length(&complex_type); field->elem_owner_name_length = len; if (0 == len) { @@ -1051,35 +1060,53 @@ unpack_fields(const MYSQL *mysql, } else { - field->elem_owner_name = (unsigned char *)ma_memdup_root(alloc, (char *)complex_type, len); + CHECK_PKT_LENGTH(len, (pkt_len - ((char*)complex_type - row->data[i]))); + field->elem_owner_name = (unsigned char *)ma_memdup_root(alloc, (char *)complex_type, len + 1); + field->elem_owner_name[len] = 0; complex_type += len; } + CHECK_PKT_LENGTH_END((char*)complex_type - row->data[i], (long)pkt_len); len=(ulong) net_field_length(&complex_type); field->elem_type_name_length = len; if (0 == len) { field->elem_type_name = NULL; } else { - field->elem_type_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len); + CHECK_PKT_LENGTH(len, (pkt_len - ((char*)complex_type - row->data[i]))); + field->elem_type_name = (unsigned char *)ma_memdup_root(alloc, (char*)complex_type, len+1); + field->elem_type_name[len] = 0; complex_type += len; } - + CHECK_PKT_LENGTH_END((char*)complex_type - row->data[i], (long)pkt_len); field->elem_version = (ulong) net_field_length(&complex_type); } } - len = (ulong) net_field_length(&complex_type); - - if (default_value && len > 0) { - field->def=ma_memdup_root(alloc, (char*)complex_type, len); - } else { - field->def=0; + //object 检查下长度,这里后面应该是没有数据了,防止core + if ((char*)complex_type - row->data[i] > (long)pkt_len) + { + //CHECK_PKT_LENGTH_END((char*)complex_type - row->data[i], pkt_len); + len = (ulong)net_field_length(&complex_type); + if (default_value && len > 0 && len != NULL_LENGTH) { + field->def = ma_memdup_root(alloc, (char*)complex_type, len); + } else { + field->def = 0; + } } } else { - if (default_value && row->data[i]) { - field->def=ma_strdup_root(alloc,(char*) row->data[i]); + /* + mthd_my_read_query_result ma_result_set_rows 9:8->8:7, 保证最后的row->data[i]里面含有length + 为了兼容PS协议/二合一协议object处理,最后row->data[i]里面包含length,所以这里要先解析length + */ + if (default_value && row->data[i] && row->data_length[i] > 0) { + len = (ulong)net_field_length(&(row->data[i])); + if (default_value && len > 0 && len != NULL_LENGTH) { + field->def = ma_strdup_root(alloc, (char*)row->data[i]); + } else { + field->def = 0; + } } else { - field->def=0; + field->def = 0; } } field->def_length= 0; @@ -1580,7 +1607,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, uint field; ulong pkt_len; ulong len; - uchar *cp; + uchar *cp, *end_cp; char *to, *end_to; MYSQL_DATA *result; MYSQL_ROWS **prev_ptr,*cur; @@ -1603,6 +1630,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, while (*(cp=net->read_pos) != 254 || pkt_len >= 8) { + end_cp = cp + pkt_len; if (mysql_fields) { for (field=0 ; field < fields ; field++) { if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH) { @@ -1632,17 +1660,21 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, } } cp = net->read_pos; + end_cp = cp + pkt_len; result->rows++; - if (!(cur= (MYSQL_ROWS*) ma_alloc_root(&result->alloc, - sizeof(MYSQL_ROWS))) || + if (!(cur= (MYSQL_ROWS*) ma_alloc_root(&result->alloc, sizeof(MYSQL_ROWS))) || !(cur->data= ((MYSQL_ROW) - ma_alloc_root(&result->alloc, - (fields+1)*sizeof(char *)+fields+pkt_len)))) + ma_alloc_root(&result->alloc, (fields+1)*sizeof(char *)+fields+pkt_len))) || + !(cur->data_length= (unsigned long*) + ma_alloc_root(&result->alloc, (fields + 1) * sizeof(unsigned long))) + ) { free_rows(result); SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); return(0); } + memset(cur->data, 0, (fields + 1) * sizeof(char *) + fields + pkt_len); + memset(cur->data_length, 0, (fields + 1) * sizeof(unsigned long)); *prev_ptr=cur; prev_ptr= &cur->next; to= (char*) (cur->data+fields+1); @@ -1652,6 +1684,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH) { /* null field */ cur->data[field] = 0; + cur->data_length[field] = 0; } else { @@ -1682,6 +1715,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, to+=convert_len+1; cp+=len; len = convert_len; + cur->data_length[field] = len; is_done = 1; } else if (mysql_fields[field].type == MYSQL_TYPE_OB_RAW) { uchar *end = cp + len; @@ -1691,6 +1725,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, (*to++)=0; len *= 2; + cur->data_length[field] = len; is_done = 1; } else if (mysql_fields[field].type == MYSQL_TYPE_OB_INTERVAL_YM || mysql_fields[field].type == MYSQL_TYPE_OB_INTERVAL_DS) { @@ -1702,6 +1737,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, to+=convert_len+1; cp+=len; len = convert_len; + cur->data_length[field] = len; is_done = 1; } } @@ -1709,6 +1745,7 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, memcpy(to,(char*) cp,len); to[len]=0; to+=len+1; cp+=len; + cur->data_length[field] = len; is_done = 1; } @@ -1719,8 +1756,12 @@ MYSQL_DATA *mthd_my_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, } } } - memcpy(to, (char *)cp, (ulong)(end_to - to)); + convert_len = (ulong)(end_cp - cp >= 0 ? (end_cp - cp) : 0); + memcpy(to, (char *)cp, convert_len); + //convert_len = (ulong)(end_to - to >= 0 ? (end_to - to) : 0); + //memcpy(to, (char *)cp, (ulong)(end_to - to)); cur->data[field]=to; /* End of last field */ + cur->data_length[field] = convert_len; //convert_len if ((pkt_len=ma_net_safe_read(mysql)) == packet_error) { free_rows(result); @@ -2147,7 +2188,7 @@ ma_set_ob_connect_attrs(MYSQL *mysql) cap |= OBCLIENT_CAP_PROXY_LOCAL_INFILES; } - snprintf(cap_buf, OB_MAX_UINT64_BUF_LEN, "%lu", cap); + snprintf(cap_buf, OB_MAX_UINT64_BUF_LEN, "%llu", 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"); @@ -2156,7 +2197,7 @@ ma_set_ob_connect_attrs(MYSQL *mysql) 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); + snprintf(caplob_buf, OB_MAX_UINT64_BUF_LEN, "%llu", 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]) { diff --git a/libmariadb/mariadb_stmt.c b/libmariadb/mariadb_stmt.c index 1aec9a5..39f8199 100644 --- a/libmariadb/mariadb_stmt.c +++ b/libmariadb/mariadb_stmt.c @@ -1275,6 +1275,35 @@ static void store_param_oracle_timestamp_tz_complex(unsigned char **pos, MYSQL_C *(*pos - length - 1) = length; } +static void store_param_oracle_interval_complex(unsigned char **pos, MYSQL_COMPLEX_BIND_HEADER *param) +{ + ORACLE_INTERVAL *interval = (ORACLE_INTERVAL *)param->buffer; + uchar buff[20] = {0}; + int len = 0; + + if (param->buffer_type == MYSQL_TYPE_OB_INTERVAL_YM) { + len = 8; + buff[0] = 7; + buff[1] = interval->data_symbol > 0 ? 0 : 1; //正 0, 负 1 + int4store(buff + 2, interval->data_object.ym_object.ym_year); + buff[6] = (uchar)(interval->data_object.ym_object.ym_month); + buff[7] = (uchar)(interval->data_object.ym_object.ym_scale); + } else if (param->buffer_type == MYSQL_TYPE_OB_INTERVAL_DS) { + len = 15; + buff[0] = 14; + buff[1] = interval->data_symbol > 0 ? 0 : 1; //正 0, 负 1 + int4store(buff + 2, interval->data_object.ds_object.ds_day); + buff[6] = (uchar)(interval->data_object.ds_object.ds_hour); + buff[7] = (uchar)(interval->data_object.ds_object.ds_minute); + buff[8] = (uchar)(interval->data_object.ds_object.ds_second); + int4store(buff + 9, interval->data_object.ds_object.ds_frac_second); + buff[13] = (uchar)(interval->data_object.ds_object.ds_day_scale); + buff[14] = (uchar)(interval->data_object.ds_object.ds_frac_second_scale); + } + memcpy((char *)*pos, buff, len); + (*pos) += len; +} + static void store_param_str_complex(unsigned char **pos, MYSQL_COMPLEX_BIND_STRING *param) { /* param->length is always set in mysql_stmt_bind_param */ @@ -1453,6 +1482,10 @@ static void store_param_all_complex(unsigned char **pos, MYSQL_COMPLEX_BIND_HEAD case MYSQL_TYPE_OB_TIMESTAMP_WITH_TIME_ZONE: store_param_oracle_timestamp_tz_complex(pos, header); break; + case MYSQL_TYPE_OB_INTERVAL_YM: + case MYSQL_TYPE_OB_INTERVAL_DS: + store_param_oracle_interval_complex(pos, header); + break; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: @@ -1807,6 +1840,8 @@ int convert_type_to_complex(enum enum_field_types type) case MYSQL_TYPE_CURSOR: case MYSQL_TYPE_ORA_BLOB: case MYSQL_TYPE_ORA_CLOB: + case MYSQL_TYPE_OB_INTERVAL_DS: + case MYSQL_TYPE_OB_INTERVAL_YM: case MYSQL_TYPE_OB_TIMESTAMP_NANO: case MYSQL_TYPE_OB_TIMESTAMP_WITH_TIME_ZONE: case MYSQL_TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE: @@ -3160,6 +3195,8 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned lon if (length == (unsigned long) -1) length= (unsigned long)strlen(query); + free_old_query(mysql); //new query clean old feilds + /* clear flags */ CLEAR_CLIENT_STMT_ERROR(stmt); CLEAR_CLIENT_ERROR(stmt->mysql); @@ -3370,6 +3407,12 @@ static int madb_alloc_stmt_fields(MYSQL_STMT *stmt) SET_CLIENT_STMT_ERROR(stmt, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); return(1); } + if (!stmt->mysql->fields) { + if (stmt->mysql->net.last_errno == 0) + SET_CLIENT_STMT_ERROR(stmt, CR_NEW_STMT_METADATA, SQLSTATE_UNKNOWN, 0); + return(1); + } + memset(stmt->fields, 0, sizeof(MYSQL_FIELD) * stmt->mysql->field_count); stmt->field_count= stmt->mysql->field_count; @@ -3558,8 +3601,8 @@ int stmt_read_execute_response(MYSQL_STMT *stmt) /* Only cursor read */ stmt->default_rset_handler = _mysql_stmt_use_result; - - } else if (stmt->flags & CURSOR_TYPE_READ_ONLY) + stmt->state = MYSQL_STMT_WAITING_USE_OR_STORE; + } else if ((stmt->flags & CURSOR_TYPE_READ_ONLY) && !(stmt->upsert_status.server_status & SERVER_MORE_RESULTS_EXIST)) { /* We have asked for CURSOR but got no cursor, because the condition @@ -3571,6 +3614,8 @@ int stmt_read_execute_response(MYSQL_STMT *stmt) precached on client and server's resources are freed. */ + if (stmt->mysql->status == MYSQL_STATUS_GET_RESULT) + stmt->mysql->status = MYSQL_STATUS_STMT_RESULT; /* preferred is buffered read */ if (mysql_stmt_store_result(stmt)) return 1; @@ -3590,8 +3635,9 @@ int stmt_read_execute_response(MYSQL_STMT *stmt) } else { stmt->mysql->status= MYSQL_STATUS_STMT_RESULT; } + stmt->state = MYSQL_STMT_WAITING_USE_OR_STORE; } - stmt->state= MYSQL_STMT_WAITING_USE_OR_STORE; + //stmt->state= MYSQL_STMT_WAITING_USE_OR_STORE; /* in certain cases parameter types can change: For example see bug 4026 (SELECT ?), so we need to update field information */ // if (mysql->field_count == stmt->field_count) @@ -4523,7 +4569,7 @@ uint32 ob_crc32(uint64_t crc, const char *buf, int64_t len) return crc64 & 0xffffffff; } -uint64 ob_crc64(uint64_t crc, const char *buf, int64_t len) +uint64_t ob_crc64(uint64_t crc, const char *buf, int64_t len) { uint64_t crc64 = crc64_sse42_dispatch(crc, buf, len); return crc64; @@ -5248,6 +5294,8 @@ mysql_stmt_prepare_v2(MYSQL_STMT *stmt, const char *query, if (length == (unsigned long) -1) length= (unsigned long)strlen(query); + free_old_query(mysql); //new query clean old feilds + /* clear flags */ CLEAR_CLIENT_STMT_ERROR(stmt); CLEAR_CLIENT_ERROR(stmt->mysql); @@ -6139,7 +6187,7 @@ mysql_stmt_read_piece_data(MYSQL_STMT *stmt, unsigned int param_number, *param->error = 1; } else { ulong copy_length = MIN(*ret_data_len, param->buffer_length); - memcpy(param->buffer, (char *)*row, copy_length); + memcpy(param->buffer, (char *)row, copy_length); *param->error = copy_length < *ret_data_len; } *param->length = *ret_data_len; diff --git a/libmariadb/ob_complex.c b/libmariadb/ob_complex.c index 2f01751..a50b44d 100644 --- a/libmariadb/ob_complex.c +++ b/libmariadb/ob_complex.c @@ -207,6 +207,26 @@ static enum_types convert_type(const char *type) { return TYPE_DATE; } else if (!strcmp(type, "RAW")) { return TYPE_RAW; + } else if (!strcmp(type, "NVARCHAR2")) { + return TYPE_NVARCHAR2; + } else if (!strcmp(type, "FLOAT")) { + return TYPE_OB_NUMBER_FLOAT; + } else if (!strncmp(type, "INTERVAL YEAR", 13)) { + return TYPE_OB_INTERVAL_YM; + } else if (!strncmp(type, "INTERVAL DAY", 12)) { + return TYPE_OB_INTERVAL_DS; + } else if (!strncmp(type, "TIMESTAMP", 9)) { + if (strstr(type, "WITH TIME ZONE")) { + return TYPE_OB_TIMESTAMP_WITH_TIME_ZONE; + } else if (strstr(type, "WITH LOCAL TIME ZONE")) { + return TYPE_OB_TIMESTAMP_WITH_LOCAL_TIME_ZONE; + } else { + return TYPE_OB_TIMESTAMP_NANO; + } + } else if (!strcmp(type, "BINARY_FLOAT")) { + return TYPE_FLOAT; + } else if (!strcmp(type, "BINARY_DOUBLE")) { + return TYPE_DOUBLE; } else { return TYPE_MAX; } diff --git a/libmariadb/ob_load_balance.c b/libmariadb/ob_load_balance.c index 9f820f6..6d690e9 100644 --- a/libmariadb/ob_load_balance.c +++ b/libmariadb/ob_load_balance.c @@ -44,8 +44,8 @@ typedef struct _st_ob_lb_address_list { }ObLbAddressList; typedef struct _st_connect_info { - int connect_cnt; - int connect_max; + unsigned int connect_cnt; + unsigned int connect_max; int64_t *connect_list; }ConnectInfo; @@ -137,8 +137,8 @@ static ObLbAddress* get_ob_address_by_address_list(ObLbAddressList *addr_list) break; } case OBCLIENT_LB_OPTION_SERVERAFFINITY: { - int rand_number = (int)rand() % weight + 1; int index = 0; + int rand_number = (int)rand() % weight + 1; for (index = 0; index < valid_cnt; ++index) { rand_number -= addr_list->add_arr[idxarr[index]].weight; if (index == valid_cnt - 1 || rand_number <= 0) { @@ -192,7 +192,7 @@ static void check_ob_address_black(ObLbAddress * address, ObClientLbConfig *conf 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 + int64_t duration = config->black_append_duration * 1000;// µ¥Î»msתΪus for (idx = 0; idx < len; idx++) { if (curtime - list[idx] <= duration) { break; @@ -236,16 +236,74 @@ static void check_ob_address_white(ObLbAddressList * addr_list, ObClientLbConfig } } -static int init_oblb_addresslist(ObLbAddressList* list, ObClientLbAddressList* addrlist) { +static int init_oblb_addresslist_str(ObLbAddressList* list, char* str, ObClientLBOption oblb_strategy) { + int ret = 0; + if (NULL == list || NULL == str) { + ret = -1; + } else { + char *p = str, *s = NULL, *e = NULL; + int count = 1; + while (p && *p) { + if (*p++ == ',') + count++; + } + + if (OB_ISNULL(list->add_arr = (ObLbAddress*)calloc(1, count * sizeof(ObLbAddress)))) { + ret = -1; + } else { + unsigned int i = 0; + my_bool valid = 0; + my_bool instring = 0; + int idx = 0; + int port = 0; + p = str; + while (p && *p) { + if (instring == 0 && *p == '[') { + instring = 1; + s = p + 1; + valid = 0; + } else if (instring == 1 && *p == ']') { + instring = 0; + e = p; + valid = 1; + } else if (instring == 0 && *p == ',') { + s = p + 1; + e = NULL; + valid = 0; + } else if (instring == 0 && *p == ':') { + if (valid == 0) { + e = p; + } + if (s && e) { + memcpy(list->add_arr[idx].host, s, e - s); + list->add_arr[idx].port = atoi(p + 1); + list->add_arr[i].weight = 1; + list->add_arr[i].state = OBCLIENT_LB_WHITE; + + idx++; + s = NULL; + e = NULL; + valid = 0; + } + } + p++; + } + list->count = idx; + list->rotation_flag = 0; + list->option = oblb_strategy; + } + } + return ret; +} +static int init_oblb_addresslist(ObLbAddressList* list, ObClientLbAddressList* addrlist, ObClientLBOption oblb_strategy) { 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)))) { + } else if (OB_ISNULL(list->add_arr = (ObLbAddress*)calloc(1, 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; @@ -254,19 +312,18 @@ static int init_oblb_addresslist(ObLbAddressList* list, ObClientLbAddressList* a } list->count = addrlist->address_list_count; list->rotation_flag = 0; - list->option = OBCLIENT_LB_OPTION_ROTATION; + list->option = oblb_strategy; } return ret; } -static int init_oblb_addresslist_tns(ObLbAddressList* list, ObClientAddressList* addrlist) { +static int init_oblb_addresslist_tns(ObLbAddressList* list, ObClientAddressList* addrlist, ObClientLBOption oblb_strategy) { 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)))){ + } else if (OB_ISNULL(list->add_arr = (ObLbAddress*)calloc(1, 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; @@ -275,18 +332,57 @@ static int init_oblb_addresslist_tns(ObLbAddressList* list, ObClientAddressList* } list->count = addrlist->address_count; list->rotation_flag = 0; - list->option = addrlist->oblb_strategy; + if (addrlist->oblb_strategy != OBCLIENT_LB_OPTION_RANDOM && + addrlist->oblb_strategy != OBCLIENT_LB_OPTION_SERVERAFFINITY && + addrlist->oblb_strategy != OBCLIENT_LB_OPTION_ROTATION) { + list->option = oblb_strategy; + } else { + list->option = addrlist->oblb_strategy; + } + } + return ret; +} +static void release_oblb_addresslist(ObLbAddressList* list) { + if (list && list->add_arr) { + free(list->add_arr); + list->add_arr = NULL; + list->count = 0; + } +} + +static int post_session_variable(MYSQL *mysql, char *session_variable, int session_variable_len) +{ + int ret = 0; + + if (NULL == mysql) { + ret = -1; + } else if (0 == session_variable_len) { + ; + } else { + char post_sql[1024] = { 0 }; + int post_sql_len = snprintf(post_sql, 1024, "set %.*s", session_variable_len, session_variable); + if (post_sql_len < 0) { + ret = -1; + } else if (mysql_real_query(mysql, post_sql, post_sql_len)) { + ret = -1; + } } return ret; } -static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, ObClientLbConfig *config, + +static MYSQL* connect_by_addresslist(MYSQL* mysql, int64_t lb_starttime, 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; + char buf[128] = { 0 }; + int64_t lb_endtime = 0; + my_bool default_report_data_truncation = 1; + unsigned int default_local_infile = 2; + unsigned int default_connect_timeout = 6;//s unsigned int mysql_connect_timeout = 0; unsigned int mysql_read_timeout = 0; @@ -307,6 +403,7 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O my_bool mysql_opt_interactive = 0; my_bool mysql_report_data_truncation = 0; my_bool mysql_opt_reconnect = 0; + char* mysql_read_default_file = NULL; my_bool mysql_opt_use_ssl = 0; my_bool mysql_opt_ssl_verify_server_cert = 0; @@ -318,8 +415,9 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O 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) { + SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "invalid handle or address list is zero."); return NULL; } @@ -328,13 +426,6 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O 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; @@ -344,6 +435,8 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O } init_connect_info(&(addr_list->add_arr[i])); } + lb_endtime = lb_starttime + config->retry_timeout * 1000; + srand(time(NULL)); //init mysql options mysql_connect_timeout = config->mysql_connect_timeout; @@ -364,6 +457,7 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O mysql_opt_interactive = config->mysql_opt_interactive; mysql_report_data_truncation = config->mysql_report_data_truncation; mysql_opt_reconnect = config->mysql_opt_reconnect; + mysql_read_default_file = config->mysql_read_default_file; mysql_opt_use_ssl = config->mysql_opt_use_ssl; mysql_opt_ssl_verify_server_cert = config->mysql_opt_ssl_verify_server_cert; @@ -382,6 +476,7 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O //get address if (NULL == (address = get_ob_address_by_address_list(addr_list))) { + SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "address list is empty(all in black)."); break; } @@ -392,6 +487,10 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O #ifdef DEBUG_LOAD_BALANCE printf("host:%s,port:%d,state:%d\n", address->host, address->port, address->state); #endif + //set default options + mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, (char *)&default_report_data_truncation); + mysql_options(mysql, MYSQL_OPT_LOCAL_INFILE, (char*)&default_local_infile); + mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &default_connect_timeout); //mysql options if (mysql_connect_timeout > 0) @@ -430,6 +529,8 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O 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_read_default_file && *mysql_read_default_file) + mysql_options(mysql, MYSQL_READ_DEFAULT_FILE, (char*)mysql_read_default_file); 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); @@ -459,8 +560,18 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O //check black check_ob_address_black(address, config); + if (config->retry_timeout > 0 && get_current_time_us() > lb_endtime) { + snprintf(buf, sizeof(buf), "retry_timeout(%d)(%lld-%lld).", config->retry_timeout, lb_starttime, get_current_time_us()); + SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, buf); + break; + } + config->retry_all_downs--; - } while (address && config->retry_all_downs > 0); + if (config->retry_all_downs <= 0) { + SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "retry_all_downs is zero."); + break; + } + } while (address); //release connect for (i = 0; i < addr_list->count; i++) { @@ -470,23 +581,28 @@ static MYSQL* connect_by_addresslist(MYSQL* mysql, ObLbAddressList *addr_list, O return tmp; } -static MYSQL* connect_by_tnsname(MYSQL* mysql, const char* tns_name, ObClientLbConfig * config, +static MYSQL* connect_by_tnsname(MYSQL* mysql, int64_t lb_starttime, 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; + char buf[128] = { 0 }; my_bool find = 0; ObClientTns tns; const char *sid = db; + char session_variable[1024] = { 0 }; char new_user_name[256] = { 0 }; int user_len = strlen((const char *)user ? user : ""); + int64_t lb_endtime = 0; - if (OB_FAIL(ObClientTnsInit(&tns))) { - tmp = NULL; + if (NULL == tns_name || NULL == config) { + SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "invalid tns_name or config."); + } else if (OB_FAIL(ObClientTnsInit(&tns))) { + SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "tns init fail."); } else if (OB_FAIL(ObClientTnsBuild(&tns, tns_name, strlen(tns_name), &find))) { - tmp = NULL; + SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "ob client tns build fail."); } else if (1 != find || !tns.tns_service || !tns.tns_service->description || tns.tns_service->description_count == 0) { - tmp = NULL; + SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "tns description is null."); } else { unsigned int i = 0; ObClientDescription *des = tns.tns_service->description; @@ -507,28 +623,40 @@ static MYSQL* connect_by_tnsname(MYSQL* mysql, const char* tns_name, ObClientLbC //tns config config->retry_all_downs = des->retry_all_downs; + config->retry_timeout = des->retry_timeout; 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; + if (des->connect_timout > 0) config->mysql_connect_timeout = des->connect_timout; + if (des->read_timout > 0) config->mysql_read_timeout = des->read_timout; + if (des->write_timout > 0) config->mysql_write_timeout = des->write_timout; + lb_endtime = lb_starttime + config->retry_timeout * 1000; 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; + ObLbAddressList list; + memset(&list, 0, sizeof(list)); + if (OB_SUCC(init_oblb_addresslist_tns(&list, &(des->address_list[i]), des->oblb_strategy))) { + tmp = connect_by_addresslist(mysql, lb_starttime, &list, config, new_user_name, passwd, sid, unix_socket, client_flag, success); } + release_oblb_addresslist(&list); + + //connect success if (tmp) { + if (des && des->connect_data && des->connect_data->session_variable_len > 0) { + post_session_variable(tmp, des->connect_data->session_variable, des->connect_data->session_variable_len); + } + break; + } + + if (config->retry_timeout > 0 && get_current_time_us() > lb_endtime) { + snprintf(buf, sizeof(buf), "retry_timeout(%d)(%lld-%lld).", config->retry_timeout, lb_starttime, get_current_time_us()); + SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, buf); break; } } @@ -542,20 +670,84 @@ MYSQL* ob_mysql_real_connect(MYSQL* mysql, const char* tns_name, ObClientLbAddre { int ret = 0; MYSQL *tmp = NULL; + ObClientLbConfig default_config = {0}; + int64_t lb_starttime = get_current_time_us(); + + if (NULL == config) { + memset(&default_config, 0, sizeof(ObClientLbConfig)); + config = &default_config; + } if (tns_name && *tns_name) { - tmp = connect_by_tnsname(mysql, tns_name, config, user, passwd, db, unix_socket, client_flag, success); - } else { + tmp = connect_by_tnsname(mysql, lb_starttime, tns_name, config, user, passwd, db, unix_socket, client_flag, success); + } else if (addr_list) { 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; + if (OB_SUCC(init_oblb_addresslist(&list, addr_list, OBCLIENT_LB_OPTION_ROTATION))) { + if (config->retry_all_downs <= 0) config->retry_all_downs = addr_list->address_list_count; + if (config->retry_timeout <= 0) config->retry_timeout = 0; //list µØÖ·Ä£Ê½Ä¬ÈÏÂÖѵ£¬Õâ¸ö²ÎÊý²»ÉúЧ + 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->black_append_duration <= 0) config->black_append_duration = 10 * 1000; + if (config->black_append_retrytimes <= 0) config->black_append_retrytimes = 1; + if (config->black_remove_strategy != OBCLIENT_LB_OPTION_TIMEOUT) { + config->black_remove_strategy = OBCLIENT_LB_OPTION_TIMEOUT; + } + //if (config->black_remove_timeout <= 0) config->black_remove_timeout = 50 * 1000; + + tmp = connect_by_addresslist(mysql, lb_starttime, &list, config, user, passwd, db, unix_socket, client_flag, success); } + release_oblb_addresslist(&list); + } else { + SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "tns_name/addr_list is null."); + } + + return tmp; +} + +MYSQL* ob_mysql_real_connect2(MYSQL* mysql, const char* tns_name, const char *addr_list, ObClientLbConfig *config, + const char *user, const char *passwd, const char *db, const char *unix_socket, unsigned long client_flag, char* success, int len_success) +{ + int ret = 0; + MYSQL *tmp = NULL; + ObClientLbConfig default_config = { 0 }; + ObClientLbAddress success_addr; + int64_t lb_starttime = get_current_time_us(); + memset(&success_addr, 0, sizeof(success_addr)); + + if (NULL == config) { + memset(&default_config, 0, sizeof(ObClientLbConfig)); + config = &default_config; + } + + if (tns_name && *tns_name) { + tmp = connect_by_tnsname(mysql, lb_starttime, tns_name, config, user, passwd, db, unix_socket, client_flag, &success_addr); + } else if (addr_list) { + ObLbAddressList list; + memset(&list, 0, sizeof(list)); + if (OB_SUCC(init_oblb_addresslist_str(&list, (char*)addr_list, OBCLIENT_LB_OPTION_ROTATION))) { + if (config->retry_all_downs <= 0) config->retry_all_downs = list.count; + if (config->retry_timeout <= 0) config->retry_timeout = 0; //list µØÖ·Ä£Ê½Ä¬ÈÏÂÖѵ£¬Õâ¸ö²ÎÊý²»ÉúЧ + 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->black_append_duration <= 0) config->black_append_duration = 10 * 1000; + if (config->black_append_retrytimes <= 0) config->black_append_retrytimes = 1; + if (config->black_remove_strategy != OBCLIENT_LB_OPTION_TIMEOUT) { + config->black_remove_strategy = OBCLIENT_LB_OPTION_TIMEOUT; + } + //if (config->black_remove_timeout <= 0) config->black_remove_timeout = 50 * 1000; + tmp = connect_by_addresslist(mysql, lb_starttime, &list, config, user, passwd, db, unix_socket, client_flag, &success_addr); + } + release_oblb_addresslist(&list); + } else { + SET_CLIENT_ERROR(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "tns_name/addr_list is null."); + } + if (tmp && success && len_success > 0) { + snprintf(success, len_success, "[%s]:%d", success_addr.host, success_addr.port); } return tmp; diff --git a/libmariadb/ob_protocol20.c b/libmariadb/ob_protocol20.c index 4ac7f82..8e3da03 100644 --- a/libmariadb/ob_protocol20.c +++ b/libmariadb/ob_protocol20.c @@ -5,7 +5,6 @@ #include "mysql.h" #include "ma_global.h" -#include "ob_object.h" #include "ob_full_link_trace.h" #include "ob_rwlock.h" diff --git a/libmariadb/ob_tnsname.c b/libmariadb/ob_tnsname.c index 13eacd9..a30acf3 100644 --- a/libmariadb/ob_tnsname.c +++ b/libmariadb/ob_tnsname.c @@ -101,7 +101,7 @@ static ObClientLBKeyType tns_keytype_15[] = { OBCLIENT_LB_REMOVE_STRATEGY, OBCLI static ObClientLBKeyType tns_keytype_16[] = { OBCLIENT_LB_SESSION_VARIABLE}; static ObClientLBKeyType tns_keytype_17[] = { OBCLIENT_LB_READ_TIMEOUT}; static ObClientLBKeyType tns_keytype_18[] = { OBCLIENT_LB_EXTRA_INFO, OBCLIENT_LB_OBLB_RETRY_TIMEOUT, OBCLIENT_LB_WRITE_TIMEOUT}; -static ObClientLBKeyType tns_keytype_19[] = { OBCLIENT_LB_OBLB_GROUP_STRATEGY }; +static ObClientLBKeyType tns_keytype_19[] = { OBCLIENT_LB_OBLB_GROUP_STRATEGY}; static ObClientLBKeyType tns_keytype_20[] = { OBCLIENT_LB_OBLB_RETRY_ALL_DOWNS, OBCLIENT_LB_CONNECT_TIMEOUT}; static const void *tns_key_array[] = { @@ -568,7 +568,7 @@ int ObClientTnsServiceSkip(ObClientTnsParseParams *parse_params) return ret; } -int ObClientTnsServiceExtraInfoGet(ObClientTnsService *tns_service, char *extra_info, int *extra_info_len, int *ob_mode) +int ObClientTnsServiceExtraInfoGet(ObClientTnsService *tns_service, char *extra_info, int *extra_info_len, int *ob_mode, char* session_variable, int *session_variable_len) { int ret = 0; ObClientDescription *des; @@ -580,10 +580,16 @@ int ObClientTnsServiceExtraInfoGet(ObClientTnsService *tns_service, char *extra_ ret = -1; } else if (OB_ISNULL(con_data = des->connect_data)) { ret = -1; - } else if (0 != con_data->user_extra_info_len) { - *extra_info_len = con_data->user_extra_info_len; - strncpy(extra_info, con_data->user_extra_info, *extra_info_len); - *ob_mode = con_data->ob_mode; + } else { + if (0 != con_data->user_extra_info_len) { + *extra_info_len = con_data->user_extra_info_len; + strncpy(extra_info, con_data->user_extra_info, *extra_info_len); + *ob_mode = con_data->ob_mode; + } + if (0 != con_data->session_variable_len) { + *session_variable_len = con_data->session_variable_len; + strncpy(session_variable, con_data->session_variable, *session_variable_len); + } } return ret; @@ -791,6 +797,17 @@ int ObClientDescriptionBuild(ObClientTnsService *tns_service, ObClientTnsParsePa TNS_PARSE_INTRGER_VALUE(parse_params, des->read_timout); } else if (OBCLIENT_LB_WRITE_TIMEOUT == parse_params->key_type) { TNS_PARSE_INTRGER_VALUE(parse_params, des->write_timout); + } else if (OBCLIENT_LB_OBLB_STRATEGY == parse_params->key_type) { + TNS_PARSE(parse_params, TNS_KEY); + if (0 == strncasecmp(parse_params->tns_key, "RANDOM", parse_params->tns_key_len)) { + des->oblb_strategy = OBCLIENT_LB_OPTION_RANDOM; + } else if (0 == strncasecmp(parse_params->tns_key, "SERVERAFFINITY", parse_params->tns_key_len)) { + des->oblb_strategy = OBCLIENT_LB_OPTION_SERVERAFFINITY; + } else if (0 == strncasecmp(parse_params->tns_key, "ROTATION", parse_params->tns_key_len)) { + des->oblb_strategy = OBCLIENT_LB_OPTION_ROTATION; + } else { + ret = -1; + } } else if (OBCLIENT_LB_OBLB_GROUP_STRATEGY == parse_params->key_type) { TNS_PARSE(parse_params, TNS_KEY); if (0 == strncasecmp(parse_params->tns_key, "ROTATION", parse_params->tns_key_len)) { @@ -1244,6 +1261,9 @@ int ObClientConnectDataDisplay(ObClientConnectData *con_data, FILE *display_file fprintf(display_file, "----------obmode:%ld\n", con_data->ob_mode); fprintf(display_file, "----------use_default_sid:%ld\n", con_data->use_default_sid); } + if (0 != con_data->session_variable_len) { + fprintf(display_file, "----------session_variable:%.*s\n", con_data->session_variable_len, con_data->session_variable); + } } return ret; @@ -1283,6 +1303,8 @@ int ObClientConnectDataBuild(ObClientDescription *des, ObClientTnsParseParams *p TNS_PARSE_INTRGER_VALUE(parse_params, connect_data->ob_mode); } else if (OBCLIENT_LB_USE_DEFAULT_SID == parse_params->key_type) { TNS_PARSE_INTRGER_VALUE(parse_params, connect_data->use_default_sid); + } else if (OBCLIENT_LB_SESSION_VARIABLE == parse_params->key_type) { + TNS_PARSE_STRING_VALUE(parse_params, connect_data->session_variable, connect_data->session_variable_len, OBCLIENT_TNS_KEY_SIZE); } else { ret = -1; } @@ -1467,19 +1489,25 @@ int ObClientTnsParseBlank(ObClientTnsParseParams *parse_params) } } else { while (parse_params->buffer_pos < parse_params->buffer_len) { - ch = parse_params->tns_buffer[parse_params->buffer_pos]; - if ('\t' == ch || '\n' == ch || ' ' == ch) { - parse_params->buffer_pos++; - } else if ('#' == ch) { // ignore comments + if (!parse_params->is_comment) { + ch = parse_params->tns_buffer[parse_params->buffer_pos]; + if (('\t' == ch || '\n' == ch || ' ' == ch || '\r' == ch)) { + parse_params->buffer_pos++; + } else if ('#' == ch) { // ignore comments + parse_params->is_comment = 1; + } else { + break; + } + } else { unsigned int tmp = parse_params->buffer_pos; for (; tmp < parse_params->buffer_len; tmp++) { char tmpch = parse_params->tns_buffer[tmp]; - if ('\n' == tmpch || '\0' == tmpch) + if ('\n' == tmpch || '\0' == tmpch) { + parse_params->is_comment = 0; break; + } } parse_params->buffer_pos = tmp; - } else { - break; } } if (parse_params->buffer_pos < parse_params->buffer_len) { diff --git a/libmariadb/ob_tnsname.h b/libmariadb/ob_tnsname.h index ed80dac..8498b9f 100644 --- a/libmariadb/ob_tnsname.h +++ b/libmariadb/ob_tnsname.h @@ -149,6 +149,7 @@ struct obclient_description unsigned long read_timout; // 单次读的超时时间 unsigned long write_timout; // 单次写的超时时间 unsigned long retry_timeout; // 整个LB阶段的超时时间 + ObClientLBOption oblb_strategy; ObClientLBOption oblb_group_strategy; ObClientBlacklistConf black_list_conf; }; @@ -178,6 +179,8 @@ struct obclient_connect_data unsigned int service_name_len; char user_extra_info[OBCLIENT_TNS_KEY_SIZE]; unsigned int user_extra_info_len; + char session_variable[OBCLIENT_TNS_KEY_SIZE]; + unsigned int session_variable_len; unsigned long ob_mode; unsigned long use_default_sid; }; @@ -196,6 +199,7 @@ struct obclient_tns_parse_params char *description; int description_len; int description_offset; + int is_comment; ObClientTnsTokenType tns_token_type; ObClientLBKeyType key_type; }; @@ -214,7 +218,7 @@ int ObClientTnsServiceDisplay(ObClientTnsService *tns_service, FILE *display_fil 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); +int ObClientTnsServiceExtraInfoGet(ObClientTnsService *tns_service, char *extra_info, int *extra_info_len, int *ob_mode, char* session_variable, int *session_variable_len); // 非负载均衡模式下获取dblink, 直接获取第一个address,拼接dblink int ObClientTnsServiceDblinkGet(ObClientTnsService *tns_service, char *dblink, int *dblink_len); diff --git a/libmariadb/ob_utils.c b/libmariadb/ob_utils.c index 1abc9d4..471dd63 100644 --- a/libmariadb/ob_utils.c +++ b/libmariadb/ob_utils.c @@ -32,5 +32,5 @@ int64_t get_current_time_us() { struct timeval tv; gettimeofday(&tv, NULL); - return tv.tv_sec * 1000000 + tv.tv_usec; + return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec; } diff --git a/rpm/libobclient-VER.txt b/rpm/libobclient-VER.txt index 5bc1cc4..23a63f5 100644 --- a/rpm/libobclient-VER.txt +++ b/rpm/libobclient-VER.txt @@ -1 +1 @@ -2.2.7 +2.2.8