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