/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #ifndef _nsMsgDatabase_H_ #define _nsMsgDatabase_H_ #include "nsIMsgDatabase.h" #include "nsMsgHdr.h" #include "nsVoidArray.h" #include "nsString.h" #include "nsFileSpec.h" #include "nsIDBChangeListener.h" #include "nsIDBChangeAnnouncer.h" #include "nsMsgMessageFlags.h" #include "nsIMsgFolder.h" #include "nsISupportsArray.h" #include "nsDBFolderInfo.h" #include "nsICollation.h" #include "nsIMimeConverter.h" #include "nsCOMPtr.h" #include "nsCOMArray.h" #include "nsHashtable.h" #include "pldhash.h" class ListContext; class nsMsgKeyArray; class nsMsgKeySet; class nsMsgThread; class nsIMsgThread; class nsIDBFolderInfo; class nsIMsgHeaderParser; const PRInt32 kMsgDBVersion = 1; class nsMsgDBService : public nsIMsgDBService { public: NS_DECL_ISUPPORTS NS_DECL_NSIMSGDBSERVICE nsMsgDBService(); ~nsMsgDBService(); protected: nsCOMArray m_foldersPendingListeners; nsCOMArray m_pendingListeners; }; class nsMsgDatabase : public nsIMsgDatabase { public: friend class nsMsgDBService; NS_DECL_ISUPPORTS NS_DECL_NSIDBCHANGEANNOUNCER NS_DECL_NSIMSGDATABASE virtual nsresult IsHeaderRead(nsIMsgDBHdr *hdr, PRBool *pRead); virtual nsresult MarkHdrReadInDB(nsIMsgDBHdr *msgHdr, PRBool bRead, nsIDBChangeListener *instigator); virtual nsresult OpenMDB(const char *dbName, PRBool create); virtual nsresult CloseMDB(PRBool commit); virtual nsresult CreateMsgHdr(nsIMdbRow* hdrRow, nsMsgKey key, nsIMsgDBHdr **result); virtual nsresult GetThreadForMsgKey(nsMsgKey msgKey, nsIMsgThread **result); virtual nsresult EnumerateMessagesWithFlag(nsISimpleEnumerator* *result, PRUint32 *pFlag); nsresult GetSearchResultsTable(const char *searchFolderUri, PRBool createIfMissing, nsIMdbTable **table); // this might just be for debugging - we'll see. nsresult ListAllThreads(nsMsgKeyArray *threadIds); ////////////////////////////////////////////////////////////////////////////// // nsMsgDatabase methods: nsMsgDatabase(); virtual ~nsMsgDatabase(); static nsIMdbFactory *GetMDBFactory(); nsIMdbEnv *GetEnv() {return m_mdbEnv;} nsIMdbStore *GetStore() {return m_mdbStore;} virtual PRUint32 GetCurVersion(); nsIMsgHeaderParser *GetHeaderParser(); nsresult GetCollationKeyGenerator(); nsIMimeConverter * GetMimeConverter(); nsresult GetTableCreateIfMissing(const char *scope, const char *kind, nsIMdbTable **table, mdb_token &scopeToken, mdb_token &kindToken); static nsMsgDatabase* FindInCache(nsFileSpec &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, PRUint32 *uint32Result, PRUint32 defaultValue = 0); nsresult RowCellColumnToUInt32(nsIMdbRow *row, mdb_token columnToken, PRUint32 &uint32Result, PRUint32 defaultValue = 0); nsresult RowCellColumnToMime2DecodedString(nsIMdbRow *row, mdb_token columnToken, PRUnichar **); nsresult RowCellColumnToCollationKey(nsIMdbRow *row, mdb_token columnToken, PRUint8 **result, PRUint32 *len); nsresult RowCellColumnToConstCharPtr(nsIMdbRow *row, mdb_token columnToken, const char **ptr); nsresult RowCellColumnToAddressCollationKey(nsIMdbRow *row, mdb_token colToken, PRUint8 **result, PRUint32 *len); // these methods take the property name as a string, not a token. // they should be used when the properties aren't accessed a lot nsresult GetProperty(nsIMdbRow *row, const char *propertyName, char **result); nsresult SetProperty(nsIMdbRow *row, const char *propertyName, const char *propertyVal); nsresult GetPropertyAsNSString(nsIMdbRow *row, const char *propertyName, nsAString &result); nsresult SetPropertyFromNSString(nsIMdbRow *row, const char *propertyName, const nsAString &propertyVal); nsresult GetUint32Property(nsIMdbRow *row, const char *propertyName, PRUint32 *result, PRUint32 defaultValue = 0); nsresult SetUint32Property(nsIMdbRow *row, const char *propertyName, PRUint32 propertyVal); // helper function for once we have the token. nsresult SetNSStringPropertyWithToken(nsIMdbRow *row, mdb_token aProperty, const nsAString &propertyStr); // helper functions to put values in cells for the passed-in row nsresult UInt32ToRowCellColumn(nsIMdbRow *row, mdb_token columnToken, PRUint32 value); nsresult CharPtrToRowCellColumn(nsIMdbRow *row, mdb_token columnToken, const char *charPtr); nsresult RowCellColumnToCharPtr(nsIMdbRow *row, mdb_token columnToken, char **result); // helper functions to copy an nsString to a yarn, int32 to yarn, and vice versa. static struct mdbYarn *nsStringToYarn(struct mdbYarn *yarn, const nsAString &str); static struct mdbYarn *UInt32ToYarn(struct mdbYarn *yarn, PRUint32 i); static void YarnTonsString(struct mdbYarn *yarn, nsAString &str); static void YarnTonsCString(struct mdbYarn *yarn, nsACString &str); static void YarnToUInt32(struct mdbYarn *yarn, PRUint32 *i); static void CleanupCache(); #ifdef DEBUG static int GetNumInCache(void) {return(GetDBCache()->Count());} static void DumpCache(); virtual nsresult DumpContents(); nsresult DumpThread(nsMsgKey threadId); nsresult DumpMsgChildren(nsIMsgDBHdr *msgHdr); #endif friend class nsMsgHdr; // use this to get access to cached tokens for hdr fields friend class nsMsgThread; // use this to get access to cached tokens for hdr fields friend class nsMsgDBEnumerator; friend class nsMsgDBThreadEnumerator; protected: // prefs stuff - in future, we might want to cache the prefs interface nsresult GetBoolPref(const char *prefName, PRBool *result); nsresult GetIntPref(const char *prefName, PRInt32 *result); virtual void GetGlobalPrefs(); // retrieval methods nsIMsgThread * GetThreadForReference(nsCString &msgID, nsIMsgDBHdr **pMsgHdr); nsIMsgThread * GetThreadForSubject(nsCString &subject); nsIMsgThread * GetThreadForThreadId(nsMsgKey threadId); nsMsgHdr * GetMsgHdrForReference(nsCString &reference); nsIMsgDBHdr * GetMsgHdrForSubject(nsCString &msgID); // threading interfaces virtual nsresult CreateNewThread(nsMsgKey key, const char *subject, nsMsgThread **newThread); virtual PRBool ThreadBySubjectWithoutRe(); virtual PRBool UseStrictThreading(); virtual nsresult ThreadNewHdr(nsMsgHdr* hdr, PRBool &newThread); virtual nsresult AddNewThread(nsMsgHdr *msgHdr); virtual nsresult AddToThread(nsMsgHdr *newHdr, nsIMsgThread *thread, nsIMsgDBHdr *pMsgHdr, PRBool threadInThread); // open db cache static void AddToCache(nsMsgDatabase* pMessageDB) {GetDBCache()->AppendElement(pMessageDB);} static void RemoveFromCache(nsMsgDatabase* pMessageDB); static int FindInCache(nsMsgDatabase* pMessageDB); PRBool MatchDbName(nsFileSpec &dbName); // returns TRUE if they match #if defined(XP_WIN) || defined(XP_OS2) || defined(XP_MAC) // this should go away when we can provide our own file stream to MDB/Mork static void UnixToNative(char*& ioPath); #endif // Flag handling routines virtual nsresult SetKeyFlag(nsMsgKey key, PRBool set, PRUint32 flag, nsIDBChangeListener *instigator = NULL); virtual nsresult SetMsgHdrFlag(nsIMsgDBHdr *msgHdr, PRBool set, PRUint32 flag, nsIDBChangeListener *instigator); virtual PRBool SetHdrFlag(nsIMsgDBHdr *, PRBool bSet, MsgFlags flag); virtual PRBool SetHdrReadFlag(nsIMsgDBHdr *, PRBool pRead); virtual PRUint32 GetStatusFlags(nsIMsgDBHdr *msgHdr, PRUint32 origFlags); // helper function which doesn't involve thread object virtual nsresult RemoveHeaderFromDB(nsMsgHdr *msgHdr); virtual nsresult RemoveHeaderFromThread(nsMsgHdr *msgHdr); virtual nsresult AdjustExpungedBytesOnDelete(nsIMsgDBHdr *msgHdr); static nsVoidArray/**/* GetDBCache(); static nsVoidArray/**/* m_dbCache; nsCOMPtr m_collationKeyGenerator; nsCOMPtr m_mimeConverter; nsCOMPtr m_retentionSettings; nsCOMPtr m_downloadSettings; nsresult PurgeMessagesOlderThan(PRUint32 daysToKeepHdrs, PRBool keepUnreadMessagesOnly, nsISupportsArray *hdrsToDelete); nsresult PurgeExcessMessages(PRUint32 numHeadersToKeep, PRBool keepUnreadMessagesOnly, nsISupportsArray *hdrsToDelete); // mdb bookkeeping stuff virtual nsresult InitExistingDB(); virtual nsresult InitNewDB(); virtual nsresult InitMDBInfo(); nsCOMPtr m_folder; nsDBFolderInfo *m_dbFolderInfo; nsMsgKey m_nextPseudoMsgKey; nsIMdbEnv *m_mdbEnv; // to be used in all the db calls. nsIMdbStore *m_mdbStore; nsIMdbTable *m_mdbAllMsgHeadersTable; nsIMdbTable *m_mdbAllThreadsTable; nsFileSpec m_dbName; nsMsgKeyArray m_newSet; // new messages since last open. PRBool m_mdbTokensInitialized; nsCOMPtr m_ChangeListeners; mdb_token m_hdrRowScopeToken; mdb_token m_threadRowScopeToken; mdb_token m_hdrTableKindToken; mdb_token m_threadTableKindToken; mdb_token m_allThreadsTableKindToken; mdb_token m_subjectColumnToken; mdb_token m_senderColumnToken; mdb_token m_messageIdColumnToken; mdb_token m_referencesColumnToken; mdb_token m_recipientsColumnToken; mdb_token m_dateColumnToken; mdb_token m_messageSizeColumnToken; mdb_token m_flagsColumnToken; mdb_token m_priorityColumnToken; mdb_token m_labelColumnToken; mdb_token m_statusOffsetColumnToken; mdb_token m_numLinesColumnToken; mdb_token m_ccListColumnToken; mdb_token m_threadFlagsColumnToken; mdb_token m_threadIdColumnToken; mdb_token m_threadChildrenColumnToken; mdb_token m_threadUnreadChildrenColumnToken; mdb_token m_messageThreadIdColumnToken; mdb_token m_threadSubjectColumnToken; mdb_token m_numReferencesColumnToken; mdb_token m_messageCharSetColumnToken; mdb_token m_threadParentColumnToken; mdb_token m_threadRootKeyColumnToken; mdb_token m_threadNewestMsgDateColumnToken; mdb_token m_offlineMsgOffsetColumnToken; mdb_token m_offlineMessageSizeColumnToken; nsIMsgHeaderParser *m_HeaderParser; // header caching stuff - MRU headers, keeps them around in memory nsresult GetHdrFromCache(nsMsgKey key, nsIMsgDBHdr* *result); nsresult AddHdrToCache(nsIMsgDBHdr *hdr, nsMsgKey key); nsresult ClearHdrCache(PRBool reInit); nsresult RemoveHdrFromCache(nsIMsgDBHdr *hdr, nsMsgKey key); // all headers currently instantiated, doesn't hold refs // these get added when msg hdrs get constructed, and removed when they get destroyed. nsresult GetHdrFromUseCache(nsMsgKey key, nsIMsgDBHdr* *result); nsresult AddHdrToUseCache(nsIMsgDBHdr *hdr, nsMsgKey key); nsresult ClearUseHdrCache(); nsresult RemoveHdrFromUseCache(nsIMsgDBHdr *hdr, nsMsgKey key); mdb_pos FindInsertIndexInSortedTable(nsIMdbTable *table, mdb_id idToInsert); void ClearCachedObjects(PRBool dbGoingAway); // all instantiated headers, but doesn't hold refs. PLDHashTable *m_headersInUse; static const void* PR_CALLBACK GetKey(PLDHashTable* aTable, PLDHashEntryHdr* aEntry); static PLDHashNumber PR_CALLBACK HashKey(PLDHashTable* aTable, const void* aKey); static PRBool PR_CALLBACK MatchEntry(PLDHashTable* aTable, const PLDHashEntryHdr* aEntry, const void* aKey); static void PR_CALLBACK MoveEntry(PLDHashTable* aTable, const PLDHashEntryHdr* aFrom, PLDHashEntryHdr* aTo); static void PR_CALLBACK ClearEntry(PLDHashTable* aTable, PLDHashEntryHdr* aEntry); static PLDHashOperator PR_CALLBACK HeaderEnumerator (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void *arg); static PLDHashOperator PR_CALLBACK ClearHeaderEnumerator (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void *arg); static PLDHashTableOps gMsgDBHashTableOps; struct MsgHdrHashElement { PLDHashEntryHdr mHeader; nsMsgKey mKey; nsIMsgDBHdr *mHdr; }; PLDHashTable *m_cachedHeaders; PRBool m_bCacheHeaders; nsMsgKey m_cachedThreadId; nsCOMPtr m_cachedThread; private: PRUint32 m_cacheSize; }; class nsMsgRetentionSettings : public nsIMsgRetentionSettings { public: nsMsgRetentionSettings(); virtual ~nsMsgRetentionSettings(); NS_DECL_ISUPPORTS NS_DECL_NSIMSGRETENTIONSETTINGS protected: nsMsgRetainByPreference m_retainByPreference; PRUint32 m_daysToKeepHdrs; PRUint32 m_numHeadersToKeep; PRUint32 m_keepUnreadMessagesProp; PRBool m_keepUnreadMessagesOnly; PRBool m_useServerDefaults; PRBool m_cleanupBodiesByDays; PRUint32 m_daysToKeepBodies; }; class nsMsgDownloadSettings : public nsIMsgDownloadSettings { public: nsMsgDownloadSettings(); virtual ~nsMsgDownloadSettings(); NS_DECL_ISUPPORTS NS_DECL_NSIMSGDOWNLOADSETTINGS protected: PRBool m_useServerDefaults; PRBool m_downloadUnreadOnly; PRBool m_downloadByDate; PRInt32 m_ageLimitOfMsgsToDownload; }; #endif