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.
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.
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.
```

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")
execute_process(COMMAND dpgk --print-architecture OUTPUT_VARIABLE 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
*/
*/
/** getpid */
#include <my_config.h>
@ -33,90 +33,96 @@ EXTERN_C_BLOCK_BEGIN
* The meaninful difference is where operation is done and whether master data
* is modified
*/
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_READ = 0x000002, /*< Read database data:any */
QUERY_TYPE_WRITE = 0x000004, /*< Master data will be modified:master */
QUERY_TYPE_MASTER_READ = 0x000008, /*< Read from the master:master */
QUERY_TYPE_SESSION_WRITE = 0x000010, /*< Session data will be modified:master or all */
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_READ = 0x000002, /*< Read database data:any */
QUERY_TYPE_WRITE = 0x000004, /*< Master data will be modified:master */
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 */
// 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_SYSVAR_READ = 0x000080, /*< Read a system variable:master or any */
// 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_SYSVAR_READ = 0x000080, /*< Read a system variable:master or any */
/** Not implemented yet */
// 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_WRITE = 0x000400, /*< Write global system variable:master or all */
QUERY_TYPE_BEGIN_TRX = 0x000800, /*< BEGIN or START TRANSACTION */
QUERY_TYPE_ENABLE_AUTOCOMMIT = 0x001000, /*< SET autocommit=1 */
QUERY_TYPE_DISABLE_AUTOCOMMIT = 0x002000, /*< SET autocommit=0 */
QUERY_TYPE_ROLLBACK = 0x004000, /*< ROLLBACK */
QUERY_TYPE_COMMIT = 0x008000, /*< COMMIT */
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_EXEC_STMT = 0x040000, /*< Execute prepared statement:master or any */
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_SHOW_DATABASES = 0x200000, /*< Show list of databases */
QUERY_TYPE_SHOW_TABLES = 0x400000 /*< Show list of tables */
// 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_WRITE = 0x000400, /*< Write global system variable:master or all */
QUERY_TYPE_BEGIN_TRX = 0x000800, /*< BEGIN or START TRANSACTION */
QUERY_TYPE_ENABLE_AUTOCOMMIT = 0x001000, /*< SET autocommit=1 */
QUERY_TYPE_DISABLE_AUTOCOMMIT = 0x002000, /*< SET autocommit=0 */
QUERY_TYPE_ROLLBACK = 0x004000, /*< ROLLBACK */
QUERY_TYPE_COMMIT = 0x008000, /*< COMMIT */
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_EXEC_STMT = 0x040000, /*< Execute prepared statement:master or any */
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_SHOW_DATABASES = 0x200000, /*< Show list of databases */
QUERY_TYPE_SHOW_TABLES = 0x400000 /*< Show list of tables */
} skygw_query_type_t;
typedef enum {
QUERY_OP_UNDEFINED = 0,
QUERY_OP_SELECT = 1,
QUERY_OP_UPDATE = (1 << 1),
QUERY_OP_INSERT = (1 << 2),
QUERY_OP_DELETE = (1 << 3),
QUERY_OP_INSERT_SELECT = (1 << 4),
QUERY_OP_TRUNCATE = (1 << 5),
QUERY_OP_ALTER_TABLE = (1 << 6),
QUERY_OP_CREATE_TABLE = (1 << 7),
QUERY_OP_CREATE_INDEX = (1 << 8),
QUERY_OP_DROP_TABLE = (1 << 9),
QUERY_OP_DROP_INDEX = (1 << 10),
QUERY_OP_CHANGE_DB = (1 << 11),
QUERY_OP_LOAD = (1 << 12)
}skygw_query_op_t;
typedef enum
{
QUERY_OP_UNDEFINED = 0,
QUERY_OP_SELECT = 1,
QUERY_OP_UPDATE = (1 << 1),
QUERY_OP_INSERT = (1 << 2),
QUERY_OP_DELETE = (1 << 3),
QUERY_OP_INSERT_SELECT = (1 << 4),
QUERY_OP_TRUNCATE = (1 << 5),
QUERY_OP_ALTER_TABLE = (1 << 6),
QUERY_OP_CREATE_TABLE = (1 << 7),
QUERY_OP_CREATE_INDEX = (1 << 8),
QUERY_OP_DROP_TABLE = (1 << 9),
QUERY_OP_DROP_INDEX = (1 << 10),
QUERY_OP_CHANGE_DB = (1 << 11),
QUERY_OP_LOAD = (1 << 12)
} skygw_query_op_t;
typedef struct parsing_info_st {
typedef struct parsing_info_st
{
#if defined(SS_DEBUG)
skygw_chk_t pi_chk_top;
skygw_chk_t pi_chk_top;
#endif
void* pi_handle; /*< parsing info object pointer */
char* pi_query_plain_str; /*< query as plain string */
void (*pi_done_fp)(void *); /*< clean-up function for parsing info */
void* pi_handle; /*< parsing info object pointer */
char* pi_query_plain_str; /*< query as plain string */
void (*pi_done_fp)(void *); /*< clean-up function for parsing info */
#if defined(SS_DEBUG)
skygw_chk_t pi_chk_tail;
skygw_chk_t pi_chk_tail;
#endif
} parsing_info_t;
#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.
*/
skygw_query_type_t query_classifier_get_type(GWBUF* querybuf);
skygw_query_op_t query_classifier_get_operation(GWBUF* querybuf);
/** Free THD context and close MYSQL */
#if defined(NOT_USED)
char* skygw_query_classifier_get_stmtname(GWBUF* buf);
char* skygw_query_classifier_get_stmtname(GWBUF* buf);
#endif
char* skygw_get_created_table_name(GWBUF* querybuf);
bool is_drop_table_query(GWBUF* querybuf);
bool skygw_is_real_query(GWBUF* querybuf);
char** skygw_get_table_names(GWBUF* querybuf, int* tblsize, bool fullnames);
char* skygw_get_canonical(GWBUF* querybuf);
bool parse_query (GWBUF* querybuf);
char* skygw_get_created_table_name(GWBUF* querybuf);
bool is_drop_table_query(GWBUF* querybuf);
bool skygw_is_real_query(GWBUF* querybuf);
char** skygw_get_table_names(GWBUF* querybuf, int* tblsize, bool fullnames);
char* skygw_get_canonical(GWBUF* querybuf);
bool parse_query(GWBUF* querybuf);
parsing_info_t* parsing_info_init(void (*donefun)(void *));
void parsing_info_done(void* ptr);
bool query_is_parsed(GWBUF* buf);
bool skygw_query_has_clause(GWBUF* buf);
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);
/** Free THD context and close MYSQL */
void parsing_info_done(void* ptr);
bool query_is_parsed(GWBUF* buf);
bool skygw_query_has_clause(GWBUF* buf);
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

View File

@ -210,7 +210,7 @@ static bool resolve_maxscale_conf_fname(
char* cnf_file_arg);
static char* check_dir_access(char* dirname, bool, bool);
static int set_user();
static int set_user(const char* user);
bool pid_file_exists();
void write_child_exit_code(int fd, int code);
/** SSL multi-threading functions and structures */
@ -968,7 +968,7 @@ static void usage(void)
" (default: /etc/)\n"
" -D, --datadir=PATH path to data directory, stored embedded mysql tables\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"
" -P, --piddir=PATH path to PID file directory\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;
}
static int set_user(char* user)
static int set_user(const char* user)
{
errno = 0;
struct passwd *pwname;

View File

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

View File

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

View File

@ -284,7 +284,7 @@ char task_name[BLRM_TASK_NAME_LEN+1] = "";
inst->m_errno = 0;
inst->m_errmsg = NULL;
inst->trx_safe = 1;
inst->trx_safe = 0;
inst->pending_transaction = 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
* are enough operative backends available and connected. Otherwise it fails,
* are enough operative backends available and connected. Otherwise it fails,
* and session is terminated.
*
* @param instance The router instance
@ -4662,7 +4662,7 @@ static void rwsplit_process_router_options(
* @param backend_dcb The backend DCB
* @param action The action: ERRACT_NEW_CONNECTION or ERRACT_REPLY_CLIENT
* @param succp Result of action: true iff router can continue
*
*
* 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.
*/
@ -4670,7 +4670,7 @@ static void handleError (
ROUTER* instance,
void* router_session,
GWBUF* errmsgbuf,
DCB* backend_dcb,
DCB* problem_dcb,
error_action_t action,
bool* succp)
{
@ -4678,10 +4678,10 @@ static void handleError (
ROUTER_INSTANCE* inst = (ROUTER_INSTANCE *)instance;
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 */
if (backend_dcb->dcb_errhandle_called)
if (problem_dcb->dcb_errhandle_called)
{
/** we optimistically assume that previous call succeed */
/*
@ -4693,24 +4693,28 @@ static void handleError (
}
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)
{
*succp = false;
}
}
else if (dcb_isclient(problem_dcb))
{
*succp = false;
}
else
{
CHK_SESSION(session);
CHK_CLIENT_RSES(rses);
switch (action) {
case ERRACT_NEW_CONNECTION:
{
SERVER* srv;
if (!rses_begin_locked_router_action(rses))
{
*succp = false;
@ -4718,14 +4722,14 @@ static void handleError (
}
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.
*/
if (rses->rses_master_ref->bref_dcb == backend_dcb &&
if (rses->rses_master_ref->bref_dcb == problem_dcb &&
!SERVER_IS_MASTER(srv))
{
backend_ref_t* bref;
bref = get_bref_from_dcb(rses, backend_dcb);
bref = get_bref_from_dcb(rses, problem_dcb);
if (bref != NULL)
{
CHK_BACKEND_REF(bref);
@ -4739,7 +4743,7 @@ static void handleError (
"corresponding backend ref.",
srv->name,
srv->port);
dcb_close(backend_dcb);
dcb_close(problem_dcb);
}
if (!srv->master_err_is_logged)
{
@ -4756,35 +4760,35 @@ static void handleError (
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.
*/
*succp = handle_error_new_connection(inst,
&rses,
backend_dcb,
*succp = handle_error_new_connection(inst,
&rses,
problem_dcb,
errmsgbuf);
}
/* Free the lock if rses still exists */
if (rses) rses_end_locked_router_action(rses);
break;
}
case ERRACT_REPLY_CLIENT:
{
handle_error_reply_client(session,
rses,
backend_dcb,
handle_error_reply_client(session,
rses,
problem_dcb,
errmsgbuf);
*succp = false; /*< no new backend servers were made available */
break;
break;
}
default:
default:
*succp = false;
break;
}
}
dcb_close(backend_dcb);
dcb_close(problem_dcb);
}
@ -4797,7 +4801,7 @@ static void handle_error_reply_client(
session_state_t sesstate;
DCB* client_dcb;
backend_ref_t* bref;
spinlock_acquire(&ses->ses_lock);
sesstate = ses->state;
client_dcb = ses->client;
@ -4812,7 +4816,7 @@ static void handle_error_reply_client(
bref_clear_state(bref, BREF_IN_USE);
bref_set_state(bref, BREF_CLOSED);
}
if (sesstate == SESSION_STATE_ROUTER_READY)
{
CHK_DCB(client_dcb);

View File

@ -4001,7 +4001,7 @@ return_succp:
/**
* 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.
*
* @param instance The router instance
@ -4010,7 +4010,7 @@ return_succp:
* @param backend_dcb The backend DCB
* @param action The action: ERRACT_NEW_CONNECTION or ERRACT_REPLY_CLIENT
* @param succp Result of action: true iff router can continue
*
*
* 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.
*/
@ -4018,7 +4018,7 @@ static void handleError (
ROUTER* instance,
void* router_session,
GWBUF* errmsgbuf,
DCB* backend_dcb,
DCB* problem_dcb,
error_action_t action,
bool* succp)
{
@ -4026,10 +4026,10 @@ static void handleError (
ROUTER_INSTANCE* inst = (ROUTER_INSTANCE *)instance;
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 */
if (backend_dcb->dcb_errhandle_called)
if (problem_dcb->dcb_errhandle_called)
{
/** we optimistically assume that previous call succeed */
*succp = true;
@ -4037,19 +4037,23 @@ static void handleError (
}
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)
{
*succp = false;
}
else if (dcb_isclient(problem_dcb))
{
*succp = false;
}
else
{
CHK_SESSION(session);
CHK_CLIENT_RSES(rses);
switch (action) {
case ERRACT_NEW_CONNECTION:
{
@ -4059,33 +4063,33 @@ static void handleError (
break;
}
/**
* This is called in hope of getting replacement for
* This is called in hope of getting replacement for
* failed slave(s).
*/
*succp = handle_error_new_connection(inst,
rses,
backend_dcb,
*succp = handle_error_new_connection(inst,
rses,
problem_dcb,
errmsgbuf);
rses_end_locked_router_action(rses);
break;
}
case ERRACT_REPLY_CLIENT:
{
handle_error_reply_client(session,
rses,
backend_dcb,
handle_error_reply_client(session,
rses,
problem_dcb,
errmsgbuf);
*succp = false; /*< no new backend servers were made available */
break;
break;
}
default:
*succp = false;
break;
}
}
dcb_close(backend_dcb);
dcb_close(problem_dcb);
}