From c55e855fdd5c78d5cea74202e7c770edf7a7df24 Mon Sep 17 00:00:00 2001 From: Harald Radi Date: Sun, 9 Jun 2002 14:51:41 +0000 Subject: [PATCH] - using stas' abstraction now - layer can add individual ini settings now - classentries for the loaded rpc object are created dynamically now class hirarchy looks like: rpc<-[layer]<-[object] (e.g. rpc<-com<-adodb), thus the whole class tree is reflected into php - added user-functions to mark an object as a singleton and as poolable #rest of the linuxtag work --- ext/rpc/handler.h | 77 +++++----- ext/rpc/php_rpc.h | 6 +- ext/rpc/rpc.c | 343 +++++++++++++++++++------------------------- ext/rpc/rpc.h | 21 +-- ext/rpc/rpc_proxy.c | 6 +- 5 files changed, 204 insertions(+), 249 deletions(-) diff --git a/ext/rpc/handler.h b/ext/rpc/handler.h index 04ec2c2f09..81d4fbad8a 100644 --- a/ext/rpc/handler.h +++ b/ext/rpc/handler.h @@ -2,16 +2,18 @@ #define HANDLER_H #include "php.h" +#include "php_ini.h" #define RPC_HANDLER(layer) {#layer, layer##_handler_init, &layer##_object_handlers, \ &layer##_class_entry, layer##_function_entry, \ - layer##_method_entry} + layer##_method_entry, layer##_ini_entry} #define RPC_DECLARE_HANDLER(layer) void layer##_handler_init(); \ rpc_object_handlers layer##_object_handlers; \ zend_class_entry layer##_class_entry; \ function_entry layer##_function_entry[]; \ - function_entry layer##_method_entry[]; + function_entry layer##_method_entry[]; \ + zend_ini_entry layer##_ini_entry[]; #define RPC_INIT_FUNCTION(layer) void layer##_handler_init() @@ -20,12 +22,16 @@ #define RPC_REGISTER_HANDLERS_END() }; +#define RPC_INI_START(layer) zend_ini_entry layer##_ini_entry[] = { +#define RPC_INI_END() { 0, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, NULL } }; -#define RPC_FUNCTION_ENTRY_START(layer) function_entry layer##_function_entry[] = { \ - ZEND_FALIAS(layer##_load, rpc_load, NULL) \ - ZEND_FALIAS(layer##_call, rpc_call, NULL) \ - ZEND_FALIAS(layer##_get, rpc_get, NULL) \ - ZEND_FALIAS(layer##_set, rpc_set, NULL) +#define RPC_FUNCTION_ENTRY_START(layer) function_entry layer##_function_entry[] = { \ + ZEND_FALIAS(layer##_load, rpc_load, NULL) \ + ZEND_FALIAS(layer##_call, rpc_call, NULL) \ + ZEND_FALIAS(layer##_get, rpc_get, NULL) \ + ZEND_FALIAS(layer##_set, rpc_get, NULL) \ + ZEND_FALIAS(layer##_singleton, rpc_singleton, NULL) \ + ZEND_FALIAS(layer##_poolable, rpc_poolable, NULL) #define RPC_FUNCTION_ENTRY_END() {NULL, NULL, NULL} \ }; @@ -35,73 +41,69 @@ #define RPC_METHOD_ENTRY_END() {NULL, NULL, NULL} \ }; -#define POOL TRUE -#define DONT_POOL FALSE - #define DONT_HASH 0 #define HASH_AS_INT 1 #define HASH_AS_STRING 2 #define HASH_WITH_SIGNATURE 4 -#define HASH_AS_INT_WITH_SIGNATURE (HASH_AS_INT + HASH_WITH_SIGNATURE) -#define HASH_AS_STRING_WITH_SIGNATURE (HASH_AS_STRING + HASH_WITH_SIGNATURE) +#define HASH_AS_INT_WITH_SIGNATURE (HASH_AS_INT & HASH_WITH_SIGNATURE) +#define HASH_AS_STRING_WITH_SIGNATURE (HASH_AS_STRING & HASH_WITH_SIGNATURE) #define CLASS 0 #define METHOD 1 #define PROPERTY 2 +/* string */ +typedef struct _rpc_string { + char *str; + zend_uint len; +} rpc_string; + /* rpc handler that have to be implemented by a * specific rpc layer */ typedef struct _rpc_object_handlers { - const zend_bool pool_instances; + const zend_bool poolable; const zend_uint hash_type; - int (*rpc_hash)(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int num_args, char *arg_types, int type); - int (*rpc_ctor)(char *class_name, zend_uint class_name_len, void **data, int num_args, zval **args[]); + int (*rpc_hash)(rpc_string name, rpc_string *hash, int num_args, char *arg_types, int type); + int (*rpc_name)(rpc_string hash, rpc_string *name, int type); + int (*rpc_ctor)(rpc_string class_name, void **data, int num_args, zval **args[]); int (*rpc_dtor)(void **data); - int (*rpc_call)(char *method_name, zend_uint method_name_len, void **data, zval **return_value, int num_args, zval **args[]); - int (*rpc_get)(char *property_name, zend_uint property_name_len, zval *return_value, void **data); - int (*rpc_set)(char *property_name, zend_uint property_name_len, zval *value, void **data); + int (*rpc_call)(rpc_string method_name, void **data, zval **return_value, int num_args, zval **args[]); + int (*rpc_get)(rpc_string property_name, zval *return_value, void **data); + int (*rpc_set)(rpc_string property_name, zval *value, void **data); int (*rpc_compare)(void **data1, void **data2); - int (*rpc_get_classname)(char **class_name, zend_uint *class_name_length, void **data); - int (*rpc_has_property)(char *property_name, zend_uint property_name_length, void **data); - int (*rpc_unset_property)(char *property_name, zend_uint property_name_length, void **data); + int (*rpc_has_property)(rpc_string property_name, void **data); + int (*rpc_unset_property)(rpc_string property_name, void **data); int (*rpc_get_properties)(HashTable **properties, void **data); } rpc_object_handlers; /* handler entry */ typedef struct _rpc_handler_entry { - char *name; + char *name; void (*rpc_handler_init)(); - rpc_object_handlers *handlers; + rpc_object_handlers *handlers; zend_class_entry *ce; function_entry *functions; function_entry *methods; + zend_ini_entry *ini; } rpc_handler_entry; -/* string */ -typedef struct _rpc_string { - char *str; - zend_uint len; -} rpc_string; - /* class/method/function hash */ typedef struct _rpc_class_hash { rpc_string name; /* must be first entry */ TsHashTable methods; TsHashTable properties; + zend_class_entry *ce; } rpc_class_hash; /* internal data */ typedef struct _rpc_internal { - char *class_name; - zend_uint class_name_len; + zend_bool poolable; + zend_bool singleton; zend_class_entry *ce; - rpc_object_handlers **handlers; - void *data; - zend_uint refcount; - zend_uint clonecount; - zend_bool pool_instances; + rpc_object_handlers **handlers; + void *data; rpc_class_hash *hash; TsHashTable function_table; MUTEX_T mx_handler; @@ -109,8 +111,7 @@ typedef struct _rpc_internal { /* proxy data */ typedef struct _rpc_proxy { - zend_uint refcount; - zend_uint clonecount; + zend_uint dummy; } rpc_proxy; diff --git a/ext/rpc/php_rpc.h b/ext/rpc/php_rpc.h index be95b20940..32074ee70d 100644 --- a/ext/rpc/php_rpc.h +++ b/ext/rpc/php_rpc.h @@ -18,15 +18,19 @@ extern zend_module_entry rpc_module_entry; ZEND_MINIT_FUNCTION(rpc); ZEND_MSHUTDOWN_FUNCTION(rpc); +ZEND_RINIT_FUNCTION(rpc); +ZEND_RSHUTDOWN_FUNCTION(rpc); ZEND_MINFO_FUNCTION(rpc); ZEND_FUNCTION(rpc_load); ZEND_FUNCTION(rpc_call); ZEND_FUNCTION(rpc_set); ZEND_FUNCTION(rpc_get); +ZEND_FUNCTION(rpc_singleton); +ZEND_FUNCTION(rpc_poolable); ZEND_BEGIN_MODULE_GLOBALS(rpc) - int dummy; + TsHashTable *proxy; ZEND_END_MODULE_GLOBALS(rpc) #ifdef ZTS diff --git a/ext/rpc/rpc.c b/ext/rpc/rpc.c index d0fc90a49c..04a5f1f02c 100644 --- a/ext/rpc/rpc.c +++ b/ext/rpc/rpc.c @@ -13,18 +13,14 @@ ZEND_DECLARE_MODULE_GLOBALS(rpc) static void rpc_globals_ctor(zend_rpc_globals * TSRMLS_DC); -static void rpc_instance_dtor(void *); -static void rpc_proxy_dtor(void *pDest); static void rpc_class_dtor(void *); static void rpc_string_dtor(void *); static void rpc_export_functions(char *, zend_class_entry *, function_entry[] TSRMLS_DC); -static zend_object_value rpc_create_object(zend_class_entry * TSRMLS_DC); + +static zend_object_value rpc_objects_new(zend_class_entry * TSRMLS_DC); +static void rpc_objects_delete(void *object, zend_object_handle handle TSRMLS_DC); /* object handler */ -static void rpc_add_ref(zval * TSRMLS_DC); -static void rpc_del_ref(zval * TSRMLS_DC); -static void rpc_delete(zval * TSRMLS_DC); -static zend_object_value rpc_clone(zval * TSRMLS_DC); static zval* rpc_read(zval *, zval *, int TSRMLS_DC); static void rpc_write(zval *, zval *, zval * TSRMLS_DC); static zval** rpc_get_property(zval *, zval * TSRMLS_DC); @@ -35,8 +31,7 @@ static void rpc_unset_property(zval *, zval * TSRMLS_DC); static HashTable* rpc_get_properties(zval * TSRMLS_DC); static union _zend_function* rpc_get_method(zval *, char *, int TSRMLS_DC); static union _zend_function* rpc_get_constructor(zval * TSRMLS_DC); -static zend_class_entry** rpc_get_class_entry(zval *object TSRMLS_DC); -static int rpc_get_classname(zval *, char **, zend_uint *, int TSRMLS_DC); +static zend_class_entry* rpc_get_class_entry(zval *object TSRMLS_DC); static int rpc_compare(zval *, zval * TSRMLS_DC); /**/ @@ -48,16 +43,16 @@ static void rpc_internal_set(rpc_internal *, char *, zend_uint, zval *); extern zend_object_handlers rpc_proxy_handlers; static zend_object_handlers rpc_handlers = { - rpc_add_ref, - rpc_del_ref, - rpc_delete, - rpc_clone, + ZEND_OBJECTS_STORE_HANDLERS, + rpc_read, rpc_write, rpc_get_property, NULL, rpc_get, rpc_set, + NULL, + NULL, rpc_has_property, rpc_unset_property, rpc_get_properties, @@ -65,7 +60,7 @@ static zend_object_handlers rpc_handlers = { NULL, rpc_get_constructor, rpc_get_class_entry, - rpc_get_classname, + NULL, rpc_compare }; @@ -92,9 +87,9 @@ zend_module_entry rpc_module_entry = { }; /* }}} */ +zend_class_entry rpc_class_entry; + static HashTable *handlers; -static TsHashTable *instance; -static TsHashTable *proxy; static TsHashTable *classes; static zend_llist *classes_list; @@ -102,12 +97,8 @@ static zend_llist *classes_list; ZEND_GET_MODULE(rpc); #endif -/* {{{ PHP_INI - */ -PHP_INI_BEGIN() -/* TODO: add module specific ini settings here */ -PHP_INI_END() -/* }}} */ +ZEND_INI_BEGIN() +ZEND_INI_END() static void rpc_globals_ctor(zend_rpc_globals *rpc_globals TSRMLS_DC) { @@ -117,15 +108,17 @@ static void rpc_globals_ctor(zend_rpc_globals *rpc_globals TSRMLS_DC) */ ZEND_MINIT_FUNCTION(rpc) { + zend_class_entry *rpc_entry; + + /* rpc base class entry */ + INIT_CLASS_ENTRY(rpc_class_entry, "rpc", NULL); + rpc_entry = zend_register_internal_class(&rpc_class_entry TSRMLS_CC); + handlers = (HashTable *) pemalloc(sizeof(HashTable), TRUE); - instance = (TsHashTable *) pemalloc(sizeof(TsHashTable), TRUE); - proxy = (TsHashTable *) pemalloc(sizeof(TsHashTable), TRUE); classes = (TsHashTable *) pemalloc(sizeof(TsHashTable), TRUE); classes_list = (zend_llist *) pemalloc(sizeof(zend_llist), TRUE); zend_hash_init(handlers, 0, NULL, NULL, TRUE); - zend_ts_hash_init(instance, 0, NULL, rpc_instance_dtor, TRUE); - zend_ts_hash_init(proxy, 0, NULL, rpc_proxy_dtor, TRUE); zend_ts_hash_init(classes, 0, NULL, NULL, TRUE); zend_llist_init(classes_list, sizeof(rpc_class_hash **), rpc_class_dtor, TRUE); @@ -133,21 +126,19 @@ ZEND_MINIT_FUNCTION(rpc) HANDLER.rpc_handler_init(); /* create a class entry for every rpc handler */ - INIT_OVERLOADED_CLASS_ENTRY((*(HANDLER.ce)), - HANDLER.name, - HANDLER.methods, - NULL, - NULL, - NULL); + INIT_CLASS_ENTRY((*(HANDLER.ce)), + HANDLER.name, + HANDLER.methods); - HANDLER.ce->create_object = rpc_create_object; + HANDLER.ce->create_object = rpc_objects_new; /* load all available rpc handler into a hash */ zend_hash_add(handlers, HANDLER.name, strlen(HANDLER.name) + 1, &(HANDLER.handlers), sizeof(rpc_object_handlers *), NULL); /* register classes and functions */ - zend_register_internal_class(HANDLER.ce TSRMLS_CC); + zend_register_internal_class_ex(HANDLER.ce, rpc_entry, NULL TSRMLS_CC); zend_register_functions(HANDLER.functions, NULL, MODULE_PERSISTENT TSRMLS_CC); + zend_register_ini_entries(HANDLER.ini, module_number TSRMLS_CC); } ZEND_INIT_MODULE_GLOBALS(rpc, rpc_globals_ctor, NULL); @@ -162,16 +153,12 @@ ZEND_MINIT_FUNCTION(rpc) ZEND_MSHUTDOWN_FUNCTION(rpc) { /* destroy instances first */ - zend_ts_hash_destroy(instance); - zend_ts_hash_destroy(proxy); zend_ts_hash_destroy(classes); zend_llist_destroy(classes_list); zend_hash_destroy(handlers); pefree(handlers, TRUE); - pefree(instance, TRUE); - pefree(proxy, TRUE); pefree(classes, TRUE); UNREGISTER_INI_ENTRIES(); @@ -191,30 +178,6 @@ ZEND_MINFO_FUNCTION(rpc) } /* }}} */ -static void rpc_instance_dtor(void *pDest) -{ - rpc_internal **intern; - - intern = (rpc_internal **) pDest; - - (*(*intern)->handlers)->rpc_dtor(&((*intern)->data)); - - tsrm_mutex_free((*intern)->function_table.mx_reader); - tsrm_mutex_free((*intern)->function_table.mx_writer); - tsrm_mutex_free((*intern)->mx_handler); - - pefree(*intern, TRUE); -} - -static void rpc_proxy_dtor(void *pDest) -{ - rpc_proxy **proxy_intern; - - proxy_intern = (rpc_proxy **) pDest; - - pefree(*proxy_intern, TRUE); -} - static void rpc_class_dtor(void *pDest) { rpc_class_hash **hash; @@ -238,7 +201,7 @@ static void rpc_string_dtor(void *pDest) pefree(*string, TRUE); } -static zend_object_value rpc_create_object(zend_class_entry *class_type TSRMLS_DC) +static zend_object_value rpc_objects_new(zend_class_entry *class_type TSRMLS_DC) { zend_object_value *zov; rpc_internal *intern; @@ -250,13 +213,10 @@ static zend_object_value rpc_create_object(zend_class_entry *class_type TSRMLS_D /* set up the internal representation of our rpc instance */ intern = (rpc_internal *) pemalloc(sizeof(rpc_internal), TRUE); - intern->class_name = NULL; - intern->class_name_len = 0; intern->ce = class_type; - intern->refcount = 1; - intern->clonecount = 1; intern->data = NULL; - intern->pool_instances = 0; + intern->singleton = FALSE; + intern->poolable = FALSE; intern->function_table.hash = intern->ce->function_table; intern->function_table.reader = 0; intern->function_table.mx_reader = tsrm_mutex_alloc(); @@ -267,15 +227,7 @@ static zend_object_value rpc_create_object(zend_class_entry *class_type TSRMLS_D /* TODO: exception */ } - /* store the instance in a hash and set the key as handle, thus - * we can find it later easily - */ - tsrm_mutex_lock(instance->mx_writer); - { - zov->handle = zend_hash_next_free_element(&(instance->hash)); - zend_ts_hash_next_index_insert(instance, &intern, sizeof(rpc_internal *), NULL); - } - tsrm_mutex_unlock(instance->mx_writer); + zov->handle = zend_objects_store_put(intern, rpc_objects_delete, NULL TSRMLS_CC); return *zov; } @@ -295,69 +247,26 @@ static zend_object_value rpc_create_proxy(TSRMLS_D) /* store the instance in a hash and set the key as handle, thus * we can find it later easily */ - tsrm_mutex_lock(proxy->mx_writer); +/* tsrm_mutex_lock(proxy->mx_writer); { zov->handle = zend_hash_next_free_element(&(proxy->hash)); zend_ts_hash_next_index_insert(proxy, &proxy_intern, sizeof(rpc_proxy *), NULL); } tsrm_mutex_unlock(proxy->mx_writer); - +*/ return *zov; } /* object handler */ -static void rpc_add_ref(zval *object TSRMLS_DC) -{ - GET_INTERNAL(intern); - RPC_ADDREF(intern); -} - -static void rpc_del_ref(zval *object TSRMLS_DC) +static void rpc_objects_delete(void *object, zend_object_handle handle TSRMLS_DC) { - rpc_internal **intern; - - if (GET_INTERNAL_EX(intern, object) == SUCCESS) { - if (RPC_REFCOUNT(intern) > 0) { - RPC_DELREF(intern); - } - - if (RPC_REFCOUNT(intern) == 0) { - zend_ts_hash_index_del(instance, Z_OBJ_HANDLE(*object)); - } - } -} - -static void rpc_delete(zval *object TSRMLS_DC) -{ - rpc_internal **intern; + rpc_internal *intern = (rpc_internal *) object; - if (GET_INTERNAL_EX(intern, object) == SUCCESS) { - if (RPC_CLONECOUNT(intern) > 0) { - RPC_DELCLONE(intern); - } - - if (RPC_CLONECOUNT(intern) == 0) { - zend_ts_hash_index_del(instance, Z_OBJ_HANDLE_P(object)); + if (intern->poolable) { } - } -} - -static zend_object_value rpc_clone(zval *object TSRMLS_DC) -{ - GET_INTERNAL(intern); - - /* cloning the underlaying resource is neither possible nor would it - * make sense, therfore we return the old zend_object_value and increase - * the clone count to not loose the clone when the original object gets - * deleted. - */ - RPC_ADDCLONE(intern); - - /* also increase the refcounter as a clone is just another reference */ - RPC_ADDREF(intern); - - return object->value.obj; + /* TODO: pool */ + pefree(intern, TRUE); } static zval* rpc_read(zval *object, zval *member, int type TSRMLS_DC) @@ -372,10 +281,10 @@ static zval* rpc_read(zval *object, zval *member, int type TSRMLS_DC) ZVAL_DELREF(return_value); ZVAL_NULL(return_value); - if ((*intern)->hash && Z_TYPE_P(member) == IS_LONG) { - rpc_internal_get(*intern, NULL, Z_LVAL_P(member), return_value); + if (intern->hash && Z_TYPE_P(member) == IS_LONG) { + rpc_internal_get(intern, NULL, Z_LVAL_P(member), return_value); } else if (Z_TYPE_P(member) == IS_STRING) { - rpc_internal_get(*intern, Z_STRVAL_P(member), Z_STRLEN_P(member), return_value); + rpc_internal_get(intern, Z_STRVAL_P(member), Z_STRLEN_P(member), return_value); } else { /* TODO: exception here */ } @@ -387,10 +296,10 @@ static void rpc_write(zval *object, zval *member, zval *value TSRMLS_DC) { GET_INTERNAL(intern); - if ((*intern)->hash && Z_TYPE_P(member) == IS_LONG) { - rpc_internal_set(*intern, NULL, Z_LVAL_P(member), value); + if (intern->hash && Z_TYPE_P(member) == IS_LONG) { + rpc_internal_set(intern, NULL, Z_LVAL_P(member), value); } else if (Z_TYPE_P(member) == IS_STRING) { - rpc_internal_set(*intern, Z_STRVAL_P(member), Z_STRLEN_P(member), value); + rpc_internal_set(intern, Z_STRVAL_P(member), Z_STRLEN_P(member), value); } else { /* TODO: exception here */ } @@ -403,7 +312,6 @@ static zval** rpc_get_property(zval *object, zval *member TSRMLS_DC) return_value = emalloc(sizeof(zval *)); MAKE_STD_ZVAL(*return_value); -// ZVAL_DELREF(*return_value); Z_TYPE_P(object) = IS_OBJECT; (*return_value)->value.obj = rpc_create_proxy(TSRMLS_C); @@ -448,7 +356,7 @@ static union _zend_function* rpc_get_method(zval *object, char *method, int meth zend_function *function; GET_INTERNAL(intern); - if (zend_ts_hash_find(&((*intern)->function_table), method, method_len + 1, &function) != SUCCESS) { + if (zend_ts_hash_find(&(intern->function_table), method, method_len + 1, &function) != SUCCESS) { zend_internal_function *zif; zif = (zend_internal_function *) emalloc(sizeof(zend_internal_function)); @@ -459,7 +367,7 @@ static union _zend_function* rpc_get_method(zval *object, char *method, int meth zif->type = ZEND_INTERNAL_FUNCTION; /* add new method to the method table */ - zend_ts_hash_add(&((*intern)->function_table), method, method_len + 1, zif, sizeof(zend_function), &function); + zend_ts_hash_add(&(intern->function_table), method, method_len + 1, zif, sizeof(zend_function), &function); efree(zif); } @@ -470,39 +378,31 @@ static union _zend_function* rpc_get_constructor(zval *object TSRMLS_DC) { zend_function *rpc_ctor; GET_INTERNAL(intern); - - if (zend_ts_hash_find(&((*intern)->function_table), (*intern)->ce->name, (*intern)->ce->name_length + 1, &rpc_ctor) != SUCCESS) { + + if (zend_ts_hash_find(&(intern->function_table), intern->ce->name, intern->ce->name_length + 1, &rpc_ctor) != SUCCESS) { zend_internal_function *zif; zif = (zend_internal_function *) emalloc(sizeof(zend_internal_function)); zif->type = ZEND_INTERNAL_FUNCTION; - zif->function_name = (*intern)->ce->name; - zif->scope = (*intern)->ce; + zif->function_name = intern->ce->name; + zif->scope = intern->ce; zif->arg_types = NULL; zif->handler = ZEND_FN(rpc_load); /* add new constructor to the method table */ - zend_ts_hash_add(&((*intern)->function_table), (*intern)->ce->name, (*intern)->ce->name_length + 1, zif, sizeof(zend_function), &rpc_ctor); + zend_ts_hash_add(&(intern->function_table), intern->ce->name, intern->ce->name_length + 1, zif, sizeof(zend_function), &rpc_ctor); efree(zif); } return rpc_ctor; } -static zend_class_entry** rpc_get_class_entry(zval *object TSRMLS_DC) +static zend_class_entry* rpc_get_class_entry(zval *object TSRMLS_DC) { GET_INTERNAL(intern); - return &((*intern)->ce); -} - -static int rpc_get_classname(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) -{ -// GET_INTERNAL(intern); - - /* FIXME */ - return FAILURE; + return intern->ce; } static int rpc_compare(zval *object1, zval *object2 TSRMLS_DC) @@ -518,11 +418,12 @@ ZEND_FUNCTION(rpc_load) { zval *object = getThis(); zval ***args, ***args_free; - zend_uint num_args = ZEND_NUM_ARGS(); + zend_uint num_args = ZEND_NUM_ARGS(); + zend_class_entry overloaded_class_entry; rpc_class_hash *class_hash; rpc_class_hash **class_hash_find = NULL; - rpc_internal **intern; - rpc_string hash_val; + rpc_internal *intern; + rpc_string hash_val, class_val; int retval, append = 0; char *arg_types; @@ -541,7 +442,7 @@ ZEND_FUNCTION(rpc_load) Z_TYPE_P(object) = IS_OBJECT; /* create a new object */ - object->value.obj = rpc_create_object(*ce TSRMLS_CC); + object->value.obj = rpc_objects_new(*ce TSRMLS_CC); /* now everything is set up the same way as if we were called as a constructor */ } @@ -554,22 +455,22 @@ ZEND_FUNCTION(rpc_load) GET_ARGS_EX(num_args, args, args_free, 1); /* if classname != integer */ - if ((zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 1 TSRMLS_CC, "l", &((*intern)->class_name_len)) != SUCCESS) || + if ((zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 1 TSRMLS_CC, "l", &class_val.str) != SUCCESS) || /* or we have no hash function */ - !((*(*intern)->handlers)->rpc_hash) || + !(RPC_HT(intern)->rpc_hash) || /* or integer hashing is not allowed */ - !((*(*intern)->handlers)->hash_type & HASH_AS_INT)) { + !(RPC_HT(intern)->hash_type & HASH_AS_INT)) { /* else check for string - classname */ - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 1 TSRMLS_CC, "s", &((*intern)->class_name), &((*intern)->class_name_len)) != SUCCESS) { + if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 1 TSRMLS_CC, "s", &class_val.str, &class_val.len) != SUCCESS) { /* none of the two possibilities */ /* TODO: exception */ php_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C)); } else { /* hash classname if hashing function exists */ - if ((*(*intern)->handlers)->rpc_hash) { + if (RPC_HT(intern)->rpc_hash) { - GET_CTOR_SIGNATURE(intern, hash_val, num_args, arg_types); + GET_SIGNATURE(intern, class_val.str, class_val.len, hash_val, num_args, arg_types); /* check if already hashed */ if (zend_ts_hash_find(classes, hash_val.str, hash_val.len + 1, (void **) &class_hash_find) != SUCCESS) { @@ -579,14 +480,20 @@ ZEND_FUNCTION(rpc_load) zend_ts_hash_init(&(class_hash->methods), 0, NULL, rpc_string_dtor, TRUE); zend_ts_hash_init(&(class_hash->properties), 0, NULL, rpc_string_dtor, TRUE); - /* do hashing */ - if ((*(*intern)->handlers)->rpc_hash((*intern)->class_name, (*intern)->class_name_len, &(class_hash->name.str), - &(class_hash->name.len), num_args, arg_types, CLASS) != SUCCESS) { + if (RPC_HT(intern)->rpc_hash(class_val, (rpc_string *)(class_hash), num_args, arg_types, CLASS) != SUCCESS) { /* TODO: exception */ } - /* register with non-hashed key + /* overload class entry */ + RPC_HT(intern)->rpc_name(class_val, &class_val, CLASS); + INIT_CLASS_ENTRY(overloaded_class_entry, NULL, NULL); + overloaded_class_entry.name = class_val.str; + overloaded_class_entry.name_length = class_val.len; + class_hash->ce = zend_register_internal_class_ex(&overloaded_class_entry, intern->ce, NULL TSRMLS_CC); + intern->ce = class_hash->ce; + + /* register with non-hashed key * also track all instaces in a llist for destruction later on, because there might be duplicate entries in * the hashtable and we can't determine if a pointer references to an already freed element */ @@ -598,49 +505,61 @@ ZEND_FUNCTION(rpc_load) if (class_hash->name.str) { /* register string hashcode */ zend_ts_hash_add(classes, class_hash->name.str, class_hash->name.len + 1, &class_hash, sizeof(rpc_class_hash *), NULL); - } else if (!class_hash->name.str && ((*(*intern)->handlers)->hash_type & HASH_AS_INT)) { + } else if (!class_hash->name.str && (RPC_HT(intern)->hash_type & HASH_AS_INT)) { /* register int hashcode */ zend_ts_hash_index_update(classes, class_hash->name.len, &class_hash, sizeof(rpc_class_hash *), NULL); } } else { class_hash = *class_hash_find; + intern->ce = class_hash->ce; } FREE_SIGNATURE(hash_val, arg_types); + } else { + /* overload class entry */ + INIT_CLASS_ENTRY(overloaded_class_entry, class_val.str, NULL); + intern->ce = zend_register_internal_class_ex(&overloaded_class_entry, intern->ce, NULL TSRMLS_CC); } } } else { /* integer classname (hashcode) */ - if (zend_ts_hash_index_find(classes, (*intern)->class_name_len, (void**) &class_hash_find) != SUCCESS) { + if (zend_ts_hash_index_find(classes, class_val.len, (void**) &class_hash_find) != SUCCESS) { class_hash = pemalloc(sizeof(rpc_class_hash), TRUE); /* set up the cache */ class_hash->name.str = NULL; - class_hash->name.len = (*intern)->class_name_len; + class_hash->name.len = class_val.len; zend_ts_hash_init(&(class_hash->methods), 0, NULL, rpc_string_dtor, TRUE); zend_ts_hash_init(&(class_hash->properties), 0, NULL, rpc_string_dtor, TRUE); + /* overload class entry */ + RPC_HT(intern)->rpc_name(class_val, &class_val, CLASS); + INIT_CLASS_ENTRY(overloaded_class_entry, class_val.str, NULL); + class_hash->ce = zend_register_internal_class_ex(&overloaded_class_entry, intern->ce, NULL TSRMLS_CC); + intern->ce = class_hash->ce; + /* register int hashcode, we don't know more */ zend_ts_hash_index_update(classes, class_hash->name.len, &class_hash, sizeof(rpc_class_hash *), NULL); } else { class_hash = *class_hash_find; + intern->ce = class_hash->ce; } } /* if hash function available */ - if ((*(*intern)->handlers)->rpc_hash) { + if (RPC_HT(intern)->rpc_hash) { /* assign cache structure */ - (*intern)->hash = class_hash; + intern->hash = class_hash; /* call the rpc ctor */ - retval = (*(*intern)->handlers)->rpc_ctor(class_hash->name.str, class_hash->name.len, &((*intern)->data), num_args, args); + retval = RPC_HT(intern)->rpc_ctor(*(rpc_string *)(class_hash), &(intern->data), num_args, args); } else { /* disable caching from now on */ - (*intern)->hash = NULL; + intern->hash = NULL; /* call the rpc ctor */ - retval = (*(*intern)->handlers)->rpc_ctor((*intern)->class_name, (*intern)->class_name_len, &((*intern)->data), num_args, args); + retval = RPC_HT(intern)->rpc_ctor(class_val, &(intern->data), num_args, args); } efree(args_free); @@ -654,7 +573,7 @@ ZEND_FUNCTION(rpc_call) { zval *object = getThis(); zval ***args, ***args_free; - zend_uint num_args = ZEND_NUM_ARGS(); + zend_uint num_args = ZEND_NUM_ARGS(); char *hash = NULL, *arg_types; int hash_len, retval, strip = 0; @@ -690,23 +609,23 @@ ZEND_FUNCTION(rpc_call) method_hash->str = hash; method_hash->len = hash_len; - if ((*intern)->hash) { + if (intern->hash) { /* cache method table lookups */ - if (!hash && !((*(*intern)->handlers)->hash_type & HASH_AS_INT)) { + if (!hash && !(RPC_HT(intern)->hash_type & HASH_AS_INT)) { /* TODO: exception */ } else if(hash) { /* string passed */ GET_METHOD_SIGNATURE(intern, method_hash, hash_val, num_args, arg_types); /* check if already hashed */ - if (zend_ts_hash_find(&((*intern)->hash->methods), hash_val.str, hash_val.len + 1, (void **) &method_hash_find) != SUCCESS) { - if ((*(*intern)->handlers)->rpc_hash(hash, hash_len, &(method_hash->str), &(method_hash->len), num_args, arg_types, METHOD) != SUCCESS) { + if (zend_ts_hash_find(&(intern->hash->methods), hash_val.str, hash_val.len + 1, (void **) &method_hash_find) != SUCCESS) { + if (RPC_HT(intern)->rpc_hash(*method_hash, method_hash, num_args, arg_types, METHOD) != SUCCESS) { /* TODO: exception */ } /* register with non-hashed key */ - zend_ts_hash_add(&((*intern)->hash->methods), hash_val.str, hash_val.len + 1, &method_hash, sizeof(rpc_string *), NULL); + zend_ts_hash_add(&(intern->hash->methods), hash_val.str, hash_val.len + 1, &method_hash, sizeof(rpc_string *), NULL); } else { pefree(method_hash, TRUE); method_hash = *method_hash_find; @@ -720,9 +639,9 @@ ZEND_FUNCTION(rpc_call) * considering possible thread implementations in future php versions * and srm it is better to do concurrency checks */ - tsrm_mutex_lock((*intern)->mx_handler); - retval = (*(*intern)->handlers)->rpc_call(method_hash->str, method_hash->len, &((*intern)->data), &return_value, num_args, args); - tsrm_mutex_unlock((*intern)->mx_handler); + tsrm_mutex_lock(intern->mx_handler); + retval = RPC_HT(intern)->rpc_call(*method_hash, &(intern->data), &return_value, num_args, args); + tsrm_mutex_unlock(intern->mx_handler); } efree(args_free); @@ -737,7 +656,7 @@ ZEND_FUNCTION(rpc_set) zval *object, *value; char *property = NULL; int property_len; - rpc_internal **intern; + rpc_internal *intern; /* get class entry */ GET_CLASS(ce); @@ -750,10 +669,10 @@ ZEND_FUNCTION(rpc_set) } GET_INTERNAL_EX(intern, object); - if (!property && !(*intern)->hash) { + if (!property && !intern->hash) { /* TODO: exception here */ } else { - rpc_internal_set(*intern, property, property_len, value); + rpc_internal_set(intern, property, property_len, value); } } @@ -762,7 +681,7 @@ ZEND_FUNCTION(rpc_get) zval *object; char *property = NULL; int property_len; - rpc_internal **intern; + rpc_internal *intern; /* get class entry */ GET_CLASS(ce); @@ -775,13 +694,49 @@ ZEND_FUNCTION(rpc_get) } GET_INTERNAL_EX(intern, object); - if (!property && !(*intern)->hash) { + if (!property && !intern->hash) { /* TODO: exception here */ } else { - rpc_internal_get(*intern, property, property_len, return_value); + rpc_internal_get(intern, property, property_len, return_value); } } +ZEND_FUNCTION(rpc_singleton) +{ + zval *object; + rpc_internal *intern; + /* get class entry */ + GET_CLASS(ce); + + zend_parse_parameters(1 TSRMLS_CC, "O", &object, *ce); + + GET_INTERNAL_EX(intern, object); + + if (!intern->singleton) { + intern->singleton = TRUE; + /* TODO: add to instance list */ + } +} + +ZEND_FUNCTION(rpc_poolable) +{ + zval *object; + rpc_internal *intern; + /* get class entry */ + GET_CLASS(ce); + + zend_parse_parameters(1 TSRMLS_CC, "O", &object, *ce); + + GET_INTERNAL_EX(intern, object); + + + if (RPC_HT(intern)->poolable == TRUE) { + intern->poolable = TRUE; + } +} + +/*******************/ + static void rpc_internal_get(rpc_internal *intern, char *property, zend_uint property_len, zval *return_value) { int retval; @@ -796,12 +751,12 @@ static void rpc_internal_get(rpc_internal *intern, char *property, zend_uint pro if (intern->hash) { /* cache method table lookups */ - if (!property && !((*intern->handlers)->hash_type & HASH_AS_INT)) { + if (!property && !(RPC_HT(intern)->hash_type & HASH_AS_INT)) { /* TODO: exception */ } else if(property) { /* check if already hashed */ if (zend_ts_hash_find(&(intern->hash->properties), property, property_len + 1, (void **) &property_hash_find) != SUCCESS) { - if ((*intern->handlers)->rpc_hash(property, property_len, &(property_hash->str), &(property_hash->len), 0, NULL, PROPERTY) != SUCCESS) { + if (RPC_HT(intern)->rpc_hash(*property_hash, property_hash, 0, NULL, PROPERTY) != SUCCESS) { /* TODO: exception */ } @@ -816,7 +771,7 @@ static void rpc_internal_get(rpc_internal *intern, char *property, zend_uint pro tsrm_mutex_lock(intern->mx_handler); - retval = (*intern->handlers)->rpc_get(property_hash->str, property_hash->len, return_value, intern->data); + retval = RPC_HT(intern)->rpc_get(*property_hash, return_value, intern->data); tsrm_mutex_unlock(intern->mx_handler); if (retval != SUCCESS) { @@ -827,9 +782,13 @@ static void rpc_internal_get(rpc_internal *intern, char *property, zend_uint pro static void rpc_internal_set(rpc_internal *intern, char *property, zend_uint property_len, zval *value) { int retval; + rpc_string property_name; + + property_name.str = property; + property_name.len = property_len; tsrm_mutex_lock(intern->mx_handler); - retval = (*intern->handlers)->rpc_set(property, property_len, value, intern->data); + retval = RPC_HT(intern)->rpc_set(property_name, value, intern->data); tsrm_mutex_unlock(intern->mx_handler); if (retval != SUCCESS) { diff --git a/ext/rpc/rpc.h b/ext/rpc/rpc.h index 43f6bd8ae3..092707fa13 100644 --- a/ext/rpc/rpc.h +++ b/ext/rpc/rpc.h @@ -5,12 +5,14 @@ #define HANDLER handler_entries[__handler_counter] #define HANDLER_COUNT (sizeof(handler_entries) / sizeof(rpc_handler_entry)) -#define GET_INTERNAL(intern) rpc_internal **intern; \ +#define RPC_HT(intern) (*(intern->handlers)) + +#define GET_INTERNAL(intern) rpc_internal *intern; \ if (GET_INTERNAL_EX(intern, object) != SUCCESS) { \ /* TODO: exception */ \ } -#define GET_INTERNAL_EX(intern, object) zend_ts_hash_index_find(instance, object->value.obj.handle, (void **) &intern) +#define GET_INTERNAL_EX(intern, object) (((intern = zend_object_store_get_object(object TSRMLS_CC)) == NULL) ? FAILURE : SUCCESS) #define GET_CLASS(ce) char *key; \ int key_len; \ @@ -48,16 +50,13 @@ /* TODO: exception */ \ } -#define GET_CTOR_SIGNATURE(intern, hash_val, num_args, arg_types) \ - GET_SIGNATURE(intern, (*intern)->class_name, (*intern)->class_name_len, hash_val, num_args, arg_types) - #define GET_METHOD_SIGNATURE(intern, method, hash_val, num_args, arg_types) \ GET_SIGNATURE(intern, method->str, method->len, hash_val, num_args, arg_types) #define GET_SIGNATURE(intern, name, name_len, hash_val, num_args, arg_types) \ hash_val.len = name_len; \ \ - if ((*(*intern)->handlers)->hash_type & HASH_WITH_SIGNATURE) { \ + if ((*intern->handlers)->hash_type & HASH_WITH_SIGNATURE) { \ zend_uint _signature_counter; \ \ arg_types = (char *) emalloc(sizeof(char) * (num_args + 1)); \ @@ -109,16 +108,6 @@ efree(arg_types); \ efree(hash_val.str); - - -#define RPC_REFCOUNT(intern) ((*intern)->refcount) -#define RPC_ADDREF(intern) (++RPC_REFCOUNT(intern)) -#define RPC_DELREF(intern) (--RPC_REFCOUNT(intern)) - -#define RPC_CLONECOUNT(intern) ((*intern)->clonecount) -#define RPC_ADDCLONE(intern) (++RPC_CLONECOUNT(intern)) -#define RPC_DELCLONE(intern) (--RPC_CLONECOUNT(intern)) - static int __handler_counter; #endif \ No newline at end of file diff --git a/ext/rpc/rpc_proxy.c b/ext/rpc/rpc_proxy.c index ef1cabe0ed..e36303a3fc 100644 --- a/ext/rpc/rpc_proxy.c +++ b/ext/rpc/rpc_proxy.c @@ -18,7 +18,7 @@ static void rpc_proxy_unset_property(zval *, zval * TSRMLS_DC); static HashTable* rpc_proxy_get_properties(zval * TSRMLS_DC); static union _zend_function* rpc_proxy_get_method(zval *, char *, int TSRMLS_DC); static union _zend_function* rpc_proxy_get_constructor(zval * TSRMLS_DC); -static zend_class_entry** rpc_proxy_get_class_entry(zval *object TSRMLS_DC); +static zend_class_entry* rpc_proxy_get_class_entry(zval *object TSRMLS_DC); static int rpc_proxy_get_classname(zval *, char **, zend_uint *, int TSRMLS_DC); static int rpc_proxy_compare(zval *, zval * TSRMLS_DC); /**/ @@ -34,6 +34,8 @@ zend_object_handlers rpc_proxy_handlers = { NULL, rpc_proxy_get, rpc_proxy_set, + NULL, + NULL, rpc_proxy_has_property, rpc_proxy_unset_property, rpc_proxy_get_properties, @@ -111,7 +113,7 @@ static union _zend_function* rpc_proxy_get_constructor(zval *object TSRMLS_DC) return NULL; } -static zend_class_entry** rpc_proxy_get_class_entry(zval *object TSRMLS_DC) +static zend_class_entry* rpc_proxy_get_class_entry(zval *object TSRMLS_DC) { return NULL; } -- 2.50.1