tests: Fix the glob used for the python module
[libjio.git] / doc / guide.rst
blobdf9e939cf09f3406fcd05a2ee492110cd0c6adf7
2 libjio Programmer's Guide
3 =========================
5 Introduction
6 ------------
8 This small document attempts to serve as a guide to the programmer who wants
9 to use the library. It's not a replacement for the man page or reading the
10 code, but is a good starting point for everyone who wants to get involved with
11 it.
13 The library is not complex to use at all, and the interfaces were designed to
14 be as intuitive as possible, so the text is structured as a guide to present
15 the reader all the common structures and functions the way they're normally
16 used.
19 Definitions
20 -----------
22 This is a library which provides a transaction-oriented I/O API.
24 We say this is a transaction-oriented API because we make transactions the
25 center of our operations, and journaled because we use a journal (which takes
26 the form of a directory with files on it) to guarantee coherency even after a
27 crash at any point.
29 In this document, we think of a transaction as a list of *(buffer, length,
30 offset)* to be written to a file. That triplet is called an *operation*, so we
31 can say that a transaction represents an ordered group of operations on the
32 same file.
34 The act of *committing* a transaction means writing all the elements of that
35 list; and *rolling back* means to undo a previous commit, and leave the data
36 just as it was before doing the commit.
38 The library provides several guarantees, the most relevant and useful being
39 that at any point of time, even if the machine crash horribly, a transaction
40 will be either fully applied or not applied at all.
42 To achieve this, the library uses what is called a journal, a very vague and
43 fashionable term we use to describe a set of auxiliary files that get created
44 to store temporary data at several stages. The proper definition and how we
45 use them is outside the scope of this document, and you as a programmer
46 shouldn't need to deal with it. In case you're curious, it's described in a
47 bit more detail in another text which talks about how the library works
48 internally.
51 The data types
52 --------------
54 libjio has two basic opaque types which have a very strong relationship, and
55 represent the essential objects it deals with. Note that you don't manipulate
56 them directly, but use them through the API.
58 The first is *jfs_t*, usually called the file structure, and it represents an
59 open file, just like a regular file descriptor or a *FILE **.
61 Then second is *jtrans_t*, usually called the transaction structure, which
62 represents a single transaction.
65 Basic operation
66 ---------------
68 First of all, as with regular I/O, you need to open your files. This is done
69 with *jopen()*, which looks a lot like *open()* but returns a file structure
70 instead of a file descriptor (this will be very common among all the
71 functions), and adds a new parameter *jflags* that can be used to modify some
72 library behaviour we'll see later, and is normally not used.
74 Now that you have opened a file, the next thing to do would be to create a
75 transaction. This is what *jtrans_new()* is for: it takes a file structure and
76 returns a new transaction structure.
78 To add a write operation to the transaction, use *jtrans_add_w()*. You can add
79 as many operations as you want. Operations within a transaction may overlap,
80 and will be applied in order.
82 Finally, to apply our transaction to the file, use *jtrans_commit()*.
84 When you're done using the file, call *jclose()*.
86 Let's put it all together and code a nice "hello world" program (return values
87 are ignored for simplicity)::
89   char buf[] = "Hello world!";
90   jfs_t *file;
91   jtrans_t *trans;
93   file = jopen("filename", O_RDWR | O_CREAT, 0600, 0);
95   trans = jtrans_new(file, 0);
96   jtrans_add_w(trans, buf, strlen(buf), 0);
97   jtrans_commit(trans);
98   jtrans_free(trans);
100   jclose(file);
102 As we've seen, you open the file and initialize the structure with *jopen()*
103 (with the parameter *jflags* being the last 0), create a new transaction with
104 *jtrans_new()*, then add an operation with *jtrans_add_w()* (the last 0 is the
105 offset, in this case the beginning of the file), commit the transaction with
106 *jtrans_commit()*, free it with *jtrans_free()*, and finally close the file
107 with *jclose()*.
109 Reading is much easier: the library provides three functions, *jread()*,
110 *jpread()* and *jreadv()*, that behave exactly like *read()*, *pread()* and
111 *readv()*, except that they play safe with libjio's writing code. You should
112 use these to read from files when using libjio.
114 You can also add read operations to a transaction using *jtrans_add_r()*, and
115 the data will be read atomically at commit time.
118 Integrity checking and recovery
119 -------------------------------
121 An essential part of the library is taking care of recovering from crashes and
122 be able to assure a file is consistent. When you're working with the file,
123 this is taking care of; but what about when you first open it? To answer that
124 question, the library provides you with a function named *jfsck()*, which
125 checks the integrity of a file and makes sure that everything is consistent.
127 It must be called "offline", that is when you are not actively committing and
128 rollbacking; it is normally done before calling *jopen()* and is **very, very
129 important**.
131 You can also do this manually with an utility named jiofsck, which can be used
132 from the shell to perform the checking.
135 Rollback
136 --------
138 There is a very nice and important feature in transactions, that allows them
139 to be "undone", which means that you can undo a transaction and leave the file
140 just as it was the moment before applying it. The action of undoing it is
141 called *rollback*, and the function is called *jtrans_rollback()*, which takes
142 the transaction as the only parameter.
144 Be aware that rollbacking a transaction can be dangerous if you're not careful
145 and cause you a lot of troubles. For instance, consider you have two
146 transactions (let's call them 1 and 2, and assume they were applied in that
147 order) that modify the same offset, and you rollback transaction 1; then 2
148 would be lost. It is not an dangerous operation itself, but its use requires
149 care and thought.
152 UNIX-alike API
153 --------------
155 There is a set of functions that emulate the UNIX API (*read()*, *write()*,
156 and so on) which make each operation a transaction. This can be useful if you
157 don't need to have the full power of the transactions but only to provide
158 guarantees between the different functions. They are a lot like the normal
159 UNIX functions, but instead of getting a file descriptor as their first
160 parameter they get a file structure. You can check out the manual page to see
161 the details, but they work just like their UNIX version, only that they
162 preserve atomicity and thread-safety within each call.
164 In particular, the group of functions related to reading (which was described
165 above in `Basic operation`_) are extremely useful because they take care of
166 the locking needed for the library proper behaviour. You should use them
167 instead of the regular calls.
169 The full function list is available on the man page and I won't reproduce it
170 here; however the naming is quite simple: just prepend a 'j' to all the names:
171 *jread()*, *jwrite()*, etc.
174 Processes, threads and locking
175 ------------------------------
177 The library is completely safe to use in multi-process and/or multi-thread
178 applications, as long as you abide by the following rules:
180  - Within a process, a file must not be held open at the same time more than
181    once, due to *fcntl()* locking limitations. Opening, closing and then
182    opening again is safe.
183  - *jclose()* must only be called when there are no other I/O operations in
184    progress.
185  - *jfsck()* must only be called when the file is known **not** to be open by
186    any process.
187  - *jmove_journal()* must only be called when the file is known **not** to be
188    open by any other processes.
190 All other operations (committing a transaction, rolling it back, adding
191 operations, etc.) and all the wrappers are safe and don't require any special
192 considerations.
195 Lingering transactions
196 ----------------------
198 If you need to increase performance, you can use lingering transactions. In
199 this mode, transactions take up more disk space but allows you to do the
200 synchronous write only once, making commits much faster. To use them, just add
201 *J_LINGER* to the *jflags* parameter in *jopen()*. You should call *jsync()*
202 frequently to avoid using up too much space, or start an asynchronous thread
203 that calls *jsync()* automatically using *jfs_autosync_start()*. Note that
204 files opened with this mode must not be opened by more than one process at the
205 same time.
208 Disk layout
209 -----------
211 The library creates a single directory for each file opened, named after it.
212 So if we open a file *output*, a directory named *.output.jio* will be
213 created. We call it the journal directory, and it's used internally by the
214 library to save temporary data; **you shouldn't modify any of the files that
215 are inside it, nor move it while it's in use**.
217 It doesn't grow much (it only uses space for transactions that are in the
218 process of committing) and gets automatically cleaned while working with it so
219 you can (and should) ignore it. Besides that, the file you work with has no
220 special modification and is just like any other file, all the internal stuff
221 is kept isolated on the journal directory.
224 ANSI C alike API
225 ----------------
227 Besides the UNIX-alike API you can find an ANSI C alike API, which emulates
228 the traditional *fread()*, *fwrite()*, etc. It's still in development and has
229 not been tested carefully, so I won't spend time documenting them. Let me know
230 if you need them.
233 Compiling and linking
234 ---------------------
236 If you have *pkg-config* in your build environment, then you can get the build
237 flags you need to use when building and linking against the library by
238 running::
240   pkg-config --cflags --libs libjio
242 If *pkg-config* is not available, you have to make sure your application uses
243 the Large File Support (*"LFS"* from now on), to be able to handle large files
244 properly. This means that you will have to pass some special standard flags to
245 the compiler, so your C library uses the same data types as the library. For
246 instance, on 32-bit platforms (like x86), when using LFS, offsets are usually
247 64 bits, as opposed to the usual 32.
249 The library is always built with LFS; however, linking it against an
250 application without LFS support could lead to serious problems because this
251 kind of size differences and ABI compatibility.
253 The Single Unix Specification standard proposes a simple and practical way to
254 get the flags you need to pass your C compiler to tell you want to compile
255 your application with LFS: use a program called "getconf" which should be
256 called like "getconf LFS_CFLAGS", and it outputs the appropiate parameters.
258 In the end, the command line would be something like::
260   gcc `getconf LFS_CFLAGS` app.c -ljio -o app
262 If you want more detailed information or examples, you can check out how the
263 library and sample applications get built.
266 Where to go from here
267 ---------------------
269 If you're still interested in learning more, you can find some small and clean
270 samples are in the *samples* directory (*full.c* is a simple and complete
271 one), other more advanced examples can be found in the web page, as well as
272 modifications to well known software to make use of the library. For more
273 information about the inner workings of the library, you can read the "libjio"
274 document, the internal API reference, and the source code.