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