commit d1ddeb89941cafaa52457468cd83f6c00277faa6
Author: Hideo Yamauchi <renayama19661014@ybb.ne.jp>
Date:   Fri Feb 23 09:28:47 2018 +0900

    Mid: attrd: Synchronize attributes held only on own node.

Index: pacemaker-1.1.16+20170320.77ea74d/attrd/commands.c
===================================================================
--- pacemaker-1.1.16+20170320.77ea74d.orig/attrd/commands.c
+++ pacemaker-1.1.16+20170320.77ea74d/attrd/commands.c
@@ -81,11 +81,13 @@ typedef struct attribute_value_s {
         char *nodename;
         char *current;
         char *requested;
+        gboolean seen;
 } attribute_value_t;
 
 
 void write_attribute(attribute_t *a);
 void write_or_elect_attribute(attribute_t *a);
+void attrd_current_only_attribute_update(crm_node_t *peer, xmlNode *xml);
 void attrd_peer_update(crm_node_t *peer, xmlNode *xml, const char *host, bool filter);
 void attrd_peer_sync(crm_node_t *peer, xmlNode *xml);
 void attrd_peer_remove(const char *host, gboolean uncache, const char *source);
@@ -158,6 +160,24 @@ build_attribute_xml(
     return xml;
 }
 
+static void
+clear_attribute_value_seen(void)
+{
+    GHashTableIter aIter;
+    GHashTableIter vIter;
+    attribute_t *a;
+    attribute_value_t *v = NULL;
+
+    g_hash_table_iter_init(&aIter, attributes);
+    while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
+        g_hash_table_iter_init(&vIter, a->values);
+        while (g_hash_table_iter_next(&vIter, NULL, (gpointer *) & v)) {
+            v->seen = FALSE;
+            crm_trace("Clear seen flag %s[%s] = %s.", a->id, v->nodename, v->current);
+        }
+    }
+}
+
 static attribute_t *
 create_attribute(xmlNode *xml)
 {
@@ -670,10 +690,21 @@ attrd_peer_message(crm_node_t *peer, xml
         xmlNode *child = NULL;
 
         crm_info("Processing %s from %s", op, peer->uname);
+
+        /* Clear the seen flag for attribute processing held only in the own node. */
+        if (peer_state == election_won) {
+            clear_attribute_value_seen();
+        }
+
         for (child = __xml_first_child(xml); child != NULL; child = __xml_next(child)) {
             host = crm_element_value(child, F_ATTRD_HOST);
             attrd_peer_update(peer, child, host, TRUE);
         }
+
+        if (peer_state == election_won) {
+            /* Synchronize if there is an attribute held only by own node that Writer does not have. */
+            attrd_current_only_attribute_update(peer, xml);
+        }
     }
 }
 
@@ -778,6 +809,42 @@ attrd_lookup_or_create_value(GHashTable
     return(v);
 }
 
+void 
+attrd_current_only_attribute_update(crm_node_t *peer, xmlNode *xml)
+{
+    GHashTableIter aIter;
+    GHashTableIter vIter;
+    attribute_t *a;
+    attribute_value_t *v = NULL;
+    xmlNode *sync = create_xml_node(NULL, __FUNCTION__);
+    gboolean build = FALSE;    
+
+    crm_xml_add(sync, F_ATTRD_TASK, ATTRD_OP_SYNC_RESPONSE);
+
+    g_hash_table_iter_init(&aIter, attributes);
+    while (g_hash_table_iter_next(&aIter, NULL, (gpointer *) & a)) {
+        g_hash_table_iter_init(&vIter, a->values);
+        while (g_hash_table_iter_next(&vIter, NULL, (gpointer *) & v)) {
+            if (safe_str_eq(v->nodename, attrd_cluster->uname) && v->seen == FALSE) {
+                crm_trace("Syncing %s[%s] = %s to everyone.(from local only attributes)", a->id, v->nodename, v->current);
+
+                build = TRUE;
+                build_attribute_xml(sync, a->id, a->set, a->uuid, a->timeout_ms, a->user, a->is_private,
+                            v->nodename, v->nodeid, v->current);
+            } else {
+                crm_trace("Local attribute(%s[%s] = %s) was ignore.(another host) : [%s]", a->id, v->nodename, v->current, attrd_cluster->uname);
+                continue;
+            }
+        }
+    }
+
+    if (build) {
+        crm_debug("Syncing values to everyone.(from local only attributes)");
+        send_attrd_message(NULL, sync);
+    }
+    free_xml(sync);
+}
+
 void
 attrd_peer_update(crm_node_t *peer, xmlNode *xml, const char *host, bool filter)
 {
@@ -906,6 +973,9 @@ attrd_peer_update(crm_node_t *peer, xmlN
         crm_trace("Unchanged %s[%s] from %s is %s", attr, host, peer->uname, value);
     }
 
+    /* Set the seen flag for attribute processing held only in the own node. */
+    v->seen = TRUE;
+
     /* If this is a cluster node whose node ID we are learning, remember it */
     if ((v->nodeid == 0) && (v->is_remote == FALSE)
         && (crm_element_value_int(xml, F_ATTRD_HOST_ID, (int*)&v->nodeid) == 0)) {
