/* * pocli_pmemobj_do_tx_alloc -- pmemobj_tx_zalloc() and pmemobj_tx_zalloc() * commands common part */ static enum pocli_ret pocli_pmemobj_do_tx_alloc(struct pocli_ctx *ctx, struct pocli_args *args, PMEMoid (*fn_alloc)(size_t size, uint64_t type_num)) { if (args->argc != 4) return POCLI_ERR_ARGS; if (pmemobj_tx_stage() != TX_STAGE_WORK) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot use in stage different than TX_STAGE_WORK\n"); PMEMoid *oidp = NULL; uint64_t type_num = 0; size_t size = 0; enum pocli_ret ret; ret = pocli_args_obj(ctx, args, 1, &oidp); if (ret) return ret; if (oidp == &ctx->root) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot allocate to root object\n"); ret = pocli_args_size(args, 2, &size); if (ret) return ret; ret = pocli_args_number(args, 3, &type_num); if (ret) return ret; *oidp = fn_alloc(size, type_num); pocli_printf(ctx, "%s(%zu, %llu): off = 0x%llx uuid = 0x%llx\n", args->argv[0], size, type_num, oidp->off, oidp->pool_uuid_lo); return ret; }
/* * pocli_pmemobj_tx_free -- pmemobj_tx_free() command */ static enum pocli_ret pocli_pmemobj_tx_free(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 2) return POCLI_ERR_ARGS; if (pmemobj_tx_stage() != TX_STAGE_WORK) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot use in stage different than TX_STAGE_WORK\n"); PMEMoid *oidp = NULL; enum pocli_ret ret; ret = pocli_args_obj(ctx, args, 1, &oidp); if (ret) return ret; if (oidp == &ctx->root) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot free root object\n"); int r = pmemobj_tx_free(*oidp); if (r != POCLI_RET_OK) return pocli_err(ctx, POCLI_ERR_ARGS, "pmemobj_tx_free() failed\n"); pocli_printf(ctx, "%s(%p): off = 0x%llx uuid = 0x%llx\n", args->argv[0], oidp, oidp->off, oidp->pool_uuid_lo); return ret; }
/* * pocli_pmemobj_tx_strdup -- pmemobj_tx_strdup() command */ static enum pocli_ret pocli_pmemobj_tx_strdup(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 4) return POCLI_ERR_ARGS; if (pmemobj_tx_stage() != TX_STAGE_WORK) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot use in stage different than TX_STAGE_WORK\n"); PMEMoid *oidp = NULL; uint64_t type_num; enum pocli_ret ret; ret = pocli_args_obj(ctx, args, 1, &oidp); if (ret) return ret; if (oidp == &ctx->root) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot use root object\n"); ret = pocli_args_number(args, 3, &type_num); if (ret) return ret; *oidp = pmemobj_tx_strdup(args->argv[2], type_num); pocli_printf(ctx, "%s(%s, %llu): off = 0x%llx uuid = 0x%llx\n", args->argv[0], args->argv[2], type_num, oidp->off, oidp->pool_uuid_lo); return ret; }
/* * pocli_pmemobj_strdup -- pmemobj_strdup() command */ static enum pocli_ret pocli_pmemobj_strdup(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 4) return POCLI_ERR_ARGS; PMEMoid *oidp = NULL; uint64_t type_num; enum pocli_ret ret; ret = pocli_args_obj(ctx, args, 1, &oidp); if (ret) return ret; if (oidp == &ctx->root) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot use root object\n"); ret = pocli_args_number(args, 3, &type_num); if (ret) return ret; int r = pmemobj_strdup(ctx->pop, oidp, args->argv[2], type_num); if (r != POCLI_RET_OK) return pocli_err(ctx, POCLI_ERR_ARGS, "pmemobj_strdup() failed\n"); pocli_printf(ctx, "%s(%s, %s, %llu): %d\n", args->argv[0], args->argv[1], args->argv[2], type_num, r); return ret; }
/* * pocli_pmemobj_tx_add_range -- pmemobj_tx_add_range() command */ static enum pocli_ret pocli_pmemobj_tx_add_range(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 4) return POCLI_ERR_ARGS; PMEMoid *oidp; size_t offset = 0; size_t size = 0; enum pocli_ret ret; ret = pocli_args_obj(ctx, args, 1, &oidp); if (ret) return ret; if (oidp == NULL) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot add NULL pointer\n"); ret = pocli_args_size(args, 2, &offset); if (ret) return ret; ret = pocli_args_size(args, 3, &size); if (ret) return ret; int r = pmemobj_tx_add_range(*oidp, offset, size); if (r != POCLI_RET_OK) return pocli_err(ctx, POCLI_ERR_ARGS, "pmemobj_tx_add_range() failed"); pocli_printf(ctx, "%s(%s, %zu, %zu): %d\n", args->argv[0], args->argv[1], offset, size, ret, r); return ret; }
/* * pocli_pmemobj_free -- pmemobj_free() command */ static enum pocli_ret pocli_pmemobj_free(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 2) return POCLI_ERR_ARGS; PMEMoid *oidp = NULL; enum pocli_ret ret; ret = pocli_args_obj(ctx, args, 1, &oidp); if (ret) return ret; if (oidp == NULL) return pocli_err(ctx, POCLI_ERR_ARGS, "NULL pointer not allowed here\n"); if (oidp == &ctx->root) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot free root object\n"); pmemobj_free(oidp); pocli_printf(ctx, "%s(%p): off = 0x%llx uuid = 0x%llx\n", args->argv[0], oidp, oidp->off, oidp->pool_uuid_lo); return ret; }
/* * pocli_pmemobj_list_insert_new -- pmemobj_list_insert_new() command */ static enum pocli_ret pocli_pmemobj_list_insert_new(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 7) return POCLI_ERR_ARGS; PMEMoid nulloid = OID_NULL; PMEMoid *dest; PMEMoid *oid; PMEMoid *head_oid; enum pocli_ret ret; uint64_t before; uint64_t type_num; uint64_t size; if ((ret = pocli_args_obj(ctx, args, 1, &oid))) return ret; if (oid == &ctx->root) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot allocate to root object\n"); if ((ret = pocli_args_obj(ctx, args, 2, &head_oid))) return ret; struct plist *head = pmemobj_direct(*head_oid); if ((ret = pocli_args_list_elm(ctx, args, 3, &dest, head))) return ret; if (dest == NULL) dest = &nulloid; if ((ret = pocli_args_number(args, 4, &before))) return ret; if (before > 1) return pocli_err(ctx, POCLI_ERR_ARGS, "Before flag different than 0 or 1\n"); if ((ret = pocli_args_number(args, 5, &type_num))) return ret; if ((ret = pocli_args_number(args, 6, &size))) return ret; *oid = pmemobj_list_insert_new(ctx->pop, offsetof(struct item, field), head, *dest, (int)before, size, type_num, NULL, NULL); if (OID_IS_NULL(*oid)) return pocli_err(ctx, POCLI_ERR_ARGS, "pmemobj_list_insert_new() failed\n"); pocli_printf(ctx, "%s(%s, %p, %u, %llu, %zu): off = 0x%jx uuid = 0x%jx" " ptr = %p\n", args->argv[0], args->argv[2], dest, before, type_num, size, oid->off, oid->pool_uuid_lo, pmemobj_direct(*oid)); return ret; }
/* * pocli_pmemobj_list_move -- pmemobj_list_move() command */ static enum pocli_ret pocli_pmemobj_list_move(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 6) return POCLI_ERR_ARGS; PMEMoid nulloid = OID_NULL; PMEMoid *dest; PMEMoid *oid; PMEMoid *head_oid; enum pocli_ret ret; uint64_t before; size_t offset = offsetof(struct item, field); if ((ret = pocli_args_obj(ctx, args, 2, &head_oid))) return ret; struct plist *head_src = pmemobj_direct(*head_oid); if ((ret = pocli_args_obj(ctx, args, 3, &head_oid))) return ret; struct plist *head_dest = pmemobj_direct(*head_oid); if ((ret = pocli_args_list_elm(ctx, args, 1, &oid, head_src))) return ret; if ((ret = pocli_args_list_elm(ctx, args, 4, &dest, head_dest))) return ret; if (dest == NULL) dest = &nulloid; if ((ret = pocli_args_number(args, 5, &before))) return ret; if (before > 1) return pocli_err(ctx, POCLI_ERR_ARGS, "Before flag different than 0 or 1\n"); int r = pmemobj_list_move(ctx->pop, offset, head_src, offset, head_dest, *dest, (int)before, *oid); if (r != POCLI_RET_OK) return pocli_err(ctx, POCLI_ERR_ARGS, "pmemobj_list_move() failed\n"); pocli_printf(ctx, "%s(%p, %s, %s, %p, %u): %d\n", args->argv[0], pmemobj_direct(*oid), args->argv[2], args->argv[3], pmemobj_direct(*dest), before, r); return ret; }
/* * pocli_process -- process input commands */ int pocli_process(struct pocli *pcli) { while (1) { pocli_prompt(pcli); if (!fgets(pcli->inbuf, (int)pcli->inbuf_len, pcli->in)) return 0; char *nl = strchr(pcli->inbuf, '\n'); if (!nl) return 1; *nl = '\0'; char *hash = strchr(pcli->inbuf, '#'); if (hash) { if (pcli->opts.enable_comments) *hash = '\0'; else return 1; } if (pcli->inbuf[0] == 0 || pcli->inbuf[0] == '\n') { if (pcli->opts.enable_empty_cmds) continue; else return 1; } if (pcli->opts.echo_mode) pocli_printf(&pcli->ctx, "%s\n", pcli->inbuf); char *argstr = strchr(pcli->inbuf, ' '); if (argstr) { *argstr = '\0'; argstr++; } char *cmds = pcli->inbuf; const struct pocli_cmd *cmd = pocli_get_cmd(pcli, cmds); if (!cmd) { pocli_err(&pcli->ctx, 0, "unknown command -- '%s'\n", cmds); if (pcli->opts.exit_on_error) return 1; else continue; } if (!argstr) argstr = cmds + strlen(pcli->inbuf) + 1; struct pocli_args *args = pocli_args_alloc(pcli->inbuf, argstr, POCLI_CMD_DELIM); if (!args) return 1; enum pocli_ret ret = cmd->func(&pcli->ctx, args); free(args); if (ret != POCLI_RET_OK) return ret; } }
/* * pocli_pmemobj_zalloc -- pmemobj_zalloc() command */ static enum pocli_ret pocli_pmemobj_zalloc(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 4) return POCLI_ERR_ARGS; PMEMoid *oidp = NULL; unsigned type_num = 0; size_t size = 0; enum pocli_ret ret; ret = pocli_args_obj(ctx, args, 1, &oidp); if (ret) return ret; if (oidp == &ctx->root) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot allocate to root object\n"); ret = pocli_args_type_num(args, 2, &type_num); if (ret) return ret; ret = pocli_args_size(args, 3, &size); if (ret) return ret; int r = pmemobj_zalloc(ctx->pop, oidp, size, type_num); pocli_printf(ctx, "%s(%s, %llu, %u): %d\n", args->argv[0], args->argv[1], size, type_num, r); return ret; }
/* * pocli_args_obj -- parse object's descriptor */ static enum pocli_ret pocli_args_obj(struct pocli_ctx *ctx, struct pocli_args *args, int arg, PMEMoid **oidp) { assert(args != NULL); assert(arg >= 0 && arg < args->argc); assert(oidp != NULL); assert(ctx != NULL); char *objs = args->argv[arg]; if (strcmp(objs, "r") == 0) { *oidp = &ctx->root; } else if (strcmp(objs, "0") == 0) { *oidp = NULL; } else if (strcmp(objs, "NULL") == 0) { *oidp = NULL; } else if (objs[0] == 'r') { return pocli_args_obj_root(ctx, args->argv[arg], oidp); } else { return pocli_err(ctx, POCLI_ERR_PARS, "invalid object specified -- '%s'\n", objs); } return POCLI_RET_OK; }
/* * pocli_pmemobj_root -- pmemobj_root() command */ static enum pocli_ret pocli_pmemobj_root(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 2) return POCLI_ERR_ARGS; size_t size = 0; enum pocli_ret ret; ret = pocli_args_size(args, 1, &size); if (ret) return ret; PMEMoid root = pmemobj_root(ctx->pop, size); if (OID_IS_NULL(root)) return pocli_err(ctx, POCLI_ERR_CMD, "pmemobj_root failed\n"); ctx->root = root; pocli_printf(ctx, "%s(%llu): off = 0x%jx uuid = 0x%jx\n", args->argv[0], size, ctx->root.off, ctx->root.pool_uuid_lo); return POCLI_RET_OK; }
/* * pocli_pmemobj_tx_begin -- pmemobj_tx_begin() command */ static enum pocli_ret pocli_pmemobj_tx_begin(struct pocli_ctx *ctx, struct pocli_args *args) { enum pocli_ret ret = POCLI_RET_OK; int r; switch (args->argc) { case 1: { r = pmemobj_tx_begin(ctx->pop, NULL, TX_PARAM_NONE); if (r != POCLI_RET_OK) return pocli_err(ctx, POCLI_ERR_ARGS, "pmemobj_tx_begin() failed"); pocli_printf(ctx, "%s: %d\n", args->argv[0], r); } break; case 2: { if (strcmp(args->argv[1], "jmp") != 0) return POCLI_ERR_ARGS; jmp_buf jmp; if (setjmp(jmp)) { const char *command = ctx->tx_aborted ? "pmemobj_tx_abort" : "pmemobj_tx_end"; pocli_printf(ctx, "%s: %d\n", command, pmemobj_tx_errno()); return POCLI_RET_OK; } else { r = pmemobj_tx_begin(ctx->pop, jmp, TX_PARAM_NONE); if (r != POCLI_RET_OK) return pocli_err(ctx, POCLI_ERR_ARGS, "pmemobj_tx_begin() failed"); } pocli_printf(ctx, "%s(jmp): %d\n", args->argv[0], r); ret = (enum pocli_ret)pocli_process(ctx->pocli); if (ret) return ret; } break; default: return POCLI_ERR_ARGS; } return ret; }
/* * pocli_pmemobj_do_realloc -- pmemobj_realloc and pmemobj_zrealloc() commands * common part */ static enum pocli_ret pocli_pmemobj_do_realloc(struct pocli_ctx *ctx, struct pocli_args *args, int (*fn_realloc)(PMEMobjpool *pop, PMEMoid *oid, size_t size, uint64_t type_num)) { if (args->argc != 4) return POCLI_ERR_ARGS; PMEMoid *oidp = NULL; uint64_t type_num = 0; size_t size = 0; enum pocli_ret ret; ret = pocli_args_obj(ctx, args, 1, &oidp); if (ret) return ret; if (oidp == NULL) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot realloc with NULL oid pointer\n"); if (oidp == &ctx->root) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot reallocate to root object\n"); ret = pocli_args_number(args, 2, &type_num); if (ret) return ret; ret = pocli_args_size(args, 3, &size); if (ret) return ret; int r = fn_realloc(ctx->pop, oidp, size, type_num); pocli_printf(ctx, "%s(%s, %zu, %llu): %d off = 0x%llx uuid = 0x%llx\n", args->argv[0], args->argv[1], size, type_num, r, oidp->off, oidp->pool_uuid_lo); return ret; }
/* * pocli_pmemobj_tx_add_range_direct -- pmemobj_tx_add_range_direct() command */ static enum pocli_ret pocli_pmemobj_tx_add_range_direct(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 4) return POCLI_ERR_ARGS; PMEMoid *oidp; size_t off = 0; size_t size = 0; enum pocli_ret ret; ret = pocli_args_obj(ctx, args, 1, &oidp); if (ret) return ret; if (oidp == NULL) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot add NULL pointer\n"); char *ptr = (char *)pmemobj_direct(*oidp); ret = pocli_args_size(args, 2, &off); if (ret) return ret; ret = pocli_args_size(args, 3, &size); if (ret) return ret; int r = pmemobj_tx_add_range_direct((void *)(ptr + off), size); if (r != POCLI_RET_OK) return pocli_err(ctx, POCLI_ERR_ARGS, "pmemobj_tx_add_range_direct() failed"); pocli_printf(ctx, "%s(%p, %zu, %zu): %d\n", args->argv[0], ptr, off, size, r); return ret; }
/* * pocli_pmemobj_list_remove -- pmemobj_list_remove() command */ static enum pocli_ret pocli_pmemobj_list_remove(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 4) return POCLI_ERR_ARGS; PMEMoid *oid; PMEMoid *head_oid; enum pocli_ret ret; uint64_t if_free; if ((ret = pocli_args_obj(ctx, args, 2, &head_oid))) return ret; struct plist *head = pmemobj_direct(*head_oid); if ((ret = pocli_args_list_elm(ctx, args, 1, &oid, head))) return ret; if ((ret = pocli_args_number(args, 3, &if_free))) return ret; if (if_free > 1) return pocli_err(ctx, POCLI_ERR_ARGS, "Free flag different than 0 or 1\n"); void *oidp = pmemobj_direct(*oid); int r = pmemobj_list_remove(ctx->pop, offsetof(struct item, field), head, *oid, (int)if_free); if (r != POCLI_RET_OK) return pocli_err(ctx, POCLI_ERR_ARGS, "pmemobj_list_remove() failed\n"); pocli_printf(ctx, "%s(%p, %s, %u): off = 0x%jx uuid = 0x%jx\n", args->argv[0], oidp, args->argv[2], if_free, oid->off, oid->pool_uuid_lo); return ret; }
/* * pocli_pmemobj_tx_commit -- pmemobj_tx_commit() command */ static enum pocli_ret pocli_pmemobj_tx_commit(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 1) return POCLI_ERR_ARGS; if (pmemobj_tx_stage() != TX_STAGE_WORK) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot use in stage different than TX_STAGE_WORK\n"); pmemobj_tx_commit(); pocli_printf(ctx, "%s\n", args->argv[0]); return POCLI_RET_OK; }
/* * pocli_pmemobj_first -- pmemobj_first() command */ static enum pocli_ret pocli_pmemobj_first(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 1) return POCLI_ERR_ARGS; PMEMoid oidp = pmemobj_first(ctx->pop); if (OID_IS_NULL(oidp)) return pocli_err(ctx, POCLI_ERR_ARGS, "pmemobj_first() failed\n"); pocli_printf(ctx, "%s: off = 0x%llx uuid = 0x%llx\n", args->argv[0], oidp.off, oidp.pool_uuid_lo); return POCLI_RET_OK; }
/* * pocli_pmemobj_tx_end -- pmemobj_tx_end() command */ static enum pocli_ret pocli_pmemobj_tx_end(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 1) return POCLI_ERR_ARGS; if (pmemobj_tx_stage() == TX_STAGE_NONE || pmemobj_tx_stage() == TX_STAGE_WORK) return pocli_err(ctx, POCLI_ERR_ARGS, "transaction in improper stage\n"); ctx->tx_aborted = false; int ret = pmemobj_tx_end(); pocli_printf(ctx, "%s: %d\n", args->argv[0], ret); return POCLI_RET_OK; }
/* * pocli_args_list_elm -- parse object's descriptor and checks if it's on list */ static enum pocli_ret pocli_args_list_elm(struct pocli_ctx *ctx, struct pocli_args *args, int arg, PMEMoid **oidp, struct plist *head) { enum pocli_ret ret; ret = pocli_args_obj(ctx, args, arg, oidp); if (ret) return ret; if (*oidp == NULL) return POCLI_RET_OK; TOID(struct item) tmp; POBJ_LIST_FOREACH(tmp, head, field) { if (OID_EQUALS(tmp.oid, **oidp)) return POCLI_RET_OK; } return pocli_err(ctx, POCLI_ERR_PARS, "object %s is not member of given list\n", args->argv[arg]); }
/* * pocli_pmemobj_tx_abort -- pmemobj_tx_abort() command */ static enum pocli_ret pocli_pmemobj_tx_abort(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 2) return POCLI_ERR_ARGS; if (pmemobj_tx_stage() != TX_STAGE_WORK) return pocli_err(ctx, POCLI_ERR_ARGS, "cannot use in stage different than TX_STAGE_WORK\n"); int err; int count = sscanf(args->argv[1], "%d", &err); if (count != 1) return POCLI_ERR_PARS; ctx->tx_aborted = true; free(args); pmemobj_tx_abort(err); pocli_printf(ctx, "pmemobj_tx_abort: %d", err); return POCLI_RET_OK; }
/* * pocli_pmemobj_alloc_usable_size -- pmemobj_alloc_usable_size() command */ static enum pocli_ret pocli_pmemobj_alloc_usable_size(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 2) return POCLI_ERR_ARGS; PMEMoid *oidp = NULL; enum pocli_ret ret; ret = pocli_args_obj(ctx, args, 1, &oidp); if (ret) return ret; if (oidp == NULL) return pocli_err(ctx, POCLI_ERR_ARGS, "invalid object -- '%s'\n", args->argv[1]); size_t size = pmemobj_alloc_usable_size(*oidp); pocli_printf(ctx, "%s(%s): size = %zu\n", args->argv[0], args->argv[1], size); return POCLI_RET_OK; }
/* * pocli_pmemobj_type_num -- pmemobj_type_num() command */ static enum pocli_ret pocli_pmemobj_type_num(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 2) return POCLI_ERR_ARGS; PMEMoid *oidp = NULL; enum pocli_ret ret; ret = pocli_args_obj(ctx, args, 1, &oidp); if (ret) return ret; if (oidp == NULL) return pocli_err(ctx, POCLI_ERR_ARGS, "invalid object -- '%s'\n", args->argv[1]); uint64_t type_num = pmemobj_type_num(*oidp); pocli_printf(ctx, "%s(%s): type num = %llu\n", args->argv[0], args->argv[1], type_num); return POCLI_RET_OK; }
/* * pocli_pmemobj_direct -- pmemobj_direct() command */ static enum pocli_ret pocli_pmemobj_direct(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 2) return POCLI_ERR_ARGS; PMEMoid *oidp = NULL; enum pocli_ret ret; ret = pocli_args_obj(ctx, args, 1, &oidp); if (ret) return ret; if (oidp == NULL) return pocli_err(ctx, POCLI_ERR_ARGS, "invalid object -- '%s'\n", args->argv[1]); void *obj = pmemobj_direct(*oidp); pocli_printf(ctx, "%s(%s): off = 0x%jx uuid = 0x%jx ptr = %p\n", args->argv[0], args->argv[1], oidp->off, oidp->pool_uuid_lo, obj); return POCLI_RET_OK; }