diff --git a/src/engine/qofbook-p.h b/src/engine/qofbook-p.h index d3251bfce3..1edd3a2546 100644 --- a/src/engine/qofbook-p.h +++ b/src/engine/qofbook-p.h @@ -62,6 +62,9 @@ struct _QofBook */ GHashTable *data_tables; + /** Hash table of destroy callbacks for the data table. */ + GHashTable *data_table_finalizers; + /** state flag: 'y' means 'open for editing', * 'n' means 'book is closed' */ diff --git a/src/engine/qofbook.c b/src/engine/qofbook.c index 15daffd3d9..800dc46b01 100644 --- a/src/engine/qofbook.c +++ b/src/engine/qofbook.c @@ -69,6 +69,7 @@ qof_book_init (QofBook *book) book->kvp_data = kvp_frame_new (); book->data_tables = g_hash_table_new (g_str_hash, g_str_equal); + book->data_table_finalizers = g_hash_table_new (g_str_hash, g_str_equal); book->book_open = 'y'; book->version = 0; @@ -98,21 +99,35 @@ coll_destroy(gpointer key, gpointer value, gpointer not_used) return TRUE; } +static void +book_final (gpointer key, gpointer value, gpointer booq) +{ + QofBookFinalCB cb = value; + QofBook *book = booq; + + gpointer user_data = g_hash_table_lookup (book->data_tables, key); + (*cb) (book, key, user_data); +} + void qof_book_destroy (QofBook *book) { if (!book) return; + ENTER ("book=%p", book); book->shutting_down = TRUE; - - ENTER ("book=%p", book); gnc_engine_force_event (&book->entity, GNC_EVENT_DESTROY); + /* Call the list of finalizers, let them do thier thing. + * Do this before tearing into the rest of the book. + */ + g_hash_table_foreach (book->data_table_finalizers, book_final, book); + qof_object_book_end (book); kvp_frame_delete (book->kvp_data); - /* FIXME: Make sure the data_table is empty */ + g_hash_table_destroy (book->data_table_finalizers); g_hash_table_destroy (book->data_tables); qof_entity_release (&book->entity); @@ -201,13 +216,6 @@ void qof_book_kvp_changed (QofBook *book) /* Store arbitrary pointers in the QofBook for data storage extensibility */ /* XXX if data is NULL, we should remove the key from the hash table! - * - * XXX We need some design comments: an equivalent storage mechanism - * would have been to give each item a GUID, store the GUID in a kvp frame, - * and then do a GUID lookup to get the pointer to the actual object. - * Of course, doing a kvp lookup followed by a GUID lookup would be - * a good bit slower, but may be that's OK? In most cases, book data - * is accessed only infrequently? --linas */ void qof_book_set_data (QofBook *book, const char *key, gpointer data) @@ -216,6 +224,16 @@ qof_book_set_data (QofBook *book, const char *key, gpointer data) g_hash_table_insert (book->data_tables, (gpointer)key, data); } +void +qof_book_set_data_fin (QofBook *book, const char *key, gpointer data, QofBookFinalCB cb) +{ + if (!book || !key) return; + g_hash_table_insert (book->data_tables, (gpointer)key, data); + + if (!cb) return; + g_hash_table_insert (book->data_table_finalizers, (gpointer)key, cb); +} + gpointer qof_book_get_data (QofBook *book, const char *key) { diff --git a/src/engine/qofbook.h b/src/engine/qofbook.h index ab1e5cfffc..96df2ecb0b 100644 --- a/src/engine/qofbook.h +++ b/src/engine/qofbook.h @@ -67,6 +67,8 @@ typedef struct _QofBook QofBook; /** GList of QofBook */ typedef GList QofBookList; +typedef void (*QofBookFinalCB) (QofBook *, gpointer key, gpointer user_data); + /** Register the book object with the QOF object system. */ gboolean qof_book_register (void); @@ -90,19 +92,33 @@ QofCollection * qof_book_get_collection (QofBook *, QofIdType); typedef void (*QofCollectionForeachCB) (QofCollection *, gpointer user_data); void qof_book_foreach_collection (QofBook *, QofCollectionForeachCB, gpointer); -/** \return The kvp data for the book */ +/** \return The kvp data for the book. + * Note that the boom KVP data is persistant, and is stored/retrevied + * from the file/database. Thus, the book KVP is the correct place to + * store data that needs to be persistant accross sessions (or shared + * between multiple users). To store application runtime data, use + * qof_book_set_data() isntead. + */ KvpFrame * qof_book_get_slots (QofBook *book); /** The qof_book_set_data() allows arbitrary pointers to structs * to be stored in QofBook. This is the "prefered" method for - * extending QofBook to hold new data types. + * extending QofBook to hold new data types. This is also + * the ideal location to store other arbitrary runtime data + * that the application may need. * - * XXX FIXME: we need to add a destroy callback, so that when the - * book gets destroyed, the user gets notified and thus has a chance - * to clean up. + * The book data differs from the book KVP in that the contents + * of the book KVP are persistant (are saved and restored to file + * or database), whereas the data pointers exist only at runtime. */ void qof_book_set_data (QofBook *book, const char *key, gpointer data); +/** Same as qof_book_set_data(), except that the callback will be called + * when the book is destroyed. The argument to the callback will be + * the book followed by the data pointer. + */ +void qof_book_set_data_fin (QofBook *book, const char *key, gpointer data, QofBookFinalCB); + /** Retreives arbitrary pointers to structs stored by qof_book_set_data. */ gpointer qof_book_get_data (QofBook *book, const char *key);