00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "config.h"
00037
00038 #include <stdlib.h>
00039 #include <string.h>
00040
00041 #include <glib.h>
00042
00043 #include "qof.h"
00044 #include "qofevent-p.h"
00045 #include "qofbackend-p.h"
00046 #include "qofbook-p.h"
00047 #include "qofid-p.h"
00048 #include "qofobject-p.h"
00049
00050 static QofLogModule log_module = QOF_MOD_ENGINE;
00051
00052 QOF_GOBJECT_IMPL(qof_book, QofBook, QOF_TYPE_INSTANCE);
00053
00054
00055
00056
00057 static void coll_destroy(gpointer col)
00058 {
00059 qof_collection_destroy((QofCollection *) col);
00060 }
00061
00062 static void
00063 qof_book_init (QofBook *book)
00064 {
00065 if (!book) return;
00066
00067 book->hash_of_collections = g_hash_table_new_full(
00068 g_str_hash, g_str_equal,
00069 (GDestroyNotify)qof_util_string_cache_remove,
00070 coll_destroy);
00071
00072 qof_instance_init_data (&book->inst, QOF_ID_BOOK, book);
00073
00074 book->data_tables = g_hash_table_new (g_str_hash, g_str_equal);
00075 book->data_table_finalizers = g_hash_table_new (g_str_hash, g_str_equal);
00076
00077 book->book_open = 'y';
00078 book->version = 0;
00079 }
00080
00081 QofBook *
00082 qof_book_new (void)
00083 {
00084 QofBook *book;
00085
00086 ENTER (" ");
00087 book = g_object_new(QOF_TYPE_BOOK, NULL);
00088 qof_object_book_begin (book);
00089
00090 qof_event_gen (&book->inst, QOF_EVENT_CREATE, NULL);
00091 LEAVE ("book=%p", book);
00092 return book;
00093 }
00094
00095 static void
00096 book_final (gpointer key, gpointer value, gpointer booq)
00097 {
00098 QofBookFinalCB cb = value;
00099 QofBook *book = booq;
00100
00101 gpointer user_data = g_hash_table_lookup (book->data_tables, key);
00102 (*cb) (book, key, user_data);
00103 }
00104
00105 static void
00106 qof_book_dispose_real (GObject *bookp)
00107 {
00108 }
00109
00110 static void
00111 qof_book_finalize_real (GObject *bookp)
00112 {
00113 }
00114
00115 void
00116 qof_book_destroy (QofBook *book)
00117 {
00118 GHashTable* cols;
00119
00120 if (!book) return;
00121 ENTER ("book=%p", book);
00122
00123 book->shutting_down = TRUE;
00124 qof_event_force (&book->inst, QOF_EVENT_DESTROY, NULL);
00125
00126
00127
00128
00129 g_hash_table_foreach (book->data_table_finalizers, book_final, book);
00130
00131 qof_object_book_end (book);
00132
00133 g_hash_table_destroy (book->data_table_finalizers);
00134 book->data_table_finalizers = NULL;
00135 g_hash_table_destroy (book->data_tables);
00136 book->data_tables = NULL;
00137
00138
00139
00140
00141
00142
00143
00144
00145 cols = book->hash_of_collections;
00146 g_object_unref (book);
00147 g_hash_table_destroy (cols);
00148 book->hash_of_collections = NULL;
00149
00150 LEAVE ("book=%p", book);
00151 }
00152
00153
00154
00155
00156 gboolean
00157 qof_book_equal (const QofBook *book_1, const QofBook *book_2)
00158 {
00159 if (book_1 == book_2) return TRUE;
00160 if (!book_1 || !book_2) return FALSE;
00161 return FALSE;
00162 }
00163
00164
00165
00166 gboolean
00167 qof_book_not_saved (const QofBook *book)
00168 {
00169 if (!book) return FALSE;
00170
00171 return(qof_instance_get_dirty_flag(book) || qof_object_is_dirty(book));
00172 }
00173
00174 void
00175 qof_book_mark_saved (QofBook *book)
00176 {
00177 gboolean was_dirty;
00178
00179 if (!book) return;
00180
00181 was_dirty = qof_instance_get_dirty_flag(book);
00182 qof_instance_set_dirty_flag(book, FALSE);
00183 book->dirty_time = 0;
00184 qof_object_mark_clean (book);
00185 if (was_dirty) {
00186 if (book->dirty_cb)
00187 book->dirty_cb(book, FALSE, book->dirty_data);
00188 }
00189 }
00190
00191 void qof_book_mark_dirty (QofBook *book)
00192 {
00193 gboolean was_dirty;
00194
00195 if (!book) return;
00196
00197 was_dirty = qof_instance_get_dirty_flag(book);
00198 qof_instance_set_dirty_flag(book, TRUE);
00199 if (!was_dirty) {
00200 book->dirty_time = time(NULL);
00201 if (book->dirty_cb)
00202 book->dirty_cb(book, TRUE, book->dirty_data);
00203 }
00204 }
00205
00206 void
00207 qof_book_print_dirty (const QofBook *book)
00208 {
00209 if (qof_instance_get_dirty_flag(book))
00210 printf("book is dirty.\n");
00211 qof_book_foreach_collection
00212 (book, (QofCollectionForeachCB)qof_collection_print_dirty, NULL);
00213 }
00214
00215 time_t
00216 qof_book_get_dirty_time (const QofBook *book)
00217 {
00218 return book->dirty_time;
00219 }
00220
00221 void
00222 qof_book_set_dirty_cb(QofBook *book, QofBookDirtyCB cb, gpointer user_data)
00223 {
00224 if (book->dirty_cb)
00225 g_warning("qof_book_set_dirty_cb: Already existing callback %p, will be overwritten by %p\n",
00226 book->dirty_cb, cb);
00227 book->dirty_data = user_data;
00228 book->dirty_cb = cb;
00229 }
00230
00231
00232
00233
00234 QofBackend *
00235 qof_book_get_backend (const QofBook *book)
00236 {
00237 if (!book) return NULL;
00238 return book->backend;
00239 }
00240
00241 gboolean
00242 qof_book_shutting_down (const QofBook *book)
00243 {
00244 if (!book) return FALSE;
00245 return book->shutting_down;
00246 }
00247
00248
00249
00250
00251 void
00252 qof_book_set_backend (QofBook *book, QofBackend *be)
00253 {
00254 if (!book) return;
00255 ENTER ("book=%p be=%p", book, be);
00256 book->backend = be;
00257 LEAVE (" ");
00258 }
00259
00260 void qof_book_kvp_changed (QofBook *book)
00261 {
00262 qof_book_mark_dirty(book);
00263 }
00264
00265
00266
00267
00268
00269
00270 void
00271 qof_book_set_data (QofBook *book, const char *key, gpointer data)
00272 {
00273 if (!book || !key) return;
00274 g_hash_table_insert (book->data_tables, (gpointer)key, data);
00275 }
00276
00277 void
00278 qof_book_set_data_fin (QofBook *book, const char *key, gpointer data, QofBookFinalCB cb)
00279 {
00280 if (!book || !key) return;
00281 g_hash_table_insert (book->data_tables, (gpointer)key, data);
00282
00283 if (!cb) return;
00284 g_hash_table_insert (book->data_table_finalizers, (gpointer)key, cb);
00285 }
00286
00287 gpointer
00288 qof_book_get_data (const QofBook *book, const char *key)
00289 {
00290 if (!book || !key) return NULL;
00291 return g_hash_table_lookup (book->data_tables, (gpointer)key);
00292 }
00293
00294
00295
00296 QofCollection *
00297 qof_book_get_collection (const QofBook *book, QofIdType entity_type)
00298 {
00299 QofCollection *col;
00300
00301 if (!book || !entity_type) return NULL;
00302
00303 col = g_hash_table_lookup (book->hash_of_collections, entity_type);
00304 if (!col) {
00305 col = qof_collection_new (entity_type);
00306 g_hash_table_insert(
00307 book->hash_of_collections,
00308 qof_util_string_cache_insert((gpointer) entity_type), col);
00309 }
00310 return col;
00311 }
00312
00313 struct _iterate {
00314 QofCollectionForeachCB fn;
00315 gpointer data;
00316 };
00317
00318 static void
00319 foreach_cb (gpointer key, gpointer item, gpointer arg)
00320 {
00321 struct _iterate *iter = arg;
00322 QofCollection *col = item;
00323
00324 iter->fn (col, iter->data);
00325 }
00326
00327 void
00328 qof_book_foreach_collection (const QofBook *book,
00329 QofCollectionForeachCB cb, gpointer user_data)
00330 {
00331 struct _iterate iter;
00332
00333 g_return_if_fail (book);
00334 g_return_if_fail (cb);
00335
00336 iter.fn = cb;
00337 iter.data = user_data;
00338
00339 g_hash_table_foreach (book->hash_of_collections, foreach_cb, &iter);
00340 }
00341
00342
00343
00344 void qof_book_mark_closed (QofBook *book)
00345 {
00346 if(!book) { return; }
00347 book->book_open = 'n';
00348 }
00349
00350 gchar qof_book_get_open_marker(const QofBook *book)
00351 {
00352 if(!book) { return 'n'; }
00353 return book->book_open;
00354 }
00355
00356 gint32 qof_book_get_version (const QofBook *book)
00357 {
00358 if(!book) { return -1; }
00359 return book->version;
00360 }
00361
00362 void qof_book_set_version (QofBook *book, gint32 version)
00363 {
00364 if(!book && version < 0) { return; }
00365 book->version = version;
00366 }
00367
00368 gint64
00369 qof_book_get_counter (const QofBook *book, const char *counter_name)
00370 {
00371 QofBackend *be;
00372 KvpFrame *kvp;
00373 KvpValue *value;
00374 gint64 counter;
00375
00376 if (!book) {
00377 PWARN ("No book!!!");
00378 return -1;
00379 }
00380
00381 if (!counter_name || *counter_name == '\0') {
00382 PWARN ("Invalid counter name.");
00383 return -1;
00384 }
00385
00386
00387 be = book->backend;
00388 if (be && be->counter)
00389 return ((be->counter)(be, counter_name));
00390
00391
00392 kvp = qof_book_get_slots (book);
00393
00394 if (!kvp) {
00395 PWARN ("Book has no KVP_Frame");
00396 return -1;
00397 }
00398
00399 value = kvp_frame_get_slot_path (kvp, "counters", counter_name, NULL);
00400 if (value) {
00401
00402 counter = kvp_value_get_gint64 (value);
00403 } else {
00404
00405 counter = 0;
00406 }
00407
00408
00409 counter++;
00410
00411
00412 value = kvp_value_new_gint64 (counter);
00413 kvp_frame_set_slot_path (kvp, value, "counters", counter_name, NULL);
00414 kvp_value_delete (value);
00415
00416
00417 return counter;
00418 }
00419
00420
00421 gboolean qof_book_register (void)
00422 {
00423 static QofParam params[] = {
00424 { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_entity_get_guid, NULL },
00425 { QOF_PARAM_KVP, QOF_TYPE_KVP, (QofAccessFunc)qof_instance_get_slots, NULL },
00426 { NULL },
00427 };
00428
00429 qof_class_register (QOF_ID_BOOK, NULL, params);
00430
00431 return TRUE;
00432 }
00433
00434