/*
	$Id: CBaseDatabase.h,v 1.1 2003/04/20 23:32:51 dasenbro Exp $

	File:		CBaseDatabase.h

	Contains:	xxx put contents here xxx

	Version:	Apple Mail Server - Mac OS X :  $Revision: 1.1 $

	Written by:	David O'Rourke

	Copyright:	© 1997-2001 by Apple Computer, Inc., all rights reserved.

 	NOT_FOR_OPEN_SOURCE <to be reevaluated at a later time>

	Notes:

		// *********************************************************************************
		// Warning: DO NOT CHANGE/ADD/REMOVE PUBLIC/PRIVATE DATA FIELDS TO THIS CLASS/STRUCT
		// WITHOUT CONSULTING WITH A APPLE MAIL TEAM MEMBER.  CHANGES TO
		// THIS STRUCTURE __WILL__ CAUSE FILE FORMAT COMPATIBILITY ISSUES FOR APPLESHARE IP 5.0
		// AND 6.0 MAIL DATABASES.
		//
		// FAILURE TO HEED THIS WARNING __WILL__ LEAD TO DATA LOSS
		// AND/OR CRASHING BUGS WHEN CUSTOMERS ATTEMPT TO USE YOUR SIMPLE MODIFICATIONS WITH
		// A PRE-EXISTING MAIL DATABASE.
		//
		// SINCE THIS FILE IS SHARED BY MORE COMPONENTS THAN JUST YOURS, PLEASE BE AWARE OF THE
		// C++ FRAGILE BASE CLASS PROBLEM AND DON'T MAKE CHANGES IN THE BASE CLASS SOURCE CODE
		// WITH OUT CONSULTING OTHER SOURCES THAT ARE DEPENDANT ON THIS STURUCTURE.
		// *********************************************************************************

	Change History:

		$Log: CBaseDatabase.h,v $
		Revision 1.1  2003/04/20 23:32:51  dasenbro
		Initial check-in.
		
		Revision 1.24  2002/04/21 16:56:46  dasenbro
		Added a 10.2 DB header tag.
		
		Revision 1.23  2002/03/21 16:41:16  dasenbro
		Updated file version information.
		
		Revision 1.22  2002/02/20 21:16:46  dasenbro
		Changed the DB header tag.
		
		Revision 1.21  2002/01/14 16:56:01  dasenbro
		Initial S4 updates.
		
		Revision 1.20  2001/06/21 20:50:53  dasenbro
		Updated file header info.
		
		Revision 1.19  2001/06/21 17:05:39  dasenbro
		Added Change History.
		

	Projector History:

	 <ASX12>	 10/5/99	DOR		More counters...
	 <ASX11>	 10/5/99	DOR		<med>  Minor changes to support better 2nd ID performance.
	 <ASX10>	  6/7/99	DOR		Add routine & data field member to store the cache pointer.
	  <ASX9>	  6/4/99	DOR		Remove "virtual" Assert
	  <ASX8>	  6/4/99	DOR		New callback message type & a new ObjectTooBigError code.
	  <ASX7>	 5/12/99	DOR		For the time being set the version back to 6.0 version so that
									6.3 can open DB's created by 6.0, 6.1, and 6.2 (Mail Tool also)
	  <ASX6>	 5/11/99	rds		MADmin changes.
	  <ASX4>	 4/27/99	rds		MADmin support.
	  <ASX2>	 4/12/99	DOR		Move some functions private, and add some comments.

	To Do:
*/

#ifndef __CBaseDatabase_h__
#define __CBaseDatabase_h__	1

#include "CFile.h"
#include "DatabaseTypes.h"
#include "CIDTable.h"
#include "CStr2IDTable.h"

#define		kASIP6xDBTag			"ASIP6.0"		// ASIP 6.x
#define		kOSX10_0DBTag			"OSX.0.0"		// OS X 10.0
#define		kOSX10_1DBTag			"AMS.OSX.10.1"	// OS X 10.1
#define		kCurrentDBTag			"AMS.OSX.10.2"	// OS X 10.2

const uInt32	kFreeSpaceCheckDelta = 15;

typedef struct 
{
	// *********************************************************************************
	// Warning: DO NOT CHANGE/ADD/REMOVE PUBLIC/PRIVATE DATA FIELDS TO THIS CLASS/STRUCT
	// WITHOUT CONSULTING WITH A APPLE MAIL TEAM MEMBER.  CHANGES TO
	// THIS STRUCTURE __WILL__ CAUSE FILE FORMAT COMPATIBILITY ISSUES FOR APPLESHARE IP 5.0
	// AND 6.0 MAIL DATABASES.
	//
	// FAILURE TO HEED THIS WARNING __WILL__ LEAD TO DATA LOSS
	// AND/OR CRASHING BUGS WHEN CUSTOMERS ATTEMPT TO USE YOUR SIMPLE MODIFICATIONS WITH
	// A PRE-EXISTING MAIL DATABASE.
	//
	// SINCE THIS FILE IS SHARED BY MORE COMPONENTS THAN JUST YOURS, PLEASE BE AWARE OF THE
	// C++ FRAGILE BASE CLASS PROBLEM AND DON'T MAKE CHANGES IN THE BASE CLASS SOURCE CODE
	// WITH OUT CONSULTING OTHER SOURCES THAT ARE DEPENDANT ON THIS STURUCTURE.
	// *********************************************************************************


	// NOTE: THIS ITEM IS WRITTEN TO DISK AS A BINARY "BLOB"...CHANGES WILL
	// CAUSE FILE FORMAT COMPATIBILITY PROBLEMS.
	OSType	fObjType;
	uInt32	fObjSize;
} SObjTypeInfo;

typedef enum
{
	kNoListType		= 0,
	kListNotEnabled = 'off ',
	kID2Data		= 'data',
	kID2PageMap		= 'idmp',
	kIDRangeMap		= 'idrg',
	kStr2ID			= 'stid',
	k2ndIDListMap	= '2idm'
} enumListType;

typedef struct
{
	// *********************************************************************************
	// Warning: DO NOT CHANGE/ADD/REMOVE PUBLIC/PRIVATE DATA FIELDS TO THIS CLASS/STRUCT
	// WITHOUT CONSULTING WITH A APPLE MAIL TEAM MEMBER.  CHANGES TO
	// THIS STRUCTURE __WILL__ CAUSE FILE FORMAT COMPATIBILITY ISSUES FOR APPLESHARE IP 5.0
	// AND 6.0 MAIL DATABASES.
	//
	// FAILURE TO HEED THIS WARNING __WILL__ LEAD TO DATA LOSS
	// AND/OR CRASHING BUGS WHEN CUSTOMERS ATTEMPT TO USE YOUR SIMPLE MODIFICATIONS WITH
	// A PRE-EXISTING MAIL DATABASE.
	//
	// SINCE THIS FILE IS SHARED BY MORE COMPONENTS THAN JUST YOURS, PLEASE BE AWARE OF THE
	// C++ FRAGILE BASE CLASS PROBLEM AND DON'T MAKE CHANGES IN THE BASE CLASS SOURCE CODE
	// WITH OUT CONSULTING OTHER SOURCES THAT ARE DEPENDANT ON THIS STURUCTURE.
	// *********************************************************************************

	// NOTE: THIS ITEM IS WRITTEN TO DISK AS A BINARY "BLOB"...CHANGES WILL
	// CAUSE FILE FORMAT COMPATIBILITY PROBLEMS.

	OSType			fListType;
	Boolean			fListSorted;
	volatile uInt32	fPageCount;
	volatile uInt32	fEntryCount;
	uInt32			fEntryDataSize;
	volatile PageID	fHeadPageID;
	PageID			fLastPageUsed;
} SObjList;

typedef enum
{
	kNoRequest			= 'none',
	kSetObjID			= 'nwID',
	k2ndIDRequest		= '2nID',	// outFieldData points to a ObjID setup by the "caller"
	kStringNameRequest	= 'name',	// outFieldData points to a str64 setup by the "caller"
	kObjectPINGRequest	= 'PING',	// called when the "type" is successfully registered...
	k2ndIDTargetChk		= '2chk'
} eFieldDataRequest;

typedef Boolean	(*DataFieldProc)(const eFieldDataRequest inFieldRequest, const void *inObjDataPtr, void *outFieldData);	// return false if there is no data....

class SDBIterator;
class CBaseDatabase;

typedef SDBIterator	*SDBIteratorPtr;

class SDBIterator
{
public:
				SDBIterator		( CBaseDatabase *inBaseDBPtr = NULL );
	virtual	   ~SDBIterator		( void );

	SDBIteratorPtr	fNextIterator;
	Boolean			fIteratorDone;
	OSType			fIteratorDataType;
	ObjID			fCurrentObjID;
	PageID			fCurrentPageID;
	ObjID			f2ndIDMatch;
	CBaseDatabase	*fParentDatabase;
};

typedef struct
{
	// *********************************************************************************
	// Warning: DO NOT CHANGE/ADD/REMOVE PUBLIC/PRIVATE DATA FIELDS TO THIS CLASS/STRUCT
	// WITHOUT CONSULTING WITH A APPLE MAIL TEAM MEMBER.  CHANGES TO
	// THIS STRUCTURE __WILL__ CAUSE FILE FORMAT COMPATIBILITY ISSUES FOR APPLESHARE IP 5.0
	// AND 6.0 MAIL DATABASES.
	//
	// FAILURE TO HEED THIS WARNING __WILL__ LEAD TO DATA LOSS
	// AND/OR CRASHING BUGS WHEN CUSTOMERS ATTEMPT TO USE YOUR SIMPLE MODIFICATIONS WITH
	// A PRE-EXISTING MAIL DATABASE.
	//
	// SINCE THIS FILE IS SHARED BY MORE COMPONENTS THAN JUST YOURS, PLEASE BE AWARE OF THE
	// C++ FRAGILE BASE CLASS PROBLEM AND DON'T MAKE CHANGES IN THE BASE CLASS SOURCE CODE
	// WITH OUT CONSULTING OTHER SOURCES THAT ARE DEPENDANT ON THIS STURUCTURE.
	// *********************************************************************************

	// NOTE: THIS ITEM IS WRITTEN TO DISK AS A BINARY "BLOB"...CHANGES WILL
	// CAUSE FILE FORMAT COMPATIBILITY PROBLEMS.

	OSType			fObjType;
	Boolean			fObjStrCaseSensitive;
	DataFieldProc	fObjDataFieldProc;
	SDBIteratorPtr	fIteratorList;
	SObjList		fDataList;			// head pointer to a linked list of Data Table pages..
	SObjList		fIDList;			// head pointer to a linked list of ID to Page Number Tables
	SObjList		fIDRangeList;		// head pointer to a linked list of ID Range to Page Tables...
	SObjList		fStringList;		// head pointer to a linked list of String to ID Tables...
} SPrivObjTypeInfo;

typedef SPrivObjTypeInfo *SPrivObjTypeInfoPtr;

typedef struct
{
	// *********************************************************************************
	// Warning: DO NOT CHANGE/ADD/REMOVE PUBLIC/PRIVATE DATA FIELDS TO THIS CLASS/STRUCT
	// WITHOUT CONSULTING WITH A APPLE MAIL TEAM MEMBER.  CHANGES TO
	// THIS STRUCTURE __WILL__ CAUSE FILE FORMAT COMPATIBILITY ISSUES FOR APPLESHARE IP 5.0
	// AND 6.0 MAIL DATABASES.
	//
	// FAILURE TO HEED THIS WARNING __WILL__ LEAD TO DATA LOSS
	// AND/OR CRASHING BUGS WHEN CUSTOMERS ATTEMPT TO USE YOUR SIMPLE MODIFICATIONS WITH
	// A PRE-EXISTING MAIL DATABASE.
	//
	// SINCE THIS FILE IS SHARED BY MORE COMPONENTS THAN JUST YOURS, PLEASE BE AWARE OF THE
	// C++ FRAGILE BASE CLASS PROBLEM AND DON'T MAKE CHANGES IN THE BASE CLASS SOURCE CODE
	// WITH OUT CONSULTING OTHER SOURCES THAT ARE DEPENDANT ON THIS STURUCTURE.
	// *********************************************************************************

	// NOTE: THIS ITEM IS WRITTEN TO DISK AS A BINARY "BLOB"...CHANGES WILL
	// CAUSE FILE FORMAT COMPATIBILITY PROBLEMS.

	PageID	fFreePageCount;
	PageID	fFreeListHead;
} SOldFreeList;

typedef struct
{
	// *********************************************************************************
	// Warning: DO NOT CHANGE/ADD/REMOVE PUBLIC/PRIVATE DATA FIELDS TO THIS CLASS/STRUCT
	// WITHOUT CONSULTING WITH A APPLE MAIL TEAM MEMBER.  CHANGES TO
	// THIS STRUCTURE __WILL__ CAUSE FILE FORMAT COMPATIBILITY ISSUES FOR APPLESHARE IP 5.0
	// AND 6.0 MAIL DATABASES.
	//
	// FAILURE TO HEED THIS WARNING __WILL__ LEAD TO DATA LOSS
	// AND/OR CRASHING BUGS WHEN CUSTOMERS ATTEMPT TO USE YOUR SIMPLE MODIFICATIONS WITH
	// A PRE-EXISTING MAIL DATABASE.
	//
	// SINCE THIS FILE IS SHARED BY MORE COMPONENTS THAN JUST YOURS, PLEASE BE AWARE OF THE
	// C++ FRAGILE BASE CLASS PROBLEM AND DON'T MAKE CHANGES IN THE BASE CLASS SOURCE CODE
	// WITH OUT CONSULTING OTHER SOURCES THAT ARE DEPENDANT ON THIS STURUCTURE.
	// *********************************************************************************

	// NOTE: THIS ITEM IS WRITTEN TO DISK AS A BINARY "BLOB"...CHANGES WILL
	// CAUSE FILE FORMAT COMPATIBILITY PROBLEMS.

	uInt32	fEntryCount;
	uInt32	f1stEntry;
	PageID	fFreeListPage;
} SNewFreeListEntry;

typedef enum
{
	kNoDBState		= 'none',
	kDBOpen			= 'open',
	kDBClosed		= 'clos',
	kDBFlushing		= 'flsh',
	kDBSafe			= 'dbok',
	kDBNotSafe		= 'ntok'
} eDBState;


// OS X database calculations for a max database size of 132 Gig

const uInt32	kBitsPerByte		= 8;
const uInt32	kMaxDBPageCount		= 16777216;												// Will yield a 128 gig db
const uInt32	kFreeCountPerPage	= kStandardPageSize * kBitsPerByte;						// 65536
const uInt32	kFreeMapPageCount	= (kMaxDBPageCount / kFreeCountPerPage) + 1;			// 257
const uInt64	kMaxDBFileSize		= (uInt64)kMaxDBPageCount * (uInt64)kStandardPageSize;	// 137438953472

// the following definitions are 100% backwards compatible with
// AppleShare IP Mail: 6.0, 6.1, 6.2
//	const uInt32	kBitsPerByte		= 8;
//	const uInt32	kMaxDBPageCount		= (0x7fffffff / kStandardPageSize) - 1;	// subtract 1, no need to push it to the absolute limit..
//	const uInt32	kFreeCountPerPage	= kStandardPageSize * kBitsPerByte;
//	const uInt32	kFreeMapPageCount	= (kMaxDBPageCount / kFreeCountPerPage) + 1;
//	const long long	kMaxDBFileSize		= kMaxDBPageCount * kStandardPageSize;

typedef struct
{	// header type stuff, basic counts & such...

	// *********************************************************************************
	// Warning: DO NOT CHANGE/ADD/REMOVE PUBLIC/PRIVATE DATA FIELDS TO THIS CLASS/STRUCT
	// WITHOUT CONSULTING WITH A APPLE MAIL TEAM MEMBER.  CHANGES TO
	// THIS STRUCTURE __WILL__ CAUSE FILE FORMAT COMPATIBILITY ISSUES FOR APPLESHARE IP 5.0
	// AND 6.0 MAIL DATABASES.
	//
	// FAILURE TO HEED THIS WARNING __WILL__ LEAD TO DATA LOSS
	// AND/OR CRASHING BUGS WHEN CUSTOMERS ATTEMPT TO USE YOUR SIMPLE MODIFICATIONS WITH
	// A PRE-EXISTING MAIL DATABASE.
	//
	// SINCE THIS FILE IS SHARED BY MORE COMPONENTS THAN JUST YOURS, PLEASE BE AWARE OF THE
	// C++ FRAGILE BASE CLASS PROBLEM AND DON'T MAKE CHANGES IN THE BASE CLASS SOURCE CODE
	// WITH OUT CONSULTING OTHER SOURCES THAT ARE DEPENDANT ON THIS STURUCTURE.
	// *********************************************************************************

	// NOTE: THIS ITEM IS WRITTEN TO DISK AS A BINARY "BLOB"...CHANGES WILL
	// CAUSE FILE FORMAT COMPATIBILITY PROBLEMS.

	char				fDatabaseTag[ 16 ];
	uInt32				fDatabaseVersion;
	uInt32				fPageSize;
	uInt32				fSmallObjectSize;
	uInt32				fMaxObjectSize;
	uInt32				fMaxObjTypeCount;
	uInt32				f1stPageOffset;

	// current state of the DB...
	volatile uInt32		fNextObjID;
	volatile uInt32		fPageCount;
	eDBState			fDBState;
	eDBState			fDBReOpenState;

	uInt32				fObjTypeCount;
	SPrivObjTypeInfo	fObjTypeList[ kMaxObjTypeCount ];
	SNewFreeListEntry	fNewFreeList[ kFreeMapPageCount ];
} SDatabaseHeaderData;

typedef struct
{
	PageID	fPageID;
	uInt32	fRefCount;
	uInt32	fNextPageIndex;	// hash table next pointer for collisions
	
	uInt32  fLRUPrevIndex;	// for the LRU list membership.
	uInt32  fLRUNextIndex;

	Boolean	fDirty;
	char	fPageData[ kStandardPageSize ];
} PageCacheEntry;

typedef PageCacheEntry *PageCacheEntryPtr;

const uInt32 kMaxPageCacheEntries = (16 * 1024 * 1024) / kStandardPageSize;		// we really don't want more than 16 meg cache, since all of
																				// that could become "dirty" and need to be written to disk...
const uInt32 kMaxHashTableSize = kMaxPageCacheEntries * 2;

typedef struct
{
	uInt32				fCount;
	uInt32				fEntryCount;
	uInt32				fLRUEntryCount;
	uInt32				fDirtyCount;
	uInt32				fPageCacheFreeListHead;
	
	uInt32				fLRUListHead;
	uInt32				fLRUListTail;
	
	uInt32				fPageCacheHashTable[ kMaxHashTableSize ];
	PageCacheEntryPtr	fPageCacheEntryList[ kMaxPageCacheEntries ];
} PageCacheList;

// Version is divided into parts:
//	0xFF000000 == Major Version
//	0x00FF0000 == Minor Version
//	0x0000FF00 == Development Stage (Dev = D, Alpha = A, Beta = B, Final = F)
//	0x000000FF == Development Substage

const uInt32 k501DataBaseVersion	= 0x05010B06;		// 5.01b6
const uInt32 k502DataBaseVersion	= 0x05020B03;		// 5.02b3
const uInt32 k60DataBaseVersion		= 0x06000D03;		// 6.0d3
const uInt32 k63DatabaseVersion		= 0x07000001;		// 6.x
const uInt32 kOSXDatabaseVersion	= 0x1000F001;		// OS X 10.0 Final Version
const uInt32 kOSX_10_02_DBVersion	= 0x10020A02;		// OS X 10.2 alpha Version
const uInt32 kOSX_10_04_DBVersion	= 0x10040A01;		// OS X 10.4 alpha Version

const uInt32 kCurrentDBVersion		= kOSX_10_04_DBVersion;

const uInt32 kBadDBVersion			= 0xffffffff;
const uInt32 kNoIndexHint			= 0xffffffff;
const uInt32 kNULLIndex				= 0xffffffff;
const uInt32 kStartingObjID			= 100;
const uInt32 kNormalPageCacheCount	= 16;

class CDBBaseObjectCache;
class CBaseDatabase
{
public:
						CBaseDatabase		(	const uInt32 inMinFreeDiskSpace,
												CDBBaseObjectCache *inBaseObjectCachePtr,
												uInt32 inPageCacheCount = kNormalPageCacheCount );

	virtual				~CBaseDatabase		( void );
	
	static void			CheckBackwardCompatibility	( void );
	static void			ReportBackwardCompatibility	( const uInt32 curSize, const uInt32 correctSize );
	
	virtual	OSStatus	OpenDatabaseFile	(	const CFileSpecPtr	inFSSpec,
												const OSType		inFileType,
												const OSType		inFileCreator,
												const Boolean		inCreateFlag = false,
												const uInt32		inDBVersion = kCurrentDBVersion	);
	
	virtual CDBBaseObjectCache	*GetBaseObjectCachePtr	( void );

	virtual	OSStatus	CloseDatabaseFile	( void );
	virtual	OSStatus	FlushDatabaseFile	( eDBState inReOpenState );
	virtual	eDBState	GetDBOpenState		( void );
	virtual	void		SetDBOpenState		( const eDBState inReOpenState);
	
	virtual	void		DBIdle				( Bool inForceFlush );
	
	virtual	OSStatus	AddObjType			( const OSType inObjType, const uInt32 inObjectSize, const Boolean inCaseSensitiveFlag, const DataFieldProc inFieldCallBackProc = NULL);
	virtual uInt32		GetObjTypeCount		( void );
	virtual uInt32		GetMaxObjTypeCount	( void );
	virtual OSStatus	GetObjTypeInfo		( const uInt32 inObjTypeIndex, SObjTypeInfo &outObjTypeInfo );
	virtual uInt32		GetMaxObjSize		( void );

	virtual uInt32		GetPageCount		( void );
	virtual uInt32		GetPageCacheCount	( void );
	virtual uInt32		GetPageSize			( void );
	
	virtual uInt32		GetMinFreeDiskSpace	( void );
	virtual void		SetMinFreeDiskSpace ( const uInt32 inMinFreeDiskSpace );

	virtual sInt64		GetDatabaseSize		( void ) { return( fStore.FileSize() ); };

	virtual OSStatus	CreateObj						( const OSType inObjType, ObjID &outNewObjID, void *inObjData = NULL);
	virtual OSStatus	GetObjectCount					( const OSType inObjType, uInt32 &outObjectCount );	
	virtual OSStatus	GetObjectStingNameEntryCount	( const OSType inObjType, uInt32 &outNameEntryCount );	
	virtual OSStatus	SetObjData						( const OSType inObjType, const ObjID inObjID, void *inObjData );
	virtual OSStatus	GetObjData						( const OSType inObjType, const ObjID inObjID, void *outObjData );
	virtual OSStatus	GetObjDataByString				( const OSType inObjType, const char *inSearchString, ObjID &outObjID, void *outObjData = NULL );
	virtual OSStatus	RemoveObj						( const OSType inObjType, ObjID inObjID );

	virtual ObjID		GetNextDBObjID					( void ) { return( fDatabaseHeader.fNextObjID + 1 ); };

	// iteration routines...
	virtual OSStatus	CreateIterator			( const OSType inObjType, SDBIteratorPtr outIterator, const ObjID in2ndID2Match = 0 );
	virtual OSStatus	ReleaseIterator			( SDBIteratorPtr inOutIterator );
	virtual OSStatus	ResetIterator			( SDBIteratorPtr inOutIterator, ObjID &outObjID, void *outObjData = NULL );
	virtual OSStatus	GetCurObject			( SDBIteratorPtr inOutIterator, ObjID &outObjID, void *outObjData = NULL );
	virtual OSStatus	NextObject				( SDBIteratorPtr inOutIterator, ObjID &outObjID, void *outObjData = NULL );
	virtual OSStatus	PrevObject				( SDBIteratorPtr inOutIterator, ObjID &outObjID, void *outObjData = NULL );
	virtual OSStatus	FixAndRemoveCurObject	( SDBIteratorPtr inOutIterator );
	virtual	OSStatus	GetIteratorItemCnt		( SDBIteratorPtr inOutIterator, uInt32 &outCount );
	virtual	ObjID		GetCurrentObjID			( void );

	enum
	{
		kDBNoErr						=   0,
		kDBTypeListFull					=  -1,
		kDBObjTypeCount2Big				=  -2,
		kDBObjTypeIndexBad				=  -3,
		kDBBadFile						=  -4,
		kDBBadDBVersion					=  -5,
		kDBNoSuchObjType				=  -6,
		kDBNotOpen						=  -7,
		kDBFreeListErr					=  -8,
		kDBBadIterator					=  -9,
		kDBNoSuchPage					= -10,
		kDBListNotEnabled				= -11,
		kDBNoAddObject					= -12,
		kDBOutOfMemory					= -13,
		kDBObjTypeExists				= -14,
		kDBWrongVersion					= -15,
		kDBPageTableAllUsed				= -16,
		kDB2ManyReleases				= -17,
		kDBObjNotFound					= -18,
		kDBDataTypeSizesNoMatch			= -19,
		kDBDataTypeHasFieldProc			= -20,
		kDBNotClosedProperly			= -21,
		kDBCanNotOpen					= -22,
		kDBMismatchFileTypeCreator		= -23,
		kDBDuplicateObjNamesNotAllowed	= -24,
		kDBDiskFull			 			= -25,
		kDBPageNotInCache				= -26,
		kDBObjTypeNotAllowedDBInteral	= -27,
		kDBObjStringNameListNeedsUpdate	= -28,
		kDBObjTypeSize2Big2Fit			= -29
	};
	
private:

	// ****************************************************
	// While not _REQUIRED_ it is _HIGHLY_ recommended that any clients of
	// this Base Class override the following virtual functions.
	// The Base implementation provided here will cause a debugger break,
	// this is intention to call attention to the fact that they should be
	// overridden, if at all possible I would've left them as "pure-virtual"
	// functions, but that can't be done since the base class needs to call
	// these virtual functions.

	virtual	void	DoYield				( const Boolean inForceYieldFlag );
	virtual Boolean IsThreadQuitting	( void );

	virtual void DoLockDB		( void );
	virtual void DoReleaseDB	( void );
	

	// ****************************************************

	virtual OSStatus	MakeNew2ndIDObject	( const ObjID inObjID, const SObjList *outObjListPtr );
	virtual OSStatus	CreateObjWithID		( const OSType inObjType, const ObjID inObjID, void *inObjData = NULL);
	virtual OSStatus	Delete2ndIDList		( const ObjID inObjID );

	// Free List Management
	virtual	OSStatus	GetNextFreePage		( PageID &outPageNum );
	virtual OSStatus	AddPage2FreeList	( const PageID inPageNum, const Boolean inAllowFileShrink );

	virtual	uInt32		GetDBVersion		( void );
	virtual uInt32		Get1stPageOffset	( void );
	virtual uInt32		GetSmallObjSize		( void );

	virtual	ObjID		GetNextObjID		( void );
	virtual OSStatus	PrivGetNextObject	( SDBIterator *inOutIterator, ObjID &outObjID, Boolean inForwardFlag, void *outObjData = NULL );
	virtual void		FixIteratorList		( SPrivObjTypeInfoPtr inObjTypeInfoPtr, const ObjID inObjID, const ObjID in2ndID );

	// Internal List Management Functions
	virtual OSStatus 	AddObject2List			( SObjList &inObjTypeInfo, const ObjID inObjID, void *inData, PageID &outPageID );
	virtual OSStatus	RemovePageFromList		( SObjList &inObjTypeInfo, const PageID inPageID, SPrivObjTypeInfoPtr inObjTypeInfoPtr );
	virtual OSStatus	RemovePageFromStrList	( SObjList &inObjTypeInfo, const PageID inPageID, const Boolean inCaseFlag );

	virtual OSStatus	RemoveObjFromList			( SObjList &inObjTypeInfo, const ObjID inObjID, PageID inHintPage, SPrivObjTypeInfoPtr inObjTypeInfoPtr );
	virtual OSStatus	RemoveObjectFromStringList	( SPrivObjTypeInfoPtr inObjTypeInfo, const ObjID inObjID, char *inObjDataPtr );
	virtual OSStatus	FindObjectInList			( SObjList &inObjTypeInfo, const ObjID inObjID, void *outData, PageID &outPageID, PageID inHintPage = kNoHintPage );
	virtual OSStatus	FuzzyFind					( SObjList &inObjTypeInfo, const ObjID inObjID, void *outData, PageID inHintPage = kNoHintPage );
	virtual OSStatus	SetObjectDataInList 		( SObjList &inObjTypeInfo, const ObjID inObjID, void *inData, PageID inHintPage = kNoHintPage );

	virtual OSStatus	FindObjectInStrList 	( SPrivObjTypeInfoPtr inObjTypeInfo, const char *inSearchString, ObjID &outObjID, PageID &outObjPageID, PageID &outStrIndexPageID );
	virtual OSStatus	AddObject2StringList	( SPrivObjTypeInfoPtr inObjTypeInfo, const ObjID inObjID, const void *inObjData, const PageID inObjPageID );

	virtual OSStatus	AddObject2DataList	( SPrivObjTypeInfoPtr inObjTypeInfo, const ObjID inObjID, void *inData, PageID &outPageID );
	virtual OSStatus	AddObject2IDList	( SPrivObjTypeInfoPtr inObjTypeInfo, const ObjID inObjID, void *inData, PageID &outPageID );

	virtual OSStatus	RemoveObjectFrom2ndIDList	(SPrivObjTypeInfoPtr inObjTypeInfo, const ObjID inObjID, char *inObjDataPtr );
	virtual OSStatus	AddObjectTo2ndIDList		(SPrivObjTypeInfoPtr inObjTypeInfo, const ObjID inObjID, void *inObjData, const PageID inObjDataPageID );

	virtual OSStatus	GetPage 			( const PageID inPageNum, char * &outPageData, const Boolean inSkipPageIOFlag, uInt32 &outPageIndexHint );
	virtual OSStatus	GetStr2IDPage		( const PageID inPageNum, const Boolean inSkipPageIOFlag, CStr2IDTable &outStr2IDTable );
	virtual OSStatus	GetIDPage			( const PageID inPageNum, const Boolean inSkipPageIOFlag, CIDTable &outCIDTable, uInt32 &outPageIndexHint );

	virtual OSStatus	ReleasePage			( const PageID inPageID, const Boolean inDirtyFlag );
	virtual OSStatus	ReleaseStr2IDPage	( CStr2IDTable &outStr2IDTable, Boolean inDirtyFlag = false );
	virtual OSStatus	ReleaseIDPage		( CIDTable &outCIDTable, Boolean inDirtyFlag );

	virtual OSStatus	ClearPageFromCache	( const PageID inPageID );
	virtual OSStatus	DirtyPage			( const PageID inPageID );
	virtual OSStatus	FlushPageCache		( const Boolean inMarkEmpty = false );
	
	virtual Boolean		FindPageByIndex		( const PageID inPageID, uInt32 &outPageIndex );
	virtual void		RemovePageFromIndex	( const PageID inPageID );
	virtual uInt32		HashResult			( const PageID inPageID );
	virtual void		AddPage2Index 		( const uInt32 inPageIndex );

	virtual void		Add2LRUList 		( const uInt32 inPageIndex );
	virtual uInt32		GetLRUTailPage 		( void );
	virtual void		RemoveFromLRUList 	( const uInt32 inPageIndex );

	virtual OSStatus	SetPageCount		( uInt32 inPageCount );
	virtual OSStatus	AddPage				( PageID &outPageNum );
	virtual OSStatus	ReadPage			( const PageID inPageNum, char *outDataPtr );
	virtual OSStatus	WritePage			( const PageID inPageNum, char *inDataPtr );
	
	virtual OSStatus	SetObjTypeCount		( uInt32 inObjTypeCount );
	virtual	OSStatus	SetObjTypeEntry		( const uInt32 inIndex, const SPrivObjTypeInfo &inObjTypeInfo );
	virtual	OSStatus	GetObjTypeEntry		( const uInt32 inIndex, SPrivObjTypeInfoPtr &inObjTypeInfoPtr );
	virtual OSStatus	FindObjTypeEntry	( const OSType inObjType, uInt32 &outIndex);
	
	virtual	OSStatus	ReadDatabaseHeader	( const uInt32 inDBVersion );
	virtual	OSStatus	WriteDatabaseHeader	( Boolean inTrueWriteFlag = false );
	virtual	OSStatus	SetupDatabase		( const uInt32 inDBVersion );

	// Database Page Consolodate Routines...	
	virtual uInt32		CalcPageSavings				( const SObjList	*inList );
	virtual uInt32		CalcMaxItems				( const SObjList	*inList );
	virtual void		ConsolodatePages			( void );
	virtual Boolean		MakeFreeSpace				( SPrivObjTypeInfoPtr inObjTypeInfo );
	virtual Boolean		CheckGenericList4Space		( SObjList *inList );
	virtual Boolean		CheckDataPages4FreeSpace	( SPrivObjTypeInfoPtr inObjTypeInfo );
	virtual Boolean		CheckID2PageIndex4FreeSpace	( SPrivObjTypeInfoPtr inObjTypeInfo );
	virtual Boolean		ConsolodateDataPages		( SPrivObjTypeInfoPtr inObjTypeInfo,
										  			  const uInt32		  inMaxDataItemCount );
	virtual Boolean		ConsolodateIndexPages		( SPrivObjTypeInfoPtr inObjTypeInfo,
										  			  const uInt32		  inMaxDataItemCount );
	virtual void		MoveData					( SPrivObjTypeInfoPtr inObjTypeInfo,
													  const PageID		  inTargetDataPageID,
													  const uInt32		  inObjectCount,
													  uInt32 			  &outObjectMoved,
													  Boolean			  &outPageDeleteFlag	);
	virtual void		MoveIndexData				( SPrivObjTypeInfoPtr inObjTypeInfo,
													  const PageID		  inTargetDataPageID,
													  const uInt32		  inObjectCount,
													  uInt32 			  &outObjectMoved,
													  Boolean			  &outPageDeleteFlag	);
	virtual void		MoveDataFromNextPage		(	SObjList			*inList,
														const PageID		inTargetPageID,
														const uInt32		inObjectCount,
														uInt32 				&outObjectMoved,
														Boolean				&outPageDeleteFlag	);


	// instance data that is not stored on disk
//		FSSpec				fFSSpec;
		CFile				fStore;
//		short				fFileRef;
		OSType				fFileType;
		OSType				fFileCreator;
		PageCacheList		fPageCache;
		volatile Boolean	fHeaderDirty;
//		ParamBlockRec		fFileIOPB;
		uInt32				fMinFreeDiskSpace;
		sInt32				fOldPageCount;	
		
		uTime_t				fNextFreeSpaceCheck;
		long				fPageCountTillFreeCheck;
		
		CDBBaseObjectCache	*fObjectCachePtr;

	// persistant data stored on disk		
		SDatabaseHeaderData	fDatabaseHeader;
};

#endif	// __CBaseDatabase_h__
