00001 /* 00002 * Copyright (C) 2004, 2006, 2007, 2013 Internet Systems Consortium, Inc. ("ISC") 00003 * 00004 * Permission to use, copy, modify, and/or distribute this software for any 00005 * purpose with or without fee is hereby granted, provided that the above 00006 * copyright notice and this permission notice appear in all copies. 00007 * 00008 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 00009 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 00010 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 00011 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 00012 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 00013 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 00014 * PERFORMANCE OF THIS SOFTWARE. 00015 */ 00016 00017 /* $Id: acache.h,v 1.8 2007/06/19 23:47:16 tbox Exp $ */ 00018 00019 #ifndef DNS_ACACHE_H 00020 #define DNS_ACACHE_H 1 00021 00022 /***** 00023 ***** Module Info 00024 *****/ 00025 00026 /* 00027 * Acache 00028 * 00029 * The Additional Cache Object 00030 * 00031 * This module manages internal caching entries that correspond to 00032 * the additional section data of a DNS DB node (an RRset header, more 00033 * accurately). An additional cache entry is expected to be (somehow) 00034 * attached to a particular RR in a particular DB node, and contains a set 00035 * of information of an additional data for the DB node. 00036 * 00037 * An additional cache object is intended to be created as a per-view 00038 * object, and manages all cache entries within the view. 00039 * 00040 * The intended usage of the additional caching is to provide a short cut 00041 * to additional glue RRs of an NS RR. For each NS RR, it is often 00042 * necessary to look for glue RRs to make a proper response. Once the 00043 * glue RRs are known, the additional caching allows the client to 00044 * associate the information to the original NS RR so that further 00045 * expensive lookups can be avoided for the NS RR. 00046 * 00047 * Each additional cache entry contains information to identify a 00048 * particular DB node and (optionally) an associated RRset. The 00049 * information consists of its zone, database, the version of the 00050 * database, database node, and RRset. 00051 * 00052 * A "negative" information can also be cached. For example, if a glue 00053 * RR does not exist as an authoritative data in the same zone as that 00054 * of the NS RR, this fact can be cached by specifying a NULL pointer 00055 * for the database, version, and node. (See the description for 00056 * dns_acache_getentry() below for more details.) 00057 * 00058 * Since each member stored in an additional cache entry holds a reference 00059 * to a corresponding object, a stale cache entry may cause unnecessary 00060 * memory consumption. For instance, when a zone is reloaded, additional 00061 * cache entries that have a reference to the zone (and its DB and/or 00062 * DB nodes) can delay the cleanup of the referred objects. In order to 00063 * minimize such a bad effect, this module provides several cleanup 00064 * mechanisms. 00065 * 00066 * The first one is a shutdown procedure called when the associated view 00067 * is shut down. In this case, dns_acache_shutdown() will be called and 00068 * all cache entries will be purged. This mechanism will help the 00069 * situation when the configuration is reloaded or the main server is 00070 * stopped. 00071 * 00072 * Per-DB cleanup mechanism is also provided. Each additional cache entry 00073 * is associated with related DB, which is expected to have been 00074 * registered when the DB was created by dns_acache_setdb(). If a 00075 * particular DB is going to be destroyed, the primary holder of the DB, 00076 * a typical example of which is a zone, will call dns_acache_putdb(). 00077 * Then this module will clean-up all cache entries associated with the 00078 * DB. This mechanism is effective when a secondary zone DB is going to 00079 * be stale after a zone transfer. 00080 * 00081 * Finally, this module supports for periodic clean-up of stale entries. 00082 * Each cache entry has a timestamp field, which is updated every time 00083 * the entry is referred. A periodically invoked cleaner checks the 00084 * timestamp of each entry, and purge entries that have not been referred 00085 * for a certain period. The cleaner interval can be specified by 00086 * dns_acache_setcleaninginterval(). If the periodic clean-up is not 00087 * enough, it is also possible to specify the upper limit of entries 00088 * in terms of the memory consumption. If the maximum value is 00089 * specified, the cleaner is invoked when the memory consumption reaches 00090 * the high watermark inferred from the maximum value. In this case, 00091 * the cleaner will use more aggressive algorithm to decide the "victim" 00092 * entries. The maximum value can be specified by 00093 * dns_acache_setcachesize(). 00094 * 00095 * When a cache entry is going to be purged within this module, the 00096 * callback function specified at the creation time will be called. 00097 * The callback function is expected to release all internal resources 00098 * related to the entry, which will typically be specific to DB 00099 * implementation, and to call dns_acache_detachentry(). The callback 00100 * mechanism is very important, since the holder of an additional cache 00101 * entry may not be able to initiate the clean-up of the entry, due to 00102 * the reference ordering. For example, as long as an additional cache 00103 * entry has a reference to a DB object, the DB cannot be freed, in which 00104 * a DB node may have a reference to the cache entry. 00105 * 00106 * Credits: 00107 * The basic idea of this kind of short-cut for frequently used 00108 * information is similar to the "pre-compiled answer" approach adopted 00109 * in nsd by NLnet LABS with RIPE NCC. Our work here is an independent 00110 * effort, but the success of nsd encouraged us to pursue this path. 00111 * 00112 * The design and implementation of the periodic memory management and 00113 * the upper limitation of memory consumption was derived from the cache 00114 * DB implementation of BIND9. 00115 * 00116 * MP: 00117 * There are two main locks in this module. One is for each entry, and 00118 * the other is for the additional cache object. 00119 * 00120 * Reliability: 00121 * The callback function for a cache entry is called with holding the 00122 * entry lock. Thus, it implicitly assumes the callback function does not 00123 * call a function that can require the lock. Typically, the only 00124 * function that can be called from the callback function safely is 00125 * dns_acache_detachentry(). The breakage of this implicit assumption 00126 * may cause a deadlock. 00127 * 00128 * Resources: 00129 * In a 32-bit architecture (such as i386), the following additional 00130 * memory is required comparing to the case that disables this module. 00131 * - 76 bytes for each additional cache entry 00132 * - if the entry has a DNS name and associated RRset, 00133 * * 44 bytes + size of the name (1-255 bytes) 00134 * * 52 bytes x number_of_RRs 00135 * - 28 bytes for each DB related to this module 00136 * 00137 * Using the additional cache also requires extra memory consumption in 00138 * the DB implementation. In the current implementation for rbtdb, we 00139 * need: 00140 * - two additional pointers for each DB node (8 bytes for a 32-bit 00141 * architecture 00142 * - for each RR associated to an RR in a DB node, we also need 00143 * a pointer and management objects to support the additional cache 00144 * function. These are allocated on-demand. The total size is 00145 * 32 bytes for a 32-bit architecture. 00146 * 00147 * Security: 00148 * Since this module does not handle any low-level data directly, 00149 * no security issue specific to this module is anticipated. 00150 * 00151 * Standards: 00152 * None. 00153 */ 00154 00155 /*** 00156 *** Imports 00157 ***/ 00158 00159 #include <isc/mutex.h> 00160 #include <isc/lang.h> 00161 #include <isc/refcount.h> 00162 #include <isc/stdtime.h> 00163 00164 #include <dns/types.h> 00165 00166 /*** 00167 *** Functions 00168 ***/ 00169 ISC_LANG_BEGINDECLS 00170 00171 isc_result_t 00172 dns_acache_create(dns_acache_t **acachep, isc_mem_t *mctx, 00173 isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr); 00174 /* 00175 * Create a new DNS additional cache object. 00176 * 00177 * Requires: 00178 * 00179 * 'mctx' is a valid memory context 00180 * 00181 * 'taskmgr' is a valid task manager 00182 * 00183 * 'timermgr' is a valid timer or NULL. If NULL, no periodic cleaning of 00184 * the cache will take place. 00185 * 00186 * 'acachep' is a valid pointer, and *acachep == NULL 00187 * 00188 * Ensures: 00189 * 00190 * '*acachep' is attached to the newly created cache 00191 * 00192 * Returns: 00193 * 00194 * ISC_R_SUCCESS 00195 * ISC_R_NOMEMORY 00196 * ISC_R_UNEXPECTED 00197 */ 00198 00199 void 00200 dns_acache_attach(dns_acache_t *source, dns_acache_t **targetp); 00201 /* 00202 * Attach *targetp to cache. 00203 * 00204 * Requires: 00205 * 00206 * 'acache' is a valid additional cache. 00207 * 00208 * 'targetp' points to a NULL dns_acache_t *. 00209 * 00210 * Ensures: 00211 * 00212 * *targetp is attached to the 'source' additional cache. 00213 */ 00214 00215 void 00216 dns_acache_detach(dns_acache_t **acachep); 00217 /* 00218 * Detach *acachep from its cache. 00219 * 00220 * Requires: 00221 * 00222 * '*acachep' points to a valid additional cache. 00223 * 00224 * Ensures: 00225 * 00226 * *acachep is NULL. 00227 * 00228 * If '*acachep' is the last reference to the cache and the additional 00229 * cache does not have an outstanding task, all resources used by the 00230 * cache will be freed. 00231 */ 00232 00233 void 00234 dns_acache_setcleaninginterval(dns_acache_t *acache, unsigned int t); 00235 /* 00236 * Set the periodic cleaning interval of an additional cache to 'interval' 00237 * seconds. 00238 */ 00239 00240 void 00241 dns_acache_setcachesize(dns_acache_t *acache, size_t size); 00242 /* 00243 * Set the maximum additional cache size. 0 means unlimited. 00244 */ 00245 00246 isc_result_t 00247 dns_acache_setdb(dns_acache_t *acache, dns_db_t *db); 00248 /* 00249 * Set 'db' in 'acache' when the db can be referred from acache, in order 00250 * to provide a hint for resolving the back reference. 00251 * 00252 * Requires: 00253 * 'acache' is a valid acache pointer. 00254 * 'db' is a valid DNS DB pointer. 00255 * 00256 * Ensures: 00257 * 'acache' will have a reference to 'db'. 00258 * 00259 * Returns: 00260 * ISC_R_SUCCESS 00261 * ISC_R_EXISTS (which means the specified 'db' is already set) 00262 * ISC_R_NOMEMORY 00263 */ 00264 00265 isc_result_t 00266 dns_acache_putdb(dns_acache_t *acache, dns_db_t *db); 00267 /* 00268 * Release 'db' from 'acache' if it has been set by dns_acache_setdb(). 00269 * 00270 * Requires: 00271 * 'acache' is a valid acache pointer. 00272 * 'db' is a valid DNS DB pointer. 00273 * 00274 * Ensures: 00275 * 'acache' will release the reference to 'db'. Additionally, the content 00276 * of each cache entry that is related to the 'db' will be released via 00277 * the callback function. 00278 * 00279 * Returns: 00280 * ISC_R_SUCCESS 00281 * ISC_R_NOTFOUND (which means the specified 'db' is not set in 'acache') 00282 * ISC_R_NOMEMORY 00283 */ 00284 00285 void 00286 dns_acache_shutdown(dns_acache_t *acache); 00287 /* 00288 * Shutdown 'acache'. 00289 * 00290 * Requires: 00291 * 00292 * '*acache' is a valid additional cache. 00293 */ 00294 00295 isc_result_t 00296 dns_acache_createentry(dns_acache_t *acache, dns_db_t *origdb, 00297 void (*callback)(dns_acacheentry_t *, void **), 00298 void *cbarg, dns_acacheentry_t **entryp); 00299 /* 00300 * Create an additional cache entry. A new entry is created and attached to 00301 * the given additional cache object. A callback function is also associated 00302 * with the created entry, which will be called when the cache entry is purged 00303 * for some reason. 00304 * 00305 * Requires: 00306 * 00307 * 'acache' is a valid additional cache. 00308 * 'entryp' is a valid pointer, and *entryp == NULL 00309 * 'origdb' is a valid DNS DB pointer. 00310 * 'callback' and 'cbarg' can be NULL. In this case, however, the entry 00311 * is meaningless (and will be cleaned-up in the next periodical 00312 * cleaning). 00313 * 00314 * Ensures: 00315 * '*entryp' will point to a new additional cache entry. 00316 * 00317 * Returns: 00318 * ISC_R_SUCCESS 00319 * ISC_R_NOMEMORY 00320 */ 00321 00322 isc_result_t 00323 dns_acache_getentry(dns_acacheentry_t *entry, dns_zone_t **zonep, 00324 dns_db_t **dbp, dns_dbversion_t **versionp, 00325 dns_dbnode_t **nodep, dns_name_t *fname, 00326 dns_message_t *msg, isc_stdtime_t now); 00327 /* 00328 * Get content from a particular additional cache entry. 00329 * 00330 * Requires: 00331 * 00332 * 'entry' is a valid additional cache entry. 00333 * 'zonep' is a NULL pointer or '*zonep' == NULL (this is the only 00334 * optional parameter.) 00335 * 'dbp' is a valid pointer, and '*dbp' == NULL 00336 * 'versionp' is a valid pointer, and '*versionp' == NULL 00337 * 'nodep' is a valid pointer, and '*nodep' == NULL 00338 * 'fname' is a valid DNS name. 00339 * 'msg' is a valid DNS message. 00340 * 00341 * Ensures: 00342 * Several possible cases can happen according to the content. 00343 * 1. For a positive cache entry, 00344 * '*zonep' will point to the corresponding zone (if zonep is a valid 00345 * pointer), 00346 * '*dbp' will point to a DB for the zone, 00347 * '*versionp' will point to its version, and 00348 * '*nodep' will point to the corresponding DB node. 00349 * 'fname' will have the DNS name of the DB node and contain a list of 00350 * rdataset for the node (which can be an empty list). 00351 * 00352 * 2. For a negative cache entry that means no corresponding zone exists, 00353 * '*zonep' == NULL (if zonep is a valid pointer) 00354 * '*dbp', '*versionp', and '*nodep' will be NULL. 00355 * 00356 * 3. For a negative cache entry that means no corresponding DB node 00357 * exists, '*zonep' will point to the corresponding zone (if zonep is a 00358 * valid pointer), 00359 * '*dbp' will point to a corresponding DB for zone, 00360 * '*versionp' will point to its version. 00361 * '*nodep' will be kept as NULL. 00362 * 'fname' will not change. 00363 * 00364 * On failure, no new references will be created. 00365 * 00366 * Returns: 00367 * ISC_R_SUCCESS 00368 * ISC_R_NOMEMORY 00369 */ 00370 00371 isc_result_t 00372 dns_acache_setentry(dns_acache_t *acache, dns_acacheentry_t *entry, 00373 dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, 00374 dns_dbnode_t *node, dns_name_t *fname); 00375 /* 00376 * Set content to a particular additional cache entry. 00377 * 00378 * Requires: 00379 * 'acache' is a valid additional cache. 00380 * 'entry' is a valid additional cache entry. 00381 * All the others pointers are NULL or a valid pointer of the 00382 * corresponding type. 00383 * 00384 * Returns: 00385 * ISC_R_SUCCESS 00386 * ISC_R_NOMEMORY 00387 * ISC_R_NOTFOUND 00388 */ 00389 00390 isc_boolean_t 00391 dns_acache_cancelentry(dns_acacheentry_t *entry); 00392 /* 00393 * Cancel the use of the cache entry 'entry'. This function is supposed to 00394 * be called when the node that holds the entry finds the content is not 00395 * correct any more. This function will try to release as much dependency as 00396 * possible, and will be ready to be cleaned-up. The registered callback 00397 * function will be canceled and will never called. 00398 * 00399 * Requires: 00400 * 'entry' is a valid additional cache entry. 00401 * 00402 * Returns: 00403 * ISC_TRUE if the entry was active when canceled 00404 */ 00405 00406 void 00407 dns_acache_attachentry(dns_acacheentry_t *source, dns_acacheentry_t **targetp); 00408 /* 00409 * Attach *targetp to the cache entry 'source'. 00410 * 00411 * Requires: 00412 * 00413 * 'source' is a valid additional cache entry. 00414 * 00415 * 'targetp' points to a NULL dns_acacheentry_t *. 00416 * 00417 * Ensures: 00418 * 00419 * *targetp is attached to 'source'. 00420 */ 00421 00422 void 00423 dns_acache_detachentry(dns_acacheentry_t **entryp); 00424 /* 00425 * Detach *entryp from its cache. 00426 * 00427 * Requires: 00428 * 00429 * '*entryp' points to a valid additional cache entry. 00430 * 00431 * Ensures: 00432 * 00433 * *entryp is NULL. 00434 * 00435 * If '*entryp' is the last reference to the entry, 00436 * cache does not have an outstanding task, all resources used by the 00437 * entry (including the entry object itself) will be freed. 00438 */ 00439 00440 void 00441 dns_acache_countquerymiss(dns_acache_t *acache); 00442 /* 00443 * Count up a missed acache query. XXXMLG need more docs. 00444 */ 00445 00446 ISC_LANG_ENDDECLS 00447 00448 #endif /* DNS_ACACHE_H */