a2e0ba908b258b6cc9e5b8750b69d306aefd5b54
[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_handle_t {
32 void *ptr;
33 } http_persistent_handle;
34
35 typedef HashTable *http_persistent_handle_list;
36
37 typedef struct _http_persistent_handle_provider_t {
38 http_persistent_handle_list list; /* "ident" => array(handles) entries */
39 http_persistent_handle_ctor ctor;
40 http_persistent_handle_dtor dtor;
41 } http_persistent_handle_provider;
42
43 static void http_persistent_handles_hash_dtor(void *p)
44 {
45 http_persistent_handle_provider *provider = (http_persistent_handle_provider *) p;
46 http_persistent_handle_list *list;
47 http_persistent_handle *handle;
48 HashPosition pos1, pos2;
49
50 FOREACH_HASH_VAL(pos1, provider->list, list) {
51 FOREACH_HASH_VAL(pos2, *list, handle) {
52 provider->dtor(handle->ptr);
53 }
54 zend_hash_destroy(*list);
55 pefree(*list, 1);
56 }
57 zend_hash_destroy(provider->list);
58 pefree(provider->list, 1);
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 = FAILURE;
82 http_persistent_handle_provider provider;
83
84 LOCK();
85 provider.list = pemalloc(sizeof(HashTable), 1);
86 if (provider.list) {
87 provider.ctor = ctor;
88 provider.dtor = dtor;
89 zend_hash_init(provider.list, 0, NULL, NULL, 1);
90 if (SUCCESS == zend_hash_add(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &provider, sizeof(http_persistent_handle_provider), NULL)) {
91 status = SUCCESS;
92 } else {
93 pefree(provider.list, 1);
94 }
95 }
96 UNLOCK();
97
98 return status;
99 }
100
101 PHP_HTTP_API STATUS _http_persistent_handle_acquire_ex(const char *name_str, size_t name_len, void **handle_ptr TSRMLS_DC)
102 {
103 STATUS status = FAILURE;
104 ulong index;
105 http_persistent_handle_provider *provider;
106 http_persistent_handle_list *list;
107 http_persistent_handle *handle;
108
109 *handle_ptr = NULL;
110 LOCK();
111 if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &provider)) {
112 if (SUCCESS == zend_hash_quick_find(provider->list, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &list)) {
113 zend_hash_internal_pointer_end(*list);
114 if (HASH_KEY_NON_EXISTANT != zend_hash_get_current_key(*list, NULL, &index, 0) && SUCCESS == zend_hash_get_current_data(*list, (void *) &handle)) {
115 *handle_ptr = handle->ptr;
116 zend_hash_index_del(*list, index);
117 }
118 }
119 if (*handle_ptr || (*handle_ptr = provider->ctor())) {
120 status = SUCCESS;
121 }
122 }
123 UNLOCK();
124
125 return status;
126 }
127
128 PHP_HTTP_API STATUS _http_persistent_handle_release_ex(const char *name_str, size_t name_len, void **handle_ptr TSRMLS_DC)
129 {
130 STATUS status = FAILURE;
131 http_persistent_handle_provider *provider;
132 http_persistent_handle_list *list, new_list;
133 http_persistent_handle handle = {*handle_ptr};
134
135 LOCK();
136 if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &provider)) {
137 if (SUCCESS == zend_hash_quick_find(provider->list, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &list)) {
138 status = zend_hash_next_index_insert(*list, (void *) &handle, sizeof(http_persistent_handle), NULL);
139 } else if ((new_list = pemalloc(sizeof(HashTable), 1))) {
140 zend_hash_init(new_list, 0, NULL, NULL, 1);
141 if ( SUCCESS == zend_hash_next_index_insert(new_list, (void *) &handle, sizeof(http_persistent_handle), NULL) &&
142 SUCCESS == zend_hash_quick_add(provider->list, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &new_list, sizeof(http_persistent_handle_list *), NULL)) {
143 status = SUCCESS;
144 } else {
145 pefree(new_list, 1);
146 }
147 }
148 }
149 UNLOCK();
150
151 return status;
152 }
153
154 PHP_HTTP_API void _http_persistent_handle_cleanup_ex(const char *name_str, size_t name_len, int current_ident_only TSRMLS_DC)
155 {
156 http_persistent_handle_provider *provider;
157 http_persistent_handle_list *list;
158 http_persistent_handle *handle;
159 HashPosition pos1, pos2, pos3;
160
161 LOCK();
162 if (name_str && name_len) {
163 if (SUCCESS == zend_hash_find(&http_persistent_handles_hash, (char *) name_str, name_len+1, (void *) &provider)) {
164 if (current_ident_only) {
165 if (SUCCESS == zend_hash_quick_find(provider->list, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &list)) {
166 FOREACH_HASH_VAL(pos1, *list, handle) {
167 provider->dtor(handle->ptr);
168 }
169 zend_hash_clean(*list);
170 }
171 } else {
172 FOREACH_HASH_VAL(pos1, provider->list, list) {
173 FOREACH_HASH_VAL(pos2, *list, handle) {
174 provider->dtor(handle->ptr);
175 }
176 zend_hash_clean(*list);
177 }
178 }
179 }
180 } else {
181 FOREACH_HASH_VAL(pos1, &http_persistent_handles_hash, provider) {
182 if (current_ident_only) {
183 if (SUCCESS == zend_hash_quick_find(provider->list, HTTP_G->persistent.handles.ident.s, HTTP_G->persistent.handles.ident.l, HTTP_G->persistent.handles.ident.h, (void *) &list)) {
184 FOREACH_HASH_VAL(pos2, *list, handle) {
185 provider->dtor(handle->ptr);
186 }
187 zend_hash_clean(*list);
188 }
189 } else {
190 FOREACH_HASH_VAL(pos2, provider->list, list) {
191 FOREACH_HASH_VAL(pos3, *list, handle) {
192 provider->dtor(handle->ptr);
193 }
194 zend_hash_clean(*list);
195 }
196 }
197 }
198 }
199 UNLOCK();
200 }
201
202 PHP_HTTP_API HashTable *_http_persistent_handle_statall_ex(HashTable *ht)
203 {
204 zval *zlist, *zentry;
205 HashPosition pos1, pos2;
206 HashKey key1 = initHashKey(0), key2 = initHashKey(0);
207 http_persistent_handle_provider *provider;
208 http_persistent_handle_list *list;
209
210 LOCK();
211 if (zend_hash_num_elements(&http_persistent_handles_hash)) {
212 if (!ht) {
213 ALLOC_HASHTABLE(ht);
214 zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
215 }
216
217 FOREACH_HASH_KEYVAL(pos1, &http_persistent_handles_hash, key1, provider) {
218 MAKE_STD_ZVAL(zlist);
219 array_init(zlist);
220 FOREACH_HASH_KEYVAL(pos2, provider->list, key2, list) {
221 MAKE_STD_ZVAL(zentry);
222 ZVAL_LONG(zentry, zend_hash_num_elements(*list));
223 zend_hash_quick_add(Z_ARRVAL_P(zlist), key2.str, key2.len, key2.num, (void *) &zentry, sizeof(zval *), NULL);
224 }
225 zend_hash_quick_add(ht, key1.str, key1.len, key1.num, (void *) &zlist, sizeof(zval *), NULL);
226 }
227 } else if (ht) {
228 ht = NULL;
229 }
230 UNLOCK();
231
232 return ht;
233 }
234
235 #endif /* HTTP_HAVE_PERSISTENT_HANDLES */
236
237 /*
238 * Local variables:
239 * tab-width: 4
240 * c-basic-offset: 4
241 * End:
242 * vim600: noet sw=4 ts=4 fdm=marker
243 * vim<600: noet sw=4 ts=4
244 */
245