Alien-Libjio
view release on metacpan or search on metacpan
libjio/doc/libjio.rst view on Meta::CPAN
The rollback procedure
----------------------
First of all, rollbacking is like "undo" a commit: returns the data to the
state it had exactly before a given commit was applied. Due to the way we
handle commits, doing this operation becomes quite simple and straightforward.
In the previous section we said that each transaction held the data that was
on it before commiting. That data saved is precisely the one we need to be
able to rollback.
So, to rollback a transaction all that has to be done is recover the
previous data from the transaction we want to rollback, and save it to the
disk. In the end, this ends up being a new transaction with the previous data
as the new one, and that's how it's done: create a new transaction structure,
fill in the data from the transaction we want to rollback, and commit it. All
this is performed by jtrans_rollback().
By doing this we can provide the same warranties a commit has, it's really
fast, eases the recovery, and the code is simple and clean. What a deal.
But be aware that rollbacking is dangerous. And I really mean it: you should
only do it if you're really sure it's ok. Consider, for instance, that you
commit transaction A, then B, and then you rollback A. If A and B happen to
touch the same portion of the file, the rollback will, of course, not return
the state previous to B, but previous to A.
If it's not done safely, this can lead to major corruption. Now, if you add to
this transactions that extend the file (and thus rollbacking truncates it
back), it gets even worse. So, again, be aware, I can't stress this enough,
rollback only if you really really know what you are doing.
The recovery procedure
----------------------
Recovering from crashes is done by the jfsck() call (or the program *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
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 rollbacked, or not.
In the case the transaction file was not completely written, there is no
possibility that it has been partially applied to the disk: remember that,
from the commit procedure, we only apply the transaction after saving it in
the journal, so there is really nothing left to be done. So if the transaction
is complete, we only need to rollback.
UNIX-alike API
--------------
We call UNIX-alike API to the functions provided by the library that emulate
the good old UNIX file manipulation calls. Most of them are just wrappers
around commits, and implement proper locking when operating in order to allow
simultaneous operations (either across threads or processes). They are
described in detail in the manual pages, we'll only list them here for
completion:
- jopen()
- jread(), jpread(), jreadv()
- jwrite(), jpwrite(), jwritev()
- jtruncate()
- jclose()
ACID warranties
---------------
Database people like ACID (well, that's not news for anybody), which they say
mean "Atomicity, Consistency, Isolation, Durability".
So, even when libjio is not a purely database thing, its transactions provide
those properties. Let's take a look one by one:
Atomicity
In a transaction involving two or more discrete pieces of information,
either all of the pieces are committed or none are. This has been talked
before and we've seen how the library achieves this point, mostly based on
locks and relying on a commit procedure.
Consistency
A transaction either creates a new and valid state of data, or, if any
failure occurs, returns all data to its state before the transaction was
started. This, like atomicity, has been discussed before, specially in the
recovery section, when we saw how in case of a crash we end up with a fully
applied transaction, or no transaction applied at all.
Isolation
A transaction in process and not yet committed must remain isolated from any
other transaction. This comes as a side effect of doing proper locking on
the sections each transaction affect, and guarantees that there can't be two
transactions working on the same section at the same time.
Durability
Committed data is saved by the system such that, even in the event of a
failure, the data is available in a correct state. To provide this, libjio
relies on the disk as a method of permanent storage, and expects that when
it does syncronous I/O, data is safely written and can be recovered after a
crash.
Working from outside
--------------------
If you want, and are careful enough, you can safely use the library and still
do I/O using the regular UNIX calls.
This section provides some general guidelines that you need to follow in order
to prevent corruption. Of course you can bend or break them according to your
use, this is just a general overview on how to interact from outside.
- Lock the sections you want to use: the library, as we have already exposed,
relies on fcntl() locking; so, if you intend to operate on parts on the
file while using it, you should lock them.
- Don't truncate, unlink or rename: these operations have serious
( run in 0.622 second using v1.01-cache-2.11-cpan-5b529ec07f3 )