static void test_allocs(PMEMobjpool *pop, const char *path) { PMEMoid oid[TEST_ALLOC_SIZE]; if (pmemobj_alloc(pop, &oid[0], 0, 0, NULL, NULL) == 0) UT_FATAL("pmemobj_alloc(0) succeeded"); for (int i = 1; i < TEST_ALLOC_SIZE; ++i) { struct cargs args = { i }; if (pmemobj_alloc(pop, &oid[i], i, 0, test_constructor, &args) != 0) UT_FATAL("!pmemobj_alloc"); UT_ASSERT(!OID_IS_NULL(oid[i])); } pmemobj_close(pop); UT_ASSERT(pmemobj_check(path, LAYOUT_NAME) == 1); UT_ASSERT((pop = pmemobj_open(path, LAYOUT_NAME)) != NULL); for (int i = 1; i < TEST_ALLOC_SIZE; ++i) { pmemobj_free(&oid[i]); UT_ASSERT(OID_IS_NULL(oid[i])); } }
/* * test_open -- in the open test we should be able to allocate exactly * one object. */ static void test_open(const char *path) { PMEMobjpool *pop; if ((pop = pmemobj_open(path, LAYOUT_NAME)) == NULL) UT_FATAL("!pmemobj_open: %s", path); int ret = pmemobj_alloc(pop, NULL, ALLOC_SIZE, 0, NULL, NULL); UT_ASSERTeq(ret, 0); ret = pmemobj_alloc(pop, NULL, ALLOC_SIZE, 0, NULL, NULL); UT_ASSERTne(ret, 0); pmemobj_close(pop); }
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; } } }
int main(int argc, char *argv[]) { START(argc, argv, "obj_direct"); if (argc != 3) FATAL("usage: %s [directory] [# of pools]", argv[0]); int npools = atoi(argv[2]); const char *dir = argv[1]; int r; PMEMobjpool *pops[npools]; char path[MAX_PATH_LEN]; for (int i = 0; i < npools; ++i) { snprintf(path, MAX_PATH_LEN, "%s/testfile%d", dir, i); pops[i] = pmemobj_create(path, LAYOUT_NAME, PMEMOBJ_MIN_POOL, S_IWUSR | S_IRUSR); if (pops[i] == NULL) FATAL("!pmemobj_create"); } PMEMoid oids[npools]; PMEMoid tmpoids[npools]; oids[0] = OID_NULL; ASSERTeq(pmemobj_direct(oids[0]), NULL); for (int i = 0; i < npools; ++i) { oids[i] = (PMEMoid) {pops[i]->uuid_lo, 0}; ASSERTeq(pmemobj_direct(oids[i]), NULL); uint64_t off = pops[i]->heap_offset; oids[i] = (PMEMoid) {pops[i]->uuid_lo, off}; ASSERTeq(pmemobj_direct(oids[i]) - off, pops[i]); r = pmemobj_alloc(pops[i], &tmpoids[i], 100, 1, NULL, NULL); ASSERTeq(r, 0); } for (int i = 0; i < npools; ++i) { ASSERTne(pmemobj_direct(tmpoids[i]), NULL); pmemobj_free(&tmpoids[i]); ASSERTeq(pmemobj_direct(tmpoids[i]), NULL); pmemobj_close(pops[i]); ASSERTeq(pmemobj_direct(oids[i]), NULL); } DONE(NULL); }
static void test_lazy_load(PMEMobjpool *pop, const char *path) { PMEMoid oid[3]; int ret = pmemobj_alloc(pop, &oid[0], LAZY_LOAD_SIZE, 0, NULL, NULL); UT_ASSERTeq(ret, 0); ret = pmemobj_alloc(pop, &oid[1], LAZY_LOAD_SIZE, 0, NULL, NULL); UT_ASSERTeq(ret, 0); ret = pmemobj_alloc(pop, &oid[2], LAZY_LOAD_SIZE, 0, NULL, NULL); UT_ASSERTeq(ret, 0); pmemobj_close(pop); UT_ASSERT((pop = pmemobj_open(path, LAYOUT_NAME)) != NULL); pmemobj_free(&oid[1]); ret = pmemobj_alloc(pop, &oid[1], LAZY_LOAD_BIG_SIZE, 0, NULL, NULL); UT_ASSERTeq(ret, 0); }
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); }
static void * oom_worker(void *arg) { allocated = 0; while (pmemobj_alloc(pop, NULL, TEST_ALLOC_SIZE, 0, NULL, NULL) == 0) allocated++; PMEMoid iter, iter2; int type; POBJ_FOREACH_SAFE(pop, iter, iter2, type) pmemobj_free(&iter); return NULL; }
void make_persistent_atomic(pool_base &pool, typename detail::pp_if_array<T>::type &ptr, std::size_t N) { typedef typename detail::pp_array_type<T>::type I; auto ret = pmemobj_alloc(pool.get_handle(), ptr.raw_ptr(), sizeof(I) * N, detail::type_num<I>(), &detail::array_constructor<I>, static_cast<void *>(&N)); if (ret != 0) throw std::bad_alloc(); }
/* * pmemlog_append -- add data to a log memory pool */ int pmemlog_append(PMEMlogpool *plp, const void *buf, size_t count) { PMEMobjpool *pop = (PMEMobjpool *)plp; struct create_args args = { count, buf }; size_t obj_size = sizeof(size_t) + count; /* alloc-construct to an internal list */ PMEMoid obj; pmemobj_alloc(pop, &obj, obj_size, 0, create_log_entry, &args); return 0; }
static void test_alloc(PMEMobjpool *pop, size_t size) { unsigned long cnt = 0; while (1) { struct cargs args = { size }; if (pmemobj_alloc(pop, NULL, size, 0, test_constructor, &args) != 0) break; cnt++; } OUT("size: %zu allocs: %lu", size, cnt); }
/* * 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; /* append the data */ for (int i = 0; i < iovcnt; ++i) { struct create_args args = { iov[i].iov_len, iov[i].iov_base }; size_t obj_size = sizeof(size_t) + args.size; /* alloc-construct to an internal list */ pmemobj_alloc(pop, NULL, obj_size, 0, create_log_entry, &args); } return 0; }
static void test_all_classes(PMEMobjpool *pop) { for (int i = 1; i <= MAX_BUCKET_MAP_ENTRIES; ++i) { int err; int nallocs = 0; while ((err = pmemobj_alloc(pop, NULL, i * ALLOC_BLOCK_SIZE, 0, NULL, NULL)) == 0) { nallocs++; } UT_ASSERT(nallocs > 0); PMEMoid iter, niter; POBJ_FOREACH_SAFE(pop, iter, niter) { pmemobj_free(&iter); } }
/* * test_create -- allocate all possible objects and log the number. It should * exceed what would be possible on a single zone. * Additionally, free one object so that we can later check that it can be * allocated after the next open. */ static void test_create(const char *path) { PMEMobjpool *pop = NULL; if ((pop = pmemobj_create(path, LAYOUT_NAME, 0, S_IWUSR | S_IRUSR)) == NULL) UT_FATAL("!pmemobj_create: %s", path); PMEMoid oid; int n = 0; while (1) { if (pmemobj_alloc(pop, &oid, ALLOC_SIZE, 0, NULL, NULL) != 0) break; n++; } UT_OUT("allocated: %d", n); pmemobj_free(&oid); pmemobj_close(pop); }
/* * pobj_init_worker -- worker initialization */ static int pobj_init_worker(struct benchmark *bench, struct benchmark_args *args, struct worker_info *worker) { size_t i, idx = worker->index; auto *bench_priv = (struct pobj_bench *)pmembench_get_priv(bench); auto *pw = (struct pobj_worker *)calloc(1, sizeof(struct pobj_worker)); if (pw == nullptr) { perror("calloc"); return -1; } worker->priv = pw; pw->oids = (PMEMoid *)calloc(bench_priv->args_priv->n_objs, sizeof(PMEMoid)); if (pw->oids == nullptr) { free(pw); perror("calloc"); return -1; } PMEMobjpool *pop = bench_priv->pop[bench_priv->pool(idx)]; for (i = 0; i < bench_priv->args_priv->n_objs; i++) { size_t size = bench_priv->fn_size(bench_priv, i); size_t type = bench_priv->fn_type_num(bench_priv, idx, i); if (pmemobj_alloc(pop, &pw->oids[i], size, type, nullptr, nullptr) != 0) { perror("pmemobj_alloc"); goto out; } } return 0; out: for (; i > 0; i--) pmemobj_free(&pw->oids[i - 1]); free(pw->oids); free(pw); return -1; }
int main(int argc, char *argv[]) { START(argc, argv, "obj_direct"); if (argc != 3) FATAL("usage: %s [directory] [# of pools]", argv[0]); int npools = atoi(argv[2]); const char *dir = argv[1]; int r; PMEMobjpool *pops[npools]; char path[MAX_PATH_LEN]; for (int i = 0; i < npools; ++i) { snprintf(path, MAX_PATH_LEN, "%s/testfile%d", dir, i); pops[i] = pmemobj_create(path, LAYOUT_NAME, PMEMOBJ_MIN_POOL, S_IWUSR | S_IRUSR); if (pops[i] == NULL) FATAL("!pmemobj_create"); } PMEMoid oids[npools]; PMEMoid tmpoids[npools]; oids[0] = OID_NULL; ASSERTeq(pmemobj_direct(oids[0]), NULL); for (int i = 0; i < npools; ++i) { oids[i] = (PMEMoid) {pops[i]->uuid_lo, 0}; ASSERTeq(pmemobj_direct(oids[i]), NULL); uint64_t off = pops[i]->heap_offset; oids[i] = (PMEMoid) {pops[i]->uuid_lo, off}; ASSERTeq((char *)pmemobj_direct(oids[i]) - off, (char *)pops[i]); r = pmemobj_alloc(pops[i], &tmpoids[i], 100, 1, NULL, NULL); ASSERTeq(r, 0); } r = pmemobj_alloc(pops[0], &thread_oid, 100, 2, NULL, NULL); ASSERTeq(r, 0); ASSERTne(pmemobj_direct(thread_oid), NULL); pthread_mutex_lock(&lock); pthread_t t; pthread_create(&t, NULL, test_worker, NULL); /* wait for the thread to perform the first direct */ while (flag) ; for (int i = 0; i < npools; ++i) { ASSERTne(pmemobj_direct(tmpoids[i]), NULL); pmemobj_free(&tmpoids[i]); ASSERTeq(pmemobj_direct(tmpoids[i]), NULL); pmemobj_close(pops[i]); ASSERTeq(pmemobj_direct(oids[i]), NULL); } pthread_mutex_unlock(&lock); pthread_join(t, NULL); DONE(NULL); }
int main(int argc, char *argv[]) { START(argc, argv, "obj_direct"); if (argc != 3) UT_FATAL("usage: %s [directory] [# of pools]", argv[0]); int npools = atoi(argv[2]); const char *dir = argv[1]; int r; PMEMobjpool *pops[npools]; void *guard_after[npools]; char path[MAX_PATH_LEN]; for (int i = 0; i < npools; ++i) { snprintf(path, MAX_PATH_LEN, "%s/testfile%d", dir, i); pops[i] = pmemobj_create(path, LAYOUT_NAME, PMEMOBJ_MIN_POOL, S_IWUSR | S_IRUSR); /* * Reserve a page after the pool for address checks, if it * doesn't map precisely at that address - it's OK. */ guard_after[i] = MMAP((char *)pops[i] + PMEMOBJ_MIN_POOL, Ut_pagesize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); UT_ASSERTne(guard_after[i], NULL); if (pops[i] == NULL) UT_FATAL("!pmemobj_create"); } PMEMoid oids[npools]; for (int i = 0; i < npools; ++i) { r = pmemobj_alloc(pops[i], &oids[i], ALLOC_SIZE, 1, NULL, NULL); UT_ASSERTeq(r, 0); } PMEMoid invalid = {123, 321}; UT_ASSERTeq(pmemobj_pool_by_oid(OID_NULL), NULL); UT_ASSERTeq(pmemobj_pool_by_oid(invalid), NULL); for (int i = 0; i < npools; ++i) { UT_ASSERTeq(pmemobj_pool_by_oid(oids[i]), pops[i]); } UT_ASSERTeq(pmemobj_pool_by_ptr(NULL), NULL); UT_ASSERTeq(pmemobj_pool_by_ptr((void *)0xCBA), NULL); for (int i = 0; i < npools; ++i) { void *before_pool = (char *)pops[i] - 1; void *after_pool = (char *)pops[i] + PMEMOBJ_MIN_POOL + 1; void *edge = (char *)pops[i] + PMEMOBJ_MIN_POOL; void *middle = (char *)pops[i] + (PMEMOBJ_MIN_POOL / 2); void *in_oid = (char *)pmemobj_direct(oids[i]) + (ALLOC_SIZE / 2); UT_ASSERTeq(pmemobj_pool_by_ptr(before_pool), NULL); UT_ASSERTeq(pmemobj_pool_by_ptr(after_pool), NULL); UT_ASSERTeq(pmemobj_pool_by_ptr(edge), NULL); UT_ASSERTeq(pmemobj_pool_by_ptr(middle), pops[i]); UT_ASSERTeq(pmemobj_pool_by_ptr(in_oid), pops[i]); pmemobj_close(pops[i]); UT_ASSERTeq(pmemobj_pool_by_ptr(middle), NULL); UT_ASSERTeq(pmemobj_pool_by_ptr(in_oid), NULL); MUNMAP(guard_after[i], Ut_pagesize); } DONE(NULL); }
POBJ_ZREALLOC(pop, &node_constructed, struct dummy_node_c, sizeof(struct dummy_node_c) + 2000); UT_ASSERTeq(pmemobj_type_num(node_constructed.oid), TOID_TYPE_NUM(struct dummy_node_c)); POBJ_FREE(&node_constructed); POBJ_ZALLOC(pop, &node_zeroed, struct dummy_node, sizeof(struct dummy_node)); POBJ_FREE(&node_zeroed); int err = 0; err = pmemobj_alloc(pop, NULL, SIZE_MAX, 0, NULL, NULL); UT_ASSERTeq(err, -1); UT_ASSERTeq(errno, ENOMEM); err = pmemobj_zalloc(pop, NULL, SIZE_MAX, 0); UT_ASSERTeq(err, -1); UT_ASSERTeq(errno, ENOMEM); err = pmemobj_alloc(pop, NULL, PMEMOBJ_MAX_ALLOC_SIZE + 1, 0, NULL, NULL); UT_ASSERTeq(err, -1); UT_ASSERTeq(errno, ENOMEM); err = pmemobj_zalloc(pop, NULL, PMEMOBJ_MAX_ALLOC_SIZE + 1, 0); UT_ASSERTeq(err, -1); UT_ASSERTeq(errno, ENOMEM);
/* * do_alloc -- wrapper for pmemobj_alloc() function with default constructor. */ static int do_alloc(PMEMobjpool *pop, PMEMoid *oidp, size_t size, uint64_t type_num) { return pmemobj_alloc(pop, oidp, size, type_num, NULL, NULL); }
int main(int argc, char *argv[]) { START(argc, argv, "obj_constructor"); if (argc != 2) UT_FATAL("usage: %s file-name", argv[0]); const char *path = argv[1]; PMEMobjpool *pop = NULL; int ret; TOID(struct root) root; TOID(struct node) node; if ((pop = pmemobj_create(path, POBJ_LAYOUT_NAME(constr), 0, S_IWUSR | S_IRUSR)) == NULL) UT_FATAL("!pmemobj_create: %s", path); /* * Allocate memory until OOM, so we can check later if the alloc * cancellation didn't damage the heap in any way. */ int allocs = 0; while (pmemobj_alloc(pop, NULL, sizeof (struct node), 1, NULL, NULL) == 0) allocs++; UT_ASSERTne(allocs, 0); PMEMoid oid; PMEMoid next; POBJ_FOREACH_SAFE(pop, oid, next) pmemobj_free(&oid); errno = 0; root.oid = pmemobj_root_construct(pop, sizeof (struct root), root_constr_cancel, NULL); UT_ASSERT(TOID_IS_NULL(root)); UT_ASSERTeq(errno, ECANCELED); errno = 0; ret = pmemobj_alloc(pop, NULL, sizeof (struct node), 1, node_constr_cancel, NULL); UT_ASSERTeq(ret, -1); UT_ASSERTeq(errno, ECANCELED); /* the same number of allocations should be possible. */ while (pmemobj_alloc(pop, NULL, sizeof (struct node), 1, NULL, NULL) == 0) allocs--; UT_ASSERTeq(allocs, 0); POBJ_FOREACH_SAFE(pop, oid, next) pmemobj_free(&oid); root.oid = pmemobj_root_construct(pop, sizeof (struct root), NULL, NULL); UT_ASSERT(!TOID_IS_NULL(root)); errno = 0; node.oid = pmemobj_list_insert_new(pop, offsetof(struct node, next), &D_RW(root)->list, OID_NULL, 0, sizeof (struct node), 1, node_constr_cancel, NULL); UT_ASSERT(TOID_IS_NULL(node)); UT_ASSERTeq(errno, ECANCELED); pmemobj_close(pop); DONE(NULL); }
int main(int argc, char *argv[]) { START(argc, argv, "obj_direct"); if (argc != 3) UT_FATAL("usage: %s [directory] [# of pools]", argv[0]); int npools = atoi(argv[2]); const char *dir = argv[1]; int r; pthread_mutex_init(&lock1, NULL); pthread_mutex_init(&lock2, NULL); pthread_cond_init(&sync_cond1, NULL); pthread_cond_init(&sync_cond2, NULL); cond1 = cond2 = 0; PMEMobjpool **pops = MALLOC(npools * sizeof(PMEMobjpool *)); UT_ASSERTne(pops, NULL); char path[MAX_PATH_LEN]; for (int i = 0; i < npools; ++i) { snprintf(path, MAX_PATH_LEN, "%s/testfile%d", dir, i); pops[i] = pmemobj_create(path, LAYOUT_NAME, PMEMOBJ_MIN_POOL, S_IWUSR | S_IRUSR); if (pops[i] == NULL) UT_FATAL("!pmemobj_create"); } PMEMoid *oids = MALLOC(npools * sizeof(PMEMoid)); UT_ASSERTne(oids, NULL); PMEMoid *tmpoids = MALLOC(npools * sizeof(PMEMoid)); UT_ASSERTne(tmpoids, NULL); oids[0] = OID_NULL; UT_ASSERTeq(pmemobj_direct(oids[0]), NULL); for (int i = 0; i < npools; ++i) { oids[i] = (PMEMoid) {pops[i]->uuid_lo, 0}; UT_ASSERTeq(pmemobj_direct(oids[i]), NULL); uint64_t off = pops[i]->heap_offset; oids[i] = (PMEMoid) {pops[i]->uuid_lo, off}; UT_ASSERTeq((char *)pmemobj_direct(oids[i]) - off, (char *)pops[i]); r = pmemobj_alloc(pops[i], &tmpoids[i], 100, 1, NULL, NULL); UT_ASSERTeq(r, 0); } r = pmemobj_alloc(pops[0], &thread_oid, 100, 2, NULL, NULL); UT_ASSERTeq(r, 0); UT_ASSERTne(pmemobj_direct(thread_oid), NULL); pthread_t t; PTHREAD_CREATE(&t, NULL, test_worker, NULL); /* wait for the worker thread to perform the first check */ pthread_mutex_lock(&lock1); while (!cond1) pthread_cond_wait(&sync_cond1, &lock1); pthread_mutex_unlock(&lock1); for (int i = 0; i < npools; ++i) { UT_ASSERTne(pmemobj_direct(tmpoids[i]), NULL); pmemobj_free(&tmpoids[i]); UT_ASSERTeq(pmemobj_direct(tmpoids[i]), NULL); pmemobj_close(pops[i]); UT_ASSERTeq(pmemobj_direct(oids[i]), NULL); } /* signal the worker that we're free and closed */ pthread_mutex_lock(&lock2); cond2 = 1; pthread_cond_signal(&sync_cond2); pthread_mutex_unlock(&lock2); PTHREAD_JOIN(t, NULL); pthread_cond_destroy(&sync_cond1); pthread_cond_destroy(&sync_cond2); pthread_mutex_destroy(&lock1); pthread_mutex_destroy(&lock2); FREE(pops); FREE(tmpoids); FREE(oids); DONE(NULL); }