#ifndef _CEGOBUFFERPOOL_H_INCLUDED_
#define _CEGOBUFFERPOOL_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoBufferPool.h
// ----------------
// Cego BufferPool class definition
//                                                         
// Design and Implementation by Bjoern Lemke
//
// (C)opyright 2000-2019 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"

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, int tabSetId, PageIdType pageId, FixMode m, CegoLockHandler *pLockHandle, int numTry = 0);
    void emptyFix(CegoBufferPage &bp, int 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(""), int escTimeout = ESCCMDTIMEOUT, int archTimeout = LOGARCHTIMEOUT);
    unsigned long long writeCheckPoint(int tabSetId, bool switchLog, const Chain& escCmd, int timeout, CegoLockHandler *pLockHandle);
    void writeAndRemoveTabSet(int tabSetId, CegoLockHandler *pLockHandle);

    unsigned long long getCPCount() const;
    
    unsigned long long uptime() const;
    void poolInfo(int& 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(int tabSetId, CegoLogRecord& lr, CegoLockHandler* pLockHandle, bool flushLog = true);
	
    void printPool();

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

    void restoreCheckpointDump(int tabSetId, CegoLockHandler *pLockHandle);
	
    Chain getDBName();

private:

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

    // dump methods
    void dumpCheckpoint(int tabSetId);
    void commitCheckpoint(int tabSetId, CegoLockHandler *pLockHandle);

    
    typedef struct BufferPoolHead {
	int numPages;
    } BufferPoolHead;
    
    enum OccState { NOT_OCCUPIED, WRITE_ON_SYNC, WRITE_ON_DIRTY, PERSISTENT_OCCUPIED };
    
    typedef struct BufferHead {
	OccState isOccupied;
	char isDirty;
	int numFixes;
	int tabSetId;
	PageIdType pageId;
	unsigned fixStat;
	unsigned long long numUsage;
    } BufferHead;
    
    Chain _dbName;
    unsigned long long _numSegment;
    unsigned long long _numPages;
    int _key;
    
    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;
    int _maxFixTries;
    int _maxPageDelete;

    ListT<PageIdType> _deletedPageList;
    
    unsigned long _modId;

    
};

#endif
