aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-folder-search.c
diff options
context:
space:
mode:
authorNot Zed <NotZed@HelixCode.com>2000-11-21 21:38:53 +0800
committerMichael Zucci <zucchi@src.gnome.org>2000-11-21 21:38:53 +0800
commita34a4b15b8e5ab5f0a145c17ef0969da9666d8d0 (patch)
tree9115b83535becfc19b984178b8cf40d0fca64e70 /camel/camel-folder-search.c
parentc657e20b4c142f72de93fd133e0afeabca872a66 (diff)
downloadgsoc2013-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.c113
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");