/*!**************************************************************************

  module:       vbd22.cpp
  special area: OMS_KeyManagement
  responsible:  UweH
  last changed: 1999-11-05  17:00
  version:      7.2.0.0
  see also: 
  copyright:    (c) 1998-2004 SAP AG
  description:  Map an object key to an OID, there is no consistent-check done.



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

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

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

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


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


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

#include "hbd22.h"

#include "ggg01.h" // OMS errors
#include "ggg12.h"
#include "gbd900.h"
#include "gsp03_3.h"

#include "hbd01.h"
#include "hbd03.h"
#include "hbd17.h" 
#include "hbd911.h"
#include "hbd92.h"
#include "hgg01_1.h"
#include "hgg01_3.h"
#include "SAPDB/SAPDBCommon/SAPDB_RangeCode.hpp" // Kernel_move_and_fill
#include "KernelCommon/Kernel_IAdminInfo.hpp"
#include "RunTime/System/RTESys_MemoryBarrier.h" 
#include "hgg10.h"

#include "Trace/Trace_Entry.hpp"

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

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

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

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

//PTS 1112190 18/10/2001
#define CHECK_NUM_KEY_FILES( NUM_KEY_FILES) \
    if ((NUM_KEY_FILES) == 0)\
	{\
		g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,\
			"BD22NumKeyFiles: FileNo ", ObjFileNo);\
		g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,\
			"BD22NumKeyFiles: Root   ", ObjFileInfo.GetRootPage());\
		g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,\
			"BD22NumKeyFiles: DropFile", ObjFileInfo.ofiDropFile_bd900);\		
		g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,\
			"BD22NumKeyFiles: RelFile", ObjFileInfo.ofiRelFileIsReq_bd900);\		
		Trans.trError_gg00 = e_illegal_filename;\
		return;\
	}


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

extern cbd900_ObjFileDir  bd90ObjFileDir;

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

static const bool bExclusive = true;

/*===========================================================================*
 *  LOCAL FUNCTIONS                                                          *
 *===========================================================================*/

inline static void 
bd22_GetOId (tgg00_TransContext   &Trans,
			 cbd900_ObjKeyFileId   ObjKeyFileId,
			 tsp00_Int4            KeyLen,
			 void                 *pKey,
			 tgg92_KernelOid      &Oid)
{
    ROUTINE_DBG_MEO00 ("bd22_GetOid");

    tgg00_BasisError &TrError = Trans.trError_gg00;

	if (TrError != e_ok) return;
        
    tsp00_Int4 DummyOIdLen;
    bd03OmsGetInv (Trans, ObjKeyFileId, tsp00_BytePtr (pKey), KeyLen, sizeof(Oid), tsp00_BytePtr(&Oid), DummyOIdLen);

	switch (TrError)
	{
    case e_ok                :  SAPDBERR_ASSERT_STATE (DummyOIdLen == sizeof(tgg92_KernelOid));break;
	case e_inv_list_not_found:
	case e_key_not_found     : 	
        TrError = e_hash_key_not_found; 
        Oid.gg92SetNil();           /* PTS 1116881 to avoid that error-tracing uses uninitialized OID */
        break;
	case e_inv_not_found     :  
        TrError = e_hash_not_found;     
        Oid.gg92SetNil();           /* PTS 1116881 to avoid that error-tracing uses uninitialized OID */
        break;
	}
};

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

externCpp tsp00_Int4
bd22ObjKeyFileIndex (const	tsp00_Int4      KeyLen,
                     void                 *pKey,
                     const tsp00_Uint4     NumHashValues)
{
    /* this function hashes a key onto an integer value h with 0<= h <  NumHashValues */

    tsp00_Int4 sum = 0;
    for (tsp00_Int4 i=0; i<KeyLen; ++i)
        sum += *((char *) pKey + i);

    return (sum%NumHashValues);
}

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

externCpp void 
bd22CreateObjKeyFiles (tgg00_TransContext &Trans,
                       tgg00_ObjFileNo     ObjFileNo,
					   tsp00_Int4          NumObjKeyFiles)
{
    ROUTINE_DBG_MEO00 ("bd22CreateObjKeyFile");
	
	cbd900_ObjFileInfo    &ObjFileInfo = bd90ObjFileDir [ObjFileNo];
	
    for (tsp00_Int4 iKeyFile=0; iKeyFile < NumObjKeyFiles; ++iKeyFile)
    {
        cbd900_ObjKeyFileId    ObjKeyFileId (ObjFileInfo, ObjFileNo, iKeyFile);
        b01fcreate_file (Trans, ObjKeyFileId, 0, false);

        /* store root pno in the object file info */
        if (e_ok == Trans.trError_gg00)
            ObjFileInfo.ofiKeyRoots_bd900[iKeyFile] = ObjKeyFileId.fileRoot_gg00();
        else if ((e_duplicate_filename == Trans.trError_gg00) &&
            Kernel_IAdminInfo::Instance().KernelStateIsRestart())
        {
            /* PTS 1130786 FF 2004-07-28 ignore error during restart */
            Trans.trError_gg00 = e_ok;
            b01filestate (Trans, ObjKeyFileId);
            if (e_ok == Trans.trError_gg00)
                ObjFileInfo.ofiKeyRoots_bd900[iKeyFile] = ObjKeyFileId.fileRoot_gg00();
        }
        if (e_ok != Trans.trError_gg00)
        {
            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                "BD22CreKeyFile:b_error  ", Trans.trError_gg00);
            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                "BD22CreKeyFile:ObjFileNo", ObjFileNo);
            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
                "BD22CreKeyFile:KeyIndex ", iKeyFile);
            Trans.trError_gg00 = e_wrong_class_id;
        }
    }
}

/*-----------------------------------------------------------------------------------*/
/* PTS 1107153 AK 17/07/2000 */

externCpp void
bd22GetLeaveCountOfObjKeyFiles (tgg00_TransContext  &Trans,
							    tgg00_ObjFileNo      ObjFileNo,
							    cbd900_ObjFileInfo  &ObjFileInfo,
							    tsp00_Int4          &NumKeyLeaves)
{
	const tsp00_Bool       cCountLeavesOnly = true;
	tsp00_Int4             DummyAvgPrimKeyCountPerPage;
	tsp00_Int4             NumKeyLeavesOfOneFile;
	NumKeyLeaves = 0;          
	
	for (tsp00_Uint4 iKeyFile=0; iKeyFile<ObjFileInfo.GetKeyPartitionCount(); ++iKeyFile)
	{
		cbd900_ObjKeyFileId    ObjKeyFileId (ObjFileInfo, ObjFileNo, iKeyFile);
		
		bd03StatisticsUpdate (Trans, ObjKeyFileId, NumKeyLeavesOfOneFile,
			DummyAvgPrimKeyCountPerPage, cCountLeavesOnly);
		NumKeyLeaves += NumKeyLeavesOfOneFile;
	}
	
}

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

externCpp void
bd22ReleaseObjKeyFiles (tgg00_TransContext  &Trans,
						tgg00_ObjFileNo      ObjFileNo,
						cbd900_ObjFileInfo  &ObjFileInfo)
{
	ROUTINE_DBG_MEO00 ("bd22ReleaseObjKeyFiles");
	
#   if COMPILEMODE_MEO00 >= QUICK_MEO00
	if (ObjFileInfo.GetKeyPartitionCount() <= 0)
		g01abort (csp3_bd_msg, csp3_n_obj, "BD22RelKeyFile:NoKeyFile", ObjFileNo);
#   endif
	
	for (tsp00_Uint4 iKeyFile=0; iKeyFile<ObjFileInfo.GetKeyPartitionCount(); ++iKeyFile)
	{
		cbd900_ObjKeyFileId    ObjKeyFileId (ObjFileInfo, ObjFileNo, iKeyFile);
		b01pdestroy_perm_file (Trans, ObjKeyFileId);
		if (e_ok != Trans.trError_gg00)
		{
			g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
				"BD22RelKeyFile:FileIndex", iKeyFile);
			g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
				"BD22RelKeyFile:FileNo   ", ObjFileNo);
			g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
				"BD22RelKeyFile:Error   ", Trans.trError_gg00);			
			return;
		}
		//ObjFileInfo.ofiKeyRoots_bd900[iKeyFile] = NIL_PAGE_NO_GG00;
	}
}

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

externCpp void 
bd22GetOId (tgg00_TransContext  &Trans,
			tgg00_ObjFileNo      ObjFileNo,
			tsp00_Int4           KeyLen,
			void                *pKey,
			tgg92_KernelOid     &Oid)
{
    ROUTINE_DBG_MEO00 ("bd22GetOid");
	 
	cbd900_ObjFileInfo    &ObjFileInfo    = bd90ObjFileDir [ObjFileNo];

    cbd911RecreateIndexLock lock(Trans);   
    if (ObjFileInfo.bd900RecreateIndex()) 
        lock.Lock( !bExclusive );

	const tsp00_Int4       NumObjKeyFiles = ObjFileInfo.GetKeyPartitionCount();
	CHECK_NUM_KEY_FILES (NumObjKeyFiles); //PTS 1112190 18/10/2001
	tsp00_Int4 ObjKeyFileIndex = (NumObjKeyFiles == 1 ? 0:bd22ObjKeyFileIndex (KeyLen, pKey, NumObjKeyFiles)); 
	cbd900_ObjKeyFileId  ObjKeyFileId (ObjFileInfo, ObjFileNo, ObjKeyFileIndex);
	bd22_GetOId (Trans, ObjKeyFileId , KeyLen, pKey, Oid);		
}

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

externCpp void 
bd22InsertOId (tgg00_TransContext &Trans,
			   tgg00_ObjFileNo     ObjFileNo,
			   tsp00_Int4          KeyLen,
			   void               *pKey,
			   tgg92_KernelOid     OId,
			   tgg92_KernelOid    &FoundOId)
{
    ROUTINE_DBG_MEO00 ("bd22InsertOId");

    tgg00_BasisError &TrError   = Trans.trError_gg00;

    if ( TrError != e_ok) return;

	cbd900_ObjFileInfo    &ObjFileInfo = bd90ObjFileDir [ObjFileNo];

    cbd911RecreateIndexLock lock(Trans);   
    if (ObjFileInfo.bd900RecreateIndex()) 
        lock.Lock( !bExclusive );

    const tsp00_Int4       NumObjKeyFiles = ObjFileInfo.GetKeyPartitionCount();
	CHECK_NUM_KEY_FILES (NumObjKeyFiles); //PTS 1112190 18/10/2001
	tsp00_Int4 ObjKeyFileIndex = (NumObjKeyFiles == 1 ? 0 :bd22ObjKeyFileIndex (KeyLen, pKey, NumObjKeyFiles)); 
    cbd900_ObjKeyFileId  ObjKeyFileId (ObjFileInfo, ObjFileNo, ObjKeyFileIndex);

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

	switch (TrError)
	{
	case e_duplicate_invkey:
	case e_duplicate_key   : TrError = e_duplicate_hash_key; break;
    case e_inv_not_found   : TrError = e_hash_not_found;     break;
	}
         // PTS 1134645
    if ( ObjFileInfo.bd900RecreateIndex() && ( e_ok == TrError ))
    {
        cbd900_ObjKeyFileId& ObjKeyFileId = bd911GetObjKeyFileId(ObjKeyFileIndex);
        bd03OmsAddInv (Trans, ObjKeyFileId,
            tsp00_BytePtr (pKey), KeyLen, tsp00_BytePtr(&OId), sizeof(OId),
            sizeof(FoundOId), tsp00_BytePtr(&FoundOId), FoundOIdLen);
        if (e_ok != TrError)
        {			
            Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                << "bd22InsertOId for RecreateIndex - error:" << TrError
                << " FileNo:" << ObjFileNo
                << " OId=" 
                << OId.gg92GetPno() << "." 
                << OId.gg92GetPos() << " (vers " 
                << OId.gg92GetFrameVers() << " )";
            bd911KeyToConsole(pKey, KeyLen);
            RTESys_ReadMemoryBarrier();
            if ( ObjFileInfo.bd900RecreateIndexError() == e_ok )
                ObjFileInfo.bd900RecreateIndexError() = TrError;
            RTESys_WriteMemoryBarrier();
            TrError = e_ok;
        }
    }
}
 /*-----------------------------------------------------------------------------------*/
 
externCpp void 
bd22InsertOIdReCreate (tgg00_TransContext &Trans,
                       tgg00_ObjFileNo     ObjFileNo,
                       tsp00_Int4          KeyLen,
                       void               *pKey,
                       tgg92_KernelOid     OId,
                       tgg92_KernelOid    &FoundOId)
{
    ROUTINE_DBG_MEO00 ("bd22InsertOIdReCreate");

    tgg00_BasisError &TrError   = Trans.trError_gg00;

    if ( TrError != e_ok) return;

    cbd900_ObjFileInfo    &ObjFileInfo = bd90ObjFileDir [ObjFileNo];

    const tsp00_Int4       NumObjKeyFiles = ObjFileInfo.GetKeyPartitionCount();
    CHECK_NUM_KEY_FILES (NumObjKeyFiles); //PTS 1112190 18/10/2001
    tsp00_Int4 ObjKeyFileIndex = (NumObjKeyFiles == 1 ? 0 :bd22ObjKeyFileIndex (KeyLen, pKey, NumObjKeyFiles)); 
    cbd900_ObjKeyFileId& ObjKeyFileId = bd911GetObjKeyFileId(ObjKeyFileIndex);

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

    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 ) 
                << "bd22InsertOId for RecreateIndex - 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, KeyLen);
            RTESys_ReadMemoryBarrier();
            if ( ObjFileInfo.bd900RecreateIndexError() == e_ok )
                ObjFileInfo.bd900RecreateIndexError() = TrError;
            RTESys_WriteMemoryBarrier();
            TrError = e_ok;
        }
        break;
    default:
        {
            Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                << "bd22InsertOId for RecreateIndex - error:" << TrError
                << " FileNo:" << ObjFileNo
                << " OId=" 
                << OId.gg92GetPno() << "." 
                << OId.gg92GetPos() << " (vers " 
                << OId.gg92GetFrameVers() << " )";
            bd911KeyToConsole(pKey, KeyLen);
            RTESys_ReadMemoryBarrier();
            if ( ObjFileInfo.bd900RecreateIndexError() == e_ok )
                ObjFileInfo.bd900RecreateIndexError() = TrError;
            RTESys_WriteMemoryBarrier();
            if ( ObjFileInfo.bd900RecreateIndex() ) 
                TrError = e_ok;
        }
    }
}

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

externCpp void 
bd22RemoveOid (tgg00_TransContext &Trans,
               tgg00_ObjFileNo     ObjFileNo,
               tsp00_Int4          KeyLen,
               void               *pKey,
               tgg92_KernelOid     Oid)
{
    ROUTINE_DBG_MEO00 ("bd22RemoveOid");

    tgg00_BasisError    &TrError = Trans.trError_gg00;
    tgg92_KernelOid      OidOfKey;
	
    cbd900_ObjFileInfo    &ObjFileInfo    = bd90ObjFileDir [ObjFileNo];
    const tsp00_Int4       NumObjKeyFiles = ObjFileInfo.GetKeyPartitionCount();
    CHECK_NUM_KEY_FILES (NumObjKeyFiles); //PTS 1112190 18/10/2001
    tsp00_Int4 ObjKeyFileIndex = (NumObjKeyFiles == 1 ? 0:bd22ObjKeyFileIndex (KeyLen, pKey, NumObjKeyFiles)); 
    cbd900_ObjKeyFileId  ObjKeyFileId (ObjFileInfo, ObjFileNo, ObjKeyFileIndex);

    tsp00_Int4 OidOfKeyLen;
    tsp00_Int4 OidPrefixToCompareLen = sizeof(OidOfKey) - sizeof(teo00_Uint2);
    bd03OmsDelInv (Trans, ObjKeyFileId,             /* PTS 1131960 FF */ 
        tsp00_BytePtr (pKey), KeyLen, tsp00_BytePtr(&Oid), sizeof(Oid),
        sizeof(OidOfKey), tsp00_BytePtr(&OidOfKey), OidPrefixToCompareLen, OidOfKeyLen );
    if (TrError == e_primkey_does_not_match)
    {
        TrError = e_ok;

        if (g01vtrace.vtrOmsUpd_gg00)
        {
            tgg12_OmsOidTrace TrLineOId;

            TrLineOId.ooidTrType_gg12.becomes(otOid_egg12);
            TrLineOId.ooidTrType2_gg12.becomes(ot2Input_egg12);
            TrLineOId.ooidObjId_gg12   = Oid;

            Trace_CommonEntry( Trans, tgg00_Debug::fromConst(bd), tgg00_VtraceType::fromConst(b22rem_oid), 
                REINTERPRET_CAST( tsp00_BytePtr, &TrLineOId ), sizeof (TrLineOId) );

            TrLineOId.ooidObjId_gg12   = OidOfKey;
            TrLineOId.ooidTrType2_gg12.becomes(ot2Output_egg12);

            Trace_CommonEntry( Trans, tgg00_Debug::fromConst(bd), tgg00_VtraceType::fromConst(b22rem_oid), 
                REINTERPRET_CAST( tsp00_BytePtr, &TrLineOId ), sizeof (TrLineOId) );

            bd92VtraceObjKey (Trans, ObjFileNo, KeyLen, pKey, b22rem_oid);
        }

        return;
    }

	switch (TrError)
	{
    case e_ok                : break;
	case e_inv_list_not_found:
	case e_key_not_found     : 	
        TrError = e_hash_key_not_found; 
        Oid.gg92SetNil();           
        break;
	case e_inv_not_found     :  
        TrError = e_hash_not_found;     
        Oid.gg92SetNil();          
        break;
	}

        // PTS 1134645
    if ( ObjFileInfo.bd900RecreateIndex() && ( e_ok == TrError ))
    {
        cbd900_ObjKeyFileId& ObjKeyFileId = bd911GetObjKeyFileId(ObjKeyFileIndex);
        bd03OmsDelInv (Trans, ObjKeyFileId,             
            tsp00_BytePtr (pKey), KeyLen, tsp00_BytePtr(&Oid), sizeof(Oid),
            sizeof(OidOfKey), tsp00_BytePtr(&OidOfKey), OidPrefixToCompareLen, OidOfKeyLen );
        switch (TrError)
        {
        case e_ok                :  break;
        case e_inv_list_not_found:
        case e_key_not_found     :  
            TrError = e_ok; 
            break;
        case e_inv_not_found     :  
            TrError = e_ok;     
            break;
        default:
            {
                Kernel_OpError( csp3_bd_msg, csp3_n_obj ) 
                    << "bd22RemoveOid for RecreateIndex - error:" << TrError
                    << " FileNo:" << ObjFileNo
                    << " Oid=" 
                    << Oid.gg92GetPno() << "." 
                    << Oid.gg92GetPos() << " (vers " 
                    << Oid.gg92GetFrameVers() << " )";
                bd911KeyToConsole(pKey, KeyLen);
                RTESys_ReadMemoryBarrier();
                if ( ObjFileInfo.bd900RecreateIndexError() == e_ok )
                    ObjFileInfo.bd900RecreateIndexError() = TrError;
                RTESys_WriteMemoryBarrier();
                TrError = e_ok;
            }
        }
    }
}

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


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