- add persistent cURL handle support
[m6w6/ext-http] / http_persistent_handle_api.c
diff --git a/http_persistent_handle_api.c b/http_persistent_handle_api.c
new file mode 100644 (file)
index 0000000..8fc1b02
--- /dev/null
@@ -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 <mike@php.net>            |
+    +--------------------------------------------------------------------+
+*/
+
+/* $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
+ */
+