2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-04 16:45:24 +00:00

refactor the slab rdataset implementation

- use externally accessible functions for attachnode/detachnode
  so these functions can be moved outside rbtdb.c
- simplify and tidy up some other functions
- use struct initializers when appropriate
- remove the flag RDATASET_ATTR_RETAIN; it was never being set
- renamed the rdataset attributes to
- remove the 'slab_methods' rdataset implementation. this was
  a reduced set of slab rdataset methods, omitting 'setownercase()'
  and 'getownercase()'. we can get the identical result by using
  an DNS_RDATASETATTR_KEEPCASE attribute in rdatasets that
  shouldn't have their case modified, and then we only need one
  set of rdataset methods.
This commit is contained in:
Evan Hunt
2023-04-25 17:26:47 +01:00
committed by Ondřej Surý
parent 83a33c3555
commit 9330fada3a
3 changed files with 165 additions and 190 deletions

View File

@@ -204,6 +204,7 @@ struct dns_rdataset {
#define DNS_RDATASETATTR_ANCIENT 0x02000000 #define DNS_RDATASETATTR_ANCIENT 0x02000000
#define DNS_RDATASETATTR_STALE_WINDOW 0x04000000 #define DNS_RDATASETATTR_STALE_WINDOW 0x04000000
#define DNS_RDATASETATTR_STALE_ADDED 0x08000000 #define DNS_RDATASETATTR_STALE_ADDED 0x08000000
#define DNS_RDATASETATTR_KEEPCASE 0x10000000
/*% /*%
* _OMITDNSSEC: * _OMITDNSSEC:

View File

@@ -300,31 +300,22 @@ typedef struct rdatasetheader {
typedef ISC_LIST(rdatasetheader_t) rdatasetheaderlist_t; typedef ISC_LIST(rdatasetheader_t) rdatasetheaderlist_t;
typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t; typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t;
#define RDATASET_ATTR_NONEXISTENT 0x0001 enum {
/*%< May be potentially served as stale data. */ RDATASET_ATTR_NONEXISTENT = 1 << 0,
#define RDATASET_ATTR_STALE 0x0002 RDATASET_ATTR_STALE = 1 << 1,
#define RDATASET_ATTR_IGNORE 0x0004 RDATASET_ATTR_IGNORE = 1 << 2,
#define RDATASET_ATTR_RETAIN 0x0008 RDATASET_ATTR_NXDOMAIN = 1 << 3,
#define RDATASET_ATTR_NXDOMAIN 0x0010 RDATASET_ATTR_RESIGN = 1 << 4,
#define RDATASET_ATTR_RESIGN 0x0020 RDATASET_ATTR_STATCOUNT = 1 << 5,
#define RDATASET_ATTR_STATCOUNT 0x0040 RDATASET_ATTR_OPTOUT = 1 << 6,
#define RDATASET_ATTR_OPTOUT 0x0080 RDATASET_ATTR_NEGATIVE = 1 << 7,
#define RDATASET_ATTR_NEGATIVE 0x0100 RDATASET_ATTR_PREFETCH = 1 << 8,
#define RDATASET_ATTR_PREFETCH 0x0200 RDATASET_ATTR_CASESET = 1 << 9,
#define RDATASET_ATTR_CASESET 0x0400 RDATASET_ATTR_ZEROTTL = 1 << 10,
#define RDATASET_ATTR_ZEROTTL 0x0800 RDATASET_ATTR_CASEFULLYLOWER = 1 << 11,
#define RDATASET_ATTR_CASEFULLYLOWER 0x1000 RDATASET_ATTR_ANCIENT = 1 << 12,
/*%< Ancient - awaiting cleanup. */ RDATASET_ATTR_STALE_WINDOW = 1 << 13,
#define RDATASET_ATTR_ANCIENT 0x2000 };
#define RDATASET_ATTR_STALE_WINDOW 0x4000
/*
* XXX
* When the cache will pre-expire data (due to memory low or other
* situations) before the rdataset's TTL has expired, it MUST
* respect the RETAIN bit and not expire the data until its TTL is
* expired.
*/
#define EXISTS(header) \ #define EXISTS(header) \
((atomic_load_acquire(&(header)->attributes) & \ ((atomic_load_acquire(&(header)->attributes) & \
@@ -335,9 +326,6 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t;
#define IGNORE(header) \ #define IGNORE(header) \
((atomic_load_acquire(&(header)->attributes) & \ ((atomic_load_acquire(&(header)->attributes) & \
RDATASET_ATTR_IGNORE) != 0) RDATASET_ATTR_IGNORE) != 0)
#define RETAIN(header) \
((atomic_load_acquire(&(header)->attributes) & \
RDATASET_ATTR_RETAIN) != 0)
#define NXDOMAIN(header) \ #define NXDOMAIN(header) \
((atomic_load_acquire(&(header)->attributes) & \ ((atomic_load_acquire(&(header)->attributes) & \
RDATASET_ATTR_NXDOMAIN) != 0) RDATASET_ATTR_NXDOMAIN) != 0)
@@ -666,15 +654,6 @@ static dns_rdatasetmethods_t rdataset_methods = {
.addglue = rdataset_addglue .addglue = rdataset_addglue
}; };
static dns_rdatasetmethods_t slab_methods = {
.disassociate = rdataset_disassociate,
.first = rdataset_first,
.next = rdataset_next,
.current = rdataset_current,
.clone = rdataset_clone,
.count = rdataset_count,
};
static void static void
rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG); rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG);
static isc_result_t static isc_result_t
@@ -5715,15 +5694,8 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
printname); printname);
} }
} else if (force_expire) { } else if (force_expire) {
if (!RETAIN(header)) {
set_ttl(rbtdb, header, 0); set_ttl(rbtdb, header, 0);
mark_header_ancient(rbtdb, header); mark_header_ancient(rbtdb, header);
} else if (log) {
isc_log_write(dns_lctx, category, module, level,
"overmem cache: "
"reprieve by RETAIN() %s",
printname);
}
} else if (isc_mem_isovermem(rbtdb->common.mctx) && log) { } else if (isc_mem_isovermem(rbtdb->common.mctx) && log) {
isc_log_write(dns_lctx, category, module, level, isc_log_write(dns_lctx, category, module, level,
"overmem cache: saved %s", printname); "overmem cache: saved %s", printname);
@@ -6789,90 +6761,79 @@ delegating_type(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
static isc_result_t static isc_result_t
addnoqname(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader, addnoqname(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
dns_rdataset_t *rdataset) { dns_rdataset_t *rdataset) {
struct noqname *noqname;
isc_mem_t *mctx = rbtdb->common.mctx;
dns_name_t name;
dns_rdataset_t neg, negsig;
isc_result_t result; isc_result_t result;
isc_region_t r; struct noqname *noqname = NULL;
isc_mem_t *mctx = rbtdb->common.mctx;
dns_name_init(&name, NULL); dns_name_t name = DNS_NAME_INITEMPTY;
dns_rdataset_init(&neg); dns_rdataset_t neg = DNS_RDATASET_INIT, negsig = DNS_RDATASET_INIT;
dns_rdataset_init(&negsig); isc_region_t r1, r2;
result = dns_rdataset_getnoqname(rdataset, &name, &neg, &negsig); result = dns_rdataset_getnoqname(rdataset, &name, &neg, &negsig);
RUNTIME_CHECK(result == ISC_R_SUCCESS); RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = dns_rdataslab_fromrdataset(&neg, mctx, &r1, 0);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
result = dns_rdataslab_fromrdataset(&negsig, mctx, &r2, 0);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
noqname = isc_mem_get(mctx, sizeof(*noqname)); noqname = isc_mem_get(mctx, sizeof(*noqname));
dns_name_init(&noqname->name, NULL); *noqname = (struct noqname){
noqname->neg = NULL; .neg = r1.base,
noqname->negsig = NULL; .negsig = r2.base,
noqname->type = neg.type; .type = neg.type,
.name = DNS_NAME_INITEMPTY,
};
dns_name_dup(&name, mctx, &noqname->name); dns_name_dup(&name, mctx, &noqname->name);
result = dns_rdataslab_fromrdataset(&neg, mctx, &r, 0);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
noqname->neg = r.base;
result = dns_rdataslab_fromrdataset(&negsig, mctx, &r, 0);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
noqname->negsig = r.base;
dns_rdataset_disassociate(&neg);
dns_rdataset_disassociate(&negsig);
newheader->noqname = noqname; newheader->noqname = noqname;
return (ISC_R_SUCCESS);
cleanup: cleanup:
dns_rdataset_disassociate(&neg); dns_rdataset_disassociate(&neg);
dns_rdataset_disassociate(&negsig); dns_rdataset_disassociate(&negsig);
free_noqname(mctx, &noqname);
return (result); return (result);
} }
static isc_result_t static isc_result_t
addclosest(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader, addclosest(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
dns_rdataset_t *rdataset) { dns_rdataset_t *rdataset) {
struct noqname *closest;
isc_mem_t *mctx = rbtdb->common.mctx;
dns_name_t name;
dns_rdataset_t neg, negsig;
isc_result_t result; isc_result_t result;
isc_region_t r; struct noqname *closest = NULL;
isc_mem_t *mctx = rbtdb->common.mctx;
dns_name_init(&name, NULL); dns_name_t name = DNS_NAME_INITEMPTY;
dns_rdataset_init(&neg); dns_rdataset_t neg = DNS_RDATASET_INIT, negsig = DNS_RDATASET_INIT;
dns_rdataset_init(&negsig); isc_region_t r1, r2;
result = dns_rdataset_getclosest(rdataset, &name, &neg, &negsig); result = dns_rdataset_getclosest(rdataset, &name, &neg, &negsig);
RUNTIME_CHECK(result == ISC_R_SUCCESS); RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = dns_rdataslab_fromrdataset(&neg, mctx, &r1, 0);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
result = dns_rdataslab_fromrdataset(&negsig, mctx, &r2, 0);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
closest = isc_mem_get(mctx, sizeof(*closest)); closest = isc_mem_get(mctx, sizeof(*closest));
dns_name_init(&closest->name, NULL); *closest = (struct noqname){
closest->neg = NULL; .neg = r1.base,
closest->negsig = NULL; .negsig = r2.base,
closest->type = neg.type; .name = DNS_NAME_INITEMPTY,
.type = neg.type,
};
dns_name_dup(&name, mctx, &closest->name); dns_name_dup(&name, mctx, &closest->name);
result = dns_rdataslab_fromrdataset(&neg, mctx, &r, 0);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
closest->neg = r.base;
result = dns_rdataslab_fromrdataset(&negsig, mctx, &r, 0);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
closest->negsig = r.base;
dns_rdataset_disassociate(&neg);
dns_rdataset_disassociate(&negsig);
newheader->closest = closest; newheader->closest = closest;
return (ISC_R_SUCCESS);
cleanup: cleanup:
dns_rdataset_disassociate(&neg); dns_rdataset_disassociate(&neg);
dns_rdataset_disassociate(&negsig); dns_rdataset_disassociate(&negsig);
free_noqname(mctx, &closest);
return (result); return (result);
} }
@@ -8527,7 +8488,7 @@ rdataset_disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) {
dns_db_t *db = rdataset->private1; dns_db_t *db = rdataset->private1;
dns_dbnode_t *node = rdataset->private2; dns_dbnode_t *node = rdataset->private2;
detachnode(db, &node DNS__DB_FLARG_PASS); dns__db_detachnode(db, &node DNS__DB_FLARG_PASS);
} }
static isc_result_t static isc_result_t
@@ -8640,7 +8601,7 @@ rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target DNS__DB_FLARG) {
dns_dbnode_t *node = source->private2; dns_dbnode_t *node = source->private2;
dns_dbnode_t *cloned_node = NULL; dns_dbnode_t *cloned_node = NULL;
attachnode(db, node, &cloned_node DNS__DB_FLARG_PASS); dns__db_attachnode(db, node, &cloned_node DNS__DB_FLARG_PASS);
INSIST(!ISC_LINK_LINKED(target, link)); INSIST(!ISC_LINK_LINKED(target, link));
*target = *source; *target = *source;
ISC_LINK_INIT(target, link); ISC_LINK_INIT(target, link);
@@ -8668,40 +8629,50 @@ rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
dns_rdataset_t *nsecsig DNS__DB_FLARG) { dns_rdataset_t *nsecsig DNS__DB_FLARG) {
dns_db_t *db = rdataset->private1; dns_db_t *db = rdataset->private1;
dns_dbnode_t *node = rdataset->private2; dns_dbnode_t *node = rdataset->private2;
dns_dbnode_t *cloned_node;
const struct noqname *noqname = rdataset->private6; const struct noqname *noqname = rdataset->private6;
cloned_node = NULL; /*
attachnode(db, node, &cloned_node DNS__DB_FLARG_PASS); * Usually, rdataset->slab.raw refers the data following an
nsec->methods = &slab_methods; * rdatasetheader, but in this case it points to a bare
nsec->rdclass = db->rdclass; * rdataslab belonging to the rdatasetheader's `noqname` field.
nsec->type = noqname->type; * The DNS_RDATASETATTR_KEEPCASE attribute is set to prevent
nsec->covers = 0; * setownercase and getownercase methods from affecting the
nsec->ttl = rdataset->ttl; * case of NSEC/NSEC3 owner names.
nsec->trust = rdataset->trust; */
nsec->private1 = rdataset->private1; dns__db_attachnode(db, node,
nsec->private2 = rdataset->private2; &(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
nsec->private3 = noqname->neg; *nsec = (dns_rdataset_t){
nsec->privateuint4 = 0; .methods = &rdataset_methods,
nsec->private5 = NULL; .rdclass = db->rdclass,
nsec->private6 = NULL; .type = noqname->type,
nsec->private7 = NULL; .ttl = rdataset->ttl,
.trust = rdataset->trust,
.private1 = rdataset->private1,
.private2 = rdataset->private2,
.private3 = noqname->neg,
.link = nsec->link,
.count = nsec->count,
.attributes = nsec->attributes | DNS_RDATASETATTR_KEEPCASE,
.magic = nsec->magic,
};
cloned_node = NULL; dns__db_attachnode(db, node,
attachnode(db, node, &cloned_node DNS__DB_FLARG_PASS); &(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
nsecsig->methods = &slab_methods; *nsecsig = (dns_rdataset_t){
nsecsig->rdclass = db->rdclass; .methods = &rdataset_methods,
nsecsig->type = dns_rdatatype_rrsig; .rdclass = db->rdclass,
nsecsig->covers = noqname->type; .type = dns_rdatatype_rrsig,
nsecsig->ttl = rdataset->ttl; .covers = noqname->type,
nsecsig->trust = rdataset->trust; .ttl = rdataset->ttl,
nsecsig->private1 = rdataset->private1; .trust = rdataset->trust,
nsecsig->private2 = rdataset->private2; .private1 = rdataset->private1,
nsecsig->private3 = noqname->negsig; .private2 = rdataset->private2,
nsecsig->privateuint4 = 0; .private3 = noqname->negsig,
nsecsig->private5 = NULL; .link = nsecsig->link,
nsec->private6 = NULL; .count = nsecsig->count,
nsec->private7 = NULL; .attributes = nsecsig->attributes | DNS_RDATASETATTR_KEEPCASE,
.magic = nsecsig->magic,
};
dns_name_clone(&noqname->name, name); dns_name_clone(&noqname->name, name);
@@ -8714,46 +8685,57 @@ rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
dns_rdataset_t *nsecsig DNS__DB_FLARG) { dns_rdataset_t *nsecsig DNS__DB_FLARG) {
dns_db_t *db = rdataset->private1; dns_db_t *db = rdataset->private1;
dns_dbnode_t *node = rdataset->private2; dns_dbnode_t *node = rdataset->private2;
dns_dbnode_t *cloned_node;
const struct noqname *closest = rdataset->private7; const struct noqname *closest = rdataset->private7;
cloned_node = NULL; /*
attachnode(db, node, &cloned_node DNS__DB_FLARG_PASS); * As mentioned above, rdataset->slab.raw usually refers the data
nsec->methods = &slab_methods; * following an rdatasetheader, but in this case it points to a bare
nsec->rdclass = db->rdclass; * rdataslab belonging to the rdatasetheader's `closest` field.
nsec->type = closest->type; */
nsec->covers = 0; dns__db_attachnode(db, node,
nsec->ttl = rdataset->ttl; &(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
nsec->trust = rdataset->trust; *nsec = (dns_rdataset_t){
nsec->private1 = rdataset->private1; .methods = &rdataset_methods,
nsec->private2 = rdataset->private2; .rdclass = db->rdclass,
nsec->private3 = closest->neg; .type = closest->type,
nsec->privateuint4 = 0; .ttl = rdataset->ttl,
nsec->private5 = NULL; .trust = rdataset->trust,
nsec->private6 = NULL; .private1 = rdataset->private1,
nsec->private7 = NULL; .private2 = rdataset->private2,
.private3 = closest->neg,
.link = nsec->link,
.count = nsec->count,
.attributes = nsec->attributes | DNS_RDATASETATTR_KEEPCASE,
.magic = nsec->magic,
};
cloned_node = NULL; dns__db_attachnode(db, node,
attachnode(db, node, &cloned_node DNS__DB_FLARG_PASS); &(dns_dbnode_t *){ NULL } DNS__DB_FLARG_PASS);
nsecsig->methods = &slab_methods; *nsecsig = (dns_rdataset_t){
nsecsig->rdclass = db->rdclass; .methods = &rdataset_methods,
nsecsig->type = dns_rdatatype_rrsig; .rdclass = db->rdclass,
nsecsig->covers = closest->type; .type = dns_rdatatype_rrsig,
nsecsig->ttl = rdataset->ttl; .covers = closest->type,
nsecsig->trust = rdataset->trust; .ttl = rdataset->ttl,
nsecsig->private1 = rdataset->private1; .trust = rdataset->trust,
nsecsig->private2 = rdataset->private2; .private1 = rdataset->private1,
nsecsig->private3 = closest->negsig; .private2 = rdataset->private2,
nsecsig->privateuint4 = 0; .private3 = closest->negsig,
nsecsig->private5 = NULL; .link = nsecsig->link,
nsec->private6 = NULL; .count = nsecsig->count,
nsec->private7 = NULL; .attributes = nsecsig->attributes | DNS_RDATASETATTR_KEEPCASE,
.magic = nsecsig->magic,
};
dns_name_clone(&closest->name, name); dns_name_clone(&closest->name, name);
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
/*
* Non-slab rdataset methods (these require knowledge of the
* database storage format).
*/
static void static void
rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
dns_rbtdb_t *rbtdb = rdataset->private1; dns_rbtdb_t *rbtdb = rdataset->private1;
@@ -8811,7 +8793,7 @@ rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) {
&rbtiterator->common.version, &rbtiterator->common.version,
false DNS__DB_FLARG_PASS); false DNS__DB_FLARG_PASS);
} }
detachnode(rbtiterator->common.db, dns__db_detachnode(rbtiterator->common.db,
&rbtiterator->common.node DNS__DB_FLARG_PASS); &rbtiterator->common.node DNS__DB_FLARG_PASS);
isc_mem_put(rbtiterator->common.db->mctx, rbtiterator, isc_mem_put(rbtiterator->common.db->mctx, rbtiterator,
sizeof(*rbtiterator)); sizeof(*rbtiterator));
@@ -9739,11 +9721,12 @@ glue_nsdname_cb(void *arg, const dns_name_t *name, dns_rdatatype_t qtype,
} }
if (node_a != NULL) { if (node_a != NULL) {
detachnode((dns_db_t *)ctx->rbtdb, dns__db_detachnode((dns_db_t *)ctx->rbtdb,
(dns_dbnode_t *)&node_a DNS__DB_FLARG_PASS); (dns_dbnode_t *)&node_a DNS__DB_FLARG_PASS);
} }
if (node_aaaa != NULL) { if (node_aaaa != NULL) {
detachnode((dns_db_t *)ctx->rbtdb, dns__db_detachnode(
(dns_db_t *)ctx->rbtdb,
(dns_dbnode_t *)&node_aaaa DNS__DB_FLARG_PASS); (dns_dbnode_t *)&node_aaaa DNS__DB_FLARG_PASS);
} }

View File

@@ -54,24 +54,11 @@ dns_rdataset_init(dns_rdataset_t *rdataset) {
REQUIRE(rdataset != NULL); REQUIRE(rdataset != NULL);
rdataset->magic = DNS_RDATASET_MAGIC; *rdataset = (dns_rdataset_t){
rdataset->methods = NULL; .magic = DNS_RDATASET_MAGIC,
ISC_LINK_INIT(rdataset, link); .link = ISC_LINK_INITIALIZER,
rdataset->rdclass = 0; .count = DNS_RDATASET_COUNT_UNDEFINED,
rdataset->type = 0; };
rdataset->ttl = 0;
rdataset->trust = 0;
rdataset->covers = 0;
rdataset->attributes = 0;
rdataset->count = DNS_RDATASET_COUNT_UNDEFINED;
rdataset->private1 = NULL;
rdataset->private2 = NULL;
rdataset->private3 = NULL;
rdataset->privateuint4 = 0;
rdataset->private5 = NULL;
rdataset->private6 = NULL;
rdataset->private7 = NULL;
rdataset->resign = 0;
} }
void void
@@ -684,7 +671,9 @@ dns_rdataset_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) {
REQUIRE(DNS_RDATASET_VALID(rdataset)); REQUIRE(DNS_RDATASET_VALID(rdataset));
REQUIRE(rdataset->methods != NULL); REQUIRE(rdataset->methods != NULL);
if (rdataset->methods->setownercase != NULL) { if (rdataset->methods->setownercase != NULL &&
(rdataset->attributes & DNS_RDATASETATTR_KEEPCASE) == 0)
{
(rdataset->methods->setownercase)(rdataset, name); (rdataset->methods->setownercase)(rdataset, name);
} }
} }
@@ -694,7 +683,9 @@ dns_rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) {
REQUIRE(DNS_RDATASET_VALID(rdataset)); REQUIRE(DNS_RDATASET_VALID(rdataset));
REQUIRE(rdataset->methods != NULL); REQUIRE(rdataset->methods != NULL);
if (rdataset->methods->getownercase != NULL) { if (rdataset->methods->getownercase != NULL &&
(rdataset->attributes & DNS_RDATASETATTR_KEEPCASE) == 0)
{
(rdataset->methods->getownercase)(rdataset, name); (rdataset->methods->getownercase)(rdataset, name);
} }
} }