- use a HashTable to stat persistent handles
[m6w6/ext-http] / http_persistent_handle_api.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: http |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2004-2006, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 /* $Id$ */
14
15 #include "php_http.h"
16 #include "php_http_api.h"
17
18 #ifdef HTTP_HAVE_PERSISTENT_HANDLES
19 #include "php_http_persistent_handle_api.h"
20
21 static HashTable http_persistent_handles_hash;
22 #ifdef ZTS
23 # define LOCK() tsrm_mutex_lock(http_persistent_handles_lock)
24 # define UNLOCK() tsrm_mutex_unlock(http_persistent_handles_lock)
25 static MUTEX_T http_persistent_handles_lock;
26 #else
27 # define LOCK()
28 # define UNLOCK()
29 #endif
30
31 typedef struct _http_persistent_handles_hash_entry_t {
32 HashTable list;
33 http_persistent_handle_ctor ctor;
34 http_persistent_handle_dtor dtor;
35 } http_persistent_handles_hash_entry;
36
37 typedef struct _http_persistent_handles_list_entry_t {
38 void *handle;
39 } http_persistent_handles_list_entry;
40
41 static inline void http_persistent_handles_hash_dtor_ex(http_persistent_handles_hash_entry *hentry, void (*list_dtor)(HashTable*))
42 {
43 http_persistent_handles_list_entry *lentry;
44
45 for ( zend_hash_internal_pointer_reset(&hentry->list);
46 SUCCESS == zend_hash_get_current_data(&hentry->list, (void *) &lentry);
47 zend_hash_move_forward(&hentry->list)) {
48 hentry->dtor(lentry->handle);
49 }
50
51 if (list_dtor) {
52 list_dtor(&hentry->list);
53 }
54 }
55
56 static void http_persistent_handles_hash_dtor(void *h)
57 {
58 http_persistent_handles_hash_dtor_ex(h, zend_hash_destroy);
59 }
60
61 PHP_MINIT_FUNCTION(http_persistent_handle)
62 {
63 zend_hash_init(&http_persistent_handles_hash, 0, NULL, http_persistent_handles_hash_dtor, 1);
64 #ifdef ZTS
65 http_persistent_handles_lock = tsrm_mutex_alloc();
66 #endif
67 return SUCCESS;
68 }
69
70 PHP_MSHUTDOWN_FUNCTION(http_persistent_handle)
71 {
72 zend_hash_destroy(&http_persistent_handles_hash);
73 #ifdef ZTS
74 tsrm_mutex_free(http_persistent_handles_lock);
75 #endif
76 return SUCCESS;
77 }
78
79 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)
80 {
81 STATUS status = SUCCESS;
82 http_persistent_handles_hash_entry e;
83
84 zend_hash_init(&e.list, 0, NULL, NULL, 1);
85 e.ctor = ctor;
86 e.dtor = dtor;
87
88 LOCK();
89 if (SUCCESS != zend_hash_add(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &e, sizeof(http_persistent_handles_hash_entry), NULL)) {
90 zend_hash_destroy(&e.list);
91 status = FAILURE;
92 }
93 UNLOCK();
94
95 return status;
96 }
97
98 PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len)
99 {
100 http_persistent_handles_hash_entry *hentry;
101
102 LOCK();
103 if (name_str && name_len) {
104 if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &hentry)) {
105 http_persistent_handles_hash_dtor_ex(hentry, zend_hash_clean);
106 }
107 } else {
108 for ( zend_hash_internal_pointer_reset(&http_persistent_handles_hash);
109 SUCCESS == zend_hash_get_current_data(&http_persistent_handles_hash, (void *) &hentry);
110 zend_hash_move_forward(&http_persistent_handles_hash)) {
111 http_persistent_handles_hash_dtor_ex(hentry, zend_hash_clean);
112 }
113 }
114 UNLOCK();
115 }
116
117 PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht)
118 {
119 zval *tmp;
120 HashPosition pos;
121 HashKey key = initHashKey(0);
122 http_persistent_handles_hash_entry *hentry;
123
124 LOCK();
125 if (zend_hash_num_elements(&http_persistent_handles_hash)) {
126 if (!ht) {
127 ALLOC_HASHTABLE(ht);
128 zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
129 }
130
131 FOREACH_HASH_KEYVAL(pos, &http_persistent_handles_hash, key, hentry) {
132 MAKE_STD_ZVAL(tmp);
133 ZVAL_LONG(tmp, zend_hash_num_elements(&hentry->list));
134 zend_hash_add(ht, key.str, key.len, (void *) &tmp, sizeof(zval *), NULL);
135 }
136 } else if (ht) {
137 ht = NULL;
138 }
139 UNLOCK();
140
141 return ht;
142 }
143
144 PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle)
145 {
146 STATUS status = FAILURE;
147 ulong index;
148 http_persistent_handles_hash_entry *hentry;
149 http_persistent_handles_list_entry *lentry;
150
151 LOCK();
152 if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &hentry)) {
153 zend_hash_internal_pointer_end(&hentry->list);
154 if ( HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(&hentry->list, NULL, &index, 0) &&
155 SUCCESS == zend_hash_get_current_data(&hentry->list, (void *) &lentry)) {
156 *handle = lentry->handle;
157 zend_hash_index_del(&hentry->list, index);
158 status = SUCCESS;
159 } else if ((*handle = hentry->ctor())) {
160 status = SUCCESS;
161 }
162 }
163 UNLOCK();
164
165 return status;
166 }
167
168 PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle)
169 {
170 STATUS status = FAILURE;
171 http_persistent_handles_hash_entry *hentry;
172 http_persistent_handles_list_entry lentry;
173
174 LOCK();
175 if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &hentry)) {
176 lentry.handle = *handle;
177 if (SUCCESS == zend_hash_next_index_insert(&hentry->list, (void *) &lentry, sizeof(http_persistent_handles_list_entry), NULL)) {
178 status = SUCCESS;
179 }
180 }
181 UNLOCK();
182
183 return status;
184 }
185
186 #endif /* HTTP_HAVE_PERSISTENT_HANDLES */
187
188 /*
189 * Local variables:
190 * tab-width: 4
191 * c-basic-offset: 4
192 * End:
193 * vim600: noet sw=4 ts=4 fdm=marker
194 * vim<600: noet sw=4 ts=4
195 */
196