gint imapx_uidset_done(struct _uidset_state *ss, struct _CamelIMAPXCommand *ic);
gint imapx_uidset_add(struct _uidset_state *ss, struct _CamelIMAPXCommand *ic, const gchar *uid);
static gboolean imapx_disconnect (CamelIMAPXServer *is);
+static gint imapx_uid_cmp(gconstpointer ap, gconstpointer bp, gpointer data);
typedef struct _CamelIMAPXCommandPart CamelIMAPXCommandPart;
typedef struct _CamelIMAPXCommand CamelIMAPXCommand;
struct _refresh_info {
gchar *uid;
+ gboolean exists;
guint32 server_flags;
CamelFlag *server_user_flags;
};
/* If we need to select a folder for the first command, do it now, once
it is complete it will re-call us if it succeeded */
if (ic->job->folder) {
+ QUEUE_UNLOCK (imap);
imapx_select(imap, ic->job->folder, FALSE, ex);
+ QUEUE_LOCK (imap);
} else {
pri = ic->pri;
nc = ic->next;
summary->saved_count++;
camel_folder_summary_touch(summary);
}
+
+ info->flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED;
}
static void
r.server_flags = finfo->flags;
r.server_user_flags = finfo->user_flags;
finfo->user_flags = NULL;
+ r.exists = FALSE;
g_array_append_val(job->u.refresh_info.infos, r);
} else {
printf("Unsolicited flags response '%s' %08x\n", finfo->uid, finfo->flags);
if (!(finfo->got & FETCH_FLAGS))
{
+ struct _refresh_info *r = NULL;
GArray *infos = job->u.refresh_info.infos;
- gint i = job->u.refresh_info.last_index;
-
- /* This is rather inefficent, but should be ok if we're expecting it
- since we break each fetch into lots of 100. */
- for (i= 0;i<infos->len;i++) {
- struct _refresh_info *r = &g_array_index(infos, struct _refresh_info, i);
-
- if (r->uid && !strcmp(r->uid, finfo->uid)) {
- update_flags_for_new_summary (mi, r->server_flags, r->server_user_flags);
- break;
- }
- }
- } else
+ gint min = job->u.refresh_info.last_index;
+ gint max, mid;
+ gboolean found = FALSE;
+
+ if ((min + BATCH_FETCH_COUNT) < infos->len)
+ max = min + BATCH_FETCH_COUNT;
+ else
+ max = infos->len;
+
+ /* array is sorted, so use a binary search */
+ do {
+ gint cmp = 0;
+
+ mid = (min + max)/2;
+ r = &g_array_index(infos, struct _refresh_info, mid);
+ cmp = imapx_uid_cmp (finfo->uid, r->uid, NULL);
+
+ if (cmp > 0)
+ min = mid + 1;
+ else if (cmp < 0)
+ max = mid - 1;
+ else
+ found = TRUE;
+
+ } while (!found && min <= max);
+
+ if (!found)
+ g_assert_not_reached ();
+
+ update_flags_for_new_summary (mi, r->server_flags, r->server_user_flags);
+ } else {
update_flags_for_new_summary (mi, finfo->flags, finfo->user_flags);
+ /* free user_flags ? */
+ finfo->user_flags = NULL;
+ }
if (!camel_folder_summary_check_uid (job->folder->summary, mi->uid)) {
camel_folder_summary_add(job->folder->summary, mi);
camel_imapx_command_free (ic);
}
+/* Should not have a queue lock. TODO Change the way select is written */
static void
-imapx_select(CamelIMAPXServer *is, CamelFolder *folder, gboolean forced, CamelException *ex)
+imapx_select (CamelIMAPXServer *is, CamelFolder *folder, gboolean forced, CamelException *ex)
{
CamelIMAPXCommand *ic;
is->select_pending = folder;
camel_object_ref(folder);
if (is->select_folder) {
+ QUEUE_LOCK(is);
while (!camel_dlist_empty(&is->active)) {
QUEUE_UNLOCK(is);
sleep (1);
QUEUE_LOCK(is);
}
+ QUEUE_UNLOCK(is);
+
g_free(is->select);
camel_object_unref(is->select_folder);
is->select = NULL;
gint res;
struct _refresh_info *r = &g_array_index(infos, struct _refresh_info, i);
- if (r->uid) {
+ if (!r->exists) {
res = imapx_uidset_add(&job->u.refresh_info.uidset, ic, r->uid);
if (res == 1) {
camel_imapx_command_add(ic, " (RFC822.SIZE RFC822.HEADER)");
if (info->server_flags != r->server_flags
&& camel_message_info_set_flags((CamelMessageInfo *)info, info->server_flags ^ r->server_flags, r->server_flags))
camel_folder_change_info_change_uid (job->u.refresh_info.changes, camel_message_info_uid (s_minfo));
-
- g_free(r->uid);
- r->uid = NULL;
+ r->exists = TRUE;
} else
fetch_new = TRUE;