2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2001 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
19 * $Id: dbtable.c,v 1.25.2.2 2004/04/15 01:38:06 marka Exp $
23 * Principal Author: DCL
29 #include <isc/rwlock.h>
32 #include <dns/dbtable.h>
35 #include <dns/result.h>
41 dns_rdataclass_t rdclass
;
43 isc_rwlock_t tree_lock
;
45 unsigned int references
;
46 /* Locked by tree_lock. */
48 dns_db_t
* default_db
;
51 #define DBTABLE_MAGIC ISC_MAGIC('D', 'B', '-', '-')
52 #define VALID_DBTABLE(dbtable) ISC_MAGIC_VALID(dbtable, DBTABLE_MAGIC)
55 dbdetach(void *data
, void *arg
) {
64 dns_dbtable_create(isc_mem_t
*mctx
, dns_rdataclass_t rdclass
,
65 dns_dbtable_t
**dbtablep
)
67 dns_dbtable_t
*dbtable
;
70 REQUIRE(mctx
!= NULL
);
71 REQUIRE(dbtablep
!= NULL
&& *dbtablep
== NULL
);
73 dbtable
= (dns_dbtable_t
*)isc_mem_get(mctx
, sizeof(*dbtable
));
75 return (ISC_R_NOMEMORY
);
78 result
= dns_rbt_create(mctx
, dbdetach
, NULL
, &dbtable
->rbt
);
79 if (result
!= ISC_R_SUCCESS
)
82 result
= isc_mutex_init(&dbtable
->lock
);
83 if (result
!= ISC_R_SUCCESS
)
86 result
= isc_rwlock_init(&dbtable
->tree_lock
, 0, 0);
87 if (result
!= ISC_R_SUCCESS
)
91 dbtable
->default_db
= NULL
;
93 dbtable
->rdclass
= rdclass
;
94 dbtable
->magic
= DBTABLE_MAGIC
;
95 dbtable
->references
= 1;
99 return (ISC_R_SUCCESS
);
102 DESTROYLOCK(&dbtable
->lock
);
105 dns_rbt_destroy(&dbtable
->rbt
);
108 isc_mem_put(mctx
, dbtable
, sizeof(*dbtable
));
114 dbtable_free(dns_dbtable_t
*dbtable
) {
116 * Caller must ensure that it is safe to call.
119 RWLOCK(&dbtable
->tree_lock
, isc_rwlocktype_write
);
121 if (dbtable
->default_db
!= NULL
)
122 dns_db_detach(&dbtable
->default_db
);
124 dns_rbt_destroy(&dbtable
->rbt
);
126 RWUNLOCK(&dbtable
->tree_lock
, isc_rwlocktype_write
);
128 isc_rwlock_destroy(&dbtable
->tree_lock
);
132 isc_mem_put(dbtable
->mctx
, dbtable
, sizeof(*dbtable
));
136 dns_dbtable_attach(dns_dbtable_t
*source
, dns_dbtable_t
**targetp
) {
137 REQUIRE(VALID_DBTABLE(source
));
138 REQUIRE(targetp
!= NULL
&& *targetp
== NULL
);
142 INSIST(source
->references
> 0);
143 source
->references
++;
144 INSIST(source
->references
!= 0);
146 UNLOCK(&source
->lock
);
152 dns_dbtable_detach(dns_dbtable_t
**dbtablep
) {
153 dns_dbtable_t
*dbtable
;
154 isc_boolean_t free_dbtable
= ISC_FALSE
;
156 REQUIRE(dbtablep
!= NULL
);
158 REQUIRE(VALID_DBTABLE(dbtable
));
160 LOCK(&dbtable
->lock
);
162 INSIST(dbtable
->references
> 0);
163 dbtable
->references
--;
164 if (dbtable
->references
== 0)
165 free_dbtable
= ISC_TRUE
;
167 UNLOCK(&dbtable
->lock
);
170 dbtable_free(dbtable
);
176 dns_dbtable_add(dns_dbtable_t
*dbtable
, dns_db_t
*db
) {
180 REQUIRE(VALID_DBTABLE(dbtable
));
181 REQUIRE(dns_db_class(db
) == dbtable
->rdclass
);
184 dns_db_attach(db
, &clone
);
186 RWLOCK(&dbtable
->tree_lock
, isc_rwlocktype_write
);
187 result
= dns_rbt_addname(dbtable
->rbt
, dns_db_origin(clone
), clone
);
188 RWUNLOCK(&dbtable
->tree_lock
, isc_rwlocktype_write
);
194 dns_dbtable_remove(dns_dbtable_t
*dbtable
, dns_db_t
*db
) {
195 dns_db_t
*stored_data
= NULL
;
199 REQUIRE(VALID_DBTABLE(dbtable
));
201 name
= dns_db_origin(db
);
204 * There is a requirement that the association of name with db
205 * be verified. With the current rbt.c this is expensive to do,
206 * because effectively two find operations are being done, but
207 * deletion is relatively infrequent.
208 * XXXDCL ... this could be cheaper now with dns_rbt_deletenode.
211 RWLOCK(&dbtable
->tree_lock
, isc_rwlocktype_write
);
213 result
= dns_rbt_findname(dbtable
->rbt
, name
, 0, NULL
,
214 (void **) (void *)&stored_data
);
216 if (result
== ISC_R_SUCCESS
) {
217 INSIST(stored_data
== db
);
219 dns_rbt_deletename(dbtable
->rbt
, name
, ISC_FALSE
);
222 RWUNLOCK(&dbtable
->tree_lock
, isc_rwlocktype_write
);
226 dns_dbtable_adddefault(dns_dbtable_t
*dbtable
, dns_db_t
*db
) {
227 REQUIRE(VALID_DBTABLE(dbtable
));
228 REQUIRE(dbtable
->default_db
== NULL
);
229 REQUIRE(dns_name_compare(dns_db_origin(db
), dns_rootname
) == 0);
231 RWLOCK(&dbtable
->tree_lock
, isc_rwlocktype_write
);
233 dbtable
->default_db
= NULL
;
234 dns_db_attach(db
, &dbtable
->default_db
);
236 RWUNLOCK(&dbtable
->tree_lock
, isc_rwlocktype_write
);
240 dns_dbtable_getdefault(dns_dbtable_t
*dbtable
, dns_db_t
**dbp
) {
241 REQUIRE(VALID_DBTABLE(dbtable
));
242 REQUIRE(dbp
!= NULL
&& *dbp
== NULL
);
244 RWLOCK(&dbtable
->tree_lock
, isc_rwlocktype_read
);
246 dns_db_attach(dbtable
->default_db
, dbp
);
248 RWUNLOCK(&dbtable
->tree_lock
, isc_rwlocktype_read
);
252 dns_dbtable_removedefault(dns_dbtable_t
*dbtable
) {
253 REQUIRE(VALID_DBTABLE(dbtable
));
255 RWLOCK(&dbtable
->tree_lock
, isc_rwlocktype_write
);
257 dns_db_detach(&dbtable
->default_db
);
259 RWUNLOCK(&dbtable
->tree_lock
, isc_rwlocktype_write
);
263 dns_dbtable_find(dns_dbtable_t
*dbtable
, dns_name_t
*name
,
264 unsigned int options
, dns_db_t
**dbp
)
266 dns_db_t
*stored_data
= NULL
;
268 unsigned int rbtoptions
= 0;
270 REQUIRE(dbp
!= NULL
&& *dbp
== NULL
);
272 if ((options
& DNS_DBTABLEFIND_NOEXACT
) != 0)
273 rbtoptions
|= DNS_RBTFIND_NOEXACT
;
275 RWLOCK(&dbtable
->tree_lock
, isc_rwlocktype_read
);
277 result
= dns_rbt_findname(dbtable
->rbt
, name
, rbtoptions
, NULL
,
278 (void **) (void *)&stored_data
);
280 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
)
281 dns_db_attach(stored_data
, dbp
);
282 else if (dbtable
->default_db
!= NULL
) {
283 dns_db_attach(dbtable
->default_db
, dbp
);
284 result
= DNS_R_PARTIALMATCH
;
286 result
= ISC_R_NOTFOUND
;
288 RWUNLOCK(&dbtable
->tree_lock
, isc_rwlocktype_read
);