#ifndef _CEGOXMLSPACE_H_INCLUDED_
#define _CEGOXMLSPACE_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoXMLSpace.h
// -----------------
// Cego XML space management
//     
// Design and Implementation by Bjoern Lemke
//
// (C)opyright 2000-2019 Bjoern Lemke
//
// INTERFACE MODULE
//
// Class: CegoXMLSpace 
// 
// Description: XML based database control file management
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

// base includes
#include <lfcbase/ListT.h>
#include <lfcbase/SetT.h>
#include <lfcbase/Chain.h>
#include <lfcbase/Logger.h>

// xml includes
#include <lfcxml/Document.h>

// cego includes
#include "CegoDefs.h"

class CegoXMLSpace {
    
public:

    enum AccessMode { READ, WRITE, MODIFY, EXEC, ALL };

    CegoXMLSpace(const Chain& xmlDef);
    ~CegoXMLSpace();

    Element* getDbSpec();

    Element* getTableSetInfo(const Chain& tableSet);
    void setTableSetInfo(const Chain& tableSet, Element *pTS);

    Element* getTableSetList();
    Element* getNodeList();

    void getTableSetList(ListT<Chain>& tsList);

    Chain getDbName();

    int getPageSize();
	
    void addHost(const Chain& hostName, const Chain& status);
    void setHostStatus(const Chain& hostName, const Chain& status);
    void getStatusByHost(const Chain& hostName, Chain& status);
    void removeHost(const Chain& hostName);

    int getSelectTimeout();
    int getQueueDelay();
    
    int getNumRBRecordSema();
    int getNumRecordSema();
    int getNumSysRecordSema();
    int getNumSysPageSema();
    int getNumDataPageSema();
    int getNumIndexPageSema();
    int getNumRBPageSema();
    int getNumDataFileSema();
    int getNumBufferPoolSema();
    int getMaxFixTries();
    int getMaxPageDelete();

    int getPageLockTimeout();
    int getRecLockTimeout();
    int getFileLockTimeout();
    int getPoolLockTimeout();
    int getNumLockTries();

    int getMaxSendLen();

    PageIdType getNextPageOffset(int numPages);

    void setSysPageOffset(const int tabSetId, const PageIdType pageOffset);
    PageIdType getSysPageOffset(const int tabSetId);
    
    void setTempPageOffset(const int tabSetId, const PageIdType pageOffset);
    PageIdType getTempPageOffset(const int tabSetId);
	
    bool allowDuplicateNull();
    
    char getCaseSensitiveFlag();

    void setQuoteEscapeMode(bool m);
    bool isQuoteEscapeMode();

    Chain getDateTimeFormat();
    ListT<Chain> getDateFormatList();

    void setArchRestoreProg(const Chain& progname);
    Chain getArchRestoreProg();

    void setArchRestoreTimeout(int timeout);
    int getArchRestoreTimeout();

    void setBackupProg(const Chain& progname);
    Chain getBackupProg();
    
    void setUserPwd(const Chain& user, const Chain& password);
    Chain getUserPwd(const Chain& user);

    bool isArchiveMode(int tabSetId);
    bool isArchiveMode(const Chain& tableSet);

    void enableArchLog(const Chain& tableSet);
    void disableArchLog(const Chain& tableSet);

    void addUser(const Chain& user, const Chain& password);
    void removeUser(const Chain& user);
    void changePassword(const Chain& user, const Chain& password);    
    void assignUserRole(const Chain& user, const Chain& role);
    void removeUserRole(const Chain& user, const Chain& role);

    void createRole(const Chain& role);
    void dropRole(const Chain& role);

    Element* getPermInfo(const Chain& role);
    void setPerm(const Chain& role, const Chain& permid, const Chain& tableset, const Chain& filter, const Chain& perm);
    void removePerm(const Chain& role, const Chain& permid);

    Chain getUserRole(const Chain& user);
    void setUserTrace(const Chain& user, bool isOn);
    
    bool checkAdminUser(const Chain& user, const Chain& password);

    
    void getAdminUser(Chain& user, Chain& password);
    
    bool checkUser(const Chain& user, const Chain& password, Chain& msg, bool& isTrace);
    void incUserQuery(const Chain& user);
    Element* getUserList();
    Element* getRoleList();
    
    Chain getPrimary(const int tabSetId);
    Chain getPrimary(const Chain& tabSetName);
    Chain getSecondary(const int tabSetId);
    Chain getSecondary(const Chain& tabSetName);
    Chain getMediator(const int tabSetId);
    Chain getMediator(const Chain& tabSetName);

    void setPrimary(const Chain& tabSetName, const Chain& hostName);
    void setSecondary(const Chain& tabSetName, const Chain& hostName);
    void setMediator(const Chain& tabSetName, const Chain& hostName);

    void getMedList(const Chain& hostname, ListT<Chain>& medList);
    void getTSforMedAndPrim(const Chain& mediator, const Chain& primary, ListT<Chain>& tsList);

    int getTabSetId(const Chain& tabSetName) const;
    Chain getTabSetName(int tabSetId);
    int getTmpFid(const Chain& tabSetName);

    void setTSSysSize(const Chain& tabSetName, int sysSize);
    int getSysSize(const Chain& tabSetName);

    void setTSTmpSize(const Chain& tabSetName, int tmpSize);
    int getTmpSize(const Chain& tabSetName);

    void setTSLogNum(const Chain& tabSetName, int logNum);
    void setTSLogSize(const Chain& tabSetName, int logSize);
    void resetTSRoot(const Chain& tableSet, const Chain& tsRoot);

    void setTSAppSize(const Chain& tabSetName, int appSize);

    void setAutoCorrect(const Chain& tabSetName, bool isAutoCorrect);
    bool getAutoCorrect(const Chain& tabSetName);

    void setTableCacheMode(const Chain& tabSetName, bool isEnabled);
    bool getTableCacheMode(const Chain& tabSetName);

    void setMaxTableCacheEntry(const Chain& tabSetName, int numEntry);
    int getMaxTableCacheEntry(const Chain& tabSetName);
    
    void setMaxTableCacheSize(const Chain& tabSetName, int cacheSize);
    int getMaxTableCacheSize(const Chain& tabSetName);
        
    void setQueryCacheMode(const Chain& tabSetName, bool isEnabled);
    bool getQueryCacheMode(const Chain& tabSetName);

    void setMaxQueryCacheEntry(const Chain& tabSetName, int numEntry);
    int getMaxQueryCacheEntry(const Chain& tabSetName);
    
    void setMaxQueryCacheSize(const Chain& tabSetName, int cacheSize);
    int getMaxQueryCacheSize(const Chain& tabSetName);

    void setCheckPointDump(const Chain& tabSetName, bool isEnabled);
    bool checkPointDumpEnabled(int tabSetId);

    void addTableSetDef(const Chain& tabSetName,
			const Chain& tsRoot,
			const Chain& primary,
			const Chain& secondary,
			const Chain& mediator,
			int sysFileId, int tempFileId, int sysFileSize, int tmpFileSize, int appFileSize,
			int logFileSize, int logFileNum, unsigned long long sortAreaSize);

    void rmTableSetDef(const Chain& tabSetName);

    void setDBHost(const Chain& dbHost);
    void getDBHost(Chain& dbHost);
    void getDataPort(int& dataPort);
    void getAdminPort(int& adminPort);
    void getLogPort(int& logPort);
    void getPidFile(Chain& pidFile);
    
    void setXmlDef(const Chain& xmlDef);

    void initXml(const Chain& dbName, int pageSize, const Chain& hostName, int dbPort, int admPort, int logPort, const Chain& pidFile,
		 const Chain& logLevel, const Chain& csmode, bool qescmode);
    void xml2Doc();
    void doc2Xml();
    void initDoc();
    
    void setTSRoot(const Chain& tableSet, const Chain& tsRoot);
    Chain getTSRoot(const Chain& tableSet);    

    void setTSTicket(const Chain& tableSet, const Chain& tsTicket);
    Chain getTSTicket(const Chain& tableSet);

    unsigned long long getTID(const Chain& tableSet);

    bool tableSetExists(const Chain& tableSet);

    void setTSSortAreaSize(const Chain& tabSetName, unsigned long long sortAreaSize);
    unsigned long long getTSSortAreaSize(int tabSetId);
    
    void setTSLogUser(const Chain& tabSetName, const Chain& logUser);
    Chain getTSLogUser(const Chain& tableSet);

    
    unsigned long long nextTID(int tabSetId);
    int nextFID();
    int nextTSID();

    void getAllActiveTableSet(ListT<Chain>& tsList);
    void getActiveTableSet(const Chain& primary, ListT<Chain>& tsList, bool includeRecovery = true);
    ListT<int> getOnlineTableSet() const;
    
    Chain getTableSetRunState(int tabSetId);
    void setTableSetRunState(int tabSetId, const Chain& status);
    
    Chain getTableSetRunState(const Chain& tableSet);
    void setTableSetRunState(const Chain& tableSet, const Chain& status);

    Chain getTableSetSyncState(const Chain& tableSet);
    void setTableSetSyncState(const Chain& tableSet, const Chain& status);
    
    void setCommittedLSN(int tabSetId, unsigned long long lsn);
    void setCommittedLSN(const Chain& tableSet, unsigned long long lsn);
    unsigned long long getCommittedLSN(const Chain& tableSet);

    void getArchLogInfo(int tabSetId, ListT<Chain>& archIdList, ListT<Chain>& archPathList);
    void getArchLogInfo(const Chain& tableSet, ListT<Chain>& archIdList, ListT<Chain>& archPathList);
    void getOccupiedLogList(int tabSetId, ListT<Chain>& occupiedLogList);
    void setLogFileStatus(int tabSetId, const Chain& logFile, const Chain& status);

    bool addArchLog(const Chain& tableSet, const Chain& archId, const Chain& archPath);
    bool removeArchLog(const Chain& tableSet, const Chain& archId);
    
    void addDataFile(const Chain& tableSet, const Chain& type, int fileId, const Chain& fileName, int fileSize);

    void getLogFileInfo(const Chain& tableSet, ListT<Chain>& lfList, ListT<int>& sizeList, ListT<Chain>& statusList);
    void setLogFileStatus(const Chain& tableSet, const Chain& logFile, const Chain& status);

    void getDataFileInfo(const Chain& tableSet, ListT<Chain>& dfList);
    void getDataFileInfo(const Chain& tableSet, const Chain& type, ListT<Chain>& dfList, ListT<int>& fidList, ListT<int>& sizeList );

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

    void addCounter(int tabSetId, const Chain& counterName, unsigned long long initValue, bool forceSet = false);

    unsigned long long getCounterValue(int tabSetId, const Chain& counterName, unsigned long long incValue = 0);
    unsigned long long setCounterValue(int tabSetId, const Chain& counterName, unsigned long long value);

    void removeCounter(int tabSetId, const Chain& counterName);
    void getCounterList(int tabSetId, ListT<Chain>& counterNameList);

    void setCheckpointInterval(const Chain& tableSet, int timeout);
    int getCheckpointInterval(const Chain& tableSet);

    void setTSInitFile(const Chain& tableSet, const Chain& initFile);
    Chain getTSInitFile(const Chain& tableSet);

    void getRoleSet(const Chain& user, SetT<Chain>& roleSet);

    bool matchRole(const Chain& role, const Chain tableSet, const Chain& objPattern, AccessMode perm);

    bool getModuleList(ListT<Chain> &modList);
    Logger::LogLevel getLogLevel(const Chain& module);

    Chain getSysFileName(const Chain& tableSet);
    Chain getTmpFileName(const Chain& tableSet);

private:

    void P() const;
    void V() const;

    void getDBHostLocked(Chain& dbHost);
    
    Element* getTableSetElement(const Chain& tableSet) const;
    Element* getCachedTableSetElement(int tabSetId);

    bool fitsPerm(const Chain& perm, AccessMode req);
    
    Document *_pDoc;    
    Chain _xmlDef;

    Element* _tsCache[TABMNG_MAXTABSET];
};

#endif
