#ifndef _CEGODATABASEMANAGER_H_INCLUDED_
#define _CEGODATABASEMANAGER_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoDatabaseManager.h
// ---------------------
// Cego database manager
//     
// Design and Implementation by Bjoern Lemke
//
// (C)opyright 2000-2025 Bjoern Lemke
//
// INTERFACE MODULE
//
// Class: CegoDatabaseManager 
// 
// Description: General database manager
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

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

// CEGO INCLUDES
#include "CegoBufferPool.h"
#include "CegoDbHandler.h"
#include "CegoQueryCache.h"
#include "CegoTableCache.h"
#include "CegoDefs.h"

class CegoTableManager;

class CegoDatabaseManager : public CegoBufferPool {
    
 public:

    enum RecoveryMode { REQOFF, OFF, ON};

    enum ObjectUseMode { SHARED, EXCLUSIVE_WRITE };

    CegoDatabaseManager(const Chain& xmlDef, const Chain& lckFileName, const Chain& lockExpire, const Chain& logFile, const Chain& progName, CegoDbHandler::ProtocolType protType = CegoDbHandler::SERIAL);
    ~CegoDatabaseManager();

    void allocateQueryCache(const Chain& tableSet);
    void allocateTableCache(const Chain& tableSet);
    void releaseQueryCache(const Chain& tableSet);
    void releaseTableCache(const Chain& tableSet);

    CegoQueryCache* getQueryCache(const Chain& tableSet) const;
    CegoQueryCache* getQueryCache(unsigned tabSetId) const;
    CegoTableCache* getTableCache(const Chain& tableSet) const;
    CegoTableCache* getTableCache(unsigned tabSetId) const;

    void cleanCache(unsigned tabSetId, CegoObject::ObjectType objType, const Chain& objName);
    
    void beat();

    void checkTableSetRunState(unsigned tabSetId);
    
    void startRecovery(const Chain& tableSet);

    RecoveryMode getRecoveryMode(unsigned tabSetId);
    void setRecoveryMode(unsigned tabSetId, RecoveryMode m);

    void setAllRecoveryOff();

    bool nextRecovery(Chain& tableSet);

    void addObject(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type);

    void useObject(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type, ObjectUseMode mode, CegoTableManager *pTabMng);

    void unuseObject(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type, unsigned long long tid = 0 );
    void removeObject(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type);
    void removeAllObjects(unsigned tabSetId);
    
    bool objectExists(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type);
    
    void printObjectList();

    void setThreadInfo(unsigned numDbThread, unsigned numAdmThread);
    void getThreadInfo(unsigned& numDbThread, unsigned& numAdmThread,
		       unsigned& activeDbThread, unsigned& activeAdmThread, unsigned& activeLogThread);
    
    void increaseActiveAdmThread();
    void decreaseActiveAdmThread();

    void increaseActiveDbThread();
    void decreaseActiveDbThread();


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


    void configureLogger();

    bool isLoggerConfigured();

    bool verifyJDBC(const Chain& user);
    bool verifyAccess(const unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type, CegoXMLSpace::AccessMode mode, const Chain& user);

    void initLogFiles(const Chain& tableSet, bool overwrite);
    void releaseLogFiles(const Chain& tableSet, bool waitForArchive);

    CegoDbHandler::ProtocolType getProtType() const;

    bool getQCLockStat(unsigned tabSetId, unsigned& lockCount, unsigned long long &numRdLock, unsigned long long &numWrLock, unsigned long long &sumRdDelay, unsigned long long &sumWrDelay);

    void getAggQCLockStat(Chain& lockGroup, unsigned& numLock, unsigned& lockCount, unsigned long long &numRdLock, unsigned long long &numWrLock, unsigned long long &sumRdDelay, unsigned long long &sumWrDelay);

    bool getTCLockStat(unsigned tabSetId, unsigned& lockCount, unsigned long long &numRdLock, unsigned long long &numWrLock, unsigned long long &sumRdDelay, unsigned long long &sumWrDelay);

    void getAggTCLockStat(Chain& lockGroup, unsigned& numLock, unsigned& lockCount, unsigned long long &numRdLock, unsigned long long &numWrLock, unsigned long long &sumRdDelay, unsigned long long &sumWrDelay);

    
    Chain getTSTicket(const Chain& tableSet) const;

    void verifyLocks(CegoAdminHandler* pAH);
    
private:


    void PR();
    void PW();
    void V();

    void configureLogger(Logger::LogLevel level);
	
    class ObjectRecord {
	
    public:
	
	ObjectRecord();
	ObjectRecord(const unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type);

	~ObjectRecord();

	const unsigned getTabSetId() const;

	const Chain& getName() const;
	const CegoObject::ObjectType getType() const;

	void incUsed();
	void decUsed();
	unsigned numUsed() const;

	void setMode(ObjectUseMode mode); 
	ObjectUseMode getMode() const;

	void setTid(unsigned long long tid);	
	unsigned long long getTid() const;

	ObjectRecord& operator = ( const ObjectRecord& t);
        bool operator == ( const ObjectRecord& t);
	
	friend ostream& operator << (ostream& s, const ObjectRecord& t)
	{
	    s << "(" << t._objName << "," << t._tabSetId << ")";
	    return s;
	}

    private:

	Chain _objName;
	CegoObject::ObjectType _type;
	unsigned _tabSetId;
	unsigned _numUsed;
	ObjectUseMode _mode;
	unsigned long long _tid;
    };


    ListT<ObjectRecord> _objList;

    RecoveryMode _recoveryMode[TABMNG_MAXTABSET];
    ListT<Chain> _recoveryList;
    
    unsigned _numDbThread;
    unsigned _numAdmThread;

    unsigned _activeDbThread;
    unsigned _activeAdmThread;

    CegoDbHandler::ProtocolType _protType;

    Chain _lckFileName;
    bool _logConfigured;

    CegoQueryCache* _pQueryCache[TABMNG_MAXTABSET];
    CegoTableCache* _pTableCache[TABMNG_MAXTABSET];
    
    unsigned long _modId;
};
#endif
