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