Commit a7e185ff authored by Bob Halley's avatar Bob Halley
Browse files

Add dns_db_subtractrdataset().

Add DNS_R_UNCHANGED results for dns_db_{add,delete}rdataset().
Add merge flag to dns_db_addrdataset().
The way add and delete work should now match the .h file comments.
parent b683976f
......@@ -420,7 +420,7 @@ dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
dns_result_t
dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
isc_stdtime_t now, dns_rdataset_t *rdataset,
dns_rdataset_t *addedrdataset)
isc_boolean_t merge, dns_rdataset_t *addedrdataset)
{
/*
* Add 'rdataset' to 'node' in version 'version' of 'db'.
......@@ -429,7 +429,8 @@ dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
REQUIRE(DNS_DB_VALID(db));
REQUIRE(node != NULL);
REQUIRE(((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL)||
((db->attributes & DNS_DBATTR_CACHE) != 0 && version == NULL));
((db->attributes & DNS_DBATTR_CACHE) != 0 &&
version == NULL && !merge));
REQUIRE(DNS_RDATASET_VALID(rdataset));
REQUIRE(rdataset->methods != NULL);
REQUIRE(rdataset->rdclass == db->rdclass);
......@@ -438,7 +439,31 @@ dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
addedrdataset->methods == NULL));
return ((db->methods->addrdataset)(db, node, version, now, rdataset,
addedrdataset));
merge, addedrdataset));
}
dns_result_t
dns_db_subtractrdataset(dns_db_t *db, dns_dbnode_t *node,
dns_dbversion_t *version, dns_rdataset_t *rdataset,
dns_rdataset_t *newrdataset)
{
/*
* Remove any rdata in 'rdataset' from 'node' in version 'version' of
* 'db'.
*/
REQUIRE(DNS_DB_VALID(db));
REQUIRE(node != NULL);
REQUIRE(((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL));
REQUIRE(DNS_RDATASET_VALID(rdataset));
REQUIRE(rdataset->methods != NULL);
REQUIRE(rdataset->rdclass == db->rdclass);
REQUIRE(newrdataset == NULL ||
(DNS_RDATASET_VALID(newrdataset) &&
newrdataset->methods == NULL));
return ((db->methods->subtractrdataset)(db, node, version, rdataset,
newrdataset));
}
dns_result_t
......
......@@ -119,7 +119,12 @@ typedef struct dns_dbmethods {
dns_dbversion_t *version,
isc_stdtime_t now,
dns_rdataset_t *rdataset,
isc_boolean_t merge,
dns_rdataset_t *addedrdataset);
dns_result_t (*subtractrdataset)(dns_db_t *db, dns_dbnode_t *node,
dns_dbversion_t *version,
dns_rdataset_t *rdataset,
dns_rdataset_t *newrdataset);
dns_result_t (*deleterdataset)(dns_db_t *db, dns_dbnode_t *node,
dns_dbversion_t *version,
dns_rdatatype_t type);
......@@ -794,12 +799,18 @@ dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
dns_result_t
dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
isc_stdtime_t now, dns_rdataset_t *rdataset,
dns_rdataset_t *addedrdataset);
isc_boolean_t merge, dns_rdataset_t *addedrdataset);
/*
* Add 'rdataset' to 'node' in version 'version' of 'db'.
*
* Notes:
*
* If the database has zone semantics, 'merge' is ISC_TRUE, and an
* rdataset of the same type as 'rdataset' already exists at 'node',
* then the contents of 'rdataset' will be merged with the existing
* rdataset. If merge is ISC_FALSE, then rdataset will replace any
* existing rdataset of the same type.
*
* The 'now' field is ignored if 'db' is a zone database. If 'db' is
* a cache database, then the added rdataset will expire no later than
* now + rdataset->ttl.
......@@ -822,13 +833,52 @@ dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
* read-write version, or the database has cache semantics
* and version is NULL.
*
* If the database has cache semantics, 'merge' must be ISC_FALSE.
*
* Returns:
*
* DNS_R_SUCCESS
* DNS_R_UNCHANGED The operation did not change anything.
* DNS_R_NOMEMORY
* DNS_R_EXISTS An rdataset with the specified
* rdataset's type and version's serial
* number already exists.
*
* Other results are possible, depending upon the database
* implementation used.
*/
dns_result_t
dns_db_subtractrdataset(dns_db_t *db, dns_dbnode_t *node,
dns_dbversion_t *version, dns_rdataset_t *rdataset,
dns_rdataset_t *newrdataset);
/*
* Remove any rdata in 'rdataset' from 'node' in version 'version' of
* 'db'.
*
* Notes:
*
* If 'newrdataset' is not NULL, then it will be attached to the
* rdataset added to the database, unless the rdataset has become
* nonexistent.
*
* Requires:
*
* 'db' is a valid database.
*
* 'node' is a valid node.
*
* 'rdataset' is a valid, associated rdataset with the same class
* as 'db'.
*
* 'newrdataset' is NULL, or a valid, unassociated rdataset.
*
* The database has zone semantics and 'version' is a valid
* read-write version.
*
* Returns:
*
* DNS_R_SUCCESS
* DNS_R_UNCHANGED The operation did not change anything.
* DNS_R_NXRDATASET All rdata of the same type as those
* in 'rdataset' have been deleted.
*
* Other results are possible, depending upon the database
* implementation used.
......@@ -867,7 +917,8 @@ dns_db_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
* Returns:
*
* DNS_R_SUCCESS
* DNS_R_NOTFOUND
* DNS_R_UNCHANGED No rdatasets of 'type' existed before
* the operation was attempted.
*
* Other results are possible, depending upon the database
* implementation used.
......
......@@ -2274,6 +2274,9 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
rdatasetheader_t *header, *header_prev;
unsigned char *merged;
dns_result_t result;
isc_boolean_t force = ISC_FALSE;
isc_boolean_t header_nx;
isc_boolean_t newheader_nx;
/*
* Add an rdatasetheader_t to a node.
......@@ -2284,11 +2287,19 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
*/
if (rbtversion != NULL && !loading) {
/*
* We always add a changed record, even if no changes end up
* being made to this node, because it's harmless and
* simplifies the code.
*/
changed = add_changed(rbtdb, rbtversion, rbtnode);
if (changed == NULL)
return (DNS_R_NOMEMORY);
}
newheader_nx = ((newheader->attributes & RDATASET_ATTR_NONEXISTENT)
!= 0 ? ISC_TRUE : ISC_FALSE);
header_prev = NULL;
for (header = rbtnode->data; header != NULL; header = header->next) {
if (header->type == newheader->type)
......@@ -2296,13 +2307,28 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
header_prev = header;
}
if (header != NULL) {
header_nx = ((header->attributes & RDATASET_ATTR_NONEXISTENT)
!= 0 ? ISC_TRUE : ISC_FALSE);
/*
* Deleting an already non-existent rdataset has no effect.
*/
if (header_nx && newheader_nx) {
free_rdataset(rbtdb->common.mctx, newheader);
return (DNS_R_UNCHANGED);
}
/*
* Don't merge if a nonexistent rdataset is involved.
*/
if (merge &&
((newheader->attributes & RDATASET_ATTR_NONEXISTENT) != 0
|| (header->attributes & RDATASET_ATTR_NONEXISTENT) != 0))
if (merge && (header_nx || newheader_nx))
merge = ISC_FALSE;
/*
* XXXRTH We should turn off merging for rdata types that
* cannot be merged, e.g. SOA, CNAME, WKS.
*/
/*
* If 'merge' is ISC_TRUE, we'll try to create a new rdataset
* that is the union of 'newheader' and 'header'.
......@@ -2310,6 +2336,12 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
if (merge) {
INSIST(rbtversion->serial >= header->serial);
merged = NULL;
if (newheader->ttl != header->ttl)
force = ISC_TRUE;
/*
* XXXRTH we're going to have to deal with signatures
* somehow here...
*/
result = dns_rdataslab_merge(
(unsigned char *)header,
(unsigned char *)newheader,
......@@ -2317,6 +2349,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
rbtdb->common.mctx,
rbtdb->common.rdclass,
header->type,
force,
&merged);
if (result == DNS_R_SUCCESS) {
/*
......@@ -2331,13 +2364,6 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
newheader = (rdatasetheader_t *)merged;
} else {
free_rdataset(rbtdb->common.mctx, newheader);
if (result == DNS_R_UNCHANGED) {
if (addedrdataset != NULL)
bind_rdataset(rbtdb, rbtnode,
header, now,
addedrdataset);
return (DNS_R_SUCCESS);
}
return (result);
}
}
......@@ -2368,6 +2394,15 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
/*
* The rdataset type doesn't exist at this node.
*/
/*
* If we're trying to delete it, don't bother.
*/
if (newheader_nx) {
free_rdataset(rbtdb->common.mctx, newheader);
return (DNS_R_UNCHANGED);
}
newheader->next = rbtnode->data;
newheader->down = NULL;
rbtnode->data = newheader;
......@@ -2394,7 +2429,7 @@ delegating_type(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
static dns_result_t
addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
isc_stdtime_t now, dns_rdataset_t *rdataset,
isc_stdtime_t now, dns_rdataset_t *rdataset, isc_boolean_t merge,
dns_rdataset_t *addedrdataset)
{
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
......@@ -2403,7 +2438,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
isc_region_t region;
rdatasetheader_t *newheader;
dns_result_t result;
isc_boolean_t merge, delegating;
isc_boolean_t delegating;
REQUIRE(VALID_RBTDB(rbtdb));
......@@ -2459,6 +2494,18 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
return (result);
}
static dns_result_t
subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
dns_rdataset_t *rdataset, dns_rdataset_t *newrdataset) {
(void)db;
(void)node;
(void)version;
(void)rdataset;
(void)newrdataset;
return (DNS_R_NOTIMPLEMENTED);
}
static dns_result_t
deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
dns_rdatatype_t type)
......@@ -2659,6 +2706,7 @@ static dns_dbmethods_t zone_methods = {
zone_findrdataset,
allrdatasets,
addrdataset,
subtractrdataset,
deleterdataset
};
......@@ -2681,6 +2729,7 @@ static dns_dbmethods_t cache_methods = {
cache_findrdataset,
allrdatasets,
addrdataset,
subtractrdataset,
deleterdataset
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment