int main(int argc, char *argv[]) { if (argc != 2) { printf("usage: %s file-name\n", argv[0]); return 1; } PMEMobjpool *pop = pmemobj_create(argv[1], LAYOUT_NAME, PMEMOBJ_MIN_POOL, 0666); if (pop == NULL) { perror("pmemobj_create"); return 1; } PMEMoid root = pmemobj_root(pop, sizeof(struct my_root)); struct my_root *rootp = pmemobj_direct(root); char buf[MAX_BUF_LEN]; if (scanf("%9s", buf) == EOF) { fprintf(stderr, "EOF\n"); return 1; } rootp->len = strlen(buf); pmemobj_persist(pop, &rootp->len, sizeof(rootp->len)); pmemobj_memcpy_persist(pop, rootp->buf, buf, rootp->len); pmemobj_close(pop); return 0; }
/* * 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_str_root_copy -- copy a string into a root object data */ static enum pocli_ret pocli_str_root_copy(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 3) return POCLI_ERR_ARGS; size_t offset = 0; enum pocli_ret ret = pocli_args_size(args, 1, &offset); if (ret) return ret; const char *str = args->argv[2]; if (str == NULL) return POCLI_ERR_ARGS; size_t len = strlen(str); size_t root_size = pmemobj_root_size(ctx->pop); if (offset + len > root_size) return POCLI_ERR_ARGS; PMEMoid root = pmemobj_root(ctx->pop, root_size); assert(!OID_IS_NULL(root)); char *root_data = pmemobj_direct(root); pmemobj_memcpy_persist(ctx->pop, root_data + offset, str, len); return ret; }
/* * pmemlog_rewind -- discard all data, resetting a log memory pool to empty */ void pmemlog_rewind(PMEMlogpool *plp) { PMEMobjpool *pop = (PMEMobjpool *)plp; PMEMoid baseoid = pmemobj_root(pop, sizeof (struct base)); struct base *bp = pmemobj_direct(baseoid); /* set the return point */ jmp_buf env; if (setjmp(env)) { /* end the transaction */ pmemobj_tx_end(); return; } /* begin a transaction, also acquiring the write lock for the log */ pmemobj_tx_begin(pop, env, TX_LOCK_RWLOCK, &bp->rwlock, TX_LOCK_NONE); /* add the root object to the undo log */ pmemobj_tx_add_range(baseoid, 0, sizeof (struct base)); /* free all log nodes */ while (bp->head.off != 0) { PMEMoid nextoid = ((struct log *)pmemobj_direct(bp->head))->hdr.next; pmemobj_tx_free(bp->head); bp->head = nextoid; } bp->head = OID_NULL; bp->tail = OID_NULL; bp->bytes_written = 0; pmemobj_tx_commit(); pmemobj_tx_end(); }
/* * pocli_str_root_print -- print a string stored in the root object data */ static enum pocli_ret pocli_str_root_print(struct pocli_ctx *ctx, struct pocli_args *args) { if (args->argc != 3) return POCLI_ERR_ARGS; size_t offset = 0; enum pocli_ret ret = pocli_args_size(args, 1, &offset); if (ret) return ret; size_t len = 0; ret = pocli_args_number(args, 2, &len); if (ret) return ret; size_t root_size = pmemobj_root_size(ctx->pop); if (offset + len > root_size) return POCLI_ERR_ARGS; PMEMoid root = pmemobj_root(ctx->pop, root_size); assert(!OID_IS_NULL(root)); char *root_data = pmemobj_direct(root); char *buff = malloc(len + 1); memcpy(buff, root_data + offset, len); buff[len] = '\0'; printf("%s\n", buff); return ret; }
int main(int argc, char *argv[]) { START(argc, argv, "obj_heap_state"); if (argc != 2) FATAL("usage: %s file-name", argv[0]); const char *path = argv[1]; PMEMobjpool *pop = NULL; if ((pop = pmemobj_create(path, LAYOUT_NAME, PMEMOBJ_MIN_POOL, S_IWUSR | S_IRUSR)) == NULL) FATAL("!pmemobj_create: %s", path); pmemobj_root(pop, ROOT_SIZE); /* just to trigger allocation */ pmemobj_close(pop); pop = pmemobj_open(path, LAYOUT_NAME); ASSERTne(pop, NULL); for (int i = 0; i < ALLOCS; ++i) { PMEMoid oid; pmemobj_alloc(pop, &oid, ALLOC_SIZE, 0, NULL, NULL); OUT("%d %lu", i, oid.off); } pmemobj_close(pop); DONE(NULL); }
static void allocate_objects(PMEMobjpool *pop, size_t size_min, size_t size_max) { size_t allocated_total = 0; size_t sstart = 0; PMEMoid oid = pmemobj_root(pop, 1); uint64_t uuid_lo = oid.pool_uuid_lo; while (allocated_total < ALLOC_TOTAL) { size_t s = RRAND(seed, size_max, size_min); pmemobj_alloc(pop, &oid, s, 0, NULL, NULL); s = pmemobj_alloc_usable_size(oid); UT_ASSERTeq(OID_IS_NULL(oid), 0); objects[nobjects++] = oid.off; UT_ASSERT(nobjects < MAX_OBJECTS); allocated_total += s; allocated_current += s; if (allocated_current > ALLOC_CURR) { shuffle_objects(sstart, nobjects); for (int i = 0; i < FREES_P; ++i) { oid.pool_uuid_lo = uuid_lo; oid.off = remove_last(); allocated_current -= pmemobj_alloc_usable_size(oid); pmemobj_free(&oid); } sstart = nobjects; } } }
/** * Retrieves pool's root object. * * @return persistent pointer to the root object. */ persistent_ptr<T> get_root() { if (pop == nullptr) throw pool_error("Invalid pool handle"); persistent_ptr<T> root = pmemobj_root(this->pop, sizeof(T)); return root; }
int main(int argc, char *argv[]) { START(argc, argv, "obj_fragmentation2"); if (argc < 3) UT_FATAL("usage: %s filename workload [seed]", argv[0]); const char *path = argv[1]; PMEMobjpool *pop = pmemobj_create(path, LAYOUT_NAME, DEFAULT_FILE_SIZE, S_IWUSR | S_IRUSR); if (pop == NULL) UT_FATAL("!pmemobj_create: %s", path); int w = atoi(argv[2]); if (argc > 3) seed = (unsigned)atoi(argv[3]); else seed = time(NULL); objects = ZALLOC(sizeof(uint64_t) * MAX_OBJECTS); UT_ASSERTne(objects, NULL); workloads[w - 1](pop); PMEMoid oid; size_t remaining = 0; size_t chunk = 100; /* calc at chunk level */ while (pmemobj_alloc(pop, &oid, chunk, 0, NULL, NULL) == 0) remaining += pmemobj_alloc_usable_size(oid) + 16; size_t allocated_sum = 0; oid = pmemobj_root(pop, 1); for (size_t n = 0; n < nobjects; ++n) { if (objects[n] == 0) continue; oid.off = objects[n]; allocated_sum += pmemobj_alloc_usable_size(oid) + 16; } size_t used = DEFAULT_FILE_SIZE - remaining; float frag = ((float)used / allocated_sum) - 1.f; UT_ASSERT(frag <= workloads_target[w - 1]); pmemobj_close(pop); FREE(objects); DONE(NULL); }
/* * pmemlog_appendv -- add gathered data to a log memory pool */ int pmemlog_appendv(PMEMlogpool *plp, const struct iovec *iov, int iovcnt) { PMEMobjpool *pop = (PMEMobjpool *)plp; PMEMoid baseoid = pmemobj_root(pop, sizeof (struct base)); struct base *bp = pmemobj_direct(baseoid); /* set the return point */ jmp_buf env; if (setjmp(env)) { /* end the transaction */ pmemobj_tx_end(); return 1; } /* begin a transaction, also acquiring the write lock for the log */ pmemobj_tx_begin(pop, env, TX_LOCK_RWLOCK, &bp->rwlock, TX_LOCK_NONE); /* add the base object to the undo log - once for the transaction */ pmemobj_tx_add_range(baseoid, 0, sizeof (struct base)); /* add the tail entry once to the undo log, if it is set */ if (!OID_IS_NULL(bp->tail)) pmemobj_tx_add_range(bp->tail, 0, sizeof (struct log)); /* append the data */ for (int i = 0; i < iovcnt; ++i) { char *buf = iov[i].iov_base; size_t count = iov[i].iov_len; /* allocate the new node to be inserted */ PMEMoid log = pmemobj_tx_alloc(count + sizeof (struct log_hdr), LOG_TYPE); struct log *logp = pmemobj_direct(log); logp->hdr.size = count; memcpy(logp->data, buf, count); logp->hdr.next = OID_NULL; if (bp->tail.off == 0) { bp->head = log; /* update head */ } else { ((struct log *)pmemobj_direct(bp->tail))->hdr.next = log; } bp->tail = log; /* update tail */ bp->bytes_written += count; } pmemobj_tx_commit(); pmemobj_tx_end(); return 0; }
/* * pmemlog_tell -- returns the current write point for the log */ off_t pmemlog_tell(PMEMlogpool *plp) { PMEMobjpool *pop = (PMEMobjpool *)plp; struct base *bp = pmemobj_direct(pmemobj_root(pop, sizeof (struct base))); if (pmemobj_rwlock_rdlock(pop, &bp->rwlock) != 0) return 0; off_t bytes_written = bp->bytes_written; pmemobj_rwlock_unlock(pop, &bp->rwlock); return bytes_written; }
/* * pmemlog_append -- add data to a log memory pool */ int pmemlog_append(PMEMlogpool *plp, const void *buf, size_t count) { PMEMobjpool *pop = (PMEMobjpool *)plp; PMEMoid baseoid = pmemobj_root(pop, sizeof (struct base)); struct base *bp = pmemobj_direct(baseoid); /* set the return point */ jmp_buf env; if (setjmp(env)) { /* end the transaction */ pmemobj_tx_end(); return 1; } /* begin a transaction, also acquiring the write lock for the log */ pmemobj_tx_begin(pop, env, TX_LOCK_RWLOCK, &bp->rwlock, TX_LOCK_NONE); /* allocate the new node to be inserted */ PMEMoid log = pmemobj_tx_alloc(count + sizeof (struct log_hdr), LOG_TYPE); struct log *logp = pmemobj_direct(log); logp->hdr.size = count; memcpy(logp->data, buf, count); logp->hdr.next = OID_NULL; /* add the modified root object to the undo log */ pmemobj_tx_add_range(baseoid, 0, sizeof (struct base)); if (bp->tail.off == 0) { /* update head */ bp->head = log; } else { /* add the modified tail entry to the undo log */ pmemobj_tx_add_range(bp->tail, 0, sizeof (struct log)); ((struct log *)pmemobj_direct(bp->tail))->hdr.next = log; } bp->tail = log; /* update tail */ bp->bytes_written += count; pmemobj_tx_commit(); pmemobj_tx_end(); return 0; }
static void delete_objects(PMEMobjpool *pop, float pct) { size_t nfree = (float)nobjects * pct; PMEMoid oid = pmemobj_root(pop, 1); uint64_t uuid_lo = oid.pool_uuid_lo; shuffle_objects(0, nobjects); while (nfree--) { oid.off = remove_last(); oid.pool_uuid_lo = uuid_lo; allocated_current -= pmemobj_alloc_usable_size(oid); pmemobj_free(&oid); } }
/* * pocli_alloc -- allocate main context */ static struct pocli * pocli_alloc(FILE *input, const char *fname, const struct pocli_cmd *cmds, size_t ncmds, size_t inbuf_len) { assert(inbuf_len < INT_MAX); struct pocli_opts opts; if (pocli_read_opts(&opts)) return NULL; struct pocli *pcli = calloc(1, sizeof (*pcli)); if (!pcli) return NULL; memcpy(&pcli->opts, &opts, sizeof (pcli->opts)); pcli->in = input; pcli->istty = isatty(fileno(pcli->in)); pcli->cmds = cmds; pcli->ncmds = ncmds; pcli->ctx.pocli = pcli; pcli->ctx.err = stderr; pcli->ctx.out = stdout; pcli->ctx.pop = pmemobj_open(fname, NULL); if (!pcli->ctx.pop) { fprintf(stderr, "%s: %s\n", fname, pmemobj_errormsg()); goto err_free_pcli; } size_t root_size = pmemobj_root_size(pcli->ctx.pop); if (root_size) pcli->ctx.root = pmemobj_root(pcli->ctx.pop, root_size); pcli->inbuf_len = inbuf_len; pcli->inbuf = malloc(inbuf_len); if (!pcli->inbuf) goto err_close_pool; return pcli; err_close_pool: pmemobj_close(pcli->ctx.pop); err_free_pcli: free(pcli); return NULL; }
/* * pmemlog_walk -- walk through all data in a log memory pool * * As this implementation holds the size of each entry, the chunksize is ignored * and the process_chunk function gets the actual entry length. */ void pmemlog_walk(PMEMlogpool *plp, size_t chunksize, int (*process_chunk)(const void *buf, size_t len, void *arg), void *arg) { PMEMobjpool *pop = (PMEMobjpool *)plp; struct base *bp = pmemobj_direct(pmemobj_root(pop, sizeof (struct base))); if (pmemobj_rwlock_rdlock(pop, &bp->rwlock) != 0) return; /* process all chunks */ struct log *next = pmemobj_direct(bp->head); while (next != NULL) { (*process_chunk)(next->data, next->hdr.size, arg); next = pmemobj_direct(next->hdr.next); } pmemobj_rwlock_unlock(pop, &bp->rwlock); }
/* * pmemobj_vg_boot -- (internal) notify Valgrind about pool objects */ static void pmemobj_vg_boot(struct pmemobjpool *pop) { if (!On_valgrind) return; LOG(4, "pop %p", pop); PMEMoid oid; int rs = pmemobj_root_size(pop); if (rs) { oid = pmemobj_root(pop, rs); pmemobj_vg_register_object(pop, oid, 1); } for (int i = 0; i < PMEMOBJ_NUM_OID_TYPES; ++i) { for (oid = pmemobj_first(pop, i); !OID_IS_NULL(oid); oid = pmemobj_next(oid)) pmemobj_vg_register_object(pop, oid, 0); } if (getenv("PMEMOBJ_VG_CHECK_UNDEF")) pmemobj_vg_check_no_undef(pop); }
int main(int argc, char *argv[]) { if (argc != 2) { printf("usage: %s file-name\n", argv[0]); return 1; } PMEMobjpool *pop = pmemobj_open(argv[1], LAYOUT_NAME); if (pop == NULL) { perror("pmemobj_open"); return 1; } PMEMoid root = pmemobj_root(pop, sizeof(struct my_root)); struct my_root *rootp = pmemobj_direct(root); if (rootp->len == strlen(rootp->buf)) printf("%s\n", rootp->buf); pmemobj_close(pop); return 0; }
int main(int argc, char *argv[]) { START(argc, argv, "obj_pvector"); if (argc != 2) UT_FATAL("usage: %s [file]", argv[0]); const char *path = argv[1]; PMEMobjpool *pop; if ((pop = pmemobj_create(path, "obj_pvector", PMEMOBJ_MIN_POOL * 3, S_IWUSR | S_IRUSR)) == NULL) UT_FATAL("!pmemobj_create: %s", path); PMEMoid root = pmemobj_root(pop, sizeof(struct test_root)); struct test_root *r = (struct test_root *)pmemobj_direct(root); UT_ASSERTne(r, NULL); struct pvector_context *ctx = pvector_new(pop, &r->vec); uint64_t *val = pvector_push_back(ctx); *val = 5; val = pvector_push_back(ctx); *val = 10; val = pvector_push_back(ctx); *val = 15; uint64_t v; int n = 0; for (v = pvector_first(ctx); v != 0; v = pvector_next(ctx)) { if (n == 0) UT_ASSERTeq(v, 5); if (n == 1) UT_ASSERTeq(v, 10); if (n == 2) UT_ASSERTeq(v, 15); if (n == 3) UT_ASSERT(0); n++; } uint64_t removed = pvector_pop_back(ctx, NULL); UT_ASSERTeq(removed, 15); n = 0; for (v = pvector_first(ctx); v != 0; v = pvector_next(ctx)) { if (n == 0) UT_ASSERTeq(v, 5); if (n == 1) UT_ASSERTeq(v, 10); if (n == 3) UT_ASSERT(0); n++; } while (pvector_pop_back(ctx, vec_zero_entry) != 0) ; pvector_delete(ctx); ctx = pvector_new(pop, &r->vec); for (int i = 0; i < PVECTOR_INSERT_VALUES; ++i) { val = pvector_push_back(ctx); UT_ASSERTne(val, NULL); *val = i; pmemobj_persist(pop, val, sizeof(*val)); } n = 0; for (v = pvector_first(ctx); v != 0; v = pvector_next(ctx)) { UT_ASSERTeq(v, n); n++; } n = 0; for (int i = PVECTOR_INSERT_VALUES - 1; i >= 0; --i) { v = pvector_pop_back(ctx, NULL); UT_ASSERTeq(v, i); } UT_ASSERTeq(pvector_first(ctx), 0); pvector_delete(ctx); pmemobj_close(pop); DONE(NULL); }
/* * Retrieve pool's root object. * * Returns a persistent pointer to the root object. */ persistent_ptr<T> get_root() { persistent_ptr<T> root = pmemobj_root(this->pop, sizeof (T)); return root; }
int main(int argc, char *argv[]) { #ifdef _WIN32 wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc); for (int i = 0; i < argc; i++) { argv[i] = util_toUTF8(wargv[i]); if (argv[i] == NULL) { for (i--; i >= 0; i--) free(argv[i]); fprintf(stderr, "Error during arguments conversion\n"); return 1; } } #endif int opt; int tmpi; long long tmpl; int ret = 0; size_t size = 0; size_t root_size = 0; unsigned type_num = 0; char exit_at = '\0'; int do_set = 0; int do_free = 0; if (argc < 2) { USAGE(); ret = 1; goto end; } while ((opt = getopt(argc, argv, "r:o:t:e:sf")) != -1) { switch (opt) { case 'r': tmpl = atoll(optarg); if (tmpl < 0) { USAGE(); ret = 1; goto end; } root_size = (size_t)tmpl; break; case 'o': tmpl = atoll(optarg); if (tmpl < 0) { USAGE(); ret = 1; goto end; } size = (size_t)tmpl; break; case 't': tmpi = atoi(optarg); if (tmpi < 0) { USAGE(); ret = 1; goto end; } type_num = (unsigned)tmpi; break; case 'e': exit_at = optarg[0]; break; case 's': do_set = 1; break; case 'f': do_free = 1; break; default: USAGE(); ret = 1; goto end; } } char *file = argv[optind]; PMEMobjpool *pop; if ((pop = pmemobj_open(file, NULL)) == NULL) { fprintf(stderr, "pmemobj_open: %s\n", pmemobj_errormsg()); ret = 1; goto end; } if (root_size) { PMEMoid oid = pmemobj_root(pop, root_size); if (OID_IS_NULL(oid)) { fprintf(stderr, "pmemobj_root: %s\n", pmemobj_errormsg()); ret = 1; goto end; } } if (size) { PMEMoid oid; TX_BEGIN(pop) { oid = pmemobj_tx_alloc(size, type_num); if (exit_at == 'a') exit(1); } TX_END if (OID_IS_NULL(oid)) { fprintf(stderr, "pmemobj_tx_alloc: %s\n", pmemobj_errormsg()); ret = 1; goto end; } if (do_set) { TX_BEGIN(pop) { pmemobj_tx_add_range(oid, 0, size); if (exit_at == 's') exit(1); } TX_END } if (do_free) { TX_BEGIN(pop) { pmemobj_tx_free(oid); if (exit_at == 'f') exit(1); } TX_END } } pmemobj_close(pop); end: #ifdef _WIN32 for (int i = argc; i > 0; i--) free(argv[i - 1]); #endif return ret; }
int main(int argc, char *argv[]) { int opt; int tmpi; long long tmpl; size_t size = 0; size_t root_size = 0; unsigned int type_num = 0; char exit_at = '\0'; int do_set = 0; int do_free = 0; if (argc < 2) { USAGE(); return -1; } while ((opt = getopt(argc, argv, "r:o:t:e:sf")) != -1) { switch (opt) { case 'r': tmpl = atoll(optarg); if (tmpl < 0) { USAGE(); return -1; } root_size = (size_t)tmpl; break; case 'o': tmpl = atoll(optarg); if (tmpl < 0) { USAGE(); return -1; } size = (size_t)tmpl; break; case 't': tmpi = atoi(optarg); if (tmpi < 0) { USAGE(); return -1; } type_num = (unsigned)tmpi; break; case 'e': exit_at = optarg[0]; break; case 's': do_set = 1; break; case 'f': do_free = 1; break; default: USAGE(); return -1; } } char *file = argv[optind]; PMEMobjpool *pop; if ((pop = pmemobj_open(file, NULL)) == NULL) { fprintf(stderr, "pmemobj_open: %s\n", pmemobj_errormsg()); return -1; } if (root_size) { PMEMoid oid = pmemobj_root(pop, root_size); if (OID_IS_NULL(oid)) { fprintf(stderr, "pmemobj_root: %s\n", pmemobj_errormsg()); return -1; } } if (size) { PMEMoid oid; TX_BEGIN(pop) { oid = pmemobj_tx_alloc(size, type_num); if (exit_at == 'a') exit(1); } TX_END if (OID_IS_NULL(oid)) { fprintf(stderr, "pmemobj_tx_alloc: %s\n", pmemobj_errormsg()); return -1; } if (do_set) { TX_BEGIN(pop) { pmemobj_tx_add_range(oid, 0, size); if (exit_at == 's') exit(1); } TX_END } if (do_free) { TX_BEGIN(pop) { pmemobj_tx_free(oid); if (exit_at == 'f') exit(1); } TX_END } } pmemobj_close(pop); return 0; }