///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoObjectManager.cc
// --------------------
// Cego database object manager implementation
//     
// Design and Implementation by Bjoern Lemke               
//     
// (C)opyright 2000-2025 Bjoern Lemke
//
// IMPLEMENTATION MODULE
//
// Class: CegoObjectManager
// 
// Description: Basic database object handling
//
// Status: CLEAN
//
///////////////////////////////////////////////////////////////////////////////

// LFC INCLUDES
#include <lfcbase/Exception.h>

// CEGO INCLUDES
#include "CegoDefs.h"
#include "CegoObjectManager.h"
#include "CegoBTreeManager.h"
#include "CegoXMLdef.h"
#include "CegoBTreeNode.h"

// POSIX INCLUDES
#include <string.h>
#include <stdlib.h>

CegoObjectManager::CegoObjectManager(CegoDatabaseManager* pDBMng)
{
    _pDBMng = pDBMng;
    _pLockHandle = new CegoLockHandler(pDBMng);    
    _ignoreInvalid = false;
    _modId = _pDBMng->getModId("CegoObjectManager");
}

CegoObjectManager::~CegoObjectManager()
{
    delete _pLockHandle;
}

CegoDatabaseManager* CegoObjectManager::getDBMng()
{
    return _pDBMng;
}

CegoLockHandler* CegoObjectManager::getLockHandler()
{
    return _pLockHandle;
}

void CegoObjectManager::createTableObject(CegoTableObject& tableObject)
{
    PageIdType dataPageId = 0;
    
    try
    {
	/*
	CegoBufferPool::FixMode lockMode = CegoBufferPool::SYNC;
	
	if ( tableObject.getType() == CegoObject::SYSTEM )
	{
	    lockMode = CegoBufferPool::PERSISTENT;
	}
	*/
	
	if ( tableObjectExists(tableObject.getTabSetId(), tableObject.getName()) )
	{
	    Chain msg = Chain("Table object ") +  tableObject.getName() + Chain(" exists");
	    throw Exception(EXLOC, msg);
	}
	
	PageIdType pageOffset;	    	     
	if ( tableObject.getType() == CegoObject::RBSEG )
	{    
	    pageOffset = _pDBMng->getTempPageOffset(tableObject.getTabSetId());
	}
	else
	{
	    pageOffset = _pDBMng->getSysPageOffset(tableObject.getTabSetId());
	}

	PageIdType pageId;
	pageId = pageOffset + tableObject.getTabName().getHashPos(TABMNG_HASHSIZE);
	
	// we previously have to create tuple page
	// allocating and encoding table entry must be done without interrupt by a checkpoint
	// otherwise, inconsistent table information is written to datafile
	
	CegoBufferPage tupPage;

	getNewFilePage(tupPage, tableObject.getTabSetId(), tableObject.getType());   	
	tupPage.setType(CegoBufferPage::TUPLE);		
	dataPageId = tupPage.getPageId();
	_pDBMng->bufferUnfix(tupPage, true, _pLockHandle);
	
	tableObject.setDataPageId(dataPageId);
	tableObject.setLastDataPageId(dataPageId);

	createObject(tableObject, pageId);
    }
    catch ( Exception e)
    {
	if ( dataPageId )
	    freeObjectPages(tableObject.getTabSetId(), dataPageId);	
	throw Exception(EXLOC, Chain("Cannot create table object"), e);	
    }
}

void CegoObjectManager::createBTreeObject(CegoBTreeObject& btreeObject)
{    
    try
    {   		
	if ( objectExists(btreeObject.getTabSetId(), btreeObject.getName(), CegoObject::BTREE) )
	{
	    Chain msg = Chain("Btree ") +  btreeObject.getName() + Chain(" exists");
	    throw Exception(EXLOC, msg);
	}
	
	PageIdType pageOffset;	
	pageOffset = _pDBMng->getSysPageOffset(btreeObject.getTabSetId());

	PageIdType pageId;
	pageId = pageOffset + btreeObject.getTabName().getHashPos(TABMNG_HASHSIZE);

	// object is still invalid
	btreeObject.setDataPageId(0);

	createObject(btreeObject, pageId);
    }
    catch ( Exception e)
    {
	throw Exception(EXLOC, Chain("Cannot create btree object"), e);	
    }
}

void CegoObjectManager::createKeyObject(CegoKeyObject& keyObject)
{    
    try
    {
	if ( objectExists(keyObject.getTabSetId(), keyObject.getName(), keyObject.getType()) )
	{
	    Chain msg = Chain("Object ") +  keyObject.getName() + Chain(" exists");
	    throw Exception(EXLOC, msg);
	}

	PageIdType pageOffset;	
	pageOffset = _pDBMng->getSysPageOffset(keyObject.getTabSetId());	

	PageIdType pageId;
	pageId = pageOffset + keyObject.getTabName().getHashPos(TABMNG_HASHSIZE);

	createObject(keyObject, pageId);
    }
    catch ( Exception e)
    {
	throw Exception(EXLOC, Chain("Cannot create key object"), e);	
    }
}

void CegoObjectManager::createCheckObject(CegoCheckObject& checkObject)
{
    try
    {
	if ( objectExists(checkObject.getTabSetId(), checkObject.getName(), checkObject.getType()) )
	{
	    Chain msg = Chain("Object ") +  checkObject.getName() + Chain(" exists");
	    throw Exception(EXLOC, msg);
	}

	PageIdType pageOffset;	
	pageOffset = _pDBMng->getSysPageOffset(checkObject.getTabSetId());	

	PageIdType pageId;
	pageId = pageOffset + checkObject.getTabName().getHashPos(TABMNG_HASHSIZE);

	createObject(checkObject, pageId);
    }
    catch ( Exception e)
    {
	throw Exception(EXLOC, Chain("Cannot create check object"), e);	
    }
}

void CegoObjectManager::createViewObject(CegoViewObject& viewObject)
{
    try
    {
	if ( tableObjectExists(viewObject.getTabSetId(), viewObject.getName()) )
	{
	    Chain msg = Chain("Table object ") +  viewObject.getName() + Chain(" exists");
	    throw Exception(EXLOC, msg);
	}

	PageIdType pageOffset;	
	pageOffset = _pDBMng->getSysPageOffset(viewObject.getTabSetId());	

	PageIdType pageId;
	pageId = pageOffset + viewObject.getTabName().getHashPos(TABMNG_HASHSIZE);

	createObject(viewObject, pageId);
    }
    catch ( Exception e)
    {
	throw Exception(EXLOC, Chain("Cannot create view object"), e);	
    }
}

void CegoObjectManager::createProcObject(CegoProcObject& procObject)
{
    try
    {
	
	if ( objectExists(procObject.getTabSetId(), procObject.getName(), procObject.getType()) )
	{
	    Chain msg = Chain("Object ") +  procObject.getName() + Chain(" exists");
	    throw Exception(EXLOC, msg);
	}
		
	PageIdType pageOffset;	
	pageOffset = _pDBMng->getSysPageOffset(procObject.getTabSetId());	

	PageIdType pageId;
	pageId = pageOffset + procObject.getName().getHashPos(TABMNG_HASHSIZE);

	createObject(procObject, pageId);
    }
    catch ( Exception e)
    {
	throw Exception(EXLOC, Chain("Cannot create procedure object"), e);
    }
}

void CegoObjectManager::createTriggerObject(CegoTriggerObject& triggerObject)
{
    try
    {	
	if ( objectExists(triggerObject.getTabSetId(), triggerObject.getName(), triggerObject.getType()) )
	{
	    Chain msg = Chain("Object ") +  triggerObject.getName() + Chain(" exists");
	    throw Exception(EXLOC, msg);
	}
		
	PageIdType pageOffset;	
	pageOffset = _pDBMng->getSysPageOffset(triggerObject.getTabSetId());	

	PageIdType pageId;
	pageId = pageOffset + triggerObject.getName().getHashPos(TABMNG_HASHSIZE);

	createObject(triggerObject, pageId);
    }
    catch ( Exception e)
    {
	throw Exception(EXLOC, Chain("Cannot create trigger object"), e);
    }
}

void CegoObjectManager::createAliasObject(CegoAliasObject& aliasObject)
{
    try
    {	
	if ( tableObjectExists(aliasObject.getTabSetId(), aliasObject.getName()) )
	{
	    Chain msg = Chain("Table object ") +  aliasObject.getName() + Chain(" exists");
	    throw Exception(EXLOC, msg);
	}
		
	PageIdType pageOffset;	
	pageOffset = _pDBMng->getSysPageOffset(aliasObject.getTabSetId());	

	PageIdType pageId;
	pageId = pageOffset + aliasObject.getName().getHashPos(TABMNG_HASHSIZE);

	createObject(aliasObject, pageId);
    }
    catch ( Exception e)
    {
	throw Exception(EXLOC, Chain("Cannot create alias object"), e);
    }
}

void CegoObjectManager::truncateObject(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type)
{
    unsigned long long lockId = 0;
    CegoBufferPage bp;

    _pDBMng->checkTableSetRunState(tabSetId);
    
    try
    {
	PageIdType pageOffset;
	
	if ( type == CegoObject::RBSEG )
	{		      
	    pageOffset = _pDBMng->getTempPageOffset(tabSetId);	
	}
	else
	{
	    pageOffset = _pDBMng->getSysPageOffset(tabSetId);
	}

	PageIdType lowPage;
	PageIdType highPage; 

	getHashPageId(objName, type, lowPage, highPage);
	
	for ( PageIdType hashPage = lowPage; hashPage < highPage ; hashPage++)
	{	    	    
	    PageIdType pageId = pageOffset + hashPage;
	    
	    bool lastPage = false;
	    
	    while ( ! lastPage )
	    {   	    
		_pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::PERSISTENT, _pLockHandle);
		
		lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::WRITE);
		char* pE = (char*)bp.getFirstEntry();
		
		while ( pE )
		{	    
		    CegoObject obj;
		    
		    unsigned size;
		    obj.decodeBase(pE, size);   
		    
		    bool typeMatch =  ( type == CegoObject::AVLTREE
					&& ( obj.getType() == CegoObject::AVLTREE
					     || obj.getType() == CegoObject::PAVLTREE
					     || obj.getType() == CegoObject::UAVLTREE ));
		    if ( ! typeMatch )
			typeMatch = obj.getType() == type;
		    
		    if ( typeMatch && objName == obj.getName() && tabSetId == obj.getTabSetId() )
		    {
			switch ( type ) 
			{
			case CegoObject::FKEY:
			case CegoObject::CHECK:
			case CegoObject::VIEW:
			case CegoObject::PROCEDURE:
			case CegoObject::TRIGGER:
			{
			    /* nothing to do */
			    _pLockHandle->unlockSysPage(lockId);	    
			    _pDBMng->bufferUnfix(bp, true, _pLockHandle);
			    return;   
			}
			case CegoObject::TABLE:
			case CegoObject::SYSTEM:
			case CegoObject::RBSEG:
			case CegoObject::AVLTREE:
			case CegoObject::PAVLTREE:
			case CegoObject::UAVLTREE:
			{
			    CegoTableObject to;			
			    to.decode(pE);
			  
			    pageId = to.getDataPageId();
			    
			    CegoBufferPage tupPage;
			    getNewFilePage(tupPage, tabSetId, type);   
			    
			    tupPage.setType(CegoBufferPage::TUPLE);
			    
			    PageIdType dataPageId = tupPage.getPageId();
			    
			    _pDBMng->bufferUnfix(tupPage, true, _pLockHandle);

			    to.setDataPageId(dataPageId);
			    to.setLastDataPageId(dataPageId);
			    to.encode(pE);
					    
			    _pLockHandle->unlockSysPage(lockId);
			    lockId = 0;

			    freeObjectPages(tabSetId, pageId);
			    _pDBMng->bufferUnfix(bp, true, _pLockHandle);
			    
			    return;		       
			}
			case CegoObject::BTREE:
			case CegoObject::PBTREE:
			case CegoObject::UBTREE:
			{
			    CegoBTreeObject btoe;		
			    btoe.decode(pE);
			  
			    CegoBTreeManager btreeMng(this, &btoe);
			    btreeMng.freeBTree();

			    CegoBufferPage rootPage;
			    getNewFilePage(rootPage, btoe.getTabSetId(), btoe.getType());   
	
			    rootPage.setType(CegoBufferPage::BTREE_LEAF);
			    CegoBTreeNode rootNode;
			    // rootNode.setType(CegoBTreeNode::LEAF);
			    rootNode.setPtr(rootPage.getChunkEntry(), rootPage.getChunkLen());
			    rootNode.initNode();
	
			    PageIdType dataPageId = rootPage.getPageId();

			    btoe.setDataPageId(dataPageId);

			    _pDBMng->bufferUnfix(rootPage, true, _pLockHandle);
			    			   
			    btoe.encode(pE);
					    
			    _pLockHandle->unlockSysPage(lockId);
			    lockId = 0;

			    _pDBMng->bufferUnfix(bp, true, _pLockHandle);
			    
			    return;		       
			}
			case CegoObject::JOIN:
			case CegoObject::ALIAS:
			case CegoObject::UNDEFINED:
			    throw Exception(EXLOC, "Invalid object");
			}
		    }
		    pE = (char*)bp.getNextEntry();
		}
		
		pageId = bp.getNextPageId();
		
		_pLockHandle->unlockSysPage(lockId);
		lockId = 0;
		
		_pDBMng->bufferUnfix(bp, true, _pLockHandle);
		
		if ( pageId == 0 )
		{
		    lastPage = true;
		}
	    }	
	}    
	Chain msg = Chain("Object ") +  objName + Chain(" not found");
	throw Exception(EXLOC, msg);
    }
    catch ( Exception e)
    {	
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);

	throw Exception(EXLOC, Chain("Cannot truncate object"), e);
    }
}

void CegoObjectManager::removeObject(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type)
{    
    unsigned long long lockId = 0;
    CegoBufferPage bp;

    _pDBMng->checkTableSetRunState(tabSetId);
	
    try
    {
	PageIdType pageOffset;	    
	
	if ( type == CegoObject::RBSEG )
	{		      
	    pageOffset = _pDBMng->getTempPageOffset(tabSetId);	
	}
	else
	{
	    pageOffset = _pDBMng->getSysPageOffset(tabSetId);
	}
	    
	PageIdType lowPage;
	PageIdType highPage; 

	getHashPageId(objName, type, lowPage, highPage);	

	for ( PageIdType hashPage = lowPage; hashPage < highPage ; hashPage++)
	{ 
	    PageIdType pageId = pageOffset + hashPage;
	   	    	    
	    bool lastPage = false;
	    
	    while ( ! lastPage )
	    {  	    
		_pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::PERSISTENT, _pLockHandle);
		
		lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::WRITE);
		char* pE = (char*)bp.getFirstEntry();
		
		while ( pE )
		{	    
		    CegoObject obj;
		    
		    unsigned size;
		    obj.decodeBase(pE, size);   

		    bool typeMatch =  
			( type == CegoObject::AVLTREE && ( obj.getType() == CegoObject::AVLTREE
							 || obj.getType() == CegoObject::PAVLTREE
							 || obj.getType() == CegoObject::UAVLTREE )) ||
			( type == CegoObject::BTREE && ( obj.getType() == CegoObject::BTREE
							 || obj.getType() == CegoObject::PBTREE
							 || obj.getType() == CegoObject::UBTREE ));
		    
		    if ( ! typeMatch )		   
			typeMatch = obj.getType() == type;
		    
		    if ( typeMatch && objName == obj.getName() && tabSetId == obj.getTabSetId() )
		    {
			switch ( type ) 
			{
			case CegoObject::FKEY:
			case CegoObject::CHECK:
			case CegoObject::VIEW:
			case CegoObject::PROCEDURE:
			case CegoObject::TRIGGER:
			case CegoObject::ALIAS:
			{
			    bp.freeEntry(pE);
			    _pLockHandle->unlockSysPage(lockId);
			    
			    _pDBMng->bufferUnfix(bp, true, _pLockHandle);
			    return;	    
			}
			case CegoObject::BTREE:
			case CegoObject::PBTREE:
			case CegoObject::UBTREE:
			{
			    CegoBTreeObject btoe;			
			    btoe.decode(pE);

			    CegoBTreeManager btreeMng(this, &btoe);
			    
			    btreeMng.freeBTree();
			    
			    bp.freeEntry(pE);

			    _pLockHandle->unlockSysPage(lockId);
			    lockId = 0;

			    _pDBMng->bufferUnfix(bp, true, _pLockHandle);			    			   
			    
			    return;
			}
			case CegoObject::TABLE:
			case CegoObject::SYSTEM:
			case CegoObject::RBSEG:
			case CegoObject::AVLTREE:
			case CegoObject::PAVLTREE:
			case CegoObject::UAVLTREE:
			{	    
			    CegoTableObject to;			
			    to.decode(pE);
			    			    
			    bp.freeEntry(pE);			    
			    
			    pageId = to.getDataPageId();	       			
			    
			    _pLockHandle->unlockSysPage(lockId);
			    lockId = 0;

			    freeObjectPages(tabSetId, pageId);
			    _pDBMng->bufferUnfix(bp, true, _pLockHandle);
			    
			    return;		       
			}
			case CegoObject::JOIN:
			case CegoObject::UNDEFINED:
			    throw Exception(EXLOC, "Invalid object");
			}
		    }
		    pE = (char*)bp.getNextEntry();
		}
		
		pageId = bp.getNextPageId();
		
		_pLockHandle->unlockSysPage(lockId);
		lockId = 0;
		
		_pDBMng->bufferUnfix(bp, true, _pLockHandle);
		
		if ( pageId == 0 )
		{
		    lastPage = true;
		}
	    }	
	}    
	Chain msg = Chain("Object ") +  objName + Chain(" not found");
	throw Exception(EXLOC, msg);
    }
    catch ( Exception e)
    {	
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);
	
	throw Exception(EXLOC, Chain("Cannot remove object"), e);	
    }
}

unsigned CegoObjectManager::traceObject(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type)
{    
    unsigned long long lockId = 0;
    CegoBufferPage bp;

    _pDBMng->checkTableSetRunState(tabSetId);
	
    try
    {
	PageIdType pageOffset;	    
	
	if ( type == CegoObject::RBSEG )
	{		      
	    pageOffset = _pDBMng->getTempPageOffset(tabSetId);	
	}
	else
	{
	    pageOffset = _pDBMng->getSysPageOffset(tabSetId);
	}
	    
	PageIdType lowPage;
	PageIdType highPage; 

	getHashPageId(objName, type, lowPage, highPage);	

	for ( PageIdType hashPage = lowPage; hashPage < highPage ; hashPage++)
	{ 
	    PageIdType pageId = pageOffset + hashPage;
	   	    	    
	    bool lastPage = false;
	    
	    while ( ! lastPage )
	    {
		_pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::PERSISTENT, _pLockHandle);
		
		lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::WRITE);
		char* pE = (char*)bp.getFirstEntry();
		
		while ( pE )
		{	    
		    CegoObject obj;
		    
		    unsigned size;
		    obj.decodeBase(pE, size);   

		    bool typeMatch =  
			( type == CegoObject::AVLTREE && ( obj.getType() == CegoObject::AVLTREE
							 || obj.getType() == CegoObject::PAVLTREE
							 || obj.getType() == CegoObject::UAVLTREE )) ||
			( type == CegoObject::BTREE && ( obj.getType() == CegoObject::BTREE
							 || obj.getType() == CegoObject::PBTREE
							 || obj.getType() == CegoObject::UBTREE ));
		    
		    if ( ! typeMatch )		   
			typeMatch = obj.getType() == type;
		    
		    if ( typeMatch && objName == obj.getName() && tabSetId == obj.getTabSetId() )
		    {
			switch ( type ) 
			{
			case CegoObject::FKEY:
			case CegoObject::CHECK:
			case CegoObject::VIEW:
			case CegoObject::PROCEDURE:
			case CegoObject::TRIGGER:
			{
			    _pLockHandle->unlockSysPage(lockId);
			    lockId = 0;
			    
			    _pDBMng->bufferUnfix(bp, true, _pLockHandle);
			    return 0;	    
			}
			case CegoObject::BTREE:
			case CegoObject::PBTREE:
			case CegoObject::UBTREE:
			{
			    CegoBTreeObject btoe;			
			    btoe.decode(pE);

			    CegoBTreeManager btreeMng(this, &btoe);
			    
			    unsigned traceCount = btreeMng.traceBTree();
			    
			    _pLockHandle->unlockSysPage(lockId);
			    lockId = 0;

			    _pDBMng->bufferUnfix(bp, true, _pLockHandle);			    			   
			    
			    return traceCount;
			}
			case CegoObject::TABLE:
			case CegoObject::SYSTEM:
			case CegoObject::RBSEG:
			case CegoObject::AVLTREE:
			case CegoObject::PAVLTREE:
			case CegoObject::UAVLTREE:
			{
			    CegoTableObject to;			
			    to.decode(pE);
			    			    			    
			    pageId = to.getDataPageId();	       			
			    
			    _pLockHandle->unlockSysPage(lockId);
			    lockId = 0;

			    unsigned traceCount = traceObjectPages(tabSetId, pageId);
			    _pDBMng->bufferUnfix(bp, true, _pLockHandle);
			    
			    return traceCount;       
			}
			case CegoObject::JOIN:
			case CegoObject::ALIAS:
			case CegoObject::UNDEFINED:
			    throw Exception(EXLOC, "Invalid object"); 
			}
		    }
		    pE = (char*)bp.getNextEntry();
		}
		
		pageId = bp.getNextPageId();
		
		_pLockHandle->unlockSysPage(lockId);
		lockId = 0;
		
		_pDBMng->bufferUnfix(bp, true, _pLockHandle);
		
		if ( pageId == 0 )
		{
		    lastPage = true;
		}
	    }	
	}    
	Chain msg = Chain("Object ") +  objName + Chain(" not found");
	throw Exception(EXLOC, msg);
    }
    catch ( Exception e)
    {	
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);
	
	throw Exception(EXLOC, Chain("Cannot trace object"), e);	
    }
}

void CegoObjectManager::reorgObject(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type)
{
    unsigned long long lockId = 0;
    CegoBufferPage bp;

    _pDBMng->checkTableSetRunState(tabSetId);
	
    try
    {
	PageIdType pageOffset;	    
	
	if ( type == CegoObject::RBSEG )
	{		      
	    pageOffset = _pDBMng->getTempPageOffset(tabSetId);	
	}
	else
	{
	    pageOffset = _pDBMng->getSysPageOffset(tabSetId);
	}
	    
	PageIdType lowPage;
	PageIdType highPage; 

	getHashPageId(objName, type, lowPage, highPage);
	       	
	for ( PageIdType hashPage = lowPage; hashPage < highPage ; hashPage++)
	{ 	    
	    PageIdType pageId = pageOffset + hashPage;
	    
	    bool lastPage = false;
	    
	    while ( ! lastPage )
	    {	
		_pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::PERSISTENT, _pLockHandle);
		
		lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::WRITE);
		
		char* pE = (char*)bp.getFirstEntry();
		
		while ( pE )
		{	    
		    CegoObject obj;
		    
		    unsigned size;
		    obj.decodeBase(pE, size);   
		    
		    bool typeMatch = ( type == CegoObject::AVLTREE
				       && ( obj.getType() == CegoObject::AVLTREE
					    || obj.getType() == CegoObject::PAVLTREE
					    || obj.getType() == CegoObject::UAVLTREE ));
		    if ( ! typeMatch )
			typeMatch = obj.getType() == type;
		    
		    if ( typeMatch && objName == obj.getName() && tabSetId == obj.getTabSetId() )
		    {
			switch ( type ) 
			{
			case CegoObject::TABLE:
			case CegoObject::SYSTEM:
			case CegoObject::RBSEG:
			case CegoObject::AVLTREE:
			case CegoObject::PAVLTREE:
			case CegoObject::UAVLTREE:
			{
			    CegoTableObject to;			
			    to.decode(pE);
			    
			    pageId = to.getDataPageId();	       			
			    
			    PageIdType newPageId;
			    
			    PageIdType newLastPageId;
			    
			    removeEmptyPages(tabSetId, pageId, newPageId, newLastPageId);
			    
			    to.setDataPageId(newPageId);			   
			    to.setLastDataPageId(newLastPageId);			    
			    to.setRefLastDataPageId(newLastPageId);			       
			    
			    to.encode(pE);
			    
			    _pLockHandle->unlockSysPage(lockId);
			    lockId = 0;

			    _pDBMng->bufferUnfix(bp, true, _pLockHandle);
			    
			    return;		    
			}
			case CegoObject::VIEW:
			case CegoObject::PROCEDURE:
			case CegoObject::FKEY:			    
			case CegoObject::JOIN:
			case CegoObject::ALIAS:
			case CegoObject::UNDEFINED:
			case CegoObject::BTREE:
			case CegoObject::PBTREE:
			case CegoObject::UBTREE:
			case CegoObject::CHECK:
			case CegoObject::TRIGGER:
			    throw Exception(EXLOC, "Invalid object");
			}
		    }
		    pE = (char*)bp.getNextEntry();
		}
		
		pageId = bp.getNextPageId();
		
		_pLockHandle->unlockSysPage(lockId);
		lockId = 0;

		_pDBMng->bufferUnfix(bp, true, _pLockHandle);
		
		if ( pageId == 0 )
		{
		    lastPage = true;
		}    
	    }	
	}
	Chain msg = Chain("Object ") +  objName + Chain(" not found");
	throw Exception(EXLOC, msg);
    }
    catch ( Exception e)
    {	
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);

	throw Exception(EXLOC, Chain("Cannot reorganize object"), e);
    }
}

void CegoObjectManager::invalidateObject(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type)
{
    unsigned long long lockId = 0;
    CegoBufferPage bp;

    _pDBMng->checkTableSetRunState(tabSetId);
	
    try
    {
	PageIdType pageOffset;	    
	
	if ( type == CegoObject::RBSEG )
	{		      
	    pageOffset = _pDBMng->getTempPageOffset(tabSetId);	
	}
	else
	{
	    pageOffset = _pDBMng->getSysPageOffset(tabSetId);
	}
	    
	PageIdType lowPage;
	PageIdType highPage; 

	getHashPageId(objName, type, lowPage, highPage);
	       	
	for ( PageIdType hashPage = lowPage; hashPage < highPage ; hashPage++)
	{ 
	    PageIdType pageId = pageOffset + hashPage;
	    
	    bool lastPage = false;
	    
	    while ( ! lastPage )
	    {	
		_pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::PERSISTENT, _pLockHandle);
		
		lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::WRITE);
		
		char* pE = (char*)bp.getFirstEntry();
		
		while ( pE )
		{	    
		    CegoObject obj;
		    
		    unsigned size;
		    obj.decodeBase(pE, size);   
		    
		    bool typeMatch =  
			( type == CegoObject::AVLTREE 
			  && ( obj.getType() == CegoObject::AVLTREE
			       || obj.getType() == CegoObject::PAVLTREE
			       || obj.getType() == CegoObject::UAVLTREE )) ||
			( type == CegoObject::BTREE 
			  && ( obj.getType() == CegoObject::BTREE
			       || obj.getType() == CegoObject::PBTREE
			       || obj.getType() == CegoObject::UBTREE ));

		    if ( ! typeMatch )
			typeMatch = obj.getType() == type;
		    
		    if ( typeMatch && objName == obj.getName() && tabSetId == obj.getTabSetId() )
		    {
			switch ( type ) 
			{
			case CegoObject::TABLE:
			case CegoObject::SYSTEM:
			case CegoObject::RBSEG:
			case CegoObject::AVLTREE:
			case CegoObject::PAVLTREE:
			case CegoObject::UAVLTREE:		       
			{
			    CegoTableObject to;			
			    to.decode(pE);
			    
			    pageId = to.getDataPageId();	       			
			    
			    freeObjectPages(tabSetId, pageId);			    
			    
			    to.setDataPageId(0);
			    
			    to.setLastDataPageId(0);
			    
			    to.encode(pE);
			    
			    _pLockHandle->unlockSysPage(lockId);
			    lockId = 0;

			    _pDBMng->bufferUnfix(bp, true, _pLockHandle);
			    
			    return;			    
			}
			case CegoObject::BTREE:
			case CegoObject::PBTREE:
			case CegoObject::UBTREE:
			{		
			    CegoBTreeObject bto;			
			    bto.decode(pE);
			    
			    pageId = bto.getDataPageId();	       			

			    CegoBTreeManager btreeMng(this, &bto);
			    btreeMng.freeBTree();
			    			    
			    bto.setDataPageId(0);
			    			    
			    bto.encode(pE);
			    
			    _pLockHandle->unlockSysPage(lockId);
			    lockId = 0;

			    _pDBMng->bufferUnfix(bp, true, _pLockHandle);
			    
			    return;	    
			}
			case CegoObject::VIEW:
			case CegoObject::FKEY:
			case CegoObject::PROCEDURE:
			case CegoObject::JOIN:
			case CegoObject::ALIAS:
			case CegoObject::UNDEFINED:
			case CegoObject::CHECK:
			case CegoObject::TRIGGER:			    
			    throw Exception(EXLOC, "Invalid object");
			}
		    }
		    pE = (char*)bp.getNextEntry();
		}
		
		pageId = bp.getNextPageId();
		
		_pLockHandle->unlockSysPage(lockId);
		lockId = 0;

		_pDBMng->bufferUnfix(bp, true, _pLockHandle);
		
		if ( pageId == 0 )
		{
		    lastPage = true;
		}    
	    }	
	}
	Chain msg = Chain("Object ") +  objName + Chain(" not found");
	throw Exception(EXLOC, msg);
    }
    catch ( Exception e)
    {	
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);
	
	throw Exception(EXLOC, Chain("Cannot invalidate object"), e);	
    }
}

void CegoObjectManager::alterTableObject(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type, CegoTableObject& objEntry)
{
    alterObject(tabSetId, objName, type, objEntry);
}

void CegoObjectManager::alterBTreeObject(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type, CegoBTreeObject& objEntry)
{
    alterObject(tabSetId, objName, type, objEntry);
}

void CegoObjectManager::alterKeyObject(unsigned tabSetId, const Chain& keyName, CegoKeyObject& objEntry)
{
    alterObject(tabSetId, keyName, objEntry.getType(), objEntry);
}

void CegoObjectManager::alterTriggerObject(unsigned tabSetId, const Chain& triggerName, CegoTriggerObject& objEntry)
{
    alterObject(tabSetId, triggerName, objEntry.getType(), objEntry);
}

void CegoObjectManager::alterCheckObject(unsigned tabSetId, const Chain& checkName, CegoCheckObject& checkEntry)
{
    alterObject(tabSetId, checkName, checkEntry.getType(), checkEntry);
}

void CegoObjectManager::getObjectList(unsigned tabSetId, CegoObject::ObjectType type, ListT<Chain>& objList)
{        
    unsigned long long lockId = 0;
    CegoBufferPage bp;

    _pDBMng->checkTableSetRunState(tabSetId);
    
    try
    {	
	PageIdType pageOffset;	    

	if ( type == CegoObject::RBSEG )
	{		      
	    pageOffset = _pDBMng->getTempPageOffset(tabSetId);	
	}
	else
	{
	    pageOffset = _pDBMng->getSysPageOffset(tabSetId);
	}

	unsigned maxPos = TABMNG_HASHSIZE;
	
	for ( PageIdType hashPos = 0 ; hashPos < (PageIdType)maxPos; hashPos++ )
	{	    
	    PageIdType pageId = pageOffset + hashPos;
	    	    
	    bool lastPage = false;
	    
	    while ( ! lastPage )
	    {		
		_pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::PERSISTENT, _pLockHandle);
	    		
		lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::READ);
		
		char* pE = (char*)bp.getFirstEntry();
		
		while (pE)
		{		    
		    CegoObject obj;
		    unsigned entrySize;
		    
		    obj.decodeBase(pE, entrySize);   
		    
		    if ( tabSetId == obj.getTabSetId() )
		    {
			bool typeMatch =  
			    ( type == CegoObject::AVLTREE && ( obj.getType() == CegoObject::AVLTREE
							     || obj.getType() == CegoObject::PAVLTREE
							     || obj.getType() == CegoObject::UAVLTREE )) ||
			    ( type == CegoObject::BTREE && ( obj.getType() == CegoObject::BTREE
							     || obj.getType() == CegoObject::PBTREE
							     || obj.getType() == CegoObject::UBTREE ));
			if ( ! typeMatch )
			    typeMatch = obj.getType() == type;
			
			if ( typeMatch )
			{
			    objList.Insert(obj.getName());
			}
		    }		    
		    pE = (char*)bp.getNextEntry();
		}
		
		pageId = bp.getNextPageId();
		
		_pLockHandle->unlockSysPage(lockId);		    
		lockId = 0;

		_pDBMng->bufferUnfix(bp, false, _pLockHandle);
		
		if ( pageId == 0 )
		{
		    lastPage = true;
		}
	    }
	}
    }
    catch ( Exception e )
    {	
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);	    	
	
	throw Exception(EXLOC, Chain("Cannot get object list"), e);	
    }
}

void CegoObjectManager::setIgnoreInvalid(bool ignoreInvalid)
{
    _ignoreInvalid = ignoreInvalid;
} 

void CegoObjectManager::getObjectListByTable(unsigned tabSetId, const Chain& tabName, 
					     ListT<CegoTableObject>& idxList, 
					     ListT<CegoBTreeObject>& btreeList, 
					     ListT<CegoKeyObject>& keyList,
					     ListT<CegoCheckObject>& checkList,
					     ListT<CegoTriggerObject>& triggerList,
					     ListT<CegoAliasObject>& aliasList,
					     unsigned& numInvalid)
{    
    unsigned long long lockId = 0;
    CegoBufferPage bp;
    bool objectFound = false;

    _pDBMng->checkTableSetRunState(tabSetId);

    keyList.Empty();
    checkList.Empty();
    idxList.Empty();
    btreeList.Empty();
    keyList.Empty();
    checkList.Empty();
    triggerList.Empty();
    aliasList.Empty();
    numInvalid = 0;
    
    try
    {
	PageIdType pageOffset;	    

	pageOffset = _pDBMng->getSysPageOffset(tabSetId);

	unsigned maxPos = TABMNG_HASHSIZE;
	
	for ( PageIdType hashPos = 0; hashPos < (PageIdType)maxPos; hashPos++ )
	{	    
	    PageIdType pageId = pageOffset + hashPos;
	    
	    bool lastPage = false;	
	    
	    while ( ! lastPage )
	    {	
		_pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::PERSISTENT, _pLockHandle);	
		lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::READ);	
		
		char* pE = (char*)bp.getFirstEntry();
		
		while (pE)
		{	    
		    CegoObject obj;
		    unsigned entrySize;
		    obj.decodeBase(pE, entrySize);   
		    
		    if ( tabSetId == obj.getTabSetId() )
		    {
			if ( ( obj.getType() == CegoObject::TABLE
			       || obj.getType() == CegoObject::VIEW )
			     && (Chain)obj.getName() == (Chain)tabName )
			{
			    objectFound = true;
			}		      
			else if ( obj.getType() == CegoObject::FKEY)
			{
			    CegoKeyObject ko;
			    ko.decode(pE);
			    if ( (Chain)ko.getTabName() == (Chain)tabName || (Chain)ko.getRefTable() == (Chain)tabName )
			    {
				keyList.Insert(ko);
			    }
			}
			else if ( obj.getType() == CegoObject::CHECK )
			{	    
			    CegoCheckObject co;
			    co.decode(pE);

			    if ( (Chain)co.getTabName() == (Chain)tabName )
			    {
				checkList.Insert(co);
			    }
			}
			else if ( obj.getType() == CegoObject::TRIGGER )
			{			    
			    CegoTriggerObject to;
			    to.decode(pE);

			    if ( (Chain)to.getTabName() == (Chain)tabName )
			    {
				triggerList.Insert(to);
			    }
			}
			else if ( obj.getType() == CegoObject::ALIAS )
			{			    
			    CegoAliasObject ao;
			    ao.decode(pE);

			    if ( (Chain)ao.getTabName() == (Chain)tabName )
			    {
				aliasList.Insert(ao);
			    }
			}

			else if ( obj.getType() == CegoObject::AVLTREE 
				  || obj.getType() == CegoObject::UAVLTREE 
				  || obj.getType() == CegoObject::PAVLTREE ) 
			{
			    CegoTableObject io;
			    io.decode(pE);
			    			    
			    if ( (Chain)io.getTabName() == (Chain)tabName)
			    {				
				if ( io.getDataPageId() == 0 )
				{
				    if ( _ignoreInvalid == false )  
				    {
					numInvalid++;
					idxList.Insert(io);
				    }
				}
				else
				{
				    idxList.Insert(io);
				}
			    }
			}
			else if ( obj.getType() == CegoObject::BTREE 
				  || obj.getType() == CegoObject::UBTREE 
				  || obj.getType() == CegoObject::PBTREE ) 
			{
			    CegoBTreeObject bto;
			    bto.decode(pE);
			    			    
			    if ( (Chain)bto.getTabName() == (Chain)tabName)
			    {
				if (  bto.getDataPageId() == 0 )
				{
				    if ( _ignoreInvalid == false )
				    {
					numInvalid++;
					btreeList.Insert(bto);
				    }
				}
				else
				{
				    btreeList.Insert(bto);
				}
			    }
			}
		    }
		    pE = (char*)bp.getNextEntry();
		}
		
		pageId = bp.getNextPageId();
		
		_pLockHandle->unlockSysPage(lockId);
		lockId = 0;

		_pDBMng->bufferUnfix(bp, false, _pLockHandle);
		
		if ( pageId == 0 )
		{
		    lastPage = true;
		}
	    }
	}
    }
    catch ( Exception e)
    {	
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);	    	
	
	throw Exception(EXLOC, Chain("Cannot get object list by table"), e);
    }

    if ( objectFound == false )
    {
	Chain msg = Chain("Object ") +  tabName + Chain(" not found");
	throw Exception(EXLOC, msg);
    }	
}

void CegoObjectManager::getObject(unsigned tabSetId, const Chain& objectName, CegoObject::ObjectType type, CegoDecodableObject& oe)
{    
    CegoBufferPage bp;
    getObjectWithFix(tabSetId, objectName, type, oe, bp);
    _pDBMng->bufferUnfix(bp, false, _pLockHandle);    
}

void CegoObjectManager::getObjectWithFix(unsigned tabSetId, const Chain& objectName, CegoObject::ObjectType type, CegoDecodableObject& oe, CegoBufferPage &bp)
{
    unsigned long long lockId = 0;

    _pDBMng->checkTableSetRunState(tabSetId);
    
    try
    {
	bool notFound = true;

	PageIdType pageOffset;	    

	if ( type == CegoObject::RBSEG )
	{		      
	    pageOffset = _pDBMng->getTempPageOffset(tabSetId);	
	}
	else
	{
	    pageOffset = _pDBMng->getSysPageOffset(tabSetId);
	}

	PageIdType lowPage;
	PageIdType highPage;

	getHashPageId(objectName, type, lowPage, highPage);
	
	for ( PageIdType hashPage = lowPage; hashPage < highPage ; hashPage++)
	{ 	    
	    PageIdType pageId = pageOffset + hashPage;
	    
	    bool lastPage = false;
	    
	    while ( ! lastPage && notFound )
	    {	
		_pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::PERSISTENT, _pLockHandle);
		lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::READ);
	
		char* pE = (char*)bp.getFirstEntry();
			       
		while (pE && notFound )
		{		    
		    CegoObject obj;
		    unsigned entrySize;
		    obj.decodeBase(pE, entrySize);
		    
		    if ( tabSetId == obj.getTabSetId() )
		    {
			bool typeMatch =  
			    ( type == CegoObject::AVLTREE && ( obj.getType() == CegoObject::AVLTREE
							     || obj.getType() == CegoObject::PAVLTREE
							     || obj.getType() == CegoObject::UAVLTREE )) ||
			    ( type == CegoObject::BTREE && ( obj.getType() == CegoObject::BTREE
							     || obj.getType() == CegoObject::PBTREE
							     || obj.getType() == CegoObject::UBTREE ));
			if ( ! typeMatch )
			    typeMatch = obj.getType() == type;
	
			if ((Chain)obj.getName() == (Chain)objectName && typeMatch ) // && type != CegoObject::FKEY)
			{
			    oe.decode(pE);
			    notFound = false;
			}
			else
			{		    
			    pE = (char*)bp.getNextEntry();
			}
		    }
		    else
		    {		    
			pE = (char*)bp.getNextEntry();
		    }
		}
		
		pageId = bp.getNextPageId();
		
		_pLockHandle->unlockSysPage(lockId);
		lockId = 0;

		if ( notFound == false )
		{
		    return;
		}
		else
		{
		    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
		}
		
		if ( pageId == 0 )
		{
		    lastPage = true;
		}   
	    }	
	}
	if ( notFound ) 
	{
	    Chain msg = Chain("Object ") +  objectName + Chain(" not found");
	    throw Exception(EXLOC, msg);
	}	
    }
    catch ( Exception e )
    {	
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);	    	
	
	throw Exception(EXLOC, Chain("Cannot get object with fix"), e);
    }
}

bool CegoObjectManager::tableObjectExists(unsigned tabSetId, const Chain& objectName)
{
    return objectExists(tabSetId, objectName, CegoObject::TABLE)
	|| objectExists(tabSetId, objectName, CegoObject::VIEW)
	|| objectExists(tabSetId, objectName, CegoObject::ALIAS);	
}

bool CegoObjectManager::objectExists(unsigned tabSetId, const Chain& objectName, CegoObject::ObjectType type)
{
    CegoBufferPage bp;
    unsigned long long lockId = 0;	    

    _pDBMng->checkTableSetRunState(tabSetId);
    
    try
    {		
	bool found = false;	
	PageIdType pageOffset;	    
		
	if ( type == CegoObject::RBSEG )
	{		      
	    pageOffset = _pDBMng->getTempPageOffset(tabSetId);	
	}
	else
	{
	    pageOffset = _pDBMng->getSysPageOffset(tabSetId);
	}

	PageIdType lowPage;
	PageIdType highPage;

	getHashPageId(objectName, type, lowPage, highPage);
	
	for ( PageIdType hashPage = lowPage; hashPage < highPage ; hashPage++)
	{ 	    
	    PageIdType pageId = pageOffset + hashPage;
	    
	    bool lastPage = false;
	    	    
	    while ( ! lastPage && ! found )
	    {
		_pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::PERSISTENT, _pLockHandle);

		lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::READ);
		
		char* pE = (char*)bp.getFirstEntry();
		
		while (pE && ! found )
		{	    
		    CegoObject oe;
		    unsigned entrySize;
		    oe.decodeBase(pE, entrySize);
		    
		    if ( tabSetId == oe.getTabSetId() )
		    {
			bool typeMatch =  
			    ( type == CegoObject::AVLTREE && ( oe.getType() == CegoObject::AVLTREE
							     || oe.getType() == CegoObject::PAVLTREE
							     || oe.getType() == CegoObject::UAVLTREE )) ||
			    ( type == CegoObject::BTREE && ( oe.getType() == CegoObject::BTREE
							     || oe.getType() == CegoObject::PBTREE
							     || oe.getType() == CegoObject::UBTREE ));
			if ( ! typeMatch )
			    typeMatch = oe.getType() == type;
			
			if ((Chain)oe.getName() == objectName && typeMatch ) 
			{	
			    found = true;
			}
			else
			{		    		    
			    pE = (char*)bp.getNextEntry();
			}
		    }
		    else
		    {		    
			pE = (char*)bp.getNextEntry();
		    }		
		}
		
		pageId = bp.getNextPageId();
		
		_pLockHandle->unlockSysPage(lockId);		    
		lockId = 0;

		_pDBMng->bufferUnfix(bp, false, _pLockHandle);
		
		if ( pageId == 0 )
		{
		    lastPage = true;
		}
	    }	    
	    if ( found )
		return true;
	}	
	return false;	
    }
    catch ( Exception e )
    {
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);	    	
	
	throw Exception(EXLOC, Chain("Cannot check object"), e);
    }
}

CegoDataPointer CegoObjectManager::insertData(CegoTableObject& oe, char* data, unsigned dataSize, bool doAppend, bool allowWrite)
{
    unsigned long long recLock = 0;
    unsigned long long lockId = 0;
    CegoBufferPage bp;
    
    try
    {	
	PageIdType pageOffset;	    
		
	if ( oe.getType() == CegoObject::RBSEG )
	{		      
	    pageOffset = _pDBMng->getTempPageOffset(oe.getTabSetId());	
	}
	else
	{
	    pageOffset = _pDBMng->getSysPageOffset(oe.getTabSetId());
	}

	PageIdType lowPage;
	PageIdType highPage;

	getHashPageId(oe.getTabName(), oe.getType(), lowPage, highPage);
	
	for ( PageIdType hashPage = lowPage; hashPage < highPage ; hashPage++)
	{ 	    
	    PageIdType pageId = pageOffset + hashPage;
		    
	    bool lastPage = false;	
	    
	    while ( ! lastPage )
	    {		
		_pDBMng->bufferFix(bp, oe.getTabSetId(), pageId, CegoBufferPool::PERSISTENT, _pLockHandle);
		
		lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::READ); 
		
		char* pE = (char*)bp.getFirstEntry();
		
		while ( pE )
		{
		    CegoObject obj;
		    unsigned entrySize;
		    obj.decodeBase(pE, entrySize);
		    		    
		    if ( oe.getTabSetId() == obj.getTabSetId() 
			 && (Chain)oe.getName() == (Chain)obj.getName() 
			 && oe.getType() == obj.getType())
		    {	    	
			CegoDataPointer recDP(pageId, bp.getEntryPos());

			if ( oe.getType() == CegoObject::RBSEG )
			{
			    recLock = _pLockHandle->lockRBRecord(recDP, CegoLockHandler::WRITE);
			}
			else
			{
			    recLock = _pLockHandle->lockSysRecord(recDP, CegoLockHandler::WRITE);
			}
			
			// resolve required
			oe.decode(pE);
			
			CegoDataPointer dp;
			
			PageIdType startPageId;

			// cout << "Last Ref page id = " << oe.getRefLastDataPageId() << endl;
			if (  doAppend ) 
			{			
			    startPageId = oe.getRefLastDataPageId();
			    // cout << "Insert page data at append page " << startPageId << endl;
			}
			else
			{
			    startPageId = oe.getDataPageId();
			    // cout << "Insert page data at start page " << startPageId << endl;
			}			
			
			bool isNewPage;
			
			dp = insertPageData(oe.getTabSetId(), oe.getType(), startPageId, data, dataSize, isNewPage, allowWrite, doAppend);
			
			if ( isNewPage )
			{			       
			    oe.setRefLastDataPageId(dp.getPageId());			       
			}			

			if ( oe.getType() == CegoObject::RBSEG )
			{
			    _pLockHandle->unlockRBRecord(recLock);
			}
			else
			{			    
			    _pLockHandle->unlockSysRecord(recLock);
			}
			
			recLock = 0;
			
			_pLockHandle->unlockSysPage(lockId);
			lockId = 0;
			
			_pDBMng->bufferUnfix(bp, true, _pLockHandle);
			
			return dp;	
		    }
		    else
		    {
			pE = (char*)bp.getNextEntry();
		    }		    
		}
		
		pageId = bp.getNextPageId();
		
		_pLockHandle->unlockSysPage(lockId);
		lockId = 0;

		_pDBMng->bufferUnfix(bp, false, _pLockHandle);
		
		if ( pageId == 0 )
		{
		    lastPage = true;
		}
	    }
	}
	Chain msg = Chain("Object ") +  oe.getName() + Chain(" not found");
	throw Exception(EXLOC, msg);	
    }
    catch ( Exception e )
    {
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);
	
	if ( recLock )
	{
	    if ( oe.getType() == CegoObject::RBSEG )
	    {
		_pLockHandle->unlockRBRecord(recLock);
	    }
	    else
	    {			    
		_pLockHandle->unlockSysRecord(recLock);
	    }	   
	}
	throw Exception(EXLOC, Chain("Cannot insert native data"), e);
    }
}

/* 
   The second insertData method is performance optimized and can be used, if the the data pointer for the corresponding object 
   is already available (sysEntry). In this case, no lookup up is required to get the entry point for the object.
   Anyway the TableObject is given as an argument to set up the lastpage information for the object.
   The insertAtLast flag enables append mode rather then looking for unued page slots in the available data pages.
   The allowWrite flag is used to allow asynchronous writes of data pages to the data files.
   Normally, this is used for index and temp objects.
 */

CegoDataPointer CegoObjectManager::insertData( const CegoDataPointer& sysEntry, CegoTableObject& oe, char* data, unsigned dataSize, bool doAppend, bool allowWrite)
{		
    unsigned long long recLock = 0;

    try
    {
	if ( oe.getType() == CegoObject::RBSEG )
	{
	    recLock = _pLockHandle->lockRBRecord(sysEntry, CegoLockHandler::WRITE);
	}
	else
	{
	    recLock = _pLockHandle->lockSysRecord(sysEntry, CegoLockHandler::WRITE);
	}

	CegoDataPointer dp;
	
	PageIdType pageId;
	
	// int lockPageId = oe.getDataPageId();	       	    
	
	if ( doAppend )      
	{				    
	    pageId = oe.getRefLastDataPageId();
	}
	else
	{
	    pageId = oe.getDataPageId();	       
	}
	
	bool isNewPage;
		
	dp = insertPageData(oe.getTabSetId(), oe.getType(), pageId, data, dataSize, isNewPage, allowWrite, doAppend);
	if ( isNewPage )
	{
	    // setLastPage
	    oe.setRefLastDataPageId(dp.getPageId());		  
	}

	if ( oe.getType() == CegoObject::RBSEG )
	{
	    _pLockHandle->unlockRBRecord(recLock);
	}
	else
	{			    
	    _pLockHandle->unlockSysRecord(recLock);
	}	   

	recLock = 0;
	
	return dp;	
    }
    catch ( Exception e )
    {
	if ( recLock )
	{
	    if ( oe.getType() == CegoObject::RBSEG )
	    {
		_pLockHandle->unlockRBRecord(recLock);
	    }
	    else
	    {			    
		_pLockHandle->unlockSysRecord(recLock);
	    }	   	   
	}	
	throw Exception(EXLOC, Chain("Cannot insert sysentry data"), e);
    }
}

void CegoObjectManager::deleteData(CegoObject::ObjectType type, unsigned tabSetId, const CegoDataPointer& dp)
{
    CegoBufferPage bp;
    unsigned long long lockId = 0;

    try
    {	
	_pDBMng->bufferFix(bp, tabSetId, dp.getPageId(), CegoBufferPool::SYNC, _pLockHandle);
	
	char* pE = (char*)bp.getPagePtr() + dp.getOffset();
	       	
	lockId = _pLockHandle->lockData(type, dp.getPageId(), CegoLockHandler::WRITE);
	bp.freeEntry(pE);
	
	_pLockHandle->unlockData(type, lockId);
	lockId = 0;

	_pDBMng->bufferUnfix(bp, true, _pLockHandle);
    }
    catch ( Exception e)
    {
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);

	if ( lockId )
	    _pLockHandle->unlockData(type, lockId);

	throw Exception(EXLOC, Chain("Cannot delete data"), e);
    }
}

CegoObjectCursor* CegoObjectManager::getObjectCursor(unsigned tabSetId, const Chain& hashName, const Chain& objName, CegoObject::ObjectType type)
{
    CegoBufferPage bp;
    unsigned long long lockId = 0;
    
    try
    {
	PageIdType pageOffset;	    
		
	if ( type == CegoObject::RBSEG )
	{		      
	    pageOffset = _pDBMng->getTempPageOffset(tabSetId);	
	}
	else
	{
	    pageOffset = _pDBMng->getSysPageOffset(tabSetId);
	}

	PageIdType lowPage;
	PageIdType highPage;

	getHashPageId(hashName, type, lowPage, highPage);
	
	for ( PageIdType hashPage = lowPage; hashPage < highPage ; hashPage++)
	{ 	    	    
	    PageIdType pageId = pageOffset + hashPage;
	    	    
	    bool lastPage = false;    
	    bool inserted = false;
	    
	    while ( ! lastPage && ! inserted)
	    {			
		_pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::PERSISTENT, _pLockHandle);
		lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::READ);

		char* pE = (char*)bp.getFirstEntry();
		
		while (pE && ! inserted )
		{
		    CegoObject obj;
		    unsigned entrySize;
		    
		    obj.decodeBase(pE, entrySize);
		    
		    if ( obj.getTabSetId() == tabSetId )
		    {
			bool typeMatch =  
			    ( type == CegoObject::AVLTREE && ( obj.getType() == CegoObject::AVLTREE
							     || obj.getType() == CegoObject::PAVLTREE
							     || obj.getType() == CegoObject::UAVLTREE ));
			if ( ! typeMatch )
			    typeMatch = obj.getType() == type;
					
			if ( (Chain)objName == (Chain)obj.getName() && typeMatch)
			{
			    CegoTableObject to;
			    to.decode(pE);			   			    
			    
			    _pLockHandle->unlockSysPage(lockId);
			    lockId = 0;

			    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
			    
			    CegoObjectCursor* pC = new CegoObjectCursor(_pDBMng,
									_pLockHandle,
									tabSetId,
									type,
									to.getDataPageId());
			    return pC;   
			}
			else
			{
			    pE = (char*)bp.getNextEntry();
			}
		    }
		    else
		    {
			pE = (char*)bp.getNextEntry();
		    }
		}
		_pLockHandle->unlockSysPage(lockId);
		lockId = 0;

		pageId = bp.getNextPageId();
		
		_pDBMng->bufferUnfix(bp, false, _pLockHandle);
		
		if ( pageId == 0 )
		{
		    lastPage = true;
		}
	    }
	}
	Chain msg = Chain("Object ") +  objName + Chain(" not found");
	throw Exception(EXLOC, msg);
    }
    catch ( Exception e )
    {
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);
	throw Exception(EXLOC, Chain("Cannot get object cursor"), e);
    }
}

void CegoObjectManager::claimDataPtrUnlocked(unsigned tabSetId, CegoBufferPool::FixMode fixMode, const CegoDataPointer& dp, char*& ptr, unsigned& len, CegoBufferPage& bp)
{     
    _pDBMng->bufferFix(bp, tabSetId, dp.getPageId(), fixMode, _pLockHandle);    
    ptr = (char*)bp.getPagePtr() + dp.getOffset();
    len = *(unsigned*)((long long)bp.getPagePtr() + (long)dp.getOffset() - sizeof(unsigned));
}

void CegoObjectManager::releaseDataPtrUnlocked(CegoBufferPage& bp, bool isDirty)
{
    if ( bp.getPageId() )
	_pDBMng->bufferUnfix(bp, isDirty, _pLockHandle);
}

void CegoObjectManager::releaseAndClaimDataPtrUnlocked(CegoBufferPage& bp, bool isDirty, unsigned tabSetId, CegoBufferPool::FixMode fixMode, const CegoDataPointer& dp, char*& ptr, unsigned& len, CegoBufferPage& nbp)
{
    // do we have to unfix and fix ?
    if ( bp.getPageId() == dp.getPageId() )
    {
	// same page id, so we just setup
	nbp = bp;
	ptr = (char*)nbp.getPagePtr() + dp.getOffset();
	len = *(unsigned*)((long long)nbp.getPagePtr() + (long)dp.getOffset() - sizeof(unsigned));
    }
    else
    {
	releaseDataPtrUnlocked(bp, isDirty);
	claimDataPtrUnlocked(tabSetId, fixMode, dp, ptr, len, nbp);
    }
}

void CegoObjectManager::freeObjectPages(unsigned tabSetId, PageIdType pageId)
{
    bool lastPage = false;

    while ( ! lastPage )
    {	
	if ( pageId == 0 )
	{
	    lastPage = true;
	}
	else
	{	    
	    CegoBufferPage delPage;
		
	    _pDBMng->bufferFix(delPage,
			       tabSetId, 
			       pageId,
			       CegoBufferPool::SYNC, _pLockHandle);
		
	    pageId = delPage.getNextPageId();
	    _pDBMng->bufferRelease(delPage, _pLockHandle);	    	    
	} 	   
    }
}

unsigned CegoObjectManager::traceObjectPages(unsigned tabSetId, PageIdType pageId)
{
    bool lastPage = false;

    unsigned pageCount = 0;
    
    while ( ! lastPage )
    {	
	if ( pageId == 0 )
	{
	    lastPage = true;
	}
	else
	{	    
	    CegoBufferPage tracePage;
		
	    _pDBMng->bufferFix(tracePage,
			       tabSetId, 
			       pageId,
			       CegoBufferPool::SYNC, _pLockHandle);

	    _pDBMng->commitPageEntry(pageId);

	    pageCount++;
	    
	    pageId = tracePage.getNextPageId();

	    _pDBMng->bufferUnfix(tracePage, false, _pLockHandle);	    	    
	} 	   
    }
    return pageCount;
}

unsigned CegoObjectManager::countObjectPages(unsigned tabSetId, PageIdType pageId)
{
    bool lastPage = false;
    unsigned pageCount=0;

    while ( ! lastPage )
    {	
	if ( pageId == 0 )
	{
	    lastPage = true;
	}
	else
	{	    
	    CegoBufferPage countPage;
   
	    _pDBMng->bufferFix(countPage,
			       tabSetId, 
			       pageId,
			       CegoBufferPool::SYNC, _pLockHandle);

	    pageCount++;

	    PageIdType nextPageId = countPage.getNextPageId();

	    _pDBMng->bufferUnfix(countPage, false, _pLockHandle);
	    
	    pageId = nextPageId;	    
	} 	   
    }
    return pageCount;
}

void CegoObjectManager::removeEmptyPages(unsigned tabSetId, PageIdType pageId, PageIdType& newPageId, PageIdType& newLastPageId)
{
    bool lastPage = false;
    
    CegoBufferPage prevPage;
    CegoBufferPage chkPage;
    
    newPageId = 0;
    newLastPageId = 0;
    bool isFirst = true;

    while ( ! lastPage )
    {
	if ( pageId == 0  )
	{
	    lastPage = true;
	}
	else
	{	    
	    prevPage = chkPage;

	    bool isEmptyPage = true;
	    PageIdType basePageId = pageId;
	    
	    while ( isEmptyPage && ! lastPage )
	    {	
		_pDBMng->bufferFix(chkPage, tabSetId, pageId, CegoBufferPool::SYNC, _pLockHandle);
	       
		if ( chkPage.getNumEntries() > 0 )
		{
		    isEmptyPage = false;
		    if ( isFirst )
		    {
			newPageId = pageId;
			isFirst = false;
		    }
		    newLastPageId = pageId;	
		}
				
		if ( isEmptyPage )
		{		   
		    if ( chkPage.getNextPageId() == 0 )
		    {
			lastPage = true;			
		    }
		    
		    if ( isFirst == false || lastPage == false )
		    {
			pageId = chkPage.getNextPageId();
			_pDBMng->bufferRelease(chkPage, _pLockHandle); 
		    }
		    else
		    {
			newPageId = pageId;			
		    }		    
		}
	    }
	    
	    if ( basePageId != pageId )
	    {		
		if ( prevPage.isFixed() )
		{
		    prevPage.setNextPageId(pageId);		    
		    _pDBMng->bufferUnfix(prevPage, true, _pLockHandle);
		}
	    }
	    else
	    {
		if ( prevPage.isFixed() )
		{
		    _pDBMng->bufferUnfix(prevPage, false, _pLockHandle);
		}
	    }
	    if ( lastPage == false )
	    { 
		pageId = chkPage.getNextPageId();
	    }
	}
    }
    
    if ( chkPage.isFixed() )
    {
	_pDBMng->bufferUnfix(chkPage, false, _pLockHandle);
    }

    if ( newLastPageId == 0 )
    {
	newLastPageId = newPageId;
    }
}

CegoDataPointer CegoObjectManager::insertPageData(unsigned tabSetId, CegoObject::ObjectType type, PageIdType pageId, char* data, unsigned dataSize, bool& isNewPage, bool allowWrite, bool doAppend)
{
    unsigned long long lockId = 0;
    CegoBufferPage bp;
    
    try
    {
	isNewPage=false;
	
	CegoBufferPool::FixMode fixMode = CegoBufferPool::SYNC;
	
	if ( type == CegoObject::SYSTEM )
	{
	    fixMode = CegoBufferPool::PERSISTENT; 
	}
	if ( allowWrite )
	{
	    fixMode = CegoBufferPool::NOSYNC;
	}

	// diabled with version 2.53.5 
	// unsigned long long cpCount = _pDBMng->getCPCount();
	
	_pDBMng->bufferFix(bp,
			   tabSetId,
			   pageId, 
			   fixMode, _pLockHandle);
	
	bool inserted = false;
	
	while ( ! inserted )
	{	    	    
	    lockId = _pLockHandle->lockData(type, pageId, CegoLockHandler::WRITE);
	    	    
	    char *pE = (char*)bp.newEntry(dataSize);
	    
	    if (pE)
	    {	
		_pLockHandle->unlockData(type, lockId);
		lockId = 0;
		
		memcpy(pE, data, dataSize);
		inserted = true;
		
		CegoDataPointer dp(bp.getPageId(),
				   (long long)pE - (long long)bp.getPagePtr());
		
		_pDBMng->bufferUnfix(bp, true, _pLockHandle);

		/* to check of this is still needed, from version 2.53.5, we have set LOGREC_SYCN to lsn = 0 */
		/*
		  if a checkpoint has occured before writing data to page, 
		  we have to force checkpoint again, since the log entry is ignored.
		  This is important in case of crash recovery.
		*/

		/*
		if ( _pDBMng->getCPCount() > cpCount )
		{
		    _pDBMng->log(_modId, Logger::NOTICE, Chain("Forced checkpoint by insertPageData"));
		    unsigned long long lsn = _pDBMng->writeCheckPoint(tabSetId, true, Chain(), 0,  _pLockHandle);
		    _pDBMng->log(_modId, Logger::NOTICE, Chain("Forced checkpoint for insertPageData at ") + Chain(lsn));
		}
		*/
		
		return dp;	
	    }
	    else
	    {
		// did we already allocate a new page with maximum available space
		// if so, the record len is too long
		if ( isNewPage == true )
		{
		    throw Exception(EXLOC, Chain("Data entry of length ") + Chain(dataSize) + Chain(" exceeds maximum available space in page "));	    
		}
		pageId = bp.getNextPageId();
		
		CegoBufferPage nbp;
		
		if ( pageId == 0 )
		{	 	
		    getNewFilePage(nbp, tabSetId, type, allowWrite, doAppend);
		    
		    isNewPage=true;
		    
		    pageId = nbp.getPageId();
		    bp.setNextPageId(pageId);
		    
		    _pLockHandle->unlockData(type, lockId);		
		    lockId = 0;
		    
		    _pDBMng->bufferUnfix(bp, true, _pLockHandle);		    
		}
		else
		{
		    // release locked and fixed data page
		    _pLockHandle->unlockData(type, lockId);
		    lockId = 0;

		    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
		    
		    // fix next data page
		    _pDBMng->bufferFix(nbp, tabSetId, pageId, fixMode, _pLockHandle);
		}
		bp = nbp;
	    }
	}
	throw Exception(EXLOC, Chain("Cannot allocate bufferpage"));
    }
    catch ( Exception e )
    {
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockData(type, lockId);

	throw Exception(EXLOC, Chain("Cannot insert page data"), e);
    }
}

void CegoObjectManager::getNewFilePage(CegoBufferPage& bp, unsigned tabSetId, CegoObject::ObjectType type, bool allowWrite, bool doAppend)
{
    CegoBufferPool::FixMode fixMode;
    CegoFileHandler::FileType fileType;

    if ( type == CegoObject::SYSTEM)
    {
	fixMode = CegoBufferPool::PERSISTENT;
	fileType = CegoFileHandler::SYSTEMFILE;
    }
    else if ( type == CegoObject::TABLE
	      || type == CegoObject::UAVLTREE
	      || type == CegoObject::PAVLTREE
	      || type == CegoObject::AVLTREE
	      || type == CegoObject::UBTREE
	      || type == CegoObject::PBTREE
	      || type == CegoObject::BTREE
	      || type  == CegoObject::VIEW)
    {
	if ( allowWrite )
	    fixMode = CegoBufferPool::NOSYNC;
	else
	    fixMode = CegoBufferPool::SYNC;

	fileType = CegoFileHandler::DATAFILE;
    }
    else if ( type == CegoObject::RBSEG )
    {
	fixMode = CegoBufferPool::SYNC;
	fileType = CegoFileHandler::TEMP;
    }
    else
    {
	throw Exception(EXLOC, Chain("Invalid object type to allocate page"));
    }

    _pDBMng->emptyFix(bp, tabSetId, fixMode, fileType, _pLockHandle, doAppend);
}

unsigned CegoObjectManager::getPageCount(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type)
{
    CegoBufferPage bp;
    unsigned long long lockId = 0;
	    
    try
    {
	unsigned pageCount=0;
	bool notFound = true;

	CegoBufferPool::FixMode lockMode;
	if ( type == CegoObject::SYSTEM )
	{
	    lockMode = CegoBufferPool::PERSISTENT; 
	}
	else
	{
	    lockMode = CegoBufferPool::SYNC;
	}
		
	PageIdType pageOffset;	    
		
	if ( type == CegoObject::RBSEG )
	{		      
	    pageOffset = _pDBMng->getTempPageOffset(tabSetId);	
	}
	else
	{
	    pageOffset = _pDBMng->getSysPageOffset(tabSetId);
	}

	PageIdType lowPage;
	PageIdType highPage;

	getHashPageId(objName, type, lowPage, highPage);
	
	for ( PageIdType hashPage = lowPage; hashPage < highPage ; hashPage++)
	{ 	    	    
	    PageIdType pageId = pageOffset + hashPage;
	
	    bool lastPage = false;
	    
	    while ( ! lastPage && notFound )
	    {		
		_pDBMng->bufferFix(bp, tabSetId, pageId, lockMode, _pLockHandle);
		
		lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::READ);	
		
		char* pE = (char*)bp.getFirstEntry();
		
		while (pE && notFound )
		{		    
		    CegoObject obj;
		    
		    unsigned size;
		    obj.decodeBase(pE, size);   

		    bool typeMatch =  
			( type == CegoObject::AVLTREE && ( obj.getType() == CegoObject::AVLTREE
							 || obj.getType() == CegoObject::PAVLTREE
							 || obj.getType() == CegoObject::UAVLTREE )) ||
			( type == CegoObject::BTREE && ( obj.getType() == CegoObject::BTREE
							 || obj.getType() == CegoObject::PBTREE
							 || obj.getType() == CegoObject::UBTREE ));
		    		   
		    if ( ! typeMatch )
			typeMatch = obj.getType() == type;
		    
		    if ( typeMatch && objName == obj.getName() )
		    {
			if ( type == CegoObject::FKEY )
			{
			    pageCount=0;
			}
			else if ( type == CegoObject::BTREE 
				  || type == CegoObject::PBTREE 
				  || type == CegoObject::UBTREE  )
			{
			    CegoBTreeObject bto;
			    
			    bto.decode(pE);   
			    
			    _pLockHandle->unlockSysPage(lockId);
			    lockId = 0;

			    notFound = false;
			    
			    pageId = bto.getDataPageId();	       			
			   
			    CegoBTreeManager btreeMng(this, &bto);

			    if ( pageId == 0 )
			    {
				pageCount=0;
			    }
			    else
			    {
				pageCount = btreeMng.getNumPages();
			    }				    
			}
			else
			{
			    CegoTableObject to;
			    
			    to.decode(pE);   
			    
			    _pLockHandle->unlockSysPage(lockId);
			    lockId = 0;

			    notFound = false;
			    
			    pageId = to.getDataPageId();	       			
			    
			    pageCount = countObjectPages(tabSetId, pageId);
			}
		    }
		    if ( notFound ) 
			pE = (char*)bp.getNextEntry();
		}
		
		pageId = bp.getNextPageId();
		
		if (notFound)
		{
		    _pLockHandle->unlockSysPage(lockId);
		    lockId = 0;
		}
	    	
		_pDBMng->bufferUnfix(bp, false, _pLockHandle);
		
		if ( pageId == 0 )
		{
		    lastPage = true;
		}    
	    }
	}
	
	if ( notFound ) 
	{
	    Chain msg = Chain("Object ") +  objName + Chain(" not found");
	    throw Exception(EXLOC, msg);
	}
	
	return pageCount;
    }
    catch ( Exception e )
    {
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);

	throw Exception(EXLOC, Chain("Cannot get page count"), e);
    }
}

void CegoObjectManager::getHashPageId(const Chain& objName, const CegoObject::ObjectType objType, PageIdType& lowPageId, PageIdType& highPageId)
{
    if ( objType == CegoObject::AVLTREE 
	 || objType == CegoObject::PAVLTREE 
	 || objType == CegoObject::UAVLTREE 
	 || objType == CegoObject::BTREE 
	 || objType == CegoObject::PBTREE 
	 || objType == CegoObject::UBTREE 
	 || objType == CegoObject::FKEY 
	 || objType == CegoObject::CHECK )
    { 
	lowPageId = 0;
	highPageId = TABMNG_HASHSIZE;
    }
    else
    {
	lowPageId = objName.getHashPos(TABMNG_HASHSIZE);
	highPageId = lowPageId + 1;    
    }
}

void CegoObjectManager::createObject(const CegoDecodableObject& obj, PageIdType& pageId)
{	
    CegoBufferPage bp;
    unsigned long long lockId = 0;
    
    try
    {
	_pDBMng->bufferFix(bp, obj.getTabSetId(), pageId, CegoBufferPool::PERSISTENT, _pLockHandle);

	bool created = false;
	
	while ( ! created )
	{
	    char *buf;
	    
	    lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::WRITE);
	    
	    buf = (char*)bp.newEntry(obj.getEntrySize());
	    
	    if ( buf )
	    {
		_pLockHandle->unlockSysPage(lockId); 
		lockId = 0;
		
		obj.encode(buf);
		
		_pDBMng->bufferUnfix(bp, true, _pLockHandle);
		
		created = true;		
	    }
	    else
	    {
		pageId = bp.getNextPageId();
		
		CegoBufferPage nbp;

		bool isDirty=false;
		
		if ( pageId == 0)
		{	 	 
		    getNewFilePage(nbp, obj.getTabSetId(), CegoObject::SYSTEM);
		    bp.setNextPageId(nbp.getPageId());
		    isDirty=true;
		}
		else
		{			
		    _pDBMng->bufferFix(nbp, obj.getTabSetId(), pageId, CegoBufferPool::SYNC, _pLockHandle);
		}
		
		_pLockHandle->unlockSysPage(lockId);	    
		lockId = 0;
		
		_pDBMng->bufferUnfix(bp, isDirty, _pLockHandle);
		
		bp = nbp;
	    }
	}
    }
    catch ( Exception e )
    {
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);

	throw Exception(EXLOC, Chain("Cannot create object"), e);
    }
}

void CegoObjectManager::alterObject(unsigned tabSetId, const Chain& objName, CegoObject::ObjectType type, CegoDecodableObject& obj)
{
    unsigned long long lockId = 0;
    unsigned long long altLockId = 0;
    CegoBufferPage bp;    
    CegoBufferPage altPage;

    _pDBMng->checkTableSetRunState(tabSetId);
	
    try
    {	
	CegoBufferPool::FixMode lockMode = CegoBufferPool::SYNC;

	if ( type == CegoObject::SYSTEM )
	{
	    lockMode = CegoBufferPool::PERSISTENT; 
	}

	PageIdType pageOffset;	    
	
	if ( type == CegoObject::RBSEG )
	{		      
	    pageOffset = _pDBMng->getTempPageOffset(tabSetId);	
	}
	else
	{
	    pageOffset = _pDBMng->getSysPageOffset(tabSetId);
	}
	    
	PageIdType lowPage;
	PageIdType highPage; 

	getHashPageId(objName, obj.getType(), lowPage, highPage);
	       	
	for ( PageIdType hashPage = lowPage; hashPage < highPage ; hashPage++)
	{ 	    
	    PageIdType pageId = pageOffset + hashPage;
       	    
	    bool lastPage = false;
	    
	    while ( ! lastPage )
	    {
		_pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::PERSISTENT, _pLockHandle);
				
		lockId = _pLockHandle->lockSysPage(pageId, CegoLockHandler::WRITE);
		
		char* pE = (char*)bp.getFirstEntry();
		
		while ( pE )
		{	    
		    CegoObject compObj;
		    unsigned entrySize;
		    
		    compObj.decodeBase(pE, entrySize);   
		    
		    if ((Chain)compObj.getName() == objName && compObj.getType() == obj.getType() && tabSetId == compObj.getTabSetId())
		    {
			// free old entry
			bp.freeEntry(pE);	       
		    
			_pLockHandle->unlockSysPage(lockId);
			lockId = 0;

			_pDBMng->bufferUnfix(bp, true, _pLockHandle);
						    
			// make new entry here
			
			PageIdType altPageId = pageOffset + obj.getName().getHashPos(TABMNG_HASHSIZE);
			
			bool created = false;
						
			_pDBMng->bufferFix(altPage, tabSetId, altPageId, lockMode, _pLockHandle);
			
			while ( ! created )
			{
			    char *buf;
			    
			    altLockId = _pLockHandle->lockSysPage(altPageId, CegoLockHandler::WRITE);
			    
			    buf = (char*)altPage.newEntry(obj.getEntrySize());
			    
			    if ( buf )
			    {			    
				obj.encode(buf);			    			    
				_pLockHandle->unlockSysPage(altLockId);
				altLockId = 0;

				_pDBMng->bufferUnfix(altPage, true, _pLockHandle);
				return;			    
			    }
			    else
			    {
				altPageId = altPage.getNextPageId();
				
				CegoBufferPage nbp;
								
				if ( altPageId == 0 )
				{
				    getNewFilePage(nbp, tabSetId, CegoObject::SYSTEM);
				    altPage.setNextPageId(nbp.getPageId());
				}
				else
				{
				    _pDBMng->bufferFix(nbp, tabSetId, altPageId, lockMode, _pLockHandle);
				}
				
				_pLockHandle->unlockSysPage(altLockId);
				altLockId = 0;

				_pDBMng->bufferUnfix(altPage, true, _pLockHandle);
				
				altPage = nbp;
			    }
			}			
		    }
		    pE = (char*)bp.getNextEntry();
		}
		
		pageId = bp.getNextPageId();
		
		_pLockHandle->unlockSysPage(lockId);	    
		lockId = 0;

		_pDBMng->bufferUnfix(bp, false, _pLockHandle);		
		
		if ( pageId == 0 )
		{
		    lastPage = true;
		}	    
	    }	
	}
	
	Chain msg = Chain("Object ") +  objName + Chain(" not found");
	throw Exception(EXLOC, msg);
    }
    catch ( Exception e )
    {
	if ( bp.isFixed() )
	    _pDBMng->bufferUnfix(bp, false, _pLockHandle);

	if ( altPage.isFixed() )
	    _pDBMng->bufferUnfix(altPage, false, _pLockHandle);
	
	if ( lockId )
	    _pLockHandle->unlockSysPage(lockId);

	if ( altLockId )
	    _pLockHandle->unlockSysPage(altLockId);	    

	throw Exception(EXLOC, Chain("Cannot alter object"), e);
    }
}
