static int swoole_mysql_onRead(swReactor *reactor, swEvent *event) { #if PHP_MAJOR_VERSION < 7 TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL); #endif mysql_client *client = event->socket->object; int sock = event->fd; zval *zobject = client->object; swString *buffer = client->buffer; int ret; zval **args[2]; zval *callback = NULL; zval *retval = NULL; zval *result = NULL; while(1) { ret = recv(sock, buffer->str + buffer->length, buffer->size - buffer->length, 0); if (ret < 0) { if (errno == EINTR) { continue; } else { switch (swConnection_error(errno)) { case SW_ERROR: swSysError("Read from socket[%d] failed.", event->fd); return SW_ERR; case SW_CLOSE: goto close_fd; case SW_WAIT: goto parse_response; default: return SW_ERR; } } } else if (ret == 0) { close_fd: if (client->state == SW_MYSQL_STATE_READ_END) { goto parse_response; } sw_zend_call_method_with_0_params(&zobject, swoole_mysql_class_entry_ptr, NULL, "close", &retval); if (retval) { sw_zval_ptr_dtor(&retval); } if (client->callback) { args[0] = &zobject; args[1] = &result; SW_ALLOC_INIT_ZVAL(result); ZVAL_BOOL(result, 0); callback = client->callback; if (sw_call_user_function_ex(EG(function_table), NULL, callback, &retval, 2, args, 0, NULL TSRMLS_CC) != SUCCESS) { swoole_php_fatal_error(E_WARNING, "swoole_async_mysql callback[2] handler error."); } if (result) { sw_zval_ptr_dtor(&result); } sw_zval_ptr_dtor(&callback); client->callback = NULL; client->state = SW_MYSQL_STATE_QUERY; if (retval) { sw_zval_ptr_dtor(&retval); } } return SW_OK; } else { buffer->length += ret; //recv again if (buffer->length == buffer->size) { if (swString_extend(buffer, buffer->size * 2) < 0) { swoole_php_fatal_error(E_ERROR, "malloc failed."); reactor->del(SwooleG.main_reactor, event->fd); } continue; } parse_response: if (mysql_response(client) < 0) { return SW_OK; } //remove from eventloop reactor->del(reactor, event->fd); zend_update_property_long(swoole_mysql_class_entry_ptr, zobject, ZEND_STRL("affected_rows"), client->response.affected_rows TSRMLS_CC); zend_update_property_long(swoole_mysql_class_entry_ptr, zobject, ZEND_STRL("insert_id"), client->response.insert_id TSRMLS_CC); client->state = SW_MYSQL_STATE_QUERY; args[0] = &zobject; //OK if (client->response.response_type == 0) { SW_ALLOC_INIT_ZVAL(result); ZVAL_BOOL(result, 1); } //ERROR else if (client->response.response_type == 255) { SW_ALLOC_INIT_ZVAL(result); ZVAL_BOOL(result, 0); zend_update_property_string(swoole_mysql_class_entry_ptr, zobject, ZEND_STRL("error"), client->response.server_msg TSRMLS_CC); zend_update_property_long(swoole_mysql_class_entry_ptr, zobject, ZEND_STRL("errno"), client->response.error_code TSRMLS_CC); } //ResultSet else { result = client->response.result_array; } args[1] = &result; callback = client->callback; if (sw_call_user_function_ex(EG(function_table), NULL, callback, &retval, 2, args, 0, NULL TSRMLS_CC) != SUCCESS) { swoole_php_fatal_error(E_WARNING, "swoole_async_mysql callback[2] handler error."); reactor->del(SwooleG.main_reactor, event->fd); } /* free memory */ if (retval) { sw_zval_ptr_dtor(&retval); } if (result) { sw_zval_ptr_dtor(&result); #if PHP_MAJOR_VERSION > 5 efree(result); #endif } //free callback object sw_zval_ptr_dtor(&callback); //clear buffer swString_clear(client->buffer); if (client->response.columns) { efree(client->response.columns); } if (client->object) { sw_zval_ptr_dtor(&client->object); } #if PHP_MAJOR_VERSION > 5 if (client->response.result_array) { efree(client->response.result_array); } #endif bzero(&client->response, sizeof(client->response)); return SW_OK; } } return SW_OK; }
static swVal* swoole_call_php_func(const char *name, int length) { #if PHP_MAJOR_VERSION < 7 TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL); #endif int i; zval **args[SW_PHP_FUNCTION_MAX_ARG]; zval *zval_array[SW_PHP_FUNCTION_MAX_ARG]; #if PHP_MAJOR_VERSION >= 7 zval _zval_array[SW_PHP_FUNCTION_MAX_ARG]; #endif zval *arg; uint32_t offset = 0; swVal *val; void *params = SwooleG.call_php_func_args->str; for (i = 0; i < SwooleG.call_php_func_argc; i++) { #if PHP_MAJOR_VERSION >= 7 zval_array[i] = &_zval_array[i]; #else SW_ALLOC_INIT_ZVAL(zval_array[i]); #endif arg = zval_array[i]; val = params + offset; if (swVal_to_zval(val, arg) < 0) { return NULL; } args[i] = &zval_array[i]; offset += sizeof(swVal) + val->length; } zval *func_name; zval *retval = NULL; SW_MAKE_STD_ZVAL(func_name); SW_ZVAL_STRING(func_name, name, 1); if (sw_call_user_function_ex(EG(function_table), NULL, func_name, &retval, SwooleG.call_php_func_argc, args, 0, NULL TSRMLS_CC) == FAILURE) { swoole_php_fatal_error(E_WARNING, "swoole_server: onPipeMessage handler error"); return NULL; } if (EG(exception)) { zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } //clear input buffer swArgs_clear(); for (i = 0; i < SwooleG.call_php_func_argc; i++) { sw_zval_ptr_dtor(&zval_array[i]); } //return value if (!retval) { return NULL; } swVal *val_c = NULL; switch(Z_TYPE_P(retval)) { #if PHP_MAJOR_VERSION < 7 case IS_BOOL: val_c = sw_malloc(sizeof(swVal) + 1); swVal_bool(val_c, Z_BVAL_P(retval)); break; #else case IS_TRUE: val_c = sw_malloc(sizeof(swVal) + 1); swVal_bool(val_c, 1); break; case IS_FALSE: val_c = sw_malloc(sizeof(swVal) + 1); swVal_bool(val_c, 0); break; #endif case IS_STRING: val_c = sw_malloc(sizeof(swVal) + Z_STRLEN_P(retval) + 1); swVal_string(val_c, Z_STRVAL_P(retval) , Z_STRLEN_P(retval)); break; case IS_LONG: val_c = sw_malloc(sizeof(swVal) + sizeof(long)); swVal_long(val_c, Z_LVAL_P(retval)); break; case IS_DOUBLE: val_c = sw_malloc(sizeof(swVal) + sizeof(double)); swVal_double(val_c, Z_DVAL_P(retval)); break; case IS_NULL: return NULL; default: swWarn("unknown type."); break; } sw_zval_ptr_dtor(&retval); return val_c; }