зеркало из https://github.com/mozilla/gecko-dev.git
fix threading performance with header cache, r=mscott,a=phil 28233
This commit is contained in:
Родитель
38aeed8620
Коммит
f990b71747
|
@ -36,6 +36,7 @@
|
|||
#include "nsICollation.h"
|
||||
#include "nsIMimeConverter.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashtable.h"
|
||||
|
||||
class ListContext;
|
||||
class nsMsgKeyArray;
|
||||
|
@ -346,6 +347,16 @@ protected:
|
|||
mdb_token m_threadParentColumnToken;
|
||||
mdb_token m_threadRootKeyColumnToken;
|
||||
nsIMsgHeaderParser *m_HeaderParser;
|
||||
|
||||
// header caching stuff
|
||||
nsresult GetHdrFromCache(nsMsgKey key, nsIMsgDBHdr* *result);
|
||||
nsresult AddHdrToCache(nsIMsgDBHdr *hdr, nsMsgKey key);
|
||||
nsresult ClearHdrCache();
|
||||
nsresult RemoveHdrFromCache(nsIMsgDBHdr *hdr, nsMsgKey key);
|
||||
|
||||
nsSupportsHashtable *m_cachedHeaders;
|
||||
PRBool m_bCacheHeaders;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -57,6 +57,7 @@ protected:
|
|||
nsresult GetUInt32Column(mdb_token token, PRUint32 *pvalue, PRUint32 defaultValue = 0);
|
||||
|
||||
// reference and threading stuff.
|
||||
nsresult ParseReferences(nsCString &references);
|
||||
const char* GetNextReference(const char *startNextRef, nsCString &reference);
|
||||
const char* GetPrevReference(const char *prevRef, nsCString &reference);
|
||||
|
||||
|
@ -70,7 +71,7 @@ protected:
|
|||
PRUint16 m_numReferences; // x-ref header for threading
|
||||
PRInt16 m_csID; // cs id of message
|
||||
nsCString m_charSet; // OK, charset of headers, since cs id's aren't supported.
|
||||
nsCString m_references;
|
||||
nsCStringArray m_references; // avoid parsing references every time we want one
|
||||
nsMsgPriority m_priority;
|
||||
|
||||
PRBool m_recipientsIsNewsgroup;
|
||||
|
|
|
@ -70,18 +70,96 @@ static NS_DEFINE_CID(kMsgHeaderParserCID, NS_MSGHEADERPARSER_CID);
|
|||
|
||||
|
||||
const int kMsgDBVersion = 1;
|
||||
const PRInt32 kMaxHdrsInCache = 200;
|
||||
|
||||
nsresult nsMsgDatabase::GetHdrFromCache(nsMsgKey key, nsIMsgDBHdr* *result)
|
||||
{
|
||||
if (!result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
*result = nsnull;
|
||||
|
||||
if (m_bCacheHeaders && m_cachedHeaders)
|
||||
{
|
||||
// it would be nice if we had an nsISupports hash table that hashed 32 bit int's
|
||||
nsCAutoString strKey;
|
||||
strKey.Append(key, 10);
|
||||
nsStringKey hashKey(strKey.GetBuffer());
|
||||
// nsSupportsHashtable does an addref
|
||||
*result = (nsIMsgDBHdr *) m_cachedHeaders->Get(&hashKey);
|
||||
if (*result)
|
||||
rv = NS_OK;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgDatabase::AddHdrToCache(nsIMsgDBHdr *hdr, nsMsgKey key) // do we want key? We could get it from hdr
|
||||
{
|
||||
if (m_bCacheHeaders)
|
||||
{
|
||||
if (!m_cachedHeaders)
|
||||
m_cachedHeaders = new nsSupportsHashtable;
|
||||
if (m_cachedHeaders)
|
||||
{
|
||||
nsCOMPtr<nsISupports> supports(do_QueryInterface(hdr));
|
||||
if (m_cachedHeaders->Count() > kMaxHdrsInCache)
|
||||
ClearHdrCache();
|
||||
// it would be nice if we had an nsISupports hash table that hashed 32 bit int's
|
||||
nsCAutoString strKey;
|
||||
strKey.Append(key, 10);
|
||||
nsStringKey hashKey(strKey.GetBuffer());
|
||||
m_cachedHeaders->Put(&hashKey, hdr);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsMsgDatabase::ClearHdrCache()
|
||||
{
|
||||
if (m_cachedHeaders)
|
||||
{
|
||||
m_cachedHeaders->Reset();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgDatabase::RemoveHdrFromCache(nsIMsgDBHdr *hdr, nsMsgKey key)
|
||||
{
|
||||
if (m_cachedHeaders)
|
||||
{
|
||||
if (key == nsMsgKey_None)
|
||||
hdr->GetMessageKey(&key);
|
||||
|
||||
nsCAutoString strKey;
|
||||
strKey.Append(key, 10);
|
||||
nsStringKey hashKey(strKey.GetBuffer());
|
||||
nsIMsgDBHdr *removedHdr = (nsIMsgDBHdr *) m_cachedHeaders->Remove(&hashKey); // does this release, or do I have to?
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMsgDatabase::CreateMsgHdr(nsIMdbRow* hdrRow, nsMsgKey key, nsIMsgDBHdr* *result)
|
||||
{
|
||||
nsresult rv = GetHdrFromCache(key, result);
|
||||
if (NS_SUCCEEDED(rv) && *result)
|
||||
{
|
||||
hdrRow->Release();
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsMsgHdr *msgHdr = new nsMsgHdr(this, hdrRow);
|
||||
if(!msgHdr)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
msgHdr->SetMessageKey(key);
|
||||
msgHdr->AddRef();
|
||||
*result = msgHdr;
|
||||
|
||||
|
||||
AddHdrToCache(msgHdr, key);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -349,14 +427,20 @@ nsMsgDatabase::nsMsgDatabase()
|
|||
m_messageCharSetColumnToken(0),
|
||||
m_threadParentColumnToken(0),
|
||||
m_threadRootKeyColumnToken(0),
|
||||
m_bCacheHeaders(PR_FALSE),
|
||||
m_cachedHeaders(nsnull),
|
||||
m_HeaderParser(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
m_bCacheHeaders = PR_TRUE;
|
||||
}
|
||||
|
||||
nsMsgDatabase::~nsMsgDatabase()
|
||||
{
|
||||
// Close(FALSE); // better have already been closed.
|
||||
ClearHdrCache();
|
||||
delete m_cachedHeaders;
|
||||
|
||||
RemoveFromCache(this);
|
||||
#ifdef DEBUG_bienvenu1
|
||||
if (GetNumInCache() != 0)
|
||||
|
@ -946,6 +1030,10 @@ NS_IMETHODIMP nsMsgDatabase::GetMsgHdrForKey(nsMsgKey key, nsIMsgDBHdr **pmsgHdr
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*pmsgHdr = NULL;
|
||||
err = GetHdrFromCache(key, pmsgHdr);
|
||||
if (NS_SUCCEEDED(err) && *pmsgHdr)
|
||||
return err;
|
||||
|
||||
rowObjectId.mOid_Id = key;
|
||||
rowObjectId.mOid_Scope = m_hdrRowScopeToken;
|
||||
err = m_mdbAllMsgHeadersTable->HasOid(GetEnv(), &rowObjectId, &hasOid);
|
||||
|
@ -1098,6 +1186,7 @@ nsresult nsMsgDatabase::RemoveHeaderFromDB(nsMsgHdr *msgHdr)
|
|||
// even if we couldn't find the thread,we should try to remove the header.
|
||||
// if (NS_SUCCEEDED(ret))
|
||||
{
|
||||
RemoveHdrFromCache(msgHdr, nsMsgKey_None);
|
||||
nsIMdbRow* row = msgHdr->GetMDBRow();
|
||||
ret = m_mdbAllMsgHeadersTable->CutRow(GetEnv(), msgHdr->GetMDBRow());
|
||||
row->CutAllColumns(GetEnv());
|
||||
|
|
|
@ -300,31 +300,36 @@ NS_IMETHODIMP nsMsgHdr::GetNumReferences(PRUint16 *result)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgHdr::ParseReferences(nsCString &references)
|
||||
{
|
||||
const char *startNextRef = references.GetBuffer();
|
||||
nsCAutoString resultReference;
|
||||
|
||||
while (startNextRef && *startNextRef)
|
||||
{
|
||||
startNextRef = GetNextReference(startNextRef, resultReference);
|
||||
m_references.AppendCString(resultReference);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgHdr::GetStringReference(PRInt32 refNum, nsCString &resultReference)
|
||||
{
|
||||
nsresult err = NS_OK;
|
||||
|
||||
if(!(m_initedValues & REFERENCES_INITED))
|
||||
{
|
||||
m_mdb->RowCellColumnTonsCString(GetMDBRow(), m_mdb->m_referencesColumnToken, m_references);
|
||||
|
||||
nsCAutoString references;
|
||||
err = m_mdb->RowCellColumnTonsCString(GetMDBRow(), m_mdb->m_referencesColumnToken, references);
|
||||
|
||||
if(NS_SUCCEEDED(err))
|
||||
{
|
||||
ParseReferences(references);
|
||||
m_initedValues |= REFERENCES_INITED;
|
||||
}
|
||||
}
|
||||
|
||||
nsCAutoString cStr(m_references);
|
||||
const char *startNextRef = cStr.GetBuffer();
|
||||
PRInt32 refIndex;
|
||||
for (refIndex = 0; refIndex <= refNum && startNextRef; refIndex++)
|
||||
{
|
||||
startNextRef = GetNextReference(startNextRef, resultReference);
|
||||
if (refIndex == refNum)
|
||||
break;
|
||||
}
|
||||
|
||||
if (refIndex != refNum)
|
||||
resultReference.Truncate(0);
|
||||
|
||||
m_references.CStringAt(refNum, resultReference);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -354,20 +359,12 @@ NS_IMETHODIMP nsMsgHdr::SetAuthor(const char *author)
|
|||
|
||||
NS_IMETHODIMP nsMsgHdr::SetReferences(const char *references)
|
||||
{
|
||||
nsCAutoString reference;
|
||||
nsCAutoString CStrReference(references);
|
||||
ParseReferences(CStrReference);
|
||||
|
||||
for (const char *startNextRef = references; startNextRef != nsnull;)
|
||||
{
|
||||
startNextRef = GetNextReference(startNextRef, reference);
|
||||
|
||||
if (reference.Length() == 0)
|
||||
break;
|
||||
|
||||
m_numReferences++;
|
||||
}
|
||||
m_numReferences = m_references.Count();
|
||||
SetUInt32Column(m_numReferences, m_mdb->m_numReferencesColumnToken);
|
||||
|
||||
m_references = references;
|
||||
m_initedValues |= REFERENCES_INITED;
|
||||
|
||||
return SetStringColumn(references, m_mdb->m_referencesColumnToken);
|
||||
|
|
Загрузка…
Ссылка в новой задаче