.bm 8
.fm 4
.bt $Copyright (c) 2000-2005 SAP AG$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $SQL$Project Distributed Database System$VBD20$
.tt 2 $$$
.tt 3 $JuergenP$BD-data-cache$$2000-12-12$
***********************************************************
.nf
 
 .nf
 
    ========== 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
.fo
 
 
.fo
.nf
.sp
Module  : systembufferinterface
=========
.sp
Purpose : dynamic cache for B*-tree-nodes (data cache)
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :
 
        PROCEDURE
              bd20CheckExclusiveLockedPageForIO (
                    TaskId         : tsp00_TaskId;
                    VAR FileId     : tgg00_FileId;
                    PageNo         : tsp00_PageNo;
                    recMode        : tgg00_RecoveryMode;
                    pCBlock        : tbd02_pDataCBlock (* ptocSynonym tbd_nodeptr *);
                    VAR bWritePage : boolean;
                    VAR PageState  : tbd02_CachePageState);
 
        PROCEDURE
              bd20CheckRootNptrs (
                    TaskId      : tsp00_TaskId;
                    VAR TrError : tgg00_BasisError;
                    Root        : tsp00_PageNo;
                    pageNo      : tsp00_PageNo;
                    pCBlock     : tbd02_pDataCBlock (* ptocSynonym tbd_nodeptr *));
 
        PROCEDURE
              bd20LockPageForFree (
                    TaskId               : tsp00_TaskId;
                    VAR TrError          : tgg00_BasisError;
                    VAR FileId           : tgg00_FileId;
                    PageNo               : tsp00_PageNo;
                    recMode              : tgg00_RecoveryMode;
                    FirstCall            : boolean;
                    VAR PageLockedToFree : boolean;
                    VAR PageState        : tbd02_CachePageState;
                    VAR nptr             : tbd_nodeptr;
                    VAR cbptr            : tbd02_pDataCBlock);
 
        PROCEDURE
              bd20FreePage (
                    TaskId              : tsp00_TaskId;
                    PageNo              : tsp00_PageNo;
                    recMode             : tgg00_RecoveryMode;
                    VAR TrError         : tgg00_BasisError;
                    VAR ExclFileLockCnt : tsp00_Int2);
 
        PROCEDURE
              bd20FlushDataCache (
                    VAR Trans : tgg00_TransContext);
 
        PROCEDURE
              bd20ForcedIODone (
                    pCBlock : tbd02_pDataCBlock (* ptocSynonym tbd_nodeptr *);
                    TaskId  : tsp00_TaskId);
 
        PROCEDURE
              bd20GetPage (
                    TaskId              : tsp00_TaskId;
                    VAR WaitContext     : tgg00_WaitContext;
                    VAR TrError         : tgg00_BasisError;
                    VAR ExclFileLockCnt : tsp00_Int2;
                    VAR FileId          : tgg00_FileId;
                    PageNo              : tsp00_PageNo;
                    recMode             : tgg00_RecoveryMode;
                    NodeRequest         : tbd_node_request;
                    VAR nptr            : tbd_nodeptr;
                    VAR cbptr           : tbd02_pDataCBlock (* ptocSynonym tbd_nodeptr &*);
                    VAR PageState       : tbd02_CachePageState);
 
        PROCEDURE
              bd20InitDataCache (
                    TaskId          : tsp00_TaskId;
                    VAR TrError     : tgg00_BasisError;
                    TotalFreeFrames : tsp00_Int4;
                    TotalDataPages  : tsp00_Int4);
 
        FUNCTION
              bd20IsPageChanged (
                    pCBlock : tbd02_pDataCBlock (* ptocSynonym tbd_nodeptr *) ) : boolean;
 
        FUNCTION
              bd20IsPageExclusiveLocked (
                    pCBlock : tbd02_pDataCBlock (* ptocSynonym tbd_nodeptr *)) : boolean;
 
        FUNCTION
              bd20IsPageShareLocked (
                    pCBlock : tbd02_pDataCBlock (* ptocSynonym tbd_nodeptr *)) : boolean;
 
        FUNCTION
              bd20GetPageUsageCount (
                    pCBlock : tbd02_pDataCBlock (* ptocSynonym tbd_nodeptr *)) : tsp00_Int2;
 
        PROCEDURE
              bd20LoadPage (
                    taskId        : tsp00_TaskId;
                    pageNo        : tsp00_PageNo;
                    recMode       : tgg00_RecoveryMode;
                    bSetToChanged : boolean;
                    bIsClustered  : boolean;
                    VAR pageType  : tgg00_PageType;
                    VAR trError   : tgg00_BasisError;
                    VAR fileId    : tgg00_FileId;
                    VAR pFrame    : tbd_nodeptr;
                    VAR pCBlock   : tbd02_pDataCBlock (* ptocSynonym tbd_nodeptr &*);
                    VAR pageState : tbd02_CachePageState);
 
        PROCEDURE
              bd20NewPage (
                    TaskId        : tsp00_TaskId;
                    VAR TrError   : tgg00_BasisError;
                    VAR FileId    : tgg00_FileId;
                    PageNo        : tsp00_PageNo;
                    recMode       : tgg00_RecoveryMode;
                    VAR nptr      : tbd_nodeptr;
                    VAR cbptr     : tbd02_pDataCBlock;
                    VAR PageState : tbd02_CachePageState);
 
        PROCEDURE
              bd20RReleasePage (
                    TaskId              : tsp00_TaskId;
                    VAR ExclFileLockCnt : tsp00_Int2;
                    VAR FileId          : tgg00_FileId;
                    VAR nptr            : tbd_nodeptr;
                    VAR cbptr           : tbd02_pDataCBlock;
                    pageNo              : tsp00_PageNo;
                    recMode             : tgg00_RecoveryMode;
                    LruInfo             : tbd_lru_info;
                    bDoReduceSyncCnt    : boolean);
 
        PROCEDURE
              bd20WReleasePage (
                    TaskId              : tsp00_TaskId;
                    VAR ExclFileLockCnt : tsp00_Int2;
                    VAR FileId          : tgg00_FileId;
                    VAR nptr            : tbd_nodeptr;
                    VAR cbptr           : tbd02_pDataCBlock;
                    pageNo              : tsp00_PageNo;
                    recMode             : tgg00_RecoveryMode;
                    isClustered         : boolean;
                    VAR IoState         : tbd02_SwapState);
 
        PROCEDURE
              bd20ReplaceOldOccupant (
                    TaskId               : tsp00_TaskId;
                    PageNo               : tsp00_PageNo;
                    recMode              : tgg00_RecoveryMode;
                    cbptr                : tbd02_pDataCBlock (* ptocSynonym tbd_nodeptr *);
                    bLockPageExclusive   : boolean);
 
        PROCEDURE
              bd20ShutdownDataCache ( TaskId : tsp00_TaskId );
 
        PROCEDURE
              bd20UsePage (
                    TaskId              : tsp00_TaskId;
                    VAR TrError         : tgg00_BasisError;
                    PageNo              : tsp00_PageNo;
                    recMode             : tgg00_RecoveryMode;
                    cbptr               : tbd02_pDataCBlock (* ptocSynonym tbd_nodeptr *);
                    VAR nptr            : tbd_nodeptr;
                    bLockPageExclusive  : boolean);
 
        PROCEDURE
              bd20UsePageAfterLoad (
                    taskId        : tsp00_TaskId;
                    pageNo        : tsp00_PageNo;
                    recMode       : tgg00_RecoveryMode;
                    bSetToChanged : boolean;
                    bIsClustered  : boolean;
                    pCBlock       : tbd02_pDataCBlock(* ptocSynonym tbd_nodeptr *);
                    VAR file_id   : tgg00_FileId;
                    VAR trError   : tgg00_BasisError);
 
        PROCEDURE
              bd20ClearAccessStatistic(
                    TaskId : tsp00_TaskId );
 
        PROCEDURE
              bd20GetAccessStatistic(
                    TaskId               : tsp00_TaskId;
                    VAR HistoryTotal     : tsp00_8ByteCounter;
                    VAR HistoryHit       : tsp00_8ByteCounter;
                    VAR HistoryMiss      : tsp00_8ByteCounter;
                    VAR OmsDataTotal     : tsp00_8ByteCounter;
                    VAR OmsDataHit       : tsp00_8ByteCounter;
                    VAR OmsDataMiss      : tsp00_8ByteCounter;
                    VAR SqlDataTotal     : tsp00_8ByteCounter;
                    VAR SqlDataHit       : tsp00_8ByteCounter;
                    VAR SqlDataMiss      : tsp00_8ByteCounter);
              (* ptocExport hbd20_1.h *)
 
        PROCEDURE
              bd20GetCacheSize( VAR TotalPages : tsp00_Int4 );
 
        PROCEDURE
              bd20GetWorkloadCounter (
                    VAR DataCacheSize          : tsp00_Int4;
                    VAR OmsHistoryPageCnt      : tsp00_Int4;
                    VAR OmsDataPageCnt         : tsp00_Int4;
                    VAR OmsUnloadedVersPageCnt : tsp00_Int4;
                    VAR SqlDataPageCnt         : tsp00_Int4);
              (* ptocExport hbd20_2.h *)
 
        FUNCTION
              bd20IsPageRequested (
                    cbptr : tbd02_pDataCBlock (* ptocSynonym tbd_nodeptr *)) : boolean;
              (* ptocExport hbd20_3.h *)
 
        FUNCTION
              bd20ShrinkDataCache(TaskId : tsp00_TaskId) : tbd_nodeptr;
 
        FUNCTION
              bd20GrowDataCache (
                    TaskId : tsp00_TaskId;
                    pFrame : tbd_nodeptr) : boolean;
              (* ptocExport hbd20_4.h *)
 
        FUNCTION
              bd20PrepareDropDataVolume(
                    taskId   : tsp00_TaskId;
                    pMsgList : tgg00_VoidPtr ) : boolean;
 
        PROCEDURE
              bd20PrepareSavepoint (
                    TaskId           : tsp00_TaskId;
                    ConverterVersion : tgg00_ConverterVersion);
 
        PROCEDURE
              bd20IsSavepointCompleted( TaskId : tsp00_TaskId );
 
        PROCEDURE
              bd20SavepointCompleted (
                    TaskId           : tsp00_TaskId;
                    ConverterVersion : tgg00_ConverterVersion);
 
        PROCEDURE
              bd20SetPreventSvpSyncOperation (TaskId : tsp00_TaskId);
 
        PROCEDURE
              bd20UnSetPreventSvpSyncOperation (TaskId : tsp00_TaskId);
              (* ptocExport hbd20_5.h *)
 
        FUNCTION
              bd20ExclusiveLocks (TaskId : tsp00_TaskId) : boolean;
 
        PROCEDURE
              bd20FullestDataCacheSegment (
                    TaskId      : tsp00_TaskId;
                    VAR CacheNo : integer);
 
        PROCEDURE
              bd20GetPageForIO (
                    TaskId           : tsp00_TaskId;
                    RegOffset        : integer;
                    VAR TrError      : tgg00_BasisError;
                    VAR FlushElems   : tsp00_Int2;
                    VAR NodePtrList  : tbd00_NodePtrList;
                    VAR CBlockList   : tbd2_data_cb_flush_list;
                    VAR Completed    : boolean);
 
        FUNCTION
              bd20GetPageFromClusterIOChain (
                    TaskId           : tsp00_TaskId;
                    RegOffset        : integer) : tbd02_pDataCBlock;
 
        PROCEDURE
              bd20GetLeftChangedNode(
                    TaskId           : tsp00_TaskId;
                    pCBlock          : tbd02_pDataCBlock;
                    VAR leftpCBlock  : tbd02_pDataCBlock;
                    VAR found        : boolean);
 
        PROCEDURE
              bd20GetRightChangedNode(
                    TaskId           : tsp00_TaskId;
                    pCBlock          : tbd02_pDataCBlock;
                    VAR rightpCBlock : tbd02_pDataCBlock;
                    VAR found        : boolean);
 
        FUNCTION
              bd20IOElemCount (
                    TaskId    : tsp00_TaskId;
                    RegOffset : integer) : tsp00_Int4;
 
        PROCEDURE
              bd20GetTempFromLRURechain (
                    TaskId           : tsp00_TaskId;
                    RegOffset        : integer;
                    VAR TrError      : tgg00_BasisError;
                    VAR FlushElems   : tsp00_Int2;
                    VAR NodePtrList  : tbd00_NodePtrList;
                    VAR CBlockList   : tbd2_data_cb_flush_list);
 
        PROCEDURE
              bd20ResetIOState (
                    TaskId         : tsp00_TaskId;
                    RegOffset      : integer;
                    FlushElems     : tsp00_Int2;
                    VAR CBlockList : tbd2_data_cb_flush_list);
              (* ptocExport hbd20_6.h *)
 
        FUNCTION
              bd20GetNumberOfChangedPages : tsp00_Int4;
              (* ptocExport hbd20_7.h *)
 
        PROCEDURE
              bd20DumpDataCache (
                    VAR hostfile   : tgg00_VfFileref;
                    VAR b          : tsp00_Page;
                    VAR dump_pno   : tsp00_Int4;
                    VAR pos        : integer;
                    VAR host_error : tsp00_VfReturn;
                    VAR errtext    : tsp00_ErrText);
 
        PROCEDURE
              bd20DumpDataCacheFrames (
                    VAR hostfile   : tgg00_VfFileref;
                    VAR b          : tsp00_Page;
                    VAR dump_pno   : tsp00_Int4;
                    VAR pos        : integer;
                    VAR host_error : tsp00_VfReturn;
                    VAR errtext    : tsp00_ErrText);
              (* ptocExport hbd20_8.h *)
 
        PROCEDURE
              bd20ProtectDataCacheFrames (
                    Enable : boolean );
              (* ptocExport hbd20_9.h *)
 
        FUNCTION
              bd20GetDestinationConverterVersion (
                    TaskId  : tsp00_TaskId;
                    pCBlock : tbd02_pDataCBlock (* ptocSynonym tbd_nodeptr *)) : tgg00_ConverterVersion;
              (* ptocExport hbd20_10.h *)
 
        PROCEDURE
              bd20SystemViewDataCache (
                    VAR usableSize             : tsp00_Int4;
                    VAR usedSize               : tsp00_Int4;
                    VAR maxUsedSize            : tsp00_Int4;
                    VAR omsDataPageCnt         : tsp00_Int4;
                    VAR omsUnloadedVersPageCnt : tsp00_Int4;
                    VAR omsHistoryPageCnt      : tsp00_Int4;
                    VAR sqlDataPageCnt         : tsp00_Int4;
                    VAR changedPageCnt         : tsp00_Int4;
                    VAR pendingSyncSvpCnt      : tsp00_Int4);
              (* ptocExport hbd20_11.h *)
 
        FUNCTION
              bd20IsPreventSvpSyncOperationPending : boolean;
              (* ptocExport hbd20_12.h *)
 
        FUNCTION
              bd20GetAccessCounter( pCBlock : tbd02_pDataCBlock(*ptocSynonym const tbd_nodeptr*)): tsp00_Uint4;
 
        FUNCTION
              bd20GetCollisionCounter( pCBlock : tbd02_pDataCBlock(*ptocSynonym const tbd_nodeptr*)): tsp00_Uint4;
 
        FUNCTION
              bd20GetUpdateCounter( pCBlock : tbd02_pDataCBlock(*ptocSynonym const tbd_nodeptr*)): tsp00_Uint4;
 
.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :
 
        FROM
              error_text_handling : VBD06;
 
        PROCEDURE
              b06check_vresume_cnt (pid : tsp00_TaskId);
 
        PROCEDURE
              b06write_filename_and_root (VAR file_id : tgg00_FileId);
 
      ------------------------------ 
 
        FROM
              pagestore : VBD10;
 
        FUNCTION
              bd10GetConverterVersion : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              BD_Wrapper : VBD999;
 
        FUNCTION
              bd999GetFrame( TaskId : tsp00_TaskId ) : tbd_nodeptr;
 
        FUNCTION
              bd999GetPageSize : tsp00_Int4;
 
        FUNCTION
              bd999PrepareDropDataVolume(
                    taskId  : tsp00_TaskId;
                    errList : tgg00_VoidPtr ) : boolean;
 
        PROCEDURE
              bd999ReleaseFrame(
                    TaskId : tsp00_TaskId;
                    pNode  : tbd_nodeptr);
 
        PROCEDURE
              bd999WriteDataPage(
                    VAR Trans : tgg00_TransContext;
                    VAR pNode : tbd_nodeptr);
 
        PROCEDURE
              bd999FlushDataCache (
                    TaskId    : tsp00_TaskId);
 
      ------------------------------ 
 
        FROM
              KB_Logging : VKB560;
 
        PROCEDURE
              kb560InsertToWaitForPrepare(taskid : tsp00_TaskId;
                    VAR waitcontext : tgg00_WaitContext);
 
      ------------------------------ 
 
        FROM
              KB_ServerTasks : VKB900;
 
        FUNCTION
              kb900AvailableServerTasks : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              Configuration_Parameter : VGG01;
 
        VAR
              g01default_lru                : boolean;
              gg01DataCacheMemoryProtection : boolean;
              g01ConsistentReadEnabled      : boolean;
              g01glob                       : tgg00_KernelGlobals;
 
        PROCEDURE
              g01allocate_msg (msg_label : tsp00_C8;
                    msg_text   : tsp00_C24;
                    alloc_size : tsp00_Int4);
 
        PROCEDURE
              g01abort (msg_no : tsp00_Int4;
                    msg_label : tsp00_C8;
                    msg_text  : tsp00_C24;
                    bad_value : tsp00_Int4);
 
        FUNCTION
              g01dw_io_area_size : tsp00_Int4;
 
        FUNCTION
              g01dw_io_area_flush : tsp00_Int4;
 
        FUNCTION
              g01dw_lru_tail_flush : tsp00_Int4;
 
        FUNCTION
              g01maxdatawriter : tsp00_Int4;
 
        FUNCTION
              g01maxuser : tsp00_Int4;
 
        PROCEDURE
              g01next_prim_number (VAR prim_int : tsp00_Int4);
 
        PROCEDURE
              g01new_dump_page (VAR hostfile : tgg00_VfFileref;
                    VAR buf      : tsp00_Page;
                    VAR out_pno  : tsp00_Int4;
                    VAR out_pos  : integer;
                    VAR host_err : tsp00_VfReturn;
                    VAR errtext  : tsp00_ErrText);
 
        PROCEDURE
              g01opmsg (msg_prio : tsp3_priority;
                    msg_type  : tsp3_msg_type;
                    msg_no    : tsp00_Int4;
                    msg_label : tsp00_C8;
                    msg_text  : tsp00_C24;
                    msg_value : tsp00_Int4);
 
        PROCEDURE
              g01optextmsg (msg_prio : tsp3_priority;
                    msg_type  : tsp3_msg_type;
                    msg_no    : tsp00_Int4;
                    msg_label : tsp00_C8;
                    msg_text  : tsp00_C40);
 
        FUNCTION
              g01region_cnt (region_type : tgg00_RegionType) : tsp00_Int4;
 
      ------------------------------ 
 
        FROM
              Regions_and_Longwaits : VGG08;
 
        VAR
              g08datacache : tsp00_RegionId;
              g08data1     : tsp00_RegionId;
 
      ------------------------------ 
 
        FROM
              Kernel_move_and_fill : VGG101;
 
        PROCEDURE
              SAPDB_PascalForcedMove (
                    source_upb  : tsp00_Int4;
                    destin_upb  : tsp00_Int4;
                    source      : tsp00_MoveObjPtr;
                    source_pos  : tsp00_Int4;
                    destin      : tsp00_MoveObjPtr;
                    destin_pos  : tsp00_Int4;
                    length      : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              GG_edit_routines : VGG17;
 
        PROCEDURE
              g17hexto_line (c : char;
                    VAR ln_len : integer;
                    VAR ln     : tsp_c40);
 
        PROCEDURE
              g17trimint4_to_line (int : tsp00_Int4;
                    VAR ln_len : integer;
                    VAR ln     : tsp_c40);
 
      ------------------------------ 
 
        FROM
              KernelAdministration_Interface : VGG999;
 
        PROCEDURE
              gg999Abort (writeCore : boolean);
 
      ------------------------------ 
 
        FROM
              RTE_kernel : VEN101;
 
        PROCEDURE
              vbegexcl (pid : tsp00_TaskId;
                    region : tsp00_RegionId);
 
        PROCEDURE
              vendexcl (pid : tsp00_TaskId;
                    region : tsp00_RegionId);
 
        PROCEDURE
              vfwrite (hostfileno : tsp00_Int4;
                    buf         : tsp00_VfBufaddr;
                    VAR error   : tsp00_VfReturn;
                    VAR errtext : tsp00_ErrText);
 
        PROCEDURE
              vmalloc (length : tsp00_Int4;
                    VAR p  : tbd02_pDataCBlock;
                    VAR ok : boolean);
 
        PROCEDURE
              vmfree  (p : tbd02_pDataCBlock);
 
        PROCEDURE
              vprio (pid     : tsp00_TaskId;
                    prio     : tsp00_Uint1;
                    set_prio : boolean);
 
        PROCEDURE
              v2prio (pid : tsp00_TaskId;
                    prio     : tsp00_Uint1;
                    set_prio : boolean;
                    root     : tsp00_PageNo;
                    leaf     : tsp00_PageNo;
                    locktype : integer);
 
        PROCEDURE
              vresume (pid  : tsp00_TaskId);
 
        PROCEDURE
              vsleep (pid : tsp00_TaskId;
                    limit : tsp00_Int2);
 
        PROCEDURE
              vtracewriter_alive;
 
        PROCEDURE
              vgetpid (VAR pid : tsp00_TaskId);
 
        FUNCTION
              RTESys_MemProtectReadWrite(
                    pvAdr  : tbd_nodeptr;
                    ulSize : tsp00_Longint) : tsp00_Longint;
 
        FUNCTION
              RTESys_MemProtectReadOnly(
                    pvAdr  : tbd_nodeptr;
                    ulSize : tsp00_Longint) : tsp00_Longint;
 
      ------------------------------ 
 
        FROM
              RTE-Extension-20 : VSP20;
 
        PROCEDURE
              s20int4_to_buf (val : tsp00_Int4;
                    VAR dest : tsp00_Page;
                    di       : tsp00_Int4);
 
      ------------------------------ 
 
        FROM
              RTE-Extension-30 : VSP30;
 
&       ifdef TRACE
      ------------------------------ 
 
        FROM
              Test_Procedures : VTA01;
 
        PROCEDURE
              t01addr (debug : tgg00_Debug;
                    nam     : tsp00_Sname;
                    pointer : tbd02_pDataCBlock);
 
        PROCEDURE
              t01addr2 (debug : tgg00_Debug;
                    nam1     : tsp00_Sname;
                    pointer1 : tbd02_pDataCBlock;
                    nam2     : tsp00_Sname;
                    pointer2 : tbd02_pDataCBlock);
 
        PROCEDURE
              t01bool (debug : tgg00_Debug;
                    nam      : tsp00_Sname;
                    curr_bool: boolean);
 
        PROCEDURE
              t01int4 (layer : tgg00_Debug;
                    nam : tsp00_Sname;
                    int : tsp00_Int4);
 
        PROCEDURE
              t01int4_addr (layer : tgg00_Debug;
                    nam1    : tsp00_Sname;
                    int     : tsp00_Int4;
                    nam2    : tsp00_Sname;
                    bufaddr : tbd02_pDataCBlock);
 
        PROCEDURE
              t01name (layer : tgg00_Debug;
                    nam : tsp00_Name);
 
        PROCEDURE
              t01p2int4 (layer : tgg00_Debug;
                    nam1 : tsp00_Sname;
                    int1 : tsp00_Int4;
                    nam2 : tsp00_Sname;
                    int2 : tsp00_Int4);
 
        FUNCTION
              t01trace (layer : tgg00_Debug) : boolean;
&       endif
 
.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :
 
        PROCEDURE
              g17hexto_line;
 
              tsp00_Line tsp_c40
 
        PROCEDURE
              g17trimint4_to_line;
 
              tsp00_Line tsp_c40
 
        FUNCTION
              RTESys_MemProtectReadWrite;
 
              tsp00_MoveObjPtr tbd_nodeptr
 
        FUNCTION
              RTESys_MemProtectReadOnly;
 
              tsp00_MoveObjPtr tbd_nodeptr
 
        PROCEDURE
              vmalloc;
 
              tsp00_ObjAddr tbd02_pDataCBlock
 
        PROCEDURE
              vmfree;
 
              tsp00_ObjAddr tbd02_pDataCBlock
 
        PROCEDURE
              vfwrite;
 
              tsp_vf_bufaddr tsp00_VfBufaddr
 
        PROCEDURE
              v2prio;
 
              integer  tsp00_PageNo
 
        PROCEDURE
              s20int4_to_buf;
 
              tsp00_MoveObj tsp00_Page
&             ifdef TRACE
 
        PROCEDURE
              t01addr;
 
              tsp00_BufAddr tbd02_pDataCBlock
 
        PROCEDURE
              t01addr2;
 
              tsp00_BufAddr tbd02_pDataCBlock
 
        PROCEDURE
              t01int4_addr;
 
              tsp00_BufAddr tbd02_pDataCBlock
&             endif
 
.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : JuergenP
.sp
.cp 3
Created : 1982-11-19
.sp
.cp 3
.sp
.cp 3
Release :      Date : 2000-11-21
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:
 
.CM *-END-* specification -------------------------------
.sp 2
************************************************************
.sp
.cp 10
.fo
.oc _/1
Description:
 
 
.CM *-END-* description ---------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:
 
.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
 
 
CONST
      c_hl_lower_lim           =    9973;
      c_hl_upper_lim           = 1999993;
      c_max_aux_cbs            = 2000000;
      c_max_copies             =       2;
      c_max_headlist           = 2000000;
      c_max_pids               =   66000;
      c_nil_hash               =      -1;
      c_p50_percent            =       2;
      c_rechain_frac           =      10;
      c_dc_task_prio           =       2;
      (* *)
      FIRST_SEGMENT_BD20       =  0;
      LAST_SEGMENT_BD20        = 63;
      (* *)
      ASSERT_ID_15_BD20       = 15;
      ASSERT_ID_16_BD20       = 16;
      ASSERT_ID_17_BD20       = 17;
      ASSERT_ID_18_BD20       = 18;
      ASSERT_ID_19_BD20       = 19;
      ASSERT_ID_20_BD20       = 20;
      ASSERT_ID_21_BD20       = 21;
      (* *)
      ADD_TMP_TO_IO_CHAIN_BD20 =    true;
      RESUME_ALL_BD20          =    true;
      SET_PRIO_BD20            =    true;
      WRITE_CORE_BD20          =    true;
      IGNORE_DIRTY_PAGES_BD20  =    true;
      PREVENT_WRITE_IO_BD20    =    true;
      (* *)
      MSG_MID_EXIST           = 'MID ALREADY EXIST       ';
      MSG_IOMID_EXIST         = 'IO MID ALREADY EXIST    ';
      MSG_CBLOCK_NOT_FOUND    = 'CBLOCK NOT FOUND        ';
      MSG_LOOP_OVERFLOW       = 'MORE LOOPS THAN CBLOCKS ';
 
TYPE
 
      t_head_list_elem = RECORD
            he_cb          : tbd02_pDataCBlock;
            he_old_occ_cnt : tsp00_Int4;
&           ifdef BIT64
            he_fill        : tsp00_Int4;
&           endif
      END;
 
      t_head_list = ARRAY [0..c_max_headlist] OF t_head_list_elem;
      (* *)
      t_head_list_ptr = ^t_head_list;
      (* *)
      t_aux_controlblocks = ARRAY [0..c_max_aux_cbs] OF tbd02_DataCBlock;
      (* *)
      t_aux_pid_queue_list = ARRAY [1..c_max_pids] OF tbd02_TaskQueueItem;
      (* *)
      t_aux_cb_ptr = ^t_aux_controlblocks;
      (* *)
      t_aux_pid_queue_ptr  = ^t_aux_pid_queue_list;
      (* *)
 
      b20ptr = RECORD
            CASE integer OF
                1 :
                    (nodeaddr       : tbd_nodeptr);
                2 :
                    (cblockaddr     : tbd02_pDataCBlock);
                3 :
                    (aux_cb_addr    : t_aux_cb_ptr);
                4 :
                    (pid_queue_addr : tbd02_pTaskQueueItem);
                5 :
                    (aux_hl_addr    : t_head_list_ptr);
                6:
                    (aux_chain_addr : t_aux_pid_queue_ptr);
                END;
            (*ENDCASE*) 
 
 
      t_datacache = RECORD
            dc_pHeadList          : t_head_list_ptr;
            (* *)
            dc_pIOQueueHead1      : tbd02_pDataCBlock;
            dc_pIOQueueHead2      : tbd02_pDataCBlock;
            dc_pIOQueueTail1      : tbd02_pDataCBlock;
            dc_pIOQueueTail2      : tbd02_pDataCBlock;
            (* *)
            dc_pClusterQueueHead1 : tbd02_pDataCBlock;
            dc_pClusterQueueHead2 : tbd02_pDataCBlock;
            dc_pClusterQueueTail1 : tbd02_pDataCBlock;
            dc_pClusterQueueTail2 : tbd02_pDataCBlock;
            (* *)
            dc_pFirstCBlock       : tbd02_pDataCBlock;
            dc_pLastCBlock        : tbd02_pDataCBlock;
            dc_pFirstLRU          : tbd02_pDataCBlock;
            dc_pLastLRU           : tbd02_pDataCBlock;
            dc_pMid               : tbd02_pDataCBlock;
            dc_pIOMid             : tbd02_pDataCBlock;
            dc_pFreeList          : tbd02_pDataCBlock;
            dc_pFrameLessCBlocks  : tbd02_pDataCBlock;
            (* *)
            dc_pTaskQueueHead     : tbd02_pTaskQueueItem;
            dc_pTaskQueueFree     : tbd02_pTaskQueueItem;
            dc_pOverflowTaskQueue : tbd02_pTaskQueueItem;
            dc_pSvpEndTaskQueue   : tbd02_pTaskQueueItem;
            (* *)
            dc_SegmentId          : tsp00_Int4;
            dc_IOAreaSize         : tsp00_Int4;
            dc_SVPElems           : tsp00_Int4;
            dc_clusteredSVPElems  : tsp00_Int4;
            dc_IOElems            : tsp00_Int4;
            dc_clusteredIOElems   : tsp00_Int4;
            dc_HeadListSize       : tsp00_Int4;
            dc_FreeCount          : tsp00_Int4;
            dc_OldOccupants       : tsp00_Int4;
            dc_SegmentSize        : tsp00_Int4;
            dc_RecAreaSize        : tsp00_Int4;
            dc_TotalSvpSyncCnt    : tsp00_Int4;
            dc_IOAreaFlushCnt     : tsp00_Int4;
            dc_LruTailFlushCnt    : tsp00_Int4;
            dc_FrameLessCBlockCnt : tsp00_Int4;
            (* *)
            dc_UndoFilePageCnt    : tsp00_Int4;
            dc_OmsDataPageCnt     : tsp00_Int4;
            dc_OmsTempPageCnt     : tsp00_Int4;
            dc_SqlDataPageCnt     : tsp00_Int4;
            (* *)
            dc_UndoFileHit        : tsp00_8ByteCounter;
            dc_UndoFileMiss       : tsp00_8ByteCounter;
            dc_OmsDataHit         : tsp00_8ByteCounter;
            dc_OmsDataMiss        : tsp00_8ByteCounter;
            dc_SqlDataHit         : tsp00_8ByteCounter;
            dc_SqlDataMiss        : tsp00_8ByteCounter;
            (* *)
            dc_SVPActive          : boolean;
            dc_SegmentActive      : boolean;
            dc_PreventSvpSync     : boolean;
            dc_IOSwitch           : boolean;
            dc_MemoryProtection   : boolean;
            dc_PreventWriteIO     : boolean;
      END;
 
 
VAR
      bd20CBlockInit           : tbd02_DataCBlockInit;
      bd20DataCacheList        : ARRAY [FIRST_SEGMENT_BD20..LAST_SEGMENT_BD20] OF t_datacache;
      bd20RegionCount          : tsp00_Int4;
      bd20TotalChangedPages    : tsp00_Int4;
      bd20NextShrinkSegment    : tsp00_Int4;
      bd20MaxUsedSize          : tsp00_Int4;
      (* *)
 
 
(*------------------------------*) 
 
FUNCTION
      bd20GetAccessCounter( pCBlock : tbd02_pDataCBlock ): tsp00_Uint4;
 
BEGIN
bd20GetAccessCounter := pCBlock^.dcb_AccessCnt_bd02;
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20GetCollisionCounter( pCBlock : tbd02_pDataCBlock ): tsp00_Uint4;
 
BEGIN
bd20GetCollisionCounter := pCBlock^.dcb_CollisionCnt_bd02;
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20GetUpdateCounter( pCBlock : tbd02_pDataCBlock ): tsp00_Uint4;
 
BEGIN
bd20GetUpdateCounter := pCBlock^.dcb_UpdateCnt_bd02;
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20GetDestinationConverterVersion (
            TaskId  : tsp00_TaskId;
            pCBlock : tbd02_pDataCBlock ) : tgg00_ConverterVersion;
 
VAR
      RegOffset : integer;
 
BEGIN
RegOffset := pCBlock^.dcb_occupant MOD bd20RegionCount;
(* *)
vbegexcl (TaskId, g08data1 + RegOffset);
(* *)
WITH bd20DataCacheList [RegOffset], pCBlock^ DO
    BEGIN
    IF  (dc_SVPActive AND (dcb_ChangedState_bd02 <> cstSvpRelevant_ebd02))
    THEN
        bd20GetDestinationConverterVersion := bd10GetConverterVersion + 1
    ELSE
        bd20GetDestinationConverterVersion := bd10GetConverterVersion;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
(* *)
vendexcl (TaskId, g08data1 + RegOffset);
(* *)
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20GetNumberOfChangedPages : tsp00_Int4;
 
BEGIN
bd20GetNumberOfChangedPages := bd20TotalChangedPages;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20CheckExclusiveLockedPageForIO (
            TaskId         : tsp00_TaskId;
            VAR FileId     : tgg00_FileId;
            PageNo         : tsp00_PageNo;
            recMode        : tgg00_RecoveryMode;
            pCBlock        : tbd02_pDataCBlock;
            VAR bWritePage : boolean;
            VAR PageState  : tbd02_CachePageState);
 
VAR
      RegOffset     : integer;
      HashIndex     : tsp00_Int4;
      pPredCBlock   : tbd02_pDataCBlock; (* not used *)
      pCurrCBlock   : tbd02_pDataCBlock; (* not used *)
      pSourceCBlock : tbd02_pDataCBlock;
 
BEGIN
bWritePage := false;
IF  (pCBlock^.dcb_UsageCnt_bd02 = 1                 ) AND
    (pCBlock^.dcb_io_state = iosBlocked_ebd02       ) AND
    (pCBlock^.dcb_ChangedState_bd02 <> cstNone_ebd02)
THEN
    BEGIN
    RegOffset  := PageNo MOD bd20RegionCount;
    HashIndex  := PageNo MOD bd20DataCacheList [RegOffset].dc_HeadListSize;
    (* *)
    vbegexcl (TaskId, g08data1 + RegOffset);
    (* *)
    WITH bd20DataCacheList [RegOffset] DO
        BEGIN
        IF  dc_SegmentActive
        THEN
            BEGIN
            IF  (dc_SVPActive AND (pCBlock^.dcb_ChangedState_bd02 = cstSvpRelevant_ebd02  )) OR
                ((NOT dc_SVPActive) AND (pCBlock^.dcb_ChangedState_bd02 = cstChanged_ebd02))
            THEN
                BEGIN
                IF  pCBlock^.dcb_copy_no = 0
                THEN
                    bWritePage := true
                ELSE
                    BEGIN (* dcb_copy_no > 0 ==> pSourceCBlock <> NIL *)
                    PageState.cpsWaitForWrite_bd02 := true;
                    bd20c_search_in_chain_incl_copy (bd20DataCacheList [RegOffset],
                          HashIndex, PageNo, recMode, pCurrCBlock, pPredCBlock,
                          PageState.cpsFound_bd02, pSourceCBlock);
                    bd20_InsertOccupant (TaskId, FileId, bd20DataCacheList [RegOffset],
                          pSourceCBlock)
                    END
                (*ENDIF*) 
                END
            ELSE
                IF  (dc_SVPActive AND (pCBlock^.dcb_ChangedState_bd02 = cstChanged_ebd02))
                THEN
                    BEGIN
                    PageState.cpsWaitForSvpEnd_bd02 := true;
                    bd20_InsertSavepointEnd (TaskId, FileId, bd20DataCacheList [RegOffset]);
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
    (* *)
    vendexcl (TaskId, g08data1 + RegOffset);
    (* *)
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20CheckRootNptrs (
            TaskId      : tsp00_TaskId;
            VAR TrError : tgg00_BasisError;
            Root        : tsp00_PageNo;
            pageNo      : tsp00_PageNo;
            pCBlock     : tbd02_pDataCBlock);
 
VAR
      RegOffset : integer;
 
BEGIN
(* PTS 1106125 TS 2000-03-24 *)
RegOffset := Root MOD bd20RegionCount;
(* *)
vbegexcl (TaskId, g08data1 + RegOffset);
(* *)
IF  NOT bd20DataCacheList [RegOffset].dc_SegmentActive
THEN
    TrError := e_shutdown
ELSE
    BEGIN
    IF  pageNo <> Root
    THEN
        g01abort (csp3_b20x1_illegal_page_no, csp3_n_datacache,
              'BD20CheckRoot id <> root', pageNo);
    (*ENDIF*) 
    IF  pCBlock <> NIL
    THEN
        BEGIN
        IF  pCBlock^.dcb_occupant <> pageNo
        THEN
            g01abort (csp3_b20x1_illegal_page_no, csp3_n_datacache,
                  'BD20CheckRoot occu <> id', pageNo);
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDIF*) 
(* *)
vendexcl (TaskId, g08data1 + RegOffset);
(* *)
(* PTS 1106125 *)
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20ClearAccessStatistic(
            TaskId : tsp00_TaskId );
 
VAR
      RegOffset : tsp00_Int4;
 
BEGIN
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    WITH bd20DataCacheList [RegOffset] DO
        BEGIN
        vbegexcl (TaskId, g08data1 + RegOffset);
        dc_UndoFileHit      := 0;
        dc_UndoFileMiss     := 0;
        dc_OmsDataHit       := 0;
        dc_OmsDataMiss      := 0;
        dc_SqlDataHit       := 0;
        dc_SqlDataMiss      := 0;
        vendexcl (TaskId, g08data1 + RegOffset);
        END
    (*ENDWITH*) 
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20GetAccessStatistic(
            TaskId               : tsp00_TaskId;
            VAR HistoryTotal     : tsp00_8ByteCounter;
            VAR HistoryHit       : tsp00_8ByteCounter;
            VAR HistoryMiss      : tsp00_8ByteCounter;
            VAR OmsDataTotal     : tsp00_8ByteCounter;
            VAR OmsDataHit       : tsp00_8ByteCounter;
            VAR OmsDataMiss      : tsp00_8ByteCounter;
            VAR SqlDataTotal     : tsp00_8ByteCounter;
            VAR SqlDataHit       : tsp00_8ByteCounter;
            VAR SqlDataMiss      : tsp00_8ByteCounter);
 
VAR
      RegOffset : tsp00_Int4;
 
BEGIN
HistoryTotal  := 0;
HistoryHit    := 0;
HistoryMiss   := 0;
OmsDataTotal  := 0;
OmsDataHit    := 0;
OmsDataMiss   := 0;
SqlDataTotal  := 0;
SqlDataHit    := 0;
SqlDataMiss   := 0;
(* *)
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    WITH bd20DataCacheList [RegOffset] DO
        BEGIN
        vbegexcl (TaskId, g08data1 + RegOffset);
        (* *)
        HistoryHit   := HistoryHit   + dc_UndoFileHit;
        HistoryMiss  := HistoryMiss  + dc_UndoFileMiss;
        HistoryTotal := HistoryTotal + dc_UndoFileHit + dc_UndoFileMiss;
        (* *)
        OmsDataHit      := OmsDataHit   + dc_OmsDataHit;
        OmsDataMiss     := OmsDataMiss  + dc_OmsDataMiss;
        OmsDataTotal    := OmsDataTotal + dc_OmsDataHit + dc_OmsDataMiss;
        (* *)
        SqlDataHit      := SqlDataHit   + dc_SqlDataHit;
        SqlDataMiss     := SqlDataMiss  + dc_SqlDataMiss;
        SqlDataTotal    := SqlDataTotal + dc_SqlDataHit + dc_SqlDataMiss;
        vendexcl (TaskId, g08data1 + RegOffset);
        END;
    (*ENDWITH*) 
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20GetCacheSize( VAR TotalPages : tsp00_Int4 );
 
VAR
      RegOffset : tsp00_Int4;
 
BEGIN
TotalPages := 0;
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    BEGIN
    TotalPages := TotalPages + bd20DataCacheList [RegOffset].dc_SegmentSize;
    END;
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20_GetCacheSize : tsp00_Int4;
 
VAR
      CacheSize : tsp00_Int4;
      RegOffset : tsp00_Int4;
 
BEGIN
CacheSize := 0;
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    CacheSize := CacheSize + bd20DataCacheList [RegOffset].dc_SegmentSize;
(*ENDFOR*) 
bd20_GetCacheSize := CacheSize;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20GetWorkloadCounter (
            VAR DataCacheSize          : tsp00_Int4;
            VAR OmsHistoryPageCnt      : tsp00_Int4;
            VAR OmsDataPageCnt         : tsp00_Int4;
            VAR OmsUnloadedVersPageCnt : tsp00_Int4;
            VAR SqlDataPageCnt         : tsp00_Int4);
 
VAR
      RegOffset      : tsp00_Int4;
 
BEGIN
(* PTS 1111572 E.Z. *)
OmsHistoryPageCnt      := 0;
OmsDataPageCnt         := 0;
OmsUnloadedVersPageCnt := 0;
SqlDataPageCnt         := 0;
DataCacheSize          := bd20_GetCacheSize;
(* *)
(* Dirty read to avoid performance problems *)
(* *)
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    WITH bd20DataCacheList [RegOffset] DO
        BEGIN
        OmsHistoryPageCnt      := OmsHistoryPageCnt      + dc_UndoFilePageCnt;
        OmsDataPageCnt         := OmsDataPageCnt         + dc_OmsDataPageCnt;
        OmsUnloadedVersPageCnt := OmsUnloadedVersPageCnt + dc_OmsTempPageCnt;
        SqlDataPageCnt         := SqlDataPageCnt         + dc_SqlDataPageCnt;
        END
    (*ENDWITH*) 
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20SystemViewDataCache (
            VAR usableSize             : tsp00_Int4;
            VAR usedSize               : tsp00_Int4;
            VAR maxUsedSize            : tsp00_Int4;
            VAR omsDataPageCnt         : tsp00_Int4;
            VAR omsUnloadedVersPageCnt : tsp00_Int4;
            VAR omsHistoryPageCnt      : tsp00_Int4;
            VAR sqlDataPageCnt         : tsp00_Int4;
            VAR changedPageCnt         : tsp00_Int4;
            VAR pendingSyncSvpCnt      : tsp00_Int4);
 
VAR
      regOffset : tsp00_Int4;
      freeSize  : tsp00_Int4;
      dummySize : tsp00_Int4;
 
BEGIN
(* *)
bd20GetWorkloadCounter ( dummySize, omsHistoryPageCnt,
      omsDataPageCnt, omsUnloadedVersPageCnt, sqlDataPageCnt );
(* *)
freeSize := 0;
(* *)
FOR regOffset := 0 TO bd20RegionCount - 1 DO
    WITH bd20DataCacheList [regOffset] DO
        BEGIN
        changedPageCnt    := changedPageCnt    + dc_IOElems + dc_clusteredIOElems;
        pendingSyncSvpCnt := pendingSyncSvpCnt + dc_TotalSvpSyncCnt;
        usableSize        := usableSize        + dc_SegmentSize;
        freeSize          := freeSize          + dc_FreeCount;
        END;
    (*ENDWITH*) 
(*ENDFOR*) 
usedSize := usableSize - freeSize;
IF  usedSize > bd20MaxUsedSize
THEN
    bd20MaxUsedSize := usedSize;
(*ENDIF*) 
maxUsedSize := bd20MaxUsedSize;
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20IsPageRequested (cbptr : tbd02_pDataCBlock) : boolean;
 
BEGIN
bd20IsPageRequested := (cbptr^.dcb_lock_req_head <> NIL);
END;
 
&ifdef TESTONLY
(*------------------------------*) 
 
PROCEDURE
      bd20ReduceCache(TaskId : tsp00_TaskId);
 
VAR
      AuxPtr  : tbd_nodeptr;
 
BEGIN
IF  bd20DataCacheList [FIRST_SEGMENT_BD20].dc_SegmentActive
THEN
    WITH bd20DataCacheList[ FIRST_SEGMENT_BD20 ] DO
        BEGIN
        IF  ( dc_FrameLessCBlockCnt < (( dc_SegmentSize + dc_FrameLessCBlockCnt ) DIV 2 ))
        THEN
            BEGIN
            AuxPtr := bd20ShrinkDataCache( TaskId );
            g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_datacache,
                  'TimeOut Task Shrink Cach', dc_SegmentSize);
            END;
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
&endif
(*------------------------------*) 
 
FUNCTION
      bd20ShrinkDataCache (TaskId : tsp00_TaskId) : tbd_nodeptr;
 
VAR
      Dummy               : boolean;
      CurrRegOffset       : tsp00_Int4; (* PTS 1111664 TS 2001-11-27 *)
      StopRegOffset       : tsp00_Int4; (* PTS 1111664 TS 2001-11-27 *)
      HashIndex           : tsp00_Int4;
      pFrame              : tbd_nodeptr;
      pCBlock             : tbd02_pDataCBlock;
      pPredCBlock         : tbd02_pDataCBlock;
 
BEGIN
pCBlock := NIL;
pFrame  := NIL;
(* *)
vbegexcl (TaskId, g08datacache);
(* *)
CurrRegOffset         := bd20NextShrinkSegment;
bd20NextShrinkSegment := (bd20NextShrinkSegment + 1) MOD bd20RegionCount;
(* *)
vendexcl (TaskId, g08datacache);
(* *)
StopRegOffset := CurrRegOffset;
REPEAT   (* PTS 1111664 TS 2001-11-27 *)
    (* *)
    vbegexcl (TaskId, g08data1 + CurrRegOffset);
    (* *)
    WITH bd20DataCacheList [CurrRegOffset] DO
        BEGIN
        IF  (dc_pFreeList <> NIL)
        THEN
            BEGIN
            dc_FreeCount  := dc_FreeCount - 1;
            pCBlock       := dc_pFreeList;
            pFrame        := pCBlock^.dcb_pFrame_bd02;
            dc_pFreeList  := pCBlock^.dcb_VarNext_bd02;
&           ifdef torsten
            g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_datacache,
                  'Shrink Data Cache (pool)', dc_SegmentSize);
&           endif
            END
        ELSE
            BEGIN
            pCBlock := dc_pLastLRU;
            WHILE (pFrame = NIL) AND (pCBlock <> NIL) DO
                WITH pCBlock^ DO
                    BEGIN (* PTS 1114525 TS 2002-02-27 *)
                    IF  (dcb_UsageCnt_bd02 <> 0       ) OR
                        (dcb_io_state <> iosNone_ebd02) OR
                        (dcb_pFrame_bd02 = NIL        ) OR
                        (dcb_IsSourceOfACopy_bd02     ) OR
                        (dcb_copy_no <> 0             )
                    THEN
                        pCBlock := dcb_lru_prev
                    ELSE
                        BEGIN (* Usable *)
                        IF  (dcb_ChangedState_bd02 = cstNone_ebd02)
                        THEN
                            BEGIN
                            pFrame    := pCBlock^.dcb_pFrame_bd02;
                            HashIndex := pCBlock^.dcb_occupant MOD dc_HeadListSize;
                            bd20_SearchInChain (bd20DataCacheList [CurrRegOffset], HashIndex, pCBlock^.dcb_occupant,
                                  pCBlock^.dcb_RecMode_bd02, pCBlock, pPredCBlock, Dummy);
                            bd20del_from_chain (bd20DataCacheList [CurrRegOffset], HashIndex, pCBlock, pPredCBlock);
                            bd20_DelFromLRUList (bd20DataCacheList [CurrRegOffset], pCBlock);
                            bd20_DecrementWorkloadCounter (bd20DataCacheList [CurrRegOffset], pCBlock^.dcb_tfn);
                            END
                        ELSE
                            pCBlock := dcb_lru_prev
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDWITH*) 
            (*ENDWHILE*) 
&           ifdef torsten
            IF  pFrame <> NIL (* PTS 1114525 TS 2002-02-27 *)
            THEN
                g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_datacache,
                      'Shrink Data Cache (LRU) ', dc_SegmentSize);
&           endif
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  pFrame = NIL
        THEN
            BEGIN
            (* *)
            vendexcl (TaskId, g08data1 + CurrRegOffset);
            (* *)
            CurrRegOffset := (CurrRegOffset + 1) MOD bd20RegionCount;
&           ifdef torsten
            g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_datacache,
                  'Hop to next segment     ', CurrRegOffset);
&           endif
            vsleep (TaskId, 1)
            END
        ELSE
            BEGIN (* bFound *)
            dc_FrameLessCBlockCnt         := dc_FrameLessCBlockCnt + 1;
            pPredCBlock                   := dc_pFrameLessCBlocks;
            pCBlock^.dcb_VarNext_bd02     := pPredCBlock;
            dc_pFrameLessCBlocks          := pCBlock;
            pCBlock^.dcb_pFrame_bd02      := NIL;
            (* *)
            dc_SegmentSize := dc_SegmentSize - 1;
            dc_RecAreaSize := (dc_SegmentSize + 1) DIV c_rechain_frac;
            bd20_AdjustRechainAndIOArea (bd20DataCacheList [CurrRegOffset]);
            IF  bd20DataCacheList [CurrRegOffset].dc_MemoryProtection
            THEN
                bd20_ReadWriteAccessToFrame (pFrame);
            (* *)
            (*ENDIF*) 
            vendexcl (TaskId, g08data1 + CurrRegOffset);
            (* *)
            END
        (*ENDIF*) 
        END
    (*ENDWITH*) 
UNTIL
    ((pFrame <> NIL) OR (CurrRegOffset = StopRegOffset));
(*ENDREPEAT*) 
bd20ShrinkDataCache := pFrame;
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20GrowDataCache (
            TaskId : tsp00_TaskId;
            pFrame : tbd_nodeptr) : boolean;
 
VAR
      bFound        : boolean;
      currRegOffset : tsp00_Int4;
      stopRegOffset : tsp00_Int4;
      pCBlock       : tbd02_pDataCBlock;
 
BEGIN
bFound        := false;
currRegOffset := bd20NextShrinkSegment;
currRegOffset := currRegOffset MOD bd20RegionCount;
stopRegOffset := currRegOffset;
pCBlock       := NIL;
(* *)
REPEAT
    (* *)
    vbegexcl (TaskId, g08data1 + currRegOffset);
    (* *)
    WITH bd20DataCacheList [currRegOffset] DO
        BEGIN
        IF  dc_FrameLessCBlockCnt <> 0
        THEN
            BEGIN
            bFound := true;
            (* take frame less cotrol block *)
            dc_FrameLessCBlockCnt    := dc_FrameLessCBlockCnt - 1;
            pCBlock                  := dc_pFrameLessCBlocks;
            dc_pFrameLessCBlocks     := dc_pFrameLessCBlocks^.dcb_VarNext_bd02;
            pCBlock^.dcb_pFrame_bd02 := pFrame;
            (* insert into free list *)
            dc_FreeCount              := dc_FreeCount + 1;
            pCBlock^.dcb_VarNext_bd02 := dc_pFreeList;
            dc_pFreeList              := pCBlock;
            (* *)
            dc_SegmentSize := dc_SegmentSize + 1;
            dc_RecAreaSize := (dc_SegmentSize + 1) DIV c_rechain_frac;
            bd20_AdjustRechainAndIOArea (bd20DataCacheList [currRegOffset]);
            IF  bd20DataCacheList [currRegOffset].dc_MemoryProtection
            THEN
                bd20_ReadAccessToFrame (pFrame);
            (* *)
&           ifdef torsten
            (*ENDIF*) 
            g01opmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_datacache,
                  'Grow Data Cache (pool)  ', dc_SegmentSize);
&           endif
            END
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
    (* *)
    vendexcl (TaskId, g08data1 + currRegOffset);
    (* *)
    IF  NOT bFound
    THEN
        currRegOffset := (currRegOffset + 1) MOD bd20RegionCount;
    (*ENDIF*) 
UNTIL
    ((bFound) OR (currRegOffset = stopRegOffset));
(*ENDREPEAT*) 
bd20GrowDataCache := bFound;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20IsSavepointCompleted( TaskId : tsp00_TaskId );
 
CONST
      msg1 = '+++ SAVEPOINT INCOMPLETE +++            ';
      msg2 = 'Data cache still contains pages which   ';
      msg3 = 'are relevant for the current savepoint. ';
      msg4 = 'Number of cluster pages ';
      msg5 = 'Number of left pages    ';
 
VAR
      RegOffset : integer;
 
BEGIN
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    vbegexcl (TaskId, g08data1 + RegOffset);
(*ENDFOR*) 
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    WITH bd20DataCacheList [RegOffset] DO
        BEGIN
        IF  (0 <> dc_SVPElems) OR (0 <> dc_clusteredSVPElems)
        THEN
            BEGIN
            g01optextmsg (sp3p_knldiag, sp3m_error, csp3_b20x1_check_io_cnt, csp3_n_datacache, msg1);
            g01optextmsg (sp3p_knldiag, sp3m_error, csp3_b20x1_check_io_cnt, csp3_n_datacache, msg2);
            g01optextmsg (sp3p_knldiag, sp3m_error, csp3_b20x1_check_io_cnt, csp3_n_datacache, msg3);
            g01opmsg(sp3p_knldiag, sp3m_error, csp3_b20x1_check_io_cnt, csp3_n_datacache, msg4,
                  dc_clusteredSVPElems);
            g01abort (csp3_b20x1_check_io_cnt, csp3_n_datacache, msg5, dc_SVPElems);
            END;
        (*ENDIF*) 
        IF  g01glob.datacachecheck
        THEN
            bd20check_svp_chain (bd20DataCacheList [RegOffset]);
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDFOR*) 
(* *)
FOR RegOffset := bd20RegionCount - 1 DOWNTO 0 DO
    vendexcl (TaskId, g08data1 + RegOffset);
(*ENDFOR*) 
(* *)
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20SavepointCompleted (
            TaskId           : tsp00_TaskId;
            ConverterVersion : tgg00_ConverterVersion);
 
VAR
      RegOffset : integer;
 
BEGIN
bd20TotalChangedPages := 0;
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    vbegexcl (TaskId, g08data1 + RegOffset);
(*ENDFOR*) 
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    WITH bd20DataCacheList [RegOffset] DO
        BEGIN
        bd20TotalChangedPages := bd20TotalChangedPages + dc_IOElems + dc_clusteredIOElems;
        dc_SVPActive          := false;
        bd20_ResumeOverflow (bd20DataCacheList [RegOffset], MAX_INT4_SP00);
        bd20_ResumeSavepointEnd (bd20DataCacheList [RegOffset]);
        END;
    (*ENDWITH*) 
(*ENDFOR*) 
(* *)
FOR RegOffset := bd20RegionCount - 1 DOWNTO 0 DO
    vendexcl (TaskId, g08data1 + RegOffset);
(*ENDFOR*) 
(* *)
g01opmsg ( sp3p_knldiag, sp3m_info, csp3_b20_savepoint_completed,
      csp3_n_savepoint, 'B20SVP_COMPLETED        ', ConverterVersion);
END;
 
(* CR 1105627  *)
(*------------------------------*) 
 
PROCEDURE
      bd20DumpDataCache (
            VAR hostfile   : tgg00_VfFileref;
            VAR b          : tsp00_Page;
            VAR dump_pno   : tsp00_Int4;
            VAR pos        : integer;
            VAR host_error : tsp00_VfReturn;
            VAR errtext    : tsp00_ErrText);
 
VAR
      RegOffset : tsp00_Int4;
 
BEGIN
RegOffset := 0;
(* *)
(* First dump all the small structures and than the space consuming frames *)
(* *)
WHILE (host_error = vf_ok) AND (RegOffset <= bd20RegionCount - 1) DO
    BEGIN
    bd20_DumpDataCache (bd20DataCacheList [RegOffset], RegOffset,
          hostfile, b, dump_pno, pos, host_error, errtext);
    RegOffset := succ (RegOffset)
    END;
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_DumpDataCache (
            VAR datacache  : t_datacache;
            RegOffset      : tsp00_Int4;
            VAR hostfile   : tgg00_VfFileref;
            VAR b          : tsp00_Page;
            VAR dump_pno   : tsp00_Int4;
            VAR pos        : integer;
            VAR host_error : tsp00_VfReturn;
            VAR errtext    : tsp00_ErrText);
 
CONST
      mark0_b20bufco   = 'B20BUFCO';
      code0_b20bufco   = 205;
      mark1_b20hdlis   = 'B20HDLIS';
      code1_b20hdlis   = 209;
      mark2_b20hdlfo   = 'B20HDLFO';
      code2_b20hdlfo   = 211;
      mark3_b20cbloc   = 'B20CBLOC';
      code3_b20cbloc   = 213;
      mark4_b20cblfo   = 'B20CBLFO';
      code4_b20cblfo   = 215;
      mark5_b20vars    = 'B20VARS ';
      code5_b20vars    = 207;
      mark6_b20quele   = 'B20QUELE';
      code6_b20quele   = 217;
      mark7_b20qufol   = 'B20QUFOL';
      code7_b20qufol   = 219;
      mark11_b20regio  = 'B20REGIO';
      code11_b20regio  = 203;
      (* *)
      mark20_b20all    = 'B20ALL  ';
      code20_b20all    = 237;
 
VAR
      dump_mark          : tsp00_C8;
      buf_ptr            : tsp00_VfBufaddr;
      act_block          : tbd02_pDataCBlock;
      act_pid_queue      : tbd02_pTaskQueueItem;
      p                  : b20ptr;
      i                  : tsp00_Int4;
      hd_elem_count      : tsp00_Int4;
      elems_on_page      : tsp00_Int4;
      elems_pos          : integer;
      cb_len             : integer;
      hd_elem_len        : integer;
      queue_elem_len     : integer;
      h_int              : tsp00_IntMapC2;
 
BEGIN
buf_ptr      := @b;
cb_len       := sizeof (tbd02_DataCBlock)
      +         sizeof (tbd02_pDataCBlock)
      +         sizeof (tsp00_PageNo)
      +         sizeof (tsp00_PageNo);
hd_elem_len  := sizeof (t_head_list_elem)
      +         sizeof (tsp00_Int4);
WITH datacache DO
    BEGIN
    (* *)
    (* --- FILL PREVIOUS DUMPPAGE --- *)
    (* *)
    IF  host_error = vf_ok
    THEN
        g01new_dump_page (hostfile, b, dump_pno, pos, host_error, errtext);
    (*ENDIF*) 
    IF  host_error = vf_ok
    THEN
        BEGIN
        IF  RegOffset = 0
        THEN
            BEGIN
            (* *)
            (* --- BUFFERSIZE --- *)
            (* *)
            dump_mark := mark0_b20bufco;
            SAPDB_PascalForcedMove (sizeof (dump_mark), sizeof (b),
                  @dump_mark, 1,@b, pos, sizeof (dump_mark));
            pos           := pos + sizeof (dump_mark);
            h_int.mapInt_sp00 := code0_b20bufco;
            b[pos]        := h_int.mapC2_sp00[1];
            b[pos + 1]    := h_int.mapC2_sp00[2];
            pos           := pos + 2;
            s20int4_to_buf (bd20_GetCacheSize, b, pos);
            pos           := pos + 4;
            (* *)
            (* --- NO OF DATACACHE REGIONS --- *)
            (* *)
            dump_mark := mark11_b20regio;
            SAPDB_PascalForcedMove (sizeof (dump_mark), sizeof (b),
                  @dump_mark, 1, @b, pos, sizeof (dump_mark));
            pos           := pos + sizeof (dump_mark);
            h_int.mapInt_sp00 := code11_b20regio;
            b[pos]        := h_int.mapC2_sp00[1];
            b[pos + 1]    := h_int.mapC2_sp00[2];
            pos           := pos + 2;
            s20int4_to_buf (bd20RegionCount, b, pos);
            pos           := pos + 4;
            (* *)
            (* --- GENERAL INFO ABOUT CACHES --- *)
            (* *)
            dump_mark := mark20_b20all;
            SAPDB_PascalForcedMove (sizeof (dump_mark), sizeof (b),
                  @dump_mark, 1, @b, pos, sizeof (dump_mark));
            pos           := pos + sizeof (dump_mark);
            h_int.mapInt_sp00 := code20_b20all;
            b[pos]        := h_int.mapC2_sp00[1];
            b[pos + 1]    := h_int.mapC2_sp00[2];
            pos           := pos + 2;
            s20int4_to_buf (bd20NextShrinkSegment, b, pos);
            pos           := pos + 4;
            s20int4_to_buf (bd20TotalChangedPages, b, pos);
            pos           := pos + 4;
            END;
        (* *)
        (* --- DATACACHE VARIABLES --- *)
        (* *)
        (*ENDIF*) 
        IF  host_error = vf_ok
        THEN
            BEGIN
            dump_mark := mark5_b20vars;
            SAPDB_PascalForcedMove (
                  sizeof (dump_mark), sizeof (b),
                  @dump_mark, 1, @b, pos, sizeof (dump_mark));
            pos := pos + sizeof (dump_mark);
            h_int.mapInt_sp00 := code5_b20vars;
            b[pos]     := h_int.mapC2_sp00[1];
            b[pos + 1] := h_int.mapC2_sp00[2];
            pos := pos + 2;
            s20int4_to_buf (RegOffset, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_SegmentSize, b, pos);
            pos := pos + 4;
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pFirstCBlock), sizeof (b),
                  @dc_pFirstCBlock, 1, @b, pos, sizeof (dc_pFirstCBlock));
            pos      := pos + sizeof (dc_pFirstCBlock);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pLastCBlock), sizeof (b),
                  @dc_pLastCBlock, 1, @b, pos, sizeof (dc_pLastCBlock));
            pos      := pos + sizeof (dc_pLastCBlock);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pFirstLRU), sizeof (b),
                  @dc_pFirstLRU, 1,@b, pos, sizeof (dc_pFirstLRU));
            pos      := pos + sizeof (dc_pFirstLRU);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pLastLRU), sizeof (b),
                  @dc_pLastLRU, 1, @b, pos, sizeof (dc_pLastLRU));
            pos      := pos + sizeof (dc_pLastLRU);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pMid), sizeof (b),
                  @dc_pMid, 1,@b, pos, sizeof (dc_pMid));
            pos      := pos + sizeof (dc_pMid);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pIOMid), sizeof (b),
                  @dc_pIOMid, 1, @b, pos, sizeof (dc_pIOMid));
            pos      := pos + sizeof (dc_pIOMid);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pFreeList), sizeof (b),
                  @dc_pFreeList, 1, @b, pos, sizeof (dc_pFreeList));
            pos      := pos + sizeof (dc_pFreeList);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pFrameLessCBlocks), sizeof (b),
                  @dc_pFrameLessCBlocks, 1,
                  @b, pos, sizeof (dc_pFrameLessCBlocks));
            pos      := pos + sizeof (dc_pFrameLessCBlocks);
            (* *)
            s20int4_to_buf (dc_FreeCount, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_FrameLessCBlockCnt, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_HeadListSize, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_SVPElems, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_clusteredSVPElems, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_IOElems, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_clusteredIOElems, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_TotalSvpSyncCnt, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_OldOccupants, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_IOAreaSize, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_RecAreaSize, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_IOAreaFlushCnt, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_LruTailFlushCnt, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_UndoFilePageCnt, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_OmsDataPageCnt, b, pos);
            pos := pos + 4;
            s20int4_to_buf (dc_SqlDataPageCnt, b, pos);
            pos := pos + 4;
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pIOQueueHead1), sizeof (b),
                  @dc_pIOQueueHead1, 1, @b, pos, sizeof (dc_pIOQueueHead1));
            pos      := pos + sizeof (dc_pIOQueueHead1);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pIOQueueHead2), sizeof (b),
                  @dc_pIOQueueHead2, 1, @b, pos, sizeof (dc_pIOQueueHead2));
            pos      := pos + sizeof (dc_pIOQueueHead2);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pIOQueueTail1), sizeof (b),
                  @dc_pIOQueueTail1, 1, @b, pos, sizeof (dc_pIOQueueTail1));
            pos      := pos + sizeof (dc_pIOQueueTail1);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pIOQueueTail2), sizeof (b),
                  @dc_pIOQueueTail2, 1, @b, pos, sizeof (dc_pIOQueueTail2));
            pos      := pos + sizeof (dc_pIOQueueTail2);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pClusterQueueHead1), sizeof (b),
                  @dc_pClusterQueueHead1, 1, @b, pos, sizeof (dc_pClusterQueueHead1));
            pos      := pos + sizeof (dc_pClusterQueueHead1);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pClusterQueueHead2), sizeof (b),
                  @dc_pClusterQueueHead2, 1, @b, pos, sizeof (dc_pClusterQueueHead2));
            pos      := pos + sizeof (dc_pClusterQueueHead2);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pClusterQueueTail1), sizeof (b),
                  @dc_pClusterQueueTail1, 1, @b, pos, sizeof (dc_pClusterQueueTail1));
            pos      := pos + sizeof (dc_pClusterQueueTail1);
            (* *)
            SAPDB_PascalForcedMove (
                  sizeof (dc_pClusterQueueTail2), sizeof (b),
                  @dc_pClusterQueueTail2, 1, @b, pos, sizeof (dc_pClusterQueueTail2));
            pos      := pos + sizeof (dc_pClusterQueueTail2);
            (* *)
            p.pid_queue_addr := dc_pOverflowTaskQueue;
            SAPDB_PascalForcedMove (
                  sizeof (p.cblockaddr), sizeof (b),
                  @p.cblockaddr, 1,@b, pos, sizeof (p.cblockaddr));
            pos      := pos + sizeof (p.cblockaddr);
            (* *)
            p.pid_queue_addr := dc_pSvpEndTaskQueue;
            SAPDB_PascalForcedMove (
                  sizeof (p.cblockaddr), sizeof (b),
                  @p.cblockaddr, 1, @b, pos, sizeof (p.cblockaddr));
            pos      := pos + sizeof (p.cblockaddr);
            (* *)
            p.pid_queue_addr := dc_pTaskQueueHead;
            SAPDB_PascalForcedMove (
                  sizeof (p.cblockaddr), sizeof (b),
                  @p.cblockaddr, 1, @b, pos, sizeof (p.cblockaddr));
            pos      := pos + sizeof (p.cblockaddr);
            (* *)
            p.pid_queue_addr := dc_pTaskQueueFree;
            SAPDB_PascalForcedMove (
                  sizeof (p.cblockaddr), sizeof (b),
                  @p.cblockaddr, 1,@b, pos, sizeof (p.cblockaddr));
            pos      := pos + sizeof (p.cblockaddr);
            (* *)
            b [pos]     := chr (ord (dc_SegmentActive));
            b [pos + 1] := chr (ord (dc_SVPActive));
            b [pos + 2] := chr (ord (dc_PreventSvpSync));
            b [pos + 3] := chr (ord (dc_IOSwitch));
            b [pos + 4] := chr (ord (dc_MemoryProtection));
            b [pos + 5] := chr (ord (dc_PreventWriteIO));
            pos         := pos + 6;
            IF  host_error = vf_ok
            THEN
                g01new_dump_page (hostfile, b, dump_pno, pos, host_error, errtext);
            (*ENDIF*) 
            END;
        (* *)
        (* --- HASHLIST --- *)
        (* *)
        (*ENDIF*) 
        IF  (dc_SegmentSize > 0)
        THEN
            BEGIN
            IF  dc_pHeadList <> NIL
            THEN
                BEGIN
                dump_mark := mark1_b20hdlis;
                SAPDB_PascalForcedMove (
                      sizeof (dump_mark), sizeof (b),
                      @dump_mark, 1, @b, pos, sizeof (dump_mark));
                pos           := pos + sizeof (dump_mark);
                h_int.mapInt_sp00 := code1_b20hdlis;
                b[pos]        := h_int.mapC2_sp00[1];
                b[pos + 1]    := h_int.mapC2_sp00[2];
                pos           := pos + 2;
                s20int4_to_buf (dc_HeadListSize, b, pos);
                pos           := pos + 4;
                i             := 0;
                hd_elem_count := 0;
                WHILE i < dc_HeadListSize DO
                    BEGIN
                    IF  dc_pHeadList^ [i].he_cb <> NIL
                    THEN
                        hd_elem_count := succ (hd_elem_count);
                    (*ENDIF*) 
                    i := i + 1;
                    END;
                (*ENDWHILE*) 
                s20int4_to_buf (hd_elem_count, b, pos);
                pos           := pos + 4;
                elems_pos     := pos;
                pos           := pos + 3;
                elems_on_page := 0;
                i             := 0;
                WHILE (host_error = vf_ok) AND (i < dc_HeadListSize) DO
                    IF  dc_pHeadList^ [i].he_cb <> NIL
                    THEN
                        IF  pos + hd_elem_len <= sizeof (b)
                        THEN
                            WITH dc_pHeadList^ [i] DO
                                BEGIN
                                elems_on_page := succ (elems_on_page);
                                s20int4_to_buf (i, b, pos);
                                pos := pos + 4;
                                SAPDB_PascalForcedMove (
                                      sizeof (he_cb), sizeof (b),
                                      @he_cb, 1, @b, pos, sizeof (he_cb));
                                pos      := pos + sizeof (he_cb);
                                s20int4_to_buf (he_old_occ_cnt, b, pos);
                                pos := pos + 4;
&                               ifdef BIT64
                                s20int4_to_buf (he_fill, b, pos);
                                pos := pos + 4;
&                               endif
                                i := i + 1;
                                END
                            (*ENDWITH*) 
                        ELSE
                            BEGIN
                            h_int.mapInt_sp00 := elems_on_page;
                            b [elems_pos]     := h_int.mapC2_sp00 [1];
                            b [elems_pos + 1] := h_int.mapC2_sp00 [2];
                            b [elems_pos + 2] := chr (ord (false));
                            g01new_dump_page (hostfile, b, dump_pno, pos, host_error, errtext);
                            IF  host_error = vf_ok
                            THEN
                                BEGIN
                                dump_mark := mark2_b20hdlfo;
                                SAPDB_PascalForcedMove (
                                      sizeof (dump_mark), sizeof (b),
                                      @dump_mark, 1, @b, pos, sizeof (dump_mark));
                                pos := pos + sizeof (dump_mark);
                                h_int.mapInt_sp00 := code2_b20hdlfo;
                                b[pos]     := h_int.mapC2_sp00[1];
                                b[pos + 1] := h_int.mapC2_sp00[2];
                                pos        := pos + 2;
                                elems_pos  := pos;
                                pos        := pos + 3;
                                elems_on_page := 0
                                END
                            (*ENDIF*) 
                            END
                        (*ENDIF*) 
                    ELSE
                        i := i + 1;
                    (*ENDIF*) 
                (*ENDWHILE*) 
                IF  (host_error = vf_ok)
                THEN
                    BEGIN
                    h_int.mapInt_sp00 := elems_on_page;
                    b [elems_pos]     := h_int.mapC2_sp00 [1];
                    b [elems_pos + 1] := h_int.mapC2_sp00 [2];
                    b [elems_pos + 2] := chr (ord (true));
                    g01new_dump_page (hostfile, b, dump_pno, pos, host_error, errtext)
                    END
                (*ENDIF*) 
                END;
            (* *)
            (* --- CONTROLBLOCKS --- *)
            (* *)
            (*ENDIF*) 
            IF  host_error = vf_ok
            THEN
                BEGIN
                dump_mark := mark3_b20cbloc;
                SAPDB_PascalForcedMove (
                      sizeof (dump_mark), sizeof (b),
                      @dump_mark, 1, @b, pos, sizeof (dump_mark));
                pos := pos + sizeof (dump_mark);
                h_int.mapInt_sp00 := code3_b20cbloc;
                b[pos]     := h_int.mapC2_sp00[1];
                b[pos + 1] := h_int.mapC2_sp00[2];
                pos := pos + 2;
                END;
            (*ENDIF*) 
            elems_pos     := pos;
            pos           := pos + 3;
            elems_on_page := 0;
            act_block     := dc_pFirstCBlock;
            WHILE (host_error = vf_ok) AND (act_block <> NIL) DO
                BEGIN
                IF  pos + cb_len <= sizeof (b)
                THEN
                    BEGIN
                    WITH act_block^ DO
                        BEGIN
                        elems_on_page := succ (elems_on_page);
                        (* *)
                        SAPDB_PascalForcedMove (
                              sizeof (act_block), sizeof (b),
                              @act_block, 1,
                              @b, pos, sizeof (act_block));
                        pos := pos + sizeof (act_block);
                        (* *)
                        p.nodeaddr := dcb_pFrame_bd02;
                        SAPDB_PascalForcedMove (
                              sizeof (p.cblockaddr), sizeof (b),
                              @p.cblockaddr, 1,
                              @b, pos, sizeof (p.cblockaddr));
                        pos := pos + sizeof (p.cblockaddr);
                        (* *)
                        s20int4_to_buf (dcb_occupant, b, pos);
                        pos := pos + 4;
                        (* RecMode *)
                        b [pos]       := chr (dcb_RecMode_bd02);
                        pos           := pos + 1;
                        (* *)
                        s20int4_to_buf (dcb_OldOccupant_bd02, b, pos);
                        pos := pos + 4;
                        (* *)
                        b [pos]       := chr (dcb_OldRecMode_bd02);
                        pos           := pos + 1;
                        (* *)
                        IF  dcb_pFrame_bd02 <> NIL
                        THEN
                            BEGIN
                            s20int4_to_buf (dcb_pFrame_bd02^.nd_id, b, pos);
                            pos := pos + 4;
                            s20int4_to_buf (dcb_pFrame_bd02^.nd_root, b, pos);
                            END
                        ELSE
                            BEGIN
                            s20int4_to_buf (-1, b, pos);
                            pos := pos + 4;
                            s20int4_to_buf (NIL_PAGE_NO_GG00, b, pos);
                            END;
                        (*ENDIF*) 
                        pos := pos + 4;
                        (* *)
                        s20int4_to_buf (dcb_LastOwner_bd02, b, pos);
                        pos := pos + 4;
                        (* *)
                        (* *)
                        s20int4_to_buf (dcb_AccessCnt_bd02, b, pos);
                        pos := pos + 4;
                        (* *)
                        s20int4_to_buf (dcb_CollisionCnt_bd02, b, pos);
                        pos := pos + 4;
                        (* *)
                        s20int4_to_buf (dcb_UpdateCnt_bd02, b, pos);
                        pos := pos + 4;
                        (* *)
                        h_int.mapInt_sp00 := dcb_UsageCnt_bd02;
                        b [pos]       := h_int.mapC2_sp00 [1];
                        b [pos + 1]   := h_int.mapC2_sp00 [2];
                        pos           := pos + 2;
                        (* *)
                        b [pos]       := chr (ord (dcb_io_state));
                        b [pos + 1]   := chr (ord (dcb_ChangedState_bd02));
                        pos           := pos + 2;
                        (* *)
                        b [pos]       := chr (ord (dcb_tfn));
                        pos           := pos + 1;
                        (* *)
                        h_int.mapInt_sp00 := dcb_SvpSyncCnt_bd02;
                        b [pos]       := h_int.mapC2_sp00 [1];
                        b [pos + 1]   := h_int.mapC2_sp00 [2];
                        pos           := pos + 2;
                        (* *)
                        b [pos]       := chr (ord (dcb_IsSourceOfACopy_bd02));
                        pos           := pos + 1;
                        (* *)
                        b [pos]       := chr (dcb_copy_no);
                        pos           := pos + 1;
                        (* *)
                        b [pos]       := chr (dcb_dw_io_area);
                        pos           := pos + 1;
                        (* *)
                        b [pos]       := chr (ord(dcb_IsClustered_bd02));
                        pos           := pos + 1;
                        (* *)
                        b [pos]       := chr (ord (dcb_lru_rechain));
                        pos           := pos + 1;
                        (* *)
                        SAPDB_PascalForcedMove (
                              sizeof (dcb_lru_next), sizeof (b),
                              @dcb_lru_next, 1,
                              @b, pos, sizeof (dcb_lru_next));
                        pos := pos + sizeof (dcb_lru_next);
                        (* *)
                        SAPDB_PascalForcedMove (
                              sizeof (dcb_lru_prev), sizeof (b),
                              @dcb_lru_prev, 1,
                              @b, pos, sizeof (dcb_lru_prev));
                        pos := pos + sizeof (dcb_lru_prev);
                        (* *)
                        p.pid_queue_addr := dcb_lock_req_head;
                        SAPDB_PascalForcedMove (
                              sizeof (p.cblockaddr), sizeof (b),
                              @p.cblockaddr, 1,
                              @b, pos, sizeof (p.cblockaddr));
                        pos := pos + sizeof (p.cblockaddr);
                        (* *)
                        p.pid_queue_addr := dcb_lock_req_tail;
                        SAPDB_PascalForcedMove (
                              sizeof (p.cblockaddr), sizeof (b),
                              @p.cblockaddr, 1,
                              @b, pos, sizeof (p.cblockaddr));
                        pos := pos + sizeof (p.cblockaddr);
                        (* *)
                        p.pid_queue_addr := dcb_queue_occ;
                        SAPDB_PascalForcedMove (
                              sizeof (p.cblockaddr), sizeof (b),
                              @p.cblockaddr, 1,
                              @b, pos, sizeof (p.cblockaddr));
                        pos := pos + sizeof (p.cblockaddr);
                        (* *)
                        p.pid_queue_addr := dcb_queue_old_occ;
                        SAPDB_PascalForcedMove (
                              sizeof (p.cblockaddr), sizeof (b),
                              @p.cblockaddr, 1,
                              @b, pos, sizeof (p.cblockaddr));
                        pos  := pos + sizeof (p.cblockaddr);
                        (* *)
                        SAPDB_PascalForcedMove (
                              sizeof (dcb_io_next), sizeof (b),
                              @dcb_io_next, 1,
                              @b, pos, sizeof (dcb_io_next));
                        pos  := pos + sizeof (dcb_io_next);
                        (* *)
                        SAPDB_PascalForcedMove (
                              sizeof (dcb_io_prev), sizeof (b),
                              @dcb_io_prev, 1,
                              @b, pos, sizeof (dcb_io_prev));
                        pos := pos + sizeof (dcb_io_prev);
                        (* *)
                        SAPDB_PascalForcedMove (
                              sizeof (dcb_FixedNext_bd02), sizeof (b),
                              @dcb_FixedNext_bd02, 1,
                              @b, pos, sizeof (dcb_FixedNext_bd02));
                        pos := pos + sizeof (dcb_FixedNext_bd02);
                        (* *)
                        SAPDB_PascalForcedMove (
                              sizeof (dcb_VarNext_bd02), sizeof (b),
                              @dcb_VarNext_bd02, 1,
                              @b, pos, sizeof (dcb_VarNext_bd02));
                        pos  := pos + sizeof (dcb_VarNext_bd02);
                        (* *)
                        act_block     := act_block^.dcb_FixedNext_bd02;
                        END
                    (*ENDWITH*) 
                    END
                ELSE
                    BEGIN
                    h_int.mapInt_sp00 := elems_on_page;
                    b [elems_pos]     := h_int.mapC2_sp00 [1];
                    b [elems_pos + 1] := h_int.mapC2_sp00 [2];
                    b [elems_pos + 2] := chr (ord (false));
                    g01new_dump_page (hostfile, b, dump_pno, pos,
                          host_error, errtext);
                    IF  host_error = vf_ok
                    THEN
                        BEGIN
                        dump_mark := mark4_b20cblfo;
                        SAPDB_PascalForcedMove (
                              sizeof (dump_mark), sizeof (b),
                              @dump_mark, 1,
                              @b, pos, sizeof (dump_mark));
                        pos              := pos + sizeof (dump_mark);
                        h_int.mapInt_sp00:= code4_b20cblfo;
                        b[pos]           := h_int.mapC2_sp00[1];
                        b[pos + 1]       := h_int.mapC2_sp00[2];
                        pos              := pos + 2;
                        elems_pos        := pos;
                        pos              := pos + 3;
                        elems_on_page    := 0
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDWHILE*) 
            IF  (host_error = vf_ok)
            THEN
                BEGIN
                h_int.mapInt_sp00 := elems_on_page;
                b [elems_pos]     := h_int.mapC2_sp00 [1];
                b [elems_pos + 1] := h_int.mapC2_sp00 [2];
                b [elems_pos + 2] := chr (ord (true));
                g01new_dump_page (hostfile, b, dump_pno, pos,
                      host_error, errtext)
                END;
            (* *)
            (* --- TASK QUEUE ELEMS --- *)
            (* *)
            (*ENDIF*) 
            IF  host_error = vf_ok
            THEN
                BEGIN
                dump_mark := mark6_b20quele;
                SAPDB_PascalForcedMove (
                      sizeof (dump_mark), sizeof (b),
                      @dump_mark, 1, @b, pos, sizeof (dump_mark));
                pos           := pos + sizeof (dump_mark);
                h_int.mapInt_sp00 := code6_b20quele;
                b[pos]        := h_int.mapC2_sp00[1];
                b[pos + 1]    := h_int.mapC2_sp00[2];
                pos           := pos + 2;
                END;
            (*ENDIF*) 
            elems_pos      := pos;
            pos            := pos + 3;
            elems_on_page  := 0;
            i              := 0;
            act_pid_queue  := dc_pTaskQueueHead;
            queue_elem_len := sizeof (tbd02_TaskQueueItem) +
                  sizeof (tbd02_pTaskQueueItem);
            WHILE (host_error = vf_ok) AND (act_pid_queue <> NIL) DO
                BEGIN
                IF  pos + queue_elem_len <= sizeof (b)
                THEN
                    BEGIN
                    WITH act_pid_queue^ DO
                        BEGIN
                        IF  tqiTaskId_bd02 <> 0
                        THEN
                            BEGIN
                            elems_on_page := succ (elems_on_page);
                            p.pid_queue_addr := act_pid_queue;
                            SAPDB_PascalForcedMove (
                                  sizeof (p.cblockaddr), sizeof (b),
                                  @p.cblockaddr, 1, @b, pos, sizeof (p.cblockaddr));
                            pos := pos + sizeof (p.cblockaddr);
                            p.pid_queue_addr := tqiFixedNext_bd02;
                            SAPDB_PascalForcedMove (
                                  sizeof (p.cblockaddr), sizeof (b),
                                  @p.cblockaddr, 1, @b, pos, sizeof (p.cblockaddr));
                            pos := pos + sizeof (p.cblockaddr);
                            p.pid_queue_addr := tqiVarNext_bd02;
                            SAPDB_PascalForcedMove (
                                  sizeof (p.cblockaddr), sizeof (b),
                                  @p.cblockaddr, 1, @b, pos, sizeof (p.cblockaddr));
                            pos := pos + sizeof (p.cblockaddr);
                            s20int4_to_buf (tqiTaskId_bd02, b, pos);
                            pos           := pos + 4;
                            b [pos]       := chr (tqiReason_bd02);
                            pos           := pos + 1;
                            b [pos]       := chr (tqiFiller1_bd02);
                            pos           := pos + 1;
                            h_int.mapInt_sp00 := tqiFiller2_bd02;
                            b [pos]       := h_int.mapC2_sp00 [1];
                            b [pos + 1]   := h_int.mapC2_sp00 [2];
                            pos           := pos + 2;
                            END;
                        (*ENDIF*) 
                        act_pid_queue := act_pid_queue^.tqiFixedNext_bd02
                        END
                    (*ENDWITH*) 
                    END
                ELSE
                    BEGIN
                    h_int.mapInt_sp00 := elems_on_page;
                    b [elems_pos]     := h_int.mapC2_sp00 [1];
                    b [elems_pos + 1] := h_int.mapC2_sp00 [2];
                    b [elems_pos + 2] := chr (ord (false));
                    g01new_dump_page (hostfile, b, dump_pno, pos,
                          host_error, errtext);
                    IF  host_error = vf_ok
                    THEN
                        BEGIN
                        dump_mark := mark7_b20qufol;
                        SAPDB_PascalForcedMove (
                              sizeof (dump_mark), sizeof (b),
                              @dump_mark, 1, @b, pos, sizeof (dump_mark));
                        pos           := pos + sizeof (dump_mark);
                        h_int.mapInt_sp00 := code7_b20qufol;
                        b[pos]        := h_int.mapC2_sp00[1];
                        b[pos + 1]    := h_int.mapC2_sp00[2];
                        pos           := pos + 2;
                        elems_pos     := pos;
                        pos           := pos + 3;
                        elems_on_page := 0
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDWHILE*) 
            IF  (host_error = vf_ok)
            THEN
                BEGIN
                h_int.mapInt_sp00 := elems_on_page;
                b [elems_pos]     := h_int.mapC2_sp00 [1];
                b [elems_pos + 1] := h_int.mapC2_sp00 [2];
                b [elems_pos + 2] := chr (ord (true));
                g01new_dump_page (hostfile, b, dump_pno, pos, host_error, errtext)
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (* *)
    (* --- FILL REMAINING  DUMPPAGE --- *)
    (* *)
    (*ENDIF*) 
    IF  host_error = vf_ok
    THEN
        g01new_dump_page (hostfile, b, dump_pno, pos, host_error, errtext)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20DumpDataCacheFrames (
            VAR hostfile   : tgg00_VfFileref;
            VAR b          : tsp00_Page;
            VAR dump_pno   : tsp00_Int4;
            VAR pos        : integer;
            VAR host_error : tsp00_VfReturn;
            VAR errtext    : tsp00_ErrText);
 
VAR
      RegOffset : tsp00_Int4;
 
BEGIN
RegOffset := 0;
WHILE (host_error = vf_ok) AND (RegOffset <= bd20RegionCount - 1) DO
    BEGIN
    bd20_DumpDataCacheFrames (bd20DataCacheList [RegOffset],
          hostfile, b, dump_pno, pos, host_error, errtext);
    RegOffset := succ (RegOffset)
    END;
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_DumpDataCacheFrames (
            VAR DataCache   : t_datacache;
            VAR HostFile    : tgg00_VfFileref;
            VAR DumpPage    : tsp00_Page;
            VAR DumpPageNo  : tsp00_Int4;
            VAR PagePos     : integer;
            VAR HostError   : tsp00_VfReturn;
            VAR ErrorText   : tsp00_ErrText);
 
VAR
      AuxError  : tgg00_BasisError;
      pDumpPage : tsp00_VfBufaddr;
      pCBlock   : tbd02_pDataCBlock;
 
BEGIN
AuxError   := e_ok;
pDumpPage  := @DumpPage;
WITH DataCache DO
    BEGIN
    IF  (dc_SegmentSize > 0)
    THEN
        BEGIN
        (* *)
        (* --- FILL PREVIOUS DUMPPAGE --- *)
        (* *)
        IF  HostError = vf_ok
        THEN
            g01new_dump_page (HostFile, DumpPage, DumpPageNo, PagePos, HostError, ErrorText);
        (*ENDIF*) 
        IF  HostError = vf_ok
        THEN
            BEGIN
            PagePos := 1;
            pCBlock := dc_pFirstCBlock;
            WHILE (HostError = vf_ok) AND (pCBlock <> NIL) DO
                BEGIN
                WITH pCBlock^ DO
                    IF  (dcb_pFrame_bd02 <> NIL) AND (dcb_occupant <> NIL_PAGE_NO_GG00)
                    THEN
                        BEGIN
                        SAPDB_PascalForcedMove (
                              sizeof (dcb_pFrame_bd02^), sizeof (DumpPage),
                              @dcb_pFrame_bd02^, 1,
                              @DumpPage, 1, sizeof (dcb_pFrame_bd02^));
                        vfwrite (HostFile.no, pDumpPage, HostError, ErrorText)
                        END;
                    (*ENDIF*) 
                (*ENDWITH*) 
                vtracewriter_alive;
                pCBlock := pCBlock^.dcb_FixedNext_bd02
                END
            (*ENDWHILE*) 
            END;
        (* *)
        (* --- FILL REMAINING  DUMPPAGE --- *)
        (* *)
        (*ENDIF*) 
        IF  HostError = vf_ok
        THEN
            g01new_dump_page (HostFile, DumpPage, DumpPageNo, PagePos, HostError, ErrorText)
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20ExclusiveLocks (TaskId : tsp00_TaskId) : boolean;
 
VAR
      bLockFound : boolean;
      RegOffset  : tsp00_Int4;
 
BEGIN
RegOffset  := 0;
bLockFound := false;
WHILE (RegOffset <= bd20RegionCount - 1) AND NOT bLockFound DO
    BEGIN
    vbegexcl (TaskId, g08data1 + RegOffset);
    WITH bd20DataCacheList [RegOffset] DO
        BEGIN
        bLockFound := dc_TotalSvpSyncCnt > 0;
        (* PTS 1106254 TS 2000-04-04 *)
        IF  (dc_TotalSvpSyncCnt < 0) OR (dc_TotalSvpSyncCnt > 2 * g01maxuser)
        THEN
            g01abort (csp3_bd_msg, csp3_n_datacache, 'Wrong SVP sync Count    ',
                  dc_TotalSvpSyncCnt);
        (* PTS 1106254 *)
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
    vendexcl (TaskId, g08data1 + RegOffset);
    RegOffset := succ (RegOffset)
    END;
(*ENDWHILE*) 
bd20ExclusiveLocks := bLockFound
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20LoadPage (
            taskId        : tsp00_TaskId;
            pageNo        : tsp00_PageNo;
            recMode       : tgg00_RecoveryMode;
            bSetToChanged : boolean;
            bIsClustered  : boolean;
            VAR pageType  : tgg00_PageType;
            VAR trError   : tgg00_BasisError;
            VAR fileId    : tgg00_FileId;
            VAR pFrame    : tbd_nodeptr;
            VAR pCBlock   : tbd02_pDataCBlock;
            VAR pageState : tbd02_CachePageState);
 
VAR
      bUnlockFrame    : boolean;
      regOffset       : integer;
      numOldOccupants : integer;
      changedCnt      : tsp00_Int4;
      hashIndex       : tsp00_Int4;
      oldHashIndex    : tsp00_Int4;
      pPrevCBlock     : tbd02_pDataCBlock;
 
BEGIN
bUnlockFrame   := false;
pFrame     := NIL;
pCBlock    := NIL;
changedCnt := 0;
regOffset  := pageNo MOD bd20RegionCount;
hashIndex  := pageNo MOD bd20DataCacheList[ regOffset ].dc_HeadListSize;
WITH bd20DataCacheList[ regOffset ] DO
    BEGIN
    (* *)
    vbegexcl (taskId, g08data1 + regOffset);
    (* *)
    IF  NOT dc_SegmentActive
    THEN
        trError := e_shutdown;
    (*ENDIF*) 
    IF  trError = e_ok
    THEN
        BEGIN
        bd20_SearchInChain (bd20DataCacheList[ regOffset ], hashIndex,
              pageNo, recMode, pCBlock, pPrevCBlock, pageState.cpsFound_bd02);
        IF  pageState.cpsFound_bd02
        THEN
            WITH pCBlock^ DO
                BEGIN
                IF  pCBlock^.dcb_io_state = iosUserIO_ebd02
                THEN
                    BEGIN (* wait for i/o completion *)
                    pageState.cpsDirty_bd02 := true;
                    bd20_InsertOccupant (taskId, fileId, bd20DataCacheList [regOffset], pCBlock)
                    END
                ELSE
                    BEGIN
                    IF  (dc_MemoryProtection)
                        AND
                        (dcb_UsageCnt_bd02 = 0) AND (dcb_io_state = iosNone_ebd02)
                    THEN
                        BEGIN
                        bUnlockFrame := true;
                        bd20_ReadWriteAccessToFrame( dcb_pFrame_bd02 );
                        END;
                    (*ENDIF*) 
                    pageType := dcb_pFrame_bd02^.nd_pt;
                    IF  bUnlockFrame
                    THEN
                        bd20_ReadAccessToFrame( dcb_pFrame_bd02 );
                    (*ENDIF*) 
                    IF  bSetToChanged
                    THEN
                        bd20set_changed (bd20DataCacheList [ regOffset ], pCBlock, ADD_TMP_TO_IO_CHAIN_BD20, bIsClustered)
                    ELSE (* prefetch page should be held in the data cache *)
                        BEGIN
                        IF  pCBlock^.dcb_lru_rechain
                        THEN
                            bd20_PutFirstLRUList (bd20DataCacheList[ regOffset ], pCBlock)
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        ELSE (* Not bFound *)
            BEGIN
            IF  dc_pHeadList^[ hashIndex ].he_old_occ_cnt > 0
            THEN
                BEGIN (* is requested page in write io? *)
                numOldOccupants := dc_OldOccupants;
                pCBlock         := dc_pFirstLRU;
                WHILE (NOT pageState.cpsWaitForWrite_bd02) AND (pCBlock <> NIL) AND (numOldOccupants > 0) DO
                    BEGIN
                    WITH pCBlock^ DO
                        BEGIN
                        IF  (dcb_OldOccupant_bd02 = pageNo) AND (dcb_OldRecMode_bd02 = recMode)
                        THEN
                            BEGIN
                            pageState.cpsWaitForWrite_bd02 := true;
                            bd20_InsertOldOccupant( taskId, fileId, bd20DataCacheList[ regOffset ], pCBlock )
                            END
                        ELSE
                            BEGIN
                            IF  dcb_OldOccupant_bd02 <> NIL_PAGE_NO_GG00
                            THEN
                                numOldOccupants := numOldOccupants - 1;
                            (*ENDIF*) 
                            pCBlock := pCBlock^.dcb_lru_next;
                            END
                        (*ENDIF*) 
                        END
                    (*ENDWITH*) 
                    END
                (*ENDWHILE*) 
                END;
            (*ENDIF*) 
            IF  NOT pageState.cpsWaitForWrite_bd02 (* io not pending *)
            THEN
                BEGIN
                bd20_GetFrameFromLRU (taskId, trError, fileId, bd20DataCacheList[ regOffset ],
                      dc_PreventWriteIO, pCBlock, changedCnt);
                IF  trError = e_ok
                THEN
                    BEGIN
                    WITH pCBlock^ DO
                        BEGIN
                        pFrame                  := dcb_pFrame_bd02;
                        dcb_io_state            := iosUserIO_ebd02;
                        pageState.cpsDirty_bd02 := dcb_ChangedState_bd02 <> cstNone_ebd02;
                        IF  pageState.cpsDirty_bd02
                        THEN
                            BEGIN
                            bd20unset_changed (bd20DataCacheList[ regOffset ], pCBlock);
                            dcb_OldOccupant_bd02 := dcb_occupant;
                            dcb_OldRecMode_bd02  := dcb_RecMode_bd02;
                            oldHashIndex         := dcb_OldOccupant_bd02 MOD dc_HeadListSize;
                            WITH  dc_pHeadList^[ oldHashIndex ] DO
                                BEGIN
                                he_old_occ_cnt  := succ (he_old_occ_cnt);
                                dc_OldOccupants := succ (dc_OldOccupants)
                                END
                            (*ENDWITH*) 
                            END;
                        (*ENDIF*) 
                        dcb_occupant     := pageNo;
                        dcb_tfn          := fileId.fileTfn_gg00;
                        dcb_RecMode_bd02 := recMode;
                        bd20add_to_chain (bd20DataCacheList[ regOffset ], hashIndex, pCBlock);
                        (* *)
                        IF  bd20DataCacheList[ regOffset ].dc_MemoryProtection
                        THEN
                            bd20_ReadWriteAccessToFrame( dcb_pFrame_bd02 );
                        (*ENDIF*) 
                        END
                    (*ENDWITH*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  g01glob.datacachecheck
        THEN
            bd20_CheckLRUList (bd20DataCacheList[ regOffset ])
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    bd20_MaintainCacheStatistic (bd20DataCacheList[ regOffset ],
          pageState.cpsFound_bd02, fileId.fileTfn_gg00);
    (* *)
    vendexcl (taskId, g08data1 + regOffset);
    (* *)
    (* *)
    (* In this case dirty read is not dangerous *)
    (* *)
    IF  trError = e_ok
    THEN
        BEGIN
        IF  (NOT dc_SVPActive               ) AND
            (
            ((dc_IOElems + dc_clusteredIOElems) > dc_IOAreaFlushCnt ) OR
            (changedCnt > dc_LruTailFlushCnt)
            )
        THEN
            bd999FlushDataCache (taskId);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20LockPageForFree (
            TaskId               : tsp00_TaskId;
            VAR TrError          : tgg00_BasisError;
            VAR FileId           : tgg00_FileId;
            PageNo               : tsp00_PageNo;
            recMode              : tgg00_RecoveryMode;
            FirstCall            : boolean;
            VAR PageLockedToFree : boolean;
            VAR PageState        : tbd02_CachePageState;
            VAR nptr             : tbd_nodeptr;
            VAR cbptr            : tbd02_pDataCBlock);
 
VAR
      RegOffset     : integer;
      old_occs      : integer;
      ChangedCnt    : tsp00_Int4;
      HashIndex     : tsp00_Int4;
      OldHashIndex  : tsp00_Int4;
      pred          : tbd02_pDataCBlock;
      there         : tbd02_pDataCBlock;
      pSourceCBlock : tbd02_pDataCBlock;
 
BEGIN
nptr        := NIL;
cbptr       := NIL;
ChangedCnt  := 0;
RegOffset   := PageNo MOD bd20RegionCount;
HashIndex   := PageNo MOD bd20DataCacheList [RegOffset].dc_HeadListSize;
(* *)
vbegexcl (TaskId, g08data1 + RegOffset);
(* *)
WITH bd20DataCacheList [RegOffset], PageState DO
    BEGIN
    IF  NOT dc_SegmentActive
    THEN
        TrError := e_shutdown
    ELSE
        BEGIN
        bd20c_search_in_chain_incl_copy (bd20DataCacheList [RegOffset],
              HashIndex, PageNo, recMode, there, pred, cpsFound_bd02, pSourceCBlock);
        IF  cpsFound_bd02
        THEN
            BEGIN
            IF  pSourceCBlock <> NIL
            THEN
                BEGIN
                there := pSourceCBlock;
                cpsWaitForWrite_bd02 := (NOT cpsIoDone_bd02) AND
                      ((there^.dcb_UsageCnt_bd02 <> 0) OR (there^.dcb_io_state <> iosNone_ebd02));
                END
            ELSE
                cpsWaitForWrite_bd02 :=
                      (there^.dcb_io_state = iosServerIO_ebd02)
                      OR
                      ((there^.dcb_io_state = iosUserIO_ebd02) AND FirstCall);
            (*ENDIF*) 
            WITH there^ DO
                IF  cpsWaitForWrite_bd02
                THEN
                    bd20_InsertOccupant (TaskId, FileId, bd20DataCacheList [RegOffset], there)
                ELSE
                    BEGIN
                    cpsDirty_bd02 :=  (NOT cpsIoDone_bd02) AND
                          (dcb_ChangedState_bd02 = cstSvpRelevant_ebd02);
                    IF  cpsDirty_bd02
                    THEN
                        BEGIN
                        dcb_io_state := iosUserIO_ebd02;
                        nptr         := dcb_pFrame_bd02;
                        cbptr        := there
                        END
                    ELSE
                        BEGIN
                        IF  pSourceCBlock <> NIL
                        THEN
                            BEGIN
                            IF  dcb_queue_occ <> NIL
                            THEN
                                bd20_ResumeOccupant (bd20DataCacheList [RegOffset], there);
                            (*ENDIF*) 
                            bd20_FreeCBlock (bd20DataCacheList [RegOffset], HashIndex, pred, there);
                            cpsIoDone_bd02 := false
                            END
                        ELSE
                            BEGIN
                            PageLockedToFree    := true;
                            (* Mark page as io pending although no further io is made *)
                            (* to ensure that nobody gets access to this page as long *)
                            (* as free page is not completed                          *)
                            there^.dcb_io_state := iosUserIO_ebd02;
                            nptr                := dcb_pFrame_bd02;
                            cbptr               := there;
                            END
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
            (*ENDWITH*) 
            END
        ELSE (* NOT bFound *)
            BEGIN
            IF  dc_pHeadList^ [HashIndex].he_old_occ_cnt > 0
            THEN
                BEGIN
                old_occs := dc_OldOccupants;
                there    := dc_pFirstLRU;
                WHILE (NOT cpsWaitForWrite_bd02) AND (there <> NIL) AND (old_occs > 0) DO
                    BEGIN
                    WITH there^ DO
                        BEGIN
                        IF  (dcb_OldOccupant_bd02 = PageNo) AND (dcb_OldRecMode_bd02 = recMode)
                        THEN
                            BEGIN
                            cpsWaitForWrite_bd02 := true;
                            bd20_InsertOldOccupant( TaskId, FileId, bd20DataCacheList [RegOffset], there )
                            END
                        ELSE
                            BEGIN
                            IF  dcb_OldOccupant_bd02 <> NIL_PAGE_NO_GG00
                            THEN
                                old_occs := old_occs - 1;
                            (*ENDIF*) 
                            there := there^.dcb_lru_next;
                            END
                        (*ENDIF*) 
                        END
                    (*ENDWITH*) 
                    END
                (*ENDWHILE*) 
                END;
            (*ENDIF*) 
            IF  NOT cpsWaitForWrite_bd02
            THEN
                BEGIN
                bd20_GetFrameFromLRU (TaskId, TrError, FileId, bd20DataCacheList [RegOffset],
                      dc_PreventWriteIO, there, ChangedCnt);
                IF  TrError = e_ok
                THEN
                    BEGIN
                    WITH there^ DO
                        BEGIN
                        dcb_io_state  := iosUserIO_ebd02;
                        cpsDirty_bd02 := dcb_ChangedState_bd02 <> cstNone_ebd02;
                        IF  cpsDirty_bd02
                        THEN
                            BEGIN
                            bd20unset_changed (bd20DataCacheList [RegOffset], there);
                            dcb_OldOccupant_bd02 := dcb_occupant;
                            dcb_OldRecMode_bd02  := dcb_RecMode_bd02;
                            OldHashIndex         := dcb_OldOccupant_bd02 MOD dc_HeadListSize;
                            WITH  dc_pHeadList^ [OldHashIndex] DO
                                BEGIN
                                he_old_occ_cnt  := succ (he_old_occ_cnt);
                                dc_OldOccupants := succ (dc_OldOccupants)
                                END
                            (*ENDWITH*) 
                            END;
                        (*ENDIF*) 
                        dcb_occupant     := PageNo;
                        dcb_RecMode_bd02 := recMode;
                        dcb_tfn          := FileId.fileTfn_gg00;
                        bd20add_to_chain (bd20DataCacheList [RegOffset], HashIndex, there);
                        cbptr := there;
                        nptr  := dcb_pFrame_bd02;
                        END
                    (*ENDWITH*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  bd20DataCacheList [RegOffset].dc_MemoryProtection
        THEN
            BEGIN
            IF  cpsDirty_bd02 AND (TrError = e_ok)
            THEN
                bd20_ReadWriteAccessToFrame (nptr);
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  g01glob.datacachecheck
        THEN
            bd20_CheckLRUList (bd20DataCacheList [RegOffset])
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
(* *)
vendexcl (TaskId, g08data1 + RegOffset);
(* *)
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20FlushDataCache (VAR Trans : tgg00_TransContext);
 
VAR
      RegOffset     : tsp00_Int4;
      pCBlock       : tbd02_pDataCBlock;
 
BEGIN
RegOffset          := 0;
Trans.trError_gg00 := e_ok;
WHILE (Trans.trError_gg00 = e_ok) AND (RegOffset <= bd20RegionCount - 1) DO
    BEGIN
    vbegexcl (Trans.trTaskId_gg00, g08data1 + RegOffset);
    WITH Trans, bd20DataCacheList [RegOffset] DO
        BEGIN
        pCBlock := dc_pFirstCBlock;
        WHILE (trError_gg00 = e_ok) AND (pCBlock <> NIL) DO
            WITH pCBlock^  DO
                BEGIN
                IF  (dcb_occupant          <> NIL_PAGE_NO_GG00) AND
                    (dcb_ChangedState_bd02 <> cstNone_ebd02   ) AND
                    (dcb_RecMode_bd02      <> rmTemp_egg00    )
                THEN
                    BEGIN
                    IF  (dcb_IsSourceOfACopy_bd02) OR (dcb_copy_no <> 0)
                    THEN
                        g01abort (csp3_bd_msg, csp3_n_datacache,
                              'B20FLUSH: copies exist! ', dcb_occupant);
                    (*ENDIF*) 
                    dcb_io_state := iosUserIO_ebd02;
                    (* *)
                    IF  bd20DataCacheList [RegOffset].dc_MemoryProtection
                    THEN
                        bd20_ReadWriteAccessToFrame (dcb_pFrame_bd02);
                    (*ENDIF*) 
                    vendexcl (trTaskId_gg00, g08data1 + RegOffset);
                    (* *)
                    bd999WriteDataPage (Trans, dcb_pFrame_bd02);
                    (* *)
                    vbegexcl (trTaskId_gg00, g08data1 + RegOffset);
                    (* *)
                    IF  trError_gg00 = e_ok
                    THEN
                        BEGIN
                        bd20unset_changed (bd20DataCacheList [RegOffset], pCBlock);
                        dcb_io_state := iosNone_ebd02;
                        IF  dcb_queue_occ <> NIL
                        THEN
                            bd20_ResumeOccupant (bd20DataCacheList [RegOffset], pCBlock);
                        (*ENDIF*) 
                        IF  dcb_IsSourceOfACopy_bd02 AND (dcb_UsageCnt_bd02 = 0)
                        THEN
                            bd20_FreeCBlock (bd20DataCacheList [RegOffset], c_nil_hash, NIL, pCBlock);
                        (*ENDIF*) 
                        IF  bd20DataCacheList [RegOffset].dc_MemoryProtection
                        THEN
                            bd20_ReadAccessToFrame (dcb_pFrame_bd02);
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                pCBlock := pCBlock^.dcb_FixedNext_bd02
                END;
            (*ENDWITH*) 
        (*ENDWHILE*) 
        END;
    (*ENDWITH*) 
    vendexcl (Trans.trTaskId_gg00, g08data1 + RegOffset);
    RegOffset := succ (RegOffset)
    END
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20ForcedIODone (
            pCBlock : tbd02_pDataCBlock;
            TaskId  : tsp00_TaskId);
 
VAR
      RegOffset : integer;
 
BEGIN
RegOffset := pCBlock^.dcb_occupant MOD bd20RegionCount;
vbegexcl (TaskId, g08data1 + RegOffset);
bd20unset_changed (bd20DataCacheList [RegOffset], pCBlock);
vendexcl (TaskId, g08data1 + RegOffset)
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20FullestDataCacheSegment (
            TaskId       : tsp00_TaskId;
            VAR CacheNo : integer);
 
VAR
      RegOffset     : integer;
      total_io_elems : tsp00_Int4;
 
BEGIN
CacheNo        := 0;
total_io_elems := 0;
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    BEGIN
    vbegexcl (TaskId, g08data1 + RegOffset);
    IF  total_io_elems < (bd20DataCacheList [RegOffset].dc_IOElems +
        bd20DataCacheList [RegOffset].dc_clusteredIOElems)
    THEN
        BEGIN
        total_io_elems := bd20DataCacheList [RegOffset].dc_IOElems +
              bd20DataCacheList [RegOffset].dc_clusteredIOElems;
        CacheNo        := RegOffset
        END;
    (*ENDIF*) 
    vendexcl (TaskId, g08data1 + RegOffset)
    END
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20FreePage (
            TaskId              : tsp00_TaskId;
            PageNo              : tsp00_PageNo;
            recMode             : tgg00_RecoveryMode;
            VAR TrError         : tgg00_BasisError;
            VAR ExclFileLockCnt : tsp00_Int2);
 
VAR
      bFound    : boolean;
      RegOffset : integer;
      HashIndex : tsp00_Int4;
      pred      : tbd02_pDataCBlock;
      there     : tbd02_pDataCBlock;
 
BEGIN
bFound    := false;
RegOffset := PageNo MOD bd20RegionCount;
HashIndex := PageNo MOD bd20DataCacheList [RegOffset].dc_HeadListSize;
vbegexcl (TaskId, g08data1 + RegOffset);
WITH bd20DataCacheList [RegOffset] DO
    BEGIN
    IF  NOT dc_SegmentActive
    THEN
        TrError := e_shutdown
    ELSE
        BEGIN
        bd20_SearchInChain (bd20DataCacheList [RegOffset],
              HashIndex, PageNo, recMode, there, pred, bFound);
        IF  bFound
        THEN
            WITH there^ DO
                BEGIN
                IF  dcb_queue_occ <> NIL
                THEN
                    bd20_ResumeOccupant (bd20DataCacheList [RegOffset], there);
                (*ENDIF*) 
                IF  (dcb_lock_req_head <> NIL)
                THEN
                    bd20_ResumeLockRequest (TaskId, bd20DataCacheList [RegOffset], there, RESUME_ALL_BD20);
                (*ENDIF*) 
                IF  (dc_pOverflowTaskQueue <> NIL)
                THEN
                    bd20_ResumeOverflow (bd20DataCacheList [RegOffset], 1);
                (*ENDIF*) 
                IF  dcb_SvpSyncCnt_bd02 > 0
                THEN
                    BEGIN
                    dc_TotalSvpSyncCnt   := dc_TotalSvpSyncCnt - dcb_SvpSyncCnt_bd02;
                    ExclFileLockCnt      := ExclFileLockCnt - dcb_SvpSyncCnt_bd02;
                    dcb_SvpSyncCnt_bd02  := 0;
                    END;
                (*ENDIF*) 
                bd20_FreeCBlock (bd20DataCacheList [RegOffset], HashIndex, pred, there)
                END;
            (*ENDWITH*) 
        (*ENDIF*) 
        IF  g01glob.datacachecheck
        THEN
            bd20_CheckLRUList (bd20DataCacheList [RegOffset])
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
vendexcl (TaskId, g08data1 + RegOffset);
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_GenerateTaskQueue (
            VAR trError      : tgg00_BasisError;
            VAR head_ptr     : tbd02_pTaskQueueItem;
            VAR free_ptr     : tbd02_pTaskQueueItem;
            alloc_msg_all    : tsp00_C24;
            alloc_msg_elem   : tsp00_C24;
            VAR SumDynPool   : tsp00_Int4);
 
VAR
      ok            : boolean;
      i             : tsp00_Int4;
      task_cnt      : tsp00_Int4;
      p             : b20ptr;
      act_chain_ptr : tbd02_pTaskQueueItem;
 
BEGIN
task_cnt := g01maxuser + kb900AvailableServerTasks + g01maxdatawriter + 8;
vmalloc (task_cnt * sizeof (tbd02_TaskQueueItem), p.cblockaddr, ok);
(* *)
IF  alloc_msg_all <> bsp_c24
THEN
    BEGIN
    g01allocate_msg (csp3_n_dynpool, alloc_msg_all,
          task_cnt * sizeof (tbd02_TaskQueueItem));
    g01allocate_msg (csp3_n_dynpool, 'US + SV + DW +  8      :',
          task_cnt);
    g01allocate_msg (csp3_n_dynpool, alloc_msg_elem,
          sizeof (tbd02_TaskQueueItem))
    END;
(* *)
(*ENDIF*) 
IF  NOT ok
THEN
    trError := e_sysbuf_storage_exceeded
ELSE
    BEGIN
    SumDynPool    := SumDynPool + task_cnt * sizeof (tbd02_TaskQueueItem);
    act_chain_ptr := p.pid_queue_addr;
    head_ptr      := act_chain_ptr;
    free_ptr      := act_chain_ptr;
    FOR i := 1 TO task_cnt DO
        BEGIN
        IF  (i < task_cnt)
        THEN
            act_chain_ptr^.tqiFixedNext_bd02 := @p.aux_chain_addr^ [i + 1]
        ELSE
            act_chain_ptr^.tqiFixedNext_bd02 := NIL;
        (*ENDIF*) 
        act_chain_ptr^.tqiVarNext_bd02 := act_chain_ptr^.tqiFixedNext_bd02;
        act_chain_ptr^.tqiTaskId_bd02  := 0;
        act_chain_ptr^.tqiReason_bd02  := tqrNil_ebd02;
        act_chain_ptr^.tqiFiller1_bd02 := false;
        act_chain_ptr^.tqiFiller2_bd02 := 0;
        act_chain_ptr                  := act_chain_ptr^.tqiFixedNext_bd02
        END
    (*ENDFOR*) 
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20GetPage (
            TaskId              : tsp00_TaskId;
            VAR WaitContext     : tgg00_WaitContext;
            VAR TrError         : tgg00_BasisError;
            VAR ExclFileLockCnt : tsp00_Int2;
            VAR FileId          : tgg00_FileId;
            PageNo              : tsp00_PageNo;
            recMode             : tgg00_RecoveryMode;
            NodeRequest         : tbd_node_request;
            VAR nptr            : tbd_nodeptr;
            VAR cbptr           : tbd02_pDataCBlock;
            VAR PageState       : tbd02_CachePageState);
 
VAR
      RegOffset         : integer;
      old_occs          : integer;
      ChangedCnt        : tsp00_Int4;
      HashIndex         : tsp00_Int4;
      OldHashIndex      : tsp00_Int4;
      there             : tbd02_pDataCBlock;
      pred              : tbd02_pDataCBlock;
      new_cb            : tbd02_pDataCBlock;
 
BEGIN
RegOffset := PageNo MOD bd20RegionCount;
HashIndex := PageNo MOD bd20DataCacheList [RegOffset].dc_HeadListSize;
WITH PageState, bd20DataCacheList [RegOffset], FileId DO
    BEGIN
    TrError              := e_ok;
    cpsWaitForWrite_bd02 := false;
    new_cb               := NIL;
    cbptr                := NIL;
    ChangedCnt           := 0;
    (* *)
    vbegexcl (TaskId, g08data1 + RegOffset);
    (* *)
    IF  cpsSyncWithSavepoint_bd02 = synCheckPreventSync_ebd02
    THEN
        IF  dc_PreventSvpSync AND (0 = ExclFileLockCnt) (* PTS 1109891 UH 2001-04-02 *)
        THEN
            BEGIN
            bd20_SearchAndResumeLockRequest( TaskId, bd20DataCacheList [RegOffset],
                  HashIndex, PageNo, recMode ); (* PTS 1113035 TS 2002-01-31 *)
            kb560InsertToWaitForPrepare(TaskId, WaitContext);
            cpsSyncWithSavepoint_bd02 := synWait_ebd02
            END
        ELSE
            cpsSyncWithSavepoint_bd02 := synUpdateSyncCnt_ebd02;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  NOT dc_SegmentActive
    THEN
        TrError := e_shutdown;
    (*ENDIF*) 
    IF  (TrError = e_ok) AND (cpsSyncWithSavepoint_bd02 <> synWait_ebd02)
    THEN
        BEGIN
        bd20_SearchInChain (bd20DataCacheList [RegOffset],
              HashIndex, PageNo, recMode, there, pred, cpsFound_bd02);
        IF  cpsFound_bd02
        THEN
            BEGIN
            cpsDirty_bd02 := false;
            IF  (NodeRequest = nr_for_update)
                AND
                (
                (there^.dcb_io_state = iosServerIO_ebd02) OR
                (
                (there^.dcb_ChangedState_bd02 =  cstSvpRelevant_ebd02) AND
                (there^.dcb_io_state         <> iosUserIO_ebd02      ) (* see bd20LockPageForFree *)
                )
                )
            THEN
                BEGIN
                IF  (there^.dcb_UsageCnt_bd02 = 0)
                THEN
                    BEGIN
                    bd20_CopyCBlock (TaskId, FileId, bd20DataCacheList [RegOffset],
                          HashIndex, there, new_cb, TrError);
                    IF  TrError = e_ok
                    THEN
                        BEGIN
                        IF  cpsSyncWithSavepoint_bd02 = synUpdateSyncCnt_ebd02
                        THEN
                            BEGIN
                            new_cb^.dcb_SvpSyncCnt_bd02 := 1;
                            dc_TotalSvpSyncCnt          := dc_TotalSvpSyncCnt + 1;
                            ExclFileLockCnt             := ExclFileLockCnt + 1;
                            cpsSyncWithSavepoint_bd02   := synNone_ebd02;
                            END;
                        (*ENDIF*) 
                        nptr  := new_cb^.dcb_pFrame_bd02;
                        cbptr := new_cb
                        END
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  (there^.dcb_LastOwner_bd02 = TaskId    ) AND
                        (there^.dcb_io_state = iosBlocked_ebd02)
                    THEN
                        bd20_Abort (FileId, csp3_b20x1_illegal_request,
                              'Second Req  ', there^.dcb_occupant, there);
                    (*ENDIF*) 
                    IF  cpsIntendToWaitForLock_bd02
                    THEN
                        BEGIN
                        bd20_InsertLockRequest (TaskId, FileId, bd20DataCacheList [RegOffset],
                              tqrExclusiveLock_ebd02, there);
                        cpsHaveToWaitForLock_bd02 := true
                        END
                    ELSE
                        TrError := e_bd_page_collision
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            ELSE (* no control block copied *)
                WITH there^ DO
                    BEGIN
                    IF  dcb_io_state = iosUserIO_ebd02
                    THEN
                        BEGIN (* wait for i/o completion *)
                        cpsDirty_bd02 := true;
                        cbptr         := there;
                        bd20_InsertOccupant (TaskId, FileId, bd20DataCacheList [RegOffset], there)
                        END
                    ELSE
                        BEGIN
                        dcb_UsageCnt_bd02 := dcb_UsageCnt_bd02 + 1;
                        nptr              := dcb_pFrame_bd02;
                        cbptr             := there;
                        IF  NodeRequest = nr_for_update (* exclusive access *)
                        THEN
                            BEGIN
                            IF  dcb_UsageCnt_bd02 > 1
                            THEN
                                BEGIN
                                IF  (dcb_LastOwner_bd02 = TaskId    ) AND
                                    (dcb_io_state = iosBlocked_ebd02)
                                THEN
                                    bd20_Abort (FileId, csp3_b20x4_illegal_request,
                                          'Illegal Req ', dcb_occupant , there);
                                (*ENDIF*) 
                                IF  cpsIntendToWaitForLock_bd02
                                THEN
                                    BEGIN
                                    bd20_InsertLockRequest (TaskId, FileId,
                                          bd20DataCacheList [RegOffset],
                                          tqrExclusiveLock_ebd02, cbptr);
                                    cpsHaveToWaitForLock_bd02 := true
                                    END
                                ELSE
                                    TrError := e_bd_page_collision;
                                (*ENDIF*) 
                                dcb_UsageCnt_bd02 := dcb_UsageCnt_bd02 - 1;
                                nptr              := NIL
                                END
                            ELSE
                                BEGIN
                                dcb_io_state       := iosBlocked_ebd02;
                                dcb_LastOwner_bd02 := TaskId;
                                dcb_AccessCnt_bd02 := dcb_AccessCnt_bd02 + 1;
                                IF  cpsSyncWithSavepoint_bd02 = synUpdateSyncCnt_ebd02
                                THEN
                                    BEGIN
                                    dcb_SvpSyncCnt_bd02       := dcb_SvpSyncCnt_bd02 + 1;
                                    dc_TotalSvpSyncCnt        := dc_TotalSvpSyncCnt + 1;
                                    ExclFileLockCnt           := ExclFileLockCnt + 1;
                                    cpsSyncWithSavepoint_bd02 := synNone_ebd02;
                                    END
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END
                        ELSE (* shared access *)
                            BEGIN
                            IF  (dcb_io_state = iosBlocked_ebd02) AND (dcb_UsageCnt_bd02 > 1)
                            THEN
                                BEGIN
                                IF  (dcb_LastOwner_bd02 <> TaskId)
                                THEN
                                    BEGIN
                                    IF  cpsIntendToWaitForLock_bd02
                                    THEN
                                        BEGIN
                                        bd20_InsertLockRequest (TaskId, FileId,
                                              bd20DataCacheList [RegOffset],
                                              tqrShareLock_ebd02, cbptr);
                                        cpsHaveToWaitForLock_bd02 := true;
                                        END
                                    ELSE
                                        TrError := e_bd_page_collision;
                                    (*ENDIF*) 
                                    dcb_UsageCnt_bd02 := dcb_UsageCnt_bd02 - 1;
                                    nptr              := NIL
                                    END
                                (*ENDIF*) 
                                END
                            ELSE
                                BEGIN
                                IF  (dcb_lock_req_head <> NIL ) AND
                                    ((NOT cpsTaskRescheduled_bd02) OR (PageNo = fileRoot_gg00))
                                THEN
                                    BEGIN
                                    (* Reschedule reader task to avoid starvation of writer *)
                                    bd20_InsertLockRequest (TaskId, FileId,
                                          bd20DataCacheList [RegOffset],
                                          tqrShareLock_ebd02, cbptr);
                                    cpsHaveToWaitForLock_bd02 := true;
                                    cpsTaskRescheduled_bd02   := true;
                                    dcb_UsageCnt_bd02         := dcb_UsageCnt_bd02 - 1;
                                    nptr                      := NIL;
                                    END
                                ELSE
                                    BEGIN
                                    dcb_LastOwner_bd02 := dcb_LastOwner_bd02 + TaskId; (* PTS 1124301 *)
                                    dcb_AccessCnt_bd02 := dcb_AccessCnt_bd02 + 1;
                                    IF  cpsSyncWithSavepoint_bd02 = synUpdateSyncCnt_ebd02
                                    THEN
                                        BEGIN
                                        dcb_SvpSyncCnt_bd02       := dcb_SvpSyncCnt_bd02 + 1;
                                        dc_TotalSvpSyncCnt        := dc_TotalSvpSyncCnt + 1;
                                        ExclFileLockCnt           := ExclFileLockCnt + 1;
                                        cpsSyncWithSavepoint_bd02 := synNone_ebd02;
                                        bd20_AssertState( ASSERT_ID_20_BD20, dc_SegmentId,
                                              dcb_SvpSyncCnt_bd02 <= dcb_UsageCnt_bd02 );
                                        END
                                    (*ENDIF*) 
                                    END;
                                (*ENDIF*) 
                                END
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        IF  dcb_lru_rechain
                        THEN
                            bd20_PutFirstLRUList (bd20DataCacheList [RegOffset], there)
                        (*ENDIF*) 
                        END
                    (*ENDIF*) 
                    END
                (*ENDWITH*) 
            (*ENDIF*) 
            END
        ELSE (* Not bFound *)
            BEGIN
            IF  dc_pHeadList^ [HashIndex].he_old_occ_cnt > 0
            THEN
                BEGIN (* is requested page in write io *)
                old_occs := dc_OldOccupants;
                there    := dc_pFirstLRU;
                WHILE (NOT cpsWaitForWrite_bd02) AND (there <> NIL) AND (old_occs > 0) DO
                    BEGIN
                    WITH there^ DO
                        BEGIN
                        IF  (dcb_OldOccupant_bd02 = PageNo) AND (dcb_OldRecMode_bd02 = recMode)
                        THEN
                            BEGIN
                            cpsWaitForWrite_bd02 := true;
                            bd20_InsertOldOccupant( TaskId, FileId, bd20DataCacheList [RegOffset], there )
                            END
                        ELSE
                            BEGIN
                            IF  dcb_OldOccupant_bd02 <> NIL_PAGE_NO_GG00
                            THEN
                                old_occs := old_occs - 1;
                            (*ENDIF*) 
                            there := there^.dcb_lru_next;
                            END
                        (*ENDIF*) 
                        END
                    (*ENDWITH*) 
                    END
                (*ENDWHILE*) 
                END;
            (*ENDIF*) 
            IF  NOT cpsWaitForWrite_bd02
            THEN
                BEGIN
                bd20_GetFrameFromLRU (TaskId, TrError, FileId, bd20DataCacheList [RegOffset],
                      dc_PreventWriteIO, there, ChangedCnt);
                IF  TrError = e_ok
                THEN
                    BEGIN
                    WITH there^ DO
                        BEGIN
                        dcb_io_state  := iosUserIO_ebd02;
                        cpsDirty_bd02 := dcb_ChangedState_bd02 <> cstNone_ebd02;
                        IF  cpsDirty_bd02
                        THEN
                            BEGIN
                            bd20unset_changed (bd20DataCacheList [RegOffset], there);
                            dcb_OldOccupant_bd02 := dcb_occupant;
                            dcb_OldRecMode_bd02  := dcb_RecMode_bd02;
                            OldHashIndex         := dcb_OldOccupant_bd02 MOD dc_HeadListSize;
                            WITH  dc_pHeadList^ [OldHashIndex] DO
                                BEGIN
                                he_old_occ_cnt  := succ (he_old_occ_cnt);
                                dc_OldOccupants := succ (dc_OldOccupants)
                                END
                            (*ENDWITH*) 
                            END;
                        (*ENDIF*) 
                        dcb_occupant     := PageNo;
                        dcb_tfn          := fileTfn_gg00;
                        dcb_RecMode_bd02 := recMode;
                        IF  cpsSyncWithSavepoint_bd02 = synUpdateSyncCnt_ebd02
                        THEN
                            BEGIN
                            dcb_SvpSyncCnt_bd02       := 1;
                            dc_TotalSvpSyncCnt        := dc_TotalSvpSyncCnt + 1;
                            ExclFileLockCnt           := ExclFileLockCnt + 1;
                            cpsSyncWithSavepoint_bd02 := synNone_ebd02;
                            END;
                        (*ENDIF*) 
                        bd20add_to_chain (bd20DataCacheList [RegOffset], HashIndex, there);
                        cbptr := there;
                        nptr  := dcb_pFrame_bd02
                        END
                    (*ENDWITH*) 
                    END
                (*ENDIF*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  bd20DataCacheList [RegOffset].dc_MemoryProtection  AND (TrError = e_ok)
        THEN
            bd20_ReadWriteAccessToFrame (nptr);
        (*ENDIF*) 
        IF  g01glob.datacachecheck
        THEN
            bd20_CheckLRUList (bd20DataCacheList [RegOffset])
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    bd20_MaintainCacheStatistic (bd20DataCacheList [RegOffset], cpsFound_bd02, fileTfn_gg00);
    (* *)
    vendexcl (TaskId, g08data1 + RegOffset);
    (* *)
    (* PTS 1106254 TS 2000-04-04 *)
    IF  cpsSyncWithSavepoint_bd02 = synUpdateSyncCnt_ebd02
    THEN
        cpsSyncWithSavepoint_bd02 := synCheckPreventSync_ebd02;
    (* PTS 1106254 *)
    (* *)
    (* In this case dirty read is not dangerous *)
    (* *)
    (*ENDIF*) 
    IF  TrError = e_ok
    THEN
        BEGIN
        IF  (NOT dc_SVPActive               ) AND
            (
            ((dc_IOElems + dc_clusteredIOElems) > dc_IOAreaFlushCnt ) OR
            (ChangedCnt > dc_LruTailFlushCnt)
            )
        THEN
            bd999FlushDataCache (TaskId);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20GetPageIfAvailable (
            TaskId              : tsp00_TaskId;
            PageNo              : tsp00_PageNo;
            recMode             : tgg00_RecoveryMode;
            VAR cbptr           : tbd02_pDataCBlock;
            VAR found           : boolean);
 
VAR
      RegOffset         : integer;
      HashIndex         : tsp00_Int4;
      there             : tbd02_pDataCBlock;
      pred              : tbd02_pDataCBlock;
      pFreeTabHandle    : tgg00_VoidPtr;
      first_io_queue : boolean;
 
BEGIN
RegOffset := PageNo MOD bd20RegionCount;
HashIndex := PageNo MOD bd20DataCacheList [RegOffset].dc_HeadListSize;
WITH bd20DataCacheList [RegOffset] DO
    BEGIN
    cbptr                := NIL;
    (* *)
    vbegexcl (TaskId, g08data1 + RegOffset);
    (* *)
    bd20_SearchInChain (bd20DataCacheList [RegOffset],
          HashIndex, PageNo, recMode, there, pred, found);
    IF   found                                            AND
        there^.dcb_IsClustered_bd02                      AND
        (there^.dcb_ChangedState_bd02 = cstChanged_ebd02) AND
        (there^.dcb_io_state          = iosNone_ebd02)    AND
        (there^.dcb_copy_no           = 0)
    THEN
        BEGIN
        cbptr := there;
        WITH bd20DataCacheList [RegOffset], cbptr^  DO
            BEGIN
            IF  NOT dc_SVPActive
            THEN
                first_io_queue := NOT dc_IOSwitch
            ELSE
                first_io_queue :=
                      ((dcb_ChangedState_bd02 = cstSvpRelevant_ebd02) AND dc_IOSwitch)
                      OR
                      ((dcb_ChangedState_bd02 <> cstSvpRelevant_ebd02) AND NOT dc_IOSwitch);
            (*ENDIF*) 
            IF  (first_io_queue AND (dc_pClusterQueueHead1 = NIL))
                OR
                (NOT first_io_queue AND (dc_pClusterQueueHead2 = NIL))
            THEN
                bd20_Abort2 ( csp3_b20x4_check,
                      'IOCHAIN empt', dcb_occupant, cbptr);
            (*ENDIF*) 
            dcb_io_state   := iosServerIO_ebd02;
            IF  bd20DataCacheList [RegOffset].dc_MemoryProtection
            THEN
                bd20_ReadWriteAccessToFrame (dcb_pFrame_bd02);
            (*ENDIF*) 
            IF  (dcb_io_prev = NIL)
            THEN
                BEGIN
                IF  first_io_queue
                THEN
                    BEGIN
                    dc_pClusterQueueHead1 := dcb_io_next;
                    IF  dcb_io_next = NIL
                    THEN
                        dc_pClusterQueueTail1 := NIL
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    dc_pClusterQueueHead2 := dcb_io_next;
                    IF  dcb_io_next = NIL
                    THEN
                        dc_pClusterQueueTail2 := NIL
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  (dcb_io_next <> NIL)
                THEN
                    BEGIN
                    dcb_io_next^.dcb_io_prev := NIL;
                    dcb_io_next              := NIL
                    END
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                dcb_io_prev^.dcb_io_next := dcb_io_next;
                IF  (dcb_io_next <> NIL)
                THEN
                    BEGIN
                    dcb_io_next^.dcb_io_prev := dcb_io_prev;
                    dcb_io_next              := NIL
                    END
                ELSE
                    IF  first_io_queue
                    THEN
                        dc_pClusterQueueTail1 := dcb_io_prev
                    ELSE
                        dc_pClusterQueueTail2 := dcb_io_prev;
                    (*ENDIF*) 
                (*ENDIF*) 
                dcb_io_prev := NIL
                END;
            (*ENDIF*) 
            END;
        (*ENDWITH*) 
        END
    ELSE
        found := false;
    (*ENDIF*) 
    (* *)
    vendexcl (TaskId, g08data1 + RegOffset);
    (* *)
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20GetPageForIO (
            TaskId           : tsp00_TaskId;
            RegOffset        : integer;
            VAR TrError      : tgg00_BasisError;
            VAR FlushElems   : tsp00_Int2;
            VAR NodePtrList  : tbd00_NodePtrList;
            VAR CBlockList   : tbd2_data_cb_flush_list;
            VAR Completed    : boolean);
 
VAR
      MaxFlushElems : tsp00_Int2;
      pCBlock       : tbd02_pDataCBlock;
 
BEGIN
MaxFlushElems := FlushElems;
FlushElems    := 0;
(* *)
vbegexcl (TaskId, g08data1 + RegOffset);
(* *)
WITH bd20DataCacheList [RegOffset] DO
    IF  NOT dc_SegmentActive
    THEN
        TrError := e_shutdown
    ELSE
        BEGIN
&       ifdef TRACE
        IF  t01trace (bd_ioqueue)
        THEN
            bd20print_io_chain (bd20DataCacheList [RegOffset]);
&       endif
        (*ENDIF*) 
        IF  ((dc_SVPActive AND (dc_SVPElems > 0))
            OR
            (NOT dc_SVPActive AND (dc_IOElems > 0)))
        THEN
            BEGIN
            IF  (dc_SVPActive AND dc_IOSwitch        ) OR
                (NOT dc_SVPActive AND NOT dc_IOSwitch)
            THEN
                pCBlock := dc_pIOQueueTail1
            ELSE
                pCBlock := dc_pIOQueueTail2;
            (*ENDIF*) 
            WHILE (pCBlock <> NIL) AND (FlushElems < MaxFlushElems) DO
                WITH pCBlock^ DO
                    BEGIN
                    IF  (dcb_copy_no  = 0) AND (dcb_io_state = iosNone_ebd02)
                    THEN
                        BEGIN
                        dcb_io_state            := iosServerIO_ebd02;
                        FlushElems              := FlushElems + 1;
                        CBlockList [FlushElems] := pCBlock;
                        NodePtrList[FlushElems] := dcb_pFrame_bd02;
                        IF  bd20DataCacheList [RegOffset].dc_MemoryProtection
                        THEN
                            bd20_ReadWriteAccessToFrame (dcb_pFrame_bd02);
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    pCBlock  := pCBlock^.dcb_io_prev
                    END;
                (*ENDWITH*) 
            (*ENDWHILE*) 
            END
        ELSE
            IF  (dc_SVPActive AND (dc_clusteredSVPElems > 0))
            THEN
                BEGIN
                IF  (dc_SVPActive AND dc_IOSwitch )
                THEN
                    pCBlock := dc_pClusterQueueTail1
                ELSE
                    pCBlock := dc_pClusterQueueTail2;
                (*ENDIF*) 
                WHILE (pCBlock <> NIL) AND (FlushElems < MaxFlushElems) DO
                    WITH pCBlock^ DO
                        BEGIN
                        IF  (dcb_copy_no  = 0) AND (dcb_io_state = iosNone_ebd02)
                        THEN
                            BEGIN
                            dcb_io_state                  := iosServerIO_ebd02;
                            FlushElems                    := FlushElems + 1;
                            CBlockList [FlushElems]       := pCBlock;
                            NodePtrList[FlushElems]       := dcb_pFrame_bd02;
                            IF  bd20DataCacheList [RegOffset].dc_MemoryProtection
                            THEN
                                bd20_ReadWriteAccessToFrame (dcb_pFrame_bd02);
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        pCBlock  := pCBlock^.dcb_io_prev
                        END
                    (*ENDWITH*) 
                (*ENDWHILE*) 
                END;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  (dc_SVPActive) AND (dc_SVPElems = 0) AND (dc_clusteredSVPElems = 0)
        THEN
            BEGIN
            Completed := true;
            IF  g01glob.datacachecheck
            THEN
                bd20check_svp_chain (bd20DataCacheList [RegOffset])
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
(*ENDWITH*) 
(* *)
vendexcl (TaskId, g08data1 + RegOffset);
(* *)
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20GetPageFromClusterIOChain (
            TaskId       : tsp00_TaskId;
            RegOffset    : integer) : tbd02_pDataCBlock;
 
VAR
      pCBlock       : tbd02_pDataCBlock;
      found         : boolean;
 
BEGIN
pCBlock := NIL;
vbegexcl (TaskId, g08data1 + RegOffset);
WITH bd20DataCacheList [RegOffset] DO
    BEGIN
    IF  (dc_SVPActive AND dc_IOSwitch        ) OR
        (NOT dc_SVPActive AND NOT dc_IOSwitch)
    THEN
        BEGIN
        pCBlock    := dc_pClusterQueueTail1;
        found      := false;
        WHILE NOT found DO
            BEGIN
            IF  (pCBlock <> NIL) AND
                (pCBlock^.dcb_io_state = iosNone_ebd02) AND
                (pCBlock^.dcb_copy_no  = 0)
            THEN
                WITH pCBlock^ DO
                    BEGIN
                    found:=true;
                    (* dequeue *)
                    IF  (dcb_io_prev = NIL) (* first *)
                    THEN
                        BEGIN
                        dc_pClusterQueueHead1 := dcb_io_next;
                        IF  dcb_io_next = NIL
                        THEN
                            dc_pClusterQueueTail1 := NIL
                        ELSE
                            BEGIN
                            dcb_io_next^.dcb_io_prev := NIL;
                            dcb_io_next              := NIL
                            END
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        dcb_io_prev^.dcb_io_next := dcb_io_next;
                        IF  (dcb_io_next <> NIL)
                        THEN
                            BEGIN
                            dcb_io_next^.dcb_io_prev := dcb_io_prev;
                            dcb_io_next              := NIL
                            END
                        ELSE
                            dc_pClusterQueueTail1 := dcb_io_prev;
                        (*ENDIF*) 
                        dcb_io_prev := NIL
                        END;
                    (*ENDIF*) 
                    END
                (*ENDWITH*) 
            ELSE
                IF  pCBlock <> NIL
                THEN
                    pCBlock := pCBlock^.dcb_io_prev
                ELSE
                    found := true;
                (*ENDIF*) 
            (*ENDIF*) 
            END
        (*ENDWHILE*) 
        END
    ELSE
        BEGIN
        pCBlock    := dc_pClusterQueueTail2;
        found      := false;
        WHILE NOT found DO
            BEGIN
            IF  (pCBlock <> NIL) AND
                (pCBlock^.dcb_io_state = iosNone_ebd02) AND
                (pCBlock^.dcb_copy_no  = 0)
            THEN
                WITH pCBlock^ DO
                    BEGIN
                    found:=true;
                    (* dequeue *)
                    IF  (dcb_io_prev = NIL) (* first *)
                    THEN
                        BEGIN
                        dc_pClusterQueueHead2 := dcb_io_next;
                        IF  dcb_io_next = NIL
                        THEN
                            dc_pClusterQueueTail2 := NIL
                        ELSE
                            BEGIN
                            dcb_io_next^.dcb_io_prev := NIL;
                            dcb_io_next              := NIL
                            END
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        dcb_io_prev^.dcb_io_next := dcb_io_next;
                        IF  (dcb_io_next <> NIL)
                        THEN
                            BEGIN
                            dcb_io_next^.dcb_io_prev := dcb_io_prev;
                            dcb_io_next              := NIL
                            END
                        ELSE
                            dc_pClusterQueueTail2 := dcb_io_prev;
                        (*ENDIF*) 
                        dcb_io_prev := NIL
                        END;
                    (*ENDIF*) 
                    END
                (*ENDWITH*) 
            ELSE
                IF  pCBlock <> NIL
                THEN
                    pCBlock := pCBlock^.dcb_io_prev
                ELSE
                    found := true;
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDWHILE*) 
        END;
    (*ENDIF*) 
    END;
(*ENDWITH*) 
(* *)
IF  pCBlock <> NIL
THEN
    WITH pCBlock^ DO
        BEGIN
        dcb_io_state   := iosServerIO_ebd02;
        dcb_io_next    := NIL;
        dcb_io_prev    := NIL;
        IF  bd20DataCacheList [RegOffset].dc_MemoryProtection
        THEN
            bd20_ReadWriteAccessToFrame (dcb_pFrame_bd02);
        (*ENDIF*) 
        END;
    (*ENDWITH*) 
(*ENDIF*) 
vendexcl (TaskId, g08data1 + RegOffset);
bd20GetPageFromClusterIOChain := pCBlock;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20GetLeftChangedNode(
            TaskId           : tsp00_TaskId;
            pCBlock          : tbd02_pDataCBlock;
            VAR leftpCBlock  : tbd02_pDataCBlock;
            VAR found        : boolean);
 
VAR
      leftPno : tsp00_PageNo;
 
BEGIN
leftPno := pCBlock^.dcb_pFrame_bd02^.nd_left;
IF  leftPno <> NIL_PAGE_NO_GG00
THEN
    BEGIN
    bd20GetPageIfAvailable(TaskId, leftPno, pCBlock^.dcb_RecMode_bd02, leftpCBlock, found);
    END
ELSE
    BEGIN
    leftpCBlock := NIL;
    found       := false;
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20GetRightChangedNode(
            TaskId           : tsp00_TaskId;
            pCBlock          : tbd02_pDataCBlock;
            VAR rightpCBlock : tbd02_pDataCBlock;
            VAR found        : boolean);
 
VAR
      rightPno : tsp00_PageNo;
 
BEGIN
rightPno := pCBlock^.dcb_pFrame_bd02^.nd_right;
IF  rightPno <> NIL_PAGE_NO_GG00
THEN
    BEGIN
    bd20GetPageIfAvailable(TaskId, rightPno, pCBlock^.dcb_RecMode_bd02, rightpCBlock, found);
    END
ELSE
    BEGIN
    rightpCBlock := NIL;
    found       := false;
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20InitDataCache (
            TaskId          : tsp00_TaskId;
            VAR TrError     : tgg00_BasisError;
            TotalFreeFrames : tsp00_Int4;
            TotalDataPages  : tsp00_Int4);
 
CONST
      msgRestart1  = 'Begin data cache restart                ';
      msgRestart2  = 'Finish data cache restart               ';
 
VAR
      RegOffset     : integer;
      Buffers       : tsp00_Int4;
      SegmentSize   : tsp00_Int4;
      SumDynData    : tsp00_Int4;
      SumDynPool    : tsp00_Int4;
 
BEGIN
RegOffset                := 0;
SumDynPool               := 0;
SumDynData               := 0;
bd20RegionCount          := g01region_cnt (rgnData_egg00);
bd20TotalChangedPages    := 0;
bd20NextShrinkSegment    := 0;
bd20MaxUsedSize          := 0;
(* *)
IF  (bd20RegionCount < (FIRST_SEGMENT_BD20 + 1)) OR
    (bd20RegionCount > (LAST_SEGMENT_BD20 + 1))
THEN
    g01abort (csp3_b20x1_invalid_region_cnt, csp3_n_config,
          'DATA_REGIONS invalid   :', bd20RegionCount);
(* *)
(* --- INITIALIZATION OF CONTROLBLOCK DEFAULT STRUCTURE --- *)
(* *)
(*ENDIF*) 
WITH bd20CBlockInit DO
    BEGIN
    dcbi_lru_next             := NIL;
    dcbi_lru_prev             := NIL;
    dcbi_io_next              := NIL;
    dcbi_io_prev              := NIL;
    dcbi_queue_occ            := NIL;
    dcbi_queue_old_occ        := NIL;
    dcbi_lock_req_head        := NIL;
    dcbi_lock_req_tail        := NIL;
    dcbi_occupant             := NIL_PAGE_NO_GG00;
    dcbi_OldOccupant_bd02     := NIL_PAGE_NO_GG00;
    dcbi_LastOwner_bd02       := cgg_nil_pid;
    dcbi_UsageCnt_bd02        := 0;
    dcbi_tfn                  := tfnNil_egg00;
    dcbi_lru_rechain          := false;
    dcbi_ChangedState_bd02    := cstNone_ebd02;
    dcbi_io_state             := iosNone_ebd02;
    dcbi_SvpSyncCnt_bd02      := 0;
    dcbi_IsSourceOfACopy_bd02 := false;
    dcbi_copy_no              := 0;
    dcbi_dw_io_area           := false;
    dcbi_IsClustered_bd02     := false;
    dcbi_AccessCnt_bd02       := 0;
    dcbi_CollisionCnt_bd02    := 0;
    dcbi_UpdateCnt_bd02       := 0;
    dcbi_Filler3_bd02         := 0;
    dcbi_RecMode_bd02         := rmNone_egg00;
    dcbi_OldRecMode_bd02      := rmNone_egg00;
    END;
(*ENDWITH*) 
IF  TotalDataPages < TotalFreeFrames
THEN
    Buffers := TotalDataPages (* more cache pages than space on devspace is stupied *)
ELSE
    Buffers := TotalFreeFrames;
(*ENDIF*) 
SegmentSize := ( Buffers DIV bd20RegionCount );
(* *)
IF  (SegmentSize < c_rechain_frac)
THEN
    g01abort (csp3_b20x1_buffer_to_small, csp3_n_config,
          'SegmentSize < 10       :', SegmentSize);
(*ENDIF*) 
g01optextmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_datacache, msgRestart1);
g01allocate_msg (csp3_n_dynpool, 'DATA_CACHE_REGIONS     :', bd20RegionCount);
(* *)
WHILE (TrError = e_ok) AND (RegOffset <= bd20RegionCount - 1) DO
    BEGIN
    bd20_InitDataCache (TaskId, SegmentSize, RegOffset,
          SumDynPool, SumDynData, TrError);
    RegOffset := RegOffset + 1;
    END;
(*ENDWHILE*) 
g01allocate_msg (csp3_n_dynpool, 'DYNP_B20_DATACACHE     :', SumDynPool);
g01allocate_msg (csp3_n_dyndata, 'DYND_B20_DATACACHE     :', SumDynData);
IF  gg01DataCacheMemoryProtection
THEN
    bd20ProtectDataCacheFrames( true );
(*ENDIF*) 
g01optextmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_datacache, msgRestart2);
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_InitDataCache (
            TaskId         : tsp00_TaskId;
            SegmentSize    : tsp00_Int4;
            RegOffset      : integer;
            VAR SumDynPool : tsp00_Int4;
            VAR SumDynData : tsp00_Int4;
            VAR TrError    : tgg00_BasisError);
 
VAR
      ok        : boolean;
      Index     : tsp00_Int4;
      act_block : tbd02_pDataCBlock;
      p         : b20ptr;
 
BEGIN
(* *)
(* --- INITIALIZATION OF DATACACHE --- *)
(* *)
WITH bd20DataCacheList[ RegOffset ] DO
    BEGIN
    dc_pFirstCBlock       := NIL;
    dc_pLastCBlock        := NIL;
    dc_pFreeList          := NIL;
    dc_pFirstLRU          := NIL;
    dc_pLastLRU           := NIL;
    dc_pMid               := NIL;
    dc_pIOMid             := NIL;
    dc_pIOQueueHead1      := NIL;
    dc_pIOQueueHead2      := NIL;
    dc_pIOQueueTail1      := NIL;
    dc_pIOQueueTail2      := NIL;
    dc_pClusterQueueHead1      := NIL;
    dc_pClusterQueueHead2      := NIL;
    dc_pClusterQueueTail1      := NIL;
    dc_pClusterQueueTail2      := NIL;
    dc_pOverflowTaskQueue := NIL;
    dc_pSvpEndTaskQueue   := NIL;
    dc_pFrameLessCBlocks  := NIL;
    (* *)
    dc_SegmentId          := RegOffset;
    dc_SegmentSize        := 0;
    dc_SVPElems           := 0;
    dc_clusteredSVPElems  := 0;
    dc_IOElems            := 0;
    dc_clusteredIOElems   := 0;
    dc_FreeCount          := 0;
    dc_OldOccupants       := 0;
    dc_TotalSvpSyncCnt    := 0;
    dc_FrameLessCBlockCnt := 0;
    (* *)
    dc_UndoFilePageCnt    := 0;
    dc_OmsTempPageCnt     := 0;
    dc_OmsDataPageCnt     := 0;
    dc_SqlDataPageCnt     := 0;
    (* *)
    dc_UndoFileHit        := 0;
    dc_UndoFileMiss       := 0;
    dc_OmsDataHit         := 0;
    dc_OmsDataMiss        := 0;
    dc_SqlDataHit         := 0;
    dc_SqlDataMiss        := 0;
    (* *)
    dc_SVPActive          := false;
    dc_PreventSvpSync     := false;
    dc_IOSwitch           := false;
    dc_MemoryProtection   := false;
    dc_PreventWriteIO     := false;
    (* *)
    (* *)
    (* --- INITIALIZATION OF HEADLIST  --- *)
    (* *)
    dc_HeadListSize := SegmentSize * 4;
    g01next_prim_number (dc_HeadListSize);
    IF  dc_HeadListSize < c_hl_lower_lim
    THEN
        dc_HeadListSize := c_hl_lower_lim
    ELSE
        IF  dc_HeadListSize > c_hl_upper_lim
        THEN
            dc_HeadListSize := c_hl_upper_lim;
        (* *)
        (*ENDIF*) 
    (*ENDIF*) 
    vmalloc (dc_HeadListSize * sizeof (t_head_list_elem), p.cblockaddr, ok);
    (* *)
    IF  RegOffset = 0
    THEN
        BEGIN
        g01allocate_msg (csp3_n_dynpool, 'B20_DATACACHE_HEAD     :',
              dc_HeadListSize * sizeof (t_head_list_elem));
        g01allocate_msg (csp3_n_dynpool, 'DATACACHE head num item:',
              dc_HeadListSize);
        g01allocate_msg (csp3_n_dynpool, 'DATACACHE head item siz:',
              sizeof (t_head_list_elem))
        END;
    (* *)
    (*ENDIF*) 
    IF  NOT ok
    THEN
        TrError := e_sysbuf_storage_exceeded
    ELSE
        BEGIN
        dc_pHeadList := p.aux_hl_addr;
        SumDynPool   := SumDynPool + dc_HeadListSize * sizeof (t_head_list_elem);
        END;
    (*ENDIF*) 
    IF  TrError = e_ok
    THEN
        BEGIN
        FOR Index := 0 TO dc_HeadListSize - 1 DO
            WITH dc_pHeadList^ [Index] DO
                BEGIN
                he_cb          := NIL;
                he_old_occ_cnt := 0;
&               ifdef BIT64
                he_fill        := 0;
&               endif
                END
            (*ENDWITH*) 
        (*ENDFOR*) 
        END;
    (* *)
    (* --- INITIALIZATION OF TASK QUEUE --- *)
    (* *)
    (*ENDIF*) 
    IF  TrError = e_ok
    THEN
        BEGIN
        IF  RegOffset = 0
        THEN
            BEGIN
            bd20_GenerateTaskQueue (TrError, dc_pTaskQueueHead, dc_pTaskQueueFree,
                  'DATACACHE task queue   :', 'DATACACHE taskq elem   :', SumDynPool);
            g01allocate_msg (csp3_n_dynpool,  'B20_DATACACHE_TASKQ    :', SumDynPool)
            END
        ELSE
            bd20_GenerateTaskQueue (TrError, dc_pTaskQueueHead, dc_pTaskQueueFree,
                  bsp_c24, bsp_c24, SumDynPool)
        (*ENDIF*) 
        END;
    (* *)
    (* --- INITIALIZATION OF CONTROLBLOCKS AND FRAMES --- *)
    (* *)
    (*ENDIF*) 
    IF  TrError = e_ok
    THEN
        BEGIN
        IF  RegOffset = 0
        THEN
            BEGIN
            g01allocate_msg (csp3_n_dyndata, 'DATA_CACHE_PAGES       :', SegmentSize);
            g01allocate_msg (csp3_n_dynpool, 'B20_DATACACHE_CB       :',
                  SegmentSize * sizeof (tbd02_DataCBlock));
            g01allocate_msg (csp3_n_dynpool, 'DATACACHE num cblocks  :', SegmentSize);
            g01allocate_msg (csp3_n_dynpool, 'DATACACHE cblock size  :', sizeof (tbd02_DataCBlock))
            END;
        (* *)
        (* --- ALLOCATE MEMORY FOR THE CONTROL BLOCKS --- *)
        (* *)
        (*ENDIF*) 
        vmalloc (SegmentSize * sizeof (tbd02_DataCBlock), p.cblockaddr, ok);
        (* *)
        IF  NOT ok
        THEN
            TrError := e_sysbuf_storage_exceeded
        ELSE
            BEGIN
            SumDynPool      := SumDynPool + SegmentSize * sizeof (tbd02_DataCBlock);
            dc_pFirstCBlock := p.cblockaddr
            END;
        (*ENDIF*) 
        IF  TrError = e_ok
        THEN
            BEGIN
            Index     := 0;
            act_block := dc_pFirstCBlock;
            REPEAT
                WITH act_block^ DO
                    BEGIN
                    IF  Index < (SegmentSize -1)
                    THEN
                        dcb_FixedNext_bd02 := @p.aux_cb_addr^[ Index + 1 ]
                    ELSE
                        BEGIN
                        dcb_FixedNext_bd02 := NIL;
                        dc_pLastCBlock     := act_block
                        END;
                    (*ENDIF*) 
                    dcb_Init_bd02 := bd20CBlockInit;
                    IF  (Index >= (SegmentSize))
                    THEN
                        BEGIN
                        dcb_pFrame_bd02 := NIL;
                        END
                    ELSE
                        BEGIN
                        dcb_pFrame_bd02 := bd999GetFrame( TaskId );
                        SumDynData := SumDynData + 1;
                        END;
                    (*ENDIF*) 
                    bd20_FreeFrame (bd20DataCacheList[ RegOffset ], act_block);
                    act_block  := act_block^.dcb_FixedNext_bd02;
                    Index      := Index + 1;
                    END
                (*ENDWITH*) 
            UNTIL
                act_block = NIL;
            (*ENDREPEAT*) 
            dc_SegmentSize   := SegmentSize;
            dc_RecAreaSize   := (dc_SegmentSize + 1) DIV c_rechain_frac;
            IF  dc_SegmentSize < 100
            THEN
                BEGIN
                dc_IOAreaSize      := (dc_SegmentSize + 1) DIV c_p50_percent;
                dc_IOAreaFlushCnt  := trunc (((dc_SegmentSize+1)/10) * 2);
                (* NOTE: dc_LruTailFlushCnt MUST BE LESS EQUAL THAN dc_RecAreaSize! *)
                dc_LruTailFlushCnt := trunc ((dc_RecAreaSize+1)/2);
                END
            ELSE
                BEGIN
                dc_IOAreaSize      := trunc (((dc_SegmentSize + 1) / 100)* g01dw_io_area_size);
                dc_IOAreaFlushCnt  := trunc (((dc_SegmentSize+1)/100) * g01dw_io_area_flush);
                dc_LruTailFlushCnt := trunc (((dc_RecAreaSize+1)/100) * g01dw_lru_tail_flush);
                END
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    dc_SegmentActive := (TrError = e_ok)
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20IOElemCount (
            TaskId    : tsp00_TaskId;
            RegOffset : integer) : tsp00_Int4;
 
BEGIN
vbegexcl (TaskId, g08data1 + RegOffset);
bd20IOElemCount := bd20DataCacheList [RegOffset].dc_IOElems +
      bd20DataCacheList [RegOffset].dc_clusteredIOElems;
vendexcl (TaskId, g08data1 + RegOffset);
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20ResetIOState (
            TaskId         : tsp00_TaskId;
            RegOffset      : integer;
            FlushElems     : tsp00_Int2;
            VAR CBlockList : tbd2_data_cb_flush_list);
 
VAR
      Index : tsp00_Int4;
 
BEGIN
(* *)
vbegexcl (TaskId, g08data1 + RegOffset);
(* *)
WITH bd20DataCacheList [RegOffset] DO
    IF  dc_SegmentActive
    THEN
        BEGIN
        FOR Index := 1 TO FlushElems DO
            BEGIN
            IF  CBlockList [Index] = NIL
            THEN
                g01abort (csp3_b20x1_nil_cbptr, csp3_n_datacache,
                      'B20IRES: NIL addr       ', 0);
            (*ENDIF*) 
            WITH CBlockList[ Index ]^ DO
                BEGIN
                IF  dcb_io_state = iosServerIO_ebd02
                THEN
                    BEGIN
                    dcb_io_state := iosNone_ebd02;
                    IF  dcb_IsClustered_bd02 AND
                        (dcb_io_next    = NIL    ) AND
                        (dcb_io_prev    = NIL    ) AND
                        (dc_pClusterQueueHead1 <> CBlockList [Index]) AND
                        (dc_pClusterQueueHead2 <> CBlockList [Index]) AND
                        (dcb_RecMode_bd02 <>  rmTemp_egg00)  (* do not count temp pages (from LRU) *)
                    THEN
                        BEGIN
                        dc_clusteredIOElems := pred(dc_clusteredIOElems);
                        IF  dcb_ChangedState_bd02 = cstSvpRelevant_ebd02
                        THEN
                            dc_clusteredSVPElems := pred (dc_clusteredSVPElems);
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  dcb_queue_occ <> NIL
                    THEN
                        bd20_ResumeOccupant (bd20DataCacheList [RegOffset], CBlockList [Index]);
                    (*ENDIF*) 
                    END;
&               ifdef TRACE
                (*ENDIF*) 
                IF  t01trace (bd_ioqueue)
                THEN
                    BEGIN
                    t01int4 (bd_ioqueue, '==> page no ', dcb_occupant);
                    t01int4 (bd_ioqueue, '==> dcb_tfn ', ord(dcb_tfn))
                    END;
&               endif
                (*ENDIF*) 
                bd20unset_changed (bd20DataCacheList [RegOffset],CBlockList [Index]);
                IF  dc_IOElems < 0
                THEN
                    bd20_Abort2 ( csp3_b20x5_check,
                          'IOElems empt', dcb_occupant, CBlockList [Index]);
                (*ENDIF*) 
                IF  dc_clusteredIOElems < 0
                THEN
                    bd20_Abort2 ( csp3_b20x6_check,
                          'clIOElemsemt', dcb_occupant, CBlockList [Index]);
                (*ENDIF*) 
                IF  dcb_IsSourceOfACopy_bd02 AND (dcb_UsageCnt_bd02 = 0)
                THEN
                    bd20_FreeCBlock (bd20DataCacheList [RegOffset],
                          c_nil_hash, NIL, CBlockList [Index]);
                (*ENDIF*) 
                IF  bd20DataCacheList [RegOffset].dc_MemoryProtection
                THEN
                    BEGIN
                    IF  dcb_UsageCnt_bd02 = 0
                    THEN
                        bd20_ReadAccessToFrame (dcb_pFrame_bd02)
                    ELSE
                        bd20_ReadWriteAccessToFrame (dcb_pFrame_bd02)
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
&           ifdef TRACE
            IF  t01trace (bd_ioqueue)
            THEN
                bd20print_io_chain (bd20DataCacheList [RegOffset]);
            (*ENDIF*) 
            IF  g01glob.datacachecheck
            THEN
                bd20check_io_chain (bd20DataCacheList [RegOffset]);
&           endif
            (*ENDIF*) 
            END;
        (*ENDFOR*) 
        IF  (dc_pOverflowTaskQueue <> NIL)
        THEN
            bd20_ResumeOverflow (bd20DataCacheList [RegOffset], FlushElems);
        (*ENDIF*) 
        END;
    (* *)
    (*ENDIF*) 
(*ENDWITH*) 
vendexcl (TaskId, g08data1 + RegOffset);
(* *)
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20IsPageChanged (
            pCBlock : tbd02_pDataCBlock) : boolean;
 
BEGIN
bd20IsPageChanged := (pCBlock^.dcb_ChangedState_bd02 = cstChanged_ebd02) OR
      (pCBlock^.dcb_ChangedState_bd02 = cstSvpRelevant_ebd02);
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20IsPageExclusiveLocked (
            pCBlock : tbd02_pDataCBlock) : boolean;
 
BEGIN
bd20IsPageExclusiveLocked := pCBlock^.dcb_io_state = iosBlocked_ebd02;
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20IsPageShareLocked (
            pCBlock : tbd02_pDataCBlock) : boolean;
 
BEGIN
bd20IsPageShareLocked :=
      (pCBlock^.dcb_io_state = iosNone_ebd02) AND (pCBlock^.dcb_UsageCnt_bd02 > 0)
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20GetPageUsageCount (
            pCBlock : tbd02_pDataCBlock) : tsp00_Int2;
 
BEGIN
bd20GetPageUsageCount := pCBlock^.dcb_UsageCnt_bd02;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20NewPage (
            TaskId        : tsp00_TaskId;
            VAR TrError   : tgg00_BasisError;
            VAR FileId    : tgg00_FileId;
            PageNo        : tsp00_PageNo;
            recMode       : tgg00_RecoveryMode;
            VAR nptr      : tbd_nodeptr;
            VAR cbptr     : tbd02_pDataCBlock;
            VAR PageState : tbd02_CachePageState);
 
VAR
      bFound        : boolean;
      RegOffset     : integer;
      ChangedCnt    : tsp00_Int4;
      HashIndex     : tsp00_Int4;
      OldHashIndex  : tsp00_Int4;
      there         : tbd02_pDataCBlock;
      pred          : tbd02_pDataCBlock;
 
BEGIN
ChangedCnt := 0;
RegOffset  := PageNo MOD bd20RegionCount;
HashIndex  := PageNo MOD bd20DataCacheList [RegOffset].dc_HeadListSize;
WITH bd20DataCacheList [RegOffset], PageState DO
    BEGIN
    (* *)
    vbegexcl (TaskId, g08data1 + RegOffset);
    (* *)
    IF  NOT dc_SegmentActive
    THEN
        TrError := e_shutdown;
    (*ENDIF*) 
    IF  TrError = e_ok
    THEN
        BEGIN
        bd20_SearchInChain (bd20DataCacheList [RegOffset], HashIndex, PageNo,
              recMode, there, pred, bFound);
        IF  bFound
        THEN
            IF  there^.dcb_io_state = iosUserIO_ebd02
            THEN
                BEGIN
                cpsWaitForWrite_bd02 := true;
                cbptr                := there;
                bd20_InsertOccupant (TaskId, FileId, bd20DataCacheList [RegOffset], there)
                END
            ELSE
                bd20_Abort (FileId, csp3_b20x1_pno_found, 'NewPno Found', PageNo, there)
            (*ENDIF*) 
        ELSE (* not bFound *)
            BEGIN
            there := NIL;
            bd20_GetFrameFromLRU (TaskId, TrError, FileId, bd20DataCacheList [RegOffset],
                  dc_PreventWriteIO, there, ChangedCnt);
            IF  TrError = e_ok
            THEN
                BEGIN
                WITH there^ DO
                    BEGIN
                    cpsDirty_bd02 := dcb_ChangedState_bd02 <> cstNone_ebd02;
                    IF  cpsDirty_bd02
                    THEN
                        BEGIN
                        bd20unset_changed (bd20DataCacheList [RegOffset], there);
                        dcb_io_state         := iosUserIO_ebd02;
                        dcb_OldOccupant_bd02 := dcb_occupant;
                        dcb_OldRecMode_bd02  := dcb_RecMode_bd02;
                        OldHashIndex         := dcb_OldOccupant_bd02 MOD dc_HeadListSize;
                        WITH  dc_pHeadList^ [OldHashIndex] DO
                            BEGIN
                            he_old_occ_cnt  := he_old_occ_cnt  + 1;
                            dc_OldOccupants := dc_OldOccupants + 1;
                            END
                        (*ENDWITH*) 
                        END
                    ELSE
                        BEGIN
                        dcb_UsageCnt_bd02  := 1;
                        dcb_io_state       := iosBlocked_ebd02;
                        dcb_LastOwner_bd02 := TaskId
                        END;
                    (*ENDIF*) 
                    dcb_occupant      := PageNo;
                    dcb_RecMode_bd02  := recMode;
                    dcb_tfn           := FileId.fileTfn_gg00;
                    (* dcb_UsageCnt_bd02 := 1; PTS 1124301 *)
                    bd20add_to_chain (bd20DataCacheList [RegOffset], HashIndex, there);
                    cbptr := there;
                    nptr  := dcb_pFrame_bd02;
                    IF  bd20DataCacheList [RegOffset].dc_MemoryProtection
                    THEN
                        bd20_ReadWriteAccessToFrame (nptr);
                    (*ENDIF*) 
                    END
                (*ENDWITH*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  g01glob.datacachecheck
        THEN
            bd20_CheckLRUList (bd20DataCacheList [RegOffset])
        (*ENDIF*) 
        END;
    (* *)
    (*ENDIF*) 
    vendexcl (TaskId, g08data1 + RegOffset);
    (* *)
    (* In this case dirty read is not dangerous *)
    (* *)
    IF  (TrError = e_ok                 ) AND
        (NOT dc_SVPActive               ) AND
        (
        ((dc_IOElems + dc_clusteredIOElems) > dc_IOAreaFlushCnt ) OR
        (ChangedCnt > dc_LruTailFlushCnt)
        )
    THEN
        bd999FlushDataCache (TaskId);
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20GetTempFromLRURechain (
            TaskId           : tsp00_TaskId;
            RegOffset        : integer;
            VAR TrError      : tgg00_BasisError;
            VAR FlushElems   : tsp00_Int2;
            VAR NodePtrList  : tbd00_NodePtrList;
            VAR CBlockList   : tbd2_data_cb_flush_list);
 
VAR
      bStop         : boolean;
      MaxFlushElems : tsp00_Int2;
      pCBlock       : tbd02_pDataCBlock;
 
BEGIN
MaxFlushElems := FlushElems;
FlushElems    := 0;
bStop         := false;
(* *)
vbegexcl (TaskId, g08data1 + RegOffset);
(* *)
WITH bd20DataCacheList [RegOffset] DO
    BEGIN
    IF  NOT dc_SegmentActive
    THEN
        TrError := e_shutdown
    ELSE
        BEGIN
        pCBlock := dc_pLastLRU;
        (* *)
        WHILE (pCBlock   <> NIL          ) AND
              (FlushElems < MaxFlushElems) AND
              NOT bStop                    DO
            WITH pCBlock^ DO
                BEGIN
                IF  (dcb_ChangedState_bd02 <> cstNone_ebd02) AND
                    (dcb_copy_no          =  0             ) AND
                    (dcb_RecMode_bd02     =  rmTemp_egg00  ) AND
                    (dcb_io_state         =  iosNone_ebd02 )
                THEN
                    BEGIN
                    dcb_io_state             := iosServerIO_ebd02;
                    FlushElems               := FlushElems + 1;
                    CBlockList [FlushElems]  := pCBlock;
                    NodePtrList [FlushElems] := dcb_pFrame_bd02;
                    IF  bd20DataCacheList [RegOffset].dc_MemoryProtection
                    THEN
                        bd20_ReadWriteAccessToFrame (dcb_pFrame_bd02);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                pCBlock := pCBlock^.dcb_lru_prev;
                IF  NOT pCBlock^.dcb_lru_rechain
                THEN
                    bStop := true
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        (*ENDWHILE*) 
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
(* *)
vendexcl (TaskId, g08data1 + RegOffset);
(* *)
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20ProtectDataCacheFrames (
            Enable : boolean);
 
CONST
      msgEnable  = 'ENABLE MEMORY PROTECTION                ';
      msgDisable = 'DISABLE MEMORY PROTECTION               ';
 
VAR
      TaskId    : tsp00_TaskId;
      RegOffset : tsp00_Int4;
      pCBlock   : tbd02_pDataCBlock;
 
BEGIN
vgetpid (TaskId);
IF  Enable
THEN
    g01optextmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_datacache, msgEnable)
ELSE
    g01optextmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_datacache, msgDisable);
(*ENDIF*) 
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    BEGIN
    (* *)
    vbegexcl (TaskId, g08data1 + RegOffset);
    (* *)
    WITH bd20DataCacheList [RegOffset] DO
        BEGIN
        pCBlock := dc_pFirstCBlock;
        WHILE  pCBlock <> NIL DO
            WITH pCBlock^ DO
                BEGIN
                IF  dcb_pFrame_bd02 <> NIL
                THEN
                    BEGIN
                    IF  (dcb_UsageCnt_bd02 = 0) AND (dcb_io_state = iosNone_ebd02) AND Enable
                    THEN
                        bd20_ReadAccessToFrame (dcb_pFrame_bd02)
                    ELSE
                        bd20_ReadWriteAccessToFrame (dcb_pFrame_bd02);
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                pCBlock := pCBlock^.dcb_FixedNext_bd02
                END;
            (*ENDWITH*) 
        (*ENDWHILE*) 
        dc_MemoryProtection := Enable;
        END;
    (*ENDWITH*) 
    (* *)
    vendexcl (TaskId, g08data1 + RegOffset);
    (* *)
    END
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20PrepareDropDataVolume (
            taskId   : tsp00_TaskId;
            pMsgList : tgg00_VoidPtr ) : boolean;
 
CONST
      MAX_RETRIES_BD20 = 10;
      (* *)
      msgDropVolume1 = 'Set data volume to read only although   ';
      msgDropVolume2 = 'pending io request exist                ';
 
VAR
      bSetReadOnlyDone : boolean;
      bPendingIO       : boolean;
      retryCnt         : tsp00_Int4;
      regOffset        : tsp00_Int4;
      pCBlock          : tbd02_pDataCBlock;
 
BEGIN
(* *)
(* Precondition: all pager tasks are stopped *)
(* *)
bd20_SetPreventWriteIO( taskId, PREVENT_WRITE_IO_BD20 );
(* *)
retryCnt         := 0;
bSetReadOnlyDone := false;
REPEAT
    (* *)
    FOR regOffset := FIRST_SEGMENT_BD20 TO bd20RegionCount - 1 DO
        vbegexcl( taskId, g08data1 + regOffset );
    (*ENDFOR*) 
    (* *)
    bPendingIO := false;
    regOffset  := FIRST_SEGMENT_BD20;
    WHILE( regOffset < bd20RegionCount - 1 ) AND ( NOT bPendingIO ) DO
        WITH bd20DataCacheList[ regOffset ] DO
            BEGIN
            pCBlock := dc_pFirstLRU;
            WHILE(( pCBlock <> NIL ) AND ( NOT bPendingIO )) DO
                BEGIN
                bPendingIO  := ( pCBlock^.dcb_io_state = iosUserIO_ebd02 );
                pCBlock     := pCBlock^.dcb_lru_next;
                END;
            (*ENDWHILE*) 
            regOffset := regOffset + 1;
            END;
        (*ENDWITH*) 
    (*ENDWHILE*) 
    IF  (( NOT bPendingIO ) OR ( retryCnt = MAX_RETRIES_BD20 ))
    THEN
        BEGIN
        IF  bPendingIO
        THEN
            BEGIN
            g01optextmsg( sp3p_knldiag, sp3m_warning, csp3_bd_msg, csp3_n_datacache, msgDropVolume1 );
            g01optextmsg( sp3p_knldiag, sp3m_warning, csp3_bd_msg, csp3_n_datacache, msgDropVolume2 )
            END;
        (*ENDIF*) 
        bSetReadOnlyDone := bd999PrepareDropDataVolume( taskId, pMsgList );
        END;
    (* *)
    (*ENDIF*) 
    FOR regOffset := FIRST_SEGMENT_BD20 TO bd20RegionCount - 1 DO
        vendexcl( taskId, g08data1 + regOffset );
    (*ENDFOR*) 
    (* *)
    IF  bPendingIO
    THEN
        BEGIN
        (* collision with not waiting user forced io, e.g. bd20LockPageForFree *)
        retryCnt := retryCnt + 1;
        vsleep( taskId, 1 )
        END
    (*ENDIF*) 
UNTIL
    (( retryCnt > MAX_RETRIES_BD20 ) OR ( NOT bPendingIO ));
(*ENDREPEAT*) 
(* *)
bd20_SetPreventWriteIO( taskId, NOT PREVENT_WRITE_IO_BD20 );
(* *)
bd20PrepareDropDataVolume := bSetReadOnlyDone;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20PrepareSavepoint (
            TaskId           : tsp00_TaskId;
            ConverterVersion : tgg00_ConverterVersion);
 
VAR
      RegOffset : tsp00_Int4;
 
BEGIN
g01opmsg (sp3p_knldiag, sp3m_info, csp3_b20_prepare_savepoint,
      csp3_n_savepoint, 'B20PREPARE_SVP          ', ConverterVersion);
(* *)
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    vbegexcl (TaskId, g08data1 + RegOffset);
(*ENDFOR*) 
(* *)
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    bd20prepare_savepoint (RegOffset);
(*ENDFOR*) 
(* *)
FOR RegOffset := bd20RegionCount - 1 DOWNTO 0 DO
    vendexcl (TaskId, g08data1 + RegOffset);
(*ENDFOR*) 
(* *)
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20prepare_savepoint (RegOffset : tsp00_Int4);
 
CONST
      MSG_NOT_ACTIVE              = 'Is not active           ';
      MSG_ELEMS_EXIST             = 'SVP Elems exist         ';
      MSG_CLUSTERED_ELEMS_EXIST   = 'Clustrd SVP Elems exist ';
      MSG_QUEUE_1_EMPTY           = 'I/O QUEUE1 is not empty ';
      MSG_QUEUE_2_EMPTY           = 'I/O QUEUE2 is not empty ';
      MSG_CLUSTERED_QUEUE_1_EMPTY = 'CLU I/O Q1 is not empty ';
      MSG_CLUSTERED_QUEUE_2_EMPTY = 'CLU I/O Q2 is not empty ';
      MSG_ITEM_UNCHANGED          = 'IOQueue Item not changed';
 
VAR
      pCBlock : tbd02_pDataCBlock;
 
BEGIN
WITH bd20DataCacheList[ RegOffset ] DO
    BEGIN
    IF  NOT dc_SegmentActive
    THEN
        g01abort (csp3_bd_msg, csp3_n_datacache, MSG_NOT_ACTIVE, 0);
    (*ENDIF*) 
    IF  0 <> dc_SVPElems
    THEN
        g01abort (BD20_SVP_ITEMS_EXIST_SP03, csp3_n_datacache, MSG_ELEMS_EXIST, dc_SVPElems);
    (*ENDIF*) 
    IF  0 <> dc_clusteredSVPElems
    THEN
        g01abort (BD20_SVP_ITEMS_EXIST_SP03, csp3_n_datacache, MSG_CLUSTERED_ELEMS_EXIST,
              dc_clusteredSVPElems);
    (*ENDIF*) 
    dc_SVPActive         := true;
    dc_IOSwitch          := NOT dc_IOSwitch;
    dc_SVPElems          := 0;
    dc_clusteredSVPElems := 0;
    IF  dc_IOSwitch
    THEN
        BEGIN
        pCBlock := dc_pClusterQueueHead1;
        IF  (NIL <> dc_pClusterQueueHead2) OR (NIL <> dc_pClusterQueueTail2)
        THEN
            g01abort (BD20_IO_QUEUE_IS_NOT_EMPTY_SP03, csp3_n_datacache, MSG_CLUSTERED_QUEUE_2_EMPTY, 0);
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        pCBlock := dc_pClusterQueueHead2;
        IF  (NIL <> dc_pClusterQueueHead1) OR (NIL <> dc_pClusterQueueTail1)
        THEN
            g01abort (BD20_IO_QUEUE_IS_NOT_EMPTY_SP03, csp3_n_datacache, MSG_CLUSTERED_QUEUE_1_EMPTY, 0 );
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    WHILE (pCBlock <> NIL) DO
        BEGIN
        IF  pCBlock^.dcb_ChangedState_bd02 <> cstChanged_ebd02
        THEN
            g01abort (BD20_ITEM_NOT_CHANGED_SP03, csp3_n_datacache, MSG_ITEM_UNCHANGED, 0);
        (*ENDIF*) 
        dc_clusteredSVPElems           := succ (dc_clusteredSVPElems);
        pCBlock^.dcb_ChangedState_bd02 := cstSvpRelevant_ebd02;
        pCBlock                        := pCBlock^.dcb_io_next
        END;
    (*ENDWHILE*) 
    IF  dc_IOSwitch
    THEN
        BEGIN
        pCBlock := dc_pIOQueueHead1;
        IF  (NIL <> dc_pIOQueueHead2) OR (NIL <> dc_pIOQueueTail2)
        THEN
            g01abort (BD20_IO_QUEUE_IS_NOT_EMPTY_SP03, csp3_n_datacache, MSG_QUEUE_2_EMPTY, 0);
        (*ENDIF*) 
        END
    ELSE
        BEGIN
        pCBlock := dc_pIOQueueHead2;
        IF  (NIL <> dc_pIOQueueHead1) OR (NIL <> dc_pIOQueueTail1)
        THEN
            g01abort (BD20_IO_QUEUE_IS_NOT_EMPTY_SP03, csp3_n_datacache, MSG_QUEUE_1_EMPTY, 0 );
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    WHILE (pCBlock <> NIL) DO
        BEGIN
        IF  pCBlock^.dcb_ChangedState_bd02 <> cstChanged_ebd02
        THEN
            g01abort (BD20_ITEM_NOT_CHANGED_SP03, csp3_n_datacache, MSG_ITEM_UNCHANGED, 0);
        (*ENDIF*) 
        dc_SVPElems                    := succ (dc_SVPElems);
        pCBlock^.dcb_ChangedState_bd02 := cstSvpRelevant_ebd02;
        pCBlock                        := pCBlock^.dcb_io_next
        END;
    (*ENDWHILE*) 
    IF  g01glob.datacachecheck
    THEN
        bd20check_svp_chain (bd20DataCacheList[ RegOffset ]);
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20RReleasePage (
            TaskId              : tsp00_TaskId;
            VAR ExclFileLockCnt : tsp00_Int2;
            VAR FileId          : tgg00_FileId;
            VAR nptr            : tbd_nodeptr;
            VAR cbptr           : tbd02_pDataCBlock;
            pageNo              : tsp00_PageNo;
            recMode             : tgg00_RecoveryMode;
            LruInfo             : tbd_lru_info;
            bDoReduceSyncCnt    : boolean);
 
VAR
      bFound     : boolean;
      RegOffset  : integer;
      HashIndex  : tsp00_Int4;
      there      : tbd02_pDataCBlock;
      pred       : tbd02_pDataCBlock;
 
BEGIN
RegOffset := pageNo MOD bd20RegionCount;
IF  cbptr <> NIL
THEN
    HashIndex := c_nil_hash
ELSE
    HashIndex := pageNo MOD bd20DataCacheList [RegOffset].dc_HeadListSize;
(*ENDIF*) 
(* *)
vbegexcl (TaskId, g08data1 + RegOffset);
(* *)
IF  bd20DataCacheList [RegOffset].dc_SegmentActive
THEN
    BEGIN
    IF  cbptr = NIL
    THEN
        bd20_SearchInChain (bd20DataCacheList [RegOffset], HashIndex,
              pageNo, recMode, there, pred, bFound)
    ELSE
        BEGIN
        IF  cbptr^.dcb_occupant <> pageNo
        THEN
            bd20_Abort (FileId, csp3_b20x5_pno_not_found,
                  'Occup <> Id ', pageNo, cbptr);
        (*ENDIF*) 
        there  := cbptr;
        bFound := true;
        pred   := NIL
        END;
    (*ENDIF*) 
    IF  bFound
    THEN
        WITH bd20DataCacheList [RegOffset], there^ DO
            BEGIN
            IF  dcb_UsageCnt_bd02 = 0
            THEN
                bd20_Abort (FileId, csp3_b20x1_usage_is_zero,
                      'Usage = 0   ', there^.dcb_occupant, there);
            (* *)
            (*ENDIF*) 
            dcb_UsageCnt_bd02 := dcb_UsageCnt_bd02 - 1;
            IF  bDoReduceSyncCnt
            THEN
                BEGIN
                bd20_AssertState( ASSERT_ID_21_BD20, dc_SegmentId, dcb_SvpSyncCnt_bd02 > 0 );
                dc_TotalSvpSyncCnt       := dc_TotalSvpSyncCnt - 1;
                ExclFileLockCnt          := ExclFileLockCnt - 1;
                dcb_SvpSyncCnt_bd02      := dcb_SvpSyncCnt_bd02 - 1;
                END;
            (*ENDIF*) 
            IF  dcb_io_state = iosNone_ebd02
            THEN
                dcb_LastOwner_bd02 := dcb_LastOwner_bd02 - TaskId; (* PTS 1124301 *)
            (* *)
            (*ENDIF*) 
            IF  dcb_UsageCnt_bd02 = 0
            THEN
                BEGIN
                IF  (dcb_lock_req_head <> NIL)
                THEN
                    bd20_ResumeLockRequest (TaskId, bd20DataCacheList [RegOffset],
                          there, NOT RESUME_ALL_BD20);
                (*ENDIF*) 
                IF  (dc_pOverflowTaskQueue <> NIL)
                THEN
                    bd20_ResumeOverflow (bd20DataCacheList [RegOffset], 1);
                (*ENDIF*) 
                IF  dcb_SvpSyncCnt_bd02 > 0
                THEN
                    BEGIN
                    dc_TotalSvpSyncCnt       := dc_TotalSvpSyncCnt - 1;
                    ExclFileLockCnt          := ExclFileLockCnt - 1;
                    bd20_AssertState( ASSERT_ID_19_BD20, dc_SegmentId, dcb_SvpSyncCnt_bd02 = 1 );
                    dcb_SvpSyncCnt_bd02      := 0;
                    END;
                (*ENDIF*) 
                dcb_LastOwner_bd02 := cgg_nil_pid; (* PTS 1124301 *)
                IF  dcb_io_state = iosBlocked_ebd02
                THEN
                    dcb_io_state := iosNone_ebd02;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  (dcb_IsSourceOfACopy_bd02                     ) AND
                (dcb_UsageCnt_bd02 = 0                        ) AND
                (dcb_io_state = iosNone_ebd02                 ) AND
                (dcb_ChangedState_bd02 <> cstSvpRelevant_ebd02)
            THEN (* -> COULD NOT HAPPEN ? *)
                bd20_FreeCBlock (bd20DataCacheList [RegOffset], HashIndex, pred, there)
            ELSE
                BEGIN
                IF  (g01default_lru               ) AND
                    (LruInfo <> lru_normal        ) AND
                    (dcb_UsageCnt_bd02 = 0        ) AND
                    (there <> dc_pLastLRU         ) AND
                    (dc_FreeCount < dc_RecAreaSize)
                THEN
                    IF  LruInfo = lru_last
                    THEN
                        bd20_PutLastLRUList (bd20DataCacheList [RegOffset], there)
                    ELSE
                        bd20_PutMidLRUList (bd20DataCacheList [RegOffset], there)
                    (*ENDIF*) 
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  bd20DataCacheList [RegOffset].dc_MemoryProtection
            THEN
                BEGIN
                IF  (dcb_UsageCnt_bd02 = 0) AND (dcb_io_state = iosNone_ebd02)
                THEN
                    bd20_ReadAccessToFrame (nptr);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  g01glob.datacachecheck
            THEN
                bd20_CheckLRUList (bd20DataCacheList [RegOffset])
            (*ENDIF*) 
            END
        (*ENDWITH*) 
    (*ENDIF*) 
    END;
(* *)
(*ENDIF*) 
vendexcl (TaskId, g08data1 + RegOffset);
(* *)
nptr  := NIL;
cbptr := NIL
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20WReleasePage (
            TaskId              : tsp00_TaskId;
            VAR ExclFileLockCnt : tsp00_Int2;
            VAR FileId          : tgg00_FileId;
            VAR nptr            : tbd_nodeptr;
            VAR cbptr           : tbd02_pDataCBlock;
            pageNo              : tsp00_PageNo;
            recMode             : tgg00_RecoveryMode;
            isClustered         : boolean;
            VAR IoState         : tbd02_SwapState);
 
VAR
      bFound    : boolean;
      RegOffset : integer;
      HashIndex : tsp00_Int4;
      pred      : tbd02_pDataCBlock;
      there     : tbd02_pDataCBlock;
 
BEGIN
RegOffset := pageNo MOD bd20RegionCount;
IF  cbptr <> NIL
THEN
    HashIndex := c_nil_hash
ELSE
    HashIndex := pageNo MOD bd20DataCacheList [RegOffset].dc_HeadListSize;
(*ENDIF*) 
(* *)
vbegexcl (TaskId, g08data1 + RegOffset);
(* *)
IF  bd20DataCacheList [RegOffset].dc_SegmentActive
THEN
    BEGIN
    IF  (cbptr <> NIL)
    THEN
        BEGIN
        IF  cbptr^.dcb_occupant <> pageNo
        THEN
            bd20_Abort (FileId, csp3_b20x6_pno_not_found,
                  'Occup <> Id ', pageNo, cbptr);
        (*ENDIF*) 
        there  := cbptr;
        bFound := true;
        pred   := NIL
        END
    ELSE
        BEGIN
        bd20_SearchInChain (bd20DataCacheList [RegOffset], HashIndex,
              pageNo, recMode, there, pred, bFound);
        IF  bFound
        THEN
            cbptr := there
        ELSE
            g01abort (csp3_b20x1_pno_not_found, csp3_n_datacache,
                  'B20REL: pno not found  :', pageNo)
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    WITH bd20DataCacheList [RegOffset], there^ DO
        BEGIN
        IF  dcb_UsageCnt_bd02 = 0
        THEN
            bd20_Abort (FileId, csp3_b20x2_usage_is_zero,
                  'Usage = 0   ', pageNo, there);
        (*ENDIF*) 
        IF  (dcb_io_state          = iosBlocked_ebd02    ) AND
            (dcb_ChangedState_bd02 = cstSvpRelevant_ebd02) AND
            (dcb_copy_no           = 0                   ) AND
            (IoState               = swsTestIo_ebd02     )
        THEN
            IoState  := swsDoIo_ebd02;
        (*ENDIF*) 
        IF  IoState  = swsIoDone_ebd02
        THEN
            BEGIN
            dcb_io_state          := iosNone_ebd02;
            dcb_ChangedState_bd02 := cstNone_ebd02;
            IF  dcb_queue_occ <> NIL
            THEN
                bd20_ResumeOccupant (bd20DataCacheList [RegOffset], there);
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  IoState <> swsDoIo_ebd02
        THEN
            BEGIN
            (* *)
            dcb_UsageCnt_bd02  := dcb_UsageCnt_bd02 - 1;
            dcb_UpdateCnt_bd02 := dcb_UpdateCnt_bd02 + 1;
            IF  dcb_io_state = iosNone_ebd02
            THEN
                dcb_LastOwner_bd02 := dcb_LastOwner_bd02 - TaskId; (* PTS 1124301 *)
            (* *)
            (*ENDIF*) 
            IF  (dcb_IsSourceOfACopy_bd02                     ) AND
                (dcb_UsageCnt_bd02 = 0                        ) AND
                (dcb_io_state = iosNone_ebd02                 ) AND
                (dcb_ChangedState_bd02 <> cstSvpRelevant_ebd02)
            THEN (* -> COULD NOT HAPPEN ? *)
                bd20_FreeCBlock (bd20DataCacheList [RegOffset], HashIndex, pred, there)
            ELSE
                BEGIN
                IF  dcb_UsageCnt_bd02 = 0
                THEN
                    BEGIN
                    IF  (dcb_lock_req_head <> NIL)
                    THEN
                        bd20_ResumeLockRequest (TaskId, bd20DataCacheList [RegOffset],
                              there, NOT RESUME_ALL_BD20);
                    (*ENDIF*) 
                    IF  (dc_pOverflowTaskQueue <> NIL)
                    THEN
                        bd20_ResumeOverflow (bd20DataCacheList [RegOffset], 1);
                    (*ENDIF*) 
                    IF  dcb_SvpSyncCnt_bd02 > 0
                    THEN
                        BEGIN
                        dc_TotalSvpSyncCnt       := dc_TotalSvpSyncCnt - 1;
                        ExclFileLockCnt          := ExclFileLockCnt - 1;
                        bd20_AssertState( ASSERT_ID_19_BD20, dc_SegmentId, dcb_SvpSyncCnt_bd02 = 1 );
                        dcb_SvpSyncCnt_bd02      := 0;
                        END;
                    (*ENDIF*) 
                    dcb_LastOwner_bd02 := cgg_nil_pid; (* PTS 1124301 *)
                    IF  dcb_io_state = iosBlocked_ebd02
                    THEN
                        dcb_io_state := iosNone_ebd02;
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  IoState = swsIoDone_ebd02
                THEN
                    bd20unset_changed (bd20DataCacheList [RegOffset], there)
                ELSE
                    bd20set_changed (bd20DataCacheList [RegOffset], there,
                          NOT ADD_TMP_TO_IO_CHAIN_BD20, isClustered);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            IF  bd20DataCacheList [RegOffset].dc_MemoryProtection  AND (dcb_UsageCnt_bd02 = 0)
            THEN
                bd20_ReadAccessToFrame (nptr);
            (*ENDIF*) 
            END
        (*ENDIF*) 
        END
    (*ENDWITH*) 
    END;
(* *)
(*ENDIF*) 
vendexcl (TaskId, g08data1 + RegOffset);
(* *)
IF  (IoState <> swsDoIo_ebd02)
THEN
    BEGIN
    nptr  := NIL;
    cbptr := NIL
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20ReplaceOldOccupant (
            TaskId               : tsp00_TaskId;
            PageNo               : tsp00_PageNo;
            recMode              : tgg00_RecoveryMode;
            cbptr                : tbd02_pDataCBlock;
            bLockPageExclusive   : boolean);
 
VAR
      bFound       : boolean;
      RegOffset    : integer;
      HashIndex    : tsp00_Int4;
      OldHashIndex : tsp00_Int4;
      there        : tbd02_pDataCBlock;
 
BEGIN
bFound    := false;
RegOffset := PageNo MOD bd20RegionCount;
HashIndex := PageNo MOD bd20DataCacheList [RegOffset].dc_HeadListSize;
(* *)
vbegexcl (TaskId, g08data1 + RegOffset);
(* *)
WITH bd20DataCacheList [RegOffset] DO
    BEGIN
    IF  dc_SegmentActive
    THEN
        BEGIN
        IF  (cbptr <> NIL                     ) AND
            (cbptr^.dcb_occupant = PageNo     ) AND
            (cbptr^.dcb_RecMode_bd02 = recMode)
        THEN
            BEGIN
            bFound := true;
            there  := cbptr;
            END
        ELSE
            BEGIN
            there := dc_pHeadList^ [HashIndex].he_cb;
            IF  there <> NIL
            THEN
                REPEAT
                    WITH there^ DO
                        BEGIN
                        IF  (dcb_occupant  = PageNo    ) AND
                            (dcb_RecMode_bd02 = recMode)
                        THEN
                            bFound := true
                        ELSE
                            there := dcb_VarNext_bd02
                        (*ENDIF*) 
                        END
                    (*ENDWITH*) 
                UNTIL
                    bFound OR (there = NIL);
                (*ENDREPEAT*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  NOT  bFound
        THEN
            g01abort (csp3_b20x3_pno_not_found, csp3_n_datacache,
                  'B20REP: pno not found   ', PageNo)
        ELSE
            WITH there^ DO
                BEGIN
                OldHashIndex         := dcb_OldOccupant_bd02 MOD dc_HeadListSize;
                dcb_OldOccupant_bd02 := NIL_PAGE_NO_GG00;
                dcb_OldRecMode_bd02  := rmNone_egg00;
                IF  bLockPageExclusive
                THEN
                    BEGIN
                    dcb_io_state       := iosBlocked_ebd02;
                    dcb_LastOwner_bd02 := TaskId;
                    dcb_UsageCnt_bd02  := 1; (* PTS 1124301 *)
                    END;
                (*ENDIF*) 
                dcb_ChangedState_bd02 := cstNone_ebd02;
                IF  dcb_queue_old_occ <> NIL
                THEN
                    bd20_ResumeOldOccupant (bd20DataCacheList [RegOffset], there);
                (*ENDIF*) 
                WITH  dc_pHeadList^ [OldHashIndex] DO
                    BEGIN
                    he_old_occ_cnt   := he_old_occ_cnt  - 1;
                    dc_OldOccupants  := dc_OldOccupants - 1;
                    IF  he_old_occ_cnt < 0
                    THEN
                        he_old_occ_cnt := 0;
                    (*ENDIF*) 
                    IF  dc_OldOccupants < 0
                    THEN
                        dc_OldOccupants := 0
                    (*ENDIF*) 
                    END
                (*ENDWITH*) 
                END
            (*ENDWITH*) 
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
(* *)
vendexcl (TaskId, g08data1 + RegOffset);
(* *)
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20SetPreventSvpSyncOperation (TaskId : tsp00_TaskId);
 
BEGIN
bd20_SetPreventSvpSyncOperation( TaskId, true );
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20UnSetPreventSvpSyncOperation (TaskId : tsp00_TaskId);
 
BEGIN
bd20_SetPreventSvpSyncOperation( TaskId, false );
END;
 
(*------------------------------*) 
 
FUNCTION
      bd20IsPreventSvpSyncOperationPending : boolean;
 
BEGIN
bd20IsPreventSvpSyncOperationPending := bd20DataCacheList[ FIRST_SEGMENT_BD20 ].dc_PreventSvpSync;
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20ShutdownDataCache ( TaskId : tsp00_TaskId );
 
CONST
      msgShutdown1   = 'Begin data cache shutdown               ';
      msgShutdown2   = 'Finish data cache shutdown              ';
      msgFreeFrames  = 'Released cache frames:  ';
 
VAR
      RegOffset  : integer;
      SumDynData : tsp00_Int4;
      pCBlock    : tbd02_pDataCBlock;
      p          : b20ptr;
 
BEGIN
g01optextmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_datacache, msgShutdown1);
SumDynData := 0;
FOR RegOffset := 0 TO bd20RegionCount - 1 DO
    BEGIN
    (* *)
    vbegexcl (TaskId, g08data1 + RegOffset);
    (* *)
    WITH bd20DataCacheList [RegOffset] DO
        BEGIN
        dc_SegmentActive := false;
        pCBlock          := dc_pFirstCBlock;
        WHILE pCBlock <> NIL DO
            BEGIN
            WITH pCBlock^  DO
                BEGIN
                IF  bd20DataCacheList [RegOffset].dc_MemoryProtection
                THEN
                    bd20_ReadWriteAccessToFrame (dcb_pFrame_bd02);
                (*ENDIF*) 
                IF  dcb_pFrame_bd02 <> NIL
                THEN
                    BEGIN
                    bd999ReleaseFrame( TaskId, dcb_pFrame_bd02 );
                    dcb_pFrame_bd02 := NIL;
                    SumDynData      := SumDynData + 1;
                    END;
                (*ENDIF*) 
                IF  dcb_queue_occ <> NIL
                THEN
                    bd20_ResumeOccupant (bd20DataCacheList [RegOffset], pCBlock);
                (*ENDIF*) 
                IF  dcb_queue_old_occ <> NIL
                THEN
                    bd20_ResumeOldOccupant (bd20DataCacheList [RegOffset], pCBlock);
                (*ENDIF*) 
                IF  (dcb_lock_req_head <> NIL)
                THEN
                    bd20_ResumeLockRequest (TaskId, bd20DataCacheList [RegOffset],
                          pCBlock, RESUME_ALL_BD20);
                (*ENDIF*) 
                dcb_occupant         := NIL_PAGE_NO_GG00;
                dcb_OldOccupant_bd02 := NIL_PAGE_NO_GG00;
                END;
            (*ENDWITH*) 
            pCBlock := pCBlock^.dcb_FixedNext_bd02
            END;
        (*ENDWHILE*) 
        (* *)
        (* --- WAKE UP TASKS FROM OVERLOW QUEUE --- *)
        (* *)
        bd20_ResumeOverflow (bd20DataCacheList [RegOffset], MAX_INT4_SP00);
        (* *)
        (* *)
        (* --- SET DATA CACHE SEGMENT SIZE TO ZERO --- *)
        (* *)
        dc_SegmentSize := 0;
        (* *)
        (* --- FREE CONTROL BLOCK MEMORY -- *)
        (* *)
        vmfree( dc_pFirstCBlock );
        dc_pFirstCBlock := NIL;
        (* *)
        (* --- FREE HEADLIST MEMORY -- *)
        (* *)
        p.aux_hl_addr := dc_pHeadList;
        vmfree( p.cblockaddr );
        dc_pHeadList := NIL;
        (* dc_HeadListSize := 0; *)
        (* Do not set the Size to zero, because the following line of code *)
        (* HashIndex := PageNo MOD dc_HeadListSize is not protected by a   *)
        (* datacache region to raise performance. So the modulo always     *)
        (* works but the subsequent call of dc_SegmentActive == TRUE will  *)
        (* fail in case of an shutdown.                                    *)
        (* *)
        (* --- FREE TASK QUEUE MEMORY -- *)
        (* *)
        p.pid_queue_addr := dc_pTaskQueueHead;
        vmfree( p.cblockaddr );
        dc_pTaskQueueHead := NIL;
        END;
    (*ENDWITH*) 
    (* *)
    vendexcl (TaskId, g08data1 + RegOffset);
    (* *)
    END;
(*ENDFOR*) 
g01allocate_msg (csp3_n_datacache, msgFreeFrames, SumDynData);
g01optextmsg (sp3p_knldiag, sp3m_info, csp3_bd_msg, csp3_n_datacache, msgShutdown2);
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20UsePage (
            TaskId              : tsp00_TaskId;
            VAR TrError         : tgg00_BasisError;
            PageNo              : tsp00_PageNo;
            recMode             : tgg00_RecoveryMode;
            cbptr               : tbd02_pDataCBlock;
            VAR nptr            : tbd_nodeptr;
            bLockPageExclusive  : boolean);
 
VAR
      bFound     : boolean;
      RegOffset : integer;
      HashIndex : tsp00_Int4;
      there     : tbd02_pDataCBlock;
 
BEGIN
bFound    := false;
RegOffset := PageNo MOD bd20RegionCount;
HashIndex := PageNo MOD bd20DataCacheList [RegOffset].dc_HeadListSize;
(* *)
vbegexcl (TaskId, g08data1 + RegOffset);
(* *)
WITH bd20DataCacheList [RegOffset] DO
    BEGIN
    IF  NOT dc_SegmentActive
    THEN
        TrError := e_shutdown
    ELSE
        BEGIN
        IF  (cbptr <> NIL                     ) AND
            (cbptr^.dcb_occupant = PageNo     ) AND
            (cbptr^.dcb_RecMode_bd02 = recMode)
        THEN
            BEGIN
            bFound := true;
            there := cbptr
            END
        ELSE
            BEGIN
            there := dc_pHeadList^ [HashIndex].he_cb;
            IF  there <> NIL
            THEN
                REPEAT
                    WITH there^ DO
                        BEGIN
                        IF  (dcb_occupant = PageNo     ) AND
                            (dcb_RecMode_bd02 = recMode)
                        THEN
                            bFound := true
                        ELSE
                            there := dcb_VarNext_bd02
                        (*ENDIF*) 
                        END
                    (*ENDWITH*) 
                UNTIL
                    bFound OR (there = NIL);
                (*ENDREPEAT*) 
            (*ENDIF*) 
            IF  NOT  bFound
            THEN
                g01abort (csp3_b20x4_pno_not_found, csp3_n_datacache,
                      'B20USE: pno not found   ', PageNo);
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        WITH there^ DO
            BEGIN
            IF  TrError = e_bd_leaf_unlocked
            THEN
                BEGIN
                dcb_LastOwner_bd02 := cgg_nil_pid; (* PTS 1124301 *)
                dcb_UsageCnt_bd02  := 0;
                nptr               := NIL
                END
            ELSE
                BEGIN
                dcb_LastOwner_bd02 := TaskId;
                dcb_UsageCnt_bd02  := 1;
                nptr               := dcb_pFrame_bd02
                END;
            (*ENDIF*) 
            IF  bLockPageExclusive
            THEN
                dcb_io_state := iosBlocked_ebd02
            ELSE
                dcb_io_state := iosNone_ebd02;
            (*ENDIF*) 
            bd20unset_changed (bd20DataCacheList [RegOffset], there);
            IF  dcb_queue_occ <> NIL
            THEN
                bd20_ResumeOccupant (bd20DataCacheList [RegOffset], there);
            (*ENDIF*) 
            END
        (*ENDWITH*) 
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
(* *)
vendexcl (TaskId, g08data1 + RegOffset);
(* *)
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20UsePageAfterLoad (
            taskId        : tsp00_TaskId;
            pageNo        : tsp00_PageNo;
            recMode       : tgg00_RecoveryMode;
            bSetToChanged : boolean;
            bIsClustered  : boolean;
            pCBlock       : tbd02_pDataCBlock;
            VAR file_id   : tgg00_FileId;
            VAR trError   : tgg00_BasisError);
 
VAR
      regOffset : integer;
      hashIndex : tsp00_Int4;
 
BEGIN
regOffset := pageNo MOD bd20RegionCount;
hashIndex := pageNo MOD bd20DataCacheList[ regOffset ].dc_HeadListSize;
(* *)
vbegexcl (taskId, g08data1 + regOffset);
(* *)
WITH bd20DataCacheList[ regOffset ] DO
    BEGIN
    IF  NOT dc_SegmentActive
    THEN
        trError := e_shutdown
    ELSE
        WITH pCBlock^ DO
            BEGIN
            IF  (pCBlock = NIL              ) OR
                (dcb_occupant     <> pageNo ) OR
                (dcb_RecMode_bd02 <> recMode)
            THEN
                g01abort (csp3_b20x7_pno_not_found, csp3_n_datacache,
                      'B20USE_AF: pno not found', pageNo);
            (*ENDIF*) 
            dcb_io_state       := iosNone_ebd02;
            dcb_UsageCnt_bd02  := 0;
            dcb_LastOwner_bd02 := cgg_nil_pid;
            IF  bSetToChanged
            THEN
                BEGIN
                bd20set_changed (bd20DataCacheList[ regOffset ], pCBlock,
                      ADD_TMP_TO_IO_CHAIN_BD20, bIsClustered);
                dcb_UsageCnt_bd02  := 0;
                dcb_LastOwner_bd02 := cgg_nil_pid
                END;
            (*ENDIF*) 
            IF  dcb_queue_occ <> NIL
            THEN
                bd20_ResumeOccupant (bd20DataCacheList[ regOffset ], pCBlock);
            (*ENDIF*) 
            IF  dc_MemoryProtection
            THEN
                bd20_ReadAccessToFrame( dcb_pFrame_bd02 );
            (*ENDIF*) 
            END
        (*ENDWITH*) 
    (*ENDIF*) 
    END;
(*ENDWITH*) 
(* *)
vendexcl (taskId, g08data1 + regOffset);
(* *)
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20add_to_chain (VAR datacache : t_datacache;
            HashIndex : tsp00_Int4;
            there     : tbd02_pDataCBlock);
 
BEGIN
WITH datacache DO
    BEGIN
    there^.dcb_VarNext_bd02         := dc_pHeadList^ [HashIndex].he_cb;
    dc_pHeadList^ [HashIndex].he_cb := there
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_FreeCBlock (
            VAR DataCache : t_datacache;
            HashIndex     : integer;
            pPrevCBlock   : tbd02_pDataCBlock;
            pCBlock       : tbd02_pDataCBlock);
 
VAR
      ConverterVersion :  tgg00_ConverterVersion;
      pCurrCBlock      : tbd02_pDataCBlock;
 
BEGIN
WITH DataCache DO
    BEGIN
    bd20_DelFromLRUList (DataCache, pCBlock);
    WITH pCBlock^ DO
        BEGIN
        IF  (dcb_queue_occ <> NIL    ) OR (dcb_queue_old_occ <> NIL) OR
            (dcb_lock_req_head <> NIL) OR (dcb_lock_req_tail <> NIL)
        THEN
            bd20_Abort2 (csp3_b20x1_pid_queue_not_empty, 'TaskQ <> 0  ', dcb_occupant, pCBlock);
        (*ENDIF*) 
        IF  DataCache.dc_MemoryProtection
        THEN
            bd20_ReadWriteAccessToFrame (dcb_pFrame_bd02);
        (*ENDIF*) 
        IF  (HashIndex = c_nil_hash) OR dcb_IsSourceOfACopy_bd02
        THEN
            BEGIN
            HashIndex := dcb_occupant MOD dc_HeadListSize;
            IF  dc_pHeadList^ [HashIndex].he_cb <> pCBlock
            THEN
                BEGIN
                pCurrCBlock := dc_pHeadList^ [HashIndex].he_cb;
                (* *)
                ConverterVersion := dcb_pFrame_bd02^.nd_conv_version;
                (* *)
                REPEAT
                    IF  (pCurrCBlock^.dcb_occupant     = dcb_occupant    ) AND
                        (pCurrCBlock^.dcb_RecMode_bd02 = dcb_RecMode_bd02) AND
                        (dcb_IsSourceOfACopy_bd02                        )
                    THEN
                        BEGIN
                        IF  pCurrCBlock^.dcb_copy_no = 0
                        THEN
                            bd20_Abort2( csp3_b20x1_copy_no_not_zero, 'CopyNo = 0  ',
                                  dcb_occupant, pCurrCBlock);
                        (*ENDIF*) 
                        IF  DataCache.dc_MemoryProtection
                        THEN
                            bd20_ReadWriteAccessToFrame (pCurrCBlock^.dcb_pFrame_bd02);
                        (*ENDIF*) 
                        pCurrCBlock^.dcb_pFrame_bd02^.nd_conv_version := ConverterVersion;
                        pCurrCBlock^.dcb_copy_no                      := pCurrCBlock^.dcb_copy_no - 1;
                        IF  DataCache.dc_MemoryProtection
                        THEN
                            BEGIN
                            IF  (pCurrCBlock^.dcb_UsageCnt_bd02 = 0) AND (pCurrCBlock^.dcb_io_state = iosNone_ebd02)
                            THEN
                                bd20_ReadAccessToFrame (pCurrCBlock^.dcb_pFrame_bd02);
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        END;
                    (*ENDIF*) 
                    IF  pCurrCBlock^.dcb_VarNext_bd02 = pCBlock
                    THEN
                        pPrevCBlock := pCurrCBlock;
                    (*ENDIF*) 
                    pCurrCBlock := pCurrCBlock^.dcb_VarNext_bd02;
                UNTIL
                    pCurrCBlock = pCBlock
                (*ENDREPEAT*) 
                END
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        bd20unset_changed (DataCache, pCBlock);
        bd20_DecrementWorkloadCounter (DataCache, dcb_tfn); (* CR 1105627 TS 2000-02-15 *)
        IF  (dcb_UsageCnt_bd02 = 0) AND (dcb_LastOwner_bd02 <> cgg_nil_pid)
        THEN
            bd20_Abort2 (csp3_bd_msg, 'TaskId <> 0 ', pCBlock^.dcb_occupant, pCBlock);
        (*ENDIF*) 
        dcb_Init_bd02 := bd20CBlockInit;
        END;
    (*ENDWITH*) 
    bd20del_from_chain (DataCache, HashIndex, pCBlock, pPrevCBlock);
    bd20_FreeFrame (DataCache, pCBlock)
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_CheckLRUList( VAR DataCache : t_datacache );
 
VAR
      bEnterIOArea      : boolean;
      bEnterRechainArea : boolean;
      bFound            : boolean;
      CBlocksInUse      : tsp00_Int4;
      LoopCount         : tsp00_Int4;
      pCBlock           : tbd02_pDataCBlock;
      pAux1CBlock       : tbd02_pDataCBlock;
      pAux2CBlock       : tbd02_pDataCBlock;
 
BEGIN
WITH DataCache DO
    BEGIN
    LoopCount         := 0;
    CBlocksInUse      := dc_SegmentSize - dc_FreeCount;
    bEnterIOArea      := false;
    bEnterRechainArea := false;
    pCBlock           := dc_pFirstLRU;
    IF  dc_pFirstLRU <> NIL
    THEN
        BEGIN
        IF  dc_pFirstLRU^.dcb_lru_prev <> NIL
        THEN
            bd20_Abort2 (csp3_b20x2_check_lru, 'Wrong LRUFst',
                  dc_pFirstLRU^.dcb_occupant, dc_pFirstLRU);
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  dc_pLastLRU <> NIL
    THEN
        IF  dc_pLastLRU^.dcb_lru_next <> NIL
        THEN
            bd20_Abort2( csp3_b20x2_check_lru, 'Wrong LRULst',
                  dc_pLastLRU^.dcb_occupant, dc_pLastLRU);
        (*ENDIF*) 
    (*ENDIF*) 
    IF  (dc_FreeCount) <= dc_IOAreaSize
    THEN
        BEGIN
        bd20_AssertState( ASSERT_ID_16_BD20, dc_SegmentId, dc_pIOMid <> NIL );
        bd20_AssertState( ASSERT_ID_17_BD20, dc_SegmentId, NOT dc_pIOMid^.dcb_lru_prev^.dcb_dw_io_area );
        IF  dc_pIOMid^.dcb_lru_next <> NIL
        THEN
            bd20_AssertState( ASSERT_ID_18_BD20, dc_SegmentId, dc_pIOMid^.dcb_lru_next^.dcb_dw_io_area );
        (*ENDIF*) 
        END
    ELSE
        bd20_AssertState( ASSERT_ID_15_BD20, dc_SegmentId, dc_pIOMid = NIL );
    (*ENDIF*) 
&   if $KIND = SLOW
    WHILE( pCBlock <> NIL ) DO
        WITH pCBlock^ DO
            BEGIN
            IF  dcb_lru_next <> NIL
            THEN
                IF  dcb_lru_next^.dcb_lru_prev <> pCBlock
                THEN
                    bd20_Abort2( csp3_b20x1_check_lru, 'Prev != Next',
                          dcb_occupant, pCBlock );
                (*ENDIF*) 
            (*ENDIF*) 
            IF  (
                (bEnterIOArea AND NOT dcb_dw_io_area) OR
                (NOT bEnterIOArea AND dcb_dw_io_area)
                )
            THEN
                bd20_Abort2( csp3_b20x2_check_lru,
                      'Wrong IOMid ', dcb_occupant, pCBlock);
            (*ENDIF*) 
            IF  (
                (bEnterRechainArea AND NOT dcb_lru_rechain) OR
                (NOT bEnterRechainArea AND dcb_lru_rechain)
                )
            THEN
                bd20_Abort2( csp3_b20x2_check_lru,
                      'Wrong Mid   ', dcb_occupant, pCBlock);
            (*ENDIF*) 
            bEnterIOArea      := bEnterIOArea OR ( pCBlock = dc_pIOMid );
            bEnterRechainArea := bEnterRechainArea OR ( pCBlock = dc_pMid );
            (* *)
            bd20_SearchInChain( DataCache, ( dcb_occupant MOD dc_HeadListSize ), dcb_occupant,
                  dcb_RecMode_bd02, pAux1CBlock, pAux2CBlock, bFound );
            IF  NOT bFound
            THEN
                g01abort (csp3_bd_msg, csp3_n_datacache, MSG_CBLOCK_NOT_FOUND, dcb_occupant);
            (*ENDIF*) 
            IF  LoopCount > CBlocksInUse
            THEN
                g01abort (csp3_bd_msg, csp3_n_datacache, MSG_LOOP_OVERFLOW,
                      dc_pFirstLRU^.dcb_occupant MOD bd20RegionCount);
            (*ENDIF*) 
            LoopCount := LoopCount + 1;
            pCBlock   := pCBlock^.dcb_lru_next;
            END;
        (*ENDWITH*) 
    (*ENDWHILE*) 
    bd20_CheckFreeList( DataCache );
&   endif
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_CheckFreeList( VAR DataCache : t_datacache );
 
VAR
      pCBlock : tbd02_pDataCBlock;
 
BEGIN
WITH  DataCache DO
    BEGIN
    pCBlock := dc_pFreeList;
    WHILE (pCBlock <> NIL) DO
        BEGIN
        IF  pCBlock^.dcb_pFrame_bd02 = NIL
        THEN
            bd20_Abort2( csp3_b20x1_check_lru,
                  'Frame = NIL ', pCBlock^.dcb_occupant, pCBlock );
        (*ENDIF*) 
        pCBlock := pCBlock^.dcb_VarNext_bd02;
        END;
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20check_io_chain (VAR datacache : t_datacache);
 
VAR
      curr_block : tbd02_pDataCBlock;
 
BEGIN
&ifdef TESTONLY
WITH datacache DO
    BEGIN
    curr_block := dc_pFirstCBlock;
    WHILE (curr_block <> NIL) DO
        BEGIN
        IF  (curr_block^.dcb_ChangedState_bd02 <> cstNone_ebd02)
            AND
            (rmTemp_egg00 <> curr_block^.dcb_RecMode_bd02)
        THEN
            BEGIN
            IF  NOT bd20check_io_chain3 (datacache, dc_pIOQueueHead1,
                curr_block)
            THEN
                IF  NOT bd20check_io_chain3 (datacache,
                    dc_pIOQueueHead2, curr_block)
                THEN
                    bd20_Abort2 (csp3_b20x2_check, 'IOCHAIN err ',
                          curr_block^.dcb_occupant,  curr_block);
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        curr_block := curr_block^.dcb_FixedNext_bd02
        END
    (*ENDWHILE*) 
    END;
(*ENDWITH*) 
&endif
END;
 
&ifdef TESTONLY
(*------------------------------*) 
 
FUNCTION
      bd20check_io_chain3 (datacache : t_datacache;
            curr_io_ptr : tbd02_pDataCBlock;
            curr_block  : tbd02_pDataCBlock) : boolean;
 
VAR
      bFound        : boolean;
      io_chain_cnt : tsp00_Int4;
      prev_io_ptr  : tbd02_pDataCBlock;
 
BEGIN
bFound        := false;
io_chain_cnt := 0;
prev_io_ptr  := NIL;
WHILE NOT bFound                      AND
      (io_chain_cnt <= datacache.dc_SegmentSize - 1) AND
      (curr_io_ptr  <> NIL)          DO
    BEGIN
    IF  (prev_io_ptr <> curr_io_ptr^.dcb_io_prev)
    THEN
        bd20_Abort2 (csp3_b20x3_check, 'IOCHAIN err ', 0, curr_io_ptr);
    (*ENDIF*) 
    IF  (curr_io_ptr = curr_block)
    THEN
        bFound := true
    ELSE
        BEGIN
        io_chain_cnt := succ (io_chain_cnt);
        prev_io_ptr  := curr_io_ptr;
        curr_io_ptr  := curr_io_ptr^.dcb_io_next
        END
    (*ENDIF*) 
    END;
(*ENDWHILE*) 
bd20check_io_chain3 := bFound
END;
 
&endif
(*------------------------------*) 
 
PROCEDURE
      bd20check_svp_chain (VAR datacache : t_datacache);
 
VAR
      curr_block   : tbd02_pDataCBlock;
      svp_elem_cnt : tsp00_Int4;
 
BEGIN
WITH datacache DO
    BEGIN
    svp_elem_cnt     := 0;
    curr_block       := dc_pFirstCBlock;
    WHILE (curr_block <> NIL) DO
        WITH curr_block^ DO
            BEGIN
            IF  (dcb_ChangedState_bd02 = cstSvpRelevant_ebd02)
                AND
                (rmTemp_egg00 <> curr_block^.dcb_RecMode_bd02)
            THEN
                svp_elem_cnt := succ (svp_elem_cnt);
            (*ENDIF*) 
            curr_block := curr_block^.dcb_FixedNext_bd02
            END;
        (*ENDWITH*) 
    (*ENDWHILE*) 
    IF  (svp_elem_cnt <> (dc_SVPElems + dc_clusteredSVPElems))
    THEN
        g01abort (csp3_b20x1_check_io_cnt, csp3_n_savepoint,
              'MISMATCH SVP COUNT      ', svp_elem_cnt);
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_CopyCBlock (
            TaskId         : tsp00_TaskId;
            VAR FileId     : tgg00_FileId;
            VAR DataCache  : t_datacache;
            HashIndex      : tsp00_Int4;
            pOldCBlock     : tbd02_pDataCBlock;
            VAR pNewCBlock : tbd02_pDataCBlock;
            VAR TrError    : tgg00_BasisError);
 
VAR
      ChangedCnt    : tsp00_Int4; (* dummy *)
 
BEGIN
WITH DataCache DO
    BEGIN
    IF  (pOldCBlock^.dcb_copy_no = c_max_copies)
        OR g01ConsistentReadEnabled (* TODO allow page copy for consistent read *)
    THEN
        BEGIN
        TrError := e_sysbuffer_overflow;
        g01opmsg (sp3p_knldiag, sp3m_warning, csp3_b20_copy_overflow,
              csp3_n_datacache, 'BD20COPY:  overflow     ', 0)
        END
    ELSE
        bd20_GetFrameFromLRU (TaskId, TrError, FileId, DataCache,
              IGNORE_DIRTY_PAGES_BD20, pNewCBlock, ChangedCnt);
    (*ENDIF*) 
    IF  TrError <> e_ok
    THEN
        pNewCBlock := NIL
    ELSE
        WITH pNewCBlock^ DO
            BEGIN
            IF  dcb_io_state <> iosNone_ebd02
            THEN
                bd20_Abort (FileId, csp3_b20x1_invalid_io_state,
                      'Illeg IoStat', dcb_occupant, pNewCBlock);
            (*ENDIF*) 
            IF  DataCache.dc_MemoryProtection
            THEN
                BEGIN
                bd20_ReadWriteAccessToFrame (pOldCBlock^.dcb_pFrame_bd02);
                bd20_ReadWriteAccessToFrame (pNewCBlock^.dcb_pFrame_bd02);
                END;
            (*ENDIF*) 
            SAPDB_PascalForcedMove (sizeof (pOldCBlock^.dcb_pFrame_bd02^), sizeof (dcb_pFrame_bd02^),
                  @pOldCBlock^.dcb_pFrame_bd02^, 1, @dcb_pFrame_bd02^, 1,
                  sizeof (pOldCBlock^.dcb_pFrame_bd02^));
            IF  DataCache.dc_MemoryProtection AND (pOldCBlock^.dcb_io_state = iosNone_ebd02)
            THEN
                bd20_ReadAccessToFrame (pOldCBlock^.dcb_pFrame_bd02);
            (*ENDIF*) 
            dcb_occupant          := pOldCBlock^.dcb_occupant;
            dcb_tfn               := pOldCBlock^.dcb_tfn;
            dcb_RecMode_bd02      := pOldCBlock^.dcb_RecMode_bd02;
            dcb_UsageCnt_bd02     := 1;
            dcb_copy_no           := pOldCBlock^.dcb_copy_no + 1;
            dcb_io_state          := iosBlocked_ebd02;
            dcb_LastOwner_bd02    := TaskId;
            dcb_AccessCnt_bd02    := pOldCBlock^.dcb_AccessCnt_bd02 + 1;
            dcb_UpdateCnt_bd02    := pOldCBlock^.dcb_UpdateCnt_bd02;
            dcb_CollisionCnt_bd02 := pOldCBlock^.dcb_CollisionCnt_bd02;
            bd20add_to_chain (DataCache, HashIndex, pNewCBlock);
            dcb_lock_req_head                    := pOldCBlock^.dcb_lock_req_head;
            dcb_lock_req_tail                    := pOldCBlock^.dcb_lock_req_tail;
            dcb_IsClustered_bd02                 := pOldCBlock^.dcb_IsClustered_bd02;
            pOldCBlock^.dcb_lock_req_head        := NIL;
            pOldCBlock^.dcb_lock_req_tail        := NIL;
            pOldCBlock^.dcb_IsSourceOfACopy_bd02 := true;
            END
        (*ENDWITH*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20c_search_in_chain_incl_copy (
            VAR DataCache     : t_datacache;
            HashIndex         : tsp00_Int4;
            PageNo            : tsp00_PageNo;
            recMode           : tgg00_RecoveryMode;
            VAR there         : tbd02_pDataCBlock;
            VAR pred          : tbd02_pDataCBlock;
            VAR bFound        : boolean;
            VAR pSourceCBlock : tbd02_pDataCBlock);
 
VAR
      act_cbptr : tbd02_pDataCBlock;
 
BEGIN
(* search for more than one control block for a single page: *)
(* the current control block referenced by THERE and         *)
(* the control block for a copy referenced by pSourceCBlock  *)
WITH DataCache DO
    BEGIN
    bFound        := false;
    pred          := NIL;
    there         := NIL;
    pSourceCBlock := NIL;
    act_cbptr     := dc_pHeadList^ [HashIndex].he_cb;
    IF  act_cbptr <> NIL
    THEN
        REPEAT
            IF  (act_cbptr^.dcb_occupant = PageNo     ) AND
                (act_cbptr^.dcb_RecMode_bd02 = recMode)
            THEN
                IF  act_cbptr^.dcb_IsSourceOfACopy_bd02
                THEN
                    pSourceCBlock := act_cbptr
                ELSE
                    BEGIN
                    there  := act_cbptr;
                    bFound := true
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            IF  NOT bFound
            THEN
                pred := act_cbptr;
            (*ENDIF*) 
            act_cbptr := act_cbptr^.dcb_VarNext_bd02
        UNTIL
            (act_cbptr = NIL)
        (*ENDREPEAT*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20del_from_chain (
            VAR DataCache : t_datacache;
            HashIndex     : tsp00_Int4;
            pCBlock       : tbd02_pDataCBlock;
            pPrevCBlock   : tbd02_pDataCBlock);
 
VAR
      pNextCBlock : tbd02_pDataCBlock;
 
BEGIN
WITH DataCache DO
    BEGIN
    pNextCBlock := pCBlock^.dcb_VarNext_bd02;
    IF  dc_pHeadList^ [HashIndex].he_cb = pCBlock
    THEN
        dc_pHeadList^ [HashIndex].he_cb := pNextCBlock
    ELSE
        pPrevCBlock^.dcb_VarNext_bd02 := pNextCBlock
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_DelFromLRUList (
            VAR DataCache : t_datacache;
            pCBlock       : tbd02_pDataCBlock);
 
VAR
      pPrevCBlock : tbd02_pDataCBlock;
      pNextCBlock : tbd02_pDataCBlock;
 
BEGIN
WITH DataCache DO
    BEGIN
    pPrevCBlock := pCBlock^.dcb_lru_prev;
    pNextCBlock := pCBlock^.dcb_lru_next;
    IF  pPrevCBlock <> NIL
    THEN
        pPrevCBlock^.dcb_lru_next := pNextCBlock
    ELSE
        dc_pFirstLRU := pNextCBlock;
    (*ENDIF*) 
    IF  pNextCBlock <> NIL
    THEN
        pNextCBlock^.dcb_lru_prev := pPrevCBlock
    ELSE
        dc_pLastLRU := pPrevCBlock;
    (*ENDIF*) 
    IF  (NOT pCBlock^.dcb_lru_rechain) AND (dc_pMid <> NIL)
    THEN
        BEGIN
        dc_pMid := dc_pMid^.dcb_lru_next;
        IF  dc_pMid <> NIL
        THEN
            dc_pMid^.dcb_lru_rechain := false
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  (NOT pCBlock^.dcb_dw_io_area) AND (dc_pIOMid <> NIL)
    THEN
        BEGIN
        dc_pIOMid := dc_pIOMid^.dcb_lru_next;
        IF  dc_pIOMid <> NIL
        THEN
            dc_pIOMid^.dcb_dw_io_area := false
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_FreeFrame (
            VAR DataCache : t_datacache;
            pCBlock       : tbd02_pDataCBlock);
 
BEGIN
WITH DataCache DO
    BEGIN
    dc_FreeCount              := dc_FreeCount + 1;
    pCBlock^.dcb_VarNext_bd02 := dc_pFreeList;
    dc_pFreeList              := pCBlock;
    IF  DataCache.dc_MemoryProtection
    THEN
        bd20_ReadAccessToFrame (pCBlock^.dcb_pFrame_bd02)
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_GetFrameFromLRU (
            TaskId            : tsp00_TaskId;
            VAR TrError       : tgg00_BasisError;
            VAR FileId        : tgg00_FileId;
            VAR DataCache     : t_datacache;
            bIgnoreDirtyPages : boolean;
            VAR pCBlock       : tbd02_pDataCBlock;
            VAR ChangedCnt    : tsp00_Int4);
 
VAR
      bFound        : boolean;
      CBlockCnt     : tsp00_Int4; (* PTS 1126174 2003-12-10 *)
      HashIndex     : tsp00_Int4;
      pPrevCBlock   : tbd02_pDataCBlock;
      pUsableCBlock : tbd02_pDataCBlock;
 
BEGIN
WITH DataCache DO
    BEGIN
    IF  dc_pFreeList <> NIL
    THEN
        BEGIN
        dc_FreeCount := dc_FreeCount - 1;
        pCBlock      := dc_pFreeList;
        dc_pFreeList := pCBlock^.dcb_VarNext_bd02;
        bd20_PutNewIntoLRUList (DataCache, pCBlock);
        bd20_IncrementWorkloadCounter (DataCache, FileId.fileTfn_gg00);
        END
    ELSE
        BEGIN
        bFound        := false;
        CBlockCnt     := 0;
        pUsableCBlock := NIL;
        pCBlock := dc_pLastLRU;
        REPEAT
            WITH  pCBlock^ DO
                BEGIN
                CBlockCnt := CBlockCnt + 1;
                IF  (dcb_UsageCnt_bd02 > 0         ) OR
                    (dcb_io_state <> iosNone_ebd02 ) OR
                    (dcb_IsSourceOfACopy_bd02      ) OR
                    (dcb_copy_no > 0               ) OR
                    (dcb_lock_req_head <> NIL      ) OR
                    (
                    (dcb_ChangedState_bd02 <> cstNone_ebd02)
                    AND
                    ((bIgnoreDirtyPages) OR (dc_SVPActive AND (dcb_RecMode_bd02 <> rmTemp_egg00)))
                    )
                THEN
                    BEGIN
                    IF  dcb_lru_rechain AND ((dcb_UsageCnt_bd02 > 0) OR (dcb_io_state = iosUserIO_ebd02))
                    THEN
                        BEGIN
                        pPrevCBlock := dcb_lru_prev;
                        bd20_PutFirstLRUList (DataCache, pCBlock);
                        pCBlock := pPrevCBlock;
                        END
                    ELSE
                        pCBlock := dcb_lru_prev;
                    (*ENDIF*) 
                    END
                ELSE (* Usable *)
                    BEGIN
                    IF  dcb_ChangedState_bd02 <> cstChanged_ebd02
                    THEN
                        bFound := true
                    ELSE
                        BEGIN
                        IF  pUsableCBlock = NIL
                        THEN
                            pUsableCBlock := pCBlock;
                        (*ENDIF*) 
                        IF  dcb_lru_rechain
                        THEN
                            ChangedCnt := ChangedCnt + 1;
                        (*ENDIF*) 
                        pCBlock := dcb_lru_prev
                        END
                    (*ENDIF*) 
                    END
                (*ENDIF*) 
                END
            (*ENDWITH*) 
        UNTIL
            bFound OR (pCBlock = NIL) OR (CBlockCnt > dc_SegmentSize); (* PTS 1126174 2003-12-10 *)
        (*ENDREPEAT*) 
        IF  (NOT bFound) AND (pUsableCBlock <> NIL)
        THEN
            BEGIN
            pCBlock := pUsableCBlock;
            bFound  := true
            END;
        (*ENDIF*) 
        IF  NOT bFound
        THEN
            BEGIN
            IF  dc_SVPActive
            THEN
                BEGIN
                TrError := e_no_more_temp_space;
                bd20_InsertOverflow (TaskId, FileId, DataCache)
                END
            ELSE
                TrError := e_sysbuffer_overflow;
            (*ENDIF*) 
            END
        ELSE (* Found mapped CBlock *)
            BEGIN
            WITH pCBlock^DO
                BEGIN
                HashIndex  := dcb_occupant MOD dc_HeadListSize;
                bd20_SearchInChain (DataCache, HashIndex, dcb_occupant,
                      dcb_RecMode_bd02, pCBlock, pPrevCBlock, bFound);
                bd20del_from_chain (DataCache, HashIndex, pCBlock, pPrevCBlock);
                bd20_DecrementWorkloadCounter (DataCache, dcb_tfn);
                IF  dcb_lru_rechain
                THEN
                    bd20_PutFirstLRUList (DataCache, pCBlock)
                (*ENDIF*) 
                END;
            (*ENDWITH*) 
            bd20_IncrementWorkloadCounter (DataCache, FileId.fileTfn_gg00);
            END
        (*ENDIF*) 
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20opmsg (msg_type  : tsp3_msg_type;
            msg_no : tsp00_Int4;
            msg_12 : tsp00_C12;
            pno    : tsp00_PageNo;
            cb_ptr : tbd02_pDataCBlock);
 
VAR
 
      cb_map_c8 : RECORD
            CASE boolean OF
                false :
                    (c8 : tsp00_C8);
                true  :
                    (cb : tbd02_pDataCBlock)
                END;
            (*ENDCASE*) 
 
      len      : integer;
      i        : integer;
      n        : tsp00_C12;
      msg      : tsp00_C40;
 
BEGIN
msg          := bsp_c40;
cb_map_c8.cb := cb_ptr;
IF  (sizeof (cb_ptr) = 4) OR (cb_ptr = NIL) OR
    (pno = NIL_PAGE_NO_GG00)
THEN
    BEGIN
    SAPDB_PascalForcedMove (sizeof (msg_12), sizeof (msg),
          @msg_12, 1, @msg, 1, sizeof (msg_12));
    len := 12
    END
ELSE
    BEGIN
    SAPDB_PascalForcedMove (sizeof (msg_12), sizeof (msg),
          @msg_12, 1, @msg, 1, 5);
    len := 5
    END;
(*ENDIF*) 
IF  pno <> NIL_PAGE_NO_GG00
THEN
    BEGIN
    n   := ' PNO        ';
    SAPDB_PascalForcedMove (sizeof (n), sizeof (msg),
          @n, 1, @msg, len + 1, 5);
    len := len + 5;
    g17trimint4_to_line (pno, len, msg)
    END;
(*ENDIF*) 
IF  (cb_ptr <> NIL) AND (len + 5 + 2 * sizeof (cb_ptr) < sizeof (msg))
THEN
    BEGIN
    n   := ' PTR        ';
    SAPDB_PascalForcedMove (sizeof (n), sizeof (msg),
          @n, 1, @msg, len + 1, 5);
    len := len + 5;
    FOR i := 1 TO sizeof (tbd02_pDataCBlock) DO
        g17hexto_line (cb_map_c8.c8 [i], len, msg)
    (*ENDFOR*) 
    END;
(*ENDIF*) 
g01optextmsg (sp3p_knldiag, msg_type, msg_no, csp3_n_datacache, msg)
END;
 
&ifdef TRACE
(*------------------------------*) 
 
PROCEDURE
      bd20print_io_chain (VAR datacache : t_datacache);
 
VAR
      curr_block : tbd02_pDataCBlock;
 
BEGIN
WITH datacache DO
    BEGIN
    t01name   (bd_ioqueue, '=-=-=-=-=-=-=-=-=-');
    t01bool   (bd_ioqueue, 'io_switch   ', dc_IOSwitch);
    t01p2int4 (bd_ioqueue, 'svp_elems   ', dc_SVPElems
          ,                'io_elems    ', dc_IOElems);
    (* *)
    (* --- IO QUEUE --- *)
    (* *)
    IF  (dc_pIOQueueHead1 <> NIL) OR (dc_pIOQueueHead2 <> NIL)
    THEN
        BEGIN
        t01addr2 (bd_ioqueue, 'ioq_head_1  ', dc_pIOQueueHead1
              ,               'ioq_head_2  ', dc_pIOQueueHead2);
        t01addr2 (bd_ioqueue, 'ioq_tail_1  ', dc_pIOQueueTail1
              ,               'ioq_tail_2  ', dc_pIOQueueTail2);
        END;
    (* *)
    (* --- B20CHANGED CONTROLBLOCKS --- *)
    (* *)
    (*ENDIF*) 
    curr_block := dc_pFirstCBlock;
    WHILE (curr_block <> NIL) DO
        WITH curr_block^ DO
            BEGIN
            IF  (dcb_ChangedState_bd02 <> cstNone_ebd02)
                AND
                (rmTemp_egg00 <> dcb_RecMode_bd02)
            THEN
                BEGIN
                t01int4_addr (bd_ioqueue, 'occupant    ', dcb_occupant
                      ,                   'address     ', curr_block);
                t01addr2     (bd_ioqueue, 'cb_io_prev  ', dcb_io_prev
                      ,                   'cb_io_next  ', dcb_io_next);
                t01int4      (bd_ioqueue, 'cb_tfn      ', ord (dcb_tfn));
                t01int4      (bd_ioqueue, 'cb_io_state ', ord (dcb_io_state));
                t01int4      (bd_ioqueue, 'ChangedState', ord (dcb_ChangedState_bd02));
                END;
            (*ENDIF*) 
            curr_block := curr_block^.dcb_FixedNext_bd02
            END
        (*ENDWITH*) 
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
&endif
(*------------------------------*) 
 
PROCEDURE
      bd20_PutFirstLRUList (
            VAR DataCache : t_datacache;
            pCBlock       : tbd02_pDataCBlock);
 
BEGIN
WITH DataCache DO
    BEGIN
    IF  pCBlock^.dcb_lru_prev <> NIL
    THEN
        BEGIN
        IF  pCBlock^.dcb_lru_rechain
        THEN
            BEGIN
            dc_pMid^.dcb_lru_rechain := true;
            dc_pMid                  := dc_pMid^.dcb_lru_prev;
            pCBlock^.dcb_lru_rechain := false;
            END
        ELSE
            IF  pCBlock = dc_pMid
            THEN
                dc_pMid := dc_pMid^.dcb_lru_prev;
            (*ENDIF*) 
        (*ENDIF*) 
        IF  dc_pIOMid <> NIL
        THEN
            BEGIN
            IF  pCBlock^.dcb_dw_io_area
            THEN
                BEGIN
                dc_pIOMid^.dcb_dw_io_area := true;
                dc_pIOMid                 := dc_pIOMid^.dcb_lru_prev;
                pCBlock^.dcb_dw_io_area   := false
                END
            ELSE
                IF  pCBlock = dc_pIOMid
                THEN
                    dc_pIOMid := dc_pIOMid^.dcb_lru_prev
                (*ENDIF*) 
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        pCBlock^.dcb_lru_prev^.dcb_lru_next := pCBlock^.dcb_lru_next;
        IF  pCBlock^.dcb_lru_next <> NIL
        THEN
            pCBlock^.dcb_lru_next^.dcb_lru_prev := pCBlock^.dcb_lru_prev
        ELSE
            dc_pLastLRU := pCBlock^.dcb_lru_prev;
        (*ENDIF*) 
        dc_pFirstLRU^.dcb_lru_prev := pCBlock;
        pCBlock^.dcb_lru_prev      := NIL;
        pCBlock^.dcb_lru_next      := dc_pFirstLRU;
        dc_pFirstLRU               := pCBlock;
        END
    (*ENDIF*) 
    END;
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_PutNewIntoLRUList (
            VAR DataCache : t_datacache;
            pCBlock       : tbd02_pDataCBlock);
 
VAR
      TotalFreeCount : tsp00_Int4;
 
BEGIN
WITH DataCache DO
    BEGIN
    IF  dc_pFirstLRU <> NIL
    THEN
        dc_pFirstLRU^.dcb_lru_prev := pCBlock
    ELSE
        dc_pLastLRU := pCBlock;
    (*ENDIF*) 
    pCBlock^.dcb_lru_prev    := NIL;
    pCBlock^.dcb_lru_next    := dc_pFirstLRU;
    pCBlock^.dcb_lru_rechain := false;
    pCBlock^.dcb_dw_io_area  := false;
    dc_pFirstLRU             := pCBlock;
    TotalFreeCount           := dc_FreeCount;
    (* *)
    IF  TotalFreeCount = dc_RecAreaSize
    THEN
        BEGIN
        IF  dc_pMid <> NIL
        THEN
            g01abort (csp3_bd_msg, csp3_n_datacache, MSG_MID_EXIST, 0);
        (*ENDIF*) 
        dc_pMid := dc_pLastLRU;
        END
    ELSE
        IF  TotalFreeCount < dc_RecAreaSize
        THEN
            BEGIN
            dc_pMid^.dcb_lru_rechain := true;
            dc_pMid                  := dc_pMid^.dcb_lru_prev
            END;
        (*ENDIF*) 
    (*ENDIF*) 
    IF  TotalFreeCount = dc_IOAreaSize
    THEN
        BEGIN
        IF  dc_pIOMid <> NIL
        THEN
            g01abort (csp3_bd_msg, csp3_n_datacache, MSG_IOMID_EXIST, 0);
        (*ENDIF*) 
        dc_pIOMid := dc_pLastLRU;
        END
    ELSE
        IF  TotalFreeCount < dc_IOAreaSize
        THEN
            BEGIN
            dc_pIOMid^.dcb_dw_io_area := true;
            dc_pIOMid                 := dc_pIOMid^.dcb_lru_prev
            END
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_PutMidLRUList (
            VAR DataCache : t_datacache;
            pCBlock       : tbd02_pDataCBlock);
 
BEGIN
WITH DataCache DO
    BEGIN
    IF  dc_pMid <> NIL
    THEN
        IF  NOT pCBlock^.dcb_lru_rechain AND (dc_pMid <> pCBlock)
        THEN
            BEGIN
            IF  NOT pCBlock^.dcb_dw_io_area AND (dc_pIOMid <> NIL)
            THEN
                IF  dc_pMid^.dcb_dw_io_area
                THEN
                    BEGIN
                    pCBlock^.dcb_dw_io_area := true;
                    dc_pIOMid := dc_pIOMid^.dcb_lru_next;
                    IF  dc_pIOMid <> NIL
                    THEN
                        dc_pIOMid^.dcb_dw_io_area := false
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  dc_pIOMid = dc_pMid
                    THEN
                        dc_pIOMid := pCBlock
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
            (*ENDIF*) 
            IF  pCBlock^.dcb_lru_prev <> NIL
            THEN
                pCBlock^.dcb_lru_prev^.dcb_lru_next := pCBlock^.dcb_lru_next
            ELSE
                dc_pFirstLRU := pCBlock^.dcb_lru_next;
            (*ENDIF*) 
            IF  pCBlock^.dcb_lru_next <> NIL
            THEN
                pCBlock^.dcb_lru_next^.dcb_lru_prev := pCBlock^.dcb_lru_prev;
            (*ENDIF*) 
            pCBlock^.dcb_lru_prev               := dc_pMid;
            pCBlock^.dcb_lru_next               := dc_pMid^.dcb_lru_next;
            pCBlock^.dcb_lru_next^.dcb_lru_prev := pCBlock;
            dc_pMid^.dcb_lru_next               := pCBlock;
            dc_pMid                             := pCBlock
            END
        (*ENDIF*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_PutLastLRUList (
            VAR DataCache : t_datacache;
            pCBlock       : tbd02_pDataCBlock);
 
BEGIN
WITH DataCache DO
    BEGIN
    IF  NOT pCBlock^.dcb_lru_rechain AND (dc_pMid <> NIL)
    THEN
        BEGIN
        dc_pMid := dc_pMid^.dcb_lru_next;
        IF  dc_pMid <> NIL
        THEN
            dc_pMid^.dcb_lru_rechain := false
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  NOT pCBlock^.dcb_dw_io_area AND (dc_pIOMid <> NIL)
    THEN
        BEGIN
        pCBlock^.dcb_dw_io_area := true;
        dc_pIOMid               := dc_pIOMid^.dcb_lru_next;
        IF  dc_pIOMid <> NIL
        THEN
            dc_pIOMid^.dcb_dw_io_area := false
        (*ENDIF*) 
        END;
    (*ENDIF*) 
    IF  pCBlock^.dcb_lru_prev <> NIL
    THEN
        pCBlock^.dcb_lru_prev^.dcb_lru_next := pCBlock^.dcb_lru_next
    ELSE
        dc_pFirstLRU := pCBlock^.dcb_lru_next;
    (*ENDIF*) 
    IF  pCBlock^.dcb_lru_next <> NIL
    THEN
        pCBlock^.dcb_lru_next^.dcb_lru_prev := pCBlock^.dcb_lru_prev;
    (*ENDIF*) 
    pCBlock^.dcb_lru_prev     := dc_pLastLRU;
    pCBlock^.dcb_lru_next     := NIL;
    pCBlock^.dcb_lru_rechain  := true;
    dc_pLastLRU^.dcb_lru_next := pCBlock;
    dc_pLastLRU               := pCBlock
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20unset_changed (VAR datacache  : t_datacache;
            act_block      : tbd02_pDataCBlock);
 
VAR
      first_io_queue : boolean;
 
BEGIN
IF  (act_block = NIL)
THEN
    g01abort (csp3_b20x7_nil_cbptr, csp3_n_datacache,
          'BD20UNSET: index = NIL  ', 0)
ELSE
    WITH datacache, act_block^ DO
        BEGIN
&       ifdef TRACE
        t01int4 (bd_ioqueue, '==> ChangedS', ord (dcb_ChangedState_bd02));
        t01int4 (bd_ioqueue, '==> tfn     ', ord (dcb_tfn));
        t01int4 (bd_ioqueue, '==> page no ', dcb_occupant);
        t01addr (bd_ioqueue, '==> del elem', act_block);
&       endif
        IF  dcb_ChangedState_bd02 <> cstNone_ebd02
        THEN
            BEGIN
            IF  (dcb_io_next    <> NIL    ) OR
                (dcb_io_prev    <> NIL    ) OR
                (dc_pIOQueueHead1 = act_block) OR
                (dc_pIOQueueHead2 = act_block) OR
                (dc_pClusterQueueHead1 = act_block) OR
                (dc_pClusterQueueHead2 = act_block)
            THEN
                BEGIN
                IF  NOT dc_SVPActive
                THEN
                    first_io_queue := NOT dc_IOSwitch
                ELSE
                    first_io_queue :=
                          ((dcb_ChangedState_bd02 = cstSvpRelevant_ebd02) AND dc_IOSwitch)
                          OR
                          ((dcb_ChangedState_bd02 <> cstSvpRelevant_ebd02) AND NOT dc_IOSwitch);
                (*ENDIF*) 
                IF  ((NOT dcb_IsClustered_bd02) AND first_io_queue AND (dc_pIOQueueHead1 = NIL))
                    OR
                    ((NOT dcb_IsClustered_bd02) AND (NOT first_io_queue) AND (dc_pIOQueueHead2 = NIL))
                THEN
                    bd20_Abort2 ( csp3_b20x7_check,
                          'IOCHAIN empt', dcb_occupant, act_block);
                (*ENDIF*) 
                IF  (dcb_IsClustered_bd02 AND first_io_queue AND (dc_pClusterQueueHead1 = NIL))
                    OR
                    (dcb_IsClustered_bd02 AND (NOT first_io_queue) AND (dc_pClusterQueueHead2 = NIL))
                THEN
                    bd20_Abort2 ( csp3_b20x8_check,
                          'IOCHAIN empt', dcb_occupant, act_block);
                (*ENDIF*) 
                IF  (dcb_IsClustered_bd02)
                THEN
                    BEGIN
                    IF  (dcb_io_prev = NIL)
                    THEN
                        BEGIN
                        IF  first_io_queue
                        THEN
                            BEGIN
                            dc_pClusterQueueHead1 := dcb_io_next;
                            IF  dcb_io_next = NIL
                            THEN
                                dc_pClusterQueueTail1 := NIL
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            dc_pClusterQueueHead2 := dcb_io_next;
                            IF  dcb_io_next = NIL
                            THEN
                                dc_pClusterQueueTail2 := NIL
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        IF  (dcb_io_next <> NIL)
                        THEN
                            BEGIN
                            dcb_io_next^.dcb_io_prev := NIL;
                            dcb_io_next              := NIL
                            END
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        dcb_io_prev^.dcb_io_next := dcb_io_next;
                        IF  (dcb_io_next <> NIL)
                        THEN
                            BEGIN
                            dcb_io_next^.dcb_io_prev := dcb_io_prev;
                            dcb_io_next              := NIL
                            END
                        ELSE
                            IF  first_io_queue
                            THEN
                                dc_pClusterQueueTail1 := dcb_io_prev
                            ELSE
                                dc_pClusterQueueTail2 := dcb_io_prev;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        dcb_io_prev := NIL
                        END;
                    (*ENDIF*) 
                    dc_clusteredIOElems := pred (dc_clusteredIOElems);
                    bd20TotalChangedPages := pred (bd20TotalChangedPages);
                    IF  dcb_ChangedState_bd02 = cstSvpRelevant_ebd02
                    THEN
                        dc_clusteredSVPElems := pred (dc_clusteredSVPElems);
                    (*ENDIF*) 
                    END
                ELSE
                    BEGIN
                    IF  (dcb_io_prev = NIL)
                    THEN
                        BEGIN
                        IF  first_io_queue
                        THEN
                            BEGIN
                            dc_pIOQueueHead1 := dcb_io_next;
                            IF  dcb_io_next = NIL
                            THEN
                                dc_pIOQueueTail1 := NIL
                            (*ENDIF*) 
                            END
                        ELSE
                            BEGIN
                            dc_pIOQueueHead2 := dcb_io_next;
                            IF  dcb_io_next = NIL
                            THEN
                                dc_pIOQueueTail2 := NIL
                            (*ENDIF*) 
                            END;
                        (*ENDIF*) 
                        IF  (dcb_io_next <> NIL)
                        THEN
                            BEGIN
                            dcb_io_next^.dcb_io_prev := NIL;
                            dcb_io_next              := NIL
                            END
                        (*ENDIF*) 
                        END
                    ELSE
                        BEGIN
                        dcb_io_prev^.dcb_io_next := dcb_io_next;
                        IF  (dcb_io_next <> NIL)
                        THEN
                            BEGIN
                            dcb_io_next^.dcb_io_prev := dcb_io_prev;
                            dcb_io_next              := NIL
                            END
                        ELSE
                            IF  first_io_queue
                            THEN
                                dc_pIOQueueTail1 := dcb_io_prev
                            ELSE
                                dc_pIOQueueTail2 := dcb_io_prev;
                            (*ENDIF*) 
                        (*ENDIF*) 
                        dcb_io_prev := NIL
                        END;
                    (*ENDIF*) 
                    dc_IOElems := pred (dc_IOElems);
                    bd20TotalChangedPages := pred (bd20TotalChangedPages);
                    IF  dcb_ChangedState_bd02 = cstSvpRelevant_ebd02
                    THEN
                        dc_SVPElems := pred (dc_SVPElems)
                    (*ENDIF*) 
                    END;
                (*ENDIF*) 
                IF  dc_IOElems < 0
                THEN
                    bd20_Abort2 ( csp3_b20x9_check,
                          'IOElems empt', dcb_occupant, act_block);
                (*ENDIF*) 
                IF  dc_clusteredIOElems < 0
                THEN
                    bd20_Abort2 ( csp3_b20x9_check,
                          'clIOElemsemp', dcb_occupant, act_block);
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            dcb_ChangedState_bd02 := cstNone_ebd02;
            END;
&       ifdef TRACE
        (*ENDIF*) 
        IF  t01trace (bd_ioqueue)
        THEN
            bd20print_io_chain (datacache);
        (*ENDIF*) 
        IF  g01glob.datacachecheck
        THEN
            bd20check_io_chain (datacache);
&       endif
        (*ENDIF*) 
        END
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20set_changed (VAR datacache : t_datacache;
            act_block          : tbd02_pDataCBlock;
            ins_this_temp_page : boolean;
            is_clustered       : boolean);
 
VAR
      is_io_relevant : boolean;
 
BEGIN
IF  (act_block = NIL)
THEN
    g01abort (csp3_b20x8_nil_cbptr, csp3_n_datacache,
          'BD20SET: cbptr = NIL    ', 0)
ELSE
    WITH datacache, act_block^ DO
        BEGIN
&       ifdef TRACE
        t01int4 (bd_ioqueue, '==> ChangedS', ord (dcb_ChangedState_bd02));
        t01int4 (bd_ioqueue, '==> tfn     ', ord (dcb_tfn));
        t01int4 (bd_ioqueue, '==> page no ', dcb_occupant);
        t01addr (bd_ioqueue, '==> ins elem', act_block);
&       endif
        IF  dcb_ChangedState_bd02 = cstNone_ebd02
        THEN
            BEGIN
            dcb_ChangedState_bd02 := cstChanged_ebd02;
            dcb_IsClustered_bd02       := is_clustered;
            is_io_relevant        := (dcb_RecMode_bd02 <> rmTemp_egg00) OR ins_this_temp_page ;
            END
        ELSE
            BEGIN
            IF  ins_this_temp_page
            THEN
                is_io_relevant :=
                      ((dcb_io_next = NIL        ) AND
                      (dcb_io_prev = NIL         ) AND
                      (dc_pIOQueueHead1 <> act_block) AND
                      (dc_pIOQueueHead2 <> act_block) AND
                      (dc_pClusterQueueHead1 <> act_block) AND
                      (dc_pClusterQueueHead2 <> act_block))
            ELSE
                is_io_relevant := false
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        (* *)
        IF  is_io_relevant
        THEN
            BEGIN
            IF  dcb_IsClustered_bd02
            THEN
                BEGIN
                dc_clusteredIOElems   := succ (dc_clusteredIOElems);
                bd20TotalChangedPages := succ (bd20TotalChangedPages);
                IF  dc_IOSwitch
                THEN
                    BEGIN
                    IF  (dc_pClusterQueueHead2 <> NIL)
                    THEN
                        BEGIN
                        act_block^.dcb_io_next        := dc_pClusterQueueHead2;
                        dc_pClusterQueueHead2^.dcb_io_prev := act_block
                        END
                    ELSE
                        dc_pClusterQueueTail2 := act_block;
                    (*ENDIF*) 
                    dc_pClusterQueueHead2 := act_block
                    END
                ELSE
                    BEGIN
                    IF  (dc_pClusterQueueHead1 <> NIL)
                    THEN
                        BEGIN
                        act_block^.dcb_io_next        := dc_pClusterQueueHead1;
                        dc_pClusterQueueHead1^.dcb_io_prev := act_block
                        END
                    ELSE
                        dc_pClusterQueueTail1 := act_block;
                    (*ENDIF*) 
                    dc_pClusterQueueHead1 := act_block
                    END;
                (*ENDIF*) 
                END
            ELSE
                BEGIN
                dc_IOElems            := succ (dc_IOElems);
                bd20TotalChangedPages := succ (bd20TotalChangedPages);
                IF  dc_IOSwitch
                THEN
                    BEGIN
                    IF  (dc_pIOQueueHead2 <> NIL)
                    THEN
                        BEGIN
                        act_block^.dcb_io_next        := dc_pIOQueueHead2;
                        dc_pIOQueueHead2^.dcb_io_prev := act_block
                        END
                    ELSE
                        dc_pIOQueueTail2 := act_block;
                    (*ENDIF*) 
                    dc_pIOQueueHead2 := act_block
                    END
                ELSE
                    BEGIN
                    IF  (dc_pIOQueueHead1 <> NIL)
                    THEN
                        BEGIN
                        act_block^.dcb_io_next        := dc_pIOQueueHead1;
                        dc_pIOQueueHead1^.dcb_io_prev := act_block
                        END
                    ELSE
                        dc_pIOQueueTail1 := act_block;
                    (*ENDIF*) 
                    dc_pIOQueueHead1 := act_block
                    END;
                (*ENDIF*) 
                END;
            (*ENDIF*) 
            END;
&       ifdef TRACE
        (*ENDIF*) 
        IF  t01trace (bd_ioqueue)
        THEN
            bd20print_io_chain (datacache);
        (*ENDIF*) 
        IF  g01glob.datacachecheck
        THEN
            bd20check_io_chain (datacache);
&       endif
        (*ENDIF*) 
        END
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_Abort (
            VAR FileId : tgg00_FileId;
            MsgNo      : tsp00_Int4;
            MsgText    : tsp00_C12;
            Pno        : tsp00_PageNo;
            pCBlock    : tbd02_pDataCBlock);
 
BEGIN
bd20opmsg (sp3m_error, MsgNo, MsgText, Pno, pCBlock);
b06write_filename_and_root (FileId);
gg999Abort (WRITE_CORE_BD20)
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_Abort2 (
            MsgNo   : tsp00_Int4;
            MsgText : tsp00_C12;
            Pno     : tsp00_PageNo;
            pCBlock : tbd02_pDataCBlock);
 
BEGIN
bd20opmsg (sp3m_error, MsgNo, MsgText, Pno, pCBlock);
gg999Abort (WRITE_CORE_BD20)
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_DecrementWorkloadCounter (
            VAR DataCache : t_datacache;
            FileType      : tgg00_Tfn);
 
BEGIN
WITH DataCache DO
    BEGIN
    CASE FileType OF
        tfnUndoLog_egg00 :
            dc_UndoFilePageCnt := dc_UndoFilePageCnt - 1;
        tfnObj_egg00, tfnContObj_egg00, tfnOmsInv_egg00 :
            dc_OmsDataPageCnt := dc_OmsDataPageCnt - 1;
        tfnTempOms_egg00:
            dc_OmsTempPageCnt := dc_OmsTempPageCnt - 1;
        OTHERWISE
            dc_SqlDataPageCnt := dc_SqlDataPageCnt - 1
        END;
    (*ENDCASE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_IncrementWorkloadCounter (
            VAR DataCache : t_datacache;
            FileType      : tgg00_Tfn);
 
BEGIN
WITH DataCache DO
    BEGIN
    CASE FileType OF
        tfnUndoLog_egg00 :
            dc_UndoFilePageCnt := dc_UndoFilePageCnt + 1;
        tfnObj_egg00, tfnContObj_egg00, tfnOmsInv_egg00 :
            dc_OmsDataPageCnt := dc_OmsDataPageCnt + 1;
        tfnTempOms_egg00:
            dc_OmsTempPageCnt := dc_OmsTempPageCnt + 1;
        OTHERWISE
            dc_SqlDataPageCnt := dc_SqlDataPageCnt + 1
        END;
    (*ENDCASE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_MaintainCacheStatistic (
            VAR datacache : t_datacache;
            Found         : boolean;
            FileType      : tgg00_Tfn);
 
BEGIN
IF  Found
THEN
    WITH datacache DO
        BEGIN
        CASE FileType OF
            tfnObj_egg00, tfnContObj_egg00, tfnOmsInv_egg00, tfnTempOms_egg00 :
                dc_OmsDataHit := dc_OmsDataHit + 1;
            tfnUndoLog_egg00 :
                dc_UndoFileHit := dc_UndoFileHit + 1;
            OTHERWISE:
                dc_SqlDataHit := dc_SqlDataHit + 1;
            END;
        (*ENDCASE*) 
        END
    (*ENDWITH*) 
ELSE
    WITH datacache DO
        BEGIN
        CASE FileType OF
            tfnObj_egg00, tfnContObj_egg00, tfnOmsInv_egg00, tfnTempOms_egg00 :
                dc_OmsDataMiss := dc_OmsDataMiss + 1;
            tfnUndoLog_egg00 :
                dc_UndoFileMiss := dc_UndoFileMiss + 1;
            OTHERWISE:
                dc_SqlDataMiss := dc_SqlDataMiss + 1;
            END;
        (*ENDCASE*) 
        END
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_InsertLockRequest (
            VAR TaskId    : tsp00_TaskId;
            VAR FileId    : tgg00_FileId;
            VAR DataCache : t_datacache;
            LockState     : tbd02_TaskQueueReason;
            pCBlock       : tbd02_pDataCBlock);
 
VAR
      pTaskQueueItem : tbd02_pTaskQueueItem;
 
BEGIN
WITH DataCache, pCBlock^ DO
    BEGIN
    dcb_CollisionCnt_bd02 := dcb_CollisionCnt_bd02 + 1;
    b06check_vresume_cnt (TaskId);
    pTaskQueueItem := dc_pTaskQueueFree;
    IF  dc_pTaskQueueFree = NIL
    THEN
        bd20_Abort (FileId, csp3_b20x2_pid_queue_empty,
              'Empty TaskQ ', dcb_occupant, pCBlock);
    (*ENDIF*) 
    dc_pTaskQueueFree               := dc_pTaskQueueFree^.tqiVarNext_bd02;
    pTaskQueueItem^.tqiTaskId_bd02  := TaskId;
    pTaskQueueItem^.tqiReason_bd02  := LockState;
    pTaskQueueItem^.tqiVarNext_bd02 := NIL;
    IF  dcb_lock_req_head = NIL
    THEN
        dcb_lock_req_head := pTaskQueueItem
    ELSE
        dcb_lock_req_tail^.tqiVarNext_bd02 := pTaskQueueItem;
    (*ENDIF*) 
    dcb_lock_req_tail := pTaskQueueItem;
    IF  iosBlocked_ebd02 = dcb_io_state
    THEN
        v2prio (dcb_LastOwner_bd02, c_dc_task_prio, SET_PRIO_BD20,
              FileId.fileRoot_gg00, dcb_occupant, 0);
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_InsertOccupant (
            TaskId        : tsp00_TaskId;
            VAR FileId    : tgg00_FileId;
            VAR DataCache : t_datacache;
            pCBlock       : tbd02_pDataCBlock);
 
VAR
      pTaskQueueItem : tbd02_pTaskQueueItem;
 
BEGIN
WITH DataCache, pCBlock^ DO
    BEGIN
    b06check_vresume_cnt (TaskId);
    pTaskQueueItem := dc_pTaskQueueFree  ;
    IF  dc_pTaskQueueFree = NIL
    THEN
        bd20_Abort (FileId, csp3_b20x7_pid_queue_empty,
              'Empty TaskQ ', dcb_occupant, pCBlock);
    (*ENDIF*) 
    dc_pTaskQueueFree               := dc_pTaskQueueFree^.tqiVarNext_bd02;
    pTaskQueueItem^.tqiVarNext_bd02 := dcb_queue_occ;
    pTaskQueueItem^.tqiTaskId_bd02  := TaskId;
    dcb_queue_occ                   := pTaskQueueItem
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_InsertOldOccupant (
            TaskId        : tsp00_TaskId;
            VAR FileId    : tgg00_FileId;
            VAR DataCache : t_datacache;
            pCBlock       : tbd02_pDataCBlock);
 
VAR
      pTaskQueueItem : tbd02_pTaskQueueItem;
 
BEGIN
WITH DataCache, pCBlock^ DO
    BEGIN
    b06check_vresume_cnt (TaskId);
    pTaskQueueItem := dc_pTaskQueueFree;
    IF  dc_pTaskQueueFree = NIL
    THEN
        bd20_Abort (FileId, csp3_b20x6_pid_queue_empty,
              'Empty TaskQ ', dcb_occupant, pCBlock);
    (*ENDIF*) 
    dc_pTaskQueueFree               := dc_pTaskQueueFree^.tqiVarNext_bd02;
    pTaskQueueItem^.tqiVarNext_bd02 := dcb_queue_old_occ;
    pTaskQueueItem^.tqiTaskId_bd02  := TaskId;
    dcb_queue_old_occ               := pTaskQueueItem
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_InsertOverflow (
            TaskId        : tsp00_TaskId;
            VAR FileId    : tgg00_FileId;
            VAR DataCache : t_datacache);
 
VAR
      pTaskQueueItem : tbd02_pTaskQueueItem;
 
BEGIN
WITH DataCache DO
    BEGIN
    b06check_vresume_cnt (TaskId);
    pTaskQueueItem := dc_pTaskQueueFree;
    IF  dc_pTaskQueueFree = NIL
    THEN
        bd20_Abort (FileId, csp3_b20x8_pid_queue_empty,
              'Empty TaskQ ', NIL_PAGE_NO_GG00, NIL);
    (*ENDIF*) 
    dc_pTaskQueueFree               := dc_pTaskQueueFree^.tqiVarNext_bd02;
    pTaskQueueItem^.tqiVarNext_bd02 := dc_pOverflowTaskQueue;
    pTaskQueueItem^.tqiTaskId_bd02  := TaskId;
    dc_pOverflowTaskQueue           := pTaskQueueItem
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_InsertSavepointEnd (
            TaskId        : tsp00_TaskId;
            VAR FileId    : tgg00_FileId;
            VAR DataCache : t_datacache);
 
VAR
      pTaskQueueItem : tbd02_pTaskQueueItem;
 
BEGIN
WITH DataCache DO
    BEGIN
    b06check_vresume_cnt (TaskId);
    pTaskQueueItem := dc_pTaskQueueFree;
    IF  dc_pTaskQueueFree = NIL
    THEN
        bd20_Abort (FileId, csp3_b20x8_pid_queue_empty,
              'Empty TaskQ ', NIL_PAGE_NO_GG00, NIL);
    (*ENDIF*) 
    dc_pTaskQueueFree               := dc_pTaskQueueFree^.tqiVarNext_bd02;
    pTaskQueueItem^.tqiVarNext_bd02 := dc_pSvpEndTaskQueue;
    pTaskQueueItem^.tqiTaskId_bd02  := TaskId;
    dc_pSvpEndTaskQueue             := pTaskQueueItem
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_ResumeLockRequest (
            TaskId        : tsp00_TaskId;
            VAR DataCache : t_datacache;
            pCBlock       : tbd02_pDataCBlock;
            bResumeAll    : boolean);
 
VAR
      bStop         : boolean;
      pTaskQueueItem : tbd02_pTaskQueueItem;
 
BEGIN
WITH DataCache, pCBlock^ DO
    BEGIN
    bStop := false;
    WHILE (dcb_lock_req_head <> NIL) AND (NOT bStop) DO
        BEGIN
        IF  TaskId = dcb_lock_req_head^.tqiTaskId_bd02
        THEN
            g01abort (csp3_b20x7_nil_cbptr, csp3_n_datacache,
                  'BD20RESUME illegal pid  ', TaskId);
        (* *)
        (*ENDIF*) 
        vresume (dcb_lock_req_head^.tqiTaskId_bd02);
        (* *)
        bStop :=
              (dcb_lock_req_head^.tqiReason_bd02 = tqrExclusiveLock_ebd02)
              AND
              (NOT bResumeAll);
        dcb_lock_req_head^.tqiTaskId_bd02  := cgg_nil_pid;
        dcb_lock_req_head^.tqiReason_bd02  := tqrNil_ebd02;
        pTaskQueueItem                     := dcb_lock_req_head^.tqiVarNext_bd02;
        dcb_lock_req_head^.tqiVarNext_bd02 := dc_pTaskQueueFree;
        dc_pTaskQueueFree                  := dcb_lock_req_head;
        dcb_lock_req_head                  := pTaskQueueItem;
        IF  dcb_lock_req_head = NIL
        THEN
            dcb_lock_req_tail := NIL
        (*ENDIF*) 
        END;
    (*ENDWHILE*) 
    IF  iosBlocked_ebd02 = dcb_io_state
    THEN
        vprio (TaskId, c_dc_task_prio, NOT SET_PRIO_BD20)
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_ResumeOccupant (
            VAR DataCache : t_datacache;
            pCBlock       : tbd02_pDataCBlock);
 
VAR
      pTaskQueueItem : tbd02_pTaskQueueItem;
 
BEGIN
WITH DataCache, pCBlock^ DO
    BEGIN
    WHILE dcb_queue_occ <> NIL DO
        BEGIN
        vresume (dcb_queue_occ^.tqiTaskId_bd02);
        dcb_queue_occ^.tqiTaskId_bd02  := cgg_nil_pid;
        pTaskQueueItem                 := dcb_queue_occ^.tqiVarNext_bd02;
        dcb_queue_occ^.tqiVarNext_bd02 := dc_pTaskQueueFree;
        dc_pTaskQueueFree              := dcb_queue_occ;
        dcb_queue_occ                  := pTaskQueueItem
        END
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_ResumeOldOccupant (
            VAR DataCache : t_datacache;
            pCBlock       : tbd02_pDataCBlock);
 
VAR
      pTaskQueueItem : tbd02_pTaskQueueItem;
 
BEGIN
WITH DataCache, pCBlock^ DO
    BEGIN
    WHILE dcb_queue_old_occ <> NIL DO
        BEGIN
        vresume (dcb_queue_old_occ^.tqiTaskId_bd02);
        dcb_queue_old_occ^.tqiTaskId_bd02  := cgg_nil_pid;
        pTaskQueueItem                     := dcb_queue_old_occ^.tqiVarNext_bd02;
        dcb_queue_old_occ^.tqiVarNext_bd02 := dc_pTaskQueueFree;
        dc_pTaskQueueFree                  := dcb_queue_old_occ;
        dcb_queue_old_occ                  := pTaskQueueItem
        END
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_ResumeOverflow (
            VAR DataCache : t_datacache;
            ResumeCount   : tsp00_Int4);
 
VAR
      pTaskQueueItem : tbd02_pTaskQueueItem;
 
BEGIN
WITH DataCache DO
    BEGIN
    WHILE (dc_pOverflowTaskQueue <> NIL) AND (ResumeCount > 0) DO
        BEGIN
        vresume (dc_pOverflowTaskQueue^.tqiTaskId_bd02);
        ResumeCount                            := pred (ResumeCount);
        dc_pOverflowTaskQueue^.tqiTaskId_bd02  := cgg_nil_pid;
        pTaskQueueItem                         := dc_pOverflowTaskQueue^.tqiVarNext_bd02;
        dc_pOverflowTaskQueue^.tqiVarNext_bd02 := dc_pTaskQueueFree;
        dc_pTaskQueueFree                      := dc_pOverflowTaskQueue;
        dc_pOverflowTaskQueue                  := pTaskQueueItem
        END
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_ResumeSavepointEnd (
            VAR DataCache : t_datacache);
 
VAR
      pTaskQueueItem : tbd02_pTaskQueueItem;
 
BEGIN
WITH DataCache DO
    BEGIN
    WHILE  dc_pSvpEndTaskQueue <> NIL DO
        BEGIN
        vresume (dc_pSvpEndTaskQueue^.tqiTaskId_bd02);
        dc_pSvpEndTaskQueue^.tqiTaskId_bd02  := cgg_nil_pid;
        pTaskQueueItem                       := dc_pSvpEndTaskQueue^.tqiVarNext_bd02;
        dc_pSvpEndTaskQueue^.tqiVarNext_bd02 := dc_pTaskQueueFree;
        dc_pTaskQueueFree                    := dc_pSvpEndTaskQueue;
        dc_pSvpEndTaskQueue                  := pTaskQueueItem
        END
    (*ENDWHILE*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_SearchInChain (
            VAR DataCache   : t_datacache;
            HashIndex       : tsp00_Int4;
            PageNo          : tsp00_PageNo;
            recMode         : tgg00_RecoveryMode;
            VAR pCBlock     : tbd02_pDataCBlock;
            VAR pPrevCBlock : tbd02_pDataCBlock;
            VAR bFound      : boolean);
 
BEGIN
bFound       := false;
pPrevCBlock  := NIL;
WITH DataCache DO
    BEGIN
    pCBlock := dc_pHeadList^ [HashIndex].he_cb;
    IF  pCBlock <> NIL
    THEN
        REPEAT
            IF  (pCBlock^.dcb_occupant = PageNo       ) AND
                (pCBlock^.dcb_RecMode_bd02 = recMode  ) AND
                (NOT pCBlock^.dcb_IsSourceOfACopy_bd02)
            THEN
                bFound := true
            ELSE
                BEGIN
                pPrevCBlock := pCBlock;
                pCBlock     := pCBlock^.dcb_VarNext_bd02
                END
            (*ENDIF*) 
        UNTIL
            bFound OR (pCBlock = NIL)
        (*ENDREPEAT*) 
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(* PTS 1113035 TS 2002-01-31 *)
(*------------------------------*) 
 
PROCEDURE
      bd20_SearchAndResumeLockRequest(
            TaskId        : tsp00_TaskId;
            VAR DataCache : t_datacache;
            HashIndex     : tsp00_Int4;
            PageNo        : tsp00_PageNo;
            recMode       : tgg00_RecoveryMode);
 
VAR
      bFound      : boolean;
      pCBlock     : tbd02_pDataCBlock;
      pPrevCBlock : tbd02_pDataCBlock;
 
BEGIN
bd20_SearchInChain (DataCache, HashIndex, PageNo, recMode, pCBlock, pPrevCBlock, bFound);
IF  bFound
THEN
    WITH pCBlock^ DO
        BEGIN
        IF  (dcb_UsageCnt_bd02 = 0) AND (dcb_lock_req_head <> NIL)
        THEN
            bd20_ResumeLockRequest (TaskId, DataCache, pCBlock, NOT RESUME_ALL_BD20);
        (*ENDIF*) 
        END
    (*ENDWITH*) 
(*ENDIF*) 
END;
 
(* PTS 1113035 *)
(*------------------------------*) 
 
PROCEDURE
      bd20_SetPreventSvpSyncOperation (
            TaskId       : tsp00_TaskId;
            bPreventSync : boolean);
 
VAR
      RegOffset : tsp00_Int4;
 
BEGIN
RegOffset := 0;
WHILE RegOffset <= bd20RegionCount - 1 DO
    BEGIN
    vbegexcl (TaskId, g08data1 + RegOffset);
    bd20DataCacheList [RegOffset].dc_PreventSvpSync := bPreventSync;
    vendexcl (TaskId, g08data1 + RegOffset);
    RegOffset := RegOffset + 1
    END
(*ENDWHILE*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_SetPreventWriteIO (
            taskId          : tsp00_TaskId;
            bPreventWriteIO : boolean);
 
VAR
      regOffset : tsp00_Int4;
 
BEGIN
FOR regOffset := 0 TO bd20RegionCount - 1 DO
    BEGIN
    vbegexcl (taskId, g08data1 + regOffset);
    bd20DataCacheList [regOffset].dc_PreventWriteIO := bPreventWriteIO;
    vendexcl (taskId, g08data1 + regOffset);
    END;
(*ENDFOR*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_AssertState(
            Ident       : tsp00_Int4;
            SegmentId   : tsp00_Int4;
            bConstraint : boolean);
 
BEGIN
IF  NOT bConstraint
THEN
    g01abort( Ident, csp3_n_datacache, 'ASSERTION FAILED        ', SegmentId );
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_AdjustRechainAndIOArea(
            VAR DataCache : t_datacache);
 
VAR
      CBlockCnt           : tsp00_Int4;
      NumOfRechainCBlocks : tsp00_Int4;
      NumOfIOAreaCBlocks  : tsp00_Int4;
      pCBlock             : tbd02_pDataCBlock;
 
BEGIN
WITH DataCache DO
    BEGIN
    IF  dc_SegmentSize < 100
    THEN
        BEGIN
        dc_IOAreaSize      := (dc_SegmentSize + 1) DIV c_p50_percent;
        dc_IOAreaFlushCnt  := trunc (((dc_SegmentSize+1)/10) * 2);
        (* NOTE: dc_LruTailFlushCnt MUST BE LESS EQUAL THAN dc_RecAreaSize! *)
        dc_LruTailFlushCnt := trunc ((dc_RecAreaSize+1)/2);
        END
    ELSE
        BEGIN
        dc_IOAreaSize      := trunc (((dc_SegmentSize + 1) / 100)* g01dw_io_area_size);
        dc_IOAreaFlushCnt  := trunc (((dc_SegmentSize+1)/100) * g01dw_io_area_flush);
        dc_LruTailFlushCnt := trunc (((dc_RecAreaSize+1)/100) * g01dw_lru_tail_flush);
        END;
    (*ENDIF*) 
    (* Maintain rechain and io-area *)
    dc_pMid             := NIL;
    dc_pIOMid           := NIL;
    pCBlock             := dc_pLastLRU;
    CBlockCnt           := 1;
    NumOfRechainCBlocks := dc_RecAreaSize - dc_FreeCount;
    NumOfIOAreaCBlocks  := dc_IOAreaSize - dc_FreeCount;
    WHILE pCBlock <> NIL DO
        BEGIN
        IF  CBlockCnt <= NumOfRechainCBlocks
        THEN
            pCBlock^.dcb_lru_rechain := true
        ELSE
            BEGIN
            pCBlock^.dcb_lru_rechain := false;
            IF  CBlockCnt = NumOfRechainCBlocks + 1
            THEN
                dc_pMid := pCBlock;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        IF  CBlockCnt <= NumOfIOAreaCBlocks
        THEN
            pCBlock^.dcb_dw_io_area := true
        ELSE
            BEGIN
            pCBlock^.dcb_dw_io_area := false;
            IF  CBlockCnt = NumOfIOAreaCBlocks + 1
            THEN
                dc_pIOMid := pCBlock;
            (*ENDIF*) 
            END;
        (*ENDIF*) 
        CBlockCnt := CBlockCnt + 1;
        pCBlock   := pCBlock^.dcb_lru_prev;
        END;
    (*ENDWHILE*) 
    IF  g01glob.datacachecheck
    THEN
        bd20_CheckLRUList (DataCache);
    (*ENDIF*) 
    END
(*ENDWITH*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_ReadAccessToFrame(pFrame : tbd_nodeptr);
 
VAR
      retCode : tsp00_Longint;
 
BEGIN
IF  (pFrame <> NIL)
THEN
    BEGIN
    retCode := RTESys_MemProtectReadOnly (pFrame, bd999GetPageSize);
    IF  retCode <> 0
    THEN
        g01abort (csp3_bd_msg, csp3_n_datacache, 'RTE MEMORY LOCK FAILED  ', retCode);
    (*ENDIF*) 
    END
(*ENDIF*) 
END;
 
(*------------------------------*) 
 
PROCEDURE
      bd20_ReadWriteAccessToFrame(pFrame : tbd_nodeptr);
 
VAR
      retCode : tsp00_Longint;
 
BEGIN
IF  (pFrame <> NIL)
THEN
    BEGIN
    retCode := RTESys_MemProtectReadWrite (pFrame, bd999GetPageSize);
    IF  retCode <> 0
    THEN
        g01abort (csp3_bd_msg, csp3_n_datacache, 'RTE MEMORY LOCK FAILED  ', retCode);
    (*ENDIF*) 
    END
(*ENDIF*) 
END;
 
.CM *-END-* code ----------------------------------------
.SP 2 
***********************************************************
.PA 
