RetroZilla/mailnews/db/msgdb/public/nsMsgDatabase.h
2015-10-20 23:03:22 -04:00

353 lines
15 KiB
C++

/* -*- 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 <nsIMsgFolder> m_foldersPendingListeners;
nsCOMArray <nsIDBChangeListener> 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/*<nsMsgDatabase>*/* GetDBCache();
static nsVoidArray/*<nsMsgDatabase>*/* m_dbCache;
nsCOMPtr <nsICollation> m_collationKeyGenerator;
nsCOMPtr <nsIMimeConverter> m_mimeConverter;
nsCOMPtr <nsIMsgRetentionSettings> m_retentionSettings;
nsCOMPtr <nsIMsgDownloadSettings> 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 <nsIMsgFolder> 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 <nsISupportsArray> 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 <nsIMsgThread> 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