1 #ifndef __GSK_TABLE_H_
2 #define __GSK_TABLE_H_
3
4 /* GskTable.
5 *
6 * A efficient on-disk table, meaning a mapping from an
7 * uninterpreted piece of binary-data to a value.
8 * When multiple values are added with the same
9 * key, they are merged, using user-definable semantics.
10 *
11 * application notes:
12 * - you may store data in the directory, but it the filename
13 * must begin with a capital letter.
14 */
15 typedef struct _GskTableReader GskTableReader;
16
17 #include "gskmempool.h"
18
19 typedef struct
20 {
21 guint len;
22 guint8 *data;
23 guint alloced;
24 } GskTableBuffer;
25
26 /* --- public table buffer api -- needed for defining merge functions --- */
27 /* calls realloc so beginning of buffer is preserved */
28 G_INLINE_FUNC guint8 *gsk_table_buffer_set_len (GskTableBuffer *buffer,
29 guint len);
30
31 /* returns pointer to new area in buffer */
32 G_INLINE_FUNC guint8 *gsk_table_buffer_append (GskTableBuffer *buffer,
33 guint len);
34
35
36 typedef int (*GskTableCompareFunc) (guint a_key_len,
37 const guint8 *a_key_data,
38 guint b_key_len,
39 const guint8 *b_key_data,
40 gpointer user_data);
41 typedef int (*GskTableCompareFuncNoLen) (const guint8 *a_key_data,
42 const guint8 *b_key_data,
43 gpointer user_data);
44 typedef enum
45 {
46 GSK_TABLE_MERGE_RETURN_A,
47 GSK_TABLE_MERGE_RETURN_B,
48 GSK_TABLE_MERGE_SUCCESS,
49 GSK_TABLE_MERGE_DROP,
50 } GskTableMergeResult;
51 typedef GskTableMergeResult (*GskTableMergeFunc) (guint key_len,
52 const guint8 *key_data,
53 guint a_len,
54 const guint8 *a_data,
55 guint b_len,
56 const guint8 *b_data,
57 GskTableBuffer *output,
58 gpointer user_data);
59 typedef GskTableMergeResult (*GskTableMergeFuncNoLen) (const guint8 *key_data,
60 const guint8 *a_data,
61 const guint8 *b_data,
62 GskTableBuffer *output,
63 gpointer user_data);
64
65 /* used for merges that go back to the beginning of the indexer */
66 typedef enum
67 {
68 GSK_TABLE_SIMPLIFY_IDENTITY,
69 GSK_TABLE_SIMPLIFY_SUCCESS,
70 GSK_TABLE_SIMPLIFY_DELETE
71 } GskTableSimplifyResult;
72 typedef GskTableSimplifyResult (*GskTableSimplifyFunc)(guint key_len,
73 const guint8 *key_data,
74 guint value_len,
75 const guint8 *value_data,
76 GskTableBuffer*val_out,
77 gpointer user_data);
78 typedef GskTableSimplifyResult (*GskTableSimplifyFuncNoLen)
79 (const guint8 *key_data,
80 const guint8 *value_data,
81 GskTableBuffer*val_out,
82 gpointer user_data);
83
84 /* only used for querying */
85 typedef gboolean (*GskTableValueIsStableFunc)(guint key_len,
86 const guint8 *key_data,
87 guint value_len,
88 const guint8 *value_data,
89 gpointer user_data);
90
91 typedef enum
92 {
93 GSK_TABLE_JOURNAL_NONE,
94 GSK_TABLE_JOURNAL_OCCASIONALLY,
95 GSK_TABLE_JOURNAL_DEFAULT
96 } GskTableJournalMode;
97
98 typedef struct _GskTableOptions GskTableOptions;
99 struct _GskTableOptions
100 {
101 /* compare configuration */
102 GskTableCompareFunc compare;
103 GskTableCompareFuncNoLen compare_no_len;
104
105 /* merging configuration */
106 GskTableMergeFunc merge;
107 GskTableMergeFuncNoLen merge_no_len;
108
109 /* final merging */
110 GskTableSimplifyFunc simplify;
111 GskTableSimplifyFuncNoLen simplify_no_len;
112
113 /* query stability */
114 GskTableValueIsStableFunc is_stable;
115
116 /* user data */
117 gpointer user_data;
118 GDestroyNotify destroy_user_data;
119
120 /* journalling mode */
121 GskTableJournalMode journal_mode;
122
123 /* tunables */
124 gsize max_in_memory_entries;
125 gsize max_in_memory_bytes;
126 };
127
128 GskTableOptions *gsk_table_options_new (void);
129 void gsk_table_options_destroy(GskTableOptions *options);
130
131 void gsk_table_options_set_replacement_semantics (GskTableOptions *options);
132
133 typedef enum
134 {
135 GSK_TABLE_MAY_EXIST = (1<<0),
136 GSK_TABLE_MAY_CREATE = (1<<1)
137 } GskTableNewFlags;
138
139 typedef struct _GskTable GskTable;
140
141 /* NOTE: hinting options will be ignored if the table already exists. */
142 GskTable * gsk_table_new (const char *dir,
143 const GskTableOptions *options,
144 GskTableNewFlags flags,
145 GError **error);
146 gboolean gsk_table_add (GskTable *table,
147 guint key_len,
148 const guint8 *key_data,
149 guint value_len,
150 const guint8 *value_data,
151 GError **error);
152 gboolean gsk_table_query (GskTable *table,
153 guint key_len,
154 const guint8 *key_data,
155 gboolean *found_value_out,
156 guint *value_len_out,
157 guint8 **value_data_out,
158 GError **error);
159 const char *gsk_table_peek_dir (GskTable *table);
160 void gsk_table_destroy (GskTable *table);
161
162
163 struct _GskTableReader
164 {
165 gboolean eof;
166 GError *error;
167 guint key_len;
168 const guint8 *key_data;
169 guint value_len;
170 const guint8 *value_data;
171
172 void (*advance) (GskTableReader *reader);
173 void (*destroy) (GskTableReader *reader);
174 };
175 typedef enum
176 {
177 GSK_TABLE_BOUND_NONE,
178 GSK_TABLE_BOUND_STRICT,
179 GSK_TABLE_BOUND_INCLUSIVE
180 } GskTableBoundType;
181 GskTableReader *gsk_table_make_reader_with_bounds (GskTable *table,
182 GskTableBoundType start_bound_type,
183 guint start_bound_len,
184 const guint8 *start_bound_data,
185 GskTableBoundType end_bound_type,
186 guint end_bound_len,
187 const guint8 *end_bound_data,
188 GError **error);
189 #define gsk_table_make_reader(table, error) \
190 gsk_table_make_reader_with_bounds (table, \
191 GSK_TABLE_BOUND_NONE, 0, NULL, \
192 GSK_TABLE_BOUND_NONE, 0, NULL, \
193 error)
194
195 G_INLINE_FUNC void gsk_table_reader_advance (GskTableReader *reader);
196 G_INLINE_FUNC void gsk_table_reader_destroy (GskTableReader *reader);
197
198
199
200
201
202 /* --- protected parts of the table-buffer api --- */
203 /* this stuff is used throughout the implementation:
204 we also cavalierly access 'len', 'data' and 'alloced'
205 and assume that they have the expected properties.
206 we do not modify 'data' or 'alloced' and we always
207 ensure that len < alloced. */
208
209 #define GSK_TABLE_BUFFER_INIT { 0, NULL, 0 }
210 G_INLINE_FUNC void gsk_table_buffer_init (GskTableBuffer *buffer);
211
212 G_INLINE_FUNC void gsk_table_buffer_clear (GskTableBuffer *buffer);
213
214 G_INLINE_FUNC void gsk_table_buffer_ensure_size (GskTableBuffer *buffer,
215 guint min_size);
216 G_INLINE_FUNC void gsk_table_buffer_ensure_extra (GskTableBuffer *buffer,
217 guint addl_size);
218
219
220 #if defined (G_CAN_INLINE) || defined (__GSK_DEFINE_INLINES__)
gsk_table_buffer_init(GskTableBuffer * buffer)221 G_INLINE_FUNC void gsk_table_buffer_init (GskTableBuffer *buffer)
222 {
223 buffer->len = 0;
224 buffer->data = NULL;
225 buffer->alloced = 0;
226 }
227
228 /* calls realloc so beginning of buffer is preserved */
229 G_INLINE_FUNC void
gsk_table_buffer_ensure_size(GskTableBuffer * buffer,guint min_size)230 gsk_table_buffer_ensure_size (GskTableBuffer *buffer,
231 guint min_size)
232 {
233 if (G_UNLIKELY (buffer->alloced < min_size))
234 {
235 guint new_size = buffer->alloced ? buffer->alloced * 2 : 32;
236 while (new_size < min_size)
237 new_size += new_size;
238 buffer->data = g_realloc (buffer->data, new_size);
239 buffer->alloced = new_size;
240 }
241 }
242
243 G_INLINE_FUNC guint8 *
gsk_table_buffer_set_len(GskTableBuffer * buffer,guint len)244 gsk_table_buffer_set_len (GskTableBuffer *buffer,
245 guint len)
246 {
247 gsk_table_buffer_ensure_size (buffer, len);
248 buffer->len = len;
249 return buffer->data;
250 }
251
252 /* returns pointer to new area in buffer */
253 G_INLINE_FUNC guint8 *
gsk_table_buffer_append(GskTableBuffer * buffer,guint len)254 gsk_table_buffer_append (GskTableBuffer *buffer,
255 guint len)
256 {
257 guint old_len = buffer->len;
258 return gsk_table_buffer_set_len (buffer, old_len + len) + old_len;
259 }
260
261 G_INLINE_FUNC void
gsk_table_buffer_clear(GskTableBuffer * buffer)262 gsk_table_buffer_clear (GskTableBuffer *buffer)
263 {
264 g_free (buffer->data);
265 }
266
267 G_INLINE_FUNC void
gsk_table_buffer_ensure_extra(GskTableBuffer * buffer,guint extra_bytes)268 gsk_table_buffer_ensure_extra (GskTableBuffer *buffer,
269 guint extra_bytes)
270 {
271 gsk_table_buffer_ensure_size (buffer, buffer->len + extra_bytes);
272 }
273 G_INLINE_FUNC void
gsk_table_reader_advance(GskTableReader * reader)274 gsk_table_reader_advance (GskTableReader *reader)
275 {
276 reader->advance (reader);
277 }
278 G_INLINE_FUNC void
gsk_table_reader_destroy(GskTableReader * reader)279 gsk_table_reader_destroy (GskTableReader *reader)
280 {
281 reader->destroy (reader);
282 }
283 #endif
284
285 #endif
286