#ifndef _CEGOTABLEMANAGER_H_INCLUDED_
#define _CEGOTABLEMANAGER_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoTableManager.h
// ------------------
// Cego table manager class definition
// 
// 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: CegoTableManager
// 
// Description: 
//
// Status: QG-2.6
//
///////////////////////////////////////////////////////////////////////////////

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

// xml includes
#include <lfc/XMLOutStream.h>

// cego includes
#include "CegoDataType.h"
#include "CegoTupleState.h"
#include "CegoField.h"
#include "CegoPredDesc.h"
#include "CegoQueryHelper.h"
#include "CegoLockHandler.h"
#include "CegoTransactionManager.h"
#include "CegoAlterDesc.h"
#include "CegoDefs.h"
#include "CegoProcedure.h"
#include "CegoView.h"
#include "CegoSystemObject.h"
#include "CegoBTreeValue.h"

class CegoTransactionManager;
class CegoDbThreadPool;

class CegoTableManager : public CegoSystemObject {

public:

    enum IsolationLevel { READ_COMMITTED, READ_UNCOMMITTED };

    CegoTableManager(CegoDatabaseManager *pDBMng);
    ~CegoTableManager();

    void setAppend(bool doAppend);    

    void createTableSet(const Chain& tableSet);
    void dropTableSet(const Chain& tableSet);
    void cleanTableSet(const Chain& tableSet);

    void stopTableSet(const Chain& tableSet, bool archComplete);

    void resetTableSet(const Chain& tableSet);

    void beginBackup(const Chain& tableSet, const Chain& msg);
    void endBackup(const Chain& tableSet, const Chain&msg, bool keepTicket = true);
    void resetBUStat(const Chain& tableSet);

    void syncTableSet(const Chain& tableSet, const Chain& msg, const Chain& escCommand, int timeout);

    void logTo(const Chain& tableSet, const Chain& secondary);

    void addDataFile(const Chain& tableSet, const Chain& type, int fileId, const Chain& dataFile, int fileSize);
    
    long writeCheckPoint(const Chain& tableSet, bool switchLog,  bool archComplete, const Chain& escCmd = Chain(""), int timeout = ESCCMDTIMEOUT);

    // transaction methods

    void setIsolationLevel(IsolationLevel level);
    IsolationLevel getIsolationLevel() const;
    
    void setAutoCommit(bool autoCommit);
    bool getAutoCommit() const;

    void beginTransaction(int tabSetId);
    void getTransactionAffectedTables(int tabSetId, SetT<Chain>& tableList);
    long commitTransaction(int tabSetId);
    long rollbackTransaction(int tabSetId);
    int getTID(int tabSetId);
    int getTAStep(int tabSetId);

    void setTID(int tabSetId, int tid);

    void getTupleInfo(int tabSetId, const CegoDataPointer dp, int &tid, int &tastep, CegoTupleState &ts);
    void setTupleInfo(int tabSetId, const CegoDataPointer dp, int tid, int tastep, CegoTupleState ts);

    // table methods

    void createDataTable(int tabSetId, const Chain& tableName, CegoObject::ObjectType type, const ListT<CegoField>& fl, bool useColumnId = false);
    void alterDataTable(int tabSetId, const Chain& tableName, CegoObject::ObjectType type, const ListT<CegoAlterDesc>& alterList);
    void renameObject(int tabSetId, const Chain& objName,  CegoObject::ObjectType type, const Chain& newObjName);

    void reorgTable(int tabSetId, const Chain& tableName);


    void invalidateIndexForTable(int tabSetId, const Chain& tableName);

    void insertDataTable(CegoTableObject& oe,
			 ListT<CegoField>& fvl,
			 CegoDataPointer& dp, 
			 bool doLogging);


    void insertDataTable(CegoTableObject& oe,  ListT<CegoField>& fvl, 
			 const ListT<CegoTableObject>& idxList,
			 const ListT<CegoBTreeObject>& btreeList,
			 const ListT<CegoKeyObject>& keyList,
			 const ListT<CegoCheckObject>& checkList,
			 const CegoDataPointer& sysEntry,
			 const Chain& virginIndex,
			 CegoDataPointer& dp, 
			 bool doLogging);

    long deleteDataTable(CegoTableObject& oe, CegoPredDesc* pPred = 0 , CegoProcBlock* pBlock = 0);

    void deleteDataTable(int tabSetId, 
			 const Chain& tableName,
			 CegoObject::ObjectType type, 
			 const CegoDataPointer& dp,
			 const ListT<CegoField>& fvl, 
			 const ListT<CegoTableObject>& idxList,
			 const ListT<CegoBTreeObject>& btreeList,
			 const ListT<CegoKeyObject>& keyList,
			 bool doCheckKey = true, 
			 bool doIgnoreIndexError = false);

    long updateDataTable(int tabSetId, 
			 const Chain& tableName,
			 const Chain& tableAlias,
			 CegoPredDesc* pPred,
			 const ListT<CegoField>& updSchema, 
			 ListT<CegoExpr*>& exprList, 
			 // bool lastPage,
			 CegoProcBlock* pBlock);

    void dropTable(int tabSetId, 
		   const Chain& tableName, 
		   CegoObject::ObjectType type,
		   ListT<CegoTableObject>& idxList, 
		   ListT<CegoBTreeObject>& btreeList, 
		   ListT<CegoKeyObject>& keyList, 
		   ListT<CegoCheckObject>& checkList);
	
    void dropIndex(int tabSetId, const Chain& idxName);
    void dropBTree(int tabSetId, const Chain& btreeName);

    void dropView(int tabSetId, const Chain& viewName);
    void dropProcedure(int tabSetId, const Chain& procName);
    void dropFKey(int tabSetId, const Chain& fkey);
    void dropCheck(int tabSetId, const Chain& check);

    // utility cursor for native table traverse

    bool getFirstTuple(CegoObjectCursor* pC, ListT<CegoField>& fl, CegoDataPointer& dp);
    bool getNextTuple(CegoObjectCursor* pC, ListT<CegoField>& fl, CegoDataPointer& dp);


    // index and key creation

    
    void createPrimaryIndexTable(int tabSetId, const Chain& indexName, const Chain& tableName, ListT<CegoField>& schema);
    /*
    void createUniqueIndexTable(int tabSetId, const Chain& indexName, const Chain& tableName, ListT<CegoField>& schema);
    void createNonUniqueIndexTable(int tabSetId, const Chain& indexName, const Chain& tableName, ListT<CegoField>& schema);
    */


    void createIndexTable(int tabSetId, const Chain& indexName, const Chain& tabName, ListT<CegoField>& schema, CegoObject::ObjectType type);

    void createBTree(int tabSetId, const Chain& indexName, const Chain& tableName, ListT<CegoField>& schema, CegoObject::ObjectType type);

    void createAVLIndexTable(int tabSetId, const Chain& indexName, const Chain& tableName, ListT<CegoField>& schema, CegoObject::ObjectType type);

    void createForeignKey(int tabSetId, const Chain& fkey, const Chain& tableName, const ListT<CegoField>& keyList, const Chain& refTable, const ListT<CegoField>& refList);

    void createCheck(int tabSetId, const Chain& checkName, const Chain& tableName, CegoPredDesc *pPredDesc);

    // info methods

    void getPoolInfo(CegoTableObject& oe, ListT< ListT<CegoFieldValue> > &info);
    void getSystemInfo(const Chain& tableSet, CegoTableObject& oe,  ListT< ListT<CegoFieldValue> > &fa, Chain& format);

    // debugging methods

    void dumpObject(const Chain& tableSet, const Chain& tableName, CegoObject::ObjectType type, Chain& chainDump);
    void dumpObject(int tabSetId, const Chain& tableName, CegoObject::ObjectType type, Chain& chainDump);
    // void dumpLockHandler(Chain& lockDump);

    void abort();
    void proceed();
    bool isAborted() const;
    
    void addCompProcedure(int tabSetId, CegoProcedure *pProc);
    void removeCompProcedure(int tabSetId, const Chain& procName);
    bool checkCompProcedure(int tabSetId, const Chain& procName);
    CegoProcedure* getCompProcedure(int tabSetId, const Chain& procName);

    void addCompView(int tabSetId, CegoView *pView);
    void removeCompView(int tabSetId, const Chain& viewName);
    bool checkCompView(int tabSetId, const Chain& viewName);
    CegoView* getCompView(int tabSetId, const Chain& viewName);

    void removeAllComp(int tabSetId);    

    void getTSLockStat(int tabSetId, Chain& lockName, long& lockCount, long &numRdLock, long &numWrLock, long &sumRdDelay, long &sumWrDelay);
    void getLHLockStat(unsigned long lockId, Chain& lockName, long& lockCount, long &numRdLock, long &numWrLock, long &sumRdDelay, long &sumWrDelay);
    void getLHAggLockStat(const Chain& lockName, int& numLock, long& lockCount, long &numRdLock, long &numWrLock, long &sumRdDelay, long &sumWrDelay);
    
    void extractIndexValue(const ListT<CegoField>& tableSchema, const ListT<CegoField>& indexSchema, char* p, int len, int& idxLen);

    void initLock(int tabSetId);
    void regDataFiles(const Chain& tableSet, bool cleanIt = false);

    void releaseBlob(int tabSetId, int fileId, int pageId);

    unsigned char* getBlobData(int tabSetId, int fileId, int pageId, long& blobSize);
    void putBlobData(int tabSetId, unsigned char* data, long blobSize, int& fileId, int& pageId);
    
    CegoTransactionManager* getTransactionManager();

    void setPoolSyncInfo(CegoDbThreadPool *pPool, int thrIdx);

    void logIt(int tabSetId, CegoLogRecord& lr);

protected:
    
    CegoTransactionManager *_pTM;

    void finishOpenTransaction(int tabSetId);

private:
    
    void renameTable(int tabSetId, const Chain& tableName, const Chain& newTableName);
    void renameIndex(int tabSetId, const Chain& idxName, CegoObject::ObjectType type, const Chain& newIdxName);
    void renameKey(int tabSetId, const Chain& keyName, const Chain& newKeyName);
    void renameProcedure(int tabSetId, const Chain& keyName, const Chain& newKeyName);
    void renameView(int tabSetId, const Chain& viewName, const Chain& newViewName);
    void renameCheck(int tabSetId, const Chain& checkName, const Chain& newCheckName);
    void renameRBO(int tabSetId, const Chain& rboName, const Chain& newRboName);

    void updateTuple(CegoTableObject& oe,  const CegoDataPointer& sysEntry, const CegoDataPointer& dp, 
		     ListT<CegoField>& fl, const ListT<CegoField>& nfvl, ListT<CegoExpr*>& exprList, 
		     const ListT<CegoTableObject>& idxList,
		     const ListT<CegoBTreeObject>& btreeList,
		     const ListT<CegoKeyObject>& keyList,
		     const ListT<CegoCheckObject>& checkList,
		     const Chain& virginIndex,
		     // bool lastPage, 
		     CegoProcBlock* pBlock);


    bool archiveComplete(const Chain& tableSet);
    
    void checkTypes(const ListT<CegoField>& fl, const ListT<CegoField>& nfl);    
    void checkIntegrity(int tabSetId, const Chain& tableName, const CegoDataPointer& dp, const ListT<CegoField>& fvl, const ListT<CegoField>& nfvl);

    void getKeyAndIdxRef(int tabSetId, const Chain& tableName, const Chain& attrName, ListT<CegoKeyObject>& refKeyList, ListT<CegoTableObject>& refIdxList, ListT<CegoBTreeObject>& refBTreeList);
    bool keyReferenceExists(int tabSetId, const Chain& tableName, const ListT<CegoField>& fl, const ListT<CegoKeyObject>& keyList);    
    bool checkKeyIntegrity(const ListT<CegoKeyObject>& keyList, int tabSetId, const Chain& tableName, const ListT<CegoField>& fvl, const ListT<CegoField>& nfvl);
    bool checkIndexIntegrity(const ListT<CegoTableObject>& idxList, int tabSetId, const CegoDataPointer& dp, const ListT<CegoField>& fvl, const ListT<CegoField>& nfvl);
    bool checkBTreeIntegrity(const ListT<CegoBTreeObject>& btreeList, int tabSetId, const CegoDataPointer& dp, const ListT<CegoField>& fvl, const ListT<CegoField>& nfvl);
    
    const CegoFieldValue& getIndexSearchValue(const ListT<CegoField>& idxSchema, const ListT<CegoField>& nfvl);

    ListT<CegoBlob> getBlobs(int tabSetId, const ListT<CegoField>& fvl);

    void addBUStat(int tabSetId, const Chain& butype, const Chain& msg);

    void poolP();
    void poolV();

    int _tid[TABMNG_MAXTABSET];
    int _tastep[TABMNG_MAXTABSET];

    ListT<CegoField> _streamSchema;

    bool _isAborted;
    bool _autoCommit;
    bool _doAppend;

    IsolationLevel _isolationLevel;

    ListT<CegoProcedure*> _procList[TABMNG_MAXTABSET];
    ListT<CegoView*> _viewList[TABMNG_MAXTABSET];

    CegoQueryHelper _qh;

    CegoDbThreadPool *_pPool;
    int _thrIdx;

    unsigned long _modId;
};



#endif




