X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=http_persistent_handle_api.c;fp=http_persistent_handle_api.c;h=8fc1b02f72d1a775d9a0a00c256472712774fd2c;hp=0000000000000000000000000000000000000000;hb=fa6e9a361695e1c273266c79d0d27ff19059bb8a;hpb=a0c54cae89e6c61a7f76037aa891898e6bd86e15 diff --git a/http_persistent_handle_api.c b/http_persistent_handle_api.c new file mode 100644 index 0000000..8fc1b02 --- /dev/null +++ b/http_persistent_handle_api.c @@ -0,0 +1,193 @@ +/* + +--------------------------------------------------------------------+ + | PECL :: http | + +--------------------------------------------------------------------+ + | 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) 2004-2006, Michael Wallner | + +--------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#include "php_http.h" + +#ifdef HTTP_HAVE_PERSISTENT_HANDLES + +#include "php_http_persistent_handle_api.h" + +static HashTable http_persistent_handles_hash; +#ifdef ZTS +# define LOCK() tsrm_mutex_lock(http_persistent_handles_lock) +# define UNLOCK() tsrm_mutex_unlock(http_persistent_handles_lock) +static MUTEX_T http_persistent_handles_lock; +#else +# define LOCK() +# define UNLOCK() +#endif + +typedef struct _http_persistent_handles_hash_entry_t { + HashTable list; + http_persistent_handle_ctor ctor; + http_persistent_handle_dtor dtor; +} http_persistent_handles_hash_entry; + +typedef struct _http_persistent_handles_list_entry_t { + void *handle; +} http_persistent_handles_list_entry; + +static inline void http_persistent_handles_hash_dtor_ex(http_persistent_handles_hash_entry *hentry, void (*list_dtor)(HashTable*)) +{ + http_persistent_handles_list_entry *lentry; + + for ( zend_hash_internal_pointer_reset(&hentry->list); + SUCCESS == zend_hash_get_current_data(&hentry->list, (void *) &lentry); + zend_hash_move_forward(&hentry->list)) { + hentry->dtor(lentry->handle); + } + + if (list_dtor) { + list_dtor(&hentry->list); + } +} + +static void http_persistent_handles_hash_dtor(void *h) +{ + http_persistent_handles_hash_dtor_ex(h, zend_hash_destroy); +} + +PHP_MINIT_FUNCTION(http_persistent_handle) +{ + zend_hash_init(&http_persistent_handles_hash, 0, NULL, http_persistent_handles_hash_dtor, 1); +#ifdef ZTS + http_persistent_handles_lock = tsrm_mutex_alloc(); +#endif + return SUCCESS; +} + +PHP_MSHUTDOWN_FUNCTION(http_persistent_handle) +{ + zend_hash_destroy(&http_persistent_handles_hash); +#ifdef ZTS + tsrm_mutex_free(http_persistent_handles_lock); +#endif + return SUCCESS; +} + +PHP_HTTP_API STATUS _http_persistent_handle_provide_ex(const char *name_str, size_t name_len, http_persistent_handle_ctor ctor, http_persistent_handle_dtor dtor) +{ + STATUS status = SUCCESS; + http_persistent_handles_hash_entry e; + + zend_hash_init(&e.list, 0, NULL, NULL, 1); + e.ctor = ctor; + e.dtor = dtor; + + LOCK(); + if (SUCCESS != zend_hash_add(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &e, sizeof(http_persistent_handles_hash_entry), NULL)) { + zend_hash_destroy(&e.list); + status = FAILURE; + } + UNLOCK(); + + return status; +} + +PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len) +{ + http_persistent_handles_hash_entry *hentry; + + LOCK(); + if (name_str && name_len) { + if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &hentry)) { + http_persistent_handles_hash_dtor_ex(hentry, zend_hash_clean); + } + } else { + for ( zend_hash_internal_pointer_reset(&http_persistent_handles_hash); + SUCCESS == zend_hash_get_current_data(&http_persistent_handles_hash, (void *) &hentry); + zend_hash_move_forward(&http_persistent_handles_hash)) { + http_persistent_handles_hash_dtor_ex(hentry, zend_hash_clean); + } + } + UNLOCK(); +} + +PHP_HTTP_API int _http_persistent_handle_statall_ex(char ***names, int **counts, int persistent) +{ + int i, n; + char *key; + http_persistent_handles_hash_entry *hentry; + + LOCK(); + if ((n = zend_hash_num_elements(&http_persistent_handles_hash))) { + *names = safe_pemalloc(n, sizeof(char **), 0, persistent); + *counts = safe_pemalloc(n, sizeof(int), 0, persistent); + + for ( i = 0, zend_hash_internal_pointer_reset(&http_persistent_handles_hash); + HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(&http_persistent_handles_hash, &key, NULL, 0) && + SUCCESS == zend_hash_get_current_data(&http_persistent_handles_hash, (void *) &hentry); + ++i, zend_hash_move_forward(&http_persistent_handles_hash)) { + (*names)[i] = pestrdup(key, persistent); + (*counts)[i] = zend_hash_num_elements(&hentry->list); + } + } + UNLOCK(); + + return n; +} + +PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle) +{ + STATUS status = FAILURE; + ulong index; + http_persistent_handles_hash_entry *hentry; + http_persistent_handles_list_entry *lentry; + + LOCK(); + if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &hentry)) { + zend_hash_internal_pointer_reset(&hentry->list); + if ( HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(&hentry->list, NULL, &index, 0) && + SUCCESS == zend_hash_get_current_data(&hentry->list, (void *) &lentry)) { + *handle = lentry->handle; + zend_hash_index_del(&hentry->list, index); + status = SUCCESS; + } else if ((*handle = hentry->ctor())) { + status = SUCCESS; + } + } + UNLOCK(); + + return status; +} + +PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle) +{ + STATUS status = FAILURE; + http_persistent_handles_hash_entry *hentry; + http_persistent_handles_list_entry lentry; + + LOCK(); + if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &hentry)) { + lentry.handle = *handle; + if (SUCCESS == zend_hash_next_index_insert(&hentry->list, (void *) &lentry, sizeof(http_persistent_handles_list_entry), NULL)) { + status = SUCCESS; + } + } + UNLOCK(); + + return status; +} + +#endif /* HTTP_HAVE_PERSISTENT_HANDLES */ + +/* + * 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 + */ +