Back to index

php5  5.3.10
ibase_events.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Ard Biesheuvel <a.k.biesheuvel@its.tudelft.nl>              |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: ibase_events.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024 
00025 #include "php.h"
00026 
00027 #if HAVE_IBASE
00028 
00029 #include "php_interbase.h"
00030 #include "php_ibase_includes.h"
00031 
00032 static int le_event;
00033 
00034 static void _php_ibase_event_free(char *event_buf, char *result_buf) /* {{{ */
00035 {
00036        isc_free(event_buf);
00037        isc_free(result_buf);
00038 }
00039 /* }}} */
00040 
00041 void _php_ibase_free_event(ibase_event *event TSRMLS_DC) /* {{{ */
00042 {
00043        unsigned short i;
00044 
00045        event->state = DEAD;
00046 
00047        if (event->link != NULL) {
00048               ibase_event **node;
00049 
00050               if (event->link->handle != NULL &&
00051                             isc_cancel_events(IB_STATUS, &event->link->handle, &event->event_id)) {
00052                      _php_ibase_error(TSRMLS_C);
00053               }
00054 
00055               /* delete this event from the link struct */
00056               for (node = &event->link->event_head; *node != event; node = &(*node)->event_next);
00057               *node = event->event_next;
00058        }
00059 
00060        if (event->callback) {
00061               zval_dtor(event->callback);
00062               FREE_ZVAL(event->callback);
00063               event->callback = NULL;
00064 
00065               _php_ibase_event_free(event->event_buffer,event->result_buffer);
00066 
00067               for (i = 0; i < event->event_count; ++i) {
00068                      efree(event->events[i]);
00069               }
00070               efree(event->events);
00071        }
00072 }
00073 /* }}} */
00074 
00075 static void _php_ibase_free_event_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
00076 {
00077        ibase_event *e = (ibase_event *) rsrc->ptr;
00078 
00079        _php_ibase_free_event(e TSRMLS_CC);
00080 
00081        efree(e);
00082 }
00083 /* }}} */
00084 
00085 void php_ibase_events_minit(INIT_FUNC_ARGS) /* {{{ */
00086 {
00087        le_event = zend_register_list_destructors_ex(_php_ibase_free_event_rsrc, NULL, 
00088            "interbase event", module_number);
00089 }
00090 /* }}} */
00091 
00092 static void _php_ibase_event_block(ibase_db_link *ib_link, unsigned short count, /* {{{ */
00093        char **events, unsigned short *l, char **event_buf, char **result_buf)
00094 {
00095        ISC_STATUS dummy_result[20];
00096        unsigned long dummy_count[15];
00097 
00108        *l = (unsigned short) isc_event_block(event_buf, result_buf, count, events[0],
00109               events[1], events[2], events[3], events[4], events[5], events[6], events[7],
00110               events[8], events[9], events[10], events[11], events[12], events[13], events[14]);
00111 
00120        isc_wait_for_event(dummy_result, &ib_link->handle, *l, *event_buf, *result_buf);
00121        isc_event_counts(dummy_count, *l, *event_buf, *result_buf);
00122 }
00123 /* }}} */
00124 
00125 /* {{{ proto string ibase_wait_event([resource link_identifier,] string event [, string event [, ...]])
00126    Waits for any one of the passed Interbase events to be posted by the database, and returns its name */
00127 PHP_FUNCTION(ibase_wait_event)
00128 {
00129        zval ***args;
00130        ibase_db_link *ib_link;
00131        int num_args;
00132        char *event_buffer, *result_buffer, *events[15];
00133        unsigned short i = 0, event_count = 0, buffer_size;
00134        unsigned long occurred_event[15];
00135 
00136        RESET_ERRMSG;
00137 
00138        /* no more than 15 events */
00139        if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 16) {
00140               WRONG_PARAM_COUNT;
00141        }
00142 
00143        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &num_args) == FAILURE) {
00144               return;
00145        }
00146 
00147        if (Z_TYPE_PP(args[0]) == IS_RESOURCE) {
00148               if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link, ibase_db_link *, args[0], -1, "InterBase link", le_link, le_plink)) {
00149                      efree(args);
00150                      RETURN_FALSE;
00151               }
00152               i = 1;
00153        } else {
00154               if (ZEND_NUM_ARGS() > 15) {
00155                      efree(args);
00156                      WRONG_PARAM_COUNT;
00157               }
00158               if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link, ibase_db_link *, NULL, IBG(default_link), "InterBase link", le_link, le_plink)) {
00159                      efree(args);
00160                      RETURN_FALSE;
00161               }
00162        }
00163 
00164        for (; i < ZEND_NUM_ARGS(); ++i) {
00165               convert_to_string_ex(args[i]);
00166               events[event_count++] = Z_STRVAL_PP(args[i]);
00167        }
00168 
00169        /* fills the required data structure with information about the events */
00170        _php_ibase_event_block(ib_link, event_count, events, &buffer_size, &event_buffer, &result_buffer);
00171 
00172        /* now block until an event occurs */
00173        if (isc_wait_for_event(IB_STATUS, &ib_link->handle, buffer_size, event_buffer, result_buffer)) {
00174               _php_ibase_error(TSRMLS_C);
00175               _php_ibase_event_free(event_buffer,result_buffer);
00176               efree(args);
00177               RETURN_FALSE;
00178        }
00179 
00180        /* find out which event occurred */
00181        isc_event_counts(occurred_event, buffer_size, event_buffer, result_buffer);
00182        for (i = 0; i < event_count; ++i) {
00183               if (occurred_event[i]) {
00184                      char *result = estrdup(events[i]);
00185                      _php_ibase_event_free(event_buffer,result_buffer);
00186                      efree(args);
00187                      RETURN_STRING(result,0);
00188               }
00189        }
00190 
00191        /* If we reach this line, isc_wait_for_event() did return, but we don't know
00192           which event fired. */
00193        _php_ibase_event_free(event_buffer,result_buffer);
00194        efree(args);
00195        RETURN_FALSE;
00196 }
00197 /* }}} */
00198 
00199 static isc_callback _php_ibase_callback(ibase_event *event, /* {{{ */
00200        unsigned short buffer_size, char *result_buf)
00201 {
00202        /* this function is called asynchronously by the Interbase client library. */
00203        TSRMLS_FETCH_FROM_CTX(event->thread_ctx);
00204 
00210        switch (event->state) {
00211               unsigned short i;
00212               unsigned long occurred_event[15];
00213               zval event_name, link_id, return_value, *args[2];
00214 
00215               default: /* == DEAD */
00216                      break;
00217               case ACTIVE:
00218                      args[0] = &event_name;
00219                      args[1] = &link_id;
00220 
00221                      /* copy the updated results into the result buffer */
00222                      memcpy(event->result_buffer, result_buf, buffer_size);
00223 
00224                      INIT_ZVAL(event_name);
00225                      INIT_ZVAL(link_id);
00226                      ZVAL_RESOURCE(&link_id, event->link_res_id);
00227 
00228                      /* find out which event occurred */
00229                      isc_event_counts(occurred_event, buffer_size, event->event_buffer, event->result_buffer);
00230                      for (i = 0; i < event->event_count; ++i) {
00231                             if (occurred_event[i]) {
00232                                    ZVAL_STRING(&event_name,event->events[i],0);
00233                                    break;
00234                             }
00235                      }
00236 
00237                      /* call the callback provided by the user */
00238                      if (SUCCESS != call_user_function(EG(function_table), NULL,
00239                                    event->callback, &return_value, 2, args TSRMLS_CC)) {
00240                             _php_ibase_module_error("Error calling callback %s" TSRMLS_CC, Z_STRVAL_P(event->callback));
00241                             break;
00242                      }
00243 
00244                      if (Z_TYPE(return_value) == IS_BOOL && !Z_BVAL(return_value)) {
00245                             event->state = DEAD;
00246                             break;
00247                      }
00248               case NEW:
00249                      /* re-register the event */
00250                      if (isc_que_events(IB_STATUS, &event->link->handle, &event->event_id, buffer_size,
00251                             event->event_buffer,(isc_callback)_php_ibase_callback, (void *)event)) {
00252 
00253                             _php_ibase_error(TSRMLS_C);
00254                      }
00255                      event->state = ACTIVE;
00256        }
00257        return 0;
00258 }
00259 /* }}} */
00260 
00261 /* {{{ proto resource ibase_set_event_handler([resource link_identifier,] callback handler, string event [, string event [, ...]])
00262    Register the callback for handling each of the named events */
00263 PHP_FUNCTION(ibase_set_event_handler)
00264 {
00270        char *cb_name;
00271        zval ***args, **cb_arg;
00272        ibase_db_link *ib_link;
00273        ibase_event *event;
00274        unsigned short i = 1, buffer_size;
00275        int link_res_id, num_args;
00276 
00277        RESET_ERRMSG;
00278        
00279        /* Minimum and maximum number of arguments allowed */
00280        if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 17) {
00281               WRONG_PARAM_COUNT;
00282        }
00283 
00284        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &num_args) == FAILURE) {
00285               return;
00286        }
00287 
00288        /* get a working link */
00289        if (Z_TYPE_PP(args[0]) != IS_STRING) {
00290               /* resource, callback, event_1 [, ... event_15]
00291                * No more than 15 events
00292                */
00293               if (ZEND_NUM_ARGS() < 3 || ZEND_NUM_ARGS() > 17) {
00294                      efree(args);
00295                      WRONG_PARAM_COUNT;
00296               }
00297 
00298               cb_arg = args[1];
00299               i = 2;
00300 
00301               if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link, ibase_db_link *, args[0], -1, "InterBase link", le_link, le_plink)) {
00302                      efree(args);
00303                      RETURN_FALSE;
00304               }
00305 
00306               convert_to_long_ex(args[0]);
00307               link_res_id = Z_LVAL_PP(args[0]);
00308 
00309        } else {
00310               /* callback, event_1 [, ... event_15] 
00311                * No more than 15 events
00312                */
00313               if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 16) {
00314                      efree(args);
00315                      WRONG_PARAM_COUNT;
00316               }
00317 
00318               cb_arg = args[0];
00319 
00320               if (!ZEND_FETCH_RESOURCE2_NO_RETURN(ib_link, ibase_db_link *, NULL, IBG(default_link), "InterBase link", le_link, le_plink)) {
00321                      efree(args);
00322                      RETURN_FALSE;
00323               }
00324               link_res_id = IBG(default_link);
00325        }
00326 
00327        /* get the callback */
00328        if (!zend_is_callable(*cb_arg, 0, &cb_name TSRMLS_CC)) {
00329               _php_ibase_module_error("Callback argument %s is not a callable function" TSRMLS_CC, cb_name);
00330               efree(cb_name);
00331               efree(args);
00332               RETURN_FALSE;
00333        }
00334        efree(cb_name);
00335 
00336        /* allocate the event resource */
00337        event = (ibase_event *) safe_emalloc(sizeof(ibase_event), 1, 0);
00338        TSRMLS_SET_CTX(event->thread_ctx);
00339        event->link_res_id = link_res_id;
00340        event->link = ib_link;
00341        event->event_count = 0;
00342        event->state = NEW;
00343        event->events = (char **) safe_emalloc(sizeof(char *),ZEND_NUM_ARGS()-i,0);
00344 
00345        ALLOC_ZVAL(event->callback);
00346        *event->callback = **cb_arg;
00347        INIT_PZVAL(event->callback);
00348        zval_copy_ctor(event->callback);
00349 
00350        for (; i < ZEND_NUM_ARGS(); ++i) {
00351               convert_to_string_ex(args[i]);
00352               event->events[event->event_count++] = estrdup(Z_STRVAL_PP(args[i]));
00353        }
00354 
00355        /* fills the required data structure with information about the events */
00356        _php_ibase_event_block(ib_link, event->event_count, event->events,
00357               &buffer_size, &event->event_buffer, &event->result_buffer);
00358 
00359        /* now register the events with the Interbase API */
00360        if (isc_que_events(IB_STATUS, &ib_link->handle, &event->event_id, buffer_size,
00361               event->event_buffer,(isc_callback)_php_ibase_callback, (void *)event)) {
00362 
00363               _php_ibase_error(TSRMLS_C);
00364               efree(event);
00365               efree(args);
00366               RETURN_FALSE;
00367        }
00368 
00369        event->event_next = ib_link->event_head;
00370        ib_link->event_head = event;
00371 
00372        ZEND_REGISTER_RESOURCE(return_value, event, le_event);
00373        zend_list_addref(Z_LVAL_P(return_value));
00374        efree(args);
00375 }
00376 /* }}} */
00377 
00378 /* {{{ proto bool ibase_free_event_handler(resource event)
00379    Frees the event handler set by ibase_set_event_handler() */
00380 PHP_FUNCTION(ibase_free_event_handler)
00381 {
00382        zval *event_arg;
00383 
00384        RESET_ERRMSG;
00385 
00386        if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &event_arg)) {
00387               ibase_event *event;
00388 
00389               ZEND_FETCH_RESOURCE(event, ibase_event *, &event_arg, -1, "Interbase event", le_event);
00390 
00391               event->state = DEAD;
00392 
00393               zend_list_delete(Z_LVAL_P(event_arg));
00394               RETURN_TRUE;
00395        } else {
00396               RETURN_FALSE;
00397        }
00398 }
00399 /* }}} */
00400 
00401 #endif /* HAVE_IBASE */
00402 
00403 /*
00404  * Local variables:
00405  * tab-width: 4
00406  * c-basic-offset: 4
00407  * End:
00408  * vim600: sw=4 ts=4 fdm=marker
00409  * vim<600: sw=4 ts=4
00410  */