author | Alberto Bertogli
<albertito@gmail.com> 2004-07-13 21:16:43 UTC |
committer | Alberto Bertogli
<albertito@gmail.com> 2007-07-15 13:10:37 UTC |
parent | 984a6da0404a35f58b3e75e4e6787baf6c52535b |
libjio.h | +10 | -0 |
trans.c | +41 | -5 |
diff --git a/libjio.h b/libjio.h index 968038c..777b792 100644 --- a/libjio.h +++ b/libjio.h @@ -27,6 +27,7 @@ struct jfs { int jdirfd; /* journal directory file descriptor */ int jfd; /* journal's lock file descriptor */ int flags; /* journal flags */ + struct jlinger *ltrans; /* lingered transactions */ pthread_mutex_t lock; /* a soft lock used in some operations */ }; @@ -53,6 +54,13 @@ struct jtrans { struct joper *op; /* list of operations */ }; +/* lingered transaction */ +struct jlinger { + int id; /* transaction id */ + char *name; /* name of the transaction file */ + struct jlinger *next; +}; + struct jfsck_result { int total; /* total transactions files we looked at */ int invalid; /* invalid files in the journal directory */ @@ -88,6 +96,7 @@ int jtrans_add(struct jtrans *ts, const void *buf, size_t count, off_t offset); int jtrans_commit(struct jtrans *ts); int jtrans_rollback(struct jtrans *ts); void jtrans_free(struct jtrans *ts); +void jsync(struct jfs *fs); int jclose(struct jfs *fs); @@ -123,6 +132,7 @@ FILE *jfsopen(struct jfs *stream, const char *mode); /* jfs constants */ #define J_NOLOCK 1 /* don't lock the file before operating on it */ #define J_NOROLLBACK 2 /* no need to read rollback information */ +#define J_LINGER 3 /* use lingering transactions */ /* jtrans constants */ #define J_COMMITED 1 /* mark a transaction as commited */ diff --git a/trans.c b/trans.c index af392f4..8c08e03 100644 --- a/trans.c +++ b/trans.c @@ -45,7 +45,7 @@ static unsigned int get_tid(struct jfs *fs) /* increment it and handle overflows */ rv = curid + 1; if (rv == 0) - rv = 1; + goto exit; /* write to the file descriptor */ r = spwrite(fs->jfd, &rv, sizeof(rv), 0); @@ -197,6 +197,7 @@ int jtrans_commit(struct jtrans *ts) char *name; unsigned char *buf_init, *bufp; struct joper *op; + struct jlinger *linger; off_t curpos = 0; size_t written = 0; @@ -355,10 +356,22 @@ int jtrans_commit(struct jtrans *ts) written += rv; } - /* the transaction has been applied, so we cleanup and remove it from - * the disk */ - free_tid(ts->fs, ts->id); - unlink(name); + if (ts->flags & J_LINGER) { + linger = malloc(sizeof(struct jlinger)); + if (linger == NULL) + goto exit; + + linger->id = id; + linger->name = strdup(name); + linger->next = ts->fs->ltrans; + + ts->fs->ltrans = linger; + } else { + /* the transaction has been applied, so we cleanup and remove + * it from the disk */ + free_tid(ts->fs, ts->id); + unlink(name); + } /* mark the transaction as commited, _after_ it was removed */ ts->flags = ts->flags | J_COMMITED; @@ -466,6 +479,7 @@ int jopen(struct jfs *fs, const char *name, int flags, int mode, int jflags) fs->fd = fd; fs->name = strdup(name); fs->flags = jflags; + fs->ltrans = NULL; /* Note on fs->lock usage: this lock is used only inside the wrappers, * and exclusively to protect the file pointer. This means that it @@ -519,9 +533,31 @@ int jopen(struct jfs *fs, const char *name, int flags, int mode, int jflags) return fd; } +/* sync a file (makes sense only if using lingering transactions) */ +void jsync(struct jfs *fs) +{ + struct jlinger *linger, *ltmp; + + fsync(fs->fd); + + linger = fs->ltrans; + while (linger != NULL) { + free_tid(fs, linger->id); + unlink(linger->name); + free(linger->name); + + ltmp = linger->next; + free(linger); + + linger = ltmp; + } +} + /* close a file */ int jclose(struct jfs *fs) { + jsync(fs); + if (close(fs->fd)) return -1; if (close(fs->jfd))