PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/interbase - ibase_events.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 102 145 70.3 %
Date: 2017-09-08 Functions: 8 9 88.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2017 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Ard Biesheuvel <a.k.biesheuvel@its.tudelft.nl>              |
      16             :    +----------------------------------------------------------------------+
      17             :  */
      18             : 
      19             : #ifdef HAVE_CONFIG_H
      20             : #include "config.h"
      21             : #endif
      22             : 
      23             : #include "php.h"
      24             : 
      25             : #if HAVE_IBASE
      26             : 
      27             : #include "php_interbase.h"
      28             : #include "php_ibase_includes.h"
      29             : 
      30             : static int le_event;
      31             : 
      32           5 : static void _php_ibase_event_free(char *event_buf, char *result_buf) /* {{{ */
      33             : {
      34           5 :         isc_free(event_buf);
      35           5 :         isc_free(result_buf);
      36           5 : }
      37             : /* }}} */
      38             : 
      39          10 : void _php_ibase_free_event(ibase_event *event) /* {{{ */
      40             : {
      41             :         unsigned short i;
      42             : 
      43          10 :         event->state = DEAD;
      44             : 
      45          10 :         if (event->link != NULL) {
      46             :                 ibase_event **node;
      47             : 
      48           5 :                 zend_list_delete(event->link_res);
      49          10 :                 if (event->link->handle != 0 &&
      50           5 :                                 isc_cancel_events(IB_STATUS, &event->link->handle, &event->event_id)) {
      51           0 :                         _php_ibase_error();
      52             :                 }
      53             : 
      54             :                 /* delete this event from the link struct */
      55           5 :                 for (node = &event->link->event_head; *node != event; node = &(*node)->event_next);
      56           5 :                 *node = event->event_next;
      57             :         }
      58             : 
      59          20 :         if (Z_TYPE(event->callback) != IS_UNDEF) {
      60           5 :                 zval_dtor(&event->callback);
      61           5 :                 ZVAL_UNDEF(&event->callback);
      62             : 
      63           5 :                 _php_ibase_event_free(event->event_buffer,event->result_buffer);
      64             : 
      65          10 :                 for (i = 0; i < event->event_count; ++i) {
      66           5 :                         if (event->events[i]) {
      67           5 :                                 efree(event->events[i]);
      68             :                         }
      69             :                 }
      70           5 :                 efree(event->events);
      71             :         }
      72          10 : }
      73             : /* }}} */
      74             : 
      75           5 : static void _php_ibase_free_event_rsrc(zend_resource *rsrc) /* {{{ */
      76             : {
      77           5 :         ibase_event *e = (ibase_event *) rsrc->ptr;
      78             : 
      79           5 :         _php_ibase_free_event(e);
      80             : 
      81           5 :         efree(e);
      82           5 : }
      83             : /* }}} */
      84             : 
      85       24608 : void php_ibase_events_minit(INIT_FUNC_ARGS) /* {{{ */
      86             : {
      87       24608 :         le_event = zend_register_list_destructors_ex(_php_ibase_free_event_rsrc, NULL,
      88             :             "interbase event", module_number);
      89       24608 : }
      90             : /* }}} */
      91             : 
      92           5 : static void _php_ibase_event_block(ibase_db_link *ib_link, unsigned short count, /* {{{ */
      93             :         char **events, unsigned short *l, char **event_buf, char **result_buf)
      94             : {
      95             :         ISC_STATUS dummy_result[20];
      96             :         ISC_ULONG dummy_count[15];
      97             : 
      98             :         /**
      99             :          * Unfortunately, there's no clean and portable way in C to pass arguments to
     100             :          * a variadic function if you don't know the number of arguments at compile time.
     101             :          * (And even if there were a way, the Interbase API doesn't provide a version of
     102             :          * this function that takes a va_list as an argument)
     103             :          *
     104             :          * In this case, the number of arguments is limited to 18 by the underlying API,
     105             :          * so we can work around it.
     106             :          */
     107             : 
     108          70 :         *l = (unsigned short) isc_event_block(event_buf, result_buf, count, events[0],
     109          35 :                 events[1], events[2], events[3], events[4], events[5], events[6], events[7],
     110          35 :                 events[8], events[9], events[10], events[11], events[12], events[13], events[14]);
     111             : 
     112             :         /**
     113             :          * Currently, this is the only way to correctly initialize an event buffer.
     114             :          * This is clearly something that should be fixed, cause the semantics of
     115             :          * isc_wait_for_event() indicate that it blocks until an event occurs.
     116             :          * If the Firebird people ever fix this, these lines should be removed,
     117             :          * otherwise, events will have to fire twice before ibase_wait_event() returns.
     118             :          */
     119             : 
     120           5 :         isc_wait_for_event(dummy_result, &ib_link->handle, *l, *event_buf, *result_buf);
     121           5 :         isc_event_counts(dummy_count, *l, *event_buf, *result_buf);
     122           5 : }
     123             : /* }}} */
     124             : 
     125             : /* {{{ proto string ibase_wait_event([resource link_identifier,] string event [, string event [, ...]])
     126             :    Waits for any one of the passed Interbase events to be posted by the database, and returns its name */
     127           0 : PHP_FUNCTION(ibase_wait_event)
     128             : {
     129             :         zval *args;
     130             :         ibase_db_link *ib_link;
     131             :         int num_args;
     132             :         char *event_buffer, *result_buffer, *events[15];
     133           0 :         unsigned short i = 0, event_count = 0, buffer_size;
     134             :         ISC_ULONG occurred_event[15];
     135             : 
     136           0 :         RESET_ERRMSG;
     137             : 
     138             :         /* no more than 15 events */
     139           0 :         if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 16) {
     140           0 :                 WRONG_PARAM_COUNT;
     141             :         }
     142             : 
     143           0 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &num_args) == FAILURE) {
     144           0 :                 return;
     145             :         }
     146             : 
     147           0 :         if (Z_TYPE(args[0]) == IS_RESOURCE) {
     148           0 :                 if ((ib_link = (ibase_db_link *)zend_fetch_resource2_ex(&args[0], "InterBase link", le_link, le_plink)) == NULL) {
     149           0 :                         RETURN_FALSE;
     150             :                 }
     151           0 :                 i = 1;
     152             :         } else {
     153           0 :                 if (ZEND_NUM_ARGS() > 15) {
     154           0 :                         WRONG_PARAM_COUNT;
     155             :                 }
     156           0 :                 if ((ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), "InterBase link", le_link, le_plink)) == NULL) {
     157           0 :                         RETURN_FALSE;
     158             :                 }
     159             :         }
     160             : 
     161           0 :         for (; i < ZEND_NUM_ARGS(); ++i) {
     162           0 :                 convert_to_string_ex(&args[i]);
     163           0 :                 events[event_count++] = Z_STRVAL(args[i]);
     164             :         }
     165             : 
     166             :         /* fills the required data structure with information about the events */
     167           0 :         _php_ibase_event_block(ib_link, event_count, events, &buffer_size, &event_buffer, &result_buffer);
     168             : 
     169             :         /* now block until an event occurs */
     170           0 :         if (isc_wait_for_event(IB_STATUS, &ib_link->handle, buffer_size, event_buffer, result_buffer)) {
     171           0 :                 _php_ibase_error();
     172           0 :                 _php_ibase_event_free(event_buffer,result_buffer);
     173           0 :                 RETURN_FALSE;
     174             :         }
     175             : 
     176             :         /* find out which event occurred */
     177           0 :         isc_event_counts(occurred_event, buffer_size, event_buffer, result_buffer);
     178           0 :         for (i = 0; i < event_count; ++i) {
     179           0 :                 if (occurred_event[i]) {
     180           0 :                         zend_string *result = zend_string_init(events[i], strlen(events[i]), 0);
     181           0 :                         _php_ibase_event_free(event_buffer,result_buffer);
     182           0 :                         RETURN_STR(result);
     183             :                 }
     184             :         }
     185             : 
     186             :         /* If we reach this line, isc_wait_for_event() did return, but we don't know
     187             :            which event fired. */
     188           0 :         _php_ibase_event_free(event_buffer,result_buffer);
     189           0 :         RETURN_FALSE;
     190             : }
     191             : /* }}} */
     192             : 
     193             : #if FB_API_VER >= 20
     194             : #define PHP_ISC_CALLBACK ISC_EVENT_CALLBACK
     195          10 : static ISC_EVENT_CALLBACK _php_ibase_callback(ibase_event *event, /* {{{ */
     196             :         ISC_USHORT buffer_size, ISC_UCHAR *result_buf)
     197             : #else
     198             : #define PHP_ISC_CALLBACK isc_callback
     199             : static isc_callback  _php_ibase_callback(ibase_event *event, /* {{{ */
     200             :         unsigned short buffer_size, char *result_buf)
     201             : #endif
     202             : {
     203             :         /* this function is called asynchronously by the Interbase client library. */
     204             :         TSRMLS_FETCH_FROM_CTX(event->thread_ctx);
     205             : 
     206             :         /**
     207             :          * The callback function is called when the event is first registered and when the event
     208             :          * is cancelled. I consider this is a bug. By clearing event->callback first and setting
     209             :          * it to -1 later, we make sure nothing happens if no event was actually posted.
     210             :          */
     211          10 :         switch (event->state) {
     212             :                 unsigned short i;
     213             :                 ISC_ULONG occurred_event[15];
     214             :                 zval return_value, args[2];
     215             : 
     216             :                 default: /* == DEAD */
     217           4 :                         break;
     218             :                 case ACTIVE:
     219             :                         /* copy the updated results into the result buffer */
     220           5 :                         memcpy(event->result_buffer, result_buf, buffer_size);
     221             : 
     222           5 :                         ZVAL_RES(&args[1], event->link_res);
     223             : 
     224             :                         /* find out which event occurred */
     225           5 :                         isc_event_counts(occurred_event, buffer_size, event->event_buffer, event->result_buffer);
     226           5 :                         for (i = 0; i < event->event_count; ++i) {
     227           5 :                                 if (occurred_event[i]) {
     228          10 :                                         ZVAL_STRING(&args[0], event->events[i]);
     229             :                                         //efree(event->events[i]);
     230           5 :                                         break;
     231             :                                 }
     232             :                         }
     233             : 
     234             :                         /* call the callback provided by the user */
     235           5 :                         if (SUCCESS != call_user_function(EG(function_table), NULL,
     236             :                                         &event->callback, &return_value, 2, args)) {
     237           0 :                                 _php_ibase_module_error("Error calling callback %s", Z_STRVAL(event->callback));
     238           0 :                                 break;
     239             :                         }
     240             : 
     241           5 :                         if (Z_TYPE(return_value) == IS_FALSE) {
     242           1 :                                 event->state = DEAD;
     243           1 :                                 break;
     244             :                         }
     245             :                 case NEW:
     246             :                         /* re-register the event */
     247          10 :                         if (isc_que_events(IB_STATUS, &event->link->handle, &event->event_id, buffer_size,
     248           5 :                                 event->event_buffer,(PHP_ISC_CALLBACK)_php_ibase_callback, (void *)event)) {
     249             : 
     250           0 :                                 _php_ibase_error();
     251             :                         }
     252           5 :                         event->state = ACTIVE;
     253             :         }
     254          10 :         return 0;
     255             : }
     256             : /* }}} */
     257             : 
     258             : /* {{{ proto resource ibase_set_event_handler([resource link_identifier,] callback handler, string event [, string event [, ...]])
     259             :    Register the callback for handling each of the named events */
     260          12 : PHP_FUNCTION(ibase_set_event_handler)
     261             : {
     262             :         /**
     263             :          * The callback passed to this function should take an event name (string) and a
     264             :          * link resource id (int) as arguments. The value returned from the function is
     265             :          * used to determine if the event handler should remain set.
     266             :          */
     267             :         zval *args, *cb_arg;
     268             :         ibase_db_link *ib_link;
     269             :         ibase_event *event;
     270          12 :         unsigned short i = 1, buffer_size;
     271             :         int num_args;
     272             :         zend_resource *link_res;
     273             : 
     274          12 :         RESET_ERRMSG;
     275             : 
     276             :         /* Minimum and maximum number of arguments allowed */
     277          12 :         if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 17) {
     278           1 :                 WRONG_PARAM_COUNT;
     279             :         }
     280             : 
     281          11 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &num_args) == FAILURE) {
     282           0 :                 return;
     283             :         }
     284             : 
     285             :         /* get a working link */
     286          22 :         if (Z_TYPE(args[0]) != IS_STRING) {
     287             :                 /* resource, callback, event_1 [, ... event_15]
     288             :                  * No more than 15 events
     289             :                  */
     290           6 :                 if (ZEND_NUM_ARGS() < 3 || ZEND_NUM_ARGS() > 17) {
     291           0 :                         WRONG_PARAM_COUNT;
     292             :                 }
     293             : 
     294           6 :                 cb_arg = &args[1];
     295           6 :                 i = 2;
     296             : 
     297           6 :                 if ((ib_link = (ibase_db_link *)zend_fetch_resource2_ex(&args[0], "InterBase link", le_link, le_plink)) == NULL) {
     298           2 :                         RETURN_FALSE;
     299             :                 }
     300             : 
     301           4 :                 link_res = Z_RES(args[0]);
     302             : 
     303             :         } else {
     304             :                 /* callback, event_1 [, ... event_15]
     305             :                  * No more than 15 events
     306             :                  */
     307           5 :                 if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 16) {
     308           0 :                         WRONG_PARAM_COUNT;
     309             :                 }
     310             : 
     311           5 :                 cb_arg = &args[0];
     312             : 
     313           5 :                 if ((ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), "InterBase link", le_link, le_plink)) == NULL) {
     314           0 :                         RETURN_FALSE;
     315             :                 }
     316           5 :                 link_res = IBG(default_link);
     317             :         }
     318             : 
     319             :         /* get the callback */
     320           9 :         if (!zend_is_callable(cb_arg, 0, NULL)) {
     321           4 :                 zend_string *cb_name = zend_get_callable_name(cb_arg);
     322           4 :                 _php_ibase_module_error("Callback argument %s is not a callable function", ZSTR_VAL(cb_name));
     323             :                 zend_string_release(cb_name);
     324           4 :                 RETURN_FALSE;
     325             :         }
     326             : 
     327             :         /* allocate the event resource */
     328           5 :         event = (ibase_event *) safe_emalloc(sizeof(ibase_event), 1, 0);
     329             :         TSRMLS_SET_CTX(event->thread_ctx);
     330           5 :         event->link_res = link_res;
     331           5 :         GC_REFCOUNT(link_res)++;
     332           5 :         event->link = ib_link;
     333           5 :         event->event_count = 0;
     334           5 :         event->state = NEW;
     335           5 :         event->events = (char **) safe_emalloc(sizeof(char *), 15, 0);
     336             : 
     337           5 :         ZVAL_DUP(&event->callback, cb_arg);
     338             : 
     339          74 :         for (; i < 15; ++i) {
     340          69 :                 if (i < ZEND_NUM_ARGS()) {
     341          12 :                         convert_to_string_ex(&args[i]);
     342           5 :                         event->events[event->event_count++] = estrdup(Z_STRVAL(args[i]));
     343             :                 } else {
     344          64 :                         event->events[i] = NULL;
     345             :                 }
     346             :         }
     347             : 
     348             :         /* fills the required data structure with information about the events */
     349           5 :         _php_ibase_event_block(ib_link, event->event_count, event->events,
     350             :                 &buffer_size, &event->event_buffer, &event->result_buffer);
     351             : 
     352             :         /* now register the events with the Interbase API */
     353          10 :         if (isc_que_events(IB_STATUS, &ib_link->handle, &event->event_id, buffer_size,
     354           5 :                 event->event_buffer,(PHP_ISC_CALLBACK)_php_ibase_callback, (void *)event)) {
     355             : 
     356           0 :                 _php_ibase_error();
     357           0 :                 efree(event);
     358           0 :                 RETURN_FALSE;
     359             :         }
     360             : 
     361           5 :         event->event_next = ib_link->event_head;
     362           5 :         ib_link->event_head = event;
     363             : 
     364           5 :         RETVAL_RES(zend_register_resource(event, le_event));
     365           5 :         Z_TRY_ADDREF_P(return_value);
     366             : }
     367             : /* }}} */
     368             : 
     369             : /* {{{ proto bool ibase_free_event_handler(resource event)
     370             :    Frees the event handler set by ibase_set_event_handler() */
     371           1 : PHP_FUNCTION(ibase_free_event_handler)
     372             : {
     373             :         zval *event_arg;
     374             : 
     375           1 :         RESET_ERRMSG;
     376             : 
     377           1 :         if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "r", &event_arg)) {
     378             :                 ibase_event *event;
     379             : 
     380           1 :                 event = (ibase_event *)zend_fetch_resource_ex(event_arg, "Interbase event", le_event);
     381             : 
     382           1 :                 event->state = DEAD;
     383             : 
     384           1 :                 zend_list_delete(Z_RES_P(event_arg));
     385           1 :                 RETURN_TRUE;
     386             :         } else {
     387           0 :                 RETURN_FALSE;
     388             :         }
     389             : }
     390             : /* }}} */
     391             : 
     392             : #endif /* HAVE_IBASE */
     393             : 
     394             : /*
     395             :  * Local variables:
     396             :  * tab-width: 4
     397             :  * c-basic-offset: 4
     398             :  * End:
     399             :  * vim600: sw=4 ts=4 fdm=marker
     400             :  * vim<600: sw=4 ts=4
     401             :  */

Generated by: LCOV version 1.10

Generated at Sat, 09 Sep 2017 03:10:37 +0000 (14 days ago)

Copyright © 2005-2017 The PHP Group
All rights reserved.