Alien-Libjio
view release on metacpan or search on metacpan
libjio/doc/guide.rst view on Meta::CPAN
to use the library. It's not a replacement for the man page or reading the
code, but is a good starting point for everyone who wants to get involved with
it.
The library is not complex to use at all, and the interfaces were designed to
be as intuitive as possible, so the text is structured as a guide to present
the reader all the common structures and functions the way they're normally
used.
Definitions
-----------
This is a library which provides a transaction-oriented I/O API.
We say this is a transaction-oriented API because we make transactions the
center of our operations, and journaled because we use a journal (which takes
the form of a directory with files on it) to guarantee coherency even after a
crash at any point.
In this document, we think of a transaction as a list of *(buffer, length,
offset)* to be written to a file. That triplet is called an *operation*, so we
can say that a transaction represents an ordered group of operations on the
same file.
The act of *committing* a transaction means writing all the elements of that
list; and *rolling back* means to undo a previous commit, and leave the data
just as it was before doing the commit.
The library provides several guarantees, the most relevant and useful being
that at any point of time, even if the machine crash horribly, a transaction
will be either fully applied or not applied at all.
To achieve this, the library uses what is called a journal, a very vague and
fashionable term we use to describe a set of auxiliary files that get created
to store temporary data at several stages. The proper definition and how we
use them is outside the scope of this document, and you as a programmer
shouldn't need to deal with it. In case you're curious, it's described in a
bit more detail in another text which talks about how the library works
internally.
The data types
--------------
libjio has two basic opaque types which have a very strong relationship, and
represent the essential objects it deals with. Note that you don't manipulate
them directly, but use them through the API.
The first is *jfs_t*, usually called the file structure, and it represents an
open file, just like a regular file descriptor or a *FILE **.
Then second is *jtrans_t*, usually called the transaction structure, which
represents a single transaction.
Basic operation
---------------
First of all, as with regular I/O, you need to open your files. This is done
with *jopen()*, which looks a lot like *open()* but returns a file structure
instead of a file descriptor (this will be very common among all the
functions), and adds a new parameter *jflags* that can be used to modify some
library behaviour we'll see later, and is normally not used.
Now that you have opened a file, the next thing to do would be to create a
transaction. This is what *jtrans_new()* is for: it takes a file structure and
returns a new transaction structure.
To add a write operation to the transaction, use *jtrans_add_w()*. You can add
as many operations as you want. Operations within a transaction may overlap,
and will be applied in order.
Finally, to apply our transaction to the file, use *jtrans_commit()*.
When you're done using the file, call *jclose()*.
Let's put it all together and code a nice "hello world" program (return values
are ignored for simplicity)::
char buf[] = "Hello world!";
jfs_t *file;
jtrans_t *trans;
file = jopen("filename", O_RDWR | O_CREAT, 0600, 0);
trans = jtrans_new(file, 0);
jtrans_add_w(trans, buf, strlen(buf), 0);
jtrans_commit(trans);
jtrans_free(trans);
jclose(file);
As we've seen, you open the file and initialize the structure with *jopen()*
(with the parameter *jflags* being the last 0), create a new transaction with
*jtrans_new()*, then add an operation with *jtrans_add_w()* (the last 0 is the
offset, in this case the beginning of the file), commit the transaction with
*jtrans_commit()*, free it with *jtrans_free()*, and finally close the file
with *jclose()*.
Reading is much easier: the library provides three functions, *jread()*,
*jpread()* and *jreadv()*, that behave exactly like *read()*, *pread()* and
*readv()*, except that they play safe with libjio's writing code. You should
use these to read from files when using libjio.
You can also add read operations to a transaction using *jtrans_add_r()*, and
the data will be read atomically at commit time.
Integrity checking and recovery
-------------------------------
An essential part of the library is taking care of recovering from crashes and
be able to assure a file is consistent. When you're working with the file,
this is taking care of; but what about when you first open it? To answer that
question, the library provides you with a function named *jfsck()*, which
checks the integrity of a file and makes sure that everything is consistent.
It must be called "offline", that is when you are not actively committing and
rollbacking; it is normally done before calling *jopen()* and is **very, very
important**.
( run in 0.675 second using v1.01-cache-2.11-cpan-f03e8824b8d )