summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Vavrusa <marek.vavrusa@nic.cz>2012-11-13 15:37:15 +0100
committerMarek Vavrusa <marek.vavrusa@nic.cz>2012-11-13 16:16:48 +0100
commit051e94325b3be83791d2bd0a757eb8b1701a0314 (patch)
tree4b56a20ca5142870dd654df2afdc4200ac925417
parentFixed small resource leak on daemon quit. (diff)
downloadknot-051e94325b3be83791d2bd0a757eb8b1701a0314.tar.xz
knot-051e94325b3be83791d2bd0a757eb8b1701a0314.zip
Implemented zone duplicate checks with AVL.
Not so slow with large number of zones now. refs #2174, #2204 Conflicts: src/knot/conf/conf.h
-rw-r--r--src/knot/conf/cf-parse.y16
-rw-r--r--src/knot/conf/conf.c34
-rw-r--r--src/knot/conf/conf.h4
3 files changed, 41 insertions, 13 deletions
diff --git a/src/knot/conf/cf-parse.y b/src/knot/conf/cf-parse.y
index 033bd2e41..4f490b540 100644
--- a/src/knot/conf/cf-parse.y
+++ b/src/knot/conf/cf-parse.y
@@ -201,28 +201,22 @@ static void conf_zone_start(void *scanner, char *name) {
cf_error(scanner, "invalid zone origin");
} else {
/* Check for duplicates. */
- conf_zone_t* pz = 0;
- WALK_LIST (pz, new_config->zones) {
- knot_dname_t *tn = knot_dname_new_from_str(pz->name, strlen(pz->name), 0);
- if (knot_dname_compare(tn, dn) == 0) {
- snprintf(buf, sizeof(buf), "zone '%s' is already present, refusing to duplicate", pz->name);
+ if (gen_tree_find(new_config->zone_tree, dn) != NULL) {
+ snprintf(buf, sizeof(buf), "zone '%s' is already present, "
+ "refusing to duplicate", this_zone->name);
knot_dname_free(&dn);
- knot_dname_free(&tn);
free(this_zone->name);
this_zone->name = NULL;
/* Must not free, some versions of flex might continue after error and segfault.
- * free(this_zone);
- * this_zone = NULL;
+ * free(this_zone); this_zone = NULL;
*/
cf_error(scanner, buf);
return;
- }
- knot_dname_free(&tn);
}
/* Directly discard dname, won't be needed. */
- knot_dname_free(&dn);
add_tail(&new_config->zones, &this_zone->n);
+ gen_tree_add(new_config->zone_tree, dn, NULL); /* Will hold reference. */
++new_config->zones_count;
/* Initialize ACL lists. */
diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c
index 0583c883e..d9d0a77bf 100644
--- a/src/knot/conf/conf.c
+++ b/src/knot/conf/conf.c
@@ -72,6 +72,30 @@ void cf_error(void *scanner, const char *msg)
_parser_res = KNOT_EPARSEFAIL;
}
+static int conf_ztree_compare(void *p1, void *p2)
+{
+ return knot_dname_compare((knot_dname_t*)p1, (knot_dname_t*)p2);
+}
+
+static void conf_ztree_free(void *node, void *data)
+{
+ UNUSED(data);
+ knot_dname_t *zname = (knot_dname_t*)node;
+ knot_dname_free(&zname);
+}
+
+static void conf_parse_begin(conf_t *conf)
+{
+ conf->zone_tree = gen_tree_new(conf_ztree_compare);
+}
+
+static void conf_parse_end(conf_t *conf)
+{
+ if (conf->zone_tree) {
+ gen_tree_destroy(&conf->zone_tree, conf_ztree_free, NULL);
+ }
+}
+
/*!
* \brief Call config hooks that need updating.
*
@@ -346,6 +370,7 @@ static int conf_fparser(conf_t *conf)
int ret = KNOT_EOK;
pthread_mutex_lock(&_parser_lock);
+
// {
// Hook new configuration
new_config = conf;
@@ -367,6 +392,7 @@ static int conf_fparser(conf_t *conf)
fclose(f);
// }
pthread_mutex_unlock(&_parser_lock);
+
return ret;
}
@@ -456,8 +482,10 @@ int conf_add_hook(conf_t * conf, int sections,
int conf_parse(conf_t *conf)
{
/* Parse file. */
+ conf_parse_begin(conf);
int ret = conf_fparser(conf);
-
+ conf_parse_end(conf);
+
/* Postprocess config. */
if (ret == 0) {
ret = conf_process(conf);
@@ -475,7 +503,9 @@ int conf_parse(conf_t *conf)
int conf_parse_str(conf_t *conf, const char* src)
{
/* Parse config from string. */
+ conf_parse_begin(conf);
int ret = conf_strparser(conf, src);
+ conf_parse_end(conf);
/* Postprocess config. */
conf_process(conf);
@@ -625,7 +655,9 @@ int conf_open(const char* path)
conf_t *nconf = conf_new(path);
/* Parse config. */
+ conf_parse_begin(nconf);
int ret = conf_fparser(nconf);
+ conf_parse_end(nconf);
if (ret == KNOT_EOK) {
/* Postprocess config. */
ret = conf_process(nconf);
diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h
index 391a85f18..9f2440e85 100644
--- a/src/knot/conf/conf.h
+++ b/src/knot/conf/conf.h
@@ -39,6 +39,7 @@
#include "common/lists.h"
#include "common/log.h"
#include "common/sockaddr.h"
+#include "common/general-tree.h"
/* Constants. */
#define CONFIG_DEFAULT_PORT 53
@@ -199,7 +200,8 @@ typedef struct conf_t {
int dbsync_timeout; /*!< Default interval between syncing to zonefile.*/
size_t ixfr_fslimit; /*!< File size limit for IXFR journal. */
int build_diffs; /*!< Calculate differences from changes. */
-
+ general_tree_t *zone_tree; /*!< Zone tree for duplicate checking. */
+
/*
* Implementation specifics
*/