1/* 2 * Copyright (C) 2004, 2006, 2007, 2013 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 ***/ 169ISC_LANG_BEGINDECLS 170 171isc_result_t 172dns_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 199void 200dns_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 215void 216dns_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 233void 234dns_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 240void 241dns_acache_setcachesize(dns_acache_t *acache, size_t size); 242/* 243 * Set the maximum additional cache size. 0 means unlimited. 244 */ 245 246isc_result_t 247dns_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 265isc_result_t 266dns_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 285void 286dns_acache_shutdown(dns_acache_t *acache); 287/* 288 * Shutdown 'acache'. 289 * 290 * Requires: 291 * 292 * '*acache' is a valid additional cache. 293 */ 294 295isc_result_t 296dns_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 322isc_result_t 323dns_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 371isc_result_t 372dns_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 390isc_boolean_t 391dns_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 * Returns: 403 * ISC_TRUE if the entry was active when canceled 404 */ 405 406void 407dns_acache_attachentry(dns_acacheentry_t *source, dns_acacheentry_t **targetp); 408/* 409 * Attach *targetp to the cache entry 'source'. 410 * 411 * Requires: 412 * 413 * 'source' is a valid additional cache entry. 414 * 415 * 'targetp' points to a NULL dns_acacheentry_t *. 416 * 417 * Ensures: 418 * 419 * *targetp is attached to 'source'. 420 */ 421 422void 423dns_acache_detachentry(dns_acacheentry_t **entryp); 424/* 425 * Detach *entryp from its cache. 426 * 427 * Requires: 428 * 429 * '*entryp' points to a valid additional cache entry. 430 * 431 * Ensures: 432 * 433 * *entryp is NULL. 434 * 435 * If '*entryp' is the last reference to the entry, 436 * cache does not have an outstanding task, all resources used by the 437 * entry (including the entry object itself) will be freed. 438 */ 439 440void 441dns_acache_countquerymiss(dns_acache_t *acache); 442/* 443 * Count up a missed acache query. XXXMLG need more docs. 444 */ 445 446ISC_LANG_ENDDECLS 447 448#endif /* DNS_ACACHE_H */ 449