diff options
author | Not Zed <NotZed@HelixCode.com> | 2000-11-21 21:38:53 +0800 |
---|---|---|
committer | Michael Zucci <zucchi@src.gnome.org> | 2000-11-21 21:38:53 +0800 |
commit | a34a4b15b8e5ab5f0a145c17ef0969da9666d8d0 (patch) | |
tree | 9115b83535becfc19b984178b8cf40d0fca64e70 /camel/camel-folder-search.c | |
parent | c657e20b4c142f72de93fd133e0afeabca872a66 (diff) | |
download | gsoc2013-evolution-a34a4b15b8e5ab5f0a145c17ef0969da9666d8d0.tar.gz gsoc2013-evolution-a34a4b15b8e5ab5f0a145c17ef0969da9666d8d0.tar.zst gsoc2013-evolution-a34a4b15b8e5ab5f0a145c17ef0969da9666d8d0.zip |
Shite, -1 on error, >=0 on success. So i've just been truncating all the
2000-11-21 Not Zed <NotZed@HelixCode.com>
* providers/local/camel-mh-summary.c (mh_summary_sync_message):
Shite, -1 on error, >=0 on success. So i've just been truncating
all the messages I touched, good one zed.
(mh_summary_sync_message): Sigh, and write to the right damn fd as
well.
(mh_summary_sync_message): Argh, and we need to compare the length
of the old xev -1 to the new xev, to check if we can optimise it.
* camel-folder.c (camel_folder_change_info_new): Init the pool.
(camel_folder_change_info_add_source): Allocate string in the
pool.
(camel_folder_change_info_add_source_list):
(camel_folder_change_info_add_update): No longer free the key, as
it cannot be yet.
(change_info_add_uid): Add a new arg, copy, telling it whether to
copy the uid argument or not, and copy using mempool_strdup.
(change_info_cat): Tell add_uid to copy the string.
(camel_folder_change_info_add_update): Call add_uid directly.
(change_info_remove): Call add_uid directly, with no copy, and
dont free the key.
(change_info_free_update): No longer required since we dont malloc
the keys.
(camel_folder_change_info_add_uid): Fix for add_uid change.
(camel_folder_change_info_remove_uid):
(camel_folder_change_info_change_uid):
(change_info_clear): No longer needed, just set the size to 0 on
the array directly.
(camel_folder_change_info_clear): Empty the arrays directly, and
flush the mempool too, and also clear uid_source, incase anyone
was silly enough to call us in the wrong order.
(camel_folder_change_info_free): Dont bother clearing the array's
contents, just free the pool and throw away all the indexes.
* camel-folder.h: Added a mempool to CamelFolderChangeInfo to
store the uid's we get.
* camel-folder-search.c (search_match_all): If we are only
matching a single info, just use that/do the search.
(camel_folder_search_match_expression): New function. Matches a
single message info against an expression.
(camel_folder_search_init): Init a hash table used to map the
returned gptrarrays' to mempools.
(camel_folder_search_execute_expression): Store all of the string
data in a mempool, slightly faster, less wasted space (usually),.
(camel_folder_search_free_result): Check for the mempool that
stores the data for the list, and free that if we have it,
otherwise assume we need to use g_free() (which should only happen
if the list is empty at the moment).
: commented out the debugging prints. Got sick of 'executing
header search' crap.
* providers/vee/camel-vee-folder.c (camel_vee_folder_init): Init
changes.
(camel_vee_folder_finalise): Free changes.
(vfolder_add_match): Simple helper to add a new matching info
record.
(camel_vee_folder_add_folder): Only trigger a changed event if we
have changes.
(vfolder_change_match): New function, changes our local vfolder
info to match the source.
(vfolder_add_match): Add a new info to the vfolder list.
(vfolder_remove_match): Remove a no-longer matching info from the
vfolder summary.
(message_changed): check if the message still matches, and
remove/etc as required.
(camel_vee_folder_finalise, init): init/free search object.
(vee_folder_build_folder): Build the changes to the folder into
the changes data, as we go.
(folder_changed): If the folder gave us an explicit list of
changes, then process each one separately (unless there's a lot
added/changed).
* providers/vee/camel-vee-folder.h: Added a changes field to the
folder.
svn path=/trunk/; revision=6628
Diffstat (limited to 'camel/camel-folder-search.c')
-rw-r--r-- | camel/camel-folder-search.c | 113 |
1 files changed, 107 insertions, 6 deletions
diff --git a/camel/camel-folder-search.c b/camel/camel-folder-search.c index ff9539c9ec..4d61b5cfa1 100644 --- a/camel/camel-folder-search.c +++ b/camel/camel-folder-search.c @@ -39,11 +39,13 @@ #include "camel-mime-message.h" #include "gmime-content-field.h" #include "camel-stream-mem.h" +#include "e-util/e-memory.h" -#define d(x) x -#define r(x) x +#define d(x) +#define r(x) struct _CamelFolderSearchPrivate { + GHashTable *mempool_hash; }; #define _PRIVATE(o) (((CamelFolderSearch *)(o))->priv) @@ -88,16 +90,39 @@ camel_folder_search_init (CamelFolderSearch *obj) p = _PRIVATE(obj) = g_malloc0(sizeof(*p)); obj->sexp = e_sexp_new(); + + /* use a hash of mempools to associate the returned uid lists with + the backing mempool. yes pretty weird, but i didn't want to change + the api just yet */ + + p->mempool_hash = g_hash_table_new(0, 0); +} + +static void +free_mempool(void *key, void *value, void *data) +{ + GPtrArray *uids = key; + EMemPool *pool = value; + + g_warning("Search closed with outstanding result unfreed: %p", uids); + + g_ptr_array_free(uids, TRUE); + e_mempool_destroy(pool); } static void camel_folder_search_finalize (CamelObject *obj) { CamelFolderSearch *search = (CamelFolderSearch *)obj; + struct _CamelFolderSearchPrivate *p = _PRIVATE(obj); + if (search->sexp) camel_object_unref((CamelObject *)search->sexp); g_free(search->last_search); + g_hash_table_foreach(p->mempool_hash, free_mempool, obj); + g_hash_table_destroy(p->mempool_hash); + g_free(p); } CamelType @@ -266,6 +291,8 @@ camel_folder_search_execute_expression(CamelFolderSearch *search, const char *ex GPtrArray *matches = g_ptr_array_new (); int i; GHashTable *results; + EMemPool *pool; + struct _CamelFolderSearchPrivate *p = _PRIVATE(search); /* only re-parse if the search has changed */ if (search->last_search == NULL @@ -281,6 +308,11 @@ camel_folder_search_execute_expression(CamelFolderSearch *search, const char *ex if (r && r->type == ESEXP_RES_ARRAY_PTR) { d(printf("got result ...\n")); + /* we use a mempool to store the strings, packed in tight as possible, and freed together */ + /* because the strings are often short (like <8 bytes long), we would be wasting appx 50% + of memory just storing the size tag that malloc assigns us and alignment padding, so this + gets around that (and is faster to allocate and free as a bonus) */ + pool = e_mempool_new(512, 256, E_MEMPOOL_ALIGN_BYTE); if (search->summary) { /* reorder result in summary order */ results = g_hash_table_new(g_str_hash, g_str_equal); @@ -291,17 +323,25 @@ camel_folder_search_execute_expression(CamelFolderSearch *search, const char *ex for (i=0;i<search->summary->len;i++) { CamelMessageInfo *info = g_ptr_array_index(search->summary, i); if (g_hash_table_lookup(results, info->uid)) { - g_ptr_array_add(matches, g_strdup(info->uid)); + char *s = e_mempool_alloc(pool, strlen(info->uid) + 1); + strcpy(s, info->uid); + g_ptr_array_add(matches, s); } } g_hash_table_destroy(results); } else { for (i=0;i<r->value.ptrarray->len;i++) { + char *s = e_mempool_alloc(pool, strlen(g_ptr_array_index(r->value.ptrarray, i)) + 1); d(printf("adding match: %s\n", (char *)g_ptr_array_index(r->value.ptrarray, i))); - g_ptr_array_add(matches, g_strdup(g_ptr_array_index(r->value.ptrarray, i))); + strcpy(s, g_ptr_array_index(r->value.ptrarray, i)); + g_ptr_array_add(matches, s); } } e_sexp_result_free(r); + /* instead of putting the mempool_hash in the structure, we keep the api clean by + putting a reference to it in a hashtable. Lets us do some debugging and catch + unfree'd results as well. */ + g_hash_table_insert(p->mempool_hash, matches, pool); } else { printf("no result!\n"); } @@ -314,12 +354,52 @@ camel_folder_search_execute_expression(CamelFolderSearch *search, const char *ex return matches; } +/** + * camel_folder_search_match_expression: + * @search: + * @expr: + * @info: + * @ex: + * + * Returns #TRUE if the expression matches the specific message info @info. + * Note that the folder and index may need to be set for body searches to + * operate as well. + * + * Return value: + **/ +gboolean +camel_folder_search_match_expression(CamelFolderSearch *search, const char *expr, const CamelMessageInfo *info, CamelException *ex) +{ + GPtrArray *uids; + int ret = FALSE; + + search->match1 = (CamelMessageInfo *)info; + + uids = camel_folder_search_execute_expression(search, expr, ex); + if (uids) { + if (uids->len == 1) + ret = TRUE; + camel_folder_search_free_result(search, uids); + } + search->match1 = NULL; + + return ret; +} + void camel_folder_search_free_result(CamelFolderSearch *search, GPtrArray *result) { int i; + struct _CamelFolderSearchPrivate *p = _PRIVATE(search); + EMemPool *pool; - for (i=0;i<result->len;i++) - g_free(g_ptr_array_index(result, i)); + pool = g_hash_table_lookup(p->mempool_hash, result); + if (pool) { + e_mempool_destroy(pool); + g_hash_table_remove(p->mempool_hash, result); + } else { + for (i=0;i<result->len;i++) + g_free(g_ptr_array_index(result, i)); + } g_ptr_array_free(result, TRUE); } @@ -352,6 +432,27 @@ search_match_all(struct _ESExp *f, int argc, struct _ESExpTerm **argv, CamelFold r = e_sexp_result_new(ESEXP_RES_ARRAY_PTR); r->value.ptrarray = g_ptr_array_new(); + /* we are only matching a single message? */ + if (search->match1) { + search->current = search->match1; + + if (argc>0) { + r1 = e_sexp_term_eval(f, argv[0]); + if (r1->type == ESEXP_RES_BOOL) { + if (r1->value.bool) + g_ptr_array_add(r->value.ptrarray, search->current->uid); + } else { + g_warning("invalid syntax, matches require a single bool result"); + } + e_sexp_result_free(r1); + } else { + g_ptr_array_add(r->value.ptrarray, search->current->uid); + } + search->current = NULL; + + return r; + } + if (search->summary == NULL) { /* TODO: make it work - e.g. use the folder and so forth for a slower search */ g_warning("No summary supplied, match-all doesn't work with no summary"); |