1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
21
#include "apr_pools.h"
22
#include "apr_tables.h"
24
#include "apr_hooks.h"
26
#include "apr_optional_hooks.h"
27
#include "apr_optional.h"
28
#define APR_WANT_MEMFUNC
29
#define APR_WANT_STRFUNC
33
#define apr_palloc(pool,size) malloc(size)
36
APU_DECLARE_DATA apr_pool_t *apr_hook_global_pool = NULL;
37
APU_DECLARE_DATA int apr_hook_debug_enabled = 0;
38
APU_DECLARE_DATA const char *apr_hook_debug_current = NULL;
40
/** @deprecated @see apr_hook_global_pool */
41
APU_DECLARE_DATA apr_pool_t *apr_global_hook_pool = NULL;
43
/** @deprecated @see apr_hook_debug_enabled */
44
APU_DECLARE_DATA int apr_debug_module_hooks = 0;
46
/** @deprecated @see apr_hook_debug_current */
47
APU_DECLARE_DATA const char *apr_current_hooking_module = NULL;
49
/* NB: This must echo the LINK_##name structure */
52
void (*dummy)(void *);
54
const char * const *aszPredecessors;
55
const char * const *aszSuccessors;
63
struct tsort_ **ppPredecessors;
68
#include "apr_private.h"
69
#define get_apd APP_DATA* apd = (APP_DATA*)get_app_data(gLibId);
70
#define s_aHooksToSort ((apr_array_header_t *)(apd->gs_aHooksToSort))
71
#define s_phOptionalHooks ((apr_hash_t *)(apd->gs_phOptionalHooks))
72
#define s_phOptionalFunctions ((apr_hash_t *)(apd->gs_phOptionalFunctions))
75
static int crude_order(const void *a_,const void *b_)
77
const TSortData *a=a_;
78
const TSortData *b=b_;
80
return a->nOrder-b->nOrder;
83
static TSort *prepare(apr_pool_t *p,TSortData *pItems,int nItems)
85
TSort *pData=apr_palloc(p,nItems*sizeof *pData);
88
qsort(pItems,nItems,sizeof *pItems,crude_order);
89
for(n=0 ; n < nItems ; ++n) {
90
pData[n].nPredecessors=0;
91
pData[n].ppPredecessors=apr_pcalloc(p,nItems*sizeof *pData[n].ppPredecessors);
93
pData[n].pData=&pItems[n];
96
for(n=0 ; n < nItems ; ++n) {
99
for(i=0 ; pItems[n].aszPredecessors && pItems[n].aszPredecessors[i] ; ++i)
100
for(k=0 ; k < nItems ; ++k)
101
if(!strcmp(pItems[k].szName,pItems[n].aszPredecessors[i])) {
104
for(l=0 ; l < pData[n].nPredecessors ; ++l)
105
if(pData[n].ppPredecessors[l] == &pData[k])
107
pData[n].ppPredecessors[pData[n].nPredecessors]=&pData[k];
108
++pData[n].nPredecessors;
112
for(i=0 ; pItems[n].aszSuccessors && pItems[n].aszSuccessors[i] ; ++i)
113
for(k=0 ; k < nItems ; ++k)
114
if(!strcmp(pItems[k].szName,pItems[n].aszSuccessors[i])) {
117
for(l=0 ; l < pData[k].nPredecessors ; ++l)
118
if(pData[k].ppPredecessors[l] == &pData[n])
120
pData[k].ppPredecessors[pData[k].nPredecessors]=&pData[n];
121
++pData[k].nPredecessors;
130
/* Topologically sort, dragging out-of-order items to the front. Note that
131
this tends to preserve things that want to be near the front better, and
132
changing that behaviour might compromise some of Apache's behaviour (in
133
particular, mod_log_forensic might otherwise get pushed to the end, and
134
core.c's log open function used to end up at the end when pushing items
135
to the back was the methedology). Also note that the algorithm could
136
go back to its original simplicity by sorting from the back instead of
139
static TSort *tsort(TSort *pData,int nItems)
145
for(nTotal=0 ; nTotal < nItems ; ++nTotal) {
150
assert(0); /* we have a loop... */
151
if(!pData[n].pNext) {
152
if(pData[n].nPredecessors) {
155
if(pData[n].ppPredecessors[k])
160
if(&pData[i] == pData[n].ppPredecessors[k]) {
170
pTail->pNext=&pData[n];
174
pTail->pNext=pTail; /* fudge it so it looks linked */
175
for(i=0 ; i < nItems ; ++i)
176
for(k=0 ; k < nItems ; ++k)
177
if(pData[i].ppPredecessors[k] == &pData[n]) {
178
--pData[i].nPredecessors;
179
pData[i].ppPredecessors[k]=NULL;
183
pTail->pNext=NULL; /* unfudge the tail */
187
static apr_array_header_t *sort_hook(apr_array_header_t *pHooks,
192
apr_array_header_t *pNew;
195
apr_pool_create(&p, apr_hook_global_pool);
196
pSort=prepare(p,(TSortData *)pHooks->elts,pHooks->nelts);
197
pSort=tsort(pSort,pHooks->nelts);
198
pNew=apr_array_make(apr_hook_global_pool,pHooks->nelts,sizeof(TSortData));
199
if(apr_hook_debug_enabled)
200
printf("Sorting %s:",szName);
201
for(n=0 ; pSort ; pSort=pSort->pNext,++n) {
203
assert(n < pHooks->nelts);
204
pHook=apr_array_push(pNew);
205
memcpy(pHook,pSort->pData,sizeof *pHook);
206
if(apr_hook_debug_enabled)
207
printf(" %s",pHook->szName);
209
if(apr_hook_debug_enabled)
215
static apr_array_header_t *s_aHooksToSort;
220
const char *szHookName;
221
apr_array_header_t **paHooks;
224
APU_DECLARE(void) apr_hook_sort_register(const char *szHookName,
225
apr_array_header_t **paHooks)
230
HookSortEntry *pEntry;
233
s_aHooksToSort=apr_array_make(apr_hook_global_pool,1,sizeof(HookSortEntry));
234
pEntry=apr_array_push(s_aHooksToSort);
235
pEntry->szHookName=szHookName;
236
pEntry->paHooks=paHooks;
239
APU_DECLARE(void) apr_hook_sort_all(void)
246
for(n=0 ; n < s_aHooksToSort->nelts ; ++n) {
247
HookSortEntry *pEntry=&((HookSortEntry *)s_aHooksToSort->elts)[n];
248
*pEntry->paHooks=sort_hook(*pEntry->paHooks,pEntry->szHookName);
253
static apr_hash_t *s_phOptionalHooks;
254
static apr_hash_t *s_phOptionalFunctions;
257
APU_DECLARE(void) apr_hook_deregister_all(void)
264
for(n=0 ; n < s_aHooksToSort->nelts ; ++n) {
265
HookSortEntry *pEntry=&((HookSortEntry *)s_aHooksToSort->elts)[n];
266
*pEntry->paHooks=NULL;
269
s_phOptionalHooks=NULL;
270
s_phOptionalFunctions=NULL;
273
APU_DECLARE(void) apr_hook_debug_show(const char *szName,
274
const char * const *aszPre,
275
const char * const *aszSucc)
279
printf(" Hooked %s",szName);
281
fputs(" pre(",stdout);
287
fputs(*aszPre,stdout);
293
fputs(" succ(",stdout);
299
fputs(*aszSucc,stdout);
307
/* Optional hook support */
309
APR_DECLARE_EXTERNAL_HOOK(apr,APU,void,_optional,(void))
311
APU_DECLARE(apr_array_header_t *) apr_optional_hook_get(const char *szName)
316
apr_array_header_t **ppArray;
318
if(!s_phOptionalHooks)
320
ppArray=apr_hash_get(s_phOptionalHooks,szName,strlen(szName));
326
APU_DECLARE(void) apr_optional_hook_add(const char *szName,void (*pfn)(void),
327
const char * const *aszPre,
328
const char * const *aszSucc,int nOrder)
333
apr_array_header_t *pArray=apr_optional_hook_get(szName);
334
apr_LINK__optional_t *pHook;
337
apr_array_header_t **ppArray;
339
pArray=apr_array_make(apr_hook_global_pool,1,
340
sizeof(apr_LINK__optional_t));
341
if(!s_phOptionalHooks)
342
s_phOptionalHooks=apr_hash_make(apr_hook_global_pool);
343
ppArray=apr_palloc(apr_hook_global_pool,sizeof *ppArray);
345
apr_hash_set(s_phOptionalHooks,szName,strlen(szName),ppArray);
346
apr_hook_sort_register(szName,ppArray);
348
pHook=apr_array_push(pArray);
350
pHook->aszPredecessors=aszPre;
351
pHook->aszSuccessors=aszSucc;
352
pHook->nOrder=nOrder;
353
pHook->szName=apr_hook_debug_current;
354
if(apr_hook_debug_enabled)
355
apr_hook_debug_show(szName,aszPre,aszSucc);
358
/* optional function support */
360
APU_DECLARE(apr_opt_fn_t *) apr_dynamic_fn_retrieve(const char *szName)
365
if(!s_phOptionalFunctions)
367
return (void(*)(void))apr_hash_get(s_phOptionalFunctions,szName,strlen(szName));
371
APU_DECLARE_NONSTD(void) apr_dynamic_fn_register(const char *szName,
377
if(!s_phOptionalFunctions)
378
s_phOptionalFunctions=apr_hash_make(apr_hook_global_pool);
379
apr_hash_set(s_phOptionalFunctions,szName,strlen(szName),(void *)pfn);
385
const char *aszAPre[]={"b","c",NULL};
386
const char *aszBPost[]={"a",NULL};
387
const char *aszCPost[]={"b",NULL};
390
{ "a",aszAPre,NULL },
391
{ "b",NULL,aszBPost },
392
{ "c",NULL,aszCPost }
396
pResult=prepare(t1,3);
397
pResult=tsort(pResult,3);
399
for( ; pResult ; pResult=pResult->pNext)
400
printf("%s\n",pResult->pData->szName);