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 1472 : 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 1472 : if (!f) {
54 72 : f = emalloc(sizeof(*f));
55 : }
56 1472 : memset(f, 0, sizeof(*f));
57 :
58 1472 : memcpy(&f->fops, fops, sizeof(*fops));
59 :
60 1472 : f->data = data;
61 1472 : f->dtor = dtor;
62 :
63 1472 : f->refcount = 1;
64 :
65 1472 : 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 1472 : void php_resource_factory_dtor(php_resource_factory_t *f)
74 : {
75 1472 : --f->refcount;
76 :
77 1472 : if (!f->refcount) {
78 1472 : if (f->dtor) {
79 148 : f->dtor(f->data);
80 : }
81 : }
82 1472 : }
83 :
84 72 : void php_resource_factory_free(php_resource_factory_t **f)
85 : {
86 72 : if (*f) {
87 72 : php_resource_factory_dtor(*f);
88 72 : if (!(*f)->refcount) {
89 72 : efree(*f);
90 72 : *f = NULL;
91 : }
92 : }
93 72 : }
94 :
95 293 : void *php_resource_factory_handle_ctor(php_resource_factory_t *f,
96 : void *init_arg TSRMLS_DC)
97 : {
98 293 : if (f->fops.ctor) {
99 293 : 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 293 : void php_resource_factory_handle_dtor(php_resource_factory_t *f,
114 : void *handle TSRMLS_DC)
115 : {
116 293 : if (f->fops.dtor) {
117 293 : f->fops.dtor(f->data, handle TSRMLS_CC);
118 : }
119 293 : }
120 :
121 1254 : 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 1254 : if ((free_list = !list)) {
127 30 : list = pemalloc(sizeof(php_persistent_handle_list_t), 1);
128 : }
129 :
130 1254 : list->used = 0;
131 :
132 1254 : 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 1254 : return list;
140 : }
141 :
142 19 : static int php_persistent_handle_apply_stat(void *p TSRMLS_DC, int argc,
143 : va_list argv, zend_hash_key *key)
144 : {
145 19 : php_persistent_handle_list_t **list = p;
146 19 : zval *zsubentry, *zentry = va_arg(argv, zval *);
147 :
148 19 : MAKE_STD_ZVAL(zsubentry);
149 19 : array_init(zsubentry);
150 19 : add_assoc_long_ex(zsubentry, ZEND_STRS("used"), (*list)->used);
151 19 : add_assoc_long_ex(zsubentry, ZEND_STRS("free"),
152 19 : zend_hash_num_elements(&(*list)->free));
153 19 : add_assoc_zval_ex(zentry, key->arKey, key->nKeyLength, zsubentry);
154 :
155 19 : return ZEND_HASH_APPLY_KEEP;
156 : }
157 :
158 36 : static int php_persistent_handle_apply_statall(void *p TSRMLS_DC, int argc,
159 : va_list argv, zend_hash_key *key)
160 : {
161 36 : php_persistent_handle_provider_t *provider = p;
162 36 : HashTable *ht = va_arg(argv, HashTable *);
163 : zval *zentry;
164 :
165 36 : MAKE_STD_ZVAL(zentry);
166 36 : array_init(zentry);
167 :
168 36 : zend_hash_apply_with_arguments(&provider->list.free TSRMLS_CC,
169 : php_persistent_handle_apply_stat, 1, zentry);
170 36 : zend_symtable_update(ht, key->arKey, key->nKeyLength, &zentry,
171 : sizeof(zval *), NULL);
172 :
173 36 : return ZEND_HASH_APPLY_KEEP;
174 : }
175 :
176 45 : static int php_persistent_handle_apply_cleanup_ex(void *pp, void *arg TSRMLS_DC)
177 : {
178 45 : php_resource_factory_t *rf = arg;
179 45 : void **handle = pp;
180 :
181 : #if PHP_RAPHF_DEBUG_PHANDLES
182 : fprintf(stderr, "DESTROY: %p\n", *handle);
183 : #endif
184 45 : php_resource_factory_handle_dtor(rf, *handle TSRMLS_CC);
185 45 : return ZEND_HASH_APPLY_REMOVE;
186 : }
187 :
188 32 : static int php_persistent_handle_apply_cleanup(void *pp, void *arg TSRMLS_DC)
189 : {
190 32 : php_resource_factory_t *rf = arg;
191 32 : php_persistent_handle_list_t **listp = pp;
192 :
193 32 : zend_hash_apply_with_argument(&(*listp)->free,
194 : php_persistent_handle_apply_cleanup_ex, rf TSRMLS_CC);
195 32 : if ((*listp)->used) {
196 2 : return ZEND_HASH_APPLY_KEEP;
197 : }
198 30 : zend_hash_destroy(&(*listp)->free);
199 : #if PHP_RAPHF_DEBUG_PHANDLES
200 : fprintf(stderr, "LSTFREE: %p\n", *listp);
201 : #endif
202 30 : pefree(*listp, 1);
203 30 : *listp = NULL;
204 30 : 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 300 : 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 300 : STATUS rv = zend_symtable_find(&provider->list.free, ident_str,
244 : ident_len + 1, (void *) &list);
245 :
246 300 : if (SUCCESS == rv) {
247 : #if PHP_RAPHF_DEBUG_PHANDLES
248 : fprintf(stderr, "LSTFIND: %p\n", *list);
249 : #endif
250 270 : return *list;
251 : }
252 :
253 30 : if ((new_list = php_persistent_handle_list_init(NULL))) {
254 30 : 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 30 : if (SUCCESS == rv) {
258 : #if PHP_RAPHF_DEBUG_PHANDLES
259 : fprintf(stderr, "LSTFIND: %p (new)\n", *list);
260 : #endif
261 30 : 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 1224 : static void php_persistent_handle_hash_dtor(void *p)
293 : {
294 : php_persistent_handle_provider_t *provider;
295 : TSRMLS_FETCH();
296 :
297 1224 : provider = (php_persistent_handle_provider_t *) p;
298 1224 : zend_hash_apply_with_argument(&provider->list.free,
299 : php_persistent_handle_list_apply_dtor, provider TSRMLS_CC);
300 1224 : zend_hash_destroy(&provider->list.free);
301 1224 : php_resource_factory_dtor(&provider->rf);
302 1224 : }
303 :
304 1224 : 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 1224 : STATUS status = FAILURE;
309 : php_persistent_handle_provider_t provider;
310 :
311 1224 : if (php_persistent_handle_list_init(&provider.list)) {
312 1224 : 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 1224 : 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 1224 : if (SUCCESS != status) {
321 0 : php_resource_factory_dtor(&provider.rf);
322 : }
323 : }
324 : }
325 :
326 1224 : return status;
327 : }
328 :
329 148 : 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 148 : STATUS status = FAILURE;
336 148 : php_persistent_handle_factory_t *free_a = NULL;
337 :
338 148 : if (!a) {
339 148 : free_a = a = emalloc(sizeof(*a));
340 : }
341 148 : memset(a, 0, sizeof(*a));
342 :
343 148 : status = zend_symtable_find(&PHP_RAPHF_G->persistent_handle.hash, name_str,
344 148 : name_len+1, (void *) &a->provider);
345 :
346 148 : if (SUCCESS == status) {
347 148 : a->ident.str = estrndup(ident_str, ident_len);
348 148 : a->ident.len = ident_len;
349 :
350 148 : a->wakeup = wakeup;
351 148 : a->retire = retire;
352 :
353 148 : if (free_a) {
354 148 : 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 148 : return a;
369 : }
370 :
371 148 : PHP_RAPHF_API void php_persistent_handle_abandon(
372 : php_persistent_handle_factory_t *a)
373 : {
374 148 : 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 148 : STR_FREE(a->ident.str);
381 148 : memset(a, 0, sizeof(*a));
382 148 : if (f) {
383 148 : efree(a);
384 : }
385 148 : }
386 :
387 148 : 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 148 : void **handle_ptr, *handle = NULL;
394 : php_persistent_handle_list_t *list;
395 :
396 148 : list = php_persistent_handle_list_find(a->provider, a->ident.str,
397 : a->ident.len TSRMLS_CC);
398 148 : if (list) {
399 148 : zend_hash_internal_pointer_end(&list->free);
400 148 : key = zend_hash_get_current_key(&list->free, NULL, &index, 0);
401 148 : rv = zend_hash_get_current_data(&list->free, (void *) &handle_ptr);
402 148 : if (HASH_KEY_NON_EXISTANT != key && SUCCESS == rv) {
403 103 : handle = *handle_ptr;
404 103 : if (a->wakeup) {
405 97 : a->wakeup(a, &handle TSRMLS_CC);
406 : }
407 103 : zend_hash_index_del(&list->free, index);
408 : } else {
409 45 : 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 148 : if (handle) {
416 148 : ++a->provider->list.used;
417 148 : ++list->used;
418 : }
419 : }
420 :
421 148 : 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 148 : 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 148 : list = php_persistent_handle_list_find(a->provider, a->ident.str,
450 : a->ident.len TSRMLS_CC);
451 148 : if (list) {
452 148 : 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 148 : if (a->retire) {
460 100 : a->retire(a, &handle TSRMLS_CC);
461 : }
462 148 : zend_hash_next_index_insert(&list->free, (void *) &handle,
463 : sizeof(void *), NULL);
464 : }
465 :
466 148 : --a->provider->list.used;
467 148 : --list->used;
468 : }
469 148 : }
470 :
471 1228 : 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 1228 : if (name_str && name_len) {
479 1226 : rv = zend_symtable_find(&PHP_RAPHF_G->persistent_handle.hash, name_str,
480 : name_len+1, (void *) &provider);
481 :
482 2452 : if (SUCCESS == rv) {
483 1226 : 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 1225 : zend_hash_apply_with_argument(&provider->list.free,
493 : php_persistent_handle_apply_cleanup,
494 1225 : &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 1228 : }
504 :
505 12 : HashTable *php_persistent_handle_statall(HashTable *ht TSRMLS_DC)
506 : {
507 12 : if (zend_hash_num_elements(&PHP_RAPHF_G->persistent_handle.hash)) {
508 12 : if (!ht) {
509 0 : ALLOC_HASHTABLE(ht);
510 0 : zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
511 : }
512 12 : 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 12 : 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 148 : php_resource_factory_ops_t *php_persistent_handle_get_resource_factory_ops(void)
529 : {
530 148 : 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 12 : static PHP_FUNCTION(raphf_stat_persistent_handles)
536 : {
537 12 : if (SUCCESS == zend_parse_parameters_none()) {
538 12 : object_init(return_value);
539 12 : if (php_persistent_handle_statall(HASH_OF(return_value) TSRMLS_CC)) {
540 12 : 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 408 : static PHP_GINIT_FUNCTION(raphf)
582 : {
583 408 : raphf_globals->persistent_handle.limit = -1;
584 :
585 408 : zend_hash_init(&raphf_globals->persistent_handle.hash, 0, NULL,
586 : php_persistent_handle_hash_dtor, 1);
587 408 : 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 408 : }
593 :
594 408 : static PHP_GSHUTDOWN_FUNCTION(raphf)
595 : {
596 408 : zend_hash_destroy(&raphf_globals->persistent_handle.hash);
597 408 : }
598 :
599 408 : PHP_MINIT_FUNCTION(raphf)
600 : {
601 408 : php_persistent_handles_global_hash = &PHP_RAPHF_G->persistent_handle.hash;
602 408 : REGISTER_INI_ENTRIES();
603 408 : return SUCCESS;
604 : }
605 :
606 408 : PHP_MSHUTDOWN_FUNCTION(raphf)
607 : {
608 408 : UNREGISTER_INI_ENTRIES();
609 408 : php_persistent_handles_global_hash = NULL;
610 408 : 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 : */
|