Landing imap integration with the memory cache!! *Yeah*

Bug #23491 --> add memory cache support for imap urls.
Bug #23325 --> fix a crasher...only try to find a folder if we have a folder name
r=bienvenu
This commit is contained in:
mscott%netscape.com 2000-01-13 04:54:23 +00:00
Родитель 69cc1d4e10
Коммит df476382d9
3 изменённых файлов: 200 добавлений и 119 удалений

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

@ -49,6 +49,12 @@
#include "nsIPipe.h" #include "nsIPipe.h"
#include "nsIMsgFolder.h" #include "nsIMsgFolder.h"
#include "nsImapStringBundle.h" #include "nsImapStringBundle.h"
// for the memory cache...
#include "nsINetDataCacheManager.h"
#include "nsINetDataCache.h"
#include "nsICachedNetData.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
PRLogModuleInfo *IMAP; PRLogModuleInfo *IMAP;
@ -1128,8 +1134,6 @@ PRBool nsImapProtocol::ProcessCurrentURL()
if (m_runningUrl && m_imapServerSink) if (m_runningUrl && m_imapServerSink)
m_imapServerSink->RemoveChannelFromUrl(mailnewsurl, NS_OK); m_imapServerSink->RemoveChannelFromUrl(mailnewsurl, NS_OK);
m_runningUrl->RemoveChannel(NS_OK);
// release this by hand so that we can load the next queued url without thinking // release this by hand so that we can load the next queued url without thinking
// this connection is busy running a url. // this connection is busy running a url.
m_runningUrl = null_nsCOMPtr(); m_runningUrl = null_nsCOMPtr();
@ -2062,6 +2066,7 @@ void nsImapProtocol::BeginMessageDownLoad(
m_imapMailFolderSink->SetupHeaderParseStream(this, total_message_size, content_type, nsnull); m_imapMailFolderSink->SetupHeaderParseStream(this, total_message_size, content_type, nsnull);
} }
} }
// if we have a mock channel, that means we have a channel listener who wants the // if we have a mock channel, that means we have a channel listener who wants the
// message. So set up a pipe. We'll write the messsage into one end of the pipe // message. So set up a pipe. We'll write the messsage into one end of the pipe
// and they will read it out of the other end. // and they will read it out of the other end.
@ -6257,10 +6262,15 @@ nsImapMockChannel::nsImapMockChannel()
NS_INIT_REFCNT(); NS_INIT_REFCNT();
m_channelContext = nsnull; m_channelContext = nsnull;
m_cancelled = PR_FALSE; m_cancelled = PR_FALSE;
mOwningRefToUrl = PR_FALSE;
} }
nsImapMockChannel::~nsImapMockChannel() nsImapMockChannel::~nsImapMockChannel()
{ {
// only release the url if we have a owning ref on it...
// this only occurrs when we are loading the url from the cache...
if (mOwningRefToUrl && m_url)
NS_RELEASE(m_url);
} }
@ -6341,12 +6351,60 @@ NS_IMETHODIMP nsImapMockChannel::AsyncOpen(nsIStreamObserver *observer, nsISuppo
NS_IMETHODIMP nsImapMockChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount, nsISupports *ctxt, nsIStreamListener *listener) NS_IMETHODIMP nsImapMockChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount, nsISupports *ctxt, nsIStreamListener *listener)
{ {
nsCOMPtr<nsICachedNetData> cacheEntry;
PRUint32 contentLength = 0;
PRBool partialFlag = PR_FALSE;
// set the stream listener and then load the url // set the stream listener and then load the url
m_channelContext = ctxt; m_channelContext = ctxt;
m_channelListener = listener; m_channelListener = listener;
// the following load group code is completely bogus....
nsresult rv = NS_OK; nsresult rv = NS_OK;
nsCOMPtr<nsIImapUrl> imapUrl = do_QueryInterface(m_url);
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_url, &rv);
if (NS_FAILED(rv)) return rv;
// look to see if this url should be added to the memory cache..
PRBool useMemoryCache = PR_FALSE;
mailnewsUrl->GetAddToMemoryCache(&useMemoryCache);
nsCOMPtr<nsINetDataCacheManager> cacheManager = do_GetService(NS_NETWORK_CACHE_MANAGER_PROGID, &rv);
if (NS_SUCCEEDED(rv) && cacheManager)
{
// Retrieve an existing cache entry or create a new one if none exists for the
// given URL.
nsXPIDLCString urlCString;
// eventually we are going to want to use the url spec - the query/ref part 'cause that doesn't
// distinguish urls.......
m_url->GetSpec(getter_Copies(urlCString));
// for now, truncate of the query part so we don't duplicate urls in the cache...
char * anchor = PL_strrchr(urlCString, '?');
if (anchor)
*anchor = '\0';
rv = cacheManager->GetCachedNetData(urlCString, 0, 0, nsINetDataCacheManager::BYPASS_PERSISTENT_CACHE,
getter_AddRefs(cacheEntry));
if (NS_SUCCEEDED(rv) && cacheEntry)
{
PRBool updateInProgress;
cacheEntry->GetPartialFlag(&partialFlag);
cacheEntry->GetUpdateInProgress(&updateInProgress);
cacheEntry->GetStoredContentLength(&contentLength);
// only try to update the cache entry if it isn't being used.
// and we want to write to the memory cache.
if (!updateInProgress && useMemoryCache)
{
// now we need to figure out if the entry is new / or partially unfinished...
// this determines if we are going to USE the cache entry for reading the data
// vs. if we need to write data into the cache entry...
if (!contentLength || partialFlag)
// we're going to fill up this cache entry,
rv = cacheEntry->InterceptAsyncRead(listener, 0, getter_AddRefs(m_channelListener));
}
}
}
// regardless as to whether we are inserting into the cache or not, proceed with
// setting up the load group!
if (m_loadGroup) if (m_loadGroup)
{ {
nsCOMPtr<nsILoadGroupListenerFactory> factory; nsCOMPtr<nsILoadGroupListenerFactory> factory;
@ -6363,10 +6421,28 @@ NS_IMETHODIMP nsImapMockChannel::AsyncRead(PRUint32 startPosition, PRInt32 readC
} }
} // if aLoadGroup } // if aLoadGroup
// now, determine if we should be loading from the cache or if we have
// to really load the msg with a protocol connection...
if (cacheEntry && contentLength > 0 && !partialFlag)
{
nsCOMPtr<nsIChannel> cacheChannel;
rv = cacheEntry->NewChannel(m_loadGroup, this, getter_AddRefs(cacheChannel));
if (NS_SUCCEEDED(rv))
{
// turn around and make our ref on m_url an owning ref...and force the url to remove
// its reference on the mock channel...this is a complicated texas two step to solve
// a nasty reference counting problem...
NS_IF_ADDREF(m_url);
mOwningRefToUrl = PR_TRUE;
imapUrl->SetMockChannel(nsnull);
rv = cacheChannel->AsyncRead(startPosition, readCount, m_channelContext, m_channelListener);
if (NS_SUCCEEDED(rv)) // ONLY if we succeeded in actually starting the read should we return
return rv;
}
}
// loading the url consists of asking the server to add the url to it's imap event queue.... // loading the url consists of asking the server to add the url to it's imap event queue....
nsCOMPtr<nsIImapUrl> imapUrl = do_QueryInterface(m_url);
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_url, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIMsgIncomingServer> server; nsCOMPtr<nsIMsgIncomingServer> server;
rv = mailnewsUrl->GetServer(getter_AddRefs(server)); rv = mailnewsUrl->GetServer(getter_AddRefs(server));
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;

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

@ -558,15 +558,19 @@ public:
nsImapMockChannel(); nsImapMockChannel();
virtual ~nsImapMockChannel(); virtual ~nsImapMockChannel();
static nsresult Create (const nsIID& iid, void **result); static nsresult Create (const nsIID& iid, void **result);
protected: protected:
// we CANNOT own the uri else we will have a circular ref count // we CANNOT own the uri else we will have a circular ref count
// because the imap uri ref counts us....so don't think about // because the imap uri ref counts us....so don't think about
// turning this into a com ptr! // turning this into a com ptr! HOWEVER, because life is complicated,
nsCOMPtr<nsIURI> m_originalUrl; // there is one scenario where we need to own the url....and that
// is when we are loading the url from the cache....so in that case,
// we'll turn around and make our m_url ptr an owning reference... *sigh*
nsIURI * m_url; nsIURI * m_url;
PRBool mOwningRefToUrl;
nsCOMPtr<nsIURI> m_originalUrl;
nsCOMPtr<nsILoadGroup> m_loadGroup; nsCOMPtr<nsILoadGroup> m_loadGroup;
nsCOMPtr<nsIStreamListener> m_channelListener; nsCOMPtr<nsIStreamListener> m_channelListener;
// non owning ref of the context in order to fix a circular ref count // non owning ref of the context in order to fix a circular ref count

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

@ -266,6 +266,8 @@ NS_IMETHODIMP nsImapService::DisplayMessage(const char* aMessageURI,
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(imapUrl)); nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(imapUrl));
msgurl->SetMsgWindow(aMsgWindow); msgurl->SetMsgWindow(aMsgWindow);
// whenever we are displaying a message, we want to add it to the memory cache..
msgurl->SetAddToMemoryCache(PR_TRUE);
imapUrl->AddChannelToLoadGroup(); imapUrl->AddChannelToLoadGroup();
rv = FetchMessage(imapUrl, nsIImapUrl::nsImapMsgFetch, folder, imapMessageSink, rv = FetchMessage(imapUrl, nsIImapUrl::nsImapMsgFetch, folder, imapMessageSink,
aURL, aDisplayConsumer, msgKey, PR_TRUE); aURL, aDisplayConsumer, msgKey, PR_TRUE);
@ -2329,7 +2331,7 @@ NS_IMETHODIMP nsImapService::NewURI(const char *aSpec, nsIURI *aBaseURI, nsIURI
nsCOMPtr<nsIFolder> aRootFolder; nsCOMPtr<nsIFolder> aRootFolder;
aServer->GetRootFolder(getter_AddRefs(aRootFolder)); aServer->GetRootFolder(getter_AddRefs(aRootFolder));
if (aRootFolder) if (aRootFolder && folderName && (* ((const char *) folderName)) )
{ {
nsCOMPtr<nsIFolder> aFolder; nsCOMPtr<nsIFolder> aFolder;
rv = aRootFolder->FindSubFolder(folderName, getter_AddRefs(aFolder)); rv = aRootFolder->FindSubFolder(folderName, getter_AddRefs(aFolder));
@ -2341,7 +2343,6 @@ NS_IMETHODIMP nsImapService::NewURI(const char *aSpec, nsIURI *aBaseURI, nsIURI
nsCOMPtr<nsIMsgFolder> msgFolder = do_QueryInterface(aFolder); nsCOMPtr<nsIMsgFolder> msgFolder = do_QueryInterface(aFolder);
rv = SetImapUrlSink(msgFolder, aImapUrl); rv = SetImapUrlSink(msgFolder, aImapUrl);
} }
} }
// we got an imap url, so be sure to return it... // we got an imap url, so be sure to return it...