167579 r=cavin sr=bienvenu making copyservice handle requests better and deal with failure cases gracefully

This commit is contained in:
naving%netscape.com 2002-09-11 01:50:21 +00:00
Родитель 3f0dcdc41f
Коммит 482654f922
6 изменённых файлов: 93 добавлений и 104 удалений

Просмотреть файл

@ -180,12 +180,36 @@ nsMsgCopyService::ClearRequest(nsCopyRequest* aRequest, nsresult rv)
return rv;
}
nsresult
nsMsgCopyService::QueueRequest(nsCopyRequest* aRequest, PRBool *aCopyImmediately)
{
NS_ENSURE_ARG_POINTER(aRequest);
NS_ENSURE_ARG_POINTER(aCopyImmediately);
*aCopyImmediately = PR_TRUE;
nsCopyRequest* copyRequest;
PRInt32 cnt, i;
cnt = m_copyRequests.Count();
for (i=0; i < cnt; i++)
{
copyRequest = (nsCopyRequest*) m_copyRequests.ElementAt(i);
if (copyRequest->m_dstFolder.get() == aRequest->m_dstFolder.get()) //if dst are same and we already have a request, we cannot copy immediately
{
*aCopyImmediately = PR_FALSE;
break;
}
}
return NS_OK;
}
nsresult
nsMsgCopyService::DoCopy(nsCopyRequest* aRequest)
{
NS_ENSURE_ARG(aRequest);
PRBool copyImmediately;
QueueRequest(aRequest, &copyImmediately);
m_copyRequests.AppendElement((void*) aRequest);
if (m_copyRequests.Count() == 1) //if only one request, then go ahead and do the copy, otherwise the request is queued
if (copyImmediately) // if there wasn't another request for this dest folder then we can copy immediately
return DoNextCopy();
return NS_OK;
@ -468,19 +492,20 @@ nsMsgCopyService::CopyFileMessage(nsIFileSpec* fileSpec,
nsresult rv = NS_ERROR_NULL_POINTER;
nsCopyRequest* copyRequest;
nsCopySource* copySource = nsnull;
nsCOMPtr<nsISupports> aSupport;
nsCOMPtr<nsISupports> fileSupport;
nsCOMPtr<nsITransactionManager> txnMgr;
if (!fileSpec || !dstFolder) return rv;
NS_ENSURE_ARG_POINTER(fileSpec);
NS_ENSURE_ARG_POINTER(dstFolder);
if (window)
window->GetTransactionManager(getter_AddRefs(txnMgr));
copyRequest = new nsCopyRequest();
if (!copyRequest) return rv;
aSupport = do_QueryInterface(fileSpec, &rv);
fileSupport = do_QueryInterface(fileSpec, &rv);
if (NS_FAILED(rv)) goto done;
rv = copyRequest->Init(nsCopyFileMessageType, aSupport, dstFolder,
rv = copyRequest->Init(nsCopyFileMessageType, fileSupport, dstFolder,
isDraft, listener, window, PR_FALSE);
if (NS_FAILED(rv)) goto done;

Просмотреть файл

@ -108,6 +108,7 @@ private:
nsresult DoCopy(nsCopyRequest* aRequest);
nsresult DoNextCopy();
nsCopyRequest* FindRequest(nsISupports* aSupport, nsIMsgFolder* dstFolder);
nsresult QueueRequest(nsCopyRequest* aRequest, PRBool *aCopyImmediately);
nsVoidArray m_copyRequests;
};

Просмотреть файл

@ -113,7 +113,6 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kMsgMailSessionCID, NS_MSGMAILSESSION_CID);
static NS_DEFINE_CID(kParseMailMsgStateCID, NS_PARSEMAILMSGSTATE_CID);
static NS_DEFINE_CID(kCImapHostSessionList, NS_IIMAPHOSTSESSIONLIST_CID);
static NS_DEFINE_CID(kMsgCopyServiceCID, NS_MSGCOPYSERVICE_CID);
static NS_DEFINE_CID(kCopyMessageStreamListenerCID, NS_COPYMESSAGESTREAMLISTENER_CID);
nsIAtom* nsImapMailFolder::mImapHdrDownloadedAtom=nsnull;
@ -4358,7 +4357,7 @@ nsImapMailFolder::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode)
if (txnMgr)
txnMgr->DoTransaction(m_copyState->m_undoMsgTxn);
}
OnCopyCompleted(aExitCode);
(void) OnCopyCompleted(m_copyState->m_srcSupport, aExitCode);
}
// we're the dest folder of a move/copy - if we're not open in the ui,
// then we should clear our nsMsgDatabase pointer. Otherwise, the db would
@ -4443,12 +4442,12 @@ nsImapMailFolder::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode)
if (txnMgr)
txnMgr->DoTransaction(m_copyState->m_undoMsgTxn);
}
OnCopyCompleted(aExitCode);
(void) OnCopyCompleted(m_copyState->m_srcSupport, aExitCode);
}
}
else
//clear the copyState if copy has failed
OnCopyCompleted(aExitCode);
(void) OnCopyCompleted(m_copyState->m_srcSupport, aExitCode);
}
break;
case nsIImapUrl::nsImapRenameFolder:
@ -5704,7 +5703,7 @@ nsImapMailFolder::CopyMessagesWithStream(nsIMsgFolder* srcFolder,
if (NS_SUCCEEDED(rv))
CopyStreamMessage(aMessage, this, msgWindow, isMove);
else
OnCopyCompleted(rv);
return rv; //we are clearing copy state in CopyMessages on failure
}
else
{
@ -6149,16 +6148,8 @@ nsresult nsImapMailFolder::CopyMessagesOffline(nsIMsgFolder* srcFolder,
txnMgr->EndBatch();
}
// since we don't have a copy state object, we can't use the normal mechanism
// of calling OnCopyCompleted to notify the copy service that the copy is complete.
// So, we notify the copy service directly.
nsCOMPtr<nsIMsgCopyService> copyService = do_GetService(NS_MSGCOPYSERVICE_CONTRACTID);
if (copyService)
{
nsCOMPtr<nsISupports> supports = do_QueryInterface(srcFolder);
(void) copyService->NotifyCompletion(supports, this, rv);
}
nsCOMPtr<nsISupports> srcSupport = do_QueryInterface(srcFolder);
OnCopyCompleted(srcSupport, rv);
if (NS_SUCCEEDED(rv) && isMove)
srcFolder->NotifyFolderEvent(mDeleteOrMoveMsgCompletedAtom);
@ -6186,7 +6177,8 @@ nsImapMailFolder::CopyMessages(nsIMsgFolder* srcFolder,
nsCOMPtr<nsIImapService> imapService(do_GetService(kCImapService, &rv));
if (!srcFolder || !messages) return NS_ERROR_NULL_POINTER;
srcSupport = do_QueryInterface(srcFolder);
nsCOMPtr <nsIMsgIncomingServer> srcServer;
nsCOMPtr <nsIMsgIncomingServer> dstServer;
@ -6211,7 +6203,6 @@ nsImapMailFolder::CopyMessages(nsIMsgFolder* srcFolder,
rv = BuildIdsAndKeyArray(messages, messageIds, srcKeyArray);
if(NS_FAILED(rv)) goto done;
srcSupport = do_QueryInterface(srcFolder);
rv = QueryInterface(NS_GET_IID(nsIUrlListener), getter_AddRefs(urlListener));
rv = InitCopyState(srcSupport, messages, isMove, PR_TRUE, listener, msgWindow, allowUndo);
@ -6252,16 +6243,17 @@ nsImapMailFolder::CopyMessages(nsIMsgFolder* srcFolder,
getter_AddRefs(m_copyState->m_undoMsgTxn) );
}
else
{
NS_ASSERTION(PR_FALSE, "online copy failed");
OnCopyCompleted(rv);
}
done:
if (NS_FAILED(rv) && isMove)
if (NS_FAILED(rv))
{
srcFolder->EnableNotifications(allMessageCountNotifications, PR_TRUE, PR_TRUE/* dbBatching*/); //enable message count notification
NotifyFolderEvent(mDeleteOrMoveMsgFailedAtom);
(void) OnCopyCompleted(srcSupport, PR_FALSE);
if (isMove)
{
srcFolder->EnableNotifications(allMessageCountNotifications, PR_TRUE, PR_TRUE/* dbBatching*/); //enable message count notification
NotifyFolderEvent(mDeleteOrMoveMsgFailedAtom);
}
}
return rv;
}
@ -6321,19 +6313,16 @@ nsImapMailFolder::CopyFileMessage(nsIFileSpec* fileSpec,
nsMsgKey key = 0xffffffff;
nsCAutoString messageId;
nsCOMPtr<nsIUrlListener> urlListener;
nsCOMPtr<nsISupports> srcSupport;
nsCOMPtr<nsISupportsArray> messages;
if (!fileSpec) return rv;
srcSupport = do_QueryInterface(fileSpec, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISupports> srcSupport = do_QueryInterface(fileSpec, &rv);
rv = NS_NewISupportsArray(getter_AddRefs(messages));
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv))
return OnCopyCompleted(srcSupport, rv);
nsCOMPtr<nsIImapService> imapService(do_GetService(kCImapService, &rv));
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv))
return OnCopyCompleted(srcSupport, rv);
rv = QueryInterface(NS_GET_IID(nsIUrlListener), getter_AddRefs(urlListener));
@ -6346,7 +6335,8 @@ nsImapMailFolder::CopyFileMessage(nsIFileSpec* fileSpec,
rv = InitCopyState(srcSupport, messages, PR_FALSE, isDraftOrTemplate,
listener, msgWindow, PR_FALSE);
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv))
return OnCopyCompleted(srcSupport, rv);
nsCOMPtr<nsISupports> copySupport;
if( m_copyState )
@ -6358,7 +6348,7 @@ nsImapMailFolder::CopyFileMessage(nsIFileSpec* fileSpec,
copySupport,
msgWindow);
if (NS_FAILED(rv))
OnCopyCompleted(rv);
return OnCopyCompleted(srcSupport, rv);
return rv;
}
@ -6490,19 +6480,16 @@ nsImapMailFolder::InitCopyState(nsISupports* srcSupport,
return rv;
}
void
nsImapMailFolder::OnCopyCompleted(nsresult rv)
nsresult
nsImapMailFolder::OnCopyCompleted(nsISupports *srcSupport, nsresult rv)
{
if (m_copyState)
{
nsCOMPtr<nsISupports> srcSupport = do_QueryInterface(m_copyState->m_srcSupport);
m_copyState = nsnull;
nsresult result;
nsCOMPtr<nsIMsgCopyService> copyService =
do_GetService(kMsgCopyServiceCID, &result);
if (NS_SUCCEEDED(result))
copyService->NotifyCompletion(srcSupport, this, rv);
}
m_copyState = nsnull;
nsresult result;
nsCOMPtr<nsIMsgCopyService> copyService =
do_GetService(NS_MSGCOPYSERVICE_CONTRACTID, &result);
if (NS_SUCCEEDED(result))
copyService->NotifyCompletion(srcSupport, this, rv);
return NS_OK;
}
NS_IMETHODIMP nsImapMailFolder::MatchName(nsString *name, PRBool *matches)

Просмотреть файл

@ -408,7 +408,7 @@ protected:
nsIMsgCopyServiceListener* listener,
nsIMsgWindow *msgWindow,
PRBool allowUndo);
void OnCopyCompleted(nsresult exitCode);
nsresult OnCopyCompleted(nsISupports *srcSupport, nsresult exitCode);
nsresult BuildIdsAndKeyArray(nsISupportsArray* messages,
nsCString& msgIds, nsMsgKeyArray& keyArray);

Просмотреть файл

@ -1630,24 +1630,19 @@ nsMsgLocalMailFolder::InitCopyState(nsISupports* aSupport,
return NS_MSG_FOLDER_BUSY;
rv = GetPath(getter_AddRefs(pathSpec));
if (NS_FAILED(rv)) goto done;
NS_ENSURE_SUCCESS(rv, rv);
rv = pathSpec->GetFileSpec(&path);
if (NS_FAILED(rv)) goto done;
NS_ENSURE_SUCCESS(rv, rv);
mCopyState = new nsLocalMailCopyState();
if(!mCopyState)
{
rv = NS_ERROR_OUT_OF_MEMORY;
goto done;
}
return NS_ERROR_OUT_OF_MEMORY;
mCopyState->m_dataBuffer = (char*) PR_CALLOC(COPY_BUFFER_SIZE+1);
if (!mCopyState->m_dataBuffer)
{
rv = NS_ERROR_OUT_OF_MEMORY;
goto done;
}
return NS_ERROR_OUT_OF_MEMORY;
mCopyState->m_dataBufferSize = COPY_BUFFER_SIZE;
//Before we continue we should verify that there is enough diskspace.
@ -1655,16 +1650,14 @@ nsMsgLocalMailFolder::InitCopyState(nsISupports* aSupport,
mCopyState->m_fileStream = new nsOutputFileStream(path, PR_WRONLY |
PR_CREATE_FILE);
if(!mCopyState->m_fileStream)
{
rv = NS_ERROR_OUT_OF_MEMORY;
goto done;
}
return NS_ERROR_OUT_OF_MEMORY;
//The new key is the end of the file
mCopyState->m_fileStream->seek(PR_SEEK_END, 0);
mCopyState->m_srcSupport = do_QueryInterface(aSupport, &rv);
if (NS_FAILED(rv)) goto done;
NS_ENSURE_SUCCESS(rv, rv);
mCopyState->m_messages = do_QueryInterface(messages, &rv);
if (NS_FAILED(rv)) goto done;
NS_ENSURE_SUCCESS(rv, rv);
mCopyState->m_curCopyIndex = 0;
mCopyState->m_isMove = isMove;
mCopyState->m_isFolder = isFolder;
@ -1674,26 +1667,15 @@ nsMsgLocalMailFolder::InitCopyState(nsISupports* aSupport,
if (listener)
mCopyState->m_listener = do_QueryInterface(listener, &rv);
mCopyState->m_copyingMultipleMessages = PR_FALSE;
done:
if (NS_FAILED(rv))
OnCopyCompleted(PR_FALSE);
return rv;
}
void
nsMsgLocalMailFolder::OnCopyCompleted(PRBool moveCopySucceeded)
nsresult
nsMsgLocalMailFolder::OnCopyCompleted(nsISupports *srcSupport, PRBool moveCopySucceeded)
{
nsCOMPtr<nsISupports> srcSupport;
if (mCopyState)
{
srcSupport = mCopyState->m_srcSupport;
delete mCopyState;
mCopyState = nsnull;
}
delete mCopyState;
mCopyState = nsnull;
// we are the destination folder for a move/copy
if (moveCopySucceeded && mDatabase)
{
@ -1723,6 +1705,7 @@ nsMsgLocalMailFolder::OnCopyCompleted(PRBool moveCopySucceeded)
if (NS_SUCCEEDED(result)) //copyService will do listener->OnStopCopy()
copyService->NotifyCompletion(srcSupport, this, moveCopySucceeded ? NS_OK : NS_ERROR_FAILURE);
return NS_OK;
}
nsresult
@ -1757,9 +1740,7 @@ nsMsgLocalMailFolder::CopyMessages(nsIMsgFolder* srcFolder, nsISupportsArray*
nsIMsgCopyServiceListener* listener,
PRBool isFolder, PRBool allowUndo)
{
if (!srcFolder || !messages)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsISupports> srcSupport = do_QueryInterface(srcFolder);
PRBool isServer;
nsresult rv = GetIsServer(&isServer);
if (NS_SUCCEEDED(rv) && isServer)
@ -1767,7 +1748,7 @@ nsMsgLocalMailFolder::CopyMessages(nsIMsgFolder* srcFolder, nsISupportsArray*
NS_ASSERTION(0, "Destination is the root folder. Cannot move/copy here");
if (isMove)
srcFolder->NotifyFolderEvent(mDeleteOrMoveMsgFailedAtom);
return NS_OK;
return OnCopyCompleted(srcSupport, PR_FALSE);
}
nsXPIDLCString uri;
@ -1794,19 +1775,19 @@ nsMsgLocalMailFolder::CopyMessages(nsIMsgFolder* srcFolder, nsISupportsArray*
if (isMove)
srcFolder->NotifyFolderEvent(mDeleteOrMoveMsgFailedAtom);
ThrowAlertMsg("cantMoveMsgWOBodyOffline", msgWindow);
return NS_OK; // I think we want to return ok here
return OnCopyCompleted(srcSupport, PR_FALSE);
}
}
}
}
nsCOMPtr<nsISupports> srcSupport(do_QueryInterface(srcFolder, &rv));
if (NS_FAILED(rv)) return rv;
// don't update the counts in the dest folder until it is all over
EnableNotifications(allMessageCountNotifications, PR_FALSE, PR_FALSE /*dbBatching*/); //dest folder doesn't need db batching
rv = InitCopyState(srcSupport, messages, isMove, listener, msgWindow, isFolder, allowUndo);
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv))
return OnCopyCompleted(srcSupport, PR_FALSE);
if (!protocolType.EqualsIgnoreCase("mailbox"))
{
mCopyState->m_dummyEnvelopeNeeded = PR_TRUE;
@ -1837,7 +1818,7 @@ nsMsgLocalMailFolder::CopyMessages(nsIMsgFolder* srcFolder, nsISupportsArray*
if (NS_FAILED(rv))
{
OnCopyCompleted(PR_FALSE);
(void) OnCopyCompleted(srcSupport, PR_FALSE);
}
else
{
@ -1872,7 +1853,7 @@ nsMsgLocalMailFolder::CopyMessages(nsIMsgFolder* srcFolder, nsISupportsArray*
if (NS_FAILED(rv))
{
NS_ASSERTION(PR_FALSE, "copy message failed");
OnCopyCompleted(PR_FALSE);
(void) OnCopyCompleted(srcSupport, PR_FALSE);
}
}
}
@ -2125,13 +2106,10 @@ nsMsgLocalMailFolder::CopyFileMessage(nsIFileSpec* fileSpec, nsIMsgDBHdr*
nsIMsgCopyServiceListener* listener)
{
nsresult rv = NS_ERROR_NULL_POINTER;
if (!fileSpec) return rv;
nsCOMPtr<nsIInputStream> inputStream;
nsParseMailMessageState* parseMsgState = nsnull;
PRUint32 fileSize = 0;
nsCOMPtr<nsISupports> fileSupport(do_QueryInterface(fileSpec, &rv));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISupportsArray> messages;
rv = NS_NewISupportsArray(getter_AddRefs(messages));
@ -2184,7 +2162,7 @@ nsMsgLocalMailFolder::CopyFileMessage(nsIFileSpec* fileSpec, nsIMsgDBHdr*
done:
if(NS_FAILED(rv))
{
OnCopyCompleted(PR_FALSE);
(void) OnCopyCompleted(fileSupport, PR_FALSE);
}
fileSpec->CloseStream();
@ -2492,7 +2470,7 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EndCopy(PRBool copySucceeded)
hdrs in place. The message that has failed has been truncated so the msf file and berkeley mailbox
are in sync*/
OnCopyCompleted(PR_TRUE);
(void) OnCopyCompleted(mCopyState->m_srcSupport, PR_TRUE);
// enable the dest folder
EnableNotifications(allMessageCountNotifications, PR_TRUE, PR_FALSE /*dbBatching*/); //dest folder doesn't need db batching
@ -2629,7 +2607,7 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EndCopy(PRBool copySucceeded)
if (srcFolder && !mCopyState->m_isFolder)
srcFolder->NotifyFolderEvent(mDeleteOrMoveMsgCompletedAtom);
OnCopyCompleted(PR_TRUE);
(void) OnCopyCompleted(mCopyState->m_srcSupport, PR_TRUE);
}
// enable the dest folder
EnableNotifications(allMessageCountNotifications, PR_TRUE, PR_FALSE /*dbBatching*/); //dest folder doesn't need db batching
@ -2654,7 +2632,7 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EndMove(PRBool moveSucceeded)
hdrs in place. The message that has failed has been truncated so the msf file and berkeley mailbox
are in sync*/
OnCopyCompleted(PR_TRUE);
(void) OnCopyCompleted(mCopyState->m_srcSupport, PR_TRUE);
// enable the dest folder
EnableNotifications(allMessageCountNotifications, PR_TRUE, PR_FALSE /*dbBatching*/ ); //dest folder doesn't need db batching
@ -2684,9 +2662,7 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EndMove(PRBool moveSucceeded)
if (txnMgr)
txnMgr->DoTransaction(mCopyState->m_undoMsgTxn);
}
nsCOMPtr<nsISupports> srcSupport = do_QueryInterface(mCopyState->m_srcSupport);
OnCopyCompleted(PR_TRUE); //clear the copy state so that the next message from a different folder can be move
(void) OnCopyCompleted(mCopyState->m_srcSupport, PR_TRUE); //clear the copy state so that the next message from a different folder can be move
}
return NS_OK;

Просмотреть файл

@ -207,7 +207,7 @@ protected:
virtual const char* GetIncomingServerType();
nsresult InitCopyState(nsISupports* aSupport, nsISupportsArray* messages,
PRBool isMove, nsIMsgCopyServiceListener* listener, nsIMsgWindow *msgWindow, PRBool isMoveFolder, PRBool allowUndo);
void OnCopyCompleted(PRBool moveCopySucceeded);
nsresult OnCopyCompleted(nsISupports *srcSupport, PRBool moveCopySucceeded);
virtual nsresult CreateBaseMessageURI(const char *aURI);
protected:
PRBool mHaveReadNameFromDB;