static void _php_ibase_event_block(ibase_db_link *ib_link, unsigned short count, /* {{{ */ char **events, unsigned short *l, char **event_buf, char **result_buf) { ISC_STATUS dummy_result[20]; unsigned long dummy_count[15]; /** * Unfortunately, there's no clean and portable way in C to pass arguments to * a variadic function if you don't know the number of arguments at compile time. * (And even if there were a way, the Interbase API doesn't provide a version of * this function that takes a va_list as an argument) * * In this case, the number of arguments is limited to 18 by the underlying API, * so we can work around it. */ *l = (unsigned short) isc_event_block(event_buf, result_buf, count, events[0], events[1], events[2], events[3], events[4], events[5], events[6], events[7], events[8], events[9], events[10], events[11], events[12], events[13], events[14]); /** * Currently, this is the only way to correctly initialize an event buffer. * This is clearly something that should be fixed, cause the semantics of * isc_wait_for_event() indicate that it blocks until an event occurs. * If the Firebird people ever fix this, these lines should be removed, * otherwise, events will have to fire twice before ibase_wait_event() returns. */ isc_wait_for_event(dummy_result, &ib_link->handle, *l, *event_buf, *result_buf); isc_event_counts(dummy_count, *l, *event_buf, *result_buf); }
static isc_callback _php_ibase_callback(ibase_event *event, /* {{{ */ unsigned short buffer_size, char *result_buf) { zval *res; /* this function is called asynchronously by the Interbase client library. */ TSRMLS_FETCH_FROM_CTX(event->thread_ctx); /** * 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 first and setting * it to -1 later, we make sure nothing happens if no event was actually posted. */ switch (event->state) { unsigned short i; unsigned long occurred_event[15]; zval return_value, args[2]; default: /* == DEAD */ break; case ACTIVE: /* copy the updated results into the result buffer */ memcpy(event->result_buffer, result_buf, buffer_size); res = zend_hash_index_find(&EG(regular_list), event->link_res_id); ZVAL_RES(&args[1], Z_RES_P(res)); /* 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(&args[0], event->events[i]); efree(event->events[i]); break; } } /* call the callback provided by the user */ if (SUCCESS != call_user_function(EG(function_table), NULL, &event->callback, &return_value, 2, args)) { _php_ibase_module_error("Error calling callback %s", Z_STRVAL(event->callback)); break; } if (Z_TYPE(return_value) == IS_FALSE) { event->state = DEAD; break; } case NEW: /* 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(); } event->state = ACTIVE; } return 0; }
EXPORT RM_ENTRY(rmc_event_counts) { ClearParamPool(); ISC_STATUS *stat = AllocStatusPool(); isc_event_counts((ISC_ULONG *)stat, (short)*CobolToShort(&arg_vector[1]), (ISC_UCHAR *)*(char **)arg_vector[2].a_address, (ISC_UCHAR *)*(char **)arg_vector[3].a_address); // Convert the event counts to Cobol format. ISC_UCHAR *counts = (ISC_UCHAR *)arg_vector[0].a_address; ISC_UCHAR *cend = counts + arg_vector[0].a_length; int i = 0; while ((counts < cend) && (i < 15)) { CvtIntToCobol(counts, stat[i], sizeof(ISC_ULONG)); counts += sizeof(ISC_ULONG); i++; } return (0); }
void API_ROUTINE gds__event_counts(ULONG* result_vector, SSHORT length, UCHAR* before, const UCHAR* after) { isc_event_counts(result_vector, length, before, after); }