Bug 876548 Move the nsMsgDatabase cache to the nsMsgDBService r=irving
This commit is contained in:
Родитель
697e8e91dd
Коммит
8ce627f54e
|
@ -234,7 +234,7 @@ NS_IMETHODIMP nsMsgDBFolder::ForceDBClosed()
|
|||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIMsgDatabase> mailDBFactory = do_CreateInstance(kCMailDB);
|
||||
nsCOMPtr<nsIMsgDBService> mailDBFactory(do_GetService(NS_MSGDB_SERVICE_CONTRACTID));
|
||||
if (mailDBFactory)
|
||||
mailDBFactory->ForceFolderDBClosed(this);
|
||||
}
|
||||
|
|
|
@ -1287,7 +1287,6 @@ static void
|
|||
msgMailNewsModuleDtor()
|
||||
{
|
||||
nsAddrDatabase::CleanupCache();
|
||||
nsMsgDatabase::CleanupCache();
|
||||
}
|
||||
|
||||
static const mozilla::Module kMailNewsModule = {
|
||||
|
|
|
@ -103,7 +103,7 @@ interface nsMsgDBCommitType
|
|||
* The contract ID for this component is
|
||||
* <tt>\@mozilla.org/msgDatabase/msgDBService;1</tt>.
|
||||
*/
|
||||
[scriptable, uuid(e4743a99-ca44-4647-87b4-d73a444226b3)]
|
||||
[scriptable, uuid(4cbbf024-3760-402d-89f3-6ababafeb07d)]
|
||||
interface nsIMsgDBService : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -234,13 +234,19 @@ interface nsIMsgDBService : nsISupports
|
|||
*/
|
||||
nsIMsgDatabase cachedDBForFolder(in nsIMsgFolder aFolder);
|
||||
|
||||
/**
|
||||
* Close the db for a folder, if already open.
|
||||
*
|
||||
* @param aFolder The folder to close the cached (open) db for.
|
||||
*/
|
||||
void forceFolderDBClosed(in nsIMsgFolder aFolder);
|
||||
|
||||
/// an enumerator to iterate over the open dbs.
|
||||
readonly attribute nsIArray openDBs;
|
||||
};
|
||||
|
||||
[scriptable, uuid(09839bbb-d55c-4d38-a006-8f9eb4894774)]
|
||||
[scriptable, uuid(2dbc9e31-5f8c-408c-960e-a91cecde368c)]
|
||||
interface nsIMsgDatabase : nsIDBChangeAnnouncer {
|
||||
void forceFolderDBClosed(in nsIMsgFolder aFolder);
|
||||
void Close(in boolean aForceCommit);
|
||||
|
||||
void Commit(in nsMsgDBCommit commitType);
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
NS_IMETHOD StartBatch() MOZ_OVERRIDE;
|
||||
NS_IMETHOD EndBatch() MOZ_OVERRIDE;
|
||||
|
||||
nsresult Open(nsIFile *aSummaryFile, bool create, bool upgrading) MOZ_OVERRIDE;
|
||||
nsresult Open(nsMsgDBService* aDBService, nsIFile *aSummaryFile, bool create, bool upgrading) MOZ_OVERRIDE;
|
||||
virtual nsMailDatabase *GetMailDB() {return this;}
|
||||
|
||||
virtual uint32_t GetCurVersion() MOZ_OVERRIDE {return kMsgDBVersion;}
|
||||
|
|
|
@ -29,11 +29,17 @@
|
|||
class ListContext;
|
||||
class nsMsgKeySet;
|
||||
class nsMsgThread;
|
||||
class nsMsgDatabase;
|
||||
class nsIMsgThread;
|
||||
class nsIDBFolderInfo;
|
||||
|
||||
const int32_t kMsgDBVersion = 1;
|
||||
|
||||
// Hopefully we're not opening up lots of databases at the same time, however
|
||||
// this will give us a buffer before we need to start reallocating the cache
|
||||
// array.
|
||||
const uint32_t kInitialMsgDBCacheSize = 20;
|
||||
|
||||
class nsMsgDBService : public nsIMsgDBService
|
||||
{
|
||||
public:
|
||||
|
@ -42,12 +48,27 @@ public:
|
|||
|
||||
nsMsgDBService();
|
||||
~nsMsgDBService();
|
||||
|
||||
void AddToCache(nsMsgDatabase* pMessageDB);
|
||||
void DumpCache();
|
||||
void EnsureCached(nsMsgDatabase* pMessageDB)
|
||||
{
|
||||
if (!m_dbCache.Contains(pMessageDB))
|
||||
m_dbCache.AppendElement(pMessageDB);
|
||||
}
|
||||
void RemoveFromCache(nsMsgDatabase* pMessageDB)
|
||||
{
|
||||
m_dbCache.RemoveElement(pMessageDB);
|
||||
}
|
||||
|
||||
protected:
|
||||
void HookupPendingListeners(nsIMsgDatabase *db, nsIMsgFolder *folder);
|
||||
void FinishDBOpen(nsIMsgFolder *aFolder, nsMsgDatabase *aMsgDB);
|
||||
nsMsgDatabase* FindInCache(nsIFile *dbName);
|
||||
|
||||
nsCOMArray <nsIMsgFolder> m_foldersPendingListeners;
|
||||
nsCOMArray <nsIDBChangeListener> m_pendingListeners;
|
||||
nsAutoTArray<nsMsgDatabase*, kInitialMsgDBCacheSize> m_dbCache;
|
||||
};
|
||||
|
||||
class nsMsgDBEnumerator : public nsISimpleEnumerator {
|
||||
|
@ -131,14 +152,14 @@ public:
|
|||
* The database is present (and was opened), but the
|
||||
* summary file is missing.
|
||||
*/
|
||||
virtual nsresult Open(nsIFile *aFolderName, bool aCreate,
|
||||
bool aLeaveInvalidDB);
|
||||
virtual nsresult Open(nsMsgDBService *aDBService, nsIFile *aFolderName,
|
||||
bool aCreate, bool aLeaveInvalidDB);
|
||||
virtual nsresult IsHeaderRead(nsIMsgDBHdr *hdr, bool *pRead);
|
||||
virtual nsresult MarkHdrReadInDB(nsIMsgDBHdr *msgHdr, bool bRead,
|
||||
nsIDBChangeListener *instigator);
|
||||
nsresult OpenInternal(nsIFile *aFolderName, bool aCreate,
|
||||
bool aLeaveInvalidDB, bool sync);
|
||||
nsresult CheckForErrors(nsresult err, bool sync, nsIFile *summaryFile);
|
||||
nsresult OpenInternal(nsMsgDBService *aDBService, nsIFile *aFolderName,
|
||||
bool aCreate, bool aLeaveInvalidDB, bool sync);
|
||||
nsresult CheckForErrors(nsresult err, bool sync, nsMsgDBService *aDBService, nsIFile *summaryFile);
|
||||
virtual nsresult OpenMDB(const char *dbName, bool create, bool sync);
|
||||
virtual nsresult CloseMDB(bool commit);
|
||||
virtual nsresult CreateMsgHdr(nsIMdbRow* hdrRow, nsMsgKey key, nsIMsgDBHdr **result);
|
||||
|
@ -163,9 +184,6 @@ public:
|
|||
nsresult GetTableCreateIfMissing(const char *scope, const char *kind, nsIMdbTable **table,
|
||||
mdb_token &scopeToken, mdb_token &kindToken);
|
||||
|
||||
static nsMsgDatabase* FindInCache(nsIFile *dbName);
|
||||
static nsIMsgDatabase* FindInCache(nsIMsgFolder *folder);
|
||||
|
||||
//helper function to fill in nsStrings from hdr row cell contents.
|
||||
nsresult RowCellColumnTonsString(nsIMdbRow *row, mdb_token columnToken, nsAString &resultStr);
|
||||
nsresult RowCellColumnToUInt32(nsIMdbRow *row, mdb_token columnToken, uint32_t *uint32Result, uint32_t defaultValue = 0);
|
||||
|
@ -207,8 +225,6 @@ public:
|
|||
static void YarnToUInt32(struct mdbYarn *yarn, uint32_t *i);
|
||||
static void YarnToUInt64(struct mdbYarn *yarn, uint64_t *i);
|
||||
|
||||
static void CleanupCache();
|
||||
static void DumpCache();
|
||||
#ifdef DEBUG
|
||||
virtual nsresult DumpContents();
|
||||
nsresult DumpThread(nsMsgKey threadId);
|
||||
|
@ -240,27 +256,11 @@ protected:
|
|||
virtual nsresult AddNewThread(nsMsgHdr *msgHdr);
|
||||
virtual nsresult AddToThread(nsMsgHdr *newHdr, nsIMsgThread *thread, nsIMsgDBHdr *pMsgHdr, bool threadInThread);
|
||||
|
||||
static nsTArray<nsMsgDatabase*>* m_dbCache;
|
||||
static nsTArray<nsMsgDatabase*>* GetDBCache();
|
||||
|
||||
static PRTime gLastUseTime; // global last use time
|
||||
PRTime m_lastUseTime; // last use time for this db
|
||||
// inline to make instrumentation as cheap as possible
|
||||
inline void RememberLastUseTime() {gLastUseTime = m_lastUseTime = PR_Now();}
|
||||
|
||||
static void AddToCache(nsMsgDatabase* pMessageDB)
|
||||
{
|
||||
#ifdef DEBUG_David_Bienvenu
|
||||
// NS_ASSERTION(GetDBCache()->Length() < 50, "50 or more open db's");
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsIMsgDatabase> msgDB = pMessageDB->m_folder ?
|
||||
dont_AddRef(FindInCache(pMessageDB->m_folder)) : nullptr;
|
||||
NS_ASSERTION(!msgDB, "shouldn't have db in cache");
|
||||
#endif
|
||||
GetDBCache()->AppendElement(pMessageDB);
|
||||
}
|
||||
static void RemoveFromCache(nsMsgDatabase* pMessageDB);
|
||||
bool MatchDbName(nsIFile *dbName); // returns TRUE if they match
|
||||
|
||||
// Flag handling routines
|
||||
|
|
|
@ -37,8 +37,8 @@ nsMailDatabase::~nsMailDatabase()
|
|||
// caller passes in upgrading==true if they want back a db even if the db is out of date.
|
||||
// If so, they'll extract out the interesting info from the db, close it, delete it, and
|
||||
// then try to open the db again, prior to reparsing.
|
||||
nsresult nsMailDatabase::Open(nsIFile *aSummaryFile, bool aCreate,
|
||||
bool aUpgrading)
|
||||
nsresult nsMailDatabase::Open(nsMsgDBService* aDBService, nsIFile *aSummaryFile,
|
||||
bool aCreate, bool aUpgrading)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsString leafName;
|
||||
|
@ -47,7 +47,7 @@ nsresult nsMailDatabase::Open(nsIFile *aSummaryFile, bool aCreate,
|
|||
nsCaseInsensitiveStringComparator()))
|
||||
NS_ERROR("non summary file passed into open\n");
|
||||
#endif
|
||||
return nsMsgDatabase::Open(aSummaryFile, aCreate, aUpgrading);
|
||||
return nsMsgDatabase::Open(aDBService, aSummaryFile, aCreate, aUpgrading);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMailDatabase::ForceClosed()
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "nsArrayEnumerator.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "mozilla/mailnews/MimeHeaderParser.h"
|
||||
#include "mozilla/mailnews/Services.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace mozilla::mailnews;
|
||||
|
@ -60,11 +61,6 @@ using namespace mozilla::mailnews;
|
|||
// This will be used on discovery, since we don't know total.
|
||||
const int32_t kMaxHdrsInCache = 512;
|
||||
|
||||
// Hopefully we're not opening up lots of databases at the same time, however
|
||||
// this will give us a buffer before we need to start reallocating the cache
|
||||
// array.
|
||||
const uint32_t kInitialMsgDBCacheSize = 20;
|
||||
|
||||
// special keys
|
||||
static const nsMsgKey kAllMsgHdrsTableKey = 1;
|
||||
static const nsMsgKey kTableKeyForThreadOne = 0xfffffffe;
|
||||
|
@ -86,6 +82,17 @@ nsMsgDBService::nsMsgDBService()
|
|||
|
||||
nsMsgDBService::~nsMsgDBService()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// If you hit this warning, it means that some code is holding onto
|
||||
// a db at shutdown.
|
||||
NS_WARN_IF_FALSE(!m_dbCache.Length(), "some msg dbs left open");
|
||||
for (uint32_t i = 0; i < m_dbCache.Length(); i++)
|
||||
{
|
||||
nsMsgDatabase* pMessageDB = m_dbCache.ElementAt(i);
|
||||
if (pMessageDB)
|
||||
printf("db left open %s\n", (const char *) pMessageDB->m_dbName.get());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBService::OpenFolderDB(nsIMsgFolder *aFolder,
|
||||
|
@ -104,7 +111,7 @@ NS_IMETHODIMP nsMsgDBService::OpenFolderDB(nsIMsgFolder *aFolder,
|
|||
rv = msgStore->GetSummaryFile(aFolder, getter_AddRefs(summaryFilePath));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsMsgDatabase *cacheDB = nsMsgDatabase::FindInCache(summaryFilePath);
|
||||
nsMsgDatabase *cacheDB = FindInCache(summaryFilePath);
|
||||
if (cacheDB)
|
||||
{
|
||||
// this db could have ended up in the folder cache w/o an m_folder pointer via
|
||||
|
@ -116,7 +123,7 @@ NS_IMETHODIMP nsMsgDBService::OpenFolderDB(nsIMsgFolder *aFolder,
|
|||
// if m_thumb is set, someone is asynchronously opening the db. But our
|
||||
// caller wants to synchronously open it, so just do it.
|
||||
if (cacheDB->m_thumb)
|
||||
return cacheDB->Open(summaryFilePath, false, aLeaveInvalidDB);
|
||||
return cacheDB->Open(this, summaryFilePath, false, aLeaveInvalidDB);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -130,7 +137,7 @@ NS_IMETHODIMP nsMsgDBService::OpenFolderDB(nsIMsgFolder *aFolder,
|
|||
// Don't try to create the database yet--let the createNewDB call do that.
|
||||
nsMsgDatabase *msgDatabase = static_cast<nsMsgDatabase *>(msgDB.get());
|
||||
msgDatabase->m_folder = aFolder;
|
||||
rv = msgDatabase->Open(summaryFilePath, false, aLeaveInvalidDB);
|
||||
rv = msgDatabase->Open(this, summaryFilePath, false, aLeaveInvalidDB);
|
||||
if (NS_FAILED(rv) && rv != NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
|
||||
return rv;
|
||||
|
||||
|
@ -162,7 +169,16 @@ NS_IMETHODIMP nsMsgDBService::AsyncOpenFolderDB(nsIMsgFolder *aFolder,
|
|||
nsIMsgDatabase **_retval)
|
||||
{
|
||||
NS_ENSURE_ARG(aFolder);
|
||||
nsMsgDatabase *cacheDB = (nsMsgDatabase *) nsMsgDatabase::FindInCache(aFolder);
|
||||
|
||||
nsCOMPtr<nsIMsgPluggableStore> msgStore;
|
||||
nsresult rv = aFolder->GetMsgStore(getter_AddRefs(msgStore));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr <nsIFile> summaryFilePath;
|
||||
rv = msgStore->GetSummaryFile(aFolder, getter_AddRefs(summaryFilePath));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsMsgDatabase *cacheDB = FindInCache(summaryFilePath);
|
||||
if (cacheDB)
|
||||
{
|
||||
// this db could have ended up in the folder cache w/o an m_folder pointer via
|
||||
|
@ -175,13 +191,6 @@ NS_IMETHODIMP nsMsgDBService::AsyncOpenFolderDB(nsIMsgFolder *aFolder,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIMsgPluggableStore> msgStore;
|
||||
nsresult rv = aFolder->GetMsgStore(getter_AddRefs(msgStore));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr <nsIFile> summaryFilePath;
|
||||
rv = msgStore->GetSummaryFile(aFolder, getter_AddRefs(summaryFilePath));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr <nsIMsgIncomingServer> incomingServer;
|
||||
rv = aFolder->GetServer(getter_AddRefs(incomingServer));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -193,7 +202,7 @@ NS_IMETHODIMP nsMsgDBService::AsyncOpenFolderDB(nsIMsgFolder *aFolder,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsMsgDatabase *msgDatabase = static_cast<nsMsgDatabase *>(msgDB.get());
|
||||
rv = msgDatabase->OpenInternal(summaryFilePath, false, aLeaveInvalidDB,
|
||||
rv = msgDatabase->OpenInternal(this, summaryFilePath, false, aLeaveInvalidDB,
|
||||
false /* open asynchronously */);
|
||||
|
||||
NS_ADDREF(*_retval = msgDB);
|
||||
|
@ -262,7 +271,7 @@ NS_IMETHODIMP nsMsgDBService::OpenMore(nsIMsgDatabase *aDB,
|
|||
if (NS_SUCCEEDED(rv))
|
||||
rv = (msgDatabase->m_mdbStore) ? msgDatabase->InitExistingDB() : NS_ERROR_FAILURE;
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = msgDatabase->CheckForErrors(rv, false, summaryFile);
|
||||
rv = msgDatabase->CheckForErrors(rv, false, this, summaryFile);
|
||||
|
||||
FinishDBOpen(msgDatabase->m_folder, msgDatabase);
|
||||
break;
|
||||
|
@ -312,6 +321,26 @@ void nsMsgDBService::FinishDBOpen(nsIMsgFolder *aFolder, nsMsgDatabase *aMsgDB)
|
|||
aMsgDB->RememberLastUseTime();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// FindInCache - this addrefs the db it finds.
|
||||
//----------------------------------------------------------------------
|
||||
nsMsgDatabase* nsMsgDBService::FindInCache(nsIFile *dbName)
|
||||
{
|
||||
for (uint32_t i = 0; i < m_dbCache.Length(); i++)
|
||||
{
|
||||
nsMsgDatabase* pMessageDB = m_dbCache[i];
|
||||
if (pMessageDB->MatchDbName(dbName))
|
||||
{
|
||||
if (pMessageDB->m_mdbStore) // don't return db without store
|
||||
{
|
||||
NS_ADDREF(pMessageDB);
|
||||
return pMessageDB;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This method is called when the caller is trying to create a db without
|
||||
// having a corresponding nsIMsgFolder object. This happens in a few
|
||||
// situations, including imap folder discovery, compacting local folders,
|
||||
|
@ -329,13 +358,13 @@ NS_IMETHODIMP nsMsgDBService::OpenMailDBFromFile(nsIFile *aFolderName,
|
|||
nsresult rv = GetSummaryFileLocation(aFolderName, getter_AddRefs(dbPath));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*pMessageDB = (nsMsgDatabase *) nsMsgDatabase::FindInCache(dbPath);
|
||||
*pMessageDB = FindInCache(dbPath);
|
||||
if (*pMessageDB)
|
||||
return NS_OK;
|
||||
|
||||
nsRefPtr<nsMailDatabase> msgDB = new nsMailDatabase;
|
||||
NS_ENSURE_TRUE(msgDB, NS_ERROR_OUT_OF_MEMORY);
|
||||
rv = msgDB->Open(dbPath, aCreate, aLeaveInvalidDB);
|
||||
rv = msgDB->Open(this, dbPath, aCreate, aLeaveInvalidDB);
|
||||
if (rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
|
||||
return rv;
|
||||
NS_IF_ADDREF(*pMessageDB = msgDB);
|
||||
|
@ -373,7 +402,7 @@ NS_IMETHODIMP nsMsgDBService::CreateNewDB(nsIMsgFolder *aFolder,
|
|||
nsMsgDatabase *msgDatabase = static_cast<nsMsgDatabase *>(msgDB.get());
|
||||
|
||||
msgDatabase->m_folder = aFolder;
|
||||
rv = msgDatabase->Open(summaryFilePath, true, true);
|
||||
rv = msgDatabase->Open(this, summaryFilePath, true, true);
|
||||
NS_ENSURE_TRUE(rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING, rv);
|
||||
|
||||
NS_ADDREF(*_retval = msgDB);
|
||||
|
@ -392,7 +421,8 @@ NS_IMETHODIMP nsMsgDBService::RegisterPendingListener(nsIMsgFolder *aFolder, nsI
|
|||
// if there is a db open on this folder already, we should register the listener.
|
||||
m_foldersPendingListeners.AppendObject(aFolder);
|
||||
m_pendingListeners.AppendObject(aListener);
|
||||
nsCOMPtr <nsIMsgDatabase> openDB = dont_AddRef((nsIMsgDatabase *) nsMsgDatabase::FindInCache(aFolder));
|
||||
nsCOMPtr <nsIMsgDatabase> openDB;
|
||||
CachedDBForFolder(aFolder, getter_AddRefs(openDB));
|
||||
if (openDB)
|
||||
openDB->AddListener(aListener);
|
||||
return NS_OK;
|
||||
|
@ -404,8 +434,8 @@ NS_IMETHODIMP nsMsgDBService::UnregisterPendingListener(nsIDBChangeListener *aLi
|
|||
int32_t listenerIndex = m_pendingListeners.IndexOfObject(aListener);
|
||||
if (listenerIndex != -1)
|
||||
{
|
||||
nsCOMPtr <nsIMsgFolder> folder = m_foldersPendingListeners[listenerIndex];
|
||||
nsCOMPtr <nsIMsgDatabase> msgDB = dont_AddRef(nsMsgDatabase::FindInCache(folder));
|
||||
nsCOMPtr<nsIMsgDatabase> msgDB;
|
||||
CachedDBForFolder(m_foldersPendingListeners[listenerIndex], getter_AddRefs(msgDB));
|
||||
if (msgDB)
|
||||
msgDB->RemoveListener(aListener);
|
||||
m_foldersPendingListeners.RemoveObjectAt(listenerIndex);
|
||||
|
@ -419,20 +449,38 @@ NS_IMETHODIMP nsMsgDBService::CachedDBForFolder(nsIMsgFolder *aFolder, nsIMsgDat
|
|||
{
|
||||
NS_ENSURE_ARG_POINTER(aFolder);
|
||||
NS_ENSURE_ARG_POINTER(aRetDB);
|
||||
*aRetDB = nsMsgDatabase::FindInCache(aFolder);
|
||||
|
||||
nsCOMPtr<nsIMsgPluggableStore> msgStore;
|
||||
nsresult rv = aFolder->GetMsgStore(getter_AddRefs(msgStore));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIFile> summaryFilePath;
|
||||
rv = msgStore->GetSummaryFile(aFolder, getter_AddRefs(summaryFilePath));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aRetDB = FindInCache(summaryFilePath);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBService::ForceFolderDBClosed(nsIMsgFolder *aFolder)
|
||||
{
|
||||
nsCOMPtr<nsIMsgDatabase> mailDB;
|
||||
nsresult rv = CachedDBForFolder(aFolder, getter_AddRefs(mailDB));
|
||||
if (mailDB)
|
||||
{
|
||||
mailDB->ForceClosed();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBService::GetOpenDBs(nsIArray **aOpenDBs)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aOpenDBs);
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMutableArray> openDBs(do_CreateInstance(NS_ARRAY_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsMsgDatabase::GetDBCache();
|
||||
NS_ENSURE_TRUE(nsMsgDatabase::m_dbCache, NS_ERROR_OUT_OF_MEMORY);
|
||||
for (uint32_t i = 0; i < nsMsgDatabase::m_dbCache->Length(); i++)
|
||||
openDBs->AppendElement(nsMsgDatabase::m_dbCache->ElementAt(i), false);
|
||||
for (uint32_t i = 0; i < m_dbCache.Length(); i++)
|
||||
openDBs->AppendElement(m_dbCache[i], false);
|
||||
|
||||
openDBs.forget(aOpenDBs);
|
||||
return NS_OK;
|
||||
|
@ -892,80 +940,6 @@ NS_IMETHODIMP nsMsgDatabase::NotifyAnnouncerGoingAway(void)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Apparently its not good for nsTArray to be allocated as static. Don't know
|
||||
// why it isn't but its not, so don't think about making it a static variable.
|
||||
// Maybe bz knows.
|
||||
nsTArray<nsMsgDatabase*>* nsMsgDatabase::m_dbCache;
|
||||
|
||||
nsTArray<nsMsgDatabase*>*
|
||||
nsMsgDatabase::GetDBCache()
|
||||
{
|
||||
if (!m_dbCache)
|
||||
m_dbCache = new nsAutoTArray<nsMsgDatabase*, kInitialMsgDBCacheSize>;
|
||||
|
||||
return m_dbCache;
|
||||
}
|
||||
|
||||
void
|
||||
nsMsgDatabase::CleanupCache()
|
||||
{
|
||||
if (m_dbCache)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// If you hit this warning, it means that some code is holding onto
|
||||
// a db at shutdown.
|
||||
NS_WARN_IF_FALSE(!m_dbCache->Length(), "some msg dbs left open");
|
||||
for (uint32_t i = 0; i < m_dbCache->Length(); i++)
|
||||
{
|
||||
nsMsgDatabase* pMessageDB = m_dbCache->ElementAt(i);
|
||||
if (pMessageDB)
|
||||
printf("db left open %s\n", (const char *) pMessageDB->m_dbName.get());
|
||||
}
|
||||
#endif
|
||||
delete m_dbCache;
|
||||
m_dbCache = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// FindInCache - this addrefs the db it finds.
|
||||
//----------------------------------------------------------------------
|
||||
nsMsgDatabase* nsMsgDatabase::FindInCache(nsIFile *dbName)
|
||||
{
|
||||
nsTArray<nsMsgDatabase*>* dbCache = GetDBCache();
|
||||
uint32_t length = dbCache->Length();
|
||||
for (uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
nsMsgDatabase* pMessageDB = dbCache->ElementAt(i);
|
||||
if (pMessageDB->MatchDbName(dbName))
|
||||
{
|
||||
if (pMessageDB->m_mdbStore) // don't return db without store
|
||||
{
|
||||
NS_ADDREF(pMessageDB);
|
||||
return pMessageDB;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// FindInCache(nsIMsgFolder) - this addrefs the db it finds.
|
||||
//----------------------------------------------------------------------
|
||||
nsIMsgDatabase* nsMsgDatabase::FindInCache(nsIMsgFolder *folder)
|
||||
{
|
||||
nsCOMPtr<nsIFile> folderPath;
|
||||
|
||||
nsresult rv = folder->GetFilePath(getter_AddRefs(folderPath));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
nsCOMPtr <nsIFile> summaryFile;
|
||||
rv = GetSummaryFileLocation(folderPath, getter_AddRefs(summaryFile));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
return (nsIMsgDatabase *) FindInCache(summaryFile);
|
||||
}
|
||||
|
||||
bool nsMsgDatabase::MatchDbName(nsIFile *dbName) // returns true if they match
|
||||
{
|
||||
nsCString dbPath;
|
||||
|
@ -973,26 +947,32 @@ bool nsMsgDatabase::MatchDbName(nsIFile *dbName) // returns true if they match
|
|||
return dbPath.Equals(m_dbName);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// RemoveFromCache
|
||||
//----------------------------------------------------------------------
|
||||
void nsMsgDatabase::RemoveFromCache(nsMsgDatabase* pMessageDB)
|
||||
void nsMsgDBService::AddToCache(nsMsgDatabase* pMessageDB)
|
||||
{
|
||||
if (m_dbCache)
|
||||
m_dbCache->RemoveElement(pMessageDB);
|
||||
#ifdef DEBUG_David_Bienvenu
|
||||
NS_ASSERTION(m_dbCache.Length() < 50, "50 or more open db's");
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
if (pMessageDB->m_folder)
|
||||
{
|
||||
nsCOMPtr<nsIMsgDatabase> msgDB;
|
||||
CachedDBForFolder(pMessageDB->m_folder, getter_AddRefs(msgDB));
|
||||
NS_ASSERTION(!msgDB, "shouldn't have db in cache");
|
||||
}
|
||||
#endif
|
||||
m_dbCache.AppendElement(pMessageDB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the open db's, and how many headers are in memory.
|
||||
*/
|
||||
void nsMsgDatabase::DumpCache()
|
||||
void nsMsgDBService::DumpCache()
|
||||
{
|
||||
nsTArray<nsMsgDatabase*>* dbCache = GetDBCache();
|
||||
nsMsgDatabase* db = nullptr;
|
||||
PR_LOG(DBLog, PR_LOG_ALWAYS, ("%d open DB's\n", dbCache->Length()));
|
||||
for (uint32_t i = 0; i < dbCache->Length(); i++)
|
||||
PR_LOG(DBLog, PR_LOG_ALWAYS, ("%d open DB's\n", m_dbCache.Length()));
|
||||
for (uint32_t i = 0; i < m_dbCache.Length(); i++)
|
||||
{
|
||||
db = dbCache->ElementAt(i);
|
||||
db = m_dbCache.ElementAt(i);
|
||||
PR_LOG(DBLog, PR_LOG_ALWAYS, ("%s - %ld hdrs in use\n",
|
||||
(const char*)db->m_dbName.get(),
|
||||
db->m_headersInUse ? db->m_headersInUse->entryCount : 0));
|
||||
|
@ -1163,7 +1143,9 @@ nsMsgDatabase::~nsMsgDatabase()
|
|||
PR_LOG(DBLog, PR_LOG_ALWAYS, ("closing database %s\n",
|
||||
(const char*)m_dbName.get()));
|
||||
|
||||
RemoveFromCache(this);
|
||||
nsCOMPtr<nsIMsgDBService> serv(mozilla::services::GetDBService());
|
||||
static_cast<nsMsgDBService*>(serv.get())->RemoveFromCache(this);
|
||||
|
||||
// if the db folder info refers to the mdb db, we must clear it because
|
||||
// the reference will be a dangling one soon.
|
||||
if (m_dbFolderInfo)
|
||||
|
@ -1204,14 +1186,15 @@ void nsMsgDatabase::GetMDBFactory(nsIMdbFactory ** aMdbFactory)
|
|||
// aLeaveInvalidDB: true if caller wants back a db even out of date.
|
||||
// If so, they'll extract out the interesting info from the db, close it,
|
||||
// delete it, and then try to open the db again, prior to reparsing.
|
||||
nsresult nsMsgDatabase::Open(nsIFile *aFolderName, bool aCreate,
|
||||
bool aLeaveInvalidDB)
|
||||
nsresult nsMsgDatabase::Open(nsMsgDBService *aDBService, nsIFile *aFolderName,
|
||||
bool aCreate, bool aLeaveInvalidDB)
|
||||
{
|
||||
return nsMsgDatabase::OpenInternal(aFolderName, aCreate, aLeaveInvalidDB,
|
||||
return nsMsgDatabase::OpenInternal(aDBService, aFolderName, aCreate, aLeaveInvalidDB,
|
||||
true /* open synchronously */);
|
||||
}
|
||||
|
||||
nsresult nsMsgDatabase::OpenInternal(nsIFile *summaryFile, bool aCreate,
|
||||
nsresult nsMsgDatabase::OpenInternal(nsMsgDBService *aDBService,
|
||||
nsIFile *summaryFile, bool aCreate,
|
||||
bool aLeaveInvalidDB, bool sync)
|
||||
{
|
||||
nsAutoCString summaryFilePath;
|
||||
|
@ -1227,7 +1210,7 @@ nsresult nsMsgDatabase::OpenInternal(nsIFile *summaryFile, bool aCreate,
|
|||
PR_LOG(DBLog, PR_LOG_ALWAYS, ("error opening db %lx", rv));
|
||||
|
||||
if (PR_LOG_TEST(DBLog, PR_LOG_DEBUG))
|
||||
DumpCache();
|
||||
aDBService->DumpCache();
|
||||
|
||||
if (rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
|
||||
return rv;
|
||||
|
@ -1236,14 +1219,15 @@ nsresult nsMsgDatabase::OpenInternal(nsIFile *summaryFile, bool aCreate,
|
|||
m_leaveInvalidDB = aLeaveInvalidDB;
|
||||
if (!sync && NS_SUCCEEDED(rv))
|
||||
{
|
||||
AddToCache(this);
|
||||
aDBService->AddToCache(this);
|
||||
// remember open options for when the parsing is complete.
|
||||
return rv;
|
||||
}
|
||||
return CheckForErrors(rv, true, summaryFile);
|
||||
return CheckForErrors(rv, true, aDBService, summaryFile);
|
||||
}
|
||||
|
||||
nsresult nsMsgDatabase::CheckForErrors(nsresult err, bool sync,
|
||||
nsMsgDBService *aDBService,
|
||||
nsIFile *summaryFile)
|
||||
{
|
||||
nsCOMPtr<nsIDBFolderInfo> folderInfo;
|
||||
|
@ -1314,7 +1298,7 @@ nsresult nsMsgDatabase::CheckForErrors(nsresult err, bool sync,
|
|||
}
|
||||
}
|
||||
if (sync && (NS_SUCCEEDED(err) || err == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING))
|
||||
AddToCache(this);
|
||||
aDBService->AddToCache(this);
|
||||
return (summaryFileExists) ? err : NS_MSG_ERROR_FOLDER_SUMMARY_MISSING;
|
||||
}
|
||||
|
||||
|
@ -1443,28 +1427,6 @@ nsresult nsMsgDatabase::CloseMDB(bool commit)
|
|||
return(NS_OK);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDatabase::ForceFolderDBClosed(nsIMsgFolder *aFolder)
|
||||
{
|
||||
NS_ENSURE_ARG(aFolder);
|
||||
|
||||
nsCOMPtr<nsIFile> folderPath;
|
||||
nsresult rv = aFolder->GetFilePath(getter_AddRefs(folderPath));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr <nsIFile> dbPath;
|
||||
rv = GetSummaryFileLocation(folderPath, getter_AddRefs(dbPath));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIMsgDatabase *mailDB = (nsMsgDatabase *) FindInCache(dbPath);
|
||||
if (mailDB)
|
||||
{
|
||||
mailDB->ForceClosed();
|
||||
//FindInCache AddRef's
|
||||
mailDB->Release();
|
||||
}
|
||||
return(NS_OK);
|
||||
}
|
||||
|
||||
|
||||
// force the database to close - this'll flush out anybody holding onto
|
||||
// a database without having a listener!
|
||||
|
@ -4110,9 +4072,8 @@ NS_IMETHODIMP nsMsgDatabase::SetSummaryValid(bool valid /* = true */)
|
|||
// not have been added to the cache. Add it now if missing.
|
||||
if (valid)
|
||||
{
|
||||
nsTArray<nsMsgDatabase*>* dbCache = GetDBCache();
|
||||
if (dbCache && !dbCache->Contains(this))
|
||||
dbCache->AppendElement(this);
|
||||
nsCOMPtr<nsIMsgDBService> serv(mozilla::services::GetDBService());
|
||||
static_cast<nsMsgDBService*>(serv.get())->EnsureCached(this);
|
||||
}
|
||||
// setting the version to 0 ought to make it pretty invalid.
|
||||
if (m_dbFolderInfo)
|
||||
|
|
|
@ -12,7 +12,9 @@ const anyOldMessage = do_get_file("../../../../data/bugmail1");
|
|||
function test_enumerator_cleanup() {
|
||||
let db = localAccountUtils.inboxFolder.msgDatabase;
|
||||
let enumerator = db.EnumerateMessages();
|
||||
db.forceFolderDBClosed(localAccountUtils.inboxFolder);
|
||||
Cc["@mozilla.org/msgDatabase/msgDBService;1"]
|
||||
.getService(Ci.nsIMsgDBService)
|
||||
.forceFolderDBClosed(localAccountUtils.inboxFolder);
|
||||
localAccountUtils.inboxFolder.msgDatabase = null;
|
||||
db = null;
|
||||
gc();
|
||||
|
|
Загрузка…
Ссылка в новой задаче