John Capo wrote:
Quoting Ken Murchison ([EMAIL PROTECTED]):
John Capo wrote:
Quoting John Capo ([EMAIL PROTECTED]):
Quoting Ken Murchison ([EMAIL PROTECTED]):
I don't think I was clear. With my proposal, we're well past "UPDATE".
I'm talking about cutting the command short after "(<flags>)". No
header_size or anything after.
I guess I don't understand what you mean.
It sure looks to me like cmd_upload() has to detect that the header
size it is waiting for will not arrive and recover gracefully rather
than sending a BAD that the client sees as the response for its
next command. Patch attached.
The server needs to push the character back except on EOF, grrrr.
Here's what I was thinking. We might be able to bump the cache flush
down to parse_err, but I'm not sure if this is correct/suboptimal for
SIMPLE.
Ths might work if you add an eatline() in the client before returning.
The BAD response from the server must be discarded somehow or the
BAD response will be seen by the client as the response to the next
client command. It seems to me that no response is needed since
the client is not expecting one.
Here is an untested patch which SHOULD allow the client to abort the
UPLOAD, with the server successfully accepting the messages transmitted
up to the abort.
Thoughts?
Index: sync_client.c
===================================================================
RCS file: /afs/andrew/system/cvs/src/cyrus/imap/sync_client.c,v
retrieving revision 1.10
diff -u -r1.10 sync_client.c
--- sync_client.c 7 May 2007 16:23:21 -0000 1.10
+++ sync_client.c 17 May 2007 15:55:35 -0000
@@ -1177,6 +1177,7 @@
if (r) {
syslog(LOG_ERR, "IOERROR: opening message file %lu of %s: %m",
record->uid, mailbox->name);
+ sync_msgid_remove(msgid_onserver, &record->uuid);
return(IMAP_IOERROR);
}
@@ -1246,7 +1247,7 @@
/* Message with this UUID exists on client but not server */
if ((r=upload_message_work(mailbox, msgno, &record)))
- return(r);
+ break;
if (msg && (msg->uid == record.uid)) /* Overwritten on server */
msg = msg->next;
@@ -1321,7 +1322,7 @@
mailbox->last_uid, mailbox->last_appenddate);
if ((r=upload_message_work(mailbox, msgno, &record)))
- return(r);
+ break;
}
if (count == 0)
Index: sync_server.c
===================================================================
RCS file: /afs/andrew/system/cvs/src/cyrus/imap/sync_server.c,v
retrieving revision 1.4
diff -u -r1.4 sync_server.c
--- sync_server.c 4 Apr 2007 15:22:42 -0000 1.4
+++ sync_server.c 17 May 2007 15:55:35 -0000
@@ -1889,8 +1889,9 @@
break;
case MSG_PARSED:
if (c != ' ') {
- err = "Invalid flags";
- goto parse_err;
+ /* Missing message - UPLOAD short-circuited by client */
+ sync_upload_list_remove(upload_list, item);
+ goto done;
}
message = sync_message_add(message_list, &item->uuid);
@@ -1943,6 +1944,7 @@
/* if we see a SP, we're trying to upload more than one message */
} while (c == ' ');
+ done:
if (c == EOF) {
err = "Unexpected end of sync_in at end of item";
goto parse_err;
Index: sync_support.c
===================================================================
RCS file: /afs/andrew/system/cvs/src/cyrus/imap/sync_support.c,v
retrieving revision 1.7
diff -u -r1.7 sync_support.c
--- sync_support.c 23 Apr 2007 14:15:32 -0000 1.7
+++ sync_support.c 17 May 2007 15:55:35 -0000
@@ -511,6 +511,22 @@
return(result);
}
+void sync_msgid_remove(struct sync_msgid_list *l,
+ struct message_uuid *uuid)
+{
+ int offset = message_uuid_hash(uuid, l->hash_size);
+ struct sync_msgid *msgid;
+
+ if (message_uuid_isnull(uuid)) return;
+
+ for (msgid = l->hash[offset] ; msgid ; msgid = msgid->hash_next) {
+ if (message_uuid_compare(&msgid->uuid, uuid)) {
+ message_uuid_set_null(&msgid->uuid);
+ return;
+ }
+ }
+}
+
void sync_msgid_list_free(struct sync_msgid_list **lp)
{
struct sync_msgid_list *l = *lp;
@@ -1363,6 +1379,27 @@
l->count++;
return(result);
+}
+
+void sync_upload_list_remove(struct sync_upload_list *l,
+ struct sync_upload_item *i)
+{
+ struct sync_upload_item *prev, *current, *next;
+
+ prev = NULL;
+ current = l->head;
+ while (current) {
+ next = current->next;
+ if (current == i) {
+ l->count--;
+ free(current);
+ if (prev) prev->next = next;
+ else l->head = next;
+ return;
+ }
+ prev = current;
+ current = next;
+ }
}
void sync_upload_list_free(struct sync_upload_list **lp)
Index: sync_support.h
===================================================================
RCS file: /afs/andrew/system/cvs/src/cyrus/imap/sync_support.h,v
retrieving revision 1.2
diff -u -r1.2 sync_support.h
--- sync_support.h 30 Nov 2006 17:11:20 -0000 1.2
+++ sync_support.h 17 May 2007 15:55:35 -0000
@@ -144,6 +144,9 @@
struct sync_msgid *sync_msgid_add(struct sync_msgid_list *list,
struct message_uuid *uuid);
+void sync_msgid_remove(struct sync_msgid_list *l,
+ struct message_uuid *uuid);
+
struct sync_msgid *sync_msgid_lookup(struct sync_msgid_list *list,
struct message_uuid *uuid);
@@ -342,6 +345,9 @@
char **flagname);
struct sync_upload_item *sync_upload_list_add(struct sync_upload_list *l);
+
+void sync_upload_list_remove(struct sync_upload_list *l,
+ struct sync_upload_item *i);
void sync_upload_list_free(struct sync_upload_list **lp);
--
Kenneth Murchison
Systems Programmer
Project Cyrus Developer/Maintainer
Carnegie Mellon University