** See bug #51045.
authorNot Zed <NotZed@Ximian.com>
Mon, 16 Feb 2004 09:38:24 +0000 (09:38 +0000)
committerMichael Zucci <zucchi@src.gnome.org>
Mon, 16 Feb 2004 09:38:24 +0000 (09:38 +0000)
2004-02-16  Not Zed  <NotZed@Ximian.com>

        ** See bug #51045.

        * providers/imap/camel-imap-store.c (fill_fi): similar to mbox
        version.
        (get_folder_counts): use fill_fi to try and get folder counts if
        we're not doing the hard slog.
        (get_one_folder_offline): use fill_fi to try to get folder counts
        from open folders or summaries.

        * providers/local/camel-maildir-store.c (fill_fi): similar to mbox
        version.
        (scan_dir): use fill_fi to get the unread count now.

        * providers/local/camel-mbox-store.c (fill_fi): helper to lookup
        unread count either from active folder or from summary file, if
        it's available.
        (scan_dir, get_folder_info): use helper above to get folder info.

        * devel-docs/camel-folder-summary.txt: New document describing the
        format/conventions in the CamelFolderSummary file.

        * providers/nntp/camel-nntp-summary.c (summary_header_load/save):
        * providers/imapp/camel-imapp-summary.c (summary_header_load/save):
        * providers/imap/camel-imap-summary.c (summary_header_load/save):
        Handle versions, per-class version number (1).

        * providers/local/camel-mbox-summary.c (summary_header_load/save):
        Handle versions properly, add a per-class version (1).  Write out the
        folder size as a size_t rather than 32 bit int.

        * providers/local/camel-local-summary.c (summary_header_load/save):
        read/write the per-class version number (1).

        * camel-folder-summary.c (summary_header_load): do version
        checking differently, allow the version to be bumped without
        aborting the load.  Added unread/deleted/junk counts to base
        header.
        (summary_header_save): Save out the new-format header.  Version
        bumped to 13.

        * camel.c (camel_init): return 0 rather than spit a compiler warning.

        * camel-file-utils.c (camel_file_util_encode_*_t): macro-ise the
        type encoder/decoders.  Also add size_t encoder/decoder.

20 files changed:
camel/ChangeLog
camel/camel-file-utils.c
camel/camel-file-utils.h
camel/camel-folder-summary.c
camel/camel-folder-summary.h
camel/camel-operation.c
camel/camel.c
camel/providers/imap/camel-imap-store.c
camel/providers/imap/camel-imap-summary.c
camel/providers/imap/camel-imap-summary.h
camel/providers/imapp/camel-imapp-summary.c
camel/providers/imapp/camel-imapp-summary.h
camel/providers/local/camel-local-summary.c
camel/providers/local/camel-local-summary.h
camel/providers/local/camel-maildir-store.c
camel/providers/local/camel-mbox-store.c
camel/providers/local/camel-mbox-summary.c
camel/providers/local/camel-mbox-summary.h
camel/providers/nntp/camel-nntp-summary.c
camel/providers/nntp/camel-nntp-summary.h

index 1330a2c..d6eee1e 100644 (file)
@@ -1,3 +1,50 @@
+2004-02-16  Not Zed  <NotZed@Ximian.com>
+
+       ** See bug #51045.
+
+       * providers/imap/camel-imap-store.c (fill_fi): similar to mbox
+       version.
+       (get_folder_counts): use fill_fi to try and get folder counts if
+       we're not doing the hard slog.
+       (get_one_folder_offline): use fill_fi to try to get folder counts
+       from open folders or summaries.
+
+       * providers/local/camel-maildir-store.c (fill_fi): similar to mbox
+       version.
+       (scan_dir): use fill_fi to get the unread count now.
+
+       * providers/local/camel-mbox-store.c (fill_fi): helper to lookup
+       unread count either from active folder or from summary file, if
+       it's available.
+       (scan_dir, get_folder_info): use helper above to get folder info.
+
+       * devel-docs/camel-folder-summary.txt: New document describing the
+       format/conventions in the CamelFolderSummary file.
+
+       * providers/nntp/camel-nntp-summary.c (summary_header_load/save): 
+       * providers/imapp/camel-imapp-summary.c (summary_header_load/save): 
+       * providers/imap/camel-imap-summary.c (summary_header_load/save):
+       Handle versions, per-class version number (1).
+
+       * providers/local/camel-mbox-summary.c (summary_header_load/save):
+       Handle versions properly, add a per-class version (1).  Write out the
+       folder size as a size_t rather than 32 bit int.
+
+       * providers/local/camel-local-summary.c (summary_header_load/save):
+       read/write the per-class version number (1).
+
+       * camel-folder-summary.c (summary_header_load): do version
+       checking differently, allow the version to be bumped without
+       aborting the load.  Added unread/deleted/junk counts to base
+       header.
+       (summary_header_save): Save out the new-format header.  Version
+       bumped to 13.
+
+       * camel.c (camel_init): return 0 rather than spit a compiler warning.
+
+       * camel-file-utils.c (camel_file_util_encode_*_t): macro-ise the
+       type encoder/decoders.  Also add size_t encoder/decoder.
+
 2004-02-13  Jeffrey Stedfast  <fejj@ximian.com>
 
        * providers/imap/camel-imap-store.c (get_folder_online): Same.
index f4ed4cd..0d51795 100644 (file)
@@ -144,6 +144,37 @@ camel_file_util_decode_fixed_int32 (FILE *in, gint32 *dest)
        }
 }
 
+#define CFU_ENCODE_T(type)                                             \
+int                                                                    \
+camel_file_util_encode_##type(FILE *out, type value)                   \
+{                                                                      \
+       int i;                                                          \
+                                                                       \
+       for (i = sizeof (type) - 1; i >= 0; i--) {                      \
+               if (fputc((value >> (i * 8)) & 0xff, out) == -1)        \
+                       return -1;                                      \
+       }                                                               \
+       return 0;                                                       \
+}
+
+#define CFU_DECODE_T(type)                             \
+int                                                    \
+camel_file_util_decode_##type(FILE *in, type *dest)    \
+{                                                      \
+       type save = 0;                                  \
+       int i = sizeof(type) - 1;                       \
+       int v = EOF;                                    \
+                                                       \
+        while (i >= 0 && (v = fgetc (in)) != EOF) {    \
+               save |= ((type)v) << (i * 8);           \
+               i--;                                    \
+       }                                               \
+       *dest = save;                                   \
+       if (v == EOF)                                   \
+               return -1;                              \
+       return 0;                                       \
+}
+
 
 /**
  * camel_file_util_encode_time_t:
@@ -154,18 +185,7 @@ camel_file_util_decode_fixed_int32 (FILE *in, gint32 *dest)
  * 
  * Return value: 0 on success, -1 on error.
  **/
-int
-camel_file_util_encode_time_t(FILE *out, time_t value)
-{
-       int i;
-
-       for (i = sizeof (time_t) - 1; i >= 0; i--) {
-               if (fputc((value >> (i * 8)) & 0xff, out) == -1)
-                       return -1;
-       }
-       return 0;
-}
-
+CFU_ENCODE_T(time_t)
 
 /**
  * camel_file_util_decode_time_t:
@@ -176,23 +196,7 @@ camel_file_util_encode_time_t(FILE *out, time_t value)
  * 
  * Return value: 0 on success, -1 on error.
  **/
-int
-camel_file_util_decode_time_t (FILE *in, time_t *dest)
-{
-       time_t save = 0;
-       int i = sizeof (time_t) - 1;
-       int v = EOF;
-
-        while (i >= 0 && (v = fgetc (in)) != EOF) {
-               save |= ((time_t)v) << (i * 8);
-               i--;
-       }
-       *dest = save;
-       if (v == EOF)
-               return -1;
-       return 0;
-}
-
+CFU_DECODE_T(time_t)
 
 /**
  * camel_file_util_encode_off_t:
@@ -203,17 +207,7 @@ camel_file_util_decode_time_t (FILE *in, time_t *dest)
  * 
  * Return value: 0 on success, -1 on error.
  **/
-int
-camel_file_util_encode_off_t (FILE *out, off_t value)
-{
-       int i;
-
-       for (i = sizeof (off_t) - 1; i >= 0; i--) {
-               if (fputc ((value >> (i * 8)) & 0xff, out) == -1)
-                       return -1;
-       }
-       return 0;
-}
+CFU_ENCODE_T(off_t)
 
 
 /**
@@ -225,22 +219,30 @@ camel_file_util_encode_off_t (FILE *out, off_t value)
  * 
  * Return value: 0 on success, -1 on failure.
  **/
-int
-camel_file_util_decode_off_t (FILE *in, off_t *dest)
-{
-       off_t save = 0;
-       int i = sizeof(off_t) - 1;
-       int v = EOF;
+CFU_DECODE_T(off_t)
 
-        while (i >= 0 && (v = fgetc (in)) != EOF) {
-               save |= ((off_t)v) << (i * 8);
-               i--;
-       }
-       *dest = save;
-       if (v == EOF)
-               return -1;
-       return 0;
-}
+/**
+ * camel_file_util_encode_size_t:
+ * @out: file to output to
+ * @value: value to output
+ * 
+ * Encode an size_t type.
+ * 
+ * Return value: 0 on success, -1 on error.
+ **/
+CFU_ENCODE_T(size_t)
+
+
+/**
+ * camel_file_util_decode_size_t:
+ * @in: file to read from
+ * @dest: pointer to a variable to put the value in
+ * 
+ * Decode an size_t type.
+ * 
+ * Return value: 0 on success, -1 on failure.
+ **/
+CFU_DECODE_T(size_t)
 
 
 /**
index 15022d9..1e37b27 100644 (file)
@@ -45,6 +45,8 @@ int camel_file_util_encode_time_t (FILE *out, time_t);
 int camel_file_util_decode_time_t (FILE *in, time_t *);
 int camel_file_util_encode_off_t (FILE *out, off_t);
 int camel_file_util_decode_off_t (FILE *in, off_t *);
+int camel_file_util_encode_size_t (FILE *out, size_t);
+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 **);
 
index 05b3f3a..ac0ca87 100644 (file)
@@ -75,7 +75,7 @@ static pthread_mutex_t info_lock = PTHREAD_MUTEX_INITIALIZER;
 extern int strdup_count, malloc_count, free_count;
 #endif
 
-#define CAMEL_FOLDER_SUMMARY_VERSION (12)
+#define CAMEL_FOLDER_SUMMARY_VERSION (13)
 
 #define _PRIVATE(o) (((CamelFolderSummary *)(o))->priv)
 
@@ -1403,45 +1403,81 @@ my_list_size(struct _node **list)
 static int
 summary_header_load(CamelFolderSummary *s, FILE *in)
 {
-       gint32 version, flags, nextuid, count;
-       time_t time;
-
        fseek(in, 0, SEEK_SET);
 
        io(printf("Loading header\n"));
 
-       if (camel_file_util_decode_fixed_int32(in, &version) == -1
-           || camel_file_util_decode_fixed_int32(in, &flags) == -1
-           || camel_file_util_decode_fixed_int32(in, &nextuid) == -1
-           || camel_file_util_decode_time_t(in, &time) == -1
-           || camel_file_util_decode_fixed_int32(in, &count) == -1) {
+       if (camel_file_util_decode_fixed_int32(in, &s->version) == -1)
                return -1;
-       }
 
-       s->nextuid = nextuid;
-       s->flags = flags;
-       s->time = time;
-       s->saved_count = count;
-       if (s->version != version) {
-               d(printf ("Summary header version mismatch"));
+       /* Legacy version check, before version 12 we have no upgrade knowledge */
+       if ((s->version > 0xff) && (s->version & 0xff) < 12) {
+               (printf ("Summary header version mismatch"));
                errno = EINVAL;
                return -1;
        }
+
+       if (!(s->version < 0x100 && s->version >= 13))
+               printf("Loading legacy summary\n");
+       else
+               printf("loading new-format summary\n");
+
+       /* legacy version */
+       if (camel_file_util_decode_fixed_int32(in, &s->flags) == -1
+           || camel_file_util_decode_fixed_int32(in, &s->nextuid) == -1
+           || camel_file_util_decode_time_t(in, &s->time) == -1
+           || camel_file_util_decode_fixed_int32(in, &s->saved_count) == -1) {
+               return -1;
+       }
+
+       /* version 13 */
+       if (s->version < 0x100 && s->version >= 13
+           && (camel_file_util_decode_fixed_int32(in, &s->unread_count) == -1
+               || camel_file_util_decode_fixed_int32(in, &s->deleted_count) == -1
+               || camel_file_util_decode_fixed_int32(in, &s->junk_count) == -1)) {
+               return -1;
+       }
+
        return 0;
 }
 
 static int
 summary_header_save(CamelFolderSummary *s, FILE *out)
 {
+       int unread = 0, deleted = 0, junk = 0, count, i;
+
        fseek(out, 0, SEEK_SET);
 
        io(printf("Savining header\n"));
 
-       camel_file_util_encode_fixed_int32(out, s->version);
+       /* 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_time_t(out, s->time);
-       return camel_file_util_encode_fixed_int32(out, camel_folder_summary_count(s));
+
+       count = camel_folder_summary_count(s);
+       for (i=0; i<count; i++) {
+               CamelMessageInfo *info = camel_folder_summary_index(s, i);
+
+               if (info == NULL)
+                       continue;
+
+               if ((info->flags & CAMEL_MESSAGE_SEEN) == 0)
+                       unread++;
+               if ((info->flags & CAMEL_MESSAGE_DELETED) != 0)
+                       deleted++;
+               if ((info->flags & CAMEL_MESSAGE_JUNK) != 0)
+                       junk++;
+
+               camel_folder_summary_info_free(s, info);
+       }
+
+       camel_file_util_encode_fixed_int32(out, 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);
 }
 
 /* are these even useful for anything??? */
index e57be75..366df70 100644 (file)
@@ -160,11 +160,14 @@ struct _CamelFolderSummary {
        struct _CamelFolderSummaryPrivate *priv;
 
        /* header info */
-       guint32 version;        /* version of file required, should be set by implementors */
+       guint32 version;        /* version of file loaded/loading */
        guint32 flags;          /* flags */
        guint32 nextuid;        /* next uid? */
-       guint32 saved_count;    /* how many were saved/loaded */
        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;
 
        /* sizes of memory objects */
        guint32 message_info_size;
index 03c0c77..5e041a1 100644 (file)
@@ -312,10 +312,11 @@ camel_operation_cancel (CamelOperation *cc)
  * Register a thread or the main thread for cancellation through @cc.
  * If @cc is NULL, then a new cancellation is created for this thread.
  *
- * All calls to operation_register() should be matched with calls to
- * operation_unregister(), or resources will be lost.
+ * All calls to operation_register() should save their value and call
+ * operation_register again with that, to automatically stack
+ * registrations.
  *
- * Return Value: Returns @cc, or if NULL, the new operation.
+ * Return Value: Returns the previously registered operatoin.
  *
  **/
 CamelOperation *
@@ -332,7 +333,7 @@ camel_operation_register (CamelOperation *cc)
  * camel_operation_unregister:
  * @cc: operation context
  * 
- * Unregister the current thread.
+ * Unregister the current thread for all cancellations.
  **/
 void
 camel_operation_unregister (CamelOperation *cc)
index 8d60968..44a894c 100644 (file)
@@ -74,7 +74,7 @@ camel_init (const char *configdir, gboolean nss_init)
        void camel_operation_init(void);
        
        if (initialised)
-               return;
+               return 0;
        
        if (getenv ("CAMEL_VERBOSE_DEBUG"))
                camel_verbose_debug = TRUE;
index 7b86773..4ca1b1d 100644 (file)
@@ -2349,6 +2349,48 @@ dumpfi(CamelFolderInfo *fi)
 #endif
 
 static void
+fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags)
+{
+       CamelFolder *folder;
+       int unread = -1;
+
+       folder = camel_object_bag_get(store->folders, fi->full_name);
+       if (folder) {
+               if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0)
+                       camel_folder_refresh_info(folder, NULL);
+               unread = camel_folder_get_unread_message_count(folder);
+               camel_object_unref(folder);
+       } else {
+               char *storage_path, *folder_dir, *path;
+               CamelFolderSummary *s;
+
+               printf("looking up counts from '%s'\n", fi->full_name);
+
+               /* This is a lot of work for one path! */
+               storage_path = g_strdup_printf("%s/folders", ((CamelImapStore *)store)->storage_path);
+               folder_dir = e_path_to_physical(storage_path, fi->full_name);
+               path = g_strdup_printf("%s/summary", folder_dir);
+               s = (CamelFolderSummary *)camel_object_new(camel_imap_summary_get_type());
+               camel_folder_summary_set_build_content(s, TRUE);
+               camel_folder_summary_set_filename(s, path);
+               if (camel_folder_summary_header_load(s) != -1) {
+                       unread = s->unread_count;
+                       printf("loaded summary header unread = %d\n", unread);
+               } else {
+                       printf("couldn't load summary header?\n");
+               }
+
+               g_free(storage_path);
+               g_free(folder_dir);
+               g_free(path);
+               
+               camel_object_unref(s);
+       }
+
+       fi->unread_message_count = unread;
+}
+
+static void
 get_folder_counts(CamelImapStore *imap_store, CamelFolderInfo *fi, CamelException *ex)
 {
        GSList *q;
@@ -2393,13 +2435,8 @@ get_folder_counts(CamelImapStore *imap_store, CamelFolderInfo *fi, CamelExceptio
                
                                CAMEL_SERVICE_UNLOCK (imap_store, connect_lock);
                        } else {
-                               /* since its cheap, get it if they're open */
-                               folder = camel_object_bag_get(CAMEL_STORE(imap_store)->folders, fi->full_name);
-                               if (folder) {
-                                       fi->unread_message_count = camel_folder_get_unread_message_count(folder);
-                                       camel_object_unref(folder);
-                               } else
-                                       fi->unread_message_count = -1;
+                               /* since its cheap, get it if they're open/consult summary file */
+                               fill_fi((CamelStore *)imap_store, fi, 0);
                        }
 
                        if (fi->child)
@@ -2636,6 +2673,8 @@ get_one_folder_offline (const char *physical_path, const char *path, gpointer da
                                g_free(fi->url);
                                fi->url = camel_url_to_string (url, 0);
                                camel_url_free (url);
+                       } else {
+                               fill_fi((CamelStore *)imap_store, fi, 0);
                        }
                        g_ptr_array_add (folders, fi);
                }
index dba1134..bebc672 100644 (file)
@@ -35,7 +35,7 @@
 #include "camel-imap-summary.h"
 #include "camel-file-utils.h"
 
-#define CAMEL_IMAP_SUMMARY_VERSION (0x300)
+#define CAMEL_IMAP_SUMMARY_VERSION (1)
 
 static int summary_header_load (CamelFolderSummary *, FILE *);
 static int summary_header_save (CamelFolderSummary *, FILE *);
@@ -94,9 +94,6 @@ camel_imap_summary_init (CamelImapSummary *obj)
        /* subclasses need to set the right instance data sizes */
        s->message_info_size = sizeof(CamelImapMessageInfo);
        s->content_info_size = sizeof(CamelImapMessageContentInfo);
-
-       /* and a unique file version */
-       s->version += CAMEL_IMAP_SUMMARY_VERSION;
 }
 
 /**
@@ -125,7 +122,6 @@ camel_imap_summary_new (const char *filename)
        return summary;
 }
 
-
 static int
 summary_header_load (CamelFolderSummary *s, FILE *in)
 {
@@ -134,7 +130,22 @@ summary_header_load (CamelFolderSummary *s, FILE *in)
        if (camel_imap_summary_parent->summary_header_load (s, in) == -1)
                return -1;
 
-       return camel_file_util_decode_uint32 (in, &ims->validity);
+       /* Legacy version */
+       if (s->version == 0x30c)
+               return camel_file_util_decode_uint32(in, &ims->validity);
+
+       /* Version 1 */
+       if (camel_file_util_decode_fixed_int32(in, &ims->version) == -1
+           || camel_file_util_decode_fixed_int32(in, &ims->validity) == -1)
+               return -1;
+
+       if (ims->version > CAMEL_IMAP_SUMMARY_VERSION) {
+               g_warning("Unkown summary version\n");
+               errno = EINVAL;
+               return -1;
+       }
+
+       return 0;
 }
 
 static int
@@ -145,9 +156,10 @@ summary_header_save (CamelFolderSummary *s, FILE *out)
        if (camel_imap_summary_parent->summary_header_save (s, out) == -1)
                return -1;
 
-       return camel_file_util_encode_uint32 (out, ims->validity);
-}
+       camel_file_util_encode_fixed_int32(out, CAMEL_IMAP_SUMMARY_VERSION);
 
+       return camel_file_util_encode_fixed_int32(out, ims->validity);
+}
 
 static CamelMessageInfo *
 message_info_load (CamelFolderSummary *s, FILE *in)
index 817e884..fc54d8d 100644 (file)
@@ -55,6 +55,7 @@ typedef struct _CamelImapMessageInfo {
 struct _CamelImapSummary {
        CamelFolderSummary parent;
 
+       guint32 version;
        guint32 validity;
 };
 
index a0df21b..05f0ec5 100644 (file)
@@ -35,7 +35,7 @@
 #include "camel-imapp-summary.h"
 #include <camel/camel-file-utils.h>
 
-#define CAMEL_IMAPP_SUMMARY_VERSION (0x1000)
+#define CAMEL_IMAPP_SUMMARY_VERSION (1)
 
 static int summary_header_load(CamelFolderSummary *, FILE *);
 static int summary_header_save(CamelFolderSummary *, FILE *);
@@ -119,8 +119,22 @@ summary_header_load(CamelFolderSummary *s, FILE *in)
        if (camel_imapp_summary_parent->summary_header_load(s, in) == -1)
                return -1;
 
-       return camel_file_util_decode_uint32(in, &ims->uidvalidity);
-}
+       /* Legacy version */
+       if (s->version == 0x100c)
+               return camel_file_util_decode_uint32(in, &ims->uidvalidity);
+
+       if (camel_file_util_decode_fixed_int32(in, &ims->version) == -1
+           || camel_file_util_decode_fixed_int32(in, &ims->uidvalidity) == -1)
+               return -1;
+
+       if (ims->version > CAMEL_IMAPP_SUMMARY_VERSION) {
+               g_warning("Unkown summary version\n");
+               errno = EINVAL;
+               return -1;
+       }
+
+       return 0;
+}      
 
 static int
 summary_header_save(CamelFolderSummary *s, FILE *out)
@@ -130,7 +144,11 @@ summary_header_save(CamelFolderSummary *s, FILE *out)
        if (camel_imapp_summary_parent->summary_header_save(s, out) == -1)
                return -1;
 
-       return camel_file_util_encode_uint32(out, ims->uidvalidity);
+       if (camel_file_util_encode_fixed_int32(out, CAMEL_IMAPP_SUMMARY_VERSION) == -1
+           || camel_file_util_encode_fixed_int32(out, ims->uidvalidity) == -1)
+               return -1;
+
+       return 0;
 }
 
 
index e978362..215ad24 100644 (file)
@@ -50,6 +50,7 @@ typedef struct _CamelIMAPPMessageInfo {
 struct _CamelIMAPPSummary {
        CamelFolderSummary parent;
 
+       guint32 version;
        guint32 uidvalidity;
 };
 
index 42534b3..a1f4831 100644 (file)
 #include "camel-local-summary.h"
 #include "camel/camel-mime-message.h"
 #include "camel/camel-stream-null.h"
+#include "camel/camel-file-utils.h"
 
 #define w(x)
 #define io(x)
 #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/
 
-#define CAMEL_LOCAL_SUMMARY_VERSION (0x200)
+#define CAMEL_LOCAL_SUMMARY_VERSION (1)
+
+static int summary_header_load (CamelFolderSummary *, FILE *);
+static int summary_header_save (CamelFolderSummary *, FILE *);
 
 static CamelMessageInfo * message_info_new (CamelFolderSummary *, struct _camel_header_raw *);
 
@@ -81,6 +85,9 @@ camel_local_summary_class_init(CamelLocalSummaryClass *klass)
        
        camel_local_summary_parent = CAMEL_FOLDER_SUMMARY_CLASS(camel_type_get_global_classfuncs(camel_folder_summary_get_type()));
 
+       sklass->summary_header_load = summary_header_load;
+       sklass->summary_header_save = summary_header_save;
+
        sklass->message_info_new  = message_info_new;
 
        klass->load = local_summary_load;
@@ -577,6 +584,35 @@ local_summary_decode_x_evolution(CamelLocalSummary *cls, const char *xev, CamelM
        return 0;
 }
 
+static int
+summary_header_load(CamelFolderSummary *s, FILE *in)
+{
+       CamelLocalSummary *cls = (CamelLocalSummary *)s;
+
+       /* We dont actually add our own headers, but version that we don't anyway */
+
+       if (((CamelFolderSummaryClass *)camel_local_summary_parent)->summary_header_load(s, in) == -1)
+               return -1;
+
+       /* Legacy version, version is in summary only */
+       if ((s->version & 0xfff) == 0x20c)
+               return 0;
+
+       /* otherwise load the version number */
+       return camel_file_util_decode_fixed_int32(in, &cls->version);
+}
+
+static int
+summary_header_save(CamelFolderSummary *s, FILE *out)
+{
+       /*CamelLocalSummary *cls = (CamelLocalSummary *)s;*/
+
+       if (((CamelFolderSummaryClass *)camel_local_summary_parent)->summary_header_save(s, out) == -1)
+               return -1;
+
+       return camel_file_util_encode_fixed_int32(out, CAMEL_LOCAL_SUMMARY_VERSION);
+}
+
 static CamelMessageInfo *
 message_info_new(CamelFolderSummary *s, struct _camel_header_raw *h)
 {
index 25d77e6..99a520f 100644 (file)
@@ -42,7 +42,9 @@ enum {
 
 struct _CamelLocalSummary {
        CamelFolderSummary parent;
-       
+
+       guint32 version;        /* file version being loaded */
+
        char *folder_path;      /* name of matching folder */
        
        CamelIndex *index;
index 0eff01f..df17bcd 100644 (file)
@@ -36,6 +36,7 @@
 #include "camel-exception.h"
 #include "camel-url.h"
 #include "camel-private.h"
+#include "camel-maildir-summary.h"
 
 #define d(x)
 
@@ -237,6 +238,45 @@ static CamelFolderInfo *camel_folder_info_new(const char *url, const char *full,
        return fi;
 }
 
+static void
+fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags)
+{
+       CamelFolder *folder;
+       int unread = -1;
+
+       folder = camel_object_bag_get(store->folders, fi->full_name);
+       if (folder) {
+               if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0)
+                       camel_folder_refresh_info(folder, NULL);
+               unread = camel_folder_get_unread_message_count(folder);
+               camel_object_unref(folder);
+       } else {
+               char *path, *folderpath;
+               CamelFolderSummary *s;
+               const char *root;
+
+               printf("looking up counts from '%s'\n", fi->full_name);
+
+               /* This should be fast enough not to have to test for INFO_FAST */
+               root = camel_local_store_get_toplevel_dir((CamelLocalStore *)store);
+               path = g_strdup_printf("%s/%s.ev-summary", root, fi->full_name);
+               folderpath = g_strdup_printf("%s/%s", root, fi->full_name);
+               s = (CamelFolderSummary *)camel_maildir_summary_new(path, folderpath, NULL);
+               if (camel_folder_summary_header_load(s) != -1) {
+                       unread = s->unread_count;
+                       printf("loaded summary header unread = %d\n", unread);
+               } else {
+                       printf("couldn't load summary header?\n");
+               }
+               
+               camel_object_unref(s);
+               g_free(folderpath);
+               g_free(path);
+       }
+
+       fi->unread_message_count = unread;
+}
+
 /* used to find out where we've visited already */
 struct _inode {
        dev_t dnode;
@@ -316,8 +356,10 @@ static int scan_dir(CamelStore *store, GHashTable *visited, char *root, const ch
                }
        }
        
-       fi = camel_folder_info_new(uri, path, base, unread);
-       
+       fi = camel_folder_info_new(uri, path, base, -1);
+       /* fills the unread count */
+       fill_fi(store, fi, flags);
+
        d(printf("found! uri = %s\n", fi->url));
        d(printf("  full_name = %s\n  name = '%s'\n", fi->full_name, fi->name));
        
index b1a5664..ef11791 100644 (file)
@@ -581,6 +581,47 @@ inode_free(void *k, void *v, void *d)
        g_free(k);
 }
 
+/* NB: duplicated in maildir store */
+static void
+fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags)
+{
+       CamelFolder *folder;
+       int unread = -1;
+
+       folder = camel_object_bag_get(store->folders, fi->full_name);
+       if (folder) {
+               if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0)
+                       camel_folder_refresh_info(folder, NULL);
+               unread = camel_folder_get_unread_message_count(folder);
+               camel_object_unref(folder);
+       } else {
+               char *path, *folderpath;
+               CamelMboxSummary *mbs;
+               const char *root;
+
+               printf("looking up counts from '%s'\n", fi->full_name);
+
+               /* This should be fast enough not to have to test for INFO_FAST */
+               root = camel_local_store_get_toplevel_dir((CamelLocalStore *)store);
+               path = camel_mbox_folder_get_meta_path(root, fi->full_name, ".ev-summary");
+               folderpath = camel_mbox_folder_get_full_path(root, fi->full_name);
+               
+               mbs = (CamelMboxSummary *)camel_mbox_summary_new(path, folderpath, NULL);
+               if (camel_folder_summary_header_load((CamelFolderSummary *)mbs) != -1) {
+                       unread = ((CamelFolderSummary *)mbs)->unread_count;
+                       printf("loaded summary header unread = %d\n", unread);
+               } else {
+                       printf("couldn't load summary header?\n");
+               }
+               
+               camel_object_unref(mbs);
+               g_free(folderpath);
+               g_free(path);
+       }
+
+       fi->unread_message_count = unread;
+}
+
 static CamelFolderInfo *
 scan_dir(CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const char *root,
         const char *name, guint32 flags, CamelException *ex)
@@ -603,9 +644,7 @@ scan_dir(CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const
        
        while ((dent = readdir(dir))) {
                char *short_name, *full_name, *path, *ext;
-               CamelFolder *folder;
                struct stat st;
-               int unread = -1;
                
                if (dent->d_name[0] == '.')
                        continue;
@@ -636,17 +675,7 @@ scan_dir(CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const
                        full_name = g_strdup_printf("%s/%s", name, short_name);
                else
                        full_name = g_strdup(short_name);
-               
-               if (!S_ISDIR(st.st_mode)) {
-                       folder = camel_object_bag_get(store->folders, full_name);
-                       if (folder) {
-                               if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0)
-                                       camel_folder_refresh_info(folder, NULL);
-                               unread = camel_folder_get_unread_message_count(folder);
-                               camel_object_unref(folder);
-                       }
-               }
-               
+                               
                if ((fi = g_hash_table_lookup(folder_hash, short_name)) != NULL) {
                        g_free(short_name);
                        g_free(full_name);
@@ -654,7 +683,6 @@ scan_dir(CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const
                        if (S_ISDIR(st.st_mode)) {
                                fi->flags =(fi->flags & ~CAMEL_FOLDER_NOCHILDREN) | CAMEL_FOLDER_CHILDREN;
                        } else {
-                               fi->unread_message_count = unread;
                                fi->flags &= ~CAMEL_FOLDER_NOSELECT;
                                if ((ext = strchr(fi->url, ';')) && !strncmp(ext, ";noselect=yes", 13))
                                        memmove(ext, ext + 13, strlen(ext + 13) + 1);
@@ -669,7 +697,7 @@ scan_dir(CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const
                        fi->name = short_name;
                        fi->full_name = full_name;
                        fi->path = g_strdup_printf("/%s", full_name);
-                       fi->unread_message_count = unread;
+                       fi->unread_message_count = -1;
                        
                        if (S_ISDIR(st.st_mode))
                                fi->flags = CAMEL_FOLDER_NOSELECT;
@@ -686,7 +714,9 @@ scan_dir(CamelStore *store, GHashTable *visited, CamelFolderInfo *parent, const
                        g_hash_table_insert(folder_hash, fi->name, fi);
                }
                
-               if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE) && S_ISDIR(st.st_mode)) {
+               if (!S_ISDIR(st.st_mode))
+                       fill_fi(store, fi, flags);
+               else if ((flags & CAMEL_STORE_FOLDER_INFO_RECURSIVE)) {
                        struct _inode in = { st.st_dev, st.st_ino };
                        
                        if (g_hash_table_lookup(visited, &in) == NULL) {
@@ -718,10 +748,8 @@ get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelExceptio
        struct _inode *inode;
        char *path, *subdir;
        CamelFolderInfo *fi;
-       CamelFolder *folder;
        const char *base;
        struct stat st;
-       int unread = -1;
        
        top = top ? top : "";
        path = mbox_folder_name_to_path(store, top);
@@ -735,7 +763,7 @@ get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelExceptio
                
                visited = g_hash_table_new(inode_hash, inode_equal);
                
-               inode = g_new(struct _inode, 1);
+               inode = g_malloc0(sizeof(*inode));
                inode->dnode = st.st_dev;
                inode->inode = st.st_ino;
                
@@ -761,26 +789,22 @@ get_folder_info(CamelStore *store, const char *top, guint32 flags, CamelExceptio
                base = top;
        else
                base++;
-       
-       folder = camel_object_bag_get(store->folders, top);
-       if (folder) {
-               if ((flags & CAMEL_STORE_FOLDER_INFO_FAST) == 0)
-                       camel_folder_refresh_info(folder, NULL);
-               unread = camel_folder_get_unread_message_count(folder);
-               camel_object_unref(folder);
-       }
-       
+
        fi = g_new0(CamelFolderInfo, 1);
        fi->parent = NULL;
        fi->url = g_strdup_printf("mbox:%s#%s",((CamelService *) store)->url->path, top);
        fi->name = g_strdup(base);
        fi->full_name = g_strdup(top);
-       fi->unread_message_count = unread;
+       fi->unread_message_count = -1;
        fi->path = g_strdup_printf("/%s", top);
        
        subdir = g_strdup_printf("%s.sbd", path);
-       if (stat(subdir, &st) == 0 && S_ISDIR(st.st_mode))
-               fi->child = scan_dir(store, visited, fi, subdir, top, flags, ex);
+       if (stat(subdir, &st) == 0) {
+               if  (S_ISDIR(st.st_mode))
+                       fi->child = scan_dir(store, visited, fi, subdir, top, flags, ex);
+               else
+                       fill_fi(store, fi, flags);
+       }
        
        if (fi->child)
                fi->flags |= CAMEL_FOLDER_CHILDREN;
index 4018fc9..ac87fd2 100644 (file)
@@ -44,7 +44,7 @@
 #define io(x)
 #define d(x) /*(printf("%s(%d): ", __FILE__, __LINE__),(x))*/
 
-#define CAMEL_MBOX_SUMMARY_VERSION (0x1000)
+#define CAMEL_MBOX_SUMMARY_VERSION (1)
 
 static int summary_header_load (CamelFolderSummary *, FILE *);
 static int summary_header_save (CamelFolderSummary *, FILE *);
@@ -172,7 +172,16 @@ summary_header_load(CamelFolderSummary *s, FILE *in)
        if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_load(s, in) == -1)
                return -1;
 
-       return camel_file_util_decode_uint32(in, (guint32 *) &mbs->folder_size);
+       /* legacy version */
+       if (s->version == 0x120c)
+               return camel_file_util_decode_uint32(in, (guint32 *) &mbs->folder_size);
+
+       /* version 1 */
+       if (camel_file_util_decode_fixed_int32(in, &mbs->version) == -1
+           || camel_file_util_decode_size_t(in, &mbs->folder_size) == -1)
+               return -1;
+
+       return 0;
 }
 
 static int
@@ -183,7 +192,9 @@ summary_header_save(CamelFolderSummary *s, FILE *out)
        if (((CamelFolderSummaryClass *)camel_mbox_summary_parent)->summary_header_save(s, out) == -1)
                return -1;
 
-       return camel_file_util_encode_uint32(out, mbs->folder_size);
+       camel_file_util_encode_fixed_int32(out, CAMEL_MBOX_SUMMARY_VERSION);
+
+       return camel_file_util_encode_size_t(out, mbs->folder_size);
 }
 
 static CamelMessageInfo *
index dc64aa2..34402ad 100644 (file)
@@ -48,6 +48,7 @@ struct _CamelMboxSummary {
 
        CamelFolderChangeInfo *changes; /* used to build change sets */
 
+       guint32 version;
        size_t folder_size;     /* size of the mbox file, last sync */
 
        unsigned int xstatus:1; /* do we store/honour xstatus/status headers */
index 2fa753b..6c9c7e5 100644 (file)
@@ -48,7 +48,7 @@
 extern int camel_verbose_debug;
 #define dd(x) (camel_verbose_debug?(x):0)
 
-#define CAMEL_NNTP_SUMMARY_VERSION (0x200)
+#define CAMEL_NNTP_SUMMARY_VERSION (1)
 
 static int xover_setup(CamelNNTPSummary *cns, CamelException *ex);
 static int add_range_xover(CamelNNTPSummary *cns, unsigned int high, unsigned int low, CamelFolderChangeInfo *changes, CamelException *ex);
@@ -191,8 +191,25 @@ summary_header_load(CamelFolderSummary *s, FILE *in)
 {
        CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(s);
 
-       if (((CamelFolderSummaryClass *)camel_nntp_summary_parent)->summary_header_load(s, in) == -1
-           || camel_file_util_decode_fixed_int32(in, &cns->high) == -1
+       if (((CamelFolderSummaryClass *)camel_nntp_summary_parent)->summary_header_load(s, in) == -1)
+               return -1;
+
+       /* Legacy version */
+       if (s->version == 0x20c) {
+               camel_file_util_decode_fixed_int32(in, &cns->high);
+               return camel_file_util_decode_fixed_int32(in, &cns->low);
+       }
+
+       if (camel_file_util_decode_fixed_int32(in, &cns->version) == -1)
+               return -1;
+
+       if (cns->version > CAMEL_NNTP_SUMMARY_VERSION) {
+               g_warning("Unknown NNTP summary version");
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (camel_file_util_decode_fixed_int32(in, &cns->high) == -1
            || camel_file_util_decode_fixed_int32(in, &cns->low) == -1)
                return -1;
 
@@ -205,6 +222,7 @@ summary_header_save(CamelFolderSummary *s, FILE *out)
        CamelNNTPSummary *cns = CAMEL_NNTP_SUMMARY(s);
 
        if (((CamelFolderSummaryClass *)camel_nntp_summary_parent)->summary_header_save(s, out) == -1
+           || camel_file_util_encode_fixed_int32(out, CAMEL_NNTP_SUMMARY_VERSION) == -1
            || camel_file_util_encode_fixed_int32(out, cns->high) == -1
            || camel_file_util_encode_fixed_int32(out, cns->low) == -1)
                return -1;
index 9db3297..b89ffe9 100644 (file)
@@ -39,6 +39,7 @@ struct _CamelNNTPSummary {
 
        struct _CamelNNTPFolder *folder;
 
+       guint32 version;
        guint32 high, low;
 };