diff options
-rw-r--r-- | addressbook/ChangeLog | 17 | ||||
-rw-r--r-- | addressbook/backend/idl/addressbook.idl | 2 | ||||
-rw-r--r-- | addressbook/backend/pas/pas-backend-file.c | 178 | ||||
-rw-r--r-- | addressbook/backend/pas/pas-book.c | 8 | ||||
-rw-r--r-- | addressbook/backend/pas/pas-book.h | 1 | ||||
-rw-r--r-- | e-util/ChangeLog | 8 | ||||
-rw-r--r-- | e-util/Makefile.am | 2 | ||||
-rw-r--r-- | e-util/e-dbhash.c | 194 | ||||
-rw-r--r-- | e-util/e-dbhash.h | 45 |
9 files changed, 390 insertions, 65 deletions
diff --git a/addressbook/ChangeLog b/addressbook/ChangeLog index 8d8097b2a8..284b703570 100644 --- a/addressbook/ChangeLog +++ b/addressbook/ChangeLog @@ -1,3 +1,20 @@ +2000-11-07 JP Rosevear <jpr@helixcode.com> + + * backend/pas/pas-book.h: Update PASRequest structure + + * backend/pas/pas-book.c (impl_Evolution_Book_get_changes): update param name + (pas_book_queue_get_changes): Use PASRequest change_id slot + + * backend/pas/pas-backend-file.c (pas_backend_file_book_view_copy): + Properly copy change_id and change_context + (pas_backend_file_book_view_free): Free change_id/change_context + (pas_backend_file_changes_foreach_key): Callback to figure out the + deleted cards + (pas_backend_file_changes): Use new e-dbhash stuff to implement. + Write out updated hash + + * backend/idl/addressbook.idl: Rename get_changes param + 2000-11-06 Christopher James Lahey <clahey@helixcode.com> * gui/component/addressbook.c: Switched from EAddressbookSearch to diff --git a/addressbook/backend/idl/addressbook.idl b/addressbook/backend/idl/addressbook.idl index 2c5a54487e..95d52e085c 100644 --- a/addressbook/backend/idl/addressbook.idl +++ b/addressbook/backend/idl/addressbook.idl @@ -83,7 +83,7 @@ module Evolution { */ void get_book_view(in BookViewListener listener, in string query); - void get_changes(in BookViewListener listener, in string changeid); + void get_changes(in BookViewListener listener, in string change_id); void check_connection (); diff --git a/addressbook/backend/pas/pas-backend-file.c b/addressbook/backend/pas/pas-backend-file.c index 84a21d4c6f..d90c33c76a 100644 --- a/addressbook/backend/pas/pas-backend-file.c +++ b/addressbook/backend/pas/pas-backend-file.c @@ -26,6 +26,7 @@ #include "pas-card-cursor.h" #include <ebook/e-card-simple.h> #include <e-util/e-sexp.h> +#include <e-util/e-dbhash.h> #include <gal/util/e-util.h> #include <gal/widgets/e-unicode.h> @@ -36,6 +37,7 @@ static PASBackendClass *pas_backend_file_parent_class; typedef struct _PASBackendFileCursorPrivate PASBackendFileCursorPrivate; typedef struct _PASBackendFileBookView PASBackendFileBookView; typedef struct _PASBackendFileSearchContext PASBackendFileSearchContext; +typedef struct _PasBackendFileChangeContext PASBackendFileChangeContext; struct _PASBackendFilePrivate { GList *clients; @@ -58,24 +60,46 @@ struct _PASBackendFileBookView { gchar *search; ESExp *search_sexp; PASBackendFileSearchContext *search_context; + gchar *change_id; + PASBackendFileChangeContext *change_context; }; struct _PASBackendFileSearchContext { ECardSimple *card; }; +struct _PasBackendFileChangeContext { + DB *db; + + GList *add_cards; + GList *add_ids; + GList *mod_cards; + GList *mod_ids; + GList *del_cards; + GList *del_ids; +}; + static PASBackendFileBookView * pas_backend_file_book_view_copy(const PASBackendFileBookView *book_view, void *closure) { PASBackendFileBookView *new_book_view; new_book_view = g_new(PASBackendFileBookView, 1); new_book_view->book_view = book_view->book_view; + new_book_view->search = g_strdup(book_view->search); new_book_view->search_sexp = book_view->search_sexp; if (new_book_view->search_sexp) gtk_object_ref(GTK_OBJECT(new_book_view->search_sexp)); new_book_view->search_context = g_new(PASBackendFileSearchContext, 1); new_book_view->search_context->card = book_view->search_context->card; + + new_book_view->change_id = g_strdup(book_view->change_id); + new_book_view->change_context = g_new(PASBackendFileChangeContext, 1); + new_book_view->change_context->db = book_view->change_context->db; + new_book_view->change_context->add_cards = book_view->change_context->add_cards; + new_book_view->change_context->mod_cards = book_view->change_context->mod_cards; + new_book_view->change_context->del_cards = book_view->change_context->del_cards; + return new_book_view; } @@ -86,6 +110,8 @@ pas_backend_file_book_view_free(PASBackendFileBookView *book_view, void *closure if (book_view->search_sexp) gtk_object_unref(GTK_OBJECT(book_view->search_sexp)); g_free(book_view->search_context); + g_free(book_view->change_id); + g_free(book_view->change_context); g_free(book_view); } @@ -485,49 +511,49 @@ pas_backend_file_search (PASBackendFile *bf, g_list_free (cards); } -typedef enum { - VCardChangeNone, - VCardChangeAdded, - VCardChangeModified, - VCardChangeDeleted -} VCardChangeType; - -static VCardChangeType -vcard_change_type (const PASBackendFileBookView *view, char *vcard_string) +static void +pas_backend_file_changes_foreach_key (const char *key, gpointer user_data) { - ECard *card; - - card = e_card_new (vcard_string); - view->search_context->card = e_card_simple_new (card); - gtk_object_unref(GTK_OBJECT(card)); - - /* if it's not a valid vcard why is it in our db? :) */ - if (!view->search_context->card) - return VCardChangeNone; - - /* FIX ME, actually need to implement this */ - - gtk_object_unref(GTK_OBJECT(view->search_context->card)); + PASBackendFileChangeContext *ctx = user_data; + DB *db = ctx->db; + DBT id_dbt, vcard_dbt; + int db_error = 0; + + string_to_dbt (key, &id_dbt); + db_error = db->get (db, &id_dbt, &vcard_dbt, 0); + + if (db_error == 1) { + char *id = id_dbt.data; + char *vcard_string = vcard_dbt.data; - return VCardChangeNone; + ctx->del_cards = g_list_append (ctx->del_cards, strdup(vcard_string)); + ctx->del_ids = g_list_append (ctx->del_ids, strdup(id)); + } } static void -pas_backend_file_search_changes (PASBackendFile *bf, - PASBook *book, - const PASBackendFileBookView *cnstview) +pas_backend_file_changes (PASBackendFile *bf, + PASBook *book, + const PASBackendFileBookView *cnstview) { int db_error = 0; - GList *add_cards = NULL; - GList *mod_cards = NULL; - GList *del_cards = NULL; DB *db = bf->priv->file_db; DBT id_dbt, vcard_dbt; + char *filename; + EDbHash *ehash; + GList *i, *v; PASBackendFileBookView *view = (PASBackendFileBookView *)cnstview; + PASBackendFileChangeContext *ctx = cnstview->change_context; if (!bf->priv->loaded) return; + /* Find the changed ids */ + filename = g_strdup ("test"); + + ehash = e_dbhash_new (filename); + g_free (filename); + db_error = db->seq(db, &id_dbt, &vcard_dbt, R_FIRST); while (db_error == 0) { @@ -535,20 +561,20 @@ pas_backend_file_search_changes (PASBackendFile *bf, /* don't include the version in the list of cards */ if (id_dbt.size != strlen(PAS_BACKEND_FILE_VERSION_NAME) + 1 || strcmp (id_dbt.data, PAS_BACKEND_FILE_VERSION_NAME)) { + char *id = id_dbt.data; char *vcard_string = vcard_dbt.data; /* check what type of change has occurred, if any */ - switch (vcard_change_type (view, vcard_string)) { - case VCardChangeNone: + switch (e_dbhash_compare (ehash, id, vcard_string)) { + case E_DBHASH_STATUS_SAME: break; - case VCardChangeAdded: - add_cards = g_list_append (add_cards, strdup(vcard_string)); + case E_DBHASH_STATUS_NOT_FOUND: + ctx->add_cards = g_list_append (ctx->add_cards, strdup(vcard_string)); + ctx->add_ids = g_list_append (ctx->add_ids, strdup(id)); break; - case VCardChangeModified: - mod_cards = g_list_append (mod_cards, strdup(vcard_string)); - break; - case VCardChangeDeleted: - del_cards = g_list_append (del_cards, strdup(vcard_string)); + case E_DBHASH_STATUS_DIFFERENT: + ctx->mod_cards = g_list_append (ctx->mod_cards, strdup(vcard_string)); + ctx->mod_ids = g_list_append (ctx->mod_ids, strdup(id)); break; } } @@ -556,31 +582,55 @@ pas_backend_file_search_changes (PASBackendFile *bf, db_error = db->seq(db, &id_dbt, &vcard_dbt, R_NEXT); } + e_dbhash_foreach_key (ehash, (EDbHashFunc *)pas_backend_file_changes_foreach_key, view->change_context); + + /* Update the hash */ + for (i = ctx->add_ids, v = ctx->add_cards; i != NULL; i = i->next, v = v->next){ + char *id = i->data; + char *vcard = v->data; + e_dbhash_add (ehash, id, vcard); + } + for (i = ctx->mod_ids, v = ctx->mod_cards; i != NULL; i = i->next, v = v->next){ + char *id = i->data; + char *vcard = v->data; + e_dbhash_add (ehash, id, vcard); + } + for (i = ctx->del_ids; i != NULL; i = i->next){ + char *id = i->data; + e_dbhash_remove (ehash, id); + } + + e_dbhash_write (ehash); + e_dbhash_destroy (ehash); + + /* Send the changes */ if (db_error == -1) { - g_warning ("pas_backend_file_search_changes: error building list\n"); + g_warning ("pas_backend_file_changes: error building list\n"); } else { - GList *l; - - pas_book_view_notify_add (view->book_view, add_cards); - pas_book_view_notify_change (view->book_view, mod_cards); + pas_book_view_notify_add (view->book_view, ctx->add_cards); + pas_book_view_notify_change (view->book_view, ctx->mod_cards); - for (l = del_cards; l != NULL; l = l->next){ - char *card = l->data; - pas_book_view_notify_remove (view->book_view, card); + for (v = ctx->del_cards; v != NULL; v = v->next){ + char *vcard = v->data; + pas_book_view_notify_remove (view->book_view, vcard); } pas_book_view_notify_complete (view->book_view); } - /* - ** It's fine to do this now since the data has been handed off. - */ - g_list_foreach (add_cards, (GFunc)g_free, NULL); - g_list_foreach (mod_cards, (GFunc)g_free, NULL); - g_list_foreach (del_cards, (GFunc)g_free, NULL); - g_list_free (add_cards); - g_list_free (mod_cards); - g_list_free (del_cards); + /* It's fine to do this now since the data has been handed off. */ + g_list_foreach (ctx->add_cards, (GFunc)g_free, NULL); + g_list_foreach (ctx->add_ids, (GFunc)g_free, NULL); + g_list_foreach (ctx->mod_cards, (GFunc)g_free, NULL); + g_list_foreach (ctx->mod_ids, (GFunc)g_free, NULL); + g_list_foreach (ctx->del_cards, (GFunc)g_free, NULL); + g_list_foreach (ctx->del_ids, (GFunc)g_free, NULL); + g_list_free (ctx->add_cards); + g_list_free (ctx->add_ids); + g_list_free (ctx->mod_cards); + g_list_free (ctx->mod_ids); + g_list_free (ctx->del_cards); + g_list_free (ctx->del_ids); } static char * @@ -955,7 +1005,7 @@ pas_backend_file_process_get_changes (PASBackend *backend, PASBookView *book_view; Evolution_Book corba_book; PASBackendFileBookView view; - PASBackendFileSearchContext ctx; + PASBackendFileChangeContext ctx; EIterator *iterator; g_return_if_fail (req->listener != NULL); @@ -985,16 +1035,24 @@ pas_backend_file_process_get_changes (PASBackend *backend, book_view); view.book_view = book_view; - view.search = req->search; + view.change_id = req->change_id; + view.change_context = &ctx; + ctx.db = NULL; + ctx.add_cards = NULL; + ctx.add_ids = NULL; + ctx.mod_cards = NULL; + ctx.mod_ids = NULL; + ctx.del_cards = NULL; + ctx.del_ids = NULL; + view.search = NULL; view.search_sexp = NULL; - view.search_context = &ctx; - ctx.card = NULL; + view.search_context = NULL; e_list_append(bf->priv->book_views, &view); iterator = e_list_get_iterator(bf->priv->book_views); e_iterator_last(iterator); - pas_backend_file_search_changes (bf, book, e_iterator_get(iterator)); + pas_backend_file_changes (bf, book, e_iterator_get(iterator)); gtk_object_unref(GTK_OBJECT(iterator)); g_free(req->search); diff --git a/addressbook/backend/pas/pas-book.c b/addressbook/backend/pas/pas-book.c index 6a8c17a584..b1d2688b3f 100644 --- a/addressbook/backend/pas/pas-book.c +++ b/addressbook/backend/pas/pas-book.c @@ -130,14 +130,14 @@ pas_book_queue_get_book_view (PASBook *book, const Evolution_BookViewListener li } static void -pas_book_queue_get_changes (PASBook *book, const Evolution_BookViewListener listener, const char *search) +pas_book_queue_get_changes (PASBook *book, const Evolution_BookViewListener listener, const char *change_id) { PASRequest *req; CORBA_Environment ev; req = g_new0 (PASRequest, 1); req->op = GetChanges; - req->search = g_strdup(search); + req->change_id= g_strdup(change_id); CORBA_exception_init (&ev); @@ -259,12 +259,12 @@ impl_Evolution_Book_get_book_view (PortableServer_Servant servant, static void impl_Evolution_Book_get_changes (PortableServer_Servant servant, const Evolution_BookViewListener listener, - const CORBA_char *search, + const CORBA_char *change_id, CORBA_Environment *ev) { PASBook *book = PAS_BOOK (bonobo_object_from_servant (servant)); - pas_book_queue_get_changes (book, listener, search); + pas_book_queue_get_changes (book, listener, change_id); } static void diff --git a/addressbook/backend/pas/pas-book.h b/addressbook/backend/pas/pas-book.h index ab59d7bb3e..68b0c60fda 100644 --- a/addressbook/backend/pas/pas-book.h +++ b/addressbook/backend/pas/pas-book.h @@ -38,6 +38,7 @@ typedef struct { char *id; char *vcard; char *search; + char *change_id; Evolution_BookViewListener listener; } PASRequest; diff --git a/e-util/ChangeLog b/e-util/ChangeLog index 9cad1815d6..f30bfe7724 100644 --- a/e-util/ChangeLog +++ b/e-util/ChangeLog @@ -1,3 +1,11 @@ +2000-11-07 JP Rosevear <jpr@helixcode.com> + + * Makefile.am: Build e-dbhash.[hc] + + * e-dbhash.[hc]: New routines to manage a db database on disk that + contains md5 hashed data and indexed by uids. Provides comparison + functions and such so the caller does not have to do the md5 bits. + 200-10-30 Kjartan Maraas <kmaraas@gnome.org> * e-dialog-widgets.c: #include <string.h> to quench warning. diff --git a/e-util/Makefile.am b/e-util/Makefile.am index a2c25b0501..856cecf46a 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -31,6 +31,8 @@ libeutil_la_SOURCES = \ e-list.h \ e-sexp.c \ e-sexp.h \ + e-dbhash.c \ + e-dbhash.h \ md5-utils.c \ md5-utils.h diff --git a/e-util/e-dbhash.c b/e-util/e-dbhash.c new file mode 100644 index 0000000000..57cf8ff9c1 --- /dev/null +++ b/e-util/e-dbhash.c @@ -0,0 +1,194 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Author: + * JP Rosevear (jpr@helixcode.com) + * + * Copyright 2000, Helix Code, Inc. + */ + +#include <config.h> +#include <string.h> +#include <fcntl.h> +#ifdef HAVE_DB_185_H +#include <db_185.h> +#else +#ifdef HAVE_DB1_DB_H +#include <db1/db.h> +#else +#include <db.h> +#endif +#endif +#include "md5-utils.h" +#include "e-dbhash.h" + +struct _EDbHashPrivate +{ + DB *db; +}; + +EDbHash * +e_dbhash_new (const char *filename) +{ + EDbHash *edbh; + DB *db; + + /* Attempt to open the database */ + db = dbopen (filename, O_RDWR, 0666, DB_HASH, NULL); + if (db == NULL) { + db = dbopen (filename, O_RDWR | O_CREAT, 0666, DB_HASH, NULL); + + if (db == NULL) + return NULL; + } + + edbh = g_new (EDbHash, 1); + edbh->priv = g_new (EDbHashPrivate, 1); + edbh->priv->db = db; + + return edbh; +} + +static void +string_to_dbt(const char *str, DBT *dbt) +{ + dbt->data = (void*)str; + dbt->size = strlen (str) + 1; +} + +void +e_dbhash_add (EDbHash *edbh, const gchar *key, const gchar *data) +{ + DB *db; + DBT dkey; + DBT ddata; + guchar local_hash[16]; + + g_return_if_fail (edbh != NULL); + g_return_if_fail (edbh->priv != NULL); + g_return_if_fail (edbh->priv->db != NULL); + g_return_if_fail (key != NULL); + g_return_if_fail (data != NULL); + + db = edbh->priv->db; + + /* Key dbt */ + string_to_dbt (key, &dkey); + + /* Data dbt */ + md5_get_digest (data, strlen (data), local_hash); + string_to_dbt (local_hash, &ddata); + + /* Add to database */ + db->put (db, &dkey, &ddata, 0); + + g_free (local_hash); +} + +void +e_dbhash_remove (EDbHash *edbh, const char *key) +{ + DB *db; + DBT dkey; + + g_return_if_fail (edbh != NULL); + g_return_if_fail (edbh->priv != NULL); + g_return_if_fail (key != NULL); + + db = edbh->priv->db; + + /* Key dbt */ + string_to_dbt (key, &dkey); + + /* Remove from database */ + db->del (db, &dkey, 0); +} + +void +e_dbhash_foreach_key (EDbHash *edbh, EDbHashFunc *func, gpointer user_data) +{ + DB *db; + DBT dkey; + DBT ddata; + int db_error = 0; + + g_return_if_fail (edbh != NULL); + g_return_if_fail (edbh->priv != NULL); + g_return_if_fail (func != NULL); + + db = edbh->priv->db; + + db_error = db->seq(db, &dkey, &ddata, R_FIRST); + + while (db_error == 0) { + (*func) ((const char *)dkey.data, user_data); + + db_error = db->seq(db, &dkey, &ddata, R_NEXT); + } +} + +EDbHashStatus +e_dbhash_compare (EDbHash *edbh, const char *key, const char *compare_data) +{ + DB *db; + DBT dkey; + DBT ddata; + guchar compare_hash[16]; + + g_return_val_if_fail (edbh != NULL, FALSE); + g_return_val_if_fail (edbh->priv != NULL, FALSE); + g_return_val_if_fail (key != NULL, FALSE); + g_return_val_if_fail (compare_hash != NULL, FALSE); + + db = edbh->priv->db; + + /* Key dbt */ + string_to_dbt (key, &dkey); + + /* Lookup in database */ + db->get (db, &dkey, &ddata, 0); + + /* Compare */ + if (ddata.data) { + md5_get_digest (compare_data, strlen (compare_data), compare_hash); + + if (memcmp (ddata.data, compare_hash, sizeof (guchar) * 16)) + return E_DBHASH_STATUS_DIFFERENT; + } else { + return E_DBHASH_STATUS_NOT_FOUND; + } + + return E_DBHASH_STATUS_SAME; +} + +void +e_dbhash_write (EDbHash *edbh) +{ + DB *db; + + g_return_if_fail (edbh != NULL); + g_return_if_fail (edbh->priv != NULL); + + db = edbh->priv->db; + + /* Flush database to disk */ + db->sync (db, 0); +} + +void +e_dbhash_destroy (EDbHash *edbh) +{ + DB *db; + + g_return_if_fail (edbh != NULL); + g_return_if_fail (edbh->priv != NULL); + + db = edbh->priv->db; + + /* Close datbase */ + db->close (db); + + g_free (edbh->priv); + g_free (edbh); +} + + diff --git a/e-util/e-dbhash.h b/e-util/e-dbhash.h new file mode 100644 index 0000000000..11fcdceb80 --- /dev/null +++ b/e-util/e-dbhash.h @@ -0,0 +1,45 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Writes hashes that go to/from disk in db form. Hash keys are strings + * + * Author: + * JP Rosevear (jpr@helixcode.com) + * + * Copyright 2000, Helix Code, Inc. + */ + +#ifndef __E_DBHASH_H__ +#define __E_DBHASH_H__ + +#include <glib.h> + +typedef enum { + E_DBHASH_STATUS_SAME, + E_DBHASH_STATUS_DIFFERENT, + E_DBHASH_STATUS_NOT_FOUND, +} EDbHashStatus; + +typedef struct _EDbHash EDbHash; +typedef struct _EDbHashPrivate EDbHashPrivate; + +struct _EDbHash +{ + EDbHashPrivate *priv; +}; + +typedef void (*EDbHashFunc) (const char *key, gpointer user_data); + +EDbHash *e_dbhash_new (const char *filename); + +void e_dbhash_add (EDbHash *edbh, const char *key, const char *data); +void e_dbhash_remove (EDbHash *edbh, const char *key); + +EDbHashStatus e_dbhash_compare (EDbHash *edbh, const char *key, const char *compare_data); +void e_dbhash_foreach_key (EDbHash *edbh, EDbHashFunc *func, gpointer user_data); + +void e_dbhash_write (EDbHash *edbh); + +void e_dbhash_destroy (EDbHash *edbh); + +#endif /* ! __E_DBHASH_H__ */ + |