Blob Blame History Raw
commit 3544fb711731cb6ebcd48c2af808e4ec25e5eaed
Author: Andrew Beekhof <andrew@beekhof.net>
Date:   Wed Apr 2 15:44:31 2014 +1100

    Refactor: PE: Store non-resource actions in a hashtable where we can easily (and cheaply) find them again
    
    (cherry picked from commit a65979cbbec616f978154e95b49e8f7bcd064a14)

diff --git a/include/crm/pengine/status.h b/include/crm/pengine/status.h
index c81566a..b74bf83 100644
--- a/include/crm/pengine/status.h
+++ b/include/crm/pengine/status.h
@@ -93,6 +93,7 @@ typedef struct pe_working_set_s {
     GHashTable *config_hash;
     GHashTable *domains;
     GHashTable *tickets;
+    GHashTable *singletons; /* Actions for which there can be only one - ie. fence nodeX */
 
     GListPtr nodes;
     GListPtr resources;
diff --git a/lib/pengine/status.c b/lib/pengine/status.c
index bb9dfcb..8695dae 100644
--- a/lib/pengine/status.c
+++ b/lib/pengine/status.c
@@ -191,6 +191,10 @@ cleanup_calculations(pe_working_set_t * data_set)
         g_hash_table_destroy(data_set->config_hash);
     }
 
+    if (data_set->singletons != NULL) {
+        g_hash_table_destroy(data_set->singletons);
+    }
+
     if (data_set->tickets) {
         g_hash_table_destroy(data_set->tickets);
     }
diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c
index 410acfc..2520eeb 100644
--- a/lib/pengine/utils.c
+++ b/lib/pengine/utils.c
@@ -362,6 +362,17 @@ custom_action(resource_t * rsc, char *key, const char *task,
 
     if (save_action && rsc != NULL) {
         possible_matches = find_actions(rsc->actions, key, on_node);
+    } else if(save_action) {
+#if 0
+        action = g_hash_table_lookup(data_set->singletons, key);
+#else
+        /* More expensive but takes 'node' into account */
+        possible_matches = find_actions(data_set->actions, key, on_node);
+#endif
+    }
+
+    if(data_set->singletons == NULL) {
+        data_set->singletons = g_hash_table_new_full(crm_str_hash, g_str_equal, NULL, NULL);
     }
 
     if (possible_matches != NULL) {
@@ -424,6 +435,9 @@ custom_action(resource_t * rsc, char *key, const char *task,
 
         if (save_action) {
             data_set->actions = g_list_prepend(data_set->actions, action);
+            if(rsc == NULL) {
+                g_hash_table_insert(data_set->singletons, action->uuid, action);
+            }
         }
 
         if (rsc != NULL) {
@@ -1588,6 +1602,9 @@ order_actions(action_t * lh_action, action_t * rh_action, enum pe_ordering order
 
     crm_trace("Ordering Action %s before %s", lh_action->uuid, rh_action->uuid);
 
+    /* Ensure we never create a dependancy on ourselves... its happened */
+    CRM_ASSERT(lh_action != rh_action);
+
     /* Filter dups, otherwise update_action_states() has too much work to do */
     gIter = lh_action->actions_after;
     for (; gIter != NULL; gIter = gIter->next) {
@@ -1624,20 +1641,12 @@ action_t *
 get_pseudo_op(const char *name, pe_working_set_t * data_set)
 {
     action_t *op = NULL;
-    const char *op_s = name;
-    GListPtr possible_matches = NULL;
 
-    possible_matches = find_actions(data_set->actions, name, NULL);
-    if (possible_matches != NULL) {
-        if (g_list_length(possible_matches) > 1) {
-            pe_warn("Action %s exists %d times", name, g_list_length(possible_matches));
-        }
-
-        op = g_list_nth_data(possible_matches, 0);
-        g_list_free(possible_matches);
-
-    } else {
-        op = custom_action(NULL, strdup(op_s), op_s, NULL, TRUE, TRUE, data_set);
+    if(data_set->singletons) {
+        op = g_hash_table_lookup(data_set->singletons, name);
+    }
+    if (op == NULL) {
+        op = custom_action(NULL, strdup(name), name, NULL, TRUE, TRUE, data_set);
         set_bit(op->flags, pe_action_pseudo);
         set_bit(op->flags, pe_action_runnable);
     }
diff --git a/pengine/allocate.c b/pengine/allocate.c
index a07fdad..b9ce069 100644
--- a/pengine/allocate.c
+++ b/pengine/allocate.c
@@ -1274,6 +1274,10 @@ pe_fence_op(node_t * node, const char *op, pe_working_set_t * data_set)
 
     key = g_strdup_printf("%s-%s-%s", CRM_OP_FENCE, node->details->uname, op);
 
+    if(data_set->singletons) {
+        stonith_op = g_hash_table_lookup(data_set->singletons, key);
+    }
+
     if(stonith_op == NULL) {
         stonith_op = custom_action(NULL, key, CRM_OP_FENCE, node, FALSE, TRUE, data_set);