From: Timm Friebe Date: Sun, 25 Jan 2004 20:03:10 +0000 (+0000) Subject: @- Added ability to define a message handler not only globally, but also X-Git-Tag: RELEASE_1_3b6~16 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=35409efd9a83dbeb52df69f91b7297ebd8d9ea3f;p=php @- Added ability to define a message handler not only globally, but also @ per connection (Timm) @- Made sybct.login_timeout changeable at runtime (Timm) @- Added ini option sybct.packet_size which lets you control the packet @ size (Timm) --- diff --git a/ext/sybase_ct/php_sybase_ct.c b/ext/sybase_ct/php_sybase_ct.c index 70cf3f4189..75e5a56bc0 100644 --- a/ext/sybase_ct/php_sybase_ct.c +++ b/ext/sybase_ct/php_sybase_ct.c @@ -38,53 +38,54 @@ static int le_link, le_plink, le_result; #if HAVE_SYBASE_CT function_entry sybase_functions[] = { - PHP_FE(sybase_connect, NULL) - PHP_FE(sybase_pconnect, NULL) - PHP_FE(sybase_close, NULL) - PHP_FE(sybase_select_db, NULL) - PHP_FE(sybase_query, NULL) - PHP_FE(sybase_unbuffered_query, NULL) - PHP_FE(sybase_free_result, NULL) - PHP_FE(sybase_get_last_message, NULL) - PHP_FE(sybase_num_rows, NULL) - PHP_FE(sybase_num_fields, NULL) - PHP_FE(sybase_fetch_row, NULL) - PHP_FE(sybase_fetch_array, NULL) - PHP_FE(sybase_fetch_assoc, NULL) - PHP_FE(sybase_fetch_object, NULL) - PHP_FE(sybase_data_seek, NULL) - PHP_FE(sybase_fetch_field, NULL) - PHP_FE(sybase_field_seek, NULL) - PHP_FE(sybase_result, NULL) - PHP_FE(sybase_affected_rows, NULL) - PHP_FE(sybase_min_client_severity, NULL) - PHP_FE(sybase_min_server_severity, NULL) - PHP_FE(sybase_set_message_handler, NULL) - PHP_FE(sybase_deadlock_retry_count, NULL) - - PHP_FALIAS(mssql_connect, sybase_connect, NULL) - PHP_FALIAS(mssql_pconnect, sybase_pconnect, NULL) - PHP_FALIAS(mssql_close, sybase_close, NULL) - PHP_FALIAS(mssql_select_db, sybase_select_db, NULL) - PHP_FALIAS(mssql_query, sybase_query, NULL) - PHP_FALIAS(mssql_unbuffered_query, sybase_unbuffered_query, NULL) - PHP_FALIAS(mssql_free_result, sybase_free_result, NULL) - PHP_FALIAS(mssql_get_last_message, sybase_get_last_message, NULL) - PHP_FALIAS(mssql_num_rows, sybase_num_rows, NULL) - PHP_FALIAS(mssql_num_fields, sybase_num_fields, NULL) - PHP_FALIAS(mssql_fetch_row, sybase_fetch_row, NULL) - PHP_FALIAS(mssql_fetch_array, sybase_fetch_array, NULL) - PHP_FALIAS(mssql_fetch_assoc, sybase_fetch_assoc, NULL) - PHP_FALIAS(mssql_fetch_object, sybase_fetch_object, NULL) - PHP_FALIAS(mssql_data_seek, sybase_data_seek, NULL) - PHP_FALIAS(mssql_fetch_field, sybase_fetch_field, NULL) - PHP_FALIAS(mssql_field_seek, sybase_field_seek, NULL) - PHP_FALIAS(mssql_result, sybase_result, NULL) - PHP_FALIAS(mssql_affected_rows, sybase_affected_rows, NULL) - PHP_FALIAS(mssql_min_client_severity, sybase_min_client_severity, NULL) - PHP_FALIAS(mssql_min_server_severity, sybase_min_server_severity, NULL) - PHP_FALIAS(mssql_set_message_handler, sybase_set_message_handler, NULL) - PHP_FALIAS(mssql_deadlock_retry_count, sybase_deadlock_retry_count, NULL) + PHP_FE(sybase_connect, NULL) + PHP_FE(sybase_pconnect, NULL) + PHP_FE(sybase_close, NULL) + PHP_FE(sybase_select_db, NULL) + PHP_FE(sybase_query, NULL) + PHP_FE(sybase_unbuffered_query, NULL) + PHP_FE(sybase_free_result, NULL) + PHP_FE(sybase_get_last_message, NULL) + PHP_FE(sybase_num_rows, NULL) + PHP_FE(sybase_num_fields, NULL) + PHP_FE(sybase_fetch_row, NULL) + PHP_FE(sybase_fetch_array, NULL) + PHP_FE(sybase_fetch_assoc, NULL) + PHP_FE(sybase_fetch_object, NULL) + PHP_FE(sybase_data_seek, NULL) + PHP_FE(sybase_fetch_field, NULL) + PHP_FE(sybase_field_seek, NULL) + PHP_FE(sybase_result, NULL) + PHP_FE(sybase_affected_rows, NULL) + PHP_FE(sybase_min_client_severity, NULL) + PHP_FE(sybase_min_server_severity, NULL) + PHP_FE(sybase_set_message_handler, NULL) + PHP_FE(sybase_deadlock_retry_count, NULL) + + PHP_FALIAS(mssql_connect, sybase_connect, NULL) + PHP_FALIAS(mssql_pconnect, sybase_pconnect, NULL) + PHP_FALIAS(mssql_close, sybase_close, NULL) + PHP_FALIAS(mssql_select_db, sybase_select_db, NULL) + PHP_FALIAS(mssql_query, sybase_query, NULL) + PHP_FALIAS(mssql_unbuffered_query, sybase_unbuffered_query, NULL) + PHP_FALIAS(mssql_free_result, sybase_free_result, NULL) + PHP_FALIAS(mssql_get_last_message, sybase_get_last_message, NULL) + PHP_FALIAS(mssql_num_rows, sybase_num_rows, NULL) + PHP_FALIAS(mssql_num_fields, sybase_num_fields, NULL) + PHP_FALIAS(mssql_fetch_row, sybase_fetch_row, NULL) + PHP_FALIAS(mssql_fetch_array, sybase_fetch_array, NULL) + PHP_FALIAS(mssql_fetch_assoc, sybase_fetch_assoc, NULL) + PHP_FALIAS(mssql_fetch_object, sybase_fetch_object, NULL) + PHP_FALIAS(mssql_data_seek, sybase_data_seek, NULL) + PHP_FALIAS(mssql_fetch_field, sybase_fetch_field, NULL) + PHP_FALIAS(mssql_field_seek, sybase_field_seek, NULL) + PHP_FALIAS(mssql_result, sybase_result, NULL) + PHP_FALIAS(mssql_affected_rows, sybase_affected_rows, NULL) + PHP_FALIAS(mssql_min_client_severity, sybase_min_client_severity, NULL) + PHP_FALIAS(mssql_min_server_severity, sybase_min_server_severity, NULL) + PHP_FALIAS(mssql_set_message_handler, sybase_set_message_handler, NULL) + PHP_FALIAS(mssql_deadlock_retry_count, sybase_deadlock_retry_count, NULL) + {NULL, NULL, NULL} }; @@ -156,6 +157,10 @@ static void _close_sybase_link(zend_rsrc_list_entry *rsrc TSRMLS_DC) CS_INT con_status; sybase_ptr->valid = 0; + if (sybase_ptr->callback_name != NULL) { + zval_ptr_dtor(&sybase_ptr->callback_name); + sybase_ptr->callback_name= NULL; + } zend_hash_apply(&EG(regular_list), (apply_func_t) _clean_invalid_results TSRMLS_CC); @@ -233,60 +238,80 @@ static CS_RETCODE CS_PUBLIC _client_message_handler(CS_CONTEXT *context, CS_CONN return CS_SUCCEED; } - -static CS_RETCODE CS_PUBLIC _server_message_handler(CS_CONTEXT *context, CS_CONNECTION *connection, CS_SERVERMSG *srvmsg) +static int _call_message_handler(zval *callback_name, CS_SERVERMSG *srvmsg TSRMLS_DC) { - zval *retval = NULL; - zval severity, msgnumber, state, line, text; - zval *ptrs[5]= {&msgnumber, &severity, &state, &line, &text}; - zval **args[5]= {&ptrs[0], &ptrs[1], &ptrs[2], &ptrs[3], &ptrs[4]}; - int handled= 0; - - TSRMLS_FETCH(); - - if (srvmsg->severity >= SybCtG(min_server_severity)) { - if (SybCtG(callback_name) != NULL) { - INIT_ZVAL(msgnumber); - INIT_ZVAL(severity); - INIT_ZVAL(state); - INIT_ZVAL(line); - INIT_ZVAL(text); + int handled = 0; + + if (callback_name) { + zval *retval = NULL; + zval severity, msgnumber, state, line, text; + zval *ptrs[5]= {&msgnumber, &severity, &state, &line, &text}; + zval **args[5]= {&ptrs[0], &ptrs[1], &ptrs[2], &ptrs[3], &ptrs[4]}; + + INIT_ZVAL(msgnumber); + INIT_ZVAL(severity); + INIT_ZVAL(state); + INIT_ZVAL(line); + INIT_ZVAL(text); - ZVAL_LONG(&msgnumber, srvmsg->msgnumber); - ZVAL_LONG(&severity, srvmsg->severity); - ZVAL_LONG(&state, srvmsg->state); - ZVAL_LONG(&line, srvmsg->line); - ZVAL_STRING(&text, srvmsg->text, 0); + ZVAL_LONG(&msgnumber, srvmsg->msgnumber); + ZVAL_LONG(&severity, srvmsg->severity); + ZVAL_LONG(&state, srvmsg->state); + ZVAL_LONG(&line, srvmsg->line); + ZVAL_STRING(&text, srvmsg->text, 0); - if (call_user_function_ex(EG(function_table), NULL, SybCtG(callback_name), &retval, 5, args, 0, NULL TSRMLS_CC)== FAILURE) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Cannot call the messagehandler %s", Z_STRVAL_P(SybCtG(callback_name))); - } - if (retval) { - handled= ((Z_TYPE_P(retval) != IS_BOOL) || (Z_BVAL_P(retval) != 0)); - zval_ptr_dtor(&retval); - } + if (call_user_function_ex(EG(function_table), NULL, callback_name, &retval, 5, args, 0, NULL TSRMLS_CC) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Cannot call the messagehandler %s", Z_STRVAL_P(callback_name)); } - - if (!handled) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Server message: %s (severity %d, procedure %s)", - srvmsg->text, srvmsg->severity, ((srvmsg->proclen>0) ? srvmsg->proc : "N/A")); + if (retval) { + handled= ((Z_TYPE_P(retval) != IS_BOOL) || (Z_BVAL_P(retval) != 0)); + zval_ptr_dtor(&retval); } } + + return handled; +} + +static CS_RETCODE CS_PUBLIC _server_message_handler(CS_CONTEXT *context, CS_CONNECTION *connection, CS_SERVERMSG *srvmsg) +{ + sybase_link *sybase; + int handled = 0; + TSRMLS_FETCH(); + + /* Remember the last server message in any case */ STR_FREE(SybCtG(server_message)); SybCtG(server_message) = estrdup(srvmsg->text); + /* Retrieve sybase link */ + if (ct_con_props(connection, CS_GET, CS_USERDATA, &sybase, CS_SIZEOF(sybase), NULL) != CS_SUCCEED) { + sybase = NULL; + } + /* If this is a deadlock message, set the connection's deadlock flag * so we will retry the request. Sorry about the bare constant here, * but it's not defined anywhere and it's a "well-known" number. */ - if (srvmsg->msgnumber == 1205) { - sybase_link *sybase; + if (sybase && (srvmsg->msgnumber == 1205)) { + sybase->deadlock = 1; + } - if (ct_con_props(connection, CS_GET, CS_USERDATA, &sybase, CS_SIZEOF(sybase), NULL)==CS_SUCCEED) { - sybase->deadlock = 1; - } else { - /* oh well */ - } + /* Check mininum server severity level */ + if (srvmsg->severity < SybCtG(min_server_severity)) { + return CS_SUCCEED; + } + + /* Call global message handler */ + handled = handled | _call_message_handler(SybCtG(callback_name), srvmsg TSRMLS_CC); + + /* Call link specific message handler */ + if (sybase) { + handled = handled | _call_message_handler(sybase->callback_name, srvmsg TSRMLS_CC); + } + + /* Spit out a warning if neither of them has handled this message */ + if (!handled) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Server message: %s (severity %d, procedure %s)", + srvmsg->text, srvmsg->severity, ((srvmsg->proclen>0) ? srvmsg->proc : "N/A")); } return CS_SUCCEED; @@ -294,19 +319,20 @@ static CS_RETCODE CS_PUBLIC _server_message_handler(CS_CONTEXT *context, CS_CONN PHP_INI_BEGIN() - STD_PHP_INI_BOOLEAN("sybct.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong, allow_persistent, zend_sybase_globals, sybase_globals) - STD_PHP_INI_ENTRY_EX("sybct.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_sybase_globals, sybase_globals, display_link_numbers) - STD_PHP_INI_ENTRY_EX("sybct.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_sybase_globals, sybase_globals, display_link_numbers) - STD_PHP_INI_ENTRY("sybct.min_server_severity", "10", PHP_INI_ALL, OnUpdateLong, min_server_severity, zend_sybase_globals, sybase_globals) - STD_PHP_INI_ENTRY("sybct.min_client_severity", "10", PHP_INI_ALL, OnUpdateLong, min_client_severity, zend_sybase_globals, sybase_globals) - STD_PHP_INI_ENTRY("sybct.hostname", NULL, PHP_INI_ALL, OnUpdateString, hostname, zend_sybase_globals, sybase_globals) - STD_PHP_INI_ENTRY_EX("sybct.deadlock_retry_count", "-1", PHP_INI_ALL, OnUpdateLong, deadlock_retry_count, zend_sybase_globals, sybase_globals, display_link_numbers) + STD_PHP_INI_BOOLEAN("sybct.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong, allow_persistent, zend_sybase_globals, sybase_globals) + STD_PHP_INI_ENTRY_EX("sybct.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_sybase_globals, sybase_globals, display_link_numbers) + STD_PHP_INI_ENTRY_EX("sybct.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_sybase_globals, sybase_globals, display_link_numbers) + STD_PHP_INI_ENTRY("sybct.min_server_severity", "10", PHP_INI_ALL, OnUpdateLong, min_server_severity, zend_sybase_globals, sybase_globals) + STD_PHP_INI_ENTRY("sybct.min_client_severity", "10", PHP_INI_ALL, OnUpdateLong, min_client_severity, zend_sybase_globals, sybase_globals) + STD_PHP_INI_ENTRY("sybct.login_timeout", "-1", PHP_INI_ALL, OnUpdateLong, login_timeout, zend_sybase_globals, sybase_globals) + STD_PHP_INI_ENTRY("sybct.hostname", NULL, PHP_INI_ALL, OnUpdateString, hostname, zend_sybase_globals, sybase_globals) + STD_PHP_INI_ENTRY_EX("sybct.deadlock_retry_count", "-1", PHP_INI_ALL, OnUpdateLong, deadlock_retry_count, zend_sybase_globals, sybase_globals, display_link_numbers) PHP_INI_END() static void php_sybase_init_globals(zend_sybase_globals *sybase_globals) { - long timeout; + long opt; TSRMLS_FETCH(); if (cs_ctx_alloc(CTLIB_VERSION, &sybase_globals->context)!=CS_SUCCEED || ct_init(sybase_globals->context, CTLIB_VERSION)!=CS_SUCCEED) { @@ -335,27 +361,29 @@ static void php_sybase_init_globals(zend_sybase_globals *sybase_globals) } } - /* Set the login and command timeouts. These are per-context and - * can't be set with ct_con_props(), so set them globally from - * their config values if requested. The defaults are 1 minute - * for CS_LOGIN_TIMEOUT and CS_NO_LIMIT for CS_TIMEOUT. The latter - * especially is fairly useless for web applications. - * Note that depite some noise in the documentation about using + /* Set the timeout, which is per context and can't be set with + * ct_con_props(), so set it globally from the config value if + * requested. The default is CS_NO_LIMIT. + * + * Note that despite some noise in the documentation about using * signals to implement timeouts, they are actually implemented * by using poll() or select() on Solaris and Linux. */ - if (cfg_get_long("sybct.login_timeout", &timeout)==SUCCESS) { - CS_INT cs_login_timeout = timeout; - if (ct_config(sybase_globals->context, CS_SET, CS_LOGIN_TIMEOUT, &cs_login_timeout, CS_UNUSED, NULL)!=CS_SUCCEED) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Unable to set login timeout"); + if (cfg_get_long("sybct.timeout", &opt)==SUCCESS) { + CS_INT cs_timeout = opt; + if (ct_config(sybase_globals->context, CS_SET, CS_TIMEOUT, &cs_timeout, CS_UNUSED, NULL)!=CS_SUCCEED) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Unable to update the timeout"); } } - if (cfg_get_long("sybct.timeout", &timeout)==SUCCESS) { - CS_INT cs_timeout = timeout; - if (ct_config(sybase_globals->context, CS_SET, CS_TIMEOUT, &cs_timeout, CS_UNUSED, NULL)!=CS_SUCCEED) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Unable to set timeout"); + + /* Set the packet size, which is also per context */ + if (cfg_get_long("sybct.packet_size", &opt)==SUCCESS) { + CS_INT cs_packet_size = opt; + if (ct_config(sybase_globals->context, CS_SET, CS_PACKETSIZE, &cs_packet_size, CS_UNUSED, NULL)!=CS_SUCCEED) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Unable to update the packet size"); } } + sybase_globals->num_persistent=0; sybase_globals->callback_name = NULL; } @@ -468,9 +496,29 @@ static int php_sybase_do_connect_internal(sybase_link *sybase, char *host, char } } + /* Set the login timeout. Actually, the login timeout is per context + * and not per connection, but we will update the context here to + * allow for code such as the following: + * + * ini_set('sybct.login_timeout', $timeout); + * sybase_connect(...) + * + * Note that preceding calls to sybase_connect() will now use the + * updated value and not the default one! + * + * The default value for CS_LOGIN_TIMEOUT is 60 (1 minute). + */ + if (SybCtG(login_timeout) != -1) { + CS_INT cs_login_timeout = SybCtG(login_timeout); + if (ct_config(SybCtG(context), CS_SET, CS_LOGIN_TIMEOUT, &cs_login_timeout, CS_UNUSED, NULL)!=CS_SUCCEED) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Unable to update the login timeout"); + } + } + sybase->valid = 1; sybase->dead = 0; sybase->active_result_index = 0; + sybase->callback_name = NULL; /* create the link */ if (ct_connect(sybase->connection, host, CS_NULLTERM)!=CS_SUCCEED) { @@ -598,7 +646,6 @@ static void php_sybase_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) break; } - if (!SybCtG(allow_persistent)) { persistent=0; } @@ -1073,7 +1120,7 @@ static int php_sybase_fetch_result_row (sybase_result *result, int numrows) * convert_to_double() on them. This is a small performance penalty, but * ensures that "select 2147483648" will be a float and "select 2147483647" * will be become an int. - */ + */ convert_to_double(&result->data[i][j]); break; } @@ -2057,49 +2104,67 @@ PHP_FUNCTION(sybase_deadlock_retry_count) /* }}} */ -/* {{{ proto bool sybase_set_message_handler(mixed error_func) +/* {{{ proto bool sybase_set_message_handler(mixed error_func [, resource connection]) Set the error handler, to be called when a server message is raised. If error_func is NULL the handler will be deleted */ PHP_FUNCTION(sybase_set_message_handler) { - zval ***params; + zval **callback, **param, **sybase_link_index= NULL; char *name; - int argc = ZEND_NUM_ARGS(); + sybase_link *sybase_ptr; - if (argc != 1) { - WRONG_PARAM_COUNT; - } - - params = safe_emalloc(sizeof(zval **), argc, 0); + switch (ZEND_NUM_ARGS()) { + case 1: /* Default message handler */ + if (zend_get_parameters_ex(1, ¶m) == FAILURE) { + RETURN_FALSE; + } + callback = &SybCtG(callback_name); + break; - if (zend_get_parameters_array_ex(argc, params) == FAILURE) { - efree(params); - RETURN_FALSE; - } + case 2: /* Connection-based message handler */ + if (zend_get_parameters_ex(2, ¶m, &sybase_link_index) == FAILURE) { + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE2(sybase_ptr, sybase_link *, sybase_link_index, -1, "Sybase-Link", le_link, le_plink); + callback = &sybase_ptr->callback_name; + break; - if (SybCtG(callback_name)) { - zval_ptr_dtor(&SybCtG(callback_name)); - SybCtG(callback_name)= NULL; + default: + WRONG_PARAM_COUNT; } - if (Z_TYPE_PP(params[0]) == IS_NULL) { - efree(params); - RETURN_TRUE; + /* Clean out old callback */ + if (*callback) { + zval_ptr_dtor(callback); + *callback = NULL; } - if (!zend_is_callable(*params[0], 0, &name)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "First argumented is expected to be a valid callback, '%s' was given", name); - efree(name); - efree(params); - RETURN_FALSE; + switch (Z_TYPE_PP(param)) { + case IS_NULL: + /* Return TRUE to indicate we deleted the message handler */ + RETURN_TRUE; + break; + + case IS_ARRAY: + case IS_STRING: + /* Either "function", array("class", "function") or array($object, "function") */ + if (!zend_is_callable(*param, 0, &name)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "First argumented is expected to be a valid callback, '%s' was given", name); + efree(name); + RETURN_FALSE; + } + efree(name); + break; + + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "First argumented is expected to be either NULL, an array or string, %s given", zend_zval_type_name(*param)); + RETURN_FALSE; } - ALLOC_ZVAL(SybCtG(callback_name)); - *SybCtG(callback_name) = **params[0]; - INIT_PZVAL(SybCtG(callback_name)); - zval_copy_ctor(SybCtG(callback_name)); - efree(params); - efree(name); + ALLOC_ZVAL(*callback); + **callback = **param; + INIT_PZVAL(*callback); + zval_copy_ctor(*callback); RETURN_TRUE; } /* }}} */ diff --git a/ext/sybase_ct/php_sybase_ct.h b/ext/sybase_ct/php_sybase_ct.h index bd19dd1a13..5eb7c0285f 100644 --- a/ext/sybase_ct/php_sybase_ct.h +++ b/ext/sybase_ct/php_sybase_ct.h @@ -65,6 +65,7 @@ ZEND_BEGIN_MODULE_GLOBALS(sybase) long default_link; long num_links,num_persistent; long max_links,max_persistent; + long login_timeout; long allow_persistent; char *appname; char *hostname; @@ -83,6 +84,7 @@ typedef struct { int dead; int active_result_index; long affected_rows; + zval *callback_name; } sybase_link; #define SYBASE_ROWS_BLOCK 128