Restore requested IMAP UIDs through Store WRITE
Debian Trixie package bundle / packages (push) Successful in 21m38s
Debian Trixie package bundle / packages (push) Successful in 21m38s
This commit is contained in:
@@ -1341,12 +1341,12 @@ StoreCommandLoop(StoreClient *client)
|
||||
|
||||
case STORE_COMMAND_WRITE:
|
||||
/* WRITE <collection> <type> <length>
|
||||
[F<filename>] [G<guid>] [T<timeCreated>]
|
||||
[I<imapuid>] [F<filename>] [G<guid>] [T<timeCreated>]
|
||||
[Z<flags>] [L<link guid>] [N]
|
||||
*/
|
||||
|
||||
if (TOKEN_OK != (ccode = RequireStore(client)) ||
|
||||
TOKEN_OK != (ccode = CheckTokC(client, n, 4, 9)) ||
|
||||
TOKEN_OK != (ccode = CheckTokC(client, n, 4, 10)) ||
|
||||
TOKEN_OK != (ccode = ParseCollection(client, tokens[1], &object)) ||
|
||||
TOKEN_OK != (ccode = ParseDocType(client, tokens[2], &doctype)) ||
|
||||
TOKEN_OK != (ccode = ParseStreamLength(client, tokens[3], &int1)))
|
||||
@@ -1357,6 +1357,7 @@ StoreCommandLoop(StoreClient *client)
|
||||
filename = NULL;
|
||||
timestamp = 0;
|
||||
ulong = 0; /* addflags */
|
||||
ulong2 = 0; /* requested IMAP UID */
|
||||
guid = 0;
|
||||
guid2 = 0; /* link guid */
|
||||
int2 = 0; /* whether or not to process the document */
|
||||
@@ -1370,6 +1371,8 @@ StoreCommandLoop(StoreClient *client)
|
||||
filename = tokens[i] + 1;
|
||||
} else if ('N' == *tokens[i] && tokens[i][1] == '\0') {
|
||||
int2 = 1;
|
||||
} else if ('I' == *tokens[i] && !ulong2) {
|
||||
ccode = ParseUnsignedLong(client, tokens[i] + 1, &ulong2);
|
||||
} else if ('T' == *tokens[i] && !timestamp) {
|
||||
ccode = ParseDateTimeToUint64(client, 1 + tokens[i], ×tamp);
|
||||
} else if ('Z' == *tokens[i] && !ulong) {
|
||||
@@ -1386,7 +1389,8 @@ StoreCommandLoop(StoreClient *client)
|
||||
}
|
||||
|
||||
ccode = StoreCommandWRITE(client, &object, doctype, int1,
|
||||
(uint32_t) ulong, guid, filename,
|
||||
(uint32_t) ulong, (uint32_t) ulong2,
|
||||
guid, filename,
|
||||
timestamp, guid2, int2);
|
||||
break;
|
||||
|
||||
@@ -3254,6 +3258,7 @@ StoreCommandWRITE(StoreClient *client,
|
||||
int doctype,
|
||||
uint64_t size,
|
||||
uint32_t addflags,
|
||||
uint32_t requested_imapuid,
|
||||
uint64_t guid,
|
||||
const char *filename,
|
||||
uint64_t timestamp,
|
||||
@@ -3354,7 +3359,7 @@ StoreCommandWRITE(StoreClient *client,
|
||||
ccode = ConnWriteStr(client->conn, MSG4224CANTWRITE);
|
||||
goto finish;
|
||||
}
|
||||
if (StoreObjectUpdateImapUID(client, &newdocument)) {
|
||||
if (StoreObjectSetImapUID(client, &newdocument, requested_imapuid)) {
|
||||
LogicalLockRelease(client, collection, LLOCK_READWRITE, "StoreCommandWRITE");
|
||||
ccode = ConnWriteStr(client->conn, MSG5005DBLIBERR);
|
||||
goto finish;
|
||||
|
||||
@@ -272,6 +272,7 @@ CCode StoreCommandWRITE(StoreClient *client,
|
||||
int doctype,
|
||||
uint64_t size,
|
||||
uint32_t addflags,
|
||||
uint32_t requested_imapuid,
|
||||
uint64_t guid,
|
||||
const char *filename,
|
||||
uint64_t timestamp,
|
||||
|
||||
@@ -1105,12 +1105,20 @@ abort:
|
||||
// correct value :(
|
||||
int
|
||||
StoreObjectUpdateImapUID(StoreClient *client, StoreObject *object)
|
||||
{
|
||||
return StoreObjectSetImapUID(client, object, 0);
|
||||
}
|
||||
|
||||
int
|
||||
StoreObjectSetImapUID(StoreClient *client, StoreObject *object,
|
||||
uint32_t requested_imapuid)
|
||||
{
|
||||
MsgSQLStatement stmt;
|
||||
MsgSQLStatement *ret;
|
||||
StoreObject collection;
|
||||
char *query;
|
||||
int new_imapuid;
|
||||
int collection_imapuid;
|
||||
int status;
|
||||
|
||||
if (StoreObjectFind(client, object->collection_guid, &collection)) {
|
||||
@@ -1121,16 +1129,22 @@ StoreObjectUpdateImapUID(StoreClient *client, StoreObject *object)
|
||||
memset(&stmt, 0, sizeof(MsgSQLStatement));
|
||||
|
||||
MsgSQLBeginTransaction(client->storedb);
|
||||
// update the imap uid in a transaction to assure atomicity
|
||||
new_imapuid = ++collection.imap_uid;
|
||||
query = "UPDATE storeobject SET imap_uid = ?1 WHERE guid IN (?2, ?3);";
|
||||
// Update the object and collection counter in one transaction. Restore
|
||||
// operations may request an existing UID, including values with gaps.
|
||||
new_imapuid = requested_imapuid ?
|
||||
(int)requested_imapuid : (int)collection.imap_uid + 1;
|
||||
collection_imapuid = MAX((int)collection.imap_uid, new_imapuid);
|
||||
query = "UPDATE storeobject SET imap_uid = "
|
||||
"CASE WHEN guid = ?1 THEN ?2 ELSE ?3 END "
|
||||
"WHERE guid IN (?1, ?4);";
|
||||
|
||||
ret = MsgSQLPrepare(client->storedb, query, &stmt);
|
||||
if (ret == NULL) goto abort;
|
||||
|
||||
MsgSQLBindInt(&stmt, 1, new_imapuid);
|
||||
MsgSQLBindInt64(&stmt, 2, object->guid);
|
||||
MsgSQLBindInt64(&stmt, 3, collection.guid);
|
||||
MsgSQLBindInt64(&stmt, 1, object->guid);
|
||||
MsgSQLBindInt(&stmt, 2, new_imapuid);
|
||||
MsgSQLBindInt(&stmt, 3, collection_imapuid);
|
||||
MsgSQLBindInt64(&stmt, 4, collection.guid);
|
||||
|
||||
status = MsgSQLExecute(client->storedb, &stmt);
|
||||
if (status != 0) {
|
||||
|
||||
@@ -107,6 +107,8 @@ void StoreOutputProperty(StoreClient *client, StorePropertyType type, const char
|
||||
// "dangerous" functions which hit the DB directly
|
||||
int StoreObjectCopyInfo(StoreClient *client, StoreObject *old, StoreObject *newobj);
|
||||
int StoreObjectUpdateImapUID(StoreClient *client, StoreObject *object);
|
||||
int StoreObjectSetImapUID(StoreClient *client, StoreObject *object,
|
||||
uint32_t requested_imapuid);
|
||||
int StoreObjectRenameSubobjects(StoreClient *client, StoreObject *container, const char *new_root);
|
||||
int StoreObjectRemoveCollection(StoreClient *client, StoreObject *collection);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user