/* * 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_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_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; }
/* * 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 * tx_snap(void *arg) { volatile int locked; for (int i = 0; i < LOOPS; ++i) { locked = 0; TX_BEGIN(pop) { pthread_mutex_lock(&mtx); locked = 1; if (!OID_IS_NULL(tab)) pmemobj_tx_add_range(tab, 0, 8); } TX_ONCOMMIT { if (locked) pthread_mutex_unlock(&mtx); } TX_ONABORT { if (locked) pthread_mutex_unlock(&mtx); } TX_END locked = 0; } return NULL; }
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; }