From 036830955ebfeb3ee681d36527d70be29d80a508 Mon Sep 17 00:00:00 2001
From: Jan Kadlec <jan.kadlec@nic.cz>
Date: Wed, 2 Apr 2014 11:16:15 +0200
Subject: [PATCH] new_node: Store additionals for cleanup.

---
 src/knot/updates/xfr-in.c | 93 +++++++++++++++++++++++++++------------
 src/knot/zone/node.c      |  2 -
 2 files changed, 66 insertions(+), 29 deletions(-)

diff --git a/src/knot/updates/xfr-in.c b/src/knot/updates/xfr-in.c
index eecef6fd27..9f04bf1016 100644
--- a/src/knot/updates/xfr-in.c
+++ b/src/knot/updates/xfr-in.c
@@ -47,7 +47,7 @@ static void rrs_list_clear(list_t *l, mm_ctx_t *mm)
 	ptrnode_t *n;
 	node_t *nxt;
 	WALK_LIST_DELSAFE(n, nxt, *l) {
-		mm_free(mm, (knot_rr_t *)n->d);
+		mm_free(mm, (void *)n->d);
 		mm_free(mm, n);
 	};
 }
@@ -784,7 +784,9 @@ static int xfrin_replace_rrs_with_copy(knot_node_t *node,
 static void clear_new_rrs(knot_node_t *node, uint16_t type)
 {
 	knot_rrs_t *new_rrs = knot_node_get_rrs(node, type);
-	knot_rrs_clear(new_rrs, NULL);
+	if (new_rrs) {
+		knot_rrs_clear(new_rrs, NULL);
+	}
 }
 
 static bool can_remove(const knot_node_t *node, const knot_rrset_t *rr)
@@ -807,6 +809,33 @@ static bool can_remove(const knot_node_t *node, const knot_rrset_t *rr)
 	return true;
 }
 
+static int add_old_data(knot_changeset_t *chset, knot_rr_t *old_data,
+                        knot_node_t **old_additional)
+{
+	if (ptrlist_add(&chset->old_data, old_data, NULL) == NULL) {
+		return KNOT_ENOMEM;
+	}
+
+	if (!old_additional) {
+		return KNOT_EOK;
+	}
+
+	if (ptrlist_add(&chset->old_data, old_additional, NULL) == NULL) {
+		return KNOT_ENOMEM;
+	}
+
+	return KNOT_EOK;
+}
+
+static int add_new_data(knot_changeset_t *chset, knot_rr_t *new_data)
+{
+	if (ptrlist_add(&chset->new_data, new_data, NULL) == NULL) {
+		return KNOT_ENOMEM;
+	}
+
+	return KNOT_EOK;
+}
+
 static int xfrin_apply_remove(knot_zone_contents_t *contents,
                               knot_changeset_t *chset,
                               list_t *old_rrs, list_t *new_rrs)
@@ -820,34 +849,39 @@ static int xfrin_apply_remove(knot_zone_contents_t *contents,
 			continue;
 		}
 
-		1 == 1; // store additional
-		knot_rrs_t *rrs = knot_node_get_rrs(node, rr->type);
-		knot_rr_t *old_data = rrs->data;
-
-		int ret = xfrin_replace_rrs_with_copy(node, rrs, rr->type, NULL);
+		knot_rrset_t removed_rrset = RRSET_INIT(node, rr->type);
+		knot_rr_t *old_data = removed_rrset.rrs.data;
+		knot_node_t **old_additional = removed_rrset.additional;
+		int ret = xfrin_replace_rrs_with_copy(node,
+		                                      &removed_rrset.rrs,
+		                                      rr->type, NULL);
 		if (ret != KNOT_EOK) {
 			return ret;
 		}
 
-		if (ptrlist_add(old_rrs, old_data, NULL) == NULL) {
+		ret = add_old_data(chset, old_data, old_additional);
+		if (ret != KNOT_EOK) {
 			clear_new_rrs(node, rr->type);
-			return KNOT_ENOMEM;
+			return ret;
 		}
 
-		knot_rrset_t rrset = RRSET_INIT(node, rr->type);
-		ret = knot_rrset_remove_rr_using_rrset(&rrset, rr, NULL);
+		knot_rrset_t changed_rrset = RRSET_INIT(node, rr->type);
+		ret = knot_rrset_remove_rr_using_rrset(&changed_rrset, rr, NULL);
 		if (ret != KNOT_EOK) {
 			clear_new_rrs(node, rr->type);
 			return ret;
 		}
 
-		if (rrset.rrs.rr_count > 0) {
-			if (ptrlist_add(new_rrs, rrset.rrs.data, NULL) == NULL) {
-				knot_rrs_clear(rrs, NULL);
-				return KNOT_ENOMEM;
+		if (changed_rrset.rrs.rr_count > 0) {
+			ret = add_new_data(chset, changed_rrset.rrs.data);
+			if (ret != KNOT_EOK) {
+				knot_rrs_clear(&changed_rrset.rrs, NULL);
+				return ret;
 			}
-			rrs = knot_node_get_rrs(node, rr->type);
-			*rrs = rrset.rrs;
+
+			// Replace with changed data
+			knot_rrs_t *rrs = knot_node_get_rrs(node, rr->type);
+			*rrs = changed_rrset.rrs;
 		} else {
 			knot_node_remove_rrset(node, rr->type);
 		}
@@ -869,17 +903,22 @@ static int xfrin_apply_add(knot_zone_contents_t *contents,
 			return KNOT_ENOMEM;
 		}
 
-		knot_rrs_t *rrs = knot_node_get_rrs(node, rr->type);
-		if (rrs) {
-			knot_rr_t *old_data = rrs->data;
-			int ret = xfrin_replace_rrs_with_copy(node, rrs, rr->type, NULL);
+		knot_rrset_t changed_rrset = RRSET_INIT(node, rr->type);
+		if (!knot_rrset_empty(&changed_rrset)) {
+			knot_rr_t *old_data = changed_rrset.rrs.data;
+			knot_node_t **old_additional = changed_rrset.additional;
+			int ret = xfrin_replace_rrs_with_copy(node,
+			                                      &changed_rrset.rrs,
+			                                      rr->type, NULL);
 			if (ret != KNOT_EOK) {
 				return ret;
 			}
+
 			// Store old RRS for cleanup
-			if (ptrlist_add(old_rrs, old_data, NULL) == NULL) {
+			ret = add_old_data(chset, old_data, old_additional);
+			if (ret != KNOT_EOK) {
 				clear_new_rrs(node, rr->type);
-				return KNOT_ENOMEM;
+				return ret;
 			}
 		}
 
@@ -890,12 +929,12 @@ static int xfrin_apply_add(knot_zone_contents_t *contents,
 			return ret;
 		}
 
-		rrs = knot_node_get_rrs(node, rr->type);
-		assert(rrs);
+		knot_rrs_t *rrs = knot_node_get_rrs(node, rr->type);
 		// Store new RRS for rollback
-		if (ptrlist_add(new_rrs, rrs->data, NULL) == NULL) {
+		ret = add_new_data(chset, rrs->data);
+		if (ret != KNOT_EOK) {
 			knot_rrs_clear(rrs, NULL);
-			return KNOT_ENOMEM;
+			return ret;
 		}
 	}
 
diff --git a/src/knot/zone/node.c b/src/knot/zone/node.c
index 747e27cf7b..4bd8c0b9cf 100644
--- a/src/knot/zone/node.c
+++ b/src/knot/zone/node.c
@@ -269,8 +269,6 @@ void knot_node_remove_rrset(knot_node_t *node, uint16_t type)
 
 	for (int i = 0; i < node->rrset_count; ++i) {
 		if (node->rrs[i].type == type) {
-			1 == 1; // old zone corrupted
-			free(node->rrs[i].additional);
 			memmove(node->rrs + i, node->rrs + i + 1, (node->rrset_count - i - 1) * sizeof(struct rr_data));
 			--node->rrset_count;
 			return;
-- 
GitLab