From 53ac08f6a91bc7ed97a54830f4d6f89e78bd29c5 Mon Sep 17 00:00:00 2001 From: "naving%netscape.com" Date: Wed, 1 Aug 2001 05:31:31 +0000 Subject: [PATCH] 91731 r=bienvenu sr=mscott; Obtain the folder lock for compacting folders and for getiing pop3 messages so that the operations do not write each other's data, only one operation should be able to write to the folder at one time. --- mailnews/base/src/nsMsgFolderCompactor.cpp | 26 +++++++++- mailnews/base/src/nsMsgFolderCompactor.h | 1 + .../locale/en-US/localMsgs.properties | 6 +++ mailnews/local/src/nsLocalStringBundle.h | 1 + mailnews/local/src/nsMailboxProtocol.cpp | 2 +- mailnews/local/src/nsPop3Protocol.cpp | 10 ++-- mailnews/local/src/nsPop3Sink.cpp | 52 ++++++++++++++----- mailnews/local/src/nsPop3Sink.h | 1 + 8 files changed, 81 insertions(+), 18 deletions(-) diff --git a/mailnews/base/src/nsMsgFolderCompactor.cpp b/mailnews/base/src/nsMsgFolderCompactor.cpp index 6cb990d56fe9..7644ba97e8be 100644 --- a/mailnews/base/src/nsMsgFolderCompactor.cpp +++ b/mailnews/base/src/nsMsgFolderCompactor.cpp @@ -291,6 +291,12 @@ void nsFolderCompactState::ShowCompactingStatusMsg() NS_IMETHODIMP nsFolderCompactState::StartCompacting() { nsresult rv = NS_OK; + PRBool isLocked; + m_folder->GetLocked(&isLocked); + if(!isLocked) + m_folder->AcquireSemaphore(m_folder); + else + FinishCompact(); if (m_size > 0) { ShowCompactingStatusMsg(); @@ -354,6 +360,9 @@ nsFolderCompactState::FinishCompact() // database m_fileSpec.Rename((const char*) idlName); newSummarySpec.Rename(dbName); + + rv = ReleaseFolderLock(); + NS_ASSERTION(NS_SUCCEEDED(rv),"folder lock not released successfully"); // Make the front end reload the folder. Calling GetMsgDatabase on a folder whose // db isn't open will cause the folder to open the db and @@ -363,10 +372,22 @@ nsFolderCompactState::FinishCompact() db = nsnull; if (m_compactAll) rv = CompactNextFolder(); - + return rv; } +nsresult +nsFolderCompactState::ReleaseFolderLock() +{ + nsresult result = NS_OK; + if (!m_folder) return result; + PRBool haveSemaphore; + result = m_folder->TestSemaphore(m_folder, &haveSemaphore); + if(NS_SUCCEEDED(result) && haveSemaphore) + result = m_folder->ReleaseSemaphore(m_folder); + return result; +} + nsresult nsFolderCompactState::CompactNextFolder() { @@ -386,6 +407,7 @@ nsFolderCompactState::CompactNextFolder() } else return rv; + } nsCOMPtr supports = getter_AddRefs(m_folderArray->ElementAt(m_folderIndex)); nsCOMPtr folder = do_QueryInterface(supports, &rv); @@ -436,6 +458,7 @@ nsFolderCompactState::OnStopRequest(nsIRequest *request, nsISupports *ctxt, if (NS_SUCCEEDED(status)) { CleanupTempFilesAfterError(); + ReleaseFolderLock(); Release(); } } @@ -444,6 +467,7 @@ done: if (NS_FAILED(rv)) { m_status = rv; // set the status to rv so the destructor can remove the // temp folder and database + ReleaseFolderLock(); Release(); // kill self return rv; } diff --git a/mailnews/base/src/nsMsgFolderCompactor.h b/mailnews/base/src/nsMsgFolderCompactor.h index 840a01f08bfc..2a3beb841aa4 100644 --- a/mailnews/base/src/nsMsgFolderCompactor.h +++ b/mailnews/base/src/nsMsgFolderCompactor.h @@ -55,6 +55,7 @@ public: nsresult BuildMessageURI(const char *baseURI, PRUint32 key, nsCString& uri); nsresult GetStatusFromMsgName(const char *statusMsgName, PRUnichar ** retval); nsresult ShowStatusMsg(const PRUnichar *aMsg); + nsresult ReleaseFolderLock(); void ShowCompactingStatusMsg(); nsresult CompactNextFolder(); diff --git a/mailnews/local/resources/locale/en-US/localMsgs.properties b/mailnews/local/resources/locale/en-US/localMsgs.properties index 0207ca7d040d..98faa698d128 100644 --- a/mailnews/local/resources/locale/en-US/localMsgs.properties +++ b/mailnews/local/resources/locale/en-US/localMsgs.properties @@ -69,6 +69,11 @@ ## @loc None 4006=Unable to write the email to the mailbox. Make sure the file system allows you write privileges, and you have enough disk space to copy the mailbox. +# Status - write error occurred +## @name POP3_MESSAGE_FOLDER_BUSY +## @loc None +4029=This folder is being processed. Please wait until processing is complete to get messages. + # Status - connecting to host ## @name POP3_CONNECT_HOST_CONTACTED_SENDING_LOGIN_INFORMATION ## @loc None @@ -187,3 +192,4 @@ ## @name MOVING_MSGS_STATUS ## @loc None 4028=Moving %S of %S messages to %S + diff --git a/mailnews/local/src/nsLocalStringBundle.h b/mailnews/local/src/nsLocalStringBundle.h index 5ce105f003d2..be0314ccef58 100644 --- a/mailnews/local/src/nsLocalStringBundle.h +++ b/mailnews/local/src/nsLocalStringBundle.h @@ -71,5 +71,6 @@ private: #define DELETING_MSGS_STATUS 4026 #define COPYING_MSGS_STATUS 4027 #define MOVING_MSGS_STATUS 4028 +#define POP3_MESSAGE_FOLDER_BUSY 4029 #endif /* _nsImapStringBundle_H__ */ diff --git a/mailnews/local/src/nsMailboxProtocol.cpp b/mailnews/local/src/nsMailboxProtocol.cpp index 35fda1fcbd53..58100487ad7a 100644 --- a/mailnews/local/src/nsMailboxProtocol.cpp +++ b/mailnews/local/src/nsMailboxProtocol.cpp @@ -539,7 +539,7 @@ PRInt32 nsMailboxProtocol::ReadMessageResponse(nsIInputStream * inputStream, PRU if (m_channelListener) { // just forward the data we read in to the listener... - m_channelListener->OnDataAvailable(this, m_channelContext, inputStream, sourceOffset, length); + rv = m_channelListener->OnDataAvailable(this, m_channelContext, inputStream, sourceOffset, length); } else { diff --git a/mailnews/local/src/nsPop3Protocol.cpp b/mailnews/local/src/nsPop3Protocol.cpp index c6a557c9a244..6b0fcfaa8751 100644 --- a/mailnews/local/src/nsPop3Protocol.cpp +++ b/mailnews/local/src/nsPop3Protocol.cpp @@ -1168,10 +1168,14 @@ nsPop3Protocol::GetStat() // write to somewhere we dont have write access error to (See bug 62480) // (Note: This is only a temp hack until the underlying XPCOM is fixed // to return errors) - if(NS_FAILED(m_nsIPop3Sink->BeginMailDelivery(m_pop3ConData->only_uidl != nsnull, - &m_pop3ConData->msg_del_started))) + nsresult rv; + rv = m_nsIPop3Sink->BeginMailDelivery(m_pop3ConData->only_uidl != nsnull, + &m_pop3ConData->msg_del_started); + if (NS_FAILED(rv)) + if (rv == NS_MSG_FOLDER_BUSY) + return(Error(POP3_MESSAGE_FOLDER_BUSY)); + else return(Error(POP3_MESSAGE_WRITE_ERROR)); - if(!m_pop3ConData->msg_del_started) { return(Error(POP3_MESSAGE_WRITE_ERROR)); diff --git a/mailnews/local/src/nsPop3Sink.cpp b/mailnews/local/src/nsPop3Sink.cpp index f0fa794014c0..abbcbe630ab9 100644 --- a/mailnews/local/src/nsPop3Sink.cpp +++ b/mailnews/local/src/nsPop3Sink.cpp @@ -141,6 +141,15 @@ nsPop3Sink::BeginMailDelivery(PRBool uidlDownload, PRBool* aBool) nsFileSpec fileSpec; // ### if we're doing a UIDL, then the fileSpec needs to be for the current folder + + PRBool isLocked; + + m_folder->GetLocked(&isLocked); + if(!isLocked) + m_folder->AcquireSemaphore(m_folder); + else + return NS_MSG_FOLDER_BUSY; + if (uidlDownload) { nsCOMPtr path; @@ -202,20 +211,23 @@ nsPop3Sink::BeginMailDelivery(PRBool uidlDownload, PRBool* aBool) nsresult nsPop3Sink::EndMailDelivery() { - if (m_newMailParser) - { - if (m_outFileStream) - m_outFileStream->flush(); // try this. - m_newMailParser->OnStopRequest(nsnull, nsnull, NS_OK); - delete m_newMailParser; - m_newMailParser = NULL; - } + if (m_newMailParser) + { if (m_outFileStream) - { - m_outFileStream->close(); - delete m_outFileStream; - m_outFileStream = 0; - } + m_outFileStream->flush(); // try this. + m_newMailParser->OnStopRequest(nsnull, nsnull, NS_OK); + delete m_newMailParser; + m_newMailParser = NULL; + } + if (m_outFileStream) + { + m_outFileStream->close(); + delete m_outFileStream; + m_outFileStream = 0; + } + + nsresult rv = ReleaseFolderLock(); + NS_ASSERTION(NS_SUCCEEDED(rv),"folder lock not released successfully"); #ifdef DEBUG printf("End mail message delivery.\n"); @@ -223,6 +235,18 @@ nsPop3Sink::EndMailDelivery() return NS_OK; } +nsresult +nsPop3Sink::ReleaseFolderLock() +{ + nsresult result = NS_OK; + if (!m_folder) return result; + PRBool haveSemaphore; + result = m_folder->TestSemaphore(m_folder, &haveSemaphore); + if(NS_SUCCEEDED(result) && haveSemaphore) + result = m_folder->ReleaseSemaphore(m_folder); + return result; +} + nsresult nsPop3Sink::AbortMailDelivery() { @@ -233,6 +257,8 @@ nsPop3Sink::AbortMailDelivery() delete m_outFileStream; m_outFileStream = 0; } + nsresult rv = ReleaseFolderLock(); + NS_ASSERTION(NS_SUCCEEDED(rv),"folder lock not released successfully"); #ifdef DEBUG printf("Abort mail message delivery.\n"); #endif diff --git a/mailnews/local/src/nsPop3Sink.h b/mailnews/local/src/nsPop3Sink.h index a96adade4759..355436d401f7 100644 --- a/mailnews/local/src/nsPop3Sink.h +++ b/mailnews/local/src/nsPop3Sink.h @@ -52,6 +52,7 @@ public: protected: nsresult WriteLineToMailbox(char *buffer); + nsresult ReleaseFolderLock(); PRBool m_authed; PRInt32 m_msgOffset;