#ifndef _CEGOFILEHANDLER_H_INCLUDED_
#define _CEGOFILEHANDLER_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoFileHandler.h
// -----------------
// Cego file handler class definition
//                                                         
// Design and Implementation by Bjoern Lemke
//
// (C)opyright 2000-2019 Bjoern Lemke
//
// INTERFACE MODULE
//
// Class: CegoFileHandler
// 
// Description: The filehandler class provides access to all datafiles. Datafiles consists
//              of a defined number of pages managed by the this class.
//              At the header of a datafile, a bitmap is stored for used page information
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

#ifndef _REENTRANT
#define _REENTRANT    /* basic 3-lines for threads */
#endif

// LFC INCLUDES
#include <lfcbase/Chain.h>
#include <lfcbase/File.h>
#include <lfcbase/Logger.h>

// CEGO INCLUDES
#include "CegoLockHandler.h"
#include "CegoDefs.h"
#include "CegoModule.h"

class CegoFileHandler : public CegoModule {
    
public:
   
    enum FileType { DATAFILE, SYSTEMFILE, TEMP };

    CegoFileHandler(const Chain& logFile, const Chain& progName);
    ~CegoFileHandler();

    void setReadOnly(bool isReadOnly);
    
    void setBackup(int fileId, bool m);

    bool needPageBackup(PageIdType pageId);
    bool isPageMarked(PageIdType pageId, int fileId);

    // obsolete
    // void cleanDataFile(int fileId, CegoLockHandler* pLockHandle);

    void initDataFile(int tabSetId, const Chain& path, int fileId, int numPages, PageIdType pageOffset, FileType ft);
    void regDataFile(int tabSetId, const Chain& path, int fileId, CegoLockHandler* pLockHandle);

    void resetDataFile(int fileId);
	
    void writePage(PageIdType pageId, unsigned fixStat, char* pageData, CegoLockHandler* pLockHandle);
    void readPage(PageIdType pageId, int& tabSetId, unsigned& fixStat, char* pageData, CegoLockHandler* pLockHandle);
    
    void claimPage(PageIdType pageId, CegoLockHandler* pLockHandle);
    void allocatePage(int tabSetId, FileType ft, PageIdType& pageId, CegoLockHandler* pLockHandle, unsigned* &fbm, int& fbmSize, bool doAppend = false);
    void releasePage(PageIdType pageId, CegoLockHandler* pLockHandle, unsigned* &fbm, int& fbmSize);

    void releaseFiles(int tabSetId);

    int getNumPages(int fileId);
    int getNumUsedPages(int fileId, CegoLockHandler* pLockHandle);

    PageIdType getPageOffset(int fileId);
    
    bool isClaimed(PageIdType pageId, CegoLockHandler *pLockHandle);
    
    void writeFBM(int fileId, unsigned *fbm, CegoLockHandler *pLockHandle);

    int getFileIdForPageId(PageIdType pageId);

    void commitPageEntry(PageIdType pageId);
    int cleanPages(CegoLockHandler *pLockHandle);
    
protected:
    
    int _pageSize;

private:

    int getFBMSize(int fileId);
    void readFBM(int fileId, unsigned *fbm, CegoLockHandler *pLockHandle);

    void markPage(PageIdType pageId);

    File* getHandle(int fileId);

    void printBitMap(unsigned bm);
    int mapDiff(unsigned bm1, unsigned bm2);
	    
    bool _isReg[FILMNG_MAXDATAFILE];
    int _tabSetId[FILMNG_MAXDATAFILE];
    int _fileType[FILMNG_MAXDATAFILE];
    int _numPages[FILMNG_MAXDATAFILE];
    PageIdType _pageOffset[FILMNG_MAXDATAFILE];
    
    File* _fhList[FILMNG_MAXDATAFILE];

    Chain _path[FILMNG_MAXDATAFILE];

    unsigned* _buMask[FILMNG_MAXDATAFILE];

    unsigned* _commitMask[FILMNG_MAXDATAFILE];
    
    bool _fbmMask[FILMNG_MAXDATAFILE];

    PageIdType _appendPos[FILMNG_MAXDATAFILE];
    int _appendFid;

    bool _isReadOnly;
    
    unsigned long _modId;
};

#endif
