/* * pmempool_sync -- synchronize replicas within a poolset */ int pmempool_sync(const char *poolset, unsigned flags) { LOG(3, "poolset %s, flags %u", poolset, flags); ASSERTne(poolset, NULL); /* check if poolset has correct signature */ if (util_is_poolset_file(poolset) != 1) { ERR("file is not a poolset file"); goto err; } /* check if flags are supported */ if (check_flags_sync(flags)) { ERR("unsupported flags"); errno = EINVAL; goto err; } /* open poolset file */ int fd = util_file_open(poolset, NULL, 0, O_RDONLY); if (fd < 0) { ERR("cannot open a poolset file"); goto err; } /* fill up pool_set structure */ struct pool_set *set = NULL; if (util_poolset_parse(&set, poolset, fd)) { ERR("parsing input poolset failed"); goto err_close_file; } if (set->remote) { if (util_remote_load()) { ERR("remote replication not available"); goto err_close_file; } } /* sync all replicas */ if (replica_sync(set, flags)) { LOG(1, "synchronization failed"); goto err_close_all; } util_poolset_close(set, 0); close(fd); return 0; err_close_all: util_poolset_close(set, 0); err_close_file: close(fd); err: if (errno == 0) errno = EINVAL; return -1; }
/* * transform_replica -- transforming one poolset into another */ int replica_transform(struct pool_set *set_in, struct pool_set *set_out, unsigned flags) { LOG(3, "set_in %p, set_out %p", set_in, set_out); int ret = 0; /* validate user arguments */ if (validate_args(set_in, set_out)) return -1; /* check if the source poolset is healthy */ struct poolset_health_status *set_in_hs = NULL; if (replica_check_poolset_health(set_in, &set_in_hs, flags)) { ERR("source poolset health check failed"); return -1; } if (!replica_is_poolset_healthy(set_in_hs)) { ERR("source poolset is broken"); ret = -1; errno = EINVAL; goto free_hs_in; } struct poolset_health_status *set_out_hs = NULL; if (replica_create_poolset_health_status(set_out, &set_out_hs)) { ERR("creating poolset health status failed"); ret = -1; goto free_hs_in; } /* check if the poolsets are transformable */ struct poolset_compare_status *set_in_cs = NULL; struct poolset_compare_status *set_out_cs = NULL; if (compare_poolsets(set_in, set_out, &set_in_cs, &set_out_cs)) { ERR("comparing poolsets failed"); ret = -1; goto free_hs_out; } enum transform_op operation = identify_transform_operation(set_in_cs, set_out_cs, set_in_hs, set_out_hs); if (operation == NOT_TRANSFORMABLE) { LOG(1, "poolsets are not transformable"); ret = -1; errno = EINVAL; goto free_cs; } if (operation == RM_HDRS) { if (!is_dry_run(flags) && remove_hdrs(set_in, set_out, set_in_hs, flags)) { ERR("removing headers failed; falling back to the " "input poolset"); if (replica_sync(set_in, set_in_hs, flags | IS_TRANSFORMED)) { LOG(1, "falling back to the input poolset " "failed"); } else { LOG(1, "falling back to the input poolset " "succeeded"); } ret = -1; } goto free_cs; } if (operation == ADD_HDRS) { if (!is_dry_run(flags) && add_hdrs(set_in, set_out, set_in_hs, flags)) { ERR("adding headers failed; falling back to the " "input poolset"); if (replica_sync(set_in, set_in_hs, flags | IS_TRANSFORMED)) { LOG(1, "falling back to the input poolset " "failed"); } else { LOG(1, "falling back to the input poolset " "succeeded"); } ret = -1; } goto free_cs; } if (operation == ADD_REPLICAS) { /* * check if any of the parts that are to be added already exists */ if (do_added_parts_exist(set_out, set_out_hs)) { ERR("some parts being added already exist"); ret = -1; errno = EINVAL; goto free_cs; } } /* signal that sync is called by transform */ if (replica_sync(set_out, set_out_hs, flags | IS_TRANSFORMED)) { ret = -1; goto free_cs; } if (operation == RM_REPLICAS) { if (!is_dry_run(flags) && delete_replicas(set_in, set_in_cs)) ret = -1; } free_cs: Free(set_in_cs); Free(set_out_cs); free_hs_out: replica_free_poolset_health_status(set_out_hs); free_hs_in: replica_free_poolset_health_status(set_in_hs); return ret; }