#ifndef _CEGODATABASEMANAGER_H_INCLUDED_
#define _CEGODATABASEMANAGER_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoDatabaseManager.h
// ---------------------
// Cego database manager
//     
// Design and Implementation by Bjoern Lemke
//
// (C)opyright 2000-2010 Bjoern Lemke
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; see the file COPYING.  If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
//
// INTERFACE MODULE
//
// Class: CegoGlobalSpace 
// 
// Description: General database manager
//
// Status: QG-2.6
//
///////////////////////////////////////////////////////////////////////////////

#include <lfc/ListT.h>
#include <lfc/Chain.h>

#include "CegoBufferPool.h"
#include "CegoDistDbHandler.h"
#include "CegoDefs.h"

class CegoDatabaseManager : public CegoBufferPool {
    
 public:

    enum RecoveryMode { REQOFF, OFF, ON};

    enum ObjectUseMode { SHARED, EXCLUSIVE, EXCLUSIVE_WRITE };

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

    void beat();

    void startRecovery(const Chain& tableSet);

    void startCopy(const Chain& tableSet, 
		   const Chain& targetHost, 
		   const Chain& mediatorHost, 
		   const Chain& user, 
		   const Chain& passwd,
		   const Chain& msg);

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

    void setAllRecoveryOff();

    bool nextRecovery(Chain& tableSet);
    bool nextCopy(int &id, Chain& tableSet, Chain& targetHost, Chain& mediatorHost, Chain& user, Chain& passwd);
    void setCopyStatus(int id, const Chain& msg);

    void addObject(int tabSetId, const Chain& objName, CegoObject::ObjectType type);
    void useObject(int tabSetId, const Chain& objName, CegoObject::ObjectType type, ObjectUseMode mode, long tid = 0 );
    void unuseObject(int tabSetId, const Chain& objName, CegoObject::ObjectType type, ObjectUseMode mode);
    void removeObject(int tabSetId, const Chain& objName, CegoObject::ObjectType type);

    bool objectExists(int tabSetId, const Chain& objName, CegoObject::ObjectType type);

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

    void increaseActiveDbThread();
    void decreaseActiveDbThread();

    void increaseActiveLogThread();
    void decreaseActiveLogThread();

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

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

    CegoDistDbHandler* allocateSession(const Chain& hostName, const Chain& tableSet, 
				       const Chain& userName, const Chain& password);
    void releaseSession(CegoDistDbHandler* pSH);
    void cleanSession(int lifetime);
    
    Element* getSessionInfo(int lifetime);
    Element* getCopyInfo();

    void configureLogger();
    void configureLogger(Logger::LogLevel level);
    bool isLoggerConfigured();

    bool verifyAccess(const int 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);
    

private:


    CegoDistDbHandler* createSession(const Chain& hostName, const Chain& tableSet,
				     const Chain& userName, const Chain& password);

    void closeSession(CegoDistDbHandler* pSH);

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

    class ObjectRecord {
	
    public:
	
	ObjectRecord();
	ObjectRecord(const int tabSetId, const Chain& objName, CegoObject::ObjectType type);

	~ObjectRecord();

	const int getTabSetId() const;

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

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

	void setTid(long tid);	
	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;
	int _tabSetId;
	int _numUsed;
	ObjectUseMode _mode;
	long _tid;
    };

    class CopyRecord {
	
    public:
	
	CopyRecord();
	CopyRecord(const Chain& tableSet, const Chain& targetHost, const Chain& mediatorHost, const Chain& user, const Chain& passwd, const Chain& msg);
	~CopyRecord();

	int getId() const;
	void setId(int id);

	const Chain& getTableSet() const;
	const Chain& getTargetHost() const;
	const Chain& getMediatorHost() const;
	
	const Chain& getUser() const;
	const Chain& getPasswd() const;
	
	void setMsg(const Chain& msg);
	const Chain& getMsg() const;

	CopyRecord& operator = ( const CopyRecord& cr);
        bool operator == ( const CopyRecord& cr);
	
	friend ostream& operator << (ostream& s, const CopyRecord& cr)
	{
	    s << "(" << cr._tableSet << "," << cr._targetHost << "," << cr._mediatorHost << ","  << cr._user << "," << cr._passwd << ")";
	    return s;
	}

    private:

	int _id;
	Chain _tableSet;
	Chain _targetHost;
	Chain _mediatorHost;

	Chain _user;
	Chain _passwd;	
	Chain _msg;
    };

    class DbSessionRecord {
	
    public:
	
	DbSessionRecord();
	DbSessionRecord(CegoDistDbHandler* pHandler);
	DbSessionRecord(const Chain& hostName, const Chain& tableSet, const Chain& userName, CegoDistDbHandler* pHandler);
	~DbSessionRecord();

	const Chain& getHostName() const;
	const Chain& getTableSet() const;
	const Chain& getUserName() const;

	bool isUsed() const;
	void setUsed(bool isUsed);
	int getTSLastUsed();
	void setTSLastUsed(int ts);

	CegoDistDbHandler* getDbHandler() const;


	DbSessionRecord& operator = ( const DbSessionRecord& sr);
        bool operator == ( const DbSessionRecord& sr);
	
	friend ostream& operator << (ostream& s, const DbSessionRecord& sr)
	{
	    s << "(" << sr._tableSet << "," << sr._hostName << ")";
	    return s;
	}

    private:

	Chain _hostName;
	Chain _tableSet;
	Chain _userName;
	int _lastUsed;
	bool _isUsed;
	CegoDistDbHandler* _pHandler;
    };

    ListT<ObjectRecord> _objList;
    ListT<CopyRecord> _copyList;
    ListT<DbSessionRecord> _dbSessionList;

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

    int _activeDbThread;
    int _activeAdmThread;
    int _activeLogThread;

    int _nextCopyId;

    unsigned long _nextBeat;

    CegoDbHandler::ProtocolType _protType;

    Chain _lckFileName;
    bool _logConfigured;
    unsigned long _modId;
};

#endif




