///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoDbHandler.cc
// -----------------
// Cego db handler class implementation
//                                                         
// Design and Implementation by Bjoern Lemke               
//     
// (C)opyright 2000-2012 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: CegoDbHandler
// 
// Description: 
//
// Status: QG-2.13
//
///////////////////////////////////////////////////////////////////////////////

#include <lfc/AESCrypt.h>
#include <lfc/Datetime.h>

#include <lfc/Element.h>

#include "CegoTypeConverter.h"
#include "CegoDbHandler.h"
#include "CegoXMLdef.h"
#include "CegoXMLHelper.h"
#include "CegoDefs.h"

#include <string.h>
#include <stdlib.h>

#define QUERY_MOREDATA 0
#define QUERY_ABORT 1
#define QUERY_RESET 2

// native requests
#define SER_OK "ok"
#define SER_SACK "sac"
#define SER_ERROR "err"
#define SER_INFO "inf"
#define SER_SDATA "sdt"
#define SER_FDATA "fdt"
#define SER_FIN "fin"
#define SER_PRODINFO "pci"
#define SER_PROCRES "pcr"
#define SER_SESSION "ses"
#define SER_QUERY "qry"
#define SER_QUERYABORT "abt"
#define SER_DBPRODINFO "dpi"

#define SER_BLOBINFO "bli"
#define SER_BLOBSIZE "bls"

#define SER_PUTBLOB "blp"
#define SER_GETBLOB "blg"
#define SER_DELBLOB "bld"

// distributed requests
#define SER_CREATETABLE "createtable"
#define SER_CREATEVIEW "creatview"
#define SER_CREATEPROCEDURE "createproc"
#define SER_CREATECHECK "createcheck"
#define SER_ALTERTABLE "altertable"
#define SER_CREATEINDEX "createindex"
#define SER_INSERT "insert"
#define SER_DELETE "delete"
#define SER_UPDATE "update"
#define SER_OBJECTINFO "objinfo"
#define SER_DROP_OBJECT "dropobj"
#define SER_GETTABLE "gettable"
#define SER_GETOBJLIST "getoblist"
#define SER_GETOBJLISTBYTABLE "getobjlistbytable"
#define SER_OBJRENAME "objrename"
#define SER_REORG "reorg"
#define SER_SYNC "sync"
#define SER_GETPAGECOUNT "getpgcount"
#define SER_STARTTRANSACTION "stta"
#define SER_COMMITTRANSACTION "ctta"
#define SER_ROLLBACKTRANSACTION "rbta"
#define SER_GETTID "gettid"
#define SER_SESSION_CLOSE "sesclose"

CegoDbHandler::CegoDbHandler(NetHandler *pN, CegoDbHandler::ProtocolType pt, CegoModule *pModule)
{
    _pN = pN;
    _pModule = pModule;
    _pRow = 0;

    _pSer = new CegoSerial(_pN);

    _protType = pt;
    
    if ( _protType == CegoDbHandler::XML )
    {
	Document *pDoc = new Document(XML_CEGO);
	pDoc->setAttribute(XML_VERSION_ATTR, XML_VERSION_VALUE);    
	_xml.setDocument(pDoc);
    }

    _wasReset = false;

    _modId = _pModule->getModId("CegoDbHandler");
}

CegoDbHandler::~CegoDbHandler()
{
    if ( _protType == CegoDbHandler::XML )
    {
	Document *pDoc = _xml.getDocument();
	pDoc->clear();
	delete pDoc;
    }
    if ( _pSer )
	delete _pSer;
}

CegoDbHandler::ResultType CegoDbHandler::requestSession(const Chain& tableSet, const Chain& user, const Chain& password, bool doEncrypt)
{   

#ifdef CGDEBUG
    _pModule->log(_modId, Logger::DEBUG, Chain("Request session for user ") + user + Chain("/") + password);
#endif

    if ( _protType == CegoDbHandler::XML )
    {

	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	
	pRoot->setAttribute(XML_TABLESET_ATTR, tableSet);   
	pRoot->setAttribute(XML_USER_ATTR, user);
	
	_tableSet = tableSet;
	
	if ( doEncrypt )
	{ 
	    AESCrypt aescrypt(CEGOAESKEY, CEGOAESKEYLEN);
	    pRoot->setAttribute(XML_PASSWD_ATTR, aescrypt.encrypt(password));
	}
	else
	{
	    pRoot->setAttribute(XML_PASSWD_ATTR, password);
	}
	return sendXMLReq(XML_DBSESSION_REQUEST, pRoot);
    }
    else
    {
	
	_tableSet = tableSet;
	
	Chain pwd;
	if ( doEncrypt )
	{ 
	    AESCrypt aescrypt(CEGOAESKEY, CEGOAESKEYLEN);
	    pwd =  aescrypt.encrypt(password);
	}
	else
	{
	    pwd = password;
	}

	_pSer->reset();
	_pSer->writeChain(Chain(SER_SESSION));
	_pSer->writeChain(tableSet);
	_pSer->writeChain(user);
	_pSer->writeChain(pwd);
	
	return sendSerialReq();
	
    }
}

CegoDbHandler::ResultType CegoDbHandler::closeSession()
{        
    if ( _protType == CegoDbHandler::XML )
    {
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	return sendXMLReq(XML_SESSION_CLOSE, pRoot);
    }
    else
    {
	_pSer->reset();
	_pSer->writeChain(Chain(SER_SESSION_CLOSE));	
	return sendSerialReq();
    }
}

bool CegoDbHandler::acceptSession()
{	    
#ifdef CGDEBUG
    _pModule->log(_modId, Logger::DEBUG, Chain("Accepting session"));
#endif

    try {

	if ( _protType == CegoDbHandler::XML )
	{
	    
	    _xml.getDocument()->clear();
	    _xml.setChain( _pN->getMsg() );	
#ifdef CGDEBUG
	    _pModule->log(_modId, Logger::DEBUG, _pN->getMsg());
#endif
	    Chain docType;

	    try
	    {
		_xml.parse();
		docType = _xml.getDocument()->getDocType();
	    }
	    catch ( Exception e )
	    {
		docType = Chain("ERROR");
	    }
#ifdef CGDEBUG
	    _pModule->log(_modId, Logger::DEBUG, Chain("XML parse ok"));
#endif
	    
	    if ( docType != Chain(XML_DBSESSION_REQUEST) )
	    {
	    
		_pModule->log(_modId, Logger::LOGERR, Chain("Invalid request"));
		
		_xml.getDocument()->clear();
		
		Element* pRoot = new Element(XML_FRAME_ELEMENT);
		pRoot->setAttribute(XML_MSG_ATTR, Chain("Invalid request"));
		
		_xml.getDocument()->setRootElement(pRoot);
		_xml.getDocument()->setDocType(XML_ERROR_DOC);
		
		Chain request;
		_xml.getXMLChain(request);
		
		_pN->setMsg(request, request.length());
		
		_pN->writeMsg();
		
		return false;
	    }
	    else
	    {
		Element *pRoot = _xml.getDocument()->getRootElement();
		if ( pRoot )
		{
		    _tableSet = pRoot->getAttributeValue(XML_TABLESET_ATTR);
		    _user = pRoot->getAttributeValue(XML_USER_ATTR);
		    _password = pRoot->getAttributeValue(XML_PASSWD_ATTR);
		    
		    // response is sent after authorization check
		    
		    return true;
		}
		else
		{
		    throw Exception(EXLOC, "Cannot get root element from message");
		}	    
	    }
	}
	else
	{

#ifdef CGDEBUG

	    _pModule->log(_modId, Logger::DEBUG, Chain("--- SER ---"));
	    _pModule->log(_modId, Logger::DEBUG, Chain(_pN->getMsg(), _pN->getMsgSize()));
	    _pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));

#endif

	    _pSer->reset();
	    Chain req = _pSer->readChain();

	    // cout << "READING REQ = " << req << endl;

	    if ( req != Chain(SER_SESSION))
	    {
		_pSer->reset();
		_pSer->writeChain(Chain(SER_ERROR));
		_pSer->writeChain(Chain("Invalid request"));
		_pN->writeMsg();		
		return false;		
	    }
	    else
	    {
		_tableSet = _pSer->readChain();
		_user = _pSer->readChain();
		_password = _pSer->readChain();
		// cout << "SESSION OK" << endl;
		return true;
	    }

	}	
    }
    catch ( Exception e)
    {
	
	Chain msg;
	e.pop(msg);
	
	_pModule->log(_modId, Logger::LOGERR, Chain("Aborting session. Reason=") + msg);
	
	_pN->sendNack();
	return false;
	
    }
}

CegoDbHandler::ResultType CegoDbHandler::reqQueryOp(const Chain& cmd)
{


    if ( _protType == CegoDbHandler::XML )
    {
		
	_xml.getDocument()->clear();
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_CMD_ATTR, cmd);
	
	_xml.getDocument()->setRootElement(pRoot);
	_xml.getDocument()->setDocType(XML_QUERY_REQUEST);
	
	Chain request;
	_xml.getXMLChain(request);
	
	_pN->setMsg(request, request.length());
	
	_pN->writeMsg();
	
	_pN->readMsg();
	
	_xml.getDocument()->clear();
	_xml.setChain( _pN->getMsg() );
	_xml.parse();
	
	Chain docType = _xml.getDocument()->getDocType();
	
	pRoot = _xml.getDocument()->getRootElement();
	
	if ( pRoot )
	{
	    _serMsg = pRoot->getAttributeValue(XML_MSG_ATTR);
	}

	if ( docType == Chain(XML_OK_DOC) )
	{
	    return DB_OK;
	}
	else if ( docType == Chain(XML_ERROR_DOC) )
	{	    
	    return DB_ERROR;
	}
	else if ( docType == Chain(XML_DATA_DOC) )
	{
	    return DB_DATA;
	}
	else if ( docType == Chain(XML_INFO_DOC) )
	{
	    return DB_INFO;
	}
	else
	{
	    throw Exception(EXLOC, "Invalid document type");
	}
    }
    else
    {
	_pSer->reset();
	_pSer->writeChain(Chain(SER_QUERY));
	_pSer->writeChain(cmd);
	return sendSerialReq();	
	
    }
}

CegoDbHandler::ResultType CegoDbHandler::reqQueryAbort(long idx)
{    
    
    if ( _protType == CegoDbHandler::XML )
    {
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_TID_ATTR, Chain(idx));
	return sendXMLReq(XML_QUERYABORT_REQUEST, pRoot);
    }
    else
    {
	_pSer->reset();
	_pSer->writeChain(Chain(SER_QUERYABORT));
	_pSer->writeChain(Chain(idx));
	return sendSerialReq();	
    }
}

const Chain& CegoDbHandler::getMsg()
{   
    return _serMsg;
}


long CegoDbHandler::getAffected()
{
    if ( _protType == CegoDbHandler::XML )
    {
    
	Element *pRoot = _xml.getDocument()->getRootElement();
	
	if ( pRoot )
	{
	    _serAffected =  pRoot->getAttributeValue(XML_AFFECTED_ATTR).asLong();
	}
    }

    return _serAffected;
}

long CegoDbHandler::getTid()
{
    if ( _protType == CegoDbHandler::XML )
    {

	Element *pRoot = _xml.getDocument()->getRootElement();
	
	if ( pRoot )
	{
	    return pRoot->getAttributeValue(XML_TID_ATTR).asLong();
	}
	else
	{
	    throw Exception(EXLOC, "No root element found");
	}
    }
    return _serTid;
    {
	return _serTid;
    }
}


const Chain& CegoDbHandler::getTableSet()
{
    return _tableSet;
}

const Chain& CegoDbHandler::getUser()
{
    return _user;
}

const Chain& CegoDbHandler::getPassword()
{
    return _password;
}

const Chain& CegoDbHandler::getFormat()
{
    if ( _protType == CegoDbHandler::XML )
    {

	Element *pRoot = _xml.getDocument()->getRootElement();
	
	if ( pRoot )
	{
	    _serFormat = pRoot->getAttributeValue(XML_FORMAT_ATTR);
	}
    }

    return _serFormat;
}

const ListT<CegoField>& CegoDbHandler::getSchema()
{

    if ( _protType == CegoDbHandler::XML )
    {
	
	Element *pRoot = _xml.getDocument()->getRootElement();
	
	if ( pRoot )
	{
	    
	    _serSchema.Empty();

	    Chain tableName = pRoot->getAttributeValue(XML_TABLENAME_ATTR);
	    
	    ListT<Element*> childList = pRoot->getChildren(Chain(XML_SCHEMA_ELEMENT));
	    Element **pRow = childList.First();
	    while ( pRow ) 
	    {
		
		Chain colTable = (*pRow)->getAttributeValue(XML_TABLENAME_ATTR);
		Chain colName = (*pRow)->getAttributeValue(XML_COLNAME_ATTR);
		Chain colType = (*pRow)->getAttributeValue(XML_COLTYPE_ATTR);
		Chain colSize = (*pRow)->getAttributeValue(XML_COLSIZE_ATTR);
		Chain colNullable = (*pRow)->getAttributeValue(XML_COLNULLABLE_ATTR);
		Chain colDefValue = (*pRow)->getAttributeValue(XML_COLDEFVALUE_ATTR);
		
		CegoTypeConverter tc;
		CegoDataType dataType = tc.getTypeId(colType);
		
		bool isNullable;
		if ( colNullable == Chain(XML_TRUE_VALUE) )
		    isNullable=true;
		else
		    isNullable=false;
		
		CegoFieldValue defValue;
		if ( colDefValue != Chain("") )
		{
		    defValue = CegoFieldValue(dataType, colDefValue);
		}
		CegoField f(CegoField(colTable, colTable, colName, dataType, colSize.asInteger(), defValue, isNullable));	
		
		_serSchema.Insert(f);
		
		pRow = childList.Next();
	    }
	}
    }

    return _serSchema;

}

Element* CegoDbHandler::getObjElement()
{
    if ( _protType == CegoDbHandler::XML )
    {
	Element *pRoot = _xml.getDocument()->getRootElement();
	
	ListT<Element*> objElementList = pRoot->getChildren(XML_OBJ_ELEMENT);
	
	Element **pOE = objElementList.First();
	if ( pOE ) 
	{
	    return *pOE;
	}
    }
    else
    {
	throw Exception(EXLOC, Chain("Serial protocol still not supported"));
	// TODO
    }
    return 0;
}

CegoObject::ObjectType CegoDbHandler::getObjType()
{

    if ( _protType == CegoDbHandler::XML )
    {
	Element *pRoot = _xml.getDocument()->getRootElement();
	
	if ( pRoot )
	{
	    ListT<Element*> objElementList = pRoot->getChildren(XML_OBJ_ELEMENT);
	    
	    Element **pOE = objElementList.First();
	    if ( pOE ) 
	    {
		CegoTypeConverter tc;
		return tc.getObjectTypeId( (*pOE)->getAttributeValue(XML_OBJTYPE_ATTR) );
	    }
	    throw Exception(EXLOC, "No object type id found");	
	}
	throw Exception(EXLOC, "No root element found");	
    }
    else
    {
	throw Exception(EXLOC, Chain("Serial protocol still not supported"));
	// TODO
    }
}

void CegoDbHandler::getProcResult(ListT<CegoProcVar>& outParamList, CegoFieldValue& retValue)
{
    if ( _protType == CegoDbHandler::XML )
    {
	Element *pRoot = _xml.getDocument()->getRootElement();
	
	if ( pRoot )
	{
	    ListT<Element*> outParamElementList = pRoot->getChildren(XML_OUTPARAM_ELEMENT);
	    
	    ListT<CegoField> fl;
	    Element **pOP = outParamElementList.First();
	    while ( pOP ) 
	    {
		Chain paramName = (*pOP)->getAttributeValue(XML_NAME_ATTR);
		Chain paramValue = (*pOP)->getAttributeValue(XML_VALUE_ATTR);
		Chain paramType = (*pOP)->getAttributeValue(XML_TYPE_ATTR);
		
		CegoTypeConverter tc;
		CegoDataType datatype = tc.getTypeId(paramType);
		
		if ( paramName == Chain("") )
		{
		    retValue = CegoFieldValue(datatype, paramValue);
		}
		else
		{
		    CegoFieldValue fv(datatype, paramValue);
		    outParamList.Insert( CegoProcVar(paramName, CegoProcVar::OUTVAR, fv.getType(), fv.getLength(), fv));
		}
		
		pOP = outParamElementList.Next();
	    }
	}
	else
	{
	    throw Exception(EXLOC, "No root element found");
	}
    }
    else
    {
	outParamList = _outParamList;
	retValue = _retValue;
    }
}

CegoDbHandler::ResultType CegoDbHandler::receiveTableData(const ListT<CegoField>& schema)
{
    ListT<CegoFieldValue> fvl;

    ResultType res = receiveTableData(schema, fvl);

    CegoField *pF = schema.First();
    CegoFieldValue *pFV = fvl.First();
    while ( pF && pFV )
    {
	pF->setValue(*pFV);
	pF = schema.Next();
	pFV = fvl.Next();	
    }
    return res;
}

CegoDbHandler::ResultType CegoDbHandler::receiveTableData(const ListT<CegoField>& schema, ListT<CegoFieldValue>& fvl)
{

#ifdef CGDEBUG
    _pModule->log(_modId, Logger::DEBUG, Chain("Receiving table data ..."));
#endif

    if ( _protType == CegoDbHandler::XML )
    {
	if ( _pRow )
	    _pRow = _rowList.Next();
	
	if ( _pRow == 0 )
	{
	    // get more data

	    ResultType res = getMoreTableData();
	     
	    switch ( res )
	    {
	    case DB_DATA:
		_pRow = _rowList.First();
		break;
	    case DB_OK:
	    case DB_FIN:
	    case DB_ERROR:
		return res;
	    case DB_INFO:
		throw Exception(EXLOC, "Invalid result type");
	    }
	}

	int col=1;
	CegoField *pF = schema.First();
	while ( pF ) 
	{
	    Chain colName = pF->getAttrName();
	    Chain colPos = Chain(NETMNG_COLPREFIX) + Chain(col);
	    
	    if ( (*_pRow)->hasAttribute(colPos) == false )
	    {
		CegoFieldValue fv;
		fvl.Insert(fv);	    
	    }
	    else
	    {
		
		Chain colVal = (*_pRow)->getAttributeValue(colPos);
			   
		if ( pF->getType() == INT_TYPE  )
		{
		    CegoFieldValue fv(INT_TYPE, colVal);	    
		    fvl.Insert(fv);
		}
		else if ( pF->getType() == LONG_TYPE  )
		{
		    CegoFieldValue fv(LONG_TYPE, colVal);
		    fvl.Insert(fv);
		}
		else if ( pF->getType() == VARCHAR_TYPE )
		{
		    char *pS = (char*)malloc(colVal.length());
		    strcpy(pS, (char*)colVal);		    
		    CegoFieldValue fv(VARCHAR_TYPE, pS, colVal.length(), true);		   
		    fvl.Insert(fv);
		}
		else if ( pF->getType() == BOOL_TYPE  )
		{
		    CegoFieldValue fv(BOOL_TYPE, colVal);
		    fvl.Insert(fv);
		}
		else if ( pF->getType() == DATETIME_TYPE  )
		{
		    CegoFieldValue fv(DATETIME_TYPE, colVal);	  
		    fvl.Insert(fv);
		}
		else if ( pF->getType() == FLOAT_TYPE  )
		{
		    CegoFieldValue fv(FLOAT_TYPE, colVal);	  
		    fvl.Insert(fv);
		}
		else if ( pF->getType() == DOUBLE_TYPE  )
		{
		    CegoFieldValue fv(DOUBLE_TYPE, colVal);	  
		    fvl.Insert(fv);
		}
		else if ( pF->getType() == SMALLINT_TYPE  )
		{
		    CegoFieldValue fv(SMALLINT_TYPE, colVal);	  
		    fvl.Insert(fv);
		}
		else if ( pF->getType() == TINYINT_TYPE  )
		{
		    CegoFieldValue fv(TINYINT_TYPE, colVal);	  
		    fvl.Insert(fv);
		}
		else if ( pF->getType() == BIGINT_TYPE )
		{
		    CegoFieldValue fv(BIGINT_TYPE, colVal);	    
		    fvl.Insert(fv);
		}
		else if ( pF->getType() == DECIMAL_TYPE )
		{
		    CegoFieldValue fv(DECIMAL_TYPE, colVal);	    
		    fvl.Insert(fv);
		}
		else if ( pF->getType() == FIXED_TYPE )
		{
		    CegoFieldValue fv(FIXED_TYPE, colVal);	    
		    fvl.Insert(fv);
		}
		else if ( pF->getType() == BLOB_TYPE )
		{
		    CegoFieldValue fv(BLOB_TYPE, colVal);	    
		    fvl.Insert(fv);
		}
	    }
	    
	    col++;
	    pF = schema.Next();
	}
	return DB_DATA;
    }
    else
    {
	
	// cout << "Num Ahead = " << _pSer->numAhead() << endl;

	if ( _pSer->numAhead() > 0 )
	{
	    fvl = _pSer->readRow(schema);
	    return DB_DATA;
	}
	else
	{
	    ResultType res = getMoreTableData();
	    switch ( res )
	    {
	    case DB_DATA:
		fvl = _pSer->readRow(schema);
		break;
	    case DB_OK:
	    case DB_ERROR:
		break;
	    case DB_INFO:
	    case DB_FIN:
		break;
	    }
	    return res;
	}

    }
}

void CegoDbHandler::abortQuery()
{
#ifdef CGDEBUG
    _pModule->log(_modId, Logger::DEBUG, Chain("Aborting query"));   
#endif

    _pN->sendChar(QUERY_ABORT);

    _pN->readMsg();

    if ( _protType == CegoDbHandler::XML )
    {

	_xml.getDocument()->clear();
	_xml.setChain( _pN->getMsg() );
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, _pN->getMsg());
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
	_xml.parse();

	Chain docType = _xml.getDocument()->getDocType();
	
	if ( docType == Chain(XML_OK_DOC) )
	{
	    _rowList.Empty();
	    _pRow = 0;
	}
	else if ( docType == Chain(XML_ERROR_DOC) )
	{
	    _rowList.Empty();
	    _pRow = 0;
	}
    }
    else
    {
	_pSer->reset();
    }
    
}

void CegoDbHandler::resetQuery()
{
#ifdef CGDEBUG
    _pModule->log(_modId, Logger::DEBUG, Chain("Resetting query"));   
#endif

    _pN->sendChar(QUERY_RESET);

    _rowList.Empty();
    _pRow = 0;

}

void CegoDbHandler::sendCollectedData()
{

    char c = QUERY_MOREDATA;

    if ( _protType == CegoDbHandler::XML )
    {
	c = _pN->recvChar();
    }
    else
    {
	if ( _serSync )
	    c = _pN->recvChar();
    }

    if ( c == QUERY_ABORT )
    {
	_pModule->log(_modId, Logger::LOGERR, Chain("User query abort"));
	throw Exception(EXLOC, "Query aborted by user");
    }
    else if ( c == QUERY_RESET )
    {
	_wasReset=true;
	if ( _protType == CegoDbHandler::XML )
	{	    
	    _xml.getDocument()->clear();
	}
	else
	{
	    _pSer->reset();
	}
    }
    else if ( c == QUERY_MOREDATA )
    {
	if ( _protType == CegoDbHandler::XML )
	{
	    
	    Chain xmlString;
	    
	    _xml.getDocument()->setDocType(XML_DATA_DOC);
	    _xml.getXMLChain(xmlString);
	    
#ifdef CGDEBUG
	    _pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	    _pModule->log(_modId, Logger::DEBUG, xmlString);
	    _pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	    
	    _pN->setMsg(xmlString, xmlString.length());
	    
	    _pN->writeMsg();
	
	    _xml.getDocument()->clear();
	}
	else
	{

#ifdef CGDEBUG
	    _pModule->log(_modId, Logger::DEBUG, Chain("--- SER ---"));
	    _pModule->log(_modId, Logger::DEBUG, Chain(_pN->getMsg(), _pN->getMsgSize()));
	    _pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif

	    _pN->writeMsg();
	    _pSer->reset();
	    _serSync = true;
	}
    }
    else
    {
	throw Exception(EXLOC, "Unknown query sync");
    }

    return;
}

bool CegoDbHandler::wasReset()
{
    if ( _wasReset )
    {
	_wasReset = false;
	return true;
    }
    else
    {
	_wasReset = false;
	return false;
    }
    
}
void CegoDbHandler::sendFinishData()
{

    char c = QUERY_MOREDATA;

    if ( _protType == CegoDbHandler::XML )
    {
	c = _pN->recvChar();
    }
    else
    {
	if ( _serSync )
	    c = _pN->recvChar();
    }
    
    if ( c == QUERY_ABORT )
    {
	// can be ignored
	// _pModule->log(_modId, Logger::LOGERR, Chain("User query abort"));
	// throw Exception(EXLOC, "Query aborted by user");
    }
    else if ( c == QUERY_RESET )
    {
	// _wasReset=true;
	// _xml.getDocument()->clear();
    }
    else if ( c == QUERY_MOREDATA )
    {
	// nothing to to
    }
    
    if ( _protType == CegoDbHandler::XML )
    {
	
	_xml.getDocument()->clear();
	_xml.getDocument()->setDocType(XML_OK_DOC);
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	_xml.getDocument()->setRootElement(pRoot);
	
	Chain xmlString;
	_xml.getXMLChain(xmlString);
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, xmlString);
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	_pN->setMsg(xmlString, xmlString.length());
	
    }
    else
    {	
	_pSer->reset();
	_pSer->writeChain(SER_FIN);
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- SER ---"));
	_pModule->log(_modId, Logger::DEBUG, Chain(_pN->getMsg(), _pN->getMsgSize()));
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif

    }

    _pN->writeMsg();
}

void CegoDbHandler::sendErrorData(const Chain& msg)
{

    char c = _pN->recvChar();
    
    if ( c == QUERY_ABORT )
    {
	// can be ignored
	// we send error back anyway
    }
    else if ( c == QUERY_RESET )
    {
	// we send error back anyway
    }
    else if ( c == QUERY_MOREDATA )
    {
	// we send error back anyway
	
    }

    if ( _protType == CegoDbHandler::XML )
    {

	
	_xml.getDocument()->clear();
	_xml.getDocument()->setDocType(XML_ERROR_DOC);
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_MSG_ATTR, msg);
	_xml.getDocument()->setRootElement(pRoot);
	
	Chain xmlString;
	_xml.getXMLChain(xmlString);
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, xmlString);
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
	_pN->setMsg(xmlString, xmlString.length());
    }
    else
    {

	_pSer->reset();
	_pSer->writeChain(SER_ERROR);
	_pSer->writeChain(msg);
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- SER ---"));
	_pModule->log(_modId, Logger::DEBUG, Chain(_pN->getMsg(), _pN->getMsgSize()));
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif

    }
    
    _pN->writeMsg();
}


void CegoDbHandler::sendSessionConfirm(const Chain& msg, 
				       long tid, 
				       const Chain& dbName, 
				       const Chain& dbVersion)
{

    
    if ( _protType == CegoDbHandler::XML )
    {

    
	_xml.getDocument()->clear();
	_xml.getDocument()->setDocType(XML_OK_DOC);
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_MSG_ATTR, msg);
	pRoot->setAttribute(XML_TID_ATTR, Chain(tid));
	pRoot->setAttribute(XML_DBPRODNAME_ATTR, dbName);
	pRoot->setAttribute(XML_DBPRODVERSION_ATTR, dbVersion);
	
	_xml.getDocument()->setRootElement(pRoot);
	
	Chain xmlString;
	_xml.getXMLChain(xmlString);
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, xmlString);
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
	_pN->setMsg(xmlString, xmlString.length());
    }
    else
    {
	_pSer->reset();

	_pSer->writeChain(Chain(SER_SACK));
	_pSer->writeChain(msg);
	_pSer->writeChain(Chain(tid));
	_pSer->writeChain(dbName);
	_pSer->writeChain(dbVersion);

#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- SER ---"));
	_pModule->log(_modId, Logger::DEBUG, Chain(_pN->getMsg(), _pN->getMsgSize()));
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif

    }
    
    _pN->writeMsg();
    
}



void CegoDbHandler::sendResponse(const Chain& msg, long affected)
{

    if ( _protType == CegoDbHandler::XML )
    {

	_xml.getDocument()->clear();
	_xml.getDocument()->setDocType(XML_OK_DOC);
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_MSG_ATTR, msg);
	pRoot->setAttribute(XML_AFFECTED_ATTR, Chain(affected));
	
	_xml.getDocument()->setRootElement(pRoot);
	
	Chain xmlString;
	_xml.getXMLChain(xmlString);

#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, xmlString);
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
	_pN->setMsg(xmlString, xmlString.length());
	
    }
    else
    {
	_pSer->reset();
	_pSer->writeChain(Chain(SER_OK));
	_pSer->writeChain(msg);
	_pSer->writeChain(Chain(affected));

#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- SER ---"));
	_pModule->log(_modId, Logger::DEBUG, Chain(_pN->getMsg(), _pN->getMsgSize()));
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
    }
    _pN->writeMsg();
    
}

void CegoDbHandler::sendError(const Chain& msg)
{

    if ( _protType == CegoDbHandler::XML )
    {

	_xml.getDocument()->clear();
	_xml.getDocument()->setDocType(XML_ERROR_DOC);
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_MSG_ATTR, msg);
	
	_xml.getDocument()->setRootElement(pRoot);
	
	Chain xmlString;
	_xml.getXMLChain(xmlString);
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, xmlString);
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
	_pN->setMsg(xmlString, xmlString.length());
	
    }
    else
    {
	_pSer->reset();
	_pSer->writeChain(Chain(SER_ERROR));
	_pSer->writeChain(msg);

#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- SER ---"));
	_pModule->log(_modId, Logger::DEBUG, Chain(_pN->getMsg(), _pN->getMsgSize()));
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
    }
    
    _pN->writeMsg();
    
}

void CegoDbHandler::sendBlobInfo(int fileId, int pageId)
{

    if ( _protType == CegoDbHandler::XML )
    {

	_xml.getDocument()->clear();
	_xml.getDocument()->setDocType(XML_OK_DOC);
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_FILEID_ATTR, Chain(fileId));
	pRoot->setAttribute(XML_PAGEID_ATTR, Chain(pageId));
	
	_xml.getDocument()->setRootElement(pRoot);
	
	Chain xmlString;
	_xml.getXMLChain(xmlString);
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, xmlString);
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
	_pN->setMsg(xmlString, xmlString.length());

    }
    else
    {
	_pSer->reset();
	_pSer->writeChain(Chain(SER_BLOBINFO));
	_pSer->writeChain(Chain(fileId));
	_pSer->writeChain(Chain(pageId));	

    }
    _pN->writeMsg();
    
}

void CegoDbHandler::sendBlobSize(long blobSize)
{

    if ( _protType == CegoDbHandler::XML )
    {

	_xml.getDocument()->clear();
	_xml.getDocument()->setDocType(XML_OK_DOC);
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_SIZE_ATTR, Chain(blobSize));
	
	_xml.getDocument()->setRootElement(pRoot);
	
	Chain xmlString;
	_xml.getXMLChain(xmlString);
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, xmlString);
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
	_pN->setMsg(xmlString, xmlString.length());
	
    }
    else
    {
	_pSer->reset();
	_pSer->writeChain(Chain(SER_BLOBSIZE));
	_pSer->writeChain(Chain(blobSize));	
    }

    _pN->writeMsg();
    
}


CegoDbHandler::ResultType CegoDbHandler::putBlob(const Chain& tableSet, CegoBlob& blob)
{

    if ( _protType == CegoDbHandler::XML )
    {

	_xml.getDocument()->clear();
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_TABLESET_ATTR, tableSet);
	pRoot->setAttribute(XML_SIZE_ATTR, blob.getSize());
	
	_xml.getDocument()->setRootElement(pRoot);
	_xml.getDocument()->setDocType(XML_PUTBLOB_REQUEST);
	
	Chain request;
	_xml.getXMLChain(request);
	
	_pN->setMsg(request, request.length());
	
    }
    else
    {
	_pSer->reset();
	_pSer->writeChain(Chain(SER_PUTBLOB));
	_pSer->writeChain(Chain(tableSet));
	_pSer->writeChain(Chain(blob.getSize()));
	
    }

    _pN->writeMsg();
	
    _pN->readMsg();
	
    if ( _protType == CegoDbHandler::XML )
    {

	_xml.getDocument()->clear();
	_xml.setChain( _pN->getMsg() );
	_xml.parse();
	
	Chain docType = _xml.getDocument()->getDocType();
	
	if ( docType == Chain(XML_ERROR_DOC) )
	{
	    return DB_ERROR;
	}    
	
	Element* pRoot;
	pRoot = _xml.getDocument()->getRootElement();
	if ( pRoot )
	{
	    blob.setFileId(pRoot->getAttributeValue(XML_FILEID_ATTR).asInteger());
	    blob.setPageId(pRoot->getAttributeValue(XML_PAGEID_ATTR).asInteger());
	}
    }
    else
    {

	_pSer->reset();
	Chain req = _pSer->readChain();

	if ( req == Chain(SER_ERROR) ) 
	{
	    return DB_ERROR;
	}

	blob.setFileId(_pSer->readChain().asInteger());
	blob.setPageId(_pSer->readChain().asInteger());
    }
	
    blob.reset();
    
    while ( blob.nextChunk(BLOBCHUNKSIZE) )
    {
	
	_pN->setMsg((char*)blob.getChunkPtr(), blob.getChunkSize());
	
	_pN->writeMsg();
	
	if ( _pN->recvAck() == false )
	{
	    _pModule->log(_modId, Logger::LOGERR, Chain("User query abort"));
	    return DB_ERROR;
	}
    }
    
    return DB_OK;
}

CegoDbHandler::ResultType CegoDbHandler::getBlob(const Chain& tableSet, CegoBlob& blob)
{

    if ( _protType == CegoDbHandler::XML )
    {

	_xml.getDocument()->clear();
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_TABLESET_ATTR, tableSet);
	pRoot->setAttribute(XML_FILEID_ATTR, blob.getFileId());
	pRoot->setAttribute(XML_PAGEID_ATTR, blob.getPageId());
	
	_xml.getDocument()->setRootElement(pRoot);
	_xml.getDocument()->setDocType(XML_GETBLOB_REQUEST);
	
	Chain request;
	_xml.getXMLChain(request);
	
	_pN->setMsg(request, request.length());
    }
    else
    {

	_pSer->reset();
	_pSer->writeChain(Chain(SER_GETBLOB));
	_pSer->writeChain(Chain(tableSet));
	_pSer->writeChain(Chain(blob.getFileId()));
	_pSer->writeChain(Chain(blob.getPageId()));
	
    }
    _pN->writeMsg();
    
    _pN->readMsg();

    long blobSize;

    if ( _protType == CegoDbHandler::XML )
    {
	
	_xml.getDocument()->clear();
	_xml.setChain( _pN->getMsg() );
	_xml.parse();
	
	Chain docType = _xml.getDocument()->getDocType();
	
	if ( docType == Chain(XML_ERROR_DOC) )
	{
	    return DB_ERROR;
	}    
	
	Element* pRoot;	
	pRoot = _xml.getDocument()->getRootElement();
	if ( pRoot )
	{
	    blobSize = pRoot->getAttributeValue(XML_SIZE_ATTR).asLong();
	}
    }
    else
    {

	_pSer->reset();
	Chain req = _pSer->readChain();

	if ( req == Chain(SER_ERROR) ) 
	{
	    return DB_ERROR;
	}

	blobSize = _pSer->readChain().asInteger();

    }

    blob.allocate(blobSize);
    blob.reset();
    
    int recvSize = 0;
    while ( recvSize < blobSize )
    {
       	_pN->sendAck();
	_pN->readMsg();
	Chain msg(_pN->getMsg(), _pN->getMsgSize() );
	
	blob.putChunk((unsigned char*)_pN->getMsg(), _pN->getMsgSize() );
	
	recvSize += _pN->getMsgSize();
    }
    
    return DB_OK;
}

CegoDbHandler::ResultType CegoDbHandler::delBlob(const Chain& tableSet, CegoBlob& blob)
{

    if ( _protType == CegoDbHandler::XML )
    {

	_xml.getDocument()->clear();
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_TABLESET_ATTR, tableSet);
	pRoot->setAttribute(XML_FILEID_ATTR, blob.getFileId());
	pRoot->setAttribute(XML_PAGEID_ATTR, blob.getPageId());
	
	_xml.getDocument()->setRootElement(pRoot);
	_xml.getDocument()->setDocType(XML_DELBLOB_REQUEST);
	
	Chain request;
	_xml.getXMLChain(request);
	
	_pN->setMsg(request, request.length());
    }
    else
    {

	_pSer->reset();
	_pSer->writeChain(Chain(SER_DELBLOB));
	_pSer->writeChain(Chain(tableSet));
	_pSer->writeChain(Chain(blob.getFileId()));
	_pSer->writeChain(Chain(blob.getPageId()));
	
    }
    _pN->writeMsg();
    
    _pN->readMsg();

    if ( _protType == CegoDbHandler::XML )
    {
	
	_xml.getDocument()->clear();
	_xml.setChain( _pN->getMsg() );
	_xml.parse();
	
	Chain docType = _xml.getDocument()->getDocType();
	
	if ( docType == Chain(XML_OK_DOC) )
	{
	    return DB_OK;
	}	
	else if ( docType == Chain(XML_ERROR_DOC) )
	{
	    return DB_ERROR;
	}
	else
	{
	    throw Exception(EXLOC, Chain("Invalid document type"));
	}
    }
    else
    {

	_pSer->reset();
	Chain req = _pSer->readChain();

	if ( req == Chain(SER_ERROR) ) 
	{
	    return DB_ERROR;
	}

	return DB_OK;

    }
}

void CegoDbHandler::sendProcResult(const Chain& msg, const ListT<CegoProcVar>& outParamList, CegoFieldValue* pRetValue)
{
#ifdef CGDEBUG
    _pModule->log(_modId, Logger::DEBUG, Chain("Sending procedure result"));
#endif

    if ( _protType == CegoDbHandler::XML )
    {

	_xml.getDocument()->clear();
	_xml.getDocument()->setDocType(XML_OK_DOC);
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_MSG_ATTR, msg);
	
	if ( pRetValue )
	{
	    Element *pOutParam = new Element(XML_OUTPARAM_ELEMENT);
	    
	    CegoXMLHelper xh;
	    
	    CegoTypeConverter tc;
	    pOutParam->setAttribute(XML_TYPE_ATTR, tc.getTypeString(pRetValue->getType()));
	    
	    pOutParam->setAttribute(XML_VALUE_ATTR, pRetValue->valAsChain());
	    pRoot->addContent(pOutParam);
	}
	
	CegoProcVar *pVar = outParamList.First();
	while ( pVar )
	{
	    Element *pOutParam = new Element(XML_OUTPARAM_ELEMENT);
	    pOutParam->setAttribute(XML_NAME_ATTR, pVar->getName());
	    
	    CegoTypeConverter tc;
	    pOutParam->setAttribute(XML_TYPE_ATTR, tc.getTypeString(pVar->getValue().getType()));
	    pOutParam->setAttribute(XML_VALUE_ATTR, pVar->getValue().valAsChain());
	    
	    pVar = outParamList.Next();
	    pRoot->addContent(pOutParam);
	}
   
	_xml.getDocument()->setRootElement(pRoot);
	
	Chain xmlString;
	_xml.getXMLChain(xmlString);
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, xmlString);
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
	_pN->setMsg(xmlString, xmlString.length());
    }
    else
    {
	
	_pSer->reset();
	_pSer->writeChain(Chain(SER_PROCRES));

	CegoTypeConverter tc;

	if ( pRetValue )
	{
	    _pSer->writeChain(Chain("@OUT"));
	    _pSer->writeChain(tc.getTypeString(pRetValue->getType()));	    
	    _pSer->writeChain(pRetValue->valAsChain());
	}
	
	CegoProcVar *pVar = outParamList.First();
	while ( pVar )
	{	    
	    _pSer->writeChain(pVar->getName());	   
	    _pSer->writeChain(tc.getTypeString(pVar->getValue().getType()));	    
	    _pSer->writeChain(pVar->getValue().valAsChain());
	    
	    pVar = outParamList.Next();
	}

#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- SER ---"));
	_pModule->log(_modId, Logger::DEBUG, Chain(_pN->getMsg(), _pN->getMsgSize()));
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif


    }
    
    _pN->writeMsg();
    
}

void CegoDbHandler::sendProdInfo()
{

    if ( _protType == CegoDbHandler::XML )
    {
	_xml.getDocument()->clear();
	_xml.getDocument()->setDocType(XML_OK_DOC);
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_DBPRODNAME_ATTR, XML_DBPRODNAME_VALUE);
	pRoot->setAttribute(XML_DBPRODVERSION_ATTR, XML_DBPRODVERSION_VALUE);
	
	_xml.getDocument()->setRootElement(pRoot);
	
	
	Chain xmlString;
	_xml.getXMLChain(xmlString);
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, xmlString);
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
	_pN->setMsg(xmlString, xmlString.length());

    }
    else
    {
	_pSer->reset();
	_pSer->writeChain(Chain(SER_PRODINFO));
	_pSer->writeChain(CEGO_PRODUCT);
	_pSer->writeChain(CEGO_VERSION);

    }

    _pN->writeMsg();
    
}

CegoDbHandler::ResultType CegoDbHandler::getMoreTableData()
{

    // cout << "GET MORE DATA .." << endl;

#ifdef CGDEBUG
    _pModule->log(_modId, Logger::DEBUG, Chain("Sending ack ..."));
#endif    

    _pN->sendChar(QUERY_MOREDATA);

#ifdef CGDEBUG
    _pModule->log(_modId, Logger::DEBUG, Chain("Reading data ..."));
#endif

    _pN->readMsg();

    if ( _protType == CegoDbHandler::XML )
    {
	_xml.getDocument()->clear();
	_xml.setChain( _pN->getMsg() );
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, _pN->getMsg());
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
	_xml.parse();
	
	Chain docType = _xml.getDocument()->getDocType();
	
	if ( docType == Chain(XML_DATA_DOC) )
	{
	    Element *pRoot = _xml.getDocument()->getRootElement();
	    if ( pRoot )
	    {
		_rowList = pRoot->getChildren(XML_ROW_ELEMENT);
	    }
	    return DB_DATA;
	}
	else if ( docType == Chain(XML_OK_DOC) )
	{
	    _rowList.Empty();
	    return DB_OK;
	}
	else if ( docType == Chain(XML_ERROR_DOC) )
	{
	    return DB_ERROR;
	}
	else
	{
	    throw Exception(EXLOC, Chain("Invalid document type"));
	}
    }
    else
    {

#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- SER ---"));
	_pModule->log(_modId, Logger::DEBUG, Chain(_pN->getMsg(), _pN->getMsgSize()));
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif

	_pSer->reset();
	Chain req = _pSer->readChain();

	// cout << "Reading req " << req << endl;
	if ( req == Chain(SER_SDATA) ) 
	{
	    return DB_DATA;
	}
	else if ( req == Chain(SER_FDATA) ) 
	{
	    return DB_DATA;
	}
	else if ( req == Chain(SER_FIN) ) 
	{
	    _pSer->reset();
	    return DB_FIN;
	}
	else if ( req == Chain(SER_ERROR) ) 
	{
	    _serMsg = _pSer->readChain();
	    _pSer->reset();
	    return DB_ERROR;
	}
	else
	{
	    throw Exception(EXLOC, Chain("Invalid serial request"));	    
	}
    }
}

CegoDbHandler::RequestType CegoDbHandler::acceptRequest()
{

#ifdef CGDEBUG
    _pModule->log(_modId, Logger::DEBUG, Chain("Accepting request ..."));
#endif
    
    if ( _pN->waitMsg(NETMNG_WAITMSG_TIMEOUT) == false )
	return CegoDbHandler::REQTIMEOUT;

    _pN->readMsg();

    if ( _protType == CegoDbHandler::XML )
    {

#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, _pN->getMsg());
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
		
	_xml.getDocument()->clear();
	_xml.setChain( _pN->getMsg() );
	_xml.parse();
        
	Chain docType = _xml.getDocument()->getDocType();
	
	if ( docType == Chain(XML_QUERY_REQUEST) ) 
	{
	    return CegoDbHandler::QUERY;
	}
	else if ( docType == Chain(XML_QUERYABORT_REQUEST) ) 
	{
	    return CegoDbHandler::QUERYABORT;
	}
	else if ( docType == Chain(XML_DBPRODINFO_REQUEST) ) 
	{
	    return CegoDbHandler::DBPRODINFO;
	}
	else if (  docType == Chain(XML_CREATETABLE_REQUEST) ) 
	{
	    return CegoDbHandler::CREATETABLE;
	}
	else if (  docType == Chain(XML_CREATEVIEW_REQUEST) ) 
	{
	    return CegoDbHandler::CREATEVIEW;
	}
	else if (  docType == Chain(XML_CREATEPROCEDURE_REQUEST) ) 
	{
	    return CegoDbHandler::CREATEPROCEDURE;
	}
	else if (  docType == Chain(XML_CREATECHECK_REQUEST) ) 
	{
	    return CegoDbHandler::CREATECHECK;
	}
	else if (  docType == Chain(XML_ALTERTABLE_REQUEST) ) 
	{
	    return CegoDbHandler::ALTERTABLE;
	}
	else if (  docType == Chain(XML_CREATEINDEX_REQUEST) ) 
	{
	    return CegoDbHandler::CREATEINDEX;
	}
	else if (  docType == Chain(XML_INSERT_REQUEST) ) 
	{
	    return CegoDbHandler::INSERT;
	}
	else if (  docType == Chain(XML_DELETE_REQUEST) ) 
	{
	    return CegoDbHandler::DELETETABLE;
	}
	else if (  docType == Chain(XML_UPDATE_REQUEST) ) 
	{
	    return CegoDbHandler::UPDATE;
	}
	else if (  docType == Chain(XML_OBJECTINFO_REQUEST) ) 
	{
	    return CegoDbHandler::OBJECTINFO;
	}
	else if (  docType == Chain(XML_DROP_OBJECT_REQUEST) ) 
	{
	    return CegoDbHandler::DROPOBJECT;
	}
	else if (  docType == Chain(XML_GETTABLE_REQUEST) ) 
	{
	    return CegoDbHandler::GETTABLE;
	}
	else if (  docType == Chain(XML_GETOBJLIST_REQUEST) ) 
	{
	    return CegoDbHandler::GETOBJLIST;
	}
	else if (  docType == Chain(XML_GETOBJLISTBYTABLE_REQUEST) ) 
	{
	    return CegoDbHandler::GETOBJLISTBYTABLE;
	}
	else if (  docType == Chain(XML_OBJRENAME_REQUEST) ) 
	{
	    return CegoDbHandler::OBJRENAME;
	}
	else if (  docType == Chain(XML_REORG_REQUEST) ) 
	{
	    return CegoDbHandler::REORGOBJ;
	}
	else if (  docType == Chain(XML_SYNC_REQUEST) ) 
	{
	    return CegoDbHandler::SYNC;
	}
	else if (  docType == Chain(XML_GETPAGECOUNT_REQUEST) ) 
	{
	    return CegoDbHandler::GETPAGECOUNT;
	}
	else if (  docType == Chain(XML_PUTBLOB_REQUEST) ) 
	{	    
	    return CegoDbHandler::PUTBLOB;
	}
	else if (  docType == Chain(XML_GETBLOB_REQUEST) ) 
	{
	    return CegoDbHandler::GETBLOB;
	}
	else if (  docType == Chain(XML_DELBLOB_REQUEST) ) 
	{
	    return CegoDbHandler::DELBLOB;
	}
	else if (  docType == Chain(XML_STARTTRANSACTION_REQUEST) ) 
	{
	    return CegoDbHandler::STARTTRANSACTION;
	}
	else if (  docType == Chain(XML_COMMITTRANSACTION_REQUEST) ) 
	{
	    return CegoDbHandler::COMMITTRANSACTION;
	}
	else if (  docType == Chain(XML_ROLLBACKTRANSACTION_REQUEST) ) 
	{
	    return CegoDbHandler::ROLLBACKTRANSACTION;
	}
	else if (  docType == Chain(XML_GETTID_REQUEST) ) 
	{
	    return CegoDbHandler::GETTID;
	}
	else if (  docType == Chain(XML_SESSION_CLOSE) ) 
	{
	    return CegoDbHandler::SESSION_CLOSE;
	}
	else
	{
	    return CegoDbHandler::UNKNOWN;
	}
    }
    else
    {

#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- SER ---"));
	_pModule->log(_modId, Logger::DEBUG, Chain(_pN->getMsg(), _pN->getMsgSize()));
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif

	_pSer->reset();
	Chain req = _pSer->readChain();
	
	if ( req == Chain(SER_QUERY) ) 
	{
	    _serQueryCmd = _pSer->readChain();
	    return CegoDbHandler::QUERY;
	}
	else if ( req == Chain(SER_QUERYABORT) ) 
	{
	    _serTid = _pSer->readChain().asLong();
	    return CegoDbHandler::QUERYABORT;
	}
	else if ( req == Chain(SER_DBPRODINFO) ) 
	{
	    return CegoDbHandler::DBPRODINFO;
	}
	else if (  req == Chain(SER_CREATETABLE) ) 
	{
	    return CegoDbHandler::CREATETABLE;
	}
	else if (  req == Chain(SER_CREATEVIEW) ) 
	{
	    return CegoDbHandler::CREATEVIEW;
	}
	else if (  req == Chain(SER_CREATEPROCEDURE) ) 
	{
	    return CegoDbHandler::CREATEPROCEDURE;
	}
	else if (  req == Chain(SER_CREATECHECK) ) 
	{
	    return CegoDbHandler::CREATECHECK;
	}
	else if (  req == Chain(SER_ALTERTABLE) ) 
	{
	    return CegoDbHandler::ALTERTABLE;
	}
	else if (  req == Chain(SER_CREATEINDEX) ) 
	{
	    return CegoDbHandler::CREATEINDEX;
	}
	else if (  req == Chain(SER_INSERT) ) 
	{
	    return CegoDbHandler::INSERT;
	}
	else if (  req == Chain(SER_DELETE) ) 
	{
	    _serAffected = _pSer->readChain().asInteger();
	    return CegoDbHandler::DELETETABLE;
	}
	else if (  req == Chain(SER_UPDATE) ) 
	{
	    _serAffected = _pSer->readChain().asInteger();
	    return CegoDbHandler::UPDATE;
	}
	else if (  req == Chain(SER_OBJECTINFO) ) 
	{
	    return CegoDbHandler::OBJECTINFO;
	}
	else if (  req == Chain(SER_DROP_OBJECT) ) 
	{
	    return CegoDbHandler::DROPOBJECT;
	}
	else if (  req == Chain(SER_GETTABLE) ) 
	{
	    return CegoDbHandler::GETTABLE;
	}
	else if (  req == Chain(SER_GETOBJLIST) ) 
	{
	    return CegoDbHandler::GETOBJLIST;
	}
	else if (  req == Chain(SER_GETOBJLISTBYTABLE) ) 
	{
	    return CegoDbHandler::GETOBJLISTBYTABLE;
	}
	else if (  req == Chain(SER_OBJRENAME) ) 
	{
	    return CegoDbHandler::OBJRENAME;
	}
	else if (  req == Chain(SER_REORG) ) 
	{
	    return CegoDbHandler::REORGOBJ;
	}
	else if (  req == Chain(SER_SYNC) ) 
	{
	    return CegoDbHandler::SYNC;
	}
	else if (  req == Chain(SER_GETPAGECOUNT) ) 
	{
	    return CegoDbHandler::GETPAGECOUNT;
	}
	else if (  req == Chain(SER_PUTBLOB) ) 
	{
	    _serTableSet = _pSer->readChain();
	    _serBlobSize = _pSer->readChain().asLong();
	    return CegoDbHandler::PUTBLOB;
	}
	else if (  req == Chain(SER_GETBLOB) ) 
	{
	    _serTableSet = _pSer->readChain();
	    _serFileId = _pSer->readChain().asInteger();
	    _serPageId = _pSer->readChain().asInteger();
	    return CegoDbHandler::GETBLOB;
	}
	else if (  req == Chain(SER_DELBLOB) ) 
	{
	    return CegoDbHandler::DELBLOB;
	}
	else if (  req == Chain(SER_STARTTRANSACTION) ) 
	{
	    return CegoDbHandler::STARTTRANSACTION;
	}
	else if (  req == Chain(SER_COMMITTRANSACTION) ) 
	{
	    return CegoDbHandler::COMMITTRANSACTION;
	}
	else if (  req == Chain(SER_ROLLBACKTRANSACTION) ) 
	{
	    return CegoDbHandler::ROLLBACKTRANSACTION;
	}
	else if (  req == Chain(SER_GETTID) ) 
	{
	    return CegoDbHandler::GETTID;
	}
	else if (  req == Chain(SER_SESSION_CLOSE) ) 
	{
	    return CegoDbHandler::SESSION_CLOSE;
	}
	else
	{
	    return CegoDbHandler::UNKNOWN;
	}	
    }
    
}

Chain CegoDbHandler::getQueryArg()
{

    if ( _protType == CegoDbHandler::XML )
    {	    
	Element *pRoot = _xml.getDocument()->getRootElement();
	
	if ( pRoot )
	{
	    _serQueryCmd = pRoot->getAttributeValue(XML_CMD_ATTR);
	}
    }
    
    return _serQueryCmd;
    
}


void CegoDbHandler::getPutBlobArg(Chain& tableSet, long& blobSize)
{

    if ( _protType == CegoDbHandler::XML )
    {	    

	Element *pRoot = _xml.getDocument()->getRootElement();
	if ( pRoot )
	{
	    tableSet = pRoot->getAttributeValue(XML_TABLESET_ATTR);
	    blobSize = pRoot->getAttributeValue(XML_SIZE_ATTR).asLong();
	}
    }
    else
    {
	tableSet = _serTableSet;
	blobSize = _serBlobSize;	
    }
}

void CegoDbHandler::getGetBlobArg(Chain& tableSet, int& fileId, int& pageId)
{


    if ( _protType == CegoDbHandler::XML )
    {	    

	Element *pRoot = _xml.getDocument()->getRootElement();
	if ( pRoot )
	{
	    tableSet = pRoot->getAttributeValue(XML_TABLESET_ATTR);
	    fileId = pRoot->getAttributeValue(XML_FILEID_ATTR).asInteger();
	    pageId = pRoot->getAttributeValue(XML_PAGEID_ATTR).asInteger();
	}
    }
    else
    {
	tableSet = _serTableSet;
	fileId = _serFileId;
	pageId = _serPageId;
    }
}

void CegoDbHandler::collectSchema(const ListT<CegoField>& schema, const Chain& format)
{

#ifdef CGDEBUG
    _pModule->log(_modId, Logger::DEBUG, Chain("Collecting schema ..."));
#endif

    if ( _protType == CegoDbHandler::XML )
    {	    

	_xml.getDocument()->clear();
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->setAttribute(XML_FORMAT_ATTR, format);
	
	_xml.getDocument()->setRootElement(pRoot);
	_xml.getDocument()->setDocType(XML_DATA_DOC);
	
	CegoField *pF = schema.First();
	while ( pF ) 
	{
	    
	    Chain tname;
	    if (pF->getTableAlias().length() > 0)
	    {
		tname = pF->getTableAlias();
	    }
	    else
	    {
		tname = pF->getTableName();
	    }
	    
	    Element *pColElement = new Element(XML_SCHEMA_ELEMENT);
	    pColElement->setAttribute(XML_TABLENAME_ATTR, tname);
	    
	    CegoXMLHelper xh;
	    xh.setColInfo(pColElement, pF);
	    
	    pRoot->addContent(pColElement);
	    pF = schema.Next();
	}
	
	Chain response;
	_xml.getXMLChain(response);
	
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, response);
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
	_pN->setMsg((char*)response, response.length());
	_pN->writeMsg();
	
	// document must be cleared because of follow up collectData calls 
	_xml.getDocument()->clear();
    }
    else
    {
	_pSer->reset();
	_pSer->writeChain(Chain(SER_SDATA));
	_pSer->writeChain(format);
	_pSer->writeSchema(schema);
	_serSync = false;
    }
}

void CegoDbHandler::sendObjInfo(CegoDecodableObject& oe)
{

    if ( _protType == CegoDbHandler::XML )
    {	    

	_xml.getDocument()->clear();
	
	Element* pRoot = new Element(XML_FRAME_ELEMENT);
	pRoot->addContent(oe.getElement());
	
	_xml.getDocument()->setRootElement(pRoot);
	_xml.getDocument()->setDocType(XML_INFO_DOC);
	
	Chain response;
	_xml.getXMLChain(response);

#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
	_pModule->log(_modId, Logger::DEBUG, response);
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
	_pN->setMsg((char*)response, response.length());
	_pN->writeMsg();
	
	_xml.getDocument()->clear();
    }
    else
    {

	_pSer->reset();
	_pSer->writeChain(Chain(SER_INFO));
	_pSer->writeObject(oe);
	
#ifdef CGDEBUG
	_pModule->log(_modId, Logger::DEBUG, Chain("--- SER ---"));
	_pModule->log(_modId, Logger::DEBUG, Chain(_pN->getMsg(), _pN->getMsgSize()));
	_pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif
	
	_pN->writeMsg();
	_pSer->reset();

    }
    
}

void CegoDbHandler::collectData(const ListT<CegoField>& schema)
{

    if ( _protType == CegoDbHandler::XML )
    {	    

	Element* pRoot = _xml.getDocument()->getRootElement();
	if ( pRoot == 0)
	{
	    pRoot = new Element(XML_FRAME_ELEMENT);
	    _xml.getDocument()->setRootElement(pRoot);	
	}
	
	Element *pRowElement = new Element(XML_ROW_ELEMENT);
	
	int col=1;
	CegoField *pF = schema.First();
	while ( pF )
	{
	    
	    Chain colPos = Chain(NETMNG_COLPREFIX) + Chain(col);
	    
	    if ( ! pF->getValue().isNull() )
	    {
		pRowElement->setAttribute(colPos, pF->getValue().valAsChain());   
	    }
	    col++;
	    pF = schema.Next();
	}
	
	pRoot->addContent(pRowElement);
    }
    else
    {
	if ( _pSer->isReset() )
	    _pSer->writeChain(SER_FDATA);
	
	_pSer->writeRow(schema);
    }
}

void CegoDbHandler::collectData(const ListT<CegoField>& schema, const ListT<CegoFieldValue>& fvl)
{

    if ( _protType == CegoDbHandler::XML )
    {	    

	Element* pRoot = _xml.getDocument()->getRootElement();
	if ( pRoot == 0)
	{
	    pRoot = new Element(XML_FRAME_ELEMENT);
	    _xml.getDocument()->setRootElement(pRoot);	
	}
	
	Element *pRowElement = new Element(XML_ROW_ELEMENT);
	
	int col=1;
	CegoField *pF = schema.First();
	CegoFieldValue *pFV = fvl.First();
	
	while ( pF && pFV )
	{
	    
	    Chain colPos = Chain(NETMNG_COLPREFIX) + Chain(col);
	    
	    if ( ! pFV->isNull() )
	    {
		pRowElement->setAttribute(colPos, pFV->valAsChain());
	    }
	    col++;
	    pF = schema.Next();
	    pFV = fvl.Next();
	}
	
	pRoot->addContent(pRowElement);    
    }
    else
    {
	if ( _pSer->isReset() )
	    _pSer->writeChain(SER_FDATA);
	_pSer->writeRow(fvl);
    }
}

NetHandler* CegoDbHandler::getNetHandler()
{
    return _pN;
}

CegoDbHandler::ResultType CegoDbHandler::sendXMLReq(const Chain& reqType, Element* pRoot)
{
    _xml.getDocument()->clear();
    _xml.getDocument()->setRootElement(pRoot);
    _xml.getDocument()->setDocType(reqType);
    
    Chain request;
    _xml.getXMLChain(request);
    _xml.getDocument()->clear();


#ifdef CGDEBUG
    _pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
    _pModule->log(_modId, Logger::DEBUG, request);
    _pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif    

    _pN->setMsg(request, request.length());

    _pN->writeMsg();
    
    _pN->readMsg();

#ifdef CGDEBUG
    _pModule->log(_modId, Logger::DEBUG, Chain("--- XML ---"));
    _pModule->log(_modId, Logger::DEBUG, _pN->getMsg());
    _pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif

    _xml.getDocument()->clear();
    _xml.setChain( _pN->getMsg() );

    Chain docType;

    try
    {	
	_xml.parse();
	docType = _xml.getDocument()->getDocType();
    }
    catch ( Exception e )
    {
	docType = Chain("INVALID");
    }
    
    
    if ( docType == Chain(XML_OK_DOC) )
    {
	return DB_OK;
    }
    else if ( docType == Chain(XML_ERROR_DOC) )
    {

	Element *pRoot = _xml.getDocument()->getRootElement();
	
	if ( pRoot )
	{
	    _serMsg = pRoot->getAttributeValue(XML_MSG_ATTR);
	}

	return DB_ERROR;
    }
    else if ( docType == Chain(XML_INFO_DOC) )
    {
	return DB_INFO;
    }
    else
    {
	_serMsg =  Chain("Wrong protocol");
	return DB_ERROR;
    }
}

CegoDbHandler::ResultType CegoDbHandler::sendSerialReq()
{

#ifdef CGDEBUG
    _pModule->log(_modId, Logger::DEBUG, Chain("--- Ser ---"));
    _pModule->log(_modId, Logger::DEBUG, Chain(_pN->getMsg(), _pN->getMsgSize()));
    _pModule->log(_modId, Logger::DEBUG, Chain("--- --- ---"));
#endif    

    _pN->writeMsg();
    
    _pN->readMsg();

    _pSer->reset();
    Chain req = _pSer->readChain();

    if ( req == Chain(SER_OK))
    {
	_serMsg = _pSer->readChain();
	_serAffected = _pSer->readChain().asInteger();
	return DB_OK;
    }
    else if ( req == Chain(SER_FIN))
    {
	_serMsg = Chain("No rows");
	_serAffected = 0;
	return DB_FIN;
    }
    else if ( req == Chain(SER_SACK))
    {
	_serMsg = _pSer->readChain();
	_serTid = _pSer->readChain().asLong();
	_serDbName = _pSer->readChain();
	_serDbVersion = _pSer->readChain();
	
	return DB_OK;
    }
    else if ( req == Chain(SER_PROCRES))
    {

	_serMsg = Chain("Procedure executed");	

	while ( _pSer->numAhead() > 0 )
	{
	    Chain paramName = _pSer->readChain();
	    Chain paramType = _pSer->readChain();
	    Chain paramValue = _pSer->readChain();
	 
	    CegoTypeConverter tc;
	    CegoDataType datatype = tc.getTypeId(paramType);
	    
	    if ( paramName == Chain("@OUT") )
	    {
		_retValue = CegoFieldValue(datatype, paramValue);
	    }
	    else
	    {
		CegoFieldValue fv(datatype, paramValue);
		_outParamList.Insert( CegoProcVar(paramName, CegoProcVar::OUTVAR, fv.getType(), fv.getLength(), fv));
	    }
	}

	return DB_OK;
    }

    else if ( req == Chain(SER_ERROR) )
    {
	_serMsg = _pSer->readChain();
	return DB_ERROR;
    }
    else if ( req == Chain(SER_INFO) )
    {
	_serMsg = _pSer->readChain();
	return DB_INFO;
    }
    else if ( req == Chain(SER_SDATA) )
    {
	_serFormat = _pSer->readChain();
	_serSchema = _pSer->readSchema();
	return DB_DATA;
    }
    else
    {
	_serMsg = Chain("Wrong protocol");
	return DB_ERROR;
    }    
}

