QOF
0.7.5
|
00001 /********************************************************************\ 00002 * qofbook.c -- dataset access (set of books of entities) * 00003 * * 00004 * This program is free software; you can redistribute it and/or * 00005 * modify it under the terms of the GNU General Public License as * 00006 * published by the Free Software Foundation; either version 2 of * 00007 * the License, or (at your option) any later version. * 00008 * * 00009 * This program is distributed in the hope that it will be useful, * 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00012 * GNU General Public License for more details. * 00013 * * 00014 * You should have received a copy of the GNU General Public License* 00015 * along with this program; if not, contact: * 00016 * * 00017 * Free Software Foundation Voice: +1-617-542-5942 * 00018 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * 00019 * Boston, MA 02110-1301, USA gnu@gnu.org * 00020 \********************************************************************/ 00021 00022 /* 00023 * FILE: 00024 * qofbook.c 00025 * 00026 * FUNCTION: 00027 * Encapsulate all the information about a QOF dataset. 00028 * 00029 * HISTORY: 00030 * Created by Linas Vepstas December 1998 00031 * Copyright (c) 1998-2001,2003 Linas Vepstas <linas@linas.org> 00032 * Copyright (c) 2000 Dave Peticolas 00033 * Copyright (c) 2006 Neil Williams <linux@codehelp.co.uk> 00034 */ 00035 00036 #include "config.h" 00037 #include <stdlib.h> 00038 #include <string.h> 00039 #include <glib.h> 00040 #include "qof.h" 00041 #include "qofevent-p.h" 00042 #include "qofbackend-p.h" 00043 #include "qofbook-p.h" 00044 #include "qofid-p.h" 00045 #include "qofobject-p.h" 00046 00047 static QofLogModule log_module = QOF_MOD_ENGINE; 00048 00049 static void 00050 coll_destroy (gpointer col) 00051 { 00052 qof_collection_destroy ((QofCollection *) col); 00053 } 00054 00055 static void 00056 qof_book_init (QofBook * book) 00057 { 00058 if (!book) 00059 return; 00060 00061 book->hash_of_collections = 00062 g_hash_table_new_full (g_str_hash, g_str_equal, 00063 (GDestroyNotify) qof_util_string_cache_remove, coll_destroy); 00064 qof_instance_init (&book->inst, QOF_ID_BOOK, book); 00065 book->data_tables = g_hash_table_new (g_str_hash, g_str_equal); 00066 book->data_table_finalizers = 00067 g_hash_table_new (g_str_hash, g_str_equal); 00068 book->book_open = 'y'; 00069 book->version = 0; 00070 book->idata = 0; 00071 book->undo_data = g_new0 (QofUndo, 1); 00072 } 00073 00074 QofBook * 00075 qof_book_new (void) 00076 { 00077 QofBook *book; 00078 00079 ENTER (" "); 00080 book = g_new0 (QofBook, 1); 00081 qof_book_init (book); 00082 qof_object_book_begin (book); 00083 qof_event_gen (&book->inst.entity, QOF_EVENT_CREATE, NULL); 00084 LEAVE ("book=%p", book); 00085 return book; 00086 } 00087 00088 static void 00089 book_final (gpointer key, gpointer value, gpointer booq) 00090 { 00091 QofBookFinalCB cb = value; 00092 QofBook *book = booq; 00093 00094 gpointer user_data = g_hash_table_lookup (book->data_tables, key); 00095 (*cb) (book, key, user_data); 00096 } 00097 00098 void 00099 qof_book_destroy (QofBook * book) 00100 { 00101 if (!book) 00102 return; 00103 ENTER ("book=%p", book); 00104 book->shutting_down = TRUE; 00105 qof_event_force (&book->inst.entity, QOF_EVENT_DESTROY, NULL); 00106 /* Call the list of finalizers, let them do their thing. 00107 * Do this before tearing into the rest of the book. 00108 */ 00109 g_hash_table_foreach (book->data_table_finalizers, book_final, book); 00110 qof_object_book_end (book); 00111 g_hash_table_destroy (book->data_table_finalizers); 00112 book->data_table_finalizers = NULL; 00113 g_hash_table_destroy (book->data_tables); 00114 book->data_tables = NULL; 00115 qof_instance_release (&book->inst); 00116 g_hash_table_destroy (book->hash_of_collections); 00117 book->hash_of_collections = NULL; 00118 g_free (book); 00119 LEAVE ("book=%p", book); 00120 } 00121 00122 /* call is_equal callbacks on QofObject ? */ 00123 00124 gboolean 00125 qof_book_equal (QofBook * book_1, QofBook * book_2) 00126 { 00127 if (book_1 == book_2) 00128 return TRUE; 00129 if (!book_1 || !book_2) 00130 return FALSE; 00131 return TRUE; 00132 } 00133 00134 gboolean 00135 qof_book_not_saved (QofBook * book) 00136 { 00137 if (!book) 00138 return FALSE; 00139 00140 return (book->inst.dirty || qof_object_is_dirty (book)); 00141 } 00142 00143 void 00144 qof_book_mark_saved (QofBook * book) 00145 { 00146 if (!book) 00147 return; 00148 00149 book->inst.dirty = FALSE; 00150 qof_object_mark_clean (book); 00151 } 00152 00153 QofBackend * 00154 qof_book_get_backend (QofBook * book) 00155 { 00156 if (!book) 00157 return NULL; 00158 return book->backend; 00159 } 00160 00161 gboolean 00162 qof_book_shutting_down (QofBook * book) 00163 { 00164 if (!book) 00165 return FALSE; 00166 return book->shutting_down; 00167 } 00168 00169 void 00170 qof_book_set_backend (QofBook * book, QofBackend * be) 00171 { 00172 if (!book) 00173 return; 00174 ENTER ("book=%p be=%p", book, be); 00175 book->backend = be; 00176 LEAVE (" "); 00177 } 00178 00179 void 00180 qof_book_kvp_changed (QofBook * book) 00181 { 00182 if (!book) 00183 return; 00184 book->inst.dirty = TRUE; 00185 } 00186 00187 /* Store arbitrary pointers in the QofBook for data storage extensibility */ 00188 /* XXX if data is NULL, we should remove the key from the hash table! 00189 */ 00190 void 00191 qof_book_set_data (QofBook * book, const gchar * key, gpointer data) 00192 { 00193 if (!book || !key) 00194 return; 00195 g_hash_table_insert (book->data_tables, (gpointer) key, data); 00196 } 00197 00198 void 00199 qof_book_set_data_fin (QofBook * book, const gchar * key, 00200 gpointer data, QofBookFinalCB cb) 00201 { 00202 if (!book || !key) 00203 return; 00204 g_hash_table_insert (book->data_tables, (gpointer) key, data); 00205 00206 if (!cb) 00207 return; 00208 g_hash_table_insert (book->data_table_finalizers, (gpointer) key, cb); 00209 } 00210 00211 gpointer 00212 qof_book_get_data (QofBook * book, const gchar * key) 00213 { 00214 if (!book || !key) 00215 return NULL; 00216 return g_hash_table_lookup (book->data_tables, (gpointer) key); 00217 } 00218 00219 QofCollection * 00220 qof_book_get_collection (QofBook * book, QofIdType entity_type) 00221 { 00222 QofCollection *col; 00223 00224 if (!book || !entity_type) 00225 return NULL; 00226 col = g_hash_table_lookup (book->hash_of_collections, entity_type); 00227 if (!col) 00228 { 00229 col = qof_collection_new (entity_type); 00230 g_hash_table_insert (book->hash_of_collections, 00231 qof_util_string_cache_insert ((gpointer) entity_type), col); 00232 } 00233 return col; 00234 } 00235 00236 struct _iterate 00237 { 00238 QofCollectionForeachCB fn; 00239 gpointer data; 00240 }; 00241 00242 static void 00243 foreach_cb (gpointer key __attribute__ ((unused)), gpointer item, gpointer arg) 00244 { 00245 struct _iterate *qiter = arg; 00246 QofCollection *col = item; 00247 00248 qiter->fn (col, qiter->data); 00249 } 00250 00251 void 00252 qof_book_foreach_collection (QofBook * book, 00253 QofCollectionForeachCB cb, gpointer user_data) 00254 { 00255 struct _iterate qiter; 00256 00257 g_return_if_fail (book); 00258 g_return_if_fail (cb); 00259 qiter.fn = cb; 00260 qiter.data = user_data; 00261 g_hash_table_foreach (book->hash_of_collections, foreach_cb, &qiter); 00262 } 00263 00264 void 00265 qof_book_mark_closed (QofBook * book) 00266 { 00267 if (!book) 00268 { 00269 return; 00270 } 00271 book->book_open = 'n'; 00272 } 00273 00274 gchar 00275 qof_book_get_open_marker (QofBook * book) 00276 { 00277 if (!book) 00278 { 00279 return 'n'; 00280 } 00281 return book->book_open; 00282 } 00283 00284 gint32 00285 qof_book_get_version (QofBook * book) 00286 { 00287 if (!book) 00288 { 00289 return -1; 00290 } 00291 return book->version; 00292 } 00293 00294 guint32 00295 qof_book_get_idata (QofBook * book) 00296 { 00297 if (!book) 00298 { 00299 return 0; 00300 } 00301 return book->idata; 00302 } 00303 00304 void 00305 qof_book_set_version (QofBook * book, gint32 version) 00306 { 00307 if (!book && version < 0) 00308 { 00309 return; 00310 } 00311 book->version = version; 00312 } 00313 00314 void 00315 qof_book_set_idata (QofBook * book, guint32 idata) 00316 { 00317 if (!book && idata == 0) 00318 { 00319 return; 00320 } 00321 book->idata = idata; 00322 } 00323 00324 gint64 00325 qof_book_get_counter (QofBook * book, const gchar * counter_name) 00326 { 00327 QofBackend *be; 00328 KvpFrame *kvp; 00329 KvpValue *value; 00330 gint64 counter; 00331 00332 if (!book) 00333 { 00334 PWARN ("No book!!!"); 00335 return -1; 00336 } 00337 if (!counter_name || *counter_name == '\0') 00338 { 00339 PWARN ("Invalid counter name."); 00340 return -1; 00341 } 00342 /* If we've got a backend with a counter method, call it */ 00343 be = book->backend; 00344 if (be && be->counter) 00345 return ((be->counter) (be, counter_name)); 00346 /* If not, then use the KVP in the book */ 00347 kvp = qof_book_get_slots (book); 00348 if (!kvp) 00349 { 00350 PWARN ("Book has no KVP_Frame"); 00351 return -1; 00352 } 00353 value = kvp_frame_get_slot_path (kvp, "counters", counter_name, NULL); 00354 if (value) 00355 { 00356 /* found it */ 00357 counter = kvp_value_get_gint64 (value); 00358 } 00359 else 00360 { 00361 /* New counter */ 00362 counter = 0; 00363 } 00364 /* Counter is now valid; increment it */ 00365 counter++; 00366 /* Save off the new counter */ 00367 value = kvp_value_new_gint64 (counter); 00368 kvp_frame_set_slot_path (kvp, value, "counters", counter_name, NULL); 00369 kvp_value_delete (value); 00370 /* and return the value */ 00371 return counter; 00372 } 00373 00374 /* QofObject function implementation and registration */ 00375 gboolean 00376 qof_book_register (void) 00377 { 00378 static QofParam params[] = { 00379 {QOF_PARAM_GUID, QOF_TYPE_GUID, 00380 (QofAccessFunc) qof_entity_get_guid, 00381 NULL, NULL}, 00382 {QOF_PARAM_KVP, QOF_TYPE_KVP, 00383 (QofAccessFunc) qof_instance_get_slots, 00384 NULL, NULL}, 00385 {NULL, NULL, NULL, NULL, NULL}, 00386 }; 00387 00388 qof_class_register (QOF_ID_BOOK, NULL, params); 00389 00390 return TRUE; 00391 } 00392 00393 /* ========================== END OF FILE =============================== */