예제 #1
0
파일: quorumd.c 프로젝트: dhazen/heartbeat
gboolean
query_quorum(gpointer data)
{
	int quorum;
	size_t	len;
	char* s = NULL;
	char buf[MAXMSG];
	struct ha_msg* msg = NULL;
	struct ha_msg* ret = NULL;

	if(session != NULL) {
		msg = ha_msg_new(10);
		ha_msg_add(msg, "t","quorum");
		ha_msg_add_int(msg, "nodenum", nodenum);
		ha_msg_add_int(msg, "weight", weight);
	
		s  = msg2wirefmt(msg, &len);
		gnutls_record_send(session, s, len);
		free(s);
		len = gnutls_record_recv(session, buf, MAXMSG);
		if ((ssize_t)len < 0) {
			gnutls_bye (session, GNUTLS_SHUT_WR);
			gnutls_deinit (session);
			close(sock);
			session = NULL;
			cur_quorum = -1;
			ha_msg_del(msg);
			return TRUE;
		}
		ret = wirefmt2msg(buf, len, FALSE);
		ha_msg_value_int(ret, "quorum", &quorum);
			
		ha_msg_del(ret);
		ha_msg_del(msg);
		
		if (cur_quorum!=-1 && cur_quorum!=quorum && callback!=NULL){
			cur_quorum = quorum;
			callback();
		}
		cur_quorum = quorum;
	}
	else {
		connect_quorum_server(NULL);
	}
	return TRUE;
}
예제 #2
0
static gboolean
send_rexmit_request( gpointer data)
{
	struct rexmit_info* ri = (struct rexmit_info*) data;
	seqno_t seq = (seqno_t) ri->seq;
	struct node_info* node = ri->node;
	struct ha_msg*	hmsg;
	
	if ((hmsg = ha_msg_new(6)) == NULL) {
		cl_log(LOG_ERR, "%s: no memory for " T_REXMIT, 
		       __FUNCTION__);
		return FALSE;
	}
	
	
	if (ha_msg_add(hmsg, F_TYPE, T_REXMIT) != HA_OK
	    ||	ha_msg_add(hmsg, F_TO, node->nodename) !=HA_OK
	    ||	ha_msg_add_int(hmsg, F_FIRSTSEQ, seq) != HA_OK
	    ||	ha_msg_add_int(hmsg, F_LASTSEQ, seq) != HA_OK) {
		cl_log(LOG_ERR, "%s: adding fields to msg failed",
		       __FUNCTION__);
		ha_msg_del(hmsg);
		return FALSE;
	}
	
	if (send_cluster_msg(hmsg) != HA_OK) {
		cl_log(LOG_ERR, "%s: cannot send " T_REXMIT
		       " request to %s",__FUNCTION__,  node->nodename);
		ha_msg_del(hmsg);
		return FALSE;
	}
	
	node->track.last_rexmit_req = time_longclock();	
	
	if (!g_hash_table_remove(rexmit_hash_table, ri)){
		cl_log(LOG_ERR, "%s: entry not found in rexmit_hash_table"
		       "for seq/node(%ld %s)", 		       
		       __FUNCTION__, ri->seq, ri->node->nodename);
		return FALSE;
	}
	
	schedule_rexmit_request(node, seq, max_rexmit_delay);
	
	return FALSE;
}
예제 #3
0
static void
struct_memfree( void* value)
{
	struct ha_msg* msg;

	if (!value){
		cl_log(LOG_ERR,
		       "value is NULL");
		return ;
	}
	
	msg = (struct ha_msg*) value;
	ha_msg_del(msg);
	return ;
}
예제 #4
0
static HA_Message *
convert_xml_message_struct(HA_Message * parent, xmlNode * src_node, const char *field)
{
    xmlNode *child = NULL;
    xmlNode *__crm_xml_iter = src_node->children;
    xmlAttrPtr prop_iter = src_node->properties;
    const char *name = NULL;
    const char *value = NULL;

    HA_Message *result = ha_msg_new(3);

    ha_msg_add(result, F_XML_TAGNAME, (const char *)src_node->name);

    while (prop_iter != NULL) {
        name = (const char *)prop_iter->name;
        value = (const char *)xmlGetProp(src_node, prop_iter->name);
        prop_iter = prop_iter->next;
        ha_msg_add(result, name, value);
    }

    while (__crm_xml_iter != NULL) {
        child = __crm_xml_iter;
        __crm_xml_iter = __crm_xml_iter->next;
        convert_xml_message_struct(result, child, NULL);
    }

    if (parent == NULL) {
        return result;
    }

    if (field) {
        HA_Message *holder = ha_msg_new(3);

        CRM_ASSERT(holder != NULL);

        ha_msg_add(holder, F_XML_TAGNAME, field);
        add_ha_nocopy(holder, result, (const char *)src_node->name);

        ha_msg_addstruct_compress(parent, field, holder);
        ha_msg_del(holder);

    } else {
        add_ha_nocopy(parent, result, (const char *)src_node->name);
    }
    return result;
}
예제 #5
0
파일: dopd.c 프로젝트: sipwise/heartbeat
/* send_message_to_the_peer()
 * send message with drbd resource to other node.
 */
static gboolean
send_message_to_the_peer(const char *drbd_peer, const char *drbd_resource)
{
	HA_Message *msg = NULL;

	cl_log(LOG_INFO, "sending start_outdate message to the other node %s -> %s",
		  node_name, drbd_peer);

	msg = ha_msg_new(3);
	ha_msg_add(msg, F_TYPE, "start_outdate");
	ha_msg_add(msg, F_ORIG, node_name);
	ha_msg_add(msg, F_DOPD_RES, drbd_resource);

	cl_log(LOG_DEBUG, "sending [start_outdate res: %s] to node: %s",
		  drbd_resource, drbd_peer);
	dopd_cluster_conn->llc_ops->sendnodemsg(dopd_cluster_conn, msg, drbd_peer);
	ha_msg_del(msg);

	return TRUE;
}
예제 #6
0
static int
compress2uncompress(struct ha_msg* msg, int index)
{
	char		*buf = NULL;
	size_t		buflen = MAXUNCOMPRESSED;	
	struct ha_msg*  msgfield;
	int 		err = HA_FAIL;

	buf = cl_malloc(buflen);
	
	if (!buf) {
		cl_log(LOG_ERR, "%s: allocating buffer for uncompression failed",
		       __FUNCTION__);
		goto out;
	}

	if (cl_decompress_field(msg, index, buf, &buflen) != HA_OK){
		cl_log(LOG_ERR, "%s: compress field failed",
		       __FUNCTION__);
		goto out;
	}
	
	msgfield = wirefmt2msg(buf, buflen, 0);
	if (msgfield == NULL){
		cl_log(LOG_ERR, "%s: wirefmt to msg failed",
		       __FUNCTION__);
		goto out;
	}
	
	err = cl_msg_replace(msg, index, (char*)msgfield, 0, FT_UNCOMPRESS);

	ha_msg_del(msgfield);

out:
	if (buf) {
		cl_free(buf);
	}

	return err;
}
예제 #7
0
파일: quorumd.c 프로젝트: dhazen/heartbeat
gboolean
connect_quorum_server(gpointer data)
{
	struct sockaddr_in addr;
	struct ha_msg* msg = NULL;
	struct ha_msg* ret = NULL;
	const char* version = "2_0_8";
	struct hostent* hp;
	int quorum;
	size_t	len;
	char* s = NULL;
	char buf[MAXMSG];
	
	cl_log(LOG_DEBUG, "quorum plugin: quorumd, connect_quorum_server");
	/* initialize gnutls */
	initialize_tls_global();

	/* create socket */
	sock=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock == -1 ) {
		return FALSE;
	}

	/* connect to server*/
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	hp = gethostbyname(quorum_server);
	if (hp == NULL) {
		return FALSE;
	}
	memcpy(&addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
	addr.sin_port = htons(5561);
	if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
		return FALSE;
	}
	session = initialize_tls_session(sock);
	if (session == NULL) {
		close(sock);
		session = NULL;
		return FALSE;
	}
	/* send the version */
	gnutls_record_send(session, version, strlen(version)+1);

	/* send initialize msg */
	msg = ha_msg_new(10);
	ha_msg_add(msg, "t","init");
	ha_msg_add(msg, "cl_name", cluster);

	s  = msg2wirefmt(msg, &len);
	gnutls_record_send(session, s, len);
	free(s);
	len = gnutls_record_recv(session, buf, MAXMSG);
	if ((ssize_t)len <=0) {
		close(sock);
		session = NULL;
		return FALSE;
	}
	ret = wirefmt2msg(buf, len, FALSE);
	if (STRNCMP_CONST(ha_msg_value(ret, "result"), "ok") != 0) {
		close(sock);
		session = NULL;
		return FALSE;
	}
	if (ha_msg_value_int(ret, "interval", &interval)!= HA_OK) {
		close(sock);
		session = NULL;
		return FALSE;
	}
	ha_msg_del(ret);
	ha_msg_del(msg);

	/* send quorum query msg */
	msg = ha_msg_new(10);
	ha_msg_add(msg, "t","quorum");
	ha_msg_add_int(msg, "nodenum", nodenum);
	ha_msg_add_int(msg, "weight", weight);

	s  = msg2wirefmt(msg, &len);
	gnutls_record_send(session, s, len);
	free(s);
	len = gnutls_record_recv(session, buf, MAXMSG);
	ret = wirefmt2msg(buf, len, FALSE);
	ha_msg_value_int(ret, "quorum", &quorum);
	LOG(LOG_DEBUG,"quorum:%d\n", quorum);
	cur_quorum = quorum;
	
	ha_msg_del(ret);
	ha_msg_del(msg);

	/* set the repeatly query */
	repeat_timer = g_timeout_add(interval, query_quorum, NULL);
	return FALSE;
}
예제 #8
0
enum cib_errors 
cib_process_diff(
	const char *op, int options, const char *section, crm_data_t *input,
	crm_data_t *existing_cib, crm_data_t **result_cib, crm_data_t **answer)
{
	unsigned int log_level = LOG_DEBUG;
	const char *value = NULL;
	const char *reason = NULL;
	gboolean apply_diff = TRUE;
	gboolean do_resync = FALSE;
	enum cib_errors result = cib_ok;

	int this_updates = 0;
	int this_epoch  = 0;
	int this_admin_epoch = 0;

	int diff_add_updates = 0;
	int diff_add_epoch  = 0;
	int diff_add_admin_epoch = 0;

	int diff_del_updates = 0;
	int diff_del_epoch  = 0;
	int diff_del_admin_epoch = 0;

	crm_debug_2("Processing \"%s\" event", op);

	if(cib_is_master) {
		/* the master is never waiting for a resync */
		sync_in_progress = 0;
	}
	
	cib_diff_version_details(
		input,
		&diff_add_admin_epoch, &diff_add_epoch, &diff_add_updates, 
		&diff_del_admin_epoch, &diff_del_epoch, &diff_del_updates);

	if(sync_in_progress > MAX_DIFF_RETRY) {
		/* request another full-sync,
		 * the last request may have been lost
		 */
		sync_in_progress = 0;
	} 
	if(sync_in_progress) {
		sync_in_progress++;
		crm_warn("Not applying diff %d.%d.%d -> %d.%d.%d (sync in progress)",
			diff_del_admin_epoch,diff_del_epoch,diff_del_updates,
			diff_add_admin_epoch,diff_add_epoch,diff_add_updates);
		return cib_diff_resync;
	}
	
	value = crm_element_value(existing_cib, XML_ATTR_GENERATION);
	this_epoch = atoi(value?value:"0");
	
	value = crm_element_value(existing_cib, XML_ATTR_NUMUPDATES);
	this_updates = atoi(value?value:"0");
	
	value = crm_element_value(existing_cib, XML_ATTR_GENERATION_ADMIN);
	this_admin_epoch = atoi(value?value:"0");
	
	if(diff_del_admin_epoch == diff_add_admin_epoch
	   && diff_del_epoch == diff_add_epoch
	   && diff_del_updates == diff_add_updates) {
		if(diff_add_admin_epoch == -1 && diff_add_epoch == -1 && diff_add_updates == -1) {
			diff_add_epoch = this_epoch;
			diff_add_updates = this_updates + 1;
			diff_add_admin_epoch = this_admin_epoch;
			diff_del_epoch = this_epoch;
			diff_del_updates = this_updates;
			diff_del_admin_epoch = this_admin_epoch;
		} else {
			apply_diff = FALSE;
			log_level = LOG_ERR;
			reason = "+ and - versions in the diff did not change";
			log_cib_diff(LOG_ERR, input, __FUNCTION__);
		}
	}

	if(apply_diff && diff_del_admin_epoch > this_admin_epoch) {
		do_resync = TRUE;
		apply_diff = FALSE;
		log_level = LOG_INFO;
		reason = "current \""XML_ATTR_GENERATION_ADMIN"\" is less than required";
		
	} else if(apply_diff && diff_del_admin_epoch < this_admin_epoch) {
		apply_diff = FALSE;
		log_level = LOG_WARNING;
		reason = "current \""XML_ATTR_GENERATION_ADMIN"\" is greater than required";
	}

	if(apply_diff && diff_del_epoch > this_epoch) {
		do_resync = TRUE;
		apply_diff = FALSE;
		log_level = LOG_INFO;
		reason = "current \""XML_ATTR_GENERATION"\" is less than required";
		
	} else if(apply_diff && diff_del_epoch < this_epoch) {
		apply_diff = FALSE;
		log_level = LOG_WARNING;
		reason = "current \""XML_ATTR_GENERATION"\" is greater than required";
	}

	if(apply_diff && diff_del_updates > this_updates) {
		do_resync = TRUE;
		apply_diff = FALSE;
		log_level = LOG_INFO;
		reason = "current \""XML_ATTR_NUMUPDATES"\" is less than required";
		
	} else if(apply_diff && diff_del_updates < this_updates) {
		apply_diff = FALSE;
		log_level = LOG_WARNING;
		reason = "current \""XML_ATTR_NUMUPDATES"\" is greater than required";
	}

	if(apply_diff) {
		free_xml(*result_cib);
		*result_cib = NULL;
		if(apply_xml_diff(existing_cib, input, result_cib) == FALSE) {
			log_level = LOG_WARNING;
			reason = "Failed application of an update diff";

			if(options & cib_force_diff) {
			    if(cib_is_master == FALSE) {
				log_level = LOG_INFO;
				reason = "Failed application of a global update."
					 "  Requesting full refresh.";
				do_resync = TRUE;

			    } else {
				reason = "Failed application of a global update."
					 "  Not requesting full refresh.";
			    }
			}
			
		} else if((options & cib_force_diff) && !validate_with_dtd(
			      *result_cib, FALSE, HA_NOARCHDATAHBDIR"/crm.dtd")) {

		    if(cib_is_master == FALSE) {
			log_level = LOG_INFO;
			reason = "Failed DTD validation of a global update."
				 "  Requesting full refresh.";
			do_resync = TRUE;
		    } else {
			log_level = LOG_WARNING;
			reason = "Failed DTD validation of a global update."
				 "  Not requesting full refresh.";
		    }
		}
	}
	
	if(reason != NULL) {
		do_crm_log(
			log_level,
			"Diff %d.%d.%d -> %d.%d.%d not applied to %d.%d.%d: %s",
			diff_del_admin_epoch,diff_del_epoch,diff_del_updates,
			diff_add_admin_epoch,diff_add_epoch,diff_add_updates,
			this_admin_epoch,this_epoch,this_updates, reason);
		
		result = cib_diff_failed;

	} else if(apply_diff) {
		crm_debug_2("Diff %d.%d.%d -> %d.%d.%d was applied",
			    diff_del_admin_epoch,diff_del_epoch,diff_del_updates,
			    diff_add_admin_epoch,diff_add_epoch,diff_add_updates);
	}

	if(do_resync && cib_is_master == FALSE) {
		HA_Message *sync_me = ha_msg_new(3);
		free_xml(*result_cib);
		*result_cib = NULL;
		result = cib_diff_resync;
		crm_info("Requesting re-sync from peer: %s", reason);
		sync_in_progress++;
		
		ha_msg_add(sync_me, F_TYPE, "cib");
		ha_msg_add(sync_me, F_CIB_OPERATION, CIB_OP_SYNC_ONE);
		ha_msg_add(sync_me, F_CIB_DELEGATED, cib_our_uname);

		if(send_ha_message(hb_conn, sync_me, NULL, FALSE) == FALSE) {
			result = cib_not_connected;
		}
		ha_msg_del(sync_me);
		
	} else if(do_resync) {
		crm_err("Not resyncing in master mode");
	}
	
	
	return result;
}