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

	File:		CDBBaseObject.h

	Contains:	C++ base class definition for persistent database objects

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

	Written by:	Nick Brosnahan

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

 	NOT_FOR_OPEN_SOURCE <to be reevaluated at a later time>

	Change History:

		$Log: CDBBaseObject.h,v $
		Revision 1.1  2003/04/20 23:32:51  dasenbro
		Initial check-in.
		
		Revision 1.8  2002/03/21 16:41:17  dasenbro
		Updated file version information.
		
		Revision 1.7  2001/06/21 20:50:53  dasenbro
		Updated file header info.
		
		Revision 1.6  2001/06/21 17:05:39  dasenbro
		Added Change History.
		

	Projector History:

	  <ASX4>	  6/7/99	DOR		Remove static functions in favor of "virtual" funcitons (i know
									they are the same...we made major changes OK???)
	  <ASX3>	  6/4/99	DOR		Add compiler struct alignment check.
	  <ASX2>	 4/27/99	rds		RADmin support.
	 <ASM23>	 1/13/99	DOR		New object type for the database.
	 <ASM22>	11/24/98	DOR		Remove the #define name from the #endif because ANSI C doesn't
									like it.
		<21>	11/23/98	DOR		Add a new DB Object Type.
		<20>	 8/21/98	DOR		Add a New   CObject type.
		<19>	 8/10/98	MED		Added a new Expansion object signature.
		<18>	  8/3/98	MED		6.1 - Added an ACL object signature.
		<17>	  6/1/98	DOR		Remove "ObjectAdd" enumerated type.  We no longer use it.
		<16>	  4/2/98	DOR		New Database version constant.
		<15>	03/23/98	DOR		Add Get/Release ObjectLock.
		<14>	 3/14/98	DOR		New implementations.
		<13>	 3/12/98	DOR		Change fRefCount to volatile..
		<11>	 3/11/98	MED		Changed setDirty() to take a force Write flag.
		<10>	  3/9/98	DOR		Add Get/Set/Clear OwnerThreadID as a feature of CDBObject
		 <9>	 2/26/98	DOR		Use CFastMutex instead of the slow one from PowerPlant.
		 <8>	  2/4/98	DOR		New small message part signature type.
		 <7>	12/15/97	DOR		Update version to a1c1.
		 <6>	 12/3/97	DOR		Add the new DNS prefs object...
		 <5>	 12/3/97	MED		Changed kInHost... and kOutHost... to kHostPrefSignature.
		 <4>	11/24/97	MED		Added kServerPrefsSignature for server prefs.
		 <3>	 10/9/97	DOR		Changed the version to reflect ASIP 6.0
		 <2>	 10/9/97	DOR		Add object types for Incoming & Outgoing routing preferences.

	To Do:
*/


#ifndef __CDBBaseObject_h__
#define __CDBBaseObject_h__	1

#include "CBaseDatabase.h"
#include "UException.h"


typedef struct
{
	OSType 	fSignature;
	uInt32 	fVersion;
	uInt32 	fSize;			// zero value indicates that object is variable length on disk
} StdDBObjHeader;

typedef struct
{
	OSType	fSignature;
} StdDBObjFooter;

// CDBObject Constants
const uInt32 kDBObjectHeaderLength = (sizeof (StdDBObjHeader));
const uInt32 kDBObjectFooterLength = sizeof (StdDBObjFooter);

const long	 kReallyBigMemSize		= 0x7fffffff;
const uInt32 kDefaultTime2Wait		= 45;	// time expressed in ticks, wait 3/4 of a second..
const uInt32 kCacheHashTableSize	= 29;
const uInt32 kAllListFlushValue 	= 0xffffffff;
const uInt32 kBaseSecondsPerMin     = 60;
const uInt32 kBaseMilliSecsPerSec	= 1000;
const uInt32 kSafetyWaitTime		= 2 * kBaseSecondsPerMin * kBaseMilliSecsPerSec;

class CSmartTimer
{
public:
					CSmartTimer ( uInt32 inTime2Wait = kDefaultTime2Wait );
	virtual		   ~CSmartTimer ( void );

	virtual	void	ResetTimer	( uInt32 inTime2Wait = kDefaultTime2Wait );
	virtual	Boolean	KeepWaiting	( void );

private:
	uInt32	fStartTime;
	uInt32	fTime2Wait;
	uInt32	fCount;
}; // CSmartTimer

class CDBBaseObject;
typedef CDBBaseObject*	(*ObjAllocFuncPtr)(void);	// return false if there is no data....

class CDBBaseObject
{
public:
			CDBBaseObject		( 	StdDBObjHeader		*inObjHeader,
									StdDBObjFooter		*inObjFooter,
									void				*inObjData,
									const OSType		inObjSignature,
									const uInt32		inObjVersion,
									const uInt32		inObjSize 		);
	virtual	~CDBBaseObject		( void );
	
	virtual CDBBaseObject*	Use			( CBaseDatabase	*inBaseDB );
	virtual void 			ChkCompilerStructAlignment	( void );
			void			Done		( CDBBaseObject* &inPtr );	// do _NOT_ make this virtual!!!!

	static	CDBBaseObject*	UniversalFindByID	( CBaseDatabase	*inBaseDB,
													const ObjID			inObjID,
													const OSType		inObjType,
													const uInt32		inObjVersion,
													const uInt32		inObjSize,
													ObjAllocFuncPtr		inObjAllocFuncPtr	);

	virtual CBaseDatabase	*GetOwnerDBPtr			( void );												
	virtual	ObjID			GetObjectID				( void ) = 0;
	virtual	void*			GetObjectData			( void );

	virtual	OSType			GetObjectType			( void );
	virtual	uInt32			GetObjectVersion		( void );
	virtual uInt32			GetObjectSize			( void );

	virtual	void			SetNextPtr				( CDBBaseObject *inObject );
	virtual CDBBaseObject*	GetNextPtr				( void );

	virtual	void			SetPrevPtr				( CDBBaseObject *inObject );
	virtual CDBBaseObject*	GetPrevPtr				( void );
	
	virtual	uInt32			GetObjectRefCount		( void );
	virtual void			SetObjectRefCount		( const uInt32 inObjectRefCount );

	virtual void			AddObjectReference		( void );
	virtual void			RemoveObjectReference	( void );
	
	virtual	void			setDirty				( const Boolean inForceWriteFlag = false );
	virtual	Boolean			GetDirtyFlag			( void );
	virtual	void			SetDirtyFlag			( const Boolean inDirtyFlag );
	
	virtual OSErr			WriteObject				( void );

	// Thread OwnerShip
	virtual	ExceptionCode	GetObjectLock			( const Boolean inWaitForObjectLock, const uInt32 inMaxWaitTime = kSafetyWaitTime );
	virtual	void			ReleaseObjectLock		( const Boolean inNotifyOtherThreadsFlag );
	virtual	void			WakeUpObjectThreads		( void );

private:
	volatile CBaseDatabase	*fOwnerDBPtr;
	volatile uInt32			fRefCount;
	volatile CDBBaseObject	*fNextPtr;
	volatile CDBBaseObject	*fPrevPtr;
	volatile Boolean		fDirty;

	StdDBObjHeader			*fObjHeader;
	StdDBObjFooter			*fObjFooter;
	void					*fObjData;

}; //  class CDBBaseObject


class CDBBaseObjectCacheList
{
public:
			 CDBBaseObjectCacheList	();
	virtual ~CDBBaseObjectCacheList	();
	
	virtual	CDBBaseObject*	AddObject		( CDBBaseObject *inObject );
	virtual	Boolean			RemoveObject	( CDBBaseObject *inObject );
	
	virtual	uInt32			GetListCount	( void );
	virtual	void			SetListCount	( const uInt32 inListCount );
	
	virtual	uInt32			GetListMax		( void );
	virtual	void			SetListMax		( const uInt32 inListCount );
	
	virtual	CDBBaseObject*	GetListHead		( void );
	virtual	void			SetListHead		( CDBBaseObject* inObject );
	
	virtual	CDBBaseObject*	FindObject		( const ObjID inObjectID );
	
	virtual	void			FlushList		( const Boolean inWakeupThreads );
	
	virtual void			DoListLock		( void );
	virtual void			DoListRelease	( void );

private:
	volatile CDBBaseObject	*fListHead;
	volatile uInt32			fListCount;
	volatile uInt32			fListMaxCount;

}; // class CDBBaseObjectCacheList

class TypeToIndexMapping
{
public:
	OSType				fObjType;
	uInt32				fCacheListIndex;
	TypeToIndexMapping *fNextPtr;
}; // class TypeToIndexMapping

class CDBBaseObjectCache
{
public:
			CDBBaseObjectCache( CBaseDatabase *inObject );
	virtual	~CDBBaseObjectCache();
	
	virtual void			SetBaseDBPtr		( CBaseDatabase *inObject );
	virtual CBaseDatabase*	GetBaseDBPtr		( void );
	
	virtual	CDBBaseObject*	Search4Object		( const ObjID inObjectID );
	virtual	CDBBaseObject*	Search4Object		( const OSType inObjectType, const ObjID  inObjectID );
	virtual	CDBBaseObject*	AddObject2List		( CDBBaseObject *inObject );
	virtual	Boolean			RemoveObjFromList	( CDBBaseObject *inObject );
	
	virtual	void			LockTheCache		( const OSType inObjectType );
	virtual	void			UnLockTheCache		( const OSType inObjectType );

	virtual	void			FlushAllList		( const Boolean inWakeupThreads );
	virtual	void			FlushList			( const OSType inObjectType, const Boolean inWakeupThreads );
	virtual	uInt32			CalcObjectCount		( void );

	virtual	void			Wait				( const uInt32 inIndex );
	virtual	void			Signal				( const uInt32 inIndex );
	
	virtual	CDBBaseObject*	AddObject			( CDBBaseObject *inObject );
	virtual	Boolean			RemoveObject		( CDBBaseObject *inObject );
	virtual	CDBBaseObject*	FindObject			( const ObjID	inObjectID );
	virtual CDBBaseObject*	FindObject			( const OSType	inObjectType, const ObjID	inObjectID );
	virtual	uInt32			GetListCount		( void );
	virtual uInt32			CalcCacheObjCount	( void );
	virtual	void			Flush				( const OSType inObjectType, const Boolean inWakeupThreads );
											
	virtual	uInt32			DoListHash			( const OSType inObjecttype, const ObjID  inObjectID );

protected:
	virtual void			SetUpHashTable		( void );
	
	CBaseDatabase 				*fBaseDBPtr;
	uInt32						fCacheListCount;

private:
	TypeToIndexMapping		   *fHashTable[ kCacheHashTableSize ];
	CDBBaseObjectCacheList	   *fCacheList;

}; // CDBBaseObjectCache


#endif // __CDBBaseObject_h__
