evolution-data-server/beagle-meta-summary.patch

560 lines
18 KiB
Diff
Raw Normal View History

Index: camel/camel-file-utils.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-file-utils.c,v
retrieving revision 1.16
diff -u -p -r1.16 camel-file-utils.c
--- camel/camel-file-utils.c 10 Jan 2006 07:56:46 -0000 1.16
+++ camel/camel-file-utils.c 12 Mar 2006 20:49:46 -0000
@@ -316,6 +316,72 @@ camel_file_util_decode_string (FILE *in,
return 0;
}
+/**
+ * camel_file_util_encode_fixed_string:
+ * @out: file to output to
+ * @str: value to output
+ * @len: total-len of str to store
+ *
+ * Encode a normal string and save it in the output file.
+ * Unlike @camel_file_util_encode_string, it pads the
+ * @str with "NULL" bytes, if @len is > strlen(str)
+ *
+ * Return value: 0 on success, -1 on error.
+ **/
+int
+camel_file_util_encode_fixed_string (FILE *out, const char *str, size_t len)
+{
+ char buf[len];
+
+ /* Don't allow empty strings to be written */
+ if (len < 1)
+ return -1;
+
+ /* Max size is 64K */
+ if (len > 65536)
+ len = 65536;
+
+ memset(buf, 0x00, len);
+ g_strlcpy(buf, str, len);
+
+ if (fwrite (buf, len, 1, out) == len)
+ return 0;
+
+ return -1;
+}
+
+
+/**
+ * camel_file_util_decode_fixed_string:
+ * @in: file to read from
+ * @str: pointer to a variable to store the value in
+ * @len: total-len to decode.
+ *
+ * Decode a normal string from the input file.
+ *
+ * Return value: 0 on success, -1 on error.
+ **/
+int
+camel_file_util_decode_fixed_string (FILE *in, char **str, size_t len)
+{
+ register char *ret;
+
+ if (len > 65536) {
+ *str = NULL;
+ return -1;
+ }
+
+ ret = g_malloc (len+1);
+ if (len > 0 && fread (ret, len, 1, in) != 1) {
+ g_free (ret);
+ *str = NULL;
+ return -1;
+ }
+
+ ret[len] = 0;
+ *str = ret;
+ return 0;
+}
/**
* camel_file_util_safe_filename:
Index: camel/camel-file-utils.h
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-file-utils.h,v
retrieving revision 1.11
diff -u -p -r1.11 camel-file-utils.h
--- camel/camel-file-utils.h 10 Jan 2006 07:56:46 -0000 1.11
+++ camel/camel-file-utils.h 12 Mar 2006 20:49:46 -0000
@@ -54,6 +54,9 @@ int camel_file_util_encode_size_t (FILE
int camel_file_util_decode_size_t (FILE *in, size_t *);
int camel_file_util_encode_string (FILE *out, const char *);
int camel_file_util_decode_string (FILE *in, char **);
+int camel_file_util_encode_fixed_string (FILE *out, const char *str, size_t len);
+int camel_file_util_decode_fixed_string (FILE *in, char **str, size_t len);
+
char *camel_file_util_safe_filename (const char *name);
Index: camel/camel-folder-summary.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-folder-summary.c,v
retrieving revision 1.147
diff -u -p -r1.147 camel-folder-summary.c
--- camel/camel-folder-summary.c 2 Feb 2006 05:38:25 -0000 1.147
+++ camel/camel-folder-summary.c 12 Mar 2006 20:49:47 -0000
@@ -78,6 +78,8 @@ extern int strdup_count, malloc_count, f
#define _PRIVATE(o) (((CamelFolderSummary *)(o))->priv)
+#define META_SUMMARY_SUFFIX_LEN 5 /* strlen("-meta") */
+
/* trivial lists, just because ... */
struct _node {
struct _node *next;
@@ -88,12 +90,15 @@ static int my_list_size(struct _node **l
static int summary_header_load(CamelFolderSummary *, FILE *);
static int summary_header_save(CamelFolderSummary *, FILE *);
+static int summary_meta_header_load(CamelFolderSummary *, FILE *);
+static int summary_meta_header_save(CamelFolderSummary *, FILE *);
static CamelMessageInfo * message_info_new_from_header(CamelFolderSummary *, struct _camel_header_raw *);
static CamelMessageInfo * message_info_new_from_parser(CamelFolderSummary *, CamelMimeParser *);
static CamelMessageInfo * message_info_new_from_message(CamelFolderSummary *s, CamelMimeMessage *msg);
static CamelMessageInfo * message_info_load(CamelFolderSummary *, FILE *);
static int message_info_save(CamelFolderSummary *, FILE *, CamelMessageInfo *);
+static int meta_message_info_save(CamelFolderSummary *s, FILE *out_meta, FILE *out, CamelMessageInfo *info);
static void message_info_free(CamelFolderSummary *, CamelMessageInfo *);
static CamelMessageContentInfo * content_info_new_from_header(CamelFolderSummary *, struct _camel_header_raw *);
@@ -146,6 +151,13 @@ camel_folder_summary_init (CamelFolderSu
p->filter_lock = g_mutex_new();
p->alloc_lock = g_mutex_new();
p->ref_lock = g_mutex_new();
+
+ s->meta_summary = g_malloc0(sizeof(CamelFolderMetaSummary));
+
+ /* Default is 20, any implementor having UIDs that has length
+ exceeding 20, has to override this value
+ */
+ s->meta_summary->uid_len = 20;
}
static void free_o_name(void *key, void *value, void *data)
@@ -193,6 +205,10 @@ camel_folder_summary_finalize (CamelObje
camel_object_unref((CamelObject *)p->filter_stream);
if (p->index)
camel_object_unref((CamelObject *)p->index);
+
+ /* Freeing memory occupied by meta-summary-header */
+ g_free(s->meta_summary->path);
+ g_free(s->meta_summary);
g_mutex_free(p->summary_lock);
g_mutex_free(p->io_lock);
@@ -256,6 +272,9 @@ camel_folder_summary_set_filename(CamelF
g_free(s->summary_path);
s->summary_path = g_strdup(name);
+ g_free(s->meta_summary->path);
+ s->meta_summary->path = g_strconcat(name, "-meta", NULL);
+
CAMEL_SUMMARY_UNLOCK(s, summary_lock);
}
@@ -544,7 +563,8 @@ camel_folder_summary_load(CamelFolderSum
int i;
CamelMessageInfo *mi;
- if (s->summary_path == NULL)
+ if (s->summary_path == NULL ||
+ s->meta_summary->path == NULL)
return 0;
in = g_fopen(s->summary_path, "rb");
@@ -630,14 +650,17 @@ int
camel_folder_summary_save(CamelFolderSummary *s)
{
FILE *out;
- int fd, i;
+ FILE *out_meta;
+ int fd, i, fd_meta;
guint32 count;
CamelMessageInfo *mi;
char *path;
+ char *path_meta;
g_assert(s->message_info_size >= sizeof(CamelMessageInfoBase));
- if (s->summary_path == NULL
+ if (s->summary_path == NULL
+ || s->meta_summary->path == NULL
|| (s->flags & CAMEL_SUMMARY_DIRTY) == 0)
return 0;
@@ -655,32 +678,65 @@ camel_folder_summary_save(CamelFolderSum
return -1;
}
+ /* Meta summary code */
+ /* This meta summary will be used by beagle in order to
+ quickly pass through the actual summary file, which
+ is quite time consuming otherwise.
+ */
+ /* FIXME: Merge meta-summary and summary */
+ path_meta = alloca(strlen(s->meta_summary->path)+4);
+ sprintf(path_meta, "%s~", s->meta_summary->path);
+ fd_meta = g_open(path_meta, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600);
+ if (fd_meta == -1)
+ return -1;
+ out_meta = fdopen(fd_meta, "wb");
+ if (out_meta == NULL) {
+ i = errno;
+ g_unlink(path);
+ g_unlink(path_meta);
+ close(fd);
+ close(fd_meta);
+ errno = i;
+ return -1;
+ }
+
io(printf("saving header\n"));
CAMEL_SUMMARY_LOCK(s, io_lock);
if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_save(s, out) == -1)
goto exception;
-
+
+ if (summary_meta_header_save(s, out_meta) == -1)
+ goto exception;
+
/* now write out each message ... */
/* we check ferorr when done for i/o errors */
count = s->messages->len;
for (i = 0; i < count; i++) {
mi = s->messages->pdata[i];
- if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS (s)))->message_info_save (s, out, mi) == -1)
+ if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS (s)))->meta_message_info_save (s, out_meta, out, mi) == -1)
goto exception;
+ if (((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS (s)))->message_info_save (s, out, mi) == -1)
+ goto exception;
+
if (s->build_content) {
if (perform_content_info_save (s, out, ((CamelMessageInfoBase *)mi)->content) == -1)
goto exception;
}
}
+ /* FIXME: Can't we use the above "fd" variables, instead of fileno()? */
if (fflush (out) != 0 || fsync (fileno (out)) == -1)
goto exception;
+ if (fflush (out_meta) != 0 || fsync (fileno (out_meta)) == -1)
+ goto exception;
+
fclose (out);
-
+ fclose (out_meta);
+
CAMEL_SUMMARY_UNLOCK(s, io_lock);
#ifdef G_OS_WIN32
@@ -692,6 +748,13 @@ camel_folder_summary_save(CamelFolderSum
errno = i;
return -1;
}
+
+ if (g_rename(path_meta, s->meta_summary->path) == -1) {
+ i = errno;
+ g_unlink(path_meta);
+ errno = i;
+ return -1;
+ }
s->flags &= ~CAMEL_SUMMARY_DIRTY;
return 0;
@@ -701,10 +764,12 @@ camel_folder_summary_save(CamelFolderSum
i = errno;
fclose (out);
+ fclose (out_meta);
CAMEL_SUMMARY_UNLOCK(s, io_lock);
g_unlink (path);
+ g_unlink (path_meta);
errno = i;
return -1;
@@ -725,20 +790,30 @@ int
camel_folder_summary_header_load(CamelFolderSummary *s)
{
FILE *in;
+ FILE *in_meta;
int ret;
- if (s->summary_path == NULL)
+ if (s->summary_path == NULL ||
+ s->meta_summary->path == NULL)
return 0;
in = g_fopen(s->summary_path, "rb");
if (in == NULL)
return -1;
+ in_meta = g_fopen(s->meta_summary->path, "rb");
+ if (in_meta == NULL) {
+ fclose(in);
+ return -1;
+ }
+
CAMEL_SUMMARY_LOCK(s, io_lock);
ret = ((CamelFolderSummaryClass *)(CAMEL_OBJECT_GET_CLASS(s)))->summary_header_load(s, in);
+ ret = summary_meta_header_load(s, in_meta);
CAMEL_SUMMARY_UNLOCK(s, io_lock);
fclose(in);
+ fclose(in_meta);
s->flags &= ~CAMEL_SUMMARY_DIRTY;
return ret;
}
@@ -1086,6 +1161,7 @@ camel_folder_summary_clear(CamelFolderSu
g_hash_table_destroy(s->messages_uid);
s->messages_uid = g_hash_table_new(g_str_hash, g_str_equal);
s->flags |= CAMEL_SUMMARY_DIRTY;
+ s->meta_summary->msg_expunged = TRUE;
CAMEL_SUMMARY_UNLOCK(s, summary_lock);
}
@@ -1104,8 +1180,9 @@ camel_folder_summary_remove(CamelFolderS
g_hash_table_remove(s->messages_uid, camel_message_info_uid(info));
g_ptr_array_remove(s->messages, info);
s->flags |= CAMEL_SUMMARY_DIRTY;
+ s->meta_summary->msg_expunged = TRUE;
CAMEL_SUMMARY_UNLOCK(s, summary_lock);
-
+
camel_message_info_free(info);
}
@@ -1390,8 +1467,30 @@ my_list_size(struct _node **list)
}
static int
+summary_meta_header_load(CamelFolderSummary *s, FILE *in)
+{
+ if (!s->meta_summary->path)
+ return -1;
+
+ fseek(in, 0, SEEK_SET);
+
+ io(printf("Loading meta-header\n"));
+
+ if (camel_file_util_decode_uint32(in, &s->meta_summary->major) == -1
+ || camel_file_util_decode_uint32(in, &s->meta_summary->minor) == -1
+ || camel_file_util_decode_uint32(in, &s->meta_summary->uid_len) == -1) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
summary_header_load(CamelFolderSummary *s, FILE *in)
{
+ if (!s->summary_path)
+ return -1;
+
fseek(in, 0, SEEK_SET);
io(printf("Loading header\n"));
@@ -1471,6 +1570,25 @@ summary_header_save(CamelFolderSummary *
return camel_file_util_encode_fixed_int32(out, junk);
}
+static int
+summary_meta_header_save(CamelFolderSummary *s, FILE *out_meta)
+{
+ fseek(out_meta, 0, SEEK_SET);
+
+ /* Save meta-summary header */
+ if (s->meta_summary->msg_expunged) {
+ s->meta_summary->msg_expunged = FALSE;
+ camel_file_util_encode_uint32(out_meta, ++s->meta_summary->major);
+ camel_file_util_encode_uint32(out_meta, (s->meta_summary->minor=0));
+ } else {
+ camel_file_util_encode_uint32(out_meta, s->meta_summary->major);
+ camel_file_util_encode_uint32(out_meta, ++s->meta_summary->minor);
+ }
+ camel_file_util_encode_uint32(out_meta, s->meta_summary->uid_len);
+
+ return ferror(out_meta);
+}
+
/* are these even useful for anything??? */
static CamelMessageInfo *
message_info_new_from_parser(CamelFolderSummary *s, CamelMimeParser *mp)
@@ -1774,6 +1892,25 @@ error:
}
static int
+meta_message_info_save(CamelFolderSummary *s, FILE *out_meta, FILE *out, CamelMessageInfo *info)
+{
+ time_t timestamp;
+ off_t offset;
+ CamelMessageInfoBase *mi = (CamelMessageInfoBase *)info;
+
+ time (&timestamp);
+ offset = ftell (out);
+ /* FIXME: errno check after ftell */
+
+ camel_file_util_encode_time_t(out_meta, timestamp);
+ camel_file_util_encode_fixed_string(out_meta, camel_message_info_uid(mi), s->meta_summary->uid_len);
+ camel_file_util_encode_uint32(out_meta, mi->flags);
+ camel_file_util_encode_off_t(out_meta, offset);
+
+ return ferror(out);
+}
+
+static int
message_info_save(CamelFolderSummary *s, FILE *out, CamelMessageInfo *info)
{
guint32 count;
@@ -3115,6 +3252,7 @@ camel_folder_summary_class_init (CamelFo
klass->message_info_new_from_message = message_info_new_from_message;
klass->message_info_load = message_info_load;
klass->message_info_save = message_info_save;
+ klass->meta_message_info_save = meta_message_info_save;
klass->message_info_free = message_info_free;
klass->message_info_clone = message_info_clone;
Index: camel/camel-folder-summary.h
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-folder-summary.h,v
retrieving revision 1.86
diff -u -p -r1.86 camel-folder-summary.h
--- camel/camel-folder-summary.h 31 Aug 2005 04:21:56 -0000 1.86
+++ camel/camel-folder-summary.h 12 Mar 2006 20:49:47 -0000
@@ -46,6 +46,8 @@ typedef struct _CamelFolderSummaryClass
typedef struct _CamelMessageInfo CamelMessageInfo;
typedef struct _CamelMessageInfoBase CamelMessageInfoBase;
+typedef struct _CamelFolderMetaSummary CamelFolderMetaSummary;
+
/* A tree of message content info structures
describe the content structure of the message (if it has any) */
struct _CamelMessageContentInfo {
@@ -224,6 +226,7 @@ struct _CamelFolderSummary {
GHashTable *messages_uid; /* CamelMessageInfo's by uid */
struct _CamelFolder *folder; /* parent folder, for events */
+ struct _CamelFolderMetaSummary *meta_summary; /* Meta summary */
};
struct _CamelFolderSummaryClass {
@@ -238,7 +241,8 @@ struct _CamelFolderSummaryClass {
CamelMessageInfo * (*message_info_new_from_parser)(CamelFolderSummary *, CamelMimeParser *);
CamelMessageInfo * (*message_info_new_from_message)(CamelFolderSummary *, CamelMimeMessage *);
CamelMessageInfo * (*message_info_load)(CamelFolderSummary *, FILE *);
- int (*message_info_save)(CamelFolderSummary *, FILE *, CamelMessageInfo *);
+ int (*message_info_save)(CamelFolderSummary *, FILE *, CamelMessageInfo *);
+ int (*meta_message_info_save)(CamelFolderSummary *, FILE *, FILE *, CamelMessageInfo *);
void (*message_info_free)(CamelFolderSummary *, CamelMessageInfo *);
CamelMessageInfo * (*message_info_clone)(CamelFolderSummary *, const CamelMessageInfo *);
@@ -272,6 +276,15 @@ struct _CamelFolderSummaryClass {
gboolean (*info_set_user_flag)(CamelMessageInfo *mi, const char *id, gboolean state);
gboolean (*info_set_user_tag)(CamelMessageInfo *mi, const char *id, const char *val);
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 */
+ char *path; /* Path to meta-summary-file */
};
CamelType camel_folder_summary_get_type (void);
Index: camel/providers/groupwise/camel-groupwise-summary.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/providers/groupwise/camel-groupwise-summary.c,v
retrieving revision 1.10
diff -u -p -r1.10 camel-groupwise-summary.c
--- camel/providers/groupwise/camel-groupwise-summary.c 9 Nov 2005 14:23:44 -0000 1.10
+++ camel/providers/groupwise/camel-groupwise-summary.c 12 Mar 2006 20:49:47 -0000
@@ -122,6 +122,9 @@ camel_groupwise_summary_init (CamelGroup
/* subclasses need to set the right instance data sizes */
s->message_info_size = sizeof(CamelGroupwiseMessageInfo);
s->content_info_size = sizeof(CamelGroupwiseMessageContentInfo);
+
+ /* Meta-summary - Overriding UID len */
+ s->meta_summary->uid_len = 2048;
}
Index: camel/providers/local/camel-mbox-summary.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/providers/local/camel-mbox-summary.c,v
retrieving revision 1.56
diff -u -p -r1.56 camel-mbox-summary.c
--- camel/providers/local/camel-mbox-summary.c 8 Dec 2005 11:28:47 -0000 1.56
+++ camel/providers/local/camel-mbox-summary.c 12 Mar 2006 20:49:47 -0000
@@ -54,6 +54,7 @@ static CamelMessageInfo * message_info_n
static CamelMessageInfo * message_info_new_from_parser(CamelFolderSummary *, CamelMimeParser *);
static CamelMessageInfo * message_info_load (CamelFolderSummary *, FILE *);
static int message_info_save (CamelFolderSummary *, FILE *, CamelMessageInfo *);
+static int meta_message_info_save(CamelFolderSummary *s, FILE *out_meta, FILE *out, CamelMessageInfo *mi);
/*static void message_info_free (CamelFolderSummary *, CamelMessageInfo *);*/
static char *mbox_summary_encode_x_evolution (CamelLocalSummary *cls, const CamelLocalMessageInfo *mi);
@@ -153,6 +154,7 @@ camel_mbox_summary_class_init(CamelMboxS
sklass->message_info_new_from_parser = message_info_new_from_parser;
sklass->message_info_load = message_info_load;
sklass->message_info_save = message_info_save;
+ sklass->meta_message_info_save = meta_message_info_save;
/*sklass->message_info_free = message_info_free;*/
sklass->info_set_user_flag = mbox_info_set_user_flag;
@@ -378,6 +380,20 @@ message_info_load(CamelFolderSummary *s,
error:
camel_message_info_free(mi);
return NULL;
+}
+
+static int
+meta_message_info_save(CamelFolderSummary *s, FILE *out_meta, FILE *out, CamelMessageInfo *mi)
+{
+ CamelMboxMessageInfo *mbi = (CamelMboxMessageInfo *)mi;
+
+ io(printf("saving mbox message info\n"));
+
+ if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->meta_message_info_save(s, out_meta, out, mi) == -1
+ || camel_file_util_encode_off_t(out_meta, mbi->frompos) == -1)
+ return -1;
+
+ return 0;
}
static int
Index: camel/providers/local/camel-mbox-store.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/providers/local/camel-mbox-store.c,v
retrieving revision 1.44
diff -u -p -r1.44 camel-mbox-store.c
--- camel/providers/local/camel-mbox-store.c 10 Jan 2006 07:56:48 -0000 1.44
+++ camel/providers/local/camel-mbox-store.c 13 Mar 2006 13:33:37 -0000
@@ -99,7 +99,7 @@ camel_mbox_store_get_type(void)
}
static char *extensions[] = {
- ".msf", ".ev-summary", ".ibex.index", ".ibex.index.data", ".cmeta", ".lock"
+ ".msf", ".ev-summary", ".ibex.index", ".ibex.index.data", ".cmeta", ".lock", ".ev-summary-meta"
};
static gboolean