/* 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; }
/* 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; }