/** Merge all mergeable zones into one big zone. * * It is reasonable to do this on systems where * BIOS reports parts in chunks, so that we could * have 1 zone (it's faster). * */ void zone_merge_all(void) { size_t i = 1; while (i < zones.count) { if (!zone_merge(i - 1, i)) i++; } }
/** * Merge zone lists. * */ static void zonelist_merge(zonelist_type* zl1, zonelist_type* zl2) { zone_type* z1 = NULL; zone_type* z2 = NULL; ldns_rbnode_t* n1 = LDNS_RBTREE_NULL; ldns_rbnode_t* n2 = LDNS_RBTREE_NULL; int ret = 0; ods_log_assert(zl1); ods_log_assert(zl2); ods_log_assert(zl1->zones); ods_log_assert(zl2->zones); ods_log_debug("[%s] merge two zone lists", zl_str); n1 = ldns_rbtree_first(zl1->zones); n2 = ldns_rbtree_first(zl2->zones); while (n2 && n2 != LDNS_RBTREE_NULL) { z2 = (zone_type*) n2->data; if (n1 && n1 != LDNS_RBTREE_NULL) { z1 = (zone_type*) n1->data; } else { z1 = NULL; } if (!z2) { /* no more zones to merge into zl1 */ return; } else if (!z1) { /* just add remaining zones from zl2 */ z2 = zonelist_add_zone(zl1, z2); if (!z2) { ods_log_crit("[%s] merge failed: z2 not added", zl_str); return; } n2 = ldns_rbtree_next(n2); } else { /* compare the zones z1 and z2 */ ret = zone_compare(z1, z2); if (ret < 0) { /* remove zone z1, it is not present in the new list zl2 */ z1->zl_status = ZONE_ZL_REMOVED; zl1->just_removed++; n1 = ldns_rbtree_next(n1); } else if (ret > 0) { /* add the new zone z2 */ z2 = zonelist_add_zone(zl1, z2); if (!z2) { ods_log_crit("[%s] merge failed: z2 not added", zl_str); return; } n2 = ldns_rbtree_next(n2); } else { /* just update zone z1 */ n1 = ldns_rbtree_next(n1); n2 = ldns_rbtree_next(n2); zone_merge(z1, z2); zone_cleanup(z2); if (z1->zl_status == ZONE_ZL_UPDATED) { zl1->just_updated++; } z1->zl_status = ZONE_ZL_UPDATED; } } } /* remove remaining zones from z1 */ while (n1 && n1 != LDNS_RBTREE_NULL) { z1 = (zone_type*) n1->data; z1->zl_status = ZONE_ZL_REMOVED; zl1->just_removed++; n1 = ldns_rbtree_next(n1); } zl1->last_modified = zl2->last_modified; return; }