File beagle-meta-summary.patch of Package evolution-data-server

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
openSUSE Build Service is sponsored by