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 )