jfsck-ignore_lockfile.patch
  Make jfsck() independant of the lockfile.

async_lockfile.patch
  Don't open the lockfile O_SYNC.

new_commit_proc.patch
  Change a bit the commit procedure so it doesn't include the data we're about
  to write.

header_for_c++.patch
  Add a conditional "extern C" to the header file so the library can be linked
  against C++ source.

doc_update.patch
  Update the README file.

new_tests.patch
  Upgrade and rewrite of the "tests" directory.

version-0.13.patch
  Version 0.13



unchanged:
--- cur-root/libjio.c	2004-04-30 10:11:24.000000000 -0300
+++ cur-root/libjio.c	2004-04-30 10:40:11.000000000 -0300
@@ -294,7 +294,23 @@
 	if (!(ts->fs->flags & J_NOLOCK))
 		plockf(ts->fs->fd, F_LOCK, ts->offset, ts->len);
 	
-	/* first the static data */
+	/* read the current content and fill in the transaction structure */
+	ts->pdata = malloc(ts->len);
+	if (ts->pdata == NULL)
+		goto exit;
+	
+	ts->plen = ts->len;
+
+	rv = spread(ts->fs->fd, ts->pdata, ts->len, ts->offset);
+	if (rv < 0)
+		goto exit;
+	if (rv < ts->len) {
+		/* we are extending the file! use ftruncate() to do it */
+		ftruncate(ts->fs->fd, ts->offset + ts->len);
+		ts->plen = rv;
+	}
+
+	/* now save the transaction to the file, static data first */
 	
 	buf_init = malloc(J_DISKTFIXSIZE);
 	if (buf_init == NULL)
@@ -311,6 +327,9 @@
 	memcpy(bufp, (void *) &(ts->len), sizeof(ts->len));
 	bufp += 4;
 	
+	memcpy(bufp, (void *) &(ts->plen), sizeof(ts->plen));
+	bufp += 4;
+	
 	memcpy(bufp, (void *) &(ts->ulen), sizeof(ts->ulen));
 	bufp += 4;
 	
@@ -324,7 +343,7 @@
 	free(buf_init);
 	
 	
-	/* and now the variable part */
+	/* and now the variable data */
 
 	if (ts->udata) {
 		rv = spwrite(fd, ts->udata, ts->ulen, J_DISKTFIXSIZE);
@@ -332,33 +351,9 @@
 			goto exit;
 	}
 	
-	ts->pdata = malloc(ts->len);
-	if (ts->pdata == NULL)
-		goto exit;
-	
-	ts->plen = ts->len;
-
-	/* copy the current content into the transaction file */
-	rv = spread(ts->fs->fd, ts->pdata, ts->len, ts->offset);
-	if (rv < 0)
-		goto exit;
-	if (rv < ts->len) {
-		/* we are extending the file! use ftruncate() to do it */
-		ftruncate(ts->fs->fd, ts->offset + ts->len);
-
-		ts->plen = rv;
-
-	}
-	
 	t = J_DISKTFIXSIZE + ts->ulen;
-	rv = spwrite(fd, ts->pdata, ts->len, t);
-	if (rv != ts->len)
-		goto exit;
-	
-	/* save the new data in the transaction file */
-	t = J_DISKTFIXSIZE + ts->ulen + ts->plen;
-	rv = spwrite(fd, ts->buf, ts->len, t);
-	if (rv != ts->len)
+	rv = spwrite(fd, ts->pdata, ts->plen, t);
+	if (rv != ts->plen)
 		goto exit;
 	
 	/* this is a simple but efficient optimization: instead of doing
@@ -373,13 +368,14 @@
 	if (rv != ts->len)
 		goto exit;
 	
-	/* mark the transaction as commited */
-	ts->flags = ts->flags | J_COMMITED;
-
 	/* 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;
+
 	
 exit:
 	close(fd);
@@ -404,11 +400,6 @@
 	/* copy the old transaction to the new one */
 	jtrans_init(ts->fs, &newts);
 
-	newts.name = malloc(strlen(ts->name));
-	if (newts.name == NULL)
-		return -1;
-	
-	strcpy(newts.name, ts->name);
 	newts.flags = ts->flags;
 	newts.offset = ts->offset;
 
@@ -427,8 +418,8 @@
 		
 	}
 	
-	newts.pdata = ts->buf;
-	newts.plen = ts->len;
+	newts.pdata = ts->pdata;
+	newts.plen = ts->plen;
 
 	newts.udata = ts->udata;
 	newts.ulen = ts->ulen;
@@ -481,12 +472,7 @@
 		return -1;
 	
 	snprintf(jlockfile, PATH_MAX, "%s/%s", jdir, "lock");
-	if (access(jlockfile, F_OK) != 0) {
-		/* file doesn't exists, create it */
-		jfd = open(jlockfile, O_RDWR | O_CREAT | O_SYNC, 0600);
-	} else {
-		jfd = open(jlockfile, O_RDWR | O_SYNC, 0600);
-	}
+	jfd = open(jlockfile, O_RDWR | O_CREAT, 0600);
 	if (jfd < 0)
 		return -1;
 	
@@ -694,13 +680,14 @@
 /* check the journal and replay the incomplete transactions */
 int jfsck(char *name, struct jfsck_result *res)
 {
-	int fd, jfd, tfd, rv, i, maxtid;
+	int fd, tfd, rv, i, maxtid;
 	char jdir[PATH_MAX], jlockfile[PATH_MAX], tname[PATH_MAX];
-	char *buf = NULL;
+	unsigned char *buf = NULL;
 	struct stat sinfo;
 	struct jfs fs;
 	struct jtrans *curts;
 	DIR *dir;
+	struct dirent *dent;
 	off_t offset;
 	
 	fd = open(name, O_RDWR | O_SYNC | O_LARGEFILE);
@@ -716,28 +703,32 @@
 	if (rv < 0 || !S_ISDIR(sinfo.st_mode))
 		return J_ENOJOURNAL;
 	
+	/* open the lock file, which is only used to complete the jfs
+	 * structure */
 	snprintf(jlockfile, PATH_MAX, "%s/%s", jdir, "lock");
-	jfd = open(jlockfile, O_RDWR | O_SYNC, 0600);
-	if (jfd < 0)
-		return J_ENOJOURNAL;
-	
-	lstat(jlockfile, &sinfo);
-	if (sinfo.st_size == 0)
-		return J_ENOJOURNAL;
-
-	plockf(jfd, F_LOCK, 0, 0);
-	rv = spread(jfd, &maxtid, sizeof(maxtid), 0);
-	if (rv != sizeof(maxtid)) {
+	rv = open(jlockfile, O_RDWR | O_CREAT, 0600);
+	if (rv < 0)
 		return J_ENOJOURNAL;
-	}
-	plockf(jfd, F_ULOCK, 0, 0);
-
-	fs.jfd = jfd;
+	fs.jfd = rv;
 	
 	dir = opendir(jdir);
 	if (dir == NULL)
 		return J_ENOJOURNAL;
 
+	/* loop for each file in the journal directory to find out the greater
+	 * transaction number */
+	maxtid = 0;
+	for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+		/* see if the file is named like a transaction, ignore
+		 * otherwise; as transactions are named as numbers > 0, a
+		 * simple atoi() is enough testing */
+		rv = atoi(dent->d_name);
+		if (rv <= 0)
+			continue;
+		if (rv > maxtid)
+			maxtid = rv;
+	}
+
 	/* we loop all the way up to the max transaction id */
 	for (i = 1; i <= maxtid; i++) {
 		curts = malloc(sizeof(struct jtrans));
@@ -780,20 +771,22 @@
 			free(buf);
 			goto loop;
 		}
-		
-		curts->flags = (int) *(buf + 4);
-		curts->len = (size_t) *(buf + 8);
-		curts->ulen = (size_t) *(buf + 16);
-		curts->offset = (off_t) *(buf + 20);
+
+		curts->flags = *( (uint32_t *) (buf + 4));
+		curts->len = *( (uint32_t *) (buf + 8));
+		curts->plen = *( (uint32_t *) (buf + 12));
+		curts->ulen = *( (uint32_t *) (buf + 16));
+		curts->offset = *( (uint64_t *) (buf + 20));
 
 		free(buf);
 
 		/* if we got here, the transaction was not applied, so we
 		 * check if the transaction file is complete (we only need to
-		 * apply it) or not (so we can't do anything but ignore it) */
+		 * rollback it) or not (so we can't do anything but ignore it)
+		 */
 
 		lstat(tname, &sinfo);
-		rv = J_DISKTFIXSIZE + curts->len + curts->ulen + curts->plen;
+		rv = J_DISKTFIXSIZE + curts->ulen + curts->plen;
 		if (sinfo.st_size != rv) {
 			/* the transaction file is incomplete, some of the
 			 * body is missing */
@@ -803,13 +796,7 @@
 
 		/* we have a complete transaction file which commit was not
 		 * successful, so we read it to complete the transaction
-		 * structure and apply it again */
-		curts->buf = malloc(curts->len);
-		if (curts->buf == NULL) {
-			res->load_error++;
-			goto loop;
-		}
-		
+		 * structure and rollback it */
 		curts->pdata = malloc(curts->plen);
 		if (curts->pdata == NULL) {
 			res->load_error++;
@@ -838,27 +825,15 @@
 			goto loop;
 		}
 
-		/* real data */
-		offset = J_DISKTFIXSIZE + curts->ulen + curts->plen;
-		rv = spread(tfd, curts->buf, curts->len, offset);
-		if (rv != curts->len) {
-			res->load_error++;
-			goto loop;
-		}
-
-		/* apply */
-		rv = jtrans_commit(curts);
+		/* rollback */
+		rv = jtrans_rollback(curts);
 		if (rv < 0) {
 			res->apply_error++;
 			goto loop;
 		}
-		res->reapplied++;
+		res->rollbacked++;
 
 		/* free the data we just allocated */
-		if (curts->len) {
-			free(curts->buf);
-			curts->buf = NULL;
-		}
 		if (curts->plen) {
 			free(curts->pdata);
 			curts->pdata = NULL;
unchanged:
--- cur-root/libjio.h	2004-04-30 10:40:32.000000000 -0300
+++ cur-root/libjio.h	2004-04-30 10:42:17.000000000 -0300
@@ -12,6 +12,10 @@
 #include <sys/uio.h>
 #include <pthread.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 
 /* logical structures */
 struct jfs {
@@ -44,7 +48,7 @@
 	int broken_body;	/* transactions broken (body missing) */
 	int load_error;		/* errors loading the transaction */
 	int apply_error;	/* errors applying the transaction */
-	int reapplied;		/* transactions that were re-applied */
+	int rollbacked;		/* transactions that were rollbacked */
 };
 
 /* on-disk structure */
@@ -54,13 +58,13 @@
 	uint32_t id;		/* id */
 	uint32_t flags;		/* flags about this transaction */
 	uint32_t len;		/* data lenght */
+	uint32_t plen;		/* previous data lenght */
 	uint32_t ulen;		/* user-supplied information lenght */
 	uint64_t offset;	/* offset relative to the BOF */
 	
 	/* payload (variable lenght) */
 	char *udata;		/* user-supplied data */
-	char *prevdata;		/* previous data, optional, for rollback */
-	char *data;		/* data */
+	char *prevdata;		/* previous data for rollback */
 };
 
 
@@ -93,7 +97,7 @@
 #define J_ROLLBACKED	2	/* mark a transaction as rollbacked */
 
 /* disk_trans constants */
-#define J_DISKTFIXSIZE	 24	/* lenght of disk_trans' header */ 
+#define J_DISKTFIXSIZE	 28	/* lenght of disk_trans' header */ 
 
 /* jfsck constants (return values) */
 #define J_ESUCCESS	0	/* success - shouldn't be used */
@@ -102,4 +106,9 @@
 #define J_ENOMEM	3	/* no enough free memory */
 
+
+#ifdef __cplusplus
+} /* from extern "C" avobe */
+#endif
+
 #endif
 
unchanged:
--- cur/doc/libjio.lyx~new_commit_proc	2004-04-30 10:12:44.000000000 -0300
+++ cur-root/doc/libjio.lyx	2004-04-30 10:26:13.000000000 -0300
@@ -112,9 +112,6 @@ This impose some restrictions to the kin
  over a file while it's currently being used: you can't move it (because
  the journal directory name depends on the filename) and you can't unlink
  it (for similar reasons).
- Some other operations, like truncating, are also done outside the library
- and the user is expected to do them atomically when no transactions are
- currently being done.
  
 \layout Standard
 
@@ -214,9 +211,6 @@ Read the previous data from the file
 Write the previous data in the transaction
 \layout Itemize
 
-Write the data to commit to the transaction file
-\layout Itemize
-
 Write the data to the file
 \layout Itemize
 
@@ -316,11 +310,11 @@ jiofsck
  which is just a simple invocation to that function), which opens the file
  and goes through all transactions in the journal (remember that transactions
  are removed from the journal directory after they're applied), loading
- and recommiting them if possible.
+ and rollbacking them if necessary.
  There are several steps where it can fail: there could be no journal, a
  given transaction file might be corrupted, incomplete, and so on; but in
  the end, there are two cases regarding each transaction: either it's complete
- and can be reapplied, or not.
+ and can be rollbacked, or not.
 \layout Standard
 
 In the case the transaction is not complete, there is no possibility that
@@ -330,11 +324,7 @@ In the case the transaction is not compl
 after
 \emph default 
  saving it in the journal, so there is really nothing left to be done.
-\layout Standard
-
-If the transaction is complete, we only need to recommit: if the transaction
- was either not applied at all, partially applied or completely applied,
- it makes no difference as we are now capable of completing it, and do so.
+ So if the transaction is complete, we only need to rollback.
 \layout Standard
 
 In any case, after making the recovery you can simply remove the journal
unchanged:
--- cur/jiofsck.c~new_commit_proc	2004-04-30 10:39:36.000000000 -0300
+++ cur-root/jiofsck.c	2004-04-30 10:39:53.000000000 -0300
@@ -55,7 +55,7 @@ int main(int argc, char **argv)
 	printf("Broken body:\t %d\n", res.broken_body);
 	printf("Load error:\t %d\n", res.load_error);
 	printf("Apply error:\t %d\n", res.apply_error);
-	printf("Reapplied:\t %d\n", res.reapplied);
+	printf("Rollbacked:\t %d\n", res.rollbacked);
 	printf("\n");
 	
 	printf("You can now safely remove the journal directory completely\n"
unchanged:
--- cur/README~doc_update	2004-04-30 10:58:04.000000000 -0300
+++ cur-root/README	2004-04-30 11:03:59.000000000 -0300
@@ -3,10 +3,10 @@ libjio - A library for Journaled I/O
 Alberto Bertogli (albertogli@telpin.com.ar)
 -------------------------------------------
 
-As the name says, this is a simple library to do journaled,
+As the name says, this is a simple userspace library to do journaled,
 transaction-oriented I/O.
 
-It provides a very simple transaction api to commit and rollback transactions,
+It provides a very simple transaction API to commit and rollback transactions,
 and on top of that a unix-alike set of functions to perform most regular
 operations (ie. open, read, write).
 
@@ -16,9 +16,10 @@ special directory is created to store in
 This allows both simple file manipulation, recovery and debugging because
 everything is isolated.
 
-There's a more detailed document about the library itself in doc/libjio.ps
-(or, alternatively, the ascii version doc/libjio.txt), and a manpage where you
-will find the programming reference.
+There's a more detailed document about the library itself in doc/libjio.lyx
+(to the 'LyX' editor; there are HTML, Postscript, PDF and TXT versions in the
+website, which are not included here for space reasons), and a manpage where
+you will find the programming reference.
 
 
 It is licensed under the Open Software License version 2.0.
unchanged:
--- /dev/null	2004-04-14 00:22:58.000000000 -0300
+++ cur-root/tests/README	2004-04-30 11:14:56.000000000 -0300
@@ -0,0 +1,9 @@
+
+Here you will find a small set of testing utilities for libjio that cover
+performance testing and recovery testings. They're really simple so there's
+not much documentation besides the code.
+
+Another really useful way of doing testing is using some of the well known
+filesystem benchmarking applications and modify them to use libjio. I regulary
+use Bonnie and dbench, so if you want the patches please let me know.
+
only in patch2:
unchanged:
--- cur/Make.conf~version-0.13	2004-04-30 11:17:10.000000000 -0300
+++ cur-root/Make.conf	2004-04-30 11:17:15.000000000 -0300
@@ -1,5 +1,5 @@
 
-VERSION="0.10"
+VERSION="0.13"
 
 CC = gcc
 CFLAGS += -Wall -O6 \

