abies           Thu Aug 14 20:06:07 2003 EDT

  Modified files:              
    /php-src/ext/interbase      php_interbase.h interbase.c 
  Log:
  Added ibase_set_event_handler()
  
  
Index: php-src/ext/interbase/php_interbase.h
diff -u php-src/ext/interbase/php_interbase.h:1.48 
php-src/ext/interbase/php_interbase.h:1.49
--- php-src/ext/interbase/php_interbase.h:1.48  Thu Aug 14 06:55:02 2003
+++ php-src/ext/interbase/php_interbase.h       Thu Aug 14 20:06:07 2003
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: php_interbase.h,v 1.48 2003/08/14 10:55:02 abies Exp $ */
+/* $Id: php_interbase.h,v 1.49 2003/08/15 00:06:07 abies Exp $ */
 
 #ifndef PHP_INTERBASE_H
 #define PHP_INTERBASE_H
@@ -91,6 +91,7 @@
 PHP_FUNCTION(ibase_errcode);
 
 PHP_FUNCTION(ibase_wait_event);
+PHP_FUNCTION(ibase_set_event_handler);
 
 #define IBASE_MSGSIZE 256
 #define MAX_ERRMSG (IBASE_MSGSIZE*2)
@@ -170,6 +171,17 @@
        unsigned char has_more_rows;
        char statement_type;
 } ibase_result;
+
+typedef struct {
+       int link_res_id;
+       ibase_db_link *link;
+       ISC_LONG event_id;
+       unsigned short event_count;
+       char **events;
+       char *event_buffer, *result_buffer;
+       zval *callback;
+       void **thread_ctx;
+} ibase_event;
 
 typedef struct _php_ibase_varchar {
        short var_len;
Index: php-src/ext/interbase/interbase.c
diff -u php-src/ext/interbase/interbase.c:1.140 php-src/ext/interbase/interbase.c:1.141
--- php-src/ext/interbase/interbase.c:1.140     Thu Aug 14 06:55:02 2003
+++ php-src/ext/interbase/interbase.c   Thu Aug 14 20:06:07 2003
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: interbase.c,v 1.140 2003/08/14 10:55:02 abies Exp $ */
+/* $Id: interbase.c,v 1.141 2003/08/15 00:06:07 abies Exp $ */
 
 /*
        Changes:
@@ -136,6 +136,7 @@
        PHP_FE(ibase_delete_user, NULL)
 #endif
        PHP_FE(ibase_wait_event, NULL)
+       PHP_FE(ibase_set_event_handler, NULL)
        {NULL, NULL, NULL}
 };
 
@@ -164,7 +165,7 @@
 #endif
 
 /* True globals, no need for thread safety */
-static int le_blob, le_link, le_plink, le_result, le_query, le_trans;
+static int le_blob, le_link, le_plink, le_result, le_query, le_trans, le_event;
 
 ZEND_DECLARE_MODULE_GLOBALS(ibase)
 
@@ -584,6 +585,34 @@
 }
 /* }}} */
 
+/* {{{ _php_ibase_event_free() */
+static void _php_ibase_event_free(char *event_buf, char *result_buf)
+{
+       isc_free(event_buf);
+       isc_free(result_buf);
+}
+/* }}} */
+
+/* {{{ _php_ibase_free_event */
+static void _php_ibase_free_event(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+       ibase_event *event = (ibase_event *) rsrc->ptr;
+       
+       IBDEBUG("Cleaning up event resource");
+
+       zval_dtor(event->callback);
+       event->callback = NULL;
+       
+       if (event->link->handle != NULL) {
+               if (isc_cancel_events(IB_STATUS, &event->link->handle, 
&event->event_id)) {
+                       _php_ibase_error(TSRMLS_C);
+               }
+       }
+       _php_ibase_event_free(event->event_buffer,event->result_buffer);
+}
+               
+/* }}} */
+
 /* {{{ startup, shutdown and info functions */
 PHP_INI_BEGIN()
        STD_PHP_INI_BOOLEAN("ibase.allow_persistent", "1", PHP_INI_SYSTEM, 
OnUpdateLong, allow_persistent, zend_ibase_globals, ibase_globals)
@@ -617,6 +646,7 @@
        le_link = zend_register_list_destructors_ex(_php_ibase_close_link, NULL, 
"interbase link", module_number);
        le_plink = zend_register_list_destructors_ex(php_ibase_commit_link_rsrc, 
_php_ibase_close_plink, "interbase link persistent", module_number);
        le_trans = zend_register_list_destructors_ex(_php_ibase_free_trans, NULL, 
"interbase transaction", module_number);
+       le_event = zend_register_list_destructors_ex(_php_ibase_free_event, NULL, 
"interbase event", module_number);
 
        REGISTER_LONG_CONSTANT("IBASE_DEFAULT", PHP_IBASE_DEFAULT, CONST_PERSISTENT);
        REGISTER_LONG_CONSTANT("IBASE_TEXT", PHP_IBASE_TEXT, CONST_PERSISTENT);
@@ -695,7 +725,7 @@
 
        php_info_print_table_start();
        php_info_print_table_row(2, "Interbase Support", "enabled");
-       php_info_print_table_row(2, "Revision", "$Revision: 1.140 $");
+       php_info_print_table_row(2, "Revision", "$Revision: 1.141 $");
 #ifdef COMPILE_DL_INTERBASE
        php_info_print_table_row(2, "Dynamic Module", "Yes");
 #endif
@@ -1910,7 +1940,7 @@
 {
        ibase_trans *trans = NULL;
        int res_id = 0;
-       ISC_STATUS result;
+       ISC_STATUS result = 0;
 
        RESET_ERRMSG;
 
@@ -3829,14 +3859,6 @@
 }
 /* }}} */
 
-/* {{{ _php_ibase_event_free() */
-static void _php_ibase_event_free(char *event_buf, char *result_buf)
-{
-       isc_free(event_buf);
-       isc_free(result_buf);
-}
-/* }}} */
-
 /* {{{ proto string ibase_wait_event([resource link,] string event [, string event [, 
...]])
    Waits for any one of the passed Interbase events to be posted by the database, and 
returns its name */
 PHP_FUNCTION(ibase_wait_event)
@@ -3865,12 +3887,15 @@
                ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, args[0], -1, "InterBase 
link", le_link, le_plink);
                i = 1;
 
-       } else if (ZEND_NUM_ARGS() > 15) {
-               efree(args);
-               WRONG_PARAM_COUNT;
-       }                               
+       } else {
+
+               if (ZEND_NUM_ARGS() > 15) {
+                       efree(args);
+                       WRONG_PARAM_COUNT;
+               }
 
-       ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, NULL, IBG(default_link), 
"InterBase link", le_link, le_plink);
+               ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, NULL, 
IBG(default_link), "InterBase link", le_link, le_plink);
+       }                               
                
        for (; i < ZEND_NUM_ARGS(); ++i) {
                convert_to_string_ex(args[i]);
@@ -3907,6 +3932,164 @@
 }
 /* }}} */
 
+/* {{{ _php_ibase_callback() */
+static isc_callback _php_ibase_callback(ibase_event *event, unsigned short 
buffer_size, char *result_buf)
+{
+       /**
+        * The callback function is called when the event is first registered and when 
the event
+        * is cancelled. I consider this is a bug. By clearing event->callback, we 
make sure 
+        * nothing happens if no event was actually posted.
+        */
+       if (event->callback != NULL) {
+
+               unsigned short i;
+               ISC_STATUS occurred_event[15];
+               zval event_name, link_id, return_value, *args[2] = { &event_name, 
&link_id };
+
+               /* this function is called asynchronously by the Interbase client 
library. */
+               TSRMLS_FETCH_FROM_CTX(event->thread_ctx);
+       
+               /* copy the updated results into the result buffer */
+               memcpy(event->result_buffer, result_buf, buffer_size);
+               
+               INIT_ZVAL(event_name);
+               INIT_ZVAL(link_id);
+               ZVAL_RESOURCE(&link_id, event->link_res_id);
+
+               /* find out which event occurred */
+               isc_event_counts(occurred_event, buffer_size, event->event_buffer, 
event->result_buffer);
+               for (i = 0; i < event->event_count; ++i) {
+                       if (occurred_event[i]) {
+                               ZVAL_STRING(&event_name,event->events[i],0);
+                               break;
+                       }
+               }       
+
+               Z_TYPE(return_value) = IS_BOOL;
+               Z_BVAL(return_value) = 1;
+
+               /* call the callback provided by the user */
+               if (SUCCESS != call_user_function(EG(function_table), NULL, 
event->callback, &return_value, 2, args TSRMLS_CC)) {
+                       _php_ibase_module_error("Error calling callback %s", 
Z_STRVAL_P(event->callback));
+                       return 0;
+               }
+
+               if (! Z_BVAL(return_value)) {
+                       return 0;
+               }                       
+       }
+               
+       /* re-register the event */
+       if (isc_que_events(IB_STATUS, &event->link->handle, &event->event_id, 
buffer_size, 
+               event->event_buffer,(isc_callback)_php_ibase_callback, (void *)event)) 
{
+
+               _php_ibase_error(TSRMLS_C);
+       }
+       return 0;
+}
+/* }}} */
+
+/* {{{ proto resource ibase_set_event_handler([resource link,] callback handler, 
string event [, string event [, ...]])
+   Register the callback for handling each of the named events */
+PHP_FUNCTION(ibase_set_event_handler)
+{
+       /**
+        * The callback passed to this function should take an event name (string) and 
a 
+        * link resource id (int) as arguments. The value returned from the function 
is 
+        * used to determine if the event handler should remain set.
+        */
+
+       zval ***args, **cb_arg;
+       ibase_db_link *ib_link;
+       ibase_event *event;
+       char *callback_name;
+       unsigned short i = 1, buffer_size;
+       int link_res_id;
+               
+       RESET_ERRMSG;
+
+       /* no more than 15 events */
+       if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 17) {
+               WRONG_PARAM_COUNT;
+       }
+
+       args = (zval ***) safe_emalloc(sizeof(zval **), ZEND_NUM_ARGS(), 0);
+       if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
+               efree(args);
+               RETURN_FALSE;
+       }
+
+       /* get a working link */
+       if (Z_TYPE_PP(args[0]) == IS_RESOURCE) {
+
+               ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, args[0], -1, "InterBase 
link", le_link, le_plink);
+               i = 2;
+
+               convert_to_long_ex(args[0]);
+               link_res_id = Z_LVAL_PP(args[0]);
+               cb_arg = args[1];
+
+       } else {
+
+               if (ZEND_NUM_ARGS() > 16) {
+                       efree(args);
+                       WRONG_PARAM_COUNT;
+               }
+
+               ZEND_FETCH_RESOURCE2(ib_link, ibase_db_link *, NULL, 
IBG(default_link), "InterBase link", le_link, le_plink);
+               link_res_id = IBG(default_link);
+               cb_arg = args[0];
+       }                               
+               
+       /* get the callback */
+       if (!zend_is_callable(*args[i-1], 0, &callback_name)) {
+               _php_ibase_module_error("Callback argument %s is not a callable 
function", callback_name);
+               efree(callback_name);
+               efree(args);
+               RETURN_FALSE;
+       }
+       efree(callback_name);
+               
+       /* allocate the event resource */
+       event = (ibase_event *) safe_emalloc(sizeof(ibase_event), 1, 0);
+       TSRMLS_SET_CTX(event->thread_ctx);
+       event->link_res_id = link_res_id;
+       event->link = ib_link;
+       event->event_count = 0;
+       event->callback = NULL;
+       event->events = (char **) safe_emalloc(sizeof(char *),ZEND_NUM_ARGS()-i,0);
+               
+       for (; i < ZEND_NUM_ARGS(); ++i) {
+               convert_to_string_ex(args[i]);
+               event->events[event->event_count++] = estrdup(Z_STRVAL_PP(args[i]));
+       }
+
+       /* fills the required data structure with information about the events */
+       _php_ibase_event_block(ib_link, event->event_count, event->events, 
+               &buffer_size, &event->event_buffer, &event->result_buffer);
+               
+       /* now register the events with the Interbase API */
+       if (isc_que_events(IB_STATUS, &ib_link->handle, &event->event_id, buffer_size, 
+               event->event_buffer,(isc_callback)_php_ibase_callback, (void *)event)) 
{
+                       
+               _php_ibase_error(TSRMLS_C);
+               efree(args);
+               efree(event);
+               RETURN_FALSE;
+       }
+
+       ALLOC_ZVAL(event->callback);
+       *event->callback = **cb_arg;
+       INIT_PZVAL(event->callback);
+       zval_copy_ctor(event->callback);
+       
+       efree(args);
+
+       ZEND_REGISTER_RESOURCE(return_value, event, le_event);
+}
+   
+/* }}} */
+  
 #endif /* HAVE_IBASE */
 
 /*

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to