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