Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3686791
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/crm/crmd/ccm.c b/crm/crmd/ccm.c
index 5c8fd7aaf9..956ea6d6c0 100644
--- a/crm/crmd/ccm.c
+++ b/crm/crmd/ccm.c
@@ -1,552 +1,555 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* put these first so that uuid_t is defined without conflicts */
#include <portability.h>
#include <ocf/oc_event.h>
#include <ocf/oc_membership.h>
#include <crm/crm.h>
#include <crm/msg_xml.h>
#include <crm/cib.h>
#include <crmd_fsa.h>
#include <fsa_proto.h>
void oc_ev_special(const oc_ev_t *, oc_ev_class_t , int );
#include <clplumbing/GSource.h>
#include <crm/common/ipcutils.h>
#include <crm/common/xmlutils.h>
#include <crmd_messages.h>
#include <string.h>
#include <crm/dmalloc_wrapper.h>
int register_with_ccm(ll_cluster_t *hb_cluster);
void msg_ccm_join(const struct ha_msg *msg, void *foo);
void crmd_ccm_input_callback(oc_ed_t event,
void *cookie,
size_t size,
const void *data);
void ccm_event_detail(const oc_ev_membership_t *oc, oc_ed_t event);
gboolean ccm_dispatch(int fd, gpointer user_data);
gboolean ghash_node_clfree(gpointer key, gpointer value, gpointer user_data);
void ghash_update_cib_node(gpointer key, gpointer value, gpointer user_data);
#define CCM_EVENT_DETAIL 1
oc_ev_t *fsa_ev_token;
/* A_CCM_CONNECT */
enum crmd_fsa_input
do_ccm_control(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
int ret;
/* fd_set rset; */
int fsa_ev_fd;
FNIN();
if(action & A_CCM_DISCONNECT){
oc_ev_unregister(fsa_ev_token);
}
if(action & A_CCM_CONNECT) {
cl_log(LOG_INFO, "Registering with CCM");
oc_ev_register(&fsa_ev_token);
cl_log(LOG_INFO, "Setting up CCM callbacks");
oc_ev_set_callback(fsa_ev_token, OC_EV_MEMB_CLASS,
crmd_ccm_input_callback,
NULL);
oc_ev_special(fsa_ev_token, OC_EV_MEMB_CLASS, 0/*don't care*/);
cl_log(LOG_INFO, "Activating CCM token");
ret = oc_ev_activate(fsa_ev_token, &fsa_ev_fd);
if (ret){
cl_log(LOG_INFO, "CCM Activation failed... unregistering");
oc_ev_unregister(fsa_ev_token);
return(I_FAIL);
}
cl_log(LOG_INFO, "CCM Activation passed... all set to go!");
/* FD_ZERO(&rset); */
/* FD_SET(fsa_ev_fd, &rset); */
//GFDSource*
G_main_add_fd(G_PRIORITY_LOW, fsa_ev_fd, FALSE, ccm_dispatch,
fsa_ev_token,
default_ipc_input_destroy);
}
if(action & ~(A_CCM_CONNECT|A_CCM_DISCONNECT)) {
cl_log(LOG_ERR, "Unexpected action %s in %s",
fsa_action2string(action), __FUNCTION__);
}
FNRET(I_NULL);
}
/* A_CCM_EVENT */
enum crmd_fsa_input
do_ccm_event(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input return_input = I_NULL;
const oc_ev_membership_t *oc = ((struct ccm_data *)data)->oc;
oc_ed_t event = *((struct ccm_data *)data)->event;
FNIN();
cl_log(LOG_INFO,"event=%s",
event==OC_EV_MS_NEW_MEMBERSHIP?"NEW MEMBERSHIP":
event==OC_EV_MS_NOT_PRIMARY?"NOT PRIMARY":
event==OC_EV_MS_PRIMARY_RESTORED?"PRIMARY RESTORED":
event==OC_EV_MS_EVICTED?"EVICTED":
"NO QUORUM MEMBERSHIP");
if(CCM_EVENT_DETAIL) {
ccm_event_detail(oc, event);
}
if (OC_EV_MS_EVICTED == event) {
/* get out... NOW! */
return_input = I_SHUTDOWN;
}
if(return_input == I_SHUTDOWN) {
; /* ignore everything, the new DC will handle it */
} else {
/* My understanding is that we will never get both
* node leaving *and* node joining callbacks at the
* same time.
*
* This logic would need to change if this is not
* the case
*/
if(oc->m_n_out !=0) {
return_input = I_NODE_LEFT;
} else if(oc->m_n_in !=0) {
/* delay the I_NODE_JOIN until they acknowledge our
* DC status and send us their CIB
*/
return_input = I_NULL;
} else {
cl_log(LOG_INFO,
"So why are we here? What CCM event happened?");
}
}
FNRET(return_input);
}
/* A_CCM_UPDATE_CACHE */
/*
* Take the opportunity to update the node status in the CIB as well
* (but only if we are the DC)
*/
enum crmd_fsa_input
do_ccm_update_cache(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
void *data)
{
enum crmd_fsa_input next_input = I_NULL;
int lpc, offset;
GHashTable *members = NULL;
oc_ed_t event = *((struct ccm_data *)data)->event;
const oc_ev_membership_t *oc = ((struct ccm_data *)data)->oc;
oc_node_list_t *tmp = NULL, *membership_copy = (oc_node_list_t *)
crm_malloc(sizeof(oc_node_list_t));
FNIN();
cl_log(LOG_INFO,"Updating CCM cache after a \"%s\" event.",
event==OC_EV_MS_NEW_MEMBERSHIP?"NEW MEMBERSHIP":
event==OC_EV_MS_NOT_PRIMARY?"NOT PRIMARY":
event==OC_EV_MS_PRIMARY_RESTORED?"PRIMARY RESTORED":
event==OC_EV_MS_EVICTED?"EVICTED":
"NO QUORUM MEMBERSHIP");
/*--*-- All Member Nodes --*--*/
offset = oc->m_memb_idx;
membership_copy->members_size = oc->m_n_member;
if(membership_copy->members_size > 0) {
- membership_copy->members = g_hash_table_new(g_str_hash, g_direct_equal);
+ membership_copy->members =
+ g_hash_table_new(g_str_hash, g_str_equal);
members = membership_copy->members;
for(lpc=0; lpc < membership_copy->members_size; lpc++) {
oc_node_t *member = (oc_node_t *)crm_malloc(sizeof(oc_node_t));
member->node_id =
oc->m_array[offset+lpc].node_id;
member->node_born_on =
oc->m_array[offset+lpc].node_born_on;
member->node_uname =
crm_strdup(oc->m_array[offset+lpc].node_uname);
-
+
+ g_hash_table_insert(members, member->node_uname, member);
}
+
} else {
membership_copy->members = NULL;
}
/*--*-- New Member Nodes --*--*/
offset = oc->m_in_idx;
membership_copy->new_members_size = oc->m_n_in;
if(membership_copy->new_members_size > 0) {
- membership_copy->new_members = g_hash_table_new(g_str_hash, g_direct_equal);
+ membership_copy->new_members =
+ g_hash_table_new(g_str_hash, g_str_equal);
members = membership_copy->new_members;
for(lpc=0; lpc < membership_copy->new_members_size; lpc++) {
oc_node_t *member = (oc_node_t *)crm_malloc(sizeof(oc_node_t));
member->node_id =
oc->m_array[offset+lpc].node_id;
member->node_born_on =
oc->m_array[offset+lpc].node_born_on;
member->node_uname =
crm_strdup(oc->m_array[offset+lpc].node_uname);
g_hash_table_insert(members, member->node_uname, member);
-
}
} else {
membership_copy->new_members = NULL;
}
/*--*-- Recently Dead Member Nodes --*--*/
offset = oc->m_out_idx;
membership_copy->dead_members_size = oc->m_n_out;
if(membership_copy->dead_members_size > 0) {
membership_copy->dead_members =
- g_hash_table_new(g_str_hash, g_direct_equal);
+ g_hash_table_new(g_str_hash, g_str_equal);
members = membership_copy->dead_members;
for(lpc=0; lpc < membership_copy->dead_members_size; lpc++) {
oc_node_t *member = (oc_node_t *)crm_malloc(sizeof(oc_node_t));
member->node_id =
oc->m_array[offset+lpc].node_id;
member->node_born_on =
oc->m_array[offset+lpc].node_born_on;
member->node_uname =
crm_strdup(oc->m_array[offset+lpc].node_uname);
g_hash_table_insert(members, member->node_uname, member);
}
} else {
membership_copy->dead_members = NULL;
}
tmp = fsa_membership_copy;
fsa_membership_copy = membership_copy;
if(AM_I_DC) {
// should be sufficient for only the DC to do this
free_xml(do_update_cib_nodes(NULL));
}
/* Free the old copy */
if(tmp != NULL) {
if(tmp->members != NULL)
g_hash_table_foreach_remove (tmp->members, ghash_node_clfree, NULL);
if(tmp->new_members != NULL)
g_hash_table_foreach_remove (tmp->new_members, ghash_node_clfree, NULL);
if(tmp->dead_members != NULL)
g_hash_table_foreach_remove (tmp->dead_members, ghash_node_clfree, NULL);
crm_free(tmp);
}
FNRET(next_input);
}
void
ccm_event_detail(const oc_ev_membership_t *oc, oc_ed_t event)
{
int member_id = -1;
gboolean member = FALSE;
int lpc;
int node_list_size;
cl_log(LOG_INFO,"trans=%d, nodes=%d, new=%d, lost=%d n_idx=%d, "
"new_idx=%d, old_idx=%d",
oc->m_instance,
oc->m_n_member,
oc->m_n_in,
oc->m_n_out,
oc->m_memb_idx,
oc->m_in_idx,
oc->m_out_idx);
cl_log(LOG_INFO, "NODES IN THE PRIMARY MEMBERSHIP");
node_list_size = oc->m_n_member;
for(lpc=0; lpc<node_list_size; lpc++) {
cl_log(LOG_INFO,"\t%s [nodeid=%d, born=%d]",
oc->m_array[oc->m_memb_idx+lpc].node_uname,
oc->m_array[oc->m_memb_idx+lpc].node_id,
oc->m_array[oc->m_memb_idx+lpc].node_born_on);
CRM_DEBUG("%s ? %s", fsa_our_uname,
oc->m_array[oc->m_memb_idx+lpc].node_uname);
if(safe_str_eq(fsa_our_uname,
oc->m_array[oc->m_memb_idx+lpc].node_uname)) {
member = TRUE;
member_id = oc->m_array[oc->m_memb_idx+lpc].node_id;
}
}
if (member == FALSE) {
cl_log(LOG_WARNING,
"MY NODE IS NOT IN CCM THE MEMBERSHIP LIST");
} else {
cl_log(LOG_INFO, "MY NODE ID IS %d", member_id);
}
cl_log(LOG_INFO, "NEW MEMBERS");
if (oc->m_n_in==0)
cl_log(LOG_INFO, "\tNONE");
for(lpc=0; lpc<oc->m_n_in; lpc++) {
cl_log(LOG_INFO,"\t%s [nodeid=%d, born=%d]",
oc->m_array[oc->m_in_idx+lpc].node_uname,
oc->m_array[oc->m_in_idx+lpc].node_id,
oc->m_array[oc->m_in_idx+lpc].node_born_on);
}
cl_log(LOG_INFO, "MEMBERS LOST");
if (oc->m_n_out==0)
cl_log(LOG_INFO, "\tNONE");
for(lpc=0; lpc<oc->m_n_out; lpc++) {
cl_log(LOG_INFO,"\t%s [nodeid=%d, born=%d]",
oc->m_array[oc->m_out_idx+lpc].node_uname,
oc->m_array[oc->m_out_idx+lpc].node_id,
oc->m_array[oc->m_out_idx+lpc].node_born_on);
if(fsa_our_uname != NULL
&& strcmp(fsa_our_uname, oc->m_array[oc->m_memb_idx+lpc].node_uname)) {
cl_log(LOG_ERR,
"We're not part of the cluster anymore");
}
}
cl_log(LOG_INFO, "-----------------------");
}
int
register_with_ccm(ll_cluster_t *hb_cluster)
{
FNRET(0);
}
gboolean ccm_dispatch(int fd, gpointer user_data)
{
oc_ev_t *ccm_token = (oc_ev_t*)user_data;
oc_ev_handle_event(ccm_token);
return TRUE;
}
void
crmd_ccm_input_callback(oc_ed_t event,
void *cookie,
size_t size,
const void *data)
{
struct ccm_data *event_data = NULL;
FNIN();
if(data != NULL) {
event_data = (struct ccm_data *)
crm_malloc(sizeof(struct ccm_data));
event_data->event = &event;
event_data->oc = (const oc_ev_membership_t *)data;
s_crmd_fsa(C_CCM_CALLBACK, I_CCM_EVENT, (void*)event_data);
event_data->event = NULL;
event_data->oc = NULL;
crm_free(event_data);
} else {
cl_log(LOG_INFO, "CCM Callback with NULL data... "
"I dont /think/ this is bad");
}
oc_ev_callback_done(cookie);
FNOUT();
}
void
msg_ccm_join(const struct ha_msg *msg, void *foo)
{
FNIN();
cl_log(LOG_INFO, "\n###### Recieved ccm_join message...");
if (msg != NULL)
{
cl_log(LOG_INFO,
"[type=%s]",
ha_msg_value(msg, F_TYPE));
cl_log(LOG_INFO,
"[orig=%s]",
ha_msg_value(msg, F_ORIG));
cl_log(LOG_INFO,
"[to=%s]",
ha_msg_value(msg, F_TO));
cl_log(LOG_INFO,
"[status=%s]",
ha_msg_value(msg, F_STATUS));
cl_log(LOG_INFO,
"[info=%s]",
ha_msg_value(msg, F_COMMENT));
cl_log(LOG_INFO,
"[rsc_hold=%s]",
ha_msg_value(msg, F_RESOURCES));
cl_log(LOG_INFO,
"[stable=%s]",
ha_msg_value(msg, F_ISSTABLE));
cl_log(LOG_INFO,
"[rtype=%s]",
ha_msg_value(msg, F_RTYPE));
cl_log(LOG_INFO,
"[ts=%s]",
ha_msg_value(msg, F_TIME));
cl_log(LOG_INFO,
"[seq=%s]",
ha_msg_value(msg, F_SEQ));
cl_log(LOG_INFO,
"[generation=%s]",
ha_msg_value(msg, F_HBGENERATION));
// cl_log(LOG_INFO, "[=%s]", ha_msg_value(msg, F_));
}
FNOUT();
}
struct update_data_s
{
xmlNodePtr updates;
const char *state;
};
xmlNodePtr
do_update_cib_nodes(xmlNodePtr updates)
{
struct update_data_s update_data;
update_data.updates = updates;
CRM_DEBUG("Processing the \"down\" list");
update_data.state = "down";
if(fsa_membership_copy->dead_members != NULL) {
g_hash_table_foreach(fsa_membership_copy->dead_members,
ghash_update_cib_node, &update_data);
}
CRM_DEBUG("Processing the \"in_ccm (old)\" list");
update_data.state = "in_ccm";
if(fsa_membership_copy->members != NULL) {
g_hash_table_foreach(fsa_membership_copy->members,
ghash_update_cib_node, &update_data);
}
-
+/*
CRM_DEBUG("Processing the \"in_ccm (new)\" list");
if(fsa_membership_copy->new_members != NULL) {
g_hash_table_foreach(fsa_membership_copy->new_members,
ghash_update_cib_node, &update_data);
}
-
+*/
if(update_data.updates != NULL) {
xmlNodePtr fragment = create_cib_fragment(update_data.updates, NULL);
send_request(NULL, fragment, CRM_OPERATION_UPDATE,
NULL, CRM_SYSTEM_DCIB, NULL);
free_xml(fragment);
}
return update_data.updates;
}
void
ghash_update_cib_node(gpointer key, gpointer value, gpointer user_data)
{
xmlNodePtr tmp1 = NULL;
const char *node_uname = (const char*)key;
struct update_data_s* data = (struct update_data_s*)user_data;
CRM_DEBUG("%s processing %s (%s)", __FUNCTION__, node_uname, data->state);
if(safe_str_eq(fsa_our_uname, node_uname)) {
// dont change ourselves
return;
}
tmp1 = create_node_state(node_uname, data->state, NULL, NULL);
if(data->updates == NULL) {
data->updates = tmp1;
} else {
data->updates = xmlAddSibling(data->updates, tmp1);
}
}
gboolean
ghash_node_clfree(gpointer key, gpointer value, gpointer user_data)
{
// value->node_uname is free'd as "key"
if(key != NULL) {
crm_free(key);
}
if(value != NULL) {
crm_free(value);
}
return TRUE;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Apr 21, 6:02 PM (1 d, 4 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1665022
Default Alt Text
(14 KB)
Attached To
Mode
rP Pacemaker
Attached
Detach File
Event Timeline
Log In to Comment