📄 php_sybase_ct.c
字号:
/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Authors: Zeev Suraski <zeev@zend.com> | | Tom May <tom@go2net.com> | | Timm Friebe <php_sybase_ct@thekid.de> | +----------------------------------------------------------------------+ *//* $Id: php_sybase_ct.c,v 1.73.2.18.2.3 2007/01/01 09:46:49 sebastian Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "php.h"#include "php_sybase_ct.h"#include "ext/standard/php_standard.h"#include "ext/standard/info.h"#include "php_globals.h"#include "php_ini.h"/* True globals, no need for thread safety */static int le_link, le_plink, le_result;#if HAVE_SYBASE_CTfunction_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) {NULL, NULL, NULL}};zend_module_entry sybase_module_entry = { STANDARD_MODULE_HEADER, "sybase_ct", sybase_functions, PHP_MINIT(sybase), PHP_MSHUTDOWN(sybase), PHP_RINIT(sybase), PHP_RSHUTDOWN(sybase), PHP_MINFO(sybase), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES};ZEND_DECLARE_MODULE_GLOBALS(sybase)/* static CS_CONTEXT *context; */#ifdef COMPILE_DL_SYBASE_CTZEND_GET_MODULE(sybase)#endifZEND_DECLARE_MODULE_GLOBALS(sybase)#define CHECK_LINK(link) { if (link==-1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: A link to the server could not be established"); RETURN_FALSE; } }static int _clean_invalid_results(list_entry *le TSRMLS_DC){ if (Z_TYPE_P(le) == le_result) { sybase_link *sybase_ptr = ((sybase_result *) le->ptr)->sybase_ptr; if (!sybase_ptr->valid) { return 1; } } return 0;}static void _free_sybase_result(sybase_result *result){ int i, j; if (result->data) { for (i = 0; i < (result->store ? result->num_rows : MIN(1, result->num_rows)); i++) { for (j=0; j<result->num_fields; j++) { zval_dtor(&result->data[i][j]); } efree(result->data[i]); } efree(result->data); } if (result->fields) { for (i=0; i<result->num_fields; i++) { STR_FREE(result->fields[i].name); STR_FREE(result->fields[i].column_source); } efree(result->fields); } efree(result);}/* Forward declaration */static int php_sybase_finish_results (sybase_result *result);static void php_free_sybase_result(zend_rsrc_list_entry *rsrc TSRMLS_DC){ sybase_result *result = (sybase_result *)rsrc->ptr; /* Check to see if we've read all rows */ if (result->sybase_ptr && result->sybase_ptr->active_result_index) { if (result->sybase_ptr->cmd) { ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_ALL); } php_sybase_finish_results(result); } _free_sybase_result(result);}static void _close_sybase_link(zend_rsrc_list_entry *rsrc TSRMLS_DC){ sybase_link *sybase_ptr = (sybase_link *)rsrc->ptr; 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); /* Non-persistent connections will always be connected or we wouldn't * get here, but since we want to check the death status anyway * we might as well double-check the connect status. */ if (ct_con_props(sybase_ptr->connection, CS_GET, CS_CON_STATUS, &con_status, CS_UNUSED, NULL)!=CS_SUCCEED) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Unable to get connection status on close"); /* Assume the worst. */ con_status = CS_CONSTAT_CONNECTED | CS_CONSTAT_DEAD; } if (con_status & CS_CONSTAT_CONNECTED) { if ((con_status & CS_CONSTAT_DEAD) || ct_close(sybase_ptr->connection, CS_UNUSED)!=CS_SUCCEED) { ct_close(sybase_ptr->connection, CS_FORCE_CLOSE); } } ct_con_drop(sybase_ptr->connection); efree(sybase_ptr); SybCtG(num_links)--;}static void _close_sybase_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC){ sybase_link *sybase_ptr = (sybase_link *)rsrc->ptr; CS_INT con_status; /* Persistent connections may have been closed before a failed * reopen attempt. */ if (ct_con_props(sybase_ptr->connection, CS_GET, CS_CON_STATUS, &con_status, CS_UNUSED, NULL)!=CS_SUCCEED) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Unable to get connection status on close"); /* Assume the worst. */ con_status = CS_CONSTAT_CONNECTED | CS_CONSTAT_DEAD; } if (con_status & CS_CONSTAT_CONNECTED) { if ((con_status & CS_CONSTAT_DEAD) || ct_close(sybase_ptr->connection, CS_UNUSED)!=CS_SUCCEED) { ct_close(sybase_ptr->connection, CS_FORCE_CLOSE); } } ct_con_drop(sybase_ptr->connection); free(sybase_ptr); SybCtG(num_persistent)--; SybCtG(num_links)--;}static CS_RETCODE CS_PUBLIC _client_message_handler(CS_CONTEXT *context, CS_CONNECTION *connection, CS_CLIENTMSG *errmsg){ TSRMLS_FETCH(); if (CS_SEVERITY(errmsg->msgnumber) >= SybCtG(min_client_severity)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Client message: %s (severity %d)", errmsg->msgstring, CS_SEVERITY(errmsg->msgnumber)); } STR_FREE(SybCtG(server_message)); SybCtG(server_message) = estrdup(errmsg->msgstring); /* If this is a timeout message, return CS_FAIL to cancel the * operation and mark the connection as dead. */ if (CS_SEVERITY(errmsg->msgnumber) == CS_SV_RETRY_FAIL && CS_NUMBER(errmsg->msgnumber) == 63 && CS_ORIGIN(errmsg->msgnumber) == 2 && CS_LAYER(errmsg->msgnumber) == 1) { return CS_FAIL; } return CS_SUCCEED;}static int _call_message_handler(zval *callback_name, CS_SERVERMSG *srvmsg TSRMLS_DC){ int handled = 0; if (callback_name) { zval *msgnumber, *severity, *state, *line, *text, *retval = NULL; zval **args[5]; MAKE_STD_ZVAL(msgnumber); ZVAL_LONG(msgnumber, srvmsg->msgnumber); args[0] = &msgnumber; MAKE_STD_ZVAL(severity); ZVAL_LONG(severity, srvmsg->severity); args[1] = &severity; MAKE_STD_ZVAL(state); ZVAL_LONG(state, srvmsg->state); args[2] = &state; MAKE_STD_ZVAL(line); ZVAL_LONG(line, srvmsg->line); args[3] = &line; MAKE_STD_ZVAL(text); ZVAL_STRING(text, srvmsg->text, 1); args[4] = &text; 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 (retval) { handled= ((Z_TYPE_P(retval) != IS_BOOL) || (Z_BVAL_P(retval) != 0)); zval_ptr_dtor(&retval); } zval_ptr_dtor(&msgnumber); zval_ptr_dtor(&severity); zval_ptr_dtor(&state); zval_ptr_dtor(&line); zval_ptr_dtor(&text); } 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 (sybase && (srvmsg->msgnumber == 1205)) { sybase->deadlock = 1; } /* 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;}PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("sybct.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateInt, allow_persistent, zend_sybase_globals, sybase_globals) STD_PHP_INI_ENTRY_EX("sybct.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateInt, max_persistent, zend_sybase_globals, sybase_globals, display_link_numbers) STD_PHP_INI_ENTRY_EX("sybct.max_links", "-1", PHP_INI_SYSTEM, OnUpdateInt, max_links, zend_sybase_globals, sybase_globals, display_link_numbers) STD_PHP_INI_ENTRY("sybct.min_server_severity", "10", PHP_INI_ALL, OnUpdateInt, min_server_severity, zend_sybase_globals, sybase_globals) STD_PHP_INI_ENTRY("sybct.min_client_severity", "10", PHP_INI_ALL, OnUpdateInt, min_client_severity, zend_sybase_globals, sybase_globals) STD_PHP_INI_ENTRY("sybct.login_timeout", "-1", PHP_INI_ALL, OnUpdateInt, 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, OnUpdateInt, 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 opt; TSRMLS_FETCH(); if (cs_ctx_alloc(CTLIB_VERSION, &sybase_globals->context)!=CS_SUCCEED || ct_init(sybase_globals->context, CTLIB_VERSION)!=CS_SUCCEED) { return; } /* Initialize message handlers */ if (ct_callback(sybase_globals->context, NULL, CS_SET, CS_SERVERMSG_CB, (CS_VOID *)_server_message_handler)!=CS_SUCCEED) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Unable to set server message handler"); } if (ct_callback(sybase_globals->context, NULL, CS_SET, CS_CLIENTMSG_CB, (CS_VOID *)_client_message_handler)!=CS_SUCCEED) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Unable to set client message handler"); } /* Set datetime conversion format to "Nov 3 1998 8:06PM". * This is the default format for the ct-lib that comes with * Sybase ASE 11.5.1 for Solaris, but the Linux libraries that * come with 11.0.3.3 default to "03/11/98" which is singularly * useless. This levels the playing field for all platforms. */ { CS_INT dt_convfmt = CS_DATES_SHORT; if (cs_dt_info(sybase_globals->context, CS_SET, NULL, CS_DT_CONVFMT, CS_UNUSED, &dt_convfmt, sizeof(dt_convfmt), NULL)!=CS_SUCCEED) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Unable to set datetime conversion format"); } } /* 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.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"); } } /* 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;}static void php_sybase_destroy_globals(zend_sybase_globals *sybase_globals){ ct_exit(sybase_globals->context, CS_UNUSED); cs_ctx_drop(sybase_globals->context);}PHP_MINIT_FUNCTION(sybase){ ZEND_INIT_MODULE_GLOBALS(sybase, php_sybase_init_globals, php_sybase_destroy_globals); REGISTER_INI_ENTRIES(); le_link = zend_register_list_destructors_ex(_close_sybase_link, NULL, "sybase-ct link", module_number); le_plink = zend_register_list_destructors_ex(NULL, _close_sybase_plink, "sybase-ct link persistent", module_number); le_result = zend_register_list_destructors_ex(php_free_sybase_result, NULL, "sybase-ct result", module_number); return SUCCESS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -