]> granicus.if.org Git - php/commitdiff
fixed memleaks
authorHarald Radi <phanto@php.net>
Tue, 19 Mar 2002 18:46:28 +0000 (18:46 +0000)
committerHarald Radi <phanto@php.net>
Tue, 19 Mar 2002 18:46:28 +0000 (18:46 +0000)
added method lookup caching
pass function signature to hash function callback

ext/rpc/com/com.c
ext/rpc/handler.h
ext/rpc/rpc.c
ext/rpc/rpc.h
ext/rpc/tests/test1.php

index 55ac252ec3172eb4a85bc3f37dc7a0f5aaf017c7..0ccccfe3b8f55017a60f7f7fcb9b31b1ae3dbf6c 100644 (file)
@@ -1,17 +1,17 @@
 #include "com.h"
 
 /* protos */
-static int com_hash(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int type);
-static int com_ctor(char *class_name, zend_uint class_name_len, void **data, int num_args, zval **args[]);
-static int com_dtor(void **data);
-static int com_call(char *method_name, zend_uint method_name_len, void **data, INTERNAL_FUNCTION_PARAMETERS);
-static int com_get(char *property_name, zend_uint property_name_len, zval *return_value, void **data);
-static int com_set(char *property_name, zend_uint property_name_len, zval *value, zval *return_value, void **data);
-static int com_compare(void **data1, void **data2);
-static int com_get_classname(char **class_name, zend_uint *class_name_length, void **data);
-static int com_has_property(char *property_name, zend_uint property_name_length, void **data);
-static int com_unset_property(char *property_name, zend_uint property_name_length, void **data);
-static int com_get_properties(HashTable **properties, void **data);
+static int com_hash(char *, zend_uint, char **, zend_uint *, int, zval ***, int);
+static int com_ctor(char *, zend_uint, void **, int , zval ***);
+static int com_dtor(void **);
+static int com_call(char *, zend_uint, void **, zval **, int, zval ***);
+static int com_get(char *, zend_uint, zval *, void **);
+static int com_set(char *, zend_uint, zval *, zval *, void **);
+static int com_compare(void **, void **);
+static int com_get_classname(char **, zend_uint *, void **);
+static int com_has_property(char *, zend_uint, void **);
+static int com_unset_property(char *, zend_uint, void **);
+static int com_get_properties(HashTable **, void **);
 
 
 /* register rpc callback function */
@@ -51,7 +51,7 @@ RPC_INIT_FUNCTION(com)
 
 /* rpc handler functions */
 
-static int com_hash(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int type)
+static int com_hash(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int num_args, zval **args[], int type)
 {
        *hash = strdup(name);
        *hash_len = name_len;
@@ -69,7 +69,7 @@ static int com_dtor(void **data)
        return SUCCESS;
 }
 
-static int com_call(char *method_name, zend_uint method_name_len, void **data, INTERNAL_FUNCTION_PARAMETERS)
+static int com_call(char *method_name, zend_uint method_name_len, void **data, zval **return_value, int num_args, zval **args[])
 {
        return SUCCESS;
 }
index 1942ca1c4c4cdcfd0426383a7cac60d93856e51b..bc3e9b34d29bda950ab6a34378e52977d66ccafa 100644 (file)
 
 #define POOL           TRUE
 #define DONT_POOL      FALSE
-#define HASH_AS_INT    TRUE
-#define HASH_AS_STRING FALSE
-#define DONT_HASH      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 CLASS 0
 #define METHOD 1
  */
 typedef struct _rpc_object_handlers {
        const zend_bool pool_instances;
-       const int hash_type;
-       int (*rpc_hash)(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int type);
+       const zend_uint hash_type;
+       int (*rpc_hash)(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int num_args, zval **args[], int type);
        int (*rpc_ctor)(char *class_name, zend_uint class_name_len, 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, INTERNAL_FUNCTION_PARAMETERS);
+       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, zval *return_value, void **data);
        int (*rpc_compare)(void **data1, void **data2);
@@ -99,6 +103,7 @@ typedef struct _rpc_internal {
        zend_uint                       clonecount;
        zend_bool                       pool_instances;
        rpc_class_hash          *hash;
+       WormHashTable           function_table;
        MUTEX_T                         mx_handler;
 } rpc_internal;
 
index a871f4284e0ce72601689bdb3b7538c34319e8fb..2652ff6ce35e69fbb39a29ef279c0362a44790f0 100644 (file)
@@ -12,8 +12,6 @@
 
 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 * TSRMLS_DC);
 static void rpc_instance_dtor(void *);
 static void rpc_class_dtor(void *);
@@ -35,7 +33,6 @@ 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);
@@ -56,7 +53,7 @@ static zend_object_handlers rpc_handlers = {
        rpc_unset_property,
        rpc_get_properties,
        rpc_get_method,
-       rpc_call,
+       NULL,
        rpc_get_constructor,
        rpc_get_classname,
        rpc_compare
@@ -89,8 +86,6 @@ static HashTable *handlers;
 static WormHashTable *instance;
 static WormHashTable *classes;
 
-static unsigned long thread_count = 0;
-
 #ifdef COMPILE_DL_RPC
 ZEND_GET_MODULE(rpc);
 #endif
@@ -102,10 +97,13 @@ PHP_INI_BEGIN()
 PHP_INI_END()
 /* }}} */
 
-/* still not sure if MINIT is really only once per server and not once per thread
- * so i keep the init stuff here here
+static void rpc_globals_ctor(zend_rpc_globals *rpc_globals TSRMLS_DC)
+{
+}
+
+/* {{{ ZEND_MINIT_FUNCTION
  */
-static int rpc_global_startup(void)
+ZEND_MINIT_FUNCTION(rpc)
 {
        handlers = (HashTable *) pemalloc(sizeof(HashTable), TRUE);
        instance = (WormHashTable *) pemalloc(sizeof(WormHashTable), TRUE);
@@ -114,7 +112,7 @@ static int rpc_global_startup(void)
        zend_hash_init(handlers, 0, NULL, NULL, 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();
                
@@ -130,39 +128,7 @@ static int rpc_global_startup(void)
 
                /* 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);
-       }
 
-       return SUCCESS;
-}
-
-/* same as above for shutdown */
-static int rpc_global_shutdown(void)
-{
-       zend_hash_destroy(handlers);
-       zend_worm_hash_destroy(instance);
-       zend_worm_hash_destroy(classes);
-
-       pefree(handlers, TRUE);
-       pefree(instance, TRUE);
-       pefree(classes, TRUE);
-
-       return SUCCESS;
-}
-
-static void rpc_globals_ctor(zend_rpc_globals *rpc_globals TSRMLS_DC)
-{
-}
-
-/* {{{ ZEND_MINIT_FUNCTION
- */
-ZEND_MINIT_FUNCTION(rpc)
-{
-       /* GINIT */
-       if (thread_count++ == 0) {
-               rpc_global_startup();
-       }
-       
-       FOREACH_HANDLER {
                /* register classes and functions */
                zend_register_internal_class(HANDLER.ce TSRMLS_CC);
                zend_register_functions(HANDLER.functions, NULL, MODULE_PERSISTENT TSRMLS_CC);
@@ -179,10 +145,15 @@ ZEND_MINIT_FUNCTION(rpc)
  */
 ZEND_MSHUTDOWN_FUNCTION(rpc)
 {
-       /* GSHUTDOWN */
-       if (--thread_count == 0) {
-               rpc_global_shutdown();
-       }
+       zend_worm_hash_destroy(instance);
+       zend_worm_hash_destroy(classes);
+
+       /* destroy instances first ! */
+       zend_hash_destroy(handlers);
+
+       pefree(handlers, TRUE);
+       pefree(instance, TRUE);
+       pefree(classes, TRUE);
 
        UNREGISTER_INI_ENTRIES();
        return SUCCESS;
@@ -206,8 +177,12 @@ static void rpc_instance_dtor(void *pDest)
        rpc_internal **intern;
        
        intern = (rpc_internal **) pDest;
+       
+       (*(*intern)->handlers)->rpc_dtor(&((*intern)->data));
 
-       /* TODO: destruct custom 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);
 }
@@ -254,9 +229,13 @@ static zend_object_value rpc_create_object(zend_class_entry *class_type TSRMLS_D
        intern->clonecount = 1;
        intern->data = NULL;
        intern->pool_instances = 0;
+       intern->function_table.hash = intern->ce->function_table;
+       intern->function_table.reader = 0;
+       intern->function_table.mx_reader = tsrm_mutex_alloc();
+       intern->function_table.mx_writer = tsrm_mutex_alloc();
        intern->mx_handler = tsrm_mutex_alloc();
 
-       if (zend_hash_find(handlers, class_type->name, class_type->name_length + 1, (void **) &(intern->handlers)) == FAILURE) {
+       if (zend_hash_find(handlers, class_type->name, class_type->name_length + 1, (void **) &(intern->handlers)) != SUCCESS) {
                /* TODO: exception */
        }
 
@@ -390,39 +369,46 @@ static union _zend_function* rpc_get_method(zval *object, char *method, int meth
        zend_function *function;
        GET_INTERNAL(intern);
 
-       if (zend_hash_find(&((*intern)->ce->function_table), method, method_len + 1, &function) == FAILURE) {
-               function = (zend_function *) emalloc(sizeof(zend_function));
-               function->type = ZEND_OVERLOADED_FUNCTION;
-               function->common.arg_types = NULL;
-               function->common.function_name = method;
-               function->common.scope = NULL;
-       }
+       if (zend_worm_hash_find(&((*intern)->function_table), method, method_len + 1, &function) != SUCCESS) {
+               zend_internal_function *zif;
 
-       return function;
-}
+               zif = (zend_internal_function *) emalloc(sizeof(zend_internal_function));
+               zif->arg_types = NULL;
+               zif->function_name = method;
+               zif->handler = ZEND_FN(rpc_call);
+               zif->scope = NULL;
+               zif->type = ZEND_INTERNAL_FUNCTION;
 
-static int rpc_call(char *method, INTERNAL_FUNCTION_PARAMETERS)
-{
-//     zval *object = getThis();
-//     GET_INTERNAL(intern);
+               /* add new method to the method table */
+               zend_worm_hash_add(&((*intern)->function_table), method, method_len + 1, zif, sizeof(zend_function), &function);
+               efree(zif);
+       }
 
-       return SUCCESS;
+       return function;
 }
 
 static union _zend_function* rpc_get_constructor(zval *object TSRMLS_DC)
 {
-       zend_internal_function *rpc_ctor;
+       zend_function *rpc_ctor;
        GET_INTERNAL(intern);
        
-       rpc_ctor = (zend_internal_function *) emalloc(sizeof(zend_internal_function));
+       if (zend_worm_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));
 
-       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);
+               zif->type = ZEND_INTERNAL_FUNCTION;
+               zif->function_name = (*intern)->ce->name;
+               zif->scope = (*intern)->ce;
+               zif->arg_types = NULL;
+               zif->handler = ZEND_FN(rpc_load);
 
-       return (zend_function *) rpc_ctor;
+               /* add new constructor to the method table */
+               zend_worm_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 int rpc_get_classname(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
@@ -445,11 +431,12 @@ static int rpc_compare(zval *object1, zval *object2 TSRMLS_DC)
 ZEND_FUNCTION(rpc_load)
 {
        zval *object = getThis();
-       zval ***args;
+       zval ***args, ***args_free;
        zend_uint num_args = ZEND_NUM_ARGS(); 
        rpc_class_hash *class_hash;
        rpc_class_hash **class_hash_find = NULL;
        rpc_internal **intern;
+       int retval;
 
        /* check if we were called as a constructor or as a function */
        if (!object) {
@@ -457,67 +444,58 @@ ZEND_FUNCTION(rpc_load)
                 * and then we have to set up a zval containing the object
                 */
 
-               char *key;
-               int key_len;
-
-               /* the name of the rpc layer is prepended to '_load' so lets strip everything after
-                * the first '_' away from the function name
-                */
-               zend_class_entry **ce;
-               key = estrdup(get_active_function_name(TSRMLS_C));
-               key_len = strchr(key, '_') - key;
-               key[key_len] = '\0';
-
-               /* get the class entry for the requested rpc layer */
-               if (zend_hash_find(CG(class_table), key, key_len + 1, (void **) &ce) == FAILURE) {
-                       /* TODO: exception here */
-               }
+               /* get class entry */
+               GET_CLASS(ce);
 
                /* set up a new zval container */
-               ALLOC_ZVAL(object);
-               INIT_PZVAL(object);
+               object = return_value;
 
                Z_TYPE_P(object) = IS_OBJECT;
 
                /* create a new object */
                object->value.obj = rpc_create_object(*ce TSRMLS_CC);
 
-               /* return the newly created object */
-               return_value = object;
-
                /* now everything is set up the same way as if we were called as a constructor */
        }
 
-       if (GET_INTERNAL_EX(intern, object) == FAILURE) {
+       if (GET_INTERNAL_EX(intern, object) != SUCCESS) {
                /* TODO: exception */
        }
 
+       /* fetch further parameters */
+       GET_ARGS_EX(num_args, args, args_free, 2);
+
        /* if classname != integer */
-       if ((zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 2 TSRMLS_CC, "l", &((*intern)->class_name_len)) == FAILURE) ||
+       if ((zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 1 TSRMLS_CC, "l", &((*intern)->class_name_len)) != SUCCESS) ||
                /* or we have no hash function */
                !((*(*intern)->handlers)->rpc_hash) ||
                /* or integer hashing is not allowed */
-               ((*(*intern)->handlers)->hash_type != HASH_AS_INT)) {
+               !((*(*intern)->handlers)->hash_type & HASH_AS_INT)) {
 
                /* 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) {
+               if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 1 TSRMLS_CC, "s", &((*intern)->class_name), &((*intern)->class_name_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) {
 
                                /* check if already hashed */   
-                               if (zend_worm_hash_find(classes, (*intern)->class_name, (*intern)->class_name_len + 1, (void **) &class_hash_find) == FAILURE) {
+                               if (zend_worm_hash_find(classes, (*intern)->class_name, (*intern)->class_name_len + 1, (void **) &class_hash_find) != SUCCESS) {
                                        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);
 
+                                       if ((*(*intern)->handlers)->hash_type & HASH_WITH_SIGNATURE) {
+                                               /* TODO: add signature to hash key */
+                                       }
+
                                        /* do hashing */
-                                       if ((*(*intern)->handlers)->rpc_hash((*intern)->class_name, (*intern)->class_name_len,
-                                                                                                                &(class_hash->name.str), &(class_hash->name.len), CLASS) == FAILURE) {
+                                       if ((*(*intern)->handlers)->rpc_hash((*intern)->class_name, (*intern)->class_name_len, &(class_hash->name.str),
+                                                                                                                &(class_hash->name.len), num_args, args, CLASS) != SUCCESS) {
                                                /* TODO: exception */
                                        }
 
@@ -527,7 +505,7 @@ ZEND_FUNCTION(rpc_load)
                                        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)) {
+                                       } 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);
                                        }
@@ -538,7 +516,7 @@ ZEND_FUNCTION(rpc_load)
                }
        } else {
                /* integer classname (hashcode) */
-               if (zend_worm_hash_index_find(classes, (*intern)->class_name_len, (void**) &class_hash_find) == FAILURE) {
+               if (zend_worm_hash_index_find(classes, (*intern)->class_name_len, (void**) &class_hash_find) != SUCCESS) {
                        class_hash = pemalloc(sizeof(rpc_class_hash), TRUE);
 
                        /* set up the cache */
@@ -548,23 +526,16 @@ ZEND_FUNCTION(rpc_load)
                        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);
 
+                       if ((*(*intern)->handlers)->hash_type & HASH_WITH_SIGNATURE) {
+                               /* TODO: add signature to hash key */
+                       }
+
                        /* 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) {
@@ -572,21 +543,104 @@ ZEND_FUNCTION(rpc_load)
                (*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);
+               retval = (*(*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);
+               retval = (*(*intern)->handlers)->rpc_ctor((*intern)->class_name, (*intern)->class_name_len, &((*intern)->data), num_args, args);
        }
 
-       /* efree hash_find stuff ? */
+       efree(args_free);
+
+       if (retval != SUCCESS) {
+               /* TODO: exception */
+       }
 }
 
 ZEND_FUNCTION(rpc_call)
 {
-       /* FIXME */
+       zval *object = getThis();
+       zval ***args, ***args_free;
+       zend_uint num_args = ZEND_NUM_ARGS(); 
+       char *hash = NULL;
+       int hash_len, retval, strip = 0;
+
+       /* check if we were called as a method or as a function */
+       if (!object) {
+               /* we were called as a function so we have to figure out which rpc layer was requested */
+
+               /* get class entry */
+               GET_CLASS(ce);
+
+               if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, 2 TSRMLS_CC, "Ol", &object, *ce, &hash_len) != SUCCESS) {
+                       if (zend_parse_parameters_ex(0, 2 TSRMLS_CC, "Os", &object, *ce, &hash, &hash_len) != SUCCESS) {
+                               /* none of the two possibilities */
+                               /* TODO: exception */
+                               php_error(E_WARNING, "wrong arguments for %s()", get_active_function_name(TSRMLS_C));
+                       }
+               }
+
+               strip = 2;
+       } else {
+               hash = get_active_function_name(TSRMLS_C);
+               hash_len = strlen(hash);
+       }
+
+       GET_ARGS_EX(num_args, args, args_free, strip);
+       
+       /* scope for internal data */
+       {
+               rpc_string *method_hash, **method_hash_find;
+               GET_INTERNAL(intern);
+
+               method_hash = (rpc_string *) pemalloc(sizeof(rpc_string), TRUE);
+               method_hash->str = hash;
+               method_hash->len = hash_len;
+               
+               if ((*intern)->hash) {
+                       /* cache method table lookups */
+               
+                       if ((*(*intern)->handlers)->hash_type & HASH_WITH_SIGNATURE) {
+                               /* TODO: add signature to hash key */
+                       }
+
+                       if (!hash && !((*(*intern)->handlers)->hash_type & HASH_AS_INT)) {
+                               /* TODO: exception */
+                       } else if(hash) {
+                               /* string method */
+
+                               /* check if already hashed */   
+                               if (zend_worm_hash_find(&((*intern)->hash->methods), hash, hash_len + 1, (void **) &method_hash_find) != SUCCESS) {
+                                       if ((*(*intern)->handlers)->rpc_hash(hash, hash_len, &(method_hash->str), &(method_hash->len),
+                                                                                                                num_args, args, METHOD) != SUCCESS) {
+                                               /* TODO: exception */
+                                       }
+
+                                       /* register with non-hashed key */
+                                       zend_worm_hash_add(&((*intern)->hash->methods), hash, hash_len + 1, &method_hash, sizeof(rpc_string *), NULL);
+                               } else {
+                                       pefree(method_hash, TRUE);
+                                       method_hash = *method_hash_find;
+                               }
+                       }
+               }
+
+               /* actually this should not be neccesary, but who knows :)
+                * 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);
+       }
+
+       efree(args_free);
+
+       if (retval != SUCCESS) {
+               /* TODO: exception here */
+       }
 }
 
 ZEND_FUNCTION(rpc_set)
index 15f9bea5bfa790df5b92cdcd157d6b961b9823b5..81f8af314a3f095a502a5806c8a491478e193466 100644 (file)
@@ -6,12 +6,48 @@
 #define HANDLER_COUNT (sizeof(handler_entries) / sizeof(rpc_handler_entry))
 
 #define GET_INTERNAL(intern)   rpc_internal **intern;                                                          \
-                                                               if (GET_INTERNAL_EX(intern, object) == FAILURE) {       \
+                                                               if (GET_INTERNAL_EX(intern, object) != SUCCESS) {       \
                                                                        /* TODO: exception */                                                   \
                                                                }
 
 #define GET_INTERNAL_EX(intern, object)        zend_worm_hash_index_find(instance, object->value.obj.handle, (void **) &intern)
 
+#define GET_CLASS(ce)  char *key;                                                                                                                                                              \
+                                               int key_len;                                                                                                                                                    \
+                                               zend_class_entry **ce;                                                                                                                                  \
+                                                                                                                                                                                                                               \
+                                               /* the name of the rpc layer is prepended to '_load' so lets strip everything after             \
+                                                * the first '_' away from the function name                                                                                    \
+                                                */                                                                                                                                                                             \
+                                               key = estrdup(get_active_function_name(TSRMLS_C));                                                                              \
+                                               key_len = strchr(key, '_') - key;                                                                                                               \
+                                               key[key_len] = '\0';                                                                                                                                    \
+                                                                                                                                                                                                                               \
+                                               /* get the class entry for the requested rpc layer */                                                                   \
+                                               if (zend_hash_find(CG(class_table), key, key_len + 1, (void **) &ce) != SUCCESS) {              \
+                                                       efree(key);                                                                                                                                                     \
+                                                       /* TODO: exception here */                                                                                                                      \
+                                               } else {                                                                                                                                                                \
+                                                       efree(key);                                                                                                                                                     \
+                                               }
+
+#define GET_ARGS_EX(num_args, args, args_free, strip)                                                                          \
+                                               GET_ARGS(num_args, args)                                                                                        \
+                                                                                                                                                                                       \
+                                               args_free = args;                                                                                                       \
+                                                                                                                                                                                       \
+                                               /* strip away the first parameters */                                                           \
+                                               num_args -= strip;                                                                                                      \
+                                               args = (num_args > 0) ? &args[strip] : NULL;
+
+#define GET_ARGS(num_args, args)                                                                                                                       \
+                                               args = (zval ***) emalloc(sizeof(zval **) * num_args);                          \
+                                                                                                                                                                                       \
+                                               if (zend_get_parameters_array_ex(num_args, args) != SUCCESS) {          \
+                                                       efree(args);                                                                                                    \
+                                                       /* TODO: exception */                                                                                   \
+                                               }
+
 #define RPC_REFCOUNT(intern) ((*intern)->refcount)
 #define RPC_ADDREF(intern) (++RPC_REFCOUNT(intern))
 #define RPC_DELREF(intern) (--RPC_REFCOUNT(intern))
index 33b14e497dda07ba70cf676dd525281b85bb03bd..e989f53168530c477aef056ccf752ee3aecf364b 100644 (file)
@@ -3,7 +3,9 @@ print "huhuhdsa";
 
 $rpc = new com("class", true);
 $rpc2 = new com("class", true, "hehe", 12);
-//$rpc->call();
+$rpc->call("blah");
+$rpc->call("heh");
+com_call($rpc, "call", 1);
 //$rpc->addref();
 
 //$clone = $rpc->__clone();
@@ -17,6 +19,6 @@ $rpc2 = new com("class", true, "hehe", 12);
 //delete $clone;
 
 $heh = com_load(1, 1);
-/*$heh->call;
-delete $heh;*/
+$heh->knorp();
+/*delete $heh;*/
 ?>
\ No newline at end of file