static void add_event(enum local_event_type type, struct local_node *lnode, void *buf, size_t buf_len) { int idx, i; struct local_node *n; struct local_event ev = { .type = type, .sender = *lnode, }; ev.buf_len = buf_len; if (buf) memcpy(ev.buf, buf, buf_len); ev.nr_lnodes = get_nodes(ev.lnodes); switch (type) { case EVENT_JOIN_REQUEST: ev.lnodes[ev.nr_lnodes] = *lnode; ev.nr_lnodes++; break; case EVENT_LEAVE: n = find_lnode(lnode, ev.nr_lnodes, ev.lnodes); idx = n - ev.lnodes; ev.nr_lnodes--; memmove(n, n + 1, sizeof(*n) * (ev.nr_lnodes - idx)); break; case EVENT_GATEWAY: n = find_lnode(lnode, ev.nr_lnodes, ev.lnodes); n->gateway = true; break; case EVENT_NOTIFY: case EVENT_BLOCK: break; case EVENT_UPDATE_NODE: n = find_lnode(lnode, ev.nr_lnodes, ev.lnodes); n->node = lnode->node; break; case EVENT_JOIN_RESPONSE: abort(); } sd_dprintf("type = %d, sender = %s", ev.type, lnode_to_str(&ev.sender)); for (i = 0; i < ev.nr_lnodes; i++) sd_dprintf("%d: %s", i, lnode_to_str(ev.lnodes + i)); shm_queue_push(&ev); shm_queue_notify(); }
static int add_event(enum local_event_type type, struct local_node *lnode, void *buf, size_t buf_len) { struct local_node *n; struct local_event ev = { .type = type, .sender = *lnode, }; ev.buf_len = buf_len; if (buf) memcpy(ev.buf, buf, buf_len); ev.nr_lnodes = get_nodes(ev.lnodes); switch (type) { case EVENT_JOIN: ev.lnodes[ev.nr_lnodes] = *lnode; ev.nr_lnodes++; break; case EVENT_LEAVE: xlremove(lnode, ev.lnodes, &ev.nr_lnodes, lnode_cmp); break; case EVENT_GATEWAY: n = xlfind(lnode, ev.lnodes, ev.nr_lnodes, lnode_cmp); n->gateway = true; break; case EVENT_NOTIFY: case EVENT_BLOCK: break; case EVENT_UPDATE_NODE: n = xlfind(lnode, ev.lnodes, ev.nr_lnodes, lnode_cmp); n->node = lnode->node; break; case EVENT_ACCEPT: abort(); } sd_debug("type = %d, sender = %s", ev.type, lnode_to_str(&ev.sender)); for (int i = 0; i < ev.nr_lnodes; i++) sd_debug("%d: %s", i, lnode_to_str(ev.lnodes + i)); shm_queue_push(&ev); shm_queue_notify(); return SD_RES_SUCCESS; }
static void shm_queue_notify(void) { int i; size_t nr; struct local_node lnodes[SD_MAX_NODES]; nr = get_nodes(lnodes); for (i = 0; i < nr; i++) { sd_dprintf("send signal to %s", lnode_to_str(lnodes + i)); kill(lnodes[i].pid, SIGUSR1); } }
/* 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; }