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:
bienvenu%netscape.com 2001-06-28 01:21:45 +00:00
Родитель b7ed53db75
Коммит 38fe93f9ff
6 изменённых файлов: 146 добавлений и 71 удалений

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

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