///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoXMLSpace.cc
// ---------------
// Cego XML space implementation
//     
// 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.
//
// IMPLEMENTATION MODULE
//
// Class: CegoXMLSpace
// 
// Description: 
//
// Status: QG-2.6
//
///////////////////////////////////////////////////////////////////////////////

#ifndef _REENTRANT
#define _REENTRANT    /* basic 3-lines for threads */
#endif

// base includes
#include <lfc/File.h>
#include <lfc/Host.h>
#include <lfc/Datetime.h>
#include <lfc/ThreadLock.h>
#include <lfc/Tokenizer.h>
#include <lfc/Matcher.h>

// xml includes
#include <lfc/XMLSuite.h>
#include <lfc/Element.h>
#include <lfc/Document.h>


// cego includes
#include "CegoXMLdef.h"
#include "CegoXMLSpace.h"

static ThreadLock xmlLock("XML");

extern char __caseSensitiveFlag;
extern bool __lockStatOn;

/////////////////////
// CegoXMLSpace //
/////////////////////

CegoXMLSpace::CegoXMLSpace(const Chain& xmlDef)
{
    for ( int i = 0 ; i < TABMNG_MAXTABSET ; i++)
	_tsCache[i] = 0;
    
    _xmlDef = xmlDef;
    _pDoc = new Document;

    xmlLock.init(LCKMNG_LOCKWAITDELAY, __lockStatOn);
}

CegoXMLSpace::~CegoXMLSpace()
{  
    delete _pDoc;
}

Element* CegoXMLSpace::getDbSpec()
{
    return _pDoc->getRootElement()->createClone();
}

Element* CegoXMLSpace::getTableSetInfo(const Chain& tableSet)
{
    P();

    Element *pTSE = getTableSetElement(tableSet);
    if ( pTSE )
    {

	Element *pTS = pTSE->createClone();
	
	V();
	return pTS;	
    }
    
    V();
    Chain msg = Chain("Unknown tableset name ") + tableSet; 
    throw Exception(EXLOC, msg);
}

void CegoXMLSpace::setTableSetInfo(const Chain& tableSet, Element *pTS)
{
    
    P();
    
    ListT<Element*> tsList;    
    tsList = _pDoc->getRootElement()->getChildren(XML_TABLESET_ELEMENT);
    
    Element **pOldTS = tsList.First();
    bool notFound = true;
    while ( pOldTS && notFound ) 
    {
	if ( (*pOldTS)->getAttributeValue(XML_NAME_ATTR) == tableSet )
	{    
	    int tabSetId = (*pOldTS)->getAttributeValue(XML_TSID_ATTR).asInteger();
	    _tsCache[tabSetId] = 0;
	    _pDoc->getRootElement()->removeChild( *pOldTS );
	    notFound = false;
	}
	pOldTS = tsList.Next();
    }

    int tabSetId = pTS->getAttributeValue(XML_TSID_ATTR).asInteger();
    _tsCache[tabSetId] = pTS;
    _pDoc->getRootElement()->addContent( pTS );
    V();
}

Element* CegoXMLSpace::getTableSetList()
{

    P();

    ListT<Element*> tabSetList = _pDoc->getRootElement()->getChildren(XML_TABLESET_ELEMENT);
    
    Element *pTabSetInfo = new Element(XML_TABLESETLIST_ELEMENT);
    
    Element **pTabSet = tabSetList.First();
    while ( pTabSet )
    {
	Element *pTS = new Element(XML_TABLESET_ELEMENT);
	pTS->setAttribute(XML_NAME_ATTR, (*pTabSet)->getAttributeValue(XML_NAME_ATTR));
	pTS->setAttribute(XML_RUNSTATE_ATTR, (*pTabSet)->getAttributeValue(XML_RUNSTATE_ATTR));
	pTS->setAttribute(XML_SYNCSTATE_ATTR, (*pTabSet)->getAttributeValue(XML_SYNCSTATE_ATTR));
	// pTS->setAttribute(XML_MEDIATOR_ATTR, (*pTabSet)->getAttributeValue(XML_MEDIATOR_ATTR));
	// pTS->setAttribute(XML_PRIMARY_ATTR, (*pTabSet)->getAttributeValue(XML_PRIMARY_ATTR));
	// pTS->setAttribute(XML_SECONDARY_ATTR, (*pTabSet)->getAttributeValue(XML_SECONDARY_ATTR));
	
	pTabSetInfo->addContent(pTS);
	pTabSet = tabSetList.Next();
    }

    V();

    return pTabSetInfo;
}

void CegoXMLSpace::getTableSetList(ListT<Chain>& tsList)
{

    P();

    ListT<Element*> tabSetList = _pDoc->getRootElement()->getChildren(XML_TABLESET_ELEMENT);
        
    Element **pTabSet = tabSetList.First();
    while ( pTabSet )
    {
	tsList.Insert ( (*pTabSet)->getAttributeValue(XML_NAME_ATTR));
	pTabSet = tabSetList.Next();
    }

    V();

    return;
}

Element* CegoXMLSpace::getNodeList()
{
    P();

    ListT<Element*> nodeList = _pDoc->getRootElement()->getChildren(XML_NODE_ELEMENT);
    Element *pNodeInfo = new Element(XML_NODEINFO_ELEMENT);
    
    Element **pNode = nodeList.First();
    while ( pNode )
    {
	Element *pN = new Element(XML_NODE_ELEMENT);
	pN->setAttribute(XML_HOSTNAME_ATTR, (*pNode)->getAttributeValue(XML_HOSTNAME_ATTR));
	pN->setAttribute(XML_STATUS_ATTR, (*pNode)->getAttributeValue(XML_STATUS_ATTR));
	pNodeInfo->addContent(pN);
	pNode = nodeList.Next();
    }
    V();

    return pNodeInfo;
}

void CegoXMLSpace::addHost(const Chain& hostName, const Chain& status)
{
    P();

    Element* rootElement = _pDoc->getRootElement();    
    Element* pHostEntry = new Element(XML_NODE_ELEMENT);
    pHostEntry->setAttribute(XML_HOSTNAME_ATTR, hostName);
    pHostEntry->setAttribute(XML_STATUS_ATTR, status);
    _pDoc->getRootElement()->addContent(pHostEntry);
    V();
}

void CegoXMLSpace::setHostStatus( const Chain& hostName, const Chain& status)
{
    P();

    ListT<Element*> nodeList;    
    nodeList = _pDoc->getRootElement()->getChildren(XML_NODE_ELEMENT);

    Element **pNode = nodeList.First();
    while ( pNode ) 
    {
	if ( (*pNode)->getAttributeValue(XML_HOSTNAME_ATTR) == hostName )
	{
	    (*pNode)->setAttribute(XML_STATUS_ATTR, status);
	    Datetime d;
	    (*pNode)->setAttribute(XML_TIMESTAMP_ATTR, d.asChain());
	    V();
	    return;
	}
	else
	    pNode = nodeList.Next();
    }
    
    V();

    addHost(hostName, status);

}

void CegoXMLSpace::getStatusByHost(const Chain& hostName, Chain& status)
{

    P();
    
    ListT<Element*> nodeList;    
    nodeList = _pDoc->getRootElement()->getChildren(XML_NODE_ELEMENT);

    Element **pNode = nodeList.First();
    while ( pNode ) 
    {
	if ( (*pNode)->getAttributeValue(XML_HOSTNAME_ATTR) == (Chain)hostName )
	{
	    status = (*pNode)->getAttributeValue(XML_STATUS_ATTR);
	    V();
	    return;
	}
	else
	{
	    pNode = nodeList.Next();
	}
    }
    V();
    Chain msg = Chain("Unknown hostname ") + hostName; 
    throw Exception(EXLOC, msg);
}

void CegoXMLSpace::removeHost( const Chain& hostName)
{
    
    P();
    ListT<Element*> nodeList;    
    nodeList = _pDoc->getRootElement()->getChildren(XML_NODE_ELEMENT);

    Element **pNode = nodeList.First();
    while ( pNode ) 
    {
	if ( (*pNode)->getAttributeValue(XML_HOSTNAME_ATTR) == hostName )
	{
	    _pDoc->getRootElement()->removeChild(*pNode);
	    V();
	    return;
	}
	else
	    pNode = nodeList.Next();
    }
    V();
    Chain msg = Chain("Unknown hostname ") + hostName; 
    throw Exception(EXLOC, msg);
}

int CegoXMLSpace::getNumRecordSema()
{
    P();
    int numRecSema = _pDoc->getRootElement()->getAttributeValue(XML_NUMRECSEMA_ATTR).asInteger();
    V();
 
    if ( numRecSema == 0 )
	numRecSema = LCKMNG_NUM_RECORD_SEMA;

    return numRecSema;
}

int CegoXMLSpace::getNumRBRecordSema()
{
    P();
    int numRBRecSema = _pDoc->getRootElement()->getAttributeValue(XML_NUMRBRECSEMA_ATTR).asInteger();
    V();
    
    if ( numRBRecSema == 0 )
	numRBRecSema = LCKMNG_NUM_RBRECORD_SEMA;

    return numRBRecSema;
}

int CegoXMLSpace::getNumSysRecordSema()
{
    P();
    int numSysRecSema = _pDoc->getRootElement()->getAttributeValue(XML_NUMSYSRECSEMA_ATTR).asInteger();
    V();
    
    if ( numSysRecSema == 0 )
	numSysRecSema = LCKMNG_NUM_SYSRECORD_SEMA;

    return numSysRecSema;
}

int CegoXMLSpace::getNumSysPageSema()
{
    P();
    int numSysPageSema = _pDoc->getRootElement()->getAttributeValue(XML_NUMSYSPAGESEMA_ATTR).asInteger();
    V();
    if ( numSysPageSema == 0 )
	numSysPageSema = LCKMNG_NUM_SYSPAGE_SEMA;
    return numSysPageSema;
}

int CegoXMLSpace::getNumDataPageSema()
{
    P();
    int numDataPageSema = _pDoc->getRootElement()->getAttributeValue(XML_NUMDATAPAGESEMA_ATTR).asInteger();
    V();
    if ( numDataPageSema == 0 )
	numDataPageSema = LCKMNG_NUM_DATAPAGE_SEMA;
    return numDataPageSema;
}

int CegoXMLSpace::getNumIndexPageSema()
{
    P();
    int numIdxPageSema = _pDoc->getRootElement()->getAttributeValue(XML_NUMIDXPAGESEMA_ATTR).asInteger();
    V();
    if ( numIdxPageSema == 0 )
	numIdxPageSema = LCKMNG_NUM_IDXPAGE_SEMA;
    return numIdxPageSema;
}

int CegoXMLSpace::getNumRBPageSema()
{
    P();
    int numRBPageSema = _pDoc->getRootElement()->getAttributeValue(XML_NUMRBPAGESEMA_ATTR).asInteger();
    V();
    if ( numRBPageSema == 0 )
	numRBPageSema = LCKMNG_NUM_RBPAGE_SEMA;
    return numRBPageSema;
}

int CegoXMLSpace::getNumDataFileSema()
{
    P();
    int numDataFileSema = _pDoc->getRootElement()->getAttributeValue(XML_NUMDATAFILESEMA_ATTR).asInteger();
    V();
    if ( numDataFileSema == 0 )
	numDataFileSema = LCKMNG_NUM_DATAFILE_SEMA;
    return numDataFileSema;
}

int CegoXMLSpace::getNumBufferPoolSema()
{
    P();
    int numBufferPoolSema = _pDoc->getRootElement()->getAttributeValue(XML_NUMBUFFERPOOLSEMA_ATTR).asInteger();
    V();
    if ( numBufferPoolSema == 0 )
	numBufferPoolSema = LCKMNG_NUM_BUFFERPOOL_SEMA;
    return numBufferPoolSema;    
}

int CegoXMLSpace::getMaxFixTries()
{
    P();
    int maxFixTries = _pDoc->getRootElement()->getAttributeValue(XML_MAXFIXTRIES_ATTR).asInteger();
    V();
    if ( maxFixTries == 0 )
	maxFixTries = BUPMNG_MAXFIXTRIES;
    return maxFixTries;    
}

int CegoXMLSpace::getPageLockTimeout()
{
    P();
    int lockTimeout = _pDoc->getRootElement()->getAttributeValue(XML_PAGELOCKTIMEOUT_ATTR).asInteger();
    V();
    if ( lockTimeout == 0 )
	lockTimeout = PG_LOCKTIMEOUT;
    return lockTimeout;
}

int CegoXMLSpace::getRecLockTimeout()
{
    P();
    int lockTimeout = _pDoc->getRootElement()->getAttributeValue(XML_RECLOCKTIMEOUT_ATTR).asInteger();
    V();
    if ( lockTimeout == 0 )
	lockTimeout = RC_LOCKTIMEOUT;
    return lockTimeout;
}

int CegoXMLSpace::getFileLockTimeout()
{
    P();
    int lockTimeout = _pDoc->getRootElement()->getAttributeValue(XML_FILELOCKTIMEOUT_ATTR).asInteger();
    V();
    if ( lockTimeout == 0 )
	lockTimeout = FH_LOCKTIMEOUT;
    return lockTimeout;
}

int CegoXMLSpace::getPoolLockTimeout()
{
    P();
    int lockTimeout = _pDoc->getRootElement()->getAttributeValue(XML_POOLLOCKTIMEOUT_ATTR).asInteger();
    V();
    if ( lockTimeout == 0 )
	lockTimeout = BP_LOCKTIMEOUT;
    return lockTimeout;
}

int CegoXMLSpace::getNumLockTries()
{
    P();
    int numLockTries = _pDoc->getRootElement()->getAttributeValue(XML_NUMLOCKTRIES_ATTR).asInteger();
    V();
    if ( numLockTries == 0 )
	numLockTries = LCKMNG_NUMLOCKTRIES;
    return numLockTries;
}

bool CegoXMLSpace::isCaseSensitiveMode()
{
    P();
    Chain mode = _pDoc->getRootElement()->getAttributeValue(XML_CSMODE_ATTR);
    V();
    if ( mode == Chain(XML_ON_VALUE) )
	return true;
    return false;    
}

bool CegoXMLSpace::isQuoteEscapeMode()
{
    P();
    Chain mode = _pDoc->getRootElement()->getAttributeValue(XML_QESCMODE_ATTR);
    V();
    if ( mode == Chain(XML_ON_VALUE) )
	return true;
    return false;    
}

Chain CegoXMLSpace::getDateFormatString()
{
    P();
    Chain dtFormat = _pDoc->getRootElement()->getAttributeValue(XML_DTFORMAT_ATTR);
    V();
    return dtFormat;
}

void CegoXMLSpace::setArchRestoreProg(const Chain& progName)
{
    P();
    _pDoc->getRootElement()->setAttribute(XML_LOGMNGPROG_ATTR, progName);
    V();
}

Chain CegoXMLSpace::getArchRestoreProg()
{
    P();
    Chain archRestoreProg = _pDoc->getRootElement()->getAttributeValue(XML_LOGMNGPROG_ATTR);
    V();
    return archRestoreProg;
}

void CegoXMLSpace::setArchRestoreTimeout(int timeout)
{
    P();
    _pDoc->getRootElement()->setAttribute(XML_LOGMNGTIMEOUT_ATTR, Chain(timeout));
    V();
}

int CegoXMLSpace::getArchRestoreTimeout()
{
    P();
    int timeout = _pDoc->getRootElement()->getAttributeValue(XML_LOGMNGTIMEOUT_ATTR).asInteger();
    V();
    return timeout;
}

Chain CegoXMLSpace::getPrimary(const int tabSetId)
{
    Chain primary;

    Element *pTSE = getCachedTableSetElement(tabSetId);

    if ( pTSE == 0 )
    {
	Chain msg = Chain("Unknown tableset id ") + Chain(tabSetId); 
	throw Exception(EXLOC, msg);
    }

    P();    
    primary = pTSE->getAttributeValue(XML_PRIMARY_ATTR);
    V();

    return primary; 
}

Chain CegoXMLSpace::getPrimary(const Chain& tabSetName)
{

    Chain primary;
    P();

    Element *pTSE = getTableSetElement(tabSetName);
    if ( pTSE )
    {
	primary = pTSE->getAttributeValue(XML_PRIMARY_ATTR);  
    }
    else
    {
	V();
	Chain msg = Chain("Unknown tableset name ") + tabSetName; 
	throw Exception(EXLOC, msg);
    }
    V();
    return primary;
}

Chain CegoXMLSpace::getSecondary(const int tabSetId)
{
    Chain secondary;

    Element *pTSE = getCachedTableSetElement(tabSetId);

    P();

    if ( pTSE )
    {
	secondary = pTSE->getAttributeValue(XML_SECONDARY_ATTR);  
    }
    else
    {
	V();
	Chain msg = Chain("Unknown tableset id ") + Chain(tabSetId); 
	throw Exception(EXLOC, msg);
    }
    V();
    return secondary;
}

Chain CegoXMLSpace::getSecondary(const Chain& tabSetName)
{

    Chain secondary;
    P();

    Element *pTSE = getTableSetElement(tabSetName);
    if ( pTSE )
    {
	secondary = pTSE->getAttributeValue(XML_SECONDARY_ATTR);  
    }
    else
    {
	V();
	Chain msg = Chain("Unknown tableset name ") + tabSetName; 
	throw Exception(EXLOC, msg);
    }
    V();
    return secondary;
}

Chain CegoXMLSpace::getMediator(const int tabSetId)
{

    Chain mediator;
    Element *pTSE = getCachedTableSetElement(tabSetId);

    P();

    if ( pTSE )
    {
	mediator = pTSE->getAttributeValue(XML_MEDIATOR_ATTR);  
    }
    else
    {
	V();
	Chain msg = Chain("Unknown tableset id ") + Chain(tabSetId); 
	throw Exception(EXLOC, msg);
    }
    V();
    return mediator;
}

Chain CegoXMLSpace::getMediator(const Chain& tabSetName)
{

    Chain mediator;
    P();

    Element *pTSE = getTableSetElement(tabSetName);
    if ( pTSE )
    {
	mediator = pTSE->getAttributeValue(XML_MEDIATOR_ATTR);  
    }
    else
    {
	V();
	Chain msg = Chain("Unknown tableset name ") + tabSetName; 
	throw Exception(EXLOC, msg);
    }
    V();
    return mediator;
}


void CegoXMLSpace::setPrimary(const Chain& tabSetName, const Chain& hostName)
{
    P();
    Element *pTSE = getTableSetElement(tabSetName);
    if ( pTSE )
    {
	pTSE->setAttribute(XML_PRIMARY_ATTR, hostName);  
    }
    else
    {
	V();
	Chain msg = Chain("Unknown tableset name ") + tabSetName; 
	throw Exception(EXLOC, msg);
    }
    V();
}

void CegoXMLSpace::setSecondary(const Chain& tabSetName, const Chain& hostName)
{
    P();
    Element *pTSE = getTableSetElement(tabSetName);
    if ( pTSE )
    {
	pTSE->setAttribute(XML_SECONDARY_ATTR, hostName);  
    }
    else
    {
	V();
	Chain msg = Chain("Unknown tableset name ") + tabSetName; 
	throw Exception(EXLOC, msg);
    }
    V();
}

void CegoXMLSpace::setMediator(const Chain& tabSetName, const Chain& hostName)
{  
    P();
    Element *pTSE = getTableSetElement(tabSetName);
    if ( pTSE )
    {
	pTSE->setAttribute(XML_MEDIATOR_ATTR, hostName);  
    }
    else
    {
	V();
	Chain msg = Chain("Unknown tableset name ") + tabSetName; 
	throw Exception(EXLOC, msg);
    }
    V();
}

void CegoXMLSpace::getMedList(const Chain& hostname, ListT<Chain>& medList)
{
    P();

    ListT<Element*> tabSetList = _pDoc->getRootElement()->getChildren(XML_TABLESET_ELEMENT);
        
    Element **pTabSet = tabSetList.First();
    while ( pTabSet )
    {
	
	if ( ( hostname == (*pTabSet)->getAttributeValue(XML_PRIMARY_ATTR) 
	       || hostname == (*pTabSet)->getAttributeValue(XML_SECONDARY_ATTR) ) 
	     && hostname != (*pTabSet)->getAttributeValue(XML_MEDIATOR_ATTR) )
	{
	    medList.Insert((*pTabSet)->getAttributeValue(XML_MEDIATOR_ATTR));
	}
	pTabSet = tabSetList.Next();
    }
    V();    
}

void CegoXMLSpace::getTSforMedAndPrim(const Chain& mediator, const Chain& primary, ListT<Chain>& tsList)
{
    P();
    ListT<Element*> tabSetList = _pDoc->getRootElement()->getChildren(XML_TABLESET_ELEMENT);
        
    Element **pTabSet = tabSetList.First();
    while ( pTabSet )
    {
	
	if ( primary == (*pTabSet)->getAttributeValue(XML_PRIMARY_ATTR) 
	     && mediator == (*pTabSet)->getAttributeValue(XML_MEDIATOR_ATTR) )
	{
	    tsList.Insert((*pTabSet)->getAttributeValue(XML_NAME_ATTR));
	}
	pTabSet = tabSetList.Next();
    }
    V();
}

int CegoXMLSpace::getTabSetId(const Chain& tabSetName)
{
    int tabSetId;

    P();
    Element *pTSE = getTableSetElement(tabSetName);
    if ( pTSE )
    {
	tabSetId = pTSE->getAttributeValue(XML_TSID_ATTR).asInteger();  
    }
    else
    {
	V();
	Chain msg = Chain("Unknown tableset name ") + tabSetName; 
	throw Exception(EXLOC, msg);
    }
    V();
    return tabSetId;
}


Chain CegoXMLSpace::getTabSetName(int tabSetId)
{
    Chain tabSetName;

    Element *pTSE = getCachedTableSetElement(tabSetId);
    if ( pTSE == 0 )
    {
	Chain msg = Chain("Unknown tableset id ") + Chain(tabSetId); 
	throw Exception(EXLOC, msg);
    }
    P();
    tabSetName = pTSE->getAttributeValue(XML_NAME_ATTR);    
    V();
    return tabSetName;
}

int CegoXMLSpace::getTmpFid(const Chain& tabSetName)
{
    int tmpFid;

    P();
    Element *pTSE = getTableSetElement(tabSetName);
    if ( pTSE )
    {
	tmpFid = pTSE->getAttributeValue(XML_TMPFID_ATTR).asInteger();  
    }
    else
    {
	V();
	Chain msg = Chain("Unknown tableset name ") + tabSetName; 
	throw Exception(EXLOC, msg);
    }
    V();
    return tmpFid;
}


void CegoXMLSpace::setTSSysSize(const Chain& tableSet, int sysSize)
{
    P();
    Element *pTS = getTableSetElement(tableSet);

    if ( pTS )
    {
	pTS->setAttribute(XML_SYSSIZE_ATTR, Chain(sysSize));
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
}


int CegoXMLSpace::getSysSize(const Chain& tabSetName)
{
    int sysSize;

    P();
    Element *pTSE = getTableSetElement(tabSetName);
    if ( pTSE )
    {
	sysSize = pTSE->getAttributeValue(XML_SYSSIZE_ATTR).asInteger();  
    }
    else
    {
	V();
	Chain msg = Chain("Unknown tableset name ") + tabSetName; 
	throw Exception(EXLOC, msg);
    }
    V();
    return sysSize;
}


void CegoXMLSpace::setTSTmpSize(const Chain& tableSet, int tmpSize)
{
    P();
    Element *pTS = getTableSetElement(tableSet);

    if ( pTS )
    {
	pTS->setAttribute(XML_TMPSIZE_ATTR, Chain(tmpSize));
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
}


int CegoXMLSpace::getTmpSize(const Chain& tabSetName)
{
    int tmpSize;

    P();
    Element *pTSE = getTableSetElement(tabSetName);
    if ( pTSE )
    {
	tmpSize =  pTSE->getAttributeValue(XML_TMPSIZE_ATTR).asInteger();  
    }
    else
    {
	V();
	Chain msg = Chain("Unknown tableset name ") + tabSetName; 
	throw Exception(EXLOC, msg);
    }
    V();
    return tmpSize;
}

void CegoXMLSpace::setTSLogNum(const Chain& tableSet, int logNum)
{

    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_NAME_ATTR) == tableSet )
	    {
		Chain tsRoot = (*pTSE)->getAttributeValue(XML_TSROOT_ATTR); 
		int logSize=0;
		ListT<Element*> logFileList = (*pTSE)->getChildren(XML_LOGFILE_ELEMENT);
		Element **pLF = logFileList.First();
		while ( pLF )
		{
		    logSize = (*pLF)->getAttributeValue(XML_SIZE_ATTR).asInteger();
		    (*pTSE)->removeChild(*pLF);
		    pLF = logFileList.Next();
		}

		for ( int i = 0 ; i < logNum ; i++ )
		{
		    Element *pLE = new Element(XML_LOGFILE_ELEMENT);
		    
		    Chain logName = tsRoot + Chain("/") + tableSet + Chain("redo") +  + Chain(i) + Chain(".log");
		    pLE->setAttribute(XML_NAME_ATTR, logName);
		    pLE->setAttribute(XML_SIZE_ATTR, Chain(logSize));
		    pLE->setAttribute(XML_STATUS_ATTR, XML_FREE_VALUE);
		    
		    (*pTSE)->addContent(pLE);
		}

		V();
		return;
	    }
	    pTSE = tabSetList.Next();
	}
	
	V();
	Chain msg = Chain("Unknown tableset ") + tableSet; 
	throw Exception(EXLOC, msg);
    }
    V();
    throw Exception(EXLOC, "Root element not found");

}

void CegoXMLSpace::setTSLogSize(const Chain& tableSet, int logSize)
{

    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_NAME_ATTR) == tableSet )
	    {
		ListT<Element*> logFileList = (*pTSE)->getChildren(XML_LOGFILE_ELEMENT);
		Element **pLF = logFileList.First();
		while ( pLF )
		{
		    (*pLF)->setAttribute(XML_SIZE_ATTR, Chain(logSize));
		    pLF = logFileList.Next();
		}
		V();
		return;
	    }
	    pTSE = tabSetList.Next();
	}
	
	V();
	Chain msg = Chain("Unknown tableset ") + tableSet; 
	throw Exception(EXLOC, msg);
    }
    V();
    throw Exception(EXLOC, "Root element not found");    
}

void CegoXMLSpace::setTSSortAreaSize(const Chain& tableSet, int sortAreaSize)
{
    P();
    Element *pTS = getTableSetElement(tableSet);

    if ( pTS )
    {
	pTS->setAttribute(XML_SORTAREASIZE_ATTR, Chain(sortAreaSize));
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
}

void CegoXMLSpace::addTableSetDef(const Chain& tabSetName, 
				  const Chain& tsRoot, 
				  const Chain& tsTicket, 
				  const Chain& primary,
				  const Chain& secondary, 
				  const Chain& mediator,
				  int sysFileId, int tempFileId, int sysFileSize, int tmpFileSize,
				  int logFileSize, int logFileNum, long sortAreaSize)
{

    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_NAME_ATTR) == tabSetName )
	    {
		V();
		Chain msg = Chain("Tableset ") + Chain(tabSetName) + Chain(" already defined"); 
		throw Exception(EXLOC, msg);
	    }
	    pTSE = tabSetList.Next();
	}	
    }

    Element *pTSE = new Element(XML_TABLESET_ELEMENT);
    pTSE->setAttribute(XML_NAME_ATTR, tabSetName);
    pTSE->setAttribute(XML_TSROOT_ATTR, tsRoot);
    pTSE->setAttribute(XML_PRIMARY_ATTR, primary);
    pTSE->setAttribute(XML_SECONDARY_ATTR, secondary);
    pTSE->setAttribute(XML_MEDIATOR_ATTR, mediator);
    pTSE->setAttribute(XML_RUNSTATE_ATTR, XML_DEFINED_VALUE);
    pTSE->setAttribute(XML_SYNCSTATE_ATTR, XML_SYNCHED_VALUE);

    pTSE->setAttribute(XML_TSTICKET_ATTR, tsTicket);
    
    pTSE->setAttribute(XML_TSID_ATTR, Chain( sysFileId ) );
    pTSE->setAttribute(XML_TMPFID_ATTR, Chain( tempFileId ) );

    pTSE->setAttribute(XML_SYSSIZE_ATTR, Chain( sysFileSize ) );
    pTSE->setAttribute(XML_TMPSIZE_ATTR, Chain( tmpFileSize ) );

    pTSE->setAttribute(XML_SORTAREASIZE_ATTR, Chain( sortAreaSize ) );

    for ( int i = 0 ; i < logFileNum ; i++ )
    {
	Element *pLE = new Element(XML_LOGFILE_ELEMENT);

	Chain logName = tsRoot + Chain("/") + tabSetName + Chain("redo") +  + Chain(i) + Chain(".log");
	pLE->setAttribute(XML_NAME_ATTR, logName);
	pLE->setAttribute(XML_SIZE_ATTR, Chain(logFileSize));
	pLE->setAttribute(XML_STATUS_ATTR, XML_FREE_VALUE);
	
	pTSE->addContent(pLE);
    }

    _pDoc->getRootElement()->addContent(pTSE);
    
    V();
}

void CegoXMLSpace::rmTableSetDef(const Chain& tabSetName)
{
    P();
    
    ListT<Element*> tsList;    
    tsList = _pDoc->getRootElement()->getChildren(XML_TABLESET_ELEMENT);
    
    Element **pTS = tsList.First();
    while ( pTS ) 
    {
	if ( (*pTS)->getAttributeValue(XML_NAME_ATTR) == tabSetName )
	{
	    
	    int tabSetId = (*pTS)->getAttributeValue(XML_TSID_ATTR).asInteger();
	    _tsCache[tabSetId] = 0;
	    _pDoc->getRootElement()->removeChild( *pTS );
	    V();
	    return;
	}
	pTS = tsList.Next();
    }
    
    V();
    Chain msg = Chain("Unknown tableset ") + Chain(tabSetName); 
    throw Exception(EXLOC, msg);
}

bool CegoXMLSpace::isArchiveMode(int tabSetId)
{

    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_TSID_ATTR).asInteger() == tabSetId )
	    {
		bool archMode=false;
		if ( (*pTSE)->getAttributeValue(XML_ARCHMODE_ATTR) == Chain(XML_ON_VALUE) )
		    archMode=true;
		V();
		return archMode;
	    }
	    pTSE = tabSetList.Next();
	}
    }
    
    V();
    Chain msg = Chain("Unknown tableset id ") + Chain(tabSetId); 
    throw Exception(EXLOC, msg);
}    

bool CegoXMLSpace::isArchiveMode(const Chain& tableSet)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_NAME_ATTR) == tableSet )
	    {
		bool archMode=false;
		if ( (*pTSE)->getAttributeValue(XML_ARCHMODE_ATTR) == Chain(XML_ON_VALUE) )
		    archMode=true;
		V();
		return archMode;
	    }
	    pTSE = tabSetList.Next();
	}
    }
    V();
    Chain msg = Chain("Unknown tableset ") + tableSet; 
    throw Exception(EXLOC, msg);
}    


void CegoXMLSpace::enableArchLog(const Chain& tableSet)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_NAME_ATTR) == tableSet )
	    {
		(*pTSE)->setAttribute(XML_ARCHMODE_ATTR, Chain(XML_ON_VALUE));
		V();
		return;
	    }
	    pTSE = tabSetList.Next();
	}
    }
    V();
    Chain msg = Chain("Unknown tableset ") + tableSet; 
    throw Exception(EXLOC, msg);
}    

void CegoXMLSpace::disableArchLog(const Chain& tableSet)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_NAME_ATTR) == tableSet )
	    {
		(*pTSE)->setAttribute(XML_ARCHMODE_ATTR, Chain(XML_OFF_VALUE));
		V();
		return;
	    }
	    pTSE = tabSetList.Next();
	}
    }
    V();
    Chain msg = Chain("Unknown tableset ") + tableSet; 
    throw Exception(EXLOC, msg);
}    

void CegoXMLSpace::getArchLogInfo(int tabSetId, ListT<Chain>& archIdList, ListT<Chain>& archPathList)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_TSID_ATTR).asInteger() == tabSetId )
	    {
		ListT<Element*> archPathElementList = (*pTSE)->getChildren(XML_ARCHIVELOG_ELEMENT);
		Element **pAP = archPathElementList.First();
		while ( pAP )
		{
		    archPathList.Insert((*pAP)->getAttributeValue(XML_ARCHPATH_ATTR));
		    archIdList.Insert((*pAP)->getAttributeValue(XML_ARCHID_ATTR));

		    pAP = archPathElementList.Next();
		}
		V();
		return;
	    }
	    pTSE = tabSetList.Next();
	}
    }
    
    V();
    Chain msg = Chain("Unknown tableset id ") + Chain(tabSetId); 
    throw Exception(EXLOC, msg);
}    

void CegoXMLSpace::getArchLogInfo(const Chain& tableSet, ListT<Chain>& archIdList, ListT<Chain>& archPathList)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (Chain)(*pTSE)->getAttributeValue(XML_NAME_ATTR) == (Chain)tableSet )
	    {
		ListT<Element*> archPathElementList = (*pTSE)->getChildren(XML_ARCHIVELOG_ELEMENT);
		Element **pAP = archPathElementList.First();
		while ( pAP )
		{
		    archPathList.Insert((*pAP)->getAttributeValue(XML_ARCHPATH_ATTR));
		    archIdList.Insert((*pAP)->getAttributeValue(XML_ARCHID_ATTR));
		    pAP = archPathElementList.Next();
		}
		V();
		return;
	    }
	    pTSE = tabSetList.Next();
	}
    }
    
    V();
    Chain msg = Chain("Unknown tableset ") + tableSet; 
    throw Exception(EXLOC, msg);
}    

void CegoXMLSpace::getOccupiedLogList(int tabSetId, ListT<Chain>& occupiedLogList)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_TSID_ATTR).asInteger() == tabSetId )
	    {
		ListT<Element*> logElementList = (*pTSE)->getChildren(XML_LOGFILE_ELEMENT);
		Element **pLE = logElementList.First();
		while ( pLE )
		{
		    if ( (*pLE)->getAttributeValue(XML_STATUS_ATTR) == Chain(XML_OCCUPIED_VALUE))	
			occupiedLogList.Insert((*pLE)->getAttributeValue(XML_NAME_ATTR));
		    pLE = logElementList.Next();
		}
		V();
		return;
	    }
	    pTSE = tabSetList.Next();
	}
    }
    V();
    Chain msg = Chain("Unknown tableset id ") + Chain(tabSetId); 
    throw Exception(EXLOC, msg);
}    

void CegoXMLSpace::setLogFileStatus(int tabSetId, const Chain& logFile, const Chain& status)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_TSID_ATTR).asInteger() == tabSetId )
	    {
		ListT<Element*> logElementList = (*pTSE)->getChildren(XML_LOGFILE_ELEMENT);
		Element **pLE = logElementList.First();
		while ( pLE )
		{
		    if ( (*pLE)->getAttributeValue(XML_NAME_ATTR) == logFile)	
		    {
			(*pLE)->setAttribute(XML_STATUS_ATTR, status);
			V();
			return;
		    }
		    pLE = logElementList.Next();
		}
	    }
	    pTSE = tabSetList.Next();
	}
    }
    V();
    Chain msg = Chain("Unknown tableset id ") + Chain(tabSetId); 
    throw Exception(EXLOC, msg);    
}

bool CegoXMLSpace::addArchLog(const Chain& tableSet, const Chain& archId, const Chain& archPath)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_NAME_ATTR) == tableSet )
	    {

		ListT<Element*> archLogList = (*pTSE)->getChildren(XML_ARCHIVELOG_ELEMENT);
		Element **pAL = archLogList.First();
		while ( pAL )
		{
		    if ( (*pAL)->getAttributeValue(XML_ARCHID_ATTR) == archId )
		    {
			V();
			return false;
		    }
		    pAL = archLogList.Next();
		} 
		
		Element *pNAL = new Element(XML_ARCHIVELOG_ELEMENT);
		pNAL->setAttribute(XML_ARCHID_ATTR, archId);
		pNAL->setAttribute(XML_ARCHPATH_ATTR, archPath);
		
		(*pTSE)->addContent(pNAL);
		V();
		return true;
		
	    }
	    pTSE = tabSetList.Next();
	}
    }
    V();
    Chain msg = Chain("Unknown tableset ") + tableSet; 
    throw Exception(EXLOC, msg);    
}

bool CegoXMLSpace::removeArchLog(const Chain& tableSet, const Chain& archId)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_NAME_ATTR) == tableSet )
	    {
		ListT<Element*> archLogList = (*pTSE)->getChildren(XML_ARCHIVELOG_ELEMENT);
		Element **pAL = archLogList.First();
		while ( pAL )
		{
		    if ( (*pAL)->getAttributeValue(XML_ARCHID_ATTR) == archId )
		    {
			(*pTSE)->removeChild(*pAL);
			V();
			return true;
		    }
		    pAL = archLogList.Next();
		} 
		V();
		return false;
	    }
	    pTSE = tabSetList.Next();
	}
	
	V();
	Chain msg = Chain("Unknown tableset ") + tableSet; 
	throw Exception(EXLOC, msg);
    }
    V();
    throw Exception(EXLOC, "Root element not found");
}

void CegoXMLSpace::setUserPwd(const Chain& user, const Chain& password)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {	
	ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
	Element **pUE = userList.First();
	while ( pUE )
	{
	    if ( (*pUE)->getAttributeValue(XML_NAME_ATTR) == user )
	    {
		(*pUE)->setAttribute(XML_PASSWD_ATTR, password);
		V();
		return;
	    }
	    pUE = userList.Next();
	} 
	
	V();
	Chain msg = Chain("Unknown user ") + user; 
	throw Exception(EXLOC, msg);
    }
    V();
}

void CegoXMLSpace::addUser(const Chain& user, const Chain& password)
{
    P();
    
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
	Element **pUE = userList.First();
	while ( pUE )
	{
	    if ( (*pUE)->getAttributeValue(XML_NAME_ATTR) == user )
	    {
		Chain msg = Chain("User ") + user + Chain(" already defined "); 
		throw Exception(EXLOC, msg);
		V();
	    }
	    pUE = userList.Next();
	} 
		
	Element *pNUE = new Element(XML_USER_ELEMENT);
	pNUE->setAttribute(XML_NAME_ATTR, user);
	pNUE->setAttribute(XML_PASSWD_ATTR, password);
	pNUE->setAttribute(XML_TRACE_ATTR, XML_OFF_VALUE);
	
	pRoot->addContent(pNUE);
	V();
	return;
    }
    V();

}

void CegoXMLSpace::assignUserRole(const Chain& user, const Chain& role)
{
    P();
    Element *pRoot = _pDoc->getRootElement();

    ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
    Element **pUE = userList.First();
    while ( pUE )
    {
	if ( (*pUE)->getAttributeValue(XML_NAME_ATTR) == user )
	{
	    
	    Chain roleString = (*pUE)->getAttributeValue(XML_ROLE_ATTR);	    
	    Tokenizer t(roleString, ",");

	    Chain assignedRole;
	    SetT<Chain> roleSet; 
	    while ( t.nextToken(assignedRole) )
	    {
		roleSet.Insert(assignedRole);
	    }
	    roleSet.Insert(role);

	    Chain newRoleString;
	    Chain *pRole = roleSet.First();
	    while ( pRole )
	    {
		newRoleString += *pRole;
		pRole = roleSet.Next();
		if ( pRole ) 
		    newRoleString += ",";
	    }
	    
	    (*pUE)->setAttribute(XML_ROLE_ATTR, newRoleString);
	    	    
	    V();
	    return;
	}
	pUE = userList.Next();
    } 
	
    V();
    Chain msg = Chain("Unknown user ") + user;
    throw Exception(EXLOC, msg);
}


void CegoXMLSpace::removeUserRole(const Chain& user, const Chain& role)
{
    P();

    Element *pRoot = _pDoc->getRootElement();
    
    ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
    Element **pUE = userList.First();
    while ( pUE )
    {
	if ( (*pUE)->getAttributeValue(XML_NAME_ATTR) == user )
	{
	    
	    Chain roleString = (*pUE)->getAttributeValue(XML_ROLE_ATTR);	    
	    Tokenizer t(roleString, ",");

	    Chain assignedRole;
	    SetT<Chain> roleSet; 
	    while ( t.nextToken(assignedRole) )
	    {
		roleSet.Insert(assignedRole);
	    }

	    roleSet.Remove(role);

	    Chain newRoleString;
	    Chain *pRole = roleSet.First();
	    while ( pRole )
	    {
		newRoleString += *pRole;
		pRole = roleSet.Next();
		if ( pRole ) 
		    newRoleString += ",";
	    }
	    
	    (*pUE)->setAttribute(XML_ROLE_ATTR, newRoleString);
	    
	    V();
	    return;
	}
	pUE = userList.Next();
    } 
	
    V();
    Chain msg = Chain("Unknown user ") + user;
    throw Exception(EXLOC, msg);
}

Chain CegoXMLSpace::getUserRole(const Chain& user)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
    Element **pUE = userList.First();
    while ( pUE )
    {
	if ( (*pUE)->getAttributeValue(XML_NAME_ATTR) == user )
	{
	    Chain role = (*pUE)->getAttributeValue(XML_ROLE_ATTR);
	    V();
	    return role;
	}
	pUE = userList.Next();
    } 
    
    V();
    Chain msg = Chain("Unknown user ") + user;
    throw Exception(EXLOC, msg);
}

void CegoXMLSpace::createRole(const Chain& role)
{
    P();
    
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> roleList = pRoot->getChildren(XML_ROLE_ELEMENT);
	Element **pRE = roleList.First();
	while ( pRE )
	{
	    if ( (*pRE)->getAttributeValue(XML_NAME_ATTR) == role )
	    {
		Chain msg = Chain("Role ") + role + Chain(" already defined "); 
		throw Exception(EXLOC, msg);
		V();
	    }
	    pRE = roleList.Next();
	} 
		
	Element *pNRE = new Element(XML_ROLE_ELEMENT);
	pNRE->setAttribute(XML_NAME_ATTR, role);	
	pRoot->addContent(pNRE);
	V();
	return;
    }
    V();
}

void CegoXMLSpace::dropRole(const Chain& role)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> roleList = pRoot->getChildren(XML_ROLE_ELEMENT);
	Element **pRE = roleList.First();
	while ( pRE )
	{
	    if ( (*pRE)->getAttributeValue(XML_NAME_ATTR) == role )
	    {
		pRoot->removeChild(*pRE);
		V();
		return;
		
	    }
	    pRE = roleList.Next();
	}
	V();
	Chain msg = Chain("Unknown role ") + role; 
	throw Exception(EXLOC, msg);
    }
    V();
}

Element* CegoXMLSpace::getPermInfo(const Chain& role)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> roleList = pRoot->getChildren(XML_ROLE_ELEMENT);
	Element **pRE = roleList.First();
	while ( pRE )
	{
	    if ( (*pRE)->getAttributeValue(XML_NAME_ATTR) == role )
	    {
	     
		Element* pPermInfo = new Element(XML_PERMINFO_ELEMENT);
	
		ListT<Element*> permList = (*pRE)->getChildren(XML_PERM_ELEMENT);
		Element **pPE = permList.First();
		while ( pPE )
		{

		    pPermInfo->addContent((*pPE)->createClone() );
		    pPE = permList.Next();
		}
		V();

		return pPermInfo;
	    }
	    pRE = roleList.Next();
	}
	V();
	Chain msg = Chain("Unknown role ") + role; 
	throw Exception(EXLOC, msg);
    }
    V();
    Chain msg = Chain("Cannot get role info ") + role; 
    throw Exception(EXLOC, msg);

}


void CegoXMLSpace::setPerm(const Chain& role, const Chain& permid, const Chain& tableset, const Chain& filter, const Chain& perm)
{

    Chain uperm = perm.toUpper();

    if ( uperm != Chain("READ") 
	 && uperm != Chain("WRITE")
	 && uperm != Chain("MODIFY")
	 && uperm != Chain("EXEC")
	 && uperm != Chain("ALL") )
    {
	Chain msg = Chain("Invalid permission ") + perm; 
	throw Exception(EXLOC, msg);
    }

    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> roleList = pRoot->getChildren(XML_ROLE_ELEMENT);
	Element **pRE = roleList.First();
	while ( pRE )
	{
	    if ( (*pRE)->getAttributeValue(XML_NAME_ATTR) == role )
	    {
		ListT<Element*> permList = (*pRE)->getChildren(XML_PERM_ELEMENT);
		Element **pPE = permList.First();
		while ( pPE )
		{
		    if ( (*pPE)->getAttributeValue(XML_PERMID_ATTR) == permid )
		    {

			(*pPE)->setAttribute(XML_TABLESET_ATTR, tableset);
			(*pPE)->setAttribute(XML_FILTER_ATTR, filter);
			(*pPE)->setAttribute(XML_PERM_ATTR, uperm);
			(*pPE)->setAttribute(XML_PERMID_ATTR, permid);
			V();
			return;		       
		    }
		    pPE = permList.Next();
		}
		
		Element *pNPE = new Element(XML_PERM_ELEMENT);
		pNPE->setAttribute(XML_TABLESET_ATTR, tableset);
		pNPE->setAttribute(XML_FILTER_ATTR, filter);
		pNPE->setAttribute(XML_PERM_ATTR, uperm);
		pNPE->setAttribute(XML_PERMID_ATTR, permid);
	
		(*pRE)->addContent(pNPE);
		V();

		return;
		
	    }
	    pRE = roleList.Next();
	}
	V();
	Chain msg = Chain("Unknown role ") + role; 
	throw Exception(EXLOC, msg);
    }
    V();
}

void CegoXMLSpace::removePerm(const Chain& role, const Chain& permid)
{

    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> roleList = pRoot->getChildren(XML_ROLE_ELEMENT);
	Element **pRE = roleList.First();
	while ( pRE )
	{
	    if ( (*pRE)->getAttributeValue(XML_NAME_ATTR) == role )
	    {

		ListT<Element*> permList = (*pRE)->getChildren(XML_PERM_ELEMENT);
		Element **pPE = permList.First();
		while ( pPE )
		{
		    if ( (*pPE)->getAttributeValue(XML_PERMID_ATTR) == permid ) 
		    {
			
			(*pRE)->removeChild(*pPE);			
			V();
			return;
			
		    }
		    pPE = permList.Next();

		}

		V();
		Chain msg = Chain("Unknown permission for role ") + role; 
		throw Exception(EXLOC, msg);
		
	    }
	    pRE = roleList.Next();
	    
	}
	V();
	Chain msg = Chain("Unknown role ") + role; 
	throw Exception(EXLOC, msg);
    }
    V();
}

void CegoXMLSpace::setUserTrace(const Chain& user, bool isOn)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
    Element **pUE = userList.First();
    while ( pUE )
    {
	if ( (*pUE)->getAttributeValue(XML_NAME_ATTR) == user )
	{
	    if ( isOn )
		(*pUE)->setAttribute(XML_TRACE_ATTR, XML_ON_VALUE);
	    else
		(*pUE)->setAttribute(XML_TRACE_ATTR, XML_OFF_VALUE);
	    V();
	    return;
	}
	pUE = userList.Next();
    } 
    
    V();
    Chain msg = Chain("Unknown user ") + user;
    throw Exception(EXLOC, msg);
}

void CegoXMLSpace::removeUser(const Chain& user)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
	Element **pUE = userList.First();
	while ( pUE )
	{
	    if ( (*pUE)->getAttributeValue(XML_NAME_ATTR) == user )
	    {
		pRoot->removeChild(*pUE);
		V();
		return;
		
	    }
	    pUE = userList.Next();
	}
	V();
	Chain msg = Chain("Unknown user ") + user; 
	throw Exception(EXLOC, msg);
    }
    V();
}

bool CegoXMLSpace::checkAdminUser(const Chain& user, const Chain& password)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
	Element **pUE = userList.First();
	while ( pUE )
	{
	    if ( (*pUE)->getAttributeValue(XML_NAME_ATTR) == user )
	    {

		Chain roleString = (*pUE)->getAttributeValue(XML_ROLE_ATTR);
		
		Tokenizer t(roleString, ",");
		Chain role;
		bool adminFound=false;

		while ( t.nextToken(role) && adminFound == false )
		{
		    if ( role == Chain(ROLE_ADMIN) )
			adminFound = true;       
		}

		bool ret = false;

		if ( adminFound && (*pUE)->getAttributeValue(XML_PASSWD_ATTR) == password )
		{
		    ret = true;
		}

		V();
		return ret;
	    }
	    pUE = userList.Next();
	}
    }
    V();
    return false;
}

void CegoXMLSpace::getAdminUser(Chain& user, Chain& password)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
	Element **pUE = userList.First();
	if ( pUE )
	{
	    user = (*pUE)->getAttributeValue(XML_NAME_ATTR);	    
	    password = (*pUE)->getAttributeValue(XML_PASSWD_ATTR);
	}
    }
    V();
    return;
}

bool CegoXMLSpace::checkUser(const Chain& user, const Chain& password, Chain& msg, bool& isTrace)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	
	ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
	Element **pUE = userList.First();
	while ( pUE )
	{
	    if ( (*pUE)->getAttributeValue(XML_NAME_ATTR) == user )
	    {
		bool ret;
		
		if ( (*pUE)->getAttributeValue(XML_PASSWD_ATTR) == password )
		{
		    ret = true;
		}
		else
		{
		    msg = Chain("Invalid password for user ") + user;
		    ret = false;
		}
		
		if ( (*pUE)->getAttributeValue(XML_TRACE_ATTR) == Chain(XML_ON_VALUE) )
		{
		    int numReq = (*pUE)->getAttributeValue(XML_NUMREQUEST_ATTR).asInteger();
		    numReq++;
		    (*pUE)->setAttribute(XML_NUMREQUEST_ATTR, Chain(numReq));
		    isTrace=true;
		}
		else
		    isTrace=false;
				
		V();
		return ret;
	    }
	    pUE = userList.Next();
	} 
	msg = Chain("Unknown user ") + user;
	V();
	return false;
    }
    V();
    return false;
}

void CegoXMLSpace::changePassword(const Chain& user, const Chain& password)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
	Element **pUE = userList.First();
	while ( pUE )
	{
	    if ( (*pUE)->getAttributeValue(XML_NAME_ATTR) == user )
	    {			
		(*pUE)->setAttribute(XML_PASSWD_ATTR, password);
		V();
		return;
	    }
	    pUE = userList.Next();
	} 
	V();
	Chain msg = Chain("Unknown user \"") + user + Chain("\""); 
	throw Exception(EXLOC, msg);
    }
    V();
}

void CegoXMLSpace::incUserQuery(const Chain& user)
{
    P();

    Element *pRoot = _pDoc->getRootElement();    
    if ( pRoot )
    {
	ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
	Element **pUE = userList.First();
	while ( pUE )
	{
	    if ( (*pUE)->getAttributeValue(XML_NAME_ATTR) == user )
	    {
		int numQuery = (*pUE)->getAttributeValue(XML_NUMQUERY_ATTR).asInteger();
		numQuery++;
		(*pUE)->setAttribute(XML_NUMQUERY_ATTR, Chain(numQuery));
		V();
		return;
	    }
	    pUE = userList.Next();
	} 
	
	V();
	Chain msg = Chain("Unknown user ") + user;
	throw Exception(EXLOC, msg);
    }
    V();
}

Element* CegoXMLSpace::getUserList()
{
    P();

    Element *pRoot = _pDoc->getRootElement();    
    if ( pRoot )
    {
	
	ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
	Element *pUserInfo = new Element(XML_USERINFO_ELEMENT);
	
	Element **pUser = userList.First();
	while ( pUser )
	{
	    Element *pN = new Element(XML_USER_ELEMENT);
	    pN->setAttribute(XML_NAME_ATTR, (*pUser)->getAttributeValue(XML_NAME_ATTR));
	    pN->setAttribute(XML_TRACE_ATTR, (*pUser)->getAttributeValue(XML_TRACE_ATTR));
	    pN->setAttribute(XML_NUMREQUEST_ATTR, (*pUser)->getAttributeValue(XML_NUMREQUEST_ATTR));
	    pN->setAttribute(XML_NUMQUERY_ATTR, (*pUser)->getAttributeValue(XML_NUMQUERY_ATTR));
	    pN->setAttribute(XML_ROLE_ATTR, (*pUser)->getAttributeValue(XML_ROLE_ATTR));
	    pUserInfo->addContent(pN);
	    pUser = userList.Next();
	}
	V();
	
	return pUserInfo;
    }
    V();

    return 0;
}    


Element* CegoXMLSpace::getRoleList()
{
    P();

    Element *pRoot = _pDoc->getRootElement();    
    if ( pRoot )
    {
	
	ListT<Element*> roleList = pRoot->getChildren(XML_ROLE_ELEMENT);
	Element *pRoleList = new Element(XML_ROLELIST_ELEMENT);
	
	Element **pRE = roleList.First();
	while ( pRE )
	{
	    Element *pN = new Element(XML_ROLE_ELEMENT);
	    pN->setAttribute(XML_NAME_ATTR, (*pRE)->getAttributeValue(XML_NAME_ATTR));
	    pRoleList->addContent(pN);
	    pRE = roleList.Next();
	}
	V();
	
	return pRoleList;
    }
    V();

    return 0;
}    


void CegoXMLSpace::getDataPort(int& dataPort)
{
    P();
    dataPort = _pDoc->getRootElement()->getAttributeValue(XML_DATAPORT_ATTR).asInteger();
    V();
}

void CegoXMLSpace::setDBHost(const Chain& dbHost)
{
    P();
    _pDoc->getRootElement()->setAttribute(XML_HOSTNAME_ATTR, dbHost);
    V();
}

void CegoXMLSpace::getDBHost(Chain& dbHost)
{
    P();
    dbHost = _pDoc->getRootElement()->getAttributeValue(XML_HOSTNAME_ATTR);
    V();
}

void CegoXMLSpace::getAdminPort(int& adminPort)
{
    P();
    adminPort = _pDoc->getRootElement()->getAttributeValue(XML_ADMINPORT_ATTR).asInteger();
    V();
}

void CegoXMLSpace::getLogPort(int& logPort)
{
    P();
    logPort = _pDoc->getRootElement()->getAttributeValue(XML_LOGPORT_ATTR).asInteger();
    V();
}

void CegoXMLSpace::getPidFile(Chain& pidFile)
{
    P();
    pidFile = _pDoc->getRootElement()->getAttributeValue(XML_PIDFILE_ATTR);
    V();
}

void CegoXMLSpace::setTSRoot(const Chain& tableSet, const Chain& tsRoot)
{
    P();
    Element *pTS = getTableSetElement(tableSet);

    if ( pTS )
    {
	pTS->setAttribute(XML_TSROOT_ATTR, tsRoot);
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
}


Chain CegoXMLSpace::getTSRoot(const Chain& tableSet)
{
    Chain tsRoot;

    P();
    
    Element *pTSE = getTableSetElement(tableSet);
    if ( pTSE )
    {
	tsRoot =  pTSE->getAttributeValue(XML_TSROOT_ATTR);  
    }
    else
    {
	V();
	Chain msg = Chain("Unknown tableset name ") + tableSet; 
	throw Exception(EXLOC, msg);
    }
    V();
    return tsRoot;
}

Chain CegoXMLSpace::getDbName()
{
    P();
    Chain dbName = _pDoc->getRootElement()->getAttributeValue(XML_NAME_ATTR);
    V();
    return dbName;
}

int CegoXMLSpace::getPageSize()
{
    P();
    int pageSize = _pDoc->getRootElement()->getAttributeValue(XML_PAGESIZE_ATTR).asInteger();
    V();
    return pageSize;
}

void CegoXMLSpace::initDoc()
{
    P();
    ListT<Element*> nodeList;
    
    nodeList = _pDoc->getRootElement()->getChildren(XML_NODE_ELEMENT);
    Element **pNode = nodeList.First();
    while ( pNode ) 
    {
	_pDoc->getRootElement()->removeChild(*pNode);
	nodeList = _pDoc->getRootElement()->getChildren(XML_NODE_ELEMENT);
	pNode = nodeList.First();
    }
    
    V();
    
    Host h;
    addHost(h.getName(), XML_ONLINE_VALUE);
   
    return;
}

void CegoXMLSpace::setXmlDef(const Chain& xmlDef)
{
    _xmlDef = xmlDef;
}


void CegoXMLSpace::initXml(const Chain& dbName, int pageSize, const Chain& hostName, int dbPort, int admPort, int logPort, const Chain& pidFile, const Chain& logLevel)
{

    P();

    try {
	
	XMLSuite xml;
	xml.setDocument(_pDoc);
	
	_pDoc->setDocType(Chain(CEGO_DB_DOC));
	_pDoc->setAttribute(XML_VERSION_ATTR, XML_VERSION_VALUE);

	Element *pElement = new Element(XML_DATABASE_ELEMENT);
	pElement->setAttribute(XML_NAME_ATTR, dbName);
	pElement->setAttribute(XML_PAGESIZE_ATTR, Chain(pageSize));
	pElement->setAttribute(XML_HOSTNAME_ATTR, hostName);
	pElement->setAttribute(XML_DATAPORT_ATTR, Chain(dbPort));
	pElement->setAttribute(XML_ADMINPORT_ATTR, Chain(admPort));
	pElement->setAttribute(XML_LOGPORT_ATTR, Chain(logPort));
	pElement->setAttribute(XML_PIDFILE_ATTR, pidFile);

	Element *pLog = new Element(XML_MODULE_ELEMENT);
	pLog->setAttribute(XML_NAME_ATTR, Chain("ALL"));
	pLog->setAttribute(XML_LEVEL_ATTR, logLevel);	
	pElement->addContent(pLog);

	_pDoc->setRootElement(pElement);

	Chain xmlChain;
	xml.getXMLChain(xmlChain);
	
	File xmlFile(_xmlDef);
	
	xmlFile.open(File::WRITE);
	
	xmlFile.writeChain(xmlChain);
	
	xmlFile.close();

    }
    catch ( Exception e )
    {
	V();
	throw Exception(EXLOC, Chain("Cannot write file ") + _xmlDef, e);
    }
    V();
}



void CegoXMLSpace::xml2Doc()
{

    P();

    Chain xmlString;

    try {

	File xmlFile(_xmlDef);
	
	xmlFile.open(File::READ);
	
	Chain line;
	while (xmlFile.readLine(line))
	{
	    
	    xmlString = xmlString + line + Chain("\n");
	    xmlString = xmlString.cutTrailing(" \t");
	    
	}
	
	xmlFile.close();
	
    }
    catch ( Exception e )
    {
	V();
	throw Exception(EXLOC, Chain("Cannot read file ") + _xmlDef, e);
    }

    XMLSuite xml(xmlString);
    xml.setDocument(_pDoc);
    
    try {

	xml.parse();
    }
    catch ( Exception e )
    {
	V();
	Chain xmlmsg;
	e.pop(xmlmsg);
	Chain msg = Chain("XML parse error at line ") + Chain( xml.getLineNo()) + Chain(" : ") + xmlmsg;
	throw Exception(EXLOC, msg);
    }
    V();
}

void CegoXMLSpace::doc2Xml()
{

    
    P();

    try {
	
	XMLSuite xml;
	xml.setDocument(_pDoc);
	
	Chain xmlChain;
	xml.getXMLChain(xmlChain);
	
	File xmlFile(_xmlDef);
	
	xmlFile.open(File::WRITE);
	
	xmlFile.writeChain(xmlChain);
	
	xmlFile.close();

    }
    catch ( Exception e )
    {
	V();
	throw Exception(EXLOC, Chain("Cannot write file ") + _xmlDef, e);
    }
    V();
}


void CegoXMLSpace::setTSTicket(const Chain& tableSet, const Chain& tsTicket)
{
    P();
    Element *pTS = getTableSetElement(tableSet);

    if ( pTS )
    {
	pTS->setAttribute(XML_TSTICKET_ATTR, tsTicket);
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
}

Chain CegoXMLSpace::getTSTicket(const Chain& tableSet)
{
    P();
    Element *pE = getTableSetElement(tableSet);
    Chain tsTicket = pE->getAttributeValue(XML_TSTICKET_ATTR);
    V();
    return tsTicket;
}

int CegoXMLSpace::getTID(const Chain& tableSet)
{
    P();
    Element *pE = getTableSetElement(tableSet);
    int tid = pE->getAttributeValue(XML_TID_ATTR).asInteger();
    V();
    return tid;
}

bool CegoXMLSpace::tableSetExists(const Chain& tableSet)
{
    P();
    Element *pE = getTableSetElement(tableSet);
    V();
    if ( pE )
	return true;
    return false;
}

long CegoXMLSpace::getSortAreaSize(int tabSetId)
{
    Element *pE = getCachedTableSetElement(tabSetId);

    if ( pE == 0 )
    {
	Chain msg = Chain("Unknown tableset id ") + Chain(tabSetId); 
	throw Exception(EXLOC, msg);
    }

    P();
    long sortAreaSize = pE->getAttributeValue(XML_SORTAREASIZE_ATTR).asLong();
    V();
    return sortAreaSize;
}

int CegoXMLSpace::nextTID(int tabSetId)
{
    Element *pE = getCachedTableSetElement(tabSetId);

    if ( pE == 0 )
    {
	Chain msg = Chain("Unknown tableset id ") + Chain(tabSetId); 
	throw Exception(EXLOC, msg);
    }
   
    P();
    int tid = pE->getAttributeValue(XML_TID_ATTR).asInteger();
    tid++;
    pE->setAttribute(XML_TID_ATTR, Chain(tid));
    V();
    return tid;
}

int CegoXMLSpace::nextFID()
{
    P();
    Element *pE = _pDoc->getRootElement();;

    int fid = pE->getAttributeValue(XML_MAXFID_ATTR).asInteger();
    if ( fid <= TABMNG_MAXTABSET )
	fid = TABMNG_MAXTABSET + 1;
    else
	fid++;
    pE->setAttribute(XML_MAXFID_ATTR, Chain(fid));
    V();
    return fid;
}

int CegoXMLSpace::nextTSID()
{
    P();
    Element *pE = _pDoc->getRootElement();;

    int tsid = pE->getAttributeValue(XML_MAXTSID_ATTR).asInteger();
    tsid++;
    if ( tsid > TABMNG_MAXTABSET )
    {
	V();
	throw Exception ( EXLOC, "TableSet Ids exceeded");
    }
    pE->setAttribute(XML_MAXTSID_ATTR, Chain(tsid));

    V();
    return tsid;
}

void CegoXMLSpace::setCommittedLSN(int tabSetId, long lsn)
{   
    Element *pTS = getCachedTableSetElement(tabSetId);

    if ( pTS == 0)
    {
	Chain msg = "Unknown tableset id <" + Chain(tabSetId) + ">"; 
	throw Exception(EXLOC, msg);
    }   
    P();
    pTS->setAttribute(XML_LSN_ATTR, Chain(lsn));
    V();
}

void CegoXMLSpace::setCommittedLSN(const Chain& tableSet, long lsn)
{  
    P();
    Element *pTS = getTableSetElement(tableSet);

    if ( pTS == 0)
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    
    pTS->setAttribute(XML_LSN_ATTR, Chain(lsn));
    V();
}

long CegoXMLSpace::getCommittedLSN(const Chain& tableSet)
{
    long lsn;

    P();
    Element *pTS = getTableSetElement(tableSet);
    if ( pTS )
    {
	lsn = pTS->getAttributeValue(XML_LSN_ATTR).asLong() ;
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
    return lsn;
}


void CegoXMLSpace::getAllActiveTableSet(ListT<Chain>& tsList)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_RUNSTATE_ATTR) 
		 == Chain(XML_ONLINE_VALUE) )
	    {
		tsList.Insert((*pTSE)->getAttributeValue(XML_NAME_ATTR));
	    }
	    pTSE = tabSetList.Next();
	}	
    }
    V();
}


void CegoXMLSpace::getActiveTableSet(const Chain& primary, ListT<Chain>& tsList, bool includeRecovery)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_PRIMARY_ATTR) == primary
		 && ( (*pTSE)->getAttributeValue(XML_RUNSTATE_ATTR) == Chain(XML_ONLINE_VALUE)  
		      || (*pTSE)->getAttributeValue(XML_RUNSTATE_ATTR) == Chain(XML_BACKUP_VALUE)
		      || ( (*pTSE)->getAttributeValue(XML_RUNSTATE_ATTR) == Chain(XML_RECOVERY_VALUE) && includeRecovery )))
	    {
		tsList.Insert((*pTSE)->getAttributeValue(XML_NAME_ATTR));
	    }
	    pTSE = tabSetList.Next();
	}	
    }
    V();
}


Chain CegoXMLSpace::getTableSetRunState(const Chain& tableSet)
{
    Chain status;

    P();
    Element *pTS = getTableSetElement(tableSet);
    if ( pTS )
    {
	status = pTS->getAttributeValue(XML_RUNSTATE_ATTR);
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
    return status;
}

void CegoXMLSpace::setTableSetRunState(const Chain& tableSet, const Chain& status)
{
    P();
    Element *pTS = getTableSetElement(tableSet);

    if ( pTS )
    {
	pTS->setAttribute(XML_RUNSTATE_ATTR, status);
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
}

Chain CegoXMLSpace::getTableSetSyncState(const Chain& tableSet)
{
    Chain status;

    P();
    Element *pTS = getTableSetElement(tableSet);
    if ( pTS )
    {
	status = pTS->getAttributeValue(XML_SYNCSTATE_ATTR);
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
    return status;
}

void CegoXMLSpace::setTableSetSyncState(const Chain& tableSet, const Chain& status)
{
    P();
    Element *pTS = getTableSetElement(tableSet);
    if ( pTS )
    {
	pTS->setAttribute(XML_SYNCSTATE_ATTR, status);
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
}

void CegoXMLSpace::addDataFile(const Chain& tableSet, const Chain& type, int fileId, const Chain& fileName, int fileSize)
{
    P();
    Element *pTS = getTableSetElement(tableSet);

    if ( pTS )
    {
	Element *pDataFile = new Element(XML_DATAFILE_ELEMENT);
	pDataFile->setAttribute(XML_TYPE_ATTR, type);
	pDataFile->setAttribute(XML_FILEID_ATTR, Chain(fileId));
	pDataFile->setAttribute(XML_NAME_ATTR, fileName);
	pDataFile->setAttribute(XML_SIZE_ATTR, Chain(fileSize));
	pTS->addContent(pDataFile);
    }
    V();
}

void CegoXMLSpace::getDataFileInfo(const Chain& tableSet, const Chain& type, ListT<Chain>& dfList, ListT<int>& fidList, ListT<int>& sizeList)
{
    P();    
    Element *pTS = getTableSetElement(tableSet);   
    if ( pTS )
    {
	ListT<Element*> fileList = pTS->getChildren(XML_DATAFILE_ELEMENT);
	Element **pFile = fileList.First();
	while ( pFile )
	{
	    if ( (*pFile)->getAttributeValue(XML_TYPE_ATTR) == Chain(type) )
	    {
		dfList.Insert( (*pFile)->getAttributeValue(XML_NAME_ATTR) );
		fidList.Insert( (*pFile)->getAttributeValue(XML_FILEID_ATTR).asInteger());
		sizeList.Insert( (*pFile)->getAttributeValue(XML_SIZE_ATTR).asInteger());
	    }
	    pFile = fileList.Next();
	}
    }
    V();
}


void CegoXMLSpace::getLogFileInfo(const Chain& tableSet, ListT<Chain>& lfList, ListT<int>& sizeList, ListT<Chain>& statusList)
{
    P();
    Element *pTS = getTableSetElement(tableSet);
    
    if ( pTS )
    {
	ListT<Element*> fileList = pTS->getChildren(XML_LOGFILE_ELEMENT);
	Element **pFile = fileList.First();
	while ( pFile )
	{
	   lfList.Insert( (*pFile)->getAttributeValue(XML_NAME_ATTR) );
	   sizeList.Insert( (*pFile)->getAttributeValue(XML_SIZE_ATTR).asInteger());
	   statusList.Insert( (*pFile)->getAttributeValue(XML_STATUS_ATTR) );
	   pFile = fileList.Next();
	}
    }
    V();
}

void CegoXMLSpace::setLogFileStatus(const Chain& tableSet, const Chain& logFile, const Chain& status)
{
    P();
    Element *pTS = getTableSetElement(tableSet);
    if ( pTS )
    {
	ListT<Element*> fileList = pTS->getChildren(XML_LOGFILE_ELEMENT);
	Element **pFile = fileList.First();
	while ( pFile )
	{
	    if ( (*pFile)->getAttributeValue(XML_NAME_ATTR) == logFile)
	    {
		(*pFile)->setAttribute(XML_STATUS_ATTR, status);
		V();
		return;
	    }	    
	    pFile = fileList.Next();
	}
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
}

void CegoXMLSpace::getXMLLockStat(Chain& lockName, long& lockCount, long &numRdLock, long &numWrLock, long &sumRdDelay, long &sumWrDelay)
{
    lockName = xmlLock.getId();
    lockCount = xmlLock.numLockTry();

    numRdLock = xmlLock.numReadLock();
    numWrLock = xmlLock.numWriteLock();
    sumRdDelay = 0;
    sumWrDelay = 0;

    if ( xmlLock.numReadLock() > 0 )
	sumRdDelay = xmlLock.sumReadDelay() / LCKMNG_DELRES;
    if ( xmlLock.numWriteLock() > 0 )
	sumWrDelay = xmlLock.sumWriteDelay() / LCKMNG_DELRES;

}

void CegoXMLSpace::addCounter(int tabSetId, const Chain& counterName, long initValue, bool forceSet)
{
   
    Element *pTS = getCachedTableSetElement(tabSetId);

    if ( pTS == 0)
    {
	Chain msg = "Unknown tableset id <" + Chain(tabSetId) + ">"; 
	throw Exception(EXLOC, msg);
    }
    P();
    ListT<Element*> counterList = pTS->getChildren(XML_COUNTER_ELEMENT);
    Element **pCE = counterList.First();
    while ( pCE )
    {
	if ( (*pCE)->getAttributeValue(XML_NAME_ATTR) == counterName )
	{
	    if ( forceSet )
	    {
		(*pCE)->setAttribute(XML_VALUE_ATTR, Chain(initValue));
		V();
		return;
	    }
	    else
	    {		
		Chain msg = Chain("Counter ") + counterName + Chain(" already defined "); 
		V();
		throw Exception(EXLOC, msg);		
	    }
	}
	pCE = counterList.Next();
    } 
    
    Element *pNCE = new Element(XML_COUNTER_ELEMENT);
    pNCE->setAttribute(XML_NAME_ATTR, counterName);
    pNCE->setAttribute(XML_VALUE_ATTR, Chain(initValue));
    
    pTS->addContent(pNCE);
    V();
}

long CegoXMLSpace::getCounterValue(int tabSetId, const Chain& counterName, long incValue)
{   
    Element *pTS = getCachedTableSetElement(tabSetId);

    if ( pTS == 0)
    {
	Chain msg = "Unknown tableset id <" + Chain(tabSetId) + ">"; 
	throw Exception(EXLOC, msg);
    }
    P();   
    ListT<Element*> counterList = pTS->getChildren(XML_COUNTER_ELEMENT);
    Element **pCE = counterList.First();
    while ( pCE )
    {
	if ( (*pCE)->getAttributeValue(XML_NAME_ATTR) == counterName )
	{
	    
	    Chain counterVal = (*pCE)->getAttributeValue(XML_VALUE_ATTR);
	    
	    long v = counterVal.asLong();
	    
	    if ( incValue > 0 )
	    {
		v+=incValue;
		(*pCE)->setAttribute(XML_VALUE_ATTR, Chain(v));		
	    }
	    V();
	    return v;
	}
	pCE = counterList.Next();
    } 
    V();
    Chain msg = Chain("Unknown counter ") + counterName;
    throw Exception(EXLOC, msg);
}

void CegoXMLSpace::setCounterValue(int tabSetId, const Chain& counterName, long value)
{
    Element *pTS = getCachedTableSetElement(tabSetId);

    if ( pTS == 0)
    {
	Chain msg = "Unknown tableset id <" + Chain(tabSetId) + ">"; 
	throw Exception(EXLOC, msg);
    }    
    P();    
    ListT<Element*> counterList = pTS->getChildren(XML_COUNTER_ELEMENT);
    Element **pCE = counterList.First();
    while ( pCE )
    {
	if ( (*pCE)->getAttributeValue(XML_NAME_ATTR) == counterName )
	{
	    
	    (*pCE)->setAttribute(XML_VALUE_ATTR, Chain(value));
	    
	    V();
	    return;
	}
	pCE = counterList.Next();
    }     
    V();
    Chain msg = Chain("Unknown counter ") + counterName;
    throw Exception(EXLOC, msg);
}

void CegoXMLSpace::getCounterList(int tabSetId, ListT<Chain>& counterNameList)
{
    Element *pTS = getCachedTableSetElement(tabSetId);

    if ( pTS == 0)
    {
	Chain msg = "Unknown tableset id <" + Chain(tabSetId) + ">"; 
	throw Exception(EXLOC, msg);
    }
    P();
    ListT<Element*> counterList = pTS->getChildren(XML_COUNTER_ELEMENT);
    Element **pCE = counterList.First();
    while ( pCE )
    {
	counterNameList.Insert(  (*pCE)->getAttributeValue(XML_NAME_ATTR));
	pCE = counterList.Next();
    } 
    V();
    return;

}

void CegoXMLSpace::removeCounter(int tabSetId, const Chain& counterName)
{
    Element *pTS = getCachedTableSetElement(tabSetId);

    if ( pTS == 0)
    {
	Chain msg = "Unknown tableset id <" + Chain(tabSetId) + ">"; 
	throw Exception(EXLOC, msg);
    }
    P();
    ListT<Element*> counterList = pTS->getChildren(XML_COUNTER_ELEMENT);
    Element **pCE = counterList.First();
    while ( pCE )
    {
	if ( (*pCE)->getAttributeValue(XML_NAME_ATTR) == counterName )
	{
	    pTS->removeChild(*pCE);
	    V();
	    return;
	    
	}
	pCE = counterList.Next();
    }
    V();
    Chain msg = Chain("Unknown counter ") + counterName; 
    throw Exception(EXLOC, msg);
}


void CegoXMLSpace::setCheckpointInterval(const Chain& tableSet, int timeout)
{
    P();
    Element *pTS = getTableSetElement(tableSet);

    if ( pTS )
    {
	pTS->setAttribute(XML_CHECKPOINT_ATTR, Chain(timeout));
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
}

int CegoXMLSpace::getCheckpointInterval(const Chain& tableSet)
{
    int checkpoint;

    P();
    Element *pTS = getTableSetElement(tableSet);
    if ( pTS )
    {
	checkpoint = pTS->getAttributeValue(XML_CHECKPOINT_ATTR).asInteger();
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
    return checkpoint;
}


void CegoXMLSpace::setTSInitFile(const Chain& tableSet, const Chain& initFile)
{
    P();
    Element *pTS = getTableSetElement(tableSet);

    if ( pTS )
    {
	pTS->setAttribute(XML_TSINITFILE_ATTR, initFile);
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
}

Chain CegoXMLSpace::getTSInitFile(const Chain& tableSet)
{
    Chain initFile;

    P();
    Element *pTS = getTableSetElement(tableSet);
    if ( pTS )
    {
	initFile = pTS->getAttributeValue(XML_TSINITFILE_ATTR);
    }
    else
    {
	V();
	Chain msg = "Unknown tableset <" + tableSet + ">"; 
	throw Exception(EXLOC, msg);
    }
    V();
    return initFile;
}


// private methods

void CegoXMLSpace::P()
{    
    xmlLock.writeLock(XS_LOCKTIMEOUT);
}

void CegoXMLSpace::V()
{
    xmlLock.unlock();
}

void CegoXMLSpace::getRoleSet(const Chain& user, SetT<Chain>& roleSet)
{

    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {	
	ListT<Element*> userList = pRoot->getChildren(XML_USER_ELEMENT);
	Element **pUE = userList.First();
	while ( pUE )
	{
	    if ( (*pUE)->getAttributeValue(XML_NAME_ATTR) == user )
	    {		
		Chain roleString = (*pUE)->getAttributeValue(XML_ROLE_ATTR);
		
		Tokenizer t(roleString, ",");
		Chain role;
		while ( t.nextToken(role) )
		{
		    roleSet.Insert(role);
		}
	    }
	    pUE = userList.Next();
	}
    }
    V();
}

/*
Chain CegoXMLSpace::getRoleAbbrev(const Chain& roleString)
{
    Chain abbrev;
    Tokenizer t(roleString, ",");
    Chain assignedRole;
    while ( t.nextToken(assignedRole) )
    {
	if ( assignedRole == Chain(XML_ROLE_ALL_VALUE) )
	    abbrev += "A";
	else if ( assignedRole == Chain(XML_ROLE_READOBJ_VALUE) )
	    abbrev += "R";
	else if ( assignedRole == Chain(XML_ROLE_WRITEOBJ_VALUE) )
	    abbrev += "W";
	else if ( assignedRole == Chain(XML_ROLE_CREATEOBJ_VALUE) )
	    abbrev += "C";
	else if ( assignedRole == Chain(XML_ROLE_DROPOBJ_VALUE) )
	    abbrev += "D";
	else if ( assignedRole == Chain(XML_ROLE_EXECPROC_VALUE) )
	    abbrev += "E";
    }

    return abbrev;

}
*/

bool CegoXMLSpace::matchRole(const Chain& role, const Chain tableSet, const Chain& objPattern, AccessMode perm)
{
    
    // admin is allowed anyway
    if ( role == Chain(ROLE_ADMIN) )
	return true;

    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> roleElementList = pRoot->getChildren(XML_ROLE_ELEMENT);
	Element **pRE = roleElementList.First();
	while ( pRE ) 
	{
	    if ( (*pRE)->getAttributeValue(XML_NAME_ATTR) == role )
	    {

		ListT<Element*> permElementList = (*pRE)->getChildren(XML_PERM_ELEMENT);

		Element **pPE = permElementList.First();
		while ( pPE ) 
		{
		    Chain actTableSet = (*pPE)->getAttributeValue(XML_TABLESET_ATTR);
		    Chain filter = (*pPE)->getAttributeValue(XML_FILTER_ATTR);
		    Chain actPerm = (*pPE)->getAttributeValue(XML_PERM_ATTR);

		    if ( actTableSet == tableSet && fitsPerm(actPerm, perm) )
		    {
			if ( filter == Chain("ALL") )
			{
			    V();
			    return true;
			}
			else
			{
			    Matcher m(filter);			
			    m.prepare();
			    
			    if ( m.match(objPattern) )
			    {			    
				V();
				return true;
			    }
			}
		    }
		    pPE = permElementList.Next();
		}
	    }
	    pRE = roleElementList.Next();
	}
    }
    V();
    return false;
}

bool CegoXMLSpace::fitsPerm(const Chain& perm, AccessMode req)
{

    Chain uperm = perm.toUpper();

    if ( uperm == Chain("ALL") )
	return true;
    else if ( req == READ )
    {
	if ( uperm == Chain("READ") || uperm == Chain("WRITE") || uperm == Chain("MODIFY") )
	    return true;
	else
	    return false;
    }
    else if ( req == WRITE )
    {
	if ( uperm == Chain("WRITE") || uperm == Chain("MODIFY") )
	    return true;
	else
	    return false;	
    }
    else if ( req == MODIFY )
    {
	if ( uperm == Chain("MODIFY") )
	    return true;
	else
	    return false;	
    }
    else if ( req == EXEC )
    {
	if ( uperm == Chain("EXEC") )
	    return true;
	else
	    return false;	
    }

    return false;
}

Element* CegoXMLSpace::getTableSetElement(const Chain& tableSet)
{
   
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    
	    bool isEqual;
	    if ( __caseSensitiveFlag == 1 )
		isEqual = (*pTSE)->getAttributeValue(XML_NAME_ATTR) == tableSet;
	    else
		isEqual = (*pTSE)->getAttributeValue(XML_NAME_ATTR).toUpper() == tableSet.toUpper();
	    
	    if ( isEqual )
	    {
		return (*pTSE);
	    }
	    pTSE = tabSetList.Next();
	}	
    }
    return 0;
}

Element* CegoXMLSpace::getCachedTableSetElement(int tabSetId)
{

    if ( _tsCache[tabSetId] != 0 )
	return _tsCache[tabSetId];
    
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot ) 
    {
	ListT<Element*> tabSetList = pRoot->getChildren(XML_TABLESET_ELEMENT);
	Element **pTSE = tabSetList.First();
	while ( pTSE ) 
	{
	    if ( (*pTSE)->getAttributeValue(XML_TSID_ATTR).asInteger() == tabSetId )
	    {
		_tsCache[tabSetId] = *pTSE;
		V();
		return (*pTSE);
	    }
	    pTSE = tabSetList.Next();
	}	
    }
    V();
    return 0;
}

bool CegoXMLSpace::getModuleList(ListT<Chain> &modList)
{
    bool isConfigured=false;

    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot )
    {
	ListT<Element*> modElementList = pRoot->getChildren(XML_MODULE_ELEMENT);
	Element **pMod = modElementList.First();
	while ( pMod ) 
	{
	    modList.Insert ( (*pMod)->getAttributeValue(XML_NAME_ATTR) );
	    pMod = modElementList.Next();	
	}
	isConfigured = true;
    }
    else
    {
	isConfigured = false;
    }
	
    V();

    return isConfigured;

}

Logger::LogLevel CegoXMLSpace::getLogLevel(const Chain& module)
{
    P();
    Element *pRoot = _pDoc->getRootElement();
    if ( pRoot )
    {
	ListT<Element*> modElementList = pRoot->getChildren(XML_MODULE_ELEMENT);
	Element **pMod = modElementList.First();
	while  ( pMod ) 
	{
	    if ( (*pMod)->getAttributeValue(XML_NAME_ATTR) == module )
	    {
		
		Logger::LogLevel logLevel = Logger::NONE;
		
		
		Chain levelString = (*pMod)->getAttributeValue(XML_LEVEL_ATTR);
		
		if ( levelString == Chain(XML_NOTICE_VALUE) )
		    logLevel = Logger::NOTICE;
		else if ( levelString == Chain(XML_LOGERR_VALUE) )
		    logLevel = Logger::LOGERR;
		else if ( levelString == Chain(XML_DEBUG_VALUE) )
		    logLevel = Logger::DEBUG;
		else if ( levelString == Chain(XML_NONE_VALUE) )
		    logLevel = Logger::NONE;
		
		V();
		
		return logLevel;
	    }
	    pMod = modElementList.Next();
	}
    }
    V();
    return Logger::NONE;
}



