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