3.3. Two journaled files and a partial transaction

When you are working with two or more journaled files, sometimes you need to close a "partial transaction" before the global transaction has completed: this happens when you want to save the fact you tried the transaction and a rollback would erase this information. The following example will show this behavior.

Example 3-3. two_files_crash2.c

     1	#include <jf_file.h>
       
     2	int main()
     3	{
     4	        int rc;
     5	        size_t write;
     6	        jf_journal_t j;
     7	        jf_file_t jf1, jf2;
     8	        struct jf_journal_opts_s jopts;
     9	        struct jf_file_open_opts_s fopts;
    10	        const char *file1_data1 = "First string for first file\n";
    11	        const char *file1_data2 = "Second string for first file\n";
    12	        const char *file2_data1 = "First string for second file\n";
    13	        const char *file2_data2 = "Second string for second file\n";
    14	        int x, y;
       
    15	        jf_set_default_journal_opts(&jopts);
    16	        jopts.flags |= JF_JOURNAL_PROP_OPEN_O_CREAT |
    17	                JF_JOURNAL_PROP_OPEN_O_EXCL;
    18	        rc = jf_journal_open(&j, "jf_tut_foo-journal", 2, &jopts);
    19	        if (JF_RC_OK != rc) {
    20	                printf("%d/%s\n", rc, jf_strerror(rc));
    21	                return 1;
    22	        }
       
    23	        jf_set_default_file_open_opts(&fopts);
    24	        fopts.join_the_journal = TRUE;
       
    25	        rc = jf_file_open(&jf1, &j, "jf_tut_foo-data1", "w", &fopts);
    26	        if (JF_RC_OK != rc) {
    27	                printf("%d/%s\n", rc, jf_strerror(rc));
    28	                return 1;
    29	        }
    30	        rc = jf_file_open(&jf2, &j, "jf_tut_foo-data2", "w", &fopts);
    31	        if (JF_RC_OK != rc) {
    32	                printf("%d/%s\n", rc, jf_strerror(rc));
    33	                return 1;
    34	        }
       
    35	        rc = jf_file_write(&jf1, file1_data1, strlen(file1_data1),
    36	                           &write);
    37	        if (JF_RC_OK != rc) {
    38	                printf("%d/%s\n", rc, jf_strerror(rc));
    39	                return 1;
    40	        }
    41	        rc = jf_file_write(&jf2, file2_data1, strlen(file2_data1),
    42	                           &write);
    43	        if (JF_RC_OK != rc) {
    44	                printf("%d/%s\n", rc, jf_strerror(rc));
    45	                return 1;
    46	        }
    47	        rc = jf_file_commit(&jf2);
    48	        if (JF_RC_OK != rc) {
    49	                printf("%d/%s\n", rc, jf_strerror(rc));
    50	                return 1;
    51	        }
       
    52	        rc = jf_file_write(&jf1, file1_data2, strlen(file1_data2),
    53	                           &write);
    54	        if (JF_RC_OK != rc) {
    55	                printf("%d/%s\n", rc, jf_strerror(rc));
    56	                return 1;
    57	        }
    58	        rc = jf_file_write(&jf2, file2_data2, strlen(file2_data2),
    59	                           &write);
    60	        if (JF_RC_OK != rc) {
    61	                printf("%d/%s\n", rc, jf_strerror(rc));
    62	                return 1;
    63	        }
    64	        /* a fool crash simulation */
    65	        x = 0; y = 5;
    66	        while (TRUE)
    67	                x += 5 / y--;
    68	        printf("This should not print x = %d\n", x);
       
    69	        rc = jf_file_close(&jf1);
    70	        if (JF_RC_OK != rc) {
    71	                printf("%d/%s\n", rc, jf_strerror(rc));
    72	                return 1;
    73	        }
    74	        rc = jf_file_close(&jf2);
    75	        if (JF_RC_OK != rc) {
    76	                printf("%d/%s\n", rc, jf_strerror(rc));
    77	                return 1;
    78	        }
       
    79	        rc = jf_journal_close(&j);
    80	        if (JF_RC_OK != rc) {
    81	                printf("%d/%s\n", rc, jf_strerror(rc));
    82	                return 1;
    83	        }
       
    84	        printf("two_files_crash II program ended OK!\n");
    85	        return 0;
    86	}
      

At row 47, we changed jf_journal_commit(&j) with jf_file_commit(&jf2): instead of committing the whole "unit of work", we decided to commit only the changes operated against jf2.

The source two_files_crash2.c can be compiled with this command:

libtool --mode=link gcc -Wall -I/opt/libjf/include -L/opt/libjf/lib -ljf \
        -o two_files_crash2 two_files_crash2.c
    
execute it after you have deleted journal and journaled files created by two_files_crash:
tiian@linux:~/tutorial> rm jf_tut_foo-*
tiian@linux:~/tutorial> ./two_files_crash2
Floating point exception
    
take a look to files produced by two_files_crash2:
tiian@linux:~/tutorial> ls -la jf_tut_foo-*
-rw-r--r--  1 tiian users     0 2005-08-12 22:37 jf_tut_foo-data1
-rw-r--r--  1 tiian users    29 2005-08-12 22:37 jf_tut_foo-data2
-rw-r--r--  1 tiian users 16561 2005-08-12 22:37 jf_tut_foo-journal
tiian@linux:~/tutorial> cat jf_tut_foo-data2
First string for second file
    
first journaled file is empty because no data has been committed to it, second journaled file contains the first string because a partial commit has been performed.

Can libjf commit/rollback a random set of journaled files? At the time of this writing, libjf can commit/rollback only:

In the future a partial commit/rollback could be implemented: it requires a partial rewrite of some core functions, but the design of libjf and the actual implementation do not obstacle this interesting feature.