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

  module      : vbd90.cpp

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

  responsible : FerdiF

  special area: BD :       Operations for processing object files
  description : 


  version     : 7.4.4.0
  last changed: 2002-12-02
  see also    : 

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

  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


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

/*  WAIT FOR LOCK RELEASE
*
* kb50LockObj
*   \kb67LockObj
*     |\kb67NewObj
*     |  |\bd90ReuseObj
*     |  |   \bd04_ReuseObj
*     |  |      \bd04NewObjKey (wait)
*     |   \bd90_NewObjFromThisPage (nowait)
*     |\bd90LockObj
*     |   \bd04LockObj (wait)
*     |\bd90_DelAllObjOnThisPage (nowait)
*      \bd90NextObjConsistentOnThisPage (nowait)
*         \bd90NextObjConsistentOnThisPage 
*/

/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/

#include <stdlib.h>

#include "hbd90.h"

#include "hgg06.h"
#include "gsp03.h"
#include "gsp03_3.h"
#include "ggg01.h" // OMS errors
#include "gbd05.h"
#include "gbd900.h"
#include "gbd910.h"
#include "gbd920.h"
#include "gbd930.h"

#include "hbd06.h"
#include "hbd17.h"
#include "hbd20_1.h"
#include "hbd22.h"
#include "hbd91.h"
#include "hbd911.h"
#include "hbd92.h"
#include "hbd93.h"
#include "hbd95_1.h"
#include "hbd300.h" // SetRootCheck
#include "hgg01.h" 
#include "hgg01_1.h" 
#include "hgg06.h"
#include "SAPDB/SAPDBCommon/SAPDB_RangeCode.hpp" // Kernel_move_and_fill
#include "hgg10.h"
#include "hgg17.h"
#include "hkb50.h"
#include "hkb67.h"

#include "liveCache/LVC_ErrorTraceObject.hpp"
#include "Logging/Log_History.hpp"
#include "Logging/Log_ActionDeleteAllObjects.hpp"
#include "Logging/Log_Transaction.hpp"              // PTS 1114914 FF 2002-03-13
#include "Converter/Converter_IPageNoManager.hpp"
#include "KernelCommon/Kernel_OpMsg.hpp"            /* PTS 1114891 FF 2002-03-14 */
#include "KernelCommon/Kernel_VTrace.hpp"           /* PTS 1120151 */ 
#include "KernelCommon/Kernel_IAdminInfo.hpp"

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

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

#ifdef NO_INLINES
#  define _INLINE
#else
#  define _INLINE   inline
#endif

#define FIRST_CHAIN_NO 0

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

#if COMPILEMODE_MEO00 >= SLOW_MEO00 

#   define BD90_CHECK_KEY_SIZE(TR_ERROR, HASH_KEY_SIZE, OBJ_KEY_SIZE) \
            if (HASH_KEY_SIZE != OBJ_KEY_SIZE)                        \
            {                                                         \
                TR_ERROR = e_illegal_keylength;                       \ 
                return;                                               \ 
            }                                                        

#else

#   define BD90_CHECK_KEY_SIZE(TR_ERROR, HASH_KEY_SIZE, OBJ_KEY_SIZE) 

#endif

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

static bool g_IsOnline = false;

enum ebd90_FunctionName {Delete, Get, KeyGet, GetCons, KeyGetCons,
                         Lock, Reuse, Unlock, Update, Redo};

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

class CNosync
{
public:
    CNosync  (tsp00_TaskId TaskId) {};
    ~CNosync ()                    {}; 
};

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

class CFreePageListEntry 
{
public:
    CFreePageListEntry() 
        : m_pageno(NIL_PAGE_NO_GG00)
        , m_PageReleased(false)
    { };
    CFreePageListEntry(tsp00_PageNo pageno) 
        : m_pageno(pageno)
        , m_PageReleased(false)
    { };
    const CFreePageListEntry & assign(const CFreePageListEntry& right, tgg00_BasisError&) {
        m_pageno = right.m_pageno;
        m_PageReleased  = right.m_PageReleased;
        return *this;
    };
    tsp00_PageNo& PageNo() { 
        return m_pageno; 
    };
    bool& PageReleased() { 
        return m_PageReleased; 
    };
private:
    tsp00_PageNo m_pageno;
    bool         m_PageReleased;
};

#define FREEPAGELISTHASH_NUM_ENTRIES_ALLOCATE  50 
#define FREEPAGELISTHASH_NUM_ENTRIES_EXTEND    50 

class  CFreePageListHash : 
public cbd920_ChainedListHash <tgg00_ObjFileNo, CFreePageListEntry, CNosync
, FREEPAGELISTHASH_NUM_ENTRIES_ALLOCATE, FREEPAGELISTHASH_NUM_ENTRIES_EXTEND>
{
public:
    CFreePageListHash(SAPDBMem_IRawAllocator& alloc)
        : cbd920_ChainedListHash <tgg00_ObjFileNo, CFreePageListEntry, CNosync
, FREEPAGELISTHASH_NUM_ENTRIES_ALLOCATE, FREEPAGELISTHASH_NUM_ENTRIES_EXTEND>(alloc)
    {};

};

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

typedef cbd920_HashIter <tgg00_ObjFileNo, CFreePageListEntry, CNosync
, FREEPAGELISTHASH_NUM_ENTRIES_ALLOCATE, FREEPAGELISTHASH_NUM_ENTRIES_EXTEND> 
CFreePageListHashIter;

/*---------------------------------------------------------------------------*/
static CFreePageListEntry DummyFreePageEntry;

static CFreePageListEntry&
bd90_GetCachedFreePage(tgg00_TransContext &Trans, tgg00_ObjFileNo FileNo)
{
    if (NULL == Trans.trFreePagesForIns_gg00)
    {
        SAPDBMem_IRawAllocator &RawAllocator = *(REINTERPRET_CAST(SAPDBMem_IRawAllocator*, Trans.trAllocator_gg00));
        Trans.trFreePagesForIns_gg00 = new (RawAllocator) CFreePageListHash(RawAllocator);
    }
    if (NULL == Trans.trFreePagesForIns_gg00)
    {
        DummyFreePageEntry.PageNo()       = NIL_PAGE_NO_GG00;
        DummyFreePageEntry.PageReleased() = false;
        return DummyFreePageEntry;
    }
    CFreePageListHash& freePageList = 
        *reinterpret_cast<CFreePageListHash*>(Trans.trFreePagesForIns_gg00);
    return freePageList[FileNo];
};

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

static bool 
bd90_PutCachedFreePage(tgg00_TransContext &Trans, tgg00_ObjFileNo FileNo, tsp00_PageNo PageNo)
{
    bool bRC = false;
    if (NULL != Trans.trFreePagesForIns_gg00)
    {
        CFreePageListHash& freePageList =
        *reinterpret_cast<CFreePageListHash*>(Trans.trFreePagesForIns_gg00);
        CFreePageListEntry entry(PageNo);
        freePageList.bd920InsItem (Trans.trTaskId_gg00, FileNo, &entry, Trans.trError_gg00);
        if (e_ok == Trans.trError_gg00)
            bRC = true;
        else 
            Trans.trError_gg00 = e_ok;
    }
    return bRC;
}

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

static void
bd90_DelCachedFreePage(tgg00_TransContext &Trans, tgg00_ObjFileNo FileNo)
{
    if (NULL != Trans.trFreePagesForIns_gg00)
    {
        CFreePageListHash& freePageList = 
        *reinterpret_cast<CFreePageListHash*>(Trans.trFreePagesForIns_gg00);
        freePageList.bd920DelItem (Trans.trTaskId_gg00, FileNo);
    }
}

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

extern cbd900_ContObjFileDir      bd93ContObjFileDir;
extern cbd930_GarbCollController  bd91GarbCollController;

/*===========================================================================*
 *  GLOBAL VARIABLES                                                          *
 *===========================================================================*/

static long    g_Committed_obsReserved_Cnt  = 0;           

cbd900_ObjFileDir     bd90ObjFileDir;

/*===========================================================================*
 *  LOCAL FUNCTIONS (PROTOTYPES)                                             *
 *===========================================================================*/

static void
bd90_CopyObjCountFromChainInfoToSubRoots (tbd_current_tree   &Current,
        cbd900_ObjFileInfo &ObjFileInfo);

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

static _INLINE void
bd90_DelAllObjOnThisPage (tbd_current_tree           &Current,
                          cbd910_PrimObjDataNode     &NptrsPage,
                          tsp00_Int4                 &NumDelObj,
                          tgg92_KernelOid            &ErrorOid);

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

static _INLINE void
bd90_GetObjBody   (tgg00_TransContext &Trans,
                   tgg92_KernelOid     OId,
                   tbd_nodeptr         pPage,
                   tsp00_Int4          ExtObjBodySize,
                   void               *pExtObjBody,
                   tbd900_ObjFrame    *pObjFrame);

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

static void
bd90_NewObjFromThisPage (tbd_current_tree         &Current,
                         cbd910_PrimObjDataNode   &NptrsPage,
                         tsp00_Int4                KeyLen,
                         void                     *pKey,
                         tgg92_KernelOid          &OId,
                         tgg91_PageRef            &ResultObjVers);

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

static _INLINE void
bd90_NoteVersionErrorInKnldiag (ebd90_FunctionName  FunctionName,
                                tgg92_KernelOid     WantedOId,
                                tgg00_ObjFrameVers  ExpectedVersion);

/*---------------------------------------------------------------------------*/
/* PTS 1111513 13/12/2001 */
static void
bd90_ReadAheadFile (tgg00_TransContext &Trans,
                    cbd910_ObjNode     &NptrsPage);

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

static void
bd90_UpdateObjBody (tbd_current_tree         &Current,
                    tgg92_KernelOid           OId,
                    tgg91_PageRef             ObjVers,
                    tbd_nodeptr               pPage,
                    tbd900_ObjFrame          *pObjFrame,
                    tsp00_Int4                NewObjBodyLen,
                    void                     *pNewObjBody,
                    const Log_EntrySequence  &RedoEntrySequence,
                    const tgg91_TransNo      &RedoUpdTransNo);

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

static _INLINE tsp00_Int4
bd90_VarObjBodySize (tbd900_ObjFrame *pObjFrame);

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

static void
bd90_GetConsistentObjImage (tbd_current_tree        &Current,       //[in/out]
                            tgg92_KernelOid         &OId,           //[in/out] frame version may change
                            tgg91_PageRef           &ResultObjVers,
                            tgg91_PageRef           &ObjHistRef,               // PTS 1125316 FF
                            tsp00_Bool               bWithObject,
                            tsp00_Int4               ExtObjBodySize,
                            void                    *pExtObjBody,
                            cbd910_PrimObjDataNode  &NptrsPage,
                            tsp00_Int4              &ObjBodySize,             //[out=length of the object]
                            tsp00_Bool              &bConsistentObjImageObjFound,
                            tsp00_Int4              &LogReadAccesses) ;

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

// PTS 1119647 FF 2002-DEC-05
static pasbool 
bd90_IsDropped (tgg00_TransContext &Trans,
                tgg00_ObjFileNo     FileNo)
{
    pasbool bCancelled  = false;			/* PTS 1120151 FF 2003-JAN-29 */
    pasbool bConsistent = false;
    cbd900_ObjFileInfo    &ObjFileInfo = bd90ObjFileDir[FileNo];
    if ( ObjFileInfo.ofiRelFileIsReq_bd900 ) 
        bConsistent = true;    
    else if ( ObjFileInfo.ofiDropFile_bd900 ) 
        kb50ObjConsistentCheck (Trans, ObjFileInfo.ofiTransNo, bConsistent, bCancelled);
    return ( bConsistent && !bCancelled );
}

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

externCpp void 
bd90TransEnd(tgg00_TransContext   &Trans)
{
    if (NULL != Trans.trFreePagesForIns_gg00)
    {
        tgg00_BasisError      &TrError  = Trans.trError_gg00;
        CFreePageListHash& freePageList = 
            *reinterpret_cast<CFreePageListHash*>(Trans.trFreePagesForIns_gg00);
        CFreePageListHashIter Iter (freePageList);
        for  (Iter.bd920Begin(); !Iter.bd920End() ; ++Iter) 
        {   
            tsp00_PageNo PageNo = Iter()->PageNo();
            if (NIL_PAGE_NO_GG00 != PageNo)
            {
                cbd900_ObjFileInfo &ObjFileInfo = bd90ObjFileDir[Iter.bd920Key()];
                cbd05_Current Current(Trans, m_update);
                ObjFileInfo.bd900BuildFileId (Iter.bd920Key(), Current.curr_tree_id);

                const tsp00_PageNo  SubRoot   = ObjFileInfo.GetRootPage();
                if ( !(Iter()->PageReleased()) )
                {
                    cbd910_SubRootNode  NptrsSubRoot (Current, SubRoot, nr_for_update);
                    if (e_ok != TrError)
                    {
                        Kernel_OpWarning (csp3_bd_msg, csp3_n_obj)
                            << "bd90TransEnd access to subroot failed"
                            << " FileNo:" << Iter.bd920Key()
                            << " SubRoot:" << SubRoot
                            << " Error:" << TrError;
                        TrError = e_ok;
                    }

                    cbd910_PrimObjDataNode NptrsPage (Current, PageNo, nr_for_update);
                    if (e_ok != TrError)
                    {
                        Kernel_OpWarning (csp3_bd_msg, csp3_n_obj)
                            << "bd90TransEnd access to page failed"
                            << " FileNo:" << Iter.bd920Key()
                            << " Pageno:" << PageNo
                            << " Error:" << TrError;
                        TrError = e_ok;
                    }

                    if ( NptrsSubRoot.bd910PageIsAvailable())
                    {
                        const tsp00_Int4      ChainNo   = ObjFileInfo.bd900CurrChain();
                        cbd900_ObjChainInfo  &ChainInfo = ObjFileInfo[ChainNo];
                        NptrsSubRoot.bd910SetAllObjCnt (ChainInfo.GetAllObjCnt());
                        if ( NptrsPage.bd910PageIsAvailable())
                        {
                            NptrsPage.np_ptr()->nd_assigned_to_spec_trans() = 0; /* re-insert allowed */
                            NptrsSubRoot.bd910InsertPageIntoFreeChain (NptrsPage); 
                        }
                    }
                    else if ( NptrsPage.bd910PageIsAvailable())
                        NptrsPage.np_ptr()->nd_assigned_to_spec_trans() = 0; /* re-insert allowed */

                }
                Iter()->PageReleased() = false;
                Iter()->PageNo() = NIL_PAGE_NO_GG00;
            } 
        }
        freePageList.bd920DelAllItems(Trans.trTaskId_gg00);
    }
};

externCpp void
bd90CreateEntryInPersFileDirectory (tbd_current_tree &Current)
{
    tbd_fileinfo FileInfo;
    FileInfo.fi_type            = Current.curr_tree_id.fileType_gg00();
    FileInfo.fi_root            = Current.curr_tree_id.fileRoot_gg00();
    FileInfo.fi_vers            = Current.curr_tree_id.fileVersion_gg00();
    FileInfo.fi_col_cnt         = 0;
    FileInfo.fi_fill1           = 0;
    FileInfo.fi_var_col_cnt_pos = cgg_nil_varcol_cnt_off;
    FileInfo.fi_descr.clear();
    FileInfo.fi_state.clear();
    FileInfo.fi_user_ref.gg91SetNilRef ();

    /* insert file into file directory */
    b17add_fdir (Current.curr_tree_id.fileName_gg00(), FileInfo, *Current.curr_trans);

    if (e_ok !=  Current.curr_trans->trError_gg00)
    {
        b06write_filename_and_root (Current.curr_tree_id);
        g01abort (csp3_bd_msg, csp3_n_obj,
                  "BD90CreatPFDE: Error    ", Current.curr_trans->trError_gg00);
    }
}

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

externCpp void
bd90CreateObjFile (tbd_current_tree    &Current,
                   tsp00_Int4           ObjBodyLen,
                   tsp00_Int4           ObjKeyLen,
                   tsp00_Int4           NumObjKeyFiles,
                   LVC_RootPageNoArray &RootPageNoArray)
{
    ROUTINE_DBG_MEO00 ("bd90CreateObjFile");

    /* please if you change this function change the */
    /* function bd90Rollforward_CreateObjFile too    */

    tgg00_BasisError      &TrError    = Current.curr_trans->trError_gg00;
    int                    iChain;

    /* check precondition for calling this function */
    SAPDBERR_ASSERT_STATE (!Kernel_IAdminInfo::Instance().KernelStateIsRestart() ||
                           (PRIM_CONT_OBJ_FILE_NO_BD900 != Current.curr_tree_id.fileContObjFileNo_gg00()));

    /* check if there is sufficient space to create a new object file */
    Converter_IPageNoManager::Instance().HandleDBFull (*Current.curr_trans,
            MAX_NUM_CHAINS_PER_CONTAINER_BD900);
    if (e_ok != TrError) return;  // PTS 1107864 AK 15/09/2000

    /* create root page */
    cbd910_RootNode   NptrsRoot (Current, nr_for_update);
    NptrsRoot.bd910AssignToNewPage (ObjBodyLen, ObjKeyLen, NIL_PAGE_NO_GG00,
                                    FIRST_CHAIN_NO, MAX_LOCK_REQUEST_SEQ_NO_BD900);
    if (e_ok != TrError)
    {
        Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
        opErrMsg << "bd90CreateObjFile:bd910AssignToNewPage" << " error:" << TrError;
        return;
    }

    RootPageNoArray[0] = NptrsRoot.np_ptr()->nd_id();

    /* update file id */
    Current.curr_tree_id.fileNumObjKeyFiles_gg00() = NumObjKeyFiles;
    Current.curr_tree_id.fileRoot_gg00()           = NptrsRoot.np_ptr()->nd_id();
    bd300SetRootCheck (Current.curr_tree_id);

    /* create sub roots */
    cbd910_SubRootNode   NptrsSubRoot (Current, nr_for_update);
    cbd900_RootPageInfo  RootPageInfo (NptrsRoot);

    /* store the pageno again at the root page */
    RootPageInfo.bd900AddSubRoot (NptrsRoot.np_ptr()->nd_id());

    /* store the number of objekt key files for this file on the root page */
    RootPageInfo.bd900NumObjKeyFiles() = NumObjKeyFiles;

    /* introduce additional chains to the file */
    for (iChain=(FIRST_CHAIN_NO+1); (iChain < MAX_NUM_CHAINS_PER_CONTAINER_BD900) && (TrError == e_ok);  ++iChain)
    {
        /* create a new Subroot */
        NptrsSubRoot.bd910AssignToNewPage (ObjBodyLen, ObjKeyLen, NIL_PAGE_NO_GG00, iChain, MAX_LOCK_REQUEST_SEQ_NO_BD900);
        if (e_ok != TrError)
        {
            Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
            opErrMsg << "bd90CreateObjFile:bd910AssignToNewPage ichain:" 
                << iChain << " error:" << TrError;
            return;
        }
        
        RootPageNoArray[iChain] = NptrsSubRoot.np_ptr()->nd_id();
        
        /* store the pageno of the subroot at the root page */
        RootPageInfo.bd900AddSubRoot (NptrsSubRoot.np_ptr()->nd_id());
        
        /* since the file is not yet added to the ObjFileDir checks  */
        /* would find differences between the content of the subroot */
        /* and the ObjFileDir. PTS 1107145 AK 10/07/2000             */
        NptrsSubRoot.bd910ReleasePage();
    }

    /* insert the new file into the object file directory */
    if (PRIM_CONT_OBJ_FILE_NO_BD900 != Current.curr_tree_id.fileContObjFileNo_gg00())
        bd91AddFileToContObjFileDir (*Current.curr_trans, Current.curr_tree_id, NptrsRoot);
    else
    {
        bd91AddFileToObjFileDir     (*Current.curr_trans, Current.curr_tree_id, NptrsRoot);

        /* copy the number of continuation files which belong to this primary file from    */
        /* the continuation file directory to the root page in order to make it persistent */
        if (pt2VarObject_egg00 == NptrsRoot.np_ptr()->nd_pt2() && (e_ok == TrError))
            RootPageInfo.bd900NumContFiles() = bd93ContObjFileDir[NptrsRoot.np_ptr()->nd_obj_file_no()].cfiNumContFiles_bd900;
    }

    /* remove pages if the file existed already in the file directory */
    if (e_duplicate_filename == TrError)
    {
        TrError = e_ok;
        for (iChain=1; iChain < RootPageInfo.bd900NumChains(); ++iChain)
        {
            NptrsSubRoot.bd910AssignToPage (RootPageInfo.bd900SubRoot(iChain));
            NptrsSubRoot.bd910FreePage();
        }
        NptrsRoot.bd910FreePage();
        TrError = e_duplicate_filename;
    }
}

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

externCpp void
bd90Rollforward_CreateObjFile (tbd_current_tree          &Current,
                               tsp00_Int4                 ObjBodyLen,
                               tsp00_Int4                 ObjKeyLen,
                               tsp00_Int4                 NumObjKeyFiles,
                               const LVC_RootPageNoArray &RootPageNoArray)
{
    ROUTINE_DBG_MEO00 ("bd90Rollforward_CreateObjFile");

    /* please if you change this function change the */
    /* function bd90CreateObjFile too                */

    tgg00_BasisError      &TrError    = Current.curr_trans->trError_gg00;
    int                    iChain;
    tsp00_Bool             bPageGenerated;

    /* check that the roll forwad of a create takes place only during a restart */
    SAPDBERR_ASSERT_STATE (Kernel_IAdminInfo::Instance().KernelStateIsRestart());

    /* check if there is sufficient space to create a new object file */
    Converter_IPageNoManager::Instance().HandleDBFull (*Current.curr_trans,
            MAX_NUM_CHAINS_PER_CONTAINER_BD900);

    if (e_ok != TrError) return;  // PTS 1107864 AK 15/09/2000

    /* create root page */
    cbd910_PrimObjDataNode NptrsRoot (Current, nr_for_update);
    NptrsRoot.bd910AssignToNewSpecifiedPage (RootPageNoArray[0], bPageGenerated);
    if (TrError != e_ok )
    {
        Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
        opErrMsg << "bd90Rollforward_CreateObjFile(1): bd910AssignToNewSpecifiedPage failed! pno:"
        << RootPageNoArray[0] << " error:" << TrError;
        return;
    }

    if ((!bPageGenerated) &&
        /* PTS 1118489 FF 21-OCT-2002 check if REDO had already been partially done before */
        !(NptrsRoot.np_ptr()->nd_obj_file_no() == Current.curr_tree_id.fileObjFileNo_gg00()))
    {
        /* the page does not belong to the wanted file and has to     */
        /* be removed from the file currently owning the object frame */
        bd95RemovePageFromObjFile (*Current.curr_trans, NptrsRoot);
        if (TrError != e_ok )
        {
            Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
            opWarnMsg << "bd90Rollforward_CreateObjFile(2): bd95RemovePageFromObjFile failed! pno:"
            << RootPageNoArray[0] << " error:" << TrError;
            TrError = e_ok; //ignore all errors, may be too soft
        }

        /* reassign the wanted page */
        NptrsRoot.bd910AssignToNewSpecifiedPage (RootPageNoArray[0], bPageGenerated);
        if (TrError != e_ok )
        {
            Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
            opErrMsg << "bd90Rollforward_CreateObjFile(2): bd910AssignToNewSpecifiedPage failed! pno:"
            << RootPageNoArray[0] << " error:" << TrError;
            return;
        }

        SAPDBERR_ASSERT_STATE (bPageGenerated);

        if (!bPageGenerated)
        {
            Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
            opErrMsg << "bd90Rollforward_CreateObjFile(2): bd910AssignToNewSpecifiedPage (bPageGenerated == false) pno:"
            << RootPageNoArray[0];
            return;
        }
    }

    NptrsRoot.bd910InitObjPage (ObjBodyLen, ObjKeyLen, NIL_PAGE_NO_GG00,
                                FIRST_CHAIN_NO, MAX_LOCK_REQUEST_SEQ_NO_BD900);
    if (e_ok != TrError)
    {
        Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
        opErrMsg << "bd90Rollforward_CreateObjFile: bd910InitObjPage failed! pno:"
        << RootPageNoArray[0] << " error:" << TrError;
        return;
    }

    /* update file id */
    Current.curr_tree_id.fileNumObjKeyFiles_gg00() = NumObjKeyFiles;
    Current.curr_tree_id.fileRoot_gg00()           = NptrsRoot.np_ptr()->nd_id();
    bd300SetRootCheck (Current.curr_tree_id);

    /* create sub roots */
    cbd910_PrimObjDataNode   NptrsSubRoot (Current, nr_for_update);
    cbd900_RootPageInfo  RootPageInfo (NptrsRoot);

    /* store the pageno again at the root page */
    RootPageInfo.bd900AddSubRoot (NptrsRoot.np_ptr()->nd_id());

    /* store the number of objekt key files for this file on the root page */
    RootPageInfo.bd900NumObjKeyFiles() = NumObjKeyFiles;

    /* introduce additional chains to the file */
    for (iChain=(FIRST_CHAIN_NO+1); (iChain < MAX_NUM_CHAINS_PER_CONTAINER_BD900) && (TrError == e_ok);  ++iChain)
    {
        NptrsSubRoot.bd910AssignToNewSpecifiedPage (RootPageNoArray[iChain], bPageGenerated);
        if (TrError != e_ok )
        {
            Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
            opErrMsg << "bd90Rollforward_CreateObjFile(3): bd910AssignToNewSpecifiedPage failed! pno:"
            << RootPageNoArray[iChain] << " error:" << TrError;
            return;
        }

        if(!bPageGenerated)
        {
            /* the page does not belong to the wanted file and has to */
            /* be removed from the file it currently belongs to       */
            bd95RemovePageFromObjFile (*Current.curr_trans, NptrsSubRoot);
            if (TrError != e_ok )
            {
                Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
                opWarnMsg << "bd90Rollforward_CreateObjFile(3): bd95RemovePageFromObjFile failed! pno:"
                << RootPageNoArray[0] << " error:" << TrError;
                TrError = e_ok; //ignore all errors, may be too soft
            }

            /* reassign the wanted page */
            NptrsSubRoot.bd910AssignToNewSpecifiedPage (RootPageNoArray[iChain], bPageGenerated);
            if (TrError != e_ok )
            {
                Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
                opErrMsg << "bd90Rollforward_CreateObjFile(2): bd910AssignToNewSpecifiedPage failed! pno:"
                << RootPageNoArray[0] << " Error:" << TrError;
                return;
            }

            SAPDBERR_ASSERT_STATE (bPageGenerated);
        }
        NptrsSubRoot.bd910InitObjPage (ObjBodyLen, ObjKeyLen, NIL_PAGE_NO_GG00, iChain, MAX_LOCK_REQUEST_SEQ_NO_BD900);
        if (e_ok != TrError) return;

        /* store the pageno of the subroot at the root page */
        RootPageInfo.bd900AddSubRoot (NptrsSubRoot.np_ptr()->nd_id());

        /* since the file is not yet added to the ObjFileDir checks  */
        /* would find differences between the content of the subroot */
        /* and the ObjFileDir. PTS 1107145 AK 10/07/2000             */
        NptrsSubRoot.bd910ReleasePage();
    }

    /* insert the new file into the object file directory */
    {
        /* cast the root page which is here of the type cbd910_PrimObjDataNode to a cbd910_RootNode */
        cbd910_RootNode   Root (Current, nr_for_update);
        Root.bd910SetTo (NptrsRoot);
        if (PRIM_CONT_OBJ_FILE_NO_BD900 != Current.curr_tree_id.fileContObjFileNo_gg00())
            bd91AddFileToContObjFileDir (*Current.curr_trans, Current.curr_tree_id, Root);
        else
        {
            bd91AddFileToObjFileDir     (*Current.curr_trans, Current.curr_tree_id, Root);

            /* copy the number of continuation files which belong to this primary file from    */
            /* the continuation file directory to the root page in order to make it persistent */
            if (pt2VarObject_egg00 == NptrsRoot.np_ptr()->nd_pt2() && (e_ok == TrError))
                RootPageInfo.bd900NumContFiles() = bd93ContObjFileDir[NptrsRoot.np_ptr()->nd_obj_file_no()].cfiNumContFiles_bd900;
        }
    }

    /* an error like e_duplicate_filename cannot occur during  */
    /* a recovery therefore here is no treatment of this error */
}

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

externCpp void
bd90DelObj (tbd_current_tree       &Current,           //[inp\out]
            tgg92_KernelOid        &OId,               //[inp\out]
            tgg91_PageRef           WantedObjVers)     //[inp]
{
    ROUTINE_DBG_MEO00 ("bd90DelObj");

    /*  This routine marks an object as deleted, i.e. the state  */
    /*  it's state  switched to free after eot                   */

    tgg00_BasisError    &TrError = Current.curr_trans->trError_gg00;

    /* check if there is sufficient space to write rollback and history entries */
    Converter_IPageNoManager::Instance().HandleDBFull (*Current.curr_trans, 10);

    if (e_ok != TrError) return;  // PTS 1107864 AK 15/09/2000

    /*  get page pointer  */
    cbd910_PrimObjDataNode    NptrsPage (Current, OId.gg92GetPno(), nr_for_update);
    if (e_ok != TrError) return;

    // PTS 1119647 FF 2002-DEC-05
    const tgg00_ObjFileNo  FileNo      = NptrsPage.np_ptr()->nd_obj_file_no();
    cbd900_ObjFileInfo    &ObjFileInfo = bd90ObjFileDir[FileNo];
    if ( ObjFileInfo.ofiDropFile_bd900 ) 
    {
        TrError = e_container_dropped;
        return;
    }

    /* determine pointer to object frame */
    BD92CHECK_OID_POSITION ("BD90DelObj", TrError, OId, NptrsPage);

    tbd900_ObjFrame  *pObjFrame = NptrsPage.bd910ObjFramePtr (OId.gg92GetPos());

    /*  check object state  */
    if ((pObjFrame->objHeader_bd900.ohdState_gg92 != obsReserved_egg00    ) &&
            (pObjFrame->objHeader_bd900.ohdState_gg92 != obsKeyReserved_egg00 ) &&
            (pObjFrame->objHeader_bd900.ohdState_gg92 != obsOccupied_egg00   ))
    {
        TrError = e_wrong_object_state;
        return;
    }

    tgg00_ObjFrameVers newFrameVers = OId.gg92GetFrameVers();  // PTS XYZXYZ FF 2003-Dec-05

    /* check object version  */
    if (pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 != OId.gg92GetFrameVers())
    {
        /* PTS XYZXYZ FF 2003-Dec-05 for omsKeyedObjects FrameVersion may have */
        /*                           been incremented by upper layers          */
        if ( cbd900_ObjFileInfo::omsKeyedFile != ObjFileInfo.GetFileType())
        {
            TrError = e_wrong_object_version;
            bd90_NoteVersionErrorInKnldiag
                (Delete,OId,pObjFrame->objHeader_bd900.ohdFrameVersion_gg92);
            return;
        }
        else {  // PTS XYZXYZ FF 2003-Dec-05
            /* make sure, the right OID is written to undo/history entries */
            OId.gg92SetFrameVers(pObjFrame->objHeader_bd900.ohdFrameVersion_gg92);
        }
    }

    /* check if object is locked and create a log entry  */
    const bool  bPageIsForVarObj = (pt2VarObject_egg00 == NptrsPage.np_ptr()->nd_pt2());

    if (bPageIsForVarObj)
        bd93LogDelVarObj (Current, OId, WantedObjVers, NptrsPage.np_ptr(), pObjFrame);
    else
    {
        const int ObjBodySize = NptrsPage.np_ptr()->nd_obj_frame_len() - sizeof(tgg92_ObjHeader);

        kb67DelUpdObj (*Current.curr_trans, m_delete, Current.curr_tree_id,
                       OId, NptrsPage.np_ptr()->nd_obj_key_len(), WantedObjVers,
                       pObjFrame->objHeader_bd900, ObjBodySize, pObjFrame->objBody_bd900);
    }

    /* reset OID to original objFrameVers  PTS XYZXYZ FF 2003-Dec-05 */   
    OId.gg92SetFrameVers(newFrameVers);

    if (TrError != e_ok) {   
      if ((g01vtrace.vtrBdObject_gg00) || (g01vtrace.vtrOmsUpd_gg00 ))
        Kernel_VTrace() << __FILE__ << " : " << __LINE__ 
        << " DelObj Error:" << TrError
        << " Oid=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
        << " (vers " << OId.gg92GetFrameVers() << ")"
        << " ohdFrameVersion:" << pObjFrame->objHeader_bd900.ohdFrameVersion_gg92
        << " ObjVers" << WantedObjVers.gg91RefPno() << "." << WantedObjVers.gg91RefPos();
      return;
    }

    /* write OID.FrameVers into object frame PTS XYZXYZ FF 2003-Dec-05 */ 
    pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 = newFrameVers; 

    if (TrError != e_ok) return;

    /* mark the object as deleted  */
    pObjFrame->objHeader_bd900.ohdState_gg92.becomes(obsFreeAfterEot_egg00);

    /* update page header */
    ++NptrsPage.np_ptr()->nd_free_eot_obj_cnt();
    --NptrsPage.np_ptr()->nd_occ_obj_cnt();
}

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

externCpp void
bd90DelAllObj (tbd_current_tree  &Current,           //[inp\out]
               tsp00_Int4        &NumDelObj,
               tgg92_KernelOid   &ErrorOid)
{
    ROUTINE_DBG_MEO00 ("bd90DelAllObj");

    /* This routine marks all objects of the current file as deleted */
    /* Completely changed by PTS 1107145 AK 10/07/2000               */

    tgg00_BasisError         &TrError      = Current.curr_trans->trError_gg00;

    /* check if there is sufficient space to write rollback and history entries */
    Converter_IPageNoManager::Instance().HandleDBFull (*Current.curr_trans, 20);

    if (e_ok != TrError) return;  // PTS 1107864 AK 15/09/2000

    const tgg00_ObjFileNo FileNo      = Current.curr_tree_id.fileObjFileNo_gg00(); //PTS 1111901 AK 24/09/2001
    // PTS 1119647 FF 2002-DEC-05
    cbd900_ObjFileInfo   &ObjFileInfo = bd90ObjFileDir[FileNo];
    if ( ObjFileInfo.ofiDropFile_bd900 ) 
    {
        TrError = e_container_dropped;
        return;
    }

    const tsp00_PageNo       &FirstSubRoot = bd90ObjFileDir[FileNo][FIRST_CHAIN_NO].ociSubRoot_bd900;
    cbd910_PrimObjDataNode    NptrsPage (Current, FirstSubRoot, nr_for_update);
    if (e_ok != TrError)
    {
        Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
        opWarnMsg << "bd90DelAllObj - error:" << TrError
            << " accessing FirstSubRoot:" << FirstSubRoot
            << " fileno:" << FileNo;
        return;
    }

    /* initialize counters */
    NumDelObj = 0;

    /* go through all pages of the chain and delete all objects */
    do
    {
        /* delete objects on this page */
        bd90_DelAllObjOnThisPage (Current, NptrsPage, NumDelObj, ErrorOid);
        if (TrError != e_ok) return;

        /* move to next page */
        NptrsPage.bd910MoveToNextPage();

    } while ((e_ok == TrError) && NptrsPage.bd910PageIsAvailable());
}

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

externCpp void
bd90DropObjFile (tbd_current_tree   &Current)
{
    ROUTINE_DBG_MEO00 ("bd90DropObjFile");
    
    /* This function marks a file as to be deleted.                       */
    /* After calling this function no Update, Delete or Lock against      */
    /* objects of this file is valid.                                     */
    /* Read-only access is still possible for transactions using a        */
    /* consistent view older than the View used for dropping.             */
    /* physical delete of the file is triggered by the new history entry  */
    /* written and is done by the garbage collectors                      */
    
    tgg00_BasisError      &TrError             = Current.curr_trans->trError_gg00;
    const tgg00_ObjFileNo  FileNo              = Current.curr_tree_id.fileObjFileNo_gg00();
    cbd900_ObjFileInfo    &ObjFileInfo         = bd90ObjFileDir[FileNo];
    
    if ((ObjFileInfo.GetRootPage() != Current.curr_tree_id.fileRoot_gg00()) ||
        ObjFileInfo.ofiDropFile_bd900 ||
        !bd90ObjFileDir.bd920IsUsed(FileNo))
    {
        TrError = e_wrong_obj_file_id;
        return;
    }

    cbd910_RootNode   NptrsRoot (Current, Current.curr_tree_id.fileRoot_gg00(), nr_for_update);
    if (e_ok != TrError)
    {
        Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
        opErrMsg << "bd90DropObjFile - error:" << TrError
            << " accessing root:" << Current.curr_tree_id.fileRoot_gg00()
            << " fileno:" << Current.curr_tree_id.fileObjFileNo_gg00();
        return;
    }

    if ( gg06IsNilTrans (Current.curr_trans->trWriteTransId_gg00) )
        k50new_write_trans(*Current.curr_trans);
    ObjFileInfo.ofiTransNo            = Current.curr_trans->trWriteTransId_gg00;
    kb67DropContainer(*Current.curr_trans, FileNo);   /* needed to trigger GC to start with remove */

    ObjFileInfo.ofiDropFile_bd900     = true;

    /* mark the file as to be deleted */
	cbd900_RootPageInfo  RootPageInfo (NptrsRoot);      // PTS 1128266 FF 2004-03-05
	RootPageInfo.bd900FileIsDeleted() = true;           // PTS 1128266 FF 2004-03-05

}

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

externCpp void
bd90ResetObjLock (tbd_current_tree   &Current,
                  tgg92_KernelOid    &OId,
                  tgg91_TransNo       LockTransId,
                  tgg00_TransIndex    LockTransIndex,
				  tgg00_ObjFileNo     ObjFileNo)
{
    ROUTINE_DBG_MSP00 ("bd90ResetObjLock");

    tgg00_BasisError      &TrError   = Current.curr_trans->trError_gg00;

    /*  get page pointer  */
    cbd910_PrimObjDataNode   NptrsPage(Current, OId.gg92GetPno(),  nr_for_update);

    /* check if the page belongs to the right container  PTS 1106143 AK 29/03/2000 */
    if ((e_ok != TrError) || (ObjFileNo != NptrsPage.np_ptr()->nd_obj_file_no()))
    {
        TrError = e_ok;
        return;
    }

    /* determine pointer to object frame */
    BD92CHECK_OID_POSITION ("bd90ResetObjLock",TrError, OId, NptrsPage);

    tbd900_ObjFrame  *pObjFrame = NptrsPage.bd910ObjFramePtr (OId.gg92GetPos());

    if (pObjFrame->objHeader_bd900.ohdState_gg92 == obsFree_egg00)
        return;
    else
    {
        kb67ResetObjLock (*Current.curr_trans, LockTransId, LockTransIndex,
                          OId, pObjFrame->objHeader_bd900.ohdTransInfo_gg92);
    }
}

/*---------------------------------------------------------------------------*/
// PTS 1119647 FF 2002-DEC-05

externC void
bd90RemoveObjFile (tgg00_TransContext &Trans,
                   tgg00_ObjFileNo     ObjFileNo)
{
    /* This function marks a file and all its continuation files as to be */
    /* physically deleted and starts garbage collectors to do the work.   */
    /* It is called by: bd95Rollforward_DropObjFile during restart        */
    /*             and  Log_History::RemoveUndoFileWithObjects            */

    cbd05_Current          Current     (Trans, m_update);
    tgg00_BasisError      &TrError             = Trans.trError_gg00;
    cbd900_ObjFileInfo    &ObjFileInfo         = bd90ObjFileDir[ObjFileNo];
    const tsp00_Bool       bRemoveContObjFiles = 
        ( cbd900_ObjFileInfo::omsVariableFile == ObjFileInfo.GetFileType());
    ObjFileInfo.bd900BuildFileId (ObjFileNo, Current.curr_tree_id);

    if (!bd90ObjFileDir.bd920IsUsed(ObjFileNo))
    {
        Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
        opWarnMsg << "bd90RemoveObjFile - File not found ! Fileno:" << ObjFileNo;
        TrError = e_ok;
        return;
    }

    if ( Kernel_IAdminInfo::Instance().KernelStateIsRestart() )
        ObjFileInfo.ofiDropFile_bd900 = true;

    cbd910_RootNode   NptrsRoot (Current, ObjFileInfo.GetRootPage(), nr_for_update);
    if (e_ok != TrError)
    {
        Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
        opWarnMsg << "bd90RemoveObjFile - error:" << TrError
            << " accessing root:" << ObjFileInfo.GetRootPage()
            << " fileno:" << ObjFileNo;
        TrError = e_ok;
    }
    else
    {
        cbd900_RootPageInfo  RootPageInfo (NptrsRoot);

        /* mark the file as to be deleted */
        RootPageInfo.bd900FileIsDeleted() = true;
        NptrsRoot.bd910ReleasePage();

        /* FIRST: mark continuation files (if they exist at all) as to be deleted */
        if ((bRemoveContObjFiles) && !bd93ContObjFileDir.bd920IsUsed(ObjFileNo))
        {
            tbd_current_tree         ContCurrent (Current);
            cbd900_ContObjFileInfo & ContObjFileInfo = bd93ContObjFileDir[ObjFileNo];

            SAPDBERR_ASSERT_STATE (ContObjFileInfo.cfiNumContFiles_bd900 != 0);

            /* here one has to copy the number of continuation files into a local variable since after               */
            /* the last continuation file has been marked for release the gc could remove the files and              */
            /* also the corresponding entry in the continuation file directory  before the end condition of          */
            /* the following loop has been evaluated. But after the entry was removed the reference ContObjFileInfo  */
            /* is invalid and  the end  ondition in the following loop would get undefined if one would work         */
            /* with the number of continuation files found by using the referene vaiable ContObjFileInfo             */
            const tsp00_Int4 NumContFiles = ContObjFileInfo.cfiNumContFiles_bd900;

            for (int iContFileNo = 1; iContFileNo <=NumContFiles; ++iContFileNo)
            {

                tsp00_PageNo ContObjFileRoot = ContObjFileInfo[iContFileNo].GetRootPage();
                if (NIL_PAGE_NO_GG00 != ContObjFileRoot)
                {
                    ContObjFileInfo.bd900BuildFileId (ObjFileNo, iContFileNo, ContCurrent.curr_tree_id);

                    cbd910_RootNode   NptrsContRoot (ContCurrent, ContObjFileRoot, nr_for_update);
                    if (e_ok != TrError)
                    {
                        Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
                        opWarnMsg << "bd90RemoveObjFile - error:" << TrError
                            << " accessing cont root:" << ContObjFileRoot
                            << " ObjFileNo:" << ObjFileNo
                            << " cont fileno:" << iContFileNo;
                        TrError = e_ok;
                    }
                    else
                    {
                        cbd900_RootPageInfo  ContRootPageInfo (NptrsContRoot);                    
                        ContRootPageInfo.bd900FileIsDeleted() = true;
                        ContObjFileInfo[iContFileNo].ofiRelFileIsReq_bd900 = true;
                        NptrsContRoot.bd910ReleasePage();
                    }
                }
            }
        }

        /* start GCs and mark the file in the object file directory */
        bd91GarbCollController.bd930StartGCToRemoveFile(*Current.curr_trans, ObjFileInfo);        
    }
};


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

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

	if (g01is_livecache ()) 
	{
		tgg00_BasisError  MoveError = e_ok;
		bd90ObjFileDir.bd900DumpObjFileDir         (HostFile, BufferSize, Buffer, OutPno, OutPos, HostError, ErrText, MoveError);
		if (( MoveError != e_ok ) || (HostError != vf_ok))
			Kernel_OpError( csp3_bd_msg, csp3_n_obj )
			<< "bd90DumpObjFileDir file error:" << HostError
			<<  " move error:" << MoveError;
		MoveError = e_ok;

		bd93ContObjFileDir.bd900DumpContObjFileDir (HostFile, BufferSize, Buffer, OutPno, OutPos, HostError, ErrText, MoveError);
		if (( MoveError != e_ok ) || (HostError != vf_ok))
			Kernel_OpError( csp3_bd_msg, csp3_n_obj )
			<< "bd900DumpContObjFileDir file error:" << HostError
			<<  " move error:" << MoveError;
	}

}

/*---------------------------------------------------------------------------*/
// PTS 1125316
externCpp void
bd90GetContainerId (tbd_current_tree  &Current,            //[in\out]
                    tgg92_KernelOid    OId)                //[in]
{
    ROUTINE_DBG_MEO00 ("bd90GetContainerId ");

    tgg00_BasisError   &TrError = Current.curr_trans->trError_gg00;
    /* PTS 1118931 FF 14-Nov-2002 */
    if (NIL_PAGE_NO_GG00 == OId.gg92GetPno()) {
        TrError = e_invalid_oid;
        return;
    }

    /* get page pointer */
    cbd910_PrimObjDataNode   NptrsPage (Current, OId.gg92GetPno(), nr_for_read);
    if (e_ok != TrError) return;

    const tgg00_ObjFileNo  FileNo = NptrsPage.np_ptr()->nd_obj_file_no();
}

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

externCpp void
bd90GetObjConsistent (tbd_current_tree  &Current,            //[inp\out]
                      tgg92_KernelOid   &OId,                //[inp\out]
                      tsp00_Int4         ExtObjBodySize,     //[inp= buffersize for object]
                      void              *pExtObjBody,        //[inp]
                      tsp00_Int4         HashKeySize,        //[inp]
                      void              *pHashKey,           //[inp]
                      tsp00_Int4        &ObjBodySize,        //[out=length of the object]
                      tsp00_Int4        &KeyLen,             //[out]
                      tsp00_Byte*       *pKey,               //[out]
                      tgg91_PageRef     &ResultObjVers,       //[out]
                      tsp00_Int4        &LogReadAccesses)    //[out] PTS 1107819 AK 12/09/2000
{
    ROUTINE_DBG_MEO00 ("bd90GetObjConsistent");

    tgg00_BasisError    &TrError    = Current.curr_trans->trError_gg00;
    const bool          bWithObject = true;
    tgg91_PageRef       historyPageRef  = ResultObjVers;    // PTS 1125316 FF 2003-12-17
    ResultObjVers.gg91SetNilRef();                          // PTS 1116881 FF 2002-07-25
    LogReadAccesses                 = 0;                    

    /* PTS 1118931 FF 14-Nov-2002 */
    if (NIL_PAGE_NO_GG00 == OId.gg92GetPno()) {
        TrError = e_invalid_oid;
        return;
    }

    /*  get page pointer  */
    cbd910_PrimObjDataNode   NptrsPage (Current, OId.gg92GetPno(), nr_for_read);
    if (e_ok != TrError) return;

    // PTS 1119647 FF 2002-DEC-05
    if ( bd90_IsDropped( *Current.curr_trans, NptrsPage.np_ptr()->nd_obj_file_no() )) {
        TrError = e_container_dropped;
        return;
    }

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

    /* check the object state  */
    if (pObjFrame->objHeader_bd900.ohdState_gg92 == obsFree_egg00)
    {
        TrError = e_wrong_object_state;
        return;
    }

    /* set parameters needed for the search in the log */
    tgg00_ObjState     ObjState        = pObjFrame->objHeader_bd900.ohdState_gg92;
    tgg00_ObjTransInfo ObjTransInfo    = pObjFrame->objHeader_bd900.ohdTransInfo_gg92;
    tgg00_ObjFrameVers ResultFrameVers = pObjFrame->objHeader_bd900.ohdFrameVersion_gg92; //???NIL_OBJ_FRAME_VERS_GG92;

    /* get object body */
    const bool  bPageIsForVarObj = (pt2VarObject_egg00 == NptrsPage.np_ptr()->nd_pt2());

    if (bPageIsForVarObj)
    {
        ObjBodySize = bd90_VarObjBodySize (pObjFrame);
        bd93GetVarObjBody (Current, OId, ExtObjBodySize, pExtObjBody, pObjFrame);
    }
    else
    {
        /* If a key is defined the key length and the pointer at */
        /* key within the returned ObjBody are determined        */
        ObjBodySize  = NptrsPage.np_ptr()->nd_obj_frame_len() - sizeof(tgg92_ObjHeader);
        KeyLen = NptrsPage.np_ptr()->nd_obj_key_len();
        if (KeyLen > 0) *pKey = (tsp00_Byte*)pExtObjBody + ObjBodySize - KeyLen;

        /* if the OId is found with a key from the hash (displayed by HashKeyLen>0)  */
        /* the key in the object and the key used for searching in the hash have     */
        /* to be equal                                                               */
        if (HashKeySize > 0)
        {
            BD90_CHECK_KEY_SIZE (TrError, HashKeySize, KeyLen);

            const void *pKeyInObjFrame = pObjFrame->objBody_bd900 + ObjBodySize - KeyLen;

            if (memcmp (pHashKey, pKeyInObjFrame, KeyLen))
            {
                TrError = e_wrong_object_version;
                if ((g01vtrace.vtrBdObject_gg00) || (g01vtrace.vtrOmsGet_gg00 ))
                    Kernel_VTrace() << __FILE__ << " : " << __LINE__ 
                    << " Error:" << TrError  
                    << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                    << " (vers " << OId.gg92GetFrameVers() << ")"
                    << " key doesn't match";  
                return;
            }
        }
        /*  move object and key into output array assigned by pExtObjBody */
        if ( historyPageRef.gg91IsNilRef()) {  // PTS 1124797 FF 2003-10-22
            bd90_GetObjBody (*Current.curr_trans, OId, NptrsPage.np_ptr(),
                ExtObjBodySize, pExtObjBody, pObjFrame);
        } else {
            /* copy key only */
            const tsp00_Uint2   KeyLen      = NptrsPage.np_ptr()->nd_obj_key_len();
            const tsp00_Int4    ObjBodySize = NptrsPage.np_ptr()->nd_obj_frame_len() - sizeof(tgg92_ObjHeader);
            SAPDB_RangeMove( __FILE__, 1,
                PAGE_MXSP00 - sizeof (tgg00_PageCheckTrailer),
                ExtObjBodySize,
                NptrsPage.np_ptr(),
                OId.gg92GetPos() + POS_OFF_DIFF_BD00 + sizeof (tgg92_ObjHeader) + ObjBodySize - KeyLen,
                pExtObjBody, 1 + ObjBodySize - KeyLen,
                KeyLen,
                TrError);
            if (TrError != e_ok) {return;}
        }
    }
    if (TrError != e_ok)  return;

    /*  the current object may be inconsistent with the wanted view        */
    /*  which consists of objects commited before the current              */
    /*  transaction had been started in that case the old object image has */
    /*  to be restored from the log. Now  the  current page is released    */
    /*  since the check if the object is consistent and the search for the */
    /*  old image of the object takes places at the log pages and not here */

    /*  release page pointer  */
    NptrsPage.bd910ReleasePage();

    /*  the log pages are searched for the right image    */
    tgg91_PageRef     ObjHistRef;       // unused parameter PTS 1125316 FF
    if ( !historyPageRef.gg91IsNilRef()) {
        kb67GetBeforeImage (*Current.curr_trans, OId, historyPageRef,
            bWithObject, KeyLen, ObjBodySize, ExtObjBodySize, pExtObjBody,
            ResultFrameVers, ResultObjVers, ObjHistRef, LogReadAccesses);   
    }
    else
        kb67GetObjConsistent (*Current.curr_trans, OId, ObjState, ObjTransInfo,
        bWithObject, KeyLen, ObjBodySize, ExtObjBodySize, pExtObjBody,
        ResultFrameVers, ResultObjVers, ObjHistRef, LogReadAccesses);   
    if (TrError != e_ok)  return;                                            

    if ( !historyPageRef.gg91IsNilRef() &&
        historyPageRef != ObjHistRef ) 
    {
        Kernel_OpError( csp3_bd_msg, csp3_n_obj )
            << "bd90GetObjConsistent: History PageNo in:" <<  historyPageRef.gg91RefPno()
            << " PagePos in::" << historyPageRef.gg91RefPos()
            << " PageNo out:"  << ObjHistRef.gg91RefPno()
            << " PagePos out:" << ObjHistRef.gg91RefPos()
            << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
            << " (vers " << OId.gg92GetFrameVers() << ")" 
            << " KeyLen:" << KeyLen
            << " ObjBodySize:" << ObjBodySize;
                   
        eo670_CTraceStack();

        ResultObjVers.gg91SetNilRef();
        bd90GetObjConsistent (Current, OId, ExtObjBodySize, pExtObjBody, HashKeySize,
            pHashKey, ObjBodySize, KeyLen, pKey, ResultObjVers, LogReadAccesses);
        return;
    }

    if (HashKeySize > 0)
    {
        // set OId version, because it is wrong, if it is coming from the
        // key-management
        OId.gg92SetFrameVers (ResultFrameVers);
    }
    else
    {
        /*  check the object version */
        if (OId.gg92GetFrameVers() != ResultFrameVers)
        {
            TrError = e_wrong_object_version;
            if ((g01vtrace.vtrBdObject_gg00) || (g01vtrace.vtrOmsGet_gg00 ))
                Kernel_VTrace() << __FILE__ << " : " << __LINE__ 
                << " Error:" << TrError  
                << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                << " (vers " << OId.gg92GetFrameVers() << ")"
                << " found Vers:" << ResultFrameVers;    
            bd90_NoteVersionErrorInKnldiag(GetCons, OId, ResultFrameVers);
        }
    }

    /* PTS 1120322 FF 2003-Feb-07*/
    if ((TrError == e_ok) &&
        ((ObjState == obsReserved_egg00) || 
        (ObjState == obsKeyReserved_egg00)) &&
        (LogReadAccesses == 0) &&
        (ObjTransInfo.otrUpdTransId_gg00 != Current.curr_trans->trWriteTransId_gg00))
    {
        if ( 0 == g_Committed_obsReserved_Cnt )                    
        {                                                                       
            g_Committed_obsReserved_Cnt++;
            Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                << "Committed object frame without stored data ( state: obsReserved ) found";
        }
        Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
        opWarnMsg << "bd90GetObjConsistent: object within state:"; 
        if (ObjState == obsReserved_egg00)
            opWarnMsg << "obsReserved_egg00"; 
        else
            opWarnMsg << "obsKeyReserved_egg00"; 
        opWarnMsg << " read, but not created by this trans!"
            << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
            << " (vers " << OId.gg92GetFrameVers() << ")"
            << " (page dumped to file d" 
            << OId.gg92GetPno() <<".obj)"; 
        cbd910_PrimObjDataNode   NptrsPage (Current, OId.gg92GetPno(), nr_for_read);
        if( TrError != e_ok) return;
        b06dump_bad_page (Current.curr_trans->trTaskId_gg00,'d', ".obj", 
            NptrsPage.np_ptr()->nd_id(), (void *) NptrsPage.np_ptr(), 1);
        TrError = e_too_old_oid;
    }
}

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

externCpp void
bd90GetObjConsistentWithLock (tbd_current_tree  &Current,            //[inp\out]
                              tgg92_KernelOid   &OId,                //[inp\out]
                              tsp00_Int4         ExtObjBodySize,     //[inp= buffersize for object]
                              void              *pExtObjBody,        //[inp]
                              tsp00_Int4         HashKeySize,        //[inp]
                              void              *pHashKey,           //[inp]
                              tsp00_Int4        &ObjBodySize,        //[out=length of the object]
                              tsp00_Int4        &KeyLen,             //[out]
                              tsp00_Byte*       *pKey,               //[out]
                              tgg91_PageRef     &ResultObjVers,      //[out]
                              tsp00_Int4        &LogReadAccesses)    //[out] PTS 1107819 AK 12/09/2000
{
    ROUTINE_DBG_MEO00 ("bd90GetObjConsistentWithLock");

    tgg00_BasisError   &TrError         = Current.curr_trans->trError_gg00;

    const bool          bDontGetObject  = false;
    tsp00_Bool          bConsistent;
    tsp00_Bool          bCancelled;			/* PTS 1120151 FF 2003-JAN-29 */

    /* PTS 1107819 AK 12/09/2000; note: only in case of the error=e_object_dirty        */
    /* a value for LogReadAccesses will be returned which is not zero will be returned  */
    LogReadAccesses                     = 0;

    Converter_IPageNoManager::Instance().HandleDBFull (*Current.curr_trans, 1);

    if (e_ok != TrError) return;

    /* PTS 1118931 FF 14-Nov-2002 */
    if (NIL_PAGE_NO_GG00 == OId.gg92GetPno()) {
        TrError = e_invalid_oid;
        return;
    }

    /* get page pointer */
    cbd910_PrimObjDataNode   NptrsPage (Current, OId.gg92GetPno(), nr_for_update);
    if (e_ok != TrError) return;

    // PTS 1119647 FF 2002-DEC-05
    const tgg00_ObjFileNo  FileNo      = NptrsPage.np_ptr()->nd_obj_file_no();
    cbd900_ObjFileInfo    &ObjFileInfo = bd90ObjFileDir[FileNo];
    if ( ObjFileInfo.ofiDropFile_bd900 ) 
    {
        TrError = e_container_dropped;
        return;
    }

    if ( ! ResultObjVers.gg91IsNilRef()) {  // PTS 1124797 FF 2003-10-22
       TrError = e_object_dirty;             // you can't lock history !
       return;
    }

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

    /* check the object state  */
    switch (pObjFrame->objHeader_bd900.ohdState_gg92)
    {
    case obsFree_egg00 :
        TrError = e_wrong_object_state;
        return;
    case obsFreeAfterEot_egg00 :
        tgg00_ObjFrameVers  ResultFrameVers = NIL_OBJ_FRAME_VERS_GG92;
        tgg91_PageRef       ObjHistRef;       // unused parameter PTS 1125316 FF
        kb67GetObjConsistent (*Current.curr_trans, OId, pObjFrame->objHeader_bd900.ohdState_gg92,
                              pObjFrame->objHeader_bd900.ohdTransInfo_gg92, bDontGetObject, KeyLen, ObjBodySize,
                              ExtObjBodySize, pExtObjBody, ResultFrameVers, ResultObjVers, ObjHistRef, LogReadAccesses);  
        if (e_ok == TrError) 
            TrError = e_object_dirty;
        return;
    }

    /* check object frame version */
    const tgg00_ObjFrameVers & CurrFrameVers = pObjFrame->objHeader_bd900.ohdFrameVersion_gg92;
    ObjBodySize = NptrsPage.np_ptr()->nd_obj_frame_len() - sizeof(tgg92_ObjHeader);
    KeyLen      = NptrsPage.np_ptr()->nd_obj_key_len();
    if (KeyLen > 0) *pKey = (tsp00_Byte*)pExtObjBody + ObjBodySize - KeyLen;

    if (HashKeySize > 0)
    {
        /* if the OId is found with a key from the hash (displayed by HashKeyLen>0)  */
        /* the key in the object and the key used for searching in the hash have     */
        /* to be equal                                                               */

        BD90_CHECK_KEY_SIZE (TrError, HashKeySize, KeyLen);
        const void *pKeyInObjFrame = pObjFrame->objBody_bd900 + ObjBodySize - KeyLen;

        if (memcmp (pHashKey, pKeyInObjFrame, KeyLen))
        {
            TrError = e_wrong_object_version;
            if ((g01vtrace.vtrBdObject_gg00) || (g01vtrace.vtrOmsGet_gg00 ))
                Kernel_VTrace() << __FILE__ << " : " << __LINE__ 
                << " Error:" << TrError 
                << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                << " (vers " << OId.gg92GetFrameVers() << ")"
                << " key doesn't match";    
            return;
        }
        OId.gg92SetFrameVers (CurrFrameVers);
    }
    else
    {
        if (CurrFrameVers != OId.gg92GetFrameVers())
        {
            TrError = e_wrong_object_version;
            if ((g01vtrace.vtrBdObject_gg00) || (g01vtrace.vtrOmsGet_gg00 ))
                Kernel_VTrace() << __FILE__ << " : " << __LINE__ 
                << " Error:" << TrError  
                << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                << " (vers " << OId.gg92GetFrameVers() << ")"
                << " found Vers:" << CurrFrameVers;    
            return;
        }
    }

	/* check if the current object version is consistent with this view*/
	tgg00_ObjTransInfo & ObjTransInfo = pObjFrame->objHeader_bd900.ohdTransInfo_gg92;
	kb50ObjConsistentCheck (*Current.curr_trans, ObjTransInfo.otrUpdTransId_gg00, bConsistent,
		bCancelled);
    //                      without otrBeforeRef:  PTS 1105492 JA 2000-03-15
	if (bCancelled) /* PTS 1120151 FF 2003-JAN-29 */
	{
		Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
		opWarnMsg << "cancelled ConsistView:";
		for (int i=0; i < sizeof(Current.curr_trans->trConsistView_gg00); i++)
			opWarnMsg << ToStr((SAPDB_UInt1)Current.curr_trans->trConsistView_gg00[i], _T_h);
		opWarnMsg << " found";
		TrError = e_consview_cancelled;
	}
    if (e_ok != TrError) return;

    /* return if the consistent version does not correspond to the current version */
    if (!bConsistent)
    {
        TrError = e_object_dirty;
        return;
    }

    /* lock object */
    ResultObjVers = ObjTransInfo.otrBeforeRef_gg00;
    kb67LockObj (*Current.curr_trans, Current.curr_tree_id, OId, ResultObjVers,
                 pObjFrame->objHeader_bd900.ohdState_gg92, pObjFrame->objHeader_bd900.ohdTransInfo_gg92);
    if (e_ok != TrError) return;

    /* get object body */
    if (pt2VarObject_egg00 == NptrsPage.np_ptr()->nd_pt2())
    {
        ObjBodySize = bd90_VarObjBodySize (pObjFrame);
        bd93GetVarObjBody (Current, OId, ExtObjBodySize, pExtObjBody, pObjFrame);
    }
    else
    {
        ObjBodySize  = NptrsPage.np_ptr()->nd_obj_frame_len() - sizeof(tgg92_ObjHeader);
        bd90_GetObjBody (*Current.curr_trans, OId, NptrsPage.np_ptr(),ExtObjBodySize, pExtObjBody, pObjFrame);
    }

    /* PTS 1120322 FF 2003-Feb-07*/
    if ((e_ok == TrError) &&
        ((pObjFrame->objHeader_bd900.ohdState_gg92 == obsReserved_egg00) || 
        (pObjFrame->objHeader_bd900.ohdState_gg92 == obsKeyReserved_egg00)) &&
        (LogReadAccesses == 0) &&
        (pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrUpdTransId_gg00 != 
        Current.curr_trans->trWriteTransId_gg00))
    {
        if ( 0 == g_Committed_obsReserved_Cnt )                    
        {                                                                       
            g_Committed_obsReserved_Cnt++;
            Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                << "Committed object frame without stored data ( state: obsReserved ) found";
        }
        Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
        opWarnMsg << "bd90GetObjConsistent: object within state:"; 
        if (pObjFrame->objHeader_bd900.ohdState_gg92 == obsReserved_egg00)
            opWarnMsg << "obsReserved_egg00"; 
        else
            opWarnMsg << "obsKeyReserved_egg00"; 
        opWarnMsg << " read, but not created by this trans!" 
            << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
            << " (vers " << OId.gg92GetFrameVers() << ")"
            << " (page dumped to file d" 
            << OId.gg92GetPno() <<".obj)"; 
        b06dump_bad_page (Current.curr_trans->trTaskId_gg00,'d', ".obj", 
            NptrsPage.np_ptr()->nd_id(), (void *) NptrsPage.np_ptr(), 1);
        TrError = e_too_old_oid;
    }
}

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

externCpp void
bd90GetObjFileStatistics (tbd_current_tree   &Current,
                          tsp00_Int4         &NumAllPages,
                          tsp00_Int4         &NumFreePages,
                          tsp00_Int4         &NumEmptyPages,
                          tsp00_Int4         &NumKeyLeaves,        /* PTS 1107153 AK 17/07/2000 */
                          tsp00_Int4         &Occupancy)           /* PTS 1107153 AK 17/07/2000 */
{

    ROUTINE_DBG_MEO00 ("bd90GetObjFileStatistics");

    /* initialize counters */
    NumAllPages   = 0;
    NumFreePages  = 0;
    NumEmptyPages = 0;
    NumKeyLeaves  = 0;

    const tgg00_ObjFileNo   ObjFileNo   = Current.curr_tree_id.fileObjFileNo_gg00(); //PTS 1111901 AK 24/09/2001
    cbd900_ObjFileInfo     &ObjFileInfo = bd90ObjFileDir[ObjFileNo];

    cbd911RecreateIndexLock lock(*Current.curr_trans);   
    if (( ObjFileInfo.bd900RecreateIndex()) && (ObjFileInfo.GetKeyPartitionCount() > 0 ))
        lock.Lock(false /*not exclusive*/);

    /* check input */
    if ((ObjFileNo < MIN_OBJ_FILE_NO_GG92)  ||
            (ObjFileNo > MAX_OBJ_FILE_NO_GG92)  ||
            (ObjFileInfo.ofiRelFileIsReq_bd900) ||
            (ObjFileInfo.GetRootPage() == NIL_PAGE_NO_GG00))
    {
        Current.curr_trans->trError_gg00 = e_wrong_class_id;
    }

    /* go trough all subroots of the file and sum the page counters */
    for (int iChain=0; iChain<ObjFileInfo.GetChainCount(); ++iChain)
    {
        NumAllPages     += ObjFileInfo[iChain].ociAllPageCnt_bd900;
        NumFreePages    += ObjFileInfo[iChain].ociFreePageCnt_bd900;
    }

    /* add continuation pages */
    if (cbd900_ObjFileInfo::omsVariableFile == ObjFileInfo.GetFileType())
    {
        /* initialize counters */
        int NumAllContPages     = 0;
        int NumFreeContPages    = 0;
        int NumEmptyContPages   = 0;

        bd93GetContObjFileStatistics (Current, NumAllContPages, NumFreeContPages, NumEmptyContPages);

        NumAllPages   += NumAllContPages;
        NumEmptyPages += NumEmptyContPages;
        NumFreePages  += NumFreeContPages;
    }

    /* get number of leaves from the key tree  PTS 1107153 AK 17/07/2000 */
    if (ObjFileInfo.GetKeyPartitionCount()>0)
    {
        /* PTS 1118554 FF 2002-10-25                                             */
        /* prevent ObjFileInfo.ofiKeyRoots_bd900 to be modified when in use      */
        vbegexcl (Current.curr_trans->trTaskId_gg00, g08garbage); /* PTS 1118554 FF 2002-10-25 */
        bd22GetLeaveCountOfObjKeyFiles (*Current.curr_trans, ObjFileNo, ObjFileInfo, NumKeyLeaves);
        vendexcl (Current.curr_trans->trTaskId_gg00, g08garbage); /* PTS 1118554 FF 2002-10-25 */
    }

    /* determines the average occupancy rate (in %) of the pages of this file */
    tsp00_Longreal NumOccPages  = ObjFileInfo.bd900NumOccPages(); // tsp00_Int4 PTS 1114534 FF 2002-02-28
    tsp00_Int4     NumAllPages2 = ObjFileInfo.bd900NumAllPages();

    if (cbd900_ObjFileInfo::omsVariableFile == ObjFileInfo.GetFileType())
    {
        /* add contributions of continuation files */
        cbd900_ContObjFileInfo & ContObjFileInfo = bd93ContObjFileDir[ObjFileNo];
        for (int iContFileNo=1;iContFileNo <= ContObjFileInfo.cfiNumContFiles_bd900; ++iContFileNo)
        {
            NumOccPages  += ContObjFileInfo[iContFileNo].bd900NumOccPages();
            NumAllPages2 += ContObjFileInfo[iContFileNo].bd900NumAllPages();
        }
    }

    if (NumAllPages > 0)
    {
        Occupancy = STATIC_CAST(tsp00_Int4,(NumOccPages/NumAllPages)); // PTS 1114534 FF 2002-02-28
        if ( 100 < Occupancy )    // Occupancy is based on 'dirty' counted ociAllObjCnt_bd900
            Occupancy = 100;        // PTS 1114534 FF 2002-02-28
    }
    else
        Occupancy = 0;

    /* check if the numbers of pages from the objfiledir and the subroots are equal */
#   if COMPILEMODE_MEO00 >= QUICK_MEO00 
    if (NumAllPages != NumAllPages2)
    {
        g01opmsg (sp3p_knldiag, sp3m_warning, csp3_bd_msg, csp3_n_obj,
                  "bd90Stat:odd AllPageCnt", ObjFileNo);
        g01opmsg (sp3p_knldiag, sp3m_warning, csp3_bd_msg, csp3_n_obj,
                  "bd90Stat: AllPageCnt1 =", NumAllPages);
        g01opmsg (sp3p_knldiag, sp3m_warning, csp3_bd_msg, csp3_n_obj,
                  "bd90Stat: AllPageCnt2 =", NumAllPages2);
    }
#   endif
}

/*----------------------------------------------------------------------------*/
/* CRS 1106284 AK 11-03-2000 */

externCpp void
bd90IsObjHistoryUsed (tbd_current_tree &Current,
                      tgg92_KernelOid   &OId,
                      bool              &bHistoryIsUsed)
{
    ROUTINE_DBG_MEO00 ("bd90IsObjSelfLocked");

    tgg00_BasisError  &TrError = Current.curr_trans->trError_gg00;

    /*  get page pointer  */
    cbd910_PrimObjDataNode  NptrsPage (Current, OId.gg92GetPno(),  nr_for_read);
    if (TrError != e_ok) return;

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

    /* begin * PTS XYZXYZ FF 2003-Dec-05
    if (pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 != OId.gg92GetFrameVers())
    {
        TrError = e_wrong_object_version;
        bd90_NoteVersionErrorInKnldiag
        (Lock, OId, pObjFrame->objHeader_bd900.ohdFrameVersion_gg92);
        return;
    }
    * end * PTS XYZXYZ FF 2003-Dec-05 */

    /* check object state */
    if (pObjFrame->objHeader_bd900.ohdState_gg92 != obsOccupied_egg00)
    {
        TrError = e_wrong_object_state;
        return;
    }

    bHistoryIsUsed =
        kb67IsObjHistoryUsed (*Current.curr_trans, OId, pObjFrame->objHeader_bd900.ohdTransInfo_gg92);
}

/*----------------------------------------------------------------------------*/
/* PTS 1001745 UH 23-11-1998 new */

externCpp void
bd90IsObjSelfLocked (tbd_current_tree   &Current,
                     tgg92_KernelOid    &OId,
                     bool               &IsSelfLocked)
{
    ROUTINE_DBG_MEO00 ("bd90IsObjSelfLocked");

    tgg00_BasisError  &TrError = Current.curr_trans->trError_gg00;

    IsSelfLocked = false;

    /*  get page pointer  */
    cbd910_PrimObjDataNode  NptrsPage (Current, OId.gg92GetPno(),  nr_for_read);
    if (e_ok != TrError) return;

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

    /*  check the object version */
    if (pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 != OId.gg92GetFrameVers())
    {
        TrError = e_wrong_object_version;
        bd90_NoteVersionErrorInKnldiag
        (Lock, OId, pObjFrame->objHeader_bd900.ohdFrameVersion_gg92);
        return;
    }

    /* check object state */
    if (pObjFrame->objHeader_bd900.ohdState_gg92 == obsFree_egg00)
    {
        TrError = e_wrong_object_state;
        return;
    }

    kb50CheckObjSelfLocked (*Current.curr_trans, OId, pObjFrame->objHeader_bd900.ohdTransInfo_gg92);

    /* PTS 1001769 Torsten Strahl 1998-11-30 */
    if (e_ok == TrError)
        IsSelfLocked = true;
    else
        if (e_object_not_locked == TrError)
            TrError = e_ok;
}

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

externCpp void
bd90LockObj (
    tbd_current_tree   &Current,
    tgg92_KernelOid    &OId,
    tgg91_PageRef       WantedObjVers
)

{
    // NOTE! if this function returns e_wait_for_lock_release then wait outside bd-locking

    ROUTINE_DBG_MEO00 ("bd90LockObj");

    tgg00_BasisError    &TrError = Current.curr_trans->trError_gg00;


    Converter_IPageNoManager::Instance().HandleDBFull (*Current.curr_trans, 1);

    if (e_ok != TrError) return;

    /*  get page pointer  */
    cbd910_PrimObjDataNode    NptrsPage(Current, OId.gg92GetPno(),  nr_for_update);
    if (e_ok != TrError) return;

    // PTS 1119647 FF 2002-DEC-05
    const tgg00_ObjFileNo  FileNo      = NptrsPage.np_ptr()->nd_obj_file_no();
    cbd900_ObjFileInfo    &ObjFileInfo = bd90ObjFileDir[FileNo];
    if ( ObjFileInfo.ofiDropFile_bd900 ) 
    {
        TrError = e_container_dropped;
        return;
    }

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

    /*  check object version  */
    if (pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 != OId.gg92GetFrameVers())
    {
        TrError = e_wrong_object_version;
    }
    else
    {
        switch (pObjFrame->objHeader_bd900.ohdState_gg92)
        {
        case obsFree_egg00 :
            TrError = e_wrong_object_state;
            break;
        /* case obsFreeAfterEot_egg00 :    PTS 1135716
            TrError = e_object_dirty;
            break; */
        default :
            kb67LockObj (*Current.curr_trans, Current.curr_tree_id, OId, WantedObjVers,
                         pObjFrame->objHeader_bd900.ohdState_gg92,
                         pObjFrame->objHeader_bd900.ohdTransInfo_gg92);
        }
    }
}

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

externCpp void
bd90LockUpdObj (
    tbd_current_tree   &Current,
    tgg92_KernelOid    &OId,
    tgg91_PageRef       WantedObjVers
)

{
    ROUTINE_DBG_MEO00 ("bd90LockUpdObj");

    tgg00_BasisError    &TrError = Current.curr_trans->trError_gg00;

    Converter_IPageNoManager::Instance().HandleDBFull (*Current.curr_trans, 1);

    if (e_ok != TrError) return;

    /*  get page pointer  */
    cbd910_PrimObjDataNode    NptrsPage(Current, OId.gg92GetPno(),  nr_for_update);
    if (TrError != e_ok) return;

    // PTS 1119647 FF 2002-DEC-05
    const tgg00_ObjFileNo  FileNo      = NptrsPage.np_ptr()->nd_obj_file_no();
    cbd900_ObjFileInfo    &ObjFileInfo = bd90ObjFileDir[FileNo];
    if ( ObjFileInfo.ofiDropFile_bd900 ) 
    {
        TrError = e_container_dropped;
        return;
    }

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

    /*  check object version  */
    if (pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 != OId.gg92GetFrameVers())
    {
        TrError = e_wrong_object_version; 
    }
    else
    {
        switch (pObjFrame->objHeader_bd900.ohdState_gg92)
        {
        case obsFree_egg00 :
            TrError = e_wrong_object_state;
            break;
        case obsFreeAfterEot_egg00 :
            TrError = e_object_dirty;
            break;
        default :
            kb67LockUpdateObj (*Current.curr_trans, Current.curr_tree_id, OId, WantedObjVers,
                               pObjFrame->objHeader_bd900,
                               pObjFrame->objHeader_bd900.ohdTransInfo_gg92);
        }
    }
}

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

externCpp void
bd90NewObj (tbd_current_tree        &Current,                  // [in\out]
            tsp00_Int4              &FrameLen,                 // [out]
            tsp00_Int4               KeyLen,                   // [in]
            void                    *pKey,                     // [in]
            tgg92_KernelOid         &ResultOId,                // [out]
            tgg91_PageRef           &ResultObjVers)            // [out]
{
    ROUTINE_DBG_MEO00 ("bd90NewObj");

    /*  This function yields a new OId. First it tries to get    */
    /*  the new OId from the free chain. If it does not find     */
    /*  a new OId in this chain a new page is included into the  */
    /*  object file and an OId from this page is served          */

    tgg00_BasisError      &TrError  = Current.curr_trans->trError_gg00;
    tgg00_TransContext    &Trans    = *Current.curr_trans;

    // PTS 1119647 FF 2002-DEC-05
    const tgg00_ObjFileNo  FileNo   = Current.curr_tree_id.fileObjFileNo_gg00();

    CFreePageListEntry&   FreePageCacheListEntry = bd90_GetCachedFreePage(Trans, FileNo);
    tsp00_PageNo          CacheFreePage = FreePageCacheListEntry.PageNo();
    if (!FreePageCacheListEntry.PageReleased() && (NIL_PAGE_NO_GG00 != CacheFreePage))
    {
        cbd910_PrimObjDataNode   NptrsPage   (Current, CacheFreePage, nr_for_update);
        if (e_ok != TrError)
        {
            Kernel_OpError ( csp3_bd_msg, csp3_n_obj )
                << "bd90NewObj:cached freepage access error" << TrError
                << " PageNo:" << CacheFreePage;
            return;
        }

        /* set return parameter */
        FrameLen  = NptrsPage.np_ptr()->nd_obj_frame_len();

        cbd900_ObjFileInfo &ObjFileInfo = bd90ObjFileDir[NptrsPage.np_ptr()->nd_obj_file_no()];
        const tsp00_Int4      ChainNo   = ObjFileInfo.bd900CurrChain();
        cbd900_ObjChainInfo  &ChainInfo = ObjFileInfo[ChainNo];
        ChainInfo.IncrementAllObjCnt();

        bd90_NewObjFromThisPage (Current, NptrsPage, KeyLen, pKey, ResultOId, ResultObjVers);
        if (NptrsPage.np_ptr()->nd_first_free_obj() == NIL_OBJ_PAGE_POS_GG92)
        {
            NptrsPage.np_ptr()->nd_assigned_to_spec_trans() = 0; /* allow chaining by GC */
            NptrsPage.bd910ReleasePage();
            FreePageCacheListEntry.PageReleased() = true;
        }
    }
    else
    {
        cbd900_ObjFileInfo &ObjFileInfo = bd90ObjFileDir[FileNo];
        if ( !bd90ObjFileDir.bd920IsUsed(FileNo) || ObjFileInfo.ofiDropFile_bd900 ) 
        {
            TrError = e_wrong_class_id;
            return;
        }

        /* check if there is sufficient space to get a new  object frame, */
        /* a rollback entry and to insert a new key into the key tree     */
        Converter_IPageNoManager::Instance().HandleDBFull (*Current.curr_trans, 10);

        if (e_ok != TrError) return;  // PTS 1107864 AK 15/09/2000

        cbd910_PrimObjDataNode   NptrsPage    (Current, nr_for_update);

        /* find the chain (i.e. subroot) where the new object should be inserted */
        const tsp00_Int4       ChainNo   = ObjFileInfo.bd900CurrChain();
        cbd900_ObjChainInfo   &ChainInfo = ObjFileInfo[ChainNo];
        const tsp00_PageNo     SubRoot   = ChainInfo.ociSubRoot_bd900;

        cbd910_SubRootNode  NptrsSubRoot (Current, SubRoot, nr_for_update);
        if (e_ok != TrError)
        {
            Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
            opErrMsg << "bd90NewObj:damaged page chain"
                << " FileNo:" << FileNo
                << " ChainNo:" << ChainNo
                << " CurrSubRoot:" << SubRoot
                << " Error:" << TrError;
            return;
        }

#       if COMPILEMODE_MEO00 >= QUICK_MEO00 
        /* check if this subroot page belongs really to this file */
        if ((NptrsSubRoot.np_ptr()->nd_root()        != ObjFileInfo.GetRootPage()) ||
            (NptrsSubRoot.np_ptr()->nd_obj_file_no() != FileNo)                    ||
            (NptrsSubRoot.np_ptr()->nd_sub_root()    != SubRoot)                   ||
            (NptrsSubRoot.np_ptr()->nd_chain_no()    != ChainNo))
        {
            g01abort (csp3_bd_msg, csp3_n_obj,
                "BD90_NewObj:wrong SRoot ", NptrsSubRoot.np_ptr()->nd_id());
        }
#       endif

        /* set return parameter */
        FrameLen  = NptrsSubRoot.np_ptr()->nd_obj_frame_len();

        bool bSubrootReleased  = false; /*PTS 1130940 ff*/
        bool noChainToFreelist = true;  

        /* get page handle for the first page with free objects */
        /* CRS 1106534 Alexander Kley 2000-05-11                */
#       ifdef STORE_OBJECTS_ON_SUBROOT_BD900
        if (NptrsSubRoot.np_ptr()->nd_free_obj_cnt() > 0)
            NptrsPage.bd910SetTo (NptrsSubRoot);
        else
#       endif
        {
            bool bNewAllocatedPage = false;
            if (NIL_PAGE_NO_GG00 != NptrsSubRoot.np_ptr()->nd_next_free())
            {
                NptrsPage.bd910AssignToPage(NptrsSubRoot.np_ptr()->nd_next_free());
            }
            else
            {
                bNewAllocatedPage = true;
                NptrsPage.bd910AssignToNewPageInDataChain (NptrsSubRoot, noChainToFreelist);
                if ((1 == NptrsPage.np_ptr()->nd_free_obj_cnt()) && (e_ok != TrError)) 
                    NptrsSubRoot.bd910InsertPageIntoFreeChain (NptrsPage);
            }
            if (e_ok != TrError) return;

            ChainInfo.IncrementAllObjCnt();
            NptrsSubRoot.bd910SetAllObjCnt (ChainInfo.GetAllObjCnt());

            /* PTS 1130940 FF check if chaining will be needed anymore >>= else release subroot */
            if ((NptrsPage.np_ptr()->nd_free_obj_cnt() > 1)) 
            {
                if (bNewAllocatedPage || (NptrsPage.np_ptr()->nd_free_obj_cnt() > 2))
                {
                    NptrsPage.np_ptr()->nd_assigned_to_spec_trans() = 1; /* no re-insert into freechain */
                    if (FreePageCacheListEntry.PageReleased())
                    {
                        FreePageCacheListEntry.PageNo() = NptrsPage.np_ptr()->nd_id();
                        FreePageCacheListEntry.PageReleased() = false;
                    }
                    else
                    {
                        if (!bd90_PutCachedFreePage(Trans, FileNo, NptrsPage.np_ptr()->nd_id()))
                        {
                            NptrsPage.np_ptr()->nd_assigned_to_spec_trans() = 0;
                            if (NptrsPage.bd910PageMustBeInsertedIntoFreeChain())
                                NptrsSubRoot.bd910InsertPageIntoFreeChain (NptrsPage);   
                            if (NptrsPage.np_ptr()->nd_in_free_chain())
                            {
                                NptrsSubRoot.bd910ReleasePage();
                                bSubrootReleased = true;
                            }
                        }
                    }
                    if (!NptrsPage.np_ptr()->nd_in_free_chain())
                    {
                        NptrsSubRoot.bd910ReleasePage();
                        bSubrootReleased = true;
                    }
                }
                else if (NptrsPage.np_ptr()->nd_in_free_chain())
                {
                    NptrsSubRoot.bd910ReleasePage();
                    bSubrootReleased = true;
                }
            }
        }

        /* get a new OId and initialize the corresponding object */
        bd90_NewObjFromThisPage (Current, NptrsPage, KeyLen, pKey, ResultOId, ResultObjVers);
        if (e_ok != TrError) 
        {
            if (bSubrootReleased)  /* PTS 1130940 FF */
            {
                NptrsPage.bd910ReleasePage();
                NptrsSubRoot.bd910AssignToPage(SubRoot);
                if (e_ok != TrError) return;
                ChainInfo.DecrementAllObjCnt();
                NptrsSubRoot.bd910SetAllObjCnt (ChainInfo.GetAllObjCnt());
            }
            return;
        }

        if (! bSubrootReleased)  /* PTS 1130940 FF */
        {
            if (NptrsPage.np_ptr()->nd_in_free_chain() && NptrsPage.np_ptr()->nd_assigned_to_spec_trans())
                NptrsSubRoot.bd910RemovePageFromFreeChain(NptrsPage);
            /* remove page from free page chain if there are no more free object frame on the page */
            NptrsSubRoot.bd910RestoreFreePageChain (NptrsPage, ChainInfo);
        }

#       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()
                << " free_chain:" << NptrsPage.np_ptr()->nd_in_free_chain()
                << " free_cnt:" << NptrsPage.np_ptr()->nd_free_obj_cnt()
                << " bad FreeCount";
            g01abort (csp3_bd_msg, csp3_n_obj, "Wrong free page chain   ", 0);
        }
#       endif
    }
}

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

externCpp void
bd90NextObjConsistent (tbd_current_tree       &Current,
                       tgg92_KernelOid        &OId,
                       bool                    bWithObject,
                       tsp00_Int4              ExtObjBodySize,
                       void                   *pExtObjBody,
                       tsp00_Int4             &ObjBodySize,         //[out=length of the object]
                       tgg91_PageRef          &ObjVers,
                       tsp00_Int4             &AllLogReadAccesses)  //[out] PTS 1107819 AK 12/09/2000
{
    // NOTE! if this function returns e_wait_for_lock_release then wait outside bd-locking

    ROUTINE_DBG_MEO00 ("bd90NextObjConsistent");

    tgg00_BasisError      &TrError         = Current.curr_trans->trError_gg00;
    tsp00_Bool             bNextObjIsFound = false;
    cbd910_PrimObjDataNode NptrsPage(Current, nr_for_read);
    tsp00_Int4             LogReadAccessesPerPage;   // PTS 1107819 AK 12/09/2000

    /*---------------------------------*/
    /*  find starting page for search  */
    /*---------------------------------*/

    if (!OId.gg92IsNil() )
    {
        /* if OID is not nil look for object following the given OID  */
        NptrsPage.bd910AssignToPage(OId.gg92GetPno());
        if (e_ok != TrError) return;

        // PTS 1119647 FF 2002-DEC-05
        if ( bd90_IsDropped( *Current.curr_trans, NptrsPage.np_ptr()->nd_obj_file_no() )) {
            TrError = e_container_dropped;
            return;
        }
        
        /* check fileno and state of input object */
        BD92CHECK_OID_POSITION ("bd90NextObjConsistent",TrError, OId, NptrsPage);
        tbd900_ObjFrame *pObjFrame = NptrsPage.bd910ObjFramePtr (OId.gg92GetPos());

        if (pObjFrame->objHeader_bd900.ohdState_gg92 == obsFree_egg00)
        {
            Kernel_OpWarning  opErrMsg( csp3_bd_msg, csp3_n_obj );
            opErrMsg << "bd90NextObjConsistent:Invalid iterator!"
            << " State:obsFree"
            << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
            << " (vers " << OId.gg92GetFrameVers() << ")";

            /* note: The previous check is very simple in principle one              */
            /*       should even check if the input OId belongs to an object which   */
            /*       owns a consistent image with respect to the current transaction */

            TrError = e_wrong_object_state;
            return;
        }
    }
    else
    {
        /*  look for very first object in file, which  */
        /*  should be on the  subroot                  */
        const tgg00_ObjFileNo  FileNo  = Current.curr_tree_id.fileObjFileNo_gg00(); //PTS 1111901 AK 24/09/2001
        const tsp00_PageNo     SubRoot = bd90ObjFileDir[FileNo][FIRST_CHAIN_NO].ociSubRoot_bd900;

        // PTS 1119647 FF 2002-DEC-05
        if ( bd90_IsDropped( *Current.curr_trans, FileNo )) {
            TrError = e_container_dropped;
            return;
        }

        NptrsPage.bd910AssignToPage(SubRoot);
        if (e_ok != TrError) return;
    }

    /*-------------------------------------------------*/
    /*  start looping over chains and pages of chains  */
    /*-------------------------------------------------*/

    /* loop over  object page */
    do
    {
        tgg91_PageRef          ObjHistRef;              // unused parameter PTS 1125316 FF
        /*  look for the next object on current page  */
        bd90NextObjConsistentOnThisPage  (Current, OId, ObjVers, ObjHistRef, bWithObject, ExtObjBodySize,
                                          pExtObjBody, NptrsPage, ObjBodySize, bNextObjIsFound, LogReadAccessesPerPage);

        /* accumulalte the number of read accesses to object history pages; PTS 1107819 AK 12/09/2000 */
        AllLogReadAccesses += LogReadAccessesPerPage;

        /* return immediately if the next object is found */
        if (bNextObjIsFound || TrError != e_ok) return;

        /* check if the command has been canceled. PTS 1105431 Alexander Kley 25/01/2000 */
        if (Current.curr_trans->trRteCommPtr_gg00->to_cancel)
        {
            TrError = e_cancelled;
            break;
        }

        /* reset OId and  goto next page */
        OId.gg92SetNil();
        NptrsPage.bd910MoveToNextPage();
    }
    while ((e_ok == TrError) && NptrsPage.bd910PageIsAvailable());
    /* end of loop over pages */

    /* nothing was found */
    OId.gg92SetNil();
    if (e_ok == TrError)
        TrError = e_no_next_object;
}

/*---------------------------------------------------------------------------*/
// PTS 1125316
externCpp void
bd90NextOidsConsistent (tbd_current_tree       &Current,
                        const tgg92_KernelOid  &CurrOid,
                        tsp00_Int4             &noOfOid,
                        tgg92_KernelOid        *pOid,
                        tgg91_PageRef          *pObjHistRef,
                        tsp00_Int4             &AllLogReadAccesses)  
{
    // NOTE! if this function returns e_wait_for_lock_release then wait outside bd-locking
    // within bd90_GetConsistentObjImage lock timeout is set to 0 therefore 
    // e_wait_for_lock_release won't be returned anymore                    FF 2003-Apr-01

    ROUTINE_DBG_MEO00 ("bd90NextOidsConsistent");

    tgg00_BasisError      &TrError         = Current.curr_trans->trError_gg00;
    tsp00_Bool             bNextObjIsFound = false;
    cbd910_PrimObjDataNode NptrsPage(Current, nr_for_read);
    tsp00_Int4             LogReadAccessesPerPage;   

    const tgg00_ObjFileNo  FileNo  = Current.curr_tree_id.fileObjFileNo_gg00();     
    if ( bd90_IsDropped( *Current.curr_trans, FileNo )) { 
        TrError = e_container_dropped;
        return;
    }

    /*---------------------------------*/
    /*  find starting page for search  */
    /*---------------------------------*/

    bool      bSkipShortVarObjects  = true;
    const int MaxPartialObjectLen   = 8072;

    if (!CurrOid.gg92IsNil() )
    {
        /* if OID is not nil look for object following the given OID  */
        NptrsPage.bd910AssignToPage(CurrOid.gg92GetPno());
        if (e_ok != TrError) return;

        /* check fileno and state of input object */
        BD92CHECK_OID_POSITION ("bd90NextOidsConsistent",TrError, CurrOid, NptrsPage);
        tbd900_ObjFrame *pObjFrame = NptrsPage.bd910ObjFramePtr (CurrOid.gg92GetPos());

        if (pObjFrame->objHeader_bd900.ohdState_gg92 == obsFree_egg00)
        {
            Kernel_OpWarning  opErrMsg( csp3_bd_msg, csp3_n_obj );
            opErrMsg << "bd90NextOidsConsistent:Invalid iterator!"
                << " State:obsFree"
                << " OID=" << CurrOid.gg92GetPno() << "." << CurrOid.gg92GetPos()
                << " (vers " << CurrOid.gg92GetFrameVers() << ")";

            /* note: The previous check is very simple in principle one              */
            /*       should even check if the input OId belongs to an object which   */
            /*       owns a consistent image with respect to the current transaction */

            TrError = e_wrong_object_state;
            return;
        }
        if (pt2VarObject_egg00 == NptrsPage.np_ptr()->nd_pt2())
        {
            if ((pObjFrame->objHeader_bd900.ohdState_gg92 == obsReserved_egg00) ||
                (pObjFrame->objHeader_bd900.ohdState_gg92 == obsKeyReserved_egg00))
                bSkipShortVarObjects = false;
            else
            {
                tsp00_Int4  ObjBodySize     = bd90_VarObjBodySize (pObjFrame);
                tsp00_Int4  ExtObjBodySize  = ObjBodySize;
                void       *pExtObjBody     = 0;
                tgg00_ObjFrameVers ResultFrameVers = pObjFrame->objHeader_bd900.ohdFrameVersion_gg92;
                tgg91_PageRef               ResultObjVers;
                tgg91_PageRef               ObjHistRef;
                ObjHistRef.gg91SetNilRef();
                tsp00_Int4                  LogReadAccesses;

                kb67GetObjConsistent (*Current.curr_trans, CurrOid,
                    pObjFrame->objHeader_bd900.ohdState_gg92,
                    pObjFrame->objHeader_bd900.ohdTransInfo_gg92,
                    false /*bWithObject*/, 0 /*ObjKeyLen*/, ObjBodySize, ExtObjBodySize, pExtObjBody,
                    ResultFrameVers,
                    ResultObjVers,
                    ObjHistRef,                       // PTS 1125316 FF
                    LogReadAccesses);  
                if (e_ok != TrError) 
                    return;
                if (ObjBodySize < 8072)
                    bSkipShortVarObjects = false;
            }
        }
    }
    else
    {
        /*  look for very first object in file, which  */
        /*  should be on the  subroot                  */
        const tsp00_PageNo     SubRoot = bd90ObjFileDir[FileNo][FIRST_CHAIN_NO].ociSubRoot_bd900;
        NptrsPage.bd910AssignToPage(SubRoot);
        if (e_ok != TrError) return;
    }

    /*-------------------------------------------------*/
    /*  start looping over chains and pages of chains  */
    /*-------------------------------------------------*/

    // loop over object page 
    tsp00_Int4 maxNoOfOid = noOfOid;
    noOfOid = 0;
    pOid[0] = CurrOid;
    bool bVarContainer = (pt2VarObject_egg00 == NptrsPage.np_ptr()->nd_pt2());

    do {
    while (noOfOid < maxNoOfOid && TrError == e_ok) {
        //  look for the next object on current page  
        tsp00_Int4    ObjBodySize;     
        do {
        ObjBodySize = 0;              
        tgg91_PageRef ObjVers;         // unused parameter PTS 1125316 FF
        bd90NextObjConsistentOnThisPage  (Current, 
                                          pOid[noOfOid], 
                                          ObjVers,      // PTS 1125316 FF
                                          pObjHistRef[noOfOid], 
                                          false, //bWithObject, 
                                          0,     //ExtObjBodySize,
                                          NULL,  //pExtObjBody, 
                                          NptrsPage, 
                                          ObjBodySize, 
                                          bNextObjIsFound, 
                                          LogReadAccessesPerPage);
        } while (bNextObjIsFound && bVarContainer && ( bSkipShortVarObjects != ( ObjBodySize == MaxPartialObjectLen)));

        // accumulalte the number of read accesses to object history pages; PTS 1107819 AK 12/09/2000 
        AllLogReadAccesses += LogReadAccessesPerPage;
        if (TrError == e_ok)
        {
          if (bNextObjIsFound) {
            if ((g01vtrace.vtrBdObject_gg00) || (g01vtrace.vtrOmsGet_gg00 )) {
              Kernel_VTrace vtrace;
              vtrace << "OidIter-NextOid="
                << pOid[noOfOid].gg92GetPno() << "." << pOid[noOfOid].gg92GetPos()
                << " (vers " << pOid[noOfOid].gg92GetFrameVers() << ")"
                << " ObjVers:";
              if (pObjHistRef[noOfOid].gg91IsNilRef())
                vtrace << " NilRef";
              else
                vtrace << pObjHistRef[noOfOid].gg91RefPno() 
                << "." << pObjHistRef[noOfOid].gg91RefPos();
            }
            // Object was found on this page. Therefore increment number of objects read 
            // and initialize next buffer element with last oid 
            ++noOfOid;
            if (noOfOid < maxNoOfOid){
              pOid[noOfOid] = pOid[noOfOid-1];
            }
          }
          else if (!bNextObjIsFound){
            // No (further) object was found on this page. 
            // Reset current oid and goto next page
            pOid[noOfOid].gg92SetNil();
            NptrsPage.bd910MoveToNextPage();
            if (!NptrsPage.bd910PageIsAvailable()){
              // There is no next page in the page chain, so all objects have been read
              TrError = e_no_next_object;
              break;
            }
          } 
          
          // check if the command has been canceled. PTS 1105431 Alexander Kley 25/01/2000 
          if (Current.curr_trans->trRteCommPtr_gg00->to_cancel){
            TrError = e_cancelled;
            break;
          }
        }
    }
    if (bVarContainer && (e_no_next_object == TrError) && bSkipShortVarObjects)
    {
        bSkipShortVarObjects = false;
        TrError = e_ok;
        const tsp00_PageNo     SubRoot = bd90ObjFileDir[FileNo][FIRST_CHAIN_NO].ociSubRoot_bd900;
        NptrsPage.bd910AssignToPage(SubRoot);
        if (e_ok != TrError) return;
    }
    } while ((e_ok == TrError) && (noOfOid < maxNoOfOid)); 
}

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

externCpp void
bd90NextObjFromKeyIterator (tgg00_TransContext         &Trans,
                            LVC_AbstractObjKeyIterator &KeyIterator,
                            bool                        bInclusive,   
                            tsp00_Int4                  KeyLen, 
                            tsp00_Int4                  objBodySize,
                            void                       *pRestartKey,  
                            tsp00_Int4                 &noOfOid,
                            tgg92_KernelOid            *pResultOId,
                            tgg91_PageRef              *pResultObjVers,
                            tsp00_Int4                 &LogReadAccesses,
                            tsp00_MoveObj              *pObjBody)    
{
    ROUTINE_DBG_MEO00 ("bd90NextObjFromKeyIterator");

    tgg00_BasisError &TrError                      = Trans.trError_gg00;
    tsp00_Int4        LogReadAccessesForThisObject = 0;
    tsp00_Bool        bConsistentObjImageObjFound  = false;
    
    // PTS 1119480
    if (!KeyIterator.AscendingKeyOrder()){  
      KeyIterator.ChangeDirection(pRestartKey, 
                                  true);  // bAscendingKeyOrder
    }

    // PTS 1119647 FF 2002-DEC-05
    if ( bd90_IsDropped(Trans, KeyIterator.GetObjFileId().fileObjFileNo_gg00()) ) {
        TrError = e_container_dropped;
        return;
    }

    // PTS 1134645
 	cbd900_ObjFileInfo    &ObjFileInfo = bd90ObjFileDir [KeyIterator.GetObjFileId().fileObjFileNo_gg00()];
 	cbd911RecreateIndexLock lock(Trans);   
 	if (ObjFileInfo.bd900RecreateIndex()) 
 		lock.Lock( false /*not Exclusive*/ );

    cbd05_Current  Current(Trans, m_update, KeyIterator.GetObjFileId());

    // Remember number of maximal Oids (size of the return array)
    tsp00_Int4 maxNoOfOid = noOfOid;
    noOfOid = 0;
    while (!KeyIterator.IsEmpty()) {
      noOfOid = maxNoOfOid;
      KeyIterator.GetNextOIds(pRestartKey, pResultOId, noOfOid, bInclusive);        

      int i,j;
      for (i=0,j=0; i<noOfOid; ++i){
        cbd910_PrimObjDataNode   NptrsPage (Current, pResultOId[i].gg92GetPno(), nr_for_read);
        if(TrError != e_ok) {
          /* PTS 1121757 FF 24-Apr-2003 */
          if ((e_page_in_wrong_tree == TrError) || (e_no_converter_entry == TrError))
          {
            TrError = e_ok;
            continue;   // Skip Oid
          }
          Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
          opErrMsg << "bd90NextObjFromKeyIterator-1-: error:" << TrError
                   << " Fileno:" << KeyIterator.GetObjFileId().fileObjFileNo_gg00()
                   << " OID=" << pResultOId[i].gg92GetPno() << "." << pResultOId[i].gg92GetPos()
                   << " (vers " << pResultOId[i].gg92GetFrameVers() << ")";
          noOfOid = 0;
          return;
        }

        tgg91_PageRef   ObjHistRef;  // not used parameter PTS 1125316 FF
        tsp00_Int4 objBodyLen;

        /* with PTS 1129992 use of mass operations have been reduced                     */
        /* in case the object body is delivered, the otrBeforeRef_gg00 Pointer is needed */
        /* for further operation on this object ( omsLock, omsStore, ... )               */
        /* in case that no body is delivered, a history position is returned to enable   */
        /* following omsDeref Operations by the iterator to be handled faster.           */
        if (pObjBody == NULL)
            bd90_GetConsistentObjImage (Current, 
                                        pResultOId[i], 
                                        ObjHistRef,
                                        pResultObjVers[i],   // return History position
                                        (pObjBody != NULL),  // bWithObject       
                                        objBodySize,               
                                        pObjBody,           
                                        NptrsPage, 
                                        objBodyLen, 
                                        bConsistentObjImageObjFound,
                                        LogReadAccessesForThisObject);
        else
            bd90_GetConsistentObjImage (Current, 
                                        pResultOId[i], 
                                        pResultObjVers[i],   // return BeforeRef
                                        ObjHistRef,
                                        (pObjBody != NULL),  // bWithObject       
                                        objBodySize,               
                                        pObjBody,           
                                        NptrsPage, 
                                        objBodyLen, 
                                        bConsistentObjImageObjFound,
                                        LogReadAccessesForThisObject);
        LogReadAccesses += LogReadAccessesForThisObject;

        if(TrError != e_ok) {  // PTS 1124380
          Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
          opErrMsg << "bd90NextObjFromKeyIterator:-2- error:" << TrError
                   << " Fileno:" << KeyIterator.GetObjFileId().fileObjFileNo_gg00()
                   << " OID=" << pResultOId[i].gg92GetPno() << "." << pResultOId[i].gg92GetPos()
                   << " (vers " << pResultOId[i].gg92GetFrameVers() << ")";
          noOfOid = 0;
          return;
        }
      
        if (bConsistentObjImageObjFound){
          if (i != j){
            // Compress array with OIds
            pResultOId[j]     = pResultOId[i];
            pResultObjVers[j] = pResultObjVers[i];
          }
          if ((g01vtrace.vtrBdObject_gg00) || (g01vtrace.vtrOmsGet_gg00 )) {
            Kernel_VTrace vtrace;
            vtrace << "KeyIter-NextOid="
              << pResultOId[j].gg92GetPno() << "." << pResultOId[j].gg92GetPos()
              << " (vers " << pResultOId[j].gg92GetFrameVers() << ")"
              << " ObjVers:";
            if (pResultObjVers[j].gg91IsNilRef())
              vtrace << " NilRef";
            else
              vtrace << pResultObjVers[j].gg91RefPno() 
              << "." << pResultObjVers[j].gg91RefPos();
          }
          ++j;
        }
        else {
          // Skip Oid
          //pResultOId[i].gg92SetNil();
        }
      }
      noOfOid = j;
      if (noOfOid > 0) {
        // There is at least one OID found
        break;
      }
      else {
        // Read next portion of OIds from kernel. The last key is remembered
        // in the iterator and if the pRestartKey equals NULL, then this locally
        // remembered key is used instead.
        pRestartKey = NULL;
        bInclusive  = false;  // PTS 1130216; otherwise if noOfOid=1 the same object 
                              //              is read ever and ever again      
      }
    }

    if (e_ok == TrError && KeyIterator.IsEmpty()){
      TrError = e_no_next_object;
    }
}

/*---------------------------------------------------------------------------*/
// PTS 1119480
externCpp void
bd90PrevObjFromKeyIterator (tgg00_TransContext         &Trans,
                            LVC_AbstractObjKeyIterator &KeyIterator,
                            bool                        bInclusive,   
                            tsp00_Int4                  KeyLen,  
                            tsp00_Int4                  objBodySize,
                            void                       *pRestartKey,  
                            tsp00_Int4                 &noOfOid,
                            tgg92_KernelOid            *pResultOId,
                            tgg91_PageRef              *pResultObjVers,
                            tsp00_Int4                 &LogReadAccesses,
                            tsp00_MoveObj              *pObjBody)   
{
    ROUTINE_DBG_MEO00 ("bd90PrevObjFromKeyIterator");

    tgg00_BasisError &TrError                      = Trans.trError_gg00;
    tsp00_Int4        LogReadAccessesForThisObject = 0;
    tsp00_Bool        bConsistentObjImageObjFound  = false;
    
    if (KeyIterator.AscendingKeyOrder()){  // PTS 1119480
      KeyIterator.ChangeDirection(pRestartKey, 
                                  false);  // bAscendingKeyOrder
    }

    // PTS 1119647 FF 2002-DEC-05
    if ( bd90_IsDropped(Trans, KeyIterator.GetObjFileId().fileObjFileNo_gg00()) ) {
        TrError = e_container_dropped;
        return;
    }
    
    // PTS 1134645
 	cbd900_ObjFileInfo    &ObjFileInfo = bd90ObjFileDir [KeyIterator.GetObjFileId().fileObjFileNo_gg00()];
 	cbd911RecreateIndexLock lock(Trans);   
 	if (ObjFileInfo.bd900RecreateIndex()) 
 		lock.Lock( false /*not Exclusive*/ );

    cbd05_Current  Current(Trans, m_update, KeyIterator.GetObjFileId());

    // Remember number of maximal Oids (size of the return array)
    tsp00_Int4 maxNoOfOid = noOfOid;
    noOfOid = 0;
    while (!KeyIterator.IsEmpty()) {
      noOfOid = maxNoOfOid;
      KeyIterator.GetPrevOIds(pRestartKey, pResultOId, noOfOid, bInclusive);        

      int i,j;
      for (i=0,j=0; i<noOfOid; ++i){
        cbd910_PrimObjDataNode   NptrsPage (Current, pResultOId[i].gg92GetPno(), nr_for_read);
        if(TrError != e_ok) {
          /* PTS 1121757 FF 24-Apr-2003 */
          if ((e_page_in_wrong_tree == TrError) || (e_no_converter_entry == TrError))
          {
            TrError = e_ok;
            continue;   // Skip Oid
          }
          Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
          opErrMsg << "bd90NextObjFromKeyIterator: error:" << TrError
                   << " Fileno:" << KeyIterator.GetObjFileId().fileObjFileNo_gg00()
                   << " OID=" << pResultOId[i].gg92GetPno() << "." << pResultOId[i].gg92GetPos()
                   << " (vers " << pResultOId[i].gg92GetFrameVers() << ")";
          return;
        }

        tsp00_Int4      ResultObjBodySize;
        tgg91_PageRef   ObjHistRef;  // not used parameter PTS 1125316 FF

        /* with PTS 1129992 use of mass operations have been reduced                     */
        /* in case the object body is delivered, the otrBeforeRef_gg00 Pointer is needed */
        /* for further operation on this object ( omsLock, omsStore, ... )               */
        /* in case that no body is delivered, a history position is returned to enable   */
        /* following omsDeref Operations by the iterator to be handled faster.           */
        if (pObjBody == NULL)
            bd90_GetConsistentObjImage (Current, 
                                        pResultOId[i], 
                                        ObjHistRef,         
                                        pResultObjVers[i],   // return History position
                                        (pObjBody != NULL),  // bWithObject
                                        objBodySize,               
                                        pObjBody,            
                                        NptrsPage, 
                                        ResultObjBodySize, 
                                        bConsistentObjImageObjFound,
                                        LogReadAccessesForThisObject);
        else
            bd90_GetConsistentObjImage (Current, 
                                        pResultOId[i], 
                                        pResultObjVers[i],   // return BeforeRef
                                        ObjHistRef,
                                        (pObjBody != NULL),  // otrBeforeRef_gg00
                                        objBodySize,               
                                        pObjBody,            
                                        NptrsPage, 
                                        ResultObjBodySize, 
                                        bConsistentObjImageObjFound,
                                        LogReadAccessesForThisObject);
        LogReadAccesses += LogReadAccessesForThisObject;
      
        if (bConsistentObjImageObjFound){
          if (i != j){
            // Compress array with OIds
            pResultOId[j]     = pResultOId[i];
            pResultObjVers[j] = pResultObjVers[i];
          }
          if ((g01vtrace.vtrBdObject_gg00) || (g01vtrace.vtrOmsGet_gg00 )) {
            Kernel_VTrace vtrace;
            vtrace << "KeyIter-PrevOid="
              << pResultOId[j].gg92GetPno() << "." << pResultOId[j].gg92GetPos()
              << " (vers " << pResultOId[j].gg92GetFrameVers() << ")"
              << " ObjVers:";
            if (pResultObjVers[j].gg91IsNilRef())
              vtrace << " NilRef";
            else
              vtrace << pResultObjVers[j].gg91RefPno() 
              << "." << pResultObjVers[j].gg91RefPos();
          }
          ++j;
        }
        else {
          // Skip Oid
          //pResultOId[i].gg92SetNil();
        }
      }
      noOfOid = j;
      if (noOfOid > 0) {
        // There is at least one OID found
        break;
      }
      else {
        // Read next portion of OIds from kernel. The last key is remembered
        // in the iterator and if the pRestartKey equals NULL, then this locally
        // remembered key is used instead.
        pRestartKey = NULL;
        bInclusive  = false;  // PTS 1130216; otherwise if noOfOid=1 the same object 
                              //              is read ever and ever again      
      }
    }

    if (e_ok == TrError && KeyIterator.IsEmpty()){
      TrError = e_no_next_object;
    }
}

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

externCpp void
bd90ReadAhead (tbd_current_tree  &Current)
{
    ROUTINE_DBG_MSP00 ("bd90ReadAhead");

    /* this function reads all pages of a file in order to load them into the data cache       */
    /* however reading is stopped if the data cache is full (i.e. occupied by more than 99.9%) */
    /* PTS 1107145 AK 11/07/00 function rewritten                                              */

    tgg00_BasisError        &TrError         = Current.curr_trans->trError_gg00;
    const tgg00_ObjFileNo    ObjFileNo       = Current.curr_tree_id.fileObjFileNo_gg00();
    const tsp00_PageNo       RootPno         = bd90ObjFileDir[ObjFileNo].GetRootPage();
    cbd900_ObjFileInfo      &ObjFileInfo     = bd90ObjFileDir[ObjFileNo]; // PTS 1114661 FF 2002-03-06

    // PTS 1114661 FF 2002-03-06 check if marked for delete
    if ( (RootPno != Current.curr_tree_id.fileRoot_gg00()) || ObjFileInfo.ofiDropFile_bd900 )
        return;

    cbd910_ObjNode           NptrsPage (Current, RootPno, nr_for_read);
    if (e_ok != TrError)     // PTS 1114661 FF 2002-03-06
        return;

    /* PTS 1111513 13/12/2001 */
    bd90_ReadAheadFile (*Current.curr_trans, NptrsPage);

    if (Current.curr_tree_id.fileObjFileType_gg00() == oftVarLenObjFile_egg00)
    {
        cbd05_Current            ContCurrent     (*Current.curr_trans, m_update);  //PTS 1113198 18/12/12/2001
        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, ContCurrent.curr_tree_id);
                cbd910_ObjNode           NptrsPage (ContCurrent, ContObjFileInfo[iContFileNo].GetRootPage(), nr_for_read);
                if (e_ok != TrError)     // PTS 1114661 FF 2002-03-06
                    return;
                bd90_ReadAheadFile (*ContCurrent.curr_trans, NptrsPage);
            }
        }
    }
}

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

externCpp void
bd90MakeObjCountPersistent (tgg00_TransContext &Trans)
{
    ROUTINE_DBG_MEO00 ("bd90MakeObjCountPersistent");

    /* This function copies the number of all objects stored in the    */
    /* global structure bd90ObjFileDir to the subroots in order to     */
    /* maintain this number after a restart                            */
    /* changed by PTS 1107306 AK 01/08/2000                            */

    cbd05_Current          Current     (Trans, m_update);
    cbd900_ObjFileDirIter  ObjFileIter (bd90ObjFileDir);
    int                    iContFileNo;

    /* 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)
    {
        const tgg00_ObjFileNo ObjFileNo = ObjFileIter.bd920Key();
        ObjFileIter()->bd900BuildFileId (ObjFileNo, Current.curr_tree_id);
        bd90_CopyObjCountFromChainInfoToSubRoots (Current, *ObjFileIter());
        if (e_ok != Trans.trError_gg00) return;

        /* update obj counter for the continuation files, PTS 1108149 14/08/2001 */
        if (cbd900_ObjFileInfo::omsVariableFile == ObjFileIter()->GetFileType())
        {
            cbd900_ContObjFileInfo & ContObjFileInfo = bd93ContObjFileDir[ObjFileNo];
            for (iContFileNo=1; iContFileNo<= ContObjFileInfo.cfiNumContFiles_bd900; ++iContFileNo)
            {
                if (NIL_PAGE_NO_GG00 != ContObjFileInfo[iContFileNo].GetRootPage())
                {
                    ContObjFileInfo.bd900BuildFileId (ObjFileNo, iContFileNo, Current.curr_tree_id);
                    bd90_CopyObjCountFromChainInfoToSubRoots (Current, ContObjFileInfo[iContFileNo]);
                    if (e_ok != Trans.trError_gg00) return;
                }
            }
        }
    }

    vendexcl (Trans.trTaskId_gg00, g08garbage); /* PTS 1115596 FF 2002-05-08 */
}

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

externCpp void
bd90ReuseObj (tbd_current_tree   &Current,
              tgg92_KernelOid    &OId,
              tgg91_PageRef      &ResultObjVers,
              tsp00_Int4          KeySize,
              void               *pKey,
              bool               &bTryAgain)
{
    // NOTE! if this function returns e_wait_for_lock_release then wait outside bd-locking

    ROUTINE_DBG_MEO00 ("bd90ReuseObj");

    tgg00_BasisError    &TrError = Current.curr_trans->trError_gg00;
    bTryAgain = false;

    /* check if there is sufficient space to write a rollback  entry */
    Converter_IPageNoManager::Instance().HandleDBFull (*Current.curr_trans, 10);

    if (e_ok != TrError) return;  // PTS 1107864 AK 15/09/2000

    /* get pointer to page */
    cbd910_PrimObjDataNode    NptrsPage (Current, OId.gg92GetPno(),  nr_for_update);

    if (TrError != e_ok)
    {
        if ((TrError == e_page_in_wrong_tree) || (TrError == e_no_converter_entry))
        {
            // OID provided from key-management isn't valid yet
            TrError = e_too_old_oid;
            bTryAgain = true;
        }
        return;
    }

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

    if (pObjFrame->objHeader_bd900.ohdState_gg92 == obsFree_egg00)
    {
        TrError   = e_wrong_object_state;
        bTryAgain = true;
        return;
    }

    const int  ObjBodySize = NptrsPage.np_ptr()->nd_obj_frame_len() - sizeof(tgg92_ObjHeader);
    void   *pKeyInObjFrame = pObjFrame->objBody_bd900 + ObjBodySize - KeySize;

    if (memcmp (pKey, pKeyInObjFrame, KeySize))
    {
        // meanwhile the information from the hash that there exists an
        // object frame with the key pKey may be wrong since the garbage
        // collector removed this object, therefore this frame cannot be
        // reused and one has to try again to insert the key pKey into the hash

        TrError   = e_wrong_object_version;
        bTryAgain = true;
        return;
    }

    tgg00_ObjTransInfo &ObjTransInfo  = pObjFrame->objHeader_bd900.ohdTransInfo_gg92;
    const bool          bWithObj      = false;
    tgg00_ObjFrameVers  ResultFrameVers = NIL_OBJ_FRAME_VERS_GG92;
    tgg91_PageRef       ObjHistRef; 
    tsp00_Int4          LogReadAccesses = 0;
    ResultObjVers.gg91SetNilRef();
    ObjHistRef.gg91SetNilRef();
    int ObjBdySz = ObjBodySize;

    /* omsDeleteAll or SubtransRollback may have delete the object within same transaction */
    /* and another transaction may already be trying to reuse the object frame             */
    if (( ObjTransInfo.otrUpdTransId_gg00 != Current.curr_trans->trWriteTransId_gg00 ) &&
        ( pObjFrame->objHeader_bd900.ohdState_gg92 == obsFreeAfterEot_egg00 ) && 
        ( !gg06IsNilTrans (Current.curr_trans->trConsistView_gg00) ))
    {
        kb67GetObjConsistent (*Current.curr_trans, 
            OId, 
            pObjFrame->objHeader_bd900.ohdState_gg92, 
            ObjTransInfo,
            bWithObj, 
            KeySize, 
            ObjBdySz, 
            0,              // ExtObjBodySize, 
            NULL,           // pExtObjBody, 
            ResultFrameVers, 
            ResultObjVers, 
            ObjHistRef, 
            LogReadAccesses);  

        if ((TrError == e_ok) && !ObjHistRef.gg91IsNilRef() )
        {
            TrError = e_key_still_visible;
            return;           
        }
        else
            TrError = e_ok;
    }

#if defined(FOR_TESTING_ONLY)
    tgg92_KernelOid     ResultOid;
    bool                fIndexNotOk = false;
    tgg00_BasisError    KeyTrError = e_ok;
    bd22GetOId (*Current.curr_trans, Current.curr_tree_id.fileObjFileNo_gg00(), KeySize, pKey, ResultOid);
    if (e_ok != TrError)
    {
        KeyTrError = TrError;
        fIndexNotOk = true;
    }

    if (!((ResultOid.gg92GetPos() == OId.gg92GetPos()) &&
            (ResultOid.gg92GetPno() == OId.gg92GetPno())))
    {
        fIndexNotOk = true;
    }
#endif

    kb67NewObj (*Current.curr_trans, Current.curr_tree_id, OId, pObjFrame->objHeader_bd900,
                ObjBodySize, KeySize);

    if (e_wait_for_lock_release == TrError)
    {
        bTryAgain = true;
        return;
    }

#if defined(FOR_TESTING_ONLY)
    if ( fIndexNotOk )
    {
        {
            Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
            opErrMsg << "bd90ReuseObj: Key-Index is not ok ! TrError:"
            << KeyTrError << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
            << " Idx OID=" << ResultOid.gg92GetPno() << "." << ResultOid.gg92GetPos();
        }
        g01abort (csp3_bd_msg, csp3_n_obj,
                  "bd90ReuseObj: IDX not ok", Current.curr_trans->trError_gg00);
    }
#endif

    // PTS 1132118 UH 2004-10-25 ResultObjVers is always assigned
    ResultObjVers = pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00;
    OId.gg92SetFrameVers(pObjFrame->objHeader_bd900.ohdFrameVersion_gg92);

    if (TrError == e_ok)
    {
        // PTS 1132118 UH 2004-10-25 ResultObjVers is always assigned
        // ResultObjVers = pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00;

        -- NptrsPage.np_ptr()->nd_free_eot_obj_cnt();
        ++ NptrsPage.np_ptr()->nd_occ_obj_cnt();

        pObjFrame->objHeader_bd900.ohdState_gg92.becomes(obsKeyReserved_egg00);

        if(pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 >= MAX_OBJ_FRAME_VERS_GG92)
            pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 = MIN_OBJ_FRAME_VERS_GG92;
        else
            pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 ++;

        OId.gg92SetFrameVers (pObjFrame->objHeader_bd900.ohdFrameVersion_gg92);
    }
}

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

externCpp void
bd90RollbackObj (tbd_current_tree     &Current,            //[inp\out]
                 tgg00_MessType_Enum   RollbackType,       //[inp]
                 tgg92_KernelOid      &OId,                //[inp]
                 const tgg00_ObjFileNo ObjFileNo,          //[inp]  //PTS 1109582 AK 09/03/2001
                 tgg00_ObjState        NewState,           //[inp]
                 tgg91_PageRef         BeforeObjRef,       //[inp]
                 tgg91_TransNo         BeforeObjUpdVers,   //[inp]
                 tsp00_Int4            BeforeObjSize,      //[inp]
                 void                 *pBeforeObj)         //[inp]
{
    ROUTINE_DBG_MEO00 ("bd90RollbackObj");

    /* possible actions which can be rollbacked by this procedure */

    /* current state  |   action   |   new state    */
    /* ---------------------------------------------*/
    /*  reserved     --- m_new    ---> feot         */ // PTS 1113342 UH 2002-01-10
    /*  key_reserved --- m_new    ---> feot         */ // PTS 1113342 UH 2002-01-10
    /*  key_reserved --- m_new    ---> feot         */
    /*  occupied     --- m_insert ---> reserved     */
    /*  occupied     --- m_insert ---> key_reserved */
    /*  occupied     --- m_update ---> occupied     */
    /*  feot         --- m_delete ---> occupied     */
    /*  feot         --- m_delete ---> reserved     */
    /*  feot         --- m_delete ---> key_reserved */

    tgg00_BasisError     &TrError                      = Current.curr_trans->trError_gg00;
    bool                  bTooManyEmptyPagesInContFile = false;
    tsp00_Int4            ContChainNo;
    tsp00_Int4            ContObjFileNo;
    cbd900_ObjFileInfo   &ObjFileInfo = bd90ObjFileDir[ObjFileNo];

    Converter_IPageNoManager::Instance().HandleDBFull (*Current.curr_trans,
            MAX_NUM_CHAINS_PER_CONTAINER_BD900);

    
    cbd910_PrimObjDataNode  NptrsPage(Current, OId.gg92GetPno(), nr_for_update);
    if (TrError != e_ok)
    {
        if ((e_page_in_wrong_tree == TrError) || (e_no_converter_entry == TrError)) 
        {
            if ((!bd90ObjFileDir.bd920IsUsed(ObjFileNo) || 
                ObjFileInfo.ofiRelFileIsReq_bd900 || ObjFileInfo.ofiDropFile_bd900) &&
                Kernel_IAdminInfo::Instance().KernelStateIsRestart())               /* PTS 1127357 2004-Jan-22 FF */
                TrError = e_ok;

            /* PTS 1114914 FF 2002-03-13 */
            if ((m_new == RollbackType) &&
                    ((obsFreeAfterEot_egg00 == NewState) || // for REUSED KeyedObjects   PTS 1119318 FF 2002-Dec-4
                    (obsFree_egg00 == NewState)) &&  // NewState == obsFree is mapped to obsFreeAfterEot (see below)
                    Kernel_IAdminInfo::Instance().KernelStateIsRestart() &&
                    ((Log_Transaction *) Current.curr_trans->trLogContext_gg00)->WasOpenInLastSavepoint() )
            {
                Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
                opWarnMsg << "bd90RollbackObj error:" << TrError << " ignored!"
                << " RollbackType:" << RollbackType 
                << " NewState:" << NewState
                << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos() << " (vers " << OId.gg92GetFrameVers() << ")";
                TrError = e_ok;
            }
        }
        return;
    }

    tbd_nodeptr &pPage            = NptrsPage.np_ptr();
    const bool   bPageIsForVarObj = (pt2VarObject_egg00 == NptrsPage.np_ptr()->nd_pt2());

    /* check if the page still belongs to the wanted file PTS 1105630 Alexander Kley 16/02/2000 */
    if ((ObjFileNo != Current.curr_tree_id.fileObjFileNo_gg00()) || //PTS 1109582 AK 09/03/2001
        (ObjFileNo != pPage->nd_obj_file_no()))
    {
        /* PTS 1114818 FF 2002-03-13 */
        if ((m_new == RollbackType) &&
            ((obsFreeAfterEot_egg00 == NewState) || // for REUSED KeyedObjects   PTS 1119318 FF 2002-Dec-4
            (obsFree_egg00 == NewState)) &&  // NewState == obsFree is mapped to obsFreeAfterEot (see below)
            Kernel_IAdminInfo::Instance().KernelStateIsRestart() &&
            ((Log_Transaction *) Current.curr_trans->trLogContext_gg00)->WasOpenInLastSavepoint() )
        {
            Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
            opWarnMsg << "bd90RollbackObj error:" << TrError << " ignored!"
                << " RollbackType:" << RollbackType 
                << " NewState:" << NewState
                << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                << " (vers " << OId.gg92GetFrameVers() << ")"
                << " FileNo:" << pPage->nd_obj_file_no() << " expected FileNo:" << ObjFileNo;
            TrError = e_ok;
        }
        else
        {
            Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
            opErrMsg << "bd90RollbackObj error:" << TrError
                << " RollbackType:" << RollbackType 
                << " NewState:" << NewState
                << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                << " (vers " << OId.gg92GetFrameVers() << ")"
                << " FileNo:" << pPage->nd_obj_file_no() << " expected FileNo:" << ObjFileNo;
            TrError = e_wrong_class_id;
        }
        return;
    }
    
    /* determine pointer to object frame */
    BD92CHECK_OID_POSITION ("bd90RollbackObj",TrError, OId, NptrsPage);
    tbd900_ObjFrame  *pObjFrame = NptrsPage.bd910ObjFramePtr (OId.gg92GetPos());

    /* check if the wanted rollback is possible */
    switch (pObjFrame->objHeader_bd900.ohdState_gg92)
    {
    case obsReserved_egg00:
        if (m_new != RollbackType || obsFree_egg00 != NewState) 
        {
            /* PTS 1114818 FF 2002-03-13 */
            if (((( m_insert == RollbackType ) || ( m_delete == RollbackType )) &&
                (obsReserved_egg00 == NewState) &&
                Kernel_IAdminInfo::Instance().KernelStateIsRestart() &&
                ((Log_Transaction *) Current.curr_trans->trLogContext_gg00)->WasOpenInLastSavepoint() ) 
                ||
                /* PTS 1127279  if update for new object fails with storing data within continous container */
                (( pt2VarObject_egg00 == NptrsPage.np_ptr()->nd_pt2() ) &&
                ( m_insert == RollbackType ) && 
                ( obsReserved_egg00 == NewState )))
            {
                Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
                opWarnMsg << "bd90RollbackObj invalid_state 'obsReserved' ignored!"
                    << " RollbackType:" << RollbackType
                    << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                    << " (vers " << OId.gg92GetFrameVers() << ")";
                TrError = e_ok;
            }
            else
            {
                Kernel_OpWarning  opErrMsg( csp3_bd_msg, csp3_n_obj );
                opErrMsg << "bd90RollbackObj invalid_state 'obsReserved' found!"
                    << " RollbackType:" << RollbackType
                    << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                    << " (vers " << OId.gg92GetFrameVers() << ")";
                TrError = e_wrong_object_state;
            }
            return;
        }
        break;

    case obsKeyReserved_egg00:
        if (m_new != RollbackType                 ||
                (obsFree_egg00         != NewState  &&
                 obsFreeAfterEot_egg00 != NewState))
        {
            /* PTS 1114818 FF 2002-03-13 */
            if ((( m_insert == RollbackType ) || ( m_delete == RollbackType )) &&
                    (obsKeyReserved_egg00 == NewState) &&
                    Kernel_IAdminInfo::Instance().KernelStateIsRestart() &&
                    ((Log_Transaction *) Current.curr_trans->trLogContext_gg00)->WasOpenInLastSavepoint() )
            {
                Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
                opWarnMsg << "bd90RollbackObj invalid_state 'obsKeyReserved' ignored!"
                << " RollbackType:" << RollbackType
                << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                << " (vers " << OId.gg92GetFrameVers() << ")";
                TrError = e_ok;
            }
            else
            {
                Kernel_OpWarning  opErrMsg( csp3_bd_msg, csp3_n_obj );
                opErrMsg << "bd90RollbackObj invalid_state 'obsKeyReserved' found!"
                << " RollbackType:" << RollbackType
                << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                << " (vers " << OId.gg92GetFrameVers() << ")";
                TrError = e_wrong_object_state;
            }
            return;
        }
        break;

    case obsOccupied_egg00:
        if (!((m_insert == RollbackType                                            &&
                ((obsReserved_egg00    == NewState && pPage->nd_obj_key_len() == 0)  ||
                 (obsKeyReserved_egg00 == NewState && pPage->nd_obj_key_len() > 0 )))    ||
                ((m_lock == RollbackType /* PTS 1109296 UH 2001-01-26 */ || m_update == RollbackType) && obsOccupied_egg00 == NewState)))
        {
            /* PTS 1114818 FF 2002-03-13 */
            if ((( m_update == RollbackType ) || ( m_delete == RollbackType )) &&
                    (obsOccupied_egg00 == NewState) &&
                    Kernel_IAdminInfo::Instance().KernelStateIsRestart() &&
                    ((Log_Transaction *) Current.curr_trans->trLogContext_gg00)->WasOpenInLastSavepoint() )
            {
                Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
                opWarnMsg << "bd90RollbackObj invalid_state 'obsOccupied' ignored!"
                << " RollbackType:" << RollbackType
                << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                << " (vers " << OId.gg92GetFrameVers() << ")";
                TrError = e_ok;
            }
            else
            {
                Kernel_OpWarning  opErrMsg( csp3_bd_msg, csp3_n_obj );
                opErrMsg << "bd90RollbackObj invalid_state 'obsOccupied' found!"
                << " RollbackType:" << RollbackType
                << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                << " (vers " << OId.gg92GetFrameVers() << ")";
                TrError = e_wrong_object_state;
            }
            return;
        }
        break;

    case obsFreeAfterEot_egg00:
        if (m_delete != RollbackType
                ||
                (obsOccupied_egg00    != NewState &&
                 obsReserved_egg00    != NewState &&
                 obsKeyReserved_egg00 != NewState))
        {
            /* PTS 1114818 FF 2002-03-13 */
            if (( m_new == RollbackType ) &&
                    ((obsFreeAfterEot_egg00 == NewState) || // for REUSED KeyedObjects   PTS 1119318 FF 2002-Dec-4
                    (obsFree_egg00 == NewState)) &&  // NewState == obsFree is mapped to obsFreeAfterEot (see below)
                    Kernel_IAdminInfo::Instance().KernelStateIsRestart() &&
                    ((Log_Transaction *) Current.curr_trans->trLogContext_gg00)->WasOpenInLastSavepoint() )
            {
                Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
                opWarnMsg << "bd90RollbackObj invalid_state 'obsFreeAfterEot' ignored!"
                << " RollbackType:" << RollbackType 
                << " NewState:" << NewState
                << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                << " (vers " << OId.gg92GetFrameVers() << ")";
                TrError = e_ok;
            }
            else
            {
                Kernel_OpWarning  opErrMsg( csp3_bd_msg, csp3_n_obj );
                opErrMsg << "bd90RollbackObj invalid_state 'obsFreeAfterEot' found!"
                << " RollbackType:" << RollbackType
                << " NewState:" << NewState
                << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                << " (vers " << OId.gg92GetFrameVers() << ")";
                TrError = e_wrong_object_state;
            }
            return;
        }
        break;

    default:
        /* PTS 1114818 FF 2002-03-13 */
        if ((m_new == RollbackType) &&
                (obsFree_egg00 == NewState) &&
                (obsFree_egg00 == pObjFrame->objHeader_bd900.ohdState_gg92) &&
                Kernel_IAdminInfo::Instance().KernelStateIsRestart() &&
                ((Log_Transaction *) Current.curr_trans->trLogContext_gg00)->WasOpenInLastSavepoint() )
        {
            Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
            opWarnMsg << "bd90RollbackObj invalid_state 'obsFree' ("
            << pObjFrame->objHeader_bd900.ohdState_gg92 << ") ignored!"
            << " RollbackType:" << RollbackType
                << " NewState:" << NewState
            << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
            << " (vers " << OId.gg92GetFrameVers() << ")";
            TrError = e_ok;
        }
        else
        {
            Kernel_OpWarning  opErrMsg( csp3_bd_msg, csp3_n_obj );
            opErrMsg << "bd90RollbackObj invalid_state 'obsFree' ("
            << pObjFrame->objHeader_bd900.ohdState_gg92 << ") found!"
            << " RollbackType:" << RollbackType
            << " NewState:" << NewState
            << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
            << " (vers " << OId.gg92GetFrameVers() << ")";
            TrError = e_wrong_object_state;
        }
        return;
    }

    if (m_lock == RollbackType) /* PTS 1109296 UH 2001-01-26 */
    {
        if ( BeforeObjSize != 0 || pBeforeObj != NULL )
        {
            TrError = e_log_error;
            return;
        }
    }
    else
    {
        /* rollback object body if necessary */
        switch (NewState)
        {
        case obsReserved_egg00:

            if (bPageIsForVarObj)
            {
                /* remove continuation object */
                tbd900_VarObjBodyHeader & VarObjBodyHeader = ((tbd900_VarObjBody*) (pObjFrame->objBody_bd900))->vbdHeader_bd900;

                if (PRIM_CONT_OBJ_FILE_NO_BD900 != VarObjBodyHeader.vhdContObjFileNo_bd900)
                {
                    bd93RemoveContObj (Current, OId, VarObjBodyHeader.vhdContObjFileNo_bd900,
                                       VarObjBodyHeader.vhdContObjPno_bd900, VarObjBodyHeader.vhdContObjPos_bd900);

                    /* reset pointer to continuation object */
                    VarObjBodyHeader.vhdContObjFileNo_bd900 = PRIM_CONT_OBJ_FILE_NO_BD900;
                    VarObjBodyHeader.vhdContObjPno_bd900    = NIL_PAGE_NO_GG00;
                    VarObjBodyHeader.vhdContObjPos_bd900    = NIL_OBJ_PAGE_POS_GG92;
                    VarObjBodyHeader.vhdObjSize_bd900       = 0;
                }
            }
            break;

        case obsOccupied_egg00:
            if (pObjFrame->objHeader_bd900.ohdState_gg92 != obsFreeAfterEot_egg00)
            {
                /* in case the object state is obsFreeAfterEot_egg00 there */
                /* is nothing to do since the object body is still as it   */
                /* was before the object was deleted otherwise the before  */
                /* image of the object hast to be inserted                 */

                if (bPageIsForVarObj)
                {
                    const bool        bRollBack = true;
                    bool              bNewContFileWasCreated;
                    tsp00_Int4        NewContObjFile;
                    Log_EntrySequence DummyRedoEntrySequence;
                    tgg91_TransNo     DummyRedoUpdTransNo;
                    tgg91_PageRef     DummyObjVers;
                    DummyObjVers.gg91SetDummyRef();


                    bd93UpdateVarObjBody (Current, OId, DummyObjVers, NptrsPage,
                                          pObjFrame, BeforeObjSize, pBeforeObj, bRollBack, bNewContFileWasCreated,
                                          bTooManyEmptyPagesInContFile, NewContObjFile, ContObjFileNo, ContChainNo,
                                          DummyRedoEntrySequence, DummyRedoUpdTransNo);

                    /* since this is a rollback the continuation file which can accomadate */
                    /* this object  must already exist, since after a continuation file is */
                    /* created once it is not removed until the complete file gets deleted */
                    SAPDBERR_ASSERT_STATE (false == bNewContFileWasCreated);
                }
                else
                {
                    /* check before object size */
                    if (0 != BeforeObjSize || (obsOccupied_egg00 == NewState))
                    {
                        if (BeforeObjSize != tsp00_Int4(pPage->nd_obj_frame_len() - sizeof(tgg92_ObjHeader) -
                                                        pPage->nd_obj_key_len()))
                        {
                            TrError = e_illegal_object_length;
                            return;
                        }

                        SAPDB_RangeMove( __FILE__, 2,
                            BeforeObjSize,
                            PAGE_MXSP00 - sizeof (tgg00_PageCheckTrailer),
                            pBeforeObj, 1,
                            pPage,
                            OId.gg92GetPos() + POS_OFF_DIFF_BD00 + sizeof (tgg92_ObjHeader),
                            BeforeObjSize,
                            TrError);
                    }
                }
                if (TrError != e_ok) return;
            }
            break;
        }
    }

    /* update page header */
    if (obsFreeAfterEot_egg00 == pObjFrame->objHeader_bd900.ohdState_gg92)
    {
        ++pPage->nd_occ_obj_cnt();
        --pPage->nd_free_eot_obj_cnt();
    }

    if ( obsFree_egg00 == NewState ) // PTS 1113342 UH 2002-01-10 added because rollback to Free is not allowed
        NewState.becomes(obsFreeAfterEot_egg00);

    /* update object header */
    if (obsFreeAfterEot_egg00 != NewState)
    {
        pObjFrame->objHeader_bd900.ohdState_gg92                        = NewState;
        pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00  = BeforeObjRef;
        pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrUpdTransId_gg00 = BeforeObjUpdVers;
        /* because OMS implementation may have change an ObjectVersion and may   */
        /* have written this change to persistent data because of omsRelease(),  */
        /* rollback has to recover the original version                          */
        /* only update and delete may change a frameversion via liboms           */
        if (obsOccupied_egg00 == NewState)
            pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 = OId.gg92GetFrameVers();
    }
    else
    {
        // PTS 1113342 UH 2002-01-10
        // Objects are only marked for delete if a NewObj is rollbacked and
        // not rollbacked to state obsFree_egg00.

        // Write new undo entry only for the garbage collectors so the gc can change the objects state
        // to obsFree_egg00.
        // This step is necessary to keep the lock of the object until end of transaction.
        // The flag m_drop means m_delete but the flag IsDone is true in this entry so it is
        // invisible during rollbacks.

        const int ObjBodySize = pPage->nd_obj_frame_len() - sizeof(tgg92_ObjHeader);

        kb67DelUpdObj (*Current.curr_trans, m_drop, Current.curr_tree_id,
                       OId, pPage->nd_obj_key_len(),
                       pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00,
                       pObjFrame->objHeader_bd900, ObjBodySize, pObjFrame->objBody_bd900);

        pObjFrame->objHeader_bd900.ohdState_gg92.becomes(obsFreeAfterEot_egg00);

        /* update page header */
        ++pPage->nd_free_eot_obj_cnt();
        --pPage->nd_occ_obj_cnt();
    }

    // PTS 1113342 UH 2002-01-10 removed handling for NewState: obsFree_egg00
}

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

externCpp void
bd90UnlockObj (
    tbd_current_tree &Current,
    tgg92_KernelOid  &OId
)

{
    ROUTINE_DBG_MEO00 ("bd90UnlockObj");

    tgg00_BasisError    &TrError = Current.curr_trans->trError_gg00;

    /*  get page pointer  */
    cbd910_PrimObjDataNode    NptrsPage(Current, OId.gg92GetPno(), nr_for_update);
    if (TrError != e_ok) return;

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

    /*  check object version  */
    if (pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 != OId.gg92GetFrameVers())
    {
        TrError = e_wrong_object_version;
        bd90_NoteVersionErrorInKnldiag
        (Unlock, OId, pObjFrame->objHeader_bd900.ohdFrameVersion_gg92);
        return;
    }

    /* check object state */
    if ((pObjFrame->objHeader_bd900.ohdState_gg92 != obsReserved_egg00    ) &&
            (pObjFrame->objHeader_bd900.ohdState_gg92 != obsKeyReserved_egg00 ) &&
            (pObjFrame->objHeader_bd900.ohdState_gg92 != obsOccupied_egg00   ))
    {
        TrError = e_wrong_object_state;
        return;
    }

    kb50UnlockObj (Current.curr_trans->trTaskId_gg00,
                   Current.curr_trans->trWriteTransId_gg00, Current.curr_trans->trIndex_gg00,
                   OId, pObjFrame->objHeader_bd900.ohdTransInfo_gg92);
}

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

externCpp  void
bd90UpdateObj (tbd_current_tree         &Current,
               tgg92_KernelOid          &OId,
               tgg91_PageRef            &ObjVers,
               tsp00_Int4                NewObjBodyLen,
               void                     *pNewObjBody,
               const Log_EntrySequence  &RedoEntrySequence,
               const tgg91_TransNo      &RedoUpdTransNo)
{
    ROUTINE_DBG_MEO00 ("bd90UpdateObj");

    tgg00_BasisError      &TrError                      = Current.curr_trans->trError_gg00;
    bool                   bTooManyEmptyPagesInContFile = false;
    tsp00_Int4             ContFileNo;
    tsp00_Int4             NewContFileNo;
    tsp00_Int4             ContChainNo;
    bool                   bNewContFileWasCreated       = false;

    /* check if there is sufficient space to write rollback, history entries */
    /* and a new continuation object in case of objects of variable length   */
    Converter_IPageNoManager::Instance().HandleDBFull (*Current.curr_trans, 10);

    if (e_ok != TrError) return;  // PTS 1107864 AK 15/09/2000

    /*  get page pointer  */
    cbd910_PrimObjDataNode    NptrsPage (Current, OId.gg92GetPno(), nr_for_update);
    if (TrError != e_ok) return;

    // PTS 1119647 FF 2002-DEC-05
    const tgg00_ObjFileNo  FileNo      = NptrsPage.np_ptr()->nd_obj_file_no();
    cbd900_ObjFileInfo    &ObjFileInfo = bd90ObjFileDir[FileNo];
    if ( !bd90ObjFileDir.bd920IsUsed(FileNo) || ObjFileInfo.ofiDropFile_bd900 ) 
    {
        TrError = e_container_dropped;
        if ((g01vtrace.vtrBdObject_gg00) || (g01vtrace.vtrOmsUpd_gg00 ))
            Kernel_VTrace() << __FILE__ << " : " << __LINE__ 
            << " UpdObj Error:" << TrError
            << " Oid=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
            << " (vers " << OId.gg92GetFrameVers() << ")";
        return;
    }

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

    tgg00_ObjFrameVers newFrameVers = OId.gg92GetFrameVers();   // PTS XYZXYZ FF 2003-Dec-05

    /* check object version */
    if ( RedoEntrySequence.IsInvalid()
            &&
            pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 != OId.gg92GetFrameVers() )
    {
        /* PTS XYZXYZ FF 2003-Dec-05  for omsKeyedObjects FrameVersion may have */
        /*                            been incremented by upper layers          */
        if ( cbd900_ObjFileInfo::omsKeyedFile != ObjFileInfo.GetFileType()) 
        {
            TrError = e_wrong_object_version;
            bd90_NoteVersionErrorInKnldiag
                (Update, OId, pObjFrame->objHeader_bd900.ohdFrameVersion_gg92);
            return;
        }
        else { // PTS XYZXYZ FF 2003-Dec-05
            /* make sure, the right OID is written to undo/history entries */
            OId.gg92SetFrameVers(pObjFrame->objHeader_bd900.ohdFrameVersion_gg92);
        }
    }

    const bool bPageIsForVarObj = (pt2VarObject_egg00 == NptrsPage.np_ptr()->nd_pt2());

    /* update object body */
    if (bPageIsForVarObj)
    {
        const bool bNoRollBack = false;
        bd93UpdateVarObjBody (Current, OId, ObjVers, NptrsPage, pObjFrame, NewObjBodyLen,
                              pNewObjBody, bNoRollBack, bNewContFileWasCreated, bTooManyEmptyPagesInContFile,
                              NewContFileNo, ContFileNo, ContChainNo, RedoEntrySequence, RedoUpdTransNo);
    }
    else
    {
        bd90_UpdateObjBody (Current, OId, ObjVers, NptrsPage.np_ptr(),
                            pObjFrame,  NewObjBodyLen, pNewObjBody, RedoEntrySequence, RedoUpdTransNo);
    }

    /* reset OID to original objFrameVers PTS XYZXYZ FF 2003-Dec-05 */ 
    OId.gg92SetFrameVers(newFrameVers);  

    if (TrError != e_ok) {
      if ((g01vtrace.vtrBdObject_gg00) || (g01vtrace.vtrOmsUpd_gg00 ))
        Kernel_VTrace() << __FILE__ << " : " << __LINE__ 
        << " UpdObj Error:" << TrError
        << " Oid=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
        << " (vers " << OId.gg92GetFrameVers() << ")"
        << " ohdFrameVersion:" << pObjFrame->objHeader_bd900.ohdFrameVersion_gg92
        << " ObjVers" << ObjVers.gg91RefPno() << "." << ObjVers.gg91RefPos();
      return;
    }

    /* write OID.FrameVers into object frame PTS XYZXYZ FF 2003-Dec-05 */ 
    pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 = newFrameVers; 

    /*  set return value of result object sequence  */
    ObjVers = pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00;

    /*  update object frame header */
    pObjFrame->objHeader_bd900.ohdState_gg92.becomes(obsOccupied_egg00);

    bool  bInsertPageIntoFreeChain = false;
    if ((!g_IsOnline) && (NptrsPage.np_ptr()->nd_assigned_to_spec_trans()))
    {
        if (!Kernel_IAdminInfo::Instance().KernelStateIsOnline())
        {
            NptrsPage.np_ptr()->nd_assigned_to_spec_trans() = 0;
            if (NptrsPage.bd910PageMustBeInsertedIntoFreeChain())
                bInsertPageIntoFreeChain = true;
        }
        else 
            g_IsOnline = true;
    }

    /* update root page numbers of continuation files stored on the root of the primary file */
    if (bNewContFileWasCreated)
    {
        cbd910_SubRootNode  NptrsRoot (Current, nr_for_update);

        if (NptrsPage.np_ptr()->nd_root() == NptrsPage.np_ptr()->nd_id())
        {
            NptrsRoot.bd910SetTo (NptrsPage);
            if (bInsertPageIntoFreeChain)
                NptrsRoot.bd910InsertPageIntoFreeChain (NptrsPage);
        }
        else
        {
            const tsp00_PageNo RootPno = NptrsPage.np_ptr()->nd_root();
            if (bInsertPageIntoFreeChain)
            {
                NptrsRoot.bd910AssignToSubroot (NptrsPage);
                if (NptrsPage.bd910PageMustBeInsertedIntoFreeChain())
                    NptrsRoot.bd910InsertPageIntoFreeChain (NptrsPage);
                NptrsPage.bd910ReleasePage();
            }
            else
            {
                NptrsPage.bd910ReleasePage();
                NptrsRoot.bd910AssignToPage(RootPno);
            }
        }

        cbd900_RootPageInfo      RootPageInfo (NptrsRoot);
        RootPageInfo.bd900ContRoot (NewContFileNo) = bd93ContObjFileDir[NptrsRoot.np_ptr()->nd_obj_file_no()][NewContFileNo].GetRootPage();
    }


}

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

static void
bd90_CopyObjCountFromChainInfoToSubRoots (tbd_current_tree   &Current,
        cbd900_ObjFileInfo &ObjFileInfo)
{
    for (int iChain = 0; iChain<ObjFileInfo.GetChainCount(); ++iChain)
    {
        cbd900_ObjChainInfo & ChainInfo = ObjFileInfo[iChain];

        const tsp00_PageNo &SubRoot = ChainInfo.ociSubRoot_bd900;
        if (NIL_PAGE_NO_GG00 != SubRoot)
        {
            /* update the counter of used objects only if it has changed since it was */
            /* written to the subroot the last time         PTS 1111390 AK 14/08/2001 */
            if (ChainInfo.GetAllObjCnt() != ChainInfo.ociAllObjCntOnSubRoot_bd900)
            {
                cbd910_SubRootNode  NptrsSubRoot (Current, SubRoot, nr_for_update);
                if (Current.curr_trans->trError_gg00 != e_ok)
                {
                    b06write_filename_and_root (Current.curr_tree_id);
                    g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                              "bd90Refresh: Error      ", Current.curr_trans->trError_gg00 );
                    g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                              "bd90Refresh: Subroot    ", SubRoot);
                    g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                              "bd90Refresh: ChainNo    ", iChain);
                    return;
                }

                /* get handler for the data stored on the root page body */
                cbd900_SubRootPageInfo  SubRootPageInfo (NptrsSubRoot);

                /* note that ociAllObjCnt_bd900 is updated dirty and need not be correct. Here it is */
                /* tried to keep the trivial restriction that the number of all objects must be >=0  */
                SubRootPageInfo.bd900AllObjCnt() = SAPDB_MAX (ChainInfo.GetAllObjCnt(), 0);

                /* store the obj counter which was made persistent also in the chain info. PTS 1111390 AK 14/08/2001 */
                ChainInfo.ociAllObjCntOnSubRoot_bd900 = ChainInfo.GetAllObjCnt();
            }
        }
    }
}

/*---------------------------------------------------------------------------*/
/* PTS 1111856 FF 2002-06-05 logic has been completely recoded               */
static _INLINE void
bd90_DelAllObjOnThisPage (tbd_current_tree           &Current,
                          cbd910_PrimObjDataNode     &NptrsPage,
                          tsp00_Int4                 &NumDelObj,
                          tgg92_KernelOid            &OId)      // PTS 1116441
{
    ROUTINE_DBG_MEO00 ("bd90_DelAllObjOnThisPage");

    tgg00_BasisError    &TrError            = Current.curr_trans->trError_gg00;
    tbd_nodeptr         &pPage              = NptrsPage.np_ptr();
    tsp00_Uint2         &ObjFrameLen        = pPage->nd_obj_frame_len();

    const int            AlignedObjFrameLen = BD92ALIGN_OBJ_FRAME (ObjFrameLen);
    tgg00_ObjPagePos     ObjPos;
    tbd900_ObjFrame     *pObjFrame;
    // tgg92_KernelOid    OId;        PTS 1116441
    tsp00_Int4           ObjBodySize;
    tsp00_Bool           bNextObjIsFound = false;
    tsp00_Int4           LogReadAccesses = 0;
    tsp00_Int4           ExtObjBodySize = 0;
    void                *pExtObjBody = NULL;
    tgg91_PageRef        WantedObjVers;
    
    /* go trough all objects on this page */
    for (ObjPos = pPage->nd_first_obj();
        ((ObjPos + ObjFrameLen) <= BODY_END_BD00) && (e_ok == TrError);
        ObjPos += AlignedObjFrameLen)
    {           
        /* create OId for current object */
        OId.gg92SetPno (NptrsPage.np_ptr()->nd_id());
        OId.gg92SetPos (ObjPos);

        const bool          bWithObject = false;
        tgg91_PageRef       ObjHistRef;              // unused parameter PTS 1125316 FF
        bd90_GetConsistentObjImage (Current, OId, WantedObjVers, ObjHistRef, bWithObject, ExtObjBodySize, 
                                    pExtObjBody, NptrsPage, ObjBodySize, bNextObjIsFound, LogReadAccesses);
        if (bNextObjIsFound && (TrError == e_ok) && ( LogReadAccesses > 0))
          TrError = e_object_dirty;
        if ((bNextObjIsFound ) && (TrError == e_ok))
        {            
            tsp00_Uint2 AuxReqTimeout = Current.curr_trans->trObjReqTimeout_gg00; //save
            Current.curr_trans->trObjReqTimeout_gg00 = 0;                         // set nowait;
            pObjFrame = NptrsPage.bd910ObjFramePtr(ObjPos);

            /* check if kb67LockObj has alread be done by bd90_GetConsistentObjImage PTS 1120036 FF 2003-JAN-16 */
            if ((pObjFrame->objHeader_bd900.ohdState_gg92 == obsOccupied_egg00    )    ||
                (pObjFrame->objHeader_bd900.ohdState_gg92 == obsFreeAfterEot_egg00)    ||
                ((pObjFrame->objHeader_bd900.ohdState_gg92 == obsKeyReserved_egg00) &&
                !pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00.gg91IsNilRef()))
            {
                kb67LockObj (*Current.curr_trans, Current.curr_tree_id, OId, WantedObjVers,
                pObjFrame->objHeader_bd900.ohdState_gg92,
                pObjFrame->objHeader_bd900.ohdTransInfo_gg92);
            }
            else
            {
                /* PTS 1120036 FF 2003-JAN-16 */
                WantedObjVers = pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00;
            }
                        
            Current.curr_trans->trObjReqTimeout_gg00 = AuxReqTimeout;             // restore timeout

            if (TrError == e_ok)
            {
                /* check if object is locked and create a log entry  */
                const bool  bPageIsForVarObj = (pt2VarObject_egg00 == NptrsPage.np_ptr()->nd_pt2());

                if (bPageIsForVarObj)
                    bd93LogDelVarObj (Current, OId, WantedObjVers, NptrsPage.np_ptr(), pObjFrame);
                else
                {
                    /* calculate ObjBodySize PTS 1120036 FF 2003-JAN-16 */
                    const int ObjBodySize = NptrsPage.np_ptr()->nd_obj_frame_len() - sizeof(tgg92_ObjHeader);
                    kb67DelUpdObj (*Current.curr_trans, m_delete, Current.curr_tree_id,
                                   OId, pPage->nd_obj_key_len(), WantedObjVers,
                                   pObjFrame->objHeader_bd900, ObjBodySize, pObjFrame->objBody_bd900);
                }
                if (TrError == e_ok)
                {
                    /* increase counter of deleted objects */
                    ++NumDelObj;

                    /* mark the object as deleted  */
                    pObjFrame->objHeader_bd900.ohdState_gg92.becomes(obsFreeAfterEot_egg00);

                    /* update page header */
                    ++pPage->nd_free_eot_obj_cnt();
                    --pPage->nd_occ_obj_cnt();

                    kb67WriteDeleteObjectAfterImage ( *Current.curr_trans,
                                                      Current.curr_tree_id.fileObjFileNo_gg00(),
                                                      OId,
                                                      WantedObjVers );
                }
            }
        }
        if (TrError != e_ok) break;
    }
}

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

static _INLINE void
bd90_GetObjBody   (
    tgg00_TransContext &Trans,
    tgg92_KernelOid     OId,
    tbd_nodeptr         pPage,
    tsp00_Int4          ExtObjBodySize,
    void               *pExtObjBody,
    tbd900_ObjFrame     *pObjFrame
)
{
    ROUTINE_DBG_MEO00 ("bd90_GetObjBody");

    /* this function copiess the object body identified by      */
    /* the OId at the position given by the pointer pExtObjBody */

    tgg00_BasisError    &TrError = Trans.trError_gg00;
    const tsp00_Uint2   KeyLen   = pPage->nd_obj_key_len();
    const tsp00_Int4 ObjBodySize = pPage->nd_obj_frame_len() - sizeof(tgg92_ObjHeader);

    /* check if the given memory is large enough to accomodate the object */
    if (ExtObjBodySize < ObjBodySize)
    {
        Kernel_OpWarning  opErrMsg( csp3_bd_msg, csp3_n_obj );
        opErrMsg << "bd90_GetObjBody:ExtObjBodySize:" << ExtObjBodySize
        << " ObjBodySize:" << ObjBodySize
        << " PNo:" <<  pPage->nd_id() << " (page dumped to file:" << pPage->nd_id() << "d)"
        << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
        << " (vers " << OId.gg92GetFrameVers() << ")";
        b06dump_bad_page (Trans.trTaskId_gg00,'d', ".obj", pPage->nd_id(), (void *) pPage, 1); //PTS 1107471 AK 09/08/2000
        TrError = e_wrong_object_version;  //e_buffer_limit PTS 1114891 FF 2002-03-15 ;
        return;
    }

    if (pObjFrame->objHeader_bd900.ohdState_gg92 == obsOccupied_egg00)
    {
        /* copy object */
        SAPDB_RangeMove( __FILE__, 3,
            PAGE_MXSP00 - sizeof (tgg00_PageCheckTrailer),
            ExtObjBodySize,
            pPage,
            OId.gg92GetPos()+ POS_OFF_DIFF_BD00 + sizeof (tgg92_ObjHeader),
            pExtObjBody,         1,
            ObjBodySize,
            TrError);
    }
    else
    {
        if (KeyLen > 0)
        {
            /* copy key only */
            SAPDB_RangeMove( __FILE__, 4,
                PAGE_MXSP00 - sizeof (tgg00_PageCheckTrailer),
                ExtObjBodySize,
                pPage,
                OId.gg92GetPos() + POS_OFF_DIFF_BD00 + sizeof (tgg92_ObjHeader) + ObjBodySize - KeyLen,
                pExtObjBody, 1 + ObjBodySize - KeyLen,
                KeyLen,
                TrError);

            if (TrError != e_ok) {return;}
        }

        /* fill the remaining object body with NIL_OBJ_FILLCHAR_BD900 */
        SAPDB_RangeFill (__FILE__, 5,
                ExtObjBodySize, pExtObjBody, 1, ObjBodySize - KeyLen, NIL_OBJ_FILLCHAR_BD900, TrError);
    }

#   if COMPILEMODE_MEO00 >= SLOW_MEO00
    if (e_ok == TrError) t01moveobj (bi, pExtObjBody, 1, ObjBodySize);
#   endif   

}

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

static void
bd90_NewObjFromThisPage (tbd_current_tree         &Current,
                         cbd910_PrimObjDataNode   &NptrsPage,
                         tsp00_Int4                KeyLen,
                         void                     *pKey,
                         tgg92_KernelOid          &OId,
                         tgg91_PageRef            &ResultObjVers)
{
    ROUTINE_DBG_MEO00 ("bd90_NewObjFromThisPage");


    /*  This routine finds the OId on a page presuming that at least one free  */
    /*  object frame exists. Moreover all pointers are restored corresponding  */
    /*  to changing the state of the frame whichs OId is returned              */

    tgg00_BasisError    &TrError          = Current.curr_trans->trError_gg00;
    tbd_nodeptr         &pPage            = NptrsPage.np_ptr();
    tsp00_Int4           ObjBodySize;
    const bool           bPageIsForVarObj = (pt2VarObject_egg00 == pPage->nd_pt2());

    /* construct position of the object frame  header */
    tbd900_ObjFrame  *pObjFrame = NptrsPage.bd910ObjFramePtr (pPage->nd_first_free_obj());

    /* check if the object frame is really free    PTS 1127804 FF 2004-FEB-17 */
    /* (PTS 1134505) check if the position of the first free obj is valid     */
    /* and                                                                    */                                                                    
    /* check if the object frame is really free                               */
    if ( !bd92ObjPosIsValid (pPage->nd_first_free_obj(), pPage->nd_first_obj(), pPage->nd_obj_frame_len())
        ||
        (obsFree_egg00 != pObjFrame->objHeader_bd900.ohdState_gg92)) 
    {
        Kernel_OpError ( csp3_bd_msg, csp3_n_obj ) << __FILE__ << ":" << __LINE__
            << " wrong position: " << pPage->nd_first_free_obj()
            << " or objectframe in freelist not marked as 'obsFree_egg00'"
            << " page:" << pPage->nd_id()
            << " first free pos: " << pPage->nd_first_free_obj()
            << " state:" << pObjFrame->objHeader_bd900.ohdState_gg92
            << " page dumped into: d" 
            << pPage->nd_id() << ".obj"; 

        b06dump_bad_page (Current.curr_trans->trTaskId_gg00,'d', ".obj", pPage->nd_id(), 
            (void *) NptrsPage.np_ptr(), 1);
        if ( bd92ObjPosIsValid (pPage->nd_first_free_obj(), pPage->nd_first_obj(), pPage->nd_obj_frame_len()))
            TrError = e_wrong_object_state;
        else
            TrError = e_illegal_object_pos;
        return;
    }

    /* construct new OId   */
    OId.gg92Set (
        pPage->nd_id(),
        pPage->nd_first_free_obj(),
        MIN_OBJ_FRAME_VERS_GG92);

    if (pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 < MAX_OBJ_FRAME_VERS_GG92)
        OId.gg92SetFrameVers (pObjFrame->objHeader_bd900.ohdFrameVersion_gg92 + 1);
    else
        OId.gg92SetFrameVers (MIN_OBJ_FRAME_VERS_GG92);

    /* determine objbodysize */
    if (bPageIsForVarObj)
        ObjBodySize = pPage->nd_obj_frame_len() - sizeof(tgg92_ObjHeader) - sizeof (tbd900_VarObjBodyHeader);
    else
        ObjBodySize = pPage->nd_obj_frame_len() - sizeof(tgg92_ObjHeader);

    /* check if the KeyLen corresponds to the KeyLen stored in the page header */
    SAPDBERR_ASSERT_STATE (pPage->nd_obj_key_len() == KeyLen);

    /* insert key into object body */
    if  (KeyLen > 0)
    {
        SAPDB_RangeMove( __FILE__, 6,
            KeyLen, ObjBodySize,
            pKey, 1, &(pObjFrame->objBody_bd900), ObjBodySize - KeyLen + 1,
            KeyLen, Current.curr_trans->trError_gg00);
        if (TrError != e_ok) {return;}

        // PTS 1134645
        pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrUpdTransId_gg00.gg90SetNil();
    }

    // new unused object ==> lock collision impossible ==> set nowait to avoid any kind of request
    tsp00_Uint2 AuxReqTimeout = Current.curr_trans->trObjReqTimeout_gg00; // save timeout
    Current.curr_trans->trObjReqTimeout_gg00 = 0; // set nowait

    /* put current lock id into object frame header and create a log entry   */
    kb67NewObj (*Current.curr_trans, Current.curr_tree_id, OId, pObjFrame->objHeader_bd900,
                ObjBodySize, KeyLen);

    Current.curr_trans->trObjReqTimeout_gg00 = AuxReqTimeout; // restore timeout

    if (TrError != e_ok) return;

    // necessary for NewHashKey
    ResultObjVers = pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00;

    /* update page header */
    -- pPage->nd_free_obj_cnt();
    ++ pPage->nd_occ_obj_cnt();
    pPage->nd_first_free_obj() = pObjFrame->objHeader_bd900.ohdNextFreeObj_gg92;

    /* set the object frame header to the state reserved and initialize the  body */
    pObjFrame->bd900SetToReservedFrame (pPage->nd_obj_frame_len(), KeyLen, OId.gg92GetFrameVers(), bPageIsForVarObj);
};

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

externCpp void
bd90NextObjConsistentOnThisPage  (tbd_current_tree        &Current,
                                  tgg92_KernelOid         &OId,
                                  tgg91_PageRef           &ResultObjVers,
                                  tgg91_PageRef           &ObjHistRef,               // PTS 1125316 FF
                                  bool                     bWithObject,
                                  tsp00_Int4               ExtObjBodySize,
                                  void                    *pExtObjBody,
                                  cbd910_PrimObjDataNode  &NptrsPage,
                                  tsp00_Int4              &ObjBodySize,             //[out=length of the object]
                                  tsp00_Bool              &bNextObjIsFound,
                                  tsp00_Int4              &LogReadAccessesPerPage)  //[out] PTS 1107819 AK 12/09/2000
{
    ROUTINE_DBG_MEO00 ("bd90NextObjConsistentOnThisPage ");

    bNextObjIsFound = false;
    LogReadAccessesPerPage = 0; // PTS 1107819 AK 12/09/2000

    tgg00_ObjPagePos   ObjPos;
    tsp00_Int4         ObjPosBeg;
    tsp00_Int4         LogReadAccesses ;
    const tsp00_Int4   ObjFrameLen  = NptrsPage.np_ptr()->nd_obj_frame_len();
    tgg00_BasisError  &TrError      = Current.curr_trans->trError_gg00;

    ObjHistRef.gg91SetNilRef(); // PTS 1125316 FF

    /* find starting object position for search */
    const int AlignedObjFrameLen = BD92ALIGN_OBJ_FRAME(ObjFrameLen);

    if ( ! OId.gg92IsNil() )
        ObjPosBeg = OId.gg92GetPos() + AlignedObjFrameLen;
    else
    {
        /* return immediately if there are no objects on this page. PTS 1107750 AK 05/09/2000 */
        if (NptrsPage.np_ptr()->nd_max_obj_cnt() == NptrsPage.np_ptr()->nd_free_obj_cnt())
            return;

        ObjPosBeg = NptrsPage.np_ptr()->nd_first_obj();
    }

    /*  start search */
    for ( ObjPos = ObjPosBeg;
            ((ObjPos + ObjFrameLen) <= BODY_END_BD00) && (!bNextObjIsFound) && (e_ok == TrError);
            ObjPos += AlignedObjFrameLen )
    {
        /* create OId for current object */
        OId.gg92SetPno (NptrsPage.np_ptr()->nd_id());
        OId.gg92SetPos (ObjPos);

        bd90_GetConsistentObjImage (Current, OId, ResultObjVers, ObjHistRef, bWithObject, ExtObjBodySize, pExtObjBody, 
                                    NptrsPage, ObjBodySize, bNextObjIsFound, LogReadAccesses);

        LogReadAccessesPerPage += LogReadAccesses;
    }
}

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

static _INLINE void
bd90_NoteVersionErrorInKnldiag (
    ebd90_FunctionName FunctionName,
    tgg92_KernelOid    WantedOId,
    tgg00_ObjFrameVers ExpectedVersion
)
{
#if COMPILEMODE_MEO00 >= SLOW_MEO00 

    ROUTINE_DBG_MEO00 ("bd90_NoteVersionErrorInKnldiag");

    /* first line */
    {
        char Message[] = bsp_c40 ;
        int Len        = 0;

        switch (FunctionName)
        {
        case Delete     : g17nameto_line ("Del:              ",Len,Message);break;
        case Get        : g17nameto_line ("Get:              ",Len,Message);break;
        case GetCons    : g17nameto_line ("GetCons:          ",Len,Message);break;
        case KeyGet     : g17nameto_line ("KeyGet:           ",Len,Message);break;
        case KeyGetCons : g17nameto_line ("KeyGetCons:       ",Len,Message);break;
        case Lock       : g17nameto_line ("Lock:             ",Len,Message);break;
        case Reuse      : g17nameto_line ("Reuse:            ",Len,Message);break;
        case Unlock     : g17nameto_line ("Unlock:           ",Len,Message);break;
        case Update     : g17nameto_line ("Update:           ",Len,Message);break;
        default         : g17nameto_line ("OMS:              ",Len,Message);break;
        }

        ++Len;
        g17nameto_line ("Wrong Vers=         ", Len, Message);
        g17trimint4_to_line (WantedOId.gg92GetFrameVers(), Len, Message);
        ++Len;
        g17nameto_line ("Corr Vers=          ", Len, Message);
        g17trimint4_to_line (ExpectedVersion, Len, Message);
        g01optextmsg (sp3p_knldiag, sp3m_warning, csp3_bd_msg, csp3_n_obj, Message);
    }

    /* second line */
    {
        char Message[] = bsp_c40 ;
        int Len        = 0;

        g17nameto_line ("Wanted OId :        ", Len, Message);
        ++Len;
        WantedOId.gg92AppendToLine (Len, *(tsp00_Line*) &Message);

        g01optextmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, Message);
    }
# endif
}

/*---------------------------------------------------------------------------*/
/* PTS 1111513 13/12/2001 */
static void
bd90_ReadAheadFile (tgg00_TransContext &Trans,
                    cbd910_ObjNode     &NptrsPage)
{
    tgg00_BasisError        &TrError         = Trans.trError_gg00;
    const tsp00_Int4         c100_Percent    = 1000;
    const tsp00_Int4         c99Dot9_Percent =  999;
    const tsp00_Int4         MaxNumPagesToReadTillNextCheck = 20;
    tsp00_Int4               NumPagesToReadTillNextCheck    = 0;
    tsp00_Int4               DataCacheSize;
    tsp00_Int4               OmsHistoryPageCnt;
    tsp00_Int4               OmsDataPageCnt;
    tsp00_Int4               OmsUnloadedVersPageCnt;
    tsp00_Int4               SqlDataPageCnt;
    double                   DataCacheOccupancy;  // tsp00_Int4 PTS 1114868 FF 202-03-15
    double                   DataCacheSize_double;

    while ((e_ok == TrError) && NptrsPage.bd910PageIsAvailable())
    {
        /* Stop reading if the cache is completely filled; PTS 1107820 AK 21/09/2000 */
        if (NumPagesToReadTillNextCheck <= 0)
        {
            NumPagesToReadTillNextCheck = MaxNumPagesToReadTillNextCheck;

            /* get data cache occupation */
            /* PTS 1111572 E.Z. */

            bd20GetWorkloadCounter (DataCacheSize, OmsHistoryPageCnt, 
                OmsDataPageCnt, OmsUnloadedVersPageCnt,SqlDataPageCnt);

            DataCacheOccupancy = OmsHistoryPageCnt + OmsDataPageCnt + OmsUnloadedVersPageCnt +SqlDataPageCnt;
            DataCacheSize_double = DataCacheSize;           // PTS 1114868 FF 202-03-15

            /* if the datacache is too full not only a cheap but not accurate check       */
            /* must be peforemed to decide  if an object can be released but an exact one */
            if  (DataCacheSize_double * c99Dot9_Percent < DataCacheOccupancy * c100_Percent)
                break;
        }
        /* move to next page, i.e. read next page into the data cache */
        NptrsPage.bd910MoveToNextPage();

        --NumPagesToReadTillNextCheck;
    }
}

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

static void
bd90_UpdateObjBody (tbd_current_tree         &Current,
                    tgg92_KernelOid           OId,
                    tgg91_PageRef             ObjVers,
                    tbd_nodeptr               pPage,
                    tbd900_ObjFrame          *pObjFrame,
                    tsp00_Int4                NewObjBodyLen,
                    void                     *pNewObjBody,
                    const Log_EntrySequence  &RedoEntrySequence,
                    const tgg91_TransNo      &RedoUpdTransNo)
{
    ROUTINE_DBG_MEO00 ("bd90_UpdateObjBody");

    /* This function moves the object given by the pointer  */
    /* pNewObjBody into the object frame given by the OId   */

    tgg00_BasisError    &TrError = Current.curr_trans->trError_gg00;

    /* check object state */
    if ((pObjFrame->objHeader_bd900.ohdState_gg92 != obsReserved_egg00   ) &&
            (pObjFrame->objHeader_bd900.ohdState_gg92 != obsKeyReserved_egg00) &&
            (pObjFrame->objHeader_bd900.ohdState_gg92 != obsOccupied_egg00   ))
    {
        TrError = e_wrong_object_state;
        return;
    }

    /*  check if the NewObjectBody fits into the ObjectFrame */
    tsp00_Int4  ObjBodySize = pPage->nd_obj_frame_len() - sizeof(tgg92_ObjHeader);
    if (NewObjBodyLen != ObjBodySize)
    {
        TrError = e_illegal_object_length;
        return;
    }

    /* update object transinfo and write a log entry */
    kb67UpdObj (*Current.curr_trans, Current.curr_tree_id,
                OId, pPage->nd_obj_key_len(), ObjVers,
                pObjFrame->objHeader_bd900, ObjBodySize,
                pObjFrame->objBody_bd900, RedoEntrySequence, RedoUpdTransNo);
    if (TrError != e_ok) {return;}

    /*  insert new object body into the object frame */
    SAPDB_RangeMove( __FILE__, 7,
        ObjBodySize,
        PAGE_MXSP00 - sizeof (tgg00_PageCheckTrailer),
        pNewObjBody,         1,
        pPage,
        OId.gg92GetPos() + POS_OFF_DIFF_BD00 + sizeof (tgg92_ObjHeader),
        NewObjBodyLen - pPage->nd_obj_key_len(), // no key update
        TrError);
}

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

static _INLINE tsp00_Int4
bd90_VarObjBodySize (tbd900_ObjFrame *pObjFrame)
{
    ROUTINE_DBG_MEO00 ("bd90_VarObjBodySize");

    tbd900_VarObjBody       &VarObjBody = *((tbd900_VarObjBody*) (pObjFrame->objBody_bd900));
    return VarObjBody.vbdHeader_bd900.vhdObjSize_bd900;
};

/*---------------------------------------------------------------------------*/
static void
bd90_GetConsistentObjImage (tbd_current_tree        &Current,       //[in/out]
                            tgg92_KernelOid         &OId,           //[in/out] frame version may change
                            tgg91_PageRef           &ResultObjVers,
                            tgg91_PageRef           &ObjHistRef,               // PTS 1125316 FF
                            tsp00_Bool               bWithObject,
                            tsp00_Int4               ExtObjBodySize,
                            void                    *pExtObjBody,
                            cbd910_PrimObjDataNode  &NptrsPage,
                            tsp00_Int4              &ObjBodySize,             //[out=length of the object]
                            tsp00_Bool              &bConsistentObjImageObjFound,
                            tsp00_Int4              &LogReadAccesses)
{
    ROUTINE_DBG_MEO00 ("bd90_GetConsistentObjImage");

    bConsistentObjImageObjFound = false;

    tgg00_ObjPagePos          ObjPos =  OId.gg92GetPos();
    tsp00_Int4                ObjKeyLen        = NptrsPage.np_ptr()->nd_obj_key_len();
    tgg00_BasisError         &TrError          = Current.curr_trans->trError_gg00;
    const bool                bPageIsForVarObj = (pt2VarObject_egg00 == NptrsPage.np_ptr()->nd_pt2());
    LogReadAccesses = 0;

    ObjHistRef.gg91SetNilRef(); // PTS 1125316 FF

    /*  get pointer to the current object frame  */
#   if COMPILEMODE_MEO00 >= QUICK_MEO00 
    BD92CHECK_OBJ_POSITION ("bd90_UpdateObjBody",TrError, ObjPos, NptrsPage);
#   endif       
    tbd900_ObjFrame* pObjFrame = NptrsPage.bd910ObjFramePtr (ObjPos);

    /* continue if the frame does not accomodate an object, PTS 1107750 AK 05/09/2000 */
    if (pObjFrame->objHeader_bd900.ohdState_gg92 == obsFree_egg00)
        return;

    /*  check current object frame and get a consistent image (if possible) */
    if ((pObjFrame->objHeader_bd900.ohdState_gg92 == obsOccupied_egg00    )    ||
            (pObjFrame->objHeader_bd900.ohdState_gg92 == obsFreeAfterEot_egg00)    ||
            ((pObjFrame->objHeader_bd900.ohdState_gg92 == obsKeyReserved_egg00) &&
             !pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00.gg91IsNilRef())) /* PTS 1001768 Torsten Strahl 1998-11-30 */
    {
        /* get object body length */
        if (bPageIsForVarObj)
            ObjBodySize = bd90_VarObjBodySize (pObjFrame);
        else
            ObjBodySize = NptrsPage.np_ptr()->nd_obj_frame_len() - sizeof(tgg92_ObjHeader);

        /* move object and key into given array assigned by pExtObjBody */
        if (bWithObject)
        {
            if (bPageIsForVarObj)
                bd93GetVarObjBody (Current, OId, ExtObjBodySize, pExtObjBody, pObjFrame);
            else
                bd90_GetObjBody (*Current.curr_trans, OId, NptrsPage.np_ptr(),
                                 ExtObjBodySize, pExtObjBody, pObjFrame);
            if (TrError != e_ok) {return;}
        }

        /* initialize the result obj frame version */
        tgg00_ObjFrameVers ResultFrameVers = pObjFrame->objHeader_bd900.ohdFrameVersion_gg92;

        /*  the current object may be inconsistent with the wanted view        */
        /*  which consists of objects commited before the current              */
        /*  transaction had been started in that case the old object image has */
        /*  to be restored from the log.                                       */
        kb67GetObjConsistent (*Current.curr_trans, OId,
                              pObjFrame->objHeader_bd900.ohdState_gg92,
                              pObjFrame->objHeader_bd900.ohdTransInfo_gg92,
                              bWithObject, ObjKeyLen, ObjBodySize, ExtObjBodySize, pExtObjBody,
                              ResultFrameVers,
                              ResultObjVers, 
                              ObjHistRef,                       // PTS 1125316 FF      
                              LogReadAccesses);  
        /* evaluate error message from kb67GetObjConsistent */
        switch (TrError)
        {
        case e_ok:
            /* PTS 1120322 FF 2003-Feb-07*/
            if ((pObjFrame->objHeader_bd900.ohdState_gg92 == obsKeyReserved_egg00) &&
                (LogReadAccesses == 0) &&
                (pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrUpdTransId_gg00 != 
                Current.curr_trans->trWriteTransId_gg00))
            {
                if ( 0 == g_Committed_obsReserved_Cnt )                    
                {                                                                       
                    g_Committed_obsReserved_Cnt++;
                    Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                        << "Committed object frame without stored data ( state: obsReserved ) found";
                }
                Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
                opWarnMsg << "bd90GetObjConsistent: object within state:obsKeyReserved_egg00"
                    << " read, but not created by this trans!" 
                    << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                    << " (vers " << OId.gg92GetFrameVers() << ")"
                    << " (page dumped to file d" 
                    << OId.gg92GetPno() <<".obj)"; 
                b06dump_bad_page (Current.curr_trans->trTaskId_gg00,'d', ".obj", NptrsPage.np_ptr()->nd_id(), 
                    (void *) NptrsPage.np_ptr(), 1);
            }
            else
            {
                /*  a consistent image was found  */
                bConsistentObjImageObjFound = true;
                OId.gg92SetFrameVers (ResultFrameVers);  // PTS 1001332 Alexander Kley 31.7.98
            }
            break;

        case e_object_not_found:
            /*  there is no consistent image of this object the */
            /*  search for the next object has to be continued  */
            /*  reset error to e_ok                             */
            TrError = e_ok;
            break;

        default :
            if ((g01vtrace.vtrBdObject_gg00) || (g01vtrace.vtrOmsGet_gg00 ))
                Kernel_VTrace() << "bd90_GetConsistentObjImage:kb67GetObjConsistent Error:" << TrError;
            /* a real error occured */
            break;
        }
    }
    else  // T.A.
    {
        /* now the frame state must be either obsReserved_egg00 or obsKeyReserved_egg00 */
        SAPDBERR_ASSERT_STATE ((pObjFrame->objHeader_bd900.ohdState_gg92 == obsReserved_egg00) ||
                               (pObjFrame->objHeader_bd900.ohdState_gg92 == obsKeyReserved_egg00))

        /* check if new object has been created by current transaction */
        tsp00_Uint2 AuxReqTimeout = Current.curr_trans->trObjReqTimeout_gg00; //save
        Current.curr_trans->trObjReqTimeout_gg00 = 0; // set nowait;

        // check that the update transid corresponds to the own transid (see PTS 1111149)
        kb67LockObj(*Current.curr_trans, Current.curr_tree_id, OId,
                    pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00,
                    pObjFrame->objHeader_bd900.ohdState_gg92,
                    pObjFrame->objHeader_bd900.ohdTransInfo_gg92);

        Current.curr_trans->trObjReqTimeout_gg00 = AuxReqTimeout; // restore timeout

        if (e_ok == TrError)
        {
            /* PTS 1120322 FF 2003-Feb-07*/
            if (pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrUpdTransId_gg00 != 
                Current.curr_trans->trWriteTransId_gg00)
            {
                if ( 0 == g_Committed_obsReserved_Cnt )                    
                {                                                                       
                    g_Committed_obsReserved_Cnt++;
                    Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                        << "Committed object frame without stored data ( state: obsReserved ) found";
                }
                Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
                opWarnMsg << "bd90GetObjConsistent: object within state:"; 
                if (pObjFrame->objHeader_bd900.ohdState_gg92 == obsReserved_egg00)
                    opWarnMsg << "obsReserved_egg00"; 
                else
                    opWarnMsg << "obsKeyReserved_egg00"; 
                opWarnMsg << " read, but not created by this trans!" 
                    << " OID=" << OId.gg92GetPno() << "." << OId.gg92GetPos()
                    << " (vers " << OId.gg92GetFrameVers() << ")"
                    << " (page dumped to file d" 
                    << OId.gg92GetPno() <<".obj)"; 
                b06dump_bad_page (Current.curr_trans->trTaskId_gg00,'d', ".obj", 
                    NptrsPage.np_ptr()->nd_id(), (void *) NptrsPage.np_ptr(), 1);
            }
            else
            {
                /*  object has been created by current transaction, return OId */
                /*  note : Object Body is of no account                        */
                bConsistentObjImageObjFound = true;
                OId.gg92SetFrameVers (pObjFrame->objHeader_bd900.ohdFrameVersion_gg92);  // PTS 1001332 Alexander Kley 31.7.98
            }
        }
        else
        {
            if ((e_lock_collision == TrError) || (e_object_dirty == TrError))
            {
                TrError = e_ok;
                if ((g01vtrace.vtrBdObject_gg00) || (g01vtrace.vtrOmsGet_gg00 ))
                    Kernel_VTrace() << "bd90_GetConsistentObjImage:kb67LockObj Error:" << TrError << " mapped to e_ok";
            }
            else
                if ((g01vtrace.vtrBdObject_gg00) || (g01vtrace.vtrOmsGet_gg00 ))
                    Kernel_VTrace() << "bd90_GetConsistentObjImage:kb67LockObj Error:" << TrError;
        }
    }
}

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