Disksummary Camel.Folder

The disksummary version of CamelFolder is a bit different from the original Evolution/Camel.Folder. One difference is that there are no functions for getting the list of messages (UIDs or MessageInfos) anymore, only iterators (cursors) are used instead through a single interface. Another major difference is that all of the message-state related functions have been removed and must all be performed by the Evolution/CamelDS.FolderSummary#Camel.MessageInfo methods instead. There are a few other minor changes as well as a major new feature - views.

Large chunks of complexity have been moved into the CamelFolderSummary object, making the CamelFolder object just having to deal with basic message operations.

The rationale behind these changes were:

  • Remove all the duplicated methods of doing things, to reduce maintenance work
  • Simplify the CamelFolder object as much as possible

  • Move to iterator-based searching and listing:

** To reduce the memory overhead required for listing and searching ** Allow incremental search results to be displayed in the user interface

  • Extend CamelFolder to provide multiple indices (views) of the same data

** Allows more reliable, efficient virtual folders to be implemented ** Should be able to write a very scalable database backend

Base Class

The public structure is still the same.

 struct _CamelFolder {
        CamelObject parent_object;
        struct _CamelFolderPrivate *priv;
        char *name;
        char *full_name;
        char *description;
        CamelStore *parent_store;
        CamelFolderSummary *summary;
        guint32 folder_flags;
        guint32 permanent_flags;

But the summary object must always be set on the object when it is initialised. It is no longer possible to create 'simple folders' anymore. Likewise, searching is not optional - it is provided internally by the Evolution/CamelDS.FolderSummary object, too. As such, the related option bits no longer do anything/are to be removed.

expunge has been removed, but apart from that, all the basic folder operations from Evolution/Camel.Folder#Base class are the same.


Same as Evolution/Camel.Folder#Hooks, except for the #Folder changes event data.


The properties are almost the same as Evolution/Camel.Folder#Properties, apart from some minor changes. One new property, and the UID_ARRAY and INFO_ARRAY properties no longer function.

  • CAMEL_FOLDER_URI: Returns the uri that can later be used to resolve this folder. This removes the need for code to keep track of the uri AND the folder all the time.

None of the folder property accessor functions exist anymore.

Folder changes

All folder changes are now handled by Evolution/CamelDS.FolderSummary - although to the client code they still appear to come from the folder itself.

In addition, CamelfolderChangeInfo has changed, it is now called CamelChangeInfo, and instead of containing UID arrays, the arrays point directly to CamelMessageInfo structures. The recent list no longer exists, and instead CAMEL_MESSAGE_RECENT is a new system flag on Evolution/CamelDS.FolderSummary#CamelDS.MessageInfo.

See Evolution/CamelDS.FolderSummary#CamelDS.ChangeInfo for more info.

The freeze and thaw interfaces remain unchanged.

Message state

All of the message-state related functions have been removed entirely. All retrieval and modifications are done through the Evolution/CamelDS.FolderSummary#CamelDS.MessageInfo structures.


Searching is radically different to the interfaces defined in Evolution/Camel.Folder#Searching. It now uses iterators, and supports an additional argument beyond the expression. It is now also implemented by the Evolution/CamelDS.FolderSummary directly, so that an implementation will rarely need to override the search method. And yes, there is no only 1 search method.

 CamelIterator *camel_folder_search(CamelFolder *folder, const char *vid, const char *expr, CamelIterator *iter, CamelException *ex);
  • vid: This is the 'view id' of the folder to search. A view id identifies a specific subset of the messages in the folder, which are maintained as an automatic index, driven by its own search term. This is managed by the Evolution/CamelDS.FolderSummary as well.

  • expr: Same basic expression as before.
  • iter: This is an iterator which selects a sub-set of messages to match against. Currently if this is passed, then vid is ignored, although that could be fixed.

There needs to be additional interfaces to add view information on a folder-by-folder basis. It should probably not be up to the client code to talk to the Evolution/CamelDS.FolderSummary object directly, although that may also be sufficient in the short term.

The iterator returned will return CamelMessageInfo objects which can be used one at a time, reffed, or whatever. This provides an incremenental search interface, that should map quite well to database type backends.


Example: Listing a folder

First, listing a whole folder:

        CamelIterator *iter;
        const CamelMessageInfo *mi;
        iter = camel_folder_search(folder, NULL, NULL, NULL, ex);
        while ((mi = camel_iterator_next(iter, NULL)))
                printf("Subject: %s\n", camel_message_info_subject(mi));

Note how iterators make the memory mangement a little simpler. They own the reference to the CamelMessageInfo, and let you use it until they are invoked again.

Example: Searching a folder

This is exactly the same as just listing a folder, but we give it an expression to match against.

        CamelIterator *iter;
        const CamelMessageInfo *mi;
        iter = camel_folder_search(folder, NULL, "(header-contains \"subject\" \"evolution\")", NULL, ex);
        while ((mi = camel_iterator_next(iter, NULL)))
                printf("Subject: %s\n", camel_message_info_subject(mi));

This will match all messages with Evolution in the subject. Note how the code loop is just the same. This simplifies most clients which will be showing a list of 'current' messages, either all or from a search.

Example: Searching deleted messages

This is a pseudo-example showing how a deleted-messages 'view' might be used to narrow down the search:

        CamelIterator *iter;
        const CamelMessageInfo *mi;
        iter = camel_folder_search(folder, "#.trash", "(header-contains \"from\" \"notzed\")", NULL, ex);
        while ((mi = camel_iterator_next(iter, NULL)))
                printf("Subject: %s\n", camel_message_info_subject(mi));

Where ".#trash" is the view-id of the deleted messages index.

Note that because the view is a constantly updated index, this search is very efficient, it only searches the deleted messages, it doesn't have to search all messages to find the deleted ones first, like the older Evolution/Camel.VFolder#Camel.VTrashFolder must. This is covered in the Evolution/CamelDS.FolderSummary page, since that is where the smarts are implemented.


There is also another proposed interface that will let a folder be used as a folder listing mechanism too - removing all of the nasty Evolution/Camel.Store#Camel.FolderInfo stuff.

 CamelIterator *camel_folder_get_folders(CamelFolder *folder, const char *pattern, CamelException *ex);

This is currently not properly implemented though. If it was, then the folder should have delete and rename methods that perform these functions so they no longer exist on the store. As well as any corresponding events.

And an optional CamelIFolderSubscribe interface could be added to support folder subscriptions too.

The same for a CamelIFolderOffline interface for offline mode.

Apps/Evolution/CamelDS.Folder (last edited 2013-08-08 22:50:01 by WilliamJonMcCann)