wez Mon Oct 21 18:54:37 2002 EDT
Modified files:
/php4/ext/standard file.c
/php4/main php_streams.h streams.c
Log:
Refine stream_select() to work with streams that have data in their read
buffers.
When selecting for read, the streams are examined; if any of them have
pending read data, no actual select(2) call is performed; instead the
streams with buffered data are returned; just like a regular select
call.
Prevent erroneous warning in stream_select when obtaining the fd.
Index: php4/ext/standard/file.c
diff -u php4/ext/standard/file.c:1.273 php4/ext/standard/file.c:1.274
--- php4/ext/standard/file.c:1.273 Sat Oct 19 09:11:48 2002
+++ php4/ext/standard/file.c Mon Oct 21 18:54:37 2002
@@ -21,7 +21,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: file.c,v 1.273 2002/10/19 13:11:48 wez Exp $ */
+/* $Id: file.c,v 1.274 2002/10/21 22:54:37 wez Exp $ */
/* Synced with php 3.0 revision 1.218 1999-06-16 [ssb] */
@@ -650,8 +650,12 @@
if (stream == NULL)
continue;
- /* get the fd */
- if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD,
(void*)&this_fd, 1)) {
+ /* 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(stream, PHP_STREAM_AS_FD |
+PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1)) {
FD_SET(this_fd, fds);
if (this_fd > *max_fd) {
*max_fd = this_fd;
@@ -666,7 +670,7 @@
zval **elem, **dest_elem;
php_stream *stream;
HashTable *new_hash;
- int this_fd;
+ int this_fd, ret = 0;
if (Z_TYPE_P(stream_array) != IS_ARRAY)
return 0;
@@ -682,12 +686,18 @@
if (stream == NULL)
continue;
- /* get the fd */
- if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD,
(void*)&this_fd, 1)) {
+ /* 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(stream, PHP_STREAM_AS_FD |
+PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1)) {
if (FD_ISSET(this_fd, fds)) {
zend_hash_next_index_insert(new_hash, (void *)elem,
sizeof(zval *), (void **)&dest_elem);
if (dest_elem)
zval_add_ref(dest_elem);
+ ret++;
+ continue;
}
}
}
@@ -699,7 +709,58 @@
zend_hash_internal_pointer_reset(new_hash);
Z_ARRVAL_P(stream_array) = new_hash;
- return 1;
+ return ret;
+}
+
+static int stream_array_emulate_read_fd_set(zval *stream_array TSRMLS_DC)
+{
+ zval **elem, **dest_elem;
+ php_stream *stream;
+ HashTable *new_hash;
+ int ret = 0;
+
+ if (Z_TYPE_P(stream_array) != IS_ARRAY)
+ return 0;
+
+ ALLOC_HASHTABLE(new_hash);
+ zend_hash_init(new_hash, 0, NULL, ZVAL_PTR_DTOR, 0);
+
+ for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream_array));
+ zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem)
+== SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(stream_array))) {
+
+ php_stream_from_zval_no_verify(stream, elem);
+ if (stream == NULL)
+ continue;
+
+ if ((stream->writepos - stream->readpos) > 0) {
+ /* allow readable non-descriptor based streams to participate
+in stream_select.
+ * Non-descriptor streams will only "work" if they have
+previously buffered the
+ * data. Not ideal, but better than nothing.
+ * This branch of code also allows blocking streams with
+buffered data to
+ * operate correctly in stream_select.
+ * */
+ zend_hash_next_index_insert(new_hash, (void *)elem,
+sizeof(zval *), (void **)&dest_elem);
+ if (dest_elem)
+ zval_add_ref(dest_elem);
+ ret++;
+ continue;
+ }
+ }
+
+ if (ret > 0) {
+ /* destroy old array and add new one */
+ zend_hash_destroy(Z_ARRVAL_P(stream_array));
+ efree(Z_ARRVAL_P(stream_array));
+
+ zend_hash_internal_pointer_reset(new_hash);
+ Z_ARRVAL_P(stream_array) = new_hash;
+ } else {
+ zend_hash_destroy(new_hash);
+ FREE_HASHTABLE(new_hash);
+ }
+
+ return ret;
}
/* }}} */
@@ -738,6 +799,17 @@
tv_p = &tv;
}
+ /* slight hack to support buffered data; if there is data sitting in the
+ * read buffer of any of the streams in the read array, let's pretend
+ * that we selected, but return only the readable sockets */
+ if (r_array != NULL) {
+
+ retval = stream_array_emulate_read_fd_set(r_array TSRMLS_CC);
+ if (retval > 0) {
+ RETURN_LONG(retval);
+ }
+ }
+
retval = select(max_fd+1, &rfds, &wfds, &efds, tv_p);
if (retval == -1) {
Index: php4/main/php_streams.h
diff -u php4/main/php_streams.h:1.56 php4/main/php_streams.h:1.57
--- php4/main/php_streams.h:1.56 Sat Oct 19 09:11:48 2002
+++ php4/main/php_streams.h Mon Oct 21 18:54:37 2002
@@ -455,7 +455,8 @@
/* try really, really hard to make sure the cast happens (socketpair) */
#define PHP_STREAM_CAST_TRY_HARD 0x80000000
#define PHP_STREAM_CAST_RELEASE 0x40000000 /* stream becomes
invalid on success */
-#define PHP_STREAM_CAST_MASK (PHP_STREAM_CAST_TRY_HARD |
PHP_STREAM_CAST_RELEASE)
+#define PHP_STREAM_CAST_INTERNAL 0x20000000 /* stream cast for internal
+use */
+#define PHP_STREAM_CAST_MASK (PHP_STREAM_CAST_TRY_HARD |
+PHP_STREAM_CAST_RELEASE | PHP_STREAM_CAST_INTERNAL)
PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show_err
TSRMLS_DC);
/* use this to check if a stream can be cast into another form */
#define php_stream_can_cast(stream, as) _php_stream_cast((stream), (as), NULL,
0 TSRMLS_CC)
Index: php4/main/streams.c
diff -u php4/main/streams.c:1.114 php4/main/streams.c:1.115
--- php4/main/streams.c:1.114 Sun Oct 20 21:33:31 2002
+++ php4/main/streams.c Mon Oct 21 18:54:37 2002
@@ -20,7 +20,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: streams.c,v 1.114 2002/10/21 01:33:31 moriyoshi Exp $ */
+/* $Id: streams.c,v 1.115 2002/10/21 22:54:37 wez Exp $ */
#define _GNU_SOURCE
#include "php.h"
@@ -1820,7 +1820,9 @@
exit_success:
- if ((stream->writepos - stream->readpos) > 0 && stream->fclose_stdiocast !=
PHP_STREAM_FCLOSE_FOPENCOOKIE) {
+ if ((stream->writepos - stream->readpos) > 0 &&
+ stream->fclose_stdiocast != PHP_STREAM_FCLOSE_FOPENCOOKIE &&
+ (flags & PHP_STREAM_CAST_INTERNAL) == 0) {
/* the data we have buffered will be lost to the third party library
that
* will be accessing the stream. Emit a warning so that the end-user
will
* know that they should try something else */
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php