#ifndef _CEGOBUFFERPOOL_H_INCLUDED_
#define _CEGOBUFFERPOOL_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoBufferPool.h
// ----------------
// Cego BufferPool class definition
//                                                         
// Design and Implementation by Bjoern Lemke
//
// (C)opyright 2000-2025 Bjoern Lemke
//
// INTERFACE MODULE
//
// Class: CegoBufferPool
// 
// Description: The buffer pool management class
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

// LFC INCLUDES
#include <lfcbase/Chain.h>
#include <lfcbase/NanoTimer.h>

// CEGO INCLUDES
#include "CegoXMLSpace.h"
#include "CegoLogManager.h"
#include "CegoFileHandler.h"
#include "CegoBufferPage.h"
#include "CegoBufferPoolEntry.h"
#include "CegoLockHandler.h"
#include "CegoAdminHandler.h"

class CegoBufferPool : public CegoLogManager {
    
public:
    
    enum FixMode { SYNC, NOSYNC, PERSISTENT };
    
    CegoBufferPool(const Chain& xmlDef, const Chain& logFile, const Chain& progName);
    ~CegoBufferPool();
    
    void initPool(unsigned long long numSegment, unsigned long long numPages);
    void removePool();
    
    void attachPool();
    void detachPool();
    
    void bufferFix(CegoBufferPage &bp, unsigned tabSetId, PageIdType pageId, FixMode m, CegoLockHandler *pLockHandle, unsigned numTry = 0);
    void emptyFix(CegoBufferPage &bp, unsigned tabSetId, FixMode m, CegoFileHandler::FileType ft, CegoLockHandler *pLockHandle, bool doAppend = false);

    void bufferUnfix(CegoBufferPage &bp, bool isDirty, CegoLockHandler *pLockHandle);
    void bufferRelease(CegoBufferPage &bp, CegoLockHandler *pLockHandle);

    unsigned long long writeCheckPoint(const Chain& tableSet, bool switchLog,  bool archComplete, CegoLockHandler *pLockHandle, const Chain& escCmd = Chain(), unsigned escTimeout = ESCCMDTIMEOUT, unsigned archTimeout = LOGARCHTIMEOUT);
    unsigned long long writeCheckPoint(unsigned tabSetId, bool switchLog, const Chain& escCmd, unsigned timeout, CegoLockHandler *pLockHandle);
    void writeAndRemoveTabSet(unsigned tabSetId, CegoLockHandler *pLockHandle);

    unsigned long long getCPCount() const;
    
    unsigned long long uptime() const;
    void poolInfo(unsigned& pageSize,
		  unsigned long long& numTotal,
		  unsigned long long& numUsed,
		  unsigned long long& numFree,
		  unsigned long long& numDirty,
		  unsigned long long& numFixes,
		  unsigned long long& numPersistent,
		  unsigned long long& numNoSync,
		  unsigned long long& numDiskRead,
		  unsigned long long& numDiskWrite,
		  double& hitRate,
		  double& spreadRate,
		  unsigned long long& avgReadDelay,
		  unsigned long long& avgWriteDelay,
		  unsigned long long& curFixCount,
		  unsigned long long& maxFixCount,
		  unsigned long long& avgFixTry,
		  unsigned long long& statStart,
	          unsigned long long& uptime) const;

    void getPoolEntryList(ListT<CegoBufferPoolEntry>& entryList);

    void resetStats();

    void logIt(unsigned tabSetId, CegoLogRecord& lr, CegoLockHandler* pLockHandle, bool flushLog = true);
	
    void printPool();

    void getLMLockStat(unsigned tabSetId, Chain& lockName, unsigned& lockCount, unsigned long long &numRdLock, unsigned long long &numWrLock, unsigned long long &sumRdDelay, unsigned long long &sumWrDelay);

    void getAggLMLockStat(Chain& lockGroup, unsigned& numLock, unsigned& lockCount, unsigned long long &numRdLock, unsigned long long &numWrLock, unsigned long long &sumRdDelay, unsigned long long &sumWrDelay);
    
    void restoreCheckpointDump(unsigned tabSetId, CegoLockHandler *pLockHandle);
	
    Chain getDBName();

    void lockPool(unsigned tabSetId, bool doWrite);
    void unlockPool(unsigned tabSetId);

    void verifyLogLocks(CegoAdminHandler*pAH);
    
private:

    unsigned calcHash(PageIdType pageId);
    unsigned calcSegment(PageIdType pageId);
    void logBM(unsigned tabSetId, unsigned fileId, unsigned* fbm, unsigned fbmSize, CegoLockHandler* pLockHandle);	
    bool archiveComplete(const Chain& tableSet);
    void optimizePool(unsigned tabSetId);

    // dump methods
    void dumpCheckpoint(unsigned tabSetId);
    void commitCheckpoint(unsigned tabSetId, CegoLockHandler *pLockHandle);
    
    typedef struct BufferPoolHead {
	unsigned numPages;
    } BufferPoolHead;
    
    enum OccState { NOT_OCCUPIED, WRITE_ON_SYNC, WRITE_ON_DIRTY, PERSISTENT_OCCUPIED };
    
    typedef struct BufferHead {
	OccState isOccupied;
	char isDirty;
	unsigned numFixes;
	unsigned tabSetId;
	PageIdType pageId;
	unsigned fixStat;
	unsigned long long numUsage;
    } BufferHead;
    
    Chain _dbName;
    unsigned long long _numSegment;
    unsigned long long _numPages;
    
    void **_pBufPool;

    unsigned long long _fixCount;
    unsigned long long _fixTry;
    unsigned long long _numDiskRead;    
    unsigned long long _numDiskWrite;
    unsigned long long _avgReadDelay;
    unsigned long long _avgWriteDelay;

    unsigned long long _cpCount;

    NanoTimer _diskReadTimer;
    NanoTimer _diskWriteTimer;

    unsigned long long _poolStart;
    unsigned long long _statStart;
    unsigned _maxFixTries;
    unsigned _maxPageDelete;

    ListT<PageIdType> _deletedPageList;
    
    unsigned long _modId;    
};
#endif
