Hello,
this patch implements "Flush zones and RRs cache when handling persistent
search reconnection" behaviour as requested
in ticket https://fedorahosted.org/bind-dyndb-ldap/ticket/44 .
Petr^2 Spacek
From 06f38006e841a210d60ae93bb5c9027e40073d84 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspa...@redhat.com>
Date: Fri, 27 Jul 2012 11:18:42 +0200
Subject: [PATCH] Flush zones and RRs cache when handling persistent search
reconnection
https://fedorahosted.org/bind-dyndb-ldap/ticket/44
Signed-off-by: Petr Spacek <pspa...@redhat.com>
---
src/cache.c | 25 ++++++++++++++++++++++++-
src/cache.h | 7 +++++++
src/ldap_helper.c | 22 +++++++++++++++++-----
src/ldap_helper.h | 2 +-
src/zone_manager.c | 4 ++--
5 files changed, 51 insertions(+), 9 deletions(-)
diff --git a/src/cache.c b/src/cache.c
index 28f93c937f23707541a015eb071d3934c96cff1f..898d48b291a83da7f77dbcf79e2bd3e7ff8281aa 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -38,7 +38,7 @@
#include "util.h"
struct ldap_cache {
- isc_mutex_t mutex;
+ isc_mutex_t mutex; /* TODO: RWLOCK? */
isc_mem_t *mctx;
dns_rbt_t *rbt;
isc_interval_t cache_ttl;
@@ -303,3 +303,26 @@ discard_from_cache(ldap_cache_t *cache, dns_name_t *name)
return result;
}
+
+isc_result_t
+flush_ldap_cache(ldap_cache_t *cache)
+{
+ isc_result_t result;
+
+ REQUIRE(cache != NULL);
+
+ LOCK(&cache->mutex);
+ if (!ldap_cache_enabled(cache)) {
+ result = ISC_R_SUCCESS;
+ } else {
+ dns_rbt_destroy(&cache->rbt);
+ CHECK(dns_rbt_create(cache->mctx, cache_node_deleter, NULL,
+ &cache->rbt));
+ }
+
+cleanup:
+ if (result != ISC_R_SUCCESS)
+ log_error_r("cache flush failed");
+ UNLOCK(&cache->mutex);
+ return result;
+}
diff --git a/src/cache.h b/src/cache.h
index 6a4e35611f048eb9d10ded68c12017c6cb25de1a..a7aa5b7e889d9e195484a11dcf4f9a10d811f623 100644
--- a/src/cache.h
+++ b/src/cache.h
@@ -77,4 +77,11 @@ ldap_cache_enabled(ldap_cache_t *cache);
isc_result_t
discard_from_cache(ldap_cache_t *cache, dns_name_t *name);
+/**
+ * Discard all names from the cache and re-initialize internal RB-tree.
+ * @return ISC_R_SUCCESS even if cache is disabled.
+ */
+isc_result_t
+flush_ldap_cache(ldap_cache_t *cache);
+
#endif /* !_LD_CACHE_H_ */
diff --git a/src/ldap_helper.c b/src/ldap_helper.c
index daffac7c7825a99a07c333217638d3beaddfaad2..717b7b12007f7db5be42e0ca761760a5da22a2bc 100644
--- a/src/ldap_helper.c
+++ b/src/ldap_helper.c
@@ -1175,11 +1175,14 @@ cleanup:
* added. In that case, only modify the zone's properties, like the update
* policy.
*
+ * @param delete_only Do LDAP vs. zone register cross-check and delete zones
+ * which aren't in LDAP, but do not load new zones.
+ *
* Returns ISC_R_SUCCESS if we found and successfully added at least one zone.
* Returns ISC_R_FAILURE otherwise.
*/
isc_result_t
-refresh_zones_from_ldap(ldap_instance_t *ldap_inst)
+refresh_zones_from_ldap(ldap_instance_t *ldap_inst, isc_boolean_t delete_only)
{
isc_result_t result = ISC_R_SUCCESS;
ldap_connection_t *ldap_conn = NULL;
@@ -1202,8 +1205,8 @@ refresh_zones_from_ldap(ldap_instance_t *ldap_inst)
REQUIRE(ldap_inst != NULL);
- if (ldap_inst->psearch) {
- /* Watcher does the work for us */
+ if (ldap_inst->psearch && !delete_only) {
+ /* Watcher does the work for us, but deletion is allowed. */
return ISC_R_SUCCESS;
}
@@ -1254,7 +1257,8 @@ refresh_zones_from_ldap(ldap_instance_t *ldap_inst)
continue;
}
- CHECK(ldap_parse_zoneentry(entry, ldap_inst));
+ if (!delete_only)
+ CHECK(ldap_parse_zoneentry(entry, ldap_inst));
zone_count++;
}
@@ -1280,10 +1284,14 @@ refresh_zones_from_ldap(ldap_instance_t *ldap_inst)
node = NULL;
result = dns_rbtnodechain_current(&chain, &fname, &forig, &node);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
+ if (result != ISC_R_NOTFOUND)
+ log_error_r("unable walk through RB-tree during zone_refresh");
goto next;
+ }
if (dns_name_concatenate(&fname, &forig, &aname, aname.buffer) != ISC_R_SUCCESS) {
+ log_error_r("unable to concatenate DNS names during zone_refresh");
goto next;
}
@@ -3505,6 +3513,10 @@ restart:
}
}
+ /* Unload old zones and flush record cache */
+ CHECK(refresh_zones_from_ldap(inst, ISC_TRUE));
+ CHECK(flush_ldap_cache(inst->cache));
+
while (!inst->exiting) {
ret = ldap_result(conn->handle, conn->msgid, 0, &tv,
&ldap_qresult->result);
diff --git a/src/ldap_helper.h b/src/ldap_helper.h
index bc784106abefe15787841578687469539c8052c3..f6cbdc593d91485f767ae5ea6017e114f95733d1 100644
--- a/src/ldap_helper.h
+++ b/src/ldap_helper.h
@@ -82,7 +82,7 @@ new_ldap_instance(isc_mem_t *mctx, const char *db_name,
isc_task_t *task, ldap_instance_t **ldap_instp);
void destroy_ldap_instance(ldap_instance_t **ldap_inst);
isc_result_t
-refresh_zones_from_ldap(ldap_instance_t *ldap_inst);
+refresh_zones_from_ldap(ldap_instance_t *ldap_inst, isc_boolean_t delete_only);
/* Functions for writing to LDAP. */
isc_result_t write_to_ldap(dns_name_t *owner, ldap_instance_t *ldap_inst,
diff --git a/src/zone_manager.c b/src/zone_manager.c
index eb761aa922d4f61b2659b2740093cef9bb102624..ca3edd010e5f6ea94adb57e5ae5e915a834e52a0 100644
--- a/src/zone_manager.c
+++ b/src/zone_manager.c
@@ -180,7 +180,7 @@ manager_create_db_instance(isc_mem_t *mctx, const char *name,
APPEND(instance_list, db_inst, link);
UNLOCK(&instance_list_lock);
- result = refresh_zones_from_ldap(db_inst->ldap_inst);
+ result = refresh_zones_from_ldap(db_inst->ldap_inst, ISC_FALSE);
if (result != ISC_R_SUCCESS) {
/* In case we don't find any zones, we at least return
* ISC_R_SUCCESS so BIND won't exit because of this. */
@@ -221,7 +221,7 @@ refresh_zones_action(isc_task_t *task, isc_event_t *event)
UNUSED(task);
- refresh_zones_from_ldap(db_inst->ldap_inst);
+ refresh_zones_from_ldap(db_inst->ldap_inst, ISC_FALSE);
isc_event_free(&event);
}
--
1.7.11.2
_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel