]> git.tuebingen.mpg.de Git - osl.git/blob - osl_core.h
9f3118114ff20c593882159efd4b688ffed632a0
[osl.git] / osl_core.h
1 /*
2  * Copyright (C) 2007-2009 Andre Noll <maan@tuebingen.mpg.de>
3  *
4  * Licensed under the GPL v2. For licencing details see COPYING.
5  */
6
7 /** \file osl_core.h Object storage layer details, not visible to users. */
8
9 #include "rbtree.h"
10 #include "hash.h"
11
12 __must_check __printf_1_2 __malloc char *make_message(const char *fmt, ...);
13
14 /** Internal representation of a column of an osl table. */
15 struct osl_column {
16         /** The memory mapping of this comumn (only used for mapped columns). */
17         struct osl_object data_map;
18         /** The root of the rbtree (only used for columns with rbtrees). */
19         struct rb_root rbtree;
20         /** The index in the array of rb nodes (only used for columns with rbtrees). */
21         unsigned rbtree_num;
22         /** Index for volatile_objects of struct osl_row. */
23         unsigned volatile_num;
24         /**
25          * Starting point of the data for this column within the index
26          * (only used for mapped columns).
27          */
28         uint16_t index_offset;
29         /**
30          * The hash value of the name of this column.
31          *
32          * This is only used for mapped and disk storage columns).
33          */
34         HASH_TYPE name_hash[HASH_SIZE];
35 };
36
37 /** Internal representation of an osl table */
38 struct osl_table {
39         /** Pointer to the table description */
40         const struct osl_table_description *desc;
41         /** The size of the index header of this table. */
42         uint16_t index_header_size;
43         /** Contains the mapping of the table's index file */
44         struct osl_object index_map;
45         /** Total number of rows, including invalid rows. */
46         unsigned num_rows;
47         /** Keeps track of the number of invalid rows in the table. */
48         uint32_t num_invalid_rows;
49         /** Number of columns of type \p OSL_MAPPED_STORAGE. */
50         unsigned num_mapped_columns;
51         /** Number of columns of type \p OSL_NO_STORAGE. */
52         unsigned num_volatile_columns;
53         /** Number of columns of type \p OSL_DISK_STORAGE. */
54         unsigned num_disk_storage_columns;
55         /** Number of columns with associated rbtree. */
56         unsigned num_rbtrees;
57         /**
58          * The number of the column that determines the name of the disk
59          * storage objects.
60          */
61         unsigned disk_storage_name_column;
62         /** The number of bytes of an index entry of a row. */
63         unsigned row_index_size;
64         /** Pointer to the internal representation of the columns. */
65         struct osl_column *columns;
66 };
67
68 /** Internal representation of a row of an osl table */
69 struct osl_row {
70         /**
71          * The row number.
72          *
73          * It is only used if there is at least one mapped column.
74          */
75         off_t num;
76         /** Array of size \a num_volatile_columns. */
77         struct osl_object *volatile_objects;
78 };
79
80 int read_table_desc(struct osl_object *map, struct osl_table_description *desc);
81 int init_table_structure(const struct osl_table_description *desc,
82                 struct osl_table **table_ptr);
83 int row_is_invalid(struct osl_table *t, uint32_t row_num);
84 int get_mapped_object(const struct osl_table *t, unsigned col_num,
85         uint32_t row_num, struct osl_object *obj);
86 int unmap_table(struct osl_table *t, enum osl_close_flags flags);
87 int init_rbtrees(struct osl_table *t);
88
89 /**
90  * Flags to be specified for map_table().
91  *
92  * \sa map_table().
93  */
94 enum map_table_flags {
95         /**
96          * Check whether the entries in the table index match the entries in
97          * the table description.
98          */
99         MAP_TBL_FL_VERIFY_INDEX = 1,
100         /** Do not complain even if the dirty flag is set. */
101         MAP_TBL_FL_IGNORE_DIRTY = 2,
102         /** Use read-only mappings. */
103         MAP_TBL_FL_MAP_RDONLY = 4
104 };
105
106 int map_table(struct osl_table *t, enum map_table_flags flags);
107 void clear_rbtrees(struct osl_table *t);
108 int mark_row_invalid(struct osl_table *t, uint32_t row_num);
109
110
111 /**
112  * Get the description of a column by column number
113  *
114  * \param d Pointer to the table description.
115  * \param col_num The number of the column to get the description for.
116  *
117  * \return The table description.
118  *
119  * \sa struct osl_column_description.
120  */
121 _static_inline_ struct osl_column_description *get_column_description(
122                 const struct osl_table_description *d, unsigned col_num)
123 {
124         return &d->column_descriptions[col_num];
125 }
126
127 /**
128  * Format of the header of the index file of an osl table.
129  *
130  * Bytes 16-31 are currently unused.
131  *
132  * \sa enum index_column_desc_offsets, HASH_SIZE, osl_table_flags.
133  */
134 enum index_header_offsets {
135         /** Bytes 0-8: PARASLASH. */
136         IDX_OSL_MAGIC = 0,
137         /** Byte 9: Dirty flag (nonzero if table is mapped). */
138         IDX_DIRTY_FLAG = 9,
139         /** Byte 10: osl table version number. */
140         IDX_VERSION = 10,
141         /** Byte 11: Table flags.*/
142         IDX_TABLE_FLAGS = 11,
143         /** Byte 12,13: Number of columns. */
144         IDX_NUM_COLUMNS,
145         /** Byte 14,15 Size of the index header. */
146         IDX_HEADER_SIZE = 14,
147         /** Column descriptions start here. */
148         IDX_COLUMN_DESCRIPTIONS = 32
149 };
150
151 /**
152  * Format of the column description in the index header.
153  *
154  * \sa index_header_offsets.
155  */
156 enum index_column_desc_offsets {
157         /** Bytes 0,1: Storage_type. */
158         IDX_CD_STORAGE_TYPE = 0,
159         /** Bytes 2,3: Storage_flags. */
160         IDX_CD_STORAGE_FLAGS = 2,
161         /** Bytes 4 - 7: Data_size (only used for fixed size columns). */
162         IDX_CD_DATA_SIZE = 4,
163         /** Bytes 8 - ... Name of the column. */
164         IDX_CD_NAME = 8,
165 };
166
167 /** Magic string contained in the header of the index file of each osl table. */
168 #define OSL_MAGIC "PARASLASH"
169
170 /**
171  * The minimal number of bytes for a column in the index header.
172  *
173  * The column name starts at byte IDX_CD_NAME and must at least contain one
174  * character, plus the terminating NULL byte.
175   */
176 #define MIN_IDX_COLUMN_DESCRIPTION_SIZE (IDX_CD_NAME + 2)
177
178 /**
179  * Get the number of bytes used for a column in the index header.
180  *
181  * \param name The name of the column.
182  *
183  * The amount of space used for a column in the index header of a table depends
184  * on the (length of the) name of the column.
185  *
186  * \return The total number of bytes needed to store one column of this name.
187  */
188 _static_inline_ size_t index_column_description_size(const char *name)
189 {
190         return MIN_IDX_COLUMN_DESCRIPTION_SIZE + strlen(name) - 1;
191 }
192
193 /*
194  * The version used by this instance of the library. Written to the index of
195  * newly created tables.
196  */
197 #define CURRENT_TABLE_VERSION 1
198
199 /*
200  * The lowest table version this library understands. On open, if
201  * current_version(table) < min_version(lib) the osl_open_table() call
202  * fails.
203  */
204 #define MIN_TABLE_VERSION 1
205
206
207 /** An index header must be at least that many bytes long. */
208 #define MIN_INDEX_HEADER_SIZE(num_cols) (MIN_IDX_COLUMN_DESCRIPTION_SIZE \
209         * num_cols + IDX_COLUMN_DESCRIPTIONS)
210
211 /**
212  * Get the number of rows from the size of the memory mapping.
213  *
214  * \param t Pointer to an open table.
215  *
216  * \return The number of rows, including invalid rows.
217  */
218 _static_inline_ unsigned table_num_rows(const struct osl_table *t)
219 {
220         return (t->index_map.size - t->index_header_size)
221                 / t->row_index_size;
222 }
223
224 /**
225  * Get the path of the index file from a table description.
226  *
227  * \param d The table description.
228  *
229  * \return The full path of the index file. Result must be freed by
230  * the caller.
231  */
232 _static_inline_ char *index_filename(const struct osl_table_description *d)
233 {
234         return make_message("%s/%s/index", d->dir, d->name);
235 }
236
237 /**
238  * Get the path of storage of a column.
239  *
240  * \param t Pointer to an initialized table.
241  * \param col_num The number of the column to get the path for.
242  *
243  * \return The full path of the mapped data file (mapped storage) or the
244  * data directory (disk storage). Result must be freed by the caller.
245  *
246  * \sa osl_storage_type.
247  */
248 _static_inline_ char *column_filename(const struct osl_table *t, unsigned col_num)
249 {
250         char asc[2 * HASH_SIZE + 1];
251         hash_to_asc(t->columns[col_num].name_hash, asc);
252         return make_message("%s/%s/%s", t->desc->dir, t->desc->name, asc);
253 }
254
255 /**
256  * Get the start of an index entry
257  *
258  * \param t Pointer to a table which has been mapped.
259  * \param row_num The number of the row whose index entry should be retrieved.
260  * \param row_index Result pointer.
261  *
262  * \return Positive on success, \p -E_INDEX_CORRUPTION otherwise.
263  *
264  * \sa get_cell_index().
265  */
266 _static_inline_ int get_row_index(const struct osl_table *t, uint32_t row_num,
267                 char **row_index)
268 {
269         uint32_t index_offset;
270         index_offset = t->index_header_size + t->row_index_size * row_num;
271         if (index_offset + 8 > t->index_map.size) {
272                 *row_index = NULL;
273                 return -E_OSL_INDEX_CORRUPTION;
274         }
275         *row_index = (char *)(t->index_map.data) + index_offset;
276         return 1;
277 }
278
279 /**
280  * Get the index entry of a row/column pair.
281  *
282  * \param t Pointer to a table which has been mapped.
283  * \param row_num The number of the row whose index entry should be retrieved.
284  * \param col_num The number of the column whose index entry should be retrieved.
285  * \param cell_index Result pointer.
286  *
287  * \return Positive on success, \p -E_INDEX_CORRUPTION otherwise.
288  *
289  * \sa get_row_index().
290  */
291 _static_inline_ int get_cell_index(const struct osl_table *t, uint32_t row_num,
292                 uint32_t col_num, char **cell_index)
293 {
294         int ret = get_row_index(t, row_num, cell_index);
295         if (ret < 0)
296                 return ret;
297         *cell_index += t->columns[col_num].index_offset;
298         return ret;
299 }
300
301 /**
302  * Change an index entry of a column after object was added.
303  *
304  * \param row_index Pointer to the index of the row to update.
305  * \param col Pointer to the column.
306  * \param map_size The new size of the data file.
307  * \param object_size The size of the object just appended to the data file.
308  *
309  * This is called right after an object was appended to the data file for a
310  * mapped column.
311  *
312  * \sa get_row_index().
313  */
314 _static_inline_ void update_cell_index(char *row_index, struct osl_column *col,
315                 uint32_t map_size, uint32_t object_size)
316 {
317         write_u32(row_index + col->index_offset, map_size - object_size);
318         write_u32(row_index + col->index_offset + 4, object_size);
319 }
320
321 /**
322  * Get the full path of a disk storage object
323  *
324  * \param t Pointer to an initialized table.
325  * \param col_num The number of the column the disk storage object belongs to.
326  * \param ds_name The disk storage name of the object.
327  *
328  * \return Pointer to the full path which must be freed by the caller.
329  *
330  * \sa column_filename(), disk_storage_name_of_row().
331  */
332 _static_inline_ char *disk_storage_path(const struct osl_table *t,
333                 unsigned col_num, const char *ds_name)
334 {
335         char *filename, *dirname = column_filename(t, col_num);
336
337         if (!dirname)
338                 return NULL;
339         filename = make_message("%s/%s", dirname, ds_name);
340         free(dirname);
341         return filename;
342 }
343
344 /**
345  * Get the column description of the next column of a given type.
346  *
347  * \param type the desired storage type.
348  * \param col_num the column to start the search.
349  * \param t the osl table.
350  * \param cd result is returned here.
351  *
352  * \return On success, \a cd contains the column description of the next column
353  * of type \a type, and the number of that column is returned.  Otherwise, \a
354  * cd is set to \p NULL and the function returns t->num_columns + 1.
355  *
356  * \sa FOR_EACH_COLUMN_OF_TYPE, FOR_EACH_MAPPED_COLUMN, FOR_EACH_RBTREE_COLUMN,
357  * FOR_EACH_DISK_STORAGE_COLUMN, FOR_EACH_VOLATILE_COLUMN, osl_storage_type.
358  */
359 _static_inline_ int next_column_of_type(enum osl_storage_type type, int col_num,
360                 const struct osl_table *t,
361                 const struct osl_column_description **cd)
362 {
363         *cd = NULL;
364         while (col_num < t->desc->num_columns) {
365                 *cd = get_column_description(t->desc, col_num);
366                 if ((*cd)->storage_type == type)
367                         break;
368                 col_num++;
369         }
370         return col_num;
371 }
372
373 /**
374  * Find the next column with an associated rbtree.
375  *
376  * \param col_num The column to start the search.
377  * \param t The osl table.
378  * \param cd Result is returned here.
379
380  * \return On success, \a cd contains the column description of the next column
381  * with associated rbtree, and the number of that column is returned.
382  * Otherwise, \a cd is set to \p NULL and the function returns t->num_columns +
383  * 1.
384  *
385  * \sa FOR_EACH_COLUMN_OF_TYPE, FOR_EACH_MAPPED_COLUMN, FOR_EACH_RBTREE_COLUMN,
386  * FOR_EACH_DISK_STORAGE_COLUMN, FOR_EACH_VOLATILE_COLUMN, osl_storage_flags.
387  */
388 _static_inline_ int next_rbtree_column(int col_num, const struct osl_table *t,
389                 const struct osl_column_description **cd)
390 {
391         *cd = NULL;
392         while (col_num < t->desc->num_columns) {
393                 *cd = get_column_description(t->desc, col_num);
394                 if ((*cd)->storage_flags & OSL_RBTREE)
395                         break;
396                 col_num++;
397         }
398         return col_num;
399 }
400
401
402 /* quite some dirty hacks */
403
404 /** Round up size of struct osl_row to multiple of 8 */
405 #define RB_NODES_OFFSET ((sizeof(struct osl_row) + 7) / 8 * 8)
406
407 /**
408  * Allocate a new osl row.
409  *
410  * \param num_rbtrees The number of rbtrees for this row.
411  *
412  * \return A pointer to a zeroed-out area suitable for holding an osl row with
413  * \a num_rbtrees rbtree columns or \p NULL if no memory could be allocated.
414  */
415 _static_inline_ struct osl_row *allocate_row(unsigned num_rbtrees)
416 {
417         size_t s = RB_NODES_OFFSET + num_rbtrees * sizeof(struct rb_node);
418         return calloc(1, s);
419 }
420
421 /**
422  * Compute the pointer to a rbtree node embedded in a osl row.
423  *
424  * \param row The row to extract the rbtree pointer from.
425  * \param rbtree_num The number of the rbtree node to extract.
426  *
427  * \return A pointer to the \a rbtree_num th node contained in \a row.
428  */
429 _static_inline_ struct rb_node *get_rb_node_pointer(const struct osl_row *row, uint32_t rbtree_num)
430 {
431         return ((struct rb_node *)(((char *)row) + RB_NODES_OFFSET)) + rbtree_num;
432 }
433
434 /**
435  * Get a pointer to the struct containing the given rbtree node.
436  *
437  * \param node Pointer to the rbtree node.
438  * \param rbtree_num Number of \a node in the array of rbtree nodes.
439  *
440  * \return A pointer to the row containing \a node.
441  */
442 _static_inline_ struct osl_row *get_row_pointer(const struct rb_node *node,
443                 unsigned rbtree_num)
444 {
445         node -= rbtree_num;
446         return (struct osl_row *)(((char *)node) - RB_NODES_OFFSET);
447 }
448
449 /**
450  * Compute a cryptographic hash of an osl object.
451  *
452  * \param obj the Object to compute the hash value from.
453  * \param hash Result is returned here.
454  */
455 _static_inline_ void hash_object(const struct osl_object *obj, HASH_TYPE *hash)
456 {
457         hash_function(obj->data, obj->size, hash);
458 }
459
460 /**
461  * Get the relative path of an object, given the hash value.
462  *
463  * \param t Pointer to an initialized osl table.
464  * \param hash An arbitrary hash value.
465  *
466  * This function is typically called with \a hash being the hash of the object
467  * stored in the disk storage name column of a row.  If the OSL_LARGE_TABLE
468  * flag is set, the first two hex digits get separated with a slash from the
469  * remaining digits.
470  *
471  * \return The relative path for all disk storage objects corresponding to \a
472  * hash.
473  *
474  * \sa struct osl_table:disk_storage_name_column.
475  */
476 _static_inline_ char *disk_storage_name_of_hash(const struct osl_table *t, HASH_TYPE *hash)
477 {
478         char asc[2 * HASH_SIZE + 2];
479
480         hash_to_asc(hash, asc);
481         if (t->desc->flags & OSL_LARGE_TABLE)
482                 return make_message("%.2s/%s", asc, asc + 2);
483         return strdup(asc);
484 }
485
486 /**
487  * Iterate over each column of an initialized table.
488  *
489  * \param col A pointer to a struct osl_column.
490  * \param desc Pointer to the table description.
491  * \param cd Pointer to struct osl_column_description.
492  *
493  * On each iteration, \a col will point to the next column of the table and \a
494  * cd will point to the column description of this column.
495  *
496  * \sa struct osl_column FOR_EACH_RBTREE_COLUMN, FOR_EACH_COLUMN_OF_TYPE,
497  * FOR_EACH_MAPPED_COLUMN, FOR_EACH_DISK_STORAGE_COLUMN,
498  * FOR_EACH_VOLATILE_COLUMN.
499  */
500 #define FOR_EACH_COLUMN(col, desc, cd) \
501         for (col = 0; col < (desc)->num_columns && \
502                 (cd = get_column_description(desc, col)); col++)
503
504 /**
505  * Iterate over each column with associated rbtree.
506  *
507  * \param col Same meaning as in FOR_EACH_COLUMN().
508  * \param table Same meaning as in FOR_EACH_COLUMN().
509  * \param cd Same meaning as in FOR_EACH_COLUMN().
510  *
511  * \sa osl_storage_flags::OSL_RBTREE, FOR_EACH_COLUMN, FOR_EACH_COLUMN_OF_TYPE,
512  * FOR_EACH_MAPPED_COLUMN, FOR_EACH_DISK_STORAGE_COLUMN,
513  * FOR_EACH_VOLATILE_COLUMN.
514  */
515 #define FOR_EACH_RBTREE_COLUMN(col, table, cd) \
516         for (col = next_rbtree_column(0, table, &cd); \
517         col < table->desc->num_columns; \
518         col = next_rbtree_column(++col, table, &cd))
519
520 /**
521  * Iterate over each column of given storage type.
522  *
523  * \param type The osl_storage_type to iterate over.
524  * \param col Same meaning as in FOR_EACH_COLUMN().
525  * \param table Same meaning as in FOR_EACH_COLUMN().
526  * \param cd Same meaning as in FOR_EACH_COLUMN().
527  *
528  * \sa osl_storage_type, FOR_EACH_COLUMN, FOR_EACH_RBTREE_COLUMN,
529  * FOR_EACH_MAPPED_COLUMN, FOR_EACH_DISK_STORAGE_COLUMN,
530  * FOR_EACH_VOLATILE_COLUMN.
531  */
532 #define FOR_EACH_COLUMN_OF_TYPE(type, col, table, cd) \
533         for (col = next_column_of_type(type, 0, table, &cd); \
534         col < table->desc->num_columns; \
535         col = next_column_of_type(type, ++col, table, &cd))
536
537 /**
538  * Iterate over each mapped column.
539  *
540  * \param col Same meaning as in FOR_EACH_COLUMN().
541  * \param table Same meaning as in FOR_EACH_COLUMN().
542  * \param cd Same meaning as in FOR_EACH_COLUMN().
543  *
544  * Just like FOR_EACH_COLUMN(), but skip columns which are
545  * not of type \p OSL_MAPPED_STORAGE.
546  *
547  * \sa osl_storage_flags::OSL_MAPPED_STORAGE, FOR_EACH_COLUMN,
548  * FOR_EACH_RBTREE_COLUMN, FOR_EACH_COLUMN_OF_TYPE,
549  * FOR_EACH_DISK_STORAGE_COLUMN, FOR_EACH_VOLATILE_COLUMN.
550  */
551 #define FOR_EACH_MAPPED_COLUMN(col, table, cd) \
552         FOR_EACH_COLUMN_OF_TYPE(OSL_MAPPED_STORAGE, col, table, cd)
553
554 /**
555  * Iterate over each disk storage column.
556  *
557  * \param col Same meaning as in FOR_EACH_COLUMN().
558  * \param table Same meaning as in FOR_EACH_COLUMN().
559  * \param cd Same meaning as in FOR_EACH_COLUMN().
560  *
561  * Just like FOR_EACH_COLUMN(), but skip columns which are
562  * not of type \p OSL_DISK_STORAGE.
563  *
564  * \sa osl_storage_flags::OSL_DISK_STORAGE, FOR_EACH_COLUMN,
565  * FOR_EACH_RBTREE_COLUMN, FOR_EACH_COLUMN_OF_TYPE, FOR_EACH_MAPPED_COLUMN,
566  * FOR_EACH_VOLATILE_COLUMN.
567  */
568 #define FOR_EACH_DISK_STORAGE_COLUMN(col, table, cd) \
569         FOR_EACH_COLUMN_OF_TYPE(OSL_DISK_STORAGE, col, table, cd)
570
571 /**
572  * Iterate over each volatile column.
573  *
574  * \param col Same meaning as in FOR_EACH_COLUMN().
575  * \param table Same meaning as in FOR_EACH_COLUMN().
576  * \param cd Same meaning as in FOR_EACH_COLUMN().
577  *
578  * Just like FOR_EACH_COLUMN(), but skip columns which are
579  * not of type \p OSL_NO_STORAGE.
580  *
581  * \sa osl_storage_flags::OSL_NO_STORAGE, FOR_EACH_COLUMN,
582  * FOR_EACH_RBTREE_COLUMN, FOR_EACH_COLUMN_OF_TYPE, FOR_EACH_MAPPED_COLUMN,
583  * FOR_EACH_DISK_STORAGE_COLUMN.
584  */
585 #define FOR_EACH_VOLATILE_COLUMN(col, table, cd) \
586         FOR_EACH_COLUMN_OF_TYPE(OSL_NO_STORAGE, col, table, cd)