///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoAdmNet.cc
// ----------
// Cego net client interface
//      
// Design and Implementation by Bjoern Lemke
//     
// (C)opyright 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.
//
// IMPLEMENTATION MODULE
//
// Class: CegoAdmNet
// 
// Description: 
//
// Status: QG-2.6
//
///////////////////////////////////////////////////////////////////////////////

// cego includes
#include "CegoAdmNet.h"
#include "CegoDefs.h"

#include <lfc/Net.h>

CegoAdmNet::CegoAdmNet()
{
    _pN = 0;
    _pAH = 0;
    _pModule = 0;
}

CegoAdmNet::CegoAdmNet(const Chain& logFile, const Chain& logLevel)
{
    _logFile = logFile;
    _logLevel = logLevel;
    _pN = 0;
    _pAH = 0;
    _pModule = 0;
}

CegoAdmNet::~CegoAdmNet()
{
    if ( _pAH )
	delete _pAH;
    if ( _pN ) 
	delete _pN;
    if ( _pModule )
	delete _pModule;
}

void CegoAdmNet::connect(const Chain& serverName, int port, const Chain& user, const Chain& pwd)
{
    Net n (  NETMNG_MSG_BUFLEN, NETMNG_SIZEBUFLEN );

    _pN = n.connect(serverName, port);

    if ( _logFile.length() > 1 )
    {
	_pModule = new CegoModule(_logFile);
	
	int modId = 100;
	
	if ( _logLevel == Chain("notice"))
	    _pModule->logModule(modId, "dbdimp", Logger::NOTICE);
	else if ( _logLevel == Chain("error"))
	    _pModule->logModule(modId, "dbdimp", Logger::LOGERR);
	else if ( _logLevel == Chain("debug"))
	    _pModule->logModule(modId, "dbdimp", Logger::DEBUG);
	else
	    _pModule->logModule(modId, "dbdimp", Logger::NONE);
	
    }
    else
    {
	_pModule = new CegoModule;
    }


    _pAH = new CegoAdminHandler( _pModule, _pN);
    
    CegoAdminHandler::ResultType res = _pAH->requestSession(user, pwd);
    if ( res != CegoAdminHandler::ADM_OK )
    {
	Chain msg;
	_pAH->getMsg(msg);
	throw Exception(EXLOC, msg);
    }
}

void CegoAdmNet::getTableSetInfo(const Chain& tableSet, 
				 ListT<Chain>& tsInfoList, 
				 ListT<Chain>& fileInfoList,
				 ListT<Chain>& logInfoList)
{

    CegoAdminHandler::ResultType res;    
    res = _pAH->medGetDetailedTableSetInfo(tableSet);
    handleMedResult(res);
        
    CegoTableObject oe;
    ListT<ListT<CegoFieldValue> > tsinfo;
    
    _pAH->getDetailedTableSetInfo(oe, tsinfo);
        
    ListT<CegoFieldValue> *pTSI = tsinfo.First();
    while ( pTSI )
    {
	Chain attr;
	Chain val;

	CegoFieldValue *pF = pTSI->First();
	if ( pF )
	    attr = pF->valAsChain();
	pF = pTSI->Next();
	if ( pF )
	    val = pF->valAsChain();
	
	Chain attrVal = attr + Chain(":") + val;
	tsInfoList.Insert( attrVal );
	pTSI = tsinfo.Next();
    }


    Chain format;
    ListT<ListT<CegoFieldValue> > fileinfo;
    _pAH->getDataFileInfo(oe, fileinfo, format);

    ListT<CegoFieldValue> *pFI = fileinfo.First();
    while ( pFI )
    {

	Chain name;
	Chain type;
	Chain size;
	Chain used;

	CegoFieldValue *pF = pFI->First();
	if ( pF )
	    name = pF->valAsChain();
	pF = pFI->Next();
	if ( pF )
	    type = pF->valAsChain();

	pF = pFI->Next();
	if ( pF )
	    size = pF->valAsChain();

	pF = pFI->Next();
	if ( pF )
	    used = pF->valAsChain();
	
	Chain attrVal = name + Chain(":") + type + Chain(":") + size + Chain(":") + used;
	fileInfoList.Insert( attrVal );

	pFI = fileinfo.Next();
    }


    ListT<ListT<CegoFieldValue> > loginfo;
    _pAH->getLogInfo(oe, loginfo);

    ListT<CegoFieldValue> *pLI = loginfo.First();
    while ( pLI )
    {

	Chain name;
	Chain status;
	Chain size;
	Chain offset;
	Chain usage;

	CegoFieldValue *pF = pLI->First();
	if ( pF )
	    name = pF->valAsChain();
	pF = pLI->Next();
	if ( pF )
	    status = pF->valAsChain();

	pF = pLI->Next();
	if ( pF )
	    size = pF->valAsChain();

	pF = pLI->Next();
	if ( pF )
	    offset= pF->valAsChain();

	pF = pLI->Next();
	if ( pF )
	    usage= pF->valAsChain();
	

	Chain attrVal = name + Chain(":") + status + Chain(":") + size + Chain(":") + offset + Chain(":") + usage;
	logInfoList.Insert( attrVal );

	pLI = loginfo.Next();
    }
}

void CegoAdmNet::getTableSetList(ListT<Chain>& tslist)
{
        
    CegoAdminHandler::ResultType res;
    
    res = _pAH->medGetTableSetList();
    handleMedResult(res);
        
    CegoTableObject oe;
    ListT<ListT<CegoFieldValue> > info;
    
    _pAH->getTableSetList(oe, info);
    
    ListT<CegoFieldValue> *pFL = info.First();
    while ( pFL )
    {
	CegoFieldValue *pF = pFL->First();
	if ( pF )
	    tslist.Insert(pF->valAsChain());
	pFL = info.Next();
    }
}

void CegoAdmNet::startTableSet(const Chain& tableSet, bool doCleanup, bool forceload)
{

    CegoAdminHandler::ResultType res;
    res = _pAH->medStartTableSet(tableSet, doCleanup, forceload);

    handleMedResult(res);
    
}

void CegoAdmNet::stopTableSet(const Chain& tableSet)
{
    CegoAdminHandler::ResultType res;    
    res = _pAH->medStopTableSet(tableSet);
    handleMedResult(res);   
}

void CegoAdmNet::getThreadInfo(ListT<Chain>& threadInfoList)
{

    CegoAdminHandler::ResultType res;
    
    res = _pAH->reqThreadInfo();
    handleMedResult(res);	

    CegoTableObject oe;
    ListT<ListT<CegoFieldValue> > threadinfo;

    _pAH->getThreadInfo(oe, threadinfo);

    ListT<CegoFieldValue> *pTI = threadinfo.First();
    while ( pTI )
    {

	Chain id;
	Chain status;

	CegoFieldValue *pF = pTI->First();
	if ( pF )
	    id = pF->valAsChain();
	pF = pTI->Next();
	if ( pF )
	    status = pF->valAsChain();

	Chain attrVal = id + Chain(":") + status;
	threadInfoList.Insert( attrVal );

	pTI = threadinfo.Next();
    }
}

void CegoAdmNet::getDbThreadInfo(ListT<Chain>& dbThreadInfoList)
{
    
    CegoAdminHandler::ResultType res;

    res = _pAH->reqDbThreadInfo();	
    handleMedResult(res);
    
    CegoTableObject oe;
    ListT<ListT<CegoFieldValue> > dbthreadinfo;
    
    Chain format;
    _pAH->getDbThreadInfo(oe, dbthreadinfo, format);

    ListT<CegoFieldValue> *pDBTI = dbthreadinfo.First();
    while ( pDBTI )
    {

	Chain id;
	Chain numReq;
	Chain status;
	Chain lastAction;

	CegoFieldValue *pF = pDBTI->First();
	if ( pF )
	    id = pF->valAsChain();
	pF = pDBTI->Next();
	if ( pF )
	    numReq = pF->valAsChain();
	pF = pDBTI->Next();
	if ( pF )
	    status = pF->valAsChain();

	CegoTableObject oe;
	ListT<ListT<CegoFieldValue> > lastactioninfo;
	
	Chain format;
	_pAH->getDbThreadLastQuery(id.asInteger(), oe, lastactioninfo, format);
	ListT<CegoFieldValue> *pLAI = lastactioninfo.First();
	if ( pLAI )
	{
	    CegoFieldValue *pF = pLAI->First();
	    if ( pF )
		lastAction = pF->valAsChain();	    
	}

	Chain attrVal = id + Chain(":") + numReq + Chain(":") + status + Chain(":") + lastAction;
	
	dbThreadInfoList.Insert( attrVal );

	pDBTI = dbthreadinfo.Next();
    }
}

void CegoAdmNet::getAdmThreadInfo(ListT<Chain>& admThreadInfoList)
{
    CegoAdminHandler::ResultType res;
    
    res = _pAH->reqAdmThreadInfo();
    handleMedResult(res);
    
    CegoTableObject oe;
    ListT<ListT<CegoFieldValue> > admthreadinfo;
    
    Chain format;
    _pAH->getAdmThreadInfo(oe, admthreadinfo, format);

    ListT<CegoFieldValue> *pAdmTI = admthreadinfo.First();
    while ( pAdmTI )
    {

	Chain id;
	Chain numReq;
	Chain status;

	CegoFieldValue *pF = pAdmTI->First();
	if ( pF )
	    id = pF->valAsChain();
	pF = pAdmTI->Next();
	if ( pF )
	    numReq = pF->valAsChain();
	pF = pAdmTI->Next();
	if ( pF )
	    status = pF->valAsChain();

	Chain attrVal = id + Chain(":") + numReq + Chain(":") + status;
	
	admThreadInfoList.Insert( attrVal );

	pAdmTI = admthreadinfo.Next();
    }
}

void CegoAdmNet::getLogThreadInfo(ListT<Chain>& logThreadInfoList)
{
    CegoAdminHandler::ResultType res;
    
    res = _pAH->reqLogThreadInfo();
    handleMedResult(res);
    
    CegoTableObject oe;
    ListT<ListT<CegoFieldValue> > logthreadinfo;
    
    Chain format;
    _pAH->getLogThreadInfo(oe, logthreadinfo, format);

    ListT<CegoFieldValue> *pLogTI = logthreadinfo.First();
    while ( pLogTI )
    {

	Chain id;
	Chain numReq;
	Chain status;

	CegoFieldValue *pF = pLogTI->First();
	if ( pF )
	    id = pF->valAsChain();
	pF = pLogTI->Next();
	if ( pF )
	    numReq = pF->valAsChain();
	pF = pLogTI->Next();
	if ( pF )
	    status = pF->valAsChain();

	Chain attrVal = id + Chain(":") + numReq + Chain(":") + status;
	
	logThreadInfoList.Insert( attrVal );

	pLogTI = logthreadinfo.Next();
    }
}

void CegoAdmNet::importTableSet(const Chain& tableSet, const Chain& impMode, const Chain& impFile)
{

    CegoAdminHandler::ResultType res;
    bool isStructure=false;
    bool doLogging=false;
    
    res = _pAH->reqImportTableSet(tableSet, isStructure, impFile, doLogging, impMode);
    handleMedResult(res);
        
}

void CegoAdmNet::exportTableSet(const Chain& tableSet, const Chain& expMode, const Chain& expFile)
{
    CegoAdminHandler::ResultType res;
    bool isStructure=false;
    res = _pAH->reqExportTableSet(tableSet, isStructure, expFile, expMode);
    handleMedResult(res);        
}

   
void CegoAdmNet::addDataFile(const Chain& tableSet, const Chain& fileType, const Chain& dataFile, int numPages)
{
    CegoAdminHandler::ResultType res;    
    res = _pAH->medAddDataFile(tableSet, fileType, dataFile, numPages);
    handleMedResult(res);
}


void CegoAdmNet::defineTableSet(const Chain& tableSet, 
				const Chain& tsRoot,
				const Chain& tsTicket,
				const Chain& primary,
				const Chain& secondary,
				int sysSize,
				int tmpSize,
				int logSize,
				int logNum, 
				long orderSize)
{
    
    CegoAdminHandler::ResultType res;
    res = _pAH->medDefineTableSet(tableSet,
				  tsRoot,
				  tsTicket,
				  primary,
				  secondary,
				  sysSize,
				  tmpSize,
				  logSize,
				  logNum, 
				  orderSize);
    handleMedResult(res);

}


void CegoAdmNet::createTableSet(const Chain& tableSet)
{
    CegoAdminHandler::ResultType res;   
    res = _pAH->medCreateTableSet(tableSet);
    handleMedResult(res);
}

void CegoAdmNet::dropTableSet(const Chain& tableSet) 
{
    CegoAdminHandler::ResultType res;   
    res = _pAH->medDropTableSet(tableSet);
    handleMedResult(res);
}

void CegoAdmNet::switchSecondary(const Chain& tableSet)
{
    CegoAdminHandler::ResultType res;
    res = _pAH->medSecSwitch(tableSet);
    handleMedResult(res);
}

void CegoAdmNet::switchMediatorAction(const Chain& tableSet)
{
    CegoAdminHandler::ResultType res;
    res = _pAH->secMedSwitch(tableSet);
    handleMedResult(res);
}

void CegoAdmNet::relocateSecondary(const Chain& tableSet, const Chain& secondary)
{
    CegoAdminHandler::ResultType res;
    res = _pAH->medSecRelocate(tableSet, secondary);
    handleMedResult(res);
}

void CegoAdmNet::relocateMediator(const Chain& tableSet, const Chain& mediator)
{
    CegoAdminHandler::ResultType res;
    res = _pAH->secMedRelocate(tableSet, mediator);
    handleMedResult(res);
}

void CegoAdmNet::recoverTableSet(const Chain& tableSet, int pit)
{
    CegoAdminHandler::ResultType res;
    res = _pAH->medRecover(tableSet, pit);
    handleMedResult(res);
}


void CegoAdmNet::handleMedResult(CegoAdminHandler::ResultType res)
{

    Chain msg;
    _pAH->getMsg(msg);
    
    bool doQuiet=true;

    if ( res == CegoAdminHandler::ADM_ERROR )
    {
	throw Exception(EXLOC, msg);
    }
    
    while ( res == CegoAdminHandler::ADM_INFO )
    {
	
	if ( doQuiet == false )
	{
	    Chain hostRole;
	    Chain hostName;
	    Chain msg;
	    
	    _pAH->getHostRole(hostRole);
	    _pAH->getHostName(hostName);
	    _pAH->getMsg(msg);
	    
	    ListT<CegoFieldValue> fvl;
	    fvl.Insert(CegoFieldValue(VARCHAR_TYPE, hostRole));
	    fvl.Insert(CegoFieldValue(VARCHAR_TYPE, hostName));
	    fvl.Insert(CegoFieldValue(VARCHAR_TYPE, msg));
	    
	}

	res = _pAH->nextInfo();
	
    }
    
    _pAH->getMsg(msg);
    
    if ( res == CegoAdminHandler::ADM_OK )
    {
	// ok
    }
    else if ( res == CegoAdminHandler::ADM_ERROR )
    {
	throw Exception(EXLOC, msg);
    }
}


   
void CegoAdmNet::disconnect()
{        
    _pAH->closeSession();
}
