static int farm_snapshot(const struct siocb *iocb) { unsigned char snap_sha1[SHA1_LEN]; unsigned char trunk_sha1[SHA1_LEN]; struct sd_node nodes[SD_MAX_NODES]; int nr_nodes; void *buffer; int log_nr, ret = SD_RES_EIO, epoch; buffer = snap_log_read(&log_nr); if (!buffer) goto out; epoch = log_nr + 1; sd_dprintf("user epoch %d", epoch); nr_nodes = epoch_log_read(sys->epoch, nodes, sizeof(nodes)); if (nr_nodes < 0) goto out; if (trunk_file_write(trunk_sha1) < 0) goto out; if (snap_file_write(sys->epoch, nodes, nr_nodes, trunk_sha1, snap_sha1) < 0) goto out; if (snap_log_write(epoch, snap_sha1) < 0) goto out; ret = SD_RES_SUCCESS; out: free(buffer); return ret; }
int snap_file_write(uint32_t epoch, unsigned char *trunksha1, unsigned char *outsha1, int user) { int ret = 0; struct strbuf buf = STRBUF_INIT; struct sd_node nodes[SD_MAX_NODES]; int tgt_epoch = user ? sys_epoch() : epoch; uint64_t epoch_size; struct sha1_file_hdr hdr; epoch_size = epoch_log_read(tgt_epoch, (char *)nodes, sizeof(nodes)); if (epoch_size == -1) return -1; memcpy(hdr.tag, TAG_SNAP, TAG_LEN); hdr.size = epoch_size + SHA1_LEN; hdr.priv = tgt_epoch; hdr.reserved = 0; strbuf_add(&buf, &hdr, sizeof(hdr)); strbuf_add(&buf, trunksha1, SHA1_LEN); strbuf_add(&buf, (char *)nodes, epoch_size); if (sha1_file_write((void *)buf.buf, buf.len, outsha1) < 0) { ret = -1; goto err; } dprintf("epoch %u, sha1: %s\n", epoch, sha1_to_hex(outsha1)); err: strbuf_release(&buf); return ret; }
static int get_nodes_nr_epoch(uint32_t epoch) { struct sd_node nodes[SD_MAX_NODES]; int nr; nr = epoch_log_read(epoch, (char *)nodes, sizeof(nodes)); nr /= sizeof(nodes[0]); return nr; }
struct vnode_info *get_vnode_info_epoch(uint32_t epoch) { struct sd_node nodes[SD_MAX_NODES]; int nr_nodes; nr_nodes = epoch_log_read(epoch, nodes, sizeof(nodes)); if (nr_nodes < 0) { nr_nodes = epoch_log_read_remote(epoch, nodes, sizeof(nodes)); if (nr_nodes == 0) return NULL; } return alloc_vnode_info(nodes, nr_nodes); }
static struct sd_node *find_entry_epoch(struct sd_node *entry, uint32_t epoch) { struct sd_node nodes[SD_MAX_NODES]; int nr, i; if (!epoch) return NULL; nr = epoch_log_read(epoch, nodes, sizeof(nodes)); for (i = 0; i < nr; i++) if (node_eq(&nodes[i], entry)) return entry; return NULL; }
static int cluster_wait_for_join_check(struct sd_node *joined, struct join_message *jm) { struct sd_node local_entries[SD_MAX_NODES]; int nr, nr_local_entries, nr_failed_entries, nr_delayed_nodes; uint32_t local_epoch = get_latest_epoch(); int ret; if (jm->nr_nodes == 0) return CJ_RES_JOIN_LATER; ret = cluster_sanity_check(jm); if (ret != CJ_RES_SUCCESS) { if (jm->epoch > sys->epoch) { eprintf("transfer mastership (%d, %d)\n", jm->epoch, sys->epoch); return CJ_RES_MASTER_TRANSFER; } return ret; } nr_local_entries = epoch_log_read(jm->epoch, local_entries, sizeof(local_entries)); if (nr_local_entries == -1) return CJ_RES_FAIL; if (jm->epoch < local_epoch) { eprintf("joining node epoch too small: %" PRIu32 " vs %" PRIu32 "\n", jm->epoch, local_epoch); return CJ_RES_JOIN_LATER; } if (jm->nr_nodes != nr_local_entries) { eprintf("epoch log entries do not match: %d vs %d\n", jm->nr_nodes, nr_local_entries); return CJ_RES_FAIL; } if (memcmp(jm->nodes, local_entries, sizeof(jm->nodes[0]) * jm->nr_nodes) != 0) { eprintf("epoch log entries does not match\n"); return CJ_RES_FAIL; } if (!current_vnode_info) nr = 1; else nr = current_vnode_info->nr_nodes + 1; nr_delayed_nodes = get_nodes_nr_from(&sys->delayed_nodes); /* * If we have all members from the last epoch log in the in-memory * node list, and no new nodes joining we can set the cluster live * now without incrementing the epoch. */ if (nr == nr_local_entries && !nr_delayed_nodes) { jm->cluster_status = SD_STATUS_OK; return CJ_RES_SUCCESS; } /* * If we reach the old node count, but some node failed we have to * update the epoch before setting the cluster live. */ nr_failed_entries = get_nodes_nr_from(&sys->failed_nodes); if (nr_local_entries == nr + nr_failed_entries - nr_delayed_nodes) { jm->inc_epoch = 1; jm->cluster_status = SD_STATUS_OK; return CJ_RES_SUCCESS; } /* * The join was successful, but we don't have enough nodes yet to set * the cluster live. */ return CJ_RES_SUCCESS; }
static int get_nodes_nr_epoch(uint32_t epoch) { struct sd_node nodes[SD_MAX_NODES]; return epoch_log_read(epoch, nodes, sizeof(nodes)); }