/****************************************************************************

  module      : vbd91.cpp

  -------------------------------------------------------------------------

  responsible : FerdiF

  special area: interface for the pascal routines to the OMSGarbageCollection
  description : description ...


  version     : 7.4.4.1
  last changed: 2003-01-22  11:32
  see also    : example.html ...

  -------------------------------------------------------------------------

  copyright:    (c) 1998-2004 SAP AG



    ========== licence begin  GPL
    Copyright (c) 1998-2005 SAP AG

    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
    of the License, 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; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end


*****************************************************************************/


/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/
#include "hbd91.h"

#include "gsp03.h" 
#include "gsp03_3.h"
#include "gbd05.h"
#include "gbd900.h"
#include "gbd910.h" 
#include "gbd920.h"
#include "gbd930.h"

#include "hbd01.h"
#include "hbd06.h"
#include "hbd17.h"
#include "hbd22.h"
#include "hbd90.h"
#include "hbd92.h"
#include "hbd93.h"
#include "hbd30.h"
#include "hbd30_1.h"
#include "hbd911.h"
#include "hgg01_1.h"
#include "hgg01_3.h"
#include "hgg11.h"  // g11ParseVersion
#include "heo55k.h" // vbegexcl/vendexcl

#include "RunTime/MemoryManagement/RTEMem_Allocator.hpp" 
#include "SAPDBCommon/MemoryManagement/SAPDBMem_NewDestroy.hpp"
#include "Trace/Trace_Entry.hpp"
#include "KernelCommon/Kernel_OpMsg.hpp"  
#include "KernelCommon/Kernel_IAdminInfo.hpp"  
#include "RunTime/Configuration/RTEConf_ParameterAccessKernelInterface.hpp"
#include "SAPDBCommon/ErrorsAndMessages/SAPDBErr_MessageList.hpp"

#if COMPILEMODE_MEO00 >= SLOW_MEO00
#include "hta99.h"
#include "hta01.h"
#endif

#include "gsp100.h"

/*===========================================================================*
 *  DEFINES                                                                  *
 *===========================================================================*/

#define RESTART true
#define WITHIN_GC_REGION true       /*PTS 1115596*/

#ifndef TRUE
 #define TRUE 1
#endif

/*===========================================================================*
 *  MACROS                                                                   *
 *===========================================================================*/

#if COMPILEMODE_MSP00 >= QUICK_MEO00 
# define    ABORT_OR_MESSAGE(MESSAGE, PARAMETER) \
        g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, MESSAGE, PARAMETER)
#else
# define    ABORT_OR_MESSAGE(MESSAGE, PARAMETER) \
        g01abort (csp3_bd_msg, csp3_n_obj, MESSAGE, PARAMETER)
#endif

/*===========================================================================*
 *  LOCAL CLASSES, STRUCTURES, TYPES, UNIONS ...                             *
 *===========================================================================*/

class cbd900_SubRootPageData_migrate_pts115760
{
public:
    tbd900_PageCounter     spdAllPageCnt_bd900;        // # all pages in chain starting at the subroot 
    tbd900_PageCounter     spdFiller0;                 // # spdEmptyPageCnt_bd900 empty pages       PTS 115760
    tbd900_PageCounter     spdFreePageCnt_bd900;       // # pages with free objetcs 
    tsp00_Int4             spdFiller1;                 // spdEmptyPageLimit_bd900;    PTS 115760 FF 2002-05-24
	tsp00_Int4             spdMaxPageSeqNo_bd900;      // max page sequence number
	tsp00_Int4             spdAllObjCnt_bd900;         // dirty counter of all objects which are not free  
};

/*===========================================================================*
 *  LOCAL FUNCTION DECLARATION                                               *
 *===========================================================================*/

/*===========================================================================*
 *  EXTERNAL VARIABLES                                                       *
 *===========================================================================*/

extern cbd900_ObjFileDir      bd90ObjFileDir;
extern cbd900_ContObjFileDir  bd93ContObjFileDir;

/*===========================================================================*
 *  LOCAL VARIABLES                                                          *
 *===========================================================================*/

/* with the change to the lock protocol which locks the subroot first before */
/* doing any change to the free-/empty- chaining, no corrupted chain is      */
/* acceptable anymore !                                                      */
/* migration ensures that chaining is correct !        PTS 1113635 FF        */
bool bd91MigrateToNewLockprotocol = false;

/* migrate to double-linked-free-list                  PTS 1115760 FF        */
bool bd91MigrateToDoubleLinkedFreelist = false;

cbd930_GarbCollController bd91GarbCollController;

GC_IGCController& 
GC_IGCController::Instance()
{
    return * STATIC_CAST(GC_IGCController*,&bd91GarbCollController);
};

/*===========================================================================*
 *  LOCAL FUNCTIONS (CODE)                                                   *
 *===========================================================================*/

/* PTS 1113635 FF */
static void
bd91_MigrateFreeChainsOfOneFile (tgg00_TransContext  &Trans,
                                 tgg00_FileId        &ObjFileId,
                                 cbd900_ObjFileInfo  &ObjFileInfo)
{
    tgg00_BasisError &TrError = Trans.trError_gg00;
    cbd05_Current   Current  (Trans, m_update, ObjFileId);   
    
    if (g01vtrace.vtrAll_gg00 || g01vtrace.vtrBdObject_gg00)
    {
        tgg12_OmsFilenameTrace TrLineIn;
        TrLineIn.ofnTrType_gg12.becomes(otFilename_egg12);
        TrLineIn.ofnTrType2_gg12.becomes(ot2Nil_egg12);
        TrLineIn.ofnFileName_gg12 = ObjFileId.fileName_gg00();
        
        Trace_CommonEntry( Trans, tgg00_Debug::fromConst(bd), tgg00_VtraceType::fromConst(b91repair), 
            REINTERPRET_CAST( tsp00_BytePtr, &TrLineIn ), sizeof (TrLineIn) );
    };
    
    for (tsp00_Int4 iChain = 0; iChain<ObjFileInfo.GetChainCount(); ++iChain)
    {    
        cbd900_ObjChainInfo & ChainInfo = ObjFileInfo[iChain];
        
        tbd900_PageCounter EmptyPageCnt = 0;
        tbd900_PageCounter FreePageCnt  = 0;
        tbd900_PageCounter AllPageCnt   = 0;
        tsp00_Int4         AllObjCnt    = 0;
        
        const tsp00_PageNo &SubRoot = ChainInfo.ociSubRoot_bd900;
        if (NIL_PAGE_NO_GG00 != SubRoot)
        {
            cbd910_SubRootNode  NptrsSubRoot (Current, SubRoot, nr_for_update);
            if (e_ok != TrError) return;
            
            if ( bd91MigrateToNewLockprotocol )
            {
                /* count pages */
                AllPageCnt ++ ;
                AllObjCnt  +=  (NptrsSubRoot.np_ptr()->nd_max_obj_cnt() - 
                    NptrsSubRoot.np_ptr()->nd_free_obj_cnt());
                if (NptrsSubRoot.np_ptr()->nd_free_obj_cnt() > 0) FreePageCnt ++;
                
                tsp00_PageNo RightPageNo = NptrsSubRoot.np_ptr()->nd_right();
                
                while (RightPageNo != NIL_PAGE_NO_GG00)
                {
                    cbd910_ObjDataNode     ObjDataNodeForRead (Current, RightPageNo, nr_for_read);
                    if (e_ok != TrError) 
                    {
                        {
                            Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
                            opErrMsg << "bd91_MigrateFreeChainsOfOneFile" << " - invalid right right chain pno "
                                << RightPageNo << " subroot " << NptrsSubRoot.np_ptr()->nd_id();
                        }
                        g01abort (csp3_bd_msg, csp3_n_obj, "BD91MigFC:rightchain Err", TrError);
                    }
                    
                    RightPageNo = ObjDataNodeForRead.np_ptr()->nd_right();
                    
                    /* count pages */
                    AllPageCnt ++;
                    AllObjCnt  +=  (ObjDataNodeForRead.np_ptr()->nd_max_obj_cnt() - 
                        ObjDataNodeForRead.np_ptr()->nd_free_obj_cnt());
                    if (ObjDataNodeForRead.np_ptr()->nd_free_obj_cnt() > 0)	FreePageCnt ++;
                    
                    /* update free chain and free page counter on sub root page*/
                    if (ObjDataNodeForRead.bd910PageMustBeInsertedIntoFreeChain())
                    {
                        tsp00_PageNo PageNo = ObjDataNodeForRead.np_ptr()->nd_id();
                        ObjDataNodeForRead.bd910ReleasePage();
                        cbd910_ObjDataNode   ObjDataNodeForWrite (Current, PageNo, nr_for_update);
                        if (e_ok != TrError) 
                        {
                            {
                                Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
                                opErrMsg << "bd91_MigrateFreeChainsOfOneFile" << " - write access to page "
                                    << PageNo << " subroot " << NptrsSubRoot.np_ptr()->nd_id();
                            }
                            g01abort (csp3_bd_msg, csp3_n_obj, "BD91MigFC:rightchain Err", TrError);
                        }
                        
                        /* a destroyed free chain can occur only if there   */
                        /* was an updater active during the save point      */
                        if (ObjDataNodeForWrite.np_ptr()->nd_num_chain_updater_mig() > 0)
                            ObjDataNodeForWrite.np_ptr()->nd_num_chain_updater_mig() = 0;
                        else
                        {
                            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                                "BD91RepChain:NoUpdActive", PageNo);
                        }
                        
                        if (ObjDataNodeForWrite.bd910PageMustBeInsertedIntoFreeChain()) 
                            NptrsSubRoot.bd910InsertPageIntoFreeChain (ObjDataNodeForWrite);
                    }
                    else
                    {
                        /* if the page is ok there must be no updater active */
                        if (ObjDataNodeForRead.np_ptr()->nd_num_chain_updater_mig() != 0)
                        {
                            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                                "BD91RepChain:Upd Active ", ObjDataNodeForRead.np_ptr()->nd_id());
                        }
                    }
                }
            }
            
            /* get handler for the data stored on the sub root page body */
            cbd900_RootPageInfo     RootPageInfo( NptrsSubRoot );
            cbd900_SubRootPageInfo  SubRootPageInfo (NptrsSubRoot);
            
            if ( bd91MigrateToDoubleLinkedFreelist
                 && 
                 MAX_LOCK_REQUEST_SEQ_NO_BD900 !=
                 bd900GetPageSeqNo(NptrsSubRoot.np_ptr()->ndLockRequestSeqNoHigh_bd00(),
                                   NptrsSubRoot.np_ptr()->ndLockRequestSeqNoLow_bd00()) )
            {
                cbd910_ObjDataNode   NptrsPage (Current, nr_for_update);
                cbd900_SubRootPageData_migrate_pts115760* oldSubRootPageData = 
                    REINTERPRET_CAST(cbd900_SubRootPageData_migrate_pts115760* ,&SubRootPageInfo.bd900AllPageCnt());
                SubRootPageInfo.bd900AllObjCnt() = oldSubRootPageData->spdAllObjCnt_bd900;
                SubRootPageInfo.bd900SetMaxPageSeqNo(oldSubRootPageData->spdMaxPageSeqNo_bd900);
                
                NptrsSubRoot.np_ptr()->nd_prev_free() = NIL_PAGE_NO_GG00;
                if (NptrsSubRoot.np_ptr()->nd_free_obj_cnt() > 0)
                    NptrsSubRoot.np_ptr()->nd_in_free_chain() = true;
                bd900SetPageSeqNo(MAX_LOCK_REQUEST_SEQ_NO_BD900, 
                    NptrsSubRoot.np_ptr()->ndLockRequestSeqNoHigh_bd00(), 
                    NptrsSubRoot.np_ptr()->ndLockRequestSeqNoLow_bd00());
                
                tsp00_PageNo nextPageNo = NptrsSubRoot.np_ptr()->nd_next_free();
                tsp00_PageNo prevPageNo = NptrsSubRoot.np_ptr()->nd_id();               

                /* empty pages remain within free-chain, because routines */
                /* to remove page from free-chain and all-chain won't     */
                /* work correctly yet                                     */
                while ((NIL_PAGE_NO_GG00 != nextPageNo) 
                    && (TrError == e_ok)
                    && (!RootPageInfo.bd900FileIsDeleted()))
                {
                    NptrsPage.bd910AssignToPage(nextPageNo);
                    if (e_ok != TrError) 
                    {
                        {
                            Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
                            opErrMsg << "bd91_MigrateFreeChainsOfOneFile" << " - write access to page in freechain "
                                << nextPageNo << " subroot " << NptrsSubRoot.np_ptr()->nd_id();
                        }
                        g01abort (csp3_bd_msg, csp3_n_obj, "BD91MigFC:rightchain Err", TrError);
                    }
                    if (NptrsPage.np_ptr()->nd_free_obj_cnt() > 0)
                        NptrsPage.np_ptr()->nd_in_free_chain() = true;
                    NptrsPage.np_ptr()->nd_space0() = false; /* initialize field used before for empty flag */
                    NptrsPage.np_ptr()->nd_prev_free() = prevPageNo;
                    nextPageNo = NptrsPage.np_ptr()->nd_next_free();
                    prevPageNo = NptrsPage.np_ptr()->nd_id();   
                    NptrsPage.bd910ReleasePage();
                }
                SubRootPageInfo.bd900Filler0() = false;
                ChainInfo.ociFiller0_bd900     = false;
                ChainInfo.ociFiller1_bd900     = false;
            }
            
            if ( TrError == e_ok && bd91MigrateToNewLockprotocol )
            {
                /* compare counted with stored number of pages and objects */
                SAPDBERR_ASSERT_STATE (SubRootPageInfo.bd900AllPageCnt()   == AllPageCnt);
                SAPDBERR_ASSERT_STATE (SubRootPageInfo.bd900FreePageCnt()  == FreePageCnt);
                
                /* update counter of all objects on the subroot and in the chaininfo */
                SubRootPageInfo.bd900AllObjCnt() = AllObjCnt;
                ChainInfo.SetAllObjCnt(AllObjCnt);
            }
        }
  }
  
  if (g01vtrace.vtrAll_gg00 || g01vtrace.vtrBdObject_gg00 || (TrError != e_ok)) 
  {
      tgg12_OmsErrorTrace TrLineOut;
      
      TrLineOut.oerrTrType_gg12.becomes  ( otError_egg12);
      TrLineOut.oerrTrType2_gg12.becomes ( ot2Nil_egg12);
      TrLineOut.oerrRoot_gg12            = ObjFileId.fileRoot_gg00();
      TrLineOut.oerrObjFileNo_gg12       = ObjFileId.fileObjFileNo_gg00();
      TrLineOut.oerrError_gg12           = TrError;
      
      Trace_CommonEntry( Trans, tgg00_Debug::fromConst(bd), tgg00_VtraceType::fromConst(b91repair), 
          REINTERPRET_CAST( tsp00_BytePtr, &TrLineOut ), sizeof (TrLineOut) );
  }
}

/*---------------------------------------------------------------------------*/

static void
bd91_RepairRootPage (tbd_current_tree        &Current,
                     cbd900_RootPageInfo     &RootPageInfo, 
                     tgg00_ObjFileNo          ObjFileNo, 
                     tsp00_Int4               ContFileNo,
                     cbd900_ContObjFileInfo  &ContObjFileInfo)
{
    tbd_fileinfo         FileInfo;
    tgg00_BasisError & TrError = Current.curr_trans->trError_gg00;
    ContObjFileInfo.bd900BuildFileId(ObjFileNo, ContFileNo, Current.curr_tree_id);
    b17state_fdir (Current.curr_tree_id.fileName_gg00(), FileInfo,
        Current.curr_tree_id.fileType_gg00().includes (ftsShared_egg00), *Current.curr_trans);
    
    if (e_file_not_found == TrError)
        TrError = e_ok;
    else if (e_ok == TrError)
    {
        tsp00_PageNo ContFileRoot = FileInfo.fi_root; 
        RootPageInfo.bd900ContRoot (ContFileNo) = ContFileRoot;
        Current.curr_tree_id.fileRoot_gg00()     = ContFileRoot;
        cbd910_RootNode  NptrsContRoot (Current, ContFileRoot, nr_for_read);
        if ((e_ok != TrError)                                                      || 
            (NptrsContRoot.np_ptr()->nd_root() != NptrsContRoot.np_ptr()->nd_id()) ||
            (NptrsContRoot.np_ptr()->nd_obj_file_no() != ObjFileNo))
        {
            Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
            opErrMsg << "bd91_RepairRootPage" << " page is no cont-container root! ObjFileNo:"
                << ObjFileNo << " ContFileNo:" << ContFileNo
                << " ContFileRoot:" << ContFileRoot << " TrError:" << TrError;
            return;
        }
        
        SAPDBERR_ASSERT_STATE (ContObjFileInfo[ContFileNo].GetObjBodySize() ==
            tsp00_Int4 (NptrsContRoot.np_ptr()->nd_obj_frame_len() - sizeof (tbd900_ContObjHeader)));
        
        bd91AddFileToContObjFileDir (*Current.curr_trans, Current.curr_tree_id, NptrsContRoot);
    }
    else
    {
        b06write_filename_and_root (Current.curr_tree_id);
        g01abort (csp3_bd_msg, csp3_n_obj, 
            "BD91RepRoot:ErrorInContE", Current.curr_trans->trError_gg00);
    }
}

/*---------------------------------------------------------------------------*/

static bool
bd91_MigrateFileDirectory( tgg00_TransContext &Trans )
{
    const bool           SHARED_FILE    = true;
    const bool           INCLUDE_BLOBS  = true;
    bool                 bMigrationDone = false;
    tgg00_BasisError    &TrError        = Trans.trError_gg00;
    tbd_fileinfo         FileInfo;
    
    tgg00_FileId   ObjFileId  = b01niltree_id;
    ObjFileId.fileTfn_gg00().becomes( tfnObj_egg00 );
    
    while( e_ok == TrError )
    {
        b17succ_fdir( ObjFileId.fileName_gg00(), ObjFileId.fileName_gg00(), FileInfo,
            !SHARED_FILE, Trans, !INCLUDE_BLOBS );
        
        if( tfnObj_egg00 != ObjFileId.fileTfn_gg00() ) 
            break; // All FileDirectory entries inspected
        
        //if( PRIM_CONT_OBJ_FILE_NO_BD900 != ObjFileId.fileContObjFileNo_gg00())
        //    break; // FileDirectory already migrated!
        
        if( e_ok == TrError )
        {
            cbd05_Current   Current( Trans, m_select );

            b30fdir_to_treeid( FileInfo, ObjFileId );
            Current.curr_tree_id = ObjFileId;
            
            cbd910_RootNode  NptrsRoot( Current, ObjFileId.fileRoot_gg00(), nr_for_read );
            if( e_ok != TrError )
                break;

            cbd900_RootPageInfo         RootPageInfo( NptrsRoot );
            tsp00_Int4 NumObjKeyFiles = RootPageInfo.bd900NumObjKeyFiles();

            if(( 0 < NptrsRoot.np_ptr()->nd_obj_key_len()) && ( 0 == NumObjKeyFiles ))
            {
                // migrate FileName of keyed object (see CRS 1109486 AK 01/03/2001)
                
                NptrsRoot.bd910ReleasePage();
                {
                    cbd910_RootNode  UpdRoot( Current, ObjFileId.fileRoot_gg00(), nr_for_update );
                    if( e_ok != TrError )
                        break;
                    
                    cbd900_RootPageInfo            UpdRootPageInfo( UpdRoot );
                    UpdRootPageInfo.bd900NumObjKeyFiles() = 1;
                    UpdRoot.bd910ReleasePage();
                }
                b17del_fdir( ObjFileId.fileName_gg00(), FileInfo, !SHARED_FILE, Trans );
                if( e_ok != TrError)
                    break;
                tgg00_FileId   KeyedObjFileId = ObjFileId;
                KeyedObjFileId.fileNumObjKeyFiles_gg00() = 1; // Change counter with fdir entry
                b17add_fdir( KeyedObjFileId.fileName_gg00(), FileInfo, Trans );
                bMigrationDone = true;
                continue; // Keyed objects are fixed sized
            }

            if( pt2VarObject_egg00 == NptrsRoot.np_ptr()->nd_pt2() )
            {
                // migrate Cont-FileDirectory entry

                const tgg00_ObjFileNo   ObjFileNo = ObjFileId.fileObjFileNo_gg00();
                
                for( tsp00_Int4 iContFileNo=1; iContFileNo <= RootPageInfo.bd900NumContFiles(); ++iContFileNo )
                {
                    const tsp00_PageNo ContFileRoot = RootPageInfo.bd900ContRoot( iContFileNo );
                    if( NIL_PAGE_NO_GG00 != ContFileRoot )
                    {
                        tgg00_FileId    ContObjFileId = ObjFileId;
                        tbd_fileinfo    ContFileInfo  = FileInfo;
                        
                        ContObjFileId.fileContObjFileNo_gg00() = iContFileNo;
                        ContObjFileId.fileTfn_gg00().becomes( tfnContObj_egg00 );
                        ContObjFileId.fileRoot_gg00() = ContFileRoot;
                        
                        b17state_fdir( ContObjFileId.fileName_gg00(), ContFileInfo, !SHARED_FILE, Trans );
                        
                        if( e_file_not_found == TrError )
                        {
                            TrError              = e_ok;
                            ContFileInfo         = FileInfo;
                            ContFileInfo.fi_root = ContFileRoot;

                            b17add_fdir( ContObjFileId.fileName_gg00(), ContFileInfo, Trans );
                            bMigrationDone = true;
                        }
                    }
                }
            }
            // TODO 
            NptrsRoot.bd910ReleasePage();
        }
    }
    if( e_file_not_found == TrError ) 
        TrError = e_ok;
    return( bMigrationDone );
}

/*===========================================================================*
 *  GLOBAL FUNCTIONS (CODE)                                                  *
 *===========================================================================*/

externC void
bd91TransEnd(tgg00_TransContext &Trans,
             pasbool             commit)
{
    bd90TransEnd(Trans);
};


/*---------------------------------------------------------------------------*/

externPascal void 
bd91InitRWRecreateIndex(void)
{
    ROUTINE_DBG_MEO00 ("bd91InitRWRecreateIndex");
    
   bd911InitRWRecreateIndex();
}

/*---------------------------------------------------------------------------*/

externC void
bd91CheckIndex (tgg00_TransContext   &Trans,
                tsp00_Uint4           ObjFileNo )
{
    ROUTINE_DBG_MEO00 ("bd91CheckIndex");
    
    bd911CheckIndex(Trans, ObjFileNo);
};

/*---------------------------------------------------------------------------*/

externC void
bd91RecreateIndex (tgg00_TransContext   &Trans,
                   tsp00_Uint4           ObjFileNo )
{
    ROUTINE_DBG_MEO00 ("bd91RecreateIndex");
    
    bd911RecreateIndex(Trans, ObjFileNo);
};
 
externCpp cbd900_ObjFileInfo*
bd91AddFileToObjFileDir (tgg00_TransContext   &Trans,
                         tgg00_FileId         &FileId,
                         cbd910_RootNode      &NptrsRoot) 
{
    ROUTINE_DBG_MEO00 ("bd91AddFileToObjFileDir");

    /* PTS 1106716 Alexander Kley 01/06/2000                 */
    
    tbd_nodeptr            &pRoot            = NptrsRoot.np_ptr();
    const tgg00_ObjFileNo   ObjFileNo        = FileId.fileObjFileNo_gg00();
    const bool              bFileIsForVarObj = (pt2VarObject_egg00 == pRoot->nd_pt2());
    const int               ObjFrameLen      = pRoot->nd_obj_frame_len();
    int                     MaxObjBodySize;
    int                     MaxObjPerPageCnt;
    tgg00_BasisError       &TrError          = Trans.trError_gg00;
    
    /* determine maximum number of objects which can be stored on this page */
    const int AlignedObjFrameLen = BD92ALIGN_OBJ_FRAME(ObjFrameLen);
    if  (FULLCOVERING_BD00 >= ObjFrameLen)
        MaxObjPerPageCnt = 1 + ((FULLCOVERING_BD00 - ObjFrameLen)/AlignedObjFrameLen);
    else
    {
        g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
            "BD91AddFile: TooLongObj ", ObjFrameLen);
        Trans.trError_gg00 = e_too_long_objects;
        return NULL;
    }
    
    /* register object file at the global structure bd90ObjFileDir */
    if (bFileIsForVarObj)
        MaxObjBodySize = ObjFrameLen - sizeof (tgg92_ObjHeader) - sizeof (tbd900_VarObjBodyHeader);
    else
        MaxObjBodySize = ObjFrameLen - sizeof (tgg92_ObjHeader);
    
    /* create entry for the object file directory */
    cbd05_Current Current (Trans, m_select, FileId);    
    cbd900_ObjFileInfo ObjFileInfo(Current, NptrsRoot, MaxObjBodySize, MaxObjPerPageCnt);
    cbd900_ObjFileInfo *pObjFileInfo = bd90ObjFileDir.bd920InsItem (Trans.trTaskId_gg00, ObjFileNo, &ObjFileInfo, TrError);
       
    /* check if the item was successfully inserted. If the key existed */
    /* already or there are no more entrie possible NULL is returned   */
    if (e_ok != TrError)
    {
        if (e_duplicate_hash_key == TrError)
        {
            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                "BD91AddFile: Dupl FileNo", ObjFileNo);
            TrError= e_duplicate_filename;
        }
        else if (e_hash_memory_exceeded == TrError)
        {
            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                "BD91AddFile:TooManyItems", ObjFileNo);
        }
        else
        {
            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                "BD91AddFile: Error      ", TrError);
        }
        return NULL;
    }
    
    /* create an empty entry in the continuation file directory for the continuation files */
    if  (bFileIsForVarObj)
    {
//        cbd900_ContObjFileInfo   *pContObjFileInfo = new (RTEMem_Allocator::Instance()) cbd900_ContObjFileInfo;
        cbd900_ContObjFileInfo    ContObjFileInfo;
        cbd900_ContObjFileInfo   *pContObjFileInfo;
                
        tsp00_Int4              NextContObjBodyLen = MaxObjBodySize;
        while (bd93NextContObjBodyLen (NextContObjBodyLen)  && 
            (ContObjFileInfo.cfiNumContFiles_bd900 <= MAX_NUM_CONT_OBJ_FILES_BD900))
        {
            ++ContObjFileInfo.cfiNumContFiles_bd900;
            ContObjFileInfo.operator[](ContObjFileInfo.cfiNumContFiles_bd900).SetObjBodySize(NextContObjBodyLen);
        }               
        
        pContObjFileInfo = bd93ContObjFileDir.bd920InsItem (Trans.trTaskId_gg00, ObjFileNo, &ContObjFileInfo, TrError);
        if (e_ok != TrError) 
        {
            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                "BD91AddFile:InsertFailed", TrError);
            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                "BD91AddFile:InsertFailed", ObjFileNo);
        }
        
        /* check if there really exists an entry in the continuation file directory */
#       if COMPILEMODE_MEO00 >= QUICK_MEO00 
        if (bd93ContObjFileDir[ObjFileNo].cfiNumContFiles_bd900 <1)
            g01abort (csp3_bd_msg, csp3_n_obj, "BD91AddFile: No Entry   ", ObjFileNo);
#       endif
    }
    return pObjFileInfo;    
};

/*---------------------------------------------------------------------------*/

externCpp cbd900_ObjFileInfo*
bd91AddFileToContObjFileDir (tgg00_TransContext   &Trans,
                             tgg00_FileId         &FileId,
                             cbd910_RootNode      &NptrsRoot)
{

    ROUTINE_DBG_MEO00 ("bd91AddFileToContObjFileDir");

    /* register object file at the global structure bd900ContObjFileDir */
    
    const tgg00_ObjFileNo   ObjFileNo     = FileId.fileObjFileNo_gg00();
    const tsp00_Int4        ContObjFileNo = FileId.fileContObjFileNo_gg00();
    cbd900_ObjFileInfo     &ObjFileInfo   = bd93ContObjFileDir[ObjFileNo][ContObjFileNo];
    
    vbegexcl (Trans.trTaskId_gg00, g08garbage); 
    if (!ObjFileInfo.bd900FileInfoIsEmpty())
        Trans.trError_gg00 = e_duplicate_filename;
    else
    {
        const int ObjFrameLen        = NptrsRoot.np_ptr()->nd_obj_frame_len();
        const int MaxObjBodySize     = ObjFrameLen - sizeof (tbd900_ContObjHeader);
        if (MaxObjBodySize != ObjFileInfo.GetObjBodySize())             
            g01abort (csp3_bd_msg, csp3_n_obj, "BD91AddCFi:WrongBodySize", NptrsRoot.np_ptr()->nd_id());
        const int AlignedObjFrameLen = BD92ALIGN_OBJ_FRAME(ObjFrameLen);
        const int MaxObjPerPageCnt   = 1 + ((FULLCOVERING_BD00 - ObjFrameLen)/AlignedObjFrameLen);
        cbd05_Current Current (Trans, m_select, FileId);
        ObjFileInfo.bd900SetFileInfo (Current, NptrsRoot, MaxObjBodySize, MaxObjPerPageCnt);
    }
    vendexcl (Trans.trTaskId_gg00, g08garbage); 

    return (&ObjFileInfo); 
}

/*---------------------------------------------------------------------------*/

externC void
bd91DumpGarbColl (tgg00_VfFileref     &HostFile,
                  tsp00_Int4            BufferSize,
                  tsp00_Page           &Buffer,
                  tsp00_Int4           &OutPno,
                  tsp00_Int4           &OutPos,
                  tsp00_VfReturn       &HostError,
                  tsp00_ErrText        &ErrText)
{
    ROUTINE_DBG_MEO00 ("bd91DumpGarbColl");

	if (g01is_livecache ()) 
		bd91GarbCollController.bd930DumpGCController (HostFile, BufferSize,  Buffer, OutPno,  OutPos, HostError, ErrText);
}

/*---------------------------------------------------------------------------*/

static tsp00_Int4 maxRetentionTime = -1;
externC tsp00_Int4 b91MaxRetentionTime() {
    if ( -1 ==  maxRetentionTime ) {
        RTEConf_Parameter::Integer  paramValue;
        SAPDBErr_MessageList        errMsg;
        if( ! RTEConf_ParameterAccess::Instance()->GetInteger(UTF8( "MAX_RETENTION_TIME" ), paramValue, errMsg))
             RTE_Crash( errMsg );
        maxRetentionTime = static_cast<tsp00_Int4>(paramValue);
    }
    return maxRetentionTime;
};
 
/*---------------------------------------------------------------------------*/

static tsp00_Int4 minRetentionTime = -1;
externC tsp00_Int4 b91MinRetentionTime() {
    if ( -1 == minRetentionTime ) {
        RTEConf_Parameter::Integer  paramValue;
        SAPDBErr_MessageList        errMsg;
        if( ! RTEConf_ParameterAccess::Instance()->GetInteger(UTF8( "MIN_RETENTION_TIME" ), paramValue, errMsg))
            RTE_Crash( errMsg );
        minRetentionTime = static_cast<tsp00_Int4>(paramValue);
    }
    return minRetentionTime;
};

/*---------------------------------------------------------------------------*/
// PTS 1113452 FF 16-Jan-2002

externC void
bd91RemoveObjFilesMarkedForDelete (tgg00_TransContext &Trans)
{
  ROUTINE_DBG_MEO00 ("bd91RemoveObjFilesMarkedForDelete");
  
  /*  count number of GCs requested and activ to release unused pages */
  cbd900_ObjFileDirIter ObjFileIter (bd90ObjFileDir);
  
  /* PTS 1115596 FF 2002-05-08                                            */ 
  /* prevent entries to be deleted within the ObjFileDir during iteration */   
  vbegexcl (Trans.trTaskId_gg00, g08garbage); 

  for  (ObjFileIter.bd920Begin(); !ObjFileIter.bd920End() ; ++ObjFileIter) 
  {           
    if (ObjFileIter()->ofiRelFileIsReq_bd900)
    {             
      /* FIRST mark continuation files, if exist, as deleted */
      if (cbd900_ObjFileInfo::omsVariableFile == ObjFileIter()->GetFileType())
      {
        cbd900_ContObjFileInfo & ContObjFileInfo = bd93ContObjFileDir[ObjFileIter.bd920Key()];                 
        for (int iContFileNo = 1; iContFileNo <=ContObjFileInfo.cfiNumContFiles_bd900; ++iContFileNo)
        {
          tsp00_PageNo ContObjFileRoot = ContObjFileInfo[iContFileNo].GetRootPage();
          if (NIL_PAGE_NO_GG00 != ContObjFileRoot)
              ContObjFileInfo[iContFileNo].ofiRelFileIsReq_bd900 = true;
        }
      }
      bd91GarbCollController.bd930StartGCToRemoveFile(Trans, *ObjFileIter(), WITHIN_GC_REGION);      
    }    
  }

  vendexcl (Trans.trTaskId_gg00, g08garbage); 
}

/*----------------- PTS 1115641 FF 25-Apr-2002 ------------------------------*/

externC void
bd91InfoContainerRoots (tgg00_TransContext       &Trans,
                        cbd900_ObjFileDirIter     **pObjFileIter,
                        cbd900_ContObjFileDirIter **pContObjFileIter,
                        tsp00_Addr                pStackarea,
                        tsp00_Int2                pStackareaLen,
                        tsp00_Int4                &ClassId,
                        tsp00_Int4                &Root,
                        tsp00_Int4                &ContainerSequelNo,
                        tsp00_Int2                &NumKeyPartitions,
                        tsp00_Bool                &VarContainer,
                        tsp00_Bool                &DeleteFlag,
                        tsp00_Int4                &MaxObjBodySize,
                        tsp00_Int4                &MaxObjPerPage,
                        tsp00_Int4                &MaxChains,
                        tsp00_Int2                &UnusedBytesPerPage) // PTS 1118335 FF 11-OCT-2002 
{
    if (pStackareaLen > (sizeof(cbd900_ObjFileDirIter) + sizeof(cbd900_ContObjFileDirIter)))
    {
        if ( NULL == *pObjFileIter ) 
        { 
            /* PTS 1118554 FF 2002-10-25 ( see also PTS 1115596 )                    */
            /* prevent entries to be deleted within the ObjFileDir during iteration  */
            vbegexcl (Trans.trTaskId_gg00, g08garbage); /* PTS 1118554 FF 2002-10-25 */
            *pObjFileIter = new(pStackarea) cbd900_ObjFileDirIter(bd90ObjFileDir);
            (*pObjFileIter)->bd920Begin();
            ClassId = 0;
        }
        
        if ( NULL == *pContObjFileIter ) {
            tsp00_Addr pStackarea2 = pStackarea + sizeof(cbd900_ObjFileDirIter);
            *pContObjFileIter = new(pStackarea2) cbd900_ContObjFileDirIter(bd93ContObjFileDir);
            (*pContObjFileIter)->bd920Begin();
        }
        
        if ( !(*pObjFileIter)->bd920End() && (NULL != *pObjFileIter) && (NULL != *pContObjFileIter))
        {
            ClassId           = (*pObjFileIter)->bd920Key();
            Root              = (**pObjFileIter)()->GetRootPage();
            ContainerSequelNo = 0;
            NumKeyPartitions  = (**pObjFileIter)()->GetKeyPartitionCount();
            VarContainer      = (cbd900_ObjFileInfo::omsVariableFile == (**pObjFileIter)()->GetFileType());
            DeleteFlag        = (**pObjFileIter)()->ofiDropFile_bd900;
            MaxObjBodySize    = (**pObjFileIter)()->GetObjBodySize();
            MaxObjPerPage     = (**pObjFileIter)()->GetObjPerPageCount();
            MaxChains         = (**pObjFileIter)()->GetChainCount();
            if ( VarContainer )
                UnusedBytesPerPage = -1;
            else
                UnusedBytesPerPage = FULLCOVERING_BD00 % BD92ALIGN_OBJ_FRAME(MaxObjBodySize+ sizeof (tgg92_ObjHeader));
            ++(**pObjFileIter);
        }
        else if ( !(*pContObjFileIter)->bd920End() )
        {
            ClassId = (*pContObjFileIter)->bd920Key();
            ContainerSequelNo++;
            
            /* skip continuation files which don't exist */
            while ((!(*pContObjFileIter)->bd920End()) &&
                ((*(**pContObjFileIter)())[ContainerSequelNo].GetRootPage() == NIL_PAGE_NO_GG00))
            {
                ContainerSequelNo++;
                if ( ContainerSequelNo > (**pContObjFileIter)()->cfiNumContFiles_bd900)
                {
                    ContainerSequelNo = 1;
                    ++(**pContObjFileIter);   
                }            
            }
            
            if ( (!(*pContObjFileIter)->bd920End()) && 
                (ContainerSequelNo > (**pContObjFileIter)()->cfiNumContFiles_bd900))
            {
                ContainerSequelNo = 1;
                ++(**pContObjFileIter);
            }
            
            if (!(*pContObjFileIter)->bd920End())
            {
                Root              = (*(**pContObjFileIter)())[ContainerSequelNo].GetRootPage();
                NumKeyPartitions  = 0;
                VarContainer      = true;
                DeleteFlag        = (*(**pContObjFileIter)())[ContainerSequelNo].ofiRelFileIsReq_bd900;
                MaxObjBodySize    = (*(**pContObjFileIter)())[ContainerSequelNo].GetObjBodySize();
                MaxObjPerPage     = (*(**pContObjFileIter)())[ContainerSequelNo].GetObjPerPageCount();
                MaxChains         = (*(**pContObjFileIter)())[ContainerSequelNo].GetChainCount(); 
                if ( VarContainer )
                    UnusedBytesPerPage = -1;
                else
                    UnusedBytesPerPage = FULLCOVERING_BD00 % BD92ALIGN_OBJ_FRAME(MaxObjBodySize+ sizeof (tgg92_ObjHeader));
            }
            else
            {
                ClassId = -1; /* eof */
            }
        }
        else
        {
            ClassId = -1; /* eof */
        }
    }
    else
    {
        ClassId = -1; /* eof */
    }

    if ( -1 == ClassId )               /* PTS 1118554 FF 2002-10-25 */  
        vendexcl (Trans.trTaskId_gg00, g08garbage); /* PTS 1118554 FF 2002-10-25 */        
}

/*----------------- PTS 1115641 FF 25-Apr-2002 ------------------------------*/

externC void
bd91InfoContainerChains (tgg00_TransContext       &Trans,
                         cbd900_ObjFileDirIter     **pObjFileIter,
                         cbd900_ContObjFileDirIter **pContObjFileIter,
                         tsp00_Addr                pStackarea,
                         tsp00_Int2                pStackareaLen,
                         tsp00_Int4                &ClassId,
                         tsp00_Int4                &ContainerSequelNo,
                         tsp00_Int4                &ChainId,
                         tsp00_Int4                &Subroot,
                         tsp00_Int4                &ObjCount,
                         tsp00_Int4                &PageCount,
                         tsp00_Int4                &ActiveGC,
                         tsp00_Bool                &RelEmptyPages) 
{
    if (pStackareaLen > (sizeof(cbd900_ObjFileDirIter) + sizeof(cbd900_ContObjFileDirIter)))
    {
        if ( NULL == *pObjFileIter ) 
        { 
            /* PTS 1118554 FF 2002-10-25 ( see also PTS 1115596 )                    */
            /* prevent entries to be deleted within the ObjFileDir during iteration  */
            vbegexcl (Trans.trTaskId_gg00, g08garbage); /* PTS 1118554 FF 2002-10-25 */
            *pObjFileIter = new(pStackarea) cbd900_ObjFileDirIter(bd90ObjFileDir);
            (*pObjFileIter)->bd920Begin();
            ClassId = 0;
            ChainId = -1;
        }   
        
        if ( NULL == *pContObjFileIter ) {
            tsp00_Addr pStackarea2 = pStackarea + sizeof(cbd900_ObjFileDirIter);
            *pContObjFileIter = new(pStackarea2) cbd900_ContObjFileDirIter(bd93ContObjFileDir);
            (*pContObjFileIter)->bd920Begin();
            ContainerSequelNo = 0;
        }
        
        if (!(*pObjFileIter)->bd920End())
        {
            ++ChainId;
            if ( ChainId >= (**pObjFileIter)()->GetChainCount() )
            {
                ++(**pObjFileIter);
                ChainId = 0;
            }
        }
        else if ( !(*pContObjFileIter)->bd920End() )
        {
            ++ChainId;
                
            if ( ChainId >= (*(**pContObjFileIter)())[ContainerSequelNo].GetChainCount())
            {
                ++ContainerSequelNo;
                ChainId = 0;
                if ( ContainerSequelNo > (**pContObjFileIter)()->cfiNumContFiles_bd900)
                {   
                    ContainerSequelNo = 1;
                    ++(**pContObjFileIter);
                }
            }
        }
        
        if (!(*pObjFileIter)->bd920End())
        {
            cbd900_ObjChainInfo &chain = (**pObjFileIter)()->operator[](ChainId);
            ClassId            = (*pObjFileIter)->bd920Key();
            ContainerSequelNo  = 0;
            Subroot            = chain.ociSubRoot_bd900;
            ObjCount           = chain.GetAllObjCnt();
            PageCount          = chain.ociAllPageCnt_bd900;
            ActiveGC           = chain.ociCurrActivGC_bd900;
            RelEmptyPages      = false;
        }
        else if ( !(*pContObjFileIter)->bd920End() )
        {
            if ( 0 == ContainerSequelNo )
            {
                ContainerSequelNo = 1;
                ChainId = 0;
            }

            ClassId = (*pContObjFileIter)->bd920Key();
             
            /* skip continuation files which don't exist */
            while ((!(*pContObjFileIter)->bd920End()) &&
                ((*(**pContObjFileIter)())[ContainerSequelNo].GetRootPage() == NIL_PAGE_NO_GG00))
            {
                ChainId = 0;
                ContainerSequelNo++;
                if ( ContainerSequelNo > (**pContObjFileIter)()->cfiNumContFiles_bd900)
                {
                    ContainerSequelNo = 1;
                    ++(**pContObjFileIter);   
                }            
            }
            
            if ( (!(*pContObjFileIter)->bd920End()) && 
                (ContainerSequelNo > (**pContObjFileIter)()->cfiNumContFiles_bd900))
            {
                ContainerSequelNo = 1;
                ChainId = 0;
                ++(**pContObjFileIter);
            }
            
            if (!(*pContObjFileIter)->bd920End())
            {
                cbd900_ObjChainInfo &chain = ((*(**pContObjFileIter)())[ContainerSequelNo])[ChainId];
                Subroot            = chain.ociSubRoot_bd900;
                ObjCount           = chain.GetAllObjCnt();
                PageCount          = chain.ociAllPageCnt_bd900;
                ActiveGC           = chain.ociCurrActivGC_bd900;
                RelEmptyPages      = false;
            }
            else
            {
                ClassId = -1; /* eof */
            }
        }
        else
        {
            ClassId = -1; /* eof */
        }
    }
    else
    {
        ClassId = -1; /* eof */
    }
    
    if ( -1 == ClassId )               /* PTS 1118554 FF 2002-10-25 */  
        vendexcl (Trans.trTaskId_gg00, g08garbage); /* PTS 1118554 FF 2002-10-25 */        
}
                         
/*----------------- PTS 1115641 FF 25-Apr-2002 ------------------------------*/

externC void
bd91InfoContainerKeys (tgg00_TransContext       &Trans,
                       cbd900_ObjFileDirIter     **pObjFileIter,
                       tsp00_Addr                pStackarea,
                       tsp00_Int2                pStackareaLen,
                       tsp00_Int2                &KeyIdx,
                       tsp00_Int4                &ClassId,
                       tsp00_Int4                &KeyRoot)
{
    if (pStackareaLen > sizeof(cbd900_ObjFileDirIter))
    {
        if ( NULL == *pObjFileIter ) 
        { 
            /* PTS 1118554 FF 2002-10-25 ( see also PTS 1115596 )                    */
            /* prevent entries to be deleted within the ObjFileDir during iteration  */
            vbegexcl (Trans.trTaskId_gg00, g08garbage); /* PTS 1118554 FF 2002-10-25 */
            *pObjFileIter = new(pStackarea) cbd900_ObjFileDirIter(bd90ObjFileDir);
            (*pObjFileIter)->bd920Begin();
            ClassId = 0;
            KeyIdx  = 0;
        }
        
        ++KeyIdx;
        /* PTS 1116116 FF 2002-06-07 */
        if (!(*pObjFileIter)->bd920End() && ( (tsp00_Uint2)KeyIdx >/*=*/ (**pObjFileIter)()->GetKeyPartitionCount()))
        {
            KeyIdx = 1;
            ++(**pObjFileIter);
        }
        
        while (!(*pObjFileIter)->bd920End() && ( 0 == (**pObjFileIter)()->GetKeyPartitionCount()))
            ++(**pObjFileIter);
        
        if (!(*pObjFileIter)->bd920End())
        {
            ClassId = (*pObjFileIter)->bd920Key();
            KeyRoot = (**pObjFileIter)()->ofiKeyRoots_bd900[KeyIdx - 1];
        }
        else
        {
            ClassId = -1; /* eof */
        }
    }
    else
    {
        ClassId = -1; /* eof */
    }

    if ( -1 == ClassId )               /* PTS 1118554 FF 2002-10-25 */  
        vendexcl (Trans.trTaskId_gg00, g08garbage); /* PTS 1118554 FF 2002-10-25 */        
}

/*---------------------------------------------------------------------------*/
externC void
bd91InfoGCReset( void )
{
  for ( int i = 0; i < bd91GarbCollController.bd930GetNumGCs(); ++i )
  {
    bd91GarbCollController.gccGCCounters_bd930[i].gccntActivateCount = 0;
    bd91GarbCollController.gccGCCounters_bd930[i].gccntObjectsDeleted = 0;
    bd91GarbCollController.gccGCCounters_bd930[i].gccntHistEntriesReleased = 0;
    bd91GarbCollController.gccGCCounters_bd930[i].gccntEmtyPagesReleased = 0;
    bd91GarbCollController.gccGCCounters_bd930[i].gccntDropPagesReleased = 0;
    bd91GarbCollController.gccGCCounters_bd930[i].gccntDropFiles = 0;
    bd91GarbCollController.gccGCCounters_bd930[i].gccntHistCreateObjFile = 0;
    bd91GarbCollController.gccGCCounters_bd930[i].gccntHistDeleteObj = 0;
    bd91GarbCollController.gccGCCounters_bd930[i].gccntHistDropObjFile = 0;
    bd91GarbCollController.gccGCCounters_bd930[i].gccntHistLockObj = 0;
    bd91GarbCollController.gccGCCounters_bd930[i].gccntHistInsertObj = 0;
    bd91GarbCollController.gccGCCounters_bd930[i].gccntHistNewObj = 0;
    bd91GarbCollController.gccGCCounters_bd930[i].gccntHistUpdateObj = 0;

  }
};

/*---------------------------------------------------------------------------*/

externC void
bd91InfoGCStats (tsp00_Int4            idxGC,   
                 tsp00_TaskId         &taskId,
                 tsp00_Bool           &active,
                 tsp00_8ByteCounter   &activateCount,
                 tsp00_8ByteCounter   &deleteObj,
                 tsp00_8ByteCounter   &relHistEntryNormal,
                 tsp00_8ByteCounter   &relHistCreateObjFile,
                 tsp00_8ByteCounter   &relHistDeleteObj,
                 tsp00_8ByteCounter   &relHistDropObjFile,
                 tsp00_8ByteCounter   &relHistLockObj,
                 tsp00_8ByteCounter   &relHistInsertObj,
                 tsp00_8ByteCounter   &relHistNewObj,
                 tsp00_8ByteCounter   &relHistUpdateObj,
                 tsp00_8ByteCounter   &relPageEmpty,
                 tsp00_8ByteCounter   &relPageDropFile,
                 tsp00_8ByteCounter   &relDropFile )
{
  taskId                = bd91GarbCollController.gccGCState_bd930[idxGC-1].gcsTaskId_bd930;
  active                = bd91GarbCollController.gccGCState_bd930[idxGC-1].gcsActive_bd930;
  activateCount         = bd91GarbCollController.gccGCCounters_bd930[idxGC-1].gccntActivateCount;
  deleteObj             = bd91GarbCollController.gccGCCounters_bd930[idxGC-1].gccntObjectsDeleted;
  relHistEntryNormal    = bd91GarbCollController.gccGCCounters_bd930[idxGC-1].gccntHistEntriesReleased;
  relHistCreateObjFile  = bd91GarbCollController.gccGCCounters_bd930[idxGC-1].gccntHistCreateObjFile;
  relHistDeleteObj      = bd91GarbCollController.gccGCCounters_bd930[idxGC-1].gccntHistDeleteObj;
  relHistDropObjFile    = bd91GarbCollController.gccGCCounters_bd930[idxGC-1].gccntHistDropObjFile;
  relHistLockObj        = bd91GarbCollController.gccGCCounters_bd930[idxGC-1].gccntHistLockObj;
  relHistInsertObj      = bd91GarbCollController.gccGCCounters_bd930[idxGC-1].gccntHistInsertObj;
  relHistNewObj         = bd91GarbCollController.gccGCCounters_bd930[idxGC-1].gccntHistNewObj;
  relHistUpdateObj      = bd91GarbCollController.gccGCCounters_bd930[idxGC-1].gccntHistUpdateObj;
  relPageEmpty          = bd91GarbCollController.gccGCCounters_bd930[idxGC-1].gccntEmtyPagesReleased;
  relPageDropFile       = bd91GarbCollController.gccGCCounters_bd930[idxGC-1].gccntDropPagesReleased;
  relDropFile           = bd91GarbCollController.gccGCCounters_bd930[idxGC-1].gccntDropFiles;
}

/*---------------------------------------------------------------------------*/

externC void
bd91InitObjFileDir (tgg00_TransContext &Trans)
{
    ROUTINE_DBG_MEO00 ("bd91InitObjFileDir");
    
    /* initialization of global structures bd90ObjFileDir */
    const bool           bNotShared          = false;
    const bool           bDontIncludeStrcols = false;
    tgg00_BasisError    &TrError             = Trans.trError_gg00;
    cbd05_Current        Current (Trans, m_select);
    tbd_fileinfo         FileInfo;
    tsp00_Int4           iContFileNo;
    cbd900_ObjFileInfo  *pObjFileInfo;
    
    /* initialize all entries in bd90ObjFileDir and bd93ContObjFileDir to "zero" */
    bd90ObjFileDir.bd920DelAllItems(Trans.trTaskId_gg00);
    bd93ContObjFileDir.bd920DelAllItems(Trans.trTaskId_gg00);

    // Migrate Filedirectory entries for liveCache migration from
    // release 7.2 to 7.4
    bd91_MigrateFileDirectory( Trans );

    /* set start FileId */
    tgg00_FileId   ObjFileId  = b01niltree_id;
    ObjFileId.fileTfn_gg00().becomes(tfnObj_egg00);

    /* go trough the persistent BD-file directory and */ 
    /* insert all found obj files into bd90ObjFileDir */
    while (TrError == e_ok)
    {
        /* get Fileinfo from BD-file directory */
        b17succ_fdir (ObjFileId.fileName_gg00(), ObjFileId.fileName_gg00(), FileInfo,
            bNotShared, Trans, bDontIncludeStrcols);

        /* check if the object files are already passed */
        if (tfnObj_egg00 != ObjFileId.fileTfn_gg00()) 
            break;
        
        if ((TrError                            == e_ok)                       &&
            (FileInfo.fi_root                   != NIL_PAGE_NO_GG00)           &&
            (ObjFileId.fileContObjFileNo_gg00() == PRIM_CONT_OBJ_FILE_NO_BD900))
        {
            b30fdir_to_treeid (FileInfo, ObjFileId);
            Current.curr_tree_id = ObjFileId;
            
            cbd910_RootNode  NptrsRoot (Current, ObjFileId.fileRoot_gg00(), nr_for_read);
            if (TrError != e_ok) 
                return;
            
            pObjFileInfo = bd91AddFileToObjFileDir (Trans, ObjFileId, NptrsRoot);
            if (e_ok != TrError) break;
            
            /* add key file root to object file directory  PTS 1106760 Alexander Kley 25/06/2000 */
            if (NptrsRoot.np_ptr()->nd_obj_key_len() > 0)  
            {
                const tsp00_Int4 NumObjKeyFiles = pObjFileInfo->GetKeyPartitionCount();
                
                for (tsp00_Int4 iKeyFile=0; iKeyFile<NumObjKeyFiles; ++iKeyFile)
                {
                    cbd900_ObjKeyFileId  ObjKeyFileId (*pObjFileInfo, ObjFileId.fileObjFileNo_gg00(), iKeyFile);
                    
                    b17state_fdir (ObjKeyFileId.fileName_gg00(), FileInfo, bNotShared, Trans);
                    if (TrError != e_ok)
                    {
                        /* check if index was beeing recreated */
                        cbd900_ObjKeyFileId  ObjKeyFileIdNew (*pObjFileInfo, ObjFileId.fileObjFileNo_gg00(), iKeyFile);
                        ObjKeyFileIdNew.fileObjKeyFileIndex_gg00() = ObjKeyFileId.fileObjKeyFileIndex_gg00() + NumObjKeyFiles;
                        b17state_fdir (ObjKeyFileIdNew.fileName_gg00(), FileInfo, bNotShared, Trans);
                        if (TrError != e_ok)
                        {
                            b06write_filename_and_root (ObjFileId);
                            b06write_filename_and_root (ObjKeyFileId);
                            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                                "BD91InitDir:No Key Entry", NptrsRoot.np_ptr()->nd_id());
                            return;
                        }
                        b01rename_file (Trans, ObjKeyFileIdNew, ObjKeyFileId);
                        if (TrError != e_ok)
                        {
                            b06write_filename_and_root (ObjFileId);
                            b06write_filename_and_root (ObjKeyFileId);
                            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                                "BD91InitDir:Rename Error", NptrsRoot.np_ptr()->nd_id());
                            return;
                        }
                        /* try to destroy old index file, if still exists */
                        ObjKeyFileIdNew.fileObjKeyFileIndex_gg00() = ObjKeyFileId.fileObjKeyFileIndex_gg00() + (2*NumObjKeyFiles);
                        b01pdestroy_perm_file (Trans, ObjKeyFileIdNew);
                        TrError = e_ok;
                    }
                    pObjFileInfo->ofiKeyRoots_bd900[iKeyFile] = FileInfo.fi_root;
                }
            }
            
            /* add continuation files to the cont obj file directory */
            /* PTS 1106716 Alexander Kley 01/06/2000                 */
            if (pt2VarObject_egg00 == NptrsRoot.np_ptr()->nd_pt2())
            {
                const tgg00_ObjFileNo    ObjFileNo       = ObjFileId.fileObjFileNo_gg00(); //PTS 1111901 AK 24/09/2001
                cbd900_ContObjFileInfo  &ContObjFileInfo = bd93ContObjFileDir[ObjFileNo];
                cbd900_RootPageInfo RootPageInfo (NptrsRoot);
                
                SAPDBERR_ASSERT_STATE (RootPageInfo.bd900NumContFiles() == ContObjFileInfo.cfiNumContFiles_bd900);
                
                for (iContFileNo=1; iContFileNo <= RootPageInfo.bd900NumContFiles(); ++iContFileNo)
                {
                    const tsp00_PageNo ContFileRoot = RootPageInfo.bd900ContRoot (iContFileNo);
                    if (NIL_PAGE_NO_GG00 != ContFileRoot)
                    {
                        ContObjFileInfo.bd900BuildFileId(ObjFileNo, iContFileNo, Current.curr_tree_id);
                        Current.curr_tree_id.fileRoot_gg00()  = ContFileRoot;
                        cbd910_RootNode  NptrsContRoot (Current, ContFileRoot, nr_for_read);
                        if (e_ok != TrError)
                        {
                            if ((e_page_in_wrong_tree == TrError || e_no_converter_entry == TrError ||
								e_old_fileversion == TrError ) &&   // PTS 1141372 ff
                                pObjFileInfo->ofiRelFileIsReq_bd900)
                            {
                                TrError = e_ok;
                                RootPageInfo.bd900ContRoot (iContFileNo) = NIL_PAGE_NO_GG00;
                                continue;
                            }

                            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                                "BD91InitDir:No Cont Root", NptrsRoot.np_ptr()->nd_id());
                            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                                "BD91InitDir:No Cont Root", ContFileRoot);
                            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                                "BD91InitDir: TrError    ", TrError);
                            return;
                        }
                        
                        SAPDBERR_ASSERT_STATE (ContObjFileInfo[iContFileNo].GetObjBodySize() ==
                            tsp00_Int4 (NptrsContRoot.np_ptr()->nd_obj_frame_len() - sizeof (tbd900_ContObjHeader)));
                        
                        /* check that there exists an entry in the persistent BD-filedirectory for this continuation file */
                        b17state_fdir (Current.curr_tree_id.fileName_gg00(), FileInfo,
                            Current.curr_tree_id.fileType_gg00().includes (ftsShared_egg00), Trans);
                        if (Trans.trError_gg00 != e_ok || FileInfo.fi_root != Current.curr_tree_id.fileRoot_gg00())
                        {
                            b06write_filename_and_root (Current.curr_tree_id);
                            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                                "BD91InitDir: Cont Root", FileInfo.fi_root);
                            g01abort (csp3_bd_msg, csp3_n_obj, 
                                "BD91InitDir:Odd PFDEntry", Current.curr_trans->trError_gg00);
                        }
                        
                        /* PTS 1107306  AK 28/07/2000 */
                        bd91AddFileToContObjFileDir (Trans, Current.curr_tree_id, NptrsContRoot);
                    }
                    else /* repair root pages pages */
                    {
                        /* !!! note this branch can be removed when it is ensured that creating     */ 
                        /* a continuation file and writing its root page number to the root page of */
                        /* the primary file is performed within one savepoint cycle.                */
                        bd91_RepairRootPage (Current, RootPageInfo, ObjFileNo, iContFileNo, ContObjFileInfo);
                    }
                }
            }
            
#if         defined(PTS1113452) // PTS 1113452 FF 16-Jan-2002
            /* start GCs for deleted files */ 
            if (pObjFileInfo->ofiRelFileIsReq_bd900)
            { 
                /* release root page before a GC is started to avoid a dead lock */
                NptrsRoot.bd910ReleasePage(); 
                
                bd91GarbCollController.bd930StartGCToRemoveFile(Trans, *pObjFileInfo);
                
                if (cbd900_ObjFileInfo::omsVariableFile == pObjFileInfo->GetFileType())
                {
                    cbd900_ContObjFileInfo & ContObjFileInfo = bd93ContObjFileDir[ObjFileId.fileObjFileNo_gg00()];                 
                    for (int iContFileNo = 1; iContFileNo <=ContObjFileInfo.cfiNumContFiles_bd900; ++iContFileNo)
                    {
                        tsp00_PageNo ContObjFileRoot = ContObjFileInfo[iContFileNo].GetRootPage();
                        if (NIL_PAGE_NO_GG00 != ContObjFileRoot)
                            bd91GarbCollController.bd930StartGCToRemoveFile(Trans, ContObjFileInfo[iContFileNo]);
                    }
                }
            }
#endif
        }
    }
    
    /* The error code which is send when the end of     */
    /* the file directory is reached is reset to e_ok   */
    if (TrError == e_file_not_found) 
        TrError = e_ok;
}

/*---------------------------------------------------------------------------*/

externC void
bd91InitOMSGarbageCollection ()
{
    ROUTINE_DBG_MEO00 ("bd91InitOMSGarbageCollection");

    bd91GarbCollController.bd930Init (bd90ObjFileDir ,bd93ContObjFileDir);
}

/*---------------------------------------------------------------------------*/
/* PTS 1113635 FF */
externC void
bd91MigrateObjFile (tgg00_TransContext  &Trans,
                    tgg00_FileId        &ObjFileId)
{
    /* go through all page chains and insert free pages which */
    /* are not yet in the free chain into the free chain      */ 
    tgg00_ObjFileNo     ObjFileNo = ObjFileId.fileObjFileNo_gg00();
    cbd900_ObjFileInfo &ObjFileInfo = bd90ObjFileDir[ObjFileNo];
    
    bd91_MigrateFreeChainsOfOneFile (Trans, ObjFileId, ObjFileInfo);
    
    if (cbd900_ObjFileInfo::omsVariableFile == ObjFileInfo.GetFileType())
    {
        cbd900_ContObjFileInfo  &ContObjFileInfo = bd93ContObjFileDir[ObjFileNo];
        for (tsp00_Int4 iContFileNo=1; iContFileNo <=  ContObjFileInfo.cfiNumContFiles_bd900; ++iContFileNo)
        {
            if (NIL_PAGE_NO_GG00 != ContObjFileInfo[iContFileNo].GetRootPage())
            {
                ContObjFileInfo.bd900BuildFileId(ObjFileNo, iContFileNo, ObjFileId);
                bd91_MigrateFreeChainsOfOneFile (Trans, ObjFileId, ContObjFileInfo[iContFileNo]);
            }
        }
    }
}

/*---------------------------------------------------------------------------*/

externC void
bd91StartOMSGarbageCollector (tgg00_TransContext &Trans)
{
    ROUTINE_DBG_MEO00 ("bd91StartOMSGarbageCollector");

    cbd930_GarbageCollector  GarbageCollector(Trans, bd91GarbCollController);
}

/*---------------------------------------------------------------------------*/

externC void
bd91StartOMSGarbageCollection (tgg00_TransContext   &Trans,
                               tsp00_Bool            bIfGCWaitTimeDone)
{
  ROUTINE_DBG_MEO00("bd91StartOMSGarbageCollection");
  bd91GarbCollController.bd930StartAllGCs (Trans.trTaskId_gg00, (TRUE == bIfGCWaitTimeDone));
}

/*---------------------------------------------------------------------------*/

externC void
bd91StartOMSGarbageCollectionAfterSpecialOp (tsp00_TaskId  TaskId)
{
    ROUTINE_DBG_MEO00("bd91StartOMSGarbageCollectionAfterSpecialOp");

    bd91GarbCollController.bd930StartAllGCsAfterSpecialOp (TaskId);
}

/*---------------------------------------------------------------------------*/

externC void
bd91StopOMSGarbageCollectionForSpecialOp (tsp00_TaskId  TaskId)

{
    ROUTINE_DBG_MEO00("bd91StopOMSGarbageCollectionForSpecialOp");

    /* this function stops all garbage collectors, which remain suspended  */
    /* until the method bd930StartAllGCsAfterSpecialOp is called           */

    bd91GarbCollController.bd930StopAllGCsForSpecialOp (TaskId); 
}

/*---------------------------------------------------------------------------*/
// PTS 1116157 FF 2002-06-07
externC void
bd91StartOMSGarbageCollectionIfRequired (tgg00_TransContext   &Trans)
{
    ROUTINE_DBG_MEO00("bd91StartOMSGarbageCollectionIfRequired");
    
    bd91GarbCollController.bd930StartGCsIfRequired(Trans.trTaskId_gg00);
}

/*---------------------------------------------------------------------------*/
// PTS 1119647 FF 2002-DEC-05
externCpp void
bd91DropObjFile (tgg00_TransContext   &Trans,
                 tgg00_ObjFileNo       ObjFileNo)
{
    ROUTINE_DBG_MEO00("bd91DropObjFile");
    bd90RemoveObjFile( Trans, ObjFileNo );
};

/*---------------------------------------------------------------------------*/
externCpp void
bd91ReleaseUnusedObject (tgg00_TransContext      &Trans,
                         Log_UndoFile::Iterator  &historyIterator,
                         const tgg92_KernelOid   &OId,
                         tgg00_ObjFileNo          ObjFileNo,
                         const tgg91_PageRef     &WantedObjVers,
                         GC_IGarbageCollector    &IGarbColl) // PTS 1113774 FF 2002-01-29
{
  /* this routine removes a single object and updates the object */
  /* counter and the free page chain, if this is neccessary      */
  
  tgg00_BasisError   &TrError    = Trans.trError_gg00;
  tgg00_FileId        ObjFileId;
  
  /* this object writes a message into the vtrace at beginning and end of this routine */
  LVC_ErrorTraceObject   ErrorTraceObject  (Trans, ObjFileId, ObjFileNo, OId, b91garbcol);
  cbd911RecreateIndexLock lock(Trans);   

  /* create FileId for the file which contains the object */
  cbd900_ObjFileInfo  &ObjFileInfo = bd90ObjFileDir[ObjFileNo];
  ObjFileInfo.bd900BuildFileId (ObjFileNo, ObjFileId);
  if (( ObjFileInfo.bd900RecreateIndex()) && (ObjFileInfo.GetKeyPartitionCount() > 0 ))
      lock.Lock(false /*not exclusive*/);
  
  /* check if the file was already dropped */
  if (!bd90ObjFileDir.bd920IsUsed(ObjFileNo) || (ObjFileInfo.ofiRelFileIsReq_bd900))
  {
    /* since the file is dropped already one can return immediately */
    ErrorTraceObject.SetStatus (rosFileAlreadyDeleted_gg12);
    return;
  }
  
  /* create current to access page */
  cbd05_Current Current (Trans, m_update, ObjFileId);
  
  /*  get page pointer  */
  cbd910_PrimObjDataNode    NptrsPage (Current, nr_for_update);
  NptrsPage.bd910AssignToPage(OId.gg92GetPno(), false /*=dont wait for lock*/);
  
  /* release history page to avoid a deadlock; PTS 1106180 AK 29/03/2000 */
  if (e_bd_page_collision == TrError)
  {
    TrError       = e_ok;
    historyIterator.Invalidate();
    NptrsPage.bd910AssignToPage(OId.gg92GetPno());
  }
  
  if (e_ok != TrError)
  {
    /* check if the error is due to a drop of the file */
    if ((e_page_in_wrong_tree == TrError) || (e_no_converter_entry == TrError))
    {
      if (!bd90ObjFileDir.bd920IsUsed(ObjFileNo) || (bd90ObjFileDir[ObjFileNo].ofiRelFileIsReq_bd900))
      {
        ErrorTraceObject.SetStatus (rosFileAlreadyDeleted_gg12);
        TrError = e_ok;
      }
      else if ((bd90ObjFileDir[ObjFileNo].GetKeyPartitionCount()>0) ||
          ( Kernel_IAdminInfo::Instance().KernelStateIsRestart() ))  // PTS 1128239 FF 2004-MAR-10
      {
        ErrorTraceObject.SetStatus (rosPageNotFound_gg12);
        TrError = e_ok;
      }
    }    
    return;
  }

  /* BEGIN PTS 1128894 FF 31-MAR-2004 ***************************************** */

  /* determine pointer to the page accomodating the object frame */
  tbd_nodeptr         &pPage     = NptrsPage.np_ptr();
  const tsp00_Int4     ObjKeyLen = pPage->nd_obj_key_len();

  bool bKeyAlreadyRemoved = false;

  if ((ObjKeyLen > 0) && (ObjFileNo == pPage->nd_obj_file_no()))
  {
      BD92CHECK_OID_POSITION ("bd91ReleaseUnusedObject", TrError, OId, NptrsPage);
      tbd900_ObjFrame  *pObjFrame = NptrsPage.bd910ObjFramePtr (OId.gg92GetPos());

      if ((WantedObjVers == pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00) &&
          (obsFreeAfterEot_egg00 == pObjFrame->objHeader_bd900.ohdState_gg92))
      {
          /* construct pointer to the key */
          void *const pKey = (tsp00_Byte*) pPage + OId.gg92GetPos() + pPage->nd_obj_frame_len() - ObjKeyLen;

          /* remove OId from hash */
          bd22RemoveOid (*Current.curr_trans, Current.curr_tree_id.fileObjFileNo_gg00(),ObjKeyLen, pKey, OId);
          if (e_hash_key_not_found == TrError)  
              TrError = e_ok;
          if ( e_ok == TrError )
          {
              bKeyAlreadyRemoved = true;
              *(unsigned char*)(pKey) = ~(*(unsigned char*)(pKey)); /* modify first byte of key to prevent reuse */
          }
          TrError = e_ok;   /* do handling as done before this change */
      }
  }
  /* END PTS 1128894 FF 31-MAR-2004 ***************************************** */

  /* get pointer to subroot page which is required if this operation forces an update of the page chain */	
  cbd910_SubRootNode    NptrsSubRoot  (Current, nr_for_update);
  
  if ( NptrsPage.bd910LockSubRootBeforeReleasingFrame()) 
  {	
    /* release history page to avoid a deadlock;  PTS 1114691 FF 2002-03-07 */
    historyIterator.Invalidate();   
    NptrsSubRoot.bd910AssignToSubroot (NptrsPage);
    if (e_ok != TrError) 
    {
      /* check if the error is due to a drop of the file */
      if ((e_page_in_wrong_tree == TrError) || (e_no_converter_entry == TrError))
      {
        if (!bd90ObjFileDir.bd920IsUsed(ObjFileNo) || (bd90ObjFileDir[ObjFileNo].ofiRelFileIsReq_bd900))
        {
          ErrorTraceObject.SetStatus (rosFileAlreadyDeleted_gg12);
          TrError = e_ok;
        }
        else if ((bd90ObjFileDir[ObjFileNo].GetKeyPartitionCount()>0) ||
          ( Kernel_IAdminInfo::Instance().KernelStateIsRestart() ))  // PTS 1128239 FF 2004-MAR-10
        {
          ErrorTraceObject.SetStatus (rosPageNotFound_gg12);
          TrError = e_ok;
        }
      }      
      return;
    }

    /* check if chaining will still be needed ( meahnwhile the page may have changed a lot */
	if ( !NptrsPage.bd910LockSubRootBeforeReleasingFrame() ) 
	{	
		/* no chaining will be needed anymore ==> release subroot */
		NptrsSubRoot.bd910ReleasePage();
	}
  }
  
  /*------------------------------------------------------------------*/
  /* check if the found object frame contains realy the wanted object */
  /*------------------------------------------------------------------*/
  
  /* determine pointer to the page accomodating the object frame */
  /*tbd_nodeptr         &*/pPage     = NptrsPage.np_ptr();     // PTS 1128894 FF 31-MAR-2004
  
  /*const tsp00_Int4     ObjKeyLen = pPage->nd_obj_key_len();     PTS 1128894 FF 31-MAR-2004 */
  
  /*  check consistency of key infos stored on the page and stored in the obj file directory */
# if COMPILEMODE_MEO00 >= QUICK_MEO00
  if ((ObjKeyLen > 0) != (bd90ObjFileDir[ObjFileNo].GetKeyPartitionCount()>0))
  {
    ErrorTraceObject.SetStatus (rosWrongKeyInfo_gg12);
    TrError = e_hash_not_found;
    return;
  }
# endif
  
  /* check the obj file no on page */
  if (ObjFileNo != pPage->nd_obj_file_no())
  {
    /* check if the error is due to a drop of the file */
    if (!bd90ObjFileDir.bd920IsUsed(ObjFileNo) || (bd90ObjFileDir[ObjFileNo].ofiRelFileIsReq_bd900))
    {
      ErrorTraceObject.SetStatus (rosFileAlreadyDeleted_gg12);
      TrError = e_ok;
    }
    else if ((ObjKeyLen > 0) || ( Kernel_IAdminInfo::Instance().KernelStateIsRestart() ))  /* PTS 1114300 FF 2002-02-20 */
    {
      ErrorTraceObject.SetStatus (rosWrongFileNo_gg12);
      TrError = e_ok;
    }
    else 
    {
      TrError = e_wrong_class_id;
      ErrorTraceObject.WriteVersionErrorMessage (pPage->nd_obj_file_no(), WantedObjVers, NULL);
    }
    return;
  }
  
  /* determine pointer to object frame */
  BD92CHECK_OID_POSITION ("bd91ReleaseUnusedObject", TrError, OId, NptrsPage);
  tbd900_ObjFrame  *pObjFrame = NptrsPage.bd910ObjFramePtr (OId.gg92GetPos());
  
  /*--------------------------------------------------------------------------------------------------*/
  /* It can happen that the GC cannot find the object which has to be  deleted. See for               */
  /* instance the history sequence : => new - upd - del - new - upd - del. Releasing an object frame  */
  /* due to the first delete must result in the error 'wrong object version', which has to be ignored */
  /* However, this can only happen in case that the object has a key and its frame was reused         */
  /*--------------------------------------------------------------------------------------------------*/
  
  /* check object version */
  if (WantedObjVers != pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00)
  {
    /* check if this could be regular error which can be ignored */
    if ((ObjKeyLen > 0) || ( Kernel_IAdminInfo::Instance().KernelStateIsRestart() ))  /* PTS 1114300 FF 2002-02-20 */
    {
      ErrorTraceObject.SetStatus (rosWrongObjVersion_gg12);
      TrError = e_ok;
    }
    else
    {
      TrError = e_wrong_object_version;
      ErrorTraceObject.WriteVersionErrorMessage (pPage->nd_obj_file_no(), WantedObjVers, pObjFrame);
    }
    return;
  }
  
# if COMPILEMODE_MEO00 >= QUICK_MEO00
  /*  check object state  */
  if (obsFreeAfterEot_egg00  != pObjFrame->objHeader_bd900.ohdState_gg92)
    // note: the Frameversion is not decreased in case of a rollback
    //       therefore the next equation need not be valid
    // (OId.gg92GetFrameVers() != pObjFrame->objHeader_bd900.ohdFrameVersion_gg92)
  {
    TrError = e_wrong_object_version;
    ErrorTraceObject.WriteVersionErrorMessage (pPage->nd_obj_file_no(), WantedObjVers, pObjFrame);
    return;
  }
# endif
  
  /* ================================================================== */
  /* ----- after passing all checks the object can now be removed ----- */
  /* ================================================================== */
  tgg92_KernelOid auxOid = OId; // only to work around the missing const qualifiers
  if (NptrsPage.np_ptr()->nd_free_obj_cnt() == (NptrsPage.np_ptr()->nd_max_obj_cnt()-1))
      IGarbColl.IncReleaseEmptyPageCount();
  bd91RemoveObjFromFile (Current, NptrsPage, NptrsSubRoot, pObjFrame, auxOid,
      ObjFileInfo, historyIterator, ErrorTraceObject,
      bKeyAlreadyRemoved); // new bKeyAlreadyRemoved PTS 1128894 FF 31-MAR-2004
  IGarbColl.IncObjReleaseCount();
}

/*---------------------------------------------------------------------------*/
/* PTS 1109441 AK 2001-02-20 */
externC void
bd91CheckUnusedObject (tgg00_TransContext      &Trans,
                       Log_UndoFile::Iterator  &historyIterator,
                       tgg92_KernelOid         &OId,
                       tgg00_ObjFileNo          ObjFileNo,
                       tgg91_PageRef           &WantedObjVers,
                       tgg00_MessType           MessType,
                       tsp00_Bool              &ObjectStateIsOk)
{
    /* This methods cheks if the state of an object corresponds */
    /* to the state stored in the object history                */ 
    tgg00_BasisError   &TrError    = Trans.trError_gg00;
    tgg00_FileId        ObjFileId;

    ObjectStateIsOk = false;

    /* create FileId for the file which contains the object */
    cbd900_ObjFileInfo  &ObjFileInfo = bd90ObjFileDir[ObjFileNo];
    ObjFileInfo.bd900BuildFileId (ObjFileNo, ObjFileId);

    /* check if the file was already dropped */
    if (!bd90ObjFileDir.bd920IsUsed(ObjFileNo) || (ObjFileInfo.ofiRelFileIsReq_bd900))
    {
        ObjectStateIsOk = true;
        return;
    }

    /* create current to access page */
    cbd05_Current Current (Trans, m_update, ObjFileId);

    /*  get page pointer  */
    cbd910_PrimObjDataNode    NptrsPage (Current, nr_for_update);
    NptrsPage.bd910AssignToPage(OId.gg92GetPno(), false /*=dont wait for lock*/);

    /* release history page to avoid a deadlock; PTS 1106180 AK 29/03/2000 */
    if (e_bd_page_collision == TrError)
    {
        TrError       = e_ok;
        historyIterator.Invalidate();
        NptrsPage.bd910AssignToPage(OId.gg92GetPno());
    }

    if (e_ok != TrError)
    {
        /* check if the error is due to a drop of the file */
        if ((e_page_in_wrong_tree == TrError) || (e_no_converter_entry == TrError))
        {
            if (!bd90ObjFileDir.bd920IsUsed(ObjFileNo)                     ||
                (bd90ObjFileDir[ObjFileNo].ofiRelFileIsReq_bd900)          ||
                (bd90ObjFileDir[ObjFileNo].GetKeyPartitionCount()>0)       ||
                (m_drop == MessType))
            {
                ObjectStateIsOk = true;
                TrError         = e_ok;
            }
            else
                ABORT_OR_MESSAGE ("BD91CheckUnusedObj:Err1 ", TrError);
        }
        else
            ABORT_OR_MESSAGE ("BD91CheckUnusedObj:Err2 ", TrError);
        
        TrError = e_ok;
        return;
    }

    /*------------------------------------------------------------------*/
    /* check if the found object frame contains realy the wanted object */
    /*------------------------------------------------------------------*/
    
    /* determine pointer to the page accomodating the object frame */
    tbd_nodeptr         &pPage     = NptrsPage.np_ptr();
    
    const tsp00_Int4     ObjKeyLen = pPage->nd_obj_key_len();

    /*  check consistency of key infos stored on the page and stored in the obj file directory */
    if ((ObjKeyLen > 0) != (bd90ObjFileDir[ObjFileNo].GetKeyPartitionCount()>0))
    {
        ABORT_OR_MESSAGE ( "BD91CUnusedObj:NoHash   ", ObjKeyLen);
        return;
    }

    /* check the obj file no on page */
    if (ObjFileNo != pPage->nd_obj_file_no())
    {
        /* check if the error is due to a drop of the file */
        if (!bd90ObjFileDir.bd920IsUsed(ObjFileNo)                        ||
            (bd90ObjFileDir[ObjFileNo].ofiRelFileIsReq_bd900)             ||
            (ObjKeyLen > 0))
        {
            ObjectStateIsOk = true;
        }
        else
        {
            TrError = e_wrong_class_id;
            ABORT_OR_MESSAGE ( "BD91CheckUnusedObj:Err3 ", TrError);
        }
        return;
    }

    /* determine pointer to object frame */
    BD92CHECK_OID_POSITION ("bd91CheckUnusedObject",TrError, OId, NptrsPage);
    tbd900_ObjFrame  *pObjFrame = NptrsPage.bd910ObjFramePtr (OId.gg92GetPos());

    /*--------------------------------------------------------------------------------------------------*/
    /* It can happen that the GC cannot find the object which has to be  deleted. See for               */
    /* instance the history sequence : => new - upd - del - new - upd - del. Releasing an object frame  */
    /* due to the first delete must result in the error 'wrong object version', which has to be ignored */
    /* However, this can only happen in case that the object has a key and its frame was reused         */
    /*--------------------------------------------------------------------------------------------------*/

    if (m_drop == MessType)
    {
        if ((WantedObjVers != pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00) ||
            (obsFree_egg00 == pObjFrame->objHeader_bd900.ohdState_gg92))
        {
            ObjectStateIsOk = true;
            return;
        }
        else
        {
            ABORT_OR_MESSAGE ("BD91CheckUObj:WrongState", MessType);
            ABORT_OR_MESSAGE ("BD91CheckUObj:WrongState", pObjFrame->objHeader_bd900.ohdState_gg92);
            return;
        }
    }
    else if (m_delete == MessType)
    {
            if (WantedObjVers == pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00) 
            {
                if (obsFreeAfterEot_egg00 == pObjFrame->objHeader_bd900.ohdState_gg92)
                {   
                   ObjectStateIsOk = true;
                   return;
                }
                else
                {
                    ABORT_OR_MESSAGE ("BD91CUObj:WrongState2   ", pObjFrame->objHeader_bd900.ohdState_gg92);
                    return;
                }
            }
            else if (ObjKeyLen > 0)
            {
                 ObjectStateIsOk = true;
                 return;
            }
            else
            {
                ABORT_OR_MESSAGE ("BD91CUObj:WrongState3   ", pObjFrame->objHeader_bd900.ohdState_gg92);
                    return;
            }
    }
    else
        ABORT_OR_MESSAGE ("BD91CUObj:WrongMessType ", MessType);
}

/*---------------------------------------------------------------------------*/

externCpp void
bd91RemoveObjFromFile (tbd_current_tree        &Current,
                       cbd910_PrimObjDataNode  &NptrsPage,
					   cbd910_SubRootNode      &NptrsSubRoot,
                       tbd900_ObjFrame         *pObjFrame,
                       tgg92_KernelOid         &OId,
                       cbd900_ObjFileInfo      &ObjFileInfo, 
                       Log_UndoFile::Iterator  &historyIterator,
                       LVC_ErrorTraceObject    &ErrorTraceObject,
                       bool                     bKeyAlreadyRemoved) // new PTS 1128894 FF 31-MAR-2004
{
    ROUTINE_DBG_MEO00("bd91RemoveObjFromFile");
    
    tgg00_BasisError  &TrError  = Current.curr_trans->trError_gg00;
    
    /*-------------------------------------------------------*/
    /* remove the object from the page                       */
    /*-------------------------------------------------------*/
    bd91RemoveObjFromPage (Current,  NptrsPage,  pObjFrame,  OId, ObjFileInfo, ErrorTraceObject, 
        bKeyAlreadyRemoved); // new PTS 1128894 FF 31-MAR-2004
    if (e_ok != TrError)
    {
        if (!bd90ObjFileDir.bd920IsUsed(NptrsPage.np_ptr()->nd_obj_file_no()) || 
            ObjFileInfo.ofiRelFileIsReq_bd900)
        {
            ErrorTraceObject.SetStatus (rosFileJustDeleted_gg12);
            TrError = e_ok;
        }
        return;
    }
    
    /*--------------------------------------------------------------------*/
    /* if the page becomes an empty page by removing the object it is     */ 
    /* released                                                           */
    /*--------------------------------------------------------------------*/
    if ( NptrsPage.bd910IsEmptyPage())
    {
        /* bd910RemovePageFromChainOfAllPages will release subroot PTS 1135421 */
        NptrsSubRoot.bd910RemovePageFromChainOfAllPages(NptrsPage);         
    }
    /*--------------------------------------------------------------------*/
    /* if the page becomes a free page by removing the object             */ 
    /* the free page chain on root page is updated                        */
    /*--------------------------------------------------------------------*/
	else if (NptrsPage.bd910PageMustBeInsertedIntoFreeChain())
    {		
        /* release history page to avoid a deadlock; PTS 1106180 AK 29/03/2000 */
        historyIterator.Invalidate();
        
        NptrsSubRoot.bd910InsertPageIntoFreeChain (NptrsPage);
        
        if (e_ok != TrError)
        {
            /* check if this error occured since the container was dropped */
            /* PTS 1106724 Alexander Kley 23/05/2000                       */
            cbd900_ObjFileInfo &ObjFileInfo = bd90ObjFileDir[Current.curr_tree_id.fileObjFileNo_gg00()];
            if (!bd90ObjFileDir.bd920IsUsed(Current.curr_tree_id.fileObjFileNo_gg00()) || 
                ObjFileInfo.ofiRelFileIsReq_bd900)
            {
                ErrorTraceObject.SetStatus (rosFileJustDeleted_gg12);
                TrError = e_ok;
            }
            else
            {
                g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                    "bd91RelObj:InsPageFailed", Current.curr_tree_id.fileObjFileNo_gg00());
            }
            return; 
        }

#       if COMPILEMODE_MEO00 >= QUICK_MEO00 
        if ((NptrsPage.np_ptr()->nd_in_free_chain() != (NptrsPage.np_ptr()->nd_free_obj_cnt() > 0)) &&
			!NptrsPage.np_ptr()->nd_assigned_to_spec_trans())
        {
            Kernel_OpError( csp3_bd_msg, csp3_n_obj ) << __FILE__ << ":" << __LINE__
                << " root:" << NptrsPage.np_ptr()->nd_root()
                << " actual page:" << NptrsPage.np_ptr()->nd_id()
                << " bad FreeCount";
            g01abort (csp3_bd_msg, csp3_n_obj, "Wrong free page chain   ", 0);
        }
#       endif
    }
}


/*---------------------------------------------------------------------------*/

externCpp void
bd91RemoveObjFromPage (tbd_current_tree        &Current,
                       cbd910_PrimObjDataNode  &NptrsPage,
                       tbd900_ObjFrame         *pObjFrame,
                       tgg92_KernelOid         &OId,
                       cbd900_ObjFileInfo      &ObjFileInfo, 
                       LVC_ErrorTraceObject    &ErrorTraceObject,
                       bool                     bKeyAlreadyRemoved) // new PTS 1128894 FF 31-MAR-2004
{
    ROUTINE_DBG_MEO00("bd91RemoveObjFromPage");
    
    tgg00_BasisError  &TrError  = Current.curr_trans->trError_gg00;
    tbd_nodeptr       &pPage    = NptrsPage.np_ptr();
    const tsp00_Int4   ObjKeyLen = pPage->nd_obj_key_len();
    
    SAPDBERR_ASSERT_STATE (ObjKeyLen == pPage->nd_obj_key_len());
    SAPDBERR_ASSERT_STATE (pObjFrame == NptrsPage.bd910ObjFramePtr (OId.gg92GetPos()));
    SAPDBERR_ASSERT_STATE (ObjFileInfo.GetRootPage() == pPage->nd_root());
    SAPDBERR_ASSERT_STATE (pObjFrame->objHeader_bd900.ohdState_gg92 != obsFree_egg00);
    
    
    /*-----------------------*/
    /* remove OMS key        */
    /*-----------------------*/
    if ((ObjKeyLen > 0) && 
        ( !bKeyAlreadyRemoved )) // new PTS 1128894 FF 31-MAR-2004
    {
        /* construct pointer to the key */
        void *const pKey = (tsp00_Byte*) pPage + OId.gg92GetPos() + pPage->nd_obj_frame_len() - ObjKeyLen;
        
        /* remove OId from hash */
        bd22RemoveOid (*Current.curr_trans, Current.curr_tree_id.fileObjFileNo_gg00(),ObjKeyLen, pKey, OId);
        if (e_hash_key_not_found == TrError)  TrError = e_ok;
        if (e_ok != TrError) 
        {
            ErrorTraceObject.SetStatus (rosDelKeyFailed_gg12);   /* PTS 1106760  Alexander Kley 25/06/2000 */
            if (!bd90ObjFileDir.bd920IsUsed(Current.curr_tree_id.fileObjFileNo_gg00()) || 
                ObjFileInfo.ofiRelFileIsReq_bd900)
            {
                ErrorTraceObject.SetStatus (rosFileJustDeleted_gg12);
                TrError = e_ok;
            }
            else
                g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, "b91RmObjFP:bd22RemoveOid", TrError);
            return;
        }
    }
    
    /*--------------------------------*/
    /* remove the continuation object */
    /*--------------------------------*/
    if (pt2VarObject_egg00 == pPage->nd_pt2())
    {
        tbd900_VarObjBody &VarObjBody  = *((tbd900_VarObjBody*) (pObjFrame->objBody_bd900));
        tgg00_ObjFileNo  ContObjFileNo = VarObjBody.vbdHeader_bd900.vhdContObjFileNo_bd900;
        
        /* check if there is really a continuation object */
        if (PRIM_CONT_OBJ_FILE_NO_BD900 != ContObjFileNo)
        {
            tsp00_PageNo     ContObjPno = VarObjBody.vbdHeader_bd900.vhdContObjPno_bd900;
            tgg00_ObjPagePos ContObjPos = VarObjBody.vbdHeader_bd900.vhdContObjPos_bd900;
            
            /* remove continuation object */
            bd93RemoveContObj (Current, OId, ContObjFileNo, ContObjPno, ContObjPos);
            if (e_ok != TrError) 
            {
                /* check if this error occured since the container was dropped */
                /* PTS 1107433 Alexander Kley 07/08/2000                       */
                cbd900_ObjFileInfo &ObjFileInfo = bd90ObjFileDir[Current.curr_tree_id.fileObjFileNo_gg00()];
                if (!bd90ObjFileDir.bd920IsUsed(Current.curr_tree_id.fileObjFileNo_gg00()) || 
                    ObjFileInfo.ofiRelFileIsReq_bd900)
                {
                    ErrorTraceObject.SetStatus (rosFileJustDeleted_gg12);
                    TrError = e_ok;
                }
                else
                {
                    g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, "b91RmObjFP:bd23RmContObj", TrError);
                    ErrorTraceObject.SetStatus (rosDelContObjFailed_gg12);   /* PTS 1106760  Alexander Kley 25/06/2000 */
                    return;
                }
            }
        }
        
        /* reset var object header */
        VarObjBody.vbdHeader_bd900.bd900SetToEmptyHeader();
    }
    
    /*-----------------------*/
    /* remove primary object */
    /*-----------------------*/
   
    /* the primary object is removed as last object, to ensure that free-list-counter and chaining to free-list */
    /* is only done, if all other resources have been cleaned up completely                                     */
    /*  update object counter in page header  */
    ++pPage->nd_free_obj_cnt();

    if (pObjFrame->objHeader_bd900.ohdState_gg92 == obsFreeAfterEot_egg00)
        --pPage->nd_free_eot_obj_cnt();
    else
    {
        SAPDBERR_ASSERT_STATE (pObjFrame->objHeader_bd900.ohdState_gg92 != obsFree_egg00);
        SAPDBERR_ASSERT_STATE (Kernel_IAdminInfo::Instance().KernelStateIsRestart());
        --pPage->nd_occ_obj_cnt();
    }
    
    /*  update object state  */
    pObjFrame->objHeader_bd900.ohdState_gg92.becomes(obsFree_egg00);

  	/* invalidate the object version PTS 1113123 13/12/2001 */
	pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00.gg91SetNilRef();
    
    /*  insert object into free object chain */
    pObjFrame->objHeader_bd900.ohdNextFreeObj_gg92 = pPage->nd_first_free_obj();
    pPage->nd_first_free_obj()                     = OId.gg92GetPos();

    /*---------------------------------------------*/
    /* update counter of all objects in chaininfo  */
    /*---------------------------------------------*/   
    ObjFileInfo[pPage->nd_chain_no()].DecrementAllObjCnt();
}

/*===========================================================================*
 *  END OF CODE                                                              *
 *===========================================================================*/
