Commit 9895e0f2 authored by Daniel Salzman's avatar Daniel Salzman

Merge branch 'trie_shallow_copy' into 'master'

trie/zone: implemented trie duplication, faster zone shallow copy

See merge request !973
parents 64119812 c81dbcae
......@@ -369,6 +369,62 @@ void trie_clear(trie_t *tbl)
tbl->weight = 0;
}
static bool dup_trie(node_t *copy, const node_t *orig, trie_dup_cb dup_cb, knot_mm_t *mm)
{
if (isbranch(orig)) {
uint n = branch_weight(orig);
node_t *cotw = mm_alloc(mm, n * sizeof(*cotw));
if (cotw == NULL) {
return NULL;
}
const node_t *ortw = twigs((node_t *)orig);
for (uint i = 0; i < n; ++i) {
if (!dup_trie(cotw + i, ortw + i, dup_cb, mm)) {
while (i-- > 0) {
clear_trie(cotw + i, mm);
}
mm_free(mm, cotw);
return false;
}
}
*copy = mkbranch(branch_index(orig), branch_bmp(orig), cotw);
} else {
tkey_t *key = tkey(orig);
if (mkleaf(copy, key->chars, key->len, mm) != KNOT_EOK) {
return false;
}
if ((copy->p = dup_cb(orig->p, mm)) == NULL) {
mm_free(mm, tkey(copy));
return false;
}
}
return true;
}
trie_t* trie_dup(const trie_t *orig, trie_dup_cb dup_cb, knot_mm_t *mm)
{
if (orig == NULL) {
return NULL;
}
trie_t *copy = mm_alloc(mm, sizeof(*copy));
if (copy == NULL) {
return NULL;
}
copy->weight = orig->weight;
if (mm != NULL) {
copy->mm = *mm;
} else {
mm_ctx_init(&copy->mm);
}
if (copy->weight) {
if (!dup_trie(&copy->root, &orig->root, dup_cb, mm)) {
mm_free(mm, copy);
return NULL;
}
}
return copy;
}
size_t trie_weight(const trie_t *tbl)
{
assert(tbl);
......
......@@ -40,6 +40,9 @@ typedef struct trie trie_t;
/*! \brief Opaque type for holding a QP-trie iterator. */
typedef struct trie_it trie_it_t;
/*! \brief Callback for cloning trie values. */
typedef trie_val_t (*trie_dup_cb)(const trie_val_t val, knot_mm_t *mm);
/*! \brief Callback for performing actions on a trie leaf
*
* Used during copy-on-write transactions
......@@ -63,6 +66,9 @@ void trie_free(trie_t *tbl);
/*! \brief Clear a trie instance (make it empty). */
void trie_clear(trie_t *tbl);
/*! \brief Create a clone of existing trie. */
trie_t* trie_dup(const trie_t *orig, trie_dup_cb dup_cb, knot_mm_t *mm);
/*! \brief Return the number of keys in the trie. */
size_t trie_weight(const trie_t *tbl);
......
......@@ -369,61 +369,38 @@ static int remove_rr(zone_contents_t *z, const knot_rrset_t *rr,
static int recreate_normal_tree(const zone_contents_t *z, zone_contents_t *out)
{
out->nodes = trie_create(NULL);
out->nodes = trie_dup(z->nodes, (trie_dup_cb)node_shallow_copy, NULL);
if (out->nodes == NULL) {
return KNOT_ENOMEM;
}
// Insert APEX first.
zone_node_t *apex_cpy = node_shallow_copy(z->apex, NULL);
if (apex_cpy == NULL) {
return KNOT_ENOMEM;
}
// Normal additions need apex ... so we need to insert directly.
int ret = zone_tree_insert(out->nodes, apex_cpy);
if (ret != KNOT_EOK) {
node_free(apex_cpy, NULL);
return ret;
}
out->apex = apex_cpy;
trie_it_t *itt = trie_it_begin(z->nodes);
// everything done, now just update "parent" and "apex" pointers
out->apex = NULL;
trie_it_t *itt = trie_it_begin(out->nodes);
if (itt == NULL) {
return KNOT_ENOMEM;
}
while (!trie_it_finished(itt)) {
const zone_node_t *to_cpy = (zone_node_t *)*trie_it_val(itt);
if (to_cpy == z->apex) {
// Inserted already.
trie_it_next(itt);
continue;
}
zone_node_t *to_add = node_shallow_copy(to_cpy, NULL);
if (to_add == NULL) {
trie_it_free(itt);
return KNOT_ENOMEM;
}
ret = add_node(out, to_add, true);
if (ret != KNOT_EOK) {
node_free(to_add, NULL);
trie_it_free(itt);
return ret;
zone_node_t *to_fix = (zone_node_t *)*trie_it_val(itt);
if (out->apex == NULL && knot_dname_cmp(to_fix->owner, z->apex->owner) == 0) {
out->apex = to_fix;
} else {
const knot_dname_t *parname = knot_wire_next_label(to_fix->owner, NULL);
const zone_node_t *parent = get_node(out, parname);
assert(parent != NULL);
node_set_parent(to_fix, parent);
}
trie_it_next(itt);
}
trie_it_free(itt);
assert(out->apex != NULL);
return KNOT_EOK;
}
static int recreate_nsec3_tree(const zone_contents_t *z, zone_contents_t *out)
{
out->nsec3_nodes = trie_create(NULL);
out->nsec3_nodes = trie_dup(z->nsec3_nodes, (trie_dup_cb)node_shallow_copy, NULL);
if (out->nsec3_nodes == NULL) {
return KNOT_ENOMEM;
}
......@@ -433,25 +410,11 @@ static int recreate_nsec3_tree(const zone_contents_t *z, zone_contents_t *out)
return KNOT_ENOMEM;
}
while (!trie_it_finished(itt)) {
const zone_node_t *to_cpy = (zone_node_t *)*trie_it_val(itt);
zone_node_t *to_add = node_shallow_copy(to_cpy, NULL);
if (to_add == NULL) {
trie_it_free(itt);
return KNOT_ENOMEM;
}
int ret = add_nsec3_node(out, to_add);
if (ret != KNOT_EOK) {
trie_it_free(itt);
node_free(to_add, NULL);
return ret;
}
zone_node_t *to_fix = (zone_node_t *)*trie_it_val(itt);
to_fix->parent = out->apex;
trie_it_next(itt);
}
trie_it_free(itt);
return KNOT_EOK;
}
......
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