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()
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);
252 /** @deprecated @see apr_hook_sort_all */
253 APU_DECLARE(void) apr_sort_hooks()
259 static apr_hash_t *s_phOptionalHooks;
260 static apr_hash_t *s_phOptionalFunctions;
263 APU_DECLARE(void) apr_hook_deregister_all(void)
270 for(n=0 ; n < s_aHooksToSort->nelts ; ++n) {
271 HookSortEntry *pEntry=&((HookSortEntry *)s_aHooksToSort->elts)[n];
272 *pEntry->paHooks=NULL;
275 s_phOptionalHooks=NULL;
276 s_phOptionalFunctions=NULL;
279 APU_DECLARE(void) apr_hook_debug_show(const char *szName,
280 const char * const *aszPre,
281 const char * const *aszSucc)
285 printf(" Hooked %s",szName);
287 fputs(" pre(",stdout);
293 fputs(*aszPre,stdout);
299 fputs(" succ(",stdout);
305 fputs(*aszSucc,stdout);
313 /** @deprecated @see apr_hook_debug_show */
314 APU_DECLARE(void) apr_show_hook(const char *szName,const char * const *aszPre,
315 const char * const *aszSucc)
317 apr_hook_debug_show(szName, aszPre, aszSucc);
320 /* Optional hook support */
322 APR_DECLARE_EXTERNAL_HOOK(apr,APU,void,_optional,(void))
324 APU_DECLARE(apr_array_header_t *) apr_optional_hook_get(const char *szName)
329 apr_array_header_t **ppArray;
331 if(!s_phOptionalHooks)
333 ppArray=apr_hash_get(s_phOptionalHooks,szName,strlen(szName));
339 APU_DECLARE(void) apr_optional_hook_add(const char *szName,void (*pfn)(void),
340 const char * const *aszPre,
341 const char * const *aszSucc,int nOrder)
346 apr_array_header_t *pArray=apr_optional_hook_get(szName);
347 apr_LINK__optional_t *pHook;
350 apr_array_header_t **ppArray;
352 pArray=apr_array_make(apr_hook_global_pool,1,
353 sizeof(apr_LINK__optional_t));
354 if(!s_phOptionalHooks)
355 s_phOptionalHooks=apr_hash_make(apr_hook_global_pool);
356 ppArray=apr_palloc(apr_hook_global_pool,sizeof *ppArray);
358 apr_hash_set(s_phOptionalHooks,szName,strlen(szName),ppArray);
359 apr_hook_sort_register(szName,ppArray);
361 pHook=apr_array_push(pArray);
363 pHook->aszPredecessors=aszPre;
364 pHook->aszSuccessors=aszSucc;
365 pHook->nOrder=nOrder;
366 pHook->szName=apr_hook_debug_current;
367 if(apr_hook_debug_enabled)
368 apr_hook_debug_show(szName,aszPre,aszSucc);
371 /* optional function support */
373 APU_DECLARE(apr_opt_fn_t *) apr_dynamic_fn_retrieve(const char *szName)
378 if(!s_phOptionalFunctions)
380 return (void(*)(void))apr_hash_get(s_phOptionalFunctions,szName,strlen(szName));
384 APU_DECLARE(apr_opt_fn_t *) apr_retrieve_optional_fn(const char *szName)
386 return apr_dynamic_fn_retrieve(szName);
389 APU_DECLARE_NONSTD(void) apr_dynamic_fn_register(const char *szName,
395 if(!s_phOptionalFunctions)
396 s_phOptionalFunctions=apr_hash_make(apr_hook_global_pool);
397 apr_hash_set(s_phOptionalFunctions,szName,strlen(szName),(void *)pfn);
401 APU_DECLARE_NONSTD(void) apr_register_optional_fn(const char *szName,
404 apr_dynamic_fn_register(szName, pfn);
410 const char *aszAPre[]={"b","c",NULL};
411 const char *aszBPost[]={"a",NULL};
412 const char *aszCPost[]={"b",NULL};
415 { "a",aszAPre,NULL },
416 { "b",NULL,aszBPost },
417 { "c",NULL,aszCPost }
421 pResult=prepare(t1,3);
422 pResult=tsort(pResult,3);
424 for( ; pResult ; pResult=pResult->pNext)
425 printf("%s\n",pResult->pData->szName);