1 /* GskTableFile:
2 * A mechanism for creating searchable files from a sorted stream of entrys.
3 */
4
5 typedef struct _GskTableFileFactory GskTableFileFactory;
6 typedef struct _GskTableFile GskTableFile;
7 typedef struct _GskTableFileHints GskTableFileHints;
8
9
10 struct _GskTableFileHints
11 {
12 guint64 max_entries;
13 guint64 max_key_bytes;
14 guint64 max_value_bytes;
15 guint min_key_size, max_key_size;
16 guint min_value_size, max_value_size;
17 gboolean allocate_disk_space_based_on_max_sizes;
18 };
19 #define GSK_TABLE_FILE_HINTS_DEFAULTS \
20 { G_MAXUINT64, G_MAXUINT64, G_MAXUINT64, \
21 0, G_MAXUINT, 0, G_MAXUINT, \
22 FALSE /* allocate_disk_space_based_on_max_sizes */ \
23 }
24
25
26 struct _GskTableFile
27 {
28 GskTableFileFactory *factory;
29 guint64 id;
30
31 /* NOTE: n_entries must be set by create_file() and open_building_file()
32 implementations, but must be set by caller for open_file().
33 (ugly, but it's internal api) */
34 guint64 n_entries;
35 };
36
37 typedef struct _GskTableFileQuery GskTableFileQuery;
38 struct _GskTableFileQuery
39 {
40 /* returns the implicit key <=> test_key; the implicit key is setup by
41 the caller somewhere in compare_data */
42 gint (*compare) (guint test_key_len,
43 const guint8 *test_key,
44 gpointer compare_data);
45 gpointer compare_data;
46
47 gboolean found;
48 GskTableBuffer value;
49 };
50
51 #define GSK_TABLE_FILE_QUERY_INIT { NULL, NULL, FALSE, GSK_TABLE_BUFFER_INIT }
52
53 G_INLINE_FUNC void gsk_table_file_query_clear (GskTableFileQuery *query);
54
55 /* Copy "dir" as passed into create_file(), open_building_file(), etc.
56 This isn't necessary b/c the "dir" is always a member of the
57 GskTable, and therefore will always be destroyed AFTER the files. */
58 #define GSK_TABLE_FILE_COPY_DIR 0
59
60 #if GSK_TABLE_FILE_COPY_DIR
61 # define GSK_TABLE_FILE_DIR_MAYBE_STRDUP(dir) g_strdup(dir)
62 # define GSK_TABLE_FILE_DIR_MAYBE_FREE(dir) g_free((char*)(dir))
63 #else
64 # define GSK_TABLE_FILE_DIR_MAYBE_STRDUP(dir) dir
65 # define GSK_TABLE_FILE_DIR_MAYBE_FREE(dir) do {} while(0)
66 #endif
67
68 typedef enum
69 {
70 GSK_TABLE_FEED_ENTRY_WANT_MORE,
71 GSK_TABLE_FEED_ENTRY_SUCCESS,
72 GSK_TABLE_FEED_ENTRY_ERROR
73 } GskTableFeedEntryResult;
74
75 struct _GskTableFileFactory
76 {
77 /* creating files (in initial, mid-build and queryable states) */
78 GskTableFile *(*create_file) (GskTableFileFactory *factory,
79 const char *dir,
80 guint64 id,
81 const GskTableFileHints *hints,
82 GError **error);
83 GskTableFile *(*open_building_file)(GskTableFileFactory *factory,
84 const char *dir,
85 guint64 id,
86 guint state_len,
87 const guint8 *state_data,
88 GError **error);
89 GskTableFile *(*open_file) (GskTableFileFactory *factory,
90 const char *dir,
91 guint64 id,
92 GError **error);
93
94 /* methods for a file which is being built */
95 GskTableFeedEntryResult
96 (*feed_entry) (GskTableFile *file,
97 guint key_len,
98 const guint8 *key_data,
99 guint value_len,
100 const guint8 *value_data,
101 GError **error);
102 gboolean (*done_feeding) (GskTableFile *file,
103 gboolean *ready_out,
104 GError **error);
105 gboolean (*get_build_state) (GskTableFile *file,
106 guint *state_len_out,
107 guint8 **state_data_out,
108 GError **error);
109 gboolean (*build_file) (GskTableFile *file,
110 gboolean *ready_out,
111 GError **error);
112 void (*release_build_data)(GskTableFile *file);
113
114 /* methods for a file which has been constructed;
115 some file types can be queried before they are constructed */
116 gboolean (*query_file) (GskTableFile *file,
117 GskTableFileQuery *query_inout,
118 GError **error);
119 GskTableReader *(*create_reader) (GskTableFile *file,
120 const char *dir,
121 GError **error);
122 /* you must always be able to get reader state */
123 gboolean (*get_reader_state) (GskTableFile *file,
124 GskTableReader *reader,
125 guint *state_len_out,
126 guint8 **state_data_out,
127 GError **error);
128 GskTableReader *(*recreate_reader) (GskTableFile *file,
129 const char *dir,
130 guint state_len,
131 const guint8 *state_data,
132 GError **error);
133
134 /* destroying files and factories */
135 gboolean (*destroy_file) (GskTableFile *file,
136 const char *dir,
137 gboolean erase,
138 GError **error);
139 void (*destroy_factory) (GskTableFileFactory *factory);
140 };
141
142 /* optimized for situations where writes predominate */
143 GskTableFileFactory *gsk_table_file_factory_new_flat (void);
144
145 /* optimized for situations where reads are common */
146 GskTableFileFactory *gsk_table_file_factory_new_btree (void);
147
148 #define gsk_table_file_factory_create_file(factory, dir, id, hints, error) \
149 ((factory)->create_file ((factory), (dir), (id), (hints), (error)))
150 #define gsk_table_file_factory_open_file(factory, dir, id, error) \
151 ((factory)->open_file ((factory), (dir), (id), (error)))
152 #define gsk_table_file_factory_open_building_file(factory, dir, id, state_len, state_data, error) \
153 ((factory)->open_building_file ((factory), (dir), (id), (state_len), (state_data), (error)))
154 #define gsk_table_file_feed_entry(file, key_len, key_data, value_len, value_data, error) \
155 ((file)->factory->feed_entry ((file), key_len, key_data, value_len, value_data, error))
156 #define gsk_table_file_get_build_state(file, state_len_out, state_data_out, error) \
157 ((file)->factory->get_build_state ((file), (state_len_out), (state_data_out), (error)))
158 #define gsk_table_file_done_feeding(file, ready_out, error) \
159 ((file)->factory->done_feeding ((file), (ready_out), (error)))
160 #define gsk_table_file_build_file(file, ready_out, error) \
161 ((file)->factory->build_file ((file), (ready_out), (error)))
162 #define gsk_table_file_query(file, query_inout, error) \
163 ((file)->factory->query_file ((file), (query_inout), (error)))
164 #define gsk_table_file_create_reader(file, dir, error) \
165 ((file)->factory->create_reader ((file), (dir), (error)))
166 #define gsk_table_file_get_reader_state(file, reader, state_len_out, state_out, error) \
167 ((file)->factory->get_reader_state ((file), (reader), (state_len_out), (state_out), (error)))
168 #define gsk_table_file_recreate_reader(file, dir, state_len, state_data, error) \
169 ((file)->factory->recreate_reader ((file), (dir), (state_len), (state_data), (error)))
170 #define gsk_table_file_destroy(file, dir, erase, error) \
171 ((file)->factory->destroy_file ((file), (dir), (erase), (error)))
172 #define gsk_table_file_factory_destroy(factory) \
173 (factory)->destroy_factory (factory)
174
175 #if defined (G_CAN_INLINE) || defined (__GSK_DEFINE_INLINES__)
gsk_table_file_query_clear(GskTableFileQuery * query)176 G_INLINE_FUNC void gsk_table_file_query_clear (GskTableFileQuery *query)
177 {
178 gsk_table_buffer_clear (&query->value);
179 }
180 #endif
181
182
183