Exemplo n.º 1
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();
}
Exemplo n.º 2
0
/*
 * 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;
}
Exemplo n.º 3
0
/*
 * 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;
}
Exemplo n.º 4
0
/*
 * pocli_free -- free main context
 */
static void
pocli_free(struct pocli *pcli)
{
	while (pmemobj_tx_stage() != TX_STAGE_NONE) {
		while (pmemobj_tx_stage() != TX_STAGE_NONE)
			pmemobj_tx_process();
		pmemobj_tx_end();
	}
	pmemobj_close(pcli->ctx.pop);

	free(pcli->inbuf);
	free(pcli);
}
Exemplo n.º 5
0
/*
 * 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;
}
Exemplo n.º 6
0
int
main(int argc, char *argv[])
{
	START(argc, argv, "obj_tx_flow");

	if (argc != 2)
		FATAL("usage: %s [file]", argv[0]);

	PMEMobjpool *pop;
	if ((pop = pmemobj_create(argv[1], LAYOUT_NAME, PMEMOBJ_MIN_POOL,
	    S_IWUSR | S_IRUSR)) == NULL)
		FATAL("!pmemobj_create");

	int a = 0;
	int b = 0;
	int c = 0;

	TX_BEGIN(pop) {
		a = TEST_VALUE_A;
	} TX_ONCOMMIT {
		ASSERT(a == TEST_VALUE_A);
		b = TEST_VALUE_B;
	} TX_ONABORT { /* not called */
		a = TEST_VALUE_B;
	} TX_FINALLY {
		ASSERT(b == TEST_VALUE_B);
		c = TEST_VALUE_C;
	} TX_END

	ASSERT(a == TEST_VALUE_A);
	ASSERT(b == TEST_VALUE_B);
	ASSERT(c == TEST_VALUE_C);

	a = 0;
	b = 0;
	c = 0;

	TX_BEGIN(pop) {
		a = TEST_VALUE_A;
		pmemobj_tx_abort(EINVAL);
		a = TEST_VALUE_B;
	} TX_ONCOMMIT { /* not called */
		a = TEST_VALUE_B;
	} TX_ONABORT {
		ASSERT(a == TEST_VALUE_A);
		b = TEST_VALUE_B;
	} TX_FINALLY {
		ASSERT(b == TEST_VALUE_B);
		c = TEST_VALUE_C;
	} TX_END

	ASSERT(a == TEST_VALUE_A);
	ASSERT(b == TEST_VALUE_B);
	ASSERT(c == TEST_VALUE_C);

	a = 0;
	b = 0;
	c = 0;

	TX_BEGIN(pop) {
		TX_BEGIN(pop) {
			a = TEST_VALUE_A;
		} TX_ONCOMMIT {
			ASSERT(a == TEST_VALUE_A);
			b = TEST_VALUE_B;
		} TX_END
	} TX_ONCOMMIT {
		c = TEST_VALUE_C;
	} TX_END

	ASSERT(a == TEST_VALUE_A);
	ASSERT(b == TEST_VALUE_B);
	ASSERT(c == TEST_VALUE_C);

	a = 0;
	b = 0;
	c = 0;

	TX_BEGIN(pop) {
		a = TEST_VALUE_C;
		TX_BEGIN(pop) {
			a = TEST_VALUE_A;
			pmemobj_tx_abort(EINVAL);
			a = TEST_VALUE_B;
		} TX_ONCOMMIT { /* not called */
			a = TEST_VALUE_C;
		} TX_ONABORT {
			ASSERT(a == TEST_VALUE_A);
			b = TEST_VALUE_B;
		} TX_FINALLY {
			ASSERT(b == TEST_VALUE_B);
			c = TEST_VALUE_C;
		} TX_END
		a = TEST_VALUE_B;
	} TX_ONCOMMIT { /* not called */
		ASSERT(a == TEST_VALUE_A);
		c = TEST_VALUE_C;
	} TX_ONABORT {
		ASSERT(a == TEST_VALUE_A);
		ASSERT(b == TEST_VALUE_B);
		ASSERT(c == TEST_VALUE_C);
		a = TEST_VALUE_B;
	} TX_FINALLY {
		ASSERT(a == TEST_VALUE_B);
		b = TEST_VALUE_A;
	} TX_END

	ASSERT(a == TEST_VALUE_B);
	ASSERT(b == TEST_VALUE_A);
	ASSERT(c == TEST_VALUE_C);

	a = 0;
	b = 0;
	c = 0;

	pmemobj_tx_begin(pop, NULL, TX_LOCK_NONE);
	pmemobj_tx_abort(EINVAL);
	ASSERT(pmemobj_tx_stage() == TX_STAGE_ONABORT);
	a = TEST_VALUE_A;
	pmemobj_tx_end();

	ASSERT(a == TEST_VALUE_A);

	pmemobj_close(pop);

	DONE(NULL);
}