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

  module      : vbd930.cpp

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

  responsible : FerdiF

  special area: GarbageCollection
  description : description ...

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

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

  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 "ggg00.h"
#include "gbd05.h"
#include "gbd900.h"
#include "gbd910.h"
#include "gbd920.h"
#include "gbd930.h"
#include "ggg91.h"

#include "Logging/Log_History.hpp"
#include "Converter/Converter_ICommon.hpp"
#include "Converter/Converter_Types.hpp"
#include "hbd06.h"
#include "hbd17.h"
#include "hbd21.h"
#include "hbd22.h"  //OMS Key Management
#include "heo00x.h"
#include "heo55k.h" //vbegexcl
#include "heo56.h"  //vsuspend
#include "SAPDB/SAPDBCommon/SAPDB_RangeCode.hpp" // Kernel_move_and_fill
#include "hgg10.h"
#include "hkb51.h"
#include "RunTime/System/RTESys_Time.h"
#include "KernelCommon/Kernel_OpMsg.hpp"           
#include "KernelCommon/Kernel_IAdminInfo.hpp" 

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

#define DC_OCCUPANCY_LIMIT_BD930    80
/* maximum occupancy of the datacache in percent */
/* before the garbage collection is started      */

#define CRITICAL_DC_OCCUPANCY_LIMIT_BD930  95
/* maximum occupancy of the datacache in percent before the garbage collectors      */
/* use an accurate but expensive check to decide wheteher an object can be released */

#define HUNDERT_PERCENT_BD930            100

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

static const SAPDB_Char hexDigitsC [] = "0123456789abcdef";

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

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

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

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

/*---------------------------------------------------------------------------*/
/* METHOD IMPLEMENTATION FOR cbd930_HistoryFileInfo                          */
/*---------------------------------------------------------------------------*/

inline bool
cbd930_HistoryFileInfo::bd930ClearHistoryFile (tgg00_TransContext        &Trans,
        GC_IGarbageCollector      &IGarbColl) // PTS 1113185 UH 2001-12-18
{
    bool                       bAnyObjectDeleted;
    Log_History::RemoveOptions option             = Log_History::Normal;

    IGarbColl.SetHistOption( option );

    Log_History::GetInstance().RemoveHistory ( Trans, hfiHistoryFileNo_bd930, option,
            IGarbColl,                             // PTS 1113185 UH 2001-12-18
            bAnyObjectDeleted );

    return bAnyObjectDeleted;
}

/*---------------------------------------------------------------------------*/
/* METHOD IMPLEMENTATION FOR cbd930_HistoryFileIter                          */
/*---------------------------------------------------------------------------*/

inline cbd930_HistoryFileInfo*
cbd930_HistoryFileIter::bd930SetToHistFileWithOldestTrans(tgg00_TransContext &Trans)
{
    int           Index;
    tgg91_TransNo OldestTransId;
    tgg91_TransNo FirstTransId;

    hitCurrHFInfoPtr_bd930 = NULL;
    hitCurrHFIndex_bd930   = NIL_HISTORY_FILE_INDEX_BD930;

    Log_History& history = Log_History::GetInstance();

    /* find first history file with a nonzero oldest transid */
    for (Index=0; Index < hitHFDir_bd930.hfdNumHFInfos_bd930; ++Index)
    {
        OldestTransId = history.GetOldestTransNo(Index);

        if (!OldestTransId.gg90IsNil())
        {
            hitCurrHFIndex_bd930 = Index;
            break;
        }
    }

    /* check if there is any history file with an older first transid */
    if (NIL_HISTORY_FILE_INDEX_BD930 != hitCurrHFIndex_bd930)
    {
        for (Index=hitCurrHFIndex_bd930; Index < hitHFDir_bd930.hfdNumHFInfos_bd930; ++Index)
        {
            FirstTransId = history.GetOldestTransNo(Index);

            if (!FirstTransId.gg90IsNil() && OldestTransId > FirstTransId)
            {
                hitCurrHFIndex_bd930 = Index;
                OldestTransId        = FirstTransId;
            }
        }

        hitCurrHFInfoPtr_bd930 = hitHFDir_bd930.hfdFirstHFInfoPtr_bd930 + hitCurrHFIndex_bd930;
    }

    return hitCurrHFInfoPtr_bd930;
}

/*---------------------------------------------------------------------------*/
/* METHOD IMPLEMENTATION FOR GC_IGabageCollector Interface                   */
/*---------------------------------------------------------------------------*/

SAPDB_UInt1
cbd930_GarbageCollector::GetHistOption() const
{
    return gcoController_bd930.gccGCState_bd930[gcoIndex_bd930].gcsHistoryOption_bd930;
};

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

void
cbd930_GarbageCollector::IncHistCreateObjFileCount()
{
    ++gcoController_bd930.gccGCCounters_bd930[gcoIndex_bd930].gccntHistCreateObjFile;
    IncHistEntryReleaseCount();
};

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

void
cbd930_GarbageCollector::IncHistDeleteObjCount()
{
    ++gcoController_bd930.gccGCCounters_bd930[gcoIndex_bd930].gccntHistDeleteObj;
    IncHistEntryReleaseCount();
};

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

void
cbd930_GarbageCollector::IncHistDropObjFileCount()
{
    ++gcoController_bd930.gccGCCounters_bd930[gcoIndex_bd930].gccntHistDropObjFile;
    IncHistEntryReleaseCount();
};

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

void
cbd930_GarbageCollector::IncHistEntryReleaseCount()
{
    ++gcoController_bd930.gccGCCounters_bd930[gcoIndex_bd930].gccntHistEntriesReleased;
};

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

void
cbd930_GarbageCollector::IncHistLockObjCount()
{
    ++gcoController_bd930.gccGCCounters_bd930[gcoIndex_bd930].gccntHistLockObj;
    IncHistEntryReleaseCount();
};

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

void
cbd930_GarbageCollector::IncHistInsertObjCount()
{
    ++gcoController_bd930.gccGCCounters_bd930[gcoIndex_bd930].gccntHistInsertObj;
    IncHistEntryReleaseCount();
};

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

void
cbd930_GarbageCollector::IncHistNewObjCount()
{
    ++gcoController_bd930.gccGCCounters_bd930[gcoIndex_bd930].gccntHistNewObj;
    IncHistEntryReleaseCount();
};

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

void
cbd930_GarbageCollector::IncHistUpdateObjCount()
{
    ++gcoController_bd930.gccGCCounters_bd930[gcoIndex_bd930].gccntHistUpdateObj;
    IncHistEntryReleaseCount();
};

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

void
cbd930_GarbageCollector::IncObjReleaseCount()
{
    ++gcoController_bd930.gccGCCounters_bd930[gcoIndex_bd930].gccntObjectsDeleted;
};

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

void
cbd930_GarbageCollector::IncReleaseEmptyPageCount()
{
    ++gcoController_bd930.gccGCCounters_bd930[gcoIndex_bd930].gccntEmtyPagesReleased;
};

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

bool
cbd930_GarbageCollector::IsInterrrupted () const
{
	// PTS 1114490 FF 2002-03-12
	if (gcoController_bd930.gccCheckSavepointNeeded_bd930 &&
		Converter_ICommon::Instance().SavepointNeeded())
    {
		gcoController_bd930.gccStopGC_bd930 = true; /* this will stop all GCs */
        return true;
    }
	return( gcoController_bd930.gccSpecialOperationIsActive_bd930 );
};

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

void
cbd930_GarbageCollector::SetHistOption(SAPDB_UInt1 option)
{
    gcoController_bd930.gccGCState_bd930[gcoIndex_bd930].gcsHistoryOption_bd930 = option;
};



/*---------------------------------------------------------------------------*/
/* METHOD IMPLEMENTATION FOR cbd930_GarbageCollector                         */
/*---------------------------------------------------------------------------*/
inline bool
cbd930_GarbageCollector::bd930_TryToReleaseUnusedObjDataPages()
{
    if (( gcoController_bd930.gccNumGCUsedToReleasePages_bd930
            <gcoController_bd930.gccNumGCReqToReleasePages_bd930) &&
            !gcoController_bd930.gccStopGC_bd930)
    {
        gcoController_bd930.gccNumGCUsedToReleasePages_bd930 ++;
        bool somethingdone = bd930_ReleaseUnusedPagesOfAllFiles();
        gcoController_bd930.gccNumGCUsedToReleasePages_bd930 --;
        if (e_ok != gcoTrans_bd930.trError_gg00)    //PTS 1107306 AK 01/08/2000
        {
            g01abort (csp3_bd_msg, csp3_n_obj,
                      "BD930TryToRelease: Error", gcoTrans_bd930.trError_gg00);
        }
        return somethingdone;
    }
    return false;
}

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

cbd930_GarbageCollector::cbd930_GarbageCollector (tgg00_TransContext        &Trans,
        cbd930_GarbCollController &GarbCollController)
        : gcoTrans_bd930          (Trans),
        gcoIndex_bd930            (GarbCollController.bd930_AddGC (Trans)),
        gcoController_bd930       (GarbCollController)
{

    ROUTINE_DBG_MEO00  ("cbd930_GarbageCollector");

    cbd930_HistoryFileIter					HistFileIter  (GarbCollController.gccHistoryFileDir_bd930);
    bool									bSomethingDone;
    tsp00_TaskId							ResumeTaskId = cgg_nil_pid;  // PTS 1111366 TS 2001-08-10

    while (true)
    {
        /*=====================================================*/
        vsuspend (Trans.trTaskId_gg00, TSK_VSUSPEND_REASON_NO_WORK);
        /*=====================================================*/

        bd930_WriteMessageIntoVtrace(GC_IS_STARTED);

        vbegexcl (Trans.trTaskId_gg00, g08garbage);

        /* check, if garbagecollector is allowed to run */
        if ( !gcoController_bd930.gccSpecialOperationIsActive_bd930 &&
            !gcoController_bd930.gccStopGC_bd930)
        {
            ++gcoController_bd930.gccGCCounters_bd930[gcoIndex_bd930].gccntActivateCount;
            
            /*first try to remove empty pages or dropped files */
            bd930_TryToReleaseUnusedObjDataPages();
            
            /* loop until db filling is below the ctritical limit */
//            do
//            {                         
                do
                {
                    bSomethingDone = false;
                    /* go trough all history files and try to truncate them */
                    for (HistFileIter.bd930First(); NULL != HistFileIter(); ++HistFileIter)
                    {
                        bool  histRemoved = false;
                        
                        /* remove unused object */
                        if (HistFileIter()->hfiCurrActivGC_bd930 == NIL_GC_INDEX_BD900)
                        {
                            if (gcoController_bd930.gccStopGC_bd930) break;
                            HistFileIter()->hfiCurrActivGC_bd930 = gcoIndex_bd930;
                            vendexcl (Trans.trTaskId_gg00, g08garbage);
                            if ( HistFileIter()->bd930ClearHistoryFile (Trans,
                                static_cast<GC_IGarbageCollector&>(*this)) ) // PTS 1113185 UH 2001-12-18
                            {
                                histRemoved    = true;
                                bSomethingDone = true;
                            }
                            vbegexcl (Trans.trTaskId_gg00, g08garbage);
                            bd930_HistoryErrorHandler();
                            HistFileIter()->hfiCurrActivGC_bd930 = NIL_GC_INDEX_BD900;
                        }
                    }
                    /* PTS 1124543 FF 2003-OCT-24 */
                    if (!bSomethingDone && !gcoController_bd930.gccStopGC_bd930)
                        bSomethingDone = bd930_TryToReleaseUnusedObjDataPages();
                }
				while (bSomethingDone && !gcoController_bd930.gccStopGC_bd930);
        /* **************************************************************
				retCode = Converter_GCNotNeeded;
				if ( (1 == gcoController_bd930.gccNumGCUsed_bd930) &&
					!Kernel_IAdminInfo::Instance().KernelStateIsRestart()&&
					!gcoController_bd930.gccStopGC_bd930)
				{
					retCode = Converter_ICommon::Instance().GarbageCollectionNeeded();
					if (Converter_GCNeeded == retCode)
					{
						tgg91_TransNo  ConsistViewNo;
						tsp00_Int4     StartDate;
						tsp00_Int4     StartTime;
						kb51CancelConsistTrans (Trans.trTaskId_gg00, ConsistViewNo, 
                            StartDate, StartTime);
						if (!ConsistViewNo.gg90IsNil())
                        {
                            int i;
                            Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
                            opWarnMsg << "ConsistView:";
							for (i=0; i < sizeof(ConsistViewNo); i++)
								opWarnMsg << ToStr((SAPDB_UInt1)ConsistViewNo[i], _T_h);
							opWarnMsg << " cancelled - creation date:" << StartDate
								<< " time:" << StartTime;

							Kernel_VTrace     vTrace;
							vTrace << "ConsistView:";
							for (i=0; i < sizeof(ConsistViewNo); i++)
								vTrace << ToStr((SAPDB_UInt1)ConsistViewNo[i], _T_h);
							vTrace << " cancelled - creation date:" << StartDate
								<< " time:" << StartTime;

							const bool cNoWaitOnTimeout = false;
							vendexcl (Trans.trTaskId_gg00, g08garbage); 
							gcoController_bd930.bd930StartAllGCs(Trans.trTaskId_gg00, cNoWaitOnTimeout);
							vbegexcl (Trans.trTaskId_gg00, g08garbage); 
						}
						else 
							retCode = Converter_GCNotNeeded;
					}
				}
			}
			while ((Converter_GCNeeded == retCode) &&
				!gcoController_bd930.gccStopGC_bd930);
                **************************************************************************** */
		}

        /* update state flag and counter of used GCs */
        gcoController_bd930.gccGCState_bd930[gcoIndex_bd930].gcsActive_bd930 = false;
        gcoController_bd930.gccNumGCUsed_bd930--;

        /* check GC,i.e. check that if the GC stops there is really nothing more to do */
#     if COMPILEMODE_MEO00 >= QUICK_MEO00 
        gcoController_bd930.bd930_CheckGC();
#     endif

        /* resume StopAllGCManager if all GC shall be */
        /* suspended and this is the last GC to stop  */
        // PTS 1111366 TS 2001-08-13
        if (gcoController_bd930.gccStopGC_bd930 && (0 == gcoController_bd930.gccNumGCUsed_bd930))
        {
            gcoController_bd930.gccGCStartRequested_bd930 = true;  // PTS 1116157 FF 2002-06-07         
            gcoController_bd930.gccStopGC_bd930 = false;
            ResumeTaskId = gcoController_bd930.gccStopGCManagerTID_bd930;
            gcoController_bd930.gccStopGCManagerTID_bd930 = cgg_nil_pid;
        }

        vendexcl (Trans.trTaskId_gg00, g08garbage);

        if (cgg_nil_pid != ResumeTaskId)
        {
            /*=======================================================================*/
            vresume (ResumeTaskId);
            /*=======================================================================*/

            ResumeTaskId = cgg_nil_pid;
        };
        bd930_WriteMessageIntoVtrace(GC_IS_STOPPED); // PTS 1111366
    };
}

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

bool
cbd930_GarbageCollector::bd930_ReleaseUnusedPagesOfAllFiles()
{
    ROUTINE_DBG_MEO00  ("bd930_ReleaseUnusedPagesOfAllFiles");

    /* check if one is exclusively in the g08garbage region */
#   if COMPILEMODE_MEO00 >= SLOW_MEO00 
    g08excl_check (gcoTrans_bd930.trTaskId_gg00, g08garbage);
#   endif

    cbd900_ObjFileDirIter  ObjFileIter (*(gcoController_bd930.gccObjFileDirPtr_bd930));
    bool                   bSomethingDoneDuringLastLoop;
    int                    FileNo;
    int                    iContFileNo;
    tgg00_FileId           ObjFileId;
    bool                   bPrimFileIsEmpty;
    bool                   bContFileIsEmpty;
    bool                   bAllContFilesAreEmptyAndDeleted;

    //#   if COMPILEMODE_MEO00 >= QUICK_MEO00      PTS 1113306  FF 10-JAN-2002
    bool                   bSomethingDoneAtAll   = false;
    bool                   bFileForDeletionExist = false;   // PTS 1136796
    //#   endif

    do
    {
        bSomethingDoneDuringLastLoop = false;
        ObjFileIter.bd920Begin();

        /* go trough all object containers stored in the object file directory */
        while  ((!ObjFileIter.bd920End())                        &&
                (NULL != ObjFileIter())                          &&
                !gcoController_bd930.gccStopGC_bd930             &&
                (  gcoController_bd930.gccNumGCUsedToReleasePages_bd930
                   <=gcoController_bd930.gccNumGCReqToReleasePages_bd930))
        {
            /* store file no of current file and build fileId */
            FileNo = ObjFileIter.bd920Key();
            ObjFileIter()->bd900BuildFileId (FileNo, ObjFileId);

            // PTS 1136793 
			if ( ObjFileIter()->ofiRelFileIsReq_bd900 )  
				bFileForDeletionExist = true; 

            bd930_ReleaseUnusedPagesOfOneFile (ObjFileId, *ObjFileIter(), bSomethingDoneDuringLastLoop, bPrimFileIsEmpty);
            if (gcoController_bd930.gccStopGC_bd930 || (e_ok != gcoTrans_bd930.trError_gg00))
                return bSomethingDoneAtAll;   

            /* go trough all cont object files an remove empty pages */
            if (ObjFileIter() && (cbd900_ObjFileInfo::omsVariableFile == ObjFileIter()->GetFileType()) 
                && ObjFileIter()->ofiRelFileIsReq_bd900)
            {
				bFileForDeletionExist = true;   // PTS 1136793 

                tgg00_FileId             ContObjFileId;
                cbd900_ContObjFileInfo & ContObjFileInfo = gcoController_bd930.gccContObjFileDirPtr_bd930->operator[](FileNo);
                bAllContFilesAreEmptyAndDeleted = true;

                /* go through all continuation object files of this file */
                for (iContFileNo=1; (iContFileNo <=ContObjFileInfo.cfiNumContFiles_bd900); ++iContFileNo)
                {
                    if (gcoController_bd930.gccStopGC_bd930)
                    {
                        bAllContFilesAreEmptyAndDeleted = false;                  //PTS 1107306 AK 01/08/2000
                        break;
                    }

                    ContObjFileInfo.bd900BuildFileId (FileNo, iContFileNo, ContObjFileId);
					ContObjFileInfo[iContFileNo].ofiRelFileIsReq_bd900 = true;
                    bd930_ReleaseUnusedPagesOfOneFile (ContObjFileId, ContObjFileInfo[iContFileNo],
                                                       bSomethingDoneDuringLastLoop, bContFileIsEmpty);
                    if (gcoController_bd930.gccStopGC_bd930 || (e_ok != gcoTrans_bd930.trError_gg00))
                        return bSomethingDoneAtAll;

                    bAllContFilesAreEmptyAndDeleted &= (bContFileIsEmpty && 
                        (ContObjFileInfo[iContFileNo].ofiRelFileIsReq_bd900 ||
                         ContObjFileInfo[iContFileNo].GetRootPage() == NIL_PAGE_NO_GG00)); // PTS 1126719 FF 2003-dec-22
                }

            }

            /* go to next entry in ObjFileEntry */
            ++ObjFileIter;

            /* remove the last entry if it is empty */
            if (bPrimFileIsEmpty                                                 &&
                (!gcoController_bd930.gccStopGC_bd930)                           &&
                ((oftVarLenObjFile_egg00 != ObjFileId.fileObjFileType_gg00()) ||
                  bAllContFilesAreEmptyAndDeleted))
            {
                /* all entries in the object file directories and the root page are removed */
                bd930_RemoveFile (ObjFileId, bSomethingDoneDuringLastLoop);

                if (Kernel_IAdminInfo::Instance().KernelStateIsRestart() &&
                    !gcoController_bd930.gccObjFileDirPtr_bd930->bd920IsUsed(FileNo))
                {
                    gcoController_bd930.WakeUpTasksWaitingForDelObjFile (gcoTrans_bd930.trTaskId_gg00, FileNo);
                }
            }
        }

        bSomethingDoneAtAll |= bSomethingDoneDuringLastLoop;
    }
    while (bSomethingDoneDuringLastLoop);

    /* check if anything was done in this function */
    if (! bSomethingDoneAtAll && !gcoController_bd930.gccStopGC_bd930 )
    {
        /* +++ PTS 1113306 correct counter to avoid hot loops FF 10-JAN-2002 */
        if ( gcoController_bd930.gccNumGCUsedToReleasePages_bd930
            <=gcoController_bd930.gccNumGCReqToReleasePages_bd930)
        {
            // PTS 1136793 
            if (!bFileForDeletionExist && (0 < gcoController_bd930.gccNumGCReqToReleasePages_bd930))
                --gcoController_bd930.gccNumGCReqToReleasePages_bd930;
            //g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_obj, "BD930RelPage: no wrk fnd", gcoIndex_bd930);
        }
        /* --- PTS 1113306 correct counter to avoid hot loops FF 10-JAN-2002 */
#       if COMPILEMODE_MEO00 >= QUICK_MEO00 
        g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, "BD930RelPage: No Task   ", gcoIndex_bd930);
        /* check if the garbage controller is destroyed */
        gcoController_bd930.bd930_CheckGC();
//        g01abort (csp3_bd_msg, csp3_n_obj, "BD930RelPage: No Task   ", gcoIndex_bd930);
#       endif
    }
    return bSomethingDoneAtAll;
}

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

void
cbd930_GarbageCollector::bd930_ReleaseUnusedPagesOfOneFile   (tgg00_FileId       &ObjFileId,
        cbd900_ObjFileInfo &ObjFileInfo,
        bool               &bSomethingDone,
        bool               &bFileIsEmpty)
{
    ROUTINE_DBG_MEO00  ("bd930_ReleaseUnusedPagesOfOneFile");

    /* go trough all chains of the current container            */
    /* and remove either unused pages are the complete          */
    /* chain if this chain was dropped (i.e. file was dropped)  */

    /* check if one is exclusively in the g08garbage region     */
#   if COMPILEMODE_MEO00 >= SLOW_MEO00 
    g08excl_check (gcoTrans_bd930.trTaskId_gg00, g08garbage);
#   endif

    /* check if the file is already removed */
    if (ObjFileInfo.GetRootPage() == NIL_PAGE_NO_GG00)
        bFileIsEmpty = true;
    else
    {
        bFileIsEmpty = false; 

        tgg00_BasisError      &TrError      = gcoTrans_bd930.trError_gg00;
        tsp00_TaskId          &GCTaskId     = gcoTrans_bd930.trTaskId_gg00;
        const int              MaxNumChains = ObjFileInfo.GetChainCount();
        int                    iChain;

        for (iChain=0; (iChain<MaxNumChains) && (!gcoController_bd930.gccStopGC_bd930); ++iChain)
        {
            /*  check if the complete chain has to be released  */
            if ((ObjFileInfo.ofiRelFileIsReq_bd900)                              &&
                    (ObjFileInfo[iChain].ociCurrActivGC_bd900 == NIL_GC_INDEX_BD900) &&
                    (ObjFileInfo[iChain].ociSubRoot_bd900     != NIL_PAGE_NO_GG00  ) &&
                    (!gcoController_bd930.gccStopGC_bd930))
            {
                ObjFileInfo[iChain].ociCurrActivGC_bd900 = gcoIndex_bd930;
                vendexcl (GCTaskId, g08garbage);
                bd930_ReleaseAllPagesOfOneChain (ObjFileId, ObjFileInfo, iChain);
                bd930_PageErrorHandler (ObjFileInfo);
                vbegexcl (GCTaskId, g08garbage);
                if ((e_ok == TrError) && (!gcoController_bd930.gccStopGC_bd930))
                {
                    /* update GC info structures */
                    cbd900_ObjChainInfo    &ChainInfo  = ObjFileInfo[iChain];
                    ChainInfo.ociSubRoot_bd900 = NIL_PAGE_NO_GG00;
                }
                ObjFileInfo[iChain].ociCurrActivGC_bd900 = NIL_GC_INDEX_BD900;
                bSomethingDone = true;
            }
        }

        /* remove the root of a file if the file is empty */
        if ((ObjFileInfo.ofiRelFileIsReq_bd900) && (!gcoController_bd930.gccStopGC_bd930))
        {
            /* check if the object file directories are still correct */
#           if COMPILEMODE_MEO00 >= QUICK_MEO00
            {
                const tgg00_ObjFileNo  FileNo       = ObjFileId.fileObjFileNo_gg00();
                const tsp00_Int4       ContFileNo   = ObjFileId.fileContObjFileNo_gg00();

                if (ContFileNo == PRIM_CONT_OBJ_FILE_NO_BD900)
                {
                    cbd900_ObjFileInfo &CheckObjFileInfo =
                        gcoController_bd930.gccObjFileDirPtr_bd930->operator[](FileNo);
                    if (CheckObjFileInfo.GetRootPage() != ObjFileId.fileRoot_gg00())
                        g01abort (csp3_bd_msg, csp3_n_obj,
                                  "BD930RemOP3:Item Changed", ObjFileInfo.GetRootPage());
                }
                else
                {
                    cbd900_ObjFileInfo  &CheckContObjFileInfo =
                        gcoController_bd930.gccContObjFileDirPtr_bd930->operator[](FileNo).operator[](ContFileNo);
                    if (CheckContObjFileInfo.GetRootPage() != ObjFileId.fileRoot_gg00())
                        g01abort (csp3_bd_msg, csp3_n_obj,
                                  "BD930RemOP4:Item Changed", CheckContObjFileInfo.GetRootPage());
                }
            }
#           endif

            /* check if all chains and subroots are removed */
            bool bAllChainsAreRemovedAndNoOtherGcIsActiv = true;
            for (iChain=0; iChain<MaxNumChains; ++iChain)
            {
                if ((ObjFileInfo[iChain].ociSubRoot_bd900     != NIL_PAGE_NO_GG00) ||
                        (ObjFileInfo[iChain].ociCurrActivGC_bd900 != NIL_GC_INDEX_BD900))
                {
                    bAllChainsAreRemovedAndNoOtherGcIsActiv = false;
                    break;
                }
            }

            /* release root and key container after all subroots are removed and */
            /* if no other GC is activ, the last condition is to avoid that the  */
            /* object file info of an activ GC gets outdated                     */
            /* PTS 1107306 AK 01/08/2000                                         */
            if  (bAllChainsAreRemovedAndNoOtherGcIsActiv)
            {
                bFileIsEmpty = true;

#if defined(PTS1113440)  // PTS 1113440 FF 16-Jan-2001
                if (PRIM_CONT_OBJ_FILE_NO_BD900 != ObjFileId.fileContObjFileNo_gg00())
                {
                    /* get root page */
                    cbd05_Current Current (gcoTrans_bd930, m_update, ObjFileId);
                    cbd910_RootNode  NptrsRoot (Current, ObjFileId.fileRoot_gg00(), nr_for_update);

                    /* remove file entry from the persistent file directory */
                    if (e_ok == TrError)
                        bd930_RemoveEntryFromPersFileDirectory (ObjFileId);

                    /* release root page */
                    if (e_ok == TrError)
                        NptrsRoot.bd910FreePage();

                    if (e_ok != TrError)
                    {
                        g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                                  "BD930RUPFile: No Root  ", ObjFileId.fileRoot_gg00());
                        g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                                  "BD930RUPFile: Error    ", TrError);
                        return;
                    }

                    /* reset entry in the object file directoty */
                    ObjFileInfo.GetRootPage() = NIL_PAGE_NO_GG00;
                }
#endif  // PTS 1113440 FF 16-Jan-2001
            }
            // END PTS 1107306 AK 01/08/2000
        }
    }
}

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

void
cbd930_GarbageCollector::bd930_ReleaseAllPagesOfOneChain (tgg00_FileId        &ObjFileId,
        cbd900_ObjFileInfo  &ObjFileInfo,
        tsp00_Int4           ChainNo)
{
    ROUTINE_DBG_MEO00 ("bd930_ReleaseAllPagesOfOneChain");

    /*----------------------------------------------------------------------------*/
    /* This function removes all pages of an chain following the right pointer    */
    /* The subroot page is removed as last page                                   */
    /* note that the next free chain is not updated when the the chain is deleted */
    /*----------------------------------------------------------------------------*/

    tgg00_BasisError       &TrError    = gcoTrans_bd930.trError_gg00;
    cbd900_ObjChainInfo    &ChainInfo  = ObjFileInfo[ChainNo];
    cbd05_Current Current (gcoTrans_bd930, m_update, ObjFileId);
    Current.curr_tree_id.fileBdUse_gg00().addElement(bd_release_acc);

    /* write vtrace */
    if (g01vtrace.vtrOmsFree_gg00 )
    {
        tgg12_OmsFilenameTrace TrLineIn;

        TrLineIn.ofnTrType_gg12.becomes(otFilename_egg12);
        TrLineIn.ofnTrType2_gg12.becomes(ot2Nil_egg12);
        TrLineIn.ofnFileName_gg12 = ObjFileId.fileName_gg00();

        Trace_CommonEntry( gcoTrans_bd930, tgg00_Debug::fromConst(bd), tgg00_VtraceType::fromConst(b930DropFile),
                           REINTERPRET_CAST( tsp00_BytePtr, &TrLineIn ), sizeof (TrLineIn) );
    }

#   if COMPILEMODE_MEO00 >= SLOW_MEO00
    t01treeid (bi, "ObjFileId   ", ObjFileId);
#   endif

    cbd910_ObjDataNode NptrsPage    (Current, nr_for_update);
    cbd910_SubRootNode NptrsSubRoot (Current, ChainInfo.ociSubRoot_bd900, nr_for_update);
    if (e_ok == TrError)
    {
        cbd900_SubRootPageInfo SubRootPageInfo (NptrsSubRoot);
        tsp00_PageNo RightPageNo = NptrsSubRoot.np_ptr()->nd_right();

        while (RightPageNo != NIL_PAGE_NO_GG00)
        {
            NptrsPage.bd910AssignToPage(RightPageNo);
            if (TrError != e_ok)
                break;

            /* update all page counters on sub root page and in filedirectory these */
            /* counters are used by check routines in the quick kernel only         */
            // PTS 1114176 FF#           if COMPILEMODE_MEO00 >= QUICK_MEO00
            --SubRootPageInfo.bd900AllPageCnt();
            ChainInfo.ociAllPageCnt_bd900  = SubRootPageInfo.bd900AllPageCnt();
            ChainInfo.SetAllObjCnt(ChainInfo.GetAllObjCnt() -
                (NptrsPage.np_ptr()->nd_max_obj_cnt() - NptrsPage.np_ptr()->nd_free_obj_cnt()));
            if (0 < NptrsPage.np_ptr()->nd_free_obj_cnt())
            {
                --SubRootPageInfo.bd900FreePageCnt();
            }
            ChainInfo.ociFreePageCnt_bd900 = SubRootPageInfo.bd900FreePageCnt();  /* PTS 1130998 */
            // PTS 1114176 FF#           endif

            RightPageNo = NptrsPage.np_ptr()->nd_right();
            NptrsPage.bd910FreePage();
            if (TrError != e_ok)
                break;

            ++gcoController_bd930.gccGCCounters_bd930[gcoIndex_bd930].gccntDropPagesReleased;

            /* update the right pointers on subroot page, all other  */
            /* chains as the feot and the free chain are not updated */
            NptrsSubRoot.np_ptr()->nd_right() = RightPageNo;

            if (gcoController_bd930.gccStopGC_bd930)
                break;
        }

        if ((e_ok == TrError) && !gcoController_bd930.gccStopGC_bd930)
        {
            /* check counter of all pages, only the subroot should still exist */
#           if COMPILEMODE_MEO00 >= QUICK_MEO00 
            if ((1 != ChainInfo.ociAllPageCnt_bd900) && ! gcoController_bd930.gccStopGC_bd930)
                g01abort (csp3_bd_msg, csp3_n_obj, "BD930RelAllPage:#Page!=1", ChainInfo.ociAllPageCnt_bd900);
#           endif

            /* free subroot page if it does not belong to the first chain since this    */
            /* page is the root of the file too and has to be deleted as very last page */
            if (0 != ChainNo)
                NptrsSubRoot.bd910FreePage();
        }
    }

    /* write vtrace entry */
    if  (g01vtrace.vtrOmsFree_gg00 || (e_ok != TrError))
    {
        tgg12_OmsErrorTrace TrLineOut;

        TrLineOut.oerrTrType_gg12.becomes  (otError_egg12);
        TrLineOut.oerrTrType2_gg12.becomes (ot2Nil_egg12);
        TrLineOut.oerrRoot_gg12            = ObjFileId.fileRoot_gg00();
        TrLineOut.oerrObjFileNo_gg12       = ObjFileId.fileObjFileNo_gg00();
        TrLineOut.oerrError_gg12           = TrError;

        Trace_CommonEntry( gcoTrans_bd930, tgg00_Debug::fromConst(bd), tgg00_VtraceType::fromConst(b930DropFile),
                           REINTERPRET_CAST( tsp00_BytePtr, &TrLineOut ), sizeof (TrLineOut) );
    }
}

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

void
cbd930_GarbageCollector::bd930_RemoveEntryFromPersFileDirectory (tgg00_FileId  &ObjFileId)
{
    /* remove a file entry from the persistent file directory */
    tbd_fileinfo FileInfo;
    b17del_fdir (ObjFileId.fileName_gg00(), FileInfo, ObjFileId.fileType_gg00().includes(ftsShared_egg00), gcoTrans_bd930);
    if (e_ok != gcoTrans_bd930.trError_gg00)
    {
        b06write_filename_and_root (ObjFileId);
        g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                  "BD930RemPFDE: Error     ",  gcoTrans_bd930.trError_gg00);
        gcoTrans_bd930.trError_gg00 = e_ok; /* ignore error * PTS 1126719 FF 2003-dec-22 */
    }
}

/*---------------------------------------------------------------------------*/
//PTS 1107306 AK 01/08/2000

void
cbd930_GarbageCollector::bd930_RemoveFile (tgg00_FileId &ObjFileId,
                                           bool         &bSomethingDone)
{
  
  /* check that this function runs within the g08garbage region */
# if COMPILEMODE_MEO00 >= SLOW_MEO00 
  g08excl_check (gcoTrans_bd930.trTaskId_gg00, g08garbage);
# endif
      

  tgg00_BasisError  &TrError  = gcoTrans_bd930.trError_gg00;
  cbd900_ObjFileInfo &ObjFileInfo = gcoController_bd930.gccObjFileDirPtr_bd930->operator[](ObjFileId.fileObjFileNo_gg00());
  if ( NIL_PAGE_NO_GG00 != ObjFileInfo.GetRootPage() )
  {
      if (g01vtrace.vtrOmsFree_gg00 )
      {
          Kernel_VTrace() << "RemoveObjFile class_id:" 
              << ObjFileId.fileObjFileNo_gg00(); 
      }
      
      /* in case omsDropContainer is done by a GC which already did a
      ** release of all unused pages before, the counter may have been
      ** decremented twice (PTS 1113306)                                           
      */
      if ( 1 < gcoController_bd930.gccNumGCReqToReleasePages_bd930 )  // PTS 1113306 & 1136793 
          gcoController_bd930.gccNumGCReqToReleasePages_bd930 --;
      
      /* check that this is the right item to delete and that the item is empty */
#     if COMPILEMODE_MEO00 >= QUICK_MEO00         
      if (ObjFileId.fileRoot_gg00() != ObjFileInfo.GetRootPage())
      {
          g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
              "BD930RemFile: Wrong Item", ObjFileId.fileRoot_gg00());
          g01abort (csp3_bd_msg, csp3_n_obj,
              "BD930RemFile: Wrong Item", ObjFileId.fileObjFileNo_gg00());
      }
      
      for (int iChain=0; iChain<ObjFileInfo.GetChainCount(); ++iChain)
      {
          if ((ObjFileInfo[iChain].ociSubRoot_bd900     != NIL_PAGE_NO_GG00) ||
              (ObjFileInfo[iChain].ociCurrActivGC_bd900 != NIL_GC_INDEX_BD900))
          {
              g01abort (csp3_bd_msg, csp3_n_obj,
                  "BD930RemFil:ItemNotEmpty", ObjFileId.fileObjFileNo_gg00());
          }
      }
#   endif
      
      tsp00_PageNo rootNo       = ObjFileId.fileRoot_gg00();
      ObjFileInfo.SetRootPage(NIL_PAGE_NO_GG00);
      /* PTS 1126807 FF 2003-12-30 don't reset ofiRelFileIsReq_bd900 because of checks       */
      /*                           if file has been deleted                                  */
      /* ObjFileInfo.ofiRelFileIsReq_bd900 = false; * other GCs now ignore entry             */
      bSomethingDone                    = true;
      
      /* to avoid deadlocks on GC reagion, root MUST be freed outside of region !        */
      vendexcl (gcoTrans_bd930.trTaskId_gg00, g08garbage);
      /* get root page of the primary file. Note, that fixing the root page first and    */
      /* free it after the filedirectory entry and the key file have been removed        */
      /* garantees that all these actions are performed  within the same savepoint cycle */
      cbd05_Current Current (gcoTrans_bd930, m_update, ObjFileId);
      cbd910_RootNode  NptrsRoot (Current, rootNo, nr_for_update);
      if (e_ok != TrError)
      {
          if (e_no_converter_entry == TrError)
          {
              Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
              opWarnMsg << "bd930_RemoveFile root:" << ObjFileId.fileRoot_gg00()  
                  << " not found. RemoveFile ignored.";
              TrError = e_ok;
          }
          else 
          {
              Kernel_OpError  opErrMsg( csp3_bd_msg, csp3_n_obj );
              opErrMsg << "bd930_RemoveFile root:" << ObjFileId.fileRoot_gg00()  
                  << " error:" << TrError;
          }
          vbegexcl (gcoTrans_bd930.trTaskId_gg00, g08garbage); 
          return;
      }
      NptrsRoot.bd910ReleasePage(); /* to avoid deadlocks */
      vbegexcl (gcoTrans_bd930.trTaskId_gg00, g08garbage); 
      
      
      /* PTS 1113440 FF 16-Jan-2001                                      ++++++++++++++  */
      /* iter over all continue container files and remove root                          */
      /* go trough all cont object files an remove empty pages */
      if (cbd900_ObjFileInfo::omsVariableFile == ObjFileInfo.GetFileType())
      {
          tsp00_Int4               iContFileNo;
          tgg00_FileId             ContObjFileId;
          tsp00_Int4               FileNo          = ObjFileId.fileObjFileNo_gg00();
          cbd900_ContObjFileInfo & ContObjFileInfo = gcoController_bd930.gccContObjFileDirPtr_bd930->operator[](FileNo);
          
          vendexcl (gcoTrans_bd930.trTaskId_gg00, g08garbage);
          
          /* go through all continuation object files of this file */
          for (iContFileNo=1; (iContFileNo <=ContObjFileInfo.cfiNumContFiles_bd900); ++iContFileNo)
          {
              ContObjFileInfo.bd900BuildFileId (FileNo, iContFileNo, ContObjFileId);
              if ( NIL_PAGE_NO_GG00 != ContObjFileId.fileRoot_gg00() )
              {
                  
                  /* get root page */
                  cbd05_Current Current (gcoTrans_bd930, m_update, ContObjFileId);
                  cbd910_RootNode  NptrsRootCont (Current, ContObjFileId.fileRoot_gg00(), nr_for_update);
                  
                  /* remove file entry from the persistent file directory */
                  if (e_ok == TrError)
                      bd930_RemoveEntryFromPersFileDirectory (ContObjFileId);
                  
                  /* release root page */
                  if (e_ok == TrError)
                      NptrsRootCont.bd910FreePage();
                  
                  if (e_ok != TrError)
                  {
                      g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                          "BD930RUPFile: No Root  ", ContObjFileId.fileRoot_gg00());
                      g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                          "BD930RUPFile: Error    ", TrError);
                      TrError = e_ok;
                  }
              }
              
          }
          vbegexcl (gcoTrans_bd930.trTaskId_gg00, g08garbage); 
          
          /* reset entry in the object file directory */
          for (iContFileNo=1; (iContFileNo <=ContObjFileInfo.cfiNumContFiles_bd900); ++iContFileNo)
              ContObjFileInfo[iContFileNo].SetRootPage(NIL_PAGE_NO_GG00);
          
          gcoController_bd930.gccContObjFileDirPtr_bd930->bd920DelItem (gcoTrans_bd930.trTaskId_gg00, FileNo);
      }
      /* PTS 1113440 FF 16-Jan-2001                                      --------------  */
      
      /* remove files containing the keys */
      if (ObjFileInfo.GetKeyPartitionCount() > 0)
      {
          vendexcl (gcoTrans_bd930.trTaskId_gg00, g08garbage);
          bd22ReleaseObjKeyFiles (gcoTrans_bd930, ObjFileId.fileObjFileNo_gg00(), ObjFileInfo);
          vbegexcl (gcoTrans_bd930.trTaskId_gg00, g08garbage); 
          if (e_ok != TrError) return;
          /* reset entry in the object file directory */
          for (tsp00_Uint4 iKeyFile=0; iKeyFile < ObjFileInfo.GetKeyPartitionCount(); ++iKeyFile)
              ObjFileInfo.ofiKeyRoots_bd900[iKeyFile] = NIL_PAGE_NO_GG00;
      }
      if (e_ok != TrError) return;
      
      vendexcl (gcoTrans_bd930.trTaskId_gg00, g08garbage);
      
      /* release root page, after having changed the object file directory */
      NptrsRoot.bd910AssignToPage (rootNo);
      if (g01vtrace.vtrOmsFree_gg00 ) { Kernel_VTrace() << "RemoveObjFile bd910FreePage(root):" << rootNo; }
      NptrsRoot.bd910FreePage();
      
      /* remove file entry from the persistent file directory */
      bd930_RemoveEntryFromPersFileDirectory (ObjFileId);
      
      vbegexcl (gcoTrans_bd930.trTaskId_gg00, g08garbage); 
      
      /* remove entry in the object file directory */
      /* MUST be done after "NptrsRoot.bd910FreePage()" because of check "bd90ObjFileDir.bd920IsUsed(ObjFileNo)"
      within  bd95_RemoveObjFile */
      if (g01vtrace.vtrOmsFree_gg00 ) { Kernel_VTrace() << "RemoveObjFile bd920DelItem:" << ObjFileId.fileObjFileNo_gg00(); }
      gcoController_bd930.gccObjFileDirPtr_bd930->bd920DelItem (gcoTrans_bd930.trTaskId_gg00, ObjFileId.fileObjFileNo_gg00());
      
      ++gcoController_bd930.gccGCCounters_bd930[gcoIndex_bd930].gccntDropFiles;
  }
}

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

void
cbd930_GarbageCollector::bd930_WritePageStatusIntoVtrace (tgg00_TransContext    &Trans,
        tbd_nodeptr            pPage,
        tgg00_VtraceType_Enum  TraceObject)
{
    ROUTINE_DBG_MEO00 ("bd930_WritePageStatusIntoVtrace");

    tgg12_OmsPageStatTrace     TrLinePage;

    TrLinePage.opsTrType_gg12.becomes(otPageStat_egg12);
    TrLinePage.opsTrType2_gg12.becomes(ot2Nil_egg12);
    TrLinePage.opsPno_gg12           = pPage->nd_id();
    TrLinePage.opsOccObjCnt_gg12     = pPage->nd_occ_obj_cnt();
    TrLinePage.opsFreeObjCnt_gg12    = pPage->nd_free_obj_cnt();
    TrLinePage.opsFreeEotObjCnt_gg12 = pPage->nd_free_eot_obj_cnt();
    TrLinePage.opsResObjCnt_gg12     = pPage->nd_max_obj_cnt()
                                       -pPage->nd_occ_obj_cnt()
                                       -pPage->nd_free_obj_cnt()
                                       -pPage->nd_free_eot_obj_cnt();

    Trace_CommonEntry( Trans, tgg00_Debug::fromConst(bd), tgg00_VtraceType::fromConst(TraceObject),
                       REINTERPRET_CAST( tsp00_BytePtr, &TrLinePage ), sizeof (TrLinePage) );
}



/*---------------------------------------------------------------------------*/
/* METHOD IMPLEMENTATION FOR cbd930_GarbCollController                       */
/*---------------------------------------------------------------------------*/

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

    tsp00_Int2        CodeVars        = 252;
    const char       *MarkVars        = "B91VARS "; // PTS 1104704 TS 1999-12-02
    tsp00_Int2        CodeGCState     = 253;
    const char       *MarkGCState     = "B91GCSTA"; // PTS 1104704 TS 1999-12-02

    tgg00_BasisError  MoveError       = e_ok;

    // OutPos is handled as a Pascal (!) Position
    // only for C-Routines 1 must be subtracted

    HostError.becomes(vf_ok);

    g01new_dump_page (HostFile, Buffer, OutPno, OutPos, HostError, ErrText);

    // --- GARBAGE COLLECTOR GLOBALS ---

    if (vf_ok == HostError)
    {
        SAPDB_RangeMove( __FILE__, 1,
                DUMPMARKSIZE_BD900, BufferSize, MarkVars, 1,
                Buffer, OutPos, DUMPMARKSIZE_BD900 , MoveError);// PTS 1104704 TS 1999-12-02
        MoveError = e_ok; // ignore error
        OutPos += DUMPMARKSIZE_BD900;

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &CodeVars, sizeof(tsp00_Int2));
        OutPos += sizeof(tsp00_Int2);

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &gccNumGC_bd930, sizeof(gccNumGC_bd930));
        OutPos += sizeof(gccNumGC_bd930);

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &gccNumGCUsed_bd930, sizeof(gccNumGCUsed_bd930));
        OutPos += sizeof(gccNumGCUsed_bd930);

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &gccNumGCReqToReleasePages_bd930, sizeof(gccNumGCReqToReleasePages_bd930));
        OutPos += sizeof(gccNumGCReqToReleasePages_bd930);

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &gccStopGCManagerTID_bd930, sizeof(gccStopGCManagerTID_bd930));
        OutPos += sizeof(gccStopGCManagerTID_bd930);

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &gccStopGC_bd930, sizeof(gccStopGC_bd930));
        OutPos += sizeof(gccStopGC_bd930);

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &gccSpecialOperationIsActive_bd930, sizeof(gccSpecialOperationIsActive_bd930)); // PTS 1113552 FF
        OutPos += sizeof(gccSpecialOperationIsActive_bd930); // PTS 1113552 FF

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &gccCheckSavepointNeeded_bd930, sizeof(gccCheckSavepointNeeded_bd930));
        OutPos += sizeof(gccCheckSavepointNeeded_bd930);
    }

    // --- GARBAGE COLLECTOR STATE ---

    if (vf_ok == HostError)
    {
        SAPDB_RangeMove( __FILE__, 2,
                DUMPMARKSIZE_BD900, BufferSize, MarkGCState, 1,
                Buffer, OutPos, DUMPMARKSIZE_BD900 , MoveError);// PTS 1104704 TS 1999-12-02
        MoveError = e_ok; // ignore error
        OutPos += DUMPMARKSIZE_BD900;

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &CodeGCState, sizeof(tsp00_Int2));
        OutPos += sizeof(tsp00_Int2);

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &gccNumGC_bd930, sizeof(gccNumGC_bd930));
        OutPos += sizeof(gccNumGC_bd930);

        for (int iGC=0; iGC<MAX_OBJ_GARB_COLL_BD00; ++iGC)
        {
            if (cgg_nil_pid != gccGCState_bd930[iGC].gcsTaskId_bd930)
            {
                SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &gccGCState_bd930[iGC].gcsTaskId_bd930,
                        sizeof(gccGCState_bd930[iGC].gcsTaskId_bd930));
                OutPos += sizeof(gccGCState_bd930[iGC].gcsTaskId_bd930);

                SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &gccGCState_bd930[iGC].gcsActive_bd930,
                        sizeof(gccGCState_bd930[iGC].gcsActive_bd930));
                OutPos += sizeof(gccGCState_bd930[iGC].gcsActive_bd930);
            }
        }
    }

    /* dump member variable gccHistoryFileDir_bd930 */
    if (vf_ok == HostError)
    {
        gccHistoryFileDir_bd930.bd930DumpHistoryFileDir (HostFile,
                BufferSize, Buffer, OutPno, OutPos, HostError,ErrText);
    }
}

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

void
cbd930_GarbCollController::bd930_CheckGC ()
{
    ROUTINE_DBG_MEO00 ("bd930_CheckGC");

    /* this function checks if this object is consistent and */
    /* writes  all detected errors into the knldiag file     */

    /* a GC is called used if it is not suspended; a GC is called activ */
    /* if it is cleaning a particular class. a GC can be used but not   */
    /* activ when it is looking for a chain which requests its service  */

    /* check if the routine was called within the  g08garbage region */
#   if COMPILEMODE_MEO00 >= SLOW_MEO00 
    g08check_excl (g08garbage);
#   endif   

    /* check if the containers bd90ObjFileDir and bd93ContObjFileDir */
    /* the garbage collector is working on are consistent            */
    unsigned int bFileDirIsOk;

    bFileDirIsOk = gccObjFileDirPtr_bd930->bd920Verify();
    if ( bFileDirIsOk > 0 )
    {
        g01abort (csp3_b90_damaged_obj_chain, csp3_n_obj,
                  "BD930CGC: odd ObjFileDir", bFileDirIsOk);
    }

    bFileDirIsOk = gccContObjFileDirPtr_bd930->bd920Verify();
    if ( bFileDirIsOk > 0 )
    {
        g01abort (csp3_b90_damaged_obj_chain, csp3_n_obj,
                  "BD930CGC:oddCoObjFileDir", bFileDirIsOk);
    }

    /* now check if the information stored in the containers  */
    /* bd90ObjFileDir and bd93ContObjFileDir are consistent   */
    tsp00_Int4            NumGCUsed                   = 0;
    tsp00_Int4            NumGCReqToReleasePages      = 0;
    tsp00_Int4            NumGCActiveToReleasePages   = 0;
    tsp00_Int4            NumGCActiveToReleaseObject  = 0;
    tsp00_Int4            NumGCReqForThisFile         = 0;
    tsp00_Int4            NumGCActiveForThisFile      = 0;
    tsp00_Int4            iContFileNo;
    tsp00_Int4            FileNo;

    /*  count number of GCs requested and activ to release unused pages */
    cbd900_ObjFileDirIter ObjFileIter (*gccObjFileDirPtr_bd930);

    for  (ObjFileIter.bd920Begin(); !ObjFileIter.bd920End() ; ++ObjFileIter)
    {
        FileNo = ObjFileIter.bd920Key();
        ObjFileIter()->bd900GetNumOfActiveGCs (NumGCReqForThisFile, NumGCActiveForThisFile);

        NumGCReqToReleasePages    += NumGCReqForThisFile;
        NumGCActiveToReleasePages += NumGCActiveForThisFile;

        if (cbd900_ObjFileInfo::omsVariableFile == ObjFileIter()->GetFileType())
        {
            /* go through all continuation object files of this file */
            cbd900_ContObjFileInfo & ContObjFileInfo = gccContObjFileDirPtr_bd930->operator[](FileNo);
            for (iContFileNo=1; iContFileNo <=ContObjFileInfo.cfiNumContFiles_bd900; ++iContFileNo)
            {
                ContObjFileInfo [iContFileNo].bd900GetNumOfActiveGCs (NumGCReqForThisFile, NumGCActiveForThisFile);

                NumGCReqToReleasePages    += NumGCReqForThisFile;
                NumGCActiveToReleasePages += NumGCActiveForThisFile;
            }
        }
    }

    /* count number of GCs releasing unused objects by   */
    /* passing all history files and count the activ GCs */
    cbd930_HistoryFileIter HistFileIter (gccHistoryFileDir_bd930);
    for (HistFileIter.bd930First(); NULL != HistFileIter(); ++HistFileIter)
    {
        if (NIL_GC_INDEX_BD900 != HistFileIter()->hfiCurrActivGC_bd930)
            NumGCActiveToReleaseObject ++;
    }

    tsp00_Int4 NumGCActive = NumGCActiveToReleasePages + NumGCActiveToReleaseObject;

    /* count number of used GCs */
    for  (int iGC=0; iGC<gccNumGC_bd930; ++iGC)
        if(gccGCState_bd930[iGC].gcsActive_bd930)
            ++NumGCUsed;

    /*  check number of requested GCs */
    if (NumGCReqToReleasePages < /*!= PTS 1114176 FF*/ gccNumGCReqToReleasePages_bd930)
        g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                  "BD930CGC: wrong NumReqGC", NumGCReqToReleasePages);

    /* check number of used GCs */
    if (NumGCUsed != gccNumGCUsed_bd930)
        g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                  "BD930CGC:wrong NumGCUsed", NumGCUsed);

    if (NumGCUsed < NumGCActive)
        g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                  "BD930CGC:wrong NumActGC ", NumGCActive);

#   if COMPILEMODE_MEO00 >= QUICK_MEO00 
    /* check if the right number of GCs is activ */
    if ((gccNumGCUsed_bd930 < (gccNumGCReqToReleasePages_bd930 + NumGCActiveToReleaseObject)) &&
            (gccNumGCUsed_bd930 < gccNumGC_bd930)                                                 &&
            !gccStopGC_bd930 &&
            !gccRestartOfAllGCsInAction   &&
            !gccCheckSavepointNeeded_bd930 &&
            !gccSpecialOperationIsActive_bd930 ) // PTS 1113552 FF
    {
        g01opmsg (sp3p_knldiag, sp3m_warning, csp3_bd_msg, csp3_n_obj,
                  "BD930CGC:too few UsedGCs", NumGCUsed);
    }
#   endif

    /* check consistency of counters for GCs removing empty pages */
    if (NumGCActiveToReleasePages > gccNumGCUsedToReleasePages_bd930)
        g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj,
                  "BD930CGC:too many ActGCs", NumGCActiveToReleasePages);
}

/*-----------------------------------------------------------*/
// PTS 1111366 TS 2001-08-10; PTS 1113552 FF, PTS 1116157 FF 2002-06-07
void
cbd930_GarbCollController::bd930StartAllGCs (tsp00_TaskId   TaskId,
                                             bool           bIfGCWaitTimeDone)
{
    ROUTINE_DBG_MEO00  ("bd930StartAllGCs");
    
    SAPDB_UInt8 gccActTime = RTESys_Time();
    
    vbegexcl (TaskId, g08garbage); 
    if (bIfGCWaitTimeDone)
        gccGCStartRequested_bd930 = true;
    
    if (!bIfGCWaitTimeDone && !gccSpecialOperationIsActive_bd930) 
    {
        gccGCStartRequested_bd930 = false;
        gccLastTimeGCsStarted     = gccActTime;
        for (int iGC=0; iGC<gccNumGC_bd930; ++iGC)
        {
            /* search for suspended GCs */
            if (!gccGCState_bd930[iGC].gcsActive_bd930)
            {
                /* remove this GC from the pool of suspended GCs */
                gccGCState_bd930[iGC].gcsActive_bd930 = true;
                gccNumGCUsed_bd930 ++;
                
                /* resume GC */
                /* ============================================================== */
                vresume (gccGCState_bd930[iGC].gcsTaskId_bd930);
                /* ============================================================== */
            }
        }
        /* check the consistency of the garbage collector controller */
        BD930_CHECK_GC;
    }
    vendexcl (TaskId, g08garbage); 
}

/*-----------------------------------------------------------*/
/* PTS 1116157 FF 2002-06-11                                 */
/* FF 03-SEP-2002 PTS 1117682                                */
/* GC MUST never call bd930StartGCsIfRequired because        */
/* if "startExactlyOneGC == true" and other GCs are active   */
/* GC will wait forever within bd930StopAllGCsForSpecialOp   */

void
cbd930_GarbCollController::bd930StartGCsIfRequired (tsp00_TaskId   TaskId)
{
    const bool startUnconditionally = false;
    SAPDB_UInt8 gccActTime = RTESys_Time();
    bool startExactlyOneGC = false;
    const bool bUseMinRetentionTime = true;
    
    Converter_GarbageCollectionReturnCode retCode = 
        Converter_ICommon::Instance().GarbageCollectionNeeded();

    /* PTS 1135666 */
    if (Kernel_IAdminInfo::Instance().KernelStateIsOnline() &&
        ((TIMEOUT_UPD_MINTRANS_INTERVAL < (gccActTime - gccLastUpdMinTrans)) ||
        (Converter_GCNeeded == retCode)))
    {
        kb51UpdateMinTrans ( TaskId, 0 /* don't trigger GC again */);
        gccLastUpdMinTrans = gccActTime;
    }
    
    if (Converter_GCNeeded == retCode)
    {
        bool dropConsistView = false;
        /* if (gccCheckSavepointNeeded_bd930 == true)                                  */
        /*     cbd930_GarbageCollector::IsInterrrupted() check filling of devspaces    */
        if (gccCheckSavepointNeeded_bd930 == false) {
            Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
            opWarnMsg << "Garbagecollection enters phase red";
        }
        gccCheckSavepointNeeded_bd930 = true;
        
        /* PTS 1120151 FF 2003-JAN-10                                                  */
        /* drop oldest consistent view if:                                             */
        /*    1. Time-Interval has elapsed                                             */
        /*    2. No garbage collector is still active at this time                     */
        /*       this is because no consistent view should be dropped, if history is   */
        /*       still being dropped.                                                  */
		if (((TIMEOUT_START_TIME_INTERVAL_RED < (gccActTime - gccLastTimeGCsStarted)) &&
			(0 >= gccNumGCUsed_bd930)) && !gccStopGC_bd930)
		{
            tgg91_TransNo  ConsistViewNo;
            tsp00_Int4     StartDate;
            tsp00_Int4     StartTime;
			if (!gccRestartOfAllGCsInAction && 
                !gccSpecialOperationIsActive_bd930 &&
                Kernel_IAdminInfo::Instance().KernelStateIsOnline()) // PTS 1134225 UH 2005-03-03
            {
                kb51CancelConsistTrans (TaskId, ConsistViewNo, 
                    StartDate, StartTime, bUseMinRetentionTime);
                if (!ConsistViewNo.gg90IsNil())
                {
          			int i;
                    Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
                    opWarnMsg << "ConsistView:";
                    for (i=0; i < sizeof(ConsistViewNo); i++){
                        opWarnMsg << hexDigitsC[(SAPDB_UInt1)ConsistViewNo[i] / 16] 
                        << hexDigitsC[(SAPDB_UInt1)ConsistViewNo[i] % 16]; 
                    }
                    opWarnMsg << " cancelled - creation date:" << StartDate
                        << " time:" << StartTime;

                    Kernel_VTrace     vTrace;
                    vTrace << "ConsistView:";
                    for (i=0; i < sizeof(ConsistViewNo); i++) {
                        vTrace << hexDigitsC[(SAPDB_UInt1)ConsistViewNo[i] / 16] 
                        << hexDigitsC[(SAPDB_UInt1)ConsistViewNo[i] % 16]; 
                    }
                    vTrace << " found";

                }
			}
        }
        bd930StartAllGCs (TaskId, startUnconditionally);
    }
	else if ((TIMEOUT_START_TIME_INTERVAL < (gccActTime - gccLastTimeGCsStarted)) &&
		(Converter_GCNotNeeded == retCode) &&
		(gccGCStartRequested_bd930 || Kernel_IAdminInfo::Instance().KernelStateIsRestart()))
	{ 
        if (gccCheckSavepointNeeded_bd930) {
            Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
            opWarnMsg << "Garbagecollection leaves phase red";
        }
        gccCheckSavepointNeeded_bd930 = false;

        tgg91_TransNo  ConsistViewNo;
        tsp00_Int4     StartDate;
        tsp00_Int4     StartTime;
        if (!gccRestartOfAllGCsInAction && 
            !gccSpecialOperationIsActive_bd930 &&
            Kernel_IAdminInfo::Instance().KernelStateIsOnline()) // PTS 1134225 UH 2005-03-03
        {
            kb51CancelConsistTrans (TaskId, ConsistViewNo, 
                StartDate, StartTime, !bUseMinRetentionTime);
            if (!ConsistViewNo.gg90IsNil())
            {
                int i;
                Kernel_OpWarning  opWarnMsg( csp3_bd_msg, csp3_n_obj );
                opWarnMsg << "ConsistView:";
                for (i=0; i < sizeof(ConsistViewNo); i++) {
                    opWarnMsg << hexDigitsC[(SAPDB_UInt1)ConsistViewNo[i] / 16] 
                    << hexDigitsC[(SAPDB_UInt1)ConsistViewNo[i] % 16]; 
                }
                opWarnMsg << " cancelled because of MAX_RETENTION_TIME - creation date:" 
                    << StartDate << " time:" << StartTime;

                Kernel_VTrace     vTrace;
                vTrace << "ConsistView:";
                for (i=0; i < sizeof(ConsistViewNo); i++){
                    vTrace << hexDigitsC[(SAPDB_UInt1)ConsistViewNo[i] / 16] 
                    << hexDigitsC[(SAPDB_UInt1)ConsistViewNo[i] % 16]; 
                }
                vTrace << " found";

                bd930StartAllGCs (TaskId, startUnconditionally);
            }
        }
        bd930StartAllGCs (TaskId, startUnconditionally);
    }
}

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

void
cbd930_GarbCollController::bd930StartGCToRemoveFile (tgg00_TransContext   &Trans,
        cbd900_ObjFileInfo   &ObjFileInfo,
        bool                  bWithinRegion)  /* PTS 1115596 FF 2002-05-08 */  
{

    ROUTINE_DBG_MEO00 ("bd930StartGCToRemoveFile");

    tsp00_TaskId           GCTaskId[MAX_NUM_CHAINS_PER_CONTAINER_BD900];
    int              	   NumGCToBeStarted = 0;

    /* mark the file as deleted in the file directory */
    if ( !bWithinRegion ) /* PTS 1115596 FF 2002-05-08  */
        vbegexcl (Trans.trTaskId_gg00, g08garbage);

    /* mark that the object file request a GC */
    ObjFileInfo.ofiRelFileIsReq_bd900 = true;

    /* find an unused GC */
    for (int iChain=0; iChain < ObjFileInfo.GetChainCount(); ++iChain)
    {
        ++gccNumGCReqToReleasePages_bd930;
        bd930_FindUnusedGC (GCTaskId[NumGCToBeStarted]);
        if (cgg_nil_pid != GCTaskId[NumGCToBeStarted]) ++NumGCToBeStarted;
    }
    BD930_CHECK_GC;

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

    /* start unused GC  ===================================== */
    for (int iGC=0; iGC<NumGCToBeStarted; ++iGC)
        vresume (GCTaskId[iGC]);
    /*======================================================= */
}

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

void
cbd930_GarbCollController::bd930StopAllGCsForSpecialOp (tsp00_TaskId    TaskId)
{
    ROUTINE_DBG_MEO00  ("bd930StopAllGCs");

    /* This routine stops all running garbage collectors */

    bool bDoSuspend = false; // PTS 1111366 TS 2001-08-13
    tsp00_TaskId ResumeTaskId  = cgg_nil_pid; // FF 03-SEP-2002 PTS 1117682 

    vbegexcl (TaskId, g08garbage);

    gccSpecialOperationIsActive_bd930 = true; // PTS 1113552 FF

    if (0<gccNumGCUsed_bd930)
    {
        bDoSuspend                 = true;            // PTS 1111366 TS 2001-08-10
        if (gccStopGC_bd930)                          // FF 03-SEP-2002 PTS 1117682
            ResumeTaskId = gccStopGCManagerTID_bd930; // FF 03-SEP-2002 PTS 1117682
        else                                          // FF 03-SEP-2002 PTS 1117682
            gccStopGC_bd930        = true;
        gccStopGCManagerTID_bd930  = TaskId;
    };

    vendexcl (TaskId, g08garbage);

    if (bDoSuspend) // PTS 1111366 TS 2001-08-13
    {
        g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_obj,
                  "Stop active garbage coll", gccNumGCUsed_bd930);

        /*=====================================================*/
        vsuspend (TaskId, 229);
        /*=====================================================*/

        g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_obj,
                  "Garbage coll stopped    ", gccNumGCUsed_bd930);

        if (cgg_nil_pid != ResumeTaskId)  /* FF 03-SEP-2002 PTS 1117682 */
        {
            /*=======================================================================*/
            vresume (ResumeTaskId);  /*FF 03-SEP-2002 PTS 1117682 */
            /*=======================================================================*/
        };
     }

    /* check if really all GCs are suspended */
    if ((0<gccNumGCUsed_bd930) || gccStopGC_bd930 )
    {
#       if COMPILEMODE_MEO00 >= QUICK_MEO00 
        g01abort (csp3_bd_msg, csp3_n_obj, "BD91_StopGC: GC ACTIVE  ", gccNumGCUsed_bd930);
#       else
            g01opmsg (sp3p_knldiag, sp3m_error, csp3_bd_msg, csp3_n_obj, 
        "BD91_StopGC: GC ACTIVE  ", gccNumGCUsed_bd930);
#       endif
    }
}

/*---------------------------------------------------------------------------*/
/* METHOD IMPLEMENTATION FOR cbd930_HistoryFileDir                           */
/*---------------------------------------------------------------------------*/

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

    tsp00_Int2        CodeVars        = 256;
    const char       *MarkVars        = "B930HFD ";
    tgg00_BasisError  MoveError       = e_ok;

    // OutPos is handled as a Pascal (!) Position
    // only for C-Routines 1 must be subtracted

    HostError.becomes(vf_ok);

    g01new_dump_page (HostFile, Buffer, OutPno, OutPos, HostError, ErrText);

    if (vf_ok == HostError)
    {
        SAPDB_RangeMove( __FILE__, 3,
                DUMPMARKSIZE_BD900, BufferSize, MarkVars, 1,
                Buffer, OutPos, DUMPMARKSIZE_BD900 , MoveError);
        MoveError = e_ok; // ignore error
        OutPos += DUMPMARKSIZE_BD900;

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &CodeVars, sizeof(tsp00_Int2));
        OutPos += sizeof(tsp00_Int2);

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &hfdNumHFInfos_bd930, sizeof(hfdNumHFInfos_bd930));
        OutPos += sizeof(hfdNumHFInfos_bd930);

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &hfdMaxNumHFInfos_bd930, sizeof(hfdMaxNumHFInfos_bd930));
        OutPos += sizeof(hfdMaxNumHFInfos_bd930);

        SAPDB_Bool1 isInitialized = Log_History::IsInitialized();

        SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &isInitialized, sizeof(isInitialized));
        OutPos += sizeof(bool);

        if ( Log_History::IsInitialized() )
        {
            Log_History &history = Log_History::GetInstance();

            /* +++ PTS 1122219 2003-05-21 FF +++ */
            cbd930_HistoryFileInfo *HFInfoDummy = NULL;
            tsp00_Int4 maxEntryOnPage = (BufferSize - OutPos + sizeof(maxEntryOnPage)) /
                (sizeof(Log_History::ExtendedHistoryFileInfo) +
                sizeof(HFInfoDummy->hfiCurrActivGC_bd930)   +
                sizeof(HFInfoDummy->hfiHistoryGetsTruncated_bd930));
            
            if ( hfdNumHFInfos_bd930 < maxEntryOnPage )
                maxEntryOnPage = hfdNumHFInfos_bd930;
            SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &maxEntryOnPage, sizeof(maxEntryOnPage));
            OutPos += sizeof(maxEntryOnPage);
            /* --- PTS 1122219 2003-05-21 FF --- */

            for (int iHFI=0; iHFI<hfdNumHFInfos_bd930; ++iHFI)
            {
                cbd930_HistoryFileInfo &HFInfo = *(hfdFirstHFInfoPtr_bd930 + iHFI);

                /* PTS 1122219 2003-05-21 FF */
                if ( (tsp00_Uint4)BufferSize < 
                    (OutPos + sizeof(Log_History::ExtendedHistoryFileInfo) +
                    sizeof(HFInfo.hfiCurrActivGC_bd930)   +
                    sizeof(HFInfo.hfiHistoryGetsTruncated_bd930)))
                {
                    g01new_dump_page (HostFile, Buffer, OutPno, OutPos, HostError, ErrText);
                    
                    if (vf_ok != HostError)
                        return;

                    SAPDB_RangeMove( __FILE__, 4,    
                        DUMPMARKSIZE_BD900, BufferSize, MarkVars, 1,
                        Buffer, OutPos, DUMPMARKSIZE_BD900 , MoveError);
                    MoveError = e_ok; // ignore error 
                    OutPos += DUMPMARKSIZE_BD900;
                    
                    SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &CodeVars, sizeof(tsp00_Int2));
                    OutPos += sizeof(tsp00_Int2);
                    
                    SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &hfdNumHFInfos_bd930, sizeof(hfdNumHFInfos_bd930));
                    OutPos += sizeof(hfdNumHFInfos_bd930);
                    
                    SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &hfdMaxNumHFInfos_bd930, sizeof(hfdMaxNumHFInfos_bd930));
                    OutPos += sizeof(hfdMaxNumHFInfos_bd930);
                    
                    SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &isInitialized, sizeof(isInitialized));
                    OutPos += sizeof(bool);
        
                    if ((hfdNumHFInfos_bd930 - iHFI) < maxEntryOnPage )
                        maxEntryOnPage = ( hfdNumHFInfos_bd930 - iHFI);
                    SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &maxEntryOnPage, sizeof(maxEntryOnPage));
                    OutPos += sizeof(maxEntryOnPage);
                }

                SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, history.GetDumpInfo (HFInfo.hfiHistoryFileNo_bd930),
                        sizeof(Log_History::ExtendedHistoryFileInfo));
                OutPos += sizeof(Log_History::ExtendedHistoryFileInfo);

                SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &HFInfo.hfiCurrActivGC_bd930, sizeof(HFInfo.hfiCurrActivGC_bd930));
                OutPos += sizeof(HFInfo.hfiCurrActivGC_bd930);

                SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &HFInfo.hfiHistoryGetsTruncated_bd930, sizeof(HFInfo.hfiHistoryGetsTruncated_bd930));
                OutPos += sizeof(HFInfo.hfiHistoryGetsTruncated_bd930);
            }
        }
        else
        {
            /* +++ PTS 1122219 2003-05-21 FF +++ */
            cbd930_HistoryFileInfo *HFInfoDummy = NULL;
            tsp00_Int4 maxEntryOnPage = (BufferSize - OutPos + sizeof(maxEntryOnPage)) /
                (sizeof(HFInfoDummy->hfiCurrActivGC_bd930)   +
                sizeof(HFInfoDummy->hfiHistoryGetsTruncated_bd930));
            
            if ( hfdNumHFInfos_bd930 < maxEntryOnPage )
                maxEntryOnPage = hfdNumHFInfos_bd930;
            SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &maxEntryOnPage, sizeof(maxEntryOnPage));
            OutPos += sizeof(maxEntryOnPage);
            /* --- PTS 1122219 2003-05-21 FF --- */

            for (int iHFI=0; iHFI<hfdNumHFInfos_bd930; ++iHFI)
            {
                cbd930_HistoryFileInfo &HFInfo = *(hfdFirstHFInfoPtr_bd930 + iHFI);

                /* PTS 1122219 2003-05-21 FF */
                if ((tsp00_Uint4)BufferSize < 
                    (OutPos + sizeof(HFInfo.hfiCurrActivGC_bd930) +
                    sizeof(HFInfo.hfiHistoryGetsTruncated_bd930)))
                {
                    g01new_dump_page (HostFile, Buffer, OutPno, OutPos, HostError, ErrText);
                    
                    if (vf_ok != HostError)
                        return;

                    SAPDB_RangeMove( __FILE__, 5,    
                        DUMPMARKSIZE_BD900, BufferSize, MarkVars, 1,
                        Buffer, OutPos, DUMPMARKSIZE_BD900 , MoveError);
                    MoveError = e_ok; // ignore error 
                    OutPos += DUMPMARKSIZE_BD900;
                    
                    SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &CodeVars, sizeof(tsp00_Int2));
                    OutPos += sizeof(tsp00_Int2);
                    
                    SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &hfdNumHFInfos_bd930, sizeof(hfdNumHFInfos_bd930));
                    OutPos += sizeof(hfdNumHFInfos_bd930);
                    
                    SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &hfdMaxNumHFInfos_bd930, sizeof(hfdMaxNumHFInfos_bd930));
                    OutPos += sizeof(hfdMaxNumHFInfos_bd930);
                    
                    SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &isInitialized, sizeof(isInitialized));
                    OutPos += sizeof(bool);
        
                    if ((hfdNumHFInfos_bd930 - iHFI) < maxEntryOnPage )
                        maxEntryOnPage = ( hfdNumHFInfos_bd930 - iHFI);
                    SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &maxEntryOnPage, sizeof(maxEntryOnPage));
                    OutPos += sizeof(maxEntryOnPage);
                }

                SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &HFInfo.hfiCurrActivGC_bd930, sizeof(HFInfo.hfiCurrActivGC_bd930));
                OutPos += sizeof(HFInfo.hfiCurrActivGC_bd930);

                SAPDB_MemCopyNoCheck (Buffer + OutPos - 1, &HFInfo.hfiHistoryGetsTruncated_bd930, sizeof(HFInfo.hfiHistoryGetsTruncated_bd930));
                OutPos += sizeof(HFInfo.hfiHistoryGetsTruncated_bd930);
            }
        }
    }
}

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

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