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

  module      : vgg941.cpp

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

  author      : JuergenA
  responsible : UweH

  special area:
  description : GG_allocator_interface

  last changed: 2001-01-05
  release     : 7.4

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

  copyright:    (c) 2000-2004 SAP AG



    ========== licence begin  GPL
    Copyright (c) 2000-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 "hgg941.h" // check of PASCAL header vgg941
#include "hak91.h"
#include "heo51.h"
#include "hgg01_1.h"
#include "gsp03_1.h"
#include "hsp77.h"

#include "SAPDBCommon/SAPDB_Types.hpp"
#include "SAPDBCommon/Tracing/SAPDBTrace_Usage.hpp"
#include "SAPDBCommon/Tracing/SAPDBTrace_Topic.hpp"
#include "SAPDBCommon/MemoryManagement/SAPDBMem_RawAllocator.hpp"
#include "RunTime/MemoryManagement/RTEMem_BlockAllocator.hpp"
#include "RunTime/RTE_Crash.hpp"
#include "RunTime/Configuration/RTEConf_ParameterAccessKernelInterface.hpp"

extern SAPDBTrace_Topic AllocatorTrace;

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

#define SMALL_BLOCK_SIZE        8192         // should be Cserv parameters ...
#define SUPPLEMENT_BLOCK_SIZE  (8192 * 16)

#define MAX_ALLOC_BYTECOUNT 0x80000000

/*==========================================================================*.
* FUNCTIONS                                                                 *
*===========================================================================*/

externPascal tsp00_Addr gg941Allocate(tgg00_TransContext &TransContext, int wantedBytes)
{
    SAPDBTRACE_ROUTINE_DEBUG( "gg941Allocate", AllocatorTrace, 5 );
	return REINTERPRET_CAST(tsp00_Addr,
        (REINTERPRET_CAST(SAPDBMem_RawAllocator*,
        TransContext.trAllocator_gg00)->Allocate(wantedBytes)));
}

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

externPascal tsp00_Addr gg941ReAllocate(tgg00_TransContext &TransContext, int wantedBytes, tsp00_Addr hint)
{
    SAPDBTRACE_ROUTINE_DEBUG( "gg941ReAllocate", AllocatorTrace, 5 );
	return REINTERPRET_CAST(tsp00_Addr,
        (REINTERPRET_CAST(SAPDBMem_RawAllocator*,
        TransContext.trAllocator_gg00)->Reallocate(wantedBytes, hint)));
}

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

externPascal pasbool gg941CheckConsistency(tgg00_TransContext &TransContext)
{
    return REINTERPRET_CAST(SAPDBMem_RawAllocator*, TransContext.trAllocator_gg00)->CheckConsistency();
}

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

// PASCAL interface
externPascal void gg941CreateAllocatorAndCallMainprog (tgg00_TransContext &TransContext)
{
    tsp2_process_type           TaskType;
    
    vptype (TransContext.trTaskId_gg00, TaskType);
    
    SAPDB_UInt InitialBlockSize;
    
    if ((sp2pt_utility == TaskType) ||
        (sp2pt_user    == TaskType) ||
        (sp2pt_server  == TaskType))
    {
        RTEConf_Parameter::Integer  paramValue;
        SAPDBErr_MessageList        errMsg;

        if( ! RTEConf_ParameterAccess::Instance()->GetInteger(
                     UTF8( "INIT_ALLOCATORSIZE" ), paramValue, errMsg ))
             RTE_Crash( errMsg );

        InitialBlockSize = (SAPDB_UInt)paramValue;
    }
    else
    {
        InitialBlockSize = SMALL_BLOCK_SIZE;
    }
    
    SAPDB_UTF8 identifier[40];
    sp77sprintf((char *)identifier, sizeof(identifier), "TransContext T%03d", TransContext.trTaskId_gg00);

    // Allocate the memory for the allocator dynamically. This is done because all allocators are
    // registered by RTEMem_AllocatorRegister using a linked list. When the database kernel is
    // stopped, some tasks are killed very hard, removing their task stack. When another returns
    // from a91mainprogam_with_allocator(), the destructor for the allocator is called, which 
    // tries to deregister itself from RTEMem_AllocatorRegister. This means accessing the allocators
    // of tasks that have been killed hard. If the allocators would be on the task stack, this would
    // crash... http://pts:1080/webpts?wptsdetail=yes&ErrorType=0&ErrorID=1126572
    SAPDBMem_RawAllocator *pAllocator = new(RTEMem_RteAllocator::Instance()) SAPDBMem_RawAllocator(
       identifier,
       RTEMem_BlockAllocator::Instance(), 
       InitialBlockSize,
       SUPPLEMENT_BLOCK_SIZE,
       SAPDBMem_RawAllocator::FREE_RAW_EXTENDS_EXCEPT_INITIAL ); // PTS 1124756 TS 2003-10-24
 
    //  MaxSize omitted --> unlimited size
            
    TransContext.trAllocator_gg00 = pAllocator;

    pAllocator->SetAllocThreshold(MAX_ALLOC_BYTECOUNT);
    
    a91mainprogam_with_allocator (TransContext);
    // proper end of task - call the destructor explicitly as it has been constructed via placement new
    pAllocator->~SAPDBMem_RawAllocator();
    RTEMem_RteAllocator::Instance().Deallocate(pAllocator);
}

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

externPascal void gg941Deallocate (
    tgg00_TransContext    VAR_VALUE_REF  TransContext,
    tsp00_Addr            VAR_VALUE_REF  p)
{
    SAPDBTRACE_ROUTINE_DEBUG( "gg941Deallocate", AllocatorTrace, 5 );
	REINTERPRET_CAST(SAPDBMem_RawAllocator*, TransContext.trAllocator_gg00)->Deallocate(p);
	p = (tsp00_Addr) 0;
}

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

// end of program
