2 +--------------------------------------------------------------------+
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 +--------------------------------------------------------------------+
16 #include "php_http_api.h"
18 #ifdef HTTP_HAVE_PERSISTENT_HANDLES
19 #include "php_http_persistent_handle_api.h"
21 #ifndef HTTP_DEBUG_PHANDLES
22 # define HTTP_DEBUG_PHANDLES 0
25 static HashTable http_persistent_handles_hash
;
27 # define LOCK() tsrm_mutex_lock(http_persistent_handles_lock)
28 # define UNLOCK() tsrm_mutex_unlock(http_persistent_handles_lock)
29 static MUTEX_T http_persistent_handles_lock
;
35 typedef struct _http_persistent_handle_t
{
37 } http_persistent_handle
;
39 typedef HashTable
*http_persistent_handle_list
;
41 typedef struct _http_persistent_handle_provider_t
{
42 http_persistent_handle_list list
; /* "ident" => array(handles) entries */
43 http_persistent_handle_ctor ctor
;
44 http_persistent_handle_dtor dtor
;
45 } http_persistent_handle_provider
;
47 static void http_persistent_handles_hash_dtor(void *p
)
49 http_persistent_handle_provider
*provider
= (http_persistent_handle_provider
*) p
;
50 http_persistent_handle_list
*list
;
51 http_persistent_handle
*handle
;
52 HashPosition pos1
, pos2
;
54 #if HTTP_DEBUG_PHANDLES
55 fprintf(stderr
, "DESTROY: %p\n", provider
->list
);
58 FOREACH_HASH_VAL(pos1
, provider
->list
, list
) {
59 FOREACH_HASH_VAL(pos2
, *list
, handle
) {
60 provider
->dtor(handle
->ptr
);
62 zend_hash_destroy(*list
);
65 zend_hash_destroy(provider
->list
);
66 pefree(provider
->list
, 1);
69 PHP_MINIT_FUNCTION(http_persistent_handle
)
71 zend_hash_init(&http_persistent_handles_hash
, 0, NULL
, http_persistent_handles_hash_dtor
, 1);
73 http_persistent_handles_lock
= tsrm_mutex_alloc();
78 PHP_MSHUTDOWN_FUNCTION(http_persistent_handle
)
80 zend_hash_destroy(&http_persistent_handles_hash
);
82 tsrm_mutex_free(http_persistent_handles_lock
);
87 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
)
89 STATUS status
= FAILURE
;
90 http_persistent_handle_provider provider
;
93 provider
.list
= pemalloc(sizeof(HashTable
), 1);
97 zend_hash_init(provider
.list
, 0, NULL
, NULL
, 1);
99 #if HTTP_DEBUG_PHANDLES
100 fprintf(stderr
, "PROVIDE: %p (%s)\n", provider
.list
, name_str
);
103 if (SUCCESS
== zend_hash_add(&http_persistent_handles_hash
, (char *) name_str
, name_len
+1, (void *) &provider
, sizeof(http_persistent_handle_provider
), NULL
)) {
106 pefree(provider
.list
, 1);
114 PHP_HTTP_API STATUS
_http_persistent_handle_acquire_ex(const char *name_str
, size_t name_len
, void **handle_ptr TSRMLS_DC
)
116 STATUS status
= FAILURE
;
118 http_persistent_handle_provider
*provider
;
119 http_persistent_handle_list
*list
;
120 http_persistent_handle
*handle
;
124 if (SUCCESS
== zend_hash_find(&http_persistent_handles_hash
, (char *) name_str
, name_len
+1, (void *) &provider
)) {
125 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
)) {
126 zend_hash_internal_pointer_end(*list
);
127 if (HASH_KEY_NON_EXISTANT
!= zend_hash_get_current_key(*list
, NULL
, &index
, 0) && SUCCESS
== zend_hash_get_current_data(*list
, (void *) &handle
)) {
128 *handle_ptr
= handle
->ptr
;
129 zend_hash_index_del(*list
, index
);
132 if (*handle_ptr
|| (*handle_ptr
= provider
->ctor())) {
138 #if HTTP_DEBUG_PHANDLES
139 fprintf(stderr
, "ACQUIRE: %p (%s)\n", *handle_ptr
, name_str
);
145 PHP_HTTP_API STATUS
_http_persistent_handle_release_ex(const char *name_str
, size_t name_len
, void **handle_ptr TSRMLS_DC
)
147 STATUS status
= FAILURE
;
148 http_persistent_handle_provider
*provider
;
149 http_persistent_handle_list
*list
, new_list
;
150 http_persistent_handle handle
= {*handle_ptr
};
153 if (SUCCESS
== zend_hash_find(&http_persistent_handles_hash
, (char *) name_str
, name_len
+1, (void *) &provider
)) {
154 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
)) {
155 status
= zend_hash_next_index_insert(*list
, (void *) &handle
, sizeof(http_persistent_handle
), NULL
);
156 } else if ((new_list
= pemalloc(sizeof(HashTable
), 1))) {
157 zend_hash_init(new_list
, 0, NULL
, NULL
, 1);
158 if ( SUCCESS
== zend_hash_next_index_insert(new_list
, (void *) &handle
, sizeof(http_persistent_handle
), NULL
) &&
159 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
)) {
162 zend_hash_destroy(new_list
);
169 #if HTTP_DEBUG_PHANDLES
170 fprintf(stderr
, "RELEASE: %p (%s)\n", *handle_ptr
, name_str
);
176 PHP_HTTP_API
void _http_persistent_handle_cleanup_ex(const char *name_str
, size_t name_len
, int current_ident_only TSRMLS_DC
)
178 http_persistent_handle_provider
*provider
;
179 http_persistent_handle_list
*list
;
180 http_persistent_handle
*handle
;
181 HashPosition pos1
, pos2
, pos3
;
184 if (name_str
&& name_len
) {
185 if (SUCCESS
== zend_hash_find(&http_persistent_handles_hash
, (char *) name_str
, name_len
+1, (void *) &provider
)) {
186 if (current_ident_only
) {
187 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
)) {
188 FOREACH_HASH_VAL(pos1
, *list
, handle
) {
189 provider
->dtor(handle
->ptr
);
191 zend_hash_clean(*list
);
194 FOREACH_HASH_VAL(pos1
, provider
->list
, list
) {
195 FOREACH_HASH_VAL(pos2
, *list
, handle
) {
196 provider
->dtor(handle
->ptr
);
198 zend_hash_clean(*list
);
203 FOREACH_HASH_VAL(pos1
, &http_persistent_handles_hash
, provider
) {
204 if (current_ident_only
) {
205 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
)) {
206 FOREACH_HASH_VAL(pos2
, *list
, handle
) {
207 provider
->dtor(handle
->ptr
);
209 zend_hash_clean(*list
);
212 FOREACH_HASH_VAL(pos2
, provider
->list
, list
) {
213 FOREACH_HASH_VAL(pos3
, *list
, handle
) {
214 provider
->dtor(handle
->ptr
);
216 zend_hash_clean(*list
);
224 PHP_HTTP_API HashTable
*_http_persistent_handle_statall_ex(HashTable
*ht
)
226 zval
*zlist
, *zentry
;
227 HashPosition pos1
, pos2
;
228 HashKey key1
= initHashKey(0), key2
= initHashKey(0);
229 http_persistent_handle_provider
*provider
;
230 http_persistent_handle_list
*list
;
233 if (zend_hash_num_elements(&http_persistent_handles_hash
)) {
236 zend_hash_init(ht
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
239 FOREACH_HASH_KEYVAL(pos1
, &http_persistent_handles_hash
, key1
, provider
) {
240 MAKE_STD_ZVAL(zlist
);
242 FOREACH_HASH_KEYVAL(pos2
, provider
->list
, key2
, list
) {
243 MAKE_STD_ZVAL(zentry
);
244 ZVAL_LONG(zentry
, zend_hash_num_elements(*list
));
245 zend_hash_quick_add(Z_ARRVAL_P(zlist
), key2
.str
, key2
.len
, key2
.num
, (void *) &zentry
, sizeof(zval
*), NULL
);
247 zend_hash_quick_add(ht
, key1
.str
, key1
.len
, key1
.num
, (void *) &zlist
, sizeof(zval
*), NULL
);
257 #endif /* HTTP_HAVE_PERSISTENT_HANDLES */
264 * vim600: noet sw=4 ts=4 fdm=marker
265 * vim<600: noet sw=4 ts=4