changeset 21702:23398ba09ac2

dsync: Fix syncing attributes with large values. This mainly meant that large Sieve scripts weren't synced properly, because their last_change field was never deserialized, so it was set to 0.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Sun, 26 Feb 2017 15:21:13 +0200
parents 2e9671812460
children f17b7e5e532a
files src/doveadm/dsync/dsync-ibc-stream.c
diffstat 1 files changed, 14 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/doveadm/dsync/dsync-ibc-stream.c	Sun Feb 26 14:32:44 2017 +0200
+++ b/src/doveadm/dsync/dsync-ibc-stream.c	Sun Feb 26 15:21:13 2017 +0200
@@ -1557,16 +1557,6 @@
 	value = dsync_deserializer_decode_get(decoder, "key");
 	attr->key = p_strdup(pool, value);
 
-	if (dsync_deserializer_decode_try(decoder, "stream", &value)) {
-		attr->value_stream = dsync_ibc_stream_input_stream(ibc);
-		if (dsync_ibc_stream_read_mail_stream(ibc) <= 0) {
-			ibc->cur_attr = attr;
-			return DSYNC_IBC_RECV_RET_TRYAGAIN;
-		}
-		/* already finished reading the stream */
-		i_assert(ibc->value_input == NULL);
-	} else if (dsync_deserializer_decode_try(decoder, "value", &value))
-		attr->value = p_strdup(pool, value);
 	if (dsync_deserializer_decode_try(decoder, "deleted", &value))
 		attr->deleted = TRUE;
 	if (dsync_deserializer_decode_try(decoder, "last_change", &value) &&
@@ -1580,6 +1570,20 @@
 		return DSYNC_IBC_RECV_RET_TRYAGAIN;
 	}
 
+	/* NOTE: stream reading must be the last here, because reading a large
+	   stream will be finished later by return TRYAGAIN. We need to
+	   deserialize all the other fields before that or they'll get lost. */
+	if (dsync_deserializer_decode_try(decoder, "stream", &value)) {
+		attr->value_stream = dsync_ibc_stream_input_stream(ibc);
+		if (dsync_ibc_stream_read_mail_stream(ibc) <= 0) {
+			ibc->cur_attr = attr;
+			return DSYNC_IBC_RECV_RET_TRYAGAIN;
+		}
+		/* already finished reading the stream */
+		i_assert(ibc->value_input == NULL);
+	} else if (dsync_deserializer_decode_try(decoder, "value", &value))
+		attr->value = p_strdup(pool, value);
+
 	*attr_r = attr;
 	return DSYNC_IBC_RECV_RET_OK;
 }