Back to index

lightning-sunbird  0.9+nobinonly
nsMsgDatabase.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef _nsMsgDatabase_H_
00039 #define _nsMsgDatabase_H_
00040 
00041 #include "nsIMsgDatabase.h"
00042 #include "nsMsgHdr.h"
00043 #include "nsVoidArray.h"
00044 #include "nsString.h"
00045 #include "nsFileSpec.h"
00046 #include "nsIDBChangeListener.h"
00047 #include "nsIDBChangeAnnouncer.h"
00048 #include "nsMsgMessageFlags.h"
00049 #include "nsIMsgFolder.h"
00050 #include "nsISupportsArray.h"
00051 #include "nsDBFolderInfo.h"
00052 #include "nsICollation.h"
00053 #include "nsIMimeConverter.h"
00054 #include "nsCOMPtr.h"
00055 #include "nsCOMArray.h"
00056 #include "nsHashtable.h"
00057 #include "pldhash.h"
00058 class ListContext;
00059 class nsMsgKeyArray;
00060 class nsMsgKeySet;
00061 class nsMsgThread;
00062 class nsIMsgThread;
00063 class nsIDBFolderInfo;
00064 class nsIMsgHeaderParser;
00065 
00066 const PRInt32 kMsgDBVersion = 1;
00067 
00068 class nsMsgDBService : public nsIMsgDBService
00069 {
00070 public:
00071   NS_DECL_ISUPPORTS
00072   NS_DECL_NSIMSGDBSERVICE
00073 
00074   nsMsgDBService();
00075   ~nsMsgDBService();
00076 protected:
00077   nsCOMArray <nsIMsgFolder> m_foldersPendingListeners;
00078   nsCOMArray <nsIDBChangeListener> m_pendingListeners;
00079 };
00080 
00081 class nsMsgDatabase : public nsIMsgDatabase 
00082 {
00083 public:
00084   friend class nsMsgDBService;
00085 
00086   NS_DECL_ISUPPORTS
00087   NS_DECL_NSIDBCHANGEANNOUNCER
00088   NS_DECL_NSIMSGDATABASE
00089 
00090   virtual nsresult IsHeaderRead(nsIMsgDBHdr *hdr, PRBool *pRead);
00091   virtual nsresult MarkHdrReadInDB(nsIMsgDBHdr *msgHdr, PRBool bRead,
00092                                nsIDBChangeListener *instigator);
00093   virtual nsresult OpenMDB(const char *dbName, PRBool create);
00094   virtual nsresult CloseMDB(PRBool commit);
00095   virtual nsresult CreateMsgHdr(nsIMdbRow* hdrRow, nsMsgKey key, nsIMsgDBHdr **result);
00096   virtual nsresult GetThreadForMsgKey(nsMsgKey msgKey, nsIMsgThread **result);
00097   virtual nsresult EnumerateMessagesWithFlag(nsISimpleEnumerator* *result, PRUint32 *pFlag);
00098   nsresult         GetSearchResultsTable(const char *searchFolderUri, PRBool createIfMissing, nsIMdbTable **table);
00099 
00100   // this might just be for debugging - we'll see.
00101   nsresult ListAllThreads(nsMsgKeyArray *threadIds);
00103   // nsMsgDatabase methods:
00104   nsMsgDatabase();
00105   virtual ~nsMsgDatabase();
00106 
00107 
00108   static nsIMdbFactory  *GetMDBFactory();
00109   nsIMdbEnv             *GetEnv() {return m_mdbEnv;}
00110   nsIMdbStore           *GetStore() {return m_mdbStore;}
00111   virtual PRUint32      GetCurVersion();
00112   nsIMsgHeaderParser    *GetHeaderParser();
00113   nsresult              GetCollationKeyGenerator();
00114   nsIMimeConverter *    GetMimeConverter();
00115 
00116   nsresult GetTableCreateIfMissing(const char *scope, const char *kind, nsIMdbTable **table, 
00117                                    mdb_token &scopeToken, mdb_token &kindToken);
00118 
00119   static nsMsgDatabase* FindInCache(nsFileSpec &dbName);
00120   static nsIMsgDatabase* FindInCache(nsIMsgFolder *folder);
00121 
00122   //helper function to fill in nsStrings from hdr row cell contents.
00123   nsresult RowCellColumnTonsString(nsIMdbRow *row, mdb_token columnToken, nsAString &resultStr);
00124   nsresult RowCellColumnToUInt32(nsIMdbRow *row, mdb_token columnToken, PRUint32 *uint32Result, PRUint32 defaultValue = 0);
00125   nsresult RowCellColumnToUInt32(nsIMdbRow *row, mdb_token columnToken, PRUint32 &uint32Result, PRUint32 defaultValue = 0);
00126   nsresult RowCellColumnToMime2DecodedString(nsIMdbRow *row, mdb_token columnToken, PRUnichar **);
00127   nsresult RowCellColumnToCollationKey(nsIMdbRow *row, mdb_token columnToken, PRUint8 **result, PRUint32 *len);
00128   nsresult RowCellColumnToConstCharPtr(nsIMdbRow *row, mdb_token columnToken, const char **ptr);
00129   nsresult RowCellColumnToAddressCollationKey(nsIMdbRow *row, mdb_token colToken, PRUint8 **result, PRUint32 *len);
00130 
00131   // these methods take the property name as a string, not a token.
00132   // they should be used when the properties aren't accessed a lot
00133   nsresult        GetProperty(nsIMdbRow *row, const char *propertyName, char **result);
00134   nsresult        SetProperty(nsIMdbRow *row, const char *propertyName, const char *propertyVal);
00135   nsresult        GetPropertyAsNSString(nsIMdbRow *row, const char *propertyName, nsAString &result);
00136   nsresult        SetPropertyFromNSString(nsIMdbRow *row, const char *propertyName, const nsAString &propertyVal);
00137   nsresult        GetUint32Property(nsIMdbRow *row, const char *propertyName, PRUint32 *result, PRUint32 defaultValue = 0);
00138   nsresult        SetUint32Property(nsIMdbRow *row, const char *propertyName, PRUint32 propertyVal);
00139   // helper function for once we have the token.
00140   nsresult        SetNSStringPropertyWithToken(nsIMdbRow *row, mdb_token aProperty, const nsAString &propertyStr);
00141   
00142   // helper functions to put values in cells for the passed-in row
00143   nsresult        UInt32ToRowCellColumn(nsIMdbRow *row, mdb_token columnToken, PRUint32 value);
00144   nsresult        CharPtrToRowCellColumn(nsIMdbRow *row, mdb_token columnToken, const char *charPtr);
00145   nsresult        RowCellColumnToCharPtr(nsIMdbRow *row, mdb_token columnToken, char **result);
00146   
00147   
00148   // helper functions to copy an nsString to a yarn, int32 to yarn, and vice versa.
00149   static struct mdbYarn *nsStringToYarn(struct mdbYarn *yarn, const nsAString &str);
00150   static struct mdbYarn *UInt32ToYarn(struct mdbYarn *yarn, PRUint32 i);
00151   static void YarnTonsString(struct mdbYarn *yarn, nsAString &str);
00152   static void YarnTonsCString(struct mdbYarn *yarn, nsACString &str);
00153   static void YarnToUInt32(struct mdbYarn *yarn, PRUint32 *i);
00154   
00155   static void   CleanupCache();
00156 #ifdef DEBUG
00157   static int    GetNumInCache(void) {return(GetDBCache()->Count());}
00158   static void   DumpCache();
00159   virtual nsresult DumpContents();
00160   nsresult DumpThread(nsMsgKey threadId);
00161   nsresult DumpMsgChildren(nsIMsgDBHdr *msgHdr);
00162 #endif
00163   
00164   friend class nsMsgHdr;    // use this to get access to cached tokens for hdr fields
00165   friend class nsMsgThread; // use this to get access to cached tokens for hdr fields
00166   friend class nsMsgDBEnumerator;
00167   friend class nsMsgDBThreadEnumerator;
00168 protected:
00169   // prefs stuff - in future, we might want to cache the prefs interface
00170   nsresult        GetBoolPref(const char *prefName, PRBool *result);
00171   nsresult        GetIntPref(const char *prefName, PRInt32 *result);
00172   virtual void    GetGlobalPrefs();
00173     // retrieval methods
00174   nsIMsgThread *  GetThreadForReference(nsCString &msgID, nsIMsgDBHdr **pMsgHdr);
00175   nsIMsgThread *  GetThreadForSubject(nsCString &subject);
00176   nsIMsgThread *  GetThreadForThreadId(nsMsgKey threadId);
00177   nsMsgHdr     *  GetMsgHdrForReference(nsCString &reference);
00178   nsIMsgDBHdr  *  GetMsgHdrForSubject(nsCString &msgID);
00179   // threading interfaces
00180   virtual nsresult CreateNewThread(nsMsgKey key, const char *subject, nsMsgThread **newThread);
00181   virtual PRBool  ThreadBySubjectWithoutRe();
00182   virtual PRBool  UseStrictThreading();
00183   virtual nsresult ThreadNewHdr(nsMsgHdr* hdr, PRBool &newThread);
00184   virtual nsresult AddNewThread(nsMsgHdr *msgHdr);
00185   virtual nsresult AddToThread(nsMsgHdr *newHdr, nsIMsgThread *thread, nsIMsgDBHdr *pMsgHdr, PRBool threadInThread);
00186   
00187   
00188   // open db cache
00189   static void        AddToCache(nsMsgDatabase* pMessageDB) 
00190   {GetDBCache()->AppendElement(pMessageDB);}
00191   static void        RemoveFromCache(nsMsgDatabase* pMessageDB);
00192   static int         FindInCache(nsMsgDatabase* pMessageDB);
00193   PRBool      MatchDbName(nsFileSpec &dbName);   // returns TRUE if they match
00194   
00195 #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
00196   static void        UnixToNative(char*& ioPath);
00197 #endif
00198   
00199   // Flag handling routines
00200   virtual nsresult SetKeyFlag(nsMsgKey key, PRBool set, PRUint32 flag,
00201                               nsIDBChangeListener *instigator = NULL);
00202   virtual nsresult SetMsgHdrFlag(nsIMsgDBHdr *msgHdr, PRBool set, PRUint32 flag, 
00203                                  nsIDBChangeListener *instigator);
00204   
00205   virtual PRBool  SetHdrFlag(nsIMsgDBHdr *, PRBool bSet, MsgFlags flag);
00206   virtual PRBool  SetHdrReadFlag(nsIMsgDBHdr *, PRBool pRead);
00207   virtual PRUint32 GetStatusFlags(nsIMsgDBHdr *msgHdr, PRUint32 origFlags);
00208   // helper function which doesn't involve thread object
00209   
00210   virtual nsresult RemoveHeaderFromDB(nsMsgHdr *msgHdr);
00211   virtual nsresult RemoveHeaderFromThread(nsMsgHdr *msgHdr);
00212   virtual nsresult AdjustExpungedBytesOnDelete(nsIMsgDBHdr *msgHdr);
00213   
00214   
00215   static nsVoidArray/*<nsMsgDatabase>*/* GetDBCache();
00216   static nsVoidArray/*<nsMsgDatabase>*/* m_dbCache;
00217   
00218   nsCOMPtr <nsICollation> m_collationKeyGenerator;
00219   nsCOMPtr <nsIMimeConverter> m_mimeConverter;
00220   nsCOMPtr <nsIMsgRetentionSettings> m_retentionSettings;
00221   nsCOMPtr <nsIMsgDownloadSettings> m_downloadSettings;
00222 
00223   nsresult PurgeMessagesOlderThan(PRUint32 daysToKeepHdrs, PRBool keepUnreadMessagesOnly,
00224                                   nsISupportsArray *hdrsToDelete);
00225   nsresult PurgeExcessMessages(PRUint32 numHeadersToKeep, PRBool keepUnreadMessagesOnly,
00226                                nsISupportsArray *hdrsToDelete);
00227   
00228   // mdb bookkeeping stuff
00229   virtual nsresult                 InitExistingDB();
00230   virtual nsresult                 InitNewDB();
00231   virtual nsresult                 InitMDBInfo();
00232   
00233   nsCOMPtr <nsIMsgFolder> m_folder;
00234   nsDBFolderInfo      *m_dbFolderInfo;
00235   nsMsgKey      m_nextPseudoMsgKey;
00236   nsIMdbEnv     *m_mdbEnv;  // to be used in all the db calls.
00237   nsIMdbStore   *m_mdbStore;
00238   nsIMdbTable   *m_mdbAllMsgHeadersTable;
00239   nsIMdbTable   *m_mdbAllThreadsTable;
00240   nsFileSpec    m_dbName;
00241   nsMsgKeyArray m_newSet;   // new messages since last open.
00242   PRBool        m_mdbTokensInitialized;
00243   nsCOMPtr <nsISupportsArray>  m_ChangeListeners;
00244   mdb_token     m_hdrRowScopeToken;
00245   mdb_token     m_threadRowScopeToken;
00246   mdb_token     m_hdrTableKindToken;
00247   mdb_token     m_threadTableKindToken;
00248   mdb_token     m_allThreadsTableKindToken;
00249   mdb_token     m_subjectColumnToken;
00250   mdb_token     m_senderColumnToken;
00251   mdb_token     m_messageIdColumnToken;
00252   mdb_token     m_referencesColumnToken;
00253   mdb_token     m_recipientsColumnToken;
00254   mdb_token     m_dateColumnToken;
00255   mdb_token     m_messageSizeColumnToken;
00256   mdb_token     m_flagsColumnToken;
00257   mdb_token     m_priorityColumnToken;
00258   mdb_token     m_labelColumnToken;
00259   mdb_token     m_statusOffsetColumnToken;
00260   mdb_token     m_numLinesColumnToken;
00261   mdb_token     m_ccListColumnToken;
00262   mdb_token     m_threadFlagsColumnToken;
00263   mdb_token     m_threadIdColumnToken;
00264   mdb_token     m_threadChildrenColumnToken;
00265   mdb_token     m_threadUnreadChildrenColumnToken;
00266   mdb_token     m_messageThreadIdColumnToken;
00267   mdb_token     m_threadSubjectColumnToken;
00268   mdb_token     m_numReferencesColumnToken;
00269   mdb_token     m_messageCharSetColumnToken;
00270   mdb_token     m_threadParentColumnToken;
00271   mdb_token     m_threadRootKeyColumnToken;
00272   mdb_token     m_threadNewestMsgDateColumnToken;
00273   mdb_token     m_offlineMsgOffsetColumnToken;
00274   mdb_token     m_offlineMessageSizeColumnToken;
00275   nsIMsgHeaderParser *m_HeaderParser;
00276   
00277   // header caching stuff - MRU headers, keeps them around in memory
00278   nsresult      GetHdrFromCache(nsMsgKey key, nsIMsgDBHdr* *result);
00279   nsresult      AddHdrToCache(nsIMsgDBHdr *hdr, nsMsgKey key);
00280   nsresult      ClearHdrCache(PRBool reInit);
00281   nsresult      RemoveHdrFromCache(nsIMsgDBHdr *hdr, nsMsgKey key);
00282   // all headers currently instantiated, doesn't hold refs
00283   // these get added when msg hdrs get constructed, and removed when they get destroyed.
00284   nsresult      GetHdrFromUseCache(nsMsgKey key, nsIMsgDBHdr* *result);
00285   nsresult      AddHdrToUseCache(nsIMsgDBHdr *hdr, nsMsgKey key); 
00286   nsresult      ClearUseHdrCache();
00287   nsresult      RemoveHdrFromUseCache(nsIMsgDBHdr *hdr, nsMsgKey key);
00288   
00289   mdb_pos       FindInsertIndexInSortedTable(nsIMdbTable *table, mdb_id idToInsert);
00290 
00291   void          ClearCachedObjects(PRBool dbGoingAway);
00292   // all instantiated headers, but doesn't hold refs. 
00293   PLDHashTable  *m_headersInUse;
00294   static const void* PR_CALLBACK GetKey(PLDHashTable* aTable, PLDHashEntryHdr* aEntry);
00295   static PLDHashNumber PR_CALLBACK HashKey(PLDHashTable* aTable, const void* aKey);
00296   static PRBool PR_CALLBACK MatchEntry(PLDHashTable* aTable, const PLDHashEntryHdr* aEntry, const void* aKey);
00297   static void PR_CALLBACK MoveEntry(PLDHashTable* aTable, const PLDHashEntryHdr* aFrom, PLDHashEntryHdr* aTo);
00298   static void PR_CALLBACK ClearEntry(PLDHashTable* aTable, PLDHashEntryHdr* aEntry);
00299   static PLDHashOperator PR_CALLBACK HeaderEnumerator (PLDHashTable *table, PLDHashEntryHdr *hdr,
00300                                PRUint32 number, void *arg);
00301   static PLDHashOperator PR_CALLBACK ClearHeaderEnumerator (PLDHashTable *table, PLDHashEntryHdr *hdr,
00302                                PRUint32 number, void *arg);
00303   static PLDHashTableOps gMsgDBHashTableOps;
00304   struct MsgHdrHashElement {
00305     PLDHashEntryHdr mHeader;
00306     nsMsgKey       mKey;
00307     nsIMsgDBHdr     *mHdr;
00308   };
00309   PLDHashTable  *m_cachedHeaders;
00310   PRBool                           m_bCacheHeaders;
00311   nsMsgKey  m_cachedThreadId;
00312   nsCOMPtr <nsIMsgThread> m_cachedThread;
00313 
00314 private:
00315   PRUint32 m_cacheSize;
00316 };
00317 
00318 class nsMsgRetentionSettings : public nsIMsgRetentionSettings
00319 {
00320 public:
00321   nsMsgRetentionSettings();
00322   virtual ~nsMsgRetentionSettings();
00323 
00324   NS_DECL_ISUPPORTS
00325   NS_DECL_NSIMSGRETENTIONSETTINGS
00326 protected:
00327   nsMsgRetainByPreference m_retainByPreference;
00328   PRUint32                m_daysToKeepHdrs;
00329   PRUint32                m_numHeadersToKeep;
00330   PRUint32                m_keepUnreadMessagesProp;
00331   PRBool                  m_keepUnreadMessagesOnly;
00332   PRBool                  m_useServerDefaults;
00333   PRBool                  m_cleanupBodiesByDays;
00334   PRUint32                m_daysToKeepBodies;
00335 };
00336 
00337 class nsMsgDownloadSettings : public nsIMsgDownloadSettings
00338 {
00339 public:
00340   nsMsgDownloadSettings();
00341   virtual ~nsMsgDownloadSettings();
00342 
00343   NS_DECL_ISUPPORTS
00344   NS_DECL_NSIMSGDOWNLOADSETTINGS
00345 protected:
00346   PRBool m_useServerDefaults;
00347   PRBool m_downloadUnreadOnly;
00348   PRBool m_downloadByDate;
00349   PRInt32 m_ageLimitOfMsgsToDownload;
00350 };
00351 
00352 #endif