Detect FPU by checking CPUID features.
[dragonfly.git] / contrib / bind-9.5.2 / lib / dns / include / dns / acache.h
1 /*
2  * Copyright (C) 2004, 2006, 2007  Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 /* $Id: acache.h,v 1.8 2007/06/19 23:47:16 tbox Exp $ */
18
19 #ifndef DNS_ACACHE_H
20 #define DNS_ACACHE_H 1
21
22 /*****
23  ***** Module Info
24  *****/
25
26 /*
27  * Acache
28  * 
29  * The Additional Cache Object
30  *
31  *      This module manages internal caching entries that correspond to
32  *      the additional section data of a DNS DB node (an RRset header, more
33  *      accurately).  An additional cache entry is expected to be (somehow)
34  *      attached to a particular RR in a particular DB node, and contains a set
35  *      of information of an additional data for the DB node.
36  *
37  *      An additional cache object is intended to be created as a per-view
38  *      object, and manages all cache entries within the view.
39  *
40  *      The intended usage of the additional caching is to provide a short cut
41  *      to additional glue RRs of an NS RR.  For each NS RR, it is often
42  *      necessary to look for glue RRs to make a proper response.  Once the
43  *      glue RRs are known, the additional caching allows the client to
44  *      associate the information to the original NS RR so that further
45  *      expensive lookups can be avoided for the NS RR.
46  *
47  *      Each additional cache entry contains information to identify a
48  *      particular DB node and (optionally) an associated RRset.  The
49  *      information consists of its zone, database, the version of the
50  *      database, database node, and RRset.
51  *
52  *      A "negative" information can also be cached.  For example, if a glue
53  *      RR does not exist as an authoritative data in the same zone as that
54  *      of the NS RR, this fact can be cached by specifying a NULL pointer
55  *      for the database, version, and node.  (See the description for
56  *      dns_acache_getentry() below for more details.)
57  *
58  *      Since each member stored in an additional cache entry holds a reference
59  *      to a corresponding object, a stale cache entry may cause unnecessary
60  *      memory consumption.  For instance, when a zone is reloaded, additional
61  *      cache entries that have a reference to the zone (and its DB and/or
62  *      DB nodes) can delay the cleanup of the referred objects.  In order to
63  *      minimize such a bad effect, this module provides several cleanup
64  *      mechanisms.
65  *
66  *      The first one is a shutdown procedure called when the associated view
67  *      is shut down.  In this case, dns_acache_shutdown() will be called and
68  *      all cache entries will be purged.  This mechanism will help the
69  *      situation when the configuration is reloaded or the main server is
70  *      stopped.
71  *
72  *      Per-DB cleanup mechanism is also provided.  Each additional cache entry
73  *      is associated with related DB, which is expected to have been
74  *      registered when the DB was created by dns_acache_setdb().  If a
75  *      particular DB is going to be destroyed, the primary holder of the DB,
76  *      a typical example of which is a zone, will call dns_acache_putdb().
77  *      Then this module will clean-up all cache entries associated with the
78  *      DB.  This mechanism is effective when a secondary zone DB is going to
79  *      be stale after a zone transfer.
80  *
81  *      Finally, this module supports for periodic clean-up of stale entries.
82  *      Each cache entry has a timestamp field, which is updated every time
83  *      the entry is referred.  A periodically invoked cleaner checks the
84  *      timestamp of each entry, and purge entries that have not been referred
85  *      for a certain period.  The cleaner interval can be specified by
86  *      dns_acache_setcleaninginterval().  If the periodic clean-up is not
87  *      enough, it is also possible to specify the upper limit of entries
88  *      in terms of the memory consumption.  If the maximum value is
89  *      specified, the cleaner is invoked when the memory consumption reaches
90  *      the high watermark inferred from the maximum value.  In this case,
91  *      the cleaner will use more aggressive algorithm to decide the "victim"
92  *      entries.  The maximum value can be specified by
93  *      dns_acache_setcachesize().
94  *
95  *      When a cache entry is going to be purged within this module, the
96  *      callback function specified at the creation time will be called.
97  *      The callback function is expected to release all internal resources
98  *      related to the entry, which will typically be specific to DB
99  *      implementation, and to call dns_acache_detachentry().  The callback
100  *      mechanism is very important, since the holder of an additional cache
101  *      entry may not be able to initiate the clean-up of the entry, due to
102  *      the reference ordering.  For example, as long as an additional cache
103  *      entry has a reference to a DB object, the DB cannot be freed, in which
104  *      a DB node may have a reference to the cache entry.
105  *
106  *      Credits:
107  *      The basic idea of this kind of short-cut for frequently used
108  *      information is similar to the "pre-compiled answer" approach adopted
109  *      in nsd by NLnet LABS with RIPE NCC.  Our work here is an independent
110  *      effort, but the success of nsd encouraged us to pursue this path.
111  *
112  *      The design and implementation of the periodic memory management and
113  *      the upper limitation of memory consumption was derived from the cache
114  *      DB implementation of BIND9.
115  *
116  * MP:
117  *      There are two main locks in this module.  One is for each entry, and
118  *      the other is for the additional cache object.
119  *
120  * Reliability:
121  *      The callback function for a cache entry is called with holding the
122  *      entry lock.  Thus, it implicitly assumes the callback function does not
123  *      call a function that can require the lock.  Typically, the only
124  *      function that can be called from the callback function safely is
125  *      dns_acache_detachentry().  The breakage of this implicit assumption
126  *      may cause a deadlock.
127  *
128  * Resources:
129  *      In a 32-bit architecture (such as i386), the following additional
130  *      memory is required comparing to the case that disables this module.
131  *      - 76 bytes for each additional cache entry
132  *      - if the entry has a DNS name and associated RRset,
133  *        * 44 bytes + size of the name (1-255 bytes)
134  *        * 52 bytes x number_of_RRs 
135  *      - 28 bytes for each DB related to this module
136  *
137  *      Using the additional cache also requires extra memory consumption in
138  *      the DB implementation.  In the current implementation for rbtdb, we
139  *      need:
140  *      - two additional pointers for each DB node (8 bytes for a 32-bit
141  *        architecture
142  *      - for each RR associated to an RR in a DB node, we also need
143  *        a pointer and management objects to support the additional cache
144  *        function.  These are allocated on-demand.  The total size is
145  *        32 bytes for a 32-bit architecture.
146  *
147  * Security:
148  *      Since this module does not handle any low-level data directly,
149  *      no security issue specific to this module is anticipated.
150  *
151  * Standards:
152  *      None.
153  */
154
155 /***
156  *** Imports
157  ***/
158
159 #include <isc/mutex.h>
160 #include <isc/lang.h>
161 #include <isc/refcount.h>
162 #include <isc/stdtime.h>
163
164 #include <dns/types.h>
165
166 /***
167  *** Functions
168  ***/
169 ISC_LANG_BEGINDECLS
170
171 isc_result_t
172 dns_acache_create(dns_acache_t **acachep, isc_mem_t *mctx,
173                   isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr);
174 /*
175  * Create a new DNS additional cache object.
176  *
177  * Requires:
178  *
179  *      'mctx' is a valid memory context
180  *
181  *      'taskmgr' is a valid task manager
182  *
183  *      'timermgr' is a valid timer or NULL.  If NULL, no periodic cleaning of
184  *      the cache will take place.
185  *
186  *      'acachep' is a valid pointer, and *acachep == NULL
187  *
188  * Ensures:
189  *
190  *      '*acachep' is attached to the newly created cache
191  *
192  * Returns:
193  *
194  *      ISC_R_SUCCESS
195  *      ISC_R_NOMEMORY
196  *      ISC_R_UNEXPECTED
197  */
198
199 void
200 dns_acache_attach(dns_acache_t *source, dns_acache_t **targetp);
201 /*
202  * Attach *targetp to cache.
203  *
204  * Requires:
205  *
206  *      'acache' is a valid additional cache.
207  *
208  *      'targetp' points to a NULL dns_acache_t *.
209  *
210  * Ensures:
211  *
212  *      *targetp is attached to the 'source' additional cache.
213  */
214
215 void
216 dns_acache_detach(dns_acache_t **acachep);
217 /*
218  * Detach *acachep from its cache.
219  *
220  * Requires:
221  *
222  *      '*acachep' points to a valid additional cache.
223  *
224  * Ensures:
225  *
226  *      *acachep is NULL.
227  *
228  *      If '*acachep' is the last reference to the cache and the additional
229  *      cache does not have an outstanding task, all resources used by the
230  *      cache will be freed.
231  */
232
233 void
234 dns_acache_setcleaninginterval(dns_acache_t *acache, unsigned int t);
235 /*
236  * Set the periodic cleaning interval of an additional cache to 'interval'
237  * seconds.
238  */
239
240 void
241 dns_acache_setcachesize(dns_acache_t *acache, isc_uint32_t size);
242 /*
243  * Set the maximum additional cache size.  0 means unlimited.
244  */
245
246 isc_result_t
247 dns_acache_setdb(dns_acache_t *acache, dns_db_t *db);
248 /*
249  * Set 'db' in 'acache' when the db can be referred from acache, in order
250  * to provide a hint for resolving the back reference.
251  *
252  * Requires:
253  *      'acache' is a valid acache pointer.
254  *      'db' is a valid DNS DB pointer.
255  *
256  * Ensures:
257  *      'acache' will have a reference to 'db'.
258  *
259  * Returns:
260  *      ISC_R_SUCCESS
261  *      ISC_R_EXISTS    (which means the specified 'db' is already set)
262  *      ISC_R_NOMEMORY
263  */
264
265 isc_result_t
266 dns_acache_putdb(dns_acache_t *acache, dns_db_t *db);
267 /*
268  * Release 'db' from 'acache' if it has been set by dns_acache_setdb().
269  *
270  * Requires:
271  *      'acache' is a valid acache pointer.
272  *      'db' is a valid DNS DB pointer.
273  *
274  * Ensures:
275  *      'acache' will release the reference to 'db'.  Additionally, the content
276  *      of each cache entry that is related to the 'db' will be released via
277  *      the callback function.
278  *
279  * Returns:
280  *      ISC_R_SUCCESS
281  *      ISC_R_NOTFOUND  (which means the specified 'db' is not set in 'acache')
282  *      ISC_R_NOMEMORY
283  */
284
285 void
286 dns_acache_shutdown(dns_acache_t *acache);
287 /*
288  * Shutdown 'acache'.
289  *
290  * Requires:
291  *
292  *      '*acache' is a valid additional cache.
293  */
294
295 isc_result_t
296 dns_acache_createentry(dns_acache_t *acache, dns_db_t *origdb,
297                        void (*callback)(dns_acacheentry_t *, void **),
298                        void *cbarg, dns_acacheentry_t **entryp);
299 /*
300  * Create an additional cache entry.  A new entry is created and attached to
301  * the given additional cache object.  A callback function is also associated
302  * with the created entry, which will be called when the cache entry is purged
303  * for some reason.
304  *
305  * Requires:
306  *
307  *      'acache' is a valid additional cache.
308  *      'entryp' is a valid pointer, and *entryp == NULL
309  *      'origdb' is a valid DNS DB pointer.
310  *      'callback' and 'cbarg' can be NULL.  In this case, however, the entry
311  *      is meaningless (and will be cleaned-up in the next periodical
312  *      cleaning).
313  *
314  * Ensures:
315  *      '*entryp' will point to a new additional cache entry.
316  *
317  * Returns:
318  *      ISC_R_SUCCESS
319  *      ISC_R_NOMEMORY
320  */
321
322 isc_result_t
323 dns_acache_getentry(dns_acacheentry_t *entry, dns_zone_t **zonep,
324                     dns_db_t **dbp, dns_dbversion_t **versionp,
325                     dns_dbnode_t **nodep, dns_name_t *fname,
326                     dns_message_t *msg, isc_stdtime_t now);
327 /*
328  * Get content from a particular additional cache entry.
329  *
330  * Requires:
331  *
332  *      'entry' is a valid additional cache entry.
333  *      'zonep' is a NULL pointer or '*zonep' == NULL (this is the only
334  *      optional parameter.)
335  *      'dbp' is a valid pointer, and '*dbp' == NULL
336  *      'versionp' is a valid pointer, and '*versionp' == NULL
337  *      'nodep' is a valid pointer, and '*nodep' == NULL
338  *      'fname' is a valid DNS name.
339  *      'msg' is a valid DNS message.
340  *
341  * Ensures:
342  *      Several possible cases can happen according to the content.
343  *      1. For a positive cache entry,
344  *      '*zonep' will point to the corresponding zone (if zonep is a valid
345  *      pointer),
346  *      '*dbp' will point to a DB for the zone,
347  *      '*versionp' will point to its version, and
348  *      '*nodep' will point to the corresponding DB node.
349  *      'fname' will have the DNS name of the DB node and contain a list of
350  *      rdataset for the node (which can be an empty list).
351  *
352  *      2. For a negative cache entry that means no corresponding zone exists,
353  *      '*zonep' == NULL (if zonep is a valid pointer)
354  *      '*dbp', '*versionp', and '*nodep' will be NULL.
355  *
356  *      3. For a negative cache entry that means no corresponding DB node
357  *      exists, '*zonep' will point to the corresponding zone (if zonep is a
358  *      valid pointer),
359  *      '*dbp' will point to a corresponding DB for zone,
360  *      '*versionp' will point to its version.
361  *      '*nodep' will be kept as NULL.
362  *      'fname' will not change.
363  *
364  *      On failure, no new references will be created.
365  *
366  * Returns:
367  *      ISC_R_SUCCESS
368  *      ISC_R_NOMEMORY
369  */
370
371 isc_result_t
372 dns_acache_setentry(dns_acache_t *acache, dns_acacheentry_t *entry,
373                     dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
374                     dns_dbnode_t *node, dns_name_t *fname);
375 /*
376  * Set content to a particular additional cache entry.
377  *
378  * Requires:
379  *      'acache' is a valid additional cache.
380  *      'entry' is a valid additional cache entry.
381  *      All the others pointers are NULL or a valid pointer of the
382  *      corresponding type.
383  *
384  * Returns:
385  *      ISC_R_SUCCESS
386  *      ISC_R_NOMEMORY
387  *      ISC_R_NOTFOUND
388  */
389
390 void
391 dns_acache_cancelentry(dns_acacheentry_t *entry);
392 /*
393  * Cancel the use of the cache entry 'entry'.  This function is supposed to
394  * be called when the node that holds the entry finds the content is not
395  * correct any more.  This function will try to release as much dependency as
396  * possible, and will be ready to be cleaned-up.  The registered callback
397  * function will be canceled and will never called.
398  *
399  * Requires:
400  *      'entry' is a valid additional cache entry.
401  */
402
403 void
404 dns_acache_attachentry(dns_acacheentry_t *source, dns_acacheentry_t **targetp);
405 /*
406  * Attach *targetp to the cache entry 'source'.
407  *
408  * Requires:
409  *
410  *      'source' is a valid additional cache entry.
411  *
412  *      'targetp' points to a NULL dns_acacheentry_t *.
413  *
414  * Ensures:
415  *
416  *      *targetp is attached to 'source'.
417  */
418                        
419 void
420 dns_acache_detachentry(dns_acacheentry_t **entryp);
421 /*
422  * Detach *entryp from its cache.
423  *
424  * Requires:
425  *
426  *      '*entryp' points to a valid additional cache entry.
427  *
428  * Ensures:
429  *
430  *      *entryp is NULL.
431  *
432  *      If '*entryp' is the last reference to the entry, 
433  *      cache does not have an outstanding task, all resources used by the
434  *      entry (including the entry object itself) will be freed.
435  */
436
437 void
438 dns_acache_countquerymiss(dns_acache_t *acache);
439 /*
440  * Count up a missed acache query.  XXXMLG need more docs.
441  */
442
443 ISC_LANG_ENDDECLS
444
445 #endif /* DNS_ACACHE_H */