use append uid returned by imap server when possible, bug 646225, r=neil
authorDavid Bienvenu <bienvenu@nventure.com>
Mon, 23 May 2011 16:33:51 -0700
changeset 7807 5d098294efd2601777dcdb3afa0748049a463f03
parent 7806 9d85ed1b2cc2d702750591391943e7478b0ee233
child 7808 f5cf5a4445409724abba0976dd1cae7ae3ccaa5f
push id4
push userbugzilla@standard8.plus.com
push dateTue, 24 May 2011 20:23:11 +0000
treeherdercomm-aurora@212a62f8c1ff [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersneil
bugs646225
use append uid returned by imap server when possible, bug 646225, r=neil
mailnews/imap/src/nsImapMailFolder.cpp
mailnews/imap/src/nsImapMailFolder.h
--- a/mailnews/imap/src/nsImapMailFolder.cpp
+++ b/mailnews/imap/src/nsImapMailFolder.cpp
@@ -3297,20 +3297,18 @@ NS_IMETHODIMP nsImapMailFolder::BeginCop
 }
 
 NS_IMETHODIMP nsImapMailFolder::CopyDataToOutputStreamForAppend(nsIInputStream *aIStream,
                      PRInt32 aLength, nsIOutputStream *outputStream)
 {
   PRUint32 readCount;
   PRUint32 writeCount;
   if (!m_copyState)
-  {
-    nsImapMailCopyState* copyState = new nsImapMailCopyState();
-    m_copyState = do_QueryInterface(copyState);
-  }
+    m_copyState = new nsImapMailCopyState();
+
   if ( aLength + m_copyState->m_leftOver > m_copyState->m_dataBufferSize )
   {
     m_copyState->m_dataBuffer = (char *) PR_REALLOC(m_copyState->m_dataBuffer, aLength + m_copyState->m_leftOver+ 1);
     NS_ENSURE_TRUE(m_copyState->m_dataBuffer, NS_ERROR_OUT_OF_MEMORY);
     m_copyState->m_dataBufferSize = aLength + m_copyState->m_leftOver;
   }
 
   char *start, *end;
@@ -5737,17 +5735,20 @@ nsImapMailFolder::SetAppendMsgUid(nsMsgK
     if (mailCopyState->m_undoMsgTxn) // CopyMessages()
     {
         nsRefPtr<nsImapMoveCopyMsgTxn> msgTxn;
         msgTxn = mailCopyState->m_undoMsgTxn;
         msgTxn->AddDstKey(aKey);
     }
     else if (mailCopyState->m_listener) // CopyFileMessage();
                                         // Draft/Template goes here
+    {
+      mailCopyState->m_appendUID = aKey;
       mailCopyState->m_listener->SetMessageKey(aKey);
+    }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsImapMailFolder::GetMessageId(nsIImapUrl * aUrl,
                                nsACString &messageId)
 {
@@ -8120,17 +8121,17 @@ nsImapMailFolder::CopyStreamMessage(nsIM
   return rv;
 }
 
 nsImapMailCopyState::nsImapMailCopyState() :
     m_isMove(PR_FALSE), m_selectedState(PR_FALSE),
     m_isCrossServerOp(PR_FALSE), m_curIndex(0),
     m_totalCount(0), m_streamCopy(PR_FALSE), m_dataBuffer(nsnull),
     m_dataBufferSize(0), m_leftOver(0), m_allowUndo(PR_FALSE),
-    m_eatLF(PR_FALSE), m_newMsgFlags(0)
+    m_eatLF(PR_FALSE), m_newMsgFlags(0), m_appendUID(nsMsgKey_None)
 {
 }
 
 nsImapMailCopyState::~nsImapMailCopyState()
 {
   PR_Free(m_dataBuffer);
   if (m_msgService && m_message)
   {
@@ -8159,18 +8160,17 @@ nsImapMailFolder::InitCopyState(nsISuppo
                                 nsIMsgCopyServiceListener* listener,
                                 nsIMsgWindow *msgWindow,
                                 PRBool allowUndo)
 {
   NS_ENSURE_ARG_POINTER(srcSupport);
   NS_ENSURE_TRUE(!m_copyState, NS_ERROR_FAILURE);
   nsresult rv;
 
-  nsImapMailCopyState* copyState = new nsImapMailCopyState();
-  m_copyState = do_QueryInterface(copyState);
+  m_copyState = new nsImapMailCopyState();
   NS_ENSURE_TRUE(m_copyState,NS_ERROR_OUT_OF_MEMORY);
 
   m_copyState->m_isCrossServerOp = acrossServers;
   m_copyState->m_srcSupport = do_QueryInterface(srcSupport, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   m_copyState->m_messages = messages;
   if (messages)
@@ -8220,29 +8220,29 @@ nsImapMailFolder::InitCopyState(nsISuppo
   m_copyState->m_selectedState = selectedState;
   m_copyState->m_msgWindow = msgWindow;
   if (listener)
     m_copyState->m_listener = do_QueryInterface(listener, &rv);
   return rv;
 }
 
 nsresult
-nsImapMailFolder::CopyFileToOfflineStore(nsILocalFile *srcFile)
+nsImapMailFolder::CopyFileToOfflineStore(nsILocalFile *srcFile, nsMsgKey msgKey)
 {
   nsCOMPtr<nsIMsgDatabase> db;
   nsresult rv = GetMsgDatabase(getter_AddRefs(db));
 
   if (mDatabase)
   {
-    nsMsgKey fakeKey;
-    mDatabase->GetNextFakeOfflineMsgKey(&fakeKey);
+    if (msgKey == nsMsgKey_None)
+      mDatabase->GetNextFakeOfflineMsgKey(&msgKey);
     nsCOMPtr<nsIMutableArray> messages(do_CreateInstance(NS_ARRAY_CONTRACTID));
 
     nsCOMPtr<nsIMsgOfflineImapOperation> op;
-    rv = mDatabase->GetOfflineOpForKey(fakeKey, PR_TRUE, getter_AddRefs(op));
+    rv = mDatabase->GetOfflineOpForKey(msgKey, PR_TRUE, getter_AddRefs(op));
     if (NS_SUCCEEDED(rv) && op)
     {
       nsCString destFolderUri;
       GetURI(destFolderUri);
       op->SetOperation(nsIMsgOfflineImapOperation::kMoveResult);
       op->SetDestinationFolderURI(destFolderUri.get());
       nsCOMPtr<nsIOutputStream> offlineStore;
       rv = GetOfflineStoreOutputStream(getter_AddRefs(offlineStore));
@@ -8273,17 +8273,17 @@ nsImapMailFolder::CopyFileToOfflineStore
           nsMsgLineStreamBuffer *inputStreamBuffer =
             new nsMsgLineStreamBuffer(inputBufferSize, PR_TRUE, PR_FALSE);
           PRInt64 fileSize;
           srcFile->GetFileSize(&fileSize);
           PRUint32 bytesWritten;
           rv = NS_OK;
           msgParser->SetState(nsIMsgParseMailMsgState::ParseHeadersState);
           // set the env pos to fake key so the msg hdr will have that for a key
-          msgParser->SetEnvelopePos(fakeKey);
+          msgParser->SetEnvelopePos(msgKey);
           PRBool needMoreData = PR_FALSE;
           char * newLine = nsnull;
           PRUint32 numBytesInLine = 0;
           const char *envelope = "From "CRLF;
           offlineStore->Write(envelope, strlen(envelope), &bytesWritten);
           fileSize += bytesWritten;
           do
           {
@@ -8333,17 +8333,17 @@ nsresult
 nsImapMailFolder::OnCopyCompleted(nsISupports *srcSupport, nsresult rv)
 {
   // if it's a file, and the copy succeeded, then fcc the offline
   // store, and add a kMoveResult offline op.
   if (NS_SUCCEEDED(rv) && m_copyState)
   {
     nsCOMPtr<nsILocalFile> srcFile(do_QueryInterface(srcSupport));
     if (srcFile && (mFlags & nsMsgFolderFlags::Offline) && !WeAreOffline())
-      (void) CopyFileToOfflineStore(srcFile);
+      (void) CopyFileToOfflineStore(srcFile, m_copyState->m_appendUID);
   }
   m_copyState = nsnull;
   nsresult result;
   nsCOMPtr<nsIMsgCopyService> copyService = do_GetService(NS_MSGCOPYSERVICE_CONTRACTID, &result);
   NS_ENSURE_SUCCESS(result, result);
   return copyService->NotifyCompletion(srcSupport, this, rv);
 }
 
--- a/mailnews/imap/src/nsImapMailFolder.h
+++ b/mailnews/imap/src/nsImapMailFolder.h
@@ -109,16 +109,19 @@ public:
     char *m_dataBuffer; // temporary buffer for this copy operation
     nsCOMPtr<nsIOutputStream> m_msgFileStream;         // temporary file (processed mail)
     PRUint32 m_dataBufferSize;
     PRUint32 m_leftOver;
     PRBool m_allowUndo;
     PRBool m_eatLF;
     PRBool m_newMsgFlags; // only used if there's no m_message
     nsCString m_newMsgKeywords; // ditto 
+    // If the server supports UIDPLUS, this is the UID for the append,
+    // if we're doing an append.
+    nsMsgKey m_appendUID;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsImapMailCopyState, NS_IMAPMAILCOPYSTATE_IID)
 
 // ACLs for this folder.
 // Generally, we will try to always query this class when performing
 // an operation on the folder.
 // If the server doesn't support ACLs, none of this data will be filled in.
@@ -372,17 +375,17 @@ protected:
                              PRUint16 userFlags, nsCString& keywords);
   nsresult NotifyMessageFlagsFromHdr(nsIMsgDBHdr *dbHdr, nsMsgKey msgKey, PRUint32 flags);
 
   nsresult SetupHeaderParseStream(PRUint32 size, const nsACString& content_type, nsIMailboxSpec *boxSpec);
   nsresult  ParseAdoptedHeaderLine(const char *messageLine, PRUint32 msgKey);
   nsresult  NormalEndHeaderParseStream(nsIImapProtocol *aProtocol, nsIImapUrl *imapUrl);
 
   void EndOfflineDownload();
-  nsresult CopyFileToOfflineStore(nsILocalFile *srcFile);
+  nsresult CopyFileToOfflineStore(nsILocalFile *srcFile, nsMsgKey msgKey);
 
   nsresult MarkMessagesImapDeleted(nsTArray<nsMsgKey> *keyArray, PRBool deleted, nsIMsgDatabase *db);
 
   // Notifies imap autosync that it should update this folder when it
   // gets a chance.
   void NotifyHasPendingMsgs();
   void UpdatePendingCounts();
   void SetIMAPDeletedFlag(nsIMsgDatabase *mailDB, const nsTArray<nsMsgKey> &msgids, PRBool markDeleted);
@@ -482,17 +485,17 @@ protected:
 
   PRInt32  m_nextMessageByteLength;
   nsCOMPtr<nsIThread> m_thread;
   nsCOMPtr<nsIUrlListener> m_urlListener;
   PRBool m_urlRunning;
 
   // undo move/copy transaction support
   nsRefPtr<nsMsgTxn> m_pendingUndoTxn;
-  nsCOMPtr<nsImapMailCopyState> m_copyState;
+  nsRefPtr<nsImapMailCopyState> m_copyState;
   char m_hierarchyDelimiter;
   PRInt32 m_boxFlags;
   nsCString m_onlineFolderName;
   nsCString m_ownerUserName;  // username of the "other user," as in
   // "Other Users' Mailboxes"
 
   nsCString m_adminUrl;   // url to run to set admin privileges for this folder
   nsIMAPNamespace  *m_namespace;