add _last, _prev, and _seek for dbiterators
This commit is contained in:
@@ -64,6 +64,7 @@ typedef struct dbinfo {
|
||||
dns_dbiterator_t * dbiterator;
|
||||
dns_dbversion_t * iversion;
|
||||
int pause_every;
|
||||
isc_boolean_t ascending;
|
||||
ISC_LINK(struct dbinfo) link;
|
||||
} dbinfo;
|
||||
|
||||
@@ -73,6 +74,7 @@ static dns_dbtable_t * dbtable;
|
||||
static ISC_LIST(dbinfo) dbs;
|
||||
static dbinfo * cache_dbi = NULL;
|
||||
static int pause_every = 0;
|
||||
static isc_boolean_t ascending = ISC_TRUE;
|
||||
|
||||
static void
|
||||
print_result(char *message, isc_result_t result) {
|
||||
@@ -158,13 +160,17 @@ select_db(char *origintext) {
|
||||
}
|
||||
|
||||
static void
|
||||
list(dbinfo *dbi) {
|
||||
list(dbinfo *dbi, char *seektext) {
|
||||
dns_fixedname_t fname;
|
||||
dns_name_t *name;
|
||||
dns_dbnode_t *node;
|
||||
dns_rdatasetiter_t *rdsiter;
|
||||
isc_result_t result;
|
||||
int i;
|
||||
size_t len;
|
||||
dns_fixedname_t fseekname;
|
||||
dns_name_t *seekname;
|
||||
isc_buffer_t source;
|
||||
|
||||
dns_fixedname_init(&fname);
|
||||
name = dns_fixedname_name(&fname);
|
||||
@@ -181,8 +187,27 @@ list(dbinfo *dbi) {
|
||||
|
||||
result = dns_db_createiterator(dbi->db, ISC_FALSE,
|
||||
&dbi->dbiterator);
|
||||
if (result == DNS_R_SUCCESS)
|
||||
result = dns_dbiterator_first(dbi->dbiterator);
|
||||
if (result == DNS_R_SUCCESS) {
|
||||
if (seektext != NULL) {
|
||||
len = strlen(seektext);
|
||||
isc_buffer_init(&source, seektext, len,
|
||||
ISC_BUFFERTYPE_TEXT);
|
||||
isc_buffer_add(&source, len);
|
||||
dns_fixedname_init(&fseekname);
|
||||
seekname = dns_fixedname_name(&fseekname);
|
||||
result = dns_name_fromtext(seekname, &source,
|
||||
dns_rootname,
|
||||
ISC_FALSE,
|
||||
NULL);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
result = dns_dbiterator_seek(
|
||||
dbi->dbiterator,
|
||||
seekname);
|
||||
} else if (dbi->ascending)
|
||||
result = dns_dbiterator_first(dbi->dbiterator);
|
||||
else
|
||||
result = dns_dbiterator_last(dbi->dbiterator);
|
||||
}
|
||||
} else
|
||||
result = DNS_R_SUCCESS;
|
||||
|
||||
@@ -202,7 +227,10 @@ list(dbinfo *dbi) {
|
||||
print_rdatasets(name, rdsiter);
|
||||
dns_rdatasetiter_destroy(&rdsiter);
|
||||
dns_db_detachnode(dbi->db, &node);
|
||||
result = dns_dbiterator_next(dbi->dbiterator);
|
||||
if (dbi->ascending)
|
||||
result = dns_dbiterator_next(dbi->dbiterator);
|
||||
else
|
||||
result = dns_dbiterator_prev(dbi->dbiterator);
|
||||
i++;
|
||||
if (result == DNS_R_SUCCESS && i == dbi->pause_every) {
|
||||
printf("[more...]\n");
|
||||
@@ -244,6 +272,7 @@ load(char *filename, char *origintext, isc_boolean_t cache) {
|
||||
dbi->dbiterator = NULL;
|
||||
dbi->iversion = NULL;
|
||||
dbi->pause_every = pause_every;
|
||||
dbi->ascending = ascending;
|
||||
|
||||
len = strlen(origintext);
|
||||
isc_buffer_init(&source, origintext, len, ISC_BUFFERTYPE_TEXT);
|
||||
@@ -618,9 +647,13 @@ main(int argc, char *argv[]) {
|
||||
((options & DNS_DBFIND_NOWILD) == 0) ?
|
||||
"TRUE" : "FALSE");
|
||||
continue;
|
||||
} else if (strstr(s, "!LS ") == s) {
|
||||
DBI_CHECK(dbi);
|
||||
list(dbi, &s[4]);
|
||||
continue;
|
||||
} else if (strcmp(s, "!LS") == 0) {
|
||||
DBI_CHECK(dbi);
|
||||
list(dbi);
|
||||
list(dbi, NULL);
|
||||
continue;
|
||||
} else if (strstr(s, "!DU ") == s) {
|
||||
DBI_CHECK(dbi);
|
||||
@@ -643,6 +676,14 @@ main(int argc, char *argv[]) {
|
||||
v = atoi(&s[2]);
|
||||
dbi->pause_every = v;
|
||||
continue;
|
||||
} else if (strcmp(s, "!+") == 0) {
|
||||
DBI_CHECK(dbi);
|
||||
dbi->ascending = ISC_TRUE;
|
||||
continue;
|
||||
} else if (strcmp(s, "!-") == 0) {
|
||||
DBI_CHECK(dbi);
|
||||
dbi->ascending = ISC_FALSE;
|
||||
continue;
|
||||
} else if (strcmp(s, "!DB") == 0) {
|
||||
dbi = NULL;
|
||||
origin = dns_rootname;
|
||||
|
||||
@@ -49,6 +49,39 @@ dns_dbiterator_first(dns_dbiterator_t *iterator) {
|
||||
return (iterator->methods->first(iterator));
|
||||
}
|
||||
|
||||
dns_result_t
|
||||
dns_dbiterator_last(dns_dbiterator_t *iterator) {
|
||||
/*
|
||||
* Move the node cursor to the first node in the database (if any).
|
||||
*/
|
||||
|
||||
REQUIRE(DNS_DBITERATOR_VALID(iterator));
|
||||
|
||||
return (iterator->methods->last(iterator));
|
||||
}
|
||||
|
||||
dns_result_t
|
||||
dns_dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
|
||||
/*
|
||||
* Move the node cursor to the node with name 'name'.
|
||||
*/
|
||||
|
||||
REQUIRE(DNS_DBITERATOR_VALID(iterator));
|
||||
|
||||
return (iterator->methods->seek(iterator, name));
|
||||
}
|
||||
|
||||
dns_result_t
|
||||
dns_dbiterator_prev(dns_dbiterator_t *iterator) {
|
||||
/*
|
||||
* Move the node cursor to the previous node in the database (if any).
|
||||
*/
|
||||
|
||||
REQUIRE(DNS_DBITERATOR_VALID(iterator));
|
||||
|
||||
return (iterator->methods->prev(iterator));
|
||||
}
|
||||
|
||||
dns_result_t
|
||||
dns_dbiterator_next(dns_dbiterator_t *iterator) {
|
||||
/*
|
||||
|
||||
@@ -76,6 +76,9 @@ ISC_LANG_BEGINDECLS
|
||||
typedef struct dns_dbiteratormethods {
|
||||
void (*destroy)(dns_dbiterator_t **iteratorp);
|
||||
dns_result_t (*first)(dns_dbiterator_t *iterator);
|
||||
dns_result_t (*last)(dns_dbiterator_t *iterator);
|
||||
dns_result_t (*seek)(dns_dbiterator_t *iterator, dns_name_t *name);
|
||||
dns_result_t (*prev)(dns_dbiterator_t *iterator);
|
||||
dns_result_t (*next)(dns_dbiterator_t *iterator);
|
||||
dns_result_t (*current)(dns_dbiterator_t *iterator,
|
||||
dns_dbnode_t **nodep, dns_name_t *name);
|
||||
@@ -136,6 +139,54 @@ dns_dbiterator_first(dns_dbiterator_t *iterator);
|
||||
* Other results are possible, depending on the DB implementation.
|
||||
*/
|
||||
|
||||
dns_result_t
|
||||
dns_dbiterator_last(dns_dbiterator_t *iterator);
|
||||
/*
|
||||
* Move the node cursor to the last node in the database (if any).
|
||||
*
|
||||
* Requires:
|
||||
* 'iterator' is a valid iterator.
|
||||
*
|
||||
* Returns:
|
||||
* DNS_R_SUCCESS
|
||||
* DNS_R_NOMORE There are no nodes in the database.
|
||||
*
|
||||
* Other results are possible, depending on the DB implementation.
|
||||
*/
|
||||
|
||||
dns_result_t
|
||||
dns_dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name);
|
||||
/*
|
||||
* Move the node cursor to the node with name 'name'.
|
||||
*
|
||||
* Requires:
|
||||
* 'iterator' is a valid iterator.
|
||||
*
|
||||
* 'name' is a valid name.
|
||||
*
|
||||
* Returns:
|
||||
* DNS_R_SUCCESS
|
||||
* DNS_R_NOTFOUND
|
||||
*
|
||||
* Other results are possible, depending on the DB implementation.
|
||||
*/
|
||||
|
||||
dns_result_t
|
||||
dns_dbiterator_prev(dns_dbiterator_t *iterator);
|
||||
/*
|
||||
* Move the node cursor to the previous node in the database (if any).
|
||||
*
|
||||
* Requires:
|
||||
* 'iterator' is a valid iterator.
|
||||
*
|
||||
* Returns:
|
||||
* DNS_R_SUCCESS
|
||||
* DNS_R_NOMORE There are no more nodes in the
|
||||
* database.
|
||||
*
|
||||
* Other results are possible, depending on the DB implementation.
|
||||
*/
|
||||
|
||||
dns_result_t
|
||||
dns_dbiterator_next(dns_dbiterator_t *iterator);
|
||||
/*
|
||||
|
||||
127
lib/dns/rbtdb.c
127
lib/dns/rbtdb.c
@@ -222,6 +222,10 @@ typedef struct rbtdb_rdatasetiter {
|
||||
|
||||
static void dbiterator_destroy(dns_dbiterator_t **iteratorp);
|
||||
static dns_result_t dbiterator_first(dns_dbiterator_t *iterator);
|
||||
static dns_result_t dbiterator_last(dns_dbiterator_t *iterator);
|
||||
static dns_result_t dbiterator_seek(dns_dbiterator_t *iterator,
|
||||
dns_name_t *name);
|
||||
static dns_result_t dbiterator_prev(dns_dbiterator_t *iterator);
|
||||
static dns_result_t dbiterator_next(dns_dbiterator_t *iterator);
|
||||
static dns_result_t dbiterator_current(dns_dbiterator_t *iterator,
|
||||
dns_dbnode_t **nodep,
|
||||
@@ -233,6 +237,9 @@ static dns_result_t dbiterator_origin(dns_dbiterator_t *iterator,
|
||||
static dns_dbiteratormethods_t dbiterator_methods = {
|
||||
dbiterator_destroy,
|
||||
dbiterator_first,
|
||||
dbiterator_last,
|
||||
dbiterator_seek,
|
||||
dbiterator_prev,
|
||||
dbiterator_next,
|
||||
dbiterator_current,
|
||||
dbiterator_pause,
|
||||
@@ -3900,6 +3907,126 @@ dbiterator_first(dns_dbiterator_t *iterator) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
static dns_result_t
|
||||
dbiterator_last(dns_dbiterator_t *iterator) {
|
||||
dns_result_t result;
|
||||
rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator;
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db;
|
||||
dns_name_t *name, *origin;
|
||||
|
||||
if (rbtdbiter->result != DNS_R_SUCCESS &&
|
||||
rbtdbiter->result != DNS_R_NOMORE)
|
||||
return (rbtdbiter->result);
|
||||
|
||||
unpause(rbtdbiter);
|
||||
|
||||
if (!rbtdbiter->tree_locked) {
|
||||
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
|
||||
rbtdbiter->tree_locked = ISC_TRUE;
|
||||
}
|
||||
|
||||
name = dns_fixedname_name(&rbtdbiter->name);
|
||||
origin = dns_fixedname_name(&rbtdbiter->origin);
|
||||
dns_rbtnodechain_reset(&rbtdbiter->chain);
|
||||
result = dns_rbtnodechain_last(&rbtdbiter->chain, rbtdb->tree, name,
|
||||
origin);
|
||||
if (result != DNS_R_NEWORIGIN) {
|
||||
INSIST(result != DNS_R_SUCCESS);
|
||||
if (result == DNS_R_NOTFOUND) {
|
||||
/*
|
||||
* The tree is empty.
|
||||
*/
|
||||
result = DNS_R_NOMORE;
|
||||
}
|
||||
rbtdbiter->node = NULL;
|
||||
} else {
|
||||
result = dns_rbtnodechain_current(&rbtdbiter->chain, NULL,
|
||||
NULL, &rbtdbiter->node);
|
||||
if (result == DNS_R_SUCCESS)
|
||||
rbtdbiter->new_origin = ISC_TRUE;
|
||||
else
|
||||
rbtdbiter->node = NULL;
|
||||
}
|
||||
rbtdbiter->result = result;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static dns_result_t
|
||||
dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
|
||||
dns_result_t result;
|
||||
rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator;
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db;
|
||||
dns_name_t *iname, *origin;
|
||||
|
||||
if (rbtdbiter->result != DNS_R_SUCCESS &&
|
||||
rbtdbiter->result != DNS_R_NOMORE)
|
||||
return (rbtdbiter->result);
|
||||
|
||||
unpause(rbtdbiter);
|
||||
|
||||
if (!rbtdbiter->tree_locked) {
|
||||
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
|
||||
rbtdbiter->tree_locked = ISC_TRUE;
|
||||
}
|
||||
|
||||
iname = dns_fixedname_name(&rbtdbiter->name);
|
||||
origin = dns_fixedname_name(&rbtdbiter->origin);
|
||||
dns_rbtnodechain_reset(&rbtdbiter->chain);
|
||||
rbtdbiter->node = NULL;
|
||||
result = dns_rbt_findnode(rbtdb->tree, name, NULL, &rbtdbiter->node,
|
||||
&rbtdbiter->chain, ISC_TRUE, NULL, NULL);
|
||||
if (result != DNS_R_SUCCESS) {
|
||||
if (result == DNS_R_PARTIALMATCH)
|
||||
result = DNS_R_NOTFOUND;
|
||||
rbtdbiter->node = NULL;
|
||||
} else {
|
||||
result = dns_rbtnodechain_current(&rbtdbiter->chain, iname,
|
||||
origin, NULL);
|
||||
if (result == DNS_R_SUCCESS)
|
||||
rbtdbiter->new_origin = ISC_TRUE;
|
||||
else
|
||||
rbtdbiter->node = NULL;
|
||||
}
|
||||
rbtdbiter->result = result;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static dns_result_t
|
||||
dbiterator_prev(dns_dbiterator_t *iterator) {
|
||||
dns_result_t result;
|
||||
rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator;
|
||||
dns_name_t *name, *origin;
|
||||
|
||||
REQUIRE(rbtdbiter->node != NULL);
|
||||
|
||||
if (rbtdbiter->result != DNS_R_SUCCESS)
|
||||
return (rbtdbiter->result);
|
||||
|
||||
if (rbtdbiter->paused)
|
||||
resume_iteration(rbtdbiter);
|
||||
|
||||
name = dns_fixedname_name(&rbtdbiter->name);
|
||||
origin = dns_fixedname_name(&rbtdbiter->origin);
|
||||
result = dns_rbtnodechain_prev(&rbtdbiter->chain, name, origin);
|
||||
if (result == DNS_R_NEWORIGIN || result == DNS_R_SUCCESS) {
|
||||
if (result == DNS_R_NEWORIGIN)
|
||||
rbtdbiter->new_origin = ISC_TRUE;
|
||||
else
|
||||
rbtdbiter->new_origin = ISC_FALSE;
|
||||
result = dns_rbtnodechain_current(&rbtdbiter->chain, NULL,
|
||||
NULL, &rbtdbiter->node);
|
||||
if (result != DNS_R_SUCCESS) {
|
||||
rbtdbiter->result = result;
|
||||
rbtdbiter->node = NULL;
|
||||
}
|
||||
} else
|
||||
rbtdbiter->result = result;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static dns_result_t
|
||||
dbiterator_next(dns_dbiterator_t *iterator) {
|
||||
dns_result_t result;
|
||||
|
||||
Reference in New Issue
Block a user