Alien-Libjio

 view release on metacpan or  search on metacpan

libjio/libjio/trans.c  view on Meta::CPAN

	struct jtrans *ts;

	ts = malloc(sizeof(struct jtrans));
	if (ts == NULL)
		return NULL;

	ts->fs = fs;
	ts->id = 0;
	ts->flags = fs->flags | flags;
	ts->op = NULL;
	ts->numops_r = 0;
	ts->numops_w = 0;
	ts->len_w = 0;

	pthread_mutexattr_init(&attr);
	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
	pthread_mutex_init(&(ts->lock), &attr);
	pthread_mutexattr_destroy(&attr);

	return ts;
}

/* Free the contents of a transaction structure */
void jtrans_free(struct jtrans *ts)
{
	struct operation *tmpop;

	ts->fs = NULL;

	while (ts->op != NULL) {
		tmpop = ts->op->next;

		if (ts->op->buf && ts->op->direction == D_WRITE)
			free(ts->op->buf);
		if (ts->op->pdata)
			free(ts->op->pdata);
		free(ts->op);

		ts->op = tmpop;
	}
	pthread_mutex_destroy(&(ts->lock));

	free(ts);
}

/** Lock/unlock the ranges of the file covered by the transaction. mode must
 * be either F_LOCKW or F_UNLOCK. Returns 0 on success, -1 on error. */
static int lock_file_ranges(struct jtrans *ts, int mode)
{
	unsigned int nops;
	off_t lr, min_offset;
	struct operation *op, *start_op;

	if (ts->flags & J_NOLOCK)
		return 0;

	/* Lock/unlock always in the same order to avoid deadlocks. We will
	 * begin with the operation that has the smallest start offset, and go
	 * from there.
	 * Note that this is O(n^2), but n is usually (very) small, and we're
	 * about to do synchronous I/O, so it's not really worrying. It has a
	 * small optimization to help when the operations tend to be in the
	 * right order. */
	nops = 0;
	min_offset = 0;
	start_op = ts->op;
	while (nops < ts->numops_r + ts->numops_w) {
		for (op = start_op; op != NULL; op = op->next) {
			if (min_offset < op->offset)
				continue;
			min_offset = op->offset;
			start_op = op->next;

			if (mode == F_LOCKW) {
				lr = plockf(ts->fs->fd, F_LOCKW, op->offset, op->len);
				if (lr == -1)
					goto error;
				op->locked = 1;
			} else if (mode == F_UNLOCK && op->locked) {
				lr = plockf(ts->fs->fd, F_UNLOCK, op->offset,
						op->len);
				if (lr == -1)
					goto error;
				op->locked = 0;
			}
		}

		nops++;
	}

	return 0;

error:
	return -1;
}

/** Read the previous information from the disk into the given operation
 * structure. Returns 0 on success, -1 on error. */
static int operation_read_prev(struct jtrans *ts, struct operation *op)
{
	ssize_t rv;

	op->pdata = malloc(op->len);
	if (op->pdata == NULL)
		return -1;

	rv = spread(ts->fs->fd, op->pdata, op->len,
			op->offset);
	if (rv < 0) {
		free(op->pdata);
		op->pdata = NULL;
		return -1;
	}

	op->plen = op->len;
	if (rv < op->len) {
		/* we are extending the file! */
		/* ftruncate(ts->fs->fd, op->offset + op->len); */
		op->plen = rv;
	}



( run in 0.634 second using v1.01-cache-2.11-cpan-501a3233654 )