File pacemaker-lrmd-use-most-recent-remote-proxy.patch of Package pacemaker.14737

commit 68438917c3b1ed305af6da2acd23454cd777e1d1
Author: Ken Gaillot <kgaillot@redhat.com>
Date:   Fri Dec 8 18:00:12 2017 -0600

    Fix: lrmd: always use most recent remote proxy
    
    Any working proxy is sufficient, but the newest connection is the most likely
    to be working. We want to avoid using an old proxy that has failed but whose
    TCP connection has not yet timed out.

diff --git a/lrmd/ipc_proxy.c b/lrmd/ipc_proxy.c
index 5d6ab344f..4d1ee01b3 100644
--- a/lrmd/ipc_proxy.c
+++ b/lrmd/ipc_proxy.c
@@ -42,7 +42,7 @@ static qb_ipcs_service_t *crmd_ipcs = NULL;
 static qb_ipcs_service_t *stonith_ipcs = NULL;
 
 /* ipc providers == crmd clients connecting from cluster nodes */
-static GHashTable *ipc_providers = NULL;
+static GList *ipc_providers = NULL;
 /* ipc clients == things like cibadmin, crm_resource, connecting locally */
 static GHashTable *ipc_clients = NULL;
 
@@ -52,24 +52,14 @@ static GHashTable *ipc_clients = NULL;
  *
  * \return Pointer to a provider if one exists, NULL otherwise
  *
- * \note Grab the first provider available; any provider will work, and usually
- *       there will be only one. These are client connections originating from a
- *       cluster node's crmd.
+ * \note Grab the first provider, which is the most recent connection. That way,
+ *       if we haven't yet timed out an old, failed connection, we don't try to
+ *       use it.
  */
 crm_client_t *
 ipc_proxy_get_provider()
 {
-    if (ipc_providers) {
-        GHashTableIter iter;
-        gpointer key = NULL;
-        gpointer value = NULL;
-
-        g_hash_table_iter_init(&iter, ipc_providers);
-        if (g_hash_table_iter_next(&iter, &key, &value)) {
-            return (crm_client_t*)value;
-        }
-    }
-    return NULL;
+    return ipc_providers? (crm_client_t*) (ipc_providers->data) : NULL;
 }
 
 static int32_t
@@ -378,10 +368,8 @@ static struct qb_ipcs_service_handlers cib_proxy_callbacks_rw = {
 void
 ipc_proxy_add_provider(crm_client_t *ipc_proxy)
 {
-    if (ipc_providers == NULL) {
-        return;
-    }
-    g_hash_table_insert(ipc_providers, ipc_proxy->id, ipc_proxy);
+    // Prepending ensures the most recent connection is always first
+    ipc_providers = g_list_prepend(ipc_providers, ipc_proxy);
 }
 
 void
@@ -393,11 +381,7 @@ ipc_proxy_remove_provider(crm_client_t *ipc_proxy)
     GList *remove_these = NULL;
     GListPtr gIter = NULL;
 
-    if (ipc_providers == NULL) {
-        return;
-    }
-
-    g_hash_table_remove(ipc_providers, ipc_proxy->id);
+    ipc_providers = g_list_remove(ipc_providers, ipc_proxy);
 
     g_hash_table_iter_init(&iter, ipc_clients);
     while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & ipc_client)) {
@@ -413,6 +397,8 @@ ipc_proxy_remove_provider(crm_client_t *ipc_proxy)
 
     for (gIter = remove_these; gIter != NULL; gIter = gIter->next) {
         ipc_client = gIter->data;
+
+        // Disconnection callback will free the client here
         qb_ipcs_disconnect(ipc_client->ipcs);
     }
 
@@ -424,7 +410,6 @@ void
 ipc_proxy_init(void)
 {
     ipc_clients = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, NULL);
-    ipc_providers = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, NULL);
 
     cib_ipc_servers_init(&cib_ro,
                          &cib_rw,
@@ -446,10 +431,12 @@ void
 ipc_proxy_cleanup(void)
 {
     if (ipc_providers) {
-        g_hash_table_destroy(ipc_providers);
+        g_list_free(ipc_providers);
+        ipc_providers = NULL;
     }
     if (ipc_clients) {
         g_hash_table_destroy(ipc_clients);
+        ipc_clients = NULL;
     }
     cib_ipc_servers_destroy(cib_ro, cib_rw, cib_shm);
     qb_ipcs_destroy(attrd_ipcs);
@@ -458,6 +445,4 @@ ipc_proxy_cleanup(void)
     cib_ro = NULL;
     cib_rw = NULL;
     cib_shm = NULL;
-    ipc_providers = NULL;
-    ipc_clients = NULL;
 }
openSUSE Build Service is sponsored by