ldap/servers/plugins/dna/dna.c | 218 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 208 insertions(+), 10 deletions(-)
New commits:
commit 06a3d0a1a2d925e314e9d50c1093a122c6ec788c
Author: Mark Reynolds <mreynolds(a)redhat.com>
Date: Mon Apr 21 11:16:09 2014 -0400
Ticket 47779 - Part of DNA shared configuration is deleted after server restart
Bug Description: After a configuration change, like updating dnaNextVal,
the shared config entries are always rebuilt, but they do
preserve some of the configuration attributes like
dnaRemoteBindMethod.
Fix Description: Maintain a global linked list of all the shared config entries,
so when we go to rebuild the shared config entry we can restore
the dnaRemote attributes.
https://fedorahosted.org/389/ticket/47779
Reviewed by: nhosoi(Thanks!)
diff --git a/ldap/servers/plugins/dna/dna.c b/ldap/servers/plugins/dna/dna.c
index cf88597..e9453a4 100644
--- a/ldap/servers/plugins/dna/dna.c
+++ b/ldap/servers/plugins/dna/dna.c
@@ -101,6 +101,7 @@
#define DNA_HOSTNAME "dnaHostname"
#define DNA_PORTNUM "dnaPortNum"
#define DNA_SECURE_PORTNUM "dnaSecurePortNum"
+#define DNA_REMOTE_BUFSIZ 15 /* max size for bind method & protocol */
#define DNA_REMOTE_BIND_METHOD "dnaRemoteBindMethod"
#define DNA_REMOTE_CONN_PROT "dnaRemoteConnProtocol"
@@ -191,6 +192,9 @@ struct configEntry {
static PRCList *dna_global_config = NULL;
static Slapi_RWLock *g_dna_cache_lock;
+static struct dnaServer *dna_global_servers = NULL;
+static Slapi_RWLock *g_dna_cache_server_lock;
+
static void *_PluginID = NULL;
static const char *_PluginDN = NULL;
@@ -204,6 +208,7 @@ static char *secureportnum = NULL;
*/
struct dnaServer {
PRCList list;
+ Slapi_DN *sdn;
char *host;
unsigned int port;
unsigned int secureport;
@@ -214,6 +219,7 @@ struct dnaServer {
char *remote_conn_prot;
char *remote_binddn; /* contains pointer to main config binddn */
char *remote_bindpw; /* contains pointer to main config bindpw */
+ struct dnaServer *next; /* used for the global server list */
};
static char *dna_extend_exop_oid_list[] = {
@@ -262,7 +268,7 @@ static void dna_notice_allocation(struct configEntry *config_entry,
PRUint64 new, PRUint64 last);
static int dna_update_shared_config(struct configEntry * config_entry);
static void dna_update_config_event(time_t event_time, void *arg);
-static int dna_get_shared_servers(struct configEntry *config_entry, PRCList **servers);
+static int dna_get_shared_servers(struct configEntry *config_entry, PRCList **servers,
int get_all);
static void dna_free_shared_server(struct dnaServer **server);
static void dna_delete_shared_servers(PRCList **servers);
static int dna_release_range(char *range_dn, PRUint64 *lower, PRUint64 *upper);
@@ -285,6 +291,9 @@ static void dna_create_valcheck_filter(struct configEntry
*config_entry, PRUint6
static int dna_isrepl(Slapi_PBlock *pb);
static int dna_get_remote_config_info( struct dnaServer *server, char **bind_dn, char
**bind_passwd,
char **bind_method, int *is_ssl, int *port);
+static int dna_load_shared_servers();
+static void dna_delete_global_servers();
+static int dna_get_shared_config_attr_val(struct configEntry *config_entry, char *attr,
char *value);
/**
*
@@ -338,6 +347,21 @@ void dna_unlock()
slapi_rwlock_unlock(g_dna_cache_lock);
}
+void dna_server_read_lock()
+{
+ slapi_rwlock_rdlock(g_dna_cache_server_lock);
+}
+
+void dna_server_write_lock()
+{
+ slapi_rwlock_wrlock(g_dna_cache_server_lock);
+}
+
+void dna_server_unlock()
+{
+ slapi_rwlock_unlock(g_dna_cache_server_lock);
+}
+
/**
*
* Get the dna plug-in version
@@ -546,11 +570,16 @@ dna_start(Slapi_PBlock * pb)
"--> dna_start\n");
g_dna_cache_lock = slapi_new_rwlock();
-
if (!g_dna_cache_lock) {
slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
- "dna_start: lock creation failed\n");
+ "dna_start: global config lock creation failed\n");
+ return DNA_FAILURE;
+ }
+ g_dna_cache_server_lock = slapi_new_rwlock();
+ if (!g_dna_cache_server_lock) {
+ slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
+ "dna_start: global server lock creation failed\n");
return DNA_FAILURE;
}
@@ -594,6 +623,15 @@ dna_start(Slapi_PBlock * pb)
return DNA_FAILURE;
}
+ /*
+ * Load all shared server configs
+ */
+ if (dna_load_shared_servers() ) {
+ slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
+ "dna_start: shared config server initialization
failed.\n");
+ return DNA_FAILURE;
+ }
+
slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
"dna: ready for service\n");
slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
@@ -618,6 +656,10 @@ dna_close(Slapi_PBlock * pb)
slapi_destroy_rwlock(g_dna_cache_lock);
g_dna_cache_lock = NULL;
+ dna_delete_global_servers();
+ slapi_destroy_rwlock(g_dna_cache_server_lock);
+ g_dna_cache_server_lock = NULL;
+
slapi_ch_free_string(&hostname);
slapi_ch_free_string(&portnum);
slapi_ch_free_string(&secureportnum);
@@ -629,6 +671,82 @@ dna_close(Slapi_PBlock * pb)
}
/*
+ * Free the global linkedl ist of shared servers
+ */
+static void
+dna_delete_global_servers()
+{
+ struct dnaServer *server, *next;
+
+ if(dna_global_servers){
+ server = dna_global_servers;
+ while(server){
+ next = server->next;
+ dna_free_shared_server(&server);
+ server = next;
+ }
+ dna_global_servers = NULL;
+ }
+}
+
+/*
+ * Look through the global config entries, and build a global
+ * shared server config list.
+ */
+static int
+dna_load_shared_servers()
+{
+ struct configEntry *config_entry = NULL;
+ struct dnaServer *server = NULL, *global_servers = NULL;
+ PRCList *server_list = NULL;
+ PRCList *config_list = NULL;
+ int ret = 0;
+
+ /* First free the existing list. */
+ dna_delete_global_servers();
+
+ /* Now build the new list. */
+ dna_write_lock();
+ if (!PR_CLIST_IS_EMPTY(dna_global_config)) {
+ config_list = PR_LIST_HEAD(dna_global_config);
+ while (config_list != dna_global_config) {
+ PRCList *shared_list = NULL;
+ config_entry = (struct configEntry *) config_list;
+
+ if(dna_get_shared_servers(config_entry,
+ &shared_list,
+ 1 /* get all the servers */))
+ {
+ dna_unlock();
+ return -1;
+ }
+
+ dna_server_write_lock();
+ if (shared_list) {
+ server_list = PR_LIST_HEAD(shared_list);
+ while (server_list != shared_list) {
+ server = (struct dnaServer *)server_list;
+ if(global_servers == NULL){
+ dna_global_servers = global_servers = server;
+ } else {
+ global_servers->next = server;
+ global_servers = server;
+ }
+ server_list = PR_NEXT_LINK(server_list);
+ }
+ slapi_ch_free((void **)&shared_list);
+ }
+ dna_server_unlock();
+
+ config_list = PR_NEXT_LINK(config_list);
+ }
+ }
+ dna_unlock();
+
+ return ret;
+}
+
+/*
* config looks like this
* - cn=myplugin
* --- cn=posix
@@ -1233,6 +1351,7 @@ dna_free_shared_server(struct dnaServer **server)
return;
}
s = *server;
+ slapi_sdn_free(&s->sdn);
slapi_ch_free_string(&s->host);
slapi_ch_free_string(&s->remote_bind_method);
slapi_ch_free_string(&s->remote_conn_prot);
@@ -1330,6 +1449,7 @@ dna_update_config_event(time_t event_time, void *arg)
Slapi_PBlock *dna_pb = NULL;
Slapi_DN *sdn =
slapi_sdn_new_normdn_byref(config_entry->shared_cfg_dn);
Slapi_Backend *be = slapi_be_select(sdn);
+
slapi_sdn_free(&sdn);
if (be) {
dna_pb = slapi_pblock_new();
@@ -1416,7 +1536,7 @@ static int dna_fix_maxval(struct configEntry *config_entry,
} else if (!skip_range_request && config_entry->shared_cfg_base) {
/* Find out if there are any other servers to request
* range from. */
- dna_get_shared_servers(config_entry, &servers);
+ dna_get_shared_servers(config_entry, &servers, 0 );
if (servers) {
/* We have other servers we can try to extend
@@ -1506,7 +1626,7 @@ dna_notice_allocation(struct configEntry *config_entry, PRUint64
new,
}
static int
-dna_get_shared_servers(struct configEntry *config_entry, PRCList **servers)
+dna_get_shared_servers(struct configEntry *config_entry, PRCList **servers, int get_all)
{
int ret = LDAP_SUCCESS;
Slapi_PBlock *pb = NULL;
@@ -1556,13 +1676,14 @@ dna_get_shared_servers(struct configEntry *config_entry, PRCList
**servers)
/* We found some entries. Go through them and
* order them based off of remaining values. */
for (i = 0; entries[i]; i++) {
- /* skip our own shared config entry */
- if (slapi_sdn_compare(cfg_sdn, slapi_entry_get_sdn(entries[i]))) {
+ /* skip our own shared config entry, unless we want all the servers */
+ if (get_all || slapi_sdn_compare(cfg_sdn, slapi_entry_get_sdn(entries[i])))
{
struct dnaServer *server = NULL;
/* set up the server list entry */
server = (struct dnaServer *) slapi_ch_calloc(1,
sizeof(struct dnaServer));
+ server->sdn =
slapi_sdn_new_dn_byval(slapi_entry_get_ndn(entries[i]));
server->host = slapi_entry_attr_get_charptr(entries[i],
DNA_HOSTNAME);
server->port = slapi_entry_attr_get_uint(entries[i], DNA_PORTNUM);
@@ -1631,7 +1752,7 @@ dna_get_shared_servers(struct configEntry *config_entry, PRCList
**servers)
} else {
/* Find the right slot for this entry. We
* want to order the entries based off of
- * the remaining number of values, higest
+ * the remaining number of values, highest
* to lowest. */
struct dnaServer *sitem;
PRCList* item = PR_LIST_HEAD(*servers);
@@ -1908,6 +2029,36 @@ static int dna_dn_is_config(char *dn)
return ret;
}
+static int
+dna_dn_is_shared_config(Slapi_PBlock *pb, char *dn)
+{
+ struct configEntry *config_entry = NULL;
+ Slapi_Entry *entry = NULL;
+ Slapi_Attr *attr = NULL;
+ PRCList *list = NULL;
+ int ret = 0;
+
+ dna_read_lock();
+ if (!PR_CLIST_IS_EMPTY(dna_global_config)) {
+ list = PR_LIST_HEAD(dna_global_config);
+ while (list != dna_global_config) {
+ config_entry = (struct configEntry *) list;
+ if (slapi_dn_issuffix(dn, config_entry->shared_cfg_base)) {
+ slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &entry);
+ /* If the entry has the dnaHost attribute, it is a shared entry */
+ if (slapi_entry_attr_find(entry, DNA_HOSTNAME, &attr) == 0) {
+ ret = 1;
+ break;
+ }
+ }
+ list = PR_NEXT_LINK(list);
+ }
+ }
+ dna_unlock();
+
+ return ret;
+}
+
#define DNA_LDAP_TAG_SK_REVERSE 0x81L
static LDAPControl *dna_build_sort_control(const char *attr)
@@ -2236,6 +2387,39 @@ static int dna_get_next_value(struct configEntry *config_entry,
}
/*
+ * Get a value from the global server list. The dna_server_read_lock()
+ * should be held prior to calling this function.
+ */
+static int
+dna_get_shared_config_attr_val(struct configEntry *config_entry, char *attr, char
*value)
+{
+ struct dnaServer *server = NULL;
+ Slapi_DN *server_sdn = NULL;
+ int found = 0;
+
+ server_sdn = slapi_sdn_new_dn_byref(config_entry->shared_cfg_dn);
+ if (dna_global_servers) {
+ server = dna_global_servers;
+ while (server) {
+ if(slapi_sdn_compare(server->sdn, server_sdn) == 0){
+ if(strcmp(attr, DNA_REMOTE_BIND_METHOD) == 0){
+ PR_snprintf(value, DNA_REMOTE_BUFSIZ, "%s",
server->remote_bind_method);
+ found = 1;
+ break;
+ } else if(strcmp(attr, DNA_REMOTE_CONN_PROT) == 0){
+ PR_snprintf(value, DNA_REMOTE_BUFSIZ, "%s",
server->remote_conn_prot);
+ found = 1;
+ break;
+ }
+ }
+ server = server->next;
+ }
+ }
+ slapi_sdn_free(&server_sdn);
+
+ return found;
+}
+/*
* dna_update_shared_config()
*
* Updates the shared config entry if one is
@@ -2287,8 +2471,9 @@ dna_update_shared_config(struct configEntry * config_entry)
* already exist, we add it. */
if (ret == LDAP_NO_SUCH_OBJECT) {
Slapi_Entry *e = NULL;
- Slapi_DN *sdn =
- slapi_sdn_new_normdn_byref(config_entry->shared_cfg_dn);
+ Slapi_DN *sdn =
slapi_sdn_new_normdn_byref(config_entry->shared_cfg_dn);
+ char bind_meth[DNA_REMOTE_BUFSIZ];
+ char conn_prot[DNA_REMOTE_BUFSIZ];
/* Set up the new shared config entry */
e = slapi_entry_alloc();
@@ -2304,6 +2489,16 @@ dna_update_shared_config(struct configEntry * config_entry)
}
slapi_entry_add_string(e, DNA_REMAINING, remaining_vals);
+ /* Grab the remote server settings */
+ dna_server_read_lock();
+ if(dna_get_shared_config_attr_val(config_entry, DNA_REMOTE_BIND_METHOD,
bind_meth)) {
+ slapi_entry_add_string(e, DNA_REMOTE_BIND_METHOD, bind_meth);
+ }
+ if(dna_get_shared_config_attr_val(config_entry, DNA_REMOTE_CONN_PROT,
conn_prot)){
+ slapi_entry_add_string(e, DNA_REMOTE_CONN_PROT,conn_prot);
+ }
+ dna_server_unlock();
+
/* clear pb for re-use */
slapi_pblock_init(pb);
@@ -3893,6 +4088,9 @@ static int dna_config_check_post_op(Slapi_PBlock * pb)
if (dna_dn_is_config(dn)) {
dna_load_plugin_config(pb, 0);
}
+ if(dna_dn_is_shared_config(pb, dn) == 0){
+ dna_load_shared_servers();
+ }
}
}