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: 3 149 2.0 %
Date: 2014-11-22 Functions: 1 9 11.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sat, 22 Nov 2014 23:01:16 +0000 (26 hours ago)

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