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