From: Milan Crha Date: Thu, 6 Oct 2011 14:57:51 +0000 (+0200) Subject: CamelFolderSummary API changes X-Git-Tag: upstream/3.7.4~1527 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=508ea7c93045d61d3f72807c253c820c9e42b262;p=platform%2Fupstream%2Fevolution-data-server.git CamelFolderSummary API changes --- diff --git a/camel/camel-db.c b/camel/camel-db.c index bef5e24..5d8d67f 100644 --- a/camel/camel-db.c +++ b/camel/camel-db.c @@ -1070,33 +1070,42 @@ camel_db_delete_uid_from_vfolder_transaction (CamelDB *db, } static gint -read_uids_callback (gpointer ref, +read_uids_callback (gpointer ref_array, gint ncol, gchar **cols, gchar **name) { - GPtrArray *array = (GPtrArray *) ref; + GPtrArray *array = ref_array; - #if 0 - gint i; - for (i = 0; i < ncol; ++i) { - if (!name[i] || !cols[i]) - continue; + g_return_val_if_fail (ncol == 1, 0); - if (!strcmp (name [i], "uid")) - g_ptr_array_add (array, (gchar *) (camel_pstring_strdup (cols[i]))); - } - #else - if (cols[0]) - g_ptr_array_add (array, (gchar *) (camel_pstring_strdup (cols[0]))); - #endif + if (cols[0]) + g_ptr_array_add (array, (gchar *) (camel_pstring_strdup (cols[0]))); - return 0; + return 0; +} + +static gint +read_uids_to_hash_callback (gpointer ref_hash, + gint ncol, + gchar **cols, + gchar **name) +{ + GHashTable *hash = ref_hash; + + g_return_val_if_fail (ncol == 2, 0); + + if (cols[0]) + g_hash_table_insert (hash, (gchar *) camel_pstring_strdup (cols[0]), GUINT_TO_POINTER (cols[1] ? strtoul (cols[1], NULL, 10) : 0)); + + return 0; } /** * camel_db_get_folder_uids: * + * Fills hash with uid->GUINT_TO_POINTER (flag) + * * Since: 2.24 **/ gint @@ -1104,15 +1113,15 @@ camel_db_get_folder_uids (CamelDB *db, const gchar *folder_name, const gchar *sort_by, const gchar *collate, - GPtrArray *array, + GHashTable *hash, GError **error) { gchar *sel_query; gint ret; - sel_query = sqlite3_mprintf("SELECT uid FROM %Q%s%s%s%s", folder_name, sort_by ? " order by " : "", sort_by ? sort_by: "", (sort_by && collate) ? " collate " : "", (sort_by && collate) ? collate : ""); + sel_query = sqlite3_mprintf("SELECT uid,flags FROM %Q%s%s%s%s", folder_name, sort_by ? " order by " : "", sort_by ? sort_by: "", (sort_by && collate) ? " collate " : "", (sort_by && collate) ? collate : ""); - ret = camel_db_select (db, sel_query, read_uids_callback, array, error); + ret = camel_db_select (db, sel_query, read_uids_to_hash_callback, hash, error); sqlite3_free (sel_query); return ret; @@ -1172,13 +1181,19 @@ camel_db_get_folder_deleted_uids (CamelDB *db, return array; } +struct ReadPreviewData +{ + GHashTable *columns_hash; + GHashTable *hash; +}; + static gint read_preview_callback (gpointer ref, gint ncol, gchar **cols, gchar **name) { - GHashTable *hash = (GHashTable *) ref; + struct ReadPreviewData *rpd = ref; const gchar *uid = NULL; gchar *msg = NULL; gint i; @@ -1187,13 +1202,20 @@ read_preview_callback (gpointer ref, if (!name[i] || !cols[i]) continue; - if (!strcmp (name [i], "uid")) - uid = camel_pstring_strdup (cols[i]); - else if (!strcmp (name [i], "preview")) - msg = g_strdup (cols[i]); + switch (camel_db_get_column_ident (&rpd->columns_hash, i, ncol, name)) { + case CAMEL_DB_COLUMN_UID: + uid = camel_pstring_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_PREVIEW: + msg = g_strdup (cols[i]); + break; + default: + g_warn_if_reached (); + break; + } } - g_hash_table_insert (hash, (gchar *) uid, msg); + g_hash_table_insert (rpd->hash, (gchar *) uid, msg); return 0; } @@ -1208,21 +1230,28 @@ camel_db_get_folder_preview (CamelDB *db, const gchar *folder_name, GError **error) { - gchar *sel_query; - gint ret; - GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal); + gchar *sel_query; + gint ret; + struct ReadPreviewData rpd; + GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal); - sel_query = sqlite3_mprintf("SELECT uid, preview FROM '%q_preview'", folder_name); + sel_query = sqlite3_mprintf ("SELECT uid, preview FROM '%q_preview'", folder_name); - ret = camel_db_select (db, sel_query, read_preview_callback, hash, error); - sqlite3_free (sel_query); + rpd.columns_hash = NULL; + rpd.hash = hash; - if (!g_hash_table_size (hash) || ret != 0) { - g_hash_table_destroy (hash); - hash = NULL; - } + ret = camel_db_select (db, sel_query, read_preview_callback, &rpd, error); + sqlite3_free (sel_query); + + if (rpd.columns_hash) + g_hash_table_destroy (rpd.columns_hash); - return hash; + if (!g_hash_table_size (hash) || ret != 0) { + g_hash_table_destroy (hash); + hash = NULL; + } + + return hash; } /** @@ -1256,20 +1285,8 @@ read_vuids_callback (gpointer ref, { GPtrArray *array = (GPtrArray *) ref; - #if 0 - gint i; - - for (i = 0; i < ncol; ++i) { - if (!name[i] || !cols[i] || strlen (cols[i]) <= 8) - continue; - - if (!strcmp (name [i], "vuid")) - g_ptr_array_add (array, (gchar *) (camel_pstring_strdup (cols[i]+8))); - } - #else - if (cols[0] && strlen (cols[0]) > 8) - g_ptr_array_add (array, (gchar *) (camel_pstring_strdup (cols[0]+8))); - #endif + if (cols[0] && strlen (cols[0]) > 8) + g_ptr_array_add (array, (gchar *) (camel_pstring_strdup (cols[0]+8))); return 0; } @@ -1768,13 +1785,19 @@ camel_db_write_folder_info_record (CamelDB *cdb, return ret; } +struct ReadFirData +{ + GHashTable *columns_hash; + CamelFIRecord *record; +}; + static gint read_fir_callback (gpointer ref, gint ncol, gchar **cols, gchar **name) { - CamelFIRecord *record = *(CamelFIRecord **) ref; + struct ReadFirData *rfd = ref; gint i; d(g_print ("\nread_fir_callback called \n")); @@ -1783,39 +1806,47 @@ read_fir_callback (gpointer ref, if (!name[i] || !cols[i]) continue; - if (!strcmp (name [i], "folder_name")) - record->folder_name = g_strdup (cols[i]); - - else if (!strcmp (name [i], "version")) - record->version = cols[i] ? strtoul (cols[i], NULL, 10) : 0; - - else if (!strcmp (name [i], "flags")) - record->flags = cols[i] ? strtoul (cols[i], NULL, 10) : 0; - - else if (!strcmp (name [i], "nextuid")) - record->nextuid = cols[i] ? strtoul (cols[i], NULL, 10) : 0; - - else if (!strcmp (name [i], "time")) - record->time = cols[i] ? strtoul (cols[i], NULL, 10) : 0; - - else if (!strcmp (name [i], "saved_count")) - record->saved_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0; - - else if (!strcmp (name [i], "unread_count")) - record->unread_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0; - - else if (!strcmp (name [i], "deleted_count")) - record->deleted_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0; - - else if (!strcmp (name [i], "junk_count")) - record->junk_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0; - else if (!strcmp (name [i], "visible_count")) - record->visible_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0; - else if (!strcmp (name [i], "jnd_count")) - record->jnd_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0; - else if (!strcmp (name [i], "bdata")) - record->bdata = g_strdup (cols[i]); - + switch (camel_db_get_column_ident (&rfd->columns_hash, i, ncol, name)) { + case CAMEL_DB_COLUMN_FOLDER_NAME: + rfd->record->folder_name = g_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_VERSION: + rfd->record->version = cols[i] ? strtoul (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_FLAGS: + rfd->record->flags = cols[i] ? strtoul (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_NEXTUID: + rfd->record->nextuid = cols[i] ? strtoul (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_TIME: + rfd->record->time = cols[i] ? strtoul (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_SAVED_COUNT: + rfd->record->saved_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_UNREAD_COUNT: + rfd->record->unread_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_DELETED_COUNT: + rfd->record->deleted_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_JUNK_COUNT: + rfd->record->junk_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_VISIBLE_COUNT: + rfd->record->visible_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_JND_COUNT: + rfd->record->jnd_count = cols[i] ? strtoul (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_BDATA: + rfd->record->bdata = g_strdup (cols[i]); + break; + default: + g_warn_if_reached (); + break; + } } return 0; @@ -1829,17 +1860,24 @@ read_fir_callback (gpointer ref, gint camel_db_read_folder_info_record (CamelDB *cdb, const gchar *folder_name, - CamelFIRecord **record, + CamelFIRecord *record, GError **error) { + struct ReadFirData rfd; gchar *query; gint ret; - query = sqlite3_mprintf ("SELECT * FROM folders WHERE folder_name = %Q", folder_name); - ret = camel_db_select (cdb, query, read_fir_callback, record, error); + rfd.columns_hash = NULL; + rfd.record = record; + query = sqlite3_mprintf ("SELECT * FROM folders WHERE folder_name = %Q", folder_name); + ret = camel_db_select (cdb, query, read_fir_callback, &rfd, error); sqlite3_free (query); - return (ret); + + if (rfd.columns_hash) + g_hash_table_destroy (rfd.columns_hash); + + return ret; } /** @@ -2370,3 +2408,94 @@ camel_db_flush_in_memory_transactions (CamelDB *cdb, return ret; } + +static struct _known_column_names { + const gchar *name; + CamelDBKnownColumnNames ident; +} known_column_names[] = { + { "attachment", CAMEL_DB_COLUMN_ATTACHMENT }, + { "bdata", CAMEL_DB_COLUMN_BDATA }, + { "bodystructure", CAMEL_DB_COLUMN_BODYSTRUCTURE }, + { "cinfo", CAMEL_DB_COLUMN_CINFO }, + { "deleted", CAMEL_DB_COLUMN_DELETED }, + { "deleted_count", CAMEL_DB_COLUMN_DELETED_COUNT }, + { "dreceived", CAMEL_DB_COLUMN_DRECEIVED }, + { "dsent", CAMEL_DB_COLUMN_DSENT }, + { "flags", CAMEL_DB_COLUMN_FLAGS }, + { "folder_name", CAMEL_DB_COLUMN_FOLDER_NAME }, + { "followup_completed_on", CAMEL_DB_COLUMN_FOLLOWUP_COMPLETED_ON }, + { "followup_due_by", CAMEL_DB_COLUMN_FOLLOWUP_DUE_BY }, + { "followup_flag", CAMEL_DB_COLUMN_FOLLOWUP_FLAG }, + { "important", CAMEL_DB_COLUMN_IMPORTANT }, + { "jnd_count", CAMEL_DB_COLUMN_JND_COUNT }, + { "junk", CAMEL_DB_COLUMN_JUNK }, + { "junk_count", CAMEL_DB_COLUMN_JUNK_COUNT }, + { "labels", CAMEL_DB_COLUMN_LABELS }, + { "mail_cc", CAMEL_DB_COLUMN_MAIL_CC }, + { "mail_from", CAMEL_DB_COLUMN_MAIL_FROM }, + { "mail_to", CAMEL_DB_COLUMN_MAIL_TO }, + { "mlist", CAMEL_DB_COLUMN_MLIST }, + { "nextuid", CAMEL_DB_COLUMN_NEXTUID }, + { "part", CAMEL_DB_COLUMN_PART }, + { "preview", CAMEL_DB_COLUMN_PREVIEW }, + { "read", CAMEL_DB_COLUMN_READ }, + { "replied", CAMEL_DB_COLUMN_REPLIED }, + { "saved_count", CAMEL_DB_COLUMN_SAVED_COUNT }, + { "size", CAMEL_DB_COLUMN_SIZE }, + { "subject", CAMEL_DB_COLUMN_SUBJECT }, + { "time", CAMEL_DB_COLUMN_TIME }, + { "uid", CAMEL_DB_COLUMN_UID }, + { "unread_count", CAMEL_DB_COLUMN_UNREAD_COUNT }, + { "usertags", CAMEL_DB_COLUMN_USERTAGS }, + { "version", CAMEL_DB_COLUMN_VERSION }, + { "visible_count", CAMEL_DB_COLUMN_VISIBLE_COUNT }, + { "vuid", CAMEL_DB_COLUMN_VUID } +}; + +/** + * camel_db_get_column_ident: + * Traverses column name from index @index into an enum #CamelDBKnownColumnNames value; + * The @col_names contains @ncols columns. First time this is called is created + * the @hash from col_names indexes into the enum, and this is reused for every other call. + * The function expects that column names are returned always in the same order. + * When all rows are read the @hash table can be freed with g_hash_table_destroy(). + **/ +CamelDBKnownColumnNames +camel_db_get_column_ident (GHashTable **hash, gint index, gint ncols, gchar **col_names) +{ + gpointer value = NULL; + + g_return_val_if_fail (hash != NULL, CAMEL_DB_COLUMN_UNKNOWN); + g_return_val_if_fail (col_names != NULL, CAMEL_DB_COLUMN_UNKNOWN); + g_return_val_if_fail (ncols > 0, CAMEL_DB_COLUMN_UNKNOWN); + g_return_val_if_fail (index >= 0, CAMEL_DB_COLUMN_UNKNOWN); + g_return_val_if_fail (index < ncols, CAMEL_DB_COLUMN_UNKNOWN); + + if (!*hash) { + gint ii, jj, from, max = G_N_ELEMENTS (known_column_names); + + *hash = g_hash_table_new (g_direct_hash, g_direct_equal); + + for (ii = 0, jj = 0; ii < ncols; ii++) { + const gchar *name = col_names[ii]; + gboolean first = TRUE; + + if (!name) + continue; + + for (from = jj; first || jj != from; jj = (jj + 1) % max, first = FALSE) { + if (g_str_equal (name, known_column_names[jj].name)) { + g_hash_table_insert (*hash, GINT_TO_POINTER (ii), GINT_TO_POINTER (known_column_names[jj].ident)); + break; + } + } + + if (from == jj && !first) + g_warning ("%s: missing column name '%s' in a list of known columns", G_STRFUNC, name); + } + } + + g_return_val_if_fail (g_hash_table_lookup_extended (*hash, GINT_TO_POINTER (index), NULL, &value), CAMEL_DB_COLUMN_UNKNOWN); + + return GPOINTER_TO_INT (value); +} diff --git a/camel/camel-db.h b/camel/camel-db.h index ad89225..b4c1721 100644 --- a/camel/camel-db.h +++ b/camel/camel-db.h @@ -200,6 +200,49 @@ typedef struct _CamelFIRecord { typedef struct _CamelDB CamelDB; +typedef enum { + CAMEL_DB_COLUMN_UNKNOWN = -1, + CAMEL_DB_COLUMN_ATTACHMENT, + CAMEL_DB_COLUMN_BDATA, + CAMEL_DB_COLUMN_BODYSTRUCTURE, + CAMEL_DB_COLUMN_CINFO, + CAMEL_DB_COLUMN_DELETED, + CAMEL_DB_COLUMN_DELETED_COUNT, + CAMEL_DB_COLUMN_DRECEIVED, + CAMEL_DB_COLUMN_DSENT, + CAMEL_DB_COLUMN_FLAGS, + CAMEL_DB_COLUMN_FOLDER_NAME, + CAMEL_DB_COLUMN_FOLLOWUP_COMPLETED_ON, + CAMEL_DB_COLUMN_FOLLOWUP_DUE_BY, + CAMEL_DB_COLUMN_FOLLOWUP_FLAG, + CAMEL_DB_COLUMN_IMPORTANT, + CAMEL_DB_COLUMN_JND_COUNT, + CAMEL_DB_COLUMN_JUNK, + CAMEL_DB_COLUMN_JUNK_COUNT, + CAMEL_DB_COLUMN_LABELS, + CAMEL_DB_COLUMN_MAIL_CC, + CAMEL_DB_COLUMN_MAIL_FROM, + CAMEL_DB_COLUMN_MAIL_TO, + CAMEL_DB_COLUMN_MLIST, + CAMEL_DB_COLUMN_NEXTUID, + CAMEL_DB_COLUMN_PART, + CAMEL_DB_COLUMN_PREVIEW, + CAMEL_DB_COLUMN_READ, + CAMEL_DB_COLUMN_REPLIED, + CAMEL_DB_COLUMN_SAVED_COUNT, + CAMEL_DB_COLUMN_SIZE, + CAMEL_DB_COLUMN_SUBJECT, + CAMEL_DB_COLUMN_TIME, + CAMEL_DB_COLUMN_UID, + CAMEL_DB_COLUMN_UNREAD_COUNT, + CAMEL_DB_COLUMN_USERTAGS, + CAMEL_DB_COLUMN_VERSION, + CAMEL_DB_COLUMN_VISIBLE_COUNT, + CAMEL_DB_COLUMN_VUID +} CamelDBKnownColumnNames; + +CamelDBKnownColumnNames camel_db_get_column_ident (GHashTable **hash, gint index, gint ncols, gchar **col_names); + /** * CamelDBSelectCB: * @@ -231,7 +274,7 @@ gint camel_db_create_folders_table (CamelDB *cdb, GError **error); gint camel_db_select (CamelDB *cdb, const gchar * stmt, CamelDBSelectCB callback, gpointer data, GError **error); gint camel_db_write_folder_info_record (CamelDB *cdb, CamelFIRecord *record, GError **error); -gint camel_db_read_folder_info_record (CamelDB *cdb, const gchar *folder_name, CamelFIRecord **record, GError **error); +gint camel_db_read_folder_info_record (CamelDB *cdb, const gchar *folder_name, CamelFIRecord *record, GError **error); gint camel_db_prepare_message_info_table (CamelDB *cdb, const gchar *folder_name, GError **error); @@ -260,7 +303,7 @@ GPtrArray * camel_db_get_vuids_from_vfolder (CamelDB *db, const gchar *folder_na gint camel_db_add_to_vfolder (CamelDB *db, gchar *folder_name, gchar *vuid, GError **error); gint camel_db_add_to_vfolder_transaction (CamelDB *db, const gchar *folder_name, const gchar *vuid, GError **error); -gint camel_db_get_folder_uids (CamelDB *db, const gchar *folder_name, const gchar *sort_by, const gchar *collate, GPtrArray *array, GError **error); +gint camel_db_get_folder_uids (CamelDB *db, const gchar *folder_name, const gchar *sort_by, const gchar *collate, GHashTable *hash, GError **error); GPtrArray * camel_db_get_folder_junk_uids (CamelDB *db, gchar *folder_name, GError **error); GPtrArray * camel_db_get_folder_deleted_uids (CamelDB *db, const gchar *folder_name, GError **error); @@ -282,5 +325,5 @@ gint camel_db_write_preview_record (CamelDB *db, const gchar *folder_name, const gint camel_db_reset_folder_version (CamelDB *cdb, const gchar *folder_name, gint reset_version, GError **error); -#endif +#endif diff --git a/camel/camel-disco-folder.c b/camel/camel-disco-folder.c index 81e54a8..56440b2 100644 --- a/camel/camel-disco-folder.c +++ b/camel/camel-disco-folder.c @@ -262,25 +262,27 @@ disco_expunge_sync (CamelFolder *folder, { GPtrArray *uids; gint i; - guint count; CamelMessageInfo *info; gboolean success; + GPtrArray *known_uids; uids = g_ptr_array_new (); camel_folder_summary_prepare_fetch_all (folder->summary, NULL); - count = camel_folder_summary_count (folder->summary); - for (i = 0; i < count; i++) { - info = camel_folder_summary_index (folder->summary, i); + known_uids = camel_folder_summary_get_array (folder->summary); + for (i = 0; known_uids && i < known_uids->len; i++) { + const gchar *uid = g_ptr_array_index (known_uids, i); + + info = camel_folder_summary_get (folder->summary, uid); if (camel_message_info_flags (info) & CAMEL_MESSAGE_DELETED) - g_ptr_array_add (uids, g_strdup (camel_message_info_uid (info))); + g_ptr_array_add (uids, (gpointer) uid); camel_message_info_free (info); } success = disco_expunge_uids (folder, uids, cancellable, error); - for (i = 0; i < uids->len; i++) - g_free (uids->pdata[i]); g_ptr_array_free (uids, TRUE); + if (known_uids) + camel_folder_summary_free_array (known_uids); return success; } diff --git a/camel/camel-folder-search.c b/camel/camel-folder-search.c index 5d71725..364c539 100644 --- a/camel/camel-folder-search.c +++ b/camel/camel-folder-search.c @@ -883,7 +883,7 @@ search_match_all (struct _ESExp *f, for (i = 0; i < v->len; i++) { const gchar *uid; - search->current = camel_folder_summary_uid (search->folder->summary, v->pdata[i]); + search->current = camel_folder_summary_get (search->folder->summary, v->pdata[i]); if (!search->current) continue; uid = camel_message_info_uid (search->current); diff --git a/camel/camel-folder-summary.c b/camel/camel-folder-summary.c index d0cf62f..354b255 100644 --- a/camel/camel-folder-summary.c +++ b/camel/camel-folder-summary.c @@ -84,6 +84,24 @@ struct _CamelFolderSummaryPrivate { gboolean need_preview; GHashTable *preview_updates; + + guint32 nextuid; /* next uid? */ + guint32 saved_count; /* how many were saved/loaded */ + guint32 unread_count; /* handy totals */ + guint32 deleted_count; + guint32 junk_count; + guint32 junk_not_deleted_count; + guint32 visible_count; + + gchar *summary_path; + gboolean build_content; /* do we try and parse/index the content, or not? */ + + GHashTable *uids; /* uids of all known message infos; the 'value' are used flags for the message info */ + GHashTable *loaded_infos; /* uid->CamelMessageInfo*, those currently in memory */ + + struct _CamelFolder *folder; /* parent folder, for events */ + time_t cache_load_time; + guint timeout_handle; }; static GStaticMutex info_lock = G_STATIC_MUTEX_INIT; @@ -101,8 +119,6 @@ static GStaticMutex info_lock = G_STATIC_MUTEX_INIT; #define CAMEL_FOLDER_SUMMARY_VERSION (14) -#define META_SUMMARY_SUFFIX_LEN 5 /* strlen("-meta") */ - /* trivial lists, just because ... */ struct _node { struct _node *next; @@ -138,6 +154,19 @@ static CamelMessageContentInfo * summary_build_content_info_message (CamelFolder static CamelMessageInfo * message_info_from_uid (CamelFolderSummary *s, const gchar *uid); +enum { + PROP_0, + PROP_FOLDER, + PROP_SAVED_COUNT, + PROP_UNREAD_COUNT, + PROP_DELETED_COUNT, + PROP_JUNK_COUNT, + PROP_JUNK_NOT_DELETED_COUNT, + PROP_VISIBLE_COUNT, + PROP_BUILD_CONTENT, + PROP_NEED_PREVIEW +}; + G_DEFINE_TYPE (CamelFolderSummary, camel_folder_summary, CAMEL_TYPE_OBJECT) static void @@ -204,36 +233,216 @@ static void folder_summary_finalize (GObject *object) { CamelFolderSummary *summary = CAMEL_FOLDER_SUMMARY (object); + CamelFolderSummaryPrivate *priv = summary->priv; - if (summary->timeout_handle) - g_source_remove (summary->timeout_handle); - /*camel_folder_summary_clear(s);*/ - g_ptr_array_foreach (summary->uids, (GFunc) camel_pstring_free, NULL); - g_ptr_array_free (summary->uids, TRUE); - g_hash_table_destroy (summary->loaded_infos); + if (priv->timeout_handle) + g_source_remove (priv->timeout_handle); - g_hash_table_foreach (summary->priv->filter_charset, free_o_name, NULL); - g_hash_table_destroy (summary->priv->filter_charset); + g_hash_table_destroy (priv->uids); + g_hash_table_destroy (priv->loaded_infos); - g_hash_table_destroy (summary->priv->preview_updates); + g_hash_table_foreach (priv->filter_charset, free_o_name, NULL); + g_hash_table_destroy (priv->filter_charset); - g_free (summary->summary_path); + g_hash_table_destroy (priv->preview_updates); - /* Freeing memory occupied by meta-summary-header */ - g_free (summary->meta_summary->path); - g_free (summary->meta_summary); + g_free (priv->summary_path); - g_static_rec_mutex_free (&summary->priv->summary_lock); - g_static_rec_mutex_free (&summary->priv->io_lock); - g_static_rec_mutex_free (&summary->priv->filter_lock); - g_static_rec_mutex_free (&summary->priv->alloc_lock); - g_static_rec_mutex_free (&summary->priv->ref_lock); + g_static_rec_mutex_free (&priv->summary_lock); + g_static_rec_mutex_free (&priv->io_lock); + g_static_rec_mutex_free (&priv->filter_lock); + g_static_rec_mutex_free (&priv->alloc_lock); + g_static_rec_mutex_free (&priv->ref_lock); /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (camel_folder_summary_parent_class)->finalize (object); } -static gint +static void +folder_summary_set_folder (CamelFolderSummary *summary, CamelFolder *folder) +{ + g_return_if_fail (summary != NULL); + g_return_if_fail (summary->priv != NULL); + g_return_if_fail (summary->priv->folder == NULL); + /* folder can be NULL in certain cases, see maildir-store */ + + summary->priv->folder = folder; +} + +static void +folder_summary_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FOLDER: + folder_summary_set_folder ( + CAMEL_FOLDER_SUMMARY (object), + CAMEL_FOLDER (g_value_get_object (value))); + return; + + case PROP_BUILD_CONTENT: + camel_folder_summary_set_build_content ( + CAMEL_FOLDER_SUMMARY (object), + g_value_get_boolean (value)); + return; + + case PROP_NEED_PREVIEW: + camel_folder_summary_set_need_preview ( + CAMEL_FOLDER_SUMMARY (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +folder_summary_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FOLDER: + g_value_set_object ( + value, camel_folder_summary_get_folder ( + CAMEL_FOLDER_SUMMARY (object))); + return; + + case PROP_SAVED_COUNT: + g_value_set_uint ( + value, camel_folder_summary_get_saved_count ( + CAMEL_FOLDER_SUMMARY (object))); + return; + + case PROP_UNREAD_COUNT: + g_value_set_uint ( + value, camel_folder_summary_get_unread_count ( + CAMEL_FOLDER_SUMMARY (object))); + return; + + case PROP_DELETED_COUNT: + g_value_set_uint ( + value, camel_folder_summary_get_deleted_count ( + CAMEL_FOLDER_SUMMARY (object))); + return; + + case PROP_JUNK_COUNT: + g_value_set_uint ( + value, camel_folder_summary_get_junk_count ( + CAMEL_FOLDER_SUMMARY (object))); + return; + + case PROP_JUNK_NOT_DELETED_COUNT: + g_value_set_uint ( + value, camel_folder_summary_get_junk_not_deleted_count ( + CAMEL_FOLDER_SUMMARY (object))); + return; + + case PROP_VISIBLE_COUNT: + g_value_set_uint ( + value, camel_folder_summary_get_visible_count ( + CAMEL_FOLDER_SUMMARY (object))); + return; + + case PROP_BUILD_CONTENT: + g_value_set_boolean ( + value, camel_folder_summary_get_build_content ( + CAMEL_FOLDER_SUMMARY (object))); + return; + + case PROP_NEED_PREVIEW: + g_value_set_boolean ( + value, camel_folder_summary_get_need_preview ( + CAMEL_FOLDER_SUMMARY (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +/** + * folder_summary_update_counts_by_flags: + * + * Since: 3.0 + **/ +static void +folder_summary_update_counts_by_flags (CamelFolderSummary *summary, + guint32 flags, + gboolean subtract) +{ + gint unread = 0, deleted = 0, junk = 0; + gboolean is_junk_folder = FALSE, is_trash_folder = FALSE; + GObject *summary_object; + + g_return_if_fail (summary != NULL); + g_return_if_fail (summary->priv != NULL); + + summary_object = G_OBJECT (summary); + + if (summary->priv->folder && CAMEL_IS_VTRASH_FOLDER (summary->priv->folder)) { + CamelVTrashFolder *vtrash = CAMEL_VTRASH_FOLDER (summary->priv->folder); + + is_junk_folder = vtrash && vtrash->type == CAMEL_VTRASH_FOLDER_JUNK; + is_trash_folder = vtrash && vtrash->type == CAMEL_VTRASH_FOLDER_TRASH; + } + + if (!(flags & CAMEL_MESSAGE_SEEN)) + unread = subtract ? -1 : 1; + + if (flags & CAMEL_MESSAGE_DELETED) + deleted = subtract ? -1 : 1; + + if (flags & CAMEL_MESSAGE_JUNK) + junk = subtract ? -1 : 1; + + dd(printf("%p: %d %d %d | %d %d %d \n", (gpointer) summary, unread, deleted, junk, summary->priv->unread_count, summary->priv->visible_count, summary->priv->saved_count)); + + g_object_freeze_notify (summary_object); + + if (deleted) { + summary->priv->deleted_count += deleted; + g_object_notify (summary_object, "deleted-count"); + } + + if (junk) { + summary->priv->junk_count += junk; + g_object_notify (summary_object, "junk-count"); + } + + if (junk && !deleted) { + summary->priv->junk_not_deleted_count += junk; + g_object_notify (summary_object, "junk-not-deleted-count"); + } + + if (!junk && !deleted) { + summary->priv->visible_count += subtract ? -1 : 1; + g_object_notify (summary_object, "visible-count"); + } + + if (junk && !is_junk_folder) + unread = 0; + if (deleted && !is_trash_folder) + unread = 0; + + if (unread) { + summary->priv->unread_count += unread; + g_object_notify (summary_object, "unread-count"); + } + + summary->priv->saved_count += subtract ? -1 : 1; + g_object_notify (summary_object, "saved-count"); + + camel_folder_summary_touch (summary); + + g_object_thaw_notify (summary_object); + + dd(printf("%p: %d %d %d | %d %d %d\n", (gpointer) summary, unread, deleted, junk, summary->priv->unread_count, summary->priv->visible_count, summary->priv->saved_count)); +} + +static gboolean summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *record) { @@ -247,7 +456,7 @@ summary_header_from_db (CamelFolderSummary *s, if ((s->version > 0xff) && (s->version & 0xff) < 12) { io(printf ("Summary header version mismatch")); errno = EINVAL; - return -1; + return FALSE; } if (!(s->version < 0x100 && s->version >= 13)) @@ -257,17 +466,17 @@ summary_header_from_db (CamelFolderSummary *s, #endif s->flags = record->flags; - s->nextuid = record->nextuid; + s->priv->nextuid = record->nextuid; s->time = record->time; - s->saved_count = record->saved_count; + s->priv->saved_count = record->saved_count; - s->unread_count = record->unread_count; - s->deleted_count = record->deleted_count; - s->junk_count = record->junk_count; - s->visible_count = record->visible_count; - s->junk_not_deleted_count = record->jnd_count; + s->priv->unread_count = record->unread_count; + s->priv->deleted_count = record->deleted_count; + s->priv->junk_count = record->junk_count; + s->priv->visible_count = record->visible_count; + s->priv->junk_not_deleted_count = record->jnd_count; - return 0; + return TRUE; } static CamelFIRecord * @@ -281,8 +490,8 @@ summary_header_to_db (CamelFolderSummary *s, /* Though we are going to read, we do this during write, * so lets use it that way. */ - table_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); + table_name = camel_folder_get_full_name (s->priv->folder); + parent_store = camel_folder_get_parent_store (s->priv->folder); db = parent_store->cdb_w; io(printf("Savining header to db\n")); @@ -292,7 +501,7 @@ summary_header_to_db (CamelFolderSummary *s, /* we always write out the current version */ record->version = CAMEL_FOLDER_SUMMARY_VERSION; record->flags = s->flags; - record->nextuid = s->nextuid; + record->nextuid = s->priv->nextuid; record->time = s->time; /* FIXME: Ever heard of Constructors and initializing ? */ @@ -309,11 +518,11 @@ summary_header_to_db (CamelFolderSummary *s, if (camel_db_count_junk_not_deleted_message_info (db, table_name, &(record->jnd_count), NULL)) record->jnd_count = 0; - s->unread_count = record->unread_count; - s->deleted_count = record->deleted_count; - s->junk_count = record->junk_count; - s->visible_count = record->visible_count; - s->junk_not_deleted_count = record->jnd_count; + s->priv->unread_count = record->unread_count; + s->priv->deleted_count = record->deleted_count; + s->priv->junk_count = record->junk_count; + s->priv->visible_count = record->visible_count; + s->priv->junk_not_deleted_count = record->jnd_count; return record; } @@ -527,7 +736,7 @@ content_info_from_db (CamelFolderSummary *s, return ci; } -static gint +static gboolean content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *ci, CamelMIRecord *record) @@ -591,14 +800,15 @@ content_info_to_db (CamelFolderSummary *s, g_string_free (str, FALSE); } - return 0; + return TRUE; } static gint summary_header_save (CamelFolderSummary *s, FILE *out) { - gint unread = 0, deleted = 0, junk = 0, count, i; + gint unread = 0, deleted = 0, junk = 0, i; + GPtrArray *known_uids; fseek (out, 0, SEEK_SET); @@ -607,12 +817,12 @@ summary_header_save (CamelFolderSummary *s, /* we always write out the current version */ camel_file_util_encode_fixed_int32 (out, CAMEL_FOLDER_SUMMARY_VERSION); camel_file_util_encode_fixed_int32 (out, s->flags); - camel_file_util_encode_fixed_int32 (out, s->nextuid); + camel_file_util_encode_fixed_int32 (out, s->priv->nextuid); camel_file_util_encode_time_t (out, s->time); - count = camel_folder_summary_count (s); - for (i = 0; i < count; i++) { - CamelMessageInfo *info = camel_folder_summary_index (s, i); + known_uids = camel_folder_summary_get_array (s); + for (i = 0; known_uids && i < known_uids->len; i++) { + CamelMessageInfo *info = camel_folder_summary_get (s, g_ptr_array_index (known_uids, i)); guint32 flags; if (info == NULL) @@ -629,13 +839,70 @@ summary_header_save (CamelFolderSummary *s, camel_message_info_free (info); } - camel_file_util_encode_fixed_int32 (out, count); + camel_folder_summary_free_array (known_uids); + + camel_file_util_encode_fixed_int32 (out, i); /* total count */ camel_file_util_encode_fixed_int32 (out, unread); camel_file_util_encode_fixed_int32 (out, deleted); return camel_file_util_encode_fixed_int32 (out, junk); } +static gboolean +folder_summary_replace_flags (CamelFolderSummary *summary, CamelMessageInfo *info) +{ + guint32 used_flags; + GObject *summary_object; + guint32 old_saved_count, old_unread_count, old_deleted_count, old_junk_count; + guint32 old_junk_not_deleted_count, old_visible_count; + + g_return_val_if_fail (summary != NULL, FALSE); + g_return_val_if_fail (summary->priv != NULL, FALSE); + g_return_val_if_fail (info != NULL, FALSE); + + if (!camel_message_info_uid (info) || + !camel_folder_summary_check_uid (summary, camel_message_info_uid (info))) + return FALSE; + + summary_object = G_OBJECT (summary); + + camel_folder_summary_lock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + g_object_freeze_notify (summary_object); + + used_flags = GPOINTER_TO_UINT (g_hash_table_lookup (summary->priv->uids, camel_message_info_uid (info))); + + old_saved_count = summary->priv->saved_count; + old_unread_count = summary->priv->unread_count; + old_deleted_count = summary->priv->deleted_count; + old_junk_count = summary->priv->junk_count; + old_junk_not_deleted_count = summary->priv->junk_not_deleted_count; + old_visible_count = summary->priv->visible_count; + + /* decrement counts with old flags */ + folder_summary_update_counts_by_flags (summary, used_flags, TRUE); + + /* update current flags on the summary */ + g_hash_table_insert (summary->priv->uids, + (gpointer) camel_pstring_strdup (camel_message_info_uid (info)), + GUINT_TO_POINTER (camel_message_info_flags (info))); + + /* increment counts with new flags */ + folder_summary_update_counts_by_flags (summary, camel_message_info_flags (info), FALSE); + + /* this approach generates false notifications at least for "saved-count", + but is it an issue? I suppose not. + */ + g_object_thaw_notify (summary_object); + camel_folder_summary_unlock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + + return old_saved_count != summary->priv->saved_count || + old_unread_count != summary->priv->unread_count || + old_deleted_count != summary->priv->deleted_count || + old_junk_count != summary->priv->junk_count || + old_junk_not_deleted_count != summary->priv->junk_not_deleted_count || + old_visible_count != summary->priv->visible_count; +} + static CamelMessageInfo * message_info_clone (CamelFolderSummary *s, const CamelMessageInfo *mi) @@ -773,15 +1040,15 @@ info_set_user_flag (CamelMessageInfo *info, res = camel_flag_set (&mi->user_flags, name, value); - /* TODO: check this item is still in the summary first */ - if (mi->summary && res && mi->summary->folder && mi->uid) { + if (mi->summary && res && mi->summary->priv->folder && mi->uid + && camel_folder_summary_check_uid (mi->summary, mi->uid)) { CamelFolderChangeInfo *changes = camel_folder_change_info_new (); mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; mi->dirty = TRUE; camel_folder_summary_touch (mi->summary); camel_folder_change_info_change_uid (changes, camel_message_info_uid (info)); - camel_folder_changed (mi->summary->folder, changes); + camel_folder_changed (mi->summary->priv->folder, changes); camel_folder_change_info_free (changes); } @@ -798,14 +1065,15 @@ info_set_user_tag (CamelMessageInfo *info, res = camel_tag_set (&mi->user_tags, name, value); - if (mi->summary && res && mi->summary->folder && mi->uid) { + if (mi->summary && res && mi->summary->priv->folder && mi->uid + && camel_folder_summary_check_uid (mi->summary, mi->uid)) { CamelFolderChangeInfo *changes = camel_folder_change_info_new (); mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; mi->dirty = TRUE; camel_folder_summary_touch (mi->summary); camel_folder_change_info_change_uid (changes, camel_message_info_uid (info)); - camel_folder_changed (mi->summary->folder, changes); + camel_folder_changed (mi->summary->priv->folder, changes); camel_folder_change_info_free (changes); } @@ -819,19 +1087,9 @@ info_set_flags (CamelMessageInfo *info, { guint32 old; CamelMessageInfoBase *mi = (CamelMessageInfoBase *) info; - gint read = 0, deleted = 0, junk = 0; - /* TODO: locking? */ - - if (flags & CAMEL_MESSAGE_SEEN && ((set & CAMEL_MESSAGE_SEEN) != (mi->flags & CAMEL_MESSAGE_SEEN))) - { read = set & CAMEL_MESSAGE_SEEN ? 1 : -1; d(printf("Setting read as %d\n", set & CAMEL_MESSAGE_SEEN ? 1 : 0));} - - if (flags & CAMEL_MESSAGE_DELETED && ((set & CAMEL_MESSAGE_DELETED) != (mi->flags & CAMEL_MESSAGE_DELETED))) - { deleted = set & CAMEL_MESSAGE_DELETED ? 1 : -1; d(printf("Setting deleted as %d\n", set & CAMEL_MESSAGE_DELETED ? 1 : 0));} - - if (flags & CAMEL_MESSAGE_JUNK && ((set & CAMEL_MESSAGE_JUNK) != (mi->flags & CAMEL_MESSAGE_JUNK))) - { junk = set & CAMEL_MESSAGE_JUNK ? 1 : -1; d(printf("Setting junk as %d\n", set & CAMEL_MESSAGE_JUNK ? 1 : 0));} + gboolean counts_changed = FALSE; - old = mi->flags; + old = camel_message_info_flags (info); mi->flags = (old & ~flags) | (set & flags); if (old != mi->flags) { mi->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; @@ -840,38 +1098,33 @@ info_set_flags (CamelMessageInfo *info, camel_folder_summary_touch (mi->summary); } - if (((old & ~CAMEL_MESSAGE_SYSTEM_MASK) == (mi->flags & ~CAMEL_MESSAGE_SYSTEM_MASK)) && !((set & CAMEL_MESSAGE_JUNK_LEARN) && !(set & CAMEL_MESSAGE_JUNK))) + if (mi->summary) { + camel_folder_summary_lock (mi->summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + g_object_freeze_notify (G_OBJECT (mi->summary)); + counts_changed = folder_summary_replace_flags (mi->summary, info); + } + + if (!counts_changed && ((old & ~CAMEL_MESSAGE_SYSTEM_MASK) == (mi->flags & ~CAMEL_MESSAGE_SYSTEM_MASK)) && !((set & CAMEL_MESSAGE_JUNK_LEARN) && !(set & CAMEL_MESSAGE_JUNK))) { + if (mi->summary) { + g_object_thaw_notify (G_OBJECT (mi->summary)); + camel_folder_summary_unlock (mi->summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + } return FALSE; + } if (mi->summary) { - if (read && junk == 0 && !(mi->flags & CAMEL_MESSAGE_JUNK)) - mi->summary->unread_count -= read; - else if (junk > 0) - mi->summary->unread_count -= (old & CAMEL_MESSAGE_SEEN) ? 0 : 1; - else if (junk < 0) - mi->summary->unread_count -= (old & CAMEL_MESSAGE_SEEN) ? 0 : -1; - - if (deleted) - mi->summary->deleted_count += deleted; - if (junk) - mi->summary->junk_count += junk; - if (junk && !deleted) - mi->summary->junk_not_deleted_count += junk; - else if ((mi->flags & CAMEL_MESSAGE_JUNK) && deleted) - mi->summary->junk_not_deleted_count -= deleted; - - if (((junk && !(mi->flags & CAMEL_MESSAGE_DELETED))) || (deleted && !(mi->flags & CAMEL_MESSAGE_JUNK))) - mi->summary->visible_count -= junk ? junk : deleted; - } - if (mi->summary && mi->summary->folder && mi->uid) { + g_object_thaw_notify (G_OBJECT (mi->summary)); + camel_folder_summary_unlock (mi->summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + } + + if (mi->summary && mi->summary->priv->folder && mi->uid) { CamelFolderChangeInfo *changes = camel_folder_change_info_new (); camel_folder_change_info_change_uid (changes, camel_message_info_uid (info)); - camel_folder_changed (mi->summary->folder, changes); + camel_folder_changed (mi->summary->priv->folder, changes); camel_folder_change_info_free (changes); } - d(printf("%d %d %d %d %d\n", mi->summary->unread_count, mi->summary->deleted_count, mi->summary->junk_count, mi->summary->junk_not_deleted_count, mi->summary->visible_count)); return TRUE; } @@ -883,6 +1136,8 @@ camel_folder_summary_class_init (CamelFolderSummaryClass *class) g_type_class_add_private (class, sizeof (CamelFolderSummaryPrivate)); object_class = G_OBJECT_CLASS (class); + object_class->set_property = folder_summary_set_property; + object_class->get_property = folder_summary_get_property; object_class->dispose = folder_summary_dispose; object_class->finalize = folder_summary_finalize; @@ -926,6 +1181,140 @@ camel_folder_summary_class_init (CamelFolderSummaryClass *class) class->info_set_flags = info_set_flags; + /** + * CamelFolderSummary:folder + * + * The #CamelFolder to which the folder summary belongs. + **/ + g_object_class_install_property ( + object_class, + PROP_FOLDER, + g_param_spec_object ( + "folder", + "Folder", + "The folder to which the folder summary belongs", + CAMEL_TYPE_FOLDER, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + /** + * CamelFolderSummary:saved-count + * + * How many infos is saved in a summary. + **/ + g_object_class_install_property ( + object_class, + PROP_SAVED_COUNT, + g_param_spec_uint ( + "saved-count", + "Saved count", + "How many infos is savef in a summary", + 0, G_MAXUINT32, + 0, G_PARAM_READABLE)); + + /** + * CamelFolderSummary:unread-count + * + * How many unread infos is saved in a summary. + **/ + g_object_class_install_property ( + object_class, + PROP_UNREAD_COUNT, + g_param_spec_uint ( + "unread-count", + "Unread count", + "How many unread infos is saved in a summary", + 0, G_MAXUINT32, + 0, G_PARAM_READABLE)); + + /** + * CamelFolderSummary:deleted-count + * + * How many deleted infos is saved in a summary. + **/ + g_object_class_install_property ( + object_class, + PROP_DELETED_COUNT, + g_param_spec_uint ( + "deleted-count", + "Deleted count", + "How many deleted infos is saved in a summary", + 0, G_MAXUINT32, + 0, G_PARAM_READABLE)); + + /** + * CamelFolderSummary:junk-count + * + * How many junk infos is saved in a summary. + **/ + g_object_class_install_property ( + object_class, + PROP_JUNK_COUNT, + g_param_spec_uint ( + "junk-count", + "Junk count", + "How many junk infos is saved in a summary", + 0, G_MAXUINT32, + 0, G_PARAM_READABLE)); + + /** + * CamelFolderSummary:junk-not-deleted-count + * + * How many junk and not deleted infos is saved in a summary. + **/ + g_object_class_install_property ( + object_class, + PROP_JUNK_NOT_DELETED_COUNT, + g_param_spec_uint ( + "junk-not-deleted-count", + "Junk not deleted count", + "How many junk and not deleted infos is saved in a summary", + 0, G_MAXUINT32, + 0, G_PARAM_READABLE)); + + /** + * CamelFolderSummary:visible-count + * + * How many visible (not deleted and not junk) infos is saved in a summary. + **/ + g_object_class_install_property ( + object_class, + PROP_VISIBLE_COUNT, + g_param_spec_uint ( + "visible-count", + "Visible count", + "How many visible (not deleted and not junk) infos is saved in a summary", + 0, G_MAXUINT32, + 0, G_PARAM_READABLE)); + + /** + * CamelFolderSummary:build-content + * + * Whether to build CamelMessageInfo.content. + **/ + g_object_class_install_property ( + object_class, + PROP_BUILD_CONTENT, + g_param_spec_boolean ( + "build-content", + "Build content", + "Whether to build CamelMessageInfo.content", + FALSE, + G_PARAM_READWRITE)); + + /** + * CamelFolderSummary:need-preview + * + **/ + g_object_class_install_property ( + object_class, + PROP_NEED_PREVIEW, + g_param_spec_boolean ( + "need-preview", + "Need preview", + "", + FALSE, + G_PARAM_READWRITE)); } static void @@ -934,24 +1323,19 @@ camel_folder_summary_init (CamelFolderSummary *summary) summary->priv = G_TYPE_INSTANCE_GET_PRIVATE ( summary, CAMEL_TYPE_FOLDER_SUMMARY, CamelFolderSummaryPrivate); + summary->version = CAMEL_FOLDER_SUMMARY_VERSION; + summary->flags = 0; + summary->time = 0; + summary->priv->filter_charset = g_hash_table_new ( camel_strcase_hash, camel_strcase_equal); - summary->message_info_chunks = NULL; - summary->content_info_chunks = NULL; summary->priv->need_preview = FALSE; summary->priv->preview_updates = g_hash_table_new (g_str_hash, g_str_equal); -#if defined (DOESTRV) || defined (DOEPOOLV) - summary->message_info_strings = CAMEL_MESSAGE_INFO_LAST; -#endif - summary->version = CAMEL_FOLDER_SUMMARY_VERSION; - summary->flags = 0; - summary->time = 0; - summary->nextuid = 1; - - summary->uids = g_ptr_array_new (); - summary->loaded_infos = g_hash_table_new (g_str_hash, g_str_equal); + summary->priv->nextuid = 1; + summary->priv->uids = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) camel_pstring_free, NULL); + summary->priv->loaded_infos = g_hash_table_new (g_str_hash, g_str_equal); g_static_rec_mutex_init (&summary->priv->summary_lock); g_static_rec_mutex_init (&summary->priv->io_lock); @@ -959,14 +1343,8 @@ camel_folder_summary_init (CamelFolderSummary *summary) g_static_rec_mutex_init (&summary->priv->alloc_lock); g_static_rec_mutex_init (&summary->priv->ref_lock); - summary->meta_summary = g_malloc0 (sizeof (CamelFolderMetaSummary)); - - /* Default is 20, any implementor having UIDs that has length - * exceeding 20, has to override this value - */ - summary->meta_summary->uid_len = 20; - summary->cache_load_time = 0; - summary->timeout_handle = 0; + summary->priv->cache_load_time = 0; + summary->priv->timeout_handle = 0; } /** @@ -978,284 +1356,535 @@ camel_folder_summary_init (CamelFolderSummary *summary) * Returns: a new #CamelFolderSummary object **/ CamelFolderSummary * -camel_folder_summary_new (struct _CamelFolder *folder) +camel_folder_summary_new (CamelFolder *folder) { - CamelFolderSummary *new; - - new = g_object_new (CAMEL_TYPE_FOLDER_SUMMARY, NULL); - new->folder = folder; - - return new; + return g_object_new (CAMEL_TYPE_FOLDER_SUMMARY, "folder", folder, NULL); } /** - * camel_folder_summary_set_filename: + * camel_folder_summary_get_index: * @summary: a #CamelFolderSummary object - * @filename: a filename * - * Set the filename where the summary will be loaded to/saved from. + * Returns: a #CamelFolder to which the summary if associated. + * + * Since: 3.4 **/ -void -camel_folder_summary_set_filename (CamelFolderSummary *s, - const gchar *name) +CamelFolder * +camel_folder_summary_get_folder (CamelFolderSummary *summary) { - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + CamelFolderSummaryPrivate *priv; - g_free (s->summary_path); - s->summary_path = g_strdup (name); + g_return_val_if_fail (summary != NULL, NULL); + g_return_val_if_fail (summary->priv != NULL, NULL); - g_free (s->meta_summary->path); - s->meta_summary->path = g_strconcat(name, "-meta", NULL); + priv = summary->priv; - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + return priv->folder; } /** - * camel_folder_summary_set_index: + * camel_folder_summary_get_saved_count: * @summary: a #CamelFolderSummary object - * @index: a #CamelIndex * - * Set the index used to index body content. If the index is %NULL, or - * not set (the default), no indexing of body content will take place. + * Returns: Count of saved infos. * - * Unlike earlier behaviour, build_content need not be set to perform indexing. + * Since: 3.4 **/ -void -camel_folder_summary_set_index (CamelFolderSummary *s, - CamelIndex *index) +guint32 +camel_folder_summary_get_saved_count (CamelFolderSummary *summary) { - struct _CamelFolderSummaryPrivate *p = s->priv; + CamelFolderSummaryPrivate *priv; - if (p->index) - g_object_unref (p->index); + g_return_val_if_fail (summary != NULL, 0); + g_return_val_if_fail (summary->priv != NULL, 0); - p->index = index; - if (index) - g_object_ref (index); -} + priv = summary->priv; -/** - * camel_folder_summary_set_build_content: - * @summary: a #CamelFolderSummary object - * @state: to build or not to build the content - * - * Set a flag to tell the summary to build the content info summary - * (#CamelMessageInfo.content). The default is not to build content - * info summaries. - **/ -void -camel_folder_summary_set_build_content (CamelFolderSummary *s, - gboolean state) -{ - s->build_content = state; + return priv->saved_count; } /** - * camel_folder_summary_count: + * camel_folder_summary_get_saved_count: * @summary: a #CamelFolderSummary object * - * Get the number of summary items stored in this summary. + * Returns: Count of unread infos. * - * Returns: the number of items in the summary + * Since: 3.4 **/ -guint -camel_folder_summary_count (CamelFolderSummary *s) +guint32 +camel_folder_summary_get_unread_count (CamelFolderSummary *summary) { - return s->uids->len; + CamelFolderSummaryPrivate *priv; + + g_return_val_if_fail (summary != NULL, 0); + g_return_val_if_fail (summary->priv != NULL, 0); + + priv = summary->priv; + + return priv->unread_count; } /** - * camel_folder_summary_index: + * camel_folder_summary_get_deleted_count: * @summary: a #CamelFolderSummary object - * @index: item index * - * Retrieve a summary item by index number. + * Returns: Count of deleted infos. * - * A referenced to the summary item is returned, which may be - * ref'd or free'd as appropriate. - * - * Returns: the summary item, or %NULL if @index is out of range + * Since: 3.4 **/ -CamelMessageInfo * -camel_folder_summary_index (CamelFolderSummary *s, - gint i) +guint32 +camel_folder_summary_get_deleted_count (CamelFolderSummary *summary) { - CamelMessageInfo *info = NULL; - - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK); - - if (i < s->uids->len) { - gchar *uid; - uid = g_ptr_array_index (s->uids, i); - - /* FIXME: Get exception from caller - and pass it on below */ - - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + CamelFolderSummaryPrivate *priv; - return camel_folder_summary_uid (s, uid); - } + g_return_val_if_fail (summary != NULL, 0); + g_return_val_if_fail (summary->priv != NULL, 0); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + priv = summary->priv; - return info; + return priv->deleted_count; } -/* FIXME[disk-summary] Implement - camel_folder_summary_uid_exist - - * directly through db than manual strcmp */ - /** - * camel_folder_summary_uid_from_index: - * @s: a #CamelFolderSummary object - * @i: item index - * - * Retrieve a summary item's uid by index number. - * - * A newly allocated uid is returned, which must be - * free'd as appropriate. + * camel_folder_summary_get_junk_count: + * @summary: a #CamelFolderSummary object * - * Returns: the summary item's uid , or %NULL if @index is out of range + * Returns: Count of junk infos. * - * Since: 2.24 + * Since: 3.4 **/ -gchar * -camel_folder_summary_uid_from_index (CamelFolderSummary *s, - gint i) +guint32 +camel_folder_summary_get_junk_count (CamelFolderSummary *summary) { - gchar *uid = NULL; - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - - if (i < s->uids->len) - uid = g_strdup (g_ptr_array_index (s->uids, i)); + CamelFolderSummaryPrivate *priv; - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + g_return_val_if_fail (summary != NULL, 0); + g_return_val_if_fail (summary->priv != NULL, 0); - return uid; + priv = summary->priv; + return priv->junk_count; } /** - * camel_folder_summary_check_uid - * @s: a #CamelFolderSummary object - * @uid: a uid - * - * Check if the uid is valid. This isn't very efficient, so it shouldn't be called iteratively. - * + * camel_folder_summary_get_junk_not_deleted_count: + * @summary: a #CamelFolderSummary object * - * Returns: if the uid is present in the summary or not (%TRUE or %FALSE) + * Returns: Count of junk and not deleted infos. * - * Since: 2.24 + * Since: 3.4 **/ -gboolean -camel_folder_summary_check_uid (CamelFolderSummary *s, - const gchar *uid) +guint32 +camel_folder_summary_get_junk_not_deleted_count (CamelFolderSummary *summary) { - gboolean ret = FALSE; - gint i; - - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + CamelFolderSummaryPrivate *priv; - for (i = 0; i < s->uids->len; i++) { - if (strcmp (s->uids->pdata[i], uid) == 0) { - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - return TRUE; - } - } + g_return_val_if_fail (summary != NULL, 0); + g_return_val_if_fail (summary->priv != NULL, 0); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + priv = summary->priv; - return ret; + return priv->junk_not_deleted_count; } /** - * camel_folder_summary_array: + * camel_folder_summary_get_visible_count: * @summary: a #CamelFolderSummary object * - * Obtain a copy of the summary array. This is done atomically, - * so cannot contain empty entries. - * - * It must be freed using g_ptr_array_free + * Returns: Count of visible (not junk and not deleted) infos. * - * Returns: a #GPtrArray of uids + * Since: 3.4 **/ -GPtrArray * -camel_folder_summary_array (CamelFolderSummary *s) +guint32 +camel_folder_summary_get_visible_count (CamelFolderSummary *summary) { - GPtrArray *res = g_ptr_array_new (); - gint i; - - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + CamelFolderSummaryPrivate *priv; - g_ptr_array_set_size (res, s->uids->len); - for (i = 0; i < s->uids->len; i++) - res->pdata[i] = (gpointer) camel_pstring_strdup ((gchar *) g_ptr_array_index (s->uids, i)); + g_return_val_if_fail (summary != NULL, 0); + g_return_val_if_fail (summary->priv != NULL, 0); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + priv = summary->priv; - return res; + return priv->visible_count; } /** - * camel_folder_summary_get_hashtable: + * camel_folder_summary_set_index: * @summary: a #CamelFolderSummary object + * @index: a #CamelIndex * - * Obtain a copy of the summary array in the hashtable. This is done atomically, + * Set the index used to index body content. If the index is %NULL, or + * not set (the default), no indexing of body content will take place. + * + * Unlike earlier behaviour, build_content need not be set to perform indexing. + **/ +void +camel_folder_summary_set_index (CamelFolderSummary *summary, + CamelIndex *index) +{ + CamelFolderSummaryPrivate *priv; + + g_return_if_fail (summary != NULL); + g_return_if_fail (summary->priv != NULL); + + priv = summary->priv; + + if (index) + g_object_ref (index); + + if (priv->index) + g_object_unref (priv->index); + + priv->index = index; +} + +/** + * camel_folder_summary_get_index: + * @summary: a #CamelFolderSummary object + * + * Returns: a #CamelIndex used to index body content. + * + * Since: 3.4 + **/ +CamelIndex * +camel_folder_summary_get_index (CamelFolderSummary *summary) +{ + CamelFolderSummaryPrivate *priv; + + g_return_val_if_fail (summary != NULL, NULL); + g_return_val_if_fail (summary->priv != NULL, NULL); + + priv = summary->priv; + + return priv->index; +} + +/** + * camel_folder_summary_set_build_content: + * @summary: a #CamelFolderSummary object + * @state: to build or not to build the content + * + * Set a flag to tell the summary to build the content info summary + * (#CamelMessageInfo.content). The default is not to build content + * info summaries. + **/ +void +camel_folder_summary_set_build_content (CamelFolderSummary *summary, + gboolean state) +{ + CamelFolderSummaryPrivate *priv; + + g_return_if_fail (summary != NULL); + g_return_if_fail (summary->priv != NULL); + + priv = summary->priv; + + if ((priv->build_content ? 1 : 0) == (state ? 1 : 0)) + return; + + priv->build_content = state; + + g_object_notify (G_OBJECT (summary), "build-content"); +} + +/** + * camel_folder_summary_get_build_content: + * @summary: a #CamelFolderSummary object + * + * Returns: Whether to build #CamelMessageInfo.content. + * + * Since: 3.4 + **/ +gboolean +camel_folder_summary_get_build_content (CamelFolderSummary *summary) +{ + CamelFolderSummaryPrivate *priv; + + g_return_val_if_fail (summary != NULL, FALSE); + g_return_val_if_fail (summary->priv != NULL, FALSE); + + priv = summary->priv; + + return priv->build_content; +} + +/** + * camel_folder_summary_set_need_preview: + * + * Since: 2.28 + **/ +void +camel_folder_summary_set_need_preview (CamelFolderSummary *summary, + gboolean preview) +{ + CamelFolderSummaryPrivate *priv; + + g_return_if_fail (summary != NULL); + g_return_if_fail (summary->priv != NULL); + + priv = summary->priv; + + priv->need_preview = preview; +} + +/** + * camel_folder_summary_get_need_preview: + * + * Since: 2.28 + **/ +gboolean +camel_folder_summary_get_need_preview (CamelFolderSummary *summary) +{ + CamelFolderSummaryPrivate *priv; + + g_return_val_if_fail (summary != NULL, FALSE); + g_return_val_if_fail (summary->priv != NULL, FALSE); + + priv = summary->priv; + + return priv->need_preview; +} + +/** + * camel_folder_summary_next_uid: + * @summary: a #CamelFolderSummary object + * + * Generate a new unique uid value as an integer. This + * may be used to create a unique sequence of numbers. + * + * Returns: the next unique uid value + **/ +guint32 +camel_folder_summary_next_uid (CamelFolderSummary *s) +{ + guint32 uid; + + camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + + uid = s->priv->nextuid++; + camel_folder_summary_touch (s); + + camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + + return uid; +} + +/** + * camel_folder_summary_set_next_uid: + * @summary: a #CamelFolderSummary object + * @uid: The next minimum uid to assign. To avoid clashing + * uid's, set this to the uid of a given messages + 1. + * + * Set the next minimum uid available. This can be used to + * ensure new uid's do not clash with existing uid's. + **/ +void +camel_folder_summary_set_next_uid (CamelFolderSummary *s, + guint32 uid) +{ + camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + + s->priv->nextuid = MAX (s->priv->nextuid, uid); + camel_folder_summary_touch (s); + + camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); +} + +/** + * camel_folder_summary_get_next_uid: + * @summary: a #CamelFolderSummary object + * + * Returns: Next uid currently awaiting for assignment. The difference from + * camel_folder_summary_next_uid() is that this function returns actual + * value and doesn't increment it before returning. + * + * Since: 3.4 + **/ +guint32 +camel_folder_summary_get_next_uid (CamelFolderSummary *summary) +{ + guint32 res; + + g_return_val_if_fail (summary != NULL, 0); + g_return_val_if_fail (summary->priv != NULL, 0); + + camel_folder_summary_lock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + + res = summary->priv->nextuid; + + camel_folder_summary_unlock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + + return res; +} + +/** + * camel_folder_summary_next_uid_string: + * @summary: a #CamelFolderSummary object + * + * Retrieve the next uid, but as a formatted string. + * + * Returns: the next uid as an unsigned integer string. + * This string must be freed by the caller. + **/ +gchar * +camel_folder_summary_next_uid_string (CamelFolderSummary *summary) +{ + CamelFolderSummaryClass *class; + + g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary), NULL); + + class = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary); + g_return_val_if_fail (class->next_uid_string != NULL, NULL); + + return class->next_uid_string (summary); +} + +/** + * camel_folder_summary_set_filename: + * @summary: a #CamelFolderSummary object + * @filename: a filename + * + * Set the filename where the summary will be loaded to/saved from. + **/ +void +camel_folder_summary_set_filename (CamelFolderSummary *s, + const gchar *name) +{ + camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + + g_free (s->priv->summary_path); + s->priv->summary_path = g_strdup (name); + + camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); +} + +/** + * camel_folder_summary_count: + * @summary: a #CamelFolderSummary object + * + * Get the number of summary items stored in this summary. + * + * Returns: the number of items in the summary + **/ +guint +camel_folder_summary_count (CamelFolderSummary *summary) +{ + g_return_val_if_fail (summary != NULL, 0); + g_return_val_if_fail (summary->priv != NULL, 0); + + return g_hash_table_size (summary->priv->uids); +} + +/** + * camel_folder_summary_check_uid + * @s: a #CamelFolderSummary object + * @uid: a uid + * + * Check if the uid is valid. This isn't very efficient, so it shouldn't be called iteratively. + * + * + * Returns: if the uid is present in the summary or not (%TRUE or %FALSE) + * + * Since: 2.24 + **/ +gboolean +camel_folder_summary_check_uid (CamelFolderSummary *s, + const gchar *uid) +{ + gboolean ret; + + g_return_val_if_fail (s != NULL, FALSE); + g_return_val_if_fail (s->priv != NULL, FALSE); + g_return_val_if_fail (uid != NULL, FALSE); + + camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + + ret = g_hash_table_lookup_extended (s->priv->uids, uid, NULL, NULL); + + camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + + return ret; +} + +static void +folder_summary_dupe_uids_to_array (gpointer key_uid, gpointer value_flags, gpointer user_data) +{ + g_ptr_array_add (user_data, (gpointer) camel_pstring_strdup (key_uid)); +} + +/** + * camel_folder_summary_get_array: + * @summary: a #CamelFolderSummary object + * + * Obtain a copy of the summary array. This is done atomically, * so cannot contain empty entries. * - * It must be freed using camel_folder_summary_free_hashtable + * Free with camel_folder_summary_free_array() * - * Returns: a #GHashTable of uids + * Returns: a #GPtrArray of uids * - * Since: 2.26 + * Since: 3.4 **/ -GHashTable * -camel_folder_summary_get_hashtable (CamelFolderSummary *s) +GPtrArray * +camel_folder_summary_get_array (CamelFolderSummary *s) { - GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal); - gint i; + GPtrArray *res; + + g_return_val_if_fail (s != NULL, NULL); + g_return_val_if_fail (s->priv != NULL, NULL); camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - for (i = 0; i < s->uids->len; i++) - g_hash_table_insert (hash, (gpointer) camel_pstring_strdup ((gchar *) g_ptr_array_index (s->uids, i)), GINT_TO_POINTER (1)); + res = g_ptr_array_sized_new (g_hash_table_size (s->priv->uids)); + g_hash_table_foreach (s->priv->uids, folder_summary_dupe_uids_to_array, res); camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - return hash; + return res; } /** - * camel_folder_summary_free_hashtable: + * camel_folder_summary_free_array: + * @array: a #GPtrArray returned from camel_folder_summary_get_array() * - * Since: 2.26 + * Free's array and its elements returned from camel_folder_summary_get_array(). + * + * Since: 3.4 **/ void -camel_folder_summary_free_hashtable (GHashTable *ht) +camel_folder_summary_free_array (GPtrArray *array) { - g_hash_table_foreach (ht, (GHFunc) camel_pstring_free, NULL); - g_hash_table_destroy (ht); + if (!array) + return; + + g_ptr_array_foreach (array, (GFunc) camel_pstring_free, NULL); + g_ptr_array_free (array, TRUE); } /** - * camel_folder_summary_peek_info: + * camel_folder_summary_peek_loaded: * * Since: 2.26 **/ CamelMessageInfo * -camel_folder_summary_peek_info (CamelFolderSummary *s, - const gchar *uid) +camel_folder_summary_peek_loaded (CamelFolderSummary *s, + const gchar *uid) { - CamelMessageInfo *info = g_hash_table_lookup (s->loaded_infos, uid); + CamelMessageInfo *info; + + g_return_val_if_fail (s != NULL, NULL); + g_return_val_if_fail (s->priv != NULL, NULL); + + info = g_hash_table_lookup (s->priv->loaded_infos, uid); if (info) camel_message_info_ref (info); + return info; } struct _db_pass_data { + GHashTable *columns_hash; CamelFolderSummary *summary; gboolean add; /* or just insert to hashtable */ }; @@ -1269,7 +1898,7 @@ message_info_from_uid (CamelFolderSummary *s, camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - info = g_hash_table_lookup (s->loaded_infos, uid); + info = g_hash_table_lookup (s->priv->loaded_infos, uid); if (!info) { CamelDB *cdb; @@ -1277,25 +1906,27 @@ message_info_from_uid (CamelFolderSummary *s, const gchar *folder_name; struct _db_pass_data data; - d(printf ("\ncamel_folder_summary_uid called \n")); - - folder_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); + folder_name = camel_folder_get_full_name (s->priv->folder); + parent_store = camel_folder_get_parent_store (s->priv->folder); cdb = parent_store->cdb_r; + data.columns_hash = NULL; data.summary = s; data.add = FALSE; ret = camel_db_read_message_info_record_with_uid ( cdb, folder_name, uid, &data, camel_read_mir_callback, NULL); + if (data.columns_hash) + g_hash_table_destroy (data.columns_hash); + if (ret != 0) { camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); return NULL; } /* We would have double reffed at camel_read_mir_callback */ - info = g_hash_table_lookup (s->loaded_infos, uid); + info = g_hash_table_lookup (s->priv->loaded_infos, uid); cfs_schedule_info_release_timer (s); } @@ -1309,7 +1940,7 @@ message_info_from_uid (CamelFolderSummary *s, } /** - * camel_folder_summary_uid: + * camel_folder_summary_get: * @summary: a #CamelFolderSummary object * @uid: a uid * @@ -1321,8 +1952,8 @@ message_info_from_uid (CamelFolderSummary *s, * Returns: the summary item, or %NULL if the uid @uid is not available **/ CamelMessageInfo * -camel_folder_summary_uid (CamelFolderSummary *summary, - const gchar *uid) +camel_folder_summary_get (CamelFolderSummary *summary, + const gchar *uid) { CamelFolderSummaryClass *class; @@ -1335,74 +1966,6 @@ camel_folder_summary_uid (CamelFolderSummary *summary, return class->message_info_from_uid (summary, uid); } -/** - * camel_folder_summary_next_uid: - * @summary: a #CamelFolderSummary object - * - * Generate a new unique uid value as an integer. This - * may be used to create a unique sequence of numbers. - * - * Returns: the next unique uid value - **/ -guint32 -camel_folder_summary_next_uid (CamelFolderSummary *s) -{ - guint32 uid; - - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - - uid = s->nextuid++; - - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - - /* FIXME: sync this to disk */ -/* summary_header_save(s);*/ - return uid; -} - -/** - * camel_folder_summary_set_uid: - * @summary: a #CamelFolderSummary object - * @uid: The next minimum uid to assign. To avoid clashing - * uid's, set this to the uid of a given messages + 1. - * - * Set the next minimum uid available. This can be used to - * ensure new uid's do not clash with existing uid's. - **/ -void -camel_folder_summary_set_uid (CamelFolderSummary *s, - guint32 uid) -{ - /* TODO: sync to disk? */ - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - - s->nextuid = MAX (s->nextuid, uid); - - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); -} - -/** - * camel_folder_summary_next_uid_string: - * @summary: a #CamelFolderSummary object - * - * Retrieve the next uid, but as a formatted string. - * - * Returns: the next uid as an unsigned integer string. - * This string must be freed by the caller. - **/ -gchar * -camel_folder_summary_next_uid_string (CamelFolderSummary *summary) -{ - CamelFolderSummaryClass *class; - - g_return_val_if_fail (CAMEL_IS_FOLDER_SUMMARY (summary), NULL); - - class = CAMEL_FOLDER_SUMMARY_GET_CLASS (summary); - g_return_val_if_fail (class->next_uid_string != NULL, NULL); - - return class->next_uid_string (summary); -} - static CamelMessageContentInfo * perform_content_info_load_from_db (CamelFolderSummary *s, CamelMIRecord *mir) @@ -1492,7 +2055,7 @@ camel_folder_summary_get_changed (CamelFolderSummary *s) * from DB and merge */ camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - g_hash_table_foreach (s->loaded_infos, (GHFunc) append_changed_uids, res); + g_hash_table_foreach (s->priv->loaded_infos, (GHFunc) append_changed_uids, res); camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); return res; @@ -1513,23 +2076,22 @@ cfs_count_dirty (CamelFolderSummary *s) gint count = 0; camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - g_hash_table_foreach (s->loaded_infos, (GHFunc) count_changed_uids, &count); + g_hash_table_foreach (s->priv->loaded_infos, (GHFunc) count_changed_uids, &count); camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); return count; } -/* FIXME[disk-summary] I should have a better LRU algorithm */ static gboolean -remove_item (gchar *key, +remove_item (gchar *uid, CamelMessageInfoBase *info, - GList **to_free_list) + GSList **to_remove_infos) { - d(printf("%d(%d)\t", info->refcount, info->dirty)); /* camel_message_info_dump (info); */ - if (info->refcount == 1 && !info->dirty && !(info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) { - *to_free_list = g_list_prepend (*to_free_list, info); + if (info->refcount == 1 && !info->dirty && (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) == 0) { + *to_remove_infos = g_slist_prepend (*to_remove_infos, info); return TRUE; } + return FALSE; } @@ -1539,32 +2101,25 @@ remove_cache (CamelSession *session, CamelFolderSummary *summary, GError **error) { - GList *to_free_list = NULL, *l; + GSList *to_remove_infos = NULL; CAMEL_DB_RELEASE_SQLITE_MEMORY; - if (time (NULL) - summary->cache_load_time < SUMMARY_CACHE_DROP) + if (time (NULL) - summary->priv->cache_load_time < SUMMARY_CACHE_DROP) return; - /* FIXME[disk-summary] hack. fix it */ - camel_folder_summary_lock ( - summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + camel_folder_summary_lock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); camel_folder_summary_lock (summary, CAMEL_FOLDER_SUMMARY_REF_LOCK); - g_hash_table_foreach_remove ( - summary->loaded_infos, (GHRFunc) remove_item, &to_free_list); + g_hash_table_foreach_remove (summary->priv->loaded_infos, (GHRFunc) remove_item, &to_remove_infos); camel_folder_summary_unlock (summary, CAMEL_FOLDER_SUMMARY_REF_LOCK); - /* Deferred freeing as _free function will try to remove - * entries from the hash_table in foreach_remove otherwise */ - for (l = to_free_list; l; l = l->next) - camel_message_info_free (l->data); - g_list_free (to_free_list); + g_slist_foreach (to_remove_infos, (GFunc) camel_message_info_free, NULL); + g_slist_free (to_remove_infos); - camel_folder_summary_unlock ( - summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + camel_folder_summary_unlock (summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - summary->cache_load_time = time (NULL); + summary->priv->cache_load_time = time (NULL); } static gboolean @@ -1574,16 +2129,16 @@ cfs_try_release_memory (CamelFolderSummary *summary) CamelSession *session; /* If folder is freed or if the cache is nil then clean up */ - if (!summary->folder || !g_hash_table_size (summary->loaded_infos)) { - summary->cache_load_time = 0; - summary->timeout_handle = 0; + if (!summary->priv->folder || !g_hash_table_size (summary->priv->loaded_infos)) { + summary->priv->cache_load_time = 0; + summary->priv->timeout_handle = 0; return FALSE; } - parent_store = camel_folder_get_parent_store (summary->folder); + parent_store = camel_folder_get_parent_store (summary->priv->folder); session = camel_service_get_session (CAMEL_SERVICE (parent_store)); - if (time (NULL) - summary->cache_load_time < SUMMARY_CACHE_DROP) + if (time (NULL) - summary->priv->cache_load_time < SUMMARY_CACHE_DROP) return TRUE; camel_session_submit_job ( @@ -1600,7 +2155,7 @@ cfs_schedule_info_release_timer (CamelFolderSummary *s) { g_return_if_fail (CAMEL_IS_FOLDER_SUMMARY (s)); - if (!s->timeout_handle) { + if (!s->priv->timeout_handle) { static gboolean know_can_do = FALSE, can_do = TRUE; if (!know_can_do) { @@ -1610,21 +2165,21 @@ cfs_schedule_info_release_timer (CamelFolderSummary *s) /* FIXME[disk-summary] LRU please and not timeouts */ if (can_do) - s->timeout_handle = g_timeout_add_seconds (SUMMARY_CACHE_DROP, (GSourceFunc) cfs_try_release_memory, s); + s->priv->timeout_handle = g_timeout_add_seconds (SUMMARY_CACHE_DROP, (GSourceFunc) cfs_try_release_memory, s); } /* update also cache load time to the actual, to not release something just loaded */ - s->cache_load_time = time (NULL); + s->priv->cache_load_time = time (NULL); } static gint cfs_cache_size (CamelFolderSummary *s) { /* FIXME[disk-summary] this is a timely hack. fix it well */ - if (!CAMEL_IS_VEE_FOLDER (s->folder)) - return g_hash_table_size (s->loaded_infos); + if (!CAMEL_IS_VEE_FOLDER (s->priv->folder)) + return g_hash_table_size (s->priv->loaded_infos); else - return s->uids->len; + return g_hash_table_size (s->priv->uids); } /* Update preview of cached messages */ @@ -1634,7 +2189,7 @@ msg_update_preview (const gchar *uid, gpointer value, CamelFolder *folder) { - CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_uid (folder->summary, uid); + CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_get (folder->summary, uid); CamelMimeMessage *msg; CamelStore *parent_store; const gchar *full_name; @@ -1660,6 +2215,15 @@ pick_uids (const gchar *uid, g_ptr_array_add (array, (gchar *) camel_pstring_strdup (uid)); } +static void +copy_all_uids_to_hash (gpointer uid, + gpointer hash) +{ + g_return_if_fail (uid != NULL); + + g_hash_table_insert (hash, (gchar *) camel_pstring_strdup (uid), GINT_TO_POINTER (1)); +} + static gboolean fill_mi (const gchar *uid, const gchar *msg, @@ -1667,7 +2231,7 @@ fill_mi (const gchar *uid, { CamelMessageInfoBase *info; - info = g_hash_table_lookup (folder->summary->loaded_infos, uid); + info = g_hash_table_lookup (folder->summary->priv->loaded_infos, uid); if (info) /* We re assign the memory of msg */ info->preview = (gchar *) msg; camel_pstring_free (uid); /* unref the uid */ @@ -1682,13 +2246,19 @@ preview_update (CamelSession *session, GError **error) { /* FIXME: Either lock & use or copy & use.*/ - GPtrArray *uids_uncached= camel_folder_get_uncached_uids (folder, folder->summary->uids, NULL); - GHashTable *hash = camel_folder_summary_get_hashtable (folder->summary); - GHashTable *preview_data; + GPtrArray *uids_uncached, *uids_array; + GHashTable *preview_data, *uids_hash; CamelStore *parent_store; const gchar *full_name; gint i; + uids_array = camel_folder_summary_get_array (folder->summary); + uids_hash = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) camel_pstring_free, NULL); + g_ptr_array_foreach (uids_array, copy_all_uids_to_hash, uids_hash); + uids_uncached = camel_folder_get_uncached_uids (folder, uids_array, NULL); + camel_folder_summary_free_array (uids_array); + uids_array = NULL; + full_name = camel_folder_get_full_name (folder); parent_store = camel_folder_get_parent_store (folder); preview_data = camel_db_get_folder_preview (parent_store->cdb_r, full_name, NULL); @@ -1698,21 +2268,20 @@ preview_update (CamelSession *session, } camel_folder_summary_lock (folder->summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - g_hash_table_foreach (folder->summary->loaded_infos, (GHFunc) pick_uids, uids_uncached); + g_hash_table_foreach (folder->summary->priv->loaded_infos, (GHFunc) pick_uids, uids_uncached); camel_folder_summary_unlock (folder->summary, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); for (i = 0; i < uids_uncached->len; i++) { - g_hash_table_remove (hash, uids_uncached->pdata[i]); - camel_pstring_free (uids_uncached->pdata[i]); /* unref the hash table key */ + g_hash_table_remove (uids_hash, uids_uncached->pdata[i]); } camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK); camel_db_begin_transaction (parent_store->cdb_w, NULL); - g_hash_table_foreach (hash, (GHFunc) msg_update_preview, folder); + g_hash_table_foreach (uids_hash, (GHFunc) msg_update_preview, folder); camel_db_end_transaction (parent_store->cdb_w, NULL); camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK); camel_folder_free_uids (folder, uids_uncached); - camel_folder_summary_free_hashtable (hash); + g_hash_table_destroy (uids_hash); } /* end */ @@ -1732,25 +2301,29 @@ cfs_reload_from_db (CamelFolderSummary *s, * load better. */ d(printf ("\ncamel_folder_summary_reload_from_db called \n")); - folder_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); + folder_name = camel_folder_get_full_name (s->priv->folder); + parent_store = camel_folder_get_parent_store (s->priv->folder); session = camel_service_get_session (CAMEL_SERVICE (parent_store)); cdb = parent_store->cdb_r; - /* FIXME FOR SANKAR: No need to pass the address of summary here. */ + data.columns_hash = NULL; data.summary = s; data.add = FALSE; + ret = camel_db_read_message_info_records ( cdb, folder_name, (gpointer) &data, camel_read_mir_callback, NULL); + if (data.columns_hash) + g_hash_table_destroy (data.columns_hash); + cfs_schedule_info_release_timer (s); if (s->priv->need_preview) camel_session_submit_job ( session, (CamelSessionCallback) preview_update, - g_object_ref (s->folder), + g_object_ref (s->priv->folder), (GDestroyNotify) g_object_unref); return ret == 0 ? 0 : -1; @@ -1800,7 +2373,7 @@ camel_folder_summary_prepare_fetch_all (CamelFolderSummary *s, } /* update also cache load time, even when not loaded anything */ - s->cache_load_time = time (NULL); + s->priv->cache_load_time = time (NULL); } /** @@ -1808,7 +2381,7 @@ camel_folder_summary_prepare_fetch_all (CamelFolderSummary *s, * * Since: 2.24 **/ -gint +gboolean camel_folder_summary_load_from_db (CamelFolderSummary *s, GError **error) { @@ -1818,23 +2391,24 @@ camel_folder_summary_load_from_db (CamelFolderSummary *s, gint ret = 0; GError *local_error = NULL; + g_return_val_if_fail (s != NULL, FALSE); + g_return_val_if_fail (s->priv != NULL, FALSE); + camel_folder_summary_save_to_db (s, NULL); /* struct _db_pass_data data; */ d(printf ("\ncamel_folder_summary_load_from_db called \n")); - full_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); - ret = camel_folder_summary_header_load_from_db (s, parent_store, full_name, error); - - if (ret) - return ret; + full_name = camel_folder_get_full_name (s->priv->folder); + parent_store = camel_folder_get_parent_store (s->priv->folder); + if (!camel_folder_summary_header_load_from_db (s, parent_store, full_name, error)) + return FALSE; cdb = parent_store->cdb_r; ret = camel_db_get_folder_uids ( cdb, full_name, s->sort_by, s->collate, - s->uids, &local_error); + s->priv->uids, &local_error); if (local_error != NULL && local_error->message != NULL && strstr (local_error->message, "no such table") != NULL) { @@ -1843,12 +2417,13 @@ camel_folder_summary_load_from_db (CamelFolderSummary *s, } else if (local_error != NULL) g_propagate_error (error, local_error); - return ret == 0 ? 0 : -1; + return ret == 0; } static void mir_from_cols (CamelMIRecord *mir, CamelFolderSummary *s, + GHashTable **columns_hash, gint ncol, gchar **cols, gchar **name) @@ -1859,58 +2434,87 @@ mir_from_cols (CamelMIRecord *mir, if (!name[i] || !cols[i]) continue; - if (!strcmp (name [i], "uid")) - mir->uid = (gchar *) camel_pstring_strdup (cols[i]); - else if (!strcmp (name [i], "flags")) - mir->flags = cols[i] ? strtoul (cols[i], NULL, 10) : 0; - else if (!strcmp (name [i], "read")) - mir->read = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE; - else if (!strcmp (name [i], "deleted")) - mir->deleted = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE; - else if (!strcmp (name [i], "replied")) - mir->replied = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE; - else if (!strcmp (name [i], "important")) - mir->important = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE; - else if (!strcmp (name [i], "junk")) - mir->junk = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE; - else if (!strcmp (name [i], "attachment")) - mir->attachment = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE; - else if (!strcmp (name [i], "size")) - mir->size = cols[i] ? strtoul (cols[i], NULL, 10) : 0; - else if (!strcmp (name [i], "dsent")) - mir->dsent = cols[i] ? strtol (cols[i], NULL, 10) : 0; - else if (!strcmp (name [i], "dreceived")) - mir->dreceived = cols[i] ? strtol (cols[i], NULL, 10) : 0; - else if (!strcmp (name [i], "subject")) - mir->subject = (gchar *) camel_pstring_strdup (cols[i]); - else if (!strcmp (name [i], "mail_from")) - mir->from = (gchar *) camel_pstring_strdup (cols[i]); - else if (!strcmp (name [i], "mail_to")) - mir->to = (gchar *) camel_pstring_strdup (cols[i]); - else if (!strcmp (name [i], "mail_cc")) - mir->cc = (gchar *) camel_pstring_strdup (cols[i]); - else if (!strcmp (name [i], "mlist")) - mir->mlist = (gchar *) camel_pstring_strdup (cols[i]); - else if (!strcmp (name [i], "followup_flag")) - mir->followup_flag = (gchar *) camel_pstring_strdup (cols[i]); - else if (!strcmp (name [i], "followup_completed_on")) - mir->followup_completed_on = (gchar *) camel_pstring_strdup (cols[i]); - else if (!strcmp (name [i], "followup_due_by")) - mir->followup_due_by = (gchar *) camel_pstring_strdup (cols[i]); - else if (!strcmp (name [i], "part")) - mir->part = g_strdup (cols[i]); - else if (!strcmp (name [i], "labels")) - mir->labels = g_strdup (cols[i]); - else if (!strcmp (name [i], "usertags")) - mir->usertags = g_strdup (cols[i]); - else if (!strcmp (name [i], "cinfo")) - mir->cinfo = g_strdup (cols[i]); - else if (!strcmp (name [i], "bdata")) - mir->bdata = g_strdup (cols[i]); - /* Evolution itself doesn't yet use this, ignoring - else if (!strcmp (name [i], "bodystructure")) - mir->bodystructure = g_strdup (cols[i]); */ - + switch (camel_db_get_column_ident (columns_hash, i, ncol, name)) { + case CAMEL_DB_COLUMN_UID: + mir->uid = (gchar *) camel_pstring_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_FLAGS: + mir->flags = cols[i] ? strtoul (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_READ: + mir->read = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE; + break; + case CAMEL_DB_COLUMN_DELETED: + mir->deleted = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE; + break; + case CAMEL_DB_COLUMN_REPLIED: + mir->replied = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE; + break; + case CAMEL_DB_COLUMN_IMPORTANT: + mir->important = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE; + break; + case CAMEL_DB_COLUMN_JUNK: + mir->junk = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE; + break; + case CAMEL_DB_COLUMN_ATTACHMENT: + mir->attachment = (cols[i]) ? ( ((strtoul (cols[i], NULL, 10)) ? TRUE : FALSE)) : FALSE; + break; + case CAMEL_DB_COLUMN_SIZE: + mir->size = cols[i] ? strtoul (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_DSENT: + mir->dsent = cols[i] ? strtol (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_DRECEIVED: + mir->dreceived = cols[i] ? strtol (cols[i], NULL, 10) : 0; + break; + case CAMEL_DB_COLUMN_SUBJECT: + mir->subject = (gchar *) camel_pstring_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_MAIL_FROM: + mir->from = (gchar *) camel_pstring_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_MAIL_TO: + mir->to = (gchar *) camel_pstring_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_MAIL_CC: + mir->cc = (gchar *) camel_pstring_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_MLIST: + mir->mlist = (gchar *) camel_pstring_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_FOLLOWUP_FLAG: + mir->followup_flag = (gchar *) camel_pstring_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_FOLLOWUP_COMPLETED_ON: + mir->followup_completed_on = (gchar *) camel_pstring_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_FOLLOWUP_DUE_BY: + mir->followup_due_by = (gchar *) camel_pstring_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_PART: + mir->part = g_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_LABELS: + mir->labels = g_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_USERTAGS: + mir->usertags = g_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_CINFO: + mir->cinfo = g_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_BDATA: + mir->bdata = g_strdup (cols[i]); + break; + case CAMEL_DB_COLUMN_BODYSTRUCTURE: + /* Evolution itself doesn't yet use this, ignoring */ + /* mir->bodystructure = g_strdup (cols[i]); */ + break; + default: + g_warn_if_reached (); + break; + } } } @@ -1927,10 +2531,10 @@ camel_read_mir_callback (gpointer ref, gint ret = 0; mir = g_new0 (CamelMIRecord , 1); - mir_from_cols (mir, s, ncol, cols, name); + mir_from_cols (mir, s, &data->columns_hash, ncol, cols, name); camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - if (!mir->uid || g_hash_table_lookup (s->loaded_infos, mir->uid)) { + if (!mir->uid || g_hash_table_lookup (s->priv->loaded_infos, mir->uid)) { /* Unlock and better return */ camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); camel_db_camel_mir_free (mir); @@ -1942,7 +2546,7 @@ camel_read_mir_callback (gpointer ref, if (info) { - if (s->build_content) { + if (s->priv->build_content) { gchar *tmp; tmp = mir->cinfo; /* FIXME: this should be done differently, how i don't know */ @@ -1993,22 +2597,22 @@ camel_folder_summary_migrate_infos (CamelFolderSummary *s) CamelDB *cdb; CamelFIRecord *record; - parent_store = camel_folder_get_parent_store (s->folder); + parent_store = camel_folder_get_parent_store (s->priv->folder); cdb = parent_store->cdb_w; /* Kick off the gc thread cycle. */ - if (s->timeout_handle) - g_source_remove (s->timeout_handle); - s->timeout_handle = 0; + if (s->priv->timeout_handle) + g_source_remove (s->priv->timeout_handle); + s->priv->timeout_handle = 0; d(g_print ("\ncamel_folder_summary_load from FLAT FILE called \n")); - if (s->summary_path == NULL) { + if (s->priv->summary_path == NULL) { g_warning ("No summary path set. Unable to migrate\n"); return -1; } - in = g_fopen(s->summary_path, "rb"); + in = g_fopen (s->priv->summary_path, "rb"); if (in == NULL) return -1; @@ -2016,7 +2620,7 @@ camel_folder_summary_migrate_infos (CamelFolderSummary *s) goto error; /* now read in each message ... */ - for (i = 0; i < s->saved_count; i++) { + for (i = 0; i < s->priv->saved_count; i++) { CamelTag *tag; mi = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->message_info_migrate (s, in); @@ -2025,7 +2629,7 @@ camel_folder_summary_migrate_infos (CamelFolderSummary *s) goto error; /* FIXME: this should be done differently, how i don't know */ - if (s->build_content) { + if (s->priv->build_content) { ((CamelMessageInfoBase *) mi)->content = perform_content_info_migrate (s, in); if (((CamelMessageInfoBase *) mi)->content == NULL) { camel_message_info_free (mi); @@ -2043,7 +2647,7 @@ camel_folder_summary_migrate_infos (CamelFolderSummary *s) } mi->dirty = TRUE; - g_hash_table_insert (s->loaded_infos, (gpointer) mi->uid, mi); + g_hash_table_insert (s->priv->loaded_infos, (gpointer) mi->uid, mi); } if (fclose (in) != 0) @@ -2079,7 +2683,7 @@ camel_folder_summary_migrate_infos (CamelFolderSummary *s) error: if (errno != EINVAL) - g_warning ("Cannot load summary file: '%s': %s", s->summary_path, g_strerror (errno)); + g_warning ("Cannot load summary file: '%s': %s", s->priv->summary_path, g_strerror (errno)); fclose (in); @@ -2088,7 +2692,7 @@ error: } /* saves the content descriptions, recursively */ -static gint +static gboolean perform_content_info_save_to_db (CamelFolderSummary *s, CamelMessageContentInfo *ci, CamelMIRecord *record) @@ -2096,8 +2700,8 @@ perform_content_info_save_to_db (CamelFolderSummary *s, CamelMessageContentInfo *part; gchar *oldr; - if (CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->content_info_to_db (s, ci, record) == -1) - return -1; + if (!CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->content_info_to_db (s, ci, record)) + return FALSE; oldr = record->cinfo; record->cinfo = g_strdup_printf ("%s %d", oldr, my_list_size ((struct _node **)&ci->childs)); @@ -2106,11 +2710,11 @@ perform_content_info_save_to_db (CamelFolderSummary *s, part = ci->childs; while (part) { if (perform_content_info_save_to_db (s, part, record) == -1) - return -1; + return FALSE; part = part->next; } - return 0; + return TRUE; } typedef struct { @@ -2133,8 +2737,8 @@ save_to_db_cb (gpointer key, CamelDB *cdb; CamelMIRecord *mir; - full_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); + full_name = camel_folder_get_full_name (s->priv->folder); + parent_store = camel_folder_get_parent_store (s->priv->folder); cdb = parent_store->cdb_w; if (!args->migration && !mi->dirty) @@ -2142,8 +2746,8 @@ save_to_db_cb (gpointer key, mir = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->message_info_to_db (s, (CamelMessageInfo *) mi); - if (mir && s->build_content) { - if (perform_content_info_save_to_db (s, ((CamelMessageInfoBase *) mi)->content, mir) == -1) { + if (mir && s->priv->build_content) { + if (!perform_content_info_save_to_db (s, ((CamelMessageInfoBase *) mi)->content, mir)) { g_warning ("unable to save mir+cinfo for uid: %s\n", mir->uid); camel_db_camel_mir_free (mir); /* FIXME: Add exception here */ @@ -2152,24 +2756,24 @@ save_to_db_cb (gpointer key, } if (!args->migration) { - if (camel_db_write_message_info_record (cdb, full_name, mir, error) != 0) { - camel_db_camel_mir_free (mir); - return; - } + if (camel_db_write_message_info_record (cdb, full_name, mir, error) != 0) { + camel_db_camel_mir_free (mir); + return; + } } else { - if (camel_db_write_fresh_message_info_record (cdb, CAMEL_DB_IN_MEMORY_TABLE, mir, error) != 0) { - camel_db_camel_mir_free (mir); - return; - } + if (camel_db_write_fresh_message_info_record (cdb, CAMEL_DB_IN_MEMORY_TABLE, mir, error) != 0) { + camel_db_camel_mir_free (mir); + return; + } - if (args->progress > CAMEL_DB_IN_MEMORY_TABLE_LIMIT) { - g_print ("BULK INsert limit reached \n"); - camel_db_flush_in_memory_transactions (cdb, full_name, error); - camel_db_start_in_memory_transactions (cdb, error); - args->progress = 0; - } else { - args->progress++; - } + if (args->progress > CAMEL_DB_IN_MEMORY_TABLE_LIMIT) { + g_print ("BULK INsert limit reached \n"); + camel_db_flush_in_memory_transactions (cdb, full_name, error); + camel_db_start_in_memory_transactions (cdb, error); + args->progress = 0; + } else { + args->progress++; + } } /* Reset the dirty flag which decides if the changes are synced to the DB or not. @@ -2194,8 +2798,8 @@ save_message_infos_to_db (CamelFolderSummary *s, args.migration = fresh_mirs; args.progress = 0; - full_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); + full_name = camel_folder_get_full_name (s->priv->folder); + parent_store = camel_folder_get_parent_store (s->priv->folder); cdb = parent_store->cdb_w; if (camel_db_prepare_message_info_table (cdb, full_name, error) != 0) @@ -2205,12 +2809,11 @@ save_message_infos_to_db (CamelFolderSummary *s, /* Push MessageInfo-es */ camel_db_begin_transaction (cdb, NULL); - g_hash_table_foreach (s->loaded_infos, save_to_db_cb, &args); + g_hash_table_foreach (s->priv->loaded_infos, save_to_db_cb, &args); camel_db_end_transaction (cdb, NULL); camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - /* FIXME[disk-summary] make sure we free the message infos that are loaded - * are freed if not used anymore or should we leave that to the timer? */ + cfs_schedule_info_release_timer (s); return 0; } @@ -2235,7 +2838,7 @@ msg_save_preview (const gchar *uid, * * Since: 2.24 **/ -gint +gboolean camel_folder_summary_save_to_db (CamelFolderSummary *s, GError **error) { @@ -2245,9 +2848,9 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s, gint ret, count; if (!(s->flags & CAMEL_SUMMARY_DIRTY)) - return 0; + return TRUE; - parent_store = camel_folder_get_parent_store (s->folder); + parent_store = camel_folder_get_parent_store (s->priv->folder); cdb = parent_store->cdb_w; d(printf ("\ncamel_folder_summary_save_to_db called \n")); @@ -2255,7 +2858,7 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s, camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); camel_db_begin_transaction (parent_store->cdb_w, NULL); - g_hash_table_foreach (s->priv->preview_updates, (GHFunc) msg_save_preview, s->folder); + g_hash_table_foreach (s->priv->preview_updates, (GHFunc) msg_save_preview, s->priv->folder); g_hash_table_remove_all (s->priv->preview_updates); camel_db_end_transaction (parent_store->cdb_w, NULL); @@ -2272,7 +2875,7 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s, if (ret != 0) { /* Failed, so lets reset the flag */ s->flags |= CAMEL_SUMMARY_DIRTY; - return -1; + return FALSE; } /* XXX So... if an error is set, how do we even reach this point @@ -2281,7 +2884,7 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s, strstr ((*error)->message, "26 columns but 28 values") != NULL) { const gchar *full_name; - full_name = camel_folder_get_full_name (s->folder); + full_name = camel_folder_get_full_name (s->priv->folder); g_warning ("Fixing up a broken summary migration on %s\n", full_name); /* Begin everything again. */ @@ -2292,14 +2895,14 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s, ret = save_message_infos_to_db (s, FALSE, error); if (ret != 0) { s->flags |= CAMEL_SUMMARY_DIRTY; - return -1; + return FALSE; } } record = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->summary_header_to_db (s, error); if (!record) { s->flags |= CAMEL_SUMMARY_DIRTY; - return -1; + return FALSE; } camel_db_begin_transaction (cdb, NULL); @@ -2311,12 +2914,12 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s, if (ret != 0) { camel_db_abort_transaction (cdb, NULL); s->flags |= CAMEL_SUMMARY_DIRTY; - return -1; + return FALSE; } camel_db_end_transaction (cdb, NULL); - return ret; + return ret == 0; } /** @@ -2324,7 +2927,7 @@ camel_folder_summary_save_to_db (CamelFolderSummary *s, * * Since: 2.24 **/ -gint +gboolean camel_folder_summary_header_save_to_db (CamelFolderSummary *s, GError **error) { @@ -2333,14 +2936,14 @@ camel_folder_summary_header_save_to_db (CamelFolderSummary *s, CamelDB *cdb; gint ret; - parent_store = camel_folder_get_parent_store (s->folder); + parent_store = camel_folder_get_parent_store (s->priv->folder); cdb = parent_store->cdb_w; d(printf ("\ncamel_folder_summary_header_save_to_db called \n")); record = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->summary_header_to_db (s, error); if (!record) { - return -1; + return FALSE; } camel_db_begin_transaction (cdb, NULL); @@ -2351,12 +2954,12 @@ camel_folder_summary_header_save_to_db (CamelFolderSummary *s, if (ret != 0) { camel_db_abort_transaction (cdb, NULL); - return -1; + return FALSE; } camel_db_end_transaction (cdb, NULL); - return ret; + return ret == 0; } /** @@ -2364,7 +2967,7 @@ camel_folder_summary_header_save_to_db (CamelFolderSummary *s, * * Since: 2.24 **/ -gint +gboolean camel_folder_summary_header_load_from_db (CamelFolderSummary *s, CamelStore *store, const gchar *folder_name, @@ -2372,22 +2975,21 @@ camel_folder_summary_header_load_from_db (CamelFolderSummary *s, { CamelDB *cdb; CamelFIRecord *record; - gint ret = 0; + gboolean ret = FALSE; - d(printf ("\ncamel_folder_summary_load_from_db called \n")); + d(printf ("\ncamel_folder_summary_header_load_from_db called \n")); camel_folder_summary_save_to_db (s, NULL); cdb = store->cdb_r; record = g_new0 (CamelFIRecord, 1); - camel_db_read_folder_info_record (cdb, folder_name, &record, error); + camel_db_read_folder_info_record (cdb, folder_name, record, error); if (record) { - if (CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->summary_header_from_db (s, record) == -1) - ret = -1; + ret = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->summary_header_from_db (s, record); } else { - ret = -1; + ret = FALSE; } g_free (record->folder_name); @@ -2397,7 +2999,7 @@ camel_folder_summary_header_load_from_db (CamelFolderSummary *s, return ret; } -static gint +static gboolean summary_assign_uid (CamelFolderSummary *s, CamelMessageInfo *info) { @@ -2413,11 +3015,11 @@ summary_assign_uid (CamelFolderSummary *s, camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - while ((mi = g_hash_table_lookup (s->loaded_infos, uid))) { + while ((mi = g_hash_table_lookup (s->priv->loaded_infos, uid))) { camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); if (mi == info) - return 0; + return FALSE; d(printf ("Trying to insert message with clashing uid (%s). new uid re-assigned", camel_message_info_uid (info))); @@ -2430,7 +3032,7 @@ summary_assign_uid (CamelFolderSummary *s, camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - return 1; + return TRUE; } /** @@ -2450,21 +3052,32 @@ void camel_folder_summary_add (CamelFolderSummary *s, CamelMessageInfo *info) { + CamelMessageInfoBase *base_info; + + g_return_if_fail (s != NULL); + g_return_if_fail (s->priv != NULL); + if (info == NULL) return; - if (summary_assign_uid (s, info) == 0) + camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + if (!summary_assign_uid (s, info)) { + camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); return; + } - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + base_info = (CamelMessageInfoBase *) info; + folder_summary_update_counts_by_flags (s, camel_message_info_flags (info), FALSE); + base_info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; + base_info->dirty = TRUE; + + g_hash_table_insert (s->priv->uids, + (gpointer) camel_pstring_strdup (camel_message_info_uid (info)), + GUINT_TO_POINTER (camel_message_info_flags (info))); /* Summary always holds a ref for the loaded infos */ - /* camel_message_info_ref(info); FIXME: Check how things are loaded. */ - /* FIXME[disk-summary] SHould we ref it or redesign it later on */ - /* The uid array should have its own memory. We will unload the infos when not reqd.*/ - g_ptr_array_add (s->uids, (gpointer) camel_pstring_strdup ((camel_message_info_uid (info)))); + g_hash_table_insert (s->priv->loaded_infos, (gpointer) camel_message_info_uid (info), info); - g_hash_table_insert (s->loaded_infos, (gpointer) camel_message_info_uid (info), info); s->flags |= CAMEL_SUMMARY_DIRTY; camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); @@ -2480,92 +3093,32 @@ camel_folder_summary_insert (CamelFolderSummary *s, CamelMessageInfo *info, gboolean load) { + g_return_if_fail (s != NULL); + g_return_if_fail (s->priv != NULL); + if (info == NULL) return; camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - /* Summary always holds a ref for the loaded infos */ - /* camel_message_info_ref(info); FIXME: Check how things are loaded. */ - /* FIXME[disk-summary] SHould we ref it or redesign it later on */ - /* The uid array should have its own memory. We will unload the infos when not reqd.*/ - if (!load) - g_ptr_array_add (s->uids, (gchar *) camel_pstring_strdup (camel_message_info_uid (info))); - - g_hash_table_insert (s->loaded_infos, (gchar *) camel_message_info_uid (info), info); - - if (!load) - s->flags |= CAMEL_SUMMARY_DIRTY; - - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); -} - -/** - * camel_folder_summary_update_counts_by_flags: - * - * Since: 3.0 - **/ -void -camel_folder_summary_update_counts_by_flags (CamelFolderSummary *summary, - guint32 flags, - gboolean subtract) -{ - gint unread = 0, deleted = 0, junk = 0; - gboolean is_junk_folder = FALSE, is_trash_folder = FALSE; + if (!load) { + CamelMessageInfoBase *base_info = (CamelMessageInfoBase *) info; - g_return_if_fail (summary != NULL); + folder_summary_update_counts_by_flags (s, camel_message_info_flags (info), FALSE); + base_info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; + base_info->dirty = TRUE; - if (summary->folder && CAMEL_IS_VTRASH_FOLDER (summary->folder)) { - CamelVTrashFolder *vtrash = CAMEL_VTRASH_FOLDER (summary->folder); + g_hash_table_insert (s->priv->uids, + (gpointer) camel_pstring_strdup (camel_message_info_uid (info)), + GUINT_TO_POINTER (camel_message_info_flags (info))); - is_junk_folder = vtrash && vtrash->type == CAMEL_VTRASH_FOLDER_JUNK; - is_trash_folder = vtrash && vtrash->type == CAMEL_VTRASH_FOLDER_TRASH; + s->flags |= CAMEL_SUMMARY_DIRTY; } - if (!(flags & CAMEL_MESSAGE_SEEN)) - unread = subtract ? -1 : 1; - - if (flags & CAMEL_MESSAGE_DELETED) - deleted = subtract ? -1 : 1; - - if (flags & CAMEL_MESSAGE_JUNK) - junk = subtract ? -1 : 1; - - dd(printf("%p: %d %d %d | %d %d %d \n", (gpointer) summary, unread, deleted, junk, summary->unread_count, summary->visible_count, summary->saved_count)); - - if (deleted) - summary->deleted_count += deleted; - if (junk) - summary->junk_count += junk; - if (junk && !deleted) - summary->junk_not_deleted_count += junk; - if (!junk && !deleted) - summary->visible_count += subtract ? -1 : 1; - - if (junk && !is_junk_folder) - unread = 0; - if (deleted && !is_trash_folder) - unread = 0; - - if (unread) - summary->unread_count += unread; - - summary->saved_count += subtract ? -1 : 1; - camel_folder_summary_touch (summary); - - dd(printf("%p: %d %d %d | %d %d %d\n", (gpointer) summary, unread, deleted, junk, summary->unread_count, summary->visible_count, summary->saved_count)); -} - -static void -update_summary (CamelFolderSummary *summary, - CamelMessageInfoBase *info) -{ - g_return_if_fail (summary != NULL); - g_return_if_fail (info != NULL); + /* Summary always holds a ref for the loaded infos */ + g_hash_table_insert (s->priv->loaded_infos, (gchar *) camel_message_info_uid (info), info); - camel_folder_summary_update_counts_by_flags (summary, info->flags, FALSE); - info->flags |= CAMEL_MESSAGE_FOLDER_FLAGGED; - info->dirty = TRUE; + camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); } /** @@ -2592,7 +3145,6 @@ camel_folder_summary_add_from_header (CamelFolderSummary *summary, info = camel_folder_summary_info_new_from_header (summary, h); camel_folder_summary_add (summary, info); - update_summary (summary, (CamelMessageInfoBase *) info); return info; } @@ -2622,7 +3174,7 @@ camel_folder_summary_add_from_parser (CamelFolderSummary *s, info = camel_folder_summary_info_new_from_parser (s, mp); camel_folder_summary_add (s, info); - update_summary (s, (CamelMessageInfoBase *) info); + return info; } @@ -2642,7 +3194,7 @@ camel_folder_summary_add_from_message (CamelFolderSummary *s, CamelMessageInfo *info = camel_folder_summary_info_new_from_message (s, msg, NULL); camel_folder_summary_add (s, info); - update_summary (s, (CamelMessageInfoBase *) info); + return info; } @@ -2844,103 +3396,55 @@ camel_folder_summary_touch (CamelFolderSummary *s) * * Empty the summary contents. **/ -void -camel_folder_summary_clear (CamelFolderSummary *s) -{ - d(printf ("\ncamel_folder_summary_clearcalled \n")); - s->flags &= ~CAMEL_SUMMARY_DIRTY; - - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - if (camel_folder_summary_count (s) == 0) { - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - return; - } - - g_ptr_array_foreach (s->uids, (GFunc) camel_pstring_free, NULL); - g_ptr_array_free (s->uids, TRUE); - s->uids = g_ptr_array_new (); - s->saved_count = 0; - s->unread_count = 0; - s->deleted_count = 0; - s->junk_count = 0; - s->junk_not_deleted_count = 0; - s->visible_count = 0; - - g_hash_table_destroy (s->loaded_infos); - s->loaded_infos = g_hash_table_new (g_str_hash, g_str_equal); - - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); -} - -/** - * camel_folder_summary_clear_db: - * - * Since: 2.24 - **/ -void -camel_folder_summary_clear_db (CamelFolderSummary *s) +gboolean +camel_folder_summary_clear (CamelFolderSummary *s, GError **error) { + GObject *summary_object; CamelStore *parent_store; CamelDB *cdb; const gchar *folder_name; + gboolean res; - /* FIXME: This is non-sense. Neither an exception is passed, - nor a value returned. How is the caller supposed to know, - whether the operation is succesful */ - - d(printf ("\ncamel_folder_summary_load_from_db called \n")); - s->flags &= ~CAMEL_SUMMARY_DIRTY; - - folder_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); - cdb = parent_store->cdb_w; + g_return_val_if_fail (s != NULL, FALSE); + g_return_val_if_fail (s->priv != NULL, FALSE); camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); if (camel_folder_summary_count (s) == 0) { camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - return; + return TRUE; } - g_ptr_array_foreach (s->uids, (GFunc) camel_pstring_free, NULL); - g_ptr_array_free (s->uids, TRUE); - s->uids = g_ptr_array_new (); - s->saved_count = 0; - s->unread_count = 0; - s->deleted_count = 0; - s->junk_count = 0; - s->junk_not_deleted_count = 0; - s->visible_count = 0; - - g_hash_table_destroy (s->loaded_infos); - s->loaded_infos = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_remove_all (s->priv->uids); + g_hash_table_remove_all (s->priv->loaded_infos); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + s->priv->saved_count = 0; + s->priv->unread_count = 0; + s->priv->deleted_count = 0; + s->priv->junk_count = 0; + s->priv->junk_not_deleted_count = 0; + s->priv->visible_count = 0; - camel_db_clear_folder_summary (cdb, folder_name, NULL); -} + camel_folder_summary_touch (s); -/* This function returns 0 on success. So the caller should not bother, - * deleting the uid from db when the return value is non-zero */ -static gint -summary_remove_uid (CamelFolderSummary *s, - const gchar *uid) -{ - gint i; + folder_name = camel_folder_get_full_name (s->priv->folder); + parent_store = camel_folder_get_parent_store (s->priv->folder); + cdb = parent_store->cdb_w; - d(printf ("\nsummary_remove_uid called \n")); + res = camel_db_clear_folder_summary (cdb, folder_name, error) == 0; - /* This could be slower, but no otherway really. FIXME: Callers have to effective and shouldn't call it recursively. */ - for (i = 0; i < s->uids->len; i++) { - if (strcmp (s->uids->pdata[i], uid) == 0) { - /* FIXME: Does using fast remove affect anything ? */ - g_ptr_array_remove_index (s->uids, i); - camel_pstring_free (uid); - return 0; - } + summary_object = G_OBJECT (s); + g_object_freeze_notify (summary_object); + g_object_notify (summary_object, "saved-count"); + g_object_notify (summary_object, "unread-count"); + g_object_notify (summary_object, "deleted-count"); + g_object_notify (summary_object, "junk-count"); + g_object_notify (summary_object, "junk-not-deleted-count"); + g_object_notify (summary_object, "visible-count"); + g_object_thaw_notify (summary_object); - } + camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - return -1; + return res; } /** @@ -2949,34 +3453,23 @@ summary_remove_uid (CamelFolderSummary *s, * @info: a #CamelMessageInfo * * Remove a specific @info record from the summary. + * + * Returns: Whether the @info was found and removed from the @summary. **/ -void +gboolean camel_folder_summary_remove (CamelFolderSummary *s, CamelMessageInfo *info) { - CamelStore *parent_store; - const gchar *full_name; - gboolean found; - gint ret; - - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - - found = g_hash_table_lookup (s->loaded_infos, camel_message_info_uid (info)) != NULL; - g_hash_table_remove (s->loaded_infos, camel_message_info_uid (info)); - ret = summary_remove_uid (s, camel_message_info_uid (info)); - - s->flags |= CAMEL_SUMMARY_DIRTY; - s->meta_summary->msg_expunged = TRUE; - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - - full_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); - - if (!ret && camel_db_delete_uid (parent_store->cdb_w, full_name, camel_message_info_uid (info), NULL) != 0) - return; + g_return_val_if_fail (s != NULL, FALSE); + g_return_val_if_fail (s->priv != NULL, FALSE); + g_return_val_if_fail (info != NULL, FALSE); - if (found) + if (camel_folder_summary_remove_uid (s, camel_message_info_uid (info))) { camel_message_info_free (info); + return TRUE; + } + + return FALSE; } /** @@ -2985,193 +3478,45 @@ camel_folder_summary_remove (CamelFolderSummary *s, * @uid: a uid * * Remove a specific info record from the summary, by @uid. + * + * Returns: Whether the @uid was found and removed from the @summary. **/ -void +gboolean camel_folder_summary_remove_uid (CamelFolderSummary *s, const gchar *uid) { - CamelMessageInfo *oldinfo; - gchar *olduid; - - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK); - if (g_hash_table_lookup_extended (s->loaded_infos, uid, (gpointer) &olduid, (gpointer) &oldinfo)) { - /* make sure it doesn't vanish while we're removing it */ - camel_message_info_ref (oldinfo); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - camel_folder_summary_remove (s, oldinfo); - camel_message_info_free (oldinfo); - } else { - CamelStore *parent_store; - const gchar *full_name; - gchar *tmpid = g_strdup (uid); - gint ret; - /* Info isn't loaded into the memory. We must just remove the UID*/ - ret = summary_remove_uid (s, uid); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - - full_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); - if (!ret && camel_db_delete_uid (parent_store->cdb_w, full_name, tmpid, NULL) != 0) { - g_free (tmpid); - return; - } - g_free (tmpid); - } -} - -/* _fast doesn't deal with db and leaves it to the caller. */ - -/** - * camel_folder_summary_remove_uid_fast: - * - * Since: 2.24 - **/ -void -camel_folder_summary_remove_uid_fast (CamelFolderSummary *s, - const gchar *uid) -{ - CamelMessageInfo *oldinfo; - gchar *olduid; - - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK); - if (g_hash_table_lookup_extended (s->loaded_infos, uid, (gpointer) &olduid, (gpointer) &oldinfo)) { - /* make sure it doesn't vanish while we're removing it */ - camel_message_info_ref (oldinfo); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK); - g_hash_table_remove (s->loaded_infos, olduid); - summary_remove_uid (s, olduid); - s->flags |= CAMEL_SUMMARY_DIRTY; - s->meta_summary->msg_expunged = TRUE; - camel_message_info_free (oldinfo); - camel_message_info_free (oldinfo); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - } else { - gchar *tmpid = g_strdup (uid); - /* Info isn't loaded into the memory. We must just remove the UID*/ - summary_remove_uid (s, uid); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - g_free (tmpid); - } -} + gpointer ptr_uid = NULL, ptr_flags = NULL; + CamelStore *parent_store; + const gchar *full_name; + const gchar *uid_copy; + gboolean res = TRUE; -/** - * camel_folder_summary_remove_index_fast: - * - * Since: 2.24 - **/ -void -camel_folder_summary_remove_index_fast (CamelFolderSummary *s, - gint index) -{ - const gchar *uid = s->uids->pdata[index]; - CamelMessageInfo *oldinfo; - gchar *olduid; + g_return_val_if_fail (s != NULL, FALSE); + g_return_val_if_fail (s->priv != NULL, FALSE); + g_return_val_if_fail (uid != NULL, FALSE); camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK); - - if (g_hash_table_lookup_extended (s->loaded_infos, uid, (gpointer) &olduid, (gpointer) &oldinfo)) { - /* make sure it doesn't vanish while we're removing it */ - g_hash_table_remove (s->loaded_infos, uid); - camel_pstring_free (uid); - g_ptr_array_remove_index (s->uids, index); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - camel_message_info_free (oldinfo); - } else { - /* Info isn't loaded into the memory. We must just remove the UID*/ - g_ptr_array_remove_index (s->uids, index); - camel_pstring_free (uid); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_REF_LOCK); + if (!g_hash_table_lookup_extended (s->priv->uids, uid, &ptr_uid, &ptr_flags)) { camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + return FALSE; } -} - -/** - * camel_folder_summary_remove_index: - * @summary: a #CamelFolderSummary object - * @index: record index - * - * Remove a specific info record from the summary, by index. - **/ -void -camel_folder_summary_remove_index (CamelFolderSummary *s, - gint index) -{ - const gchar *uid = s->uids->pdata[index]; - - camel_folder_summary_remove_uid (s, uid); -} - -/** - * camel_folder_summary_remove_range: - * @summary: a #CamelFolderSummary object - * @start: initial index - * @end: last index to remove - * - * Removes an indexed range of info records. - **/ -void -camel_folder_summary_remove_range (CamelFolderSummary *s, - gint start, - gint end) -{ - d(g_print ("\ncamel_folder_summary_remove_range called \n")); - if (end < start) - return; - - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - - if (start < s->uids->len) { - - gint i; - CamelDB *cdb; - CamelStore *parent_store; - const gchar *folder_name; - GList *uids = NULL; - - end = MIN (end + 1, s->uids->len); - - for (i = start; i < end; i++) { - const gchar *uid = s->uids->pdata[i]; - gpointer olduid, oldinfo; - - /* the uid will be freed below and will not be used because of changing size of the s->uids array */ - uids = g_list_prepend (uids, (gpointer) uid); - - if (g_hash_table_lookup_extended (s->loaded_infos, uid, &olduid, &oldinfo)) { - camel_message_info_free (oldinfo); - g_hash_table_remove (s->loaded_infos, uid); - } - } - folder_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); - cdb = parent_store->cdb_w; + folder_summary_update_counts_by_flags (s, GPOINTER_TO_UINT (ptr_flags), TRUE); - /* FIXME[disk-summary] lifecycle of infos should be checked. - * Add should add to db and del should del to db. Sync only - * the changes at interval and remove those full sync on - * folder switch */ - camel_db_delete_uids (cdb, folder_name, uids, NULL); + uid_copy = camel_pstring_strdup (uid); + g_hash_table_remove (s->priv->uids, uid_copy); + g_hash_table_remove (s->priv->loaded_infos, uid_copy); - g_list_foreach (uids, (GFunc) camel_pstring_free, NULL); - g_list_free (uids); + full_name = camel_folder_get_full_name (s->priv->folder); + parent_store = camel_folder_get_parent_store (s->priv->folder); + if (camel_db_delete_uid (parent_store->cdb_w, full_name, uid_copy, NULL) != 0) + res = FALSE; - memmove (s->uids->pdata + start, s->uids->pdata + end, (s->uids->len - end) * sizeof (s->uids->pdata[0])); - g_ptr_array_set_size (s->uids, s->uids->len - (end - start)); + camel_pstring_free (uid_copy); - s->flags |= CAMEL_SUMMARY_DIRTY; + camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - } else { - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - } + return res; } /* should be sorted, for binary search */ @@ -3366,7 +3711,7 @@ static gint summary_header_load (CamelFolderSummary *s, FILE *in) { - if (!s->summary_path) + if (!s->priv->summary_path) return -1; fseek (in, 0, SEEK_SET); @@ -3391,17 +3736,17 @@ summary_header_load (CamelFolderSummary *s, /* legacy version */ if (camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->flags) == -1 - || camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->nextuid) == -1 + || camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->priv->nextuid) == -1 || camel_file_util_decode_time_t (in, &s->time) == -1 - || camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->saved_count) == -1) { + || camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->priv->saved_count) == -1) { return -1; } /* version 13 */ if (s->version < 0x100 && s->version >= 13 - && (camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->unread_count) == -1 - || camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->deleted_count) == -1 - || camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->junk_count) == -1)) { + && (camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->priv->unread_count) == -1 + || camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->priv->deleted_count) == -1 + || camel_file_util_decode_fixed_int32 (in, (gint32 *) &s->priv->junk_count) == -1)) { return -1; } @@ -3746,8 +4091,12 @@ message_info_free (CamelFolderSummary *s, CamelMessageInfoBase *mi = (CamelMessageInfoBase *) info; if (mi->uid) { - if (s && g_hash_table_lookup (s->loaded_infos, mi->uid) == mi) { - g_hash_table_remove (s->loaded_infos, mi->uid); + if (s) { + camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); + if (g_hash_table_lookup (s->priv->loaded_infos, mi->uid) == mi) { + g_hash_table_remove (s->priv->loaded_infos, mi->uid); + } + camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); } camel_pstring_free (mi->uid); } @@ -3890,7 +4239,7 @@ summary_build_content_info (CamelFolderSummary *s, /* start of this part */ state = camel_mime_parser_step (mp, &buffer, &len); - if (s->build_content) + if (s->priv->build_content) info = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->content_info_new_from_parser (s, mp); switch (state) { @@ -4049,7 +4398,7 @@ summary_build_content_info_message (CamelFolderSummary *s, CamelContentType *ct; const struct _camel_header_raw *header; - if (s->build_content) + if (s->priv->build_content) info = CAMEL_FOLDER_SUMMARY_GET_CLASS (s)->content_info_new_from_message (s, object); containee = camel_medium_get_content (CAMEL_MEDIUM (object)); @@ -4619,7 +4968,7 @@ camel_message_info_free (gpointer o) camel_folder_summary_unlock (mi->summary, CAMEL_FOLDER_SUMMARY_REF_LOCK); /* FIXME: this is kinda busted, should really be handled by message info free */ - if (mi->summary->build_content + if (mi->summary->priv->build_content && ((CamelMessageInfoBase *) mi)->content) { camel_folder_summary_content_info_free (mi->summary, ((CamelMessageInfoBase *) mi)->content); } @@ -4863,29 +5212,6 @@ camel_message_info_dump (CamelMessageInfo *mi) camel_content_info_dump (((CamelMessageInfoBase *) mi)->content, 0); } -/** - * camel_folder_summary_set_need_preview: - * - * Since: 2.28 - **/ -void -camel_folder_summary_set_need_preview (CamelFolderSummary *summary, - gboolean preview) -{ - summary->priv->need_preview = preview; -} - -/** - * camel_folder_summary_get_need_preview: - * - * Since: 2.28 - **/ -gboolean -camel_folder_summary_get_need_preview (CamelFolderSummary *summary) -{ - return summary->priv->need_preview; -} - static gboolean compare_strings (const gchar *str1, const gchar *str2) @@ -5063,4 +5389,3 @@ bdata_extract_string (/* const */ gchar **part) return val; } - diff --git a/camel/camel-folder-summary.h b/camel/camel-folder-summary.h index aaba7ae..01a795b 100644 --- a/camel/camel-folder-summary.h +++ b/camel/camel-folder-summary.h @@ -65,8 +65,6 @@ typedef struct _CamelFolderSummaryPrivate CamelFolderSummaryPrivate; typedef struct _CamelMessageInfo CamelMessageInfo; typedef struct _CamelMessageInfoBase CamelMessageInfoBase; -typedef struct _CamelFolderMetaSummary CamelFolderMetaSummary; - typedef struct _CamelMessageContentInfo CamelMessageContentInfo; /* A tree of message content info structures @@ -239,31 +237,8 @@ struct _CamelFolderSummary { /* header info */ guint32 version; /* version of file loaded/loading */ - CamelFolderSummaryFlags flags; - guint32 nextuid; /* next uid? */ time_t time; /* timestamp for this summary (for implementors to use) */ - guint32 saved_count; /* how many were saved/loaded */ - guint32 unread_count; /* handy totals */ - guint32 deleted_count; - guint32 junk_count; - guint32 junk_not_deleted_count; - guint32 visible_count; - - /* memory allocators (setup automatically) */ - CamelMemChunk *message_info_chunks; - CamelMemChunk *content_info_chunks; - - gchar *summary_path; - gboolean build_content; /* do we try and parse/index the content, or not? */ - - /* New members to replace the above depreacted members */ - GPtrArray *uids; - GHashTable *loaded_infos; - - struct _CamelFolder *folder; /* parent folder, for events */ - struct _CamelFolderMetaSummary *meta_summary; /* Meta summary */ - time_t cache_load_time; - guint timeout_handle; + CamelFolderSummaryFlags flags; const gchar *collate; const gchar *sort_by; @@ -287,12 +262,12 @@ struct _CamelFolderSummaryClass { gint (*summary_header_save)(CamelFolderSummary *, FILE *); /* Load/Save folder summary from DB*/ - gint (*summary_header_from_db)(CamelFolderSummary *, struct _CamelFIRecord *); + gboolean (*summary_header_from_db)(CamelFolderSummary *, struct _CamelFIRecord *); struct _CamelFIRecord * (*summary_header_to_db)(CamelFolderSummary *, GError **error); CamelMessageInfo * (*message_info_from_db) (CamelFolderSummary *, struct _CamelMIRecord *); struct _CamelMIRecord * (*message_info_to_db) (CamelFolderSummary *, CamelMessageInfo *); CamelMessageContentInfo * (*content_info_from_db) (CamelFolderSummary *, struct _CamelMIRecord *); - gint (*content_info_to_db) (CamelFolderSummary *, CamelMessageContentInfo *, struct _CamelMIRecord *); + gboolean (*content_info_to_db) (CamelFolderSummary *, CamelMessageContentInfo *, struct _CamelMIRecord *); /* create/save/load an individual message info */ CamelMessageInfo * (*message_info_new_from_header)(CamelFolderSummary *, struct _camel_header_raw *); @@ -326,126 +301,204 @@ struct _CamelFolderSummaryClass { gboolean (*info_set_flags)(CamelMessageInfo *mi, guint32 mask, guint32 set); }; -/* Meta-summary info */ -struct _CamelFolderMetaSummary { - guint32 major; /* Major version of meta-summary */ - guint32 minor; /* Minor version of meta-summary */ - guint32 uid_len; /* Length of UID (for implementors to use) */ - gboolean msg_expunged; /* Whether any message is expunged or not */ - gchar *path; /* Path to meta-summary-file */ -}; - -GType camel_folder_summary_get_type (void); -CamelFolderSummary *camel_folder_summary_new (struct _CamelFolder *folder); - -/* Deprecated */ -void camel_folder_summary_set_filename (CamelFolderSummary *summary, const gchar *filename); - -void camel_folder_summary_set_index (CamelFolderSummary *summary, CamelIndex *index); -void camel_folder_summary_set_build_content (CamelFolderSummary *summary, gboolean state); - -guint32 camel_folder_summary_next_uid (CamelFolderSummary *summary); -gchar *camel_folder_summary_next_uid_string (CamelFolderSummary *summary); -void camel_folder_summary_set_uid (CamelFolderSummary *summary, guint32 uid); +GType camel_folder_summary_get_type (void); +CamelFolderSummary * camel_folder_summary_new (struct _CamelFolder *folder); + +struct _CamelFolder * camel_folder_summary_get_folder (CamelFolderSummary *summary); +CamelFolderSummaryFlags camel_folder_summary_get_flags (CamelFolderSummary *summary); + +guint32 camel_folder_summary_get_saved_count + (CamelFolderSummary *summary); +guint32 camel_folder_summary_get_unread_count + (CamelFolderSummary *summary); +guint32 camel_folder_summary_get_deleted_count + (CamelFolderSummary *summary); +guint32 camel_folder_summary_get_junk_count + (CamelFolderSummary *summary); +guint32 camel_folder_summary_get_junk_not_deleted_count + (CamelFolderSummary *summary); +guint32 camel_folder_summary_get_visible_count + (CamelFolderSummary *summary); + +void camel_folder_summary_set_index (CamelFolderSummary *summary, + CamelIndex *index); +CamelIndex * camel_folder_summary_get_index (CamelFolderSummary *summary); +void camel_folder_summary_set_build_content + (CamelFolderSummary *summary, + gboolean state); +gboolean camel_folder_summary_get_build_content + (CamelFolderSummary *summary); +void camel_folder_summary_set_need_preview + (CamelFolderSummary *summary, + gboolean preview); +gboolean camel_folder_summary_get_need_preview + (CamelFolderSummary *summary); +guint32 camel_folder_summary_next_uid (CamelFolderSummary *summary); +void camel_folder_summary_set_next_uid + (CamelFolderSummary *summary, + guint32 uid); +guint32 camel_folder_summary_get_next_uid + (CamelFolderSummary *summary); +gchar * camel_folder_summary_next_uid_string + (CamelFolderSummary *summary); /* load/save the full summary from/to the db */ -gint camel_folder_summary_save_to_db (CamelFolderSummary *s, GError **error); -gint camel_folder_summary_load_from_db (CamelFolderSummary *s, GError **error); +gboolean camel_folder_summary_save_to_db (CamelFolderSummary *s, + GError **error); +gboolean camel_folder_summary_load_from_db + (CamelFolderSummary *s, + GError **error); /* only load the header */ -gint camel_folder_summary_header_load_from_db (CamelFolderSummary *s, struct _CamelStore *store, const gchar *folder_name, GError **error); -gint camel_folder_summary_header_save_to_db (CamelFolderSummary *s, GError **error); +gboolean camel_folder_summary_header_load_from_db + (CamelFolderSummary *s, + struct _CamelStore *store, + const gchar *folder_name, + GError **error); +gboolean camel_folder_summary_header_save_to_db + (CamelFolderSummary *s, + GError **error); /* set the dirty bit on the summary */ -void camel_folder_summary_touch (CamelFolderSummary *summary); +void camel_folder_summary_touch (CamelFolderSummary *summary); -/* add a new raw summary item */ -void camel_folder_summary_add (CamelFolderSummary *summary, CamelMessageInfo *info); +/* Just build raw summary items */ +CamelMessageInfo * camel_folder_summary_info_new_from_header + (CamelFolderSummary *summary, + struct _camel_header_raw *headers); +CamelMessageInfo * camel_folder_summary_info_new_from_parser + (CamelFolderSummary *summary, + CamelMimeParser *parser); +CamelMessageInfo * camel_folder_summary_info_new_from_message + (CamelFolderSummary *summary, + CamelMimeMessage *message, + const gchar *bodystructure); + +CamelMessageContentInfo *camel_folder_summary_content_info_new + (CamelFolderSummary *summary); +void camel_folder_summary_content_info_free + (CamelFolderSummary *summary, + CamelMessageContentInfo *ci); + +void camel_folder_summary_add_preview + (CamelFolderSummary *s, + CamelMessageInfo *info); -/* Peek from mem only */ -CamelMessageInfo * camel_folder_summary_peek_info (CamelFolderSummary *s, const gchar *uid); +/* Migration code */ +gint camel_folder_summary_migrate_infos + (CamelFolderSummary *s); + +/* build/add raw summary items */ +CamelMessageInfo * camel_folder_summary_add_from_header + (CamelFolderSummary *summary, + struct _camel_header_raw *headers); +CamelMessageInfo * camel_folder_summary_add_from_parser + (CamelFolderSummary *summary, + CamelMimeParser *parser); +CamelMessageInfo * camel_folder_summary_add_from_message + (CamelFolderSummary *summary, + CamelMimeMessage *message); + +/* add a new raw summary item */ +void camel_folder_summary_add (CamelFolderSummary *summary, + CamelMessageInfo *info); -/* Get only the uids of dirty/changed things to sync to server/db */ -GPtrArray * camel_folder_summary_get_changed (CamelFolderSummary *s); -/* reload the summary at any required point if required */ -void camel_folder_summary_prepare_fetch_all (CamelFolderSummary *s, GError **error); /* insert mi to summary */ -void camel_folder_summary_insert (CamelFolderSummary *s, CamelMessageInfo *info, gboolean load); +void camel_folder_summary_insert (CamelFolderSummary *s, + CamelMessageInfo *info, + gboolean load); -void camel_folder_summary_remove_index_fast (CamelFolderSummary *s, gint index); -void camel_folder_summary_remove_uid_fast (CamelFolderSummary *s, const gchar *uid); +gboolean camel_folder_summary_remove (CamelFolderSummary *summary, + CamelMessageInfo *info); -/* build/add raw summary items */ -CamelMessageInfo *camel_folder_summary_add_from_header (CamelFolderSummary *summary, struct _camel_header_raw *headers); -CamelMessageInfo *camel_folder_summary_add_from_parser (CamelFolderSummary *summary, CamelMimeParser *parser); -CamelMessageInfo *camel_folder_summary_add_from_message (CamelFolderSummary *summary, CamelMimeMessage *message); +gboolean camel_folder_summary_remove_uid (CamelFolderSummary *summary, + const gchar *uid); -/* Just build raw summary items */ -CamelMessageInfo *camel_folder_summary_info_new_from_header (CamelFolderSummary *summary, struct _camel_header_raw *headers); -CamelMessageInfo *camel_folder_summary_info_new_from_parser (CamelFolderSummary *summary, CamelMimeParser *parser); -CamelMessageInfo *camel_folder_summary_info_new_from_message (CamelFolderSummary *summary, CamelMimeMessage *message, const gchar *bodystructure); +/* remove all items */ +gboolean camel_folder_summary_clear (CamelFolderSummary *summary, + GError **error); -CamelMessageContentInfo *camel_folder_summary_content_info_new (CamelFolderSummary *summary); -void camel_folder_summary_content_info_free (CamelFolderSummary *summary, CamelMessageContentInfo *ci); +/* lookup functions */ +guint camel_folder_summary_count (CamelFolderSummary *summary); -/* removes a summary item, doesn't fix content offsets */ -void camel_folder_summary_remove (CamelFolderSummary *summary, CamelMessageInfo *info); -void camel_folder_summary_remove_uid (CamelFolderSummary *summary, const gchar *uid); -void camel_folder_summary_remove_index (CamelFolderSummary *summary, gint index); -void camel_folder_summary_remove_range (CamelFolderSummary *summary, gint start, gint end); +gboolean camel_folder_summary_check_uid (CamelFolderSummary *s, + const gchar *uid); +CamelMessageInfo * camel_folder_summary_get (CamelFolderSummary *summary, + const gchar *uid); +GPtrArray * camel_folder_summary_get_array (CamelFolderSummary *summary); +void camel_folder_summary_free_array (GPtrArray *array); -/* remove all items */ -void camel_folder_summary_clear (CamelFolderSummary *summary); -void camel_folder_summary_clear_db (CamelFolderSummary *s); +/* Peek from mem only */ +CamelMessageInfo * camel_folder_summary_peek_loaded + (CamelFolderSummary *s, + const gchar *uid); -/* update visible/unread/... counts based on message flags */ -void camel_folder_summary_update_counts_by_flags (CamelFolderSummary *summary, guint32 flags, gboolean subtract); +/* Get only the uids of dirty/changed things to sync to server/db */ +GPtrArray * camel_folder_summary_get_changed + (CamelFolderSummary *s); -/* lookup functions */ -guint camel_folder_summary_count (CamelFolderSummary *summary); -CamelMessageInfo *camel_folder_summary_index (CamelFolderSummary *summary, gint index); -CamelMessageInfo *camel_folder_summary_uid (CamelFolderSummary *summary, const gchar *uid); -gchar * camel_folder_summary_uid_from_index (CamelFolderSummary *s, gint i); -gboolean camel_folder_summary_check_uid (CamelFolderSummary *s, const gchar *uid); +/* reload the summary at any required point if required */ +void camel_folder_summary_prepare_fetch_all + (CamelFolderSummary *s, + GError **error); -GPtrArray *camel_folder_summary_array (CamelFolderSummary *summary); -GHashTable *camel_folder_summary_get_hashtable (CamelFolderSummary *s); -void camel_folder_summary_free_hashtable (GHashTable *ht); +/* summary locking */ +void camel_folder_summary_lock (CamelFolderSummary *summary, + CamelFolderSummaryLock lock); +void camel_folder_summary_unlock (CamelFolderSummary *summary, + CamelFolderSummaryLock lock); /* basically like strings, but certain keywords can be compressed and de-cased */ -gint camel_folder_summary_encode_token (FILE *out, const gchar *str); -gint camel_folder_summary_decode_token (FILE *in, gchar **str); +gint camel_folder_summary_encode_token + (FILE *out, + const gchar *str); +gint camel_folder_summary_decode_token + (FILE *in, + gchar **str); /* message flag operations */ -gboolean camel_flag_get (CamelFlag **list, const gchar *name); -gboolean camel_flag_set (CamelFlag **list, const gchar *name, gboolean value); -gboolean camel_flag_list_copy (CamelFlag **to, CamelFlag **from); -gint camel_flag_list_size (CamelFlag **list); -void camel_flag_list_free (CamelFlag **list); - -CamelMessageFlags - camel_system_flag (const gchar *name); -gboolean camel_system_flag_get (CamelMessageFlags flags, const gchar *name); +gboolean camel_flag_get (CamelFlag **list, + const gchar *name); +gboolean camel_flag_set (CamelFlag **list, + const gchar *name, + gboolean value); +gboolean camel_flag_list_copy (CamelFlag **to, + CamelFlag **from); +gint camel_flag_list_size (CamelFlag **list); +void camel_flag_list_free (CamelFlag **list); + +CamelMessageFlags camel_system_flag (const gchar *name); +gboolean camel_system_flag_get (CamelMessageFlags flags, + const gchar *name); /* message tag operations */ -const gchar *camel_tag_get (CamelTag **list, const gchar *name); -gboolean camel_tag_set (CamelTag **list, const gchar *name, const gchar *value); -gboolean camel_tag_list_copy (CamelTag **to, CamelTag **from); -gint camel_tag_list_size (CamelTag **list); -void camel_tag_list_free (CamelTag **list); +const gchar * camel_tag_get (CamelTag **list, + const gchar *name); +gboolean camel_tag_set (CamelTag **list, + const gchar *name, + const gchar *value); +gboolean camel_tag_list_copy (CamelTag **to, + CamelTag **from); +gint camel_tag_list_size (CamelTag **list); +void camel_tag_list_free (CamelTag **list); /* Summary may be null */ /* Use anonymous pointers to avoid tons of cast crap */ -gpointer camel_message_info_new (CamelFolderSummary *summary); -gpointer camel_message_info_ref (gpointer info); -CamelMessageInfo *camel_message_info_new_from_header (CamelFolderSummary *summary, struct _camel_header_raw *header); -void camel_message_info_free (gpointer info); -gpointer camel_message_info_clone (gconstpointer info); +gpointer camel_message_info_new (CamelFolderSummary *summary); +gpointer camel_message_info_ref (gpointer info); +CamelMessageInfo * camel_message_info_new_from_header + (CamelFolderSummary *summary, + struct _camel_header_raw *header); +void camel_message_info_free (gpointer info); +gpointer camel_message_info_clone (gconstpointer info); /* accessors */ -gconstpointer camel_message_info_ptr (const CamelMessageInfo *mi, gint id); -guint32 camel_message_info_uint32 (const CamelMessageInfo *mi, gint id); -time_t camel_message_info_time (const CamelMessageInfo *mi, gint id); +gconstpointer camel_message_info_ptr (const CamelMessageInfo *mi, + gint id); +guint32 camel_message_info_uint32 (const CamelMessageInfo *mi, + gint id); +time_t camel_message_info_time (const CamelMessageInfo *mi, + gint id); #define camel_message_info_uid(mi) ((const gchar *)((const CamelMessageInfo *)mi)->uid) @@ -497,33 +550,37 @@ time_t camel_message_info_time (const CamelMessageInfo *mi, gint id); **/ #define camel_message_info_content(mi) ((const CamelMessageContentInfo *)camel_message_info_ptr((const CamelMessageInfo *)mi, CAMEL_MESSAGE_INFO_CONTENT)) -gboolean camel_message_info_user_flag (const CamelMessageInfo *mi, const gchar *id); -const gchar *camel_message_info_user_tag (const CamelMessageInfo *mi, const gchar *id); - -gboolean camel_message_info_set_flags (CamelMessageInfo *mi, CamelMessageFlags flags, guint32 set); -gboolean camel_message_info_set_user_flag (CamelMessageInfo *mi, const gchar *id, gboolean state); -gboolean camel_message_info_set_user_tag (CamelMessageInfo *mi, const gchar *id, const gchar *val); - -void camel_folder_summary_set_need_preview (CamelFolderSummary *summary, gboolean preview); -void camel_folder_summary_add_preview (CamelFolderSummary *s, CamelMessageInfo *info); -gboolean camel_folder_summary_get_need_preview (CamelFolderSummary *summary); +gboolean camel_message_info_user_flag (const CamelMessageInfo *mi, + const gchar *id); +const gchar * camel_message_info_user_tag (const CamelMessageInfo *mi, + const gchar *id); + +gboolean camel_message_info_set_flags (CamelMessageInfo *mi, + CamelMessageFlags flags, + guint32 set); +gboolean camel_message_info_set_user_flag + (CamelMessageInfo *mi, + const gchar *id, + gboolean state); +gboolean camel_message_info_set_user_tag (CamelMessageInfo *mi, + const gchar *id, + const gchar *val); const CamelMessageContentInfo * camel_folder_summary_guess_content_info (CamelMessageInfo *mi, CamelContentType *ctype); -/* debugging functions */ -void camel_content_info_dump (CamelMessageContentInfo *ci, gint depth); - -void camel_message_info_dump (CamelMessageInfo *mi); - -/* Migration code */ -gint camel_folder_summary_migrate_infos (CamelFolderSummary *s); +/* Deprecated */ +void camel_folder_summary_set_filename + (CamelFolderSummary *summary, + const gchar *filename); -void camel_folder_summary_lock (CamelFolderSummary *summary, CamelFolderSummaryLock lock); -void camel_folder_summary_unlock (CamelFolderSummary *summary, CamelFolderSummaryLock lock); +/* debugging functions */ +void camel_content_info_dump (CamelMessageContentInfo *ci, + gint depth); +void camel_message_info_dump (CamelMessageInfo *mi); /* utility functions for bdata string decomposition */ -gint bdata_extract_digit (/* const */ gchar **part); -gchar *bdata_extract_string (/* const */ gchar **part); +gint bdata_extract_digit (/* const */ gchar **part); +gchar * bdata_extract_string (/* const */ gchar **part); G_END_DECLS diff --git a/camel/camel-folder-thread.c b/camel/camel-folder-thread.c index 0c3f9b9..d8d5586 100644 --- a/camel/camel-folder-thread.c +++ b/camel/camel-folder-thread.c @@ -620,7 +620,7 @@ camel_folder_thread_messages_new (CamelFolder *folder, { CamelFolderThread *thread; GPtrArray *summary; - GPtrArray *fsummary; + GPtrArray *fsummary = NULL; gint i; thread = g_malloc (sizeof (*thread)); @@ -631,12 +631,13 @@ camel_folder_thread_messages_new (CamelFolder *folder, thread->folder = g_object_ref (folder); camel_folder_summary_prepare_fetch_all (folder->summary, NULL); - fsummary = camel_folder_summary_array (folder->summary); thread->summary = summary = g_ptr_array_new (); /* prefer given order from the summary order */ - if (!uids) + if (!uids) { + fsummary = camel_folder_summary_get_array (folder->summary); uids = fsummary; + } for (i = 0; i < uids->len; i++) { CamelMessageInfo *info; @@ -648,7 +649,8 @@ camel_folder_thread_messages_new (CamelFolder *folder, /* FIXME: Check if the info is leaking */ } - camel_folder_free_summary (folder, fsummary); + if (fsummary) + camel_folder_summary_free_array (fsummary); thread_summary (thread, summary); diff --git a/camel/camel-folder.c b/camel/camel-folder.c index 549f15e..015d621 100644 --- a/camel/camel-folder.c +++ b/camel/camel-folder.c @@ -528,7 +528,6 @@ folder_dispose (GObject *object) } if (folder->summary) { - folder->summary->folder = NULL; g_object_unref (folder->summary); folder->summary = NULL; } @@ -580,7 +579,7 @@ folder_get_message_flags (CamelFolder *folder, g_return_val_if_fail (folder->summary != NULL, 0); - info = camel_folder_summary_uid (folder->summary, uid); + info = camel_folder_summary_get (folder->summary, uid); if (info == NULL) return 0; @@ -601,7 +600,7 @@ folder_set_message_flags (CamelFolder *folder, g_return_val_if_fail (folder->summary != NULL, FALSE); - info = camel_folder_summary_uid (folder->summary, uid); + info = camel_folder_summary_get (folder->summary, uid); if (info == NULL) return FALSE; @@ -621,7 +620,7 @@ folder_get_message_user_flag (CamelFolder *folder, g_return_val_if_fail (folder->summary != NULL, FALSE); - info = camel_folder_summary_uid (folder->summary, uid); + info = camel_folder_summary_get (folder->summary, uid); if (info == NULL) return FALSE; @@ -641,7 +640,7 @@ folder_set_message_user_flag (CamelFolder *folder, g_return_if_fail (folder->summary != NULL); - info = camel_folder_summary_uid (folder->summary, uid); + info = camel_folder_summary_get (folder->summary, uid); if (info == NULL) return; @@ -659,7 +658,7 @@ folder_get_message_user_tag (CamelFolder *folder, g_return_val_if_fail (folder->summary != NULL, NULL); - info = camel_folder_summary_uid (folder->summary, uid); + info = camel_folder_summary_get (folder->summary, uid); if (info == NULL) return NULL; @@ -679,7 +678,7 @@ folder_set_message_user_tag (CamelFolder *folder, g_return_if_fail (folder->summary != NULL); - info = camel_folder_summary_uid (folder->summary, uid); + info = camel_folder_summary_get (folder->summary, uid); if (info == NULL) return; @@ -692,7 +691,7 @@ folder_get_uids (CamelFolder *folder) { g_return_val_if_fail (folder->summary != NULL, NULL); - return camel_folder_summary_array (folder->summary); + return camel_folder_summary_get_array (folder->summary); } static GPtrArray * @@ -717,11 +716,7 @@ static void folder_free_uids (CamelFolder *folder, GPtrArray *array) { - gint i; - - for (i = 0; i < array->len; i++) - camel_pstring_free (array->pdata[i]); - g_ptr_array_free (array, TRUE); + camel_folder_summary_free_array (array); } static gint @@ -749,15 +744,14 @@ folder_get_summary (CamelFolder *folder) { g_return_val_if_fail (folder->summary != NULL, NULL); - return camel_folder_summary_array (folder->summary); + return camel_folder_summary_get_array (folder->summary); } static void folder_free_summary (CamelFolder *folder, - GPtrArray *summary) + GPtrArray *array) { - g_ptr_array_foreach (summary, (GFunc) camel_pstring_free, NULL); - g_ptr_array_free (summary, TRUE); + camel_folder_summary_free_array (array); } static void @@ -777,7 +771,7 @@ folder_get_message_info (CamelFolder *folder, { g_return_val_if_fail (folder->summary != NULL, NULL); - return camel_folder_summary_uid (folder->summary, uid); + return camel_folder_summary_get (folder->summary, uid); } static void @@ -802,7 +796,7 @@ static void folder_delete (CamelFolder *folder) { if (folder->summary) - camel_folder_summary_clear (folder->summary); + camel_folder_summary_clear (folder->summary, NULL); } static void @@ -1959,7 +1953,7 @@ camel_folder_get_unread_message_count (CamelFolder *folder) g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1); g_return_val_if_fail (folder->summary != NULL, -1); - return folder->summary->unread_count; + return camel_folder_summary_get_unread_count (folder->summary); } /** @@ -1975,7 +1969,7 @@ camel_folder_get_deleted_message_count (CamelFolder *folder) g_return_val_if_fail (CAMEL_IS_FOLDER (folder), -1); g_return_val_if_fail (folder->summary != NULL, -1); - return folder->summary->deleted_count; + return camel_folder_summary_get_deleted_count (folder->summary); } /** diff --git a/camel/camel-store-summary.c b/camel/camel-store-summary.c index 5a90759..8b51e77 100644 --- a/camel/camel-store-summary.c +++ b/camel/camel-store-summary.c @@ -36,6 +36,7 @@ #include "camel-file-utils.h" #include "camel-store-summary.h" +#include "camel-folder-summary.h" #include "camel-url.h" #include "camel-win32.h" @@ -50,9 +51,11 @@ #define CAMEL_STORE_SUMMARY_VERSION (2) struct _CamelStoreSummaryPrivate { - GMutex *summary_lock; /* for the summary hashtable/array */ - GMutex *io_lock; /* load/save lock, for access to saved_count, etc */ - GMutex *ref_lock; /* for reffing/unreffing messageinfo's ALWAYS obtain before CAMEL_STORE_SUMMARY_SUMMARY_LOCK */ + GStaticRecMutex summary_lock; /* for the summary hashtable/array */ + GStaticRecMutex io_lock; /* load/save lock, for access to saved_count, etc */ + GStaticRecMutex ref_lock; /* for reffing/unreffing messageinfo's ALWAYS obtain before CAMEL_STORE_SUMMARY_SUMMARY_LOCK */ + + GHashTable *folder_summaries; /* CamelFolderSummary->path; doesn't add reference to CamelFolderSummary */ }; G_DEFINE_TYPE (CamelStoreSummary, camel_store_summary, CAMEL_TYPE_OBJECT) @@ -65,15 +68,16 @@ store_summary_finalize (GObject *object) camel_store_summary_clear (summary); g_ptr_array_free (summary->folders, TRUE); g_hash_table_destroy (summary->folders_path); + g_hash_table_destroy (summary->priv->folder_summaries); g_free (summary->summary_path); if (summary->store_info_chunks != NULL) camel_memchunk_destroy (summary->store_info_chunks); - g_mutex_free (summary->priv->summary_lock); - g_mutex_free (summary->priv->io_lock); - g_mutex_free (summary->priv->ref_lock); + g_static_rec_mutex_free (&summary->priv->summary_lock); + g_static_rec_mutex_free (&summary->priv->io_lock); + g_static_rec_mutex_free (&summary->priv->ref_lock); /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (camel_store_summary_parent_class)->finalize (object); @@ -309,10 +313,11 @@ camel_store_summary_init (CamelStoreSummary *summary) summary->folders = g_ptr_array_new (); summary->folders_path = g_hash_table_new (g_str_hash, g_str_equal); + summary->priv->folder_summaries = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); - summary->priv->summary_lock = g_mutex_new (); - summary->priv->io_lock = g_mutex_new (); - summary->priv->ref_lock = g_mutex_new (); + g_static_rec_mutex_init (&summary->priv->summary_lock); + g_static_rec_mutex_init (&summary->priv->io_lock); + g_static_rec_mutex_init (&summary->priv->ref_lock); } /** @@ -1051,13 +1056,13 @@ camel_store_summary_lock (CamelStoreSummary *summary, switch (lock) { case CAMEL_STORE_SUMMARY_SUMMARY_LOCK: - g_mutex_lock (summary->priv->summary_lock); + g_static_rec_mutex_lock (&summary->priv->summary_lock); break; case CAMEL_STORE_SUMMARY_IO_LOCK: - g_mutex_lock (summary->priv->io_lock); + g_static_rec_mutex_lock (&summary->priv->io_lock); break; case CAMEL_STORE_SUMMARY_REF_LOCK: - g_mutex_lock (summary->priv->ref_lock); + g_static_rec_mutex_lock (&summary->priv->ref_lock); break; default: g_return_if_reached (); @@ -1081,15 +1086,138 @@ camel_store_summary_unlock (CamelStoreSummary *summary, switch (lock) { case CAMEL_STORE_SUMMARY_SUMMARY_LOCK: - g_mutex_unlock (summary->priv->summary_lock); + g_static_rec_mutex_unlock (&summary->priv->summary_lock); break; case CAMEL_STORE_SUMMARY_IO_LOCK: - g_mutex_unlock (summary->priv->io_lock); + g_static_rec_mutex_unlock (&summary->priv->io_lock); break; case CAMEL_STORE_SUMMARY_REF_LOCK: - g_mutex_unlock (summary->priv->ref_lock); + g_static_rec_mutex_unlock (&summary->priv->ref_lock); break; default: g_return_if_reached (); } } + +static void +store_summary_sync_folder_summary_count_cb (CamelFolderSummary *folder_summary, GParamSpec *param, CamelStoreSummary *summary) +{ + const gchar *path; + CamelStoreInfo *si; + + g_return_if_fail (folder_summary != NULL); + g_return_if_fail (param != NULL); + g_return_if_fail (summary != NULL); + g_return_if_fail (summary->priv != NULL); + + path = g_hash_table_lookup (summary->priv->folder_summaries, folder_summary); + g_return_if_fail (path != NULL); + + camel_store_summary_lock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK); + si = camel_store_summary_path (summary, path); + if (!si) { + camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK); + g_warning ("%s: Store summary %p doesn't hold path '%s'", G_STRFUNC, summary, path); + return; + } + + if (g_strcmp0 (g_param_spec_get_name (param), "saved-count") == 0) { + si->total = camel_folder_summary_get_saved_count (folder_summary); + camel_store_summary_touch (summary); + } else if (g_strcmp0 (g_param_spec_get_name (param), "unread-count") == 0) { + si->unread = camel_folder_summary_get_unread_count (folder_summary); + camel_store_summary_touch (summary); + } else { + g_warn_if_reached (); + } + + camel_store_summary_info_free (summary, si); + + camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK); +} + +/** + * camel_store_summary_connect_folder_summary: + * @summary: a #CamelStoreSummary object + * @path: used path for @folder_summary + * @folder_summary: a #CamelFolderSummary object + * + * Connects listeners for count changes on @folder_summary to keep CamelStoreInfo.total + * and CamelStoreInfo.unread in sync transparently. The @folder_summary is stored + * in @summary as @path. Use camel_store_summary_disconnect_folder_summary() + * to disconnect from listening. + * + * Returns: Whether successfully connect callbacks for count change notifications. + * + * Since: 3.4 + **/ +gboolean +camel_store_summary_connect_folder_summary (CamelStoreSummary *summary, const gchar *path, CamelFolderSummary *folder_summary) +{ + CamelStoreInfo *si; + + g_return_val_if_fail (summary != NULL, FALSE); + g_return_val_if_fail (summary->priv != NULL, FALSE); + g_return_val_if_fail (path != NULL, FALSE); + g_return_val_if_fail (folder_summary != NULL, FALSE); + + camel_store_summary_lock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK); + + si = camel_store_summary_path (summary, path); + if (!si) { + camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK); + g_warning ("%s: Store summary %p doesn't hold path '%s'", G_STRFUNC, summary, path); + return FALSE; + } + + camel_store_summary_info_free (summary, si); + + if (g_hash_table_lookup (summary->priv->folder_summaries, folder_summary)) { + camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK); + g_warning ("%s: Store summary %p already listens on folder summary %p", G_STRFUNC, summary, folder_summary); + return FALSE; + } + + g_hash_table_insert (summary->priv->folder_summaries, folder_summary, g_strdup (path)); + g_signal_connect (folder_summary, "notify::saved-count", G_CALLBACK (store_summary_sync_folder_summary_count_cb), summary); + g_signal_connect (folder_summary, "notify::unread-count", G_CALLBACK (store_summary_sync_folder_summary_count_cb), summary); + + camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK); + + return TRUE; +} + +/** + * camel_store_summary_disconnect_folder_summary: + * @summary: a #CamelStoreSummary object + * @folder_summary: a #CamelFolderSummary object + * + * Diconnects count change listeners previously connected + * by camel_store_summary_connect_folder_summary(). + * + * Returns: Whether such connection existed and whether was successfully removed. + * + * Since: 3.4 + **/ +gboolean +camel_store_summary_disconnect_folder_summary (CamelStoreSummary *summary, CamelFolderSummary *folder_summary) +{ + g_return_val_if_fail (summary != NULL, FALSE); + g_return_val_if_fail (summary->priv != NULL, FALSE); + g_return_val_if_fail (folder_summary != NULL, FALSE); + + camel_store_summary_lock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK); + + if (!g_hash_table_lookup (summary->priv->folder_summaries, folder_summary)) { + camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK); + g_warning ("%s: Store summary %p is not connected to folder summary %p", G_STRFUNC, summary, folder_summary); + return FALSE; + } + + g_signal_handlers_disconnect_by_func (folder_summary, G_CALLBACK (store_summary_sync_folder_summary_count_cb), summary); + g_hash_table_remove (summary->priv->folder_summaries, folder_summary); + + camel_store_summary_unlock (summary, CAMEL_STORE_SUMMARY_SUMMARY_LOCK); + + return TRUE; +} diff --git a/camel/camel-store-summary.h b/camel/camel-store-summary.h index 7a2babf..b33a9d6 100644 --- a/camel/camel-store-summary.h +++ b/camel/camel-store-summary.h @@ -184,6 +184,10 @@ void camel_store_info_set_string (CamelStoreSummary *summary, CamelStoreInfo *in void camel_store_summary_lock (CamelStoreSummary *summary, CamelStoreSummaryLock lock); void camel_store_summary_unlock (CamelStoreSummary *summary, CamelStoreSummaryLock lock); +struct _CamelFolderSummary; +gboolean camel_store_summary_connect_folder_summary (CamelStoreSummary *summary, const gchar *path, struct _CamelFolderSummary *folder_summary); +gboolean camel_store_summary_disconnect_folder_summary (CamelStoreSummary *summary, struct _CamelFolderSummary *folder_summary); + G_END_DECLS #endif /* CAMEL_STORE_SUMMARY_H */ diff --git a/camel/camel-vee-folder.c b/camel/camel-vee-folder.c index 5a3d275..93c95f9 100644 --- a/camel/camel-vee-folder.c +++ b/camel/camel-vee-folder.c @@ -172,13 +172,12 @@ folder_changed_add_uid (CamelFolder *sub, } vinfo = (CamelVeeMessageInfo *) camel_folder_get_message_info ((CamelFolder *) folder_unmatched, vuid); if (vinfo) { - camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (folder_unmatched)->summary, vinfo->old_flags, TRUE); camel_folder_change_info_remove_uid ( folder_unmatched->changes, vuid); *unm_added_l = g_list_prepend (*unm_added_l, (gpointer) camel_pstring_strdup (vuid)); - camel_folder_summary_remove_uid_fast ( + camel_folder_summary_remove_uid ( CAMEL_FOLDER (folder_unmatched)->summary, vuid); camel_folder_free_message_info ( CAMEL_FOLDER (folder_unmatched), @@ -211,17 +210,11 @@ folder_changed_remove_uid (CamelFolder *sub, memcpy (vuid, hash, 8); strcpy (vuid + 8, uid); - vinfo = (CamelVeeMessageInfo *) camel_folder_summary_uid (folder->summary, vuid); - if (vinfo) { - camel_folder_summary_update_counts_by_flags (folder->summary, vinfo->old_flags, TRUE); - camel_message_info_free ((CamelMessageInfo *) vinfo); - } - camel_folder_change_info_remove_uid (vf->changes, vuid); if (use_db) *m_removed_l = g_list_prepend (*m_removed_l, (gpointer) camel_pstring_strdup (vuid)); - camel_folder_summary_remove_uid_fast (folder->summary, vuid); + camel_folder_summary_remove_uid (folder->summary, vuid); if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && !CAMEL_IS_VEE_FOLDER (sub) && folder_unmatched != NULL) { if (keep) { @@ -247,13 +240,12 @@ folder_changed_remove_uid (CamelFolder *sub, vinfo = (CamelVeeMessageInfo *) camel_folder_get_message_info ((CamelFolder *) folder_unmatched, vuid); if (vinfo) { - camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (folder_unmatched)->summary, vinfo->old_flags, TRUE); camel_folder_change_info_remove_uid ( folder_unmatched->changes, vuid); *unm_removed_l = g_list_prepend (*unm_removed_l, (gpointer) camel_pstring_strdup (vuid)); - camel_folder_summary_remove_uid_fast ( + camel_folder_summary_remove_uid ( CAMEL_FOLDER (folder_unmatched)->summary, vuid); camel_folder_free_message_info ( CAMEL_FOLDER (folder_unmatched), @@ -264,18 +256,6 @@ folder_changed_remove_uid (CamelFolder *sub, } static void -update_old_flags (CamelFolderSummary *summary, - CamelVeeMessageInfo *vinfo) -{ - g_return_if_fail (summary != NULL); - g_return_if_fail (vinfo != NULL); - - camel_folder_summary_update_counts_by_flags (summary, vinfo->old_flags, TRUE); - vinfo->old_flags = camel_message_info_flags ((CamelMessageInfo *) vinfo); - camel_folder_summary_update_counts_by_flags (summary, vinfo->old_flags, FALSE); -} - -static void folder_changed_change_uid (CamelFolder *sub, const gchar *uid, const gchar hash[8], @@ -294,21 +274,23 @@ folder_changed_change_uid (CamelFolder *sub, memcpy (vuid, hash, 8); strcpy (vuid + 8, uid); - vinfo = (CamelVeeMessageInfo *) camel_folder_summary_uid (folder->summary, vuid); + vinfo = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, vuid); if (folder_unmatched != NULL) - uinfo = (CamelVeeMessageInfo *) camel_folder_summary_uid (((CamelFolder *) folder_unmatched)->summary, vuid); + uinfo = (CamelVeeMessageInfo *) camel_folder_summary_get (((CamelFolder *) folder_unmatched)->summary, vuid); if (vinfo || uinfo) { info = camel_folder_get_message_info (sub, uid); if (info) { if (vinfo) { camel_folder_change_info_change_uid (vf->changes, vuid); - update_old_flags (folder->summary, vinfo); + vinfo->old_flags = camel_message_info_flags ((CamelMessageInfo *) vinfo); + vinfo->info.flags |= (vinfo->old_flags & ~CAMEL_MESSAGE_FOLDER_FLAGGED); camel_message_info_free ((CamelMessageInfo *) vinfo); } if (uinfo) { camel_folder_change_info_change_uid (folder_unmatched->changes, vuid); - update_old_flags (CAMEL_FOLDER (folder_unmatched)->summary, uinfo); + uinfo->old_flags = camel_message_info_flags ((CamelMessageInfo *) uinfo); + uinfo->info.flags |= (uinfo->old_flags & ~CAMEL_MESSAGE_FOLDER_FLAGGED); camel_message_info_free ((CamelMessageInfo *) uinfo); } @@ -414,7 +396,7 @@ folder_changed_change (CamelSession *session, } memcpy (vuid, hash, 8); strcpy (vuid + 8, uid); - vinfo = (CamelVeeMessageInfo *) camel_folder_summary_uid (folder->summary, vuid); + vinfo = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, vuid); if (vinfo == NULL) { g_ptr_array_add (newchanged, (gchar *) uid); } else { @@ -526,7 +508,7 @@ folder_changed_change (CamelSession *session, } memcpy (vuid, hash, 8); strcpy (vuid + 8, uid); - vinfo = (CamelVeeMessageInfo *) camel_folder_summary_uid (folder->summary, vuid); + vinfo = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, vuid); if (vinfo == NULL) { if (g_hash_table_lookup (matches_hash, uid)) { /* A uid we dont have, but now it matches, add it */ @@ -649,37 +631,33 @@ subfolder_renamed_update (CamelVeeFolder *vf, CamelFolder *sub, gchar hash[8]) { - gint count, i; + gint i; CamelFolderChangeInfo *changes = NULL; CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL; CamelFolderSummary *ssummary = sub->summary; + GPtrArray *known_uids; camel_vee_folder_lock (vf, CAMEL_VEE_FOLDER_SUMMARY_LOCK); camel_folder_summary_prepare_fetch_all (((CamelFolder *) vf)->summary, NULL); - count = camel_folder_summary_count (((CamelFolder *) vf)->summary); - for (i = 0; i < count; i++) { - CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_index (((CamelFolder *) vf)->summary, i); + known_uids = camel_folder_summary_get_array (((CamelFolder *) vf)->summary); + for (i = 0; known_uids && i < known_uids->len; i++) { + CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_get (((CamelFolder *) vf)->summary, g_ptr_array_index (known_uids, i)); CamelVeeMessageInfo *vinfo; if (mi == NULL) continue; - if (mi->summary == ssummary) { + if (mi->orig_summary == ssummary) { gchar *uid = (gchar *) camel_message_info_uid (mi); gchar *oldkey; gpointer oldval; camel_folder_change_info_remove_uid (vf->changes, uid); - camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (vf)->summary, mi->old_flags, TRUE); camel_folder_summary_remove (((CamelFolder *) vf)->summary, (CamelMessageInfo *) mi); - /* works since we always append on the end */ - i--; - count--; - vinfo = vee_folder_add_uid (vf, sub, uid + 8, hash); if (vinfo) { camel_folder_change_info_add_uid (vf->changes, camel_message_info_uid (vinfo)); @@ -699,6 +677,8 @@ subfolder_renamed_update (CamelVeeFolder *vf, camel_message_info_free ((CamelMessageInfo *) mi); } + camel_folder_summary_free_array (known_uids); + if (camel_folder_change_info_changed (vf->changes)) { changes = vf->changes; vf->changes = camel_folder_change_info_new (); @@ -733,14 +713,12 @@ unmatched_check_uid (gchar *uidin, if (vee_folder_add_uid_test (u->folder_unmatched, u->source, uidin, u->hash)) camel_folder_change_info_add_uid (u->folder_unmatched->changes, uid); } else { - CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_uid (((CamelFolder *) u->folder_unmatched)->summary, uid); + CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_get (((CamelFolder *) u->folder_unmatched)->summary, uid); if (mi) { - camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (u->folder_unmatched)->summary, mi->old_flags, TRUE); - if (u->message_uids != NULL) g_queue_push_tail (u->message_uids, g_strdup (uid)); - camel_folder_summary_remove_uid_fast ( + camel_folder_summary_remove_uid ( ((CamelFolder *) u->folder_unmatched)->summary, uid); camel_folder_change_info_remove_uid ( u->folder_unmatched->changes, uid); @@ -801,22 +779,22 @@ summary_header_to_db (CamelFolderSummary *s, const gchar *full_name; /* We do this during write, so lets use write handle, though we gonna read */ - full_name = camel_folder_get_full_name (s->folder); + full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (s)); record->folder_name = g_strdup (full_name); /* we always write out the current version */ record->version = 13; /* FIXME: CAMEL_FOLDER_SUMMARY_VERSION; */ record->flags = s->flags; - record->nextuid = s->nextuid; + record->nextuid = camel_folder_summary_get_next_uid (s); record->time = s->time; - record->saved_count = s->uids->len; - record->junk_count = s->junk_count; - record->deleted_count = s->deleted_count; - record->unread_count = s->unread_count; - record->visible_count = s->visible_count; - record->jnd_count = s->junk_not_deleted_count; + record->saved_count = camel_folder_summary_count (s); + record->junk_count = camel_folder_summary_get_junk_count (s); + record->deleted_count = camel_folder_summary_get_deleted_count (s); + record->unread_count = camel_folder_summary_get_unread_count (s); + record->visible_count = camel_folder_summary_get_visible_count (s); + record->jnd_count = camel_folder_summary_get_junk_not_deleted_count (s); return record; } @@ -1074,13 +1052,13 @@ vee_folder_search_by_expression (CamelFolder *folder, GHashTable *searched = g_hash_table_new (NULL, NULL); CamelVeeFolder *folder_unmatched = vf->parent_vee_store ? vf->parent_vee_store->folder_unmatched : NULL; gboolean is_folder_unmatched = vf == folder_unmatched && folder_unmatched; - GHashTable *folder_unmatched_hash = NULL; + CamelFolderSummary *folder_unmatched_summary = NULL; vee_folder_propagate_skipped_changes (vf); if (is_folder_unmatched) { expr = g_strdup (expression); - folder_unmatched_hash = camel_folder_summary_get_hashtable (((CamelFolder *) folder_unmatched)->summary); + folder_unmatched_summary = ((CamelFolder *) folder_unmatched)->summary; } else { expr = g_strdup_printf ("(and %s %s)", vf->expression ? vf->expression : "", expression); } @@ -1103,7 +1081,7 @@ vee_folder_search_by_expression (CamelFolder *folder, memcpy (vuid, hash, 8); strcpy (vuid + 8, uid); - if (!is_folder_unmatched || g_hash_table_lookup (folder_unmatched_hash, vuid) != NULL) + if (!is_folder_unmatched || camel_folder_summary_check_uid (folder_unmatched_summary, vuid)) g_ptr_array_add (result, (gpointer) camel_pstring_strdup (vuid)); g_free (vuid); } @@ -1114,8 +1092,6 @@ vee_folder_search_by_expression (CamelFolder *folder, node = g_list_next (node); } - if (folder_unmatched_hash) - camel_folder_summary_free_hashtable (folder_unmatched_hash); g_free (expr); g_hash_table_destroy (searched); @@ -1330,10 +1306,10 @@ vee_folder_get_message_sync (CamelFolder *folder, CamelVeeMessageInfo *mi; CamelMimeMessage *msg = NULL; - mi = (CamelVeeMessageInfo *) camel_folder_summary_uid (folder->summary, uid); + mi = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, uid); if (mi) { msg = camel_folder_get_message_sync ( - mi->summary->folder, camel_message_info_uid (mi) + 8, + camel_folder_summary_get_folder (mi->orig_summary), camel_message_info_uid (mi) + 8, cancellable, error); camel_message_info_free ((CamelMessageInfo *) mi); } else { @@ -1426,22 +1402,21 @@ vee_folder_synchronize_sync (CamelFolder *folder, CamelStore *parent_store; const gchar *full_name; GList *del = NULL; - gint i, count; + gint i; + GPtrArray *known_uids; camel_folder_summary_prepare_fetch_all (folder->summary, NULL); - count = camel_folder_summary_count (folder->summary); - for (i = 0; i < count; i++) { - CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_index (folder->summary, i); + known_uids = camel_folder_summary_get_array (folder->summary); + for (i = 0; known_uids && i < known_uids->len; i++) { + CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, g_ptr_array_index (known_uids, i)); if (mi->old_flags & CAMEL_MESSAGE_DELETED) { del = g_list_prepend (del, (gpointer) camel_pstring_strdup (((CamelMessageInfo *) mi)->uid)); - camel_folder_summary_update_counts_by_flags (folder->summary, mi->old_flags, TRUE); - camel_folder_summary_remove_index_fast (folder->summary, i); - count--; - i--; + camel_folder_summary_remove_uid (folder->summary, ((CamelMessageInfo *) mi)->uid); } camel_message_info_free (mi); } + camel_folder_summary_free_array (known_uids); full_name = camel_folder_get_full_name (folder); parent_store = camel_folder_get_parent_store (folder); @@ -1500,7 +1475,7 @@ vee_folder_set_expression (CamelVeeFolder *vee_folder, parent_store = camel_folder_get_parent_store (folder); summary = folder->summary; - camel_folder_summary_clear (summary); + camel_folder_summary_clear (summary, NULL); camel_db_recreate_vfolder (parent_store->cdb_w, full_name, NULL); } @@ -1537,7 +1512,7 @@ static void vee_folder_remove_folder_helper (CamelVeeFolder *vf, CamelFolder *source) { - gint i, count, n, still = FALSE, start, last; + gint i, n, still = FALSE; gchar *oldkey; CamelFolder *folder = (CamelFolder *) vf; gchar hash[8]; @@ -1547,6 +1522,7 @@ vee_folder_remove_folder_helper (CamelVeeFolder *vf, GHashTable *unmatched_uids = vf->parent_vee_store ? vf->parent_vee_store->unmatched_uids : NULL; CamelFolderSummary *ssummary = source->summary; gint killun = FALSE; + GPtrArray *known_uids; if (vf == folder_unmatched) return; @@ -1569,58 +1545,36 @@ vee_folder_remove_folder_helper (CamelVeeFolder *vf, /* See if we just blow all uid's from this folder away from unmatched, regardless */ if (killun) { - start = -1; - last = -1; camel_folder_summary_prepare_fetch_all (((CamelFolder *) folder_unmatched)->summary, NULL); - count = camel_folder_summary_count (((CamelFolder *) folder_unmatched)->summary); - for (i = 0; i < count; i++) { - CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_index (((CamelFolder *) folder_unmatched)->summary, i); + known_uids = camel_folder_summary_get_array (((CamelFolder *) folder_unmatched)->summary); + for (i = 0; known_uids && i < known_uids->len; i++) { + CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) + camel_folder_summary_get (((CamelFolder *) folder_unmatched)->summary, g_ptr_array_index (known_uids, i)); if (mi) { - if (mi->summary == ssummary) { + if (mi->orig_summary == ssummary) { camel_folder_change_info_remove_uid (folder_unmatched->changes, camel_message_info_uid (mi)); - camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (folder_unmatched)->summary, mi->old_flags, TRUE); - if (last == -1) { - last = start = i; - } else if (last + 1 == i) { - last = i; - } else { - camel_folder_summary_remove_range (((CamelFolder *) folder_unmatched)->summary, start, last); - i -= (last - start) + 1; - start = last = i; - } + camel_folder_summary_remove_uid (((CamelFolder *) folder_unmatched)->summary, camel_message_info_uid (mi)); } camel_message_info_free ((CamelMessageInfo *) mi); } } - if (last != -1) - camel_folder_summary_remove_range (((CamelFolder *) folder_unmatched)->summary, start, last); + camel_folder_summary_free_array (known_uids); } } /*FIXME: This can be optimized a lot like, searching for UID in the summary uids */ - start = -1; - last = -1; camel_folder_summary_prepare_fetch_all (folder->summary, NULL); - count = camel_folder_summary_count (folder->summary); - for (i = 0; i < count; i++) { - CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_index (folder->summary, i); + known_uids = camel_folder_summary_get_array (folder->summary); + for (i = 0; known_uids && i < known_uids->len; i++) { + CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, g_ptr_array_index (known_uids, i)); if (mi) { - if (mi->summary == ssummary) { + if (mi->orig_summary == ssummary) { const gchar *uid = camel_message_info_uid (mi); camel_folder_change_info_remove_uid (vf->changes, uid); - camel_folder_summary_update_counts_by_flags (folder->summary, mi->old_flags, TRUE); + camel_folder_summary_remove_uid (folder->summary, uid); - if (last == -1) { - last = start = i; - } else if (last + 1 == i) { - last = i; - } else { - camel_folder_summary_remove_range (folder->summary, start, last); - i -= (last - start) + 1; - start = last = i; - } if ((vf->flags & CAMEL_STORE_FOLDER_PRIVATE) == 0 && folder_unmatched != NULL) { if (still) { if (g_hash_table_lookup_extended (unmatched_uids, uid, (gpointer *) &oldkey, &oldval)) { @@ -1646,9 +1600,7 @@ vee_folder_remove_folder_helper (CamelVeeFolder *vf, camel_message_info_free ((CamelMessageInfo *) mi); } } - - if (last != -1) - camel_folder_summary_remove_range (folder->summary, start, last); + camel_folder_summary_free_array (known_uids); if (folder_unmatched) { if (camel_folder_change_info_changed (folder_unmatched->changes)) { @@ -1711,7 +1663,7 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder, GHashTable *allhash, *matchhash, *fullhash; GList *del_list = NULL; CamelFolder *folder = (CamelFolder *) vee_folder; - gint i, n, count, start, last; + gint i, n, count; struct _update_data u; CamelFolderChangeInfo *vee_folder_changes = NULL, *unmatched_changes = NULL; CamelVeeFolder *folder_unmatched = vee_folder->parent_vee_store ? vee_folder->parent_vee_store->folder_unmatched : NULL; @@ -1719,6 +1671,7 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder, CamelFolderSummary *ssummary = source->summary; gboolean rebuilded = FALSE; gchar *shash; + GPtrArray *known_uids; /* Since the source of a correlating vfolder has to be requeried in * full every time it changes, caching the results in the db is not @@ -1774,7 +1727,7 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder, allhash = g_hash_table_new (g_str_hash, g_str_equal); fullhash = g_hash_table_new (g_str_hash, g_str_equal); - all = camel_folder_summary_array (source->summary); + all = camel_folder_summary_get_array (source->summary); for (i = 0; i < all->len; i++) { if (g_hash_table_lookup (matchhash, all->pdata[i]) == NULL) g_hash_table_insert (allhash, all->pdata[i], GINT_TO_POINTER (1)); @@ -1800,31 +1753,20 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder, /* scan, looking for "old" uid's to be removed. "old" uid's * are those that are from previous added sources (not in * current source) */ - start = -1; - last = -1; camel_folder_summary_prepare_fetch_all (folder->summary, NULL); - count = camel_folder_summary_count (folder->summary); - for (i = 0; i < count; i++) { - CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_index (folder->summary, i); + known_uids = camel_folder_summary_get_array (folder->summary); + for (i = 0; known_uids && i < known_uids->len; i++) { + CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) camel_folder_summary_get (folder->summary, g_ptr_array_index (known_uids, i)); if (mi) { - if (mi->summary == ssummary) { + if (mi->orig_summary == ssummary) { gchar *uid = (gchar *) camel_message_info_uid (mi), *oldkey; gpointer oldval; if (g_hash_table_lookup (matchhash, uid + 8) == NULL) { - if (last == -1) { - last = start = i; - } else if (last + 1 == i) { - last = i; - } else { - camel_folder_summary_remove_range (folder->summary, start, last); - i -= (last - start) + 1; - count -= (last - start) + 1; - start = last = i; - } camel_folder_change_info_remove_uid (vee_folder->changes, camel_message_info_uid (mi)); - camel_folder_summary_update_counts_by_flags (folder->summary, mi->old_flags, TRUE); + camel_folder_summary_remove_uid (folder->summary, uid); + if (!CAMEL_IS_VEE_FOLDER (source) && unmatched_uids != NULL && g_hash_table_lookup_extended (unmatched_uids, uid, (gpointer *) &oldkey, &oldval)) { @@ -1843,8 +1785,7 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder, camel_message_info_free ((CamelMessageInfo *) mi); } } - if (last != -1) - camel_folder_summary_remove_range (folder->summary, start, last); + camel_folder_summary_free_array (known_uids); if (rebuilded && !correlating) u.message_uids = g_queue_new (); @@ -1878,29 +1819,26 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder, if (folder_unmatched != NULL) { /* scan unmatched, remove any that have vanished, etc */ - count = camel_folder_summary_count (((CamelFolder *) folder_unmatched)->summary); - for (i = 0; i < count; i++) { - gchar *uid = camel_folder_summary_uid_from_index (((CamelFolder *) folder_unmatched)->summary, i); - - if (uid) { - if (strncmp (uid, u.hash, 8) == 0) { - if (g_hash_table_lookup (allhash, uid + 8) == NULL) { - CamelVeeMessageInfo *vinfo = (CamelVeeMessageInfo *) camel_folder_summary_index (CAMEL_FOLDER (folder_unmatched)->summary, i); - if (vinfo) { - camel_folder_summary_update_counts_by_flags (CAMEL_FOLDER (folder_unmatched)->summary, vinfo->old_flags, TRUE); - camel_message_info_free (vinfo); + GPtrArray *known_uids; + + known_uids = camel_folder_summary_get_array (((CamelFolder *) folder_unmatched)->summary); + if (known_uids != NULL) { + for (i = 0; i < known_uids->len; i++) { + const gchar *uid = g_ptr_array_index (known_uids, i); + + if (uid) { + if (strncmp (uid, u.hash, 8) == 0) { + if (g_hash_table_lookup (allhash, uid + 8) == NULL) { + /* no longer exists at all, just remove it entirely */ + camel_folder_summary_remove_uid (((CamelFolder *) folder_unmatched)->summary, uid); + camel_folder_change_info_remove_uid (folder_unmatched->changes, uid); + } else { + g_hash_table_remove (allhash, uid + 8); } - /* no longer exists at all, just remove it entirely */ - camel_folder_summary_remove_index_fast (((CamelFolder *) folder_unmatched)->summary, i); - camel_folder_change_info_remove_uid (folder_unmatched->changes, uid); - i--; - count--; - } else { - g_hash_table_remove (allhash, uid + 8); } } - g_free (uid); } + camel_folder_summary_free_array (known_uids); } /* now allhash contains all potentially new uid's for the unmatched folder, process */ @@ -1976,7 +1914,7 @@ vee_folder_rebuild_folder (CamelVeeFolder *vee_folder, g_ptr_array_free (match, TRUE); } else camel_folder_search_free (source, match); - camel_folder_free_summary (source, all); + camel_folder_summary_free_array (all); if (unmatched_changes) { camel_folder_changed ( @@ -2466,7 +2404,7 @@ camel_vee_folder_get_location (CamelVeeFolder *vf, { CamelFolder *folder; - folder = vinfo->summary->folder; + folder = camel_folder_summary_get_folder (vinfo->orig_summary); /* locking? yes? no? although the vfolderinfo is valid when obtained * the folder in it might not necessarily be so ...? */ diff --git a/camel/camel-vee-summary.c b/camel/camel-vee-summary.c index 612874c..e638ed7 100644 --- a/camel/camel-vee-summary.c +++ b/camel/camel-vee-summary.c @@ -50,7 +50,7 @@ vee_message_info_free (CamelFolderSummary *s, CamelVeeMessageInfo *mi = (CamelVeeMessageInfo *) info; camel_pstring_free (info->uid); - g_object_unref (mi->summary); + g_object_unref (mi->orig_summary); } static CamelMessageInfo * @@ -62,7 +62,7 @@ vee_message_info_clone (CamelFolderSummary *s, to = (CamelVeeMessageInfo *) camel_message_info_new (s); - to->summary = g_object_ref (from->summary); + to->orig_summary = g_object_ref (from->orig_summary); to->info.summary = s; to->info.uid = camel_pstring_strdup (from->info.uid); @@ -79,7 +79,7 @@ vee_info_ptr (const CamelMessageInfo *mi, CamelMessageInfo *rmi; gpointer p; - rmi = camel_folder_summary_uid (vmi->summary, mi->uid + 8); + rmi = camel_folder_summary_get (vmi->orig_summary, mi->uid + 8); HANDLE_NULL_INFO (NULL); p = (gpointer) camel_message_info_ptr (rmi, id); camel_message_info_free (rmi); @@ -91,7 +91,7 @@ static guint32 vee_info_uint32 (const CamelMessageInfo *mi, gint id) { - CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8); + CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8); guint32 ret; HANDLE_NULL_INFO (0); @@ -106,7 +106,7 @@ static time_t vee_info_time (const CamelMessageInfo *mi, gint id) { - CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8); + CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8); time_t ret; HANDLE_NULL_INFO (0); @@ -120,7 +120,7 @@ static gboolean vee_info_user_flag (const CamelMessageInfo *mi, const gchar *id) { - CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8); + CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8); gboolean ret; HANDLE_NULL_INFO (FALSE); @@ -134,7 +134,7 @@ static const gchar * vee_info_user_tag (const CamelMessageInfo *mi, const gchar *id) { - CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8); + CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8); const gchar *ret; HANDLE_NULL_INFO(""); @@ -150,22 +150,23 @@ vee_info_set_user_flag (CamelMessageInfo *mi, gboolean value) { gint res = FALSE; - CamelVeeFolder *vf = (CamelVeeFolder *) mi->summary->folder; + CamelVeeFolder *vf = (CamelVeeFolder *) camel_folder_summary_get_folder (mi->summary); if (camel_debug("vfolderexp")) printf ( "Expression for vfolder '%s' is '%s'\n", - camel_folder_get_full_name (mi->summary->folder), + camel_folder_get_full_name (camel_folder_summary_get_folder (mi->summary)), g_strescape (vf->expression, "")); if (mi->uid) { - CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8); + CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8); + HANDLE_NULL_INFO (FALSE); /* ignore changes done in the folder itself, * unless it's a vTrash or vJunk folder */ if (!CAMEL_IS_VTRASH_FOLDER (vf)) - camel_vee_folder_ignore_next_changed_event (vf, rmi->summary->folder); + camel_vee_folder_ignore_next_changed_event (vf, camel_folder_summary_get_folder (rmi->summary)); res = camel_message_info_set_user_flag (rmi, name, value); @@ -183,13 +184,15 @@ vee_info_set_user_tag (CamelMessageInfo *mi, gint res = FALSE; if (mi->uid) { - CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8); + CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8); + CamelFolder *folder = camel_folder_summary_get_folder (mi->summary); + HANDLE_NULL_INFO (FALSE); /* ignore changes done in the folder itself, * unless it's a vTrash or vJunk folder */ - if (!CAMEL_IS_VTRASH_FOLDER (mi->summary->folder)) - camel_vee_folder_ignore_next_changed_event ((CamelVeeFolder *) mi->summary->folder, rmi->summary->folder); + if (!CAMEL_IS_VTRASH_FOLDER (folder)) + camel_vee_folder_ignore_next_changed_event ((CamelVeeFolder *) folder, camel_folder_summary_get_folder (rmi->summary)); res = camel_message_info_set_user_tag (rmi, name, value); camel_message_info_free (rmi); @@ -204,47 +207,36 @@ vee_info_set_flags (CamelMessageInfo *mi, guint32 set) { gint res = FALSE; - CamelVeeFolder *vf = (CamelVeeFolder *) mi->summary->folder; + CamelVeeFolder *vf = CAMEL_VEE_FOLDER (camel_folder_summary_get_folder (mi->summary)); if (camel_debug("vfolderexp")) printf ( "Expression for vfolder '%s' is '%s'\n", - camel_folder_get_full_name (mi->summary->folder), + camel_folder_get_full_name (CAMEL_FOLDER (vf)), g_strescape (vf->expression, "")); + /* first update original message info... */ if (mi->uid) { - CamelMessageInfo *rmi = camel_folder_summary_uid (((CamelVeeMessageInfo *) mi)->summary, mi->uid + 8); + CamelMessageInfo *rmi = camel_folder_summary_get (((CamelVeeMessageInfo *) mi)->orig_summary, mi->uid + 8); HANDLE_NULL_INFO (FALSE); - camel_folder_summary_update_counts_by_flags (mi->summary, camel_message_info_flags (rmi), TRUE); - /* ignore changes done in the folder itself, * unless it's a vTrash or vJunk folder */ if (!CAMEL_IS_VTRASH_FOLDER (vf)) - camel_vee_folder_ignore_next_changed_event (vf, rmi->summary->folder); + camel_vee_folder_ignore_next_changed_event (vf, camel_folder_summary_get_folder (rmi->summary)); - camel_folder_freeze (rmi->summary->folder); + camel_folder_freeze (camel_folder_summary_get_folder (rmi->summary)); res = camel_message_info_set_flags (rmi, flags, set); ((CamelVeeMessageInfo *) mi)->old_flags = camel_message_info_flags (rmi); - camel_folder_thaw (rmi->summary->folder); - - /* Keep the summary in sync */ - camel_folder_summary_update_counts_by_flags (mi->summary, camel_message_info_flags (rmi), FALSE); - - d(printf("VF %d %d %d %d %d\n", mi->summary->unread_count, mi->summary->deleted_count, mi->summary->junk_count, mi->summary->junk_not_deleted_count, mi->summary->visible_count)); - - if (res && mi->summary && mi->summary->folder) { - CamelFolderChangeInfo *changes = camel_folder_change_info_new (); - - camel_folder_change_info_change_uid (changes, camel_message_info_uid (mi)); - camel_folder_changed (mi->summary->folder, changes); - camel_folder_change_info_free (changes); - } + camel_folder_thaw (camel_folder_summary_get_folder (rmi->summary)); camel_message_info_free (rmi); } + if (res) + CAMEL_FOLDER_SUMMARY_CLASS (camel_vee_summary_parent_class)->info_set_flags (mi, flags, set); + return res; } @@ -254,17 +246,7 @@ message_info_from_uid (CamelFolderSummary *s, { CamelMessageInfo *info; - /* FIXME[disk-summary] too bad design. Need to peek it from cfs - * instead of hacking ugly like this */ - camel_folder_summary_lock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - - info = g_hash_table_lookup (s->loaded_infos, uid); - - if (info) - camel_message_info_ref (info); - - camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - + info = camel_folder_summary_peek_loaded (s, uid); if (!info) { CamelVeeMessageInfo *vinfo; gchar tmphash[9]; @@ -275,7 +257,8 @@ message_info_from_uid (CamelFolderSummary *s, * Otherwise, the first byte itself would return in strcmp, saving the CPU. */ if (!camel_folder_summary_check_uid (s, uid)) { - d(g_message ("Unable to find %s in the summary of %s", uid, s->folder->full_name)); + d(g_message ("Unable to find %s in the summary of %s", uid, + camel_folder_get_full_name (camel_folder_summary_get_folder (s->folder)))); return NULL; } @@ -287,10 +270,11 @@ message_info_from_uid (CamelFolderSummary *s, info->uid = camel_pstring_strdup (uid); strncpy (tmphash, uid, 8); tmphash[8] = 0; - vinfo->summary = g_hash_table_lookup (((CamelVeeFolder *) s->folder)->hashes, tmphash); - g_object_ref (vinfo->summary); + vinfo->orig_summary = g_hash_table_lookup (((CamelVeeFolder *) camel_folder_summary_get_folder (s))->hashes, tmphash); + g_object_ref (vinfo->orig_summary); camel_folder_summary_insert (s, info, FALSE); } + return info; } @@ -336,17 +320,13 @@ camel_vee_summary_new (CamelFolder *parent) CamelStore *parent_store; const gchar *full_name; - s = g_object_new (CAMEL_TYPE_VEE_SUMMARY, NULL); - s->summary.folder = parent; + s = g_object_new (CAMEL_TYPE_VEE_SUMMARY, "folder", parent, NULL); - /* FIXME[disk-summary] fix exceptions and note return values */ - /* FIXME[disk-summary] if Evo's junk/trash vfolders make it VJunk - * VTrash instead of .#evolution/Junk-or-whatever */ full_name = camel_folder_get_full_name (parent); parent_store = camel_folder_get_parent_store (parent); camel_db_create_vfolder (parent_store->cdb_w, full_name, NULL); - return &s->summary; + return (CamelFolderSummary *) s; } /** @@ -365,8 +345,8 @@ camel_vee_summary_get_ids (CamelVeeSummary *summary, const gchar *full_name; /* FIXME[disk-summary] fix exception passing */ - full_name = camel_folder_get_full_name (cfs->folder); - parent_store = camel_folder_get_parent_store (cfs->folder); + full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (cfs)); + parent_store = camel_folder_get_parent_store (camel_folder_summary_get_folder (cfs)); array = camel_db_get_vuids_from_vfolder (parent_store->cdb_r, full_name, shash, NULL); g_free (shash); @@ -387,36 +367,30 @@ camel_vee_summary_add (CamelVeeSummary *s, memcpy (vuid, hash, 8); strcpy (vuid + 8, uid); - camel_folder_summary_lock (CAMEL_FOLDER_SUMMARY (s), CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - mi = (CamelVeeMessageInfo *) g_hash_table_lookup (((CamelFolderSummary *) s)->loaded_infos, vuid); - camel_folder_summary_unlock (CAMEL_FOLDER_SUMMARY (s), CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); - + mi = (CamelVeeMessageInfo *) camel_folder_summary_peek_loaded (&s->summary, vuid); if (mi) { /* Possible that the entry is loaded, see if it has the summary */ d(g_message ("%s - already there\n", vuid)); g_free (vuid); - if (!mi->summary) - mi->summary = g_object_ref (summary); - - camel_message_info_ref (mi); + if (!mi->orig_summary) + mi->orig_summary = g_object_ref (summary); return mi; } mi = (CamelVeeMessageInfo *) camel_message_info_new (&s->summary); - mi->summary = g_object_ref (summary); + mi->orig_summary = g_object_ref (summary); mi->info.uid = (gchar *) camel_pstring_strdup (vuid); g_free (vuid); camel_message_info_ref (mi); /* Get actual flags and store it */ - rmi = camel_folder_summary_uid (summary, uid); + rmi = camel_folder_summary_get (summary, uid); if (rmi) { mi->old_flags = camel_message_info_flags (rmi); camel_message_info_free (rmi); } camel_folder_summary_insert (&s->summary, (CamelMessageInfo *) mi, FALSE); - camel_folder_summary_update_counts_by_flags (&s->summary, camel_message_info_flags (mi), FALSE); return mi; } diff --git a/camel/camel-vee-summary.h b/camel/camel-vee-summary.h index 688dcf9..2667e7a 100644 --- a/camel/camel-vee-summary.h +++ b/camel/camel-vee-summary.h @@ -59,8 +59,8 @@ typedef struct _CamelVeeSummaryClass CamelVeeSummaryClass; typedef struct _CamelVeeMessageInfo CamelVeeMessageInfo; struct _CamelVeeMessageInfo { - CamelMessageInfo info; - CamelFolderSummary *summary; + CamelMessageInfoBase info; + CamelFolderSummary *orig_summary; guint32 old_flags; /* These are just for identifying changed flags */ }; diff --git a/camel/camel-vtrash-folder.c b/camel/camel-vtrash-folder.c index f3a5038..fff4a39 100644 --- a/camel/camel-vtrash-folder.c +++ b/camel/camel-vtrash-folder.c @@ -171,18 +171,18 @@ vtrash_folder_transfer_messages_to_sync (CamelFolder *source, continue; } - if (dest == mi->summary->folder) { + if (dest == camel_folder_summary_get_folder (mi->orig_summary)) { /* Just unset the flag on the original message */ camel_folder_set_message_flags ( source, uids->pdata[i], sbit, 0); } else { if (batch == NULL) batch = g_hash_table_new (NULL, NULL); - md = g_hash_table_lookup (batch, mi->summary->folder); + md = g_hash_table_lookup (batch, camel_folder_summary_get_folder (mi->orig_summary)); if (md == NULL) { md = g_malloc0 (sizeof (*md)); md->cancellable = cancellable; - md->folder = g_object_ref (mi->summary->folder); + md->folder = g_object_ref (camel_folder_summary_get_folder (mi->orig_summary)); md->uids = g_ptr_array_new (); md->dest = dest; md->delete = delete_originals; @@ -192,7 +192,7 @@ vtrash_folder_transfer_messages_to_sync (CamelFolder *source, if (cancellable != NULL) g_object_ref (cancellable); camel_folder_freeze (md->folder); - g_hash_table_insert (batch, mi->summary->folder, md); + g_hash_table_insert (batch, camel_folder_summary_get_folder (mi->orig_summary), md); } /* unset the bit temporarily */ diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c index d419e27..97b05f1 100644 --- a/camel/providers/imap/camel-imap-folder.c +++ b/camel/providers/imap/camel-imap-folder.c @@ -192,6 +192,7 @@ static void imap_folder_dispose (GObject *object) { CamelImapFolder *imap_folder; + CamelStore *parent_store; imap_folder = CAMEL_IMAP_FOLDER (object); @@ -216,6 +217,13 @@ imap_folder_dispose (GObject *object) imap_folder->journal = NULL; } + parent_store = camel_folder_get_parent_store (CAMEL_FOLDER (imap_folder)); + if (parent_store) { + camel_store_summary_disconnect_folder_summary ( + (CamelStoreSummary *) ((CamelImapStore *) parent_store)->summary, + CAMEL_FOLDER (imap_folder)->summary); + } + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (camel_imap_folder_parent_class)->dispose (object); } @@ -488,6 +496,10 @@ camel_imap_folder_new (CamelStore *parent, imap_folder->search = camel_imap_search_new (folder_dir); + camel_store_summary_connect_folder_summary ( + (CamelStoreSummary *) ((CamelImapStore *) parent)->summary, + folder_name, folder->summary); + return folder; } @@ -557,7 +569,7 @@ camel_imap_folder_selected (CamelFolder *folder, CamelMessageFlags perm_flags = 0; GData *fetch_data; gint i, count; - gchar *resp, *old_uid; + gchar *resp; count = camel_folder_summary_count (folder->summary); @@ -599,7 +611,7 @@ camel_imap_folder_selected (CamelFolder *folder, imap_summary->validity = validity; else if (validity != imap_summary->validity) { imap_summary->validity = validity; - camel_folder_summary_clear (folder->summary); + camel_folder_summary_clear (folder->summary, NULL); CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock); camel_imap_message_cache_clear (imap_folder->cache); CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock); @@ -614,6 +626,8 @@ camel_imap_folder_selected (CamelFolder *folder, else if (count != 0 && !imap_folder->need_rescan) { CamelStore *parent_store; CamelImapStore *store; + GPtrArray *known_uids; + const gchar *old_uid; parent_store = camel_folder_get_parent_store (folder); store = CAMEL_IMAP_STORE (parent_store); @@ -649,13 +663,17 @@ camel_imap_folder_selected (CamelFolder *folder, } camel_imap_response_free_without_processing (store, response); - old_uid = camel_folder_summary_uid_from_index (folder->summary, count - 1); + known_uids = camel_folder_summary_get_array (folder->summary); + camel_folder_sort_uids (folder, known_uids); + old_uid = NULL; + if (known_uids && count - 1 >= 0 && count - 1 < known_uids->len) + old_uid = g_ptr_array_index (known_uids, count - 1); if (old_uid) { val = strtoul (old_uid, NULL, 10); - g_free (old_uid); if (uid == 0 || uid != val) imap_folder->need_rescan = TRUE; } + camel_folder_summary_free_array (known_uids); } /* Now rescan if we need to */ @@ -882,7 +900,7 @@ imap_refresh_info_sync (CamelFolder *folder, guint32 unread, total; total = camel_folder_summary_count (folder->summary); - unread = folder->summary->unread_count; + unread = camel_folder_summary_get_unread_count (folder->summary); if (si->total != total || si->unread != unread) { @@ -905,7 +923,7 @@ imap_refresh_info_sync (CamelFolder *folder, if (get_folder_status (folder, &server_total, &server_unread, cancellable, &local_error)) { total = camel_folder_summary_count (folder->summary); - unread = folder->summary->unread_count; + unread = camel_folder_summary_get_unread_count (folder->summary); if (total != server_total || unread != server_unread) check_rescan = 1; @@ -1035,6 +1053,7 @@ imap_rescan (CamelFolder *folder, gboolean ok; CamelFolderChangeInfo *changes = NULL; gboolean success; + GPtrArray *known_uids; parent_store = camel_folder_get_parent_store (folder); store = CAMEL_IMAP_STORE (parent_store); @@ -1044,8 +1063,10 @@ imap_rescan (CamelFolder *folder, imap_folder->need_rescan = FALSE; - summary_len = camel_folder_summary_count (folder->summary); + known_uids = camel_folder_summary_get_array (folder->summary); + summary_len = known_uids ? known_uids->len : 0; if (summary_len == 0) { + camel_folder_summary_free_array (known_uids); if (exists) return camel_imap_folder_changed ( folder, exists, NULL, cancellable, error); @@ -1056,19 +1077,22 @@ imap_rescan (CamelFolder *folder, camel_operation_push_message ( cancellable, _("Scanning for changed messages in %s"), camel_folder_get_display_name (folder)); - uid = camel_folder_summary_uid_from_index (folder->summary, summary_len - 1); + camel_folder_sort_uids (folder, known_uids); + + uid = g_ptr_array_index (known_uids, summary_len - 1); if (!uid) { camel_operation_pop_message (cancellable); + camel_folder_summary_free_array (known_uids); return TRUE; } ok = camel_imap_command_start ( store, folder, cancellable, error, "UID FETCH 1:%s (FLAGS)", uid); - g_free (uid); if (!ok) { camel_operation_pop_message (cancellable); + camel_folder_summary_free_array (known_uids); return FALSE; } @@ -1110,6 +1134,7 @@ imap_rescan (CamelFolder *folder, g_free (new); g_free (resp); + camel_folder_summary_free_array (known_uids); return TRUE; } @@ -1126,6 +1151,7 @@ imap_rescan (CamelFolder *folder, if (type != CAMEL_IMAP_RESPONSE_ERROR && type != CAMEL_IMAP_RESPONSE_TAGGED) camel_service_unlock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK); + camel_folder_summary_free_array (known_uids); return TRUE; } @@ -1146,12 +1172,11 @@ imap_rescan (CamelFolder *folder, for (i = 0, j = 0; i < summary_len && new[j].uid; i++) { gboolean changed = FALSE; - uid = camel_folder_summary_uid_from_index (folder->summary, i); - + uid = g_ptr_array_index (known_uids, i); if (!uid) continue; - info = camel_folder_summary_uid (folder->summary, uid); + info = camel_folder_summary_get (folder->summary, uid); if (!info) { if (g_getenv("CRASH_IMAP")) { /* Debug logs to tackle on hard to get imap crasher */ printf ("CRASH: %s: %s", @@ -1164,40 +1189,6 @@ imap_rescan (CamelFolder *folder, iinfo = (CamelImapMessageInfo *) info; if (strcmp (uid, new[j].uid) != 0) { - g_free (uid); - - /* these will be deleted from db in a moment. So adjust the counts please */ - if (info) { - CamelMessageInfoBase *dinfo = (CamelMessageInfoBase *) info; - gint unread = 0, deleted = 0, junk = 0; - guint32 flags; - - flags = dinfo->flags; - if (!(flags & CAMEL_MESSAGE_SEEN)) - unread = 1; - - if (flags & CAMEL_MESSAGE_DELETED) - deleted = 1; - - if (flags & CAMEL_MESSAGE_JUNK) - junk = 1; - - if (unread) - folder->summary->unread_count--; - - if (deleted) - folder->summary->deleted_count--; - if (junk) - folder->summary->junk_count--; - - if (junk && !deleted) - folder->summary->junk_not_deleted_count--; - - if (!junk && !deleted) - folder->summary->visible_count--; - - folder->summary->saved_count--; - } seq = i + 1 - del; del++; g_array_append_val (removed, seq); @@ -1205,49 +1196,18 @@ imap_rescan (CamelFolder *folder, continue; } - g_free (uid); - /* Update summary flags */ if (new[j].flags != iinfo->server_flags) { guint32 server_set, server_cleared; - gint read = 0, deleted = 0, junk = 0; server_set = new[j].flags & ~iinfo->server_flags; server_cleared = iinfo->server_flags & ~new[j].flags; - if (server_set & CAMEL_MESSAGE_SEEN) - read = 1; - else if (server_cleared & CAMEL_MESSAGE_SEEN) - read = -1; - - if (server_set & CAMEL_MESSAGE_DELETED) - deleted = 1; - else if (server_cleared & CAMEL_MESSAGE_DELETED) - deleted = -1; - - if (server_set & CAMEL_MESSAGE_JUNK) - junk = 1; - else if (server_cleared & CAMEL_MESSAGE_JUNK) - junk = -1; - - d(printf("%s %s %s %s\n", iinfo->info.uid, read == 1 ? "read" : ( read == -1 ? "unread" : ""), - deleted == 1 ? "deleted" : ( deleted == -1 ? "undeleted" : ""), - junk == 1 ? "junk" : ( junk == -1 ? "unjunked" : ""))); - - if (read) - folder->summary->unread_count -= read; - if (deleted) - folder->summary->deleted_count += deleted; - if (junk) - folder->summary->junk_count += junk; - if (junk && !deleted) - folder->summary->junk_not_deleted_count += junk; - if (junk || deleted) - folder->summary->visible_count -= junk ? junk : deleted; - - iinfo->info.flags = (iinfo->info.flags | server_set) & ~server_cleared; + camel_message_info_set_flags ((CamelMessageInfo *) iinfo, server_set | server_cleared, (iinfo->info.flags | server_set) & ~server_cleared); iinfo->server_flags = new[j].flags; + /* unset folder_flagged, because these are flags received froma server */ + iinfo->info.flags = iinfo->info.flags & (~CAMEL_MESSAGE_FOLDER_FLAGGED); iinfo->info.dirty = TRUE; if (info->summary) camel_folder_summary_touch (info->summary); @@ -1297,41 +1257,8 @@ imap_rescan (CamelFolder *folder, */ for (i = seq; i <= summary_len; i++) { - CamelMessageInfoBase *dinfo; gint j; - dinfo = (CamelMessageInfoBase *) camel_folder_summary_index (folder->summary, i - 1); - if (dinfo) { - /* these will be deleted from db in a moment. So adjust the counts please */ - gint unread = 0, deleted = 0, junk = 0; - guint32 flags; - - flags = dinfo->flags; - if (!(flags & CAMEL_MESSAGE_SEEN)) - unread = 1; - if (flags & CAMEL_MESSAGE_DELETED) - deleted = 1; - - if (flags & CAMEL_MESSAGE_JUNK) - junk = 1; - - if (unread) - folder->summary->unread_count--; - - if (deleted) - folder->summary->deleted_count--; - if (junk) - folder->summary->junk_count--; - - if (junk && !deleted) - folder->summary->junk_not_deleted_count--; - - if (!junk && !deleted) - folder->summary->visible_count--; - - folder->summary->saved_count--; - camel_message_info_free (dinfo); - } j = seq - del; g_array_append_val (removed, j); } @@ -1341,6 +1268,7 @@ imap_rescan (CamelFolder *folder, folder, exists, removed, cancellable, error); g_array_free (removed, TRUE); + camel_folder_summary_free_array (known_uids); return success; } @@ -1413,7 +1341,7 @@ get_matching (CamelFolder *folder, uid = summary->pdata[i]; if (uid) { - info = (CamelImapMessageInfo *) camel_folder_summary_uid (folder->summary, uid); + info = (CamelImapMessageInfo *) camel_folder_summary_get (folder->summary, uid); } else continue; @@ -1541,9 +1469,9 @@ imap_sync_offline (CamelFolder *folder, full_name = camel_folder_get_full_name (folder); si = camel_store_summary_path ((CamelStoreSummary *)((CamelImapStore *) parent_store)->summary, full_name); if (si) { - if (si->total != folder->summary->saved_count || si->unread != folder->summary->unread_count) { - si->total = folder->summary->saved_count; - si->unread = folder->summary->unread_count; + if (si->total != camel_folder_summary_get_saved_count (folder->summary) || si->unread != camel_folder_summary_get_unread_count (folder->summary)) { + si->total = camel_folder_summary_get_saved_count (folder->summary); + si->unread = camel_folder_summary_get_unread_count (folder->summary); camel_store_summary_touch ((CamelStoreSummary *)((CamelImapStore *) parent_store)->summary); } @@ -1720,7 +1648,7 @@ imap_synchronize_sync (CamelFolder *folder, if (!uid) /* Possibly it was sync by matching flags, which we NULLify */ continue; - if (!(info = (CamelImapMessageInfo *) camel_folder_summary_uid (folder->summary, uid))) { + if (!(info = (CamelImapMessageInfo *) camel_folder_summary_get (folder->summary, uid))) { continue; } @@ -1922,7 +1850,7 @@ imap_expunge_uids_offline (CamelFolder *folder, changes = camel_folder_change_info_new (); for (i = 0; i < uids->len; i++) { - camel_folder_summary_remove_uid_fast (folder->summary, uids->pdata[i]); + camel_folder_summary_remove_uid (folder->summary, uids->pdata[i]); camel_folder_change_info_remove_uid (changes, uids->pdata[i]); list = g_list_prepend (list, (gpointer) uids->pdata[i]); /* We intentionally don't remove it from the cache because @@ -2025,7 +1953,7 @@ imap_expunge_uids_online (CamelFolder *folder, changes = camel_folder_change_info_new (); for (i = 0; i < uids->len; i++) { - camel_folder_summary_remove_uid_fast (folder->summary, uids->pdata[i]); + camel_folder_summary_remove_uid (folder->summary, uids->pdata[i]); camel_folder_change_info_remove_uid (changes, uids->pdata[i]); list = g_list_prepend (list, (gpointer) uids->pdata[i]); /* We intentionally don't remove it from the cache because @@ -2050,7 +1978,7 @@ imap_expunge_sync (CamelFolder *folder, CamelStore *parent_store; GPtrArray *uids = NULL; const gchar *full_name; - gboolean success; + gboolean success, real_trash = FALSE; full_name = camel_folder_get_full_name (folder); parent_store = camel_folder_get_parent_store (folder); @@ -2066,7 +1994,8 @@ imap_expunge_sync (CamelFolder *folder, if (local_error == NULL && trash && (folder == trash || g_ascii_strcasecmp (full_name, camel_folder_get_full_name (trash)) == 0)) { /* it's a real trash folder, thus get all mails from there */ - uids = camel_folder_summary_array (folder->summary); + real_trash = TRUE; + uids = camel_folder_summary_get_array (folder->summary); } if (local_error != NULL) @@ -2086,8 +2015,12 @@ imap_expunge_sync (CamelFolder *folder, success = imap_expunge_uids_offline ( folder, uids, cancellable, error); - g_ptr_array_foreach (uids, (GFunc) camel_pstring_free, NULL); - g_ptr_array_free (uids, TRUE); + if (real_trash) { + camel_folder_summary_free_array (uids); + } else { + g_ptr_array_foreach (uids, (GFunc) camel_pstring_free, NULL); + g_ptr_array_free (uids, TRUE); + } return success; } @@ -2616,7 +2549,7 @@ imap_transfer_offline (CamelFolder *source, destuid = get_temp_uid (); - mi = camel_folder_summary_uid (source->summary, uid); + mi = camel_folder_summary_get (source->summary, uid); g_return_val_if_fail (mi != NULL, FALSE); message = camel_folder_get_message_sync ( @@ -2892,7 +2825,7 @@ do_copy (CamelFolder *source, camel_folder_delete_message ( source, uids->pdata[i]); if (mark_moved) { - CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_uid (source->summary, uids->pdata[i]); + CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_get (source->summary, uids->pdata[i]); if (info) info->flags |= CAMEL_MESSAGE_IMAP_MOVED; @@ -3515,7 +3448,7 @@ imap_folder_summary_uid_or_error (CamelFolderSummary *summary, GError **error) { CamelImapMessageInfo *mi; - mi = (CamelImapMessageInfo *) camel_folder_summary_uid (summary, uid); + mi = (CamelImapMessageInfo *) camel_folder_summary_get (summary, uid); if (mi == NULL) { g_set_error ( error, CAMEL_FOLDER_ERROR, @@ -3570,7 +3503,7 @@ imap_get_message_sync (CamelFolder *folder, || store->braindamaged || mi->info.size < IMAP_SMALL_BODY_SIZE || (!content_info_incomplete (mi->info.content) && !mi->info.content->childs)) { - CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_uid (folder->summary, uid); + CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_get (folder->summary, uid); msg = get_message_simple (imap_folder, uid, NULL, cancellable, &local_error); if (info && !info->preview && msg && camel_folder_summary_get_need_preview (folder->summary)) { if (camel_mime_message_build_preview ((CamelMimePart *) msg, (CamelMessageInfo *) info) && info->preview) @@ -3650,7 +3583,7 @@ imap_get_message_sync (CamelFolder *folder, else msg = get_message (imap_folder, uid, mi->info.content, cancellable, &local_error); if (msg && camel_folder_summary_get_need_preview (folder->summary)) { - CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_uid (folder->summary, uid); + CamelMessageInfoBase *info = (CamelMessageInfoBase *) camel_folder_summary_get (folder->summary, uid); if (info && !info->preview) { if (camel_mime_message_build_preview ((CamelMimePart *) msg, (CamelMessageInfo *) info) && info->preview) camel_folder_summary_add_preview (folder->summary, (CamelMessageInfo *) info); @@ -3950,41 +3883,6 @@ construct_junk_headers (gchar *header, } } -static void -update_summary (CamelFolderSummary *summary, - CamelMessageInfoBase *info) -{ - gint unread = 0, deleted = 0, junk = 0; - guint32 flags = info->flags; - - if (!(flags & CAMEL_MESSAGE_SEEN)) - unread = 1; - - if (flags & CAMEL_MESSAGE_DELETED) - deleted = 1; - - if (flags & CAMEL_MESSAGE_JUNK) - junk = 1; - - if (summary) { - - if (unread) - summary->unread_count += unread; - if (deleted) - summary->deleted_count += deleted; - if (junk) - summary->junk_count += junk; - if (junk && !deleted) - summary->junk_not_deleted_count += junk; - summary->visible_count++; - if (junk || deleted) - summary->visible_count -= junk ? junk : deleted; - - summary->saved_count++; - camel_folder_summary_touch (summary); - } -} - #define CAMEL_MESSAGE_INFO_HEADERS "DATE FROM TO CC SUBJECT REFERENCES IN-REPLY-TO MESSAGE-ID MIME-VERSION CONTENT-TYPE CONTENT-CLASS X-CALENDAR-ATTACHMENT " /* FIXME: this needs to be kept in sync with camel-mime-utils.c's list @@ -4067,11 +3965,19 @@ imap_update_summary (CamelFolder *folder, seq = camel_folder_summary_count (folder->summary); first = seq + 1; if (seq > 0) { - tempuid = camel_folder_summary_uid_from_index (folder->summary, seq -1 ); + GPtrArray *known_uids; - if (tempuid) { - uidval = strtoul (tempuid, NULL, 10); - g_free (tempuid); + known_uids = camel_folder_summary_get_array (folder->summary); + if (known_uids) { + camel_folder_sort_uids (folder, known_uids); + + tempuid = g_ptr_array_index (known_uids, seq - 1); + if (tempuid) + uidval = strtoul (tempuid, NULL, 10); + else + uidval = 0; + + camel_folder_summary_free_array (known_uids); } else uidval = 0; } else @@ -4322,7 +4228,7 @@ imap_update_summary (CamelFolder *folder, /* FIXME: If it enters if (info) it will always match the exception. So stupid */ /* FIXME[disk-summary] Use a db query to see if the DB exists */ -/* info = (CamelImapMessageInfo *)camel_folder_summary_uid(folder->summary, uid); */ +/* info = (CamelImapMessageInfo *)camel_folder_summary_get (folder->summary, uid); */ /* if (info) { */ /* for (seq = 0; seq < camel_folder_summary_count (folder->summary); seq++) { */ /* if (folder->summary->messages->pdata[seq] == info) */ @@ -4333,7 +4239,6 @@ imap_update_summary (CamelFolder *folder, if (((CamelMessageInfoBase *) mi)->summary) camel_folder_summary_touch (((CamelMessageInfoBase *) mi)->summary); camel_folder_summary_add (folder->summary, (CamelMessageInfo *) mi); - update_summary (folder->summary, (CamelMessageInfoBase *) mi); camel_folder_change_info_add_uid (changes, camel_message_info_uid (mi)); /* Report all new messages as recent, even without that flag, thus new @@ -4389,7 +4294,6 @@ camel_imap_folder_changed (CamelFolder *folder, CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); CamelFolderChangeInfo *changes; gint len; - gchar *uid; gboolean success = TRUE; changes = camel_folder_change_info_new (); @@ -4398,30 +4302,35 @@ camel_imap_folder_changed (CamelFolder *folder, gint i, id; GList *deleted = NULL; const gchar *full_name; + const gchar *uid; + GPtrArray *known_uids; + known_uids = camel_folder_summary_get_array (folder->summary); + camel_folder_sort_uids (folder, known_uids); for (i = 0; i < expunged->len; i++) { id = g_array_index (expunged, int, i); - uid = camel_folder_summary_uid_from_index (folder->summary, id - 1); + uid = id - 1 + i >= 0 && id - 1 + i < known_uids->len ? g_ptr_array_index (known_uids, id - 1 + i) : NULL; if (uid == NULL) { /* FIXME: danw: does this mean that the summary is corrupt? */ /* I guess a message that we never retrieved got expunged? */ continue; } - deleted = g_list_prepend (deleted, uid); + deleted = g_list_prepend (deleted, (gpointer) uid); camel_folder_change_info_remove_uid (changes, uid); CAMEL_IMAP_FOLDER_REC_LOCK (imap_folder, cache_lock); camel_imap_message_cache_remove (imap_folder->cache, uid); CAMEL_IMAP_FOLDER_REC_UNLOCK (imap_folder, cache_lock); - camel_folder_summary_remove_index_fast (folder->summary, id - 1); + camel_folder_summary_remove_uid (folder->summary, uid); } /* Delete all in one transaction */ full_name = camel_folder_get_full_name (folder); parent_store = camel_folder_get_parent_store (folder); camel_db_delete_uids (parent_store->cdb_w, full_name, deleted, NULL); - g_list_foreach (deleted, (GFunc) g_free, NULL); g_list_free (deleted); + + camel_folder_summary_free_array (known_uids); } len = camel_folder_summary_count (folder->summary); diff --git a/camel/providers/imap/camel-imap-message-cache.c b/camel/providers/imap/camel-imap-message-cache.c index 8a121a4..be9ec8f 100644 --- a/camel/providers/imap/camel-imap-message-cache.c +++ b/camel/providers/imap/camel-imap-message-cache.c @@ -190,7 +190,6 @@ camel_imap_message_cache_new (const gchar *path, const gchar *dname; gchar *uid, *p; GPtrArray *deletes; - GHashTable *shash; dir = g_dir_open (path, 0, error); if (!dir) { @@ -204,7 +203,6 @@ camel_imap_message_cache_new (const gchar *path, cache->parts = g_hash_table_new (g_str_hash, g_str_equal); cache->cached = g_hash_table_new (NULL, NULL); deletes = g_ptr_array_new (); - shash = camel_folder_summary_get_hashtable (summary); while ((dname = g_dir_read_name (dir))) { if (!isdigit (dname[0])) @@ -215,7 +213,7 @@ camel_imap_message_cache_new (const gchar *path, else uid = g_strdup (dname); - if (g_hash_table_lookup (shash, uid)) + if (camel_folder_summary_check_uid (summary, uid)) cache_put (cache, uid, dname, NULL); else g_ptr_array_add (deletes, g_strdup_printf ("%s/%s", cache->path, dname)); @@ -231,8 +229,6 @@ camel_imap_message_cache_new (const gchar *path, } g_ptr_array_free (deletes, TRUE); - camel_folder_summary_free_hashtable (shash); - return cache; } diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index 4aa299a..7838b1c 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -1654,19 +1654,24 @@ static gboolean imap_summary_is_dirty (CamelFolderSummary *summary) { CamelImapMessageInfo *info; - gint max, i; - gint found = FALSE; + gint i; + gboolean found = FALSE; + GPtrArray *known_uids; + + known_uids = camel_folder_summary_get_array (summary); + g_return_val_if_fail (known_uids != NULL, FALSE); - max = camel_folder_summary_count (summary); - for (i = 0; i < max && !found; i++) { - info = (CamelImapMessageInfo *) camel_folder_summary_index (summary, i); + for (i = 0; i < known_uids->len && !found; i++) { + info = (CamelImapMessageInfo *) camel_folder_summary_get (summary, g_ptr_array_index (known_uids, i)); if (info) { found = info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED; camel_message_info_free (info); } } - return FALSE; + camel_folder_summary_free_array (known_uids); + + return found; } static gboolean @@ -2878,8 +2883,8 @@ fill_fi (CamelStore *store, else ims = (CamelImapSummary *) camel_imap_summary_new (folder, NULL); - fi->unread = ((CamelFolderSummary *) ims)->unread_count; - fi->total = ((CamelFolderSummary *) ims)->saved_count; + fi->unread = camel_folder_summary_get_unread_count ((CamelFolderSummary *) ims); + fi->total = camel_folder_summary_get_saved_count ((CamelFolderSummary *) ims); if (!folder->summary) g_object_unref (ims); @@ -3172,27 +3177,6 @@ get_folder_info_offline (CamelStore *store, return fi; } -#if 0 -static gboolean -folder_flags_have_changed (CamelFolder *folder) -{ - CamelMessageInfo *info; - gint i, max; - - max = camel_folder_summary_count (folder->summary); - for (i = 0; i < max; i++) { - info = camel_folder_summary_index (folder->summary, i); - if (!info) - continue; - if (info->flags & CAMEL_MESSAGE_FOLDER_FLAGGED) { - return TRUE; - } - } - - return FALSE; -} -#endif - /* Use this whenever you need to ensure you're both connected and * online. */ gboolean diff --git a/camel/providers/imap/camel-imap-summary.c b/camel/providers/imap/camel-imap-summary.c index c1098dc..fc32104 100644 --- a/camel/providers/imap/camel-imap-summary.c +++ b/camel/providers/imap/camel-imap-summary.c @@ -43,11 +43,11 @@ static CamelMessageInfo *message_info_migrate (CamelFolderSummary *s, FILE *in); static gboolean info_set_user_flag (CamelMessageInfo *info, const gchar *id, gboolean state); static CamelMessageContentInfo *content_info_migrate (CamelFolderSummary *s, FILE *in); -static gint summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir); +static gboolean summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir); static CamelFIRecord * summary_header_to_db (CamelFolderSummary *s, GError **error); static CamelMIRecord * message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info); static CamelMessageInfo * message_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir); -static gint content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir); +static gboolean content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir); static CamelMessageContentInfo * content_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir); G_DEFINE_TYPE (CamelImapSummary, camel_imap_summary, CAMEL_TYPE_FOLDER_SUMMARY) @@ -123,23 +123,6 @@ sort_uid_cmp (gpointer enc, return (a1 < a1) ? -1 : (a1 > a2) ? 1 : 0; } -static gint -uid_compare (gconstpointer va, - gconstpointer vb) -{ - const gchar **sa = (const gchar **) va, **sb = (const gchar **) vb; - gulong a, b; - - a = strtoul (*sa, NULL, 10); - b = strtoul (*sb, NULL, 10); - if (a < b) - return -1; - else if (a == b) - return 0; - else - return 1; -} - /** * camel_imap_summary_new: * @folder: Parent folder. @@ -159,8 +142,8 @@ camel_imap_summary_new (CamelFolder *folder, parent_store = camel_folder_get_parent_store (folder); - summary = g_object_new (CAMEL_TYPE_IMAP_SUMMARY, NULL); - summary->folder = folder; + summary = g_object_new (CAMEL_TYPE_IMAP_SUMMARY, "folder", folder, NULL); + /* Don't do DB sort. Its pretty slow to load */ if (folder && 0) { camel_db_set_collate ( @@ -173,27 +156,25 @@ camel_imap_summary_new (CamelFolder *folder, camel_folder_summary_set_build_content (summary, TRUE); camel_folder_summary_set_filename (summary, filename); - if (camel_folder_summary_load_from_db (summary, NULL) == -1) { + if (!camel_folder_summary_load_from_db (summary, NULL)) { /* FIXME: Isn't this dangerous ? We clear the summary if it cannot be loaded, for some random reason. We need to pass the ex and find out why it is not loaded etc. ? */ - camel_folder_summary_clear_db (summary); + camel_folder_summary_clear (summary, NULL); } - g_ptr_array_sort (summary->uids, (GCompareFunc) uid_compare); - return summary; } -static gint +static gboolean summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir) { CamelImapSummary *ims = CAMEL_IMAP_SUMMARY (s); gchar *part; - if (CAMEL_FOLDER_SUMMARY_CLASS (camel_imap_summary_parent_class)->summary_header_from_db (s, mir) == -1) - return -1; + if (!CAMEL_FOLDER_SUMMARY_CLASS (camel_imap_summary_parent_class)->summary_header_from_db (s, mir)) + return FALSE; part = mir->bdata; @@ -203,10 +184,10 @@ summary_header_from_db (CamelFolderSummary *s, if (ims->version > CAMEL_IMAP_SUMMARY_VERSION) { g_warning("Unkown summary version\n"); errno = EINVAL; - return -1; + return FALSE; } - return 0; + return TRUE; } static gint @@ -375,7 +356,7 @@ content_info_migrate (CamelFolderSummary *s, return camel_folder_summary_content_info_new (s); } -static gint +static gboolean content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir) @@ -390,7 +371,7 @@ content_info_to_db (CamelFolderSummary *s, oldr = mir->cinfo; mir->cinfo = oldr ? g_strdup_printf("%s 0", oldr) : g_strdup ("0"); g_free (oldr); - return 0; + return TRUE; } } diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c index 5c47f3a..de74c6c 100644 --- a/camel/providers/imap/camel-imap-utils.c +++ b/camel/providers/imap/camel-imap-utils.c @@ -1187,15 +1187,18 @@ imap_quote_string (const gchar *str) } static inline gulong -get_summary_uid_numeric (CamelFolderSummary *summary, +get_summary_uid_numeric (GPtrArray *known_uids, gint index) { gulong uid; - gchar *suid; + const gchar *suid; - suid = camel_folder_summary_uid_from_index (summary, index); + g_return_val_if_fail (known_uids != NULL, 0); + g_return_val_if_fail (index >= 0, 0); + g_return_val_if_fail (index < known_uids->len, 0); + + suid = g_ptr_array_index (known_uids, index); uid = strtoul (suid, NULL, 10); - g_free (suid); return uid; } @@ -1235,20 +1238,26 @@ imap_uid_array_to_set (CamelFolderSummary *summary, gint si, scount; GString *gset; gchar *set; + GPtrArray *known_uids; g_return_val_if_fail (uids->len > uid, NULL); + known_uids = camel_folder_summary_get_array (summary); + g_return_val_if_fail (known_uids != NULL, NULL); + + camel_folder_sort_uids (camel_folder_summary_get_folder (summary), known_uids); + gset = g_string_new (uids->pdata[uid]); last_uid = strtoul (uids->pdata[uid], NULL, 10); next_summary_uid = 0; - scount = camel_folder_summary_count (summary); + scount = known_uids->len; for (uid++, si = 0; uid < uids->len && !UID_SET_FULL (gset->len, maxlen); uid++) { /* Find the next UID in the summary after the one we * just wrote out. */ for (; last_uid >= next_summary_uid && si < scount; si++) - next_summary_uid = get_summary_uid_numeric (summary, si); + next_summary_uid = get_summary_uid_numeric (known_uids, si); if (last_uid >= next_summary_uid) next_summary_uid = (gulong) -1; @@ -1274,6 +1283,7 @@ imap_uid_array_to_set (CamelFolderSummary *summary, set = gset->str; g_string_free (gset, FALSE); + camel_folder_summary_free_array (known_uids); return set; } @@ -1299,10 +1309,15 @@ imap_uid_set_to_array (CamelFolderSummary *summary, const gchar *uids) { GPtrArray *arr; + GPtrArray *known_uids; gchar *p, *q; gulong uid, suid; gint si, scount; + known_uids = camel_folder_summary_get_array (summary); + g_return_val_if_fail (known_uids != NULL, NULL); + + camel_folder_sort_uids (camel_folder_summary_get_folder (summary), known_uids); arr = g_ptr_array_new (); scount = camel_folder_summary_count (summary); @@ -1319,7 +1334,7 @@ imap_uid_set_to_array (CamelFolderSummary *summary, * we just saw. */ while (++si < scount) { - suid = get_summary_uid_numeric (summary, si); + suid = get_summary_uid_numeric (known_uids, si); if (suid > uid) break; } @@ -1336,7 +1351,7 @@ imap_uid_set_to_array (CamelFolderSummary *summary, while (suid <= uid) { g_ptr_array_add (arr, g_strdup_printf ("%lu", suid)); if (++si < scount) - suid = get_summary_uid_numeric (summary, si); + suid = get_summary_uid_numeric (known_uids, si); else suid++; } @@ -1344,10 +1359,12 @@ imap_uid_set_to_array (CamelFolderSummary *summary, p = q; } while (*p++ == ','); + camel_folder_summary_free_array (known_uids); return arr; lose: g_warning ("Invalid uid set %s", uids); + camel_folder_summary_free_array (known_uids); imap_uid_array_free (arr); return NULL; } diff --git a/camel/providers/imapx/camel-imapx-folder.c b/camel/providers/imapx/camel-imapx-folder.c index 11c3cec..bffcb00 100644 --- a/camel/providers/imapx/camel-imapx-folder.c +++ b/camel/providers/imapx/camel-imapx-folder.c @@ -125,6 +125,10 @@ camel_imapx_folder_new (CamelStore *store, g_free (summary_file); + camel_store_summary_connect_folder_summary ( + (CamelStoreSummary *) ((CamelIMAPXStore *) store)->summary, + folder_name, folder->summary); + return folder; } @@ -132,6 +136,7 @@ static void imapx_folder_dispose (GObject *object) { CamelIMAPXFolder *folder = CAMEL_IMAPX_FOLDER (object); + CamelStore *parent_store; if (folder->cache != NULL) { g_object_unref (folder->cache); @@ -143,6 +148,13 @@ imapx_folder_dispose (GObject *object) folder->search = NULL; } + parent_store = camel_folder_get_parent_store (CAMEL_FOLDER (folder)); + if (parent_store) { + camel_store_summary_disconnect_folder_summary ( + (CamelStoreSummary *) ((CamelIMAPXStore *) parent_store)->summary, + CAMEL_FOLDER (folder)->summary); + } + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (camel_imapx_folder_parent_class)->dispose (object); } diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c index a1caa17..430d6f1 100644 --- a/camel/providers/imapx/camel-imapx-server.c +++ b/camel/providers/imapx/camel-imapx-server.c @@ -1252,7 +1252,6 @@ imapx_expunge_uid_from_summary (CamelIMAPXServer *imap, gchar *uid, gboolean unsolicited) { - CamelMessageInfo *mi; CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) imap->select_folder; if (unsolicited && ifolder->exists_on_server) @@ -1261,13 +1260,7 @@ imapx_expunge_uid_from_summary (CamelIMAPXServer *imap, if (imap->changes == NULL) imap->changes = camel_folder_change_info_new (); - mi = camel_folder_summary_uid (imap->select_folder->summary, uid); - if (mi) { - imapx_update_summary_for_removed_message (mi, imap->select_folder, unsolicited); - camel_message_info_free (mi); - } - - camel_folder_summary_remove_uid_fast (imap->select_folder->summary, uid); + camel_folder_summary_remove_uid (imap->select_folder->summary, uid); imap->expunged = g_list_prepend (imap->expunged, uid); camel_folder_change_info_remove_uid (imap->changes, uid); @@ -1287,6 +1280,27 @@ imapx_expunge_uid_from_summary (CamelIMAPXServer *imap, } } +static gchar * +imapx_get_uid_from_index (CamelFolderSummary *summary, guint id) +{ + GPtrArray *array; + gchar *uid; + + g_return_val_if_fail (summary != NULL, NULL); + + array = camel_folder_summary_get_array (summary); + g_return_val_if_fail (array != NULL, NULL); + + if (id < array->len) { + camel_folder_sort_uids (camel_folder_summary_get_folder (summary), array); + uid = g_strdup (g_ptr_array_index (array, id)); + } + + camel_folder_summary_free_array (array); + + return uid; +} + static void invalidate_local_cache (CamelIMAPXFolder *ifolder, guint64 new_uidvalidity) @@ -1303,7 +1317,7 @@ invalidate_local_cache (CamelIMAPXFolder *ifolder, changes = camel_folder_change_info_new (); - uids = camel_folder_summary_array (cfolder->summary); + uids = camel_folder_summary_get_array (cfolder->summary); for (ii = 0; uids && ii < uids->len; ii++) { const gchar *uid = uids->pdata[ii]; @@ -1311,8 +1325,7 @@ invalidate_local_cache (CamelIMAPXFolder *ifolder, camel_folder_change_info_change_uid (changes, uid); } - g_ptr_array_foreach (uids, (GFunc) camel_pstring_free, NULL); - g_ptr_array_free (uids, TRUE); + camel_folder_summary_free_array (uids); CAMEL_IMAPX_SUMMARY (cfolder->summary)->validity = new_uidvalidity; camel_folder_summary_touch (cfolder->summary); @@ -1392,11 +1405,12 @@ imapx_untagged (CamelIMAPXServer *imap, if (imap->select_folder) { gchar *uid = NULL; - uid = camel_folder_summary_uid_from_index (imap->select_folder->summary, expunge - 1); + uid = imapx_get_uid_from_index (imap->select_folder->summary, expunge - 1); if (!uid) break; imapx_expunge_uid_from_summary (imap, uid, TRUE); + g_free (uid); } break; @@ -1534,11 +1548,11 @@ imapx_untagged (CamelIMAPXServer *imap, uid = finfo->uid; finfo->uid = NULL; } else { - uid = camel_folder_summary_uid_from_index (folder->summary, id - 1); + uid = imapx_get_uid_from_index (folder->summary, id - 1); } if (uid) { - mi = camel_folder_summary_uid (folder->summary, uid); + mi = camel_folder_summary_get (folder->summary, uid); if (mi) { /* It's unsolicited _unless_ imap->select_pending (i.e. during * a QRESYNC SELECT */ @@ -2744,8 +2758,8 @@ imapx_select (CamelIMAPXServer *is, if (total && isum->modseq && ifolder->uidvalidity_on_server) { - firstuid = camel_folder_summary_uid_from_index (folder->summary, 0); - lastuid = camel_folder_summary_uid_from_index (folder->summary, total - 1); + firstuid = imapx_get_uid_from_index (folder->summary, 0); + lastuid = imapx_get_uid_from_index (folder->summary, total - 1); c(is->tagprefix, "SELECT QRESYNC %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT "\n", @@ -2790,7 +2804,7 @@ imapx_select (CamelIMAPXServer *is, * the summary starts from zero. */ sprintf(buf, "%d", total - i + 1); g_string_prepend (seqs, buf); - uid = camel_folder_summary_uid_from_index (folder->summary, total - i); + uid = imapx_get_uid_from_index (folder->summary, total - i); g_string_prepend (uids, uid); g_free (uid); } while (i < total); @@ -3757,7 +3771,7 @@ imapx_index_next (GPtrArray *uids, if (index >= uids->len) break; - info = camel_folder_summary_uid (s, g_ptr_array_index (uids, index)); + info = camel_folder_summary_get (s, g_ptr_array_index (uids, index)); if (!info) continue; @@ -3831,8 +3845,8 @@ imapx_command_step_fetch_done (CamelIMAPXServer *is, } if (camel_folder_summary_count (job->folder->summary)) { - gchar *uid = camel_folder_summary_uid_from_index (job->folder->summary, - camel_folder_summary_count (job->folder->summary) - 1); + gchar *uid = imapx_get_uid_from_index (job->folder->summary, + camel_folder_summary_count (job->folder->summary) - 1); guint64 uidl = strtoull (uid, NULL, 10); g_free (uid); @@ -3930,13 +3944,13 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is, * for all outstanding messages to be uploaded */ /* obtain a copy to be thread safe */ - uids = camel_folder_summary_array (s); + uids = camel_folder_summary_get_array (s); qsort (infos->data, infos->len, sizeof (struct _refresh_info), imapx_refresh_info_cmp); g_ptr_array_sort (uids, (GCompareFunc) imapx_uids_array_cmp); if (uids->len) - s_minfo = camel_folder_summary_uid (s, g_ptr_array_index (uids, 0)); + s_minfo = camel_folder_summary_get (s, g_ptr_array_index (uids, 0)); for (i = 0; i < infos->len; i++) { struct _refresh_info *r = &g_array_index (infos, struct _refresh_info, i); @@ -3951,7 +3965,7 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is, j = imapx_index_next (uids, s, j); if (j < uids->len) - s_minfo = camel_folder_summary_uid (s, g_ptr_array_index (uids, j)); + s_minfo = camel_folder_summary_get (s, g_ptr_array_index (uids, j)); } info = NULL; @@ -3974,14 +3988,14 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is, j = imapx_index_next (uids, s, j); if (j < uids->len) - s_minfo = camel_folder_summary_uid (s, g_ptr_array_index (uids, j)); + s_minfo = camel_folder_summary_get (s, g_ptr_array_index (uids, j)); } if (s_minfo) camel_message_info_free (s_minfo); while (j < uids->len) { - s_minfo = camel_folder_summary_uid (s, g_ptr_array_index (uids, j)); + s_minfo = camel_folder_summary_get (s, g_ptr_array_index (uids, j)); if (!s_minfo) { j++; @@ -3996,22 +4010,15 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is, for (l = removed; l != NULL; l = g_list_next (l)) { gchar *uid = (gchar *) l->data; - CamelMessageInfo *mi; - - mi = camel_folder_summary_uid (job->folder->summary, uid); - if (mi) { - imapx_update_summary_for_removed_message (mi, job->folder, FALSE); - camel_message_info_free (mi); - } camel_folder_change_info_remove_uid (job->u.refresh_info.changes, uid); - camel_folder_summary_remove_uid_fast (s, uid); + camel_folder_summary_remove_uid (s, uid); } if (removed) { const gchar *full_name; - full_name = camel_folder_get_full_name (s->folder); + full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (s)); camel_db_delete_uids (is->store->cdb_w, full_name, removed, NULL); g_list_foreach (removed, (GFunc) g_free, NULL); g_list_free (removed); @@ -4023,7 +4030,7 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is, camel_folder_changed (job->folder, job->u.refresh_info.changes); camel_folder_change_info_clear (job->u.refresh_info.changes); - camel_folder_free_uids (job->folder, uids); + camel_folder_summary_free_array (uids); /* If we have any new messages, download their headers, but only a few (100?) at a time */ if (fetch_new) { @@ -4056,7 +4063,7 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is, /* There's no sane way to get the server-side unseen count on the * select mailbox. So just work it out from the flags */ - ((CamelIMAPXFolder *) job->folder)->unread_on_server = job->folder->summary->unread_count; + ((CamelIMAPXFolder *) job->folder)->unread_on_server = camel_folder_summary_get_unread_count (job->folder->summary); g_array_free (job->u.refresh_info.infos, TRUE); imapx_job_done (is, job); @@ -4108,8 +4115,8 @@ imapx_command_fetch_new_messages_done (CamelIMAPXServer *is, } if (camel_folder_summary_count (ic->job->folder->summary)) { - gchar *uid = camel_folder_summary_uid_from_index (ic->job->folder->summary, - camel_folder_summary_count (ic->job->folder->summary) - 1); + gchar *uid = imapx_get_uid_from_index (ic->job->folder->summary, + camel_folder_summary_count (ic->job->folder->summary) - 1); guint64 uidl = strtoull (uid, NULL, 10); g_free (uid); @@ -4170,7 +4177,7 @@ imapx_job_fetch_new_messages_start (CamelIMAPXServer *is, if (total > 0) { guint64 uidl; - uid = camel_folder_summary_uid_from_index (folder->summary, total - 1); + uid = imapx_get_uid_from_index (folder->summary, total - 1); uidl = strtoull (uid, NULL, 10); g_free (uid); uid = g_strdup_printf ("%" G_GUINT64_FORMAT, uidl+1); @@ -4250,7 +4257,7 @@ imapx_job_refresh_info_start (CamelIMAPXServer *is, * message flags, but don't depend on modseq for the selected folder */ if (total != ifolder->exists_on_server || isum->uidnext != ifolder->uidnext_on_server || - folder->summary->unread_count != ifolder->unread_on_server || + camel_folder_summary_get_unread_count (folder->summary) != ifolder->unread_on_server || (!is_selected && isum->modseq != ifolder->modseq_on_server)) need_rescan = TRUE; @@ -4309,7 +4316,7 @@ imapx_job_refresh_info_start (CamelIMAPXServer *is, /* Recalulate need_rescan */ if (total != ifolder->exists_on_server || isum->uidnext != ifolder->uidnext_on_server || - folder->summary->unread_count != ifolder->unread_on_server || + camel_folder_summary_get_unread_count (folder->summary) != ifolder->unread_on_server || (!is_selected && isum->modseq != ifolder->modseq_on_server)) need_rescan = TRUE; @@ -4320,7 +4327,7 @@ imapx_job_refresh_info_start (CamelIMAPXServer *is, e(is->tagprefix, "folder %s is %sselected, total %u / %u, unread %u / %u, modseq %" G_GUINT64_FORMAT " / %" G_GUINT64_FORMAT ", uidnext %u / %u: will %srescan\n", full_name, is_selected?"": "not ", total, ifolder->exists_on_server, - folder->summary->unread_count, ifolder->unread_on_server, + camel_folder_summary_get_unread_count (folder->summary), ifolder->unread_on_server, (guint64) isum->modseq, (guint64) ifolder->modseq_on_server, isum->uidnext, ifolder->uidnext_on_server, need_rescan?"":"not "); @@ -4352,16 +4359,16 @@ imapx_job_refresh_info_start (CamelIMAPXServer *is, isum->modseq = ifolder->modseq_on_server; total = camel_folder_summary_count (job->folder->summary); if (total != ifolder->exists_on_server || - folder->summary->unread_count != ifolder->unread_on_server || + camel_folder_summary_get_unread_count (folder->summary) != ifolder->unread_on_server || (isum->modseq != ifolder->modseq_on_server)) { c(is->tagprefix, "Eep, after QRESYNC we're out of sync. total %u / %u, unread %u / %u, modseq %" G_GUINT64_FORMAT " / %" G_GUINT64_FORMAT "\n", total, ifolder->exists_on_server, - folder->summary->unread_count, ifolder->unread_on_server, + camel_folder_summary_get_unread_count (folder->summary), ifolder->unread_on_server, isum->modseq, ifolder->modseq_on_server); } else { c(is->tagprefix, "OK, after QRESYNC we're still in sync. total %u / %u, unread %u / %u, modseq %" G_GUINT64_FORMAT " / %" G_GUINT64_FORMAT "\n", total, ifolder->exists_on_server, - folder->summary->unread_count, ifolder->unread_on_server, + camel_folder_summary_get_unread_count (folder->summary), ifolder->unread_on_server, isum->modseq, ifolder->modseq_on_server); goto done; } @@ -4402,14 +4409,8 @@ imapx_command_expunge_done (CamelIMAPXServer *is, changes = camel_folder_change_info_new (); for (i = 0; i < uids->len; i++) { gchar *uid = uids->pdata[i]; - CamelMessageInfo *mi = camel_folder_summary_uid (folder->summary, uid); - - if (mi) { - imapx_update_summary_for_removed_message (mi, folder, FALSE); - camel_message_info_free (mi); - } - camel_folder_summary_remove_uid_fast (folder->summary, uid); + camel_folder_summary_remove_uid (folder->summary, uid); camel_folder_change_info_remove_uid (changes, uids->pdata[i]); removed = g_list_prepend (removed, (gpointer) uids->pdata[i]); } @@ -4753,7 +4754,7 @@ imapx_command_sync_changes_done (CamelIMAPXServer *is, gint i; for (i = 0; i < job->u.sync_changes.changed_uids->len; i++) { - CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) camel_folder_summary_uid (job->folder->summary, + CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) camel_folder_summary_get (job->folder->summary, job->u.sync_changes.changed_uids->pdata[i]); if (!xinfo) @@ -4779,9 +4780,10 @@ imapx_command_sync_changes_done (CamelIMAPXServer *is, /* ... and store's summary when folder's summary is dirty */ si = camel_store_summary_path ((CamelStoreSummary *)((CamelIMAPXStore *) parent_store)->summary, full_name); if (si) { - if (si->total != job->folder->summary->saved_count || si->unread != job->folder->summary->unread_count) { - si->total = job->folder->summary->saved_count; - si->unread = job->folder->summary->unread_count; + if (si->total != camel_folder_summary_get_saved_count (job->folder->summary) || + si->unread != camel_folder_summary_get_unread_count (job->folder->summary)) { + si->total = camel_folder_summary_get_saved_count (job->folder->summary); + si->unread = camel_folder_summary_get_unread_count (job->folder->summary); camel_store_summary_touch ((CamelStoreSummary *)((CamelIMAPXStore *) parent_store)->summary); } @@ -4820,7 +4822,7 @@ imapx_job_sync_changes_start (CamelIMAPXServer *is, c(is->tagprefix, "checking/storing %s flags '%s'\n", on?"on":"off", flags_table[j].name); imapx_uidset_init (&ss, 0, 100); for (i = 0; i < uids->len; i++) { - CamelIMAPXMessageInfo *info = (CamelIMAPXMessageInfo *) camel_folder_summary_uid + CamelIMAPXMessageInfo *info = (CamelIMAPXMessageInfo *) camel_folder_summary_get (job->folder->summary, uids->pdata[i]); guint32 flags; guint32 sflags; @@ -5348,7 +5350,7 @@ imapx_server_get_message (CamelIMAPXServer *is, return stream; } - mi = camel_folder_summary_uid (folder->summary, uid); + mi = camel_folder_summary_get (folder->summary, uid); if (!mi) { g_set_error ( error, CAMEL_FOLDER_ERROR, @@ -5678,7 +5680,7 @@ imapx_server_sync_changes (CamelIMAPXServer *is, CamelFlag *uflags, *suflags; guint j = 0; - info = (CamelIMAPXMessageInfo *) camel_folder_summary_uid (folder->summary, uids->pdata[i]); + info = (CamelIMAPXMessageInfo *) camel_folder_summary_get (folder->summary, uids->pdata[i]); if (!info) continue; diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c index 3f749c3..c9216d6 100644 --- a/camel/providers/imapx/camel-imapx-store.c +++ b/camel/providers/imapx/camel-imapx-store.c @@ -367,8 +367,8 @@ fill_fi (CamelStore *store, else ims = (CamelIMAPXSummary *) camel_imapx_summary_new (folder, NULL); - fi->unread = ((CamelFolderSummary *) ims)->unread_count; - fi->total = ((CamelFolderSummary *) ims)->saved_count; + fi->unread = camel_folder_summary_get_unread_count ((CamelFolderSummary *) ims); + fi->total = camel_folder_summary_get_saved_count ((CamelFolderSummary *) ims); if (!folder->summary) g_object_unref (ims); diff --git a/camel/providers/imapx/camel-imapx-summary.c b/camel/providers/imapx/camel-imapx-summary.c index a135101..874cd45 100644 --- a/camel/providers/imapx/camel-imapx-summary.c +++ b/camel/providers/imapx/camel-imapx-summary.c @@ -42,11 +42,11 @@ static CamelMessageInfo *message_info_migrate (CamelFolderSummary *s, FILE *in); static gboolean info_set_user_flag (CamelMessageInfo *info, const gchar *id, gboolean state); static CamelMessageContentInfo *content_info_migrate (CamelFolderSummary *s, FILE *in); -static gint summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir); +static gboolean summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir); static CamelFIRecord * summary_header_to_db (CamelFolderSummary *s, GError **error); static CamelMIRecord * message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info); static CamelMessageInfo * message_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir); -static gint content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir); +static gboolean content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir); static CamelMessageContentInfo * content_info_from_db (CamelFolderSummary *s, CamelMIRecord *mir); G_DEFINE_TYPE (CamelIMAPXSummary, camel_imapx_summary, CAMEL_TYPE_FOLDER_SUMMARY) @@ -127,23 +127,6 @@ sort_uid_cmp (gpointer enc, return (a1 < a1) ? -1 : (a1 > a2) ? 1 : 0; } -static gint -uid_compare (gconstpointer va, - gconstpointer vb) -{ - const gchar **sa = (const gchar **) va, **sb = (const gchar **) vb; - gulong a, b; - - a = strtoul (*sa, NULL, 10); - b = strtoul (*sb, NULL, 10); - if (a < b) - return -1; - else if (a == b) - return 0; - else - return 1; -} - /** * camel_imapx_summary_new: * @folder: Parent folder. @@ -164,9 +147,8 @@ camel_imapx_summary_new (CamelFolder *folder, parent_store = camel_folder_get_parent_store (folder); - summary = g_object_new (CAMEL_TYPE_IMAPX_SUMMARY, NULL); + summary = g_object_new (CAMEL_TYPE_IMAPX_SUMMARY, "folder", folder, NULL); - summary->folder = folder; /* Don't do DB sort. Its pretty slow to load */ if (folder && 0) { camel_db_set_collate (parent_store->cdb_r, "uid", "imapx_uid_sort", (CamelDBCollate)sort_uid_cmp); @@ -177,21 +159,19 @@ camel_imapx_summary_new (CamelFolder *folder, camel_folder_summary_set_build_content (summary, TRUE); camel_folder_summary_set_filename (summary, filename); - if (camel_folder_summary_load_from_db (summary, &local_error) == -1) { + if (!camel_folder_summary_load_from_db (summary, &local_error)) { /* FIXME: Isn't this dangerous ? We clear the summary if it cannot be loaded, for some random reason. We need to pass the error and find out why it is not loaded etc. ? */ - camel_folder_summary_clear_db (summary); + camel_folder_summary_clear (summary, NULL); g_message ("Unable to load summary: %s\n", local_error->message); g_clear_error (&local_error); } - g_ptr_array_sort (summary->uids, (GCompareFunc) uid_compare); - return summary; } -static gint +static gboolean summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir) { @@ -202,8 +182,8 @@ summary_header_from_db (CamelFolderSummary *s, folder_summary_class = CAMEL_FOLDER_SUMMARY_CLASS ( camel_imapx_summary_parent_class); - if (folder_summary_class->summary_header_from_db (s, mir) == -1) - return -1; + if (!folder_summary_class->summary_header_from_db (s, mir)) + return FALSE; part = mir->bdata; @@ -218,10 +198,10 @@ summary_header_from_db (CamelFolderSummary *s, if (ims->version > CAMEL_IMAPX_SUMMARY_VERSION) { g_warning("Unknown summary version\n"); errno = EINVAL; - return -1; + return FALSE; } - return 0; + return TRUE; } static gint @@ -427,7 +407,7 @@ content_info_migrate (CamelFolderSummary *s, return camel_folder_summary_content_info_new (s); } -static gint +static gboolean content_info_to_db (CamelFolderSummary *s, CamelMessageContentInfo *info, CamelMIRecord *mir) @@ -447,7 +427,7 @@ content_info_to_db (CamelFolderSummary *s, oldr = mir->cinfo; mir->cinfo = oldr ? g_strdup_printf("%s 0", oldr) : g_strdup ("0"); g_free (oldr); - return 0; + return TRUE; } } diff --git a/camel/providers/imapx/camel-imapx-utils.c b/camel/providers/imapx/camel-imapx-utils.c index 71b3f02..a9cf44c 100644 --- a/camel/providers/imapx/camel-imapx-utils.c +++ b/camel/providers/imapx/camel-imapx-utils.c @@ -264,13 +264,10 @@ imapx_update_message_info_flags (CamelMessageInfo *info, gboolean unsolicited) { gboolean changed = FALSE; - CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) folder; CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) info; - if (server_flags != xinfo->server_flags) - { + if (server_flags != xinfo->server_flags) { guint32 server_set, server_cleared; - gint read = 0, deleted = 0, junk = 0; server_set = server_flags & ~xinfo->server_flags; server_cleared = xinfo->server_flags & ~server_flags; @@ -281,44 +278,12 @@ imapx_update_message_info_flags (CamelMessageInfo *info, if (permanent_flags > 0) server_cleared &= permanent_flags; - if (server_set & CAMEL_MESSAGE_SEEN) - read = 1; - else if (server_cleared & CAMEL_MESSAGE_SEEN) - read = -1; - - if (server_set & CAMEL_MESSAGE_DELETED) - deleted = 1; - else if (server_cleared & CAMEL_MESSAGE_DELETED) - deleted = -1; - - if (server_set & CAMEL_MESSAGE_JUNK) - junk = 1; - else if (server_cleared & CAMEL_MESSAGE_JUNK) - junk = -1; - - d('?', "%s %s %s %s\n", xinfo->info.uid, read == 1 ? "read" : ( read == -1 ? "unread" : ""), - deleted == 1 ? "deleted" : ( deleted == -1 ? "undeleted" : ""), - junk == 1 ? "junk" : ( junk == -1 ? "unjunked" : "")); - - if (read) { - folder->summary->unread_count -= read; - if (unsolicited) - ifolder->unread_on_server -= read; - } - if (deleted) - folder->summary->deleted_count += deleted; - if (junk) - folder->summary->junk_count += junk; - if (junk && !deleted) - folder->summary->junk_not_deleted_count += junk; - if (junk || deleted) - folder->summary->visible_count -= junk ? junk : deleted; - - xinfo->info.flags = (xinfo->info.flags | server_set) & ~server_cleared; + camel_message_info_set_flags ((CamelMessageInfo *) xinfo, server_set | server_cleared, (xinfo->info.flags | server_set) & ~server_cleared); + xinfo->server_flags = server_flags; + xinfo->info.flags = xinfo->info.flags & ~CAMEL_MESSAGE_FOLDER_FLAGGED; xinfo->info.dirty = TRUE; - if (info->summary) - camel_folder_summary_touch (info->summary); + changed = TRUE; } @@ -336,85 +301,17 @@ imapx_set_message_info_flags_for_new_message (CamelMessageInfo *info, { CamelMessageInfoBase *binfo = (CamelMessageInfoBase *) info; CamelIMAPXMessageInfo *xinfo = (CamelIMAPXMessageInfo *) info; - gint unread = 0, deleted = 0, junk = 0; - guint32 flags; binfo->flags |= server_flags; + camel_message_info_set_flags (info, server_flags, binfo->flags | server_flags); + xinfo->server_flags = server_flags; if (folder->permanent_flags & CAMEL_MESSAGE_USER) imapx_update_user_flags (info, server_user_flags); - /* update the summary count */ - flags = binfo->flags; - - if (!(flags & CAMEL_MESSAGE_SEEN)) - unread = 1; - - if (flags & CAMEL_MESSAGE_DELETED) - deleted = 1; - - if (flags & CAMEL_MESSAGE_JUNK) - junk = 1; - - if (folder->summary) { - - if (unread) - folder->summary->unread_count += unread; - if (deleted) - folder->summary->deleted_count += deleted; - if (junk) - folder->summary->junk_count += junk; - if (junk && !deleted) - folder->summary->junk_not_deleted_count += junk; - folder->summary->visible_count++; - if (junk || deleted) - folder->summary->visible_count -= junk ? junk : deleted; - - folder->summary->saved_count++; - camel_folder_summary_touch (folder->summary); - } - binfo->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED; -} - -void -imapx_update_summary_for_removed_message (CamelMessageInfo *info, - CamelFolder *folder, - gboolean unsolicited) -{ - CamelMessageInfoBase *dinfo = (CamelMessageInfoBase *) info; - CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) folder; - gint unread = 0, deleted = 0, junk = 0; - guint32 flags; - - flags = dinfo->flags; - if (!(flags & CAMEL_MESSAGE_SEEN)) - unread = 1; - - if (flags & CAMEL_MESSAGE_DELETED) - deleted = 1; - - if (flags & CAMEL_MESSAGE_JUNK) - junk = 1; - - if (unread) { - folder->summary->unread_count--; - if (unsolicited) - ifolder->unread_on_server--; - } - if (deleted) - folder->summary->deleted_count--; - if (junk) - folder->summary->junk_count--; - - if (junk && !deleted) - folder->summary->junk_not_deleted_count--; - - if (!junk && !deleted) - folder->summary->visible_count--; - - folder->summary->saved_count--; + binfo->dirty = TRUE; } void @@ -432,7 +329,7 @@ imapx_update_store_summary (CamelFolder *folder) guint32 unread, total; total = camel_folder_summary_count (folder->summary); - unread = folder->summary->unread_count; + unread = camel_folder_summary_get_unread_count (folder->summary); if (si->unread != unread || si->total != total) { si->unread = unread; diff --git a/camel/providers/imapx/camel-imapx-utils.h b/camel/providers/imapx/camel-imapx-utils.h index 17e4d80..848c01a 100644 --- a/camel/providers/imapx/camel-imapx-utils.h +++ b/camel/providers/imapx/camel-imapx-utils.h @@ -89,7 +89,6 @@ void imapx_write_flags (CamelStream *stream, guint32 flags, struct _CamelFlag *u gboolean imapx_update_message_info_flags (CamelMessageInfo *info, guint32 server_flags, CamelFlag *server_user_flags, guint32 permanent_flags, CamelFolder *folder, gboolean unsolicited); void imapx_set_message_info_flags_for_new_message (CamelMessageInfo *info, guint32 server_flags, CamelFlag *server_user_flags, CamelFolder *folder); -void imapx_update_summary_for_removed_message (CamelMessageInfo *info, CamelFolder *folder, gboolean unsolicited); void imapx_update_store_summary (CamelFolder *folder); /* ********************************************************************** */ diff --git a/camel/providers/local/camel-local-folder.c b/camel/providers/local/camel-local-folder.c index e1c9765..5b68f1e 100644 --- a/camel/providers/local/camel-local-folder.c +++ b/camel/providers/local/camel-local-folder.c @@ -608,7 +608,7 @@ camel_local_folder_construct (CamelLocalFolder *lf, } folder->summary = (CamelFolderSummary *) CAMEL_LOCAL_FOLDER_GET_CLASS (lf)->create_summary (lf, lf->summary_path, lf->folder_path, lf->index); - if (!(flags & CAMEL_STORE_IS_MIGRATING) && camel_local_summary_load ((CamelLocalSummary *) folder->summary, forceindex, NULL) == -1) { + if (!(flags & CAMEL_STORE_IS_MIGRATING) && !camel_local_summary_load ((CamelLocalSummary *) folder->summary, forceindex, NULL)) { /* ? */ if (need_summary_check && camel_local_summary_check ((CamelLocalSummary *) folder->summary, lf->changes, cancellable, error) == 0) { diff --git a/camel/providers/local/camel-local-summary.c b/camel/providers/local/camel-local-summary.c index 92eaf00..2575cbb 100644 --- a/camel/providers/local/camel-local-summary.c +++ b/camel/providers/local/camel-local-summary.c @@ -44,7 +44,7 @@ #define EXTRACT_FIRST_DIGIT(val) val=strtoul (part, &part, 10); static CamelFIRecord * summary_header_to_db (CamelFolderSummary *, GError **error); -static gint summary_header_from_db (CamelFolderSummary *, CamelFIRecord *); +static gboolean summary_header_from_db (CamelFolderSummary *, CamelFIRecord *); static gint summary_header_load (CamelFolderSummary *, FILE *); static gint summary_header_save (CamelFolderSummary *, FILE *); @@ -144,7 +144,7 @@ camel_local_summary_construct (CamelLocalSummary *new, g_object_ref (index); } -static gint +static gboolean local_summary_load (CamelLocalSummary *cls, gint forceindex, GError **error) @@ -154,7 +154,7 @@ local_summary_load (CamelLocalSummary *cls, } /* load/check the summary */ -gint +gboolean camel_local_summary_load (CamelLocalSummary *cls, gint forceindex, GError **error) @@ -166,13 +166,13 @@ camel_local_summary_load (CamelLocalSummary *cls, class = CAMEL_LOCAL_SUMMARY_GET_CLASS (cls); if ((forceindex && class->need_index ()) - || class->load (cls, forceindex, error) == -1) { + || !class->load (cls, forceindex, error)) { w(g_warning("Could not load summary: flags may be reset")); - camel_folder_summary_clear ((CamelFolderSummary *) cls); - return -1; + camel_folder_summary_clear ((CamelFolderSummary *) cls, NULL); + return FALSE; } - return 0; + return TRUE; } void camel_local_summary_check_force (CamelLocalSummary *cls) @@ -295,13 +295,16 @@ camel_local_summary_check (CamelLocalSummary *cls, if (ret != -1) { gint i; CamelFolderSummary *s = (CamelFolderSummary *) cls; + GPtrArray *known_uids; struct _stat_info stats = { 0 }; + known_uids = camel_folder_summary_get_array (s); for (i = 0; i < camel_folder_summary_count (s); i++) { - CamelMessageInfo *info = camel_folder_summary_index (s, i); + CamelMessageInfo *info = camel_folder_summary_get (s, g_ptr_array_index (known_uids, i)); do_stat_mi (cls, &stats, info); camel_message_info_free (info); } + camel_folder_summary_free_array (known_uids); printf("\nMemory used by summary:\n\n"); printf("Total of %d messages\n", camel_folder_summary_count(s)); @@ -456,7 +459,7 @@ local_summary_sync (CamelLocalSummary *cls, folder_summary = CAMEL_FOLDER_SUMMARY (cls); - if (camel_folder_summary_save_to_db (folder_summary, error) == -1) { + if (!camel_folder_summary_save_to_db (folder_summary, error)) { g_warning ("Could not save summary for local providers"); return -1; } @@ -475,42 +478,6 @@ local_summary_need_index (void) return 1; } -static void -update_summary (CamelFolderSummary *summary, - CamelMessageInfoBase *info, - CamelMessageInfoBase *old) -{ - gint unread = 0, deleted = 0, junk = 0; - guint32 flags = info->flags; - guint32 oldflags = old->flags; - - if ((flags & CAMEL_MESSAGE_SEEN) != (oldflags & CAMEL_MESSAGE_SEEN)) - unread = (oldflags & CAMEL_MESSAGE_SEEN) ? 1 : -1; - - if ((flags & CAMEL_MESSAGE_DELETED) != (oldflags & CAMEL_MESSAGE_DELETED)) - deleted = (oldflags & CAMEL_MESSAGE_DELETED) ? 1 : -1; - - if ((flags & CAMEL_MESSAGE_JUNK) != (oldflags & CAMEL_MESSAGE_JUNK)) - junk = (oldflags & CAMEL_MESSAGE_JUNK) ? 1 : -1; - - /* Things would already be flagged */ - - if (summary) { - - if (unread) - summary->unread_count -= unread; - if (deleted) - summary->deleted_count += deleted; - if (junk) - summary->junk_count += junk; - if (junk && !deleted) - summary->junk_not_deleted_count += junk; - if (junk || deleted) - summary->visible_count -= junk ? junk : deleted; - } - -} - static CamelMessageInfo * local_summary_add (CamelLocalSummary *cls, CamelMimeMessage *msg, @@ -519,7 +486,6 @@ local_summary_add (CamelLocalSummary *cls, GError **error) { CamelLocalMessageInfo *mi; - CamelFolderSummary *s = (CamelFolderSummary *) cls; gchar *xev; d(printf("Adding message to summary\n")); @@ -541,8 +507,7 @@ local_summary_add (CamelLocalSummary *cls, tag = tag->next; } - update_summary (s, (CamelMessageInfoBase *) mi, (CamelMessageInfoBase *) info); - mi->info.flags |= (camel_message_info_flags (info) & 0xffff); + camel_message_info_set_flags ((CamelMessageInfo *) mi, 0xffff, camel_message_info_flags (info)); mi->info.size = camel_message_info_size (info); } @@ -693,7 +658,7 @@ local_summary_decode_x_evolution (CamelLocalSummary *cls, return 0; } -static gint +static gboolean summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *fir) { @@ -702,8 +667,8 @@ summary_header_from_db (CamelFolderSummary *s, /* We dont actually add our own headers, but version that we don't anyway */ - if (CAMEL_FOLDER_SUMMARY_CLASS (camel_local_summary_parent_class)->summary_header_from_db (s, fir) == -1) - return -1; + if (!CAMEL_FOLDER_SUMMARY_CLASS (camel_local_summary_parent_class)->summary_header_from_db (s, fir)) + return FALSE; part = fir->bdata; if (part) { @@ -715,7 +680,7 @@ summary_header_from_db (CamelFolderSummary *s, g_free (fir->bdata); fir->bdata = tmp; - return 0; + return TRUE; } static gint diff --git a/camel/providers/local/camel-local-summary.h b/camel/providers/local/camel-local-summary.h index ebcb581..9de024d 100644 --- a/camel/providers/local/camel-local-summary.h +++ b/camel/providers/local/camel-local-summary.h @@ -75,7 +75,7 @@ struct _CamelLocalSummary { struct _CamelLocalSummaryClass { CamelFolderSummaryClass parent_class; - gint (*load)(CamelLocalSummary *cls, gint forceindex, GError **error); + gboolean (*load)(CamelLocalSummary *cls, gint forceindex, GError **error); gint (*check)(CamelLocalSummary *cls, CamelFolderChangeInfo *changeinfo, GCancellable *cancellable, GError **error); gint (*sync)(CamelLocalSummary *cls, gboolean expunge, CamelFolderChangeInfo *changeinfo, GCancellable *cancellable, GError **error); CamelMessageInfo *(*add)(CamelLocalSummary *cls, CamelMimeMessage *msg, const CamelMessageInfo *info, CamelFolderChangeInfo *, GError **error); @@ -89,7 +89,7 @@ GType camel_local_summary_get_type (void); void camel_local_summary_construct (CamelLocalSummary *new, const gchar *filename, const gchar *local_name, CamelIndex *index); /* load/check the summary */ -gint camel_local_summary_load (CamelLocalSummary *cls, gint forceindex, GError **error); +gboolean camel_local_summary_load (CamelLocalSummary *cls, gint forceindex, GError **error); /* check for new/removed messages */ gint camel_local_summary_check (CamelLocalSummary *cls, CamelFolderChangeInfo *, GCancellable *cancellable, GError **error); /* perform a folder sync or expunge, if needed */ diff --git a/camel/providers/local/camel-maildir-folder.c b/camel/providers/local/camel-maildir-folder.c index bbae5c2..7483546 100644 --- a/camel/providers/local/camel-maildir-folder.c +++ b/camel/providers/local/camel-maildir-folder.c @@ -54,8 +54,8 @@ maildir_folder_cmp_uids (CamelFolder *folder, g_return_val_if_fail (folder != NULL, 0); g_return_val_if_fail (folder->summary != NULL, 0); - a = camel_folder_summary_uid (folder->summary, uid1); - b = camel_folder_summary_uid (folder->summary, uid2); + a = camel_folder_summary_get (folder->summary, uid1); + b = camel_folder_summary_get (folder->summary, uid2); g_return_val_if_fail (a != NULL, 0); g_return_val_if_fail (b != NULL, 0); @@ -94,7 +94,7 @@ maildir_folder_get_filename (CamelFolder *folder, gchar *res; /* get the message summary info */ - if ((info = camel_folder_summary_uid (folder->summary, uid)) == NULL) { + if ((info = camel_folder_summary_get (folder->summary, uid)) == NULL) { set_cannot_get_message_ex ( error, CAMEL_FOLDER_ERROR_INVALID_UID, uid, lf->folder_path, _("No such message")); @@ -327,7 +327,7 @@ maildir_folder_transfer_messages_to_sync (CamelFolder *source, CamelMaildirMessageInfo *mdi; CamelMessageInfo *info; - if ((info = camel_folder_summary_uid (source->summary, uid)) == NULL) { + if ((info = camel_folder_summary_get (source->summary, uid)) == NULL) { set_cannot_get_message_ex ( error, CAMEL_FOLDER_ERROR_INVALID_UID, uid, lf->folder_path, _("No such message")); diff --git a/camel/providers/local/camel-maildir-store.c b/camel/providers/local/camel-maildir-store.c index 95bc8bc..3a5a2b0 100644 --- a/camel/providers/local/camel-maildir-store.c +++ b/camel/providers/local/camel-maildir-store.c @@ -384,9 +384,9 @@ fill_fi (CamelStore *store, } s = (CamelFolderSummary *) camel_maildir_summary_new (NULL, path, folderpath, NULL); - if (camel_folder_summary_header_load_from_db (s, store, fi->full_name, NULL) != -1) { - fi->unread = s->unread_count; - fi->total = s->saved_count; + if (camel_folder_summary_header_load_from_db (s, store, fi->full_name, NULL)) { + fi->unread = camel_folder_summary_get_unread_count (s); + fi->total = camel_folder_summary_get_saved_count (s); } g_object_unref (s); g_free (folderpath); diff --git a/camel/providers/local/camel-maildir-summary.c b/camel/providers/local/camel-maildir-summary.c index 0024c42..e673df6 100644 --- a/camel/providers/local/camel-maildir-summary.c +++ b/camel/providers/local/camel-maildir-summary.c @@ -150,8 +150,7 @@ CamelMaildirSummary { CamelMaildirSummary *o; - o = g_object_new (CAMEL_TYPE_MAILDIR_SUMMARY, NULL); - ((CamelFolderSummary *) o)->folder = folder; + o = g_object_new (CAMEL_TYPE_MAILDIR_SUMMARY, "folder", folder, NULL); if (folder) { CamelStore *parent_store; @@ -289,7 +288,7 @@ message_info_new_from_header (CamelFolderSummary *s, mdi->info.info.uid = camel_pstring_add (camel_folder_summary_next_uid_string (s), TRUE); /* handle 'duplicates' */ - info = camel_folder_summary_peek_info (s, uid); + info = camel_folder_summary_peek_loaded (s, uid); if (info) { d(printf("already seen uid '%s', just summarising instead\n", uid)); camel_message_info_free (mi); @@ -550,6 +549,7 @@ maildir_summary_check (CamelLocalSummary *cls, gchar *new, *cur; gchar *uid; struct _remove_data rd = { cls, changes }; + GPtrArray *known_uids; g_mutex_lock (((CamelMaildirSummary *) cls)->priv->summary_lock); @@ -580,10 +580,10 @@ maildir_summary_check (CamelLocalSummary *cls, /* keeps track of all uid's that have not been processed */ left = g_hash_table_new (g_str_hash, g_str_equal); camel_folder_summary_prepare_fetch_all (s, error); - count = camel_folder_summary_count (s); - forceindex = count == 0; - for (i = 0; i < count; i++) { - info = camel_folder_summary_index ((CamelFolderSummary *) cls, i); + known_uids = camel_folder_summary_get_array (s); + forceindex = !known_uids || known_uids->len == 0; + for (i = 0; known_uids && i < known_uids->len; i++) { + info = camel_folder_summary_get ((CamelFolderSummary *) cls, g_ptr_array_index (known_uids, i)); if (info) { g_hash_table_insert (left, (gchar *) camel_message_info_uid (info), info); } @@ -620,7 +620,7 @@ maildir_summary_check (CamelLocalSummary *cls, g_hash_table_remove (left, uid); } - info = camel_folder_summary_uid ((CamelFolderSummary *) cls, uid); + info = camel_folder_summary_get ((CamelFolderSummary *) cls, uid); if (info == NULL) { /* must be a message incorporated by another client, this is not a 'recent' uid */ if (camel_maildir_summary_add (cls, d->d_name, forceindex, cancellable) == 0) @@ -676,7 +676,7 @@ maildir_summary_check (CamelLocalSummary *cls, continue; /* already in summary? shouldn't happen, but just incase ... */ - if ((info = camel_folder_summary_uid ((CamelFolderSummary *) cls, name))) { + if ((info = camel_folder_summary_get ((CamelFolderSummary *) cls, name))) { camel_message_info_free (info); newname = destname = camel_folder_summary_next_uid_string (s); } else { @@ -720,6 +720,7 @@ maildir_summary_check (CamelLocalSummary *cls, g_free (new); g_free (cur); + camel_folder_summary_free_array (known_uids); g_mutex_unlock (((CamelMaildirSummary *) cls)->priv->summary_lock); return 0; @@ -734,11 +735,12 @@ maildir_summary_sync (CamelLocalSummary *cls, GError **error) { CamelLocalSummaryClass *local_summary_class; - gint count, i; + gint i; CamelMessageInfo *info; CamelMaildirMessageInfo *mdi; gchar *name; struct stat st; + GPtrArray *known_uids; d(printf("summary_sync(expunge=%s)\n", expunge?"true":"false")); @@ -748,11 +750,11 @@ maildir_summary_sync (CamelLocalSummary *cls, camel_operation_push_message (cancellable, _("Storing folder")); camel_folder_summary_prepare_fetch_all ((CamelFolderSummary *) cls, error); - count = camel_folder_summary_count ((CamelFolderSummary *) cls); - for (i = count - 1; i >= 0; i--) { - camel_operation_progress (cancellable, (count - i) * 100 / count); + known_uids = camel_folder_summary_get_array ((CamelFolderSummary *) cls); + for (i = (known_uids ? known_uids->len : 0) - 1; i >= 0; i--) { + camel_operation_progress (cancellable, (known_uids->len - i) * 100 / known_uids->len); - info = camel_folder_summary_index ((CamelFolderSummary *) cls, i); + info = camel_folder_summary_get ((CamelFolderSummary *) cls, g_ptr_array_index (known_uids, i)); mdi = (CamelMaildirMessageInfo *) info; if (mdi && (mdi->info.info.flags & CAMEL_MESSAGE_DELETED) && expunge) { name = g_strdup_printf("%s/cur/%s", cls->folder_path, camel_maildir_info_filename(mdi)); @@ -801,6 +803,7 @@ maildir_summary_sync (CamelLocalSummary *cls, camel_message_info_free (info); } + camel_folder_summary_free_array (known_uids); camel_operation_pop_message (cancellable); /* Chain up to parent's sync() method. */ diff --git a/camel/providers/local/camel-mbox-folder.c b/camel/providers/local/camel-mbox-folder.c index f31fcfc..c5d3725 100644 --- a/camel/providers/local/camel-mbox-folder.c +++ b/camel/providers/local/camel-mbox-folder.c @@ -59,8 +59,8 @@ mbox_folder_cmp_uids (CamelFolder *folder, g_return_val_if_fail (folder != NULL, 0); g_return_val_if_fail (folder->summary != NULL, 0); - a = (CamelMboxMessageInfo *) camel_folder_summary_uid (folder->summary, uid1); - b = (CamelMboxMessageInfo *) camel_folder_summary_uid (folder->summary, uid2); + a = (CamelMboxMessageInfo *) camel_folder_summary_get (folder->summary, uid1); + b = (CamelMboxMessageInfo *) camel_folder_summary_get (folder->summary, uid2); g_return_val_if_fail (a != NULL, 0); g_return_val_if_fail (b != NULL, 0); @@ -109,7 +109,7 @@ mbox_folder_get_filename (CamelFolder *folder, } /* get the message summary info */ - info = (CamelMboxMessageInfo *) camel_folder_summary_uid (folder->summary, uid); + info = (CamelMboxMessageInfo *) camel_folder_summary_get (folder->summary, uid); if (info == NULL) { set_cannot_get_message_ex ( @@ -317,7 +317,7 @@ mbox_folder_get_message_sync (CamelFolder *folder, retry: /* get the message summary info */ - info = (CamelMboxMessageInfo *) camel_folder_summary_uid (folder->summary, uid); + info = (CamelMboxMessageInfo *) camel_folder_summary_get (folder->summary, uid); if (info == NULL) { set_cannot_get_message_ex ( diff --git a/camel/providers/local/camel-mbox-store.c b/camel/providers/local/camel-mbox-store.c index f08ce83..9a39c30 100644 --- a/camel/providers/local/camel-mbox-store.c +++ b/camel/providers/local/camel-mbox-store.c @@ -130,9 +130,9 @@ fill_fi (CamelStore *store, mbs = (CamelMboxSummary *) camel_mbox_summary_new (NULL, path, folderpath, NULL); /* FIXME[disk-summary] track exception */ - if (camel_folder_summary_header_load_from_db ((CamelFolderSummary *) mbs, store, fi->full_name, NULL) != -1) { - fi->unread = ((CamelFolderSummary *) mbs)->unread_count; - fi->total = ((CamelFolderSummary *) mbs)->saved_count; + if (camel_folder_summary_header_load_from_db ((CamelFolderSummary *) mbs, store, fi->full_name, NULL)) { + fi->unread = camel_folder_summary_get_unread_count ((CamelFolderSummary *) mbs); + fi->total = camel_folder_summary_get_saved_count ((CamelFolderSummary *) mbs); } g_object_unref (mbs); diff --git a/camel/providers/local/camel-mbox-summary.c b/camel/providers/local/camel-mbox-summary.c index 4be93e7..dca35d5 100644 --- a/camel/providers/local/camel-mbox-summary.c +++ b/camel/providers/local/camel-mbox-summary.c @@ -44,7 +44,7 @@ #define CAMEL_MBOX_SUMMARY_VERSION (1) static CamelFIRecord * summary_header_to_db (CamelFolderSummary *, GError **error); -static gint summary_header_from_db (CamelFolderSummary *, CamelFIRecord *); +static gboolean summary_header_from_db (CamelFolderSummary *, CamelFIRecord *); static CamelMessageInfo * message_info_from_db (CamelFolderSummary *s, CamelMIRecord *record); static CamelMIRecord * message_info_to_db (CamelFolderSummary *s, CamelMessageInfo *info); @@ -186,8 +186,7 @@ camel_mbox_summary_new (CamelFolder *folder, { CamelMboxSummary *new; - new = g_object_new (CAMEL_TYPE_MBOX_SUMMARY, NULL); - ((CamelFolderSummary *) new)->folder = folder; + new = g_object_new (CAMEL_TYPE_MBOX_SUMMARY, "folder", folder, NULL); if (folder) { CamelFolderSummary *summary = (CamelFolderSummary *) new; CamelStore *parent_store; @@ -228,14 +227,15 @@ mbox_summary_encode_x_evolution (CamelLocalSummary *cls, } } -static gint +static gboolean summary_header_from_db (CamelFolderSummary *s, struct _CamelFIRecord *fir) { CamelMboxSummary *mbs = CAMEL_MBOX_SUMMARY (s); gchar *part; - CAMEL_FOLDER_SUMMARY_CLASS (camel_mbox_summary_parent_class)->summary_header_from_db (s, fir); + if (!CAMEL_FOLDER_SUMMARY_CLASS (camel_mbox_summary_parent_class)->summary_header_from_db (s, fir)) + return FALSE; part = fir->bdata; if (part) { @@ -243,7 +243,7 @@ summary_header_from_db (CamelFolderSummary *s, mbs->folder_size = bdata_extract_digit (&part); } - return 0; + return TRUE; } static gint @@ -335,7 +335,7 @@ message_info_new_from_header (CamelFolderSummary *s, uid = camel_message_info_uid (mi); d(printf("found valid x-evolution: %s\n", uid)); /* If one is there, it should be there already */ - info = (CamelMboxMessageInfo *) camel_folder_summary_peek_info (s, uid); + info = (CamelMboxMessageInfo *) camel_folder_summary_peek_loaded (s, uid); if (info) { if ((info->info.info.flags & CAMEL_MESSAGE_FOLDER_NOTSEEN)) { info->info.info.flags &= ~CAMEL_MESSAGE_FOLDER_NOTSEEN; @@ -360,7 +360,7 @@ message_info_new_from_header (CamelFolderSummary *s, camel_pstring_free (mi->info.info.uid); mi->info.info.uid = camel_pstring_add (camel_folder_summary_next_uid_string (s), TRUE); } else { - camel_folder_summary_set_uid (s, strtoul (camel_message_info_uid (mi), NULL, 10)); + camel_folder_summary_set_next_uid (s, strtoul (camel_message_info_uid (mi), NULL, 10)); } #ifdef STATUS_PINE if (mbs->xstatus && add&2) { @@ -465,7 +465,7 @@ summary_update (CamelLocalSummary *cls, GCancellable *cancellable, GError **error) { - gint i, count; + gint i; CamelFolderSummary *s = (CamelFolderSummary *) cls; CamelMboxSummary *mbs = (CamelMboxSummary *) cls; CamelMimeParser *mp; @@ -477,6 +477,7 @@ summary_update (CamelLocalSummary *cls, struct stat st; goffset size = 0; GList *del = NULL; + GPtrArray *known_uids; d(printf("Calling summary update, from pos %d\n", (gint)offset)); @@ -522,15 +523,16 @@ summary_update (CamelLocalSummary *cls, * If we're not starting from the start, we must be starting * from the old end, so everything must be treated as new */ camel_folder_summary_prepare_fetch_all (s, NULL); - count = camel_folder_summary_count (s); - for (i = 0; i < count; i++) { - mi = (CamelMboxMessageInfo *) camel_folder_summary_index (s, i); + known_uids = camel_folder_summary_get_array (s); + for (i = 0; known_uids && i < known_uids->len; i++) { + mi = (CamelMboxMessageInfo *) camel_folder_summary_get (s, g_ptr_array_index (known_uids, i)); if (offset == 0) mi->info.info.flags |= CAMEL_MESSAGE_FOLDER_NOTSEEN; else mi->info.info.flags &= ~CAMEL_MESSAGE_FOLDER_NOTSEEN; camel_message_info_free (mi); } + camel_folder_summary_free_array (known_uids); mbs->changes = changeinfo; while (camel_mime_parser_step (mp, NULL, NULL) == CAMEL_MIME_PARSER_STATE_FROM) { @@ -565,39 +567,34 @@ summary_update (CamelLocalSummary *cls, g_object_unref (mp); - count = camel_folder_summary_count (s); - for (i = 0; i < count; i++) { - mi = (CamelMboxMessageInfo *) camel_folder_summary_index (s, i); - /* must've dissapeared from the file? */ - if (!mi || mi->info.info.flags & CAMEL_MESSAGE_FOLDER_NOTSEEN) { - gchar *uid; - - if (mi) - uid = g_strdup (camel_message_info_uid (mi)); - else - uid = camel_folder_summary_uid_from_index (s, i); + known_uids = camel_folder_summary_get_array (s); + for (i = 0; known_uids && i < known_uids->len; i++) { + const gchar *uid; - if (!uid) { - g_debug ("%s: didn't get uid at %d of %d (%d)", G_STRFUNC, i, count, camel_folder_summary_count (s)); - continue; - } + uid = g_ptr_array_index (known_uids, i); + if (!uid) + continue; + mi = (CamelMboxMessageInfo *) camel_folder_summary_get (s, uid); + /* must've dissapeared from the file? */ + if (!mi || mi->info.info.flags & CAMEL_MESSAGE_FOLDER_NOTSEEN) { d(printf("uid '%s' vanished, removing", uid)); if (changeinfo) camel_folder_change_info_remove_uid (changeinfo, uid); del = g_list_prepend (del, (gpointer) camel_pstring_strdup (uid)); - camel_folder_summary_remove_index_fast (s, i); - count--; - i--; - g_free (uid); + camel_folder_summary_remove_uid (s, uid); } + if (mi) camel_message_info_free (mi); } + if (known_uids) + camel_folder_summary_free_array (known_uids); + /* Delete all in one transaction */ - full_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); + full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (s)); + parent_store = camel_folder_get_parent_store (camel_folder_summary_get_folder (s)); camel_db_delete_uids (parent_store->cdb_w, full_name, del, NULL); g_list_foreach (del, (GFunc) camel_pstring_free, NULL); g_list_free (del); @@ -629,7 +626,7 @@ mbox_summary_check (CamelLocalSummary *cls, CamelFolderSummary *s = (CamelFolderSummary *) cls; struct stat st; gint ret = 0; - gint i, count; + gint i; d(printf("Checking summary\n")); @@ -637,7 +634,7 @@ mbox_summary_check (CamelLocalSummary *cls, /* check if the summary is up-to-date */ if (g_stat (cls->folder_path, &st) == -1) { - camel_folder_summary_clear (s); + camel_folder_summary_clear (s, NULL); camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); g_set_error ( error, G_IO_ERROR, @@ -652,19 +649,22 @@ mbox_summary_check (CamelLocalSummary *cls, cls->check_force = 0; if (st.st_size == 0) { + GPtrArray *known_uids; + /* empty? No need to scan at all */ d(printf("Empty mbox, clearing summary\n")); camel_folder_summary_prepare_fetch_all (s, NULL); - count= camel_folder_summary_count (s); - for (i = 0; i < count; i++) { - CamelMessageInfo *info = camel_folder_summary_index (s, i); + known_uids = camel_folder_summary_get_array (s); + for (i = 0; known_uids && i < known_uids->len; i++) { + CamelMessageInfo *info = camel_folder_summary_get (s, g_ptr_array_index (known_uids, i)); if (info) { camel_folder_change_info_remove_uid (changes, camel_message_info_uid (info)); camel_message_info_free (info); } } - camel_folder_summary_clear (s); + camel_folder_summary_free_array (known_uids); + camel_folder_summary_clear (s, NULL); ret = 0; } else { /* is the summary uptodate? */ @@ -822,8 +822,8 @@ cms_sort_frompos (gpointer a, gint ret = 0; /* Things are in memory already. Sorting speeds up syncing, if things are sorted by from pos. */ - info1 = (CamelMboxMessageInfo *) camel_folder_summary_uid (summary, *(gchar **) a); - info2 = (CamelMboxMessageInfo *) camel_folder_summary_uid (summary, *(gchar **) b); + info1 = (CamelMboxMessageInfo *) camel_folder_summary_get (summary, *(gchar **) a); + info2 = (CamelMboxMessageInfo *) camel_folder_summary_get (summary, *(gchar **) b); if (info1->frompos > info2->frompos) ret = 1; @@ -905,7 +905,7 @@ mbox_summary_sync_quick (CamelMboxSummary *mbs, camel_operation_progress (cancellable, pc); - info = (CamelMboxMessageInfo *) camel_folder_summary_uid (s, summary->pdata[i]); + info = (CamelMboxMessageInfo *) camel_folder_summary_get (s, summary->pdata[i]); d(printf("Checking message %s %08x\n", camel_message_info_uid(info), ((CamelMessageInfoBase *)info)->flags)); @@ -1040,14 +1040,14 @@ mbox_summary_sync (CamelLocalSummary *cls, return -1; } - full_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); + full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (s)); + parent_store = camel_folder_get_parent_store (camel_folder_summary_get_folder (s)); /* Sync only the changes */ summary = camel_folder_summary_get_changed ((CamelFolderSummary *) mbs); for (i = 0; i < summary->len; i++) { - CamelMboxMessageInfo *info = (CamelMboxMessageInfo *) camel_folder_summary_uid (s, summary->pdata[i]); + CamelMboxMessageInfo *info = (CamelMboxMessageInfo *) camel_folder_summary_get (s, summary->pdata[i]); if ((expunge && (info->info.info.flags & CAMEL_MESSAGE_DELETED)) || (info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_XEVCHANGE))) @@ -1127,7 +1127,7 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls, CamelMimeParser *mp = NULL; CamelStore *parent_store; const gchar *full_name; - gint i, count; + gint i; CamelMboxMessageInfo *info = NULL; gchar *buffer, *xevnew = NULL; gsize len; @@ -1135,6 +1135,7 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls, gint lastdel = FALSE; gboolean touched = FALSE; GList *del = NULL; + GPtrArray *known_uids = NULL; #ifdef STATUS_PINE gchar statnew[8], xstatnew[8]; #endif @@ -1161,13 +1162,13 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls, camel_mime_parser_init_with_fd (mp, fd); camel_folder_summary_prepare_fetch_all (s, NULL); - count = camel_folder_summary_count (s); - for (i = 0; i < count; i++) { - gint pc = (i + 1) * 100 / count; + known_uids = camel_folder_summary_get_array (s); + for (i = 0; known_uids && i < known_uids->len; i++) { + gint pc = (i + 1) * 100 / known_uids->len; camel_operation_progress (cancellable, pc); - info = (CamelMboxMessageInfo *) camel_folder_summary_index (s, i); + info = (CamelMboxMessageInfo *) camel_folder_summary_get (s, g_ptr_array_index (known_uids, i)); if (!info) continue; @@ -1197,28 +1198,16 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls, lastdel = FALSE; if ((flags&1) && info->info.info.flags & CAMEL_MESSAGE_DELETED) { const gchar *uid = camel_message_info_uid (info); - guint32 flags = camel_message_info_flags (info); - gint read, junk; d(printf("Deleting %s\n", uid)); if (((CamelLocalSummary *) cls)->index) camel_index_delete_name (((CamelLocalSummary *) cls)->index, uid); /* remove it from the change list */ - junk = flags & CAMEL_MESSAGE_JUNK; - read = flags & CAMEL_MESSAGE_SEEN; - s->saved_count--; - if (junk) - s->junk_count--; - if (!read) - s->unread_count--; - s->deleted_count--; camel_folder_change_info_remove_uid (changeinfo, uid); - camel_folder_summary_remove_index_fast (s, i); + camel_folder_summary_remove_uid (s, uid); del = g_list_prepend (del, (gpointer) camel_pstring_strdup (uid)); camel_message_info_free ((CamelMessageInfo *) info); - count--; - i--; info = NULL; lastdel = TRUE; touched = TRUE; @@ -1303,8 +1292,8 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls, } } - full_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); + full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (s)); + parent_store = camel_folder_get_parent_store (camel_folder_summary_get_folder (s)); camel_db_delete_uids (parent_store->cdb_w, full_name, del, NULL); g_list_foreach (del, (GFunc) camel_pstring_free, NULL); g_list_free (del); @@ -1318,8 +1307,8 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls, g_object_unref (mp); /* clear working flags */ - for (i = 0; i < count; i++) { - info = (CamelMboxMessageInfo *) camel_folder_summary_index (s, i); + for (i = 0; known_uids && i < known_uids->len; i++) { + info = (CamelMboxMessageInfo *) camel_folder_summary_get (s, g_ptr_array_index (known_uids, i)); if (info) { if (info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED | CAMEL_MESSAGE_FOLDER_XEVCHANGE)) { info->info.info.flags &= ~(CAMEL_MESSAGE_FOLDER_NOXEV @@ -1333,6 +1322,8 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls, } } + camel_folder_summary_free_array (known_uids); + if (touched) camel_folder_summary_header_save_to_db (s, NULL); @@ -1347,6 +1338,7 @@ camel_mbox_summary_sync_mbox (CamelMboxSummary *cls, if (info) camel_message_info_free ((CamelMessageInfo *) info); + camel_folder_summary_free_array (known_uids); camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK); return -1; diff --git a/camel/providers/local/camel-mh-folder.c b/camel/providers/local/camel-mh-folder.c index f8b6286..b99f283 100644 --- a/camel/providers/local/camel-mh-folder.c +++ b/camel/providers/local/camel-mh-folder.c @@ -150,7 +150,7 @@ mh_folder_get_message_sync (CamelFolder *folder, return NULL; /* get the message summary info */ - if ((info = camel_folder_summary_uid (folder->summary, uid)) == NULL) { + if ((info = camel_folder_summary_get (folder->summary, uid)) == NULL) { set_cannot_get_message_ex ( error, CAMEL_FOLDER_ERROR_INVALID_UID, uid, lf->folder_path, _("No such message")); diff --git a/camel/providers/local/camel-mh-store.c b/camel/providers/local/camel-mh-store.c index 0f3baab..2c7d221 100644 --- a/camel/providers/local/camel-mh-store.c +++ b/camel/providers/local/camel-mh-store.c @@ -218,9 +218,9 @@ fill_fi (CamelStore *store, s = (CamelFolderSummary *) camel_mh_summary_new ( NULL, path, folderpath, NULL); if (camel_folder_summary_header_load_from_db ( - s, store, fi->full_name, NULL) != -1) { - fi->unread = s->unread_count; - fi->total = s->saved_count; + s, store, fi->full_name, NULL)) { + fi->unread = camel_folder_summary_get_unread_count (s); + fi->total = camel_folder_summary_get_saved_count (s); } g_object_unref (s); g_free (folderpath); diff --git a/camel/providers/local/camel-mh-summary.c b/camel/providers/local/camel-mh-summary.c index ada6ee5..2d9de03 100644 --- a/camel/providers/local/camel-mh-summary.c +++ b/camel/providers/local/camel-mh-summary.c @@ -98,8 +98,7 @@ camel_mh_summary_new (CamelFolder *folder, { CamelMhSummary *o; - o = g_object_new (CAMEL_TYPE_MH_SUMMARY, NULL); - ((CamelFolderSummary *) o)->folder = folder; + o = g_object_new (CAMEL_TYPE_MH_SUMMARY, "folder", folder, NULL); if (folder) { CamelStore *parent_store; @@ -127,7 +126,7 @@ mh_summary_next_uid_string (CamelFolderSummary *s) if (mhs->priv->current_uid) { uidstr = g_strdup (mhs->priv->current_uid); /* tell the summary of this, so we always append numbers to the end */ - camel_folder_summary_set_uid (s, strtoul (uidstr, NULL, 10) + 1); + camel_folder_summary_set_next_uid (s, strtoul (uidstr, NULL, 10) + 1); } else { /* else scan for one - and create it too, to make sure */ do { @@ -210,8 +209,9 @@ mh_summary_check (CamelLocalSummary *cls, CamelMessageInfo *info; CamelFolderSummary *s = (CamelFolderSummary *) cls; GHashTable *left; - gint i, count; - gint forceindex; + gint i; + gboolean forceindex; + GPtrArray *known_uids; /* FIXME: Handle changeinfo */ @@ -232,14 +232,15 @@ mh_summary_check (CamelLocalSummary *cls, /* keeps track of all uid's that have not been processed */ left = g_hash_table_new (g_str_hash, g_str_equal); camel_folder_summary_prepare_fetch_all ((CamelFolderSummary *) cls, error); - count = camel_folder_summary_count ((CamelFolderSummary *) cls); - forceindex = count == 0; - for (i = 0; i < count; i++) { - info = camel_folder_summary_index ((CamelFolderSummary *) cls, i); + known_uids = camel_folder_summary_get_array ((CamelFolderSummary *) cls); + forceindex = !known_uids || known_uids->len == 0; + for (i = 0; known_uids && i < known_uids->len; i++) { + info = camel_folder_summary_get ((CamelFolderSummary *) cls, g_ptr_array_index (known_uids, i)); if (info) { g_hash_table_insert (left, (gchar *) camel_message_info_uid (info), info); } } + camel_folder_summary_free_array (known_uids); while ((d = readdir (dir))) { /* FIXME: also run stat to check for regular file */ @@ -249,7 +250,7 @@ mh_summary_check (CamelLocalSummary *cls, break; } if (c == 0) { - info = camel_folder_summary_uid ((CamelFolderSummary *) cls, d->d_name); + info = camel_folder_summary_get ((CamelFolderSummary *) cls, d->d_name); if (info == NULL || (cls->index && (!camel_index_has_name (cls->index, d->d_name)))) { /* need to add this file to the summary */ if (info != NULL) { @@ -290,7 +291,8 @@ mh_summary_sync (CamelLocalSummary *cls, GError **error) { CamelLocalSummaryClass *local_summary_class; - gint count, i; + gint i; + GPtrArray *known_uids; CamelLocalMessageInfo *info; gchar *name; const gchar *uid; @@ -305,9 +307,9 @@ mh_summary_sync (CamelLocalSummary *cls, /* FIXME: need to update/honour .mh_sequences or whatever it is */ camel_folder_summary_prepare_fetch_all ((CamelFolderSummary *) cls, error); - count = camel_folder_summary_count ((CamelFolderSummary *) cls); - for (i = count - 1; i >= 0; i--) { - info = (CamelLocalMessageInfo *) camel_folder_summary_index ((CamelFolderSummary *) cls, i); + known_uids = camel_folder_summary_get_array ((CamelFolderSummary *) cls); + for (i = (known_uids ? known_uids->len : 0) - 1; i >= 0; i--) { + info = (CamelLocalMessageInfo *) camel_folder_summary_get ((CamelFolderSummary *) cls, g_ptr_array_index (known_uids, i)); g_assert (info); if (expunge && (info->info.flags & CAMEL_MESSAGE_DELETED)) { uid = camel_message_info_uid (info); diff --git a/camel/providers/local/camel-spool-summary.c b/camel/providers/local/camel-spool-summary.c index 3d5f6ad..222a48d 100644 --- a/camel/providers/local/camel-spool-summary.c +++ b/camel/providers/local/camel-spool-summary.c @@ -86,8 +86,7 @@ camel_spool_summary_new (CamelFolder *folder, { CamelSpoolSummary *new; - new = g_object_new (CAMEL_TYPE_SPOOL_SUMMARY, NULL); - ((CamelFolderSummary *) new)->folder = folder; + new = g_object_new (CAMEL_TYPE_SPOOL_SUMMARY, "folder", folder, NULL); if (folder) { CamelStore *parent_store; @@ -310,9 +309,11 @@ spool_summary_check (CamelLocalSummary *cls, GCancellable *cancellable, GError **error) { - gint i, work, count; + gint i; + gboolean work; struct stat st; CamelFolderSummary *s = (CamelFolderSummary *) cls; + GPtrArray *known_uids; if (CAMEL_LOCAL_SUMMARY_CLASS (camel_spool_summary_parent_class)->check (cls, changeinfo, cancellable, error) == -1) return -1; @@ -320,13 +321,14 @@ spool_summary_check (CamelLocalSummary *cls, /* check to see if we need to copy/update the file; missing xev headers prompt this */ work = FALSE; camel_folder_summary_prepare_fetch_all (s, error); - count = camel_folder_summary_count (s); - for (i = 0; !work && i < count; i++) { - CamelMboxMessageInfo *info = (CamelMboxMessageInfo *) camel_folder_summary_index (s, i); + known_uids = camel_folder_summary_get_array (s); + for (i = 0; !work && known_uids && i < known_uids->len; i++) { + CamelMboxMessageInfo *info = (CamelMboxMessageInfo *) camel_folder_summary_get (s, g_ptr_array_index (known_uids, i)); g_assert (info); work = (info->info.info.flags & (CAMEL_MESSAGE_FOLDER_NOXEV)) != 0; camel_message_info_free ((CamelMessageInfo *) info); } + camel_folder_summary_free_array (known_uids); /* if we do, then write out the headers using sync_full, etc */ if (work) { diff --git a/camel/providers/nntp/camel-nntp-folder.c b/camel/providers/nntp/camel-nntp-folder.c index 37bebfd..2881df4 100644 --- a/camel/providers/nntp/camel-nntp-folder.c +++ b/camel/providers/nntp/camel-nntp-folder.c @@ -42,11 +42,19 @@ G_DEFINE_TYPE (CamelNNTPFolder, camel_nntp_folder, CAMEL_TYPE_DISCO_FOLDER) static void nntp_folder_dispose (GObject *object) { + CamelStore *parent_store; CamelNNTPFolder *nntp_folder = CAMEL_NNTP_FOLDER (object); camel_folder_summary_save_to_db ( CAMEL_FOLDER (nntp_folder)->summary, NULL); + parent_store = camel_folder_get_parent_store (CAMEL_FOLDER (nntp_folder)); + if (parent_store) { + camel_store_summary_disconnect_folder_summary ( + (CamelStoreSummary *) ((CamelNNTPStore *) parent_store)->summary, + CAMEL_FOLDER (nntp_folder)->summary); + } + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (camel_nntp_folder_parent_class)->dispose (object); } @@ -140,7 +148,7 @@ unset_flagged_flag (const gchar *uid, { CamelMessageInfo *info; - info = camel_folder_summary_uid (summary, uid); + info = camel_folder_summary_get (summary, uid); if (info) { CamelMessageInfoBase *base = (CamelMessageInfoBase *) info; @@ -738,5 +746,9 @@ camel_nntp_folder_new (CamelStore *parent, folder = NULL; } + camel_store_summary_connect_folder_summary ( + (CamelStoreSummary *) ((CamelNNTPStore *) parent)->summary, + folder_name, folder->summary); + return folder; } diff --git a/camel/providers/nntp/camel-nntp-summary.c b/camel/providers/nntp/camel-nntp-summary.c index 105d47e..f8c02e3 100644 --- a/camel/providers/nntp/camel-nntp-summary.c +++ b/camel/providers/nntp/camel-nntp-summary.c @@ -56,7 +56,7 @@ struct _CamelNNTPSummaryPrivate { static CamelMessageInfo * message_info_new_from_header (CamelFolderSummary *, struct _camel_header_raw *); static gint summary_header_load (CamelFolderSummary *, FILE *); static gint summary_header_save (CamelFolderSummary *, FILE *); -static gint summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir); +static gboolean summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir); static CamelFIRecord * summary_header_to_db (CamelFolderSummary *s, GError **error); G_DEFINE_TYPE (CamelNNTPSummary, camel_nntp_summary, CAMEL_TYPE_FOLDER_SUMMARY) @@ -97,8 +97,7 @@ camel_nntp_summary_new (CamelFolder *folder, { CamelNNTPSummary *cns; - cns = g_object_new (CAMEL_TYPE_NNTP_SUMMARY, NULL); - ((CamelFolderSummary *) cns)->folder = folder; + cns = g_object_new (CAMEL_TYPE_NNTP_SUMMARY, "folder", folder, NULL); camel_folder_summary_set_filename ((CamelFolderSummary *) cns, path); camel_folder_summary_set_build_content ((CamelFolderSummary *) cns, FALSE); @@ -128,15 +127,15 @@ message_info_new_from_header (CamelFolderSummary *s, return (CamelMessageInfo *) mi; } -static gint +static gboolean summary_header_from_db (CamelFolderSummary *s, CamelFIRecord *mir) { CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY (s); gchar *part; - if (CAMEL_FOLDER_SUMMARY_CLASS (camel_nntp_summary_parent_class)->summary_header_from_db (s, mir) == -1) - return -1; + if (!CAMEL_FOLDER_SUMMARY_CLASS (camel_nntp_summary_parent_class)->summary_header_from_db (s, mir)) + return FALSE; part = mir->bdata; @@ -144,7 +143,7 @@ summary_header_from_db (CamelFolderSummary *s, cns->high = bdata_extract_digit (&part); cns->low = bdata_extract_digit (&part); - return 0; + return TRUE; } static gint @@ -229,10 +228,8 @@ add_range_xover (CamelNNTPSummary *cns, gint ret; guint n, count, total, size; struct _xover_header *xover; - GHashTable *summary_table; s = (CamelFolderSummary *) cns; - summary_table = camel_folder_summary_get_hashtable (s); url = camel_service_get_camel_url (CAMEL_SERVICE (store)); @@ -301,7 +298,7 @@ add_range_xover (CamelNNTPSummary *cns, /* truncated line? ignore? */ if (xover == NULL) { - if (!GPOINTER_TO_INT (g_hash_table_lookup (summary_table, cns->priv->uid))) { + if (!camel_folder_summary_check_uid (s, cns->priv->uid)) { mi = (CamelMessageInfoBase *) camel_folder_summary_add_from_header (s, headers); if (mi) { @@ -322,8 +319,6 @@ add_range_xover (CamelNNTPSummary *cns, camel_operation_pop_message (cancellable); - camel_folder_summary_free_hashtable (summary_table); - return ret; } @@ -344,12 +339,9 @@ add_range_head (CamelNNTPSummary *cns, guint i, n, count, total; CamelMessageInfo *mi; CamelMimeParser *mp; - GHashTable *summary_table; s = (CamelFolderSummary *) cns; - summary_table = camel_folder_summary_get_hashtable (s); - mp = camel_mime_parser_new (); url = camel_service_get_camel_url (CAMEL_SERVICE (store)); @@ -384,7 +376,7 @@ add_range_head (CamelNNTPSummary *cns, if ((msgid = strchr (line, '<')) && (line = strchr (msgid + 1, '>'))) { line[1] = 0; cns->priv->uid = g_strdup_printf ("%u,%s\n", n, msgid); - if (!GPOINTER_TO_INT (g_hash_table_lookup (summary_table, cns->priv->uid))) { + if (!camel_folder_summary_check_uid (s, cns->priv->uid)) { if (camel_mime_parser_init_with_stream (mp, (CamelStream *) store->stream, error) == -1) goto error; mi = camel_folder_summary_add_from_parser (s, mp); @@ -429,8 +421,6 @@ ioerror: camel_operation_pop_message (cancellable); - camel_folder_summary_free_hashtable (summary_table); - return ret; } @@ -456,8 +446,8 @@ camel_nntp_summary_check (CamelNNTPSummary *cns, s = (CamelFolderSummary *) cns; - full_name = camel_folder_get_full_name (s->folder); - parent_store = camel_folder_get_parent_store (s->folder); + full_name = camel_folder_get_full_name (camel_folder_summary_get_folder (s)); + parent_store = camel_folder_get_parent_store (camel_folder_summary_get_folder (s)); line +=3; n = strtoul (line, &line, 10); @@ -484,36 +474,37 @@ camel_nntp_summary_check (CamelNNTPSummary *cns, /* Check for messages no longer on the server */ if (cns->low != f) { - count = camel_folder_summary_count (s); - for (i = 0; i < count; i++) { - gchar *uid; - const gchar *msgid; - - uid = camel_folder_summary_uid_from_index (s, i); - n = strtoul (uid, NULL, 10); - - if (n < f || n > l) { - dd (printf ("nntp_summary: %u is lower/higher than lowest/highest article, removed\n", n)); - /* Since we use a global cache this could prematurely remove - * a cached message that might be in another folder - not that important as - * it is a true cache */ - msgid = strchr (uid, ','); - if (msgid) - camel_data_cache_remove (store->cache, "cache", msgid+1, NULL); - camel_folder_change_info_remove_uid (changes, uid); - del = g_list_prepend (del, uid); - camel_folder_summary_remove_uid_fast (s, uid); - uid = NULL; /*Lets not free it */ - count--; - i--; + GPtrArray *known_uids; + + known_uids = camel_folder_summary_get_array (s); + if (known_uids) { + for (i = 0; i < known_uids->len; i++) { + const gchar *uid; + const gchar *msgid; + + uid = g_ptr_array_index (known_uids, i); + n = strtoul (uid, NULL, 10); + + if (n < f || n > l) { + dd (printf ("nntp_summary: %u is lower/higher than lowest/highest article, removed\n", n)); + /* Since we use a global cache this could prematurely remove + * a cached message that might be in another folder - not that important as + * it is a true cache */ + msgid = strchr (uid, ','); + if (msgid) + camel_data_cache_remove (store->cache, "cache", msgid + 1, NULL); + camel_folder_change_info_remove_uid (changes, uid); + del = g_list_prepend (del, (gpointer) camel_pstring_strdup (uid)); + camel_folder_summary_remove_uid (s, uid); + } } - g_free (uid); + camel_folder_summary_free_array (known_uids); } cns->low = f; } camel_db_delete_uids (parent_store->cdb_w, full_name, del, NULL); - g_list_foreach (del, (GFunc) g_free, NULL); + g_list_foreach (del, (GFunc) camel_pstring_free, NULL); g_list_free (del); if (cns->high < l) {