1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 2.00 of the Zend license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.zend.com/license/2_00.txt. |
11 : | If you did not receive a copy of the Zend license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@zend.com so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Andi Gutmans <andi@zend.com> |
16 : | Zeev Suraski <zeev@zend.com> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: zend_list.c 272367 2008-12-31 11:12:40Z sebastian $ */
21 :
22 : /* resource lists */
23 :
24 : #include "zend.h"
25 : #include "zend_list.h"
26 : #include "zend_API.h"
27 : #include "zend_globals.h"
28 :
29 : ZEND_API int le_index_ptr;
30 :
31 : /* true global */
32 : static HashTable list_destructors;
33 :
34 : ZEND_API int zend_list_insert(void *ptr, int type) /* {{{ */
35 505592 : {
36 : int index;
37 : zend_rsrc_list_entry le;
38 : TSRMLS_FETCH();
39 :
40 505592 : le.ptr=ptr;
41 505592 : le.type=type;
42 505592 : le.refcount=1;
43 :
44 505592 : index = zend_hash_next_free_element(&EG(regular_list));
45 :
46 505592 : zend_hash_index_update(&EG(regular_list), index, (void *) &le, sizeof(zend_rsrc_list_entry), NULL);
47 505592 : return index;
48 : }
49 : /* }}} */
50 :
51 : ZEND_API int _zend_list_delete(int id TSRMLS_DC) /* {{{ */
52 1275060 : {
53 : zend_rsrc_list_entry *le;
54 :
55 1275060 : if (zend_hash_index_find(&EG(regular_list), id, (void **) &le)==SUCCESS) {
56 : /* printf("del(%d): %d->%d\n", id, le->refcount, le->refcount-1); */
57 1072528 : if (--le->refcount<=0) {
58 498929 : return zend_hash_index_del(&EG(regular_list), id);
59 : } else {
60 573599 : return SUCCESS;
61 : }
62 : } else {
63 202532 : return FAILURE;
64 : }
65 : }
66 : /* }}} */
67 :
68 : ZEND_API void *_zend_list_find(int id, int *type TSRMLS_DC) /* {{{ */
69 11421658 : {
70 : zend_rsrc_list_entry *le;
71 :
72 11421658 : if (zend_hash_index_find(&EG(regular_list), id, (void **) &le)==SUCCESS) {
73 8974033 : *type = le->type;
74 8974033 : return le->ptr;
75 : } else {
76 2447625 : *type = -1;
77 2447625 : return NULL;
78 : }
79 : }
80 : /* }}} */
81 :
82 : ZEND_API int _zend_list_addref(int id TSRMLS_DC) /* {{{ */
83 573639 : {
84 : zend_rsrc_list_entry *le;
85 :
86 573639 : if (zend_hash_index_find(&EG(regular_list), id, (void **) &le)==SUCCESS) {
87 : /* printf("add(%d): %d->%d\n", id, le->refcount, le->refcount+1); */
88 573603 : le->refcount++;
89 573603 : return SUCCESS;
90 : } else {
91 36 : return FAILURE;
92 : }
93 : }
94 : /* }}} */
95 :
96 : ZEND_API int zend_register_resource(zval *rsrc_result, void *rsrc_pointer, int rsrc_type) /* {{{ */
97 504958 : {
98 : int rsrc_id;
99 :
100 504958 : rsrc_id = zend_list_insert(rsrc_pointer, rsrc_type);
101 :
102 504958 : if (rsrc_result) {
103 21370 : Z_RESVAL_P(rsrc_result) = rsrc_id;
104 21370 : Z_TYPE_P(rsrc_result) = IS_RESOURCE;
105 : }
106 :
107 504958 : return rsrc_id;
108 : }
109 : /* }}} */
110 :
111 : ZEND_API void *zend_fetch_resource(zval **passed_id TSRMLS_DC, int default_id, char *resource_type_name, int *found_resource_type, int num_resource_types, ...) /* {{{ */
112 11147031 : {
113 : int id;
114 : int actual_resource_type;
115 : void *resource;
116 : va_list resource_types;
117 : int i;
118 : char *space;
119 : zstr class_name;
120 :
121 11147031 : if (default_id==-1) { /* use id */
122 11146903 : if (!passed_id) {
123 3 : if (resource_type_name) {
124 3 : class_name = get_active_class_name(&space TSRMLS_CC);
125 3 : zend_error(E_WARNING, "%v%s%v(): no %s resource supplied", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name);
126 : }
127 3 : return NULL;
128 11146900 : } else if (Z_TYPE_PP(passed_id) != IS_RESOURCE) {
129 16 : if (resource_type_name) {
130 16 : class_name = get_active_class_name(&space TSRMLS_CC);
131 16 : zend_error(E_WARNING, "%v%s%v(): supplied argument is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name);
132 : }
133 16 : return NULL;
134 : }
135 11146884 : id = Z_RESVAL_PP(passed_id);
136 : } else {
137 128 : id = default_id;
138 : }
139 :
140 11147012 : resource = zend_list_find(id, &actual_resource_type);
141 11147012 : if (!resource) {
142 2447512 : if (resource_type_name) {
143 2447511 : class_name = get_active_class_name(&space TSRMLS_CC);
144 2447511 : zend_error(E_WARNING, "%v%s%v(): %d is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), id, resource_type_name);
145 : }
146 2447512 : return NULL;
147 : }
148 :
149 8699500 : va_start(resource_types, num_resource_types);
150 8699778 : for (i=0; i<num_resource_types; i++) {
151 8699663 : if (actual_resource_type == va_arg(resource_types, int)) {
152 8699385 : va_end(resource_types);
153 8699385 : if (found_resource_type) {
154 8751 : *found_resource_type = actual_resource_type;
155 : }
156 8699385 : return resource;
157 : }
158 : }
159 115 : va_end(resource_types);
160 :
161 115 : if (resource_type_name) {
162 98 : class_name = get_active_class_name(&space TSRMLS_CC);
163 98 : zend_error(E_WARNING, "%v%s%v(): supplied resource is not a valid %s resource", class_name, space, get_active_function_name(TSRMLS_C), resource_type_name);
164 : }
165 :
166 115 : return NULL;
167 : }
168 : /* }}} */
169 :
170 : void list_entry_destructor(void *ptr) /* {{{ */
171 506906 : {
172 506906 : zend_rsrc_list_entry *le = (zend_rsrc_list_entry *) ptr;
173 : zend_rsrc_list_dtors_entry *ld;
174 : TSRMLS_FETCH();
175 :
176 506906 : if (zend_hash_index_find(&list_destructors, le->type, (void **) &ld)==SUCCESS) {
177 506906 : switch (ld->type) {
178 : case ZEND_RESOURCE_LIST_TYPE_STD:
179 0 : if (ld->list_dtor) {
180 0 : (ld->list_dtor)(le->ptr);
181 : }
182 0 : break;
183 : case ZEND_RESOURCE_LIST_TYPE_EX:
184 506906 : if (ld->list_dtor_ex) {
185 504904 : ld->list_dtor_ex(le TSRMLS_CC);
186 : }
187 : break;
188 : EMPTY_SWITCH_DEFAULT_CASE()
189 : }
190 : } else {
191 0 : zend_error(E_WARNING,"Unknown list entry type in request shutdown (%d)", le->type);
192 : }
193 506905 : }
194 : /* }}} */
195 :
196 : void plist_entry_destructor(void *ptr) /* {{{ */
197 1313 : {
198 1313 : zend_rsrc_list_entry *le = (zend_rsrc_list_entry *) ptr;
199 : zend_rsrc_list_dtors_entry *ld;
200 : TSRMLS_FETCH();
201 :
202 1313 : if (zend_hash_index_find(&list_destructors, le->type, (void **) &ld)==SUCCESS) {
203 1313 : switch (ld->type) {
204 : case ZEND_RESOURCE_LIST_TYPE_STD:
205 0 : if (ld->plist_dtor) {
206 0 : (ld->plist_dtor)(le->ptr);
207 : }
208 0 : break;
209 : case ZEND_RESOURCE_LIST_TYPE_EX:
210 1313 : if (ld->plist_dtor_ex) {
211 1313 : ld->plist_dtor_ex(le TSRMLS_CC);
212 : }
213 : break;
214 : EMPTY_SWITCH_DEFAULT_CASE()
215 : }
216 : } else {
217 0 : zend_error(E_WARNING,"Unknown persistent list entry type in module shutdown (%d)", le->type);
218 : }
219 1313 : }
220 : /* }}} */
221 :
222 : int zend_init_rsrc_list(TSRMLS_D) /* {{{ */
223 16993 : {
224 16993 : if (zend_hash_init(&EG(regular_list), 0, NULL, list_entry_destructor, 0)==SUCCESS) {
225 16993 : EG(regular_list).nNextFreeElement=1; /* we don't want resource id 0 */
226 16993 : return SUCCESS;
227 : } else {
228 0 : return FAILURE;
229 : }
230 : }
231 : /* }}} */
232 :
233 : int zend_init_rsrc_plist(TSRMLS_D) /* {{{ */
234 17007 : {
235 17007 : return zend_hash_init_ex(&EG(persistent_list), 0, NULL, plist_entry_destructor, 1, 0);
236 : }
237 : /* }}} */
238 :
239 : void zend_destroy_rsrc_list(HashTable *ht TSRMLS_DC) /* {{{ */
240 34064 : {
241 34064 : zend_hash_graceful_reverse_destroy(ht);
242 34064 : }
243 : /* }}} */
244 :
245 : static int clean_module_resource(zend_rsrc_list_entry *le, int *resource_id TSRMLS_DC) /* {{{ */
246 0 : {
247 0 : if (le->type == *resource_id) {
248 0 : return 1;
249 : } else {
250 0 : return 0;
251 : }
252 : }
253 : /* }}} */
254 :
255 : static int zend_clean_module_rsrc_dtors_cb(zend_rsrc_list_dtors_entry *ld, int *module_number TSRMLS_DC) /* {{{ */
256 0 : {
257 0 : if (ld->module_number == *module_number) {
258 0 : zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) clean_module_resource, (void *) &(ld->resource_id) TSRMLS_CC);
259 0 : return 1;
260 : } else {
261 0 : return 0;
262 : }
263 : }
264 : /* }}} */
265 :
266 : void zend_clean_module_rsrc_dtors(int module_number TSRMLS_DC) /* {{{ */
267 0 : {
268 0 : zend_hash_apply_with_argument(&list_destructors, (apply_func_arg_t) zend_clean_module_rsrc_dtors_cb, (void *) &module_number TSRMLS_CC);
269 0 : }
270 : /* }}} */
271 :
272 : ZEND_API int zend_register_list_destructors(void (*ld)(void *), void (*pld)(void *), int module_number) /* {{{ */
273 0 : {
274 : zend_rsrc_list_dtors_entry lde;
275 :
276 : #if 0
277 : printf("Registering destructors %d for module %d\n", list_destructors.nNextFreeElement, module_number);
278 : #endif
279 :
280 0 : lde.list_dtor=(void (*)(void *)) ld;
281 0 : lde.plist_dtor=(void (*)(void *)) pld;
282 0 : lde.list_dtor_ex = lde.plist_dtor_ex = NULL;
283 0 : lde.module_number = module_number;
284 0 : lde.resource_id = list_destructors.nNextFreeElement;
285 0 : lde.type = ZEND_RESOURCE_LIST_TYPE_STD;
286 0 : lde.type_name = NULL;
287 :
288 0 : if (zend_hash_next_index_insert(&list_destructors, (void *) &lde, sizeof(zend_rsrc_list_dtors_entry), NULL)==FAILURE) {
289 0 : return FAILURE;
290 : }
291 0 : return list_destructors.nNextFreeElement-1;
292 : }
293 : /* }}} */
294 :
295 : ZEND_API int zend_register_list_destructors_ex(rsrc_dtor_func_t ld, rsrc_dtor_func_t pld, char *type_name, int module_number) /* {{{ */
296 1020420 : {
297 : zend_rsrc_list_dtors_entry lde;
298 :
299 : #if 0
300 : printf("Registering destructors %d for module %d\n", list_destructors.nNextFreeElement, module_number);
301 : #endif
302 :
303 1020420 : lde.list_dtor = NULL;
304 1020420 : lde.plist_dtor = NULL;
305 1020420 : lde.list_dtor_ex = ld;
306 1020420 : lde.plist_dtor_ex = pld;
307 1020420 : lde.module_number = module_number;
308 1020420 : lde.resource_id = list_destructors.nNextFreeElement;
309 1020420 : lde.type = ZEND_RESOURCE_LIST_TYPE_EX;
310 1020420 : lde.type_name = type_name;
311 :
312 1020420 : if (zend_hash_next_index_insert(&list_destructors, (void *) &lde, sizeof(zend_rsrc_list_dtors_entry), NULL)==FAILURE) {
313 0 : return FAILURE;
314 : }
315 1020420 : return list_destructors.nNextFreeElement-1;
316 : }
317 : /* }}} */
318 :
319 : ZEND_API int zend_fetch_list_dtor_id(char *type_name) /* {{{ */
320 0 : {
321 : zend_rsrc_list_dtors_entry *lde;
322 : HashPosition pos;
323 :
324 0 : zend_hash_internal_pointer_reset_ex(&list_destructors, &pos);
325 0 : while (zend_hash_get_current_data_ex(&list_destructors, (void **)&lde, &pos) == SUCCESS) {
326 0 : if (lde->type_name && (strcmp(type_name, lde->type_name) == 0)) {
327 : #if 0
328 : printf("Found resource id %d for resource type %s\n", (*lde).resource_id, type_name);
329 : #endif
330 0 : return lde->resource_id;
331 : }
332 0 : zend_hash_move_forward_ex(&list_destructors, &pos);
333 : }
334 :
335 0 : return 0;
336 : }
337 : /* }}} */
338 :
339 : int zend_init_rsrc_list_dtors(void) /* {{{ */
340 17007 : {
341 : int retval;
342 :
343 17007 : retval = zend_hash_init(&list_destructors, 50, NULL, NULL, 1);
344 17007 : list_destructors.nNextFreeElement=1; /* we don't want resource type 0 */
345 :
346 17007 : return retval;
347 : }
348 : /* }}} */
349 :
350 : void zend_destroy_rsrc_list_dtors(void) /* {{{ */
351 17039 : {
352 17039 : zend_hash_destroy(&list_destructors);
353 17039 : }
354 : /* }}} */
355 :
356 : char *zend_rsrc_list_get_rsrc_type(int resource TSRMLS_DC) /* {{{ */
357 963 : {
358 : zend_rsrc_list_dtors_entry *lde;
359 : int rsrc_type;
360 :
361 963 : if (!zend_list_find(resource, &rsrc_type))
362 80 : return NULL;
363 :
364 883 : if (zend_hash_index_find(&list_destructors, rsrc_type, (void **) &lde)==SUCCESS) {
365 883 : return lde->type_name;
366 : } else {
367 0 : return NULL;
368 : }
369 : }
370 : /* }}} */
371 :
372 : /*
373 : * Local variables:
374 : * tab-width: 4
375 : * c-basic-offset: 4
376 : * indent-tabs-mode: t
377 : * End:
378 : */
|