fix threading performance with header cache, r=mscott,a=phil 28233

This commit is contained in:
bienvenu%netscape.com 2000-03-01 04:15:12 +00:00
Родитель 38aeed8620
Коммит f990b71747
4 изменённых файлов: 126 добавлений и 28 удалений

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

@ -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);