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

  module      : vbd911.cpp

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

  responsible : FerdiF

  special area: recreate/check index for omsKeyedObject Containers
  description : description ...


  version     : 7.4.02.0
  last changed: 2005-03-31  11:32
  see also    : example.html ...

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

  copyright:    Copyright by SAP AG, 1998



    ========== licence begin  GPL
    Copyright (C) 2000 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end

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


/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/
#include "hbd911.h"
#include "gbd05.h"   // cbd05_Current
#include "gbd910.h" 
#include "heo56.h"   // vsleep
#include "Logging/Log_History.hpp"  
#include "Logging/Log_Transaction.hpp"  

#include "hbd01.h"
#include "hbd03.h"
#include "hbd22.h"
#include "hbd90.h"
#include "hkb04.h"
#include "hkb50.h"
#include "hkb51.h"
#include "hkb560.h"
#include "hkb57.h"
#include "hkb67.h"
#include "RunTime/Synchronisation/RTESync_RWRegion.hpp"
#include "RunTime/MemoryManagement/RTEMem_RteAllocator.hpp"

#include "RunTime/System/RTESys_MemoryBarrier.h" 
#include "KernelCommon/Kernel_VTrace.hpp"       
#include "liveCache/LVC_AbstractObjKeyIterator.hpp"
#include "KernelCommon/Kernel_IAdminInfo.hpp"

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

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

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

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

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

extern cbd900_ObjFileDir      bd90ObjFileDir;

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

static RTESync_SpinlockPool *g_SpinLockPool   = NULL;
static RTESync_IRWRegion    *g_IRWLockRegion  = NULL;
static bool					bRecreateActive   = false;

static cbd900_ObjKeyFileId  g_ObjKeyFileId[16];

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

/*===========================================================================*
*  GLOBAL FUNCTIONS (CODE)                                                  *
*===========================================================================*/
externCpp cbd900_ObjKeyFileId& 
bd911GetObjKeyFileId(tsp00_Int4 ix)
{
    return g_ObjKeyFileId[ix];
}

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

externCpp void
bd911InitRWRecreateIndex(void)
{
    if ( NULL == g_SpinLockPool) {                    
        g_SpinLockPool = reinterpret_cast<RTESync_SpinlockPool*>(
            ( RTEMem_RteAllocator::Instance())
            .Allocate(sizeof(RTESync_SpinlockPool)) );
        g_SpinLockPool = new(g_SpinLockPool) RTESync_SpinlockPool( UTF8("bd911:RecreateIndexRWLock"),1);
        g_IRWLockRegion = RTESync_CreateRWRegion( 1, *g_SpinLockPool, RTEMem_RteAllocator::Instance());
    }
}
/*-----------------------------------------------------------------------------------*/

externCpp void
bd911EnterRecreateIndex (tsp00_TaskId  Taskid,
                         bool          exclusiveRequest)
{
    g_IRWLockRegion->enter( exclusiveRequest, Taskid );
}

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

externCpp void
bd911LeaveRecreateIndex(tsp00_TaskId   Taskid,
                        bool           exclusiveRequest)
{ 
    g_IRWLockRegion->leave( exclusiveRequest, Taskid);
} 

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

cbd911RecreateIndexLock::~cbd911RecreateIndexLock()
{
    if(m_locked)
        bd911LeaveRecreateIndex (m_Trans.trTaskId_gg00, m_mode);
};

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

bool
cbd911RecreateIndexLock::Lock(bool  bExclusive)
{
    if (Kernel_IAdminInfo::Instance().KernelStateIsOnline())
    {
        m_mode = bExclusive;
        bd911EnterRecreateIndex (m_Trans.trTaskId_gg00, m_mode);
        m_locked = true;
    }
    return m_locked;
};

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

externCpp void
bd911KeyToConsole( void *const pKey, tsp00_Int4 ObjKeyLen)
{
    Kernel_OpError errmsg( csp3_bd_msg, csp3_n_obj ); 
    errmsg << "key=0x";
    for (int i=0; i < ObjKeyLen; i++)
        errmsg << ToStr((SAPDB_UInt1)*((SAPDB_UInt1*)pKey + i), _T_h);
}

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

externCpp void
bd911CheckIndex (tgg00_TransContext   &Trans,
                 tsp00_Uint4           ObjFileNo)
{
    ROUTINE_DBG_MEO00 ("bd911CheckIndex");

    tgg00_BasisError  &TrError = Trans.trError_gg00;

    Kernel_OpInfo( csp3_n_obj ) << "CHECK INDEX FOR CONTAINER " << ObjFileNo;


    cbd900_ObjFileInfo &ObjFileInfo = bd90ObjFileDir[ObjFileNo];
    if (ObjFileInfo.ofiRelFileIsReq_bd900 ||
        (ObjFileInfo.GetRootPage() == NIL_PAGE_NO_GG00) )    
    {
        Kernel_OpWarning( csp3_bd_msg, csp3_n_obj ) 
            << "bd911CheckIndex - file not found! Fileno:" << ObjFileNo;
        TrError = e_wrong_class_id;
        return;
    }

    if (ObjFileInfo.GetKeyPartitionCount() <= 0)
    {
        Kernel_OpWarning( csp3_bd_msg, csp3_n_obj ) 
            << "bd911CheckIndex - file no keyed object container! Fileno:" << ObjFileNo;
        TrError = e_wrong_class_id;
        return;
    }

    tgg00_BasisError    ReturnError = TrError;

    kb04StartConsistentTrans (Trans);

    tgg00_FileId   ObjFileId;
    ObjFileInfo.bd900BuildFileId (ObjFileNo,ObjFileId);	

    tgg92_KernelOid    OId;    
    OId.gg92SetNil();
    tsp00_Int4         ObjKeyLen;    
    cbd05_Current Current (Trans, m_select, ObjFileId);
    {

        cbd910_PrimObjDataNode NptrsPage(Current, ObjFileInfo.GetRootPage(), nr_for_read);
        if (e_ok == TrError)
            ObjKeyLen  = NptrsPage.np_ptr()->nd_obj_key_len();

        while ((e_ok == TrError) && NptrsPage.bd910PageIsAvailable()) 
        {   
            const tsp00_Bool bWithObject        = SAPDB_FALSE;
            const bool       ignoreEmptyObjects = SAPDB_TRUE;
            const tsp00_Int4 ExtObjBodySize     = 0;
            void*            pExtObjBody        = NULL;
            tgg91_PageRef    ResultObjVers;
            tsp00_Int4       ObjBodySize        = 0;
            tsp00_Bool       bNextObjIsFound    = SAPDB_FALSE;
            tsp00_Int4       LogReadAccessesPerPage;
            tgg91_PageRef    ObjHistRef;
            bd90NextObjConsistentOnThisPage (Current, OId, ResultObjVers, ObjHistRef, bWithObject, 
                ExtObjBodySize, pExtObjBody, NptrsPage, ObjBodySize, bNextObjIsFound, LogReadAccessesPerPage);     
            if (TrError != e_ok)
            {
                Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                    << "bd91CheckIndex - error:" << TrError
                    << " FileNo:" << ObjFileNo
                    << " bd90NextObjConsistentOnThisPage OId=" 
                    << OId.gg92GetPno() << "." 
                    << OId.gg92GetPos() << " (vers " 
                    << OId.gg92GetFrameVers() << " )";
                break;
            }

            if (bNextObjIsFound) 
            { 
                tgg00_BasisError AuxError;
                tgg92_KernelOid  ResultOid;
                tsp00_Key        key;
                void *const      pKey       = (tsp00_Byte*)NptrsPage.np_ptr() + OId.gg92GetPos()
                    + NptrsPage.np_ptr()->nd_obj_frame_len() - NptrsPage.np_ptr()->nd_obj_key_len();
                memcpy(&key[0], pKey, ObjKeyLen);
                NptrsPage.bd910ReleasePage();
                bd22GetOId (Trans, ObjFileId.fileObjFileNo_gg00(), ObjKeyLen, pKey, ResultOid);
                AuxError = TrError;
                TrError = e_ok;
                NptrsPage.bd910AssignToPage(OId.gg92GetPno());
                if ( TrError != e_ok)
                    break;
                else 
                    TrError = AuxError;
                if (TrError != e_ok)
                {
                    Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                        << "bd91CheckIndex - error:" << TrError
                        << " FileNo:" << ObjFileNo
                        << " looking up key for OId=" 
                        << OId.gg92GetPno() << "." 
                        << OId.gg92GetPos() << " (vers " 
                        << OId.gg92GetFrameVers() << " )";
                    bd911KeyToConsole(&key[0], ObjKeyLen);
                    if ( e_ok == ReturnError) 
                        ReturnError = TrError;
                    TrError = e_ok;
                }
                else if ( ! OId.gg92IsEqIgnoreFrameVers(ResultOid))
                {
                    TrError = e_key_not_allowed;
                    Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                        << "bd91CheckIndex - error:" << TrError
                        << " FileNo:" << ObjFileNo
                        << " key mismatch for OId=" 
                        << OId.gg92GetPno() << "." 
                        << OId.gg92GetPos() << " (vers " 
                        << OId.gg92GetFrameVers() << " )"
                        << " found OId="
                        << ResultOid.gg92GetPno() << "." 
                        << ResultOid.gg92GetPos() << " (vers " 
                        << ResultOid.gg92GetFrameVers() << " )";
                    bd911KeyToConsole(&key[0], ObjKeyLen);
                    if ( e_ok == ReturnError) 
                        ReturnError = TrError;
                    TrError = e_ok;
                }
            }
            else
            {
                /* reset OId and  goto next page */
                OId.gg92SetNil();
                NptrsPage.bd910MoveToNextPage();
            }

            if ((TrError == e_ok) && Current.curr_trans->trRteCommPtr_gg00->to_cancel)
            {
                Current.curr_trans->trRteCommPtr_gg00->to_cancel = SAPDB_FALSE;
                TrError = e_cancelled;
                break;
            }

        }
    }

    if ( e_ok == ReturnError) 
        ReturnError = TrError;
    TrError = e_ok;
    kb04EndConsistentTrans (Trans);
    if (e_ok == TrError)
    {
        tsp00_Key     StartKey;
        tsp00_Key     EndKey;
        memset(&StartKey[0],0x00,sizeof(tsp00_Key));
        memset(&EndKey[0],0xff,sizeof(tsp00_Key));
        void *p = NULL;

        kb04CreateKeyIterator (Trans, ObjFileId, ObjKeyLen, &StartKey[0], &StartKey[0], &EndKey[0], 
            p, true /*ascending*/, false /*not readBuffered*/);
        if (NULL != p)
        {
            LVC_AbstractObjKeyIterator &KeyIterator = *reinterpret_cast<LVC_AbstractObjKeyIterator*>(p);

            cbd05_Current  Current (Trans, m_select, ObjFileId);          
            bool bInclusive = true;
            while (!KeyIterator.IsEmpty() && (e_ok == TrError))
            {
                tgg92_KernelOid ResultOId[100];
                tsp00_Int4      noOfOid = 100;
                tsp00_Int4      KeyBufLen = sizeof(StartKey);
                {
                    cbd911RecreateIndexLock lock(Trans);
                    lock.Lock(false /*non exclusive */);
                    KeyIterator.GetNextOIdsWithKey( NULL, &ResultOId[0], noOfOid, &StartKey[0], KeyBufLen, bInclusive); 
                }
                bInclusive = false;

                int i;
                for (i=0; i<noOfOid; ++i)
                {
                    unsigned char* pResultKey = &StartKey[0];
                    pResultKey = pResultKey + i*KeyBufLen;
                    cbd910_PrimObjDataNode   NptrsPage (Current, ResultOId[i].gg92GetPno(), nr_for_read);
                    if(TrError != e_ok) 
                    {
                        NptrsPage.bd910ReleasePage();
                        tgg92_KernelOid Result2OId;
                        bd22GetOId (Trans, ObjFileId.fileObjFileNo_gg00(), ObjKeyLen, pResultKey, Result2OId);
                        if (TrError != e_ok)
                            TrError = e_ok;
                        else if ( ResultOId[i].gg92IsEqIgnoreFrameVers(Result2OId))
                        {
                            TrError = e_key_not_allowed;
                            Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                                << "bd91CheckIndex - error:" << TrError
                                << " FileNo:" << ObjFileNo
                                << " dangling OId=" 
                                << ResultOId[i].gg92GetPno() << "." 
                                << ResultOId[i].gg92GetPos() << " (vers " 
                                << ResultOId[i].gg92GetFrameVers() << " )"
                                << " found";
                            bd911KeyToConsole(pResultKey, ObjKeyLen);
                            if ( e_ok == ReturnError) 
                                ReturnError = TrError;
                            TrError = e_ok;
                        }                   
                    }
                    else
                    {
                        tbd900_ObjFrame* pObjFrame = NptrsPage.bd910ObjFramePtr (ResultOId[i].gg92GetPos());
                        void *const      pKey       = (tsp00_Byte*)NptrsPage.np_ptr() + ResultOId[i].gg92GetPos()
                            + NptrsPage.np_ptr()->nd_obj_frame_len() - NptrsPage.np_ptr()->nd_obj_key_len();
                        memcpy(&StartKey[0], pKey, ObjKeyLen);

                        switch (pObjFrame->objHeader_bd900.ohdState_gg92)
                        {
                        case obsFree_egg00:
                            {
                                NptrsPage.bd910ReleasePage();
                                tgg92_KernelOid Result2OId ;
                                bd22GetOId (Trans, ObjFileId.fileObjFileNo_gg00(), ObjKeyLen, pResultKey, Result2OId);
                                if (TrError != e_ok)
                                    TrError = e_ok;
                                else if ( ResultOId[i].gg92IsEqIgnoreFrameVers(Result2OId))
                                {
                                    TrError = e_key_not_allowed;
                                    Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                                        << "bd91CheckIndex - error:" << TrError
                                        << " FileNo:" << ObjFileNo
                                        << " dangling OId=" 
                                        << ResultOId[i].gg92GetPno() << "." 
                                        << ResultOId[i].gg92GetPos() << " (vers " 
                                        << ResultOId[i].gg92GetFrameVers() << " )"
                                        << " found";
                                    bd911KeyToConsole(pKey, ObjKeyLen);
                                    if ( e_ok == ReturnError) 
                                        ReturnError = TrError;
                                    TrError = e_ok;
                                }                   
                            }
                            break;
                        case obsKeyReserved_egg00:
                        case obsFreeAfterEot_egg00:
                        case obsOccupied_egg00:
                        case obsReserved_egg00:
                            if (pResultKey != NULL)
                            {
                                if ( 0 != memcmp(pResultKey,pKey,NptrsPage.np_ptr()->nd_obj_key_len()))
                                {
                                    NptrsPage.bd910ReleasePage();
                                    tgg92_KernelOid Result2OId;
                                    bd22GetOId (Trans, ObjFileId.fileObjFileNo_gg00(), ObjKeyLen, pResultKey, Result2OId);
                                    if (TrError != e_ok)
                                    {
                                        TrError = e_ok;
                                    }
                                    else if ( ResultOId[i].gg92IsEqIgnoreFrameVers(Result2OId))
                                    {
                                        TrError = e_key_not_allowed;
                                        Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                                            << "bd91CheckIndex - error:" << TrError
                                            << " FileNo:" << ObjFileNo
                                            << " key mismatch OId=" 
                                            << ResultOId[i].gg92GetPno() << "." 
                                            << ResultOId[i].gg92GetPos() << " (vers " 
                                            << ResultOId[i].gg92GetFrameVers() << " )";
                                        bd911KeyToConsole(pKey, ObjKeyLen);
                                        bd911KeyToConsole(pResultKey, ObjKeyLen);
                                        if ( e_ok == ReturnError) 
                                            ReturnError = TrError;
                                        TrError = e_ok;
                                    }                   
                                }
                            }
                            break;
                        }                    
                    }
                }
            }
            if (e_ok == ReturnError) 
                ReturnError = TrError;
            TrError = e_ok; /* make shure the KeyIterator is destroyed */
            kb04DestroyKeyIterator(Trans, p);
        }
    };

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

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

class SingleUseControl
{
public:
    SingleUseControl(tsp00_Uint4  ObjFileNo)
        : m_active(false)
        , m_fileno(ObjFileNo)
    {
        Kernel_OpInfo( csp3_n_obj ) 
            << "start: REPLACE INDEX FOR CONTAINER " << ObjFileNo;
    };

    ~SingleUseControl() {
        if (m_active)
            bRecreateActive = false;
        Kernel_OpInfo( csp3_n_obj ) 
            << "end: REPLACE INDEX FOR CONTAINER " << m_fileno;
    };
    bool SetActive(tgg00_TransContext &Trans) 
    {
        if (! bRecreateActive)
        {
            bRecreateActive = true;
            m_active = true;
        }
        return m_active;
    }
private:
    tsp00_Uint4  m_fileno;
    bool		 m_active;
};

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

externCpp void
bd911RecreateIndex (tgg00_TransContext   &Trans,
                    tsp00_Uint4           ObjFileNo )
{
    ROUTINE_DBG_MEO00 ("bd91RecreateIndex");

    SingleUseControl callOnlyOnce(ObjFileNo); 

    tgg00_BasisError   &TrError     = Trans.trError_gg00;
    cbd900_ObjFileInfo &ObjFileInfo = bd90ObjFileDir[ObjFileNo];

    /* check if the file has been deleted already */
    if (ObjFileInfo.ofiRelFileIsReq_bd900 ||
        (ObjFileInfo.GetRootPage() == NIL_PAGE_NO_GG00) )    
    {
        Kernel_OpWarning( csp3_bd_msg, csp3_n_obj ) 
            << "bd91RecreateIndex - file not found! Fileno:" << ObjFileNo;
        TrError = e_wrong_class_id;
        return;
    }

    if (ObjFileInfo.GetKeyPartitionCount() /*PTS 1134645*/ <= 0)
    {
        Kernel_OpWarning( csp3_bd_msg, csp3_n_obj ) 
            << "bd91RecreateIndex - file no keyed object container! Fileno:" << ObjFileNo;
        TrError = e_wrong_class_id;
        return;
    }

    tgg00_FileId   ObjFileId;
    ObjFileInfo.bd900BuildFileId (ObjFileNo,ObjFileId);	

    tgg92_KernelOid     OId;    
    OId.gg92SetNil();
    tsp00_Int4          ObjFrameLen;
    int                 AlignedObjFrameLen;  
    tsp00_Int4          ObjKeyLen;
    tgg00_ObjPagePos    ObjPos;
    tsp00_Int4          ObjBodySize;

    cbd05_Current Current (Trans, m_select, ObjFileId);
    {
        cbd910_PrimObjDataNode  NptrsPage(Current, ObjFileInfo.GetRootPage() , nr_for_read);
        if (TrError != e_ok) return; 
        ObjFrameLen        = NptrsPage.np_ptr()->nd_obj_frame_len();        
        AlignedObjFrameLen = BD92ALIGN_OBJ_FRAME(ObjFrameLen);  
        ObjKeyLen          = NptrsPage.np_ptr()->nd_obj_key_len();
        ObjBodySize        = ObjFrameLen - sizeof(tgg92_ObjHeader);
    }

    int ix;
    int NumObjKeyFiles = ObjFileInfo.GetKeyPartitionCount();
    {
        cbd911RecreateIndexLock lock(Trans);
        lock.Lock(true /*exclusive */);

        if (!callOnlyOnce.SetActive(Trans))
        {
            Kernel_OpWarning( csp3_bd_msg, csp3_n_obj ) 
                << "bd91RecreateIndex - Recreate already active for some container!";
            TrError = e_recreate_index_failed;
            return;
        }

        for ( ix=0; ix < NumObjKeyFiles ; ix++ )
        {
            /* store root pno in the object file info */
            cbd900_ObjKeyFileId& ObjKeyFileId = bd911GetObjKeyFileId(ix);
            ObjKeyFileId.bd900SetObjKeyFileId(ObjFileInfo, ObjFileNo, ix + NumObjKeyFiles);
            b01fcreate_file (Trans, ObjKeyFileId, 0, false);	
            if (e_duplicate_filename == Trans.trError_gg00)
            {
                Trans.trError_gg00 = e_ok;
                b01pdestroy_perm_file (Trans, ObjKeyFileId);
                if (e_ok == Trans.trError_gg00)
                    b01fcreate_file (Trans, ObjKeyFileId, 0, false);	
            }
            if (e_ok != Trans.trError_gg00)
            {
                Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                    << "bd91RecreateIndex - file create error:" << Trans.trError_gg00
                    << " FileNo:" << ObjFileNo
                    << " KeyIndex:" << ix;
                return;
            }
        }

        RTESys_WriteMemoryBarrier();
        ObjFileInfo.bd900RecreateIndex() = SAPDB_TRUE;
        RTESys_WriteMemoryBarrier();
    }

    tgg91_TransNo WriteTransNo;
    k57new_write_trans(Trans.trTaskId_gg00 ,WriteTransNo);
    k51WaitForAllOlderActiveTransToStop(Trans);

    bool  bTryAgain = true;
    while ( bTryAgain 
        && ( ObjFileInfo.bd900RecreateIndexError() == e_ok )
        && (e_ok == TrError))
    {
        bTryAgain = false;
        tgg00_ObjPagePos ObjPosBeg = OId.gg92GetPos();
        tsp00_PageNo     actPage   = OId.gg92GetPno();
        if (NIL_PAGE_NO_GG00 == actPage) 
            actPage = ObjFileInfo.GetRootPage();
        {
            cbd910_PrimObjDataNode  NptrsPage(Current, actPage, nr_for_update);
            if (e_ok != Trans.trError_gg00)
                return;
            do 
            {
                if ( NptrsPage.np_ptr()->nd_max_obj_cnt() > NptrsPage.np_ptr()->nd_free_obj_cnt())
                {
                    if ( ObjPosBeg == 0 )
                        ObjPosBeg = NptrsPage.np_ptr()->nd_first_obj();

                    for ( ObjPos = ObjPosBeg;
                        ((ObjPos + ObjFrameLen) <= BODY_END_BD00) && (e_ok == TrError);
                        ObjPos += AlignedObjFrameLen )
                    { 
                        OId.gg92SetPno (NptrsPage.np_ptr()->nd_id());
                        OId.gg92SetPos (ObjPos);                   
                        tbd900_ObjFrame* pObjFrame = NptrsPage.bd910ObjFramePtr (ObjPos);
                        OId.gg92SetFrameVers (pObjFrame->objHeader_bd900.ohdFrameVersion_gg92);

                        switch (pObjFrame->objHeader_bd900.ohdState_gg92)
                        {
                        case obsKeyReserved_egg00:
                            if (WriteTransNo > 
                                pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrLockTransId_gg00 )
                                do 
                                {
                                    tgg91_PageRef WantedObjVers = pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00;
                                    tsp00_Uint2 AuxReqTimeout = Current.curr_trans->trObjReqTimeout_gg00; //save
                                    Current.curr_trans->trObjReqTimeout_gg00 = 9000;   
                                    kb67LockObj (*Current.curr_trans, Current.curr_tree_id, OId, WantedObjVers,
                                        pObjFrame->objHeader_bd900.ohdState_gg92,
                                        pObjFrame->objHeader_bd900.ohdTransInfo_gg92);
                                    Current.curr_trans->trObjReqTimeout_gg00 = AuxReqTimeout;   
                                    if (e_ok == Trans.trError_gg00)
                                    {
                                        Trans.trError_gg00 = e_recreate_index_failed;
                                        Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                                            << "bd91RecreateIndex - error:" << TrError
                                            << " FileNo:" << ObjFileNo
                                            << " OId=" 
                                            << OId.gg92GetPno() << "." 
                                            << OId.gg92GetPos() << " (vers " 
                                            << OId.gg92GetFrameVers() << " )"
                                            << " obsKeyReserved could be locked";
                                    }
                                }
                                while ((pObjFrame->objHeader_bd900.ohdState_gg92 == obsKeyReserved_egg00) 
                                    &&
                                    (e_ok == Trans.trError_gg00));

                                break;
                        case obsFreeAfterEot_egg00:
                            {
                                bool           bSkipOid            = false;
                                tgg91_PageRef  CurrEntryRef;
                                tsp00_Uint4    BodyLen             = ObjBodySize;
                                tgg00_ObjFrameVers ResultFrameVers = NIL_OBJ_FRAME_VERS_GG92;
                                Log_ActionType ActionType          = Log_DeleteObject;
                                tgg91_TransNo  ConsistentView;
                                tgg91_TransNo  PrevUpdTrans;
                                tgg91_PageRef  NextPageRef;
                                CurrEntryRef = pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrBeforeRef_gg00;

                                if ( NIL_PAGE_NO_GG00 == CurrEntryRef.gg91RefPno())
                                {
                                    Kernel_OpWarning( csp3_bd_msg, csp3_n_obj ) 
                                        << "bd91RecreateIndex - obsFreeAfterEot without history found"
                                        << " FileNo:" << ObjFileNo
                                        << " OId=" 
                                        << OId.gg92GetPno() << "." 
                                        << OId.gg92GetPos() << " (vers " 
                                        << OId.gg92GetFrameVers() << " )";
                                    Trans.trError_gg00 = e_obj_history_not_found;
                                }
                                else
                                {
                                    Log_History::GetBeforeImage (Trans,
                                        OId,
                                        CurrEntryRef,
                                        0,              /* ObjBodySize */
                                        NULL,           /* pBody */
                                        false,          /* bOnlyExistenceCheck */
                                        BodyLen, 
                                        ResultFrameVers,
                                        ActionType,
                                        ConsistentView,
                                        PrevUpdTrans,
                                        NextPageRef);

                                    if  ((e_ok != Trans.trError_gg00) || (ActionType != Log_DeleteObject ))
                                    {
                                        Kernel_OpWarning( csp3_bd_msg, csp3_n_obj ) 
                                            << "bd91RecreateIndex - obsFreeAfterEot error:" << TrError
                                            << " FileNo:" << ObjFileNo
                                            << " OId=" 
                                            << OId.gg92GetPno() << "." 
                                            << OId.gg92GetPos() << " (vers " 
                                            << OId.gg92GetFrameVers() << " )"
                                            << " ActionType:" << ActionType;
                                        Trans.trError_gg00 = e_recreate_index_failed;
                                        bSkipOid = true;
                                    } 
                                    else if (PrevUpdTrans != pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrUpdTransId_gg00)
                                        bSkipOid = false;
                                    else
                                    {
                                        while (e_ok == Trans.trError_gg00) 
                                        {
                                            CurrEntryRef = NextPageRef;
                                            if ( NIL_PAGE_NO_GG00 == CurrEntryRef.gg91RefPno())
                                                Trans.trError_gg00 = e_obj_history_not_found;
                                            else
                                            {
                                                Log_History::GetBeforeImage (Trans,
                                                    OId,
                                                    CurrEntryRef,
                                                    0,              /* ObjBodySize */
                                                    NULL,           /* pBody */
                                                    false,          /* bOnlyExistenceCheck */
                                                    BodyLen, 
                                                    ResultFrameVers,
                                                    ActionType,
                                                    ConsistentView,
                                                    PrevUpdTrans,
                                                    NextPageRef);
                                            }
                                            if  (e_ok == Trans.trError_gg00)
                                            {
                                                if ((ActionType == Log_NewObject )
                                                    && (PrevUpdTrans.gg90IsNil()))
                                                {
                                                    bSkipOid = true;
                                                    break;
                                                }
                                                else if (PrevUpdTrans != pObjFrame->objHeader_bd900.ohdTransInfo_gg92.otrUpdTransId_gg00)
                                                {
                                                    bSkipOid = false;
                                                    break;
                                                }
                                            }
                                            if ((e_ok != Trans.trError_gg00) 
                                                && (e_obj_history_not_found != Trans.trError_gg00))
                                            {
                                                Kernel_OpError( csp3_bd_msg, csp3_n_obj )
                                                    << " recreateindex history access error:" << Trans.trError_gg00
                                                    << " OID=" << OId.gg92GetPno() << "." 
                                                    << OId.gg92GetPos() << " (vers " << OId.gg92GetFrameVers() << ")";
                                            }
                                        }
                                    }
                                }

                                if (e_obj_history_not_found == Trans.trError_gg00)
                                {
                                    bSkipOid = true;
                                    Trans.trError_gg00 = e_ok;
                                }

                                if (e_ok != Trans.trError_gg00) 
                                    break;

                                if (!bSkipOid)                                
                                {
                                    tsp00_Int4    ObjKeyFileIndex;
                                    tbd_nodeptr  &pPage = NptrsPage.np_ptr();
                                    void *const   pKey  = (tsp00_Byte*) pPage + ObjPos + ObjFrameLen - ObjKeyLen;
                                    ObjKeyFileIndex = (NumObjKeyFiles == 1 ? 0 :bd22ObjKeyFileIndex (ObjKeyLen, pKey, NumObjKeyFiles)); 
                                    cbd900_ObjKeyFileId&  ObjKeyFileId = bd911GetObjKeyFileId(ObjKeyFileIndex);

                                    tsp00_Int4       FoundOIdLen;
                                    tgg92_KernelOid  FoundOId;
                                    FoundOId.gg92SetNil();

                                    bd03OmsAddInv (Trans, ObjKeyFileId,
                                        tsp00_BytePtr (pKey), ObjKeyLen, tsp00_BytePtr(&OId), sizeof(OId),
                                        sizeof(FoundOId), tsp00_BytePtr(&FoundOId), FoundOIdLen);
                                    if (g01vtrace.vtrOmsUpd_gg00)
                                    {
                                        Kernel_VTrace vtrace;
                                        vtrace << __FILE__ << ":" << __LINE__ << 
                                            " recreateindex ADD freeaftereot OID=" << OId.gg92GetPno() << "." 
                                            << OId.gg92GetPos() << " (vers " << OId.gg92GetFrameVers() << ") KeyLen:"
                                            << ObjKeyLen << " Key=";
                                        for (int i=0; i < ObjKeyLen; i++)
                                            vtrace << ToStr((SAPDB_UInt1)*((SAPDB_UInt1*)pKey + i), _T_h);
                                        vtrace << " error:" << TrError
                                            << " ActionType" << ActionType
                                            << " CurrEntyRef:" << ( NIL_PAGE_NO_GG00 == CurrEntryRef.gg91RefPno());
                                        vtrace << FlushLine;
                                        vtrace << "Object found via key OID=" 
                                            << FoundOId.gg92GetPno() << "." 
                                            << FoundOId.gg92GetPos() << " (vers " 
                                            << FoundOId.gg92GetFrameVers() << " )";
                                    }
                                    switch (TrError)
                                    {
                                    case e_ok:
                                        break;
                                    case e_duplicate_invkey:
                                    case e_duplicate_key   : 
                                        if ( OId.gg92IsEqIgnoreFrameVers(FoundOId))
                                            TrError = e_ok; 
                                        else
                                        {
                                            Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                                                << "bd91RecreateIndex - error:" << TrError
                                                << " FileNo:" << ObjFileNo
                                                << " OId=" 
                                                << OId.gg92GetPno() << "." 
                                                << OId.gg92GetPos() << " (vers " 
                                                << OId.gg92GetFrameVers() << " )"
                                                << " and OId=" 
                                                << FoundOId.gg92GetPno() << "." 
                                                << FoundOId.gg92GetPos() << " (vers " 
                                                << FoundOId.gg92GetFrameVers() << " )"
                                                << " have same key";
                                            bd911KeyToConsole(pKey, ObjKeyLen);
                                        }
                                        break;
                                    default:
                                        {
                                            Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                                                << "bd91RecreateIndex - error:" << TrError
                                                << " FileNo:" << ObjFileNo
                                                << " OId=" 
                                                << OId.gg92GetPno() << "." 
                                                << OId.gg92GetPos() << " (vers " 
                                                << OId.gg92GetFrameVers() << " )";
                                            bd911KeyToConsole(pKey, ObjKeyLen);
                                        }
                                    }
                                }
                                else
                                {
                                    tbd_nodeptr  &pPage = NptrsPage.np_ptr();
                                    void *const   pKey  = (tsp00_Byte*) pPage + ObjPos + ObjFrameLen - ObjKeyLen;
                                    if (g01vtrace.vtrOmsUpd_gg00)
                                    {
                                        Kernel_VTrace vtrace;
                                        vtrace << " recreateindex SKIP freeaftereot OID=" << OId.gg92GetPno() << "." 
                                            << OId.gg92GetPos() << " (vers " << OId.gg92GetFrameVers() << ") KeyLen:"
                                            << ObjKeyLen << " Key=";
                                        for (int i=0; i < ObjKeyLen; i++)
                                            vtrace << ToStr((SAPDB_UInt1)*((SAPDB_UInt1*)pKey + i), _T_h);
                                        vtrace << " error:" << TrError
                                            << " ActionType:" << ActionType;
                                    }
                                }
                            }
                            break;
                        case obsOccupied_egg00:
                            {
                                tsp00_Int4    ObjKeyFileIndex;
                                tbd_nodeptr  &pPage = NptrsPage.np_ptr();
                                void *const   pKey  = (tsp00_Byte*) pPage + ObjPos + ObjFrameLen - ObjKeyLen;
                                ObjKeyFileIndex = (NumObjKeyFiles == 1 ? 0 :bd22ObjKeyFileIndex (ObjKeyLen, pKey, NumObjKeyFiles)); 
                                cbd900_ObjKeyFileId&  ObjKeyFileId = bd911GetObjKeyFileId(ObjKeyFileIndex);

                                tsp00_Int4       FoundOIdLen;
                                tgg92_KernelOid  FoundOId;
                                FoundOId.gg92SetNil();

                                bd03OmsAddInv (Trans, ObjKeyFileId,
                                    tsp00_BytePtr (pKey), ObjKeyLen, tsp00_BytePtr(&OId), sizeof(OId),
                                    sizeof(FoundOId), tsp00_BytePtr(&FoundOId), FoundOIdLen);

                                if (g01vtrace.vtrOmsUpd_gg00)
                                {
                                    Kernel_VTrace vtrace;
                                    vtrace << " recreateindex ADD occupied OID=" << OId.gg92GetPno() << "." 
                                        << OId.gg92GetPos() << " (vers " << OId.gg92GetFrameVers() << ") KeyLen:"
                                        << ObjKeyLen << " Key=";
                                    for (int i=0; i < ObjKeyLen; i++)
                                        vtrace << ToStr((SAPDB_UInt1)*((SAPDB_UInt1*)pKey + i), _T_h);
                                    vtrace << " error:" << TrError;
                                    vtrace << FlushLine;
                                    vtrace << "Object found via key OID=" 
                                        << FoundOId.gg92GetPno() << "." 
                                        << FoundOId.gg92GetPos() << " (vers " 
                                        << FoundOId.gg92GetFrameVers() << " )";
                                }                                    
                                switch (TrError)
                                {
                                case e_ok:
                                    break;
                                case e_duplicate_invkey:
                                case e_duplicate_key   : 
                                    if ( OId.gg92IsEqIgnoreFrameVers(FoundOId))
                                        TrError = e_ok; 
                                    else
                                    {
                                        Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                                            << "bd91RecreateIndex - error:" << TrError
                                            << " FileNo:" << ObjFileNo
                                            << " OId=" 
                                            << OId.gg92GetPno() << "." 
                                            << OId.gg92GetPos() << " (vers " 
                                            << OId.gg92GetFrameVers() << " )"
                                            << " and OId=" 
                                            << FoundOId.gg92GetPno() << "." 
                                            << FoundOId.gg92GetPos() << " (vers " 
                                            << FoundOId.gg92GetFrameVers() << " )"
                                            << " have same key";
                                        bd911KeyToConsole(pKey, ObjKeyLen);
                                    }
                                    break;
                                default:
                                    {
                                        Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                                            << "bd91RecreateIndex - error:" << TrError
                                            << " FileNo:" << ObjFileNo
                                            << " OId=" 
                                            << OId.gg92GetPno() << "." 
                                            << OId.gg92GetPos() << " (vers " 
                                            << OId.gg92GetFrameVers() << " )";
                                        bd911KeyToConsole(pKey, ObjKeyLen);
                                    }
                                }
                            }
                            break;
                        case obsFree_egg00:
                            break;
                        case obsReserved_egg00:
                            {
                                TrError = e_wrong_object_state;
                                Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                                    << "bd91RecreateIndex - error:" << TrError
                                    << " FileNo:" << ObjFileNo
                                    << " OId=" 
                                    << OId.gg92GetPno() << "." 
                                    << OId.gg92GetPos() << " (vers " 
                                    << OId.gg92GetFrameVers() << " )";
                            }
                        }                      
                    }
                } 
                if (e_ok == TrError)
                {
                    ObjPosBeg = 0;
                    NptrsPage.bd910MoveToNextPage();
                }
            }  
            while ((e_ok == TrError) 
                && ( ObjFileInfo.bd900RecreateIndexError() == e_ok )
                && NptrsPage.bd910PageIsAvailable());  
        }
        if (e_wait_for_lock_release == Trans.trError_gg00)
        {   
            Trans.trError_gg00 = e_ok;
            kb50WaitAndRetryObjLock (Trans, m_lock, mm_object);
            bTryAgain = (e_ok == Trans.trError_gg00);  
        }
    }

    {
        cbd911RecreateIndexLock lock(Trans);
        lock.Lock(true /*exclusive */);
        if (( ObjFileInfo.bd900RecreateIndexError() == e_ok ) &&  (e_ok == TrError))
        {
            if ((e_ok == TrError) && ( ObjFileInfo.bd900RecreateIndexError() == e_ok ))
            {
                cbd910_PrimObjDataNode  NptrsPage(Current, ObjFileInfo.GetRootPage() , nr_for_update);
                if (e_ok == TrError)
                    TrError = ObjFileInfo.bd900RecreateIndexError();
                if (e_ok == TrError)
                {
                    cbd900_RootPageInfo RootPageInfo (NptrsPage);
                    for ( ix=0; ix < NumObjKeyFiles ; ix++ )
                    {
                        cbd900_ObjKeyFileId    ObjKeyFileId (ObjFileInfo, ObjFileNo, (ix));
                        cbd900_ObjKeyFileId    ObjKeyFileIdRenamed (ObjFileInfo, ObjFileNo, (ix));
                        ObjKeyFileIdRenamed.fileObjKeyFileIndex_gg00() = (ix + 2*NumObjKeyFiles);
                        cbd900_ObjKeyFileId    ObjKeyFileIdNew = bd911GetObjKeyFileId(ix);
                        cbd900_ObjKeyFileId    ObjKeyFileIdNewRenamed = bd911GetObjKeyFileId(ix);
                        ObjKeyFileIdNewRenamed.fileObjKeyFileIndex_gg00() = ix;

                        b01rename_file (Trans, ObjKeyFileId, ObjKeyFileIdRenamed);
                        if (e_ok != Trans.trError_gg00)
                        {
                            Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                                << "bd91RecreateIndex - original file rename error:" << Trans.trError_gg00
                                << " FileNo:" << ObjFileNo
                                << " KeyIndex:" << ix;
                        }
                        else
                        {
                            b01rename_file (Trans, ObjKeyFileIdNew, ObjKeyFileIdNewRenamed);
                            if (e_ok != Trans.trError_gg00)
                            {
                                Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                                    << "bd91RecreateIndex - new file rename error:" << Trans.trError_gg00
                                    << " FileNo:" << ObjFileNo
                                    << " KeyIndex:" << ix;
                            }
                            else
                            {
                                ObjFileInfo.ofiKeyRoots_bd900[ix] = ObjKeyFileIdNewRenamed.fileRoot_gg00(); 
                                b01pdestroy_perm_file (Trans, ObjKeyFileIdRenamed);
                                if (e_ok != Trans.trError_gg00)
                                {
                                    Kernel_OpWarning( csp3_bd_msg, csp3_n_obj ) 
                                        << "bd91RecreateIndex - old idx file destroy error:" << Trans.trError_gg00
                                        << " FileNo:" << ObjFileNo
                                        << " KeyIndex:" << ix;
                                    TrError = e_ok;
                                }
                            }
                        }
                    }
                }
            }
        }

        if ( ObjFileInfo.bd900RecreateIndexError() != e_ok )
            if (e_ok == TrError) 
                TrError = ObjFileInfo.bd900RecreateIndexError();

        if (e_ok != TrError)
        {
            tgg00_BasisError auxError = TrError;
            TrError = e_ok;
            for ( ix=0; ix < NumObjKeyFiles ; ix++ )
            {
                cbd900_ObjKeyFileId&  ObjKeyFileId = bd911GetObjKeyFileId(ix);
                b01pdestroy_perm_file (Trans, ObjKeyFileId);
                if (e_ok != Trans.trError_gg00)
                {
                    Kernel_OpWarning( csp3_bd_msg, csp3_n_obj ) 
                        << "bd91RecreateIndex - file destroy error:" << Trans.trError_gg00
                        << " FileNo:" << ObjFileNo
                        << " KeyIndex:" << ix;
                    TrError = e_ok;
                }
            }
            TrError = auxError;
        }
        RTESys_WriteMemoryBarrier();
        ObjFileInfo.bd900RecreateIndex() = SAPDB_FALSE;         
        RTESys_WriteMemoryBarrier();
    }

    /* write savepoint without holding "recreate"-lock */ 
    if (e_ok == TrError)
        kb560StartSavepointAndWait (Trans, mm_index);
        
};

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