зеркало из https://github.com/mozilla/pjs.git
fix threads created with root msg with id 1 not to have thread id 1, fix handling of errors opening dbs r=naving, sr=sspitzer 84438
This commit is contained in:
Родитель
b7ed53db75
Коммит
38fe93f9ff
|
@ -40,6 +40,7 @@ interface nsIMsgFolder;
|
|||
[ptr] native octetPtr(PRUint8);
|
||||
|
||||
typedef unsigned long nsMsgRetainByPreference;
|
||||
|
||||
|
||||
[scriptable, uuid(063bd2ac-de85-11d4-a5b6-0060b0fc04b7)]
|
||||
|
||||
|
@ -232,10 +233,10 @@ interface nsIMsgDatabase : nsIDBChangeAnnouncer {
|
|||
[noscript] void ListAllOfflineDeletes(in nsMsgKeyArrayPtr offlineDeletes);
|
||||
[noscript] void ListAllOfflineMsgs(in nsMsgKeyArrayPtr offlineMsgs);
|
||||
|
||||
readonly attribute nsMsgKey LowWaterArticleNum;
|
||||
readonly attribute nsMsgKey HighWaterArticleNum;
|
||||
attribute nsMsgKey NextPseudoMsgKey; //for undo-redo of move pop->imap
|
||||
|
||||
readonly attribute nsMsgKey lowWaterArticleNum;
|
||||
readonly attribute nsMsgKey highWaterArticleNum;
|
||||
attribute nsMsgKey nextPseudoMsgKey; //for undo-redo of move pop->imap
|
||||
readonly attribute nsMsgKey nextFakeOfflineMsgKey; // for saving "fake" offline msg hdrs
|
||||
// for sorting
|
||||
[noscript] void createCollationKey(in wstring sourceString, out octetPtr key, out unsigned long len);
|
||||
[noscript] long compareCollationKeys(out octet key1, in unsigned long len1, out octet key2, in unsigned long len2);
|
||||
|
|
|
@ -32,10 +32,6 @@ class nsIOFileStream;
|
|||
class nsFileSpec;
|
||||
class nsOfflineImapOperation;
|
||||
|
||||
// this is the version number for the mail db. If the file format changes, we
|
||||
// just reparse the mail folder.
|
||||
const int kMailDBVersion = 1;
|
||||
|
||||
class nsMailDatabase : public nsMsgDatabase
|
||||
{
|
||||
public:
|
||||
|
@ -56,7 +52,7 @@ public:
|
|||
nsresult GetFolderName(nsString &folderName);
|
||||
virtual nsMailDatabase *GetMailDB() {return this;}
|
||||
|
||||
virtual PRUint32 GetCurVersion() {return kMailDBVersion;}
|
||||
virtual PRUint32 GetCurVersion() {return kMsgDBVersion;}
|
||||
|
||||
NS_IMETHOD GetOfflineOpForKey(nsMsgKey opKey, PRBool create, nsIMsgOfflineImapOperation **op);
|
||||
NS_IMETHOD RemoveOfflineOp(nsIMsgOfflineImapOperation *op);
|
||||
|
|
|
@ -46,6 +46,8 @@ class nsMsgThread;
|
|||
class nsIMsgThread;
|
||||
class nsIDBFolderInfo;
|
||||
class nsIMsgHeaderParser;
|
||||
|
||||
const PRInt32 kMsgDBVersion = 1;
|
||||
|
||||
class nsMsgDatabase : public nsIMsgDatabase
|
||||
{
|
||||
|
|
|
@ -117,7 +117,7 @@ NS_IMETHODIMP nsImapMailDatabase::Open(nsIFileSpec *aFolderName, PRBool create,
|
|||
{
|
||||
// this will make the db folder info release its ref to the mail db...
|
||||
NS_IF_RELEASE(mailDB->m_dbFolderInfo);
|
||||
mailDB->Close(PR_TRUE);
|
||||
mailDB->ForceClosed();
|
||||
if (err == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
|
||||
summarySpec.Delete(PR_FALSE);
|
||||
|
||||
|
@ -134,8 +134,9 @@ NS_IMETHODIMP nsImapMailDatabase::Open(nsIFileSpec *aFolderName, PRBool create,
|
|||
}
|
||||
else if (err != NS_OK)
|
||||
{
|
||||
*pMessageDB = NULL;
|
||||
mailDB->Close(PR_FALSE);
|
||||
*pMessageDB = NULL;
|
||||
if (mailDB)
|
||||
mailDB->Close(PR_FALSE);
|
||||
delete mailDB;
|
||||
summarySpec.Delete(PR_FALSE); // blow away the db if it's corrupt.
|
||||
mailDB = NULL;
|
||||
|
|
|
@ -69,9 +69,15 @@ static NS_DEFINE_CID(kMsgHeaderParserCID, NS_MSGHEADERPARSER_CID);
|
|||
|
||||
#define MSG_HASH_SIZE 512
|
||||
|
||||
const int kMsgDBVersion = 1;
|
||||
const PRInt32 kMaxHdrsInCache = 512;
|
||||
|
||||
// special keys
|
||||
static const nsMsgKey kAllMsgHdrsTableKey = 1;
|
||||
static const nsMsgKey kTableKeyForThreadOne = 0xfffffffe;
|
||||
static const nsMsgKey kFirstPseudoKey = 0xfffffffd;
|
||||
static const nsMsgKey kIdStartOfFake = 0xffffff80;
|
||||
|
||||
|
||||
// we never need to call this because we check the use cache first,
|
||||
// and any hdr in this cache will be in the use cache.
|
||||
nsresult nsMsgDatabase::GetHdrFromCache(nsMsgKey key, nsIMsgDBHdr* *result)
|
||||
|
@ -600,7 +606,7 @@ void nsMsgDatabase::DumpCache()
|
|||
|
||||
nsMsgDatabase::nsMsgDatabase()
|
||||
: m_dbFolderInfo(nsnull),
|
||||
m_nextPseudoMsgKey(-1),
|
||||
m_nextPseudoMsgKey(kFirstPseudoKey),
|
||||
m_mdbEnv(nsnull), m_mdbStore(nsnull),
|
||||
m_mdbAllMsgHeadersTable(nsnull), m_dbName(""), m_newSet(nsnull),
|
||||
m_mdbTokensInitialized(PR_FALSE), m_ChangeListeners(nsnull),
|
||||
|
@ -1154,10 +1160,16 @@ nsresult nsMsgDatabase::InitNewDB()
|
|||
nsIMdbStore *store = GetStore();
|
||||
// create the unique table for the dbFolderInfo.
|
||||
mdb_err mdberr;
|
||||
struct mdbOid allMsgHdrsTableOID;
|
||||
|
||||
mdberr = (nsresult) store->NewTable(GetEnv(), m_hdrRowScopeToken,
|
||||
m_hdrTableKindToken, PR_FALSE, nsnull, &m_mdbAllMsgHeadersTable);
|
||||
// m_mdbAllMsgHeadersTable->BecomeContent(GetEnv(), &gAllMsgHdrsTableOID);
|
||||
if (!store)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
allMsgHdrsTableOID.mOid_Scope = m_hdrRowScopeToken;
|
||||
allMsgHdrsTableOID.mOid_Id = kAllMsgHdrsTableKey;
|
||||
|
||||
mdberr = GetStore()->NewTableWithOid(GetEnv(), &allMsgHdrsTableOID, m_hdrTableKindToken,
|
||||
PR_FALSE, nsnull, &m_mdbAllMsgHeadersTable);
|
||||
|
||||
m_dbFolderInfo = dbFolderInfo;
|
||||
|
||||
|
@ -1178,11 +1190,10 @@ nsresult nsMsgDatabase::InitExistingDB()
|
|||
err = GetStore()->GetTable(GetEnv(), &gAllMsgHdrsTableOID, &m_mdbAllMsgHeadersTable);
|
||||
if (err == NS_OK)
|
||||
{
|
||||
m_dbFolderInfo = new nsDBFolderInfo(this); // mscott: This is bad!!! Should be going through component manager
|
||||
m_dbFolderInfo = new nsDBFolderInfo(this);
|
||||
if (m_dbFolderInfo)
|
||||
{
|
||||
NS_ADDREF(m_dbFolderInfo); // mscott: acquire a ref count. we shouldn't do this & should be going through
|
||||
// the component manager instead.
|
||||
NS_ADDREF(m_dbFolderInfo);
|
||||
err = m_dbFolderInfo->InitFromExistingDB();
|
||||
}
|
||||
}
|
||||
|
@ -1193,8 +1204,12 @@ nsresult nsMsgDatabase::InitExistingDB()
|
|||
if (NS_SUCCEEDED(err) && !m_mdbAllMsgHeadersTable)
|
||||
{
|
||||
nsIMdbStore *store = GetStore();
|
||||
mdb_err mdberr = (nsresult) store->NewTable(GetEnv(), m_hdrRowScopeToken,
|
||||
m_hdrTableKindToken, PR_FALSE, nsnull, &m_mdbAllMsgHeadersTable);
|
||||
struct mdbOid allMsgHdrsTableOID;
|
||||
allMsgHdrsTableOID.mOid_Scope = m_hdrRowScopeToken;
|
||||
allMsgHdrsTableOID.mOid_Id = kAllMsgHdrsTableKey;
|
||||
|
||||
mdb_err mdberr = GetStore()->NewTableWithOid(GetEnv(), &allMsgHdrsTableOID, m_hdrTableKindToken,
|
||||
PR_FALSE, nsnull, &m_mdbAllMsgHeadersTable);
|
||||
if (mdberr != NS_OK || !m_mdbAllMsgHeadersTable)
|
||||
err = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -1251,7 +1266,7 @@ nsresult nsMsgDatabase::InitMDBInfo()
|
|||
{
|
||||
// The table of all message hdrs will have table id 1.
|
||||
gAllMsgHdrsTableOID.mOid_Scope = m_hdrRowScopeToken;
|
||||
gAllMsgHdrsTableOID.mOid_Id = 1;
|
||||
gAllMsgHdrsTableOID.mOid_Id = kAllMsgHdrsTableKey;
|
||||
gAllThreadsTableOID.mOid_Scope = m_threadRowScopeToken;
|
||||
gAllThreadsTableOID.mOid_Id = 1;
|
||||
|
||||
|
@ -3394,33 +3409,38 @@ nsIMsgThread * nsMsgDatabase::GetThreadForThreadId(nsMsgKey threadId)
|
|||
// make the passed in header a thread header
|
||||
nsresult nsMsgDatabase::AddNewThread(nsMsgHdr *msgHdr)
|
||||
{
|
||||
|
||||
if (!msgHdr)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsMsgThread *threadHdr = nsnull;
|
||||
|
||||
nsXPIDLCString subject;
|
||||
nsMsgKey threadKey = msgHdr->m_messageKey;
|
||||
// can't have a thread with key 1 since that's the table id of the all msg hdr table,
|
||||
// so give it kTableKeyForThreadOne (0xfffffffe).
|
||||
if (threadKey == 1)
|
||||
threadKey = kTableKeyForThreadOne;
|
||||
|
||||
if (!msgHdr)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsMsgThread *threadHdr = nsnull;
|
||||
|
||||
nsXPIDLCString subject;
|
||||
|
||||
nsresult err = msgHdr->GetSubject(getter_Copies(subject));
|
||||
|
||||
err = CreateNewThread(msgHdr->m_messageKey, subject, &threadHdr);
|
||||
msgHdr->SetThreadId(msgHdr->m_messageKey);
|
||||
if (threadHdr)
|
||||
{
|
||||
// nsCString subject;
|
||||
|
||||
threadHdr->AddRef();
|
||||
// err = msgHdr->GetSubject(subject);
|
||||
// threadHdr->SetThreadKey(msgHdr->m_messageKey);
|
||||
// threadHdr->SetSubject(subject.get());
|
||||
|
||||
// need to add the thread table to the db.
|
||||
AddToThread(msgHdr, threadHdr, nsnull, PR_FALSE);
|
||||
|
||||
threadHdr->Release();
|
||||
}
|
||||
return err;
|
||||
nsresult err = msgHdr->GetSubject(getter_Copies(subject));
|
||||
|
||||
err = CreateNewThread(threadKey, subject, &threadHdr);
|
||||
msgHdr->SetThreadId(threadKey);
|
||||
if (threadHdr)
|
||||
{
|
||||
// nsCString subject;
|
||||
|
||||
threadHdr->AddRef();
|
||||
// err = msgHdr->GetSubject(subject);
|
||||
// threadHdr->SetThreadKey(msgHdr->m_messageKey);
|
||||
// threadHdr->SetSubject(subject.get());
|
||||
|
||||
// need to add the thread table to the db.
|
||||
AddToThread(msgHdr, threadHdr, nsnull, PR_FALSE);
|
||||
|
||||
threadHdr->Release();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3551,7 +3571,7 @@ NS_IMETHODIMP nsMsgDatabase::GetLowWaterArticleNum(nsMsgKey *key)
|
|||
NS_IMETHODIMP nsMsgDatabase::GetNextPseudoMsgKey(nsMsgKey *nextPseudoMsgKey)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(nextPseudoMsgKey);
|
||||
*nextPseudoMsgKey = m_nextPseudoMsgKey;
|
||||
*nextPseudoMsgKey = m_nextPseudoMsgKey--;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3561,6 +3581,27 @@ NS_IMETHODIMP nsMsgDatabase::SetNextPseudoMsgKey(nsMsgKey nextPseudoMsgKey)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDatabase::GetNextFakeOfflineMsgKey(nsMsgKey *nextFakeOfflineMsgKey)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(nextFakeOfflineMsgKey);
|
||||
// iterate over hdrs looking for first non-existant fake offline msg key
|
||||
nsMsgKey fakeMsgKey = kIdStartOfFake;
|
||||
|
||||
PRBool containsKey;
|
||||
do
|
||||
{
|
||||
ContainsKey(fakeMsgKey, &containsKey);
|
||||
if (!containsKey)
|
||||
break;
|
||||
fakeMsgKey--;
|
||||
}
|
||||
while (containsKey);
|
||||
|
||||
*nextFakeOfflineMsgKey = fakeMsgKey;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMsgDatabase::HasThreads(PRBool *hasThreads)
|
||||
{
|
||||
nsresult rv;
|
||||
|
|
|
@ -84,6 +84,7 @@ NS_IMETHODIMP nsNewsDatabase::Open(nsIFileSpec *aNewsgroupName, PRBool create, P
|
|||
|
||||
nsNewsSummarySpec summarySpec(newsgroupName);
|
||||
nsresult err = NS_OK;
|
||||
PRBool newFile = PR_FALSE;
|
||||
|
||||
#ifdef DEBUG_NEWS_DATABASE
|
||||
printf("nsNewsDatabase::Open(%s, %s, %p, %s) -> %s\n",
|
||||
|
@ -115,27 +116,60 @@ NS_IMETHODIMP nsNewsDatabase::Open(nsIFileSpec *aNewsgroupName, PRBool create, P
|
|||
|
||||
newsDB->AddRef();
|
||||
|
||||
nsIDBFolderInfo *folderInfo = nsnull;
|
||||
err = newsDB->OpenMDB((const char *) summarySpec, create);
|
||||
if (NS_SUCCEEDED(err)) {
|
||||
#ifdef DEBUG_NEWS_DATABASE
|
||||
printf("newsDB->OpenMDB succeeded!\n");
|
||||
#endif
|
||||
*pMessageDB = newsDB;
|
||||
if (newsDB) {
|
||||
GetDBCache()->AppendElement(newsDB);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG_NEWS_DATABASE
|
||||
printf("newsDB->OpenMDB failed!\n");
|
||||
#endif
|
||||
*pMessageDB = nsnull;
|
||||
if (newsDB) {
|
||||
delete newsDB;
|
||||
}
|
||||
newsDB = nsnull;
|
||||
}
|
||||
|
||||
if (err == NS_OK)
|
||||
{
|
||||
newsDB->GetDBFolderInfo(&folderInfo);
|
||||
if (folderInfo == nsnull)
|
||||
{
|
||||
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// compare current version of db versus filed out version info.
|
||||
PRUint32 version;
|
||||
folderInfo->GetVersion(&version);
|
||||
if (newsDB->GetCurVersion() != version)
|
||||
err = NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
|
||||
NS_RELEASE(folderInfo);
|
||||
}
|
||||
if (err != NS_OK)
|
||||
{
|
||||
// this will make the db folder info release its ref to the mail db...
|
||||
NS_IF_RELEASE(newsDB->m_dbFolderInfo);
|
||||
newsDB->ForceClosed();
|
||||
if (err == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
|
||||
summarySpec.Delete(PR_FALSE);
|
||||
|
||||
newsDB = nsnull;
|
||||
}
|
||||
}
|
||||
if (err != NS_OK || newFile)
|
||||
{
|
||||
// if we couldn't open file, or we have a blank one, and we're supposed
|
||||
// to upgrade, updgrade it.
|
||||
if (newFile && !upgrading) // caller is upgrading, and we have empty summary file,
|
||||
{ // leave db around and open so caller can upgrade it.
|
||||
err = NS_MSG_ERROR_FOLDER_SUMMARY_MISSING;
|
||||
}
|
||||
else if (err != NS_OK)
|
||||
{
|
||||
*pMessageDB = nsnull;
|
||||
if (newsDB)
|
||||
newsDB->ForceClosed();
|
||||
delete newsDB;
|
||||
summarySpec.Delete(PR_FALSE); // blow away the db if it's corrupt.
|
||||
newsDB = nsnull;
|
||||
}
|
||||
}
|
||||
if (err == NS_OK || err == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
|
||||
{
|
||||
*pMessageDB = newsDB;
|
||||
if (newsDB)
|
||||
GetDBCache()->AppendElement(newsDB);
|
||||
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -157,7 +191,7 @@ nsresult nsNewsDatabase::Commit(nsMsgDBCommit commitType)
|
|||
|
||||
PRUint32 nsNewsDatabase::GetCurVersion()
|
||||
{
|
||||
return 1;
|
||||
return kMsgDBVersion;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsNewsDatabase::IsRead(nsMsgKey key, PRBool *pRead)
|
||||
|
|
Загрузка…
Ссылка в новой задаче