testing
authorMichael Wallner <mike@php.net>
Mon, 24 Nov 2014 14:01:54 +0000 (15:01 +0100)
committerMichael Wallner <mike@php.net>
Thu, 4 Dec 2014 17:35:18 +0000 (18:35 +0100)
php_raphf.c
php_raphf_test.c [new file with mode: 0644]
raphf_test.php [new file with mode: 0644]

index 2c785dd72c00201f2e21d4377fa7a7abf520d6ef..8b89669574de608e782737e32029e7cb02531331 100644 (file)
 #include "ext/standard/info.h"
 #include "php_raphf.h"
 
+#ifndef PHP_RAPHF_TEST
+#      define PHP_RAPHF_TEST 1
+#endif
+
 struct php_persistent_handle_globals {
        ulong limit;
        HashTable hash;
@@ -136,8 +140,11 @@ static int php_persistent_handle_apply_stat(zval *p TSRMLS_DC, int argc,
        add_assoc_long_ex(&zsubentry, ZEND_STRS("used"), list->used);
        add_assoc_long_ex(&zsubentry, ZEND_STRS("free"),
                        zend_hash_num_elements(&list->free));
-       add_assoc_zval_ex(zentry, key->key->val, key->key->len, &zsubentry);
-
+       if (key->key) {
+               add_assoc_zval_ex(zentry, key->key->val, key->key->len, &zsubentry);
+       } else {
+               add_index_zval(zentry, key->h, &zsubentry);
+       }
        return ZEND_HASH_APPLY_KEEP;
 }
 
@@ -152,7 +159,12 @@ static int php_persistent_handle_apply_statall(zval *p TSRMLS_DC, int argc,
 
        zend_hash_apply_with_arguments(&provider->list.free TSRMLS_CC,
                        php_persistent_handle_apply_stat, 1, &zentry);
-       zend_symtable_update(ht, key->key, &zentry);
+
+       if (key->key) {
+               zend_hash_update(ht, key->key, &zentry);
+       } else {
+               zend_hash_index_update(ht, key->h, &zentry);
+       }
 
        return ZEND_HASH_APPLY_KEEP;
 }
@@ -226,8 +238,7 @@ static inline php_persistent_handle_list_t *php_persistent_handle_list_find(
 {
        php_persistent_handle_list_t *list;
 
-       list = zend_symtable_str_find_ptr(&provider->list.free, ident_str,
-                       ident_len + 1);
+       list = zend_symtable_str_find_ptr(&provider->list.free, ident_str, ident_len);
 
        if (list) {
 #if PHP_RAPHF_DEBUG_PHANDLES
@@ -304,7 +315,7 @@ ZEND_RESULT_CODE php_persistent_handle_provide(const char *name_str,
 
                        ZVAL_PTR(&p, provider);
                        if (zend_symtable_str_update(&PHP_RAPHF_G->persistent_handle.hash,
-                                       name_str, name_len, &p)) {
+                                       name_str, name_len + 1, &p)) {
                                return SUCCESS;
                        }
                        php_resource_factory_dtor(&provider->rf);
@@ -314,6 +325,7 @@ ZEND_RESULT_CODE php_persistent_handle_provide(const char *name_str,
        return FAILURE;
 }
 
+
 php_persistent_handle_factory_t *php_persistent_handle_concede(
                php_persistent_handle_factory_t *a, const char *name_str,
                size_t name_len, const char *ident_str, size_t ident_len,
@@ -545,6 +557,10 @@ static PHP_FUNCTION(raphf_clean_persistent_handles)
        }
 }
 
+#if PHP_RAPHF_TEST
+#      include "php_raphf_test.c"
+#endif
+
 static const zend_function_entry raphf_functions[] = {
        ZEND_NS_FENTRY("raphf", stat_persistent_handles,
                        ZEND_FN(raphf_stat_persistent_handles),
@@ -552,6 +568,14 @@ static const zend_function_entry raphf_functions[] = {
        ZEND_NS_FENTRY("raphf", clean_persistent_handles,
                        ZEND_FN(raphf_clean_persistent_handles),
                        ai_raphf_clean_persistent_handles, 0)
+#if PHP_RAPHF_TEST
+       ZEND_NS_FENTRY("raphf", provide, ZEND_FN(raphf_provide), NULL, 0)
+       ZEND_NS_FENTRY("raphf", concede, ZEND_FN(raphf_concede), NULL, 0)
+       ZEND_NS_FENTRY("raphf", dispute, ZEND_FN(raphf_dispute), NULL, 0)
+       ZEND_NS_FENTRY("raphf", handle_ctor, ZEND_FN(raphf_handle_ctor), NULL, 0)
+       ZEND_NS_FENTRY("raphf", handle_copy, ZEND_FN(raphf_handle_copy), NULL, 0)
+       ZEND_NS_FENTRY("raphf", handle_dtor, ZEND_FN(raphf_handle_dtor), NULL, 0)
+#endif
        {0}
 };
 
@@ -583,12 +607,21 @@ static PHP_GSHUTDOWN_FUNCTION(raphf)
 PHP_MINIT_FUNCTION(raphf)
 {
        php_persistent_handles_global_hash = &PHP_RAPHF_G->persistent_handle.hash;
+
+#if PHP_RAPHF_TEST
+       PHP_MINIT(raphf_test)(INIT_FUNC_ARGS_PASSTHRU);
+#endif
+
        REGISTER_INI_ENTRIES();
        return SUCCESS;
 }
 
 PHP_MSHUTDOWN_FUNCTION(raphf)
 {
+#if PHP_RAPHF_TEST
+       PHP_MSHUTDOWN(raphf_test)(SHUTDOWN_FUNC_ARGS_PASSTHRU);
+#endif
+
        UNREGISTER_INI_ENTRIES();
        php_persistent_handles_global_hash = NULL;
        return SUCCESS;
@@ -667,7 +700,6 @@ zend_module_entry raphf_module_entry = {
 ZEND_GET_MODULE(raphf)
 #endif
 
-
 /*
  * Local variables:
  * tab-width: 4
diff --git a/php_raphf_test.c b/php_raphf_test.c
new file mode 100644 (file)
index 0000000..6d59789
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+    +--------------------------------------------------------------------+
+    | PECL :: raphf                                                      |
+    +--------------------------------------------------------------------+
+    | Redistribution and use in source and binary forms, with or without |
+    | modification, are permitted provided that the conditions mentioned |
+    | in the accompanying LICENSE file are met.                          |
+    +--------------------------------------------------------------------+
+    | Copyright (c) 2014, Michael Wallner <mike@php.net>                 |
+    +--------------------------------------------------------------------+
+*/
+
+#include <php.h>
+
+struct user_cb {
+       zend_fcall_info fci;
+       zend_fcall_info_cache fcc;
+};
+
+struct raphf_user {
+       struct user_cb ctor;
+       struct user_cb copy;
+       struct user_cb dtor;
+       struct {
+               struct user_cb dtor;
+               zval data;
+       } data;
+};
+
+static inline void user_cb_addref(struct user_cb *cb)
+{
+       Z_ADDREF(cb->fci.function_name);
+       if (cb->fci.object) {
+               Z_ADDREF_P((zval *) cb->fci.object);
+       }
+}
+
+static inline void user_cb_delref(struct user_cb *cb)
+{
+       if (cb->fci.object) {
+               Z_DELREF_P((zval *) cb->fci.object);
+       }
+}
+
+static void raphf_user_dtor(void *opaque)
+{
+       struct raphf_user *ru = opaque;
+
+       fprintf(stderr, "Freeing raphf_user struct\n");
+       zend_fcall_info_argn(&ru->data.dtor.fci, 1, &ru->data.data);
+       zend_fcall_info_call(&ru->data.dtor.fci, &ru->data.dtor.fcc, NULL, NULL);
+       zend_fcall_info_args_clear(&ru->data.dtor.fci, 1);
+       user_cb_delref(&ru->data.dtor);
+       zend_fcall_info_args_clear(&ru->ctor.fci, 1);
+       user_cb_delref(&ru->ctor);
+       zend_fcall_info_args_clear(&ru->copy.fci, 1);
+       user_cb_delref(&ru->copy);
+       zend_fcall_info_args_clear(&ru->dtor.fci, 1);
+       user_cb_delref(&ru->dtor);
+       memset(ru, 0, sizeof(*ru));
+       efree(ru);
+}
+
+static void *user_ctor(void *opaque, void *init_arg TSRMLS_DC)
+{
+       struct raphf_user *ru = opaque;
+       zval *zinit_arg = init_arg, *retval = ecalloc(1, sizeof(*retval));
+
+       zend_fcall_info_argn(&ru->ctor.fci, 2, &ru->data.data, zinit_arg);
+       zend_fcall_info_call(&ru->ctor.fci, &ru->ctor.fcc, retval, NULL);
+       zend_fcall_info_args_clear(&ru->ctor.fci, 0);
+
+       return retval;
+}
+
+static void *user_copy(void *opaque, void *handle TSRMLS_DC)
+{
+       struct raphf_user *ru = opaque;
+       zval *zhandle = handle, *retval = ecalloc(1, sizeof(*retval));
+
+       zend_fcall_info_argn(&ru->copy.fci, 2, &ru->data.data, zhandle);
+       zend_fcall_info_call(&ru->copy.fci, &ru->copy.fcc, retval, NULL);
+       zend_fcall_info_args_clear(&ru->copy.fci, 0);
+
+       return retval;
+}
+
+static void user_dtor(void *opaque, void *handle TSRMLS_DC)
+{
+       struct raphf_user *ru = opaque;
+       zval *zhandle = handle, retval;
+
+       ZVAL_UNDEF(&retval);
+       zend_fcall_info_argn(&ru->dtor.fci, 2, &ru->data.data, zhandle);
+       zend_fcall_info_call(&ru->dtor.fci, &ru->dtor.fcc, &retval, NULL);
+       zend_fcall_info_args_clear(&ru->dtor.fci, 0);
+       if (!Z_ISUNDEF(retval)) {
+               zval_ptr_dtor(&retval);
+       }
+}
+
+static php_resource_factory_ops_t user_ops = {
+               user_ctor,
+               user_copy,
+               user_dtor
+};
+
+static int raphf_user_le;
+
+static void raphf_user_res_dtor(zend_resource *res TSRMLS_DC)
+{
+       php_resource_factory_free((void *) &res->ptr);
+}
+
+static PHP_FUNCTION(raphf_provide)
+{
+       struct raphf_user *ru;
+       char *name_str;
+       size_t name_len;
+       zval *zdata;
+
+       ru = ecalloc(1, sizeof(*ru));
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sfffzf",
+                       &name_str, &name_len,
+                       &ru->ctor.fci, &ru->ctor.fcc,
+                       &ru->copy.fci, &ru->copy.fcc,
+                       &ru->dtor.fci, &ru->dtor.fcc,
+                       &zdata,
+                       &ru->data.dtor.fci, &ru->data.dtor.fcc)) {
+               efree(ru);
+               return;
+       }
+
+       user_cb_addref(&ru->ctor);
+       user_cb_addref(&ru->copy);
+       user_cb_addref(&ru->dtor);
+       user_cb_addref(&ru->data.dtor);
+
+       ZVAL_COPY(&ru->data.data, zdata);
+
+       if (SUCCESS != php_persistent_handle_provide(name_str, name_len,
+                       &user_ops, ru, raphf_user_dtor)) {
+               return;
+       }
+}
+
+static PHP_FUNCTION(raphf_concede)
+{
+       char *name_str, *id_str;
+       size_t name_len, id_len;
+       php_persistent_handle_factory_t *pf;
+       php_resource_factory_t *rf;
+       php_resource_factory_ops_t *ops;
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
+                       &name_str, &name_len, &id_str, &id_len)) {
+               return;
+       }
+
+       ops = php_persistent_handle_get_resource_factory_ops();
+       pf = php_persistent_handle_concede(NULL, name_str, name_len, id_str, id_len,
+                       NULL, NULL TSRMLS_CC);
+       if (!pf) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING,
+                               "Could not locate persistent handle factory '%s'", name_str);
+               RETURN_FALSE;
+       }
+       rf = php_resource_factory_init(NULL, ops, pf,
+                       (void(*)(void*)) php_persistent_handle_abandon);
+       if (!rf) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING,
+                               "Could not create resource factory "
+                               "for persistent handle factory '%s'", name_str);
+               RETURN_FALSE;
+       }
+
+       zend_register_resource(return_value, rf, raphf_user_le);
+}
+
+static PHP_FUNCTION(raphf_dispute)
+{
+       zval *zrf;
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zrf)) {
+               return;
+       }
+
+       zend_list_close(Z_RES_P(zrf));
+}
+
+static PHP_FUNCTION(raphf_handle_ctor)
+{
+       zval *zrf, *zrv, *zinit_arg;
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz",
+                       &zrf, &zinit_arg)) {
+               return;
+       }
+
+       zrv = php_resource_factory_handle_ctor(Z_RES_VAL_P(zrf), zinit_arg);
+       RETVAL_ZVAL(zrv, 0, 0);
+       efree(zrv);
+}
+
+static PHP_FUNCTION(raphf_handle_copy)
+{
+       zval *zrf, *zrv, *zhandle;
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz",
+                       &zrf, &zhandle)) {
+               return;
+       }
+
+       zrv = php_resource_factory_handle_copy(Z_RES_VAL_P(zrf), zhandle);
+       RETVAL_ZVAL(zrv, 0, 0);
+       efree(zrv);
+}
+
+static PHP_FUNCTION(raphf_handle_dtor)
+{
+       zval *zrf, *zhandle;
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz",
+                       &zrf, &zhandle)) {
+               return;
+       }
+
+       php_resource_factory_handle_dtor(Z_RES_VAL_P(zrf), zhandle);
+}
+
+static PHP_MINIT_FUNCTION(raphf_test)
+{
+       raphf_user_le = zend_register_list_destructors_ex(raphf_user_res_dtor, NULL,
+                       "raphf_user", module_number);
+       return SUCCESS;
+}
+
+static PHP_MSHUTDOWN_FUNCTION(raphf_test)
+{
+       php_persistent_handle_cleanup(ZEND_STRL("test"), NULL, 0 TSRMLS_CC);
+       return SUCCESS;
+}
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/raphf_test.php b/raphf_test.php
new file mode 100644 (file)
index 0000000..70b06de
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+function dumper($id) {
+       return function() use ($id) {
+               echo "### back '$id':\n";
+               for ($i=0; $i<func_num_args(); ++$i) {
+                       echo "#### arg $i: ";
+                       var_dump(func_get_arg($i));
+               }
+               /* relay arguments back */
+               return func_get_args();
+       };
+}
+
+echo "## call provide:\n";
+var_dump(raphf\provide("test",dumper("ctor"),dumper("copy"),dumper("dtor"),"data value",dumper("data_dtor")));
+
+echo "## call concede:\n";
+var_dump($rf = raphf\concede("test","1"));
+
+echo "## call handle_ctor:\n";
+var_dump($h = raphf\handle_ctor($rf, 1));
+
+echo "## call handle_copy:\n";
+var_dump($h2 = raphf\handle_copy($rf, $h));
+
+var_dump(raphf\stat_persistent_handles());
+
+echo "## call handle_dtor:\n";
+var_dump(raphf\handle_dtor($rf, $h));
+var_dump(raphf\stat_persistent_handles());
+
+echo "## call handle_dtor:\n";
+var_dump(raphf\handle_dtor($rf, $h2));
+var_dump(raphf\stat_persistent_handles());
+
+var_dump(raphf\dispute($rf), $rf);
+