List:Commits« Previous MessageNext Message »
From:ahristov Date:February 11 2008 1:32pm
Subject:PHP mysqlnd svn commit: r1266 - in trunk: mysqlnd php5/ext/mysqli php6/ext/mysqli
View as plain text  
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/mysqliahristov11 Feb