added lookup caching and now make use of the new thread

safe hashtables (not in cvs right now)
This commit is contained in:
Harald Radi 2002-03-19 03:36:16 +00:00
parent 68f63a012f
commit a85ea38eac
6 changed files with 214 additions and 272 deletions

View file

@ -14,29 +14,31 @@ ZEND_DECLARE_MODULE_GLOBALS(rpc)
static int rpc_global_startup(void);
static int rpc_global_shutdown(void);
static void rpc_globals_ctor(zend_rpc_globals *rpc_globals TSRMLS_DC);
static void rpc_instance_dtor(void *pDest);
static void rpc_export_functions(char *name, zend_class_entry *ce, function_entry functions[] TSRMLS_DC);
static zend_object_value rpc_create_object(zend_class_entry *class_type TSRMLS_DC);
static void rpc_globals_ctor(zend_rpc_globals * TSRMLS_DC);
static void rpc_instance_dtor(void *);
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);
/* object handler */
static void rpc_add_ref(zval *object TSRMLS_DC);
static void rpc_del_ref(zval *object TSRMLS_DC);
static void rpc_delete(zval *object TSRMLS_DC);
static zend_object_value rpc_clone(zval *object TSRMLS_DC);
static zval* rpc_read(zval *object, zval *member, int type TSRMLS_DC);
static void rpc_write(zval *object, zval *member, zval *value TSRMLS_DC);
static zval** rpc_get_property(zval *object, zval *member TSRMLS_DC);
static zval* rpc_get(zval *property TSRMLS_DC);
static void rpc_set(zval **property, zval *value TSRMLS_DC);
static int rpc_has_property(zval *object, zval *member, int check_empty TSRMLS_DC);
static void rpc_unset_property(zval *object, zval *member TSRMLS_DC);
static HashTable* rpc_get_properties(zval *object TSRMLS_DC);
static union _zend_function* rpc_get_method(zval *object, char *method, int method_len TSRMLS_DC);
static int rpc_call(char *method, INTERNAL_FUNCTION_PARAMETERS);
static union _zend_function* rpc_get_constructor(zval *object TSRMLS_DC);
static int rpc_get_classname(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC);
static int rpc_compare(zval *object1, zval *object2 TSRMLS_DC);
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);
static zval* rpc_get(zval * TSRMLS_DC);
static void rpc_set(zval **, zval * TSRMLS_DC);
static int rpc_has_property(zval *, zval *, int TSRMLS_DC);
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 int rpc_call(char *, INTERNAL_FUNCTION_PARAMETERS);
static union _zend_function* rpc_get_constructor(zval * TSRMLS_DC);
static int rpc_get_classname(zval *, char **, zend_uint *, int TSRMLS_DC);
static int rpc_compare(zval *, zval * TSRMLS_DC);
/**/
static zend_object_handlers rpc_handlers = {
@ -83,10 +85,10 @@ zend_module_entry rpc_module_entry = {
};
/* }}} */
static HashTable *instance;
static HashTable *handlers;
static WormHashTable *instance;
static WormHashTable *classes;
static MUTEX_T mx_instance;
static unsigned long thread_count = 0;
#ifdef COMPILE_DL_RPC
@ -105,13 +107,13 @@ PHP_INI_END()
*/
static int rpc_global_startup(void)
{
mx_instance = tsrm_mutex_alloc();
handlers = (HashTable *) pemalloc(sizeof(HashTable), TRUE);
instance = (HashTable *) pemalloc(sizeof(HashTable), TRUE);
instance = (WormHashTable *) pemalloc(sizeof(WormHashTable), TRUE);
classes = (WormHashTable *) pemalloc(sizeof(WormHashTable), TRUE);
zend_hash_init(handlers, 0, NULL, NULL, TRUE);
zend_hash_init(instance, 0, NULL, rpc_instance_dtor, TRUE);
zend_worm_hash_init(instance, 0, NULL, rpc_instance_dtor, TRUE);
zend_worm_hash_init(classes, 0, NULL, rpc_class_dtor, TRUE);
FOREACH_HANDLER {
HANDLER.rpc_handler_init();
@ -136,10 +138,13 @@ static int rpc_global_startup(void)
/* same as above for shutdown */
static int rpc_global_shutdown(void)
{
tsrm_mutex_free(mx_instance);
zend_hash_destroy(handlers);
zend_hash_destroy(instance);
zend_worm_hash_destroy(instance);
zend_worm_hash_destroy(classes);
pefree(handlers, TRUE);
pefree(instance, TRUE);
pefree(classes, TRUE);
return SUCCESS;
}
@ -207,6 +212,29 @@ static void rpc_instance_dtor(void *pDest)
pefree(*intern, TRUE);
}
static void rpc_class_dtor(void *pDest)
{
rpc_class_hash **hash;
hash = (rpc_class_hash **) pDest;
zend_worm_hash_destroy(&((*hash)->methods));
zend_worm_hash_destroy(&((*hash)->properties));
free((*hash)->name.str);
pefree(*hash, TRUE);
}
static void rpc_string_dtor(void *pDest)
{
rpc_string **string;
string = (rpc_string **) pDest;
free((*string)->str);
pefree(*string, TRUE);
}
static zend_object_value rpc_create_object(zend_class_entry *class_type TSRMLS_DC)
{
zend_object_value *zov;
@ -218,10 +246,16 @@ 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->mx_handler = tsrm_mutex_alloc();
if (zend_hash_find(handlers, class_type->name, class_type->name_length + 1, (void **) &(intern->handlers)) == FAILURE) {
/* TODO: exception */
}
@ -229,12 +263,12 @@ static zend_object_value rpc_create_object(zend_class_entry *class_type TSRMLS_D
/* store the instance in a hash and set the key as handle, thus
* we can find it later easily
*/
tsrm_mutex_lock(mx_instance);
tsrm_mutex_lock(instance->mx_writer);
{
zov->handle = instance->nNextFreeElement;
zend_hash_next_index_insert(instance, &intern, sizeof(rpc_internal *), NULL);
zov->handle = zend_hash_next_free_element(&(instance->hash));
zend_worm_hash_next_index_insert(instance, &intern, sizeof(rpc_internal *), NULL);
}
tsrm_mutex_unlock(mx_instance);
tsrm_mutex_unlock(instance->mx_writer);
return *zov;
}
@ -257,7 +291,7 @@ static void rpc_del_ref(zval *object TSRMLS_DC)
}
if (RPC_REFCOUNT(intern) == 0) {
zend_hash_index_del(instance, Z_OBJ_HANDLE(*object));
zend_worm_hash_index_del(instance, Z_OBJ_HANDLE(*object));
}
}
}
@ -272,7 +306,7 @@ static void rpc_delete(zval *object TSRMLS_DC)
}
if (RPC_CLONECOUNT(intern) == 0) {
zend_hash_index_del(instance, Z_OBJ_HANDLE_P(object));
zend_worm_hash_index_del(instance, Z_OBJ_HANDLE_P(object));
}
}
}
@ -320,16 +354,13 @@ static zval** rpc_get_property(zval *object, zval *member TSRMLS_DC)
static zval* rpc_get(zval *property TSRMLS_DC)
{
// GET_INTERNAL(intern);
/* FIXME */
/* not yet implemented */
return NULL;
}
static void rpc_set(zval **property, zval *value TSRMLS_DC)
{
// GET_INTERNAL(intern);
/* FIXME */
/* not yet implemented */
}
static int rpc_has_property(zval *object, zval *member, int check_empty TSRMLS_DC)
@ -386,6 +417,7 @@ static union _zend_function* rpc_get_constructor(zval *object TSRMLS_DC)
rpc_ctor = (zend_internal_function *) emalloc(sizeof(zend_internal_function));
rpc_ctor->type = ZEND_INTERNAL_FUNCTION;
rpc_ctor->function_name = (*intern)->ce->name;
rpc_ctor->scope = (*intern)->ce;
rpc_ctor->arg_types = NULL;
rpc_ctor->handler = ZEND_FN(rpc_load);
@ -413,6 +445,10 @@ static int rpc_compare(zval *object1, zval *object2 TSRMLS_DC)
ZEND_FUNCTION(rpc_load)
{
zval *object = getThis();
zval ***args;
zend_uint num_args = ZEND_NUM_ARGS();
rpc_class_hash *class_hash;
rpc_class_hash **class_hash_find = NULL;
rpc_internal **intern;
/* check if we were called as a constructor or as a function */
@ -456,9 +492,96 @@ ZEND_FUNCTION(rpc_load)
/* TODO: exception */
}
// (*intern)->handlers.rpc_ctor(
/* if classname != integer */
if ((zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 2 TSRMLS_CC, "l", &((*intern)->class_name_len)) == FAILURE) ||
/* or we have no hash function */
!((*(*intern)->handlers)->rpc_hash) ||
/* or integer hashing is not allowed */
((*(*intern)->handlers)->hash_type != HASH_AS_INT)) {
/* FIXME */
/* else check for string - classname */
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 2 TSRMLS_CC, "s", &((*intern)->class_name), &((*intern)->class_name_len)) == FAILURE) {
/* none of the two possibilities */
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) {
/* check if already hashed */
if (zend_worm_hash_find(classes, (*intern)->class_name, (*intern)->class_name_len + 1, (void **) &class_hash_find) == FAILURE) {
class_hash = pemalloc(sizeof(rpc_class_hash), TRUE);
/* set up the cache */
zend_worm_hash_init(&(class_hash->methods), 0, NULL, rpc_string_dtor, TRUE);
zend_worm_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), CLASS) == FAILURE) {
/* TODO: exception */
}
/* register with non-hashed key */
zend_worm_hash_add(classes, (*intern)->class_name, (*intern)->class_name_len + 1, &class_hash, sizeof(rpc_class_hash *), NULL);
if (class_hash->name.str) {
/* register string hashcode */
zend_worm_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)) {
/* register int hashcode */
zend_worm_hash_index_update(classes, class_hash->name.len, &class_hash, sizeof(rpc_class_hash *), NULL);
}
} else {
class_hash = *class_hash_find;
}
}
}
} else {
/* integer classname (hashcode) */
if (zend_worm_hash_index_find(classes, (*intern)->class_name_len, (void**) &class_hash_find) == FAILURE) {
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;
zend_worm_hash_init(&(class_hash->methods), 0, NULL, rpc_string_dtor, TRUE);
zend_worm_hash_init(&(class_hash->properties), 0, NULL, rpc_string_dtor, TRUE);
/* register int hashcode, we don't know more */
zend_worm_hash_index_update(classes, class_hash->name.len, &class_hash, sizeof(rpc_class_hash *), NULL);
} else {
class_hash = *class_hash_find;
}
}
/* fetch further parameters */
args = (zval ***) emalloc(sizeof(zval **) * num_args);
if (zend_get_parameters_array_ex(num_args, args) == FAILURE) {
/* TODO: exception */
}
/* strip away the first two parameters */
num_args -= 2;
args = (num_args > 0) ? &args[2] : NULL;
/* if hash function available */
if ((*(*intern)->handlers)->rpc_hash) {
/* assign cache structure */
(*intern)->hash = class_hash;
/* call the rpc ctor */
(*(*intern)->handlers)->rpc_ctor(class_hash->name.str, class_hash->name.len, &((*intern)->data), num_args, args);
} else {
/* disable caching from now on */
(*intern)->hash = NULL;
/* call the rpc ctor */
(*(*intern)->handlers)->rpc_ctor((*intern)->class_name, (*intern)->class_name_len, &((*intern)->data), num_args, args);
}
/* efree hash_find stuff ? */
}
ZEND_FUNCTION(rpc_call)