1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2017 Red Hat, Inc. (www.redhat.com)
4  *
5  * This library is free software: you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation.
8  *
9  * This library is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12  * for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #if !defined (__LIBEBACKEND_H_INSIDE__) && !defined (LIBEBACKEND_COMPILATION)
19 #error "Only <libebackend/libebackend.h> should be included directly."
20 #endif
21 
22 #ifndef E_CACHE_H
23 #define E_CACHE_H
24 
25 #include <glib-object.h>
26 #include <gio/gio.h>
27 #include <libebackend/e-backend-enums.h>
28 
29 /* Standard GObject macros */
30 #define E_TYPE_CACHE \
31 	(e_cache_get_type ())
32 #define E_CACHE(obj) \
33 	(G_TYPE_CHECK_INSTANCE_CAST \
34 	((obj), E_TYPE_CACHE, ECache))
35 #define E_CACHE_CLASS(cls) \
36 	(G_TYPE_CHECK_CLASS_CAST \
37 	((cls), E_TYPE_CACHE, ECacheClass))
38 #define E_IS_CACHE(obj) \
39 	(G_TYPE_CHECK_INSTANCE_TYPE \
40 	((obj), E_TYPE_CACHE))
41 #define E_IS_CACHE_CLASS(cls) \
42 	(G_TYPE_CHECK_CLASS_TYPE \
43 	((cls), E_TYPE_CACHE))
44 #define E_CACHE_GET_CLASS(obj) \
45 	(G_TYPE_INSTANCE_GET_CLASS \
46 	((obj), E_TYPE_CACHE, ECacheClass))
47 
48 G_BEGIN_DECLS
49 
50 #define E_CACHE_TABLE_OBJECTS	"ECacheObjects"
51 #define E_CACHE_TABLE_KEYS	"ECacheKeys"
52 
53 #define E_CACHE_COLUMN_UID	"ECacheUID"
54 #define E_CACHE_COLUMN_REVISION	"ECacheREV"
55 #define E_CACHE_COLUMN_OBJECT	"ECacheOBJ"
56 #define E_CACHE_COLUMN_STATE	"ECacheState"
57 
58 /**
59  * E_CACHE_ERROR:
60  *
61  * Error domain for #ECache operations.
62  *
63  * Since: 3.26
64  **/
65 #define E_CACHE_ERROR (e_cache_error_quark ())
66 
67 GQuark		e_cache_error_quark	(void);
68 
69 /**
70  * ECacheError:
71  * @E_CACHE_ERROR_ENGINE: An error was reported from the SQLite engine
72  * @E_CACHE_ERROR_CONSTRAINT: The error occurred due to an explicit constraint, like
73  *    when attempting to add two objects with the same UID.
74  * @E_CACHE_ERROR_NOT_FOUND: An object was not found by UID (this is
75  *    different from a query that returns no results, which is not an error).
76  * @E_CACHE_ERROR_INVALID_QUERY: A query was invalid.
77  * @E_CACHE_ERROR_UNSUPPORTED_FIELD: A field requested for inclusion in summary is not supported.
78  * @E_CACHE_ERROR_UNSUPPORTED_QUERY: A query was not supported.
79  * @E_CACHE_ERROR_END_OF_LIST: An attempt was made to fetch results past the end of a the list.
80  * @E_CACHE_ERROR_LOAD: An error occured while loading or creating the database.
81  *
82  * Defines the types of possible errors reported by the #ECache
83  *
84  * Since: 3.26
85  */
86 typedef enum {
87 	E_CACHE_ERROR_ENGINE,
88 	E_CACHE_ERROR_CONSTRAINT,
89 	E_CACHE_ERROR_NOT_FOUND,
90 	E_CACHE_ERROR_INVALID_QUERY,
91 	E_CACHE_ERROR_UNSUPPORTED_FIELD,
92 	E_CACHE_ERROR_UNSUPPORTED_QUERY,
93 	E_CACHE_ERROR_END_OF_LIST,
94 	E_CACHE_ERROR_LOAD
95 } ECacheError;
96 
97 typedef struct _ECacheColumnValues ECacheColumnValues;
98 
99 #define E_TYPE_CACHE_COLUMN_VALUES (e_cache_column_values_get_type ())
100 GType		e_cache_column_values_get_type	(void) G_GNUC_CONST;
101 ECacheColumnValues *
102 		e_cache_column_values_new	(void);
103 ECacheColumnValues *
104 		e_cache_column_values_copy	(ECacheColumnValues *other_columns);
105 void		e_cache_column_values_free	(ECacheColumnValues *other_columns);
106 void		e_cache_column_values_put	(ECacheColumnValues *other_columns,
107 						 const gchar *name,
108 						 const gchar *value);
109 void		e_cache_column_values_take_value(ECacheColumnValues *other_columns,
110 						 const gchar *name,
111 						 gchar *value);
112 void		e_cache_column_values_take	(ECacheColumnValues *other_columns,
113 						 gchar *name,
114 						 gchar *value);
115 gboolean	e_cache_column_values_contains	(ECacheColumnValues *other_columns,
116 						 const gchar *name);
117 gboolean	e_cache_column_values_remove	(ECacheColumnValues *other_columns,
118 						 const gchar *name);
119 void		e_cache_column_values_remove_all(ECacheColumnValues *other_columns);
120 const gchar *	e_cache_column_values_lookup	(ECacheColumnValues *other_columns,
121 						 const gchar *name);
122 guint		e_cache_column_values_get_size	(ECacheColumnValues *other_columns);
123 void		e_cache_column_values_init_iter	(ECacheColumnValues *other_columns,
124 						 GHashTableIter *iter);
125 
126 /**
127  * ECacheOfflineChange:
128  * @uid: UID of the object
129  * @revision: stored revision of the object
130  * @object: the object itself
131  * @state: an #EOfflineState of the object
132  *
133  * Holds the information about offline change for one object.
134  *
135  * Since: 3.26
136  **/
137 typedef struct {
138 	gchar *uid;
139 	gchar *revision;
140 	gchar *object;
141 	EOfflineState state;
142 } ECacheOfflineChange;
143 
144 #define E_TYPE_CACHE_OFFLINE_CHANGE (e_cache_offline_change_get_type ())
145 
146 GType		e_cache_offline_change_get_type	(void) G_GNUC_CONST;
147 ECacheOfflineChange *
148 		e_cache_offline_change_new	(const gchar *uid,
149 						 const gchar *revision,
150 						 const gchar *object,
151 						 EOfflineState state);
152 ECacheOfflineChange *
153 		e_cache_offline_change_copy	(const ECacheOfflineChange *change);
154 void		e_cache_offline_change_free	(/* ECacheOfflineChange */ gpointer change);
155 
156 typedef struct {
157 	gchar *name;
158 	gchar *type;
159 	gchar *index_name;
160 } ECacheColumnInfo;
161 
162 #define E_TYPE_CACHE_COLUMN_INFO (e_cache_column_info_get_type ())
163 GType		e_cache_column_info_get_type	(void) G_GNUC_CONST;
164 ECacheColumnInfo *
165 		e_cache_column_info_new		(const gchar *name,
166 						 const gchar *type,
167 						 const gchar *index_name);
168 ECacheColumnInfo *
169 		e_cache_column_info_copy	(const ECacheColumnInfo *info);
170 void		e_cache_column_info_free	(/* ECacheColumnInfo */ gpointer info);
171 
172 /**
173  * ECacheLockType:
174  * @E_CACHE_LOCK_READ: Obtain a lock for reading.
175  * @E_CACHE_LOCK_WRITE: Obtain a lock for writing. This also starts a transaction.
176  *
177  * Indicates the type of lock requested in e_cache_lock().
178  *
179  * Since: 3.26
180  **/
181 typedef enum {
182 	E_CACHE_LOCK_READ,
183 	E_CACHE_LOCK_WRITE
184 } ECacheLockType;
185 
186 /**
187  * ECacheUnlockAction:
188  * @E_CACHE_UNLOCK_NONE: Just unlock, this is appropriate for locks which were obtained with %E_CACHE_LOCK_READ.
189  * @E_CACHE_UNLOCK_COMMIT: Commit any modifications which were made while the lock was held.
190  * @E_CACHE_UNLOCK_ROLLBACK: Rollback any modifications which were made while the lock was held.
191  *
192  * Indicates what type of action to take while unlocking the cache with e_cache_unlock().
193  *
194  * Since: 3.26
195  **/
196 typedef enum {
197 	E_CACHE_UNLOCK_NONE,
198 	E_CACHE_UNLOCK_COMMIT,
199 	E_CACHE_UNLOCK_ROLLBACK
200 } ECacheUnlockAction;
201 
202 /**
203  * ECacheDeletedFlag:
204  * @E_CACHE_EXCLUDE_DELETED: Do not include locally deleted objects
205  * @E_CACHE_INCLUDE_DELETED: Include locally deleted objects
206  *
207  * Declares whether to exclude or include locally deleted objects.
208  *
209  * Since: 3.26
210  **/
211 typedef enum {
212 	E_CACHE_EXCLUDE_DELETED = 0,
213 	E_CACHE_INCLUDE_DELETED
214 } ECacheDeletedFlag;
215 
216 /**
217  * ECacheOfflineFlag:
218  * @E_CACHE_OFFLINE_UNKNOWN: Do not know current online/offline state
219  * @E_CACHE_IS_ONLINE: The operation is done in online
220  * @E_CACHE_IS_OFFLINE: The operation is done in offline
221  *
222  * Declares whether the operation is done in online or offline.
223  * This influences the offline state of the related objects.
224  *
225  * Since: 3.26
226  **/
227 typedef enum {
228 	E_CACHE_OFFLINE_UNKNOWN = -1,
229 	E_CACHE_IS_ONLINE = 0,
230 	E_CACHE_IS_OFFLINE
231 } ECacheOfflineFlag;
232 
233 typedef struct _ECache ECache;
234 typedef struct _ECacheClass ECacheClass;
235 typedef struct _ECachePrivate ECachePrivate;
236 
237 /**
238  * ECacheForeachFunc:
239  * @cache: an #ECache
240  * @uid: a unique object identifier
241  * @revision: the object revision
242  * @object: the object itself
243  * @offline_state: objects offline state, one of #EOfflineState
244  * @ncols: count of columns, items in column_names and column_values
245  * @column_names: (array length=ncols) (element-type utf8): column names
246  * @column_values: (array length=ncols) (element-type utf8): column values
247  * @user_data: user data, as used in e_cache_foreach()
248  *
249  * A callback called for each object row when using e_cache_foreach() function.
250  *
251  * Returns: %TRUE to continue, %FALSE to stop walk through.
252  *
253  * Since: 3.26
254  **/
255 typedef gboolean (* ECacheForeachFunc)	(ECache *cache,
256 					 const gchar *uid,
257 					 const gchar *revision,
258 					 const gchar *object,
259 					 EOfflineState offline_state,
260 					 gint ncols,
261 					 const gchar *column_names[],
262 					 const gchar *column_values[],
263 					 gpointer user_data);
264 
265 /**
266  * ECacheUpdateFunc:
267  * @cache: an #ECache
268  * @uid: a unique object identifier
269  * @revision: the object revision
270  * @object: the object itself
271  * @offline_state: objects offline state, one of #EOfflineState
272  * @ncols: count of columns, items in column_names and column_values
273  * @column_names: (array length=ncols) (element-type utf8): column names
274  * @column_values: (array length=ncols) (element-type utf8): column values
275  * @out_revision: (out): the new object revision to set; keep it untouched to not change
276  * @out_object: (out): the new object to set; keep it untouched to not change
277  * @out_offline_state: (out): the offline state to set; the default is the same as @offline_state
278  * @out_other_columns: (out) (transfer full): an #ECacheColumnValues with other columns to set; keep it untouched to not change any
279  * @user_data: user data, as used in e_cache_foreach_update()
280  *
281  * A callback called for each object row when using e_cache_foreach_update() function.
282  * When all out parameters are left untouched, then the row is not changed.
283  *
284  * Returns: %TRUE to continue, %FALSE to stop walk through.
285  *
286  * Since: 3.26
287  **/
288 typedef gboolean (* ECacheUpdateFunc)	(ECache *cache,
289 					 const gchar *uid,
290 					 const gchar *revision,
291 					 const gchar *object,
292 					 EOfflineState offline_state,
293 					 gint ncols,
294 					 const gchar *column_names[],
295 					 const gchar *column_values[],
296 					 gchar **out_revision,
297 					 gchar **out_object,
298 					 EOfflineState *out_offline_state,
299 					 ECacheColumnValues **out_other_columns,
300 					 gpointer user_data);
301 
302 /**
303  * ECacheSelectFunc:
304  * @cache: an #ECache
305  * @ncols: count of columns, items in column_names and column_values
306  * @column_names: (array length=ncols) (element-type utf8): column names
307  * @column_values: (array length=ncols) (element-type utf8): column values
308  * @user_data: user data, as used in e_cache_sqlite_select()
309  *
310  * A callback called for each row of a SELECT statement executed
311  * with e_cache_sqlite_select() function.
312  *
313  * Returns: %TRUE to continue, %FALSE to stop walk through.
314  *
315  * Since: 3.26
316  **/
317 typedef gboolean (* ECacheSelectFunc)	(ECache *cache,
318 					 gint ncols,
319 					 const gchar *column_names[],
320 					 const gchar *column_values[],
321 					 gpointer user_data);
322 
323 /**
324  * ECache:
325  *
326  * Contains only private data that should be read and manipulated using the
327  * functions below.
328  *
329  * Since: 3.26
330  **/
331 struct _ECache {
332 	/*< private >*/
333 	GObject parent;
334 	ECachePrivate *priv;
335 };
336 
337 struct _ECacheClass {
338 	/*< private >*/
339 	GObjectClass parent_class;
340 
341 	/* Virtual methods */
342 	gboolean	(* put_locked)		(ECache *cache,
343 						 const gchar *uid,
344 						 const gchar *revision,
345 						 const gchar *object,
346 						 ECacheColumnValues *other_columns,
347 						 EOfflineState offline_state,
348 						 gboolean is_replace,
349 						 GCancellable *cancellable,
350 						 GError **error);
351 	gboolean	(* remove_locked)	(ECache *cache,
352 						 const gchar *uid,
353 						 GCancellable *cancellable,
354 						 GError **error);
355 	gboolean	(* remove_all_locked)	(ECache *cache,
356 						 const GSList *uids, /* gchar * */
357 						 GCancellable *cancellable,
358 						 GError **error);
359 	gboolean	(* clear_offline_changes_locked)
360 						(ECache *cache,
361 						 GCancellable *cancellable,
362 						 GError **error);
363 	void		(* erase)		(ECache *cache);
364 
365 	/* Signals */
366 	gboolean	(* before_put)		(ECache *cache,
367 						 const gchar *uid,
368 						 const gchar *revision,
369 						 const gchar *object,
370 						 ECacheColumnValues *other_columns,
371 						 gboolean is_replace,
372 						 GCancellable *cancellable,
373 						 GError **error);
374 	gboolean	(* before_remove)	(ECache *cache,
375 						 const gchar *uid,
376 						 GCancellable *cancellable,
377 						 GError **error);
378 	void		(* revision_changed)	(ECache *cache);
379 
380 	/* Padding for future expansion */
381 	gpointer reserved[10];
382 };
383 
384 GType		e_cache_get_type		(void) G_GNUC_CONST;
385 
386 gboolean	e_cache_initialize_sync		(ECache *cache,
387 						 const gchar *filename,
388 						 const GSList *other_columns, /* ECacheColumnInfo * */
389 						 GCancellable *cancellable,
390 						 GError **error);
391 const gchar *	e_cache_get_filename		(ECache *cache);
392 gint		e_cache_get_version		(ECache *cache);
393 void		e_cache_set_version		(ECache *cache,
394 						 gint version);
395 gchar *		e_cache_dup_revision		(ECache *cache);
396 void		e_cache_set_revision		(ECache *cache,
397 						 const gchar *revision);
398 void		e_cache_change_revision		(ECache *cache);
399 void		e_cache_freeze_revision_change	(ECache *cache);
400 void		e_cache_thaw_revision_change	(ECache *cache);
401 gboolean	e_cache_is_revision_change_frozen
402 						(ECache *cache);
403 void		e_cache_erase			(ECache *cache);
404 gboolean	e_cache_contains		(ECache *cache,
405 						 const gchar *uid,
406 						 ECacheDeletedFlag deleted_flag);
407 gchar *		e_cache_get			(ECache *cache,
408 						 const gchar *uid,
409 						 gchar **out_revision,
410 						 ECacheColumnValues **out_other_columns,
411 						 GCancellable *cancellable,
412 						 GError **error);
413 gchar *		e_cache_get_object_include_deleted
414 						(ECache *cache,
415 						 const gchar *uid,
416 						 gchar **out_revision,
417 						 ECacheColumnValues **out_other_columns,
418 						 GCancellable *cancellable,
419 						 GError **error);
420 gboolean	e_cache_put			(ECache *cache,
421 						 const gchar *uid,
422 						 const gchar *revision,
423 						 const gchar *object,
424 						 ECacheColumnValues *other_columns,
425 						 ECacheOfflineFlag offline_flag,
426 						 GCancellable *cancellable,
427 						 GError **error);
428 gboolean	e_cache_remove			(ECache *cache,
429 						 const gchar *uid,
430 						 ECacheOfflineFlag offline_flag,
431 						 GCancellable *cancellable,
432 						 GError **error);
433 gboolean	e_cache_remove_all		(ECache *cache,
434 						 GCancellable *cancellable,
435 						 GError **error);
436 guint		e_cache_get_count		(ECache *cache,
437 						 ECacheDeletedFlag deleted_flag,
438 						 GCancellable *cancellable,
439 						 GError **error);
440 gboolean	e_cache_get_uids		(ECache *cache,
441 						 ECacheDeletedFlag deleted_flag,
442 						 GSList **out_uids, /* gchar * */
443 						 GSList **out_revisions, /* gchar * */
444 						 GCancellable *cancellable,
445 						 GError **error);
446 gboolean	e_cache_get_objects		(ECache *cache,
447 						 ECacheDeletedFlag deleted_flag,
448 						 GSList **out_objects, /* gchar * */
449 						 GSList **out_revisions, /* gchar * */
450 						 GCancellable *cancellable,
451 						 GError **error);
452 gboolean	e_cache_foreach			(ECache *cache,
453 						 ECacheDeletedFlag deleted_flag,
454 						 const gchar *where_clause,
455 						 ECacheForeachFunc func,
456 						 gpointer user_data,
457 						 GCancellable *cancellable,
458 						 GError **error);
459 gboolean	e_cache_foreach_update		(ECache *cache,
460 						 ECacheDeletedFlag deleted_flag,
461 						 const gchar *where_clause,
462 						 ECacheUpdateFunc func,
463 						 gpointer user_data,
464 						 GCancellable *cancellable,
465 						 GError **error);
466 void		e_cache_copy_missing_to_column_values
467 						(ECache *cache,
468 						 gint ncols,
469 						 const gchar *column_names[],
470 						 const gchar *column_values[],
471 						 ECacheColumnValues *other_columns);
472 
473 /* Offline support */
474 EOfflineState	e_cache_get_offline_state	(ECache *cache,
475 						 const gchar *uid,
476 						 GCancellable *cancellable,
477 						 GError **error);
478 gboolean	e_cache_set_offline_state	(ECache *cache,
479 						 const gchar *uid,
480 						 EOfflineState state,
481 						 GCancellable *cancellable,
482 						 GError **error);
483 GSList *	e_cache_get_offline_changes	(ECache *cache,
484 						 GCancellable *cancellable,
485 						 GError **error);
486 gboolean	e_cache_clear_offline_changes	(ECache *cache,
487 						 GCancellable *cancellable,
488 						 GError **error);
489 
490 /* Custom keys */
491 gboolean	e_cache_set_key			(ECache *cache,
492 						 const gchar *key,
493 						 const gchar *value,
494 						 GError **error);
495 gchar *		e_cache_dup_key			(ECache *cache,
496 						 const gchar *key,
497 						 GError **error);
498 gboolean	e_cache_set_key_int		(ECache *cache,
499 						 const gchar *key,
500 						 gint value,
501 						 GError **error);
502 gint		e_cache_get_key_int		(ECache *cache,
503 						 const gchar *key,
504 						 GError **error);
505 
506 /* Locking */
507 void		e_cache_lock			(ECache *cache,
508 						 ECacheLockType lock_type);
509 void		e_cache_unlock			(ECache *cache,
510 						 ECacheUnlockAction action);
511 
512 /* Low-level SQLite functions */
513 gpointer	e_cache_get_sqlitedb		(ECache *cache);
514 gboolean	e_cache_sqlite_exec		(ECache *cache,
515 						 const gchar *sql_stmt,
516 						 GCancellable *cancellable,
517 						 GError **error);
518 gboolean	e_cache_sqlite_select		(ECache *cache,
519 						 const gchar *sql_stmt,
520 						 ECacheSelectFunc func,
521 						 gpointer user_data,
522 						 GCancellable *cancellable,
523 						 GError **error);
524 gboolean	e_cache_sqlite_maybe_vacuum	(ECache *cache,
525 						 GCancellable *cancellable,
526 						 GError **error);
527 
528 void		e_cache_sqlite_stmt_append_printf
529 						(GString *stmt,
530 						 const gchar *format,
531 						 ...);
532 gchar *		e_cache_sqlite_stmt_printf	(const gchar *format,
533 						 ...);
534 void		e_cache_sqlite_stmt_free	(gchar *stmt);
535 
536 G_END_DECLS
537 
538 #endif /* E_CACHE_H */
539