Simplify the command factory

Since more than an year it not possible to create commands in the heap
but they are allocated on the stack and directly run. In this regard, it
doesn't make sense to have all the vararg stuff. Commands made sense
to be created and pushed onto a stack then a general executor will
run thru the stack and execute/handle the commands.
This commit is contained in:
Andrey Hristov 2019-01-07 18:45:33 +02:00
parent ba5cb2eb32
commit 8975e4dcd7
11 changed files with 214 additions and 850 deletions

View file

@ -196,7 +196,7 @@ mysqlnd_switch_to_ssl_if_needed(MYSQLND_CONN_DATA * const conn,
{
const size_t client_capabilities = mysql_flags;
ret = conn->run_command(COM_ENABLE_SSL, conn, client_capabilities, server_capabilities, charset_no);
ret = conn->command->enable_ssl(conn, client_capabilities, server_capabilities, charset_no);
}
DBG_RETURN(ret);
}

File diff suppressed because it is too large Load diff

View file

@ -20,7 +20,7 @@
#ifndef MYSQLND_COMMANDS_H
#define MYSQLND_COMMANDS_H
extern func_mysqlnd__run_command mysqlnd_run_command;
//extern func_mysqlnd__run_command mysqlnd_run_command;
#endif /* MYSQLND_COMMANDS_H */

View file

@ -379,7 +379,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_server_option)(MYSQLND_CONN_DATA * const c
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::set_server_option");
if (PASS == conn->m->local_tx_start(conn, this_func)) {
ret = conn->run_command(COM_SET_OPTION, conn, option);
ret = conn->command->set_option(conn, option);
conn->m->local_tx_end(conn, this_func, ret);
}
DBG_RETURN(ret);
@ -531,7 +531,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn,
{
size_t client_flags = mysql_flags;
ret = conn->run_command(COM_HANDSHAKE, conn, username, password, database, client_flags);
ret = conn->command->handshake(conn, *username, *password, *database, client_flags);
}
DBG_RETURN(ret);
}
@ -877,7 +877,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_query)(MYSQLND_CONN_DATA * conn, const ch
{
const MYSQLND_CSTRING query_string = {query, query_len};
ret = conn->run_command(COM_QUERY, conn, query_string);
ret = conn->command->query(conn, query_string);
if (type == MYSQLND_SEND_QUERY_EXPLICIT) {
conn->m->local_tx_end(conn, this_func, ret);
@ -901,7 +901,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, reap_query)(MYSQLND_CONN_DATA * conn, enum_mys
DBG_INF_FMT("conn->server_status=%u", UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status));
if (type == MYSQLND_REAP_RESULT_IMPLICIT || PASS == conn->m->local_tx_start(conn, this_func))
{
ret = conn->run_command(COM_REAP_RESULT, conn);
ret = conn->command->reap_result(conn);
if (type == MYSQLND_REAP_RESULT_EXPLICIT) {
conn->m->local_tx_end(conn, this_func, ret);
@ -1046,7 +1046,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, dump_debug_info)(MYSQLND_CONN_DATA * const con
DBG_ENTER("mysqlnd_conn_data::dump_debug_info");
DBG_INF_FMT("conn=%llu", conn->thread_id);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
ret = conn->run_command(COM_DEBUG, conn);
ret = conn->command->debug(conn);
conn->m->local_tx_end(conn, this_func, ret);
}
@ -1068,7 +1068,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, select_db)(MYSQLND_CONN_DATA * const conn, con
if (PASS == conn->m->local_tx_start(conn, this_func)) {
const MYSQLND_CSTRING database = {db, db_len};
ret = conn->run_command(COM_INIT_DB, conn, database);
ret = conn->command->init_db(conn, database);
conn->m->local_tx_end(conn, this_func, ret);
}
DBG_RETURN(ret);
@ -1087,7 +1087,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, ping)(MYSQLND_CONN_DATA * const conn)
DBG_INF_FMT("conn=%llu", conn->thread_id);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
ret = conn->run_command(COM_PING, conn);
ret = conn->command->ping(conn);
conn->m->local_tx_end(conn, this_func, ret);
}
DBG_INF_FMT("ret=%u", ret);
@ -1107,7 +1107,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, statistic)(MYSQLND_CONN_DATA * conn, zend_stri
DBG_INF_FMT("conn=%llu", conn->thread_id);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
ret = conn->run_command(COM_STATISTICS, conn, message);
ret = conn->command->statistics(conn, message);
conn->m->local_tx_end(conn, this_func, ret);
}
DBG_RETURN(ret);
@ -1126,11 +1126,11 @@ MYSQLND_METHOD(mysqlnd_conn_data, kill)(MYSQLND_CONN_DATA * conn, unsigned int p
DBG_INF_FMT("conn=%llu pid=%u", conn->thread_id, pid);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
unsigned int process_id = pid;
const unsigned int process_id = pid;
/* 'unsigned char' is promoted to 'int' when passed through '...' */
unsigned int read_response = (pid != conn->thread_id);
const unsigned int read_response = (pid != conn->thread_id);
ret = conn->run_command(COM_PROCESS_KILL, conn, process_id, read_response);
ret = conn->command->process_kill(conn, process_id, read_response);
conn->m->local_tx_end(conn, this_func, ret);
}
DBG_RETURN(ret);
@ -1187,9 +1187,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, refresh)(MYSQLND_CONN_DATA * const conn, uint8
DBG_INF_FMT("conn=%llu options=%lu", conn->thread_id, options);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
unsigned int options_param = (unsigned int) options;
ret = conn->run_command(COM_REFRESH, conn, options_param);
ret = conn->command->refresh(conn, options);
conn->m->local_tx_end(conn, this_func, ret);
}
DBG_RETURN(ret);
@ -1207,9 +1205,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, shutdown)(MYSQLND_CONN_DATA * const conn, uint
DBG_INF_FMT("conn=%llu level=%lu", conn->thread_id, level);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
unsigned int level_param = (unsigned int) level;
ret = conn->run_command(COM_SHUTDOWN, conn, level_param);
ret = conn->command->shutdown(conn, level);
conn->m->local_tx_end(conn, this_func, ret);
}
DBG_RETURN(ret);
@ -1240,7 +1236,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_close)(MYSQLND_CONN_DATA * const conn)
case CONN_READY:
DBG_INF("Connection clean, sending COM_QUIT");
if (net_stream) {
ret = conn->run_command(COM_QUIT, conn);
ret = conn->command->quit(conn);
vio->data->m.close_stream(vio, conn->stats, conn->error_info);
}
SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);

View file

@ -143,9 +143,9 @@ MYSQLND_METHOD(mysqlnd_object_factory, get_connection)(MYSQLND_CLASS_METHODS_TYP
data->protocol_frame_codec = mysqlnd_pfc_init(persistent, factory, data->stats, data->error_info);
data->vio = mysqlnd_vio_init(persistent, factory, data->stats, data->error_info);
data->payload_decoder_factory = mysqlnd_protocol_payload_decoder_factory_init(data, persistent);
data->run_command = mysqlnd_command_factory_get();
data->command = mysqlnd_command_get_methods();
if (!data->protocol_frame_codec || !data->vio || !data->payload_decoder_factory || !data->run_command) {
if (!data->protocol_frame_codec || !data->vio || !data->payload_decoder_factory || !data->command) {
new_object->m->dtor(new_object);
DBG_RETURN(NULL);
}

View file

@ -362,19 +362,19 @@ _mysqlnd_vio_set_methods(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_vio) * methods)
/* {{{ mysqlnd_command_factory_get */
static func_mysqlnd__run_command
static MYSQLND_CLASS_METHODS_TYPE(mysqlnd_command) *
_mysqlnd_command_factory_get()
{
return mysqlnd_run_command;
return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_command);
}
/* }}} */
/* {{{ mysqlnd_command_factory_set */
static void
_mysqlnd_command_factory_set(func_mysqlnd__run_command run_command)
_mysqlnd_command_factory_set(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_command) * methods)
{
mysqlnd_run_command = run_command;
MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_command) = *methods;
}
/* }}} */

View file

@ -117,11 +117,11 @@ struct st_mysqlnd_plugin_methods_xetters
void (*set)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_error_info) * methods);
} error_info;
struct st_mnd_command_factory_xetters
struct st_mnd_command_xetters
{
func_mysqlnd__run_command (*get)();
void (*set)(func_mysqlnd__run_command factory);
} command_factory;
MYSQLND_CLASS_METHODS_TYPE(mysqlnd_command) * (*get)();
void (*set)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_command) * methods);
} command;
};
PHPAPI extern struct st_mysqlnd_plugin_methods_xetters mysqlnd_plugin_methods_xetters;
@ -157,8 +157,8 @@ PHPAPI extern struct st_mysqlnd_plugin_methods_xetters mysqlnd_plugin_methods_xe
#define mysqlnd_vio_get_methods() mysqlnd_plugin_methods_xetters.vio.get()
#define mysqlnd_vio_set_methods(m) mysqlnd_plugin_methods_xetters.vio.set((m))
#define mysqlnd_command_factory_get() mysqlnd_plugin_methods_xetters.command_factory.get()
#define mysqlnd_command_factory_set(m) mysqlnd_plugin_methods_xetters.command_factory.set((m))
#define mysqlnd_command_get_methods() mysqlnd_plugin_methods_xetters.command.get()
#define mysqlnd_command_set_methods(m) mysqlnd_plugin_methods_xetters.command.set((m))
#define mysqlnd_error_info_get_methods() mysqlnd_plugin_methods_xetters.error_info.get()
#define mysqlnd_error_info_set_methods(m) mysqlnd_plugin_methods_xetters.error_info.set((m))

View file

@ -30,6 +30,7 @@ PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_protocol_packet_fr
PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_vio);
PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_upsert_status);
PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_error_info);
PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_command);
enum_func_status mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * const filename, zend_bool * is_warning);
#endif /* MYSQLND_PRIV_H */

View file

@ -409,7 +409,7 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
enum_func_status ret = FAIL;
const MYSQLND_CSTRING query_string = {query, query_len};
ret = conn->run_command(COM_STMT_PREPARE, conn, query_string);
ret = conn->command->stmt_prepare(conn, query_string);
if (FAIL == ret) {
goto fail;
}
@ -686,7 +686,7 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, const enum_my
if (ret == PASS) {
const MYSQLND_CSTRING payload = {(const char*) request, request_len};
ret = conn->run_command(COM_STMT_EXECUTE, conn, payload);
ret = conn->command->stmt_execute(conn, payload);
} else {
SET_CLIENT_ERROR(stmt->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Couldn't generate the request. Possibly OOM.");
}
@ -990,7 +990,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, const unsigned
{
const MYSQLND_CSTRING payload = {(const char*) buf, sizeof(buf)};
ret = conn->run_command(COM_STMT_FETCH, conn, payload);
ret = conn->command->stmt_fetch(conn, payload);
if (ret == FAIL) {
COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
DBG_RETURN(FAIL);
@ -1189,7 +1189,7 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s)
if (GET_CONNECTION_STATE(&conn->state) == CONN_READY) {
size_t stmt_id = stmt->stmt_id;
ret = stmt->conn->run_command(COM_STMT_RESET, stmt->conn, stmt_id);
ret = stmt->conn->command->stmt_reset(stmt->conn, stmt_id);
if (ret == FAIL) {
COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
}
@ -1295,7 +1295,7 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in
{
const MYSQLND_CSTRING payload = {(const char *) cmd_buf, packet_len};
ret = conn->run_command(COM_STMT_SEND_LONG_DATA, conn, payload);
ret = conn->command->stmt_send_long_data(conn, payload);
if (ret == FAIL) {
COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
}
@ -2120,9 +2120,9 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, close_on_server)(MYSQLND_STMT * const s, ze
if (GET_CONNECTION_STATE(&conn->state) == CONN_READY) {
enum_func_status ret = FAIL;
size_t stmt_id = stmt->stmt_id;
const size_t stmt_id = stmt->stmt_id;
ret = conn->run_command(COM_STMT_CLOSE, conn, stmt_id);
ret = conn->command->stmt_close(conn, stmt_id);
if (ret == FAIL) {
COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
DBG_RETURN(FAIL);

View file

@ -316,6 +316,54 @@ struct st_mysqlnd_stats
};
typedef enum_func_status (*func_mysqlnd_execute_com_set_option)(MYSQLND_CONN_DATA * const conn, const enum_mysqlnd_server_option option);
typedef enum_func_status (*func_mysqlnd_execute_com_debug)(MYSQLND_CONN_DATA * const conn);
typedef enum_func_status (*func_mysqlnd_execute_com_init_db)(MYSQLND_CONN_DATA * const conn, const MYSQLND_CSTRING db);
typedef enum_func_status (*func_mysqlnd_execute_com_ping)(MYSQLND_CONN_DATA * const conn);
typedef enum_func_status (*func_mysqlnd_execute_com_statistics)(MYSQLND_CONN_DATA * const conn, zend_string ** message);
typedef enum_func_status (*func_mysqlnd_execute_com_process_kill)(MYSQLND_CONN_DATA * const conn, const unsigned int process_id, const zend_bool read_response);
typedef enum_func_status (*func_mysqlnd_execute_com_refresh)(MYSQLND_CONN_DATA * const conn, const uint8_t options);
typedef enum_func_status (*func_mysqlnd_execute_com_shutdown)(MYSQLND_CONN_DATA * const conn, const uint8_t level);
typedef enum_func_status (*func_mysqlnd_execute_com_quit)(MYSQLND_CONN_DATA * const conn);
typedef enum_func_status (*func_mysqlnd_execute_com_query)(MYSQLND_CONN_DATA * const conn, MYSQLND_CSTRING query);
typedef enum_func_status (*func_mysqlnd_execute_com_change_user)(MYSQLND_CONN_DATA * const conn, const MYSQLND_CSTRING payload, const zend_bool silent);
typedef enum_func_status (*func_mysqlnd_execute_com_reap_result)(MYSQLND_CONN_DATA * const conn);
typedef enum_func_status (*func_mysqlnd_execute_com_stmt_prepare)(MYSQLND_CONN_DATA * const conn, const MYSQLND_CSTRING query);
typedef enum_func_status (*func_mysqlnd_execute_com_stmt_execute)(MYSQLND_CONN_DATA * conn, const MYSQLND_CSTRING payload);
typedef enum_func_status (*func_mysqlnd_execute_com_stmt_fetch)(MYSQLND_CONN_DATA * const conn, const MYSQLND_CSTRING payload);
typedef enum_func_status (*func_mysqlnd_execute_com_stmt_reset)(MYSQLND_CONN_DATA * const conn, const zend_ulong stmt_id);
typedef enum_func_status (*func_mysqlnd_execute_com_stmt_send_long_data)(MYSQLND_CONN_DATA * const conn, const MYSQLND_CSTRING payload);
typedef enum_func_status (*func_mysqlnd_execute_com_stmt_close)(MYSQLND_CONN_DATA * const conn, const zend_ulong stmt_id);
typedef enum_func_status (*func_mysqlnd_execute_com_enable_ssl)(MYSQLND_CONN_DATA * const conn, const size_t client_capabilities, const size_t server_capabilities, const unsigned int charset_no);
typedef enum_func_status (*func_mysqlnd_execute_com_handshake)(MYSQLND_CONN_DATA * const conn, const MYSQLND_CSTRING username, const MYSQLND_CSTRING password, const MYSQLND_CSTRING database, const size_t client_flags);
MYSQLND_CLASS_METHODS_TYPE(mysqlnd_command)
{
func_mysqlnd_execute_com_set_option set_option;
func_mysqlnd_execute_com_debug debug;
func_mysqlnd_execute_com_init_db init_db;
func_mysqlnd_execute_com_ping ping;
func_mysqlnd_execute_com_statistics statistics;
func_mysqlnd_execute_com_process_kill process_kill;
func_mysqlnd_execute_com_refresh refresh;
func_mysqlnd_execute_com_shutdown shutdown;
func_mysqlnd_execute_com_quit quit;
func_mysqlnd_execute_com_query query;
func_mysqlnd_execute_com_change_user change_user;
func_mysqlnd_execute_com_reap_result reap_result;
func_mysqlnd_execute_com_stmt_prepare stmt_prepare;
func_mysqlnd_execute_com_stmt_execute stmt_execute;
func_mysqlnd_execute_com_stmt_fetch stmt_fetch;
func_mysqlnd_execute_com_stmt_reset stmt_reset;
func_mysqlnd_execute_com_stmt_send_long_data stmt_send_long_data;
func_mysqlnd_execute_com_stmt_close stmt_close;
func_mysqlnd_execute_com_enable_ssl enable_ssl;
func_mysqlnd_execute_com_handshake handshake;
};
typedef enum_func_status (*func_mysqlnd_vio__init)(MYSQLND_VIO * const vio, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info);
typedef void (*func_mysqlnd_vio__dtor)(MYSQLND_VIO * const vio, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
@ -848,10 +896,6 @@ struct st_mysqlnd_vio
typedef enum_func_status (*func_mysqlnd__run_command)(enum php_mysqlnd_server_command command, ...);
typedef struct st_mysqlnd_connection_state MYSQLND_CONNECTION_STATE;
typedef enum mysqlnd_connection_state (*func_mysqlnd_connection_state__get)(const MYSQLND_CONNECTION_STATE * const state_struct);
typedef void (*func_mysqlnd_connection_state__set)(MYSQLND_CONNECTION_STATE * const state_struct, const enum mysqlnd_connection_state state);
@ -936,8 +980,7 @@ struct st_mysqlnd_connection_data
zend_bool in_async_err_cb;
MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory) object_factory;
func_mysqlnd__run_command run_command;
MYSQLND_CLASS_METHODS_TYPE(mysqlnd_command) * command;
MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data) * m;
/* persistent connection */

View file

@ -618,7 +618,7 @@ size_t php_mysqlnd_auth_write(MYSQLND_CONN_DATA * conn, void * _packet)
const MYSQLND_CSTRING payload = {(char*) buffer + MYSQLND_HEADER_SIZE, p - (buffer + MYSQLND_HEADER_SIZE)};
const unsigned int silent = packet->silent;
ret = conn->run_command(COM_CHANGE_USER, conn, payload, silent);
ret = conn->command->change_user(conn, payload, silent);
DBG_RETURN(ret == PASS? (p - buffer - MYSQLND_HEADER_SIZE) : 0);
} else {
size_t sent = pfc->data->m.send(pfc, vio, buffer, p - buffer - MYSQLND_HEADER_SIZE, stats, error_info);