Author: ahristov
Date: 2008-02-11 13:32:03 +0100 (Mon, 11 Feb 2008)
New Revision: 1266
Modified:
trunk/mysqlnd/mysqlnd.c
trunk/mysqlnd/mysqlnd.h
trunk/mysqlnd/mysqlnd_structs.h
trunk/php5/ext/mysqli/mysqli_fe.c
trunk/php5/ext/mysqli/mysqli_nonapi.c
trunk/php5/ext/mysqli/php_mysqli_structs.h
trunk/php6/ext/mysqli/mysqli.c
trunk/php6/ext/mysqli/mysqli_fe.c
trunk/php6/ext/mysqli/mysqli_mysqlnd.h
trunk/php6/ext/mysqli/mysqli_nonapi.c
trunk/php6/ext/mysqli/php_mysqli_structs.h
Log:
Async stuff.
Ulf, it's your turn ;)
Modified: trunk/mysqlnd/mysqlnd.c
===================================================================
--- trunk/mysqlnd/mysqlnd.c 2008-02-08 19:13:49 UTC (rev 1265)
+++ trunk/mysqlnd/mysqlnd.c 2008-02-11 12:32:03 UTC (rev 1266)
@@ -875,7 +875,184 @@
}
/* }}} */
+/* {{{ mysqlnd_conn::send_query */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn, reap_query)(MYSQLND *conn TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_conn::reap_query");
+ DBG_INF_FMT("conn=%llu", conn->thread_id);
+ DBG_RETURN(mysqlnd_query_read_result_set_header(conn, NULL TSRMLS_CC));
+}
+/* }}} */
+
+
+#include "php_network.h"
+
+/* {{{ stream_select mysqlnd_stream_array_to_fd_set functions */
+static int mysqlnd_stream_array_to_fd_set(MYSQLND **conn_array, fd_set *fds, php_socket_t
*max_fd TSRMLS_DC)
+{
+ php_socket_t this_fd;
+ int cnt = 0;
+ MYSQLND **p = conn_array;
+
+ while (*p) {
+ /* get the fd.
+ * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag
+ * when casting. It is only used here so that the buffered data warning
+ * is not displayed.
+ * */
+ if (SUCCESS == php_stream_cast((*p)->net.stream, PHP_STREAM_AS_FD_FOR_SELECT |
PHP_STREAM_CAST_INTERNAL,
+ (void*)&this_fd, 1) && this_fd >= 0) {
+
+ PHP_SAFE_FD_SET(this_fd, fds);
+
+ if (this_fd > *max_fd) {
+ *max_fd = this_fd;
+ }
+ cnt++;
+ }
+ p++;
+ }
+ return cnt ? 1 : 0;
+}
+
+static int mysqlnd_stream_array_from_fd_set(MYSQLND **conn_array, fd_set *fds TSRMLS_DC)
+{
+ php_socket_t this_fd;
+ int ret = 0;
+ zend_bool disproportion = FALSE;
+
+
+ MYSQLND **fwd = conn_array, **bckwd = conn_array;
+
+ while (*fwd) {
+ /* get the fd
+ * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag
+ * when casting. It is only used here so that the buffered data warning
+ * is not displayed.
+ */
+ if (SUCCESS == php_stream_cast((*fwd)->net.stream, PHP_STREAM_AS_FD_FOR_SELECT |
PHP_STREAM_CAST_INTERNAL,
+ (void*)&this_fd, 1) && this_fd >= 0) {
+ if (PHP_SAFE_FD_ISSET(this_fd, fds)) {
+ if (disproportion) {
+ *bckwd = *fwd;
+ }
+ bckwd++;
+ fwd++;
+ ret++;
+ continue;
+ }
+ }
+ disproportion = TRUE;
+ fwd++;
+ }
+ *bckwd = NULL;/* NULL-terminate the list */
+
+ return ret;
+}
+
+
+#ifndef PHP_WIN32
+#define php_select(m, r, w, e, t) select(m, r, w, e, t)
+#else
+#include "win32/select.h"
+#endif
+
+/* {{{ _mysqlnd_poll */
+enum_func_status
+_mysqlnd_poll(MYSQLND **r_array, MYSQLND **w_array, MYSQLND **e_array, zval ** sec, long
usec, uint * desc_num TSRMLS_DC)
+{
+
+ struct timeval tv;
+ struct timeval *tv_p = NULL;
+ fd_set rfds, wfds, efds;
+ php_socket_t max_fd = 0;
+ int retval, sets = 0;
+ int set_count, max_set_count = 0;
+ DBG_ENTER("mysqlnd_poll");
+
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_ZERO(&efds);
+
+ if (r_array != NULL) {
+ set_count = mysqlnd_stream_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC);
+ if (set_count > max_set_count)
+ max_set_count = set_count;
+ sets += set_count;
+ }
+
+ if (w_array != NULL) {
+ set_count = mysqlnd_stream_array_to_fd_set(w_array, &wfds, &max_fd TSRMLS_CC);
+ if (set_count > max_set_count)
+ max_set_count = set_count;
+ sets += set_count;
+ }
+
+ if (e_array != NULL) {
+ set_count = mysqlnd_stream_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC);
+ if (set_count > max_set_count)
+ max_set_count = set_count;
+ sets += set_count;
+ }
+
+ if (!sets) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No stream arrays were passed");
+ DBG_RETURN(FAIL);
+ }
+
+ PHP_SAFE_MAX_FD(max_fd, max_set_count);
+
+ /* If seconds is not set to null, build the timeval, else we wait indefinitely */
+ if (sec != NULL) {
+ convert_to_long_ex(sec);
+
+ if (Z_LVAL_PP(sec) < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The seconds parameter must be greater
than 0");
+ DBG_RETURN(FAIL);
+ } else if (usec < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The microseconds parameter must be
greater than 0");
+ DBG_RETURN(FAIL);
+ }
+
+ /* Solaris + BSD do not like microsecond values which are >= 1 sec */
+ if (usec > 999999) {
+ tv.tv_sec = Z_LVAL_PP(sec) + (usec / 1000000);
+ tv.tv_usec = usec % 1000000;
+ } else {
+ tv.tv_sec = Z_LVAL_PP(sec);
+ tv.tv_usec = usec;
+ }
+
+ tv_p = &tv;
+ }
+
+ retval = php_select(max_fd + 1, &rfds, &wfds, &efds, tv_p);
+
+ if (retval == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to select [%d]: %s (max_fd=%d)",
+ errno, strerror(errno), max_fd);
+ DBG_RETURN(FAIL);
+ }
+
+ if (r_array != NULL) {
+ mysqlnd_stream_array_from_fd_set(r_array, &rfds TSRMLS_CC);
+ }
+ if (w_array != NULL) {
+ mysqlnd_stream_array_from_fd_set(w_array, &wfds TSRMLS_CC);
+ }
+ if (e_array != NULL) {
+ mysqlnd_stream_array_from_fd_set(e_array, &efds TSRMLS_CC);
+ }
+
+ *desc_num = retval;
+
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
/*
COM_FIELD_LIST is special, different from a SHOW FIELDS FROM :
- There is no result set header - status from the command, which
@@ -1911,6 +2088,7 @@
MYSQLND_METHOD(mysqlnd_conn, set_charset),
MYSQLND_METHOD(mysqlnd_conn, query),
MYSQLND_METHOD(mysqlnd_conn, send_query),
+ MYSQLND_METHOD(mysqlnd_conn, reap_query),
MYSQLND_METHOD(mysqlnd_conn, use_result),
MYSQLND_METHOD(mysqlnd_conn, store_result),
MYSQLND_METHOD(mysqlnd_conn, background_store_result),
Modified: trunk/mysqlnd/mysqlnd.h
===================================================================
--- trunk/mysqlnd/mysqlnd.h 2008-02-08 19:13:49 UTC (rev 1265)
+++ trunk/mysqlnd/mysqlnd.h 2008-02-11 12:32:03 UTC (rev 1266)
@@ -100,8 +100,11 @@
#define mysqlnd_close(conn,is_forced) (conn)->m->close((conn), (is_forced)
TSRMLS_CC)
#define mysqlnd_query(conn, query_str, query_len) (conn)->m->query((conn),
(query_str), (query_len) TSRMLS_CC)
#define mysqlnd_async_query(conn, query_str,
query_len) (conn)->m->send_query((conn), (query_str), (query_len) TSRMLS_CC)
+#define mysqlnd_poll(r, w, err, sec, usec, desc_num) _mysqlnd_poll((r), (w), (err),
(sec), (usec), (desc_num) TSRMLS_CC)
+#define mysqlnd_reap_async_query(conn) (conn)->m->reap_query((conn) TSRMLS_CC)
#define mysqlnd_unbuffered_skip_result(result) (result)->m.skip_result((result)
TSRMLS_CC)
+enum_func_status _mysqlnd_poll(MYSQLND **r_array, MYSQLND **w_array, MYSQLND **e_array,
zval ** sec, long usec, uint * desc_num TSRMLS_DC);
#define mysqlnd_use_result(conn) (conn)->m->use_result((conn) TSRMLS_CC)
#define mysqlnd_store_result(conn) (conn)->m->store_result((conn) TSRMLS_CC)
Modified: trunk/mysqlnd/mysqlnd_structs.h
===================================================================
--- trunk/mysqlnd/mysqlnd_structs.h 2008-02-08 19:13:49 UTC (rev 1265)
+++ trunk/mysqlnd/mysqlnd_structs.h 2008-02-11 12:32:03 UTC (rev 1266)
@@ -237,6 +237,7 @@
enum_func_status (*set_charset)(MYSQLND * const conn, const char * const charset
TSRMLS_DC);
enum_func_status (*query)(MYSQLND *conn, const char *query, unsigned int query_len
TSRMLS_DC);
enum_func_status (*send_query)(MYSQLND *conn, const char *query, unsigned int query_len
TSRMLS_DC);
+ enum_func_status (*reap_query)(MYSQLND *conn TSRMLS_DC);
MYSQLND_RES * (*use_result)(MYSQLND * const conn TSRMLS_DC);
MYSQLND_RES * (*store_result)(MYSQLND * const conn TSRMLS_DC);
MYSQLND_RES * (*background_store_result)(MYSQLND * const conn TSRMLS_DC);
@@ -400,9 +401,6 @@
unsigned long client_flag;
unsigned long server_capabilities;
- int tmp_int;
-
-
/* For UPSERT queries */
mysqlnd_upsert_status upsert_status;
char *last_message;
Modified: trunk/php5/ext/mysqli/mysqli_fe.c
===================================================================
--- trunk/php5/ext/mysqli/mysqli_fe.c 2008-02-08 19:13:49 UTC (rev 1265)
+++ trunk/php5/ext/mysqli/mysqli_fe.c 2008-02-11 12:32:03 UTC (rev 1266)
@@ -116,12 +116,18 @@
PHP_FE(mysqli_num_rows, NULL)
PHP_FE(mysqli_options, NULL)
PHP_FE(mysqli_ping, NULL)
+#if defined(HAVE_MYSQLND)
+ PHP_FE(mysqli_poll, NULL)
+#endif
PHP_FE(mysqli_prepare, NULL)
PHP_FE(mysqli_report, NULL)
PHP_FE(mysqli_query, NULL)
PHP_FE(mysqli_real_connect, NULL)
PHP_FE(mysqli_real_escape_string, NULL)
PHP_FE(mysqli_real_query, NULL)
+#if defined(HAVE_MYSQLND)
+ PHP_FE(mysqli_reap_async_query, NULL)
+#endif
PHP_FE(mysqli_rollback, NULL)
PHP_FE(mysqli_select_db, NULL)
#ifdef HAVE_MYSQLI_SET_CHARSET
@@ -215,6 +221,7 @@
PHP_FALIAS(options,mysqli_options,NULL)
PHP_FALIAS(ping,mysqli_ping,NULL)
PHP_FALIAS(prepare,mysqli_prepare,NULL)
+ PHP_FALIAS(reap_async_query,mysqli_reap_async_query,NULL)
PHP_FALIAS(query,mysqli_query,NULL)
PHP_FALIAS(real_connect,mysqli_real_connect,NULL)
PHP_FALIAS(real_escape_string,mysqli_real_escape_string,NULL)
Modified: trunk/php5/ext/mysqli/mysqli_nonapi.c
===================================================================
--- trunk/php5/ext/mysqli/mysqli_nonapi.c 2008-02-08 19:13:49 UTC (rev 1265)
+++ trunk/php5/ext/mysqli/mysqli_nonapi.c 2008-02-11 12:32:03 UTC (rev 1266)
@@ -498,9 +498,9 @@
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty query");
RETURN_FALSE;
}
- if (resultmode != MYSQLI_USE_RESULT && resultmode != MYSQLI_STORE_RESULT
+ if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode &
~MYSQLI_ASYNC) != MYSQLI_STORE_RESULT
#if defined(HAVE_MYSQLND) && defined(MYSQLND_THREADED)
- && resultmode != MYSQLI_BG_STORE_RESULT
+ && (resultmode & ~MYSQLI_ASYNC) != MYSQLI_BG_STORE_RESULT
#endif
) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for resultmode");
@@ -518,6 +518,7 @@
MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
RETURN_FALSE;
}
+ mysql->async_result_fetch_type = resultmode & ~MYSQLI_ASYNC;
RETURN_TRUE;
}
#endif
@@ -568,6 +569,194 @@
#if defined(HAVE_MYSQLND)
+#include "php_network.h"
+/* {{{ mysqlnd_zval_array_to_mysqlnd_array functions */
+static int mysqlnd_zval_array_to_mysqlnd_array(zval *in_array, MYSQLND ***out_array
TSRMLS_DC)
+{
+ zval **elem;
+ int i = 0, current = 0;
+
+ if (Z_TYPE_P(in_array) != IS_ARRAY) {
+ return 0;
+ }
+ *out_array = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(in_array)) + 1, sizeof(MYSQLND
*));
+ for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(in_array));
+ zend_hash_get_current_data(Z_ARRVAL_P(in_array), (void **) &elem) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(in_array))) {
+ i++;
+ if (Z_TYPE_PP(elem) != IS_OBJECT ||
+ !instanceof_function(Z_OBJCE_PP(elem), mysqli_link_class_entry TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter %d not a mysqli object", i);
+ }
+ {
+ MY_MYSQL *mysql;
+ MYSQLI_RESOURCE *my_res;
+ mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*elem
TSRMLS_CC);
+ if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "[%d] Couldn't fetch %s", i,
intern->zo.ce->name);
+ continue;
+ }
+ mysql = (MY_MYSQL*) my_res->ptr;
+ if (MYSQLI_STATUS_VALID && my_res->status < MYSQLI_STATUS_VALID) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid object %d or resource %s", i,
intern->zo.ce->name);
+ continue;
+ }
+ (*out_array)[current++] = mysql->mysql;
+ }
+ }
+ return 0;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zval_array_from_mysqlnd_array */
+static int mysqlnd_zval_array_from_mysqlnd_array(MYSQLND **in_array, zval *out_array
TSRMLS_DC)
+{
+ MYSQLND **p = in_array;
+ HashTable *new_hash;
+ zval **elem, **dest_elem;
+ int ret = 0;
+
+ ALLOC_HASHTABLE(new_hash);
+ zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(out_array)), NULL,
ZVAL_PTR_DTOR, 0);
+
+ for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(out_array));
+ zend_hash_get_current_data(Z_ARRVAL_P(out_array), (void **) &elem) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(out_array)))
+ {
+ MY_MYSQL *mysql;
+ mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*elem TSRMLS_CC);
+ mysql = (MY_MYSQL *) ((MYSQLI_RESOURCE *)intern->ptr)->ptr;
+ if (mysql->mysql == *p) {
+ zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void
**)&dest_elem);
+ if (dest_elem) {
+ zval_add_ref(dest_elem);
+ }
+ ret++;
+ p++;
+ }
+ }
+
+ /* destroy old array and add new one */
+ zend_hash_destroy(Z_ARRVAL_P(out_array));
+ efree(Z_ARRVAL_P(out_array));
+
+ zend_hash_internal_pointer_reset(new_hash);
+ Z_ARRVAL_P(out_array) = new_hash;
+
+ return 0;
+}
+/* }}} */
+
+
+/* {{{ proto int mysqli_poll(array read, array write, array error, long sec [, long
usec]) U
+ Poll connections */
+PHP_FUNCTION(mysqli_poll)
+{
+ zval *r_array, *w_array, *e_array, **sec = NULL;
+ MYSQLND **new_r_array = NULL, **new_w_array = NULL, **new_e_array = NULL;
+ long usec = 0;
+ enum_func_status ret;
+ uint desc_num;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!a!Z!|l", &r_array,
&w_array, &e_array, &sec, &usec) == FAILURE) {
+ return;
+ }
+ if (r_array != NULL) {
+ mysqlnd_zval_array_to_mysqlnd_array(r_array, &new_r_array TSRMLS_CC);
+ }
+ if (w_array != NULL) {
+ mysqlnd_zval_array_to_mysqlnd_array(w_array, &new_w_array TSRMLS_CC);
+ }
+ if (e_array != NULL) {
+ mysqlnd_zval_array_to_mysqlnd_array(e_array, &new_e_array TSRMLS_CC);
+ }
+
+ ret = mysqlnd_poll(new_r_array, new_w_array, new_e_array, sec, usec, &desc_num);
+
+ if (r_array != NULL) {
+ mysqlnd_zval_array_from_mysqlnd_array(new_r_array, r_array TSRMLS_CC);
+ }
+ if (w_array != NULL) {
+ mysqlnd_zval_array_from_mysqlnd_array(new_w_array, w_array TSRMLS_CC);
+ }
+ if (e_array != NULL) {
+ mysqlnd_zval_array_from_mysqlnd_array(new_e_array, e_array TSRMLS_CC);
+ }
+
+ if (new_r_array) {
+ efree(new_r_array);
+ }
+ if (new_w_array) {
+ efree(new_r_array);
+ }
+ if (new_e_array) {
+ efree(new_r_array);
+ }
+ RETURN_LONG(ret == FAIL? FALSE:desc_num);
+}
+/* }}} */
+
+
+/* {{{ proto int mysqli_reap_async_query(object link) U
+ Poll connections */
+PHP_FUNCTION(mysqli_reap_async_query)
+{
+ MY_MYSQL *mysql;
+ zval *mysql_link;
+ MYSQLI_RESOURCE *mysqli_resource;
+ MYSQL_RES *result;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
&mysql_link, mysqli_link_class_entry) == FAILURE) {
+ return;
+ }
+
+ MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &mysql_link, "mysqli_link",
MYSQLI_STATUS_VALID);
+
+ if (FAIL == mysqlnd_reap_async_query(mysql->mysql)) {
+ RETURN_FALSE;
+ }
+
+ if (!mysql_field_count(mysql->mysql)) {
+ /* no result set - not a SELECT */
+ if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
+// php_mysqli_report_index("n/a", mysqli_server_status(mysql->mysql) TSRMLS_CC);
+ }
+ RETURN_TRUE;
+ }
+
+ switch (mysql->async_result_fetch_type) {
+ case MYSQLI_STORE_RESULT:
+ result = mysql_store_result(mysql->mysql);
+ break;
+ case MYSQLI_USE_RESULT:
+ result = mysql_use_result(mysql->mysql);
+ break;
+#if defined(HAVE_MYSQLND) && defined(MYSQLND_THREADED)
+ case MYSQLI_BG_STORE_RESULT:
+ result = mysqli_bg_store_result(mysql->mysql);
+ break;
+#endif
+ }
+
+ if (!result) {
+ php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql),
mysql_errno(mysql->mysql) TSRMLS_CC,
+ "%s", mysql_error(mysql->mysql));
+ RETURN_FALSE;
+ }
+
+ if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
+// php_mysqli_report_index("n/a", mysqli_server_status(mysql->mysql) TSRMLS_CC);
+ }
+
+ mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
+ mysqli_resource->ptr = (void *)result;
+ mysqli_resource->status = MYSQLI_STATUS_VALID;
+ MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
+}
+/* }}} */
+
+
/* {{{ proto object mysqli_stmt_get_result(object link) U
Buffer result set on client */
PHP_FUNCTION(mysqli_stmt_get_result)
Modified: trunk/php5/ext/mysqli/php_mysqli_structs.h
===================================================================
--- trunk/php5/ext/mysqli/php_mysqli_structs.h 2008-02-08 19:13:49 UTC (rev 1265)
+++ trunk/php5/ext/mysqli/php_mysqli_structs.h 2008-02-11 12:32:03 UTC (rev 1266)
@@ -90,8 +90,11 @@
char *hash_key;
zval *li_read;
php_stream *li_stream;
+ unsigned int multi_query;
zend_bool persistent;
- unsigned int multi_query;
+#if defined(HAVE_MYSQLND)
+ int async_result_fetch_type;
+#endif
} MY_MYSQL;
typedef struct {
@@ -449,6 +452,7 @@
PHP_FUNCTION(mysqli_num_rows);
PHP_FUNCTION(mysqli_options);
PHP_FUNCTION(mysqli_ping);
+PHP_FUNCTION(mysqli_poll);
PHP_FUNCTION(mysqli_prepare);
PHP_FUNCTION(mysqli_query);
PHP_FUNCTION(mysqli_stmt_result_metadata);
@@ -457,6 +461,7 @@
PHP_FUNCTION(mysqli_real_connect);
PHP_FUNCTION(mysqli_real_query);
PHP_FUNCTION(mysqli_real_escape_string);
+PHP_FUNCTION(mysqli_reap_async_query);
PHP_FUNCTION(mysqli_rollback);
PHP_FUNCTION(mysqli_row_seek);
PHP_FUNCTION(mysqli_select_db);
Modified: trunk/php6/ext/mysqli/mysqli.c
===================================================================
--- trunk/php6/ext/mysqli/mysqli.c 2008-02-08 19:13:49 UTC (rev 1265)
+++ trunk/php6/ext/mysqli/mysqli.c 2008-02-11 12:32:03 UTC (rev 1266)
@@ -687,6 +687,9 @@
#if defined(HAVE_MYSQLND) && defined(MYSQLND_THREADED)
REGISTER_LONG_CONSTANT("MYSQLI_BG_STORE_RESULT", MYSQLI_BG_STORE_RESULT, CONST_CS |
CONST_PERSISTENT);
#endif
+#if defined (HAVE_MYSQLND)
+ REGISTER_LONG_CONSTANT("MYSQLI_ASYNC", MYSQLI_ASYNC, CONST_CS | CONST_PERSISTENT);
+#endif
/* for mysqli_fetch_assoc */
REGISTER_LONG_CONSTANT("MYSQLI_ASSOC", MYSQLI_ASSOC, CONST_CS | CONST_PERSISTENT);
Modified: trunk/php6/ext/mysqli/mysqli_fe.c
===================================================================
--- trunk/php6/ext/mysqli/mysqli_fe.c 2008-02-08 19:13:49 UTC (rev 1265)
+++ trunk/php6/ext/mysqli/mysqli_fe.c 2008-02-11 12:32:03 UTC (rev 1266)
@@ -118,12 +118,18 @@
PHP_FE(mysqli_num_rows, NULL)
PHP_FE(mysqli_options, NULL)
PHP_FE(mysqli_ping, NULL)
+#if defined(HAVE_MYSQLND)
+ PHP_FE(mysqli_poll, NULL)
+#endif
PHP_FE(mysqli_prepare, NULL)
PHP_FE(mysqli_report, NULL)
PHP_FE(mysqli_query, NULL)
PHP_FE(mysqli_real_connect, NULL)
PHP_FE(mysqli_real_escape_string, NULL)
PHP_FE(mysqli_real_query, NULL)
+#if defined(HAVE_MYSQLND)
+ PHP_FE(mysqli_reap_async_query, NULL)
+#endif
PHP_FE(mysqli_rollback, NULL)
PHP_FE(mysqli_select_db, NULL)
#ifdef HAVE_MYSQLI_SET_CHARSET
@@ -220,6 +226,9 @@
PHP_FALIAS(query,mysqli_query,NULL)
PHP_FALIAS(real_connect,mysqli_real_connect,NULL)
PHP_FALIAS(real_escape_string,mysqli_real_escape_string,NULL)
+#if defined(HAVE_MYSQLND)
+ PHP_FALIAS(reap_async_query,mysqli_reap_async_query,NULL)
+#endif
PHP_FALIAS(escape_string, mysqli_real_escape_string,NULL)
PHP_FALIAS(real_query,mysqli_real_query,NULL)
PHP_FALIAS(rollback,mysqli_rollback,NULL)
Modified: trunk/php6/ext/mysqli/mysqli_mysqlnd.h
===================================================================
--- trunk/php6/ext/mysqli/mysqli_mysqlnd.h 2008-02-08 19:13:49 UTC (rev 1265)
+++ trunk/php6/ext/mysqli/mysqli_mysqlnd.h 2008-02-11 12:32:03 UTC (rev 1266)
@@ -38,5 +38,6 @@
#define mysqli_stmt_close(c, implicit) mysqlnd_stmt_close((c), (implicit))
#define mysqli_free_result(r, implicit) mysqlnd_free_result((r), (implicit))
#define mysqli_bg_store_result(r) mysqlnd_bg_store_result((r))
+#define mysqli_async_query(c, q, l) mysqlnd_async_query((c), (q), (l))
#endif
Modified: trunk/php6/ext/mysqli/mysqli_nonapi.c
===================================================================
--- trunk/php6/ext/mysqli/mysqli_nonapi.c 2008-02-08 19:13:49 UTC (rev 1265)
+++ trunk/php6/ext/mysqli/mysqli_nonapi.c 2008-02-11 12:32:03 UTC (rev 1266)
@@ -733,9 +733,9 @@
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty query");
RETURN_FALSE;
}
- if (resultmode != MYSQLI_USE_RESULT && resultmode != MYSQLI_STORE_RESULT
+ if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode &
~MYSQLI_ASYNC) != MYSQLI_STORE_RESULT
#if defined(HAVE_MYSQLND) && defined(MYSQLND_THREADED)
- && resultmode != MYSQLI_BG_STORE_RESULT
+ && (resultmode & ~MYSQLI_ASYNC) != MYSQLI_BG_STORE_RESULT
#endif
) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for resultmode");
@@ -746,6 +746,17 @@
MYSQLI_DISABLE_MQ;
+#ifdef HAVE_MYSQLND
+ if (resultmode & MYSQLI_ASYNC) {
+ if (mysqli_async_query(mysql->mysql, query, query_len)) {
+ MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
+ RETURN_FALSE;
+ }
+ mysql->async_result_fetch_type = resultmode & ~MYSQLI_ASYNC;
+ RETURN_TRUE;
+ }
+#endif
+
if (mysql_real_query(mysql->mysql, query, query_len)) {
MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
RETURN_FALSE;
@@ -791,6 +802,195 @@
#if defined(HAVE_MYSQLND)
+#include "php_network.h"
+/* {{{ mysqlnd_zval_array_to_mysqlnd_array functions */
+static int mysqlnd_zval_array_to_mysqlnd_array(zval *in_array, MYSQLND ***out_array
TSRMLS_DC)
+{
+ zval **elem;
+ int i = 0, current = 0;
+
+ if (Z_TYPE_P(in_array) != IS_ARRAY) {
+ return 0;
+ }
+ *out_array = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(in_array)) + 1, sizeof(MYSQLND
*));
+ for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(in_array));
+ zend_hash_get_current_data(Z_ARRVAL_P(in_array), (void **) &elem) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(in_array))) {
+ i++;
+ if (Z_TYPE_PP(elem) != IS_OBJECT ||
+ !instanceof_function(Z_OBJCE_PP(elem), mysqli_link_class_entry TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter %d not a mysqli object", i);
+ }
+ {
+ MY_MYSQL *mysql;
+ MYSQLI_RESOURCE *my_res;
+ mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*elem
TSRMLS_CC);
+ if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "[%d] Couldn't fetch %s", i,
intern->zo.ce->name);
+ continue;
+ }
+ mysql = (MY_MYSQL*) my_res->ptr;
+ if (MYSQLI_STATUS_VALID && my_res->status < MYSQLI_STATUS_VALID) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid object %d or resource %s", i,
intern->zo.ce->name);
+ continue;
+ }
+ (*out_array)[current++] = mysql->mysql;
+ }
+ }
+ return 0;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zval_array_from_mysqlnd_array */
+static int mysqlnd_zval_array_from_mysqlnd_array(MYSQLND **in_array, zval *out_array
TSRMLS_DC)
+{
+ MYSQLND **p = in_array;
+ HashTable *new_hash;
+ zval **elem, **dest_elem;
+ int ret = 0;
+
+ ALLOC_HASHTABLE(new_hash);
+ zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(out_array)), NULL,
ZVAL_PTR_DTOR, 0);
+
+ for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(out_array));
+ zend_hash_get_current_data(Z_ARRVAL_P(out_array), (void **) &elem) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(out_array)))
+ {
+ MY_MYSQL *mysql;
+ mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*elem TSRMLS_CC);
+ mysql = (MY_MYSQL *) ((MYSQLI_RESOURCE *)intern->ptr)->ptr;
+ if (mysql->mysql == *p) {
+ zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void
**)&dest_elem);
+ if (dest_elem) {
+ zval_add_ref(dest_elem);
+ }
+ ret++;
+ p++;
+ }
+ }
+
+ /* destroy old array and add new one */
+ zend_hash_destroy(Z_ARRVAL_P(out_array));
+ efree(Z_ARRVAL_P(out_array));
+
+ zend_hash_internal_pointer_reset(new_hash);
+ Z_ARRVAL_P(out_array) = new_hash;
+
+ return 0;
+}
+/* }}} */
+
+
+/* {{{ proto int mysqli_poll(array read, array write, array error, long sec [, long
usec]) U
+ Poll connections */
+PHP_FUNCTION(mysqli_poll)
+{
+ zval *r_array, *w_array, *e_array, **sec = NULL;
+ MYSQLND **new_r_array = NULL, **new_w_array = NULL, **new_e_array = NULL;
+ long usec = 0;
+ enum_func_status ret;
+ uint desc_num;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!a!Z!|l", &r_array,
&w_array, &e_array, &sec, &usec) == FAILURE) {
+ return;
+ }
+ if (r_array != NULL) {
+ mysqlnd_zval_array_to_mysqlnd_array(r_array, &new_r_array TSRMLS_CC);
+ }
+ if (w_array != NULL) {
+ mysqlnd_zval_array_to_mysqlnd_array(w_array, &new_w_array TSRMLS_CC);
+ }
+ if (e_array != NULL) {
+ mysqlnd_zval_array_to_mysqlnd_array(e_array, &new_e_array TSRMLS_CC);
+ }
+
+ ret = mysqlnd_poll(new_r_array, new_w_array, new_e_array, sec, usec, &desc_num);
+
+ if (r_array != NULL) {
+ mysqlnd_zval_array_from_mysqlnd_array(new_r_array, r_array TSRMLS_CC);
+ }
+ if (w_array != NULL) {
+ mysqlnd_zval_array_from_mysqlnd_array(new_w_array, w_array TSRMLS_CC);
+ }
+ if (e_array != NULL) {
+ mysqlnd_zval_array_from_mysqlnd_array(new_e_array, e_array TSRMLS_CC);
+ }
+
+ if (new_r_array) {
+ efree(new_r_array);
+ }
+ if (new_w_array) {
+ efree(new_r_array);
+ }
+ if (new_e_array) {
+ efree(new_r_array);
+ }
+ RETURN_LONG(ret == FAIL? FALSE:desc_num);
+}
+/* }}} */
+
+
+/* {{{ proto int mysqli_reap_async_query(object link) U
+ Poll connections */
+PHP_FUNCTION(mysqli_reap_async_query)
+{
+ MY_MYSQL *mysql;
+ zval *mysql_link;
+ MYSQLI_RESOURCE *mysqli_resource;
+ MYSQL_RES *result;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
&mysql_link, mysqli_link_class_entry) == FAILURE) {
+ return;
+ }
+
+ MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &mysql_link, "mysqli_link",
MYSQLI_STATUS_VALID);
+
+ if (FAIL == mysqlnd_reap_async_query(mysql->mysql)) {
+ RETURN_FALSE;
+ }
+
+ if (!mysql_field_count(mysql->mysql)) {
+ /* no result set - not a SELECT */
+ if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
+/* php_mysqli_report_index("n/a", mysqli_server_status(mysql->mysql) TSRMLS_CC); */
+ }
+ RETURN_TRUE;
+ }
+
+ switch (mysql->async_result_fetch_type) {
+ case MYSQLI_STORE_RESULT:
+ result = mysql_store_result(mysql->mysql);
+ break;
+ case MYSQLI_USE_RESULT:
+ result = mysql_use_result(mysql->mysql);
+ break;
+#if defined(HAVE_MYSQLND) && defined(MYSQLND_THREADED)
+ case MYSQLI_BG_STORE_RESULT:
+ result = mysqli_bg_store_result(mysql->mysql);
+ break;
+#endif
+ }
+
+ if (!result) {
+ php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql),
mysql_errno(mysql->mysql) TSRMLS_CC,
+ "%s", mysql_error(mysql->mysql));
+ RETURN_FALSE;
+ }
+
+ if (MyG(report_mode) & MYSQLI_REPORT_INDEX) {
+/* php_mysqli_report_index("n/a", mysqli_server_status(mysql->mysql) TSRMLS_CC);*/
+ }
+
+ mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
+ mysqli_resource->ptr = (void *)result;
+ mysqli_resource->status = MYSQLI_STATUS_VALID;
+ MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry);
+}
+/* }}} */
+
+
+
/* {{{ proto object mysqli_stmt_get_result(object link) U
Buffer result set on client */
PHP_FUNCTION(mysqli_stmt_get_result)
Modified: trunk/php6/ext/mysqli/php_mysqli_structs.h
===================================================================
--- trunk/php6/ext/mysqli/php_mysqli_structs.h 2008-02-08 19:13:49 UTC (rev 1265)
+++ trunk/php6/ext/mysqli/php_mysqli_structs.h 2008-02-11 12:32:03 UTC (rev 1266)
@@ -101,9 +101,12 @@
char *hash_key;
zval *li_read;
php_stream *li_stream;
- zend_bool persistent;
unsigned int multi_query;
UConverter *conv;
+ zend_bool persistent;
+#if defined(HAVE_MYSQLND)
+ int async_result_fetch_type;
+#endif
} MY_MYSQL;
typedef struct {
@@ -311,12 +314,14 @@
#define MYSQLI_STORE_RESULT 0
#define MYSQLI_USE_RESULT 1
-#ifdef HAVE_MYSQLND
+#ifdef HAVE_MYSQLND
#ifdef MYSQLND_THREADED
-#define MYSQLI_BG_STORE_RESULT 101
+#define MYSQLI_BG_STORE_RESULT 4
#endif
+#define MYSQLI_ASYNC 8
#endif
+
/* for mysqli_fetch_assoc */
#define MYSQLI_ASSOC 1
#define MYSQLI_NUM 2
@@ -461,6 +466,7 @@
PHP_FUNCTION(mysqli_num_rows);
PHP_FUNCTION(mysqli_options);
PHP_FUNCTION(mysqli_ping);
+PHP_FUNCTION(mysqli_poll);
PHP_FUNCTION(mysqli_prepare);
PHP_FUNCTION(mysqli_query);
PHP_FUNCTION(mysqli_stmt_result_metadata);
@@ -469,6 +475,7 @@
PHP_FUNCTION(mysqli_real_connect);
PHP_FUNCTION(mysqli_real_query);
PHP_FUNCTION(mysqli_real_escape_string);
+PHP_FUNCTION(mysqli_reap_async_query);
PHP_FUNCTION(mysqli_rollback);
PHP_FUNCTION(mysqli_row_seek);
PHP_FUNCTION(mysqli_select_db);
| Thread |
|---|
| • PHP mysqlnd svn commit: r1266 - in trunk: mysqlnd php5/ext/mysqli php6/ext/mysqli | ahristov | 11 Feb |