aboutsummaryrefslogtreecommitdiffstats
path: root/addressbook/backend/pas/pas-backend-summary.c
diff options
context:
space:
mode:
authorChris Toshok <toshok@ximian.com>2002-07-10 16:47:11 +0800
committerChris Toshok <toshok@src.gnome.org>2002-07-10 16:47:11 +0800
commit35624a9226fbb36f075ed40d1a61369f73570252 (patch)
tree9e7035df9ecb557a7c9c7fedfe46dc17474607d7 /addressbook/backend/pas/pas-backend-summary.c
parenteed274191e31adb925555ebbb0fb58b7fb9989e8 (diff)
downloadgsoc2013-evolution-35624a9226fbb36f075ed40d1a61369f73570252.tar
gsoc2013-evolution-35624a9226fbb36f075ed40d1a61369f73570252.tar.gz
gsoc2013-evolution-35624a9226fbb36f075ed40d1a61369f73570252.tar.bz2
gsoc2013-evolution-35624a9226fbb36f075ed40d1a61369f73570252.tar.lz
gsoc2013-evolution-35624a9226fbb36f075ed40d1a61369f73570252.tar.xz
gsoc2013-evolution-35624a9226fbb36f075ed40d1a61369f73570252.tar.zst
gsoc2013-evolution-35624a9226fbb36f075ed40d1a61369f73570252.zip
add Book.getCompletionView.
2002-07-10 Chris Toshok <toshok@ximian.com> * backend/idl/addressbook.idl: add Book.getCompletionView. * backend/ebook/e-book.c (e_book_get_completion_view): new function, basically c&p of e_book_get_book_view, but call getCompletionView. * backend/ebook/e-book.h: add prototype for e_book_get_completion_view. * backend/pas/pas-backend-ldap.c (pas_backend_ldap_process_client_requests): add a GetCompletionView case here that just calls the same code as GetBookView (since we don't build summaries for the ldap backend.) * backend/pas/pas-backend-file.c (do_summary_query): add @completion_search. If it's TRUE, just create the vcards from the summary using pas_backend_summary_get_summary_vcard instead of looking them up from the db. (pas_backend_file_search): add @completion_search and pass it on to do_summary_query. (pas_backend_file_process_get_book_view): pass FALSE to pas_backend_file_search. (pas_backend_file_process_get_completion_view): new function, basically c&p pas_backend_file_process_get_book_view, but pass TRUE to pas_backend_file_search. (pas_backend_file_process_client_requests): add a case for GetCompletionView. (pas_backend_file_load_uri): track the change to the summary api - create the summary filename * backend/pas/pas-book.c (pas_book_queue_get_completion_view): new function, queue a GetCompletionView request to our queue. (impl_GNOME_Evolution_Addressbook_Book_getCompletionView): new function, call pas_book_queue_get_completion_view. (pas_book_respond_get_completion_view): new function, just call notifyViewRequested. (pas_book_free_request): add a case for GetCompletionView. (pas_book_get_epv): fill in epv->getCompletionView. * backend/pas/pas-book.h: add a GetCompletionView PASOperation, and a new structure (PASGetCompletionViewRequest). Also, add get_completion_view to PASRequest. * backend/pas/pas-backend-summary.c (clear_items): remove the items from the hash table. (pas_backend_summary_new): db_path -> summary_path. (pas_backend_summary_destroy): db_.path -> summary_path, and destroy the hash table. (pas_backend_summary_init): db_path = summary_path, and initialize the id_to_item hashtable. (pas_backend_summary_load_header): handle the upgrading from version 1.0 to version 2.0 (the addition of an mtime field in the header) (pas_backend_summary_load_item): version 1.0 and 2.0 have the same format for items. (pas_backend_summary_open): new function. open the summary so we can load the header (and get the mtime). (pas_backend_summary_load): rework this a bit since the header has already been loaded, and also add the items to the hashtable. (pas_backend_summary_add_card): add the new item to the hashtable. (pas_backend_summary_remove_card): remove the item from the hash table. (pas_backend_summary_is_up_to_date): new function, chekc @t against the summary's mtime. (pas_backend_summary_get_summary_vcard): create a vcard from the fields we have in the summary. * backend/pas/pas-backend-summary.h: add prorotypes for pas_backend_summary_is_up_to_date and pas_backend_summary_get_summary_vcard. svn path=/trunk/; revision=17402
Diffstat (limited to 'addressbook/backend/pas/pas-backend-summary.c')
-rw-r--r--addressbook/backend/pas/pas-backend-summary.c223
1 files changed, 145 insertions, 78 deletions
diff --git a/addressbook/backend/pas/pas-backend-summary.c b/addressbook/backend/pas/pas-backend-summary.c
index 3972426367..23a24c879e 100644
--- a/addressbook/backend/pas/pas-backend-summary.c
+++ b/addressbook/backend/pas/pas-backend-summary.c
@@ -39,13 +39,16 @@
static GtkObjectClass *parent_class;
struct _PASBackendSummaryPrivate {
- char *db_path;
char *summary_path;
+ FILE *fp;
guint32 file_version;
+ time_t mtime;
gboolean dirty;
int flush_timeout_millis;
int flush_timeout;
GPtrArray *items;
+ GHashTable *id_to_item;
+ guint32 num_items; /* used only for loading */
#ifdef SUMMARY_STATS
int size;
#endif
@@ -73,19 +76,21 @@ typedef struct {
guint16 email_1_len;
guint16 email_2_len;
guint16 email_3_len;
-} PASBackendSummaryDiskItem_1_0;
+} PASBackendSummaryDiskItem;
typedef struct {
guint32 file_version;
guint32 num_items;
+ guint32 summary_mtime; /* version 2.0 field */
} PASBackendSummaryHeader;
#define PAS_SUMMARY_MAGIC "PAS-SUMMARY"
#define PAS_SUMMARY_MAGIC_LEN 11
#define PAS_SUMMARY_FILE_VERSION_1_0 1000
+#define PAS_SUMMARY_FILE_VERSION_2_0 2000
-#define PAS_SUMMARY_FILE_VERSION PAS_SUMMARY_FILE_VERSION_1_0
+#define PAS_SUMMARY_FILE_VERSION PAS_SUMMARY_FILE_VERSION_2_0
static void
free_summary_item (PASBackendSummaryItem *item)
@@ -106,17 +111,17 @@ clear_items (PASBackendSummary *summary)
int i;
for (i = 0; i < summary->priv->items->len; i++) {
PASBackendSummaryItem *item = g_ptr_array_index (summary->priv->items, i);
+ g_hash_table_remove (summary->priv->id_to_item, item->id);
free_summary_item (item);
}
}
PASBackendSummary*
-pas_backend_summary_new (const char *db_path, int flush_timeout_millis)
+pas_backend_summary_new (const char *summary_path, int flush_timeout_millis)
{
PASBackendSummary *summary = gtk_type_new (PAS_BACKEND_SUMMARY_TYPE);
- summary->priv->db_path = g_strdup (db_path);
- summary->priv->summary_path = g_strconcat (db_path, ".summary", NULL);
+ summary->priv->summary_path = g_strdup (summary_path);
summary->priv->flush_timeout_millis = flush_timeout_millis;
summary->priv->file_version = PAS_SUMMARY_FILE_VERSION_1_0;
@@ -136,11 +141,15 @@ pas_backend_summary_destroy (GtkObject *object)
summary->priv->flush_timeout = 0;
}
- g_free (summary->priv->db_path);
+ if (summary->priv->fp)
+ fclose (summary->priv->fp);
+
g_free (summary->priv->summary_path);
clear_items (summary);
g_ptr_array_free (summary->priv->items, TRUE);
+ g_hash_table_destroy (summary->priv->id_to_item);
+
g_free (summary->priv);
GTK_OBJECT_CLASS (parent_class)->destroy (object);
@@ -167,10 +176,11 @@ pas_backend_summary_init (PASBackendSummary *summary)
summary->priv = priv;
- priv->db_path = NULL;
priv->summary_path = NULL;
+ priv->fp = NULL;
priv->dirty = FALSE;
priv->items = g_ptr_array_new();
+ priv->id_to_item = g_hash_table_new (g_str_hash, g_str_equal);
priv->flush_timeout_millis = 0;
priv->flush_timeout = 0;
#ifdef SUMMARY_STATS
@@ -233,10 +243,33 @@ pas_backend_summary_load_header (PASBackendSummary *summary, FILE *fp,
return FALSE;
header->file_version = ntohl (header->file_version);
- if (header->file_version != PAS_SUMMARY_FILE_VERSION) {
- /* XXX upgrade stuff in here, but since there's only 1
- version now return FALSE */
- return FALSE;
+
+ if (header->file_version == PAS_SUMMARY_FILE_VERSION) {
+ rv = fread (&header->summary_mtime, sizeof (header->summary_mtime), 1, fp);
+ if (rv != 1)
+ return FALSE;
+ header->summary_mtime = ntohl (header->summary_mtime);
+ }
+ else {
+ if (header->file_version == PAS_SUMMARY_FILE_VERSION_1_0) {
+ /* the header lacks the mtime of the file.
+ set it to the mtime of the on-disk file,
+ and we'll save it out properly next time */
+ int fd;
+ struct stat sb;
+
+ fd = fileno (fp);
+ if (fstat (fd, &sb) == -1) {
+ g_warning ("error fstat'ing summary file.");
+ /* just set the mtime to zero and hope for the best */
+ header->summary_mtime = 0;
+ }
+ header->summary_mtime = sb.st_mtime;
+ }
+ else {
+ /* unknown version */
+ return FALSE;
+ }
}
rv = fread (&header->num_items, sizeof (header->num_items), 1, fp);
@@ -266,14 +299,15 @@ read_string (FILE *fp, int len)
}
static gboolean
-pas_backend_summary_load_item (PASBackendSummary *summary, FILE *fp,
+pas_backend_summary_load_item (PASBackendSummary *summary,
PASBackendSummaryItem **new_item)
{
PASBackendSummaryItem *item;
char *buf;
+ FILE *fp = summary->priv->fp;
- if (summary->priv->file_version == PAS_SUMMARY_FILE_VERSION_1_0) {
- PASBackendSummaryDiskItem_1_0 disk_item;
+ if (summary->priv->file_version <= PAS_SUMMARY_FILE_VERSION_2_0) {
+ PASBackendSummaryDiskItem disk_item;
int rv = fread (&disk_item, sizeof (disk_item), 1, fp);
if (rv != 1)
return FALSE;
@@ -376,22 +410,13 @@ pas_backend_summary_load_item (PASBackendSummary *summary, FILE *fp,
return TRUE;
}
-gboolean
-pas_backend_summary_load (PASBackendSummary *summary)
+/* opens the file and loads the header */
+static void
+pas_backend_summary_open (PASBackendSummary *summary)
{
+ FILE *fp;
+ PASBackendSummaryHeader header;
struct stat sb;
- time_t db_mtime, summary_mtime;
-
- /* we don't have a way to determine what was added since we
- last updated the summary (without traversing the entire db
- anyway), so if the db is newer we just lose the on-disk
- summary */
-
- if (stat (summary->priv->db_path, &sb) == -1) {
- g_warning ("no db present for summary load");
- return FALSE;
- }
- db_mtime = sb.st_mtime;
if (stat (summary->priv->summary_path, &sb) == -1) {
/* if there's no summary present, look for the .new
@@ -401,61 +426,63 @@ pas_backend_summary_load (PASBackendSummary *summary)
if (stat (new_filename, &sb) == -1) {
g_warning ("no summary present");
g_free (new_filename);
- return FALSE;
+ return;
}
else {
rename (new_filename, summary->priv->summary_path);
- stat (summary->priv->summary_path, &sb);
g_free (new_filename);
}
-
}
- summary_mtime = sb.st_mtime;
- if (summary_mtime < db_mtime) {
- /* we need to regenerate the summary */
- return FALSE;
+ fp = fopen (summary->priv->summary_path, "r");
+ if (!fp) {
+ g_warning ("failed to open summary file");
+ return;
}
- else {
- /* the mtime is ok, load the summary */
- PASBackendSummaryHeader header;
- PASBackendSummaryItem *new_item;
- FILE *fp = fopen (summary->priv->summary_path, "r");
- int i;
- if (!fp) {
- g_warning ("failed to open summary file");
- return FALSE;
- }
+ if (!pas_backend_summary_check_magic (summary, fp)) {
+ g_warning ("file is not a valid summary file");
+ fclose (fp);
+ return;
+ }
- if (!pas_backend_summary_check_magic (summary, fp)) {
- g_warning ("file is not a valid summary file");
- fclose (fp);
- return FALSE;
- }
+ if (!pas_backend_summary_load_header (summary, fp, &header)) {
+ g_warning ("failed to read summary header");
+ fclose (fp);
+ return;
+ }
- if (!pas_backend_summary_load_header (summary, fp, &header)) {
- g_warning ("failed to read summary header");
- fclose (fp);
- return FALSE;
- }
+ summary->priv->num_items = header.num_items;
+ summary->priv->file_version = header.file_version;
+ summary->priv->mtime = header.summary_mtime;
+ summary->priv->fp = fp;
+}
- summary->priv->file_version = header.file_version;
+gboolean
+pas_backend_summary_load (PASBackendSummary *summary)
+{
+ PASBackendSummaryItem *new_item;
+ int i;
+
+ pas_backend_summary_open (summary);
- for (i = 0; i < header.num_items; i ++) {
- if (!pas_backend_summary_load_item (summary, fp, &new_item)) {
- g_warning ("error while reading summary item");
- clear_items (summary);
- fclose (fp);
- return FALSE;
- }
+ if (!summary->priv->fp)
+ return FALSE;
- g_ptr_array_add (summary->priv->items, new_item);
+ for (i = 0; i < summary->priv->num_items; i ++) {
+ if (!pas_backend_summary_load_item (summary, &new_item)) {
+ g_warning ("error while reading summary item");
+ clear_items (summary);
+ fclose (summary->priv->fp);
+ summary->priv->fp = NULL;
+ return FALSE;
}
- /* XXX for now return FALSE so we'll regenerate the summary */
- return TRUE;
+ g_ptr_array_add (summary->priv->items, new_item);
+ g_hash_table_insert (summary->priv->id_to_item, new_item->id, new_item);
}
+
+ return TRUE;
}
static gboolean
@@ -475,8 +502,9 @@ pas_backend_summary_save_header (PASBackendSummary *summary, FILE *fp)
PASBackendSummaryHeader header;
int rv;
- header.file_version = htonl (summary->priv->file_version);
+ header.file_version = htonl (PAS_SUMMARY_FILE_VERSION);
header.num_items = htonl (summary->priv->items->len);
+ header.summary_mtime = htonl (time (NULL));
rv = fwrite (&header, sizeof (header), 1, fp);
if (rv != 1)
@@ -500,7 +528,7 @@ save_string (const char *str, FILE *fp)
static gboolean
pas_backend_summary_save_item (PASBackendSummary *summary, FILE *fp, PASBackendSummaryItem *item)
{
- PASBackendSummaryDiskItem_1_0 disk_item;
+ PASBackendSummaryDiskItem disk_item;
int len;
int rv;
@@ -635,6 +663,7 @@ pas_backend_summary_add_card (PASBackendSummary *summary, const char *vcard)
new_item->email_3 = e_card_simple_get (simple, E_CARD_SIMPLE_FIELD_EMAIL_3);
g_ptr_array_add (summary->priv->items, new_item);
+ g_hash_table_insert (summary->priv->id_to_item, new_item->id, new_item);
gtk_object_unref (GTK_OBJECT (simple));
gtk_object_unref (GTK_OBJECT (card));
@@ -656,16 +685,14 @@ pas_backend_summary_add_card (PASBackendSummary *summary, const char *vcard)
void
pas_backend_summary_remove_card (PASBackendSummary *summary, const char *id)
{
- int i;
+ PASBackendSummaryItem *item = g_hash_table_lookup (summary->priv->id_to_item, id);
- for (i = 0; i < summary->priv->items->len; i ++) {
- PASBackendSummaryItem *item = g_ptr_array_index (summary->priv->items, i);
- if (!strcmp (item->id, id)) {
- g_ptr_array_remove_index (summary->priv->items, i);
- free_summary_item (item);
- pas_backend_summary_touch (summary);
- return;
- }
+ if (item) {
+ g_ptr_array_remove (summary->priv->items, item);
+ g_hash_table_remove (summary->priv->id_to_item, id);
+ free_summary_item (item);
+ pas_backend_summary_touch (summary);
+ return;
}
g_warning ("pas_backend_summary_remove_card: unable to locate id `%s'", id);
@@ -702,6 +729,12 @@ pas_backend_summary_touch (PASBackendSummary *summary)
summary_flush_func, summary);
}
+gboolean
+pas_backend_summary_is_up_to_date (PASBackendSummary *summary, time_t t)
+{
+ return summary->priv->mtime >= t;
+}
+
/* we only want to do summary queries if the query is over the set fields in the summary */
@@ -955,3 +988,37 @@ pas_backend_summary_search (PASBackendSummary *summary, const char *query)
return retval;
}
+
+char*
+pas_backend_summary_get_summary_vcard(PASBackendSummary *summary, const char *id)
+{
+ PASBackendSummaryItem *item = g_hash_table_lookup (summary->priv->id_to_item, id);
+
+ if (item) {
+ ECard *card = e_card_new ("");
+ ECardSimple *simple = e_card_simple_new (card);
+ char *vcard;
+
+ e_card_simple_set_id (simple, item->id);
+ e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_FILE_AS, item->file_as);
+ e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_GIVEN_NAME, item->given_name);
+ e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_FAMILY_NAME, item->surname);
+ e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_NICKNAME, item->nickname);
+ e_card_simple_set_email (simple, E_CARD_SIMPLE_EMAIL_ID_EMAIL, item->email_1);
+ e_card_simple_set_email (simple, E_CARD_SIMPLE_EMAIL_ID_EMAIL_2, item->email_2);
+ e_card_simple_set_email (simple, E_CARD_SIMPLE_EMAIL_ID_EMAIL_3, item->email_3);
+
+ e_card_simple_sync_card (simple);
+
+ vcard = e_card_simple_get_vcard (simple);
+
+ gtk_object_unref (GTK_OBJECT (simple));
+ gtk_object_unref (GTK_OBJECT (card));
+
+ return vcard;
+ }
+ else {
+ g_warning ("in unable to locate card `%s' in summary", id);
+ }
+}
+