From d52fb4fc67ca7c754cd5e1af18452e62caafb237 Mon Sep 17 00:00:00 2001 From: "bienvenu%netscape.com" Date: Thu, 4 Feb 1999 17:35:26 +0000 Subject: [PATCH] more work on reading and writing db folder info --- mailnews/db/msgdb/public/nsDBFolderInfo.h | 41 ++++-- mailnews/db/msgdb/public/nsMsgDatabase.h | 9 +- mailnews/db/msgdb/public/nsMsgHdr.h | 1 + mailnews/db/msgdb/src/nsDBFolderInfo.cpp | 144 ++++++++++++++++++++-- mailnews/db/msgdb/src/nsMailDatabase.cpp | 6 + mailnews/db/msgdb/src/nsMsgDatabase.cpp | 56 +++++++-- mailnews/db/msgdb/src/nsMsgHdr.cpp | 24 ++++ 7 files changed, 245 insertions(+), 36 deletions(-) diff --git a/mailnews/db/msgdb/public/nsDBFolderInfo.h b/mailnews/db/msgdb/public/nsDBFolderInfo.h index 30e1431d382..805e04eee55 100644 --- a/mailnews/db/msgdb/public/nsDBFolderInfo.h +++ b/mailnews/db/msgdb/public/nsDBFolderInfo.h @@ -42,13 +42,12 @@ class nsDBFolderInfo public: nsDBFolderInfo(nsMsgDatabase *mdb); virtual ~nsDBFolderInfo(); - nsrefcnt AddRef(void); - nsrefcnt Release(void); + nsrefcnt AddRef(void); + nsrefcnt Release(void); // create the appropriate table and row in a new db. - nsresult AddToNewMDB(); - // initialize from appropriate table and row in existing db. - nsresult InitFromExistingDB(); + nsresult AddToNewMDB(); + // accessor methods. void SetHighWater(MessageKey highWater, PRBool force = FALSE) ; MessageKey GetHighWater() ; void SetExpiredMark(MessageKey expiredKey); @@ -90,10 +89,13 @@ public: PRInt32 GetImapUidValidity() ; void SetImapUidValidity(PRInt32 uidValidity) ; + void SetVersion(PRUint16 version) {m_version = version;} + MessageKey GetLastMessageLoaded(); void SetLastMessageLoaded(MessageKey lastLoaded); - // get arbitrary property, aka row cell value. + // get and set arbitrary property, aka row cell value. nsresult GetProperty(const char *propertyName, nsString &resultProperty); + nsresult SetProperty(const char *propertyName, nsString &propertyStr); PRUint16 m_version; // for upgrading... PRInt32 m_sortType; // the last sort type open on this db. @@ -102,17 +104,16 @@ public: PRInt8 m_sortOrder; // the last sort order (up or down // mail only (for now) PRInt32 m_folderSize; - PRInt32 m_expunged_bytes; // sum of size of deleted messages in folder + PRInt32 m_expungedBytes; // sum of size of deleted messages in folder time_t m_folderDate; + MessageKey m_highWaterMessageKey; // largest news article number or imap uid whose header we've seen // IMAP only - PRInt32 m_LastMessageUID; PRInt32 m_ImapUidValidity; PRInt32 m_TotalPendingMessages; PRInt32 m_UnreadPendingMessages; // news only (for now) - MessageKey m_articleNumHighWater; // largest article number whose header we've seen MessageKey m_expiredMark; // Highest invalid article number in group - for expiring PRInt32 m_viewType; // for news, the last view type open on this db. @@ -121,6 +122,10 @@ public: protected: nsrefcnt mRefCnt; + // initialize from appropriate table and row in existing db. + nsresult InitFromExistingDB(); + nsresult InitMDBInfo(); + nsString m_mailboxName; // name presented to the user, will match imap server name PRInt32 m_numVisibleMessages; // doesn't include expunged or ignored messages (but does include collapsed). PRInt32 m_numNewMessages; @@ -134,8 +139,26 @@ protected: nsMsgDatabase *m_mdb; mdbTable *m_mdbTable; // singleton table in db mdbRow *m_mdbRow; // singleton row in table; + + PRBool m_mdbTokensInitialized; + mdb_token m_rowScopeToken; mdb_token m_tableKindToken; + // tokens for the pre-set columns - we cache these for speed, which may be silly + mdb_token m_mailboxNameColumnToken; + mdb_token m_numVisibleMessagesColumnToken; + mdb_token m_numMessagesColumnToken; + mdb_token m_numNewMessagesColumnToken; + mdb_token m_flagsColumnToken; + mdb_token m_lastMessageLoadedColumnToken; + mdb_token m_folderSizeColumnToken; + mdb_token m_expungedBytesColumnToken; + mdb_token m_folderDateColumnToken; + mdb_token m_highWaterMessageKeyColumnToken; + + mdb_token m_imapUidValidityColumnToken; + mdb_token m_totalPendingMessagesColumnToken; + mdb_token m_unreadPendingMessagesColumnToken; }; diff --git a/mailnews/db/msgdb/public/nsMsgDatabase.h b/mailnews/db/msgdb/public/nsMsgDatabase.h index 44f5b45999a..35ea14bd02d 100644 --- a/mailnews/db/msgdb/public/nsMsgDatabase.h +++ b/mailnews/db/msgdb/public/nsMsgDatabase.h @@ -114,6 +114,11 @@ public: virtual nsresult DeleteMessages(nsMsgKeyArray &messageKeys, ChangeListener *instigator); + // used mainly to force the timestamp of a local mail folder db to + // match the time stamp of the corresponding berkeley mail folder, + // but also useful to tell the summary to mark itself invalid + virtual nsresult SetSummaryValid(PRBool valid = TRUE); + static mdbFactory *GetMDBFactory(); nsDBFolderInfo *GetDBFolderInfo() {return m_dbFolderInfo;} mdbEnv *GetEnv() {return m_mdbEnv;} @@ -122,8 +127,8 @@ public: static nsMsgDatabase* FindInCache(nsFilePath &dbName); //helper function to fill in nsStrings from hdr row cell contents. - nsresult HdrCellColumnTonsString(nsMsgHdr *msgHdr, mdb_token columnToken, nsString &resultStr); - nsresult HdrCellColumnToUInt32(nsMsgHdr *msgHdr, mdb_token columnToken, PRUint32 *uint32Result); + nsresult RowCellColumnTonsString(mdbRow *row, mdb_token columnToken, nsString &resultStr); + nsresult RowCellColumnToUInt32(mdbRow *row, mdb_token columnToken, PRUint32 *uint32Result); // helper functions to copy an nsString to a yarn, int32 to yarn, and vice versa. static struct mdbYarn *nsStringToYarn(struct mdbYarn *yarn, nsString *str); diff --git a/mailnews/db/msgdb/public/nsMsgHdr.h b/mailnews/db/msgdb/public/nsMsgHdr.h index a7ae7c05ea8..805f98f4591 100644 --- a/mailnews/db/msgdb/public/nsMsgHdr.h +++ b/mailnews/db/msgdb/public/nsMsgHdr.h @@ -39,6 +39,7 @@ public: nsrefcnt AddRef(void); nsrefcnt Release(void); nsresult GetProperty(const char *propertyName, nsString &resultProperty); + nsresult SetProperty(const char *propertyName, nsString &propertyStr); uint16 GetNumReferences(); nsresult GetStringReference(PRInt32 refNum, nsString &resultReference); time_t GetDate(); diff --git a/mailnews/db/msgdb/src/nsDBFolderInfo.cpp b/mailnews/db/msgdb/src/nsDBFolderInfo.cpp index bf8a3e01404..799e7634293 100644 --- a/mailnews/db/msgdb/src/nsDBFolderInfo.cpp +++ b/mailnews/db/msgdb/src/nsDBFolderInfo.cpp @@ -19,14 +19,45 @@ #include "nsDBFolderInfo.h" #include "nsMsgDatabase.h" -const char *kDBFolderInfoScope = "ns:msg:db:row:scope:dbfolderinfo:all"; -const char *kDBFolderInfoTableKind = "ns:msg:db:table:kind:dbfolderinfo"; +static const char *kDBFolderInfoScope = "ns:msg:db:row:scope:dbfolderinfo:all"; +static const char *kDBFolderInfoTableKind = "ns:msg:db:table:kind:dbfolderinfo"; struct mdbOid gDBFolderInfoOID; +static const char * kNumVisibleMessagesColumnName = "numVisMsgs"; +static const char * kNumMessagesColumnName ="numMsgs"; +static const char * kNumNewMessagesColumnName = "numNewMsgs"; +static const char * kFlagsColumnName = "flags"; +static const char * kLastMessageLoadedColumnName = "lastMsgLoaded"; +static const char * kFolderSizeColumnName = "folderSize"; +static const char * kExpungedBytesColumnName = "expungedBytes"; +static const char * kFolderDateColumnName = "folderDate"; +static const char * kHighWaterMessageKeyColumnName = "highWaterKey"; + +static const char * kImapUidValidityColumnName = "UIDValidity"; +static const char * kTotalPendingMessagesColumnName = "totPendingMsgs"; +static const char * kUnreadPendingMessagesColumnName = "unreadPendingMsgs"; +static const char * kMailboxNameColumnName = "mailboxName"; nsDBFolderInfo::nsDBFolderInfo(nsMsgDatabase *mdb) { m_mdbTable = NULL; m_mdbRow = NULL; + m_version = 0; // for upgrading... + m_sortType = 0; // the last sort type open on this db. + m_csid = 0; // default csid for these messages + m_IMAPHierarchySeparator = 0; // imap path separator + m_sortOrder = 0; // the last sort order (up or down + // mail only (for now) + m_folderSize = 0; + m_expungedBytes = 0; // sum of size of deleted messages in folder + m_folderDate = 0; + m_highWaterMessageKey = 0; + + // IMAP only + m_ImapUidValidity = 0; + m_TotalPendingMessages =0; + m_UnreadPendingMessages = 0; + + m_mdbTokensInitialized = FALSE; if (mdb) { @@ -44,6 +75,7 @@ nsDBFolderInfo::nsDBFolderInfo(nsMsgDatabase *mdb) gDBFolderInfoOID.mOid_Id = 1; } } + InitMDBInfo(); } } @@ -121,14 +153,45 @@ nsresult nsDBFolderInfo::InitFromExistingDB() return ret; } +nsresult nsDBFolderInfo::InitMDBInfo() +{ + nsresult ret = NS_OK; + if (!m_mdbTokensInitialized && m_mdb && m_mdb->GetStore()) + { + mdbStore *store = m_mdb->GetStore(); + mdbEnv *env = m_mdb->GetEnv(); + + store->StringToToken(env, kNumVisibleMessagesColumnName, &m_numVisibleMessagesColumnToken); + store->StringToToken(env, kNumMessagesColumnName, &m_numMessagesColumnToken); + store->StringToToken(env, kNumNewMessagesColumnName, &m_numNewMessagesColumnToken); + store->StringToToken(env, kFlagsColumnName, &m_flagsColumnToken); + store->StringToToken(env, kLastMessageLoadedColumnName, &m_lastMessageLoadedColumnToken); + store->StringToToken(env, kFolderSizeColumnName, &m_folderSizeColumnToken); + store->StringToToken(env, kExpungedBytesColumnName, &m_expungedBytesColumnToken); + store->StringToToken(env, kFolderDateColumnName, &m_folderDateColumnToken); + + store->StringToToken(env, kHighWaterMessageKeyColumnName, &m_highWaterMessageKeyColumnToken); + store->StringToToken(env, kMailboxNameColumnName, &m_mailboxNameColumnToken); + + store->StringToToken(env, kImapUidValidityColumnName, &m_imapUidValidityColumnToken); + store->StringToToken(env, kTotalPendingMessagesColumnName, &m_totalPendingMessagesColumnToken); + store->StringToToken(env, kUnreadPendingMessagesColumnName, &m_unreadPendingMessagesColumnToken); + m_mdbTokensInitialized = PR_TRUE; + } + return ret; +} + void nsDBFolderInfo::SetHighWater(MessageKey highWater, PRBool force /* = FALSE */) { - + if (force || m_highWaterMessageKey < highWater) + { + m_highWaterMessageKey = highWater; + } } MessageKey nsDBFolderInfo::GetHighWater() { - return m_articleNumHighWater; + return m_highWaterMessageKey; } void nsDBFolderInfo::SetExpiredMark(MessageKey expiredKey) @@ -161,10 +224,12 @@ void nsDBFolderInfo::RemoveLateredAt(PRInt32 laterIndex) void nsDBFolderInfo::SetMailboxName(const char *newBoxName) { + m_mailboxName = newBoxName; } void nsDBFolderInfo::GetMailboxName(nsString &boxName) { + boxName = m_mailboxName; } void nsDBFolderInfo::SetViewType(PRInt32 viewType) @@ -186,17 +251,41 @@ void nsDBFolderInfo::GetSortInfo(nsMsgSortType *type, nsMsgSortOrder *orde) PRInt32 nsDBFolderInfo::ChangeNumNewMessages(PRInt32 delta) { - return 0; + m_numNewMessages += delta; + if (m_numNewMessages < 0) + { +#ifdef DEBUG_bienvenu1 + XP_ASSERT(FALSE); +#endif + m_numNewMessages = 0; + } + return m_numNewMessages; } PRInt32 nsDBFolderInfo::ChangeNumMessages(PRInt32 delta) { - return 0; + m_numMessages += delta; + if (m_numMessages < 0) + { +#ifdef DEBUG_bienvenu + XP_ASSERT(FALSE); +#endif + m_numMessages = 0; + } + return m_numMessages; } PRInt32 nsDBFolderInfo::ChangeNumVisibleMessages(PRInt32 delta) { - return 0; + m_numVisibleMessages += delta; + if (m_numVisibleMessages < 0) + { +#ifdef DEBUG_bienvenu + XP_ASSERT(FALSE); +#endif + m_numVisibleMessages = 0; + } + return m_numVisibleMessages; } PRInt32 nsDBFolderInfo::GetNumNewMessages() @@ -216,24 +305,30 @@ PRInt32 nsDBFolderInfo::GetNumVisibleMessages() PRInt32 nsDBFolderInfo::GetFlags() { - return 0; + return m_flags; } void nsDBFolderInfo::SetFlags(PRInt32 flags) { + if (m_flags != flags) + { + m_flags = flags; + } } void nsDBFolderInfo::OrFlags(PRInt32 flags) { + m_flags |= flags; } void nsDBFolderInfo::AndFlags(PRInt32 flags) { + m_flags &= flags; } PRBool nsDBFolderInfo::TestFlag(PRInt32 flags) { - return PR_FALSE; + return (m_flags & flags) != 0; } PRInt16 nsDBFolderInfo::GetCSID() @@ -284,7 +379,7 @@ PRInt32 nsDBFolderInfo::GetImapUidValidity() void nsDBFolderInfo::SetImapUidValidity(PRInt32 uidValidity) { - m_ImapUidValidity=uidValidity; + m_ImapUidValidity = uidValidity; } MessageKey nsDBFolderInfo::GetLastMessageLoaded() @@ -299,8 +394,33 @@ void nsDBFolderInfo::SetLastMessageLoaded(MessageKey lastLoaded) // get arbitrary property, aka row cell value. -nsresult nsDBFolderInfo::GetProperty(const char *propertyName, nsString &resultProperty) +nsresult nsDBFolderInfo::GetProperty(const char *propertyName, nsString &resultProperty) { - return NS_OK; + nsresult err = NS_OK; + mdb_token property_token; + + err = m_mdb->GetStore()->StringToToken(m_mdb->GetEnv(), propertyName, &property_token); + if (err == NS_OK) + err = m_mdb->RowCellColumnTonsString(m_mdbRow, property_token, resultProperty); + + return err; } +nsresult nsDBFolderInfo::SetProperty(const char *propertyName, nsString &propertyStr) +{ + nsresult err = NS_OK; + mdb_token property_token; + + err = m_mdb->GetStore()->StringToToken(m_mdb->GetEnv(), propertyName, &property_token); + if (err == NS_OK) + { + struct mdbYarn yarn; + + yarn.mYarn_Grow = NULL; + err = m_mdbRow->AddColumn(m_mdb->GetEnv(), property_token, m_mdb->nsStringToYarn(&yarn, &propertyStr)); + delete[] yarn.mYarn_Buf; // won't need this when we have nsCString + } + return err; +} + + diff --git a/mailnews/db/msgdb/src/nsMailDatabase.cpp b/mailnews/db/msgdb/src/nsMailDatabase.cpp index a876340b1c9..68e0b4e4bdd 100644 --- a/mailnews/db/msgdb/src/nsMailDatabase.cpp +++ b/mailnews/db/msgdb/src/nsMailDatabase.cpp @@ -141,6 +141,12 @@ nsresult nsMailDatabase::OnNewPath (nsFilePath &newPath) nsresult nsMailDatabase::DeleteMessages(nsMsgKeyArray &messageKeys, ChangeListener *instigator) { nsresult ret = NS_OK; + m_folderFile = PR_Open(m_dbName, PR_RDWR, 0); + ret = nsMsgDatabase::DeleteMessages(messageKeys, instigator); + if (m_folderFile) + PR_Close(m_folderFile); + m_folderFile = NULL; + SetFolderInfoValid(m_dbName, 0, 0); return ret; } diff --git a/mailnews/db/msgdb/src/nsMsgDatabase.cpp b/mailnews/db/msgdb/src/nsMsgDatabase.cpp index 9727ae14fd5..b05c49ee62b 100644 --- a/mailnews/db/msgdb/src/nsMsgDatabase.cpp +++ b/mailnews/db/msgdb/src/nsMsgDatabase.cpp @@ -469,6 +469,25 @@ nsresult nsMsgDatabase::ListDone(ListContext *pContext) return err; } +nsresult nsMsgDatabase::ListAllKeys(nsMsgKeyArray &outputKeys) +{ + nsresult err = NS_OK; + mdbTableRowCursor *rowCursor; + err = m_mdbAllMsgHeadersTable->GetTableRowCursor(GetEnv(), -1, &rowCursor); + while (err == NS_OK) + { + mdbOid outOid; + mdb_pos outPos; + + err = rowCursor->NextRowOid(GetEnv(), &outOid, &outPos); + if (outPos < 0) // is this right? + break; + if (err == NS_OK) + outputKeys.Add(outOid.mOid_Id); + } + return err; +} + nsresult nsMsgDatabase::CreateNewHdr(PRBool *newThread, MessageHdrStruct *hdrStruct, nsMsgHdr **pnewHdr, PRBool notify /* = FALSE */) { nsresult err = NS_OK; @@ -532,23 +551,25 @@ nsresult nsMsgDatabase::GetMsgHdrStructFromnsMsgHdr(nsMsgHdr *msgHdr, MessageHdr { nsresult err = NS_OK; - err = HdrCellColumnTonsString(msgHdr, m_subjectColumnToken, hdrStruct.m_subject); - err = HdrCellColumnTonsString(msgHdr, m_senderColumnToken, hdrStruct.m_author); - err = HdrCellColumnTonsString(msgHdr, m_messageIdColumnToken, hdrStruct.m_messageId); - err = HdrCellColumnTonsString(msgHdr, m_referencesColumnToken, hdrStruct.m_references); - err = HdrCellColumnTonsString(msgHdr, m_recipientsColumnToken, hdrStruct.m_recipients); - err = HdrCellColumnToUInt32(msgHdr, m_messageSizeColumnToken, &hdrStruct.m_messageSize); - hdrStruct.m_messageKey = msgHdr->GetMessageKey(); + if (nsMsgHdr) + { + err = RowCellColumnTonsString(msgHdr->GetMDBRow(), m_subjectColumnToken, hdrStruct.m_subject); + err = RowCellColumnTonsString(msgHdr->GetMDBRow(), m_senderColumnToken, hdrStruct.m_author); + err = RowCellColumnTonsString(msgHdr->GetMDBRow(), m_messageIdColumnToken, hdrStruct.m_messageId); + err = RowCellColumnTonsString(msgHdr->GetMDBRow(), m_referencesColumnToken, hdrStruct.m_references); + err = RowCellColumnTonsString(msgHdr->GetMDBRow(), m_recipientsColumnToken, hdrStruct.m_recipients); + err = RowCellColumnToUInt32(msgHdr->GetMDBRow(), m_messageSizeColumnToken, &hdrStruct.m_messageSize); + hdrStruct.m_messageKey = msgHdr->GetMessageKey(); + } return err; } -nsresult nsMsgDatabase::HdrCellColumnTonsString(nsMsgHdr *msgHdr, mdb_token columnToken, nsString &resultStr) +nsresult nsMsgDatabase::RowCellColumnTonsString(mdbRow *hdrRow, mdb_token columnToken, nsString &resultStr) { nsresult err = NS_OK; - mdbRow *hdrRow = msgHdr->GetMDBRow(); mdbCell *hdrCell; - err = hdrRow->GetCell(GetEnv(), m_subjectColumnToken, &hdrCell); + err = hdrRow->GetCell(GetEnv(), columnToken, &hdrCell); if (err == NS_OK) { struct mdbYarn yarn; @@ -558,13 +579,12 @@ nsresult nsMsgDatabase::HdrCellColumnTonsString(nsMsgHdr *msgHdr, mdb_token colu return err; } -nsresult nsMsgDatabase::HdrCellColumnToUInt32(nsMsgHdr *msgHdr, mdb_token columnToken, PRUint32 *uint32Result) +nsresult nsMsgDatabase::RowCellColumnToUInt32(mdbRow *hdrRow, mdb_token columnToken, PRUint32 *uint32Result) { nsresult err = NS_OK; mdbCell *hdrCell; - mdbRow *hdrRow = msgHdr->GetMDBRow(); - err = hdrRow->GetCell(GetEnv(), m_subjectColumnToken, &hdrCell); + err = hdrRow->GetCell(GetEnv(), columnToken, &hdrCell); if (err == NS_OK) { struct mdbYarn yarn; @@ -603,3 +623,13 @@ nsresult nsMsgDatabase::HdrCellColumnToUInt32(nsMsgHdr *msgHdr, mdb_token column *i = XP_STRTOUL((char *) yarn->mYarn_Buf, &endPtr, yarn->mYarn_Fill); } +nsresult nsMsgDatabase::SetSummaryValid(PRBool valid /* = TRUE */) +{ + // setting the version to -1 ought to make it pretty invalid. + if (!valid) + m_dbFolderInfo->SetVersion(-1); + + // for default db (and news), there's no nothing to set to make it it valid + return NS_OK; +} + diff --git a/mailnews/db/msgdb/src/nsMsgHdr.cpp b/mailnews/db/msgdb/src/nsMsgHdr.cpp index 1b82dc2c9d0..0d46da1747e 100644 --- a/mailnews/db/msgdb/src/nsMsgHdr.cpp +++ b/mailnews/db/msgdb/src/nsMsgHdr.cpp @@ -80,9 +80,33 @@ MessageKey nsMsgHdr::GetMessageKey() nsresult nsMsgHdr::GetProperty(const char *propertyName, nsString &resultProperty) { nsresult err = NS_OK; + mdb_token property_token; + + err = m_mdb->GetStore()->StringToToken(m_mdb->GetEnv(), propertyName, &property_token); + if (err == NS_OK) + err = m_mdb->RowCellColumnTonsString(GetMDBRow(), property_token, resultProperty); + return err; } +nsresult nsMsgHdr::SetProperty(const char *propertyName, nsString &propertyStr) +{ + nsresult err = NS_OK; + mdb_token property_token; + + err = m_mdb->GetStore()->StringToToken(m_mdb->GetEnv(), propertyName, &property_token); + if (err == NS_OK) + { + struct mdbYarn yarn; + + yarn.mYarn_Grow = NULL; + err = m_mdbRow->AddColumn(m_mdb->GetEnv(), property_token, m_mdb->nsStringToYarn(&yarn, &propertyStr)); + delete[] yarn.mYarn_Buf; // won't need this when we have nsCString + } + return err; +} + + uint16 nsMsgHdr::GetNumReferences() { return 0;