From a74c859d8c64ac576255fbc36b5f59468b42ddce Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 25 Mar 2000 05:18:55 +0000 Subject: change the CamelFolderSummary interfaces to allow partial summary queries * camel-folder-summary.[ch]: change the CamelFolderSummary interfaces to allow partial summary queries (for dealing with very large folders). Remove the "extended_fields" from CamelFolderInfo and CamelMessageInfo: this is better dealt with by subtyping. * providers/mbox/camel-mbox-summary.[ch]: Make CamelMboxSummary a subclass of CamelFolderSummary. Update interfaces for that. Remove the internal/external summary distinction. Remove the (unused) md5 checksum in the folder summary. Change the summary file format (primarily to make it no longer byte-order dependent) and add a version number to it so it will be easier to change in the future. * providers/mbox/camel-mbox-folder.[ch] * providers/mbox/camel-mbox-search.c * providers/mbox/camel-mbox-utils.c: update for summary changes * camel-exception-list.def: add CAMEL_EXCEPTION_FOLDER_SUMMARY_INVALID svn path=/trunk/; revision=2159 --- camel/providers/mbox/camel-mbox-folder.c | 278 +++++++++++++------------------ 1 file changed, 119 insertions(+), 159 deletions(-) (limited to 'camel/providers/mbox/camel-mbox-folder.c') diff --git a/camel/providers/mbox/camel-mbox-folder.c b/camel/providers/mbox/camel-mbox-folder.c index 8c7303924e..b8a18f201a 100644 --- a/camel/providers/mbox/camel-mbox-folder.c +++ b/camel/providers/mbox/camel-mbox-folder.c @@ -39,11 +39,9 @@ #include "string-utils.h" #include "camel-log.h" #include "camel-stream-buffered-fs.h" -#include "camel-folder-summary.h" #include "camel-mbox-summary.h" #include "camel-mbox-parser.h" #include "camel-mbox-utils.h" -#include "md5-utils.h" #include "gmime-utils.h" #include "camel-mbox-search.h" #include "camel-data-wrapper.h" @@ -196,7 +194,7 @@ _init (CamelFolder *folder, CamelStore *parent_store, folder->has_summary_capability = TRUE; folder->has_uid_capability = TRUE; folder->has_search_capability = TRUE; - folder->summary = camel_folder_summary_new (); + folder->summary = NULL; CAMEL_LOG_FULL_DEBUG ("Leaving CamelMboxFolder::init_with_store\n"); } @@ -209,92 +207,74 @@ _init (CamelFolder *folder, CamelStore *parent_store, - load the summary or create it if necessary */ static void -_check_get_or_maybe_generate_summary_file (CamelMboxFolder *mbox_folder, CamelException *ex) +_check_get_or_maybe_generate_summary_file (CamelMboxFolder *mbox_folder, + CamelException *ex) { CamelFolder *folder = CAMEL_FOLDER (mbox_folder); + CamelMboxSummary *summ; GArray *message_info_array; - gboolean summary_file_exists; - gboolean summary_file_is_sync; - GArray *mbox_summary_info; gint mbox_file_fd; guint32 next_uid; guint32 file_size; - - /* test for the existence of the summary file */ - summary_file_exists = (access (mbox_folder->summary_file_path, F_OK) == 0); - - /* if the summary file exists, test if the - md5 of the mbox file is still in sync - with the one we had computed the last time - we saved the summary file */ - if (summary_file_exists) { - - summary_file_is_sync = - camel_mbox_check_summary_sync (mbox_folder->summary_file_path, - mbox_folder->folder_file_path, - ex); - if (camel_exception_get_id (ex)) return; + struct stat st; + + folder->summary = NULL; + + /* Test for the existence and up-to-dateness of the summary file. */ + if (stat (mbox_folder->summary_file_path, &st) == 0) { + summ = camel_mbox_summary_load (mbox_folder->summary_file_path, + ex); + if (summ) { + if (summ->mbox_file_size == st.st_size && + summ->mbox_modtime == st.st_mtime) + folder->summary = CAMEL_FOLDER_SUMMARY (summ); + else + gtk_object_destroy (GTK_OBJECT (summ)); + } else { + /* Bad summary file */ + if (camel_exception_get_id (ex) != + CAMEL_EXCEPTION_FOLDER_SUMMARY_INVALID) + return; + camel_exception_clear (ex); + } } - - /* in the case where the summary does not exist - or is not in sync with the mbox file - regenerate it */ - if ( !(summary_file_exists && summary_file_is_sync)) { - - /* parse the mbox folder and get some - information about the messages */ - + /* In the case where the summary does not exist (or was the + * wrong version), or is not in sync with the mbox file, + * regenerate it. + */ + if (folder->summary == NULL) { + /* Parse the mbox folder and get some information + * about the messages. + */ mbox_file_fd = open (mbox_folder->folder_file_path, O_RDONLY); - message_info_array = camel_mbox_parse_file (mbox_file_fd, - "From ", - 0, - &file_size, - &next_uid, - TRUE, - NULL, - 0, - ex); - + message_info_array = + camel_mbox_parse_file (mbox_file_fd, "From ", 0, + &file_size, &next_uid, TRUE, + NULL, 0, ex); close (mbox_file_fd); - if (camel_exception_get_id (ex)) { + if (camel_exception_get_id (ex)) return; - } - - next_uid = camel_mbox_write_xev (mbox_folder->folder_file_path, - message_info_array, &file_size, next_uid, ex); + next_uid = camel_mbox_write_xev (mbox_folder->folder_file_path, + message_info_array, + &file_size, next_uid, ex); if (camel_exception_get_id (ex)) { /* ** FIXME : free the preparsed information */ return; } - - mbox_summary_info = + + summ = CAMEL_MBOX_SUMMARY (gtk_object_new (camel_mbox_summary_get_type (), NULL)); + summ->message_info = parsed_information_to_mbox_summary (message_info_array); - + summ->nb_message = summ->message_info->len; + summ->next_uid = next_uid; + summ->mbox_file_size = file_size; /* **FIXME : Free the parsed information structure */ - /* allocate an internal summary object */ - mbox_folder->internal_summary = g_new (CamelMboxSummary, 1); - - /* generate the folder md5 signature */ - md5_get_digest_from_file (mbox_folder->folder_file_path, mbox_folder->internal_summary->md5_digest); - - /* store the number of messages as well as the summary array */ - mbox_folder->internal_summary->nb_message = mbox_summary_info->len; - mbox_folder->internal_summary->next_uid = next_uid; - mbox_folder->internal_summary->mbox_file_size = file_size; - mbox_folder->internal_summary->message_info = mbox_summary_info; - - } else { - /* every thing seems ok, just read the summary file from disk */ - mbox_folder->internal_summary = camel_mbox_load_summary (mbox_folder->summary_file_path, ex); + folder->summary = CAMEL_FOLDER_SUMMARY (summ); } - - /* copy the internal summary information to the external - folder summary used by the display engines */ - camel_mbox_summary_append_internal_to_external (mbox_folder->internal_summary, folder->summary, 0); } @@ -303,17 +283,17 @@ static void _open (CamelFolder *folder, CamelFolderOpenMode mode, CamelException *ex) { CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); - //struct dirent *dir_entry; - //struct stat stat_buf; /* call parent class */ parent_class->open (folder, mode, ex); if (camel_exception_get_id(ex)) return; +#if 0 /* get (or create) uid list */ - //if (!(mbox_load_uid_list (mbox_folder) > 0)) - // mbox_generate_uid_list (mbox_folder); + if (!(mbox_load_uid_list (mbox_folder) > 0)) + mbox_generate_uid_list (mbox_folder); +#endif _check_get_or_maybe_generate_summary_file (mbox_folder, ex); } @@ -324,12 +304,12 @@ _close (CamelFolder *folder, gboolean expunge, CamelException *ex) { CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); - /* call parent implementation */ parent_class->close (folder, expunge, ex); - - /* save the folder summary on disc */ - camel_mbox_save_summary (mbox_folder->internal_summary, mbox_folder->summary_file_path, ex); + + /* save the folder summary on disk */ + camel_mbox_summary_save (CAMEL_MBOX_SUMMARY (folder->summary), + mbox_folder->summary_file_path, ex); } @@ -340,8 +320,6 @@ _set_name (CamelFolder *folder, const gchar *name, CamelException *ex) { CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); const gchar *root_dir_path; - //gchar *full_name; - //const gchar *parent_full_name; CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::set_name\n"); @@ -353,21 +331,19 @@ _set_name (CamelFolder *folder, const gchar *name, CamelException *ex) g_free (mbox_folder->folder_dir_path); g_free (mbox_folder->index_file_path); - root_dir_path = camel_mbox_store_get_toplevel_dir (CAMEL_MBOX_STORE(folder->parent_store)); - - CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::set_name full_name is %s\n", folder->full_name); - CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::set_name root_dir_path is %s\n", root_dir_path); - - mbox_folder->folder_file_path = g_strdup_printf ("%s/%s", root_dir_path, folder->full_name); - mbox_folder->summary_file_path = g_strdup_printf ("%s/%s-ev-summary", root_dir_path, folder->full_name); - mbox_folder->folder_dir_path = g_strdup_printf ("%s/%s.sdb", root_dir_path, folder->full_name); - mbox_folder->index_file_path = g_strdup_printf ("%s/%s.ibex", root_dir_path, folder->full_name); - - CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::set_name mbox_folder->folder_file_path is %s\n", - mbox_folder->folder_file_path); - CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::set_name mbox_folder->folder_dir_path is %s\n", - mbox_folder->folder_dir_path); - CAMEL_LOG_FULL_DEBUG ("Leaving CamelMboxFolder::set_name\n"); + root_dir_path = camel_mbox_store_get_toplevel_dir (CAMEL_MBOX_STORE (folder->parent_store)); + + mbox_folder->folder_file_path = + g_strdup_printf ("%s/%s", root_dir_path, folder->full_name); + mbox_folder->summary_file_path = + g_strdup_printf ("%s/%s-ev-summary", root_dir_path, + folder->full_name); + mbox_folder->folder_dir_path = + g_strdup_printf ("%s/%s.sdb", root_dir_path, + folder->full_name); + mbox_folder->index_file_path = + g_strdup_printf ("%s/%s.ibex", root_dir_path, + folder->full_name); } @@ -387,8 +363,8 @@ _exists (CamelFolder *folder, CamelException *ex) CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::exists\n"); - mbox_folder = CAMEL_MBOX_FOLDER(folder); - + mbox_folder = CAMEL_MBOX_FOLDER (folder); + /* check if the mbox file path is determined */ if (!mbox_folder->folder_file_path) { camel_exception_set (ex, @@ -456,7 +432,8 @@ _exists (CamelFolder *folder, CamelException *ex) static gboolean _create (CamelFolder *folder, CamelException *ex) { - CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder); + CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); + CamelMboxSummary *summary; const gchar *folder_file_path, *folder_dir_path; mode_t dir_mode = S_IRWXU; gint mkdir_error; @@ -482,14 +459,17 @@ _create (CamelFolder *folder, CamelException *ex) /* if the folder already exists, simply return */ folder_already_exists = camel_folder_exists (folder,ex); - if (camel_exception_get_id (ex)) return FALSE; + if (camel_exception_get_id (ex)) + return FALSE; - if (folder_already_exists) return TRUE; + if (folder_already_exists) + return TRUE; /* create the directory for the subfolders */ mkdir_error = mkdir (folder_dir_path, dir_mode); - if (mkdir_error == -1) goto io_error; + if (mkdir_error == -1) + goto io_error; /* create the mbox file */ @@ -497,15 +477,16 @@ _create (CamelFolder *folder, CamelException *ex) creat_fd = open (folder_file_path, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR, 0600); - if (creat_fd == -1) goto io_error; + if (creat_fd == -1) + goto io_error; close (creat_fd); - /* create the summary object */ - mbox_folder->internal_summary = g_new (CamelMboxSummary, 1); - mbox_folder->internal_summary->nb_message = 0; - mbox_folder->internal_summary->next_uid = 1; - mbox_folder->internal_summary->mbox_file_size = 0; - mbox_folder->internal_summary->message_info = g_array_new (FALSE, FALSE, sizeof (CamelMboxSummaryInformation)); + /* create the summary object */ + summary = CAMEL_MBOX_SUMMARY (gtk_object_new (camel_mbox_summary_get_type (), NULL)); + summary->nb_message = 0; + summary->next_uid = 1; + summary->mbox_file_size = 0; + summary->message_info = g_array_new (FALSE, FALSE, sizeof (CamelMboxSummaryInformation)); return TRUE; @@ -531,15 +512,10 @@ _create (CamelFolder *folder, CamelException *ex) - - - - - static gboolean _delete (CamelFolder *folder, gboolean recurse, CamelException *ex) { - CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder); + CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); const gchar *folder_file_path, *folder_dir_path; gint rmdir_error = 0; gint unlink_error = 0; @@ -552,9 +528,11 @@ _delete (CamelFolder *folder, gboolean recurse, CamelException *ex) /* in the case where the folder does not exist, return immediatly */ folder_already_exists = camel_folder_exists (folder, ex); - if (camel_exception_get_id (ex)) return FALSE; + if (camel_exception_get_id (ex)) + return FALSE; - if (!folder_already_exists) return TRUE; + if (!folder_already_exists) + return TRUE; /* call default implementation. @@ -641,7 +619,7 @@ gboolean _delete_messages (CamelFolder *folder, CamelException *ex) { - CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder); + CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); const gchar *folder_file_path; gboolean folder_already_exists; int creat_fd; @@ -673,7 +651,8 @@ _delete_messages (CamelFolder *folder, CamelException *ex) creat_fd = open (folder_file_path, O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR, 0600); - if (creat_fd == -1) goto io_error; + if (creat_fd == -1) + goto io_error; close (creat_fd); return TRUE; @@ -701,25 +680,17 @@ _delete_messages (CamelFolder *folder, CamelException *ex) } - - - - - - - static GList * _list_subfolders (CamelFolder *folder, CamelException *ex) { GList *subfolder_name_list = NULL; - CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder); + CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); const gchar *folder_dir_path; gboolean folder_exists; struct stat stat_buf; gint stat_error = 0; - //GList *file_list; gchar *entry_name; gchar *full_entry_name; gchar *real_folder_name; @@ -727,9 +698,6 @@ _list_subfolders (CamelFolder *folder, CamelException *ex) DIR *dir_handle; gboolean folder_suffix_found; - //gchar *io_error_text; - - /* check if the folder object exists */ if (!folder) { @@ -839,14 +807,12 @@ _list_subfolders (CamelFolder *folder, CamelException *ex) static gint _get_message_count (CamelFolder *folder, CamelException *ex) { - - CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder); gint message_count; g_assert (folder); - g_assert (mbox_folder->internal_summary); + g_assert (folder->summary); - message_count = mbox_folder->internal_summary->nb_message; + message_count = CAMEL_MBOX_SUMMARY (folder->summary)->nb_message; CAMEL_LOG_FULL_DEBUG ("CamelMboxFolder::get_message_count found %d messages\n", message_count); return message_count; @@ -856,7 +822,8 @@ _get_message_count (CamelFolder *folder, CamelException *ex) static void _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex) { - CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder); + CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); + CamelMboxSummary *summary = CAMEL_MBOX_SUMMARY (folder->summary); CamelStream *output_stream; guint32 tmp_file_size; guint32 next_uid; @@ -868,10 +835,12 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::append_message\n"); - tmp_message_filename = g_strdup_printf ("%s.tmp", mbox_folder->folder_file_path); + tmp_message_filename = g_strdup_printf ("%s.tmp", + mbox_folder->folder_file_path); /* write the message itself */ - output_stream = camel_stream_fs_new_with_name (tmp_message_filename, CAMEL_STREAM_FS_WRITE); + output_stream = camel_stream_fs_new_with_name (tmp_message_filename, + CAMEL_STREAM_FS_WRITE); if (output_stream != NULL) { camel_stream_write_string (output_stream, "From - \n"); camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (message), output_stream); @@ -880,7 +849,7 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException /* at this point we have saved the message to a temporary file, now, we have to add the x-evolution - field and also update the main summary summary */ + field and also update the main summary */ /* First : parse the mbox file, but only from the @@ -890,7 +859,7 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException This position is still stored in the summary for the moment */ - next_uid = mbox_folder->internal_summary->next_uid; + next_uid = summary->next_uid; tmp_file_fd = open (tmp_message_filename, O_RDONLY); message_info_array = camel_mbox_parse_file (tmp_file_fd, "From - ", 0, @@ -901,7 +870,7 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException /* get the value of the last available UID as saved in the summary file */ - next_uid = mbox_folder->internal_summary->next_uid; + next_uid = summary->next_uid; /* OK, this is not very efficient, we should not use the same @@ -920,20 +889,14 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException parsed_information_to_mbox_summary (message_info_array); /* store the number of messages as well as the summary array */ - mbox_folder->internal_summary->nb_message += 1; - mbox_folder->internal_summary->next_uid = next_uid; + summary->nb_message += 1; + summary->next_uid = next_uid; - ((CamelMboxSummaryInformation *)(mbox_summary_info->data))->position += mbox_folder->internal_summary->mbox_file_size; - mbox_folder->internal_summary->mbox_file_size += tmp_file_size; - - camel_mbox_summary_append_entries (mbox_folder->internal_summary, mbox_summary_info); - - /* append the new entry of the internal summary to - the external summary */ - camel_mbox_summary_append_internal_to_external (mbox_folder->internal_summary, - folder->summary, - mbox_folder->internal_summary->nb_message-1); + ((CamelMboxSummaryInformation *)(mbox_summary_info->data))->position += + summary->mbox_file_size; + summary->mbox_file_size += tmp_file_size; + camel_mbox_summary_append_entries (summary, mbox_summary_info); g_array_free (mbox_summary_info, TRUE); @@ -964,9 +927,6 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException /* remove the temporary file */ //unlink (tmp_message_filename); - /* generate the folder md5 signature */ - md5_get_digest_from_file (mbox_folder->folder_file_path, mbox_folder->internal_summary->md5_digest); - g_free (tmp_message_filename); CAMEL_LOG_FULL_DEBUG ("Leaving CamelMboxFolder::append_message\n"); } @@ -977,7 +937,6 @@ _append_message (CamelFolder *folder, CamelMimeMessage *message, CamelException static GList * _get_uid_list (CamelFolder *folder, CamelException *ex) { - CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder); GArray *message_info_array; CamelMboxSummaryInformation *message_info; GList *uid_list = NULL; @@ -985,10 +944,10 @@ _get_uid_list (CamelFolder *folder, CamelException *ex) CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::get_uid_list\n"); - message_info_array = mbox_folder->internal_summary->message_info; + message_info_array = + CAMEL_MBOX_SUMMARY (folder->summary)->message_info; for (i=0; ilen; i++) { - message_info = (CamelMboxSummaryInformation *)(message_info_array->data) + i; uid_list = g_list_prepend (uid_list, g_strdup_printf ("%u", message_info->uid)); } @@ -1009,7 +968,7 @@ static CamelMimeMessage * _get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex) { - CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER(folder); + CamelMboxFolder *mbox_folder = CAMEL_MBOX_FOLDER (folder); GArray *message_info_array; CamelMboxSummaryInformation *message_info = NULL; guint32 searched_uid; @@ -1021,9 +980,10 @@ _get_message_by_uid (CamelFolder *folder, const gchar *uid, CamelException *ex) CAMEL_LOG_FULL_DEBUG ("Entering CamelMboxFolder::get_message_by_uid\n"); - searched_uid = strtoul(uid, (char **)NULL, 10); + searched_uid = strtoul (uid, NULL, 10); - message_info_array = mbox_folder->internal_summary->message_info; + message_info_array = + CAMEL_MBOX_SUMMARY (folder->summary)->message_info; i=0; uid_found = FALSE; -- cgit v1.2.3