Line data Source code
1 : /*
2 : +--------------------------------------------------------------------+
3 : | PECL :: raphf |
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) 2013, Michael Wallner <mike@php.net> |
10 : +--------------------------------------------------------------------+
11 : */
12 :
13 : #ifdef HAVE_CONFIG_H
14 : # include "config.h"
15 : #endif
16 :
17 : #include "php.h"
18 : #include "php_ini.h"
19 : #include "ext/standard/info.h"
20 : #include "php_raphf.h"
21 :
22 : struct php_persistent_handle_globals {
23 : ulong limit;
24 : HashTable hash;
25 : };
26 :
27 : ZEND_BEGIN_MODULE_GLOBALS(raphf)
28 : struct php_persistent_handle_globals persistent_handle;
29 : ZEND_END_MODULE_GLOBALS(raphf)
30 :
31 : #ifdef ZTS
32 : # define PHP_RAPHF_G ((zend_raphf_globals *) \
33 : (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(raphf_globals_id)])
34 : #else
35 : # define PHP_RAPHF_G (&raphf_globals)
36 : #endif
37 :
38 : ZEND_DECLARE_MODULE_GLOBALS(raphf)
39 :
40 : typedef int STATUS;
41 :
42 : #ifndef PHP_RAPHF_DEBUG_PHANDLES
43 : # define PHP_RAPHF_DEBUG_PHANDLES 0
44 : #endif
45 : #if PHP_RAPHF_DEBUG_PHANDLES
46 : # undef inline
47 : # define inline
48 : #endif
49 :
50 1224 : php_resource_factory_t *php_resource_factory_init(php_resource_factory_t *f,
51 : php_resource_factory_ops_t *fops, void *data, void (*dtor)(void *data))
52 : {
53 1224 : if (!f) {
54 105 : f = emalloc(sizeof(*f));
55 : }
56 1224 : memset(f, 0, sizeof(*f));
57 :
58 1224 : memcpy(&f->fops, fops, sizeof(*fops));
59 :
60 1224 : f->data = data;
61 1224 : f->dtor = dtor;
62 :
63 1224 : f->refcount = 1;
64 :
65 1224 : return f;
66 : }
67 :
68 0 : unsigned php_resource_factory_addref(php_resource_factory_t *rf)
69 : {
70 0 : return ++rf->refcount;
71 : }
72 :
73 1224 : void php_resource_factory_dtor(php_resource_factory_t *f)
74 : {
75 1224 : --f->refcount;
76 :
77 1224 : if (!f->refcount) {
78 1224 : if (f->dtor) {
79 20 : f->dtor(f->data);
80 : }
81 : }
82 1224 : }
83 :
84 105 : void php_resource_factory_free(php_resource_factory_t **f)
85 : {
86 105 : if (*f) {
87 105 : php_resource_factory_dtor(*f);
88 105 : if (!(*f)->refcount) {
89 105 : efree(*f);
90 105 : *f = NULL;
91 : }
92 : }
93 105 : }
94 :
95 125 : void *php_resource_factory_handle_ctor(php_resource_factory_t *f,
96 : void *init_arg TSRMLS_DC)
97 : {
98 125 : if (f->fops.ctor) {
99 125 : return f->fops.ctor(f->data, init_arg TSRMLS_CC);
100 : }
101 0 : return NULL;
102 : }
103 :
104 0 : void *php_resource_factory_handle_copy(php_resource_factory_t *f,
105 : void *handle TSRMLS_DC)
106 : {
107 0 : if (f->fops.copy) {
108 0 : return f->fops.copy(f->data, handle TSRMLS_CC);
109 : }
110 0 : return NULL;
111 : }
112 :
113 125 : void php_resource_factory_handle_dtor(php_resource_factory_t *f,
114 : void *handle TSRMLS_DC)
115 : {
116 125 : if (f->fops.dtor) {
117 125 : f->fops.dtor(f->data, handle TSRMLS_CC);
118 : }
119 125 : }
120 :
121 1128 : static inline php_persistent_handle_list_t *php_persistent_handle_list_init(
122 : php_persistent_handle_list_t *list)
123 : {
124 : int free_list;
125 :
126 1128 : if ((free_list = !list)) {
127 9 : list = pemalloc(sizeof(php_persistent_handle_list_t), 1);
128 : }
129 :
130 1128 : list->used = 0;
131 :
132 1128 : if (SUCCESS != zend_hash_init(&list->free, 0, NULL, NULL, 1)) {
133 0 : if (free_list) {
134 0 : pefree(list, 1);
135 : }
136 0 : list = NULL;
137 : }
138 :
139 1128 : return list;
140 : }
141 :
142 18 : static int php_persistent_handle_apply_stat(void *p TSRMLS_DC, int argc,
143 : va_list argv, zend_hash_key *key)
144 : {
145 18 : php_persistent_handle_list_t **list = p;
146 18 : zval *zsubentry, *zentry = va_arg(argv, zval *);
147 :
148 18 : MAKE_STD_ZVAL(zsubentry);
149 18 : array_init(zsubentry);
150 18 : add_assoc_long_ex(zsubentry, ZEND_STRS("used"), (*list)->used);
151 18 : add_assoc_long_ex(zsubentry, ZEND_STRS("free"),
152 18 : zend_hash_num_elements(&(*list)->free));
153 18 : add_assoc_zval_ex(zentry, key->arKey, key->nKeyLength, zsubentry);
154 :
155 18 : return ZEND_HASH_APPLY_KEEP;
156 : }
157 :
158 33 : static int php_persistent_handle_apply_statall(void *p TSRMLS_DC, int argc,
159 : va_list argv, zend_hash_key *key)
160 : {
161 33 : php_persistent_handle_provider_t *provider = p;
162 33 : HashTable *ht = va_arg(argv, HashTable *);
163 : zval *zentry;
164 :
165 33 : MAKE_STD_ZVAL(zentry);
166 33 : array_init(zentry);
167 :
168 33 : zend_hash_apply_with_arguments(&provider->list.free TSRMLS_CC,
169 : php_persistent_handle_apply_stat, 1, zentry);
170 33 : zend_symtable_update(ht, key->arKey, key->nKeyLength, &zentry,
171 : sizeof(zval *), NULL);
172 :
173 33 : return ZEND_HASH_APPLY_KEEP;
174 : }
175 :
176 20 : static int php_persistent_handle_apply_cleanup_ex(void *pp, void *arg TSRMLS_DC)
177 : {
178 20 : php_resource_factory_t *rf = arg;
179 20 : void **handle = pp;
180 :
181 : #if PHP_RAPHF_DEBUG_PHANDLES
182 : fprintf(stderr, "DESTROY: %p\n", *handle);
183 : #endif
184 20 : php_resource_factory_handle_dtor(rf, *handle TSRMLS_CC);
185 20 : return ZEND_HASH_APPLY_REMOVE;
186 : }
187 :
188 11 : static int php_persistent_handle_apply_cleanup(void *pp, void *arg TSRMLS_DC)
189 : {
190 11 : php_resource_factory_t *rf = arg;
191 11 : php_persistent_handle_list_t **listp = pp;
192 :
193 11 : zend_hash_apply_with_argument(&(*listp)->free,
194 : php_persistent_handle_apply_cleanup_ex, rf TSRMLS_CC);
195 11 : if ((*listp)->used) {
196 2 : return ZEND_HASH_APPLY_KEEP;
197 : }
198 9 : zend_hash_destroy(&(*listp)->free);
199 : #if PHP_RAPHF_DEBUG_PHANDLES
200 : fprintf(stderr, "LSTFREE: %p\n", *listp);
201 : #endif
202 9 : pefree(*listp, 1);
203 9 : *listp = NULL;
204 9 : return ZEND_HASH_APPLY_REMOVE;
205 : }
206 :
207 0 : static inline void php_persistent_handle_list_dtor(
208 : php_persistent_handle_list_t *list,
209 : php_persistent_handle_provider_t *provider TSRMLS_DC)
210 : {
211 : #if PHP_RAPHF_DEBUG_PHANDLES
212 : fprintf(stderr, "LSTDTOR: %p\n", list);
213 : #endif
214 0 : zend_hash_apply_with_argument(&list->free,
215 0 : php_persistent_handle_apply_cleanup_ex, &provider->rf TSRMLS_CC);
216 0 : zend_hash_destroy(&list->free);
217 0 : }
218 :
219 0 : static inline void php_persistent_handle_list_free(
220 : php_persistent_handle_list_t **list,
221 : php_persistent_handle_provider_t *provider TSRMLS_DC)
222 : {
223 0 : php_persistent_handle_list_dtor(*list, provider TSRMLS_CC);
224 : #if PHP_RAPHF_DEBUG_PHANDLES
225 : fprintf(stderr, "LSTFREE: %p\n", *list);
226 : #endif
227 0 : pefree(*list, 1);
228 0 : *list = NULL;
229 0 : }
230 :
231 0 : static int php_persistent_handle_list_apply_dtor(void *listp,
232 : void *provider TSRMLS_DC)
233 : {
234 0 : php_persistent_handle_list_free(listp, provider TSRMLS_CC);
235 0 : return ZEND_HASH_APPLY_REMOVE;
236 : }
237 :
238 44 : static inline php_persistent_handle_list_t *php_persistent_handle_list_find(
239 : php_persistent_handle_provider_t *provider, const char *ident_str,
240 : size_t ident_len TSRMLS_DC)
241 : {
242 : php_persistent_handle_list_t **list, *new_list;
243 44 : STATUS rv = zend_symtable_find(&provider->list.free, ident_str,
244 : ident_len + 1, (void *) &list);
245 :
246 44 : if (SUCCESS == rv) {
247 : #if PHP_RAPHF_DEBUG_PHANDLES
248 : fprintf(stderr, "LSTFIND: %p\n", *list);
249 : #endif
250 35 : return *list;
251 : }
252 :
253 9 : if ((new_list = php_persistent_handle_list_init(NULL))) {
254 9 : rv = zend_symtable_update(&provider->list.free, ident_str, ident_len+1,
255 : (void *) &new_list, sizeof(php_persistent_handle_list_t *),
256 : (void *) &list);
257 9 : if (SUCCESS == rv) {
258 : #if PHP_RAPHF_DEBUG_PHANDLES
259 : fprintf(stderr, "LSTFIND: %p (new)\n", *list);
260 : #endif
261 9 : return *list;
262 : }
263 0 : php_persistent_handle_list_free(&new_list, provider TSRMLS_CC);
264 : }
265 :
266 0 : return NULL;
267 : }
268 :
269 6 : static int php_persistent_handle_apply_cleanup_all(void *p TSRMLS_DC, int argc,
270 : va_list argv, zend_hash_key *key)
271 : {
272 6 : php_persistent_handle_provider_t *provider = p;
273 6 : const char *ident_str = va_arg(argv, const char *);
274 6 : size_t ident_len = va_arg(argv, size_t);
275 : php_persistent_handle_list_t *list;
276 :
277 6 : if (ident_str && ident_len) {
278 6 : if ((list = php_persistent_handle_list_find(provider, ident_str,
279 : ident_len TSRMLS_CC))) {
280 3 : zend_hash_apply_with_argument(&list->free,
281 : php_persistent_handle_apply_cleanup_ex,
282 3 : &provider->rf TSRMLS_CC);
283 : }
284 : } else {
285 3 : zend_hash_apply_with_argument(&provider->list.free,
286 3 : php_persistent_handle_apply_cleanup, &provider->rf TSRMLS_CC);
287 : }
288 :
289 6 : return ZEND_HASH_APPLY_KEEP;
290 : }
291 :
292 1119 : static void php_persistent_handle_hash_dtor(void *p)
293 : {
294 : php_persistent_handle_provider_t *provider;
295 : TSRMLS_FETCH();
296 :
297 1119 : provider = (php_persistent_handle_provider_t *) p;
298 1119 : zend_hash_apply_with_argument(&provider->list.free,
299 : php_persistent_handle_list_apply_dtor, provider TSRMLS_CC);
300 1119 : zend_hash_destroy(&provider->list.free);
301 1119 : php_resource_factory_dtor(&provider->rf);
302 1119 : }
303 :
304 1119 : PHP_RAPHF_API STATUS php_persistent_handle_provide(const char *name_str,
305 : size_t name_len, php_resource_factory_ops_t *fops, void *data,
306 : void (*dtor)(void *) TSRMLS_DC)
307 : {
308 1119 : STATUS status = FAILURE;
309 : php_persistent_handle_provider_t provider;
310 :
311 1119 : if (php_persistent_handle_list_init(&provider.list)) {
312 1119 : if (php_resource_factory_init(&provider.rf, fops, data, dtor)) {
313 : #if PHP_RAPHF_DEBUG_PHANDLES
314 : fprintf(stderr, "PROVIDE: %p %s\n", PHP_RAPHF_G, name_str);
315 : #endif
316 :
317 1119 : status = zend_symtable_update(&PHP_RAPHF_G->persistent_handle.hash,
318 : name_str, name_len+1, (void *) &provider,
319 : sizeof(php_persistent_handle_provider_t), NULL);
320 1119 : if (SUCCESS != status) {
321 0 : php_resource_factory_dtor(&provider.rf);
322 : }
323 : }
324 : }
325 :
326 1119 : return status;
327 : }
328 :
329 20 : php_persistent_handle_factory_t *php_persistent_handle_concede(
330 : php_persistent_handle_factory_t *a, const char *name_str,
331 : size_t name_len, const char *ident_str, size_t ident_len,
332 : php_persistent_handle_wakeup_t wakeup,
333 : php_persistent_handle_retire_t retire TSRMLS_DC)
334 : {
335 20 : STATUS status = FAILURE;
336 20 : php_persistent_handle_factory_t *free_a = NULL;
337 :
338 20 : if (!a) {
339 20 : free_a = a = emalloc(sizeof(*a));
340 : }
341 20 : memset(a, 0, sizeof(*a));
342 :
343 20 : status = zend_symtable_find(&PHP_RAPHF_G->persistent_handle.hash, name_str,
344 20 : name_len+1, (void *) &a->provider);
345 :
346 20 : if (SUCCESS == status) {
347 20 : a->ident.str = estrndup(ident_str, ident_len);
348 20 : a->ident.len = ident_len;
349 :
350 20 : a->wakeup = wakeup;
351 20 : a->retire = retire;
352 :
353 20 : if (free_a) {
354 20 : a->free_on_abandon = 1;
355 : }
356 : } else {
357 0 : if (free_a) {
358 0 : efree(free_a);
359 : }
360 0 : a = NULL;
361 : }
362 :
363 : #if PHP_RAPHF_DEBUG_PHANDLES
364 : fprintf(stderr, "CONCEDE: %p %p (%s) (%s)\n", PHP_RAPHF_G,
365 : a ? a->provider : NULL, name_str, ident_str);
366 : #endif
367 :
368 20 : return a;
369 : }
370 :
371 20 : PHP_RAPHF_API void php_persistent_handle_abandon(
372 : php_persistent_handle_factory_t *a)
373 : {
374 20 : zend_bool f = a->free_on_abandon;
375 :
376 : #if PHP_RAPHF_DEBUG_PHANDLES
377 : fprintf(stderr, "ABANDON: %p\n", a->provider);
378 : #endif
379 :
380 20 : STR_FREE(a->ident.str);
381 20 : memset(a, 0, sizeof(*a));
382 20 : if (f) {
383 20 : efree(a);
384 : }
385 20 : }
386 :
387 20 : void *php_persistent_handle_acquire(
388 : php_persistent_handle_factory_t *a, void *init_arg TSRMLS_DC)
389 : {
390 : int key;
391 : STATUS rv;
392 : ulong index;
393 20 : void **handle_ptr, *handle = NULL;
394 : php_persistent_handle_list_t *list;
395 :
396 20 : list = php_persistent_handle_list_find(a->provider, a->ident.str,
397 : a->ident.len TSRMLS_CC);
398 20 : if (list) {
399 20 : zend_hash_internal_pointer_end(&list->free);
400 20 : key = zend_hash_get_current_key(&list->free, NULL, &index, 0);
401 20 : rv = zend_hash_get_current_data(&list->free, (void *) &handle_ptr);
402 20 : if (HASH_KEY_NON_EXISTANT != key && SUCCESS == rv) {
403 0 : handle = *handle_ptr;
404 0 : if (a->wakeup) {
405 0 : a->wakeup(a, &handle TSRMLS_CC);
406 : }
407 0 : zend_hash_index_del(&list->free, index);
408 : } else {
409 20 : handle = php_resource_factory_handle_ctor(&a->provider->rf,
410 : init_arg TSRMLS_CC);
411 : }
412 : #if PHP_RAPHF_DEBUG_PHANDLES
413 : fprintf(stderr, "CREATED: %p\n", *handle);
414 : #endif
415 20 : if (handle) {
416 20 : ++a->provider->list.used;
417 20 : ++list->used;
418 : }
419 : }
420 :
421 20 : return handle;
422 : }
423 :
424 0 : void *php_persistent_handle_accrete(
425 : php_persistent_handle_factory_t *a, void *handle TSRMLS_DC)
426 : {
427 0 : void *new_handle = NULL;
428 : php_persistent_handle_list_t *list;
429 :
430 0 : new_handle = php_resource_factory_handle_copy(&a->provider->rf,
431 : handle TSRMLS_CC);
432 0 : if (handle) {
433 0 : list = php_persistent_handle_list_find(a->provider, a->ident.str,
434 : a->ident.len TSRMLS_CC);
435 0 : if (list) {
436 0 : ++list->used;
437 : }
438 0 : ++a->provider->list.used;
439 : }
440 :
441 0 : return new_handle;
442 : }
443 :
444 20 : void php_persistent_handle_release(
445 : php_persistent_handle_factory_t *a, void *handle TSRMLS_DC)
446 : {
447 : php_persistent_handle_list_t *list;
448 :
449 20 : list = php_persistent_handle_list_find(a->provider, a->ident.str,
450 : a->ident.len TSRMLS_CC);
451 20 : if (list) {
452 20 : if (a->provider->list.used >= PHP_RAPHF_G->persistent_handle.limit) {
453 : #if PHP_RAPHF_DEBUG_PHANDLES
454 : fprintf(stderr, "DESTROY: %p\n", *handle);
455 : #endif
456 0 : php_resource_factory_handle_dtor(&a->provider->rf,
457 : handle TSRMLS_CC);
458 : } else {
459 20 : if (a->retire) {
460 0 : a->retire(a, &handle TSRMLS_CC);
461 : }
462 20 : zend_hash_next_index_insert(&list->free, (void *) &handle,
463 : sizeof(void *), NULL);
464 : }
465 :
466 20 : --a->provider->list.used;
467 20 : --list->used;
468 : }
469 20 : }
470 :
471 1123 : void php_persistent_handle_cleanup(const char *name_str, size_t name_len,
472 : const char *ident_str, size_t ident_len TSRMLS_DC)
473 : {
474 : php_persistent_handle_provider_t *provider;
475 : php_persistent_handle_list_t *list;
476 : STATUS rv;
477 :
478 1123 : if (name_str && name_len) {
479 1121 : rv = zend_symtable_find(&PHP_RAPHF_G->persistent_handle.hash, name_str,
480 : name_len+1, (void *) &provider);
481 :
482 2242 : if (SUCCESS == rv) {
483 1121 : if (ident_str && ident_len) {
484 1 : list = php_persistent_handle_list_find(provider, ident_str,
485 : ident_len TSRMLS_CC);
486 2 : if (list) {
487 1 : zend_hash_apply_with_argument(&list->free,
488 : php_persistent_handle_apply_cleanup_ex,
489 1 : &provider->rf TSRMLS_CC);
490 : }
491 : } else {
492 1120 : zend_hash_apply_with_argument(&provider->list.free,
493 : php_persistent_handle_apply_cleanup,
494 1120 : &provider->rf TSRMLS_CC);
495 : }
496 : }
497 : } else {
498 2 : zend_hash_apply_with_arguments(
499 : &PHP_RAPHF_G->persistent_handle.hash TSRMLS_CC,
500 : php_persistent_handle_apply_cleanup_all, 2, ident_str,
501 : ident_len);
502 : }
503 1123 : }
504 :
505 11 : HashTable *php_persistent_handle_statall(HashTable *ht TSRMLS_DC)
506 : {
507 11 : if (zend_hash_num_elements(&PHP_RAPHF_G->persistent_handle.hash)) {
508 11 : if (!ht) {
509 0 : ALLOC_HASHTABLE(ht);
510 0 : zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
511 : }
512 11 : zend_hash_apply_with_arguments(
513 : &PHP_RAPHF_G->persistent_handle.hash TSRMLS_CC,
514 : php_persistent_handle_apply_statall, 1, ht);
515 0 : } else if (ht) {
516 0 : ht = NULL;
517 : }
518 :
519 11 : return ht;
520 : }
521 :
522 : static php_resource_factory_ops_t php_persistent_handle_resource_factory_ops = {
523 : (php_resource_factory_handle_ctor_t) php_persistent_handle_acquire,
524 : (php_resource_factory_handle_copy_t) php_persistent_handle_accrete,
525 : (php_resource_factory_handle_dtor_t) php_persistent_handle_release
526 : };
527 :
528 20 : php_resource_factory_ops_t *php_persistent_handle_get_resource_factory_ops(void)
529 : {
530 20 : return &php_persistent_handle_resource_factory_ops;
531 : }
532 :
533 : ZEND_BEGIN_ARG_INFO_EX(ai_raphf_stat_persistent_handles, 0, 0, 0)
534 : ZEND_END_ARG_INFO();
535 11 : static PHP_FUNCTION(raphf_stat_persistent_handles)
536 : {
537 11 : if (SUCCESS == zend_parse_parameters_none()) {
538 11 : object_init(return_value);
539 11 : if (php_persistent_handle_statall(HASH_OF(return_value) TSRMLS_CC)) {
540 11 : return;
541 : }
542 0 : zval_dtor(return_value);
543 : }
544 0 : RETURN_FALSE;
545 : }
546 :
547 : ZEND_BEGIN_ARG_INFO_EX(ai_raphf_clean_persistent_handles, 0, 0, 0)
548 : ZEND_ARG_INFO(0, name)
549 : ZEND_ARG_INFO(0, ident)
550 : ZEND_END_ARG_INFO();
551 4 : static PHP_FUNCTION(raphf_clean_persistent_handles)
552 : {
553 4 : char *name_str = NULL, *ident_str = NULL;
554 4 : int name_len = 0, ident_len = 0;
555 :
556 4 : if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!",
557 : &name_str, &name_len, &ident_str, &ident_len)) {
558 4 : php_persistent_handle_cleanup(name_str, name_len, ident_str,
559 : ident_len TSRMLS_CC);
560 : }
561 4 : }
562 :
563 : static const zend_function_entry raphf_functions[] = {
564 : ZEND_NS_FENTRY("raphf", stat_persistent_handles,
565 : ZEND_FN(raphf_stat_persistent_handles),
566 : ai_raphf_stat_persistent_handles, 0)
567 : ZEND_NS_FENTRY("raphf", clean_persistent_handles,
568 : ZEND_FN(raphf_clean_persistent_handles),
569 : ai_raphf_clean_persistent_handles, 0)
570 : {0}
571 : };
572 :
573 : PHP_INI_BEGIN()
574 : STD_PHP_INI_ENTRY("raphf.persistent_handle.limit", "-1", PHP_INI_SYSTEM,
575 : OnUpdateLong, persistent_handle.limit, zend_raphf_globals,
576 : raphf_globals)
577 : PHP_INI_END()
578 :
579 : static HashTable *php_persistent_handles_global_hash;
580 :
581 373 : static PHP_GINIT_FUNCTION(raphf)
582 : {
583 373 : raphf_globals->persistent_handle.limit = -1;
584 :
585 373 : zend_hash_init(&raphf_globals->persistent_handle.hash, 0, NULL,
586 : php_persistent_handle_hash_dtor, 1);
587 373 : if (php_persistent_handles_global_hash) {
588 0 : zend_hash_copy(&raphf_globals->persistent_handle.hash,
589 : php_persistent_handles_global_hash, NULL, NULL,
590 : sizeof(php_persistent_handle_provider_t));
591 : }
592 373 : }
593 :
594 373 : static PHP_GSHUTDOWN_FUNCTION(raphf)
595 : {
596 373 : zend_hash_destroy(&raphf_globals->persistent_handle.hash);
597 373 : }
598 :
599 373 : PHP_MINIT_FUNCTION(raphf)
600 : {
601 373 : php_persistent_handles_global_hash = &PHP_RAPHF_G->persistent_handle.hash;
602 373 : REGISTER_INI_ENTRIES();
603 373 : return SUCCESS;
604 : }
605 :
606 373 : PHP_MSHUTDOWN_FUNCTION(raphf)
607 : {
608 373 : UNREGISTER_INI_ENTRIES();
609 373 : php_persistent_handles_global_hash = NULL;
610 373 : return SUCCESS;
611 : }
612 :
613 0 : static int php_persistent_handle_apply_info_ex(void *p TSRMLS_DC, int argc,
614 : va_list argv, zend_hash_key *key)
615 : {
616 0 : php_persistent_handle_list_t **list = p;
617 0 : zend_hash_key *super_key = va_arg(argv, zend_hash_key *);
618 : char used[21], free[21];
619 :
620 0 : slprintf(used, sizeof(used), "%u", (*list)->used);
621 0 : slprintf(free, sizeof(free), "%d", zend_hash_num_elements(&(*list)->free));
622 :
623 0 : php_info_print_table_row(4, super_key->arKey, key->arKey, used, free);
624 :
625 0 : return ZEND_HASH_APPLY_KEEP;
626 : }
627 :
628 3 : static int php_persistent_handle_apply_info(void *p TSRMLS_DC, int argc,
629 : va_list argv, zend_hash_key *key)
630 : {
631 3 : php_persistent_handle_provider_t *provider = p;
632 :
633 3 : zend_hash_apply_with_arguments(&provider->list.free TSRMLS_CC,
634 : php_persistent_handle_apply_info_ex, 1, key);
635 :
636 3 : return ZEND_HASH_APPLY_KEEP;
637 : }
638 :
639 1 : PHP_MINFO_FUNCTION(raphf)
640 : {
641 1 : php_info_print_table_start();
642 1 : php_info_print_table_header(2,
643 : "Resource and persistent handle factory support", "enabled");
644 1 : php_info_print_table_row(2, "Extension version", PHP_RAPHF_VERSION);
645 1 : php_info_print_table_end();
646 :
647 1 : php_info_print_table_start();
648 1 : php_info_print_table_colspan_header(4, "Persistent handles in this "
649 : #ifdef ZTS
650 : "thread"
651 : #else
652 : "process"
653 : #endif
654 : );
655 1 : php_info_print_table_header(4, "Provider", "Ident", "Used", "Free");
656 1 : zend_hash_apply_with_arguments(
657 : &PHP_RAPHF_G->persistent_handle.hash TSRMLS_CC,
658 : php_persistent_handle_apply_info, 0);
659 1 : php_info_print_table_end();
660 :
661 1 : DISPLAY_INI_ENTRIES();
662 1 : }
663 :
664 : zend_module_entry raphf_module_entry = {
665 : STANDARD_MODULE_HEADER,
666 : "raphf",
667 : raphf_functions,
668 : PHP_MINIT(raphf),
669 : PHP_MSHUTDOWN(raphf),
670 : NULL,
671 : NULL,
672 : PHP_MINFO(raphf),
673 : PHP_RAPHF_VERSION,
674 : ZEND_MODULE_GLOBALS(raphf),
675 : PHP_GINIT(raphf),
676 : PHP_GSHUTDOWN(raphf),
677 : NULL,
678 : STANDARD_MODULE_PROPERTIES_EX
679 : };
680 : /* }}} */
681 :
682 : #ifdef COMPILE_DL_RAPHF
683 : ZEND_GET_MODULE(raphf)
684 : #endif
685 :
686 :
687 : /*
688 : * Local variables:
689 : * tab-width: 4
690 : * c-basic-offset: 4
691 : * End:
692 : * vim600: noet sw=4 ts=4 fdm=marker
693 : * vim<600: noet sw=4 ts=4
694 : */
|