Example #1
0
/* Returns true if an event is processed */
static bool local_process_event(void)
{
	struct local_event *ev;
	enum cluster_join_result res;
	int i;
	struct sd_node nodes[SD_MAX_NODES];
	size_t nr_nodes;

	ev = shm_queue_peek();
	if (!ev)
		return false;

	sd_dprintf("type = %d, sender = %s", ev->type,
		   lnode_to_str(&ev->sender));
	sd_dprintf("callbacked = %d, removed = %d", ev->callbacked,
		   ev->removed);

	nr_nodes = 0;
	for (i = 0; i < ev->nr_lnodes; i++) {
		sd_dprintf("%d: %s", i, lnode_to_str(ev->lnodes + i));
		if (!ev->lnodes[i].gateway)
			nodes[nr_nodes++] = ev->lnodes[i].node;
	}

	if (ev->removed)
		goto out;

	if (ev->callbacked)
		return false; /* wait for unblock event */

	if (ev->type == EVENT_JOIN_RESPONSE &&
	    lnode_eq(&this_node, &ev->sender)) {
		sd_dprintf("join Sheepdog");
		joined = true;
	}

	if (!joined) {
		if (ev->type == EVENT_JOIN_REQUEST &&
		    lnode_eq(&this_node, &ev->sender)) {
			struct local_node lnodes[SD_MAX_NODES];

			get_nodes(lnodes);

			if (!lnode_eq(&this_node, &lnodes[0])) {
				sd_dprintf("wait for another node"
					   " to accept this node");
				return false;
			}
		} else
			goto out;
	}

	switch (ev->type) {
	case EVENT_JOIN_REQUEST:
		res = sd_check_join_cb(&ev->sender.node, ev->buf);
		ev->join_result = res;
		ev->type = EVENT_JOIN_RESPONSE;
		msync(ev, sizeof(*ev), MS_SYNC);

		shm_queue_notify();

		if (res == CJ_RES_MASTER_TRANSFER) {
			sd_eprintf("failed to join sheepdog cluster: "
				   "please retry when master is up");
			shm_queue_unlock();
			exit(1);
		}
		return false;
	case EVENT_JOIN_RESPONSE:
		if (ev->join_result == CJ_RES_MASTER_TRANSFER) {
			/* FIXME: This code is tricky, but Sheepdog assumes that */
			/* nr_nodes = 1 when join_result = MASTER_TRANSFER... */
			ev->nr_lnodes = 1;
			ev->lnodes[0] = this_node;
			nr_nodes = 1;
			nodes[0] = this_node.node;
			msync(ev, sizeof(*ev), MS_SYNC);
		}

		sd_join_handler(&ev->sender.node, nodes, nr_nodes,
				ev->join_result, ev->buf);
		break;
	case EVENT_LEAVE:
	case EVENT_GATEWAY:
		sd_leave_handler(&ev->sender.node, nodes, nr_nodes);
		break;
	case EVENT_BLOCK:
		ev->callbacked = sd_block_handler(&ev->sender.node);
		msync(ev, sizeof(*ev), MS_SYNC);
		return false;
	case EVENT_NOTIFY:
		sd_notify_handler(&ev->sender.node, ev->buf, ev->buf_len);
		break;
	}
out:
	shm_queue_remove(ev);

	return true;
}
Example #2
0
/* Returns true if an event is processed */
static bool local_process_event(void)
{
	struct local_event *ev;
	int i;
	struct sd_node nodes[SD_MAX_NODES];
	size_t nr_nodes;

	ev = shm_queue_peek();
	if (!ev)
		return false;

	sd_debug("type = %d, sender = %s", ev->type, lnode_to_str(&ev->sender));
	sd_debug("callbacked = %d, removed = %d", ev->callbacked, ev->removed);

	nr_nodes = 0;
	for (i = 0; i < ev->nr_lnodes; i++) {
		sd_debug("%d: %s", i, lnode_to_str(ev->lnodes + i));
		if (!ev->lnodes[i].gateway)
			nodes[nr_nodes++] = ev->lnodes[i].node;
	}

	if (ev->removed)
		goto out;

	if (ev->callbacked)
		return false; /* wait for unblock event */

	if (!joined) {
		if (!lnode_eq(&this_node, &ev->sender))
			goto out;

		switch (ev->type) {
		case EVENT_JOIN:
			break;
		case EVENT_ACCEPT:
			sd_debug("join Sheepdog");
			joined = true;
			break;
		default:
			goto out;
		}
	}

	switch (ev->type) {
	case EVENT_JOIN:
		/* nodes[nr_nodes - 1] is a sender, so don't include it */
		assert(node_eq(&ev->sender.node, &nodes[nr_nodes - 1]));
		if (sd_join_handler(&ev->sender.node, nodes, nr_nodes - 1,
				      ev->buf)) {
			ev->type = EVENT_ACCEPT;
			msync(ev, sizeof(*ev), MS_SYNC);

			shm_queue_notify();
		}

		return false;
	case EVENT_ACCEPT:
		sd_accept_handler(&ev->sender.node, nodes, nr_nodes, ev->buf);
		break;
	case EVENT_LEAVE:
		if (ev->sender.gateway) {
			sd_debug("gateway %s left sheepdog",
				 lnode_to_str(&ev->sender));
			break;
		}
		/* fall through */
	case EVENT_GATEWAY:
		sd_leave_handler(&ev->sender.node, nodes, nr_nodes);
		break;
	case EVENT_BLOCK:
		ev->callbacked = sd_block_handler(&ev->sender.node);
		msync(ev, sizeof(*ev), MS_SYNC);
		return false;
	case EVENT_NOTIFY:
		sd_notify_handler(&ev->sender.node, ev->buf, ev->buf_len);
		break;
	case EVENT_UPDATE_NODE:
		if (lnode_eq(&ev->sender, &this_node))
			this_node = ev->sender;

		sd_update_node_handler(&ev->sender.node);
		break;
	}
out:
	shm_queue_remove(ev);

	return true;
}