1 /* Copyright 2000-2004 The Apache Software Foundation
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
20 #include "apr_pools.h"
21 #include "apr_tables.h"
23 #include "apr_hooks.h"
25 #include "apr_optional_hooks.h"
26 #include "apr_optional.h"
27 #define APR_WANT_MEMFUNC
28 #define APR_WANT_STRFUNC
32 #define apr_palloc(pool,size) malloc(size)
35 APU_DECLARE_DATA apr_pool_t
*apr_hook_global_pool
= NULL
;
36 APU_DECLARE_DATA
int apr_hook_debug_enabled
= 0;
37 APU_DECLARE_DATA
const char *apr_hook_debug_current
= NULL
;
39 /** @deprecated @see apr_hook_global_pool */
40 APU_DECLARE_DATA apr_pool_t
*apr_global_hook_pool
= NULL
;
42 /** @deprecated @see apr_hook_debug_enabled */
43 APU_DECLARE_DATA
int apr_debug_module_hooks
= 0;
45 /** @deprecated @see apr_hook_debug_current */
46 APU_DECLARE_DATA
const char *apr_current_hooking_module
= NULL
;
48 /* NB: This must echo the LINK_##name structure */
51 void (*dummy
)(void *);
53 const char * const *aszPredecessors
;
54 const char * const *aszSuccessors
;
62 struct tsort_
**ppPredecessors
;
67 #include "apr_private.h"
68 #define get_apd APP_DATA* apd = (APP_DATA*)get_app_data(gLibId);
69 #define s_aHooksToSort ((apr_array_header_t *)(apd->gs_aHooksToSort))
70 #define s_phOptionalHooks ((apr_hash_t *)(apd->gs_phOptionalHooks))
71 #define s_phOptionalFunctions ((apr_hash_t *)(apd->gs_phOptionalFunctions))
74 static int crude_order(const void *a_
,const void *b_
)
76 const TSortData
*a
=a_
;
77 const TSortData
*b
=b_
;
79 return a
->nOrder
-b
->nOrder
;
82 static TSort
*prepare(apr_pool_t
*p
,TSortData
*pItems
,int nItems
)
84 TSort
*pData
=apr_palloc(p
,nItems
*sizeof *pData
);
87 qsort(pItems
,nItems
,sizeof *pItems
,crude_order
);
88 for(n
=0 ; n
< nItems
; ++n
) {
89 pData
[n
].nPredecessors
=0;
90 pData
[n
].ppPredecessors
=apr_pcalloc(p
,nItems
*sizeof *pData
[n
].ppPredecessors
);
92 pData
[n
].pData
=&pItems
[n
];
95 for(n
=0 ; n
< nItems
; ++n
) {
98 for(i
=0 ; pItems
[n
].aszPredecessors
&& pItems
[n
].aszPredecessors
[i
] ; ++i
)
99 for(k
=0 ; k
< nItems
; ++k
)
100 if(!strcmp(pItems
[k
].szName
,pItems
[n
].aszPredecessors
[i
])) {
103 for(l
=0 ; l
< pData
[n
].nPredecessors
; ++l
)
104 if(pData
[n
].ppPredecessors
[l
] == &pData
[k
])
106 pData
[n
].ppPredecessors
[pData
[n
].nPredecessors
]=&pData
[k
];
107 ++pData
[n
].nPredecessors
;
111 for(i
=0 ; pItems
[n
].aszSuccessors
&& pItems
[n
].aszSuccessors
[i
] ; ++i
)
112 for(k
=0 ; k
< nItems
; ++k
)
113 if(!strcmp(pItems
[k
].szName
,pItems
[n
].aszSuccessors
[i
])) {
116 for(l
=0 ; l
< pData
[k
].nPredecessors
; ++l
)
117 if(pData
[k
].ppPredecessors
[l
] == &pData
[n
])
119 pData
[k
].ppPredecessors
[pData
[k
].nPredecessors
]=&pData
[n
];
120 ++pData
[k
].nPredecessors
;
129 /* Topologically sort, dragging out-of-order items to the front. Note that
130 this tends to preserve things that want to be near the front better, and
131 changing that behaviour might compromise some of Apache's behaviour (in
132 particular, mod_log_forensic might otherwise get pushed to the end, and
133 core.c's log open function used to end up at the end when pushing items
134 to the back was the methedology). Also note that the algorithm could
135 go back to its original simplicity by sorting from the back instead of
138 static TSort
*tsort(TSort
*pData
,int nItems
)
144 for(nTotal
=0 ; nTotal
< nItems
; ++nTotal
) {
149 assert(0); /* we have a loop... */
150 if(!pData
[n
].pNext
) {
151 if(pData
[n
].nPredecessors
) {
154 if(pData
[n
].ppPredecessors
[k
])
159 if(&pData
[i
] == pData
[n
].ppPredecessors
[k
]) {
169 pTail
->pNext
=&pData
[n
];
173 pTail
->pNext
=pTail
; /* fudge it so it looks linked */
174 for(i
=0 ; i
< nItems
; ++i
)
175 for(k
=0 ; k
< nItems
; ++k
)
176 if(pData
[i
].ppPredecessors
[k
] == &pData
[n
]) {
177 --pData
[i
].nPredecessors
;
178 pData
[i
].ppPredecessors
[k
]=NULL
;
182 pTail
->pNext
=NULL
; /* unfudge the tail */
186 static apr_array_header_t
*sort_hook(apr_array_header_t
*pHooks
,
191 apr_array_header_t
*pNew
;
194 apr_pool_create(&p
, apr_hook_global_pool
);
195 pSort
=prepare(p
,(TSortData
*)pHooks
->elts
,pHooks
->nelts
);
196 pSort
=tsort(pSort
,pHooks
->nelts
);
197 pNew
=apr_array_make(apr_hook_global_pool
,pHooks
->nelts
,sizeof(TSortData
));
198 if(apr_hook_debug_enabled
)
199 printf("Sorting %s:",szName
);
200 for(n
=0 ; pSort
; pSort
=pSort
->pNext
,++n
) {
202 assert(n
< pHooks
->nelts
);
203 pHook
=apr_array_push(pNew
);
204 memcpy(pHook
,pSort
->pData
,sizeof *pHook
);
205 if(apr_hook_debug_enabled
)
206 printf(" %s",pHook
->szName
);
208 if(apr_hook_debug_enabled
)
214 static apr_array_header_t
*s_aHooksToSort
;
219 const char *szHookName
;
220 apr_array_header_t
**paHooks
;
223 APU_DECLARE(void) apr_hook_sort_register(const char *szHookName
,
224 apr_array_header_t
**paHooks
)
229 HookSortEntry
*pEntry
;
232 s_aHooksToSort
=apr_array_make(apr_hook_global_pool
,1,sizeof(HookSortEntry
));
233 pEntry
=apr_array_push(s_aHooksToSort
);
234 pEntry
->szHookName
=szHookName
;
235 pEntry
->paHooks
=paHooks
;
238 APU_DECLARE(void) apr_hook_sort_all(void)
245 for(n
=0 ; n
< s_aHooksToSort
->nelts
; ++n
) {
246 HookSortEntry
*pEntry
=&((HookSortEntry
*)s_aHooksToSort
->elts
)[n
];
247 *pEntry
->paHooks
=sort_hook(*pEntry
->paHooks
,pEntry
->szHookName
);
252 static apr_hash_t
*s_phOptionalHooks
;
253 static apr_hash_t
*s_phOptionalFunctions
;
256 APU_DECLARE(void) apr_hook_deregister_all(void)
263 for(n
=0 ; n
< s_aHooksToSort
->nelts
; ++n
) {
264 HookSortEntry
*pEntry
=&((HookSortEntry
*)s_aHooksToSort
->elts
)[n
];
265 *pEntry
->paHooks
=NULL
;
268 s_phOptionalHooks
=NULL
;
269 s_phOptionalFunctions
=NULL
;
272 APU_DECLARE(void) apr_hook_debug_show(const char *szName
,
273 const char * const *aszPre
,
274 const char * const *aszSucc
)
278 printf(" Hooked %s",szName
);
280 fputs(" pre(",stdout
);
286 fputs(*aszPre
,stdout
);
292 fputs(" succ(",stdout
);
298 fputs(*aszSucc
,stdout
);
306 /* Optional hook support */
308 APR_DECLARE_EXTERNAL_HOOK(apr
,APU
,void,_optional
,(void))
310 APU_DECLARE(apr_array_header_t
*) apr_optional_hook_get(const char *szName
)
315 apr_array_header_t
**ppArray
;
317 if(!s_phOptionalHooks
)
319 ppArray
=apr_hash_get(s_phOptionalHooks
,szName
,strlen(szName
));
325 APU_DECLARE(void) apr_optional_hook_add(const char *szName
,void (*pfn
)(void),
326 const char * const *aszPre
,
327 const char * const *aszSucc
,int nOrder
)
332 apr_array_header_t
*pArray
=apr_optional_hook_get(szName
);
333 apr_LINK__optional_t
*pHook
;
336 apr_array_header_t
**ppArray
;
338 pArray
=apr_array_make(apr_hook_global_pool
,1,
339 sizeof(apr_LINK__optional_t
));
340 if(!s_phOptionalHooks
)
341 s_phOptionalHooks
=apr_hash_make(apr_hook_global_pool
);
342 ppArray
=apr_palloc(apr_hook_global_pool
,sizeof *ppArray
);
344 apr_hash_set(s_phOptionalHooks
,szName
,strlen(szName
),ppArray
);
345 apr_hook_sort_register(szName
,ppArray
);
347 pHook
=apr_array_push(pArray
);
349 pHook
->aszPredecessors
=aszPre
;
350 pHook
->aszSuccessors
=aszSucc
;
351 pHook
->nOrder
=nOrder
;
352 pHook
->szName
=apr_hook_debug_current
;
353 if(apr_hook_debug_enabled
)
354 apr_hook_debug_show(szName
,aszPre
,aszSucc
);
357 /* optional function support */
359 APU_DECLARE(apr_opt_fn_t
*) apr_dynamic_fn_retrieve(const char *szName
)
364 if(!s_phOptionalFunctions
)
366 return (void(*)(void))apr_hash_get(s_phOptionalFunctions
,szName
,strlen(szName
));
370 APU_DECLARE_NONSTD(void) apr_dynamic_fn_register(const char *szName
,
376 if(!s_phOptionalFunctions
)
377 s_phOptionalFunctions
=apr_hash_make(apr_hook_global_pool
);
378 apr_hash_set(s_phOptionalFunctions
,szName
,strlen(szName
),(void *)pfn
);
384 const char *aszAPre
[]={"b","c",NULL
};
385 const char *aszBPost
[]={"a",NULL
};
386 const char *aszCPost
[]={"b",NULL
};
389 { "a",aszAPre
,NULL
},
390 { "b",NULL
,aszBPost
},
391 { "c",NULL
,aszCPost
}
395 pResult
=prepare(t1
,3);
396 pResult
=tsort(pResult
,3);
398 for( ; pResult
; pResult
=pResult
->pNext
)
399 printf("%s\n",pResult
->pData
->szName
);