Merge branch 'release-1.3.0' into doc_fixes

This commit is contained in:
Johan Wikman
2015-12-07 14:41:30 +02:00
12 changed files with 2111 additions and 1985 deletions

View File

@ -117,7 +117,7 @@ This parameter is used to define the maximum amount of data that will be sent to
This parameter is used to enable/disable incomplete transactions detection in binlog router. This parameter is used to enable/disable incomplete transactions detection in binlog router.
When MaxScale starts an error message may appear if current binlog file is corrupted or an incomplete transaction is found. When MaxScale starts an error message may appear if current binlog file is corrupted or an incomplete transaction is found.
During normal operations binlog events are not distributed to the slaves until a COMMIT is seen. During normal operations binlog events are not distributed to the slaves until a COMMIT is seen.
The default value is on, set transaction_safety=off to completely disable the incomplete transactions detection. The default value is off, set transaction_safety=on to enable the incomplete transactions detection.
A complete example of a service entry for a binlog router service would be as follows. A complete example of a service entry for a binlog router service would be as follows.
``` ```

View File

@ -3,4 +3,3 @@ set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB")
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_BINARY_DIR}/postinst;{CMAKE_BINARY_DIR}/postrm") set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_BINARY_DIR}/postinst;{CMAKE_BINARY_DIR}/postrm")
execute_process(COMMAND dpgk --print-architecture OUTPUT_VARIABLE DEB_ARCHITECTURE) execute_process(COMMAND dpgk --print-architecture OUTPUT_VARIABLE DEB_ARCHITECTURE)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${DEB_ARCHITECTURE}) set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${DEB_ARCHITECTURE})
set (CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@ Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Copyright MariaDB Corporation Ab Copyright MariaDB Corporation Ab
*/ */
/** getpid */ /** getpid */
#include <my_config.h> #include <my_config.h>
@ -33,90 +33,96 @@ EXTERN_C_BLOCK_BEGIN
* The meaninful difference is where operation is done and whether master data * The meaninful difference is where operation is done and whether master data
* is modified * is modified
*/ */
typedef enum { typedef enum
QUERY_TYPE_UNKNOWN = 0x000000, /*< Initial value, can't be tested bitwisely */ {
QUERY_TYPE_LOCAL_READ = 0x000001, /*< Read non-database data, execute in MaxScale:any */ QUERY_TYPE_UNKNOWN = 0x000000, /*< Initial value, can't be tested bitwisely */
QUERY_TYPE_READ = 0x000002, /*< Read database data:any */ QUERY_TYPE_LOCAL_READ = 0x000001, /*< Read non-database data, execute in MaxScale:any */
QUERY_TYPE_WRITE = 0x000004, /*< Master data will be modified:master */ QUERY_TYPE_READ = 0x000002, /*< Read database data:any */
QUERY_TYPE_MASTER_READ = 0x000008, /*< Read from the master:master */ QUERY_TYPE_WRITE = 0x000004, /*< Master data will be modified:master */
QUERY_TYPE_SESSION_WRITE = 0x000010, /*< Session data will be modified:master or all */ QUERY_TYPE_MASTER_READ = 0x000008, /*< Read from the master:master */
QUERY_TYPE_SESSION_WRITE = 0x000010, /*< Session data will be modified:master or all */
/** Not implemented yet */ /** Not implemented yet */
// QUERY_TYPE_USERVAR_WRITE = 0x000020, /*< Write a user variable:master or all */ // QUERY_TYPE_USERVAR_WRITE = 0x000020, /*< Write a user variable:master or all */
QUERY_TYPE_USERVAR_READ = 0x000040, /*< Read a user variable:master or any */ QUERY_TYPE_USERVAR_READ = 0x000040, /*< Read a user variable:master or any */
QUERY_TYPE_SYSVAR_READ = 0x000080, /*< Read a system variable:master or any */ QUERY_TYPE_SYSVAR_READ = 0x000080, /*< Read a system variable:master or any */
/** Not implemented yet */ /** Not implemented yet */
// QUERY_TYPE_SYSVAR_WRITE = 0x000100, /*< Write a system variable:master or all */ // QUERY_TYPE_SYSVAR_WRITE = 0x000100, /*< Write a system variable:master or all */
QUERY_TYPE_GSYSVAR_READ = 0x000200, /*< Read global system variable:master or any */ QUERY_TYPE_GSYSVAR_READ = 0x000200, /*< Read global system variable:master or any */
QUERY_TYPE_GSYSVAR_WRITE = 0x000400, /*< Write global system variable:master or all */ QUERY_TYPE_GSYSVAR_WRITE = 0x000400, /*< Write global system variable:master or all */
QUERY_TYPE_BEGIN_TRX = 0x000800, /*< BEGIN or START TRANSACTION */ QUERY_TYPE_BEGIN_TRX = 0x000800, /*< BEGIN or START TRANSACTION */
QUERY_TYPE_ENABLE_AUTOCOMMIT = 0x001000, /*< SET autocommit=1 */ QUERY_TYPE_ENABLE_AUTOCOMMIT = 0x001000, /*< SET autocommit=1 */
QUERY_TYPE_DISABLE_AUTOCOMMIT = 0x002000, /*< SET autocommit=0 */ QUERY_TYPE_DISABLE_AUTOCOMMIT = 0x002000, /*< SET autocommit=0 */
QUERY_TYPE_ROLLBACK = 0x004000, /*< ROLLBACK */ QUERY_TYPE_ROLLBACK = 0x004000, /*< ROLLBACK */
QUERY_TYPE_COMMIT = 0x008000, /*< COMMIT */ QUERY_TYPE_COMMIT = 0x008000, /*< COMMIT */
QUERY_TYPE_PREPARE_NAMED_STMT = 0x010000, /*< Prepared stmt with name from user:all */ QUERY_TYPE_PREPARE_NAMED_STMT = 0x010000, /*< Prepared stmt with name from user:all */
QUERY_TYPE_PREPARE_STMT = 0x020000, /*< Prepared stmt with id provided by server:all */ QUERY_TYPE_PREPARE_STMT = 0x020000, /*< Prepared stmt with id provided by server:all */
QUERY_TYPE_EXEC_STMT = 0x040000, /*< Execute prepared statement:master or any */ QUERY_TYPE_EXEC_STMT = 0x040000, /*< Execute prepared statement:master or any */
QUERY_TYPE_CREATE_TMP_TABLE = 0x080000, /*< Create temporary table:master (could be all) */ QUERY_TYPE_CREATE_TMP_TABLE = 0x080000, /*< Create temporary table:master (could be all) */
QUERY_TYPE_READ_TMP_TABLE = 0x100000, /*< Read temporary table:master (could be any) */ QUERY_TYPE_READ_TMP_TABLE = 0x100000, /*< Read temporary table:master (could be any) */
QUERY_TYPE_SHOW_DATABASES = 0x200000, /*< Show list of databases */ QUERY_TYPE_SHOW_DATABASES = 0x200000, /*< Show list of databases */
QUERY_TYPE_SHOW_TABLES = 0x400000 /*< Show list of tables */ QUERY_TYPE_SHOW_TABLES = 0x400000 /*< Show list of tables */
} skygw_query_type_t; } skygw_query_type_t;
typedef enum { typedef enum
QUERY_OP_UNDEFINED = 0, {
QUERY_OP_SELECT = 1, QUERY_OP_UNDEFINED = 0,
QUERY_OP_UPDATE = (1 << 1), QUERY_OP_SELECT = 1,
QUERY_OP_INSERT = (1 << 2), QUERY_OP_UPDATE = (1 << 1),
QUERY_OP_DELETE = (1 << 3), QUERY_OP_INSERT = (1 << 2),
QUERY_OP_INSERT_SELECT = (1 << 4), QUERY_OP_DELETE = (1 << 3),
QUERY_OP_TRUNCATE = (1 << 5), QUERY_OP_INSERT_SELECT = (1 << 4),
QUERY_OP_ALTER_TABLE = (1 << 6), QUERY_OP_TRUNCATE = (1 << 5),
QUERY_OP_CREATE_TABLE = (1 << 7), QUERY_OP_ALTER_TABLE = (1 << 6),
QUERY_OP_CREATE_INDEX = (1 << 8), QUERY_OP_CREATE_TABLE = (1 << 7),
QUERY_OP_DROP_TABLE = (1 << 9), QUERY_OP_CREATE_INDEX = (1 << 8),
QUERY_OP_DROP_INDEX = (1 << 10), QUERY_OP_DROP_TABLE = (1 << 9),
QUERY_OP_CHANGE_DB = (1 << 11), QUERY_OP_DROP_INDEX = (1 << 10),
QUERY_OP_LOAD = (1 << 12) QUERY_OP_CHANGE_DB = (1 << 11),
}skygw_query_op_t; QUERY_OP_LOAD = (1 << 12)
} skygw_query_op_t;
typedef struct parsing_info_st { typedef struct parsing_info_st
{
#if defined(SS_DEBUG) #if defined(SS_DEBUG)
skygw_chk_t pi_chk_top; skygw_chk_t pi_chk_top;
#endif #endif
void* pi_handle; /*< parsing info object pointer */ void* pi_handle; /*< parsing info object pointer */
char* pi_query_plain_str; /*< query as plain string */ char* pi_query_plain_str; /*< query as plain string */
void (*pi_done_fp)(void *); /*< clean-up function for parsing info */ void (*pi_done_fp)(void *); /*< clean-up function for parsing info */
#if defined(SS_DEBUG) #if defined(SS_DEBUG)
skygw_chk_t pi_chk_tail; skygw_chk_t pi_chk_tail;
#endif #endif
} parsing_info_t; } parsing_info_t;
#define QUERY_IS_TYPE(mask,type) ((mask & type) == type) #define QUERY_IS_TYPE(mask,type) ((mask & type) == type)
/** /**
* Create THD and use it for creating parse tree. Examine parse tree and * Create THD and use it for creating parse tree. Examine parse tree and
* classify the query. * classify the query.
*/ */
skygw_query_type_t query_classifier_get_type(GWBUF* querybuf); skygw_query_type_t query_classifier_get_type(GWBUF* querybuf);
skygw_query_op_t query_classifier_get_operation(GWBUF* querybuf); skygw_query_op_t query_classifier_get_operation(GWBUF* querybuf);
/** Free THD context and close MYSQL */
#if defined(NOT_USED) #if defined(NOT_USED)
char* skygw_query_classifier_get_stmtname(GWBUF* buf); char* skygw_query_classifier_get_stmtname(GWBUF* buf);
#endif #endif
char* skygw_get_created_table_name(GWBUF* querybuf);
bool is_drop_table_query(GWBUF* querybuf); char* skygw_get_created_table_name(GWBUF* querybuf);
bool skygw_is_real_query(GWBUF* querybuf); bool is_drop_table_query(GWBUF* querybuf);
char** skygw_get_table_names(GWBUF* querybuf, int* tblsize, bool fullnames); bool skygw_is_real_query(GWBUF* querybuf);
char* skygw_get_canonical(GWBUF* querybuf); char** skygw_get_table_names(GWBUF* querybuf, int* tblsize, bool fullnames);
bool parse_query (GWBUF* querybuf); char* skygw_get_canonical(GWBUF* querybuf);
bool parse_query(GWBUF* querybuf);
parsing_info_t* parsing_info_init(void (*donefun)(void *)); parsing_info_t* parsing_info_init(void (*donefun)(void *));
void parsing_info_done(void* ptr);
bool query_is_parsed(GWBUF* buf); /** Free THD context and close MYSQL */
bool skygw_query_has_clause(GWBUF* buf); void parsing_info_done(void* ptr);
char* skygw_get_qtype_str(skygw_query_type_t qtype); bool query_is_parsed(GWBUF* buf);
char* skygw_get_affected_fields(GWBUF* buf); bool skygw_query_has_clause(GWBUF* buf);
char** skygw_get_database_names(GWBUF* querybuf,int* size); char* skygw_get_qtype_str(skygw_query_type_t qtype);
char* skygw_get_affected_fields(GWBUF* buf);
char** skygw_get_database_names(GWBUF* querybuf, int* size);
EXTERN_C_BLOCK_END EXTERN_C_BLOCK_END

View File

@ -210,7 +210,7 @@ static bool resolve_maxscale_conf_fname(
char* cnf_file_arg); char* cnf_file_arg);
static char* check_dir_access(char* dirname, bool, bool); static char* check_dir_access(char* dirname, bool, bool);
static int set_user(); static int set_user(const char* user);
bool pid_file_exists(); bool pid_file_exists();
void write_child_exit_code(int fd, int code); void write_child_exit_code(int fd, int code);
/** SSL multi-threading functions and structures */ /** SSL multi-threading functions and structures */
@ -968,7 +968,7 @@ static void usage(void)
" (default: /etc/)\n" " (default: /etc/)\n"
" -D, --datadir=PATH path to data directory, stored embedded mysql tables\n" " -D, --datadir=PATH path to data directory, stored embedded mysql tables\n"
" (default: /var/cache/maxscale)\n" " (default: /var/cache/maxscale)\n"
" -N, --language=PATH apth to errmsg.sys file\n" " -N, --language=PATH path to errmsg.sys file\n"
" (default: /var/lib/maxscale)\n" " (default: /var/lib/maxscale)\n"
" -P, --piddir=PATH path to PID file directory\n" " -P, --piddir=PATH path to PID file directory\n"
" (default: /var/run/maxscale)\n" " (default: /var/run/maxscale)\n"
@ -2433,7 +2433,7 @@ static int cnf_preparser(void* data, const char* section, const char* name, cons
return 1; return 1;
} }
static int set_user(char* user) static int set_user(const char* user)
{ {
errno = 0; errno = 0;
struct passwd *pwname; struct passwd *pwname;

View File

@ -109,13 +109,13 @@ bitmask_set(GWBITMASK *bitmask, int bit)
unsigned char mask; unsigned char mask;
spinlock_acquire(&bitmask->lock); spinlock_acquire(&bitmask->lock);
if (bit >= bitmask->length) while (bit >= bitmask->length)
{ {
bitmask->bits = realloc(bitmask->bits, bitmask->bits = realloc(bitmask->bits,
(bitmask->length + BIT_LENGTH_INC) / 8); (bitmask->length + BIT_LENGTH_INC) / 8);
memset(bitmask->bits + (bitmask->length / 8), 0, memset(bitmask->bits + (bitmask->length / 8), 0,
BIT_LENGTH_INC / 8); BIT_LENGTH_INC / 8);
bitmask->length += (BIT_LENGTH_INC / 8); bitmask->length += BIT_LENGTH_INC;
} }
ptr = bitmask->bits + (bit / 8); ptr = bitmask->bits + (bit / 8);
mask = 1 << (bit % 8); mask = 1 << (bit % 8);

View File

@ -33,8 +33,8 @@
*/ */
/* Both these numbers MUST be exact multiples of 8 */ /* Both these numbers MUST be exact multiples of 8 */
#define BIT_LENGTH_INITIAL 32 /**< Initial number of bits in the bitmask */ #define BIT_LENGTH_INITIAL 256 /**< Initial number of bits in the bitmask */
#define BIT_LENGTH_INC 32 /**< Number of bits to add on each increment */ #define BIT_LENGTH_INC 256 /**< Number of bits to add on each increment */
/** /**
* The bitmask structure used to store an arbitrary large bitmask * The bitmask structure used to store an arbitrary large bitmask

View File

@ -37,52 +37,55 @@
* connections to. This provides the storage for routing module specific data * connections to. This provides the storage for routing module specific data
* that is required for each of the backend servers. * that is required for each of the backend servers.
*/ */
typedef struct backend { typedef struct backend
SERVER *server; /*< The server itself */ {
int current_connection_count; /*< Number of connections to the server */ SERVER *server; /*< The server itself */
int weight; /*< Desired routing weight */ int current_connection_count; /*< Number of connections to the server */
int weight; /*< Desired routing weight */
} BACKEND; } BACKEND;
/** /**
* The client session structure used within this router. * The client session structure used within this router.
*/ */
typedef struct router_client_session { typedef struct router_client_session
{
#if defined(SS_DEBUG) #if defined(SS_DEBUG)
skygw_chk_t rses_chk_top; skygw_chk_t rses_chk_top;
#endif #endif
SPINLOCK rses_lock; /*< protects rses_deleted */ SPINLOCK rses_lock; /*< protects rses_deleted */
int rses_versno; /*< even = no active update, else odd */ int rses_versno; /*< even = no active update, else odd */
bool rses_closed; /*< true when closeSession is called */ bool rses_closed; /*< true when closeSession is called */
BACKEND *backend; /*< Backend used by the client session */ BACKEND *backend; /*< Backend used by the client session */
DCB *backend_dcb; /*< DCB Connection to the backend */ DCB *backend_dcb; /*< DCB Connection to the backend */
struct router_client_session *next; struct router_client_session *next;
int rses_capabilities; /*< input type, for example */ int rses_capabilities; /*< input type, for example */
#if defined(SS_DEBUG) #if defined(SS_DEBUG)
skygw_chk_t rses_chk_tail; skygw_chk_t rses_chk_tail;
#endif #endif
} ROUTER_CLIENT_SES; } ROUTER_CLIENT_SES;
/** /**
* The statistics for this router instance * The statistics for this router instance
*/ */
typedef struct { typedef struct
int n_sessions; /*< Number sessions created */ {
int n_queries; /*< Number of queries forwarded */ int n_sessions; /*< Number sessions created */
int n_queries; /*< Number of queries forwarded */
} ROUTER_STATS; } ROUTER_STATS;
/** /**
* The per instance data for the router. * The per instance data for the router.
*/ */
typedef struct router_instance { typedef struct router_instance
SERVICE *service; /*< Pointer to the service using this router */ {
ROUTER_CLIENT_SES *connections; /*< Link list of all the client connections */ SERVICE *service; /*< Pointer to the service using this router */
SPINLOCK lock; /*< Spinlock for the instance data */ ROUTER_CLIENT_SES *connections; /*< Link list of all the client connections */
BACKEND **servers; /*< List of backend servers */ SPINLOCK lock; /*< Spinlock for the instance data */
unsigned int bitmask; /*< Bitmask to apply to server->status */ BACKEND **servers; /*< List of backend servers */
unsigned int bitvalue; /*< Required value of server->status */ unsigned int bitmask; /*< Bitmask to apply to server->status */
ROUTER_STATS stats; /*< Statistics for this router */ unsigned int bitvalue; /*< Required value of server->status */
struct router_instance ROUTER_STATS stats; /*< Statistics for this router */
*next; struct router_instance
*next;
} ROUTER_INSTANCE; } ROUTER_INSTANCE;
#endif #endif

View File

@ -284,7 +284,7 @@ char task_name[BLRM_TASK_NAME_LEN+1] = "";
inst->m_errno = 0; inst->m_errno = 0;
inst->m_errmsg = NULL; inst->m_errmsg = NULL;
inst->trx_safe = 1; inst->trx_safe = 0;
inst->pending_transaction = 0; inst->pending_transaction = 0;
inst->last_safe_pos = 0; inst->last_safe_pos = 0;

File diff suppressed because it is too large Load Diff

View File

@ -4653,7 +4653,7 @@ static void rwsplit_process_router_options(
/** /**
* Error Handler routine to resolve _backend_ failures. If it succeeds then there * Error Handler routine to resolve _backend_ failures. If it succeeds then there
* are enough operative backends available and connected. Otherwise it fails, * are enough operative backends available and connected. Otherwise it fails,
* and session is terminated. * and session is terminated.
* *
* @param instance The router instance * @param instance The router instance
@ -4662,7 +4662,7 @@ static void rwsplit_process_router_options(
* @param backend_dcb The backend DCB * @param backend_dcb The backend DCB
* @param action The action: ERRACT_NEW_CONNECTION or ERRACT_REPLY_CLIENT * @param action The action: ERRACT_NEW_CONNECTION or ERRACT_REPLY_CLIENT
* @param succp Result of action: true iff router can continue * @param succp Result of action: true iff router can continue
* *
* Even if succp == true connecting to new slave may have failed. succp is to * Even if succp == true connecting to new slave may have failed. succp is to
* tell whether router has enough master/slave connections to continue work. * tell whether router has enough master/slave connections to continue work.
*/ */
@ -4670,7 +4670,7 @@ static void handleError (
ROUTER* instance, ROUTER* instance,
void* router_session, void* router_session,
GWBUF* errmsgbuf, GWBUF* errmsgbuf,
DCB* backend_dcb, DCB* problem_dcb,
error_action_t action, error_action_t action,
bool* succp) bool* succp)
{ {
@ -4678,10 +4678,10 @@ static void handleError (
ROUTER_INSTANCE* inst = (ROUTER_INSTANCE *)instance; ROUTER_INSTANCE* inst = (ROUTER_INSTANCE *)instance;
ROUTER_CLIENT_SES* rses = (ROUTER_CLIENT_SES *)router_session; ROUTER_CLIENT_SES* rses = (ROUTER_CLIENT_SES *)router_session;
CHK_DCB(backend_dcb); CHK_DCB(problem_dcb);
/** Don't handle same error twice on same DCB */ /** Don't handle same error twice on same DCB */
if (backend_dcb->dcb_errhandle_called) if (problem_dcb->dcb_errhandle_called)
{ {
/** we optimistically assume that previous call succeed */ /** we optimistically assume that previous call succeed */
/* /*
@ -4693,24 +4693,28 @@ static void handleError (
} }
else else
{ {
backend_dcb->dcb_errhandle_called = true; problem_dcb->dcb_errhandle_called = true;
} }
session = backend_dcb->session; session = problem_dcb->session;
if (session == NULL || rses == NULL) if (session == NULL || rses == NULL)
{ {
*succp = false; *succp = false;
} }
else if (dcb_isclient(problem_dcb))
{
*succp = false;
}
else else
{ {
CHK_SESSION(session); CHK_SESSION(session);
CHK_CLIENT_RSES(rses); CHK_CLIENT_RSES(rses);
switch (action) { switch (action) {
case ERRACT_NEW_CONNECTION: case ERRACT_NEW_CONNECTION:
{ {
SERVER* srv; SERVER* srv;
if (!rses_begin_locked_router_action(rses)) if (!rses_begin_locked_router_action(rses))
{ {
*succp = false; *succp = false;
@ -4718,14 +4722,14 @@ static void handleError (
} }
srv = rses->rses_master_ref->bref_backend->backend_server; srv = rses->rses_master_ref->bref_backend->backend_server;
/** /**
* If master has lost its Master status error can't be * If master has lost its Master status error can't be
* handled so that session could continue. * handled so that session could continue.
*/ */
if (rses->rses_master_ref->bref_dcb == backend_dcb && if (rses->rses_master_ref->bref_dcb == problem_dcb &&
!SERVER_IS_MASTER(srv)) !SERVER_IS_MASTER(srv))
{ {
backend_ref_t* bref; backend_ref_t* bref;
bref = get_bref_from_dcb(rses, backend_dcb); bref = get_bref_from_dcb(rses, problem_dcb);
if (bref != NULL) if (bref != NULL)
{ {
CHK_BACKEND_REF(bref); CHK_BACKEND_REF(bref);
@ -4739,7 +4743,7 @@ static void handleError (
"corresponding backend ref.", "corresponding backend ref.",
srv->name, srv->name,
srv->port); srv->port);
dcb_close(backend_dcb); dcb_close(problem_dcb);
} }
if (!srv->master_err_is_logged) if (!srv->master_err_is_logged)
{ {
@ -4756,35 +4760,35 @@ static void handleError (
else else
{ {
/** /**
* This is called in hope of getting replacement for * This is called in hope of getting replacement for
* failed slave(s). This call may free rses. * failed slave(s). This call may free rses.
*/ */
*succp = handle_error_new_connection(inst, *succp = handle_error_new_connection(inst,
&rses, &rses,
backend_dcb, problem_dcb,
errmsgbuf); errmsgbuf);
} }
/* Free the lock if rses still exists */ /* Free the lock if rses still exists */
if (rses) rses_end_locked_router_action(rses); if (rses) rses_end_locked_router_action(rses);
break; break;
} }
case ERRACT_REPLY_CLIENT: case ERRACT_REPLY_CLIENT:
{ {
handle_error_reply_client(session, handle_error_reply_client(session,
rses, rses,
backend_dcb, problem_dcb,
errmsgbuf); errmsgbuf);
*succp = false; /*< no new backend servers were made available */ *succp = false; /*< no new backend servers were made available */
break; break;
} }
default: default:
*succp = false; *succp = false;
break; break;
} }
} }
dcb_close(backend_dcb); dcb_close(problem_dcb);
} }
@ -4797,7 +4801,7 @@ static void handle_error_reply_client(
session_state_t sesstate; session_state_t sesstate;
DCB* client_dcb; DCB* client_dcb;
backend_ref_t* bref; backend_ref_t* bref;
spinlock_acquire(&ses->ses_lock); spinlock_acquire(&ses->ses_lock);
sesstate = ses->state; sesstate = ses->state;
client_dcb = ses->client; client_dcb = ses->client;
@ -4812,7 +4816,7 @@ static void handle_error_reply_client(
bref_clear_state(bref, BREF_IN_USE); bref_clear_state(bref, BREF_IN_USE);
bref_set_state(bref, BREF_CLOSED); bref_set_state(bref, BREF_CLOSED);
} }
if (sesstate == SESSION_STATE_ROUTER_READY) if (sesstate == SESSION_STATE_ROUTER_READY)
{ {
CHK_DCB(client_dcb); CHK_DCB(client_dcb);

View File

@ -4001,7 +4001,7 @@ return_succp:
/** /**
* Error Handler routine to resolve _backend_ failures. If it succeeds then there * Error Handler routine to resolve _backend_ failures. If it succeeds then there
* are enough operative backends available and connected. Otherwise it fails, * are enough operative backends available and connected. Otherwise it fails,
* and session is terminated. * and session is terminated.
* *
* @param instance The router instance * @param instance The router instance
@ -4010,7 +4010,7 @@ return_succp:
* @param backend_dcb The backend DCB * @param backend_dcb The backend DCB
* @param action The action: ERRACT_NEW_CONNECTION or ERRACT_REPLY_CLIENT * @param action The action: ERRACT_NEW_CONNECTION or ERRACT_REPLY_CLIENT
* @param succp Result of action: true iff router can continue * @param succp Result of action: true iff router can continue
* *
* Even if succp == true connecting to new slave may have failed. succp is to * Even if succp == true connecting to new slave may have failed. succp is to
* tell whether router has enough master/slave connections to continue work. * tell whether router has enough master/slave connections to continue work.
*/ */
@ -4018,7 +4018,7 @@ static void handleError (
ROUTER* instance, ROUTER* instance,
void* router_session, void* router_session,
GWBUF* errmsgbuf, GWBUF* errmsgbuf,
DCB* backend_dcb, DCB* problem_dcb,
error_action_t action, error_action_t action,
bool* succp) bool* succp)
{ {
@ -4026,10 +4026,10 @@ static void handleError (
ROUTER_INSTANCE* inst = (ROUTER_INSTANCE *)instance; ROUTER_INSTANCE* inst = (ROUTER_INSTANCE *)instance;
ROUTER_CLIENT_SES* rses = (ROUTER_CLIENT_SES *)router_session; ROUTER_CLIENT_SES* rses = (ROUTER_CLIENT_SES *)router_session;
CHK_DCB(backend_dcb); CHK_DCB(problem_dcb);
/** Don't handle same error twice on same DCB */ /** Don't handle same error twice on same DCB */
if (backend_dcb->dcb_errhandle_called) if (problem_dcb->dcb_errhandle_called)
{ {
/** we optimistically assume that previous call succeed */ /** we optimistically assume that previous call succeed */
*succp = true; *succp = true;
@ -4037,19 +4037,23 @@ static void handleError (
} }
else else
{ {
backend_dcb->dcb_errhandle_called = true; problem_dcb->dcb_errhandle_called = true;
} }
session = backend_dcb->session; session = problem_dcb->session;
if (session == NULL || rses == NULL) if (session == NULL || rses == NULL)
{ {
*succp = false; *succp = false;
} }
else if (dcb_isclient(problem_dcb))
{
*succp = false;
}
else else
{ {
CHK_SESSION(session); CHK_SESSION(session);
CHK_CLIENT_RSES(rses); CHK_CLIENT_RSES(rses);
switch (action) { switch (action) {
case ERRACT_NEW_CONNECTION: case ERRACT_NEW_CONNECTION:
{ {
@ -4059,33 +4063,33 @@ static void handleError (
break; break;
} }
/** /**
* This is called in hope of getting replacement for * This is called in hope of getting replacement for
* failed slave(s). * failed slave(s).
*/ */
*succp = handle_error_new_connection(inst, *succp = handle_error_new_connection(inst,
rses, rses,
backend_dcb, problem_dcb,
errmsgbuf); errmsgbuf);
rses_end_locked_router_action(rses); rses_end_locked_router_action(rses);
break; break;
} }
case ERRACT_REPLY_CLIENT: case ERRACT_REPLY_CLIENT:
{ {
handle_error_reply_client(session, handle_error_reply_client(session,
rses, rses,
backend_dcb, problem_dcb,
errmsgbuf); errmsgbuf);
*succp = false; /*< no new backend servers were made available */ *succp = false; /*< no new backend servers were made available */
break; break;
} }
default: default:
*succp = false; *succp = false;
break; break;
} }
} }
dcb_close(backend_dcb); dcb_close(problem_dcb);
} }